arena_lib/src/api/in_game.lua

983 lines
29 KiB
Lua
Executable File

local S = minetest.get_translator("arena_lib")
local function assign_team_spawner() end
local function operations_before_entering_arena() end
local function operations_before_playing_arena() end
local function operations_before_leaving_arena() end
local function handle_leaving_callbacks() end
local function show_victory_particles() end
local function time_start() end
local players_in_game = {} -- KEY: player name, VALUE: {(string) minigame, (int) arenaID}
local players_in_queue = {} -- KEY: player name, VALUE: {(string) minigame, (int) arenaID}
local players_temp_storage = {} -- KEY: player_name, VALUE: {(int) hotbar_slots, (string) hotbar_background_image, (string) hotbar_selected_image,
-- (int) bgm_handle, (int) fov, (table) camera_offset}
-- per tutti i giocatori quando finisce la coda
function arena_lib.load_arena(mod, arena_ID)
-- my child, let's talk about some black magic: in order to teleport players in their team spawners, first of all I need to
-- sort them by team. Once it's done, I need to skip every spawner of that team if the maximum number of players is not reached:
-- otherwise, people will find theirselves in the wrong team (and you don't want that to happen). So I use this int to prevent it,
-- which increases by 1 or more every time I look for a spawner, comparing the 'team' spawner value to the player's. This happens
-- in assign_team_spawner, which also returns the new value for team_count
local team_count = 1
local count = 1
local mod_ref = arena_lib.mods[mod]
local arena = mod_ref.arenas[arena_ID]
arena.in_loading = true
arena_lib.update_sign(arena)
local shuffled_spawners = table.copy(arena.spawn_points)
local sorted_team_players = {}
-- aggiungo eventuali proprietà temporanee
for temp_property, v in pairs(mod_ref.temp_properties) do
if type(v) == "table" then
arena[temp_property] = table.copy(v)
else
arena[temp_property] = v
end
end
-- randomizzo gli spawner se non è a team
if not arena.teams_enabled then
for i = #shuffled_spawners, 2, -1 do
local j = math.random(i)
shuffled_spawners[i], shuffled_spawners[j] = shuffled_spawners[j], shuffled_spawners[i]
end
-- sennò ordino i giocatori per team
else
local j = 1
for i = 1, #arena.teams do
for pl_name, pl_stats in pairs(arena.players) do
if pl_stats.teamID == i then
sorted_team_players[j] = {name = pl_name, teamID = pl_stats.teamID}
j = j +1
end
end
-- e aggiungo eventuali proprietà per ogni team
for k, v in pairs(mod_ref.team_properties) do
arena.teams[i][k] = v
end
end
end
-- per ogni giocatore...
for pl_name, _ in pairs(arena.players) do
operations_before_entering_arena(mod_ref, mod, arena, arena_ID, pl_name)
-- teletrasporto i giocatori
if not arena.teams_enabled then
minetest.get_player_by_name(pl_name):set_pos(shuffled_spawners[count].pos)
else
team_count = assign_team_spawner(arena.spawn_points, team_count, sorted_team_players[count].name, sorted_team_players[count].teamID)
end
count = count +1
end
-- eventuale codice aggiuntivo
if mod_ref.on_load then
mod_ref.on_load(arena)
end
-- inizio l'arena dopo tot secondi
minetest.after(mod_ref.load_time, function()
arena_lib.start_arena(mod_ref, arena)
end)
end
function arena_lib.start_arena(mod_ref, arena)
-- nel caso sia terminata durante la fase di caricamento
if arena.in_celebration or not arena.in_game then return end
arena.in_loading = false
arena_lib.update_sign(arena)
-- parte l'eventuale tempo
if mod_ref.time_mode ~= "none" then
arena.current_time = arena.initial_time
minetest.after(1, function()
time_start(mod_ref, arena)
end)
end
-- eventuale codice aggiuntivo
if mod_ref.on_start then
mod_ref.on_start(arena)
end
end
-- per il giocatore singolo a match iniziato
function arena_lib.join_arena(mod, p_name, arena_ID, as_spectator)
local mod_ref = arena_lib.mods[mod]
local arena = mod_ref.arenas[arena_ID]
-- se prova a entrare come spettatore
if as_spectator then
-- aggiungo temporaneamente, sennò non trova l'arena quando va a cercare lo spettatore
players_in_game[p_name] = {minigame = mod, arenaID = arena_ID}
-- se passa i controlli, lo inserisco e notifico i giocatori
if arena_lib.enter_spectate_mode(p_name, arena) then
operations_before_entering_arena(mod_ref, mod, arena, arena_ID, p_name, true)
arena_lib.send_message_in_arena(arena, "both", minetest.colorize("#cfc6b8", ">>> " .. p_name .. " (" .. S("spectator") .. ")"))
-- sennò annullo
else
players_in_game[p_name] = nil
return
end
-- se entra come giocatore
else
if arena_lib.is_player_spectating(p_name) then -- se lo fa mentre è spettatore, controllo che ci sia spazio ecc.
if not arena_lib.leave_spectate_mode(p_name, true) then return end
operations_before_playing_arena(mod_ref, arena, p_name)
else
operations_before_entering_arena(mod_ref, mod, arena, arena_ID, p_name) -- sennò entra normalmente
end
local player = minetest.get_player_by_name(p_name)
-- notifico e teletrasporto
arena_lib.send_message_in_arena(arena, "both", minetest.colorize("#c6f154", " >>> " .. p_name))
player:set_pos(arena_lib.get_random_spawner(arena, arena.players[p_name].teamID))
end
-- eventuale codice aggiuntivo
if mod_ref.on_join then
mod_ref.on_join(p_name, arena, as_spectator)
end
end
-- a partita finita.
-- winner_name può essere stringa (no team) o tabella di nomi (team)
function arena_lib.load_celebration(mod, arena, winner_name)
-- se era già in celebrazione
if arena.in_celebration then
minetest.log("error", "[" .. mod .. "] There was an attempt to call the celebration phase while already in it. This shall not be done, aborting...")
return end
arena.in_celebration = true
arena_lib.update_sign(arena)
-- ripristino HP e visibilità nome di ogni giocatore
for pl_name, stats in pairs(arena.players) do
local player = minetest.get_player_by_name(pl_name)
player:set_nametag_attributes({color = {a = 255, r = 255, g = 255, b = 255}})
end
local winning_message = ""
-- determino il messaggio da inviare
if type(winner_name) == "string" then
winning_message = S("@1 wins the game", winner_name)
elseif type(winner_name) == "table" then
local winner_team_ID = arena.players[winner_name[1]].teamID
winning_message = S("Team @1 wins the game", arena.teams[winner_team_ID].name)
end
local mod_ref = arena_lib.mods[mod]
arena_lib.HUD_send_msg_all("title", arena, winning_message, mod_ref.celebration_time)
-- eventuale codice aggiuntivo
if mod_ref.on_celebration then
mod_ref.on_celebration(arena, winner_name)
end
-- l'arena finisce dopo tot secondi
minetest.after(mod_ref.celebration_time, function()
arena_lib.end_arena(mod_ref, mod, arena, winner_name)
end)
end
function arena_lib.end_arena(mod_ref, mod, arena, winner_name, is_forced)
-- copie da passare a on_end
local spectators = {}
local players = {}
-- rimozione spettatori
for sp_name, sp_stats in pairs(arena.spectators) do
spectators[sp_name] = sp_stats
arena_lib.leave_spectate_mode(sp_name)
players_in_game[sp_name] = nil
operations_before_leaving_arena(mod_ref, arena, sp_name)
end
-- rimozione giocatori
for pl_name, stats in pairs(arena.players) do
players[pl_name] = stats
arena.players[pl_name] = nil
players_in_game[pl_name] = nil
operations_before_leaving_arena(mod_ref, arena, pl_name)
end
-- azzerramento giocatori e spettatori
arena.past_present_players = {}
arena.players_and_spectators = {}
arena.past_present_players_inside = {}
arena.players_amount = 0
if arena.teams_enabled then
for i = 1, #arena.teams do
arena.players_amount_per_team[i] = 0
if mod_ref.spectate_mode then
arena.spectators_amount_per_team[i] = 0
end
end
end
-- azzero il timer
arena.current_time = nil
-- rimuovo eventuali proprietà temporanee
for temp_property, v in pairs(mod_ref.temp_properties) do
arena[temp_property] = nil
end
-- e quelle eventuali di team
if arena.teams_enabled then
for i = 1, #arena.teams do
for t_property, _ in pairs(mod_ref.team_properties) do
arena.teams[i][t_property] = nil
end
end
end
-- effetto particellare
if type(winner_name) == "string" then
local winner = minetest.get_player_by_name(winner_name)
if winner then
show_victory_particles(winner:get_pos())
end
elseif type(winner_name) == "table" then
for _, pl_name in pairs(winner_name) do
local winner = minetest.get_player_by_name(pl_name)
if winner then
show_victory_particles(winner:get_pos())
end
end
end
-- eventuale codice aggiuntivo
if mod_ref.on_end then
mod_ref.on_end(arena, players, winner_name, spectators, is_forced)
end
arena.in_loading = false -- nel caso venga forzata mentre sta caricando, sennò rimane a caricare all'infinito
arena.in_celebration = false
arena.in_game = false
arena_lib.update_sign(arena)
end
----------------------------------------------
--------------------UTILS---------------------
----------------------------------------------
function arena_lib.is_player_in_queue(p_name, mod)
if not players_in_queue[p_name] then
return false
else
-- se il campo mod è specificato, controllo che sia lo stesso
if mod then
if players_in_queue[p_name].minigame == mod then return true
else return false
end
end
return true
end
end
-- mod è opzionale
function arena_lib.is_player_in_arena(p_name, mod)
if not players_in_game[p_name] then
return false
else
-- se il campo mod è specificato, controllo che sia lo stesso
if mod ~= nil then
if players_in_game[p_name].minigame == mod then return true
else return false
end
end
return true
end
end
function arena_lib.add_to_queue(p_name, mod, arena_ID)
local arena = arena_lib.mods[mod].arenas[arena_ID]
arena_lib.send_message_in_arena(arena, "both", minetest.colorize("#c8d692", arena.name .. " > " .. p_name))
players_in_queue[p_name] = {minigame = mod, arenaID = arena_ID}
end
function arena_lib.remove_player_from_queue(p_name)
local mod_ref = arena_lib.mods[arena_lib.get_mod_by_player(p_name)]
local arena = arena_lib.get_arena_by_player(p_name)
if not arena then return end
arena_lib.send_message_in_arena(arena, "both", minetest.colorize("#d69298", arena.name .. " < " .. p_name))
players_in_queue[p_name] = nil
arena.players_amount = arena.players_amount - 1
if arena.teams_enabled then
local p_team_ID = arena.players[p_name].teamID
arena.players_amount_per_team[p_team_ID] = arena.players_amount_per_team[p_team_ID] - 1
end
arena.players[p_name] = nil
arena.players_and_spectators[p_name] = nil
arena_lib.HUD_hide("all", p_name)
local players_required = arena_lib.get_players_to_start_queue(arena)
-- se l'arena era in coda e ora ci son troppi pochi giocatori, annullo la coda
if arena.in_queue and players_required > 0 then
local arena_max_players = arena.max_players * #arena.teams
local timer = minetest.get_node_timer(arena.sign)
timer:stop()
arena.in_queue = false
arena_lib.HUD_hide("broadcast", arena)
arena_lib.HUD_send_msg_all("hotbar", arena, arena_lib.queue_format(arena, S("Waiting for more players...")) .. " (" .. players_required .. ")")
arena_lib.send_message_in_arena(arena, "both", mod_ref.prefix .. S("The queue has been cancelled due to not enough players"))
-- se già non era in coda, aggiorno HUD
elseif players_required > 0 then
arena_lib.HUD_send_msg_all("hotbar", arena, arena_lib.queue_format(arena, S("Waiting for more players...")) .. " (" .. players_required .. ")")
-- idem se è rimasta in coda
else
local seconds = math.floor(minetest.get_node_timer(arena.sign):get_timeout() + 0.5)
arena_lib.HUD_send_msg_all("hotbar", arena, arena_lib.queue_format(arena, S("@1 seconds for the match to start", seconds)))
end
arena_lib.update_sign(arena)
end
function arena_lib.remove_player_from_arena(p_name, reason, executioner)
-- reason 0 = has disconnected
-- reason 1 = has been eliminated
-- reason 2 = has been kicked
-- reason 3 = has quit the arena
assert(reason, "[ARENA_LIB] 'remove_player_from_arena': A reason must be specified!")
-- se il giocatore non è in partita, annullo
if not arena_lib.is_player_in_arena(p_name) then return end
local mod = arena_lib.get_mod_by_player(p_name)
local mod_ref = arena_lib.mods[mod]
local arena = arena_lib.get_arena_by_player(p_name)
-- se il giocatore era in spettatore
if mod_ref.spectate_mode and arena_lib.is_player_spectating(p_name) then
arena_lib.leave_spectate_mode(p_name)
operations_before_leaving_arena(mod_ref, arena, p_name, reason)
arena.past_present_players_inside[p_name] = nil
handle_leaving_callbacks(mod_ref, arena, p_name, reason, executioner, true)
players_in_game[p_name] = nil
return
-- sennò...
else
-- rimuovo
arena.players_amount = arena.players_amount - 1
if arena.teams_enabled then
local p_team_ID = arena.players[p_name].teamID
arena.players_amount_per_team[p_team_ID] = arena.players_amount_per_team[p_team_ID] - 1
end
arena.players[p_name] = nil
-- se ha abbandonato mentre aveva degli spettatori, li riassegno
if arena_lib.is_player_spectated(p_name) then
for sp_name, _ in pairs(arena_lib.get_player_spectators(p_name)) do
arena_lib.find_and_spectate_player(sp_name)
end
end
-- se è stato eliminato, tratto il callback a parte perché è l'unico dove potrebbe venire mandato eventualmente in spettatore
if reason == 1 then
-- manda eventualmente in spettatore
if mod_ref.spectate_mode and arena.players_amount > 0 then
arena_lib.enter_spectate_mode(p_name, arena)
else
operations_before_leaving_arena(mod_ref, arena, p_name)
arena.players_and_spectators[p_name] = nil
arena.past_present_players_inside[p_name] = nil
players_in_game[p_name] = nil
end
if executioner then
arena_lib.send_message_in_arena(arena, "both", minetest.colorize("#f16a54", "<<< " .. S("@1 has been eliminated by @2", p_name, executioner)))
else
arena_lib.send_message_in_arena(arena, "both", minetest.colorize("#f16a54", "<<< " .. S("@1 has been eliminated", p_name)))
end
if mod_ref.on_eliminate then
mod_ref.on_eliminate(arena, p_name)
elseif mod_ref.on_quit then
mod_ref.on_quit(arena, p_name)
end
-- sennò procedo a rimuoverlo normalmente
else
operations_before_leaving_arena(mod_ref, arena, p_name, reason)
arena.players_and_spectators[p_name] = nil
arena.past_present_players_inside[p_name] = nil
players_in_game[p_name] = nil
end
handle_leaving_callbacks(mod_ref, arena, p_name, reason, executioner)
end
-- se è già in celebrazione, non c'è bisogno di andare oltre
if arena.in_celebration then return end
-- se l'ultimo rimasto abbandona con alt+f4, evito il crash
if arena.players_amount == 0 then
arena_lib.end_arena(mod_ref, mod, arena)
-- se l'arena ha i team e sono rimasti solo i giocatori di un team, il loro team vince
elseif arena.teams_enabled and #arena_lib.get_active_teams(arena) == 1 then
local winners
for _, pl_stats in pairs(arena.players) do
winners = arena_lib.get_players_in_team(arena, pl_stats.teamID)
break
end
arena_lib.send_message_in_arena(arena, "players", mod_ref.prefix .. S("There are no other teams left, you win!"))
arena_lib.load_celebration(mod, arena, winners)
-- se invece erano rimasti solo 2 giocatori in partita, l'altro vince
elseif arena.players_amount == 1 then
if reason == 1 then
arena_lib.send_message_in_arena(arena, "players", mod_ref.prefix .. S("You're the last player standing: you win!"))
else
arena_lib.send_message_in_arena(arena, "players", mod_ref.prefix .. S("You win the game due to not enough players"))
end
for pl_name, stats in pairs(arena.players) do
arena_lib.load_celebration(mod, arena, pl_name)
end
end
arena_lib.update_sign(arena)
end
function arena_lib.force_arena_ending(mod, arena, sender)
local mod_ref = arena_lib.mods[mod]
-- se il minigioco non esiste, annullo
if not mod_ref then
minetest.chat_send_player(sender, minetest.colorize("#e6482e", S("[!] This minigame doesn't exist!")))
return end
-- se l'arena non esiste, annullo
if not arena then
minetest.chat_send_player(sender, minetest.colorize("#e6482e", S("[!] This arena doesn't exist!")))
return end
-- se l'arena non è in partita, annullo
if not arena.in_game then
minetest.chat_send_player(sender, minetest.colorize("#e6482e", S("[!] No ongoing game!")))
return end
arena_lib.send_message_in_arena(arena, "both", minetest.colorize("#d69298", S("The arena has been forcibly terminated by @1", sender)))
arena_lib.end_arena(mod_ref, mod, arena, _, true)
return true
end
----------------------------------------------
-----------------GETTERS----------------------
----------------------------------------------
function arena_lib.get_mod_by_player(p_name)
if arena_lib.is_player_in_arena(p_name) then
return players_in_game[p_name].minigame
elseif arena_lib.is_player_in_queue(p_name) then
return players_in_queue[p_name].minigame
else
return end
end
function arena_lib.get_arena_by_player(p_name)
local mod, arenaID
if arena_lib.is_player_in_arena(p_name) then -- è in partita
mod = players_in_game[p_name].minigame
arenaID = players_in_game[p_name].arenaID
elseif arena_lib.is_player_in_queue(p_name) then -- è in coda
mod = players_in_queue[p_name].minigame
arenaID = players_in_queue[p_name].arenaID
else
return end
return arena_lib.mods[mod].arenas[arenaID]
end
function arena_lib.get_arenaID_by_player(p_name)
if players_in_game[p_name] then
return players_in_game[p_name].arenaID
end
end
function arena_lib.get_queueID_by_player(p_name)
if players_in_queue[p_name] then
return players_in_queue[p_name].arenaID
end
end
function arena_lib.get_players_in_game()
return players_in_game
end
function arena_lib.get_players_in_minigame(mod, to_player)
local players_in_minigame = {}
if to_player then
for pl_name, info in pairs(players_in_game) do
if mod == info.minigame then
table.insert(players_in_minigame, minetest.get_player_by_name(pl_name))
end
end
else
for pl_name, info in pairs(players_in_game) do
if mod == info.minigame then
table.insert(players_in_minigame, pl_name)
end
end
end
return players_in_minigame
end
----------------------------------------------
---------------FUNZIONI LOCALI----------------
----------------------------------------------
function assign_team_spawner(spawn_points, ID, p_name, p_team_ID)
for i = ID, #spawn_points do
if p_team_ID == spawn_points[i].teamID then
minetest.get_player_by_name(p_name):set_pos(spawn_points[i].pos)
return i+1
end
end
end
function operations_before_entering_arena(mod_ref, mod, arena, arena_ID, p_name)
players_temp_storage[p_name] = {}
-- applico eventuale musica di sottofondo
if arena.bgm then
players_temp_storage[p_name].bgm_handle = minetest.sound_play(arena.bgm.track, {
gain = arena.bgm.gain,
pitch = arena.bgm.pitch,
to_player = p_name,
loop = true,
})
end
local player = minetest.get_player_by_name(p_name)
-- cambio eventuale volta celeste
if next(arena.celestial_vault) then
local celvault = arena.celestial_vault
if celvault.sky then
players_temp_storage[p_name].celvault_sky = arena_lib.temp.get_sky(player)
player:set_sky(celvault.sky)
end
if celvault.sun then
players_temp_storage[p_name].celvault_sun = player:get_sun()
player:set_sun(celvault.sun)
end
if celvault.moon then
players_temp_storage[p_name].celvault_moon = player:get_moon()
player:set_moon(celvault.moon)
end
if celvault.stars then
players_temp_storage[p_name].celvault_stars = player:get_stars()
player:set_stars(celvault.stars)
end
if celvault.clouds then
players_temp_storage[p_name].celvault_clouds = player:get_clouds()
player:set_clouds(celvault.clouds)
end
end
-- nascondo i nomi se l'opzione è abilitata
if not mod_ref.show_nametags then
player:set_nametag_attributes({color = {a = 0, r = 255, g = 255, b = 255}})
end
-- disattivo eventualmente la minimappa
if not mod_ref.show_minimap then
player:hud_set_flags({minimap = false})
end
-- chiudo eventuali formspec
minetest.close_formspec(p_name, "")
-- svuoto eventualmente l'inventario, decidendo se e come salvarlo
if not mod_ref.keep_inventory then
arena_lib.store_inventory(player)
end
-- li curo
player:set_hp(minetest.PLAYER_MAX_HP_DEFAULT)
-- salvo la hotbar se c'è la spettatore o la hotbar personalizzata
if mod_ref.spectate_mode or mod_ref.hotbar then
players_temp_storage[p_name].hotbar_slots = player:hud_get_hotbar_itemcount()
players_temp_storage[p_name].hotbar_background_image = player:hud_get_hotbar_image()
players_temp_storage[p_name].hotbar_selected_image = player:hud_get_hotbar_selected_image()
end
if not arena_lib.is_player_spectating(p_name) then
operations_before_playing_arena(mod_ref, arena, p_name)
end
-- registro giocatori nella tabella apposita
players_in_queue[p_name] = nil
players_in_game[p_name] = {minigame = mod, arenaID = arena_ID}
end
function operations_before_playing_arena(mod_ref, arena, p_name)
arena.past_present_players[p_name] = true
arena.past_present_players_inside[p_name] = true
local player = minetest.get_player_by_name(p_name)
-- applico eventuale fov
if mod_ref.fov then
players_temp_storage[p_name].fov = player:get_fov()
player:set_fov(mod_ref.fov)
end
-- applico eventuale scostamento camera
if mod_ref.camera_offset then
players_temp_storage[p_name].camera_offset = player:get_eye_offset()
player:set_eye_offset(mod_ref.camera_offset[1], mod_ref.camera_offset[2])
end
-- cambio eventuale colore texture (richiede i team)
if arena.teams_enabled and mod_ref.teams_color_overlay then
player:set_properties({
textures = {player:get_properties().textures[1] .. "^[colorize:" .. mod_ref.teams_color_overlay[arena.players[p_name].teamID] .. ":85"}
})
end
-- cambio l'eventuale hotbar
if mod_ref.hotbar then
local hotbar = mod_ref.hotbar
if hotbar.slots then
player:hud_set_hotbar_itemcount(hotbar.slots)
end
if hotbar.background_image then
player:hud_set_hotbar_image(hotbar.background_image)
end
if hotbar.selected_image then
player:hud_set_hotbar_selected_image(hotbar.selected_image)
end
end
-- imposto eventuale fisica personalizzata
if mod_ref.in_game_physics then
player:set_physics_override(mod_ref.in_game_physics)
end
-- assegno eventuali proprietà giocatori
for k, v in pairs(mod_ref.player_properties) do
if type(v) == "table" then
arena.players[p_name][k] = table.copy(v)
else
arena.players[p_name][k] = v
end
end
end
-- reason parametro opzionale che passo solo quando potrebbe essersi disconnesso
function operations_before_leaving_arena(mod_ref, arena, p_name, reason)
local player = minetest.get_player_by_name(p_name)
-- reimposto eventuale volta celeste
if next(arena.celestial_vault) then
local celvault = arena.celestial_vault
if celvault.sky then
player:set_sky(players_temp_storage[p_name].celvault_sky)
end
if celvault.sun then
player:set_sun(players_temp_storage[p_name].celvault_sun)
end
if celvault.moon then
player:set_moon(players_temp_storage[p_name].celvault_moon)
end
if celvault.stars then
player:set_stars(players_temp_storage[p_name].celvault_stars)
end
if celvault.clouds then
player:set_clouds(players_temp_storage[p_name].celvault_clouds)
end
end
-- svuoto eventualmente l'inventario e ripristino gli oggetti
if not mod_ref.keep_inventory then
player:get_inventory():set_list("main", {})
player:get_inventory():set_list("craft",{})
if arena_lib.STORE_INVENTORY_MODE ~= "none" then
arena_lib.restore_inventory(p_name)
end
end
-- ripristino gli HP
player:set_hp(minetest.PLAYER_MAX_HP_DEFAULT)
-- teletrasporto con un po' di rumore
local clean_pos = mod_ref.settings.hub_spawn_point
local noise_x = math.random(-1.5, 1.5)
local noise_z = math.random(-1.5, 1.5)
local noise_pos = {x = clean_pos.x + noise_x, y = clean_pos.y, z = clean_pos.z + noise_z}
player:set_pos(noise_pos)
-- se si è disconnesso, salta il resto
if reason == 0 then
players_temp_storage[p_name] = nil
return
end
-- se ha partecipato come giocatore
if arena.past_present_players_inside[p_name] then
-- resetto eventuali texture
if arena.teams_enabled and mod_ref.teams_color_overlay then
player:set_properties({
textures = {string.match(player:get_properties().textures[1], "(.*)^%[")}
})
end
-- reimposto eventuale fov
if mod_ref.fov then
player:set_fov(players_temp_storage[p_name].fov)
end
-- ripristino eventuale camera
if mod_ref.camera_offset then
player:set_eye_offset(players_temp_storage[p_name].camera_offset[1], players_temp_storage[p_name].camera_offset[2])
end
end
-- se c'è la spettatore o l'hotbar personalizzata, la ripristino
if mod_ref.spectate_mode or mod_ref.hotbar then
player:hud_set_hotbar_itemcount(players_temp_storage[p_name].hotbar_slots)
player:hud_set_hotbar_image(players_temp_storage[p_name].hotbar_background_image)
player:hud_set_hotbar_selected_image(players_temp_storage[p_name].hotbar_selected_image)
end
-- se ho hub_manager, restituisco gli oggetti e imposto fisica della lobby
if minetest.get_modpath("hub_manager") then
hub_manager.set_items(player)
hub_manager.set_hub_physics(player)
else
player:set_physics_override(arena_lib.SERVER_PHYSICS)
end
-- riattivo la minimappa eventualmente disattivata
player:hud_set_flags({minimap = true})
-- ripristino nomi
player:set_nametag_attributes({color = {a = 255, r = 255, g = 255, b = 255}})
-- disattivo eventuale musica di sottofondo
if arena.bgm then
minetest.sound_stop(players_temp_storage[p_name].bgm_handle)
end
-- svuoto lo storage temporaneo
players_temp_storage[p_name] = nil
end
function handle_leaving_callbacks(mod_ref, arena, p_name, reason, executioner, is_spectator)
local msg_color = reason < 3 and "#f16a54" or "#d69298"
local spect_str = ""
if is_spectator then
msg_color = "#cfc6b8"
spect_str = " (" .. S("spectator") .. ")"
end
-- se si è disconnesso
if reason == 0 then
arena_lib.send_message_in_arena(arena, "both", minetest.colorize(msg_color, "<<< " .. p_name .. spect_str))
if mod_ref.on_disconnect then
mod_ref.on_disconnect(arena, p_name, is_spectator)
end
-- se è stato cacciato
elseif reason == 2 then
if executioner then
arena_lib.send_message_in_arena(arena, "both", minetest.colorize(msg_color, "<<< " .. S("@1 has been kicked by @2", p_name, executioner) .. spect_str))
else
arena_lib.send_message_in_arena(arena, "both", minetest.colorize(msg_color, "<<< " .. S("@1 has been kicked", p_name) .. spect_str))
end
if mod_ref.on_kick then
mod_ref.on_kick(arena, p_name, is_spectator)
elseif mod_ref.on_quit then
mod_ref.on_quit(arena, p_name, is_spectator)
end
-- se ha abbandonato
elseif reason == 3 then
arena_lib.send_message_in_arena(arena, "both", minetest.colorize(msg_color, "<<< " .. S("@1 has quit the match", p_name) .. spect_str))
if mod_ref.on_quit then
mod_ref.on_quit(arena, p_name, is_spectator)
end
end
end
function show_victory_particles(p_pos)
minetest.add_particlespawner({
amount = 50,
time = 0.6,
minpos = p_pos,
maxpos = p_pos,
minvel = {x=-2, y=-2, z=-2},
maxvel = {x=2, y=2, z=2},
minsize = 1,
maxsize = 3,
texture = "arenalib_winparticle.png"
})
end
function time_start(mod_ref, arena)
if arena.on_celebration or not arena.in_game then return end
if mod_ref.time_mode == "incremental" then
arena.current_time = arena.current_time + 1
else
arena.current_time = arena.current_time - 1
end
if arena.current_time <= 0 then
assert(mod_ref.on_timeout, "[ARENA_LIB] " .. S("[!] on_timeout callback must be declared to properly use a decreasing timer!"))
mod_ref.on_timeout(arena)
return
elseif mod_ref.on_time_tick then
mod_ref.on_time_tick(arena)
end
minetest.after(1, function()
time_start(mod_ref, arena)
end)
end