2021-02-17 13:18:09 -08:00
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
2022-01-23 14:57:49 -08:00
local function victory_particles ( ) end
2021-02-17 13:18:09 -08:00
local function show_victory_particles ( ) end
local function time_start ( ) end
2022-01-23 14:57:49 -08:00
local function deprecated_winning_team_celebration ( ) end
2021-02-17 13:18:09 -08:00
local players_in_game = { } -- 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,
2022-05-26 08:13:16 -07:00
-- (int) bgm_handle, (int) fov, (table) camera_offset, (table) armor_groups}
2021-02-17 13:18:09 -08:00
-- 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
2022-01-22 04:17:48 -08:00
-- randomizzo gli spawner se non è a squadre
2021-02-17 13:18:09 -08:00
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
2022-01-22 04:17:48 -08:00
-- sennò ordino i giocatori per squadra
2021-02-17 13:18:09 -08:00
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
2022-01-22 04:17:48 -08:00
-- e aggiungo eventuali proprietà per ogni squadra
2021-02-17 13:18:09 -08:00
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
2022-05-25 14:25:39 -07:00
-- se supporta la spettatore, inizializzo le varie tabelle
if mod_ref.spectate_mode then
2022-05-27 14:12:15 -07:00
arena.spectate_entities_amount = 0
arena.spectate_areas_amount = 0
2022-05-25 14:25:39 -07:00
arena_lib.init_spectate_containers ( mod , arena.name )
end
2021-02-17 13:18:09 -08:00
-- eventuale codice aggiuntivo
if mod_ref.on_load then
mod_ref.on_load ( arena )
end
2022-05-25 14:25:39 -07:00
-- avvio la partita dopo tot secondi
2021-02-17 13:18:09 -08:00
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 )
2021-02-24 15:16:19 -08:00
arena_lib.send_message_in_arena ( arena , " both " , minetest.colorize ( " #cfc6b8 " , " >>> " .. p_name .. " ( " .. S ( " spectator " ) .. " ) " ) )
2021-02-17 13:18:09 -08:00
-- 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
2021-02-24 15:16:19 -08:00
arena_lib.send_message_in_arena ( arena , " both " , minetest.colorize ( " #c6f154 " , " >>> " .. p_name ) )
2021-02-17 13:18:09 -08:00
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
2022-05-30 15:25:42 -07:00
-- a partita finita
-- `winners` può essere stringa (giocatore singolo), intero (squadra) o tabella di uno di questi (più giocatori o squadre)
2022-01-23 14:57:49 -08:00
function arena_lib . load_celebration ( mod , arena , winners )
2021-02-17 13:18:09 -08:00
-- se era già in celebrazione
if arena.in_celebration then
2022-05-30 15:25:42 -07:00
minetest.log ( " error " , debug.traceback ( " [ " .. mod .. " ] There has been an attempt to call the celebration phase whilst already in it. This shall not be done, aborting... " ) )
2021-02-17 13:18:09 -08:00
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
2022-01-23 14:57:49 -08:00
-- se è stringa, è giocatore singolo
if type ( winners ) == " string " then
winning_message = S ( " @1 wins the game " , winners )
-- se è un ID è una squadra
elseif type ( winners ) == " number " then
winning_message = S ( " Team @1 wins the game " , arena.teams [ winners ] . name )
-- se è una tabella, può essere o più giocatori singoli, o più squadre
elseif type ( winners ) == " table " then
-- v DEPRECATED, da rimuovere in 6.0 ----- v
if arena.teams_enabled and type ( winners [ 1 ] ) == " string " then
winning_message = deprecated_winning_team_celebration ( mod , arena , winners )
-- ^ -------------------------------------^
elseif type ( winners [ 1 ] ) == " string " then
for _ , pl_name in pairs ( winners ) do
winning_message = winning_message .. pl_name .. " , "
end
winning_message = S ( " @1 win the game " , winning_message : sub ( 1 , - 3 ) )
else
for _ , team_ID in pairs ( winners ) do
winning_message = winning_message .. arena.teams [ team_ID ] . name .. " , "
end
winning_message = S ( " Teams @1 win the game " , winning_message : sub ( 1 , - 3 ) )
end
2021-02-17 13:18:09 -08:00
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
2022-01-23 14:57:49 -08:00
mod_ref.on_celebration ( arena , winners )
2021-02-17 13:18:09 -08:00
end
-- l'arena finisce dopo tot secondi
minetest.after ( mod_ref.celebration_time , function ( )
2022-01-23 14:57:49 -08:00
arena_lib.end_arena ( mod_ref , mod , arena , winners )
2021-02-17 13:18:09 -08:00
end )
end
2022-01-23 14:57:49 -08:00
function arena_lib . end_arena ( mod_ref , mod , arena , winners , is_forced )
2021-02-17 13:18:09 -08:00
-- 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
2022-05-27 14:12:15 -07:00
-- dealloca eventuale modalità spettatore
if mod_ref.spectate_mode then
arena.spectate_entities_amount = nil
arena.spectate_areas_amount = nil
arena_lib.unload_spectate_containers ( mod , arena.name )
end
2022-05-25 14:25:39 -07:00
2021-02-17 13:18:09 -08:00
-- 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
2022-01-22 04:17:48 -08:00
-- e quelle eventuali di squadra
2021-02-17 13:18:09 -08:00
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
2022-01-23 14:57:49 -08:00
victory_particles ( arena , players , winners )
2021-02-17 13:18:09 -08:00
-- eventuale codice aggiuntivo
if mod_ref.on_end then
2022-01-23 14:57:49 -08:00
mod_ref.on_end ( arena , players , winners , spectators , is_forced )
2021-02-17 13:18:09 -08:00
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---------------------
----------------------------------------------
-- 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 . 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 )
2021-02-27 04:09:35 -08:00
operations_before_leaving_arena ( mod_ref , arena , p_name , reason )
2021-02-26 13:16:28 -08:00
arena.past_present_players_inside [ p_name ] = nil
2021-02-17 13:18:09 -08:00
handle_leaving_callbacks ( mod_ref , arena , p_name , reason , executioner , true )
players_in_game [ p_name ] = nil
2021-03-12 07:16:09 -08:00
return
2021-02-17 13:18:09 -08:00
-- 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
2021-02-27 04:09:35 -08:00
operations_before_leaving_arena ( mod_ref , arena , p_name , reason )
2021-02-17 13:18:09 -08:00
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 )
2022-01-23 14:57:49 -08:00
-- se l'arena è a squadre e sono rimasti solo i giocatori di una squadra, la loro squadra vince
2021-02-17 13:18:09 -08:00
elseif arena.teams_enabled and # arena_lib.get_active_teams ( arena ) == 1 then
2022-01-23 14:57:49 -08:00
local winning_team_id = arena_lib.get_active_teams ( arena ) [ 1 ]
2021-02-17 13:18:09 -08:00
arena_lib.send_message_in_arena ( arena , " players " , mod_ref.prefix .. S ( " There are no other teams left, you win! " ) )
2022-01-23 14:57:49 -08:00
arena_lib.load_celebration ( mod , arena , winning_team_id )
2021-02-17 13:18:09 -08:00
-- 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 ) ) )
2022-01-30 08:58:27 -08:00
arena_lib.end_arena ( mod_ref , mod , arena , nil , true )
2021-02-17 13:18:09 -08:00
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
2022-06-05 05:20:28 -07:00
return arena_lib.get_mod_by_queuing_player ( p_name )
end
2021-02-17 13:18:09 -08:00
end
function arena_lib . get_arena_by_player ( p_name )
if arena_lib.is_player_in_arena ( p_name ) then -- è in partita
2022-06-05 05:20:28 -07:00
local mod = players_in_game [ p_name ] . minigame
local arenaID = players_in_game [ p_name ] . arenaID
2021-02-17 13:18:09 -08:00
2022-06-05 05:20:28 -07:00
return arena_lib.mods [ mod ] . arenas [ arenaID ]
elseif arena_lib.is_player_in_queue ( p_name ) then -- è in coda
return arena_lib.get_arena_by_queuing_player ( p_name )
end
2021-02-17 13:18:09 -08:00
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_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 )
2022-04-01 03:26:26 -07:00
-- cambio eventuale illuminazione
if arena.lighting then
players_temp_storage [ p_name ] . lighting = {
light = player : get_day_night_ratio ( )
}
local lighting = arena.lighting
if lighting.light then
player : override_day_night_ratio ( lighting.light )
end
--TODO MT 5.6: set_lighting (shadows)
end
2022-01-07 14:14:41 -08:00
-- cambio eventuale volta celeste
2022-04-03 15:03:53 -07:00
if arena.celestial_vault then
2022-01-07 14:14:41 -08:00
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
2021-02-17 13:18:09 -08:00
-- 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
-- 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_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
2022-05-25 14:25:39 -07:00
-- aggiungo eventuale contenitore mod spettatore
2022-01-22 04:17:48 -08:00
if mod_ref.spectate_mode then
2022-05-25 14:25:39 -07:00
arena_lib.add_spectate_p_container ( p_name )
2022-01-22 04:17:48 -08:00
end
2021-02-17 13:18:09 -08:00
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
2022-02-02 16:16:15 -08:00
players_temp_storage [ p_name ] . camera_offset = { player : get_eye_offset ( ) }
2021-02-17 13:18:09 -08:00
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
2022-01-22 04:19:01 -08:00
-- li sgancio da eventuali entità (non lo faccio agli spettatori perché sono già
-- agganciati al giocatore, sennò cadono nel vuoto)
player : set_detach ( )
2022-05-26 08:13:16 -07:00
-- se il danno da caduta è disabilitato, disattivo il flash all'impatto
if table.indexof ( mod_ref.disabled_damage_types , " fall " ) > 0 then
players_temp_storage [ p_name ] . armor_groups = player : get_armor_groups ( )
local armor_groups = player : get_armor_groups ( )
armor_groups.fall_damage_add_percent = - 100
player : set_armor_groups ( armor_groups )
end
2022-01-27 13:07:31 -08:00
-- li curo
player : set_hp ( minetest.PLAYER_MAX_HP_DEFAULT )
2021-02-17 13:18:09 -08:00
-- 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
2021-02-27 04:09:35 -08:00
-- reason parametro opzionale che passo solo quando potrebbe essersi disconnesso
function operations_before_leaving_arena ( mod_ref , arena , p_name , reason )
2021-02-17 13:18:09 -08:00
2022-04-01 03:26:26 -07:00
-- disattivo eventuale musica di sottofondo
if arena.bgm then
minetest.sound_stop ( players_temp_storage [ p_name ] . bgm_handle )
end
2021-02-17 13:18:09 -08:00
local player = minetest.get_player_by_name ( p_name )
2022-04-01 03:26:26 -07:00
-- reimposto eventuale illuminazione
if arena.lighting then
player : override_day_night_ratio ( players_temp_storage [ p_name ] . lighting.light )
end
2022-01-07 14:14:41 -08:00
-- reimposto eventuale volta celeste
2022-04-03 15:03:53 -07:00
if arena.celestial_vault then
2022-01-07 14:14:41 -08:00
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
2021-02-17 13:18:09 -08:00
-- 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
2022-05-26 08:13:16 -07:00
local armor_groups = players_temp_storage [ p_name ] . armor_groups
-- riassegno eventuali gruppi armatura (per il flash da impatto caduta)
if armor_groups then
player : set_armor_groups ( armor_groups )
end
2021-02-27 04:09:35 -08:00
-- 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 )
2022-04-24 02:13:52 -07:00
-- TEMP: waiting for https://github.com/minetest/minetest/issues/12092 to be fixed. Forcing the teleport twice on two different steps
minetest.after ( 0.1 , function ( )
if not minetest.get_player_by_name ( p_name ) then return end
player : set_pos ( noise_pos )
end )
2021-02-27 04:09:35 -08:00
-- se si è disconnesso, salta il resto
if reason == 0 then
players_temp_storage [ p_name ] = nil
return
2021-02-17 13:18:09 -08:00
end
-- se ha partecipato come giocatore
if arena.past_present_players_inside [ p_name ] then
2022-05-25 14:25:39 -07:00
-- rimuovo eventuale contenitore mod spettatore
2022-01-22 04:17:48 -08:00
if mod_ref.spectate_mode then
2022-05-25 14:25:39 -07:00
arena_lib.remove_spectate_p_container ( p_name )
2022-01-22 04:17:48 -08:00
end
2022-05-25 14:25:39 -07:00
-- ripristino eventuali texture
2021-02-17 13:18:09 -08:00
if arena.teams_enabled and mod_ref.teams_color_overlay then
player : set_properties ( {
textures = { string.match ( player : get_properties ( ) . textures [ 1 ] , " (.*)^%[ " ) }
} )
end
2022-05-25 14:25:39 -07:00
-- ripristino eventuale fov
2021-02-17 13:18:09 -08:00
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
2021-02-27 04:09:35 -08:00
-- 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
2021-02-17 13:18:09 -08:00
-- 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 } } )
-- 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
2022-01-23 14:57:49 -08:00
function victory_particles ( arena , players , winners )
-- singolo giocatore
if type ( winners ) == " string " then
local winner = minetest.get_player_by_name ( winners )
if winner then
show_victory_particles ( winner : get_pos ( ) )
end
-- singola squadra
elseif type ( winners ) == " number " then
for pl_name , pl_stats in pairs ( players ) do
if pl_stats.teamID == winners then
local winner = minetest.get_player_by_name ( pl_name )
if winner then
show_victory_particles ( winner : get_pos ( ) )
end
end
end
-- più vincitori
elseif type ( winners ) == " table " then
-- v DEPRECATED, da rimuovere in 6.0 ----- v
if arena.teams_enabled and type ( winners [ 1 ] ) == " string " then
local teamID = 0
for pl_name , pl_stats in pairs ( players ) do
if pl_name == winners [ 1 ] then
teamID = pl_stats.teamID
break
end
end
for pl_name , pl_stats in pairs ( players ) do
if pl_stats.teamID == winners then
local winner = minetest.get_player_by_name ( pl_name )
if winner then
show_victory_particles ( winner : get_pos ( ) )
end
end
end
-- ^ -------------------------------------^
-- singoli giocatori
elseif type ( winners [ 1 ] ) == " string " then
for _ , pl_name in pairs ( winners ) do
local winner = minetest.get_player_by_name ( pl_name )
if winner then
show_victory_particles ( winner : get_pos ( ) )
end
end
-- squadre
else
for _ , team_ID in pairs ( winners ) do
local team = arena.teams [ team_ID ]
for pl_name , pl_stats in pairs ( players ) do
if pl_stats.teamID == team_ID then
local winner = minetest.get_player_by_name ( pl_name )
if winner then
show_victory_particles ( winner : get_pos ( ) )
end
end
end
end
end
end
end
2021-02-17 13:18:09 -08:00
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
2022-01-23 14:57:49 -08:00
----------------------------------------------
------------------DEPRECATED------------------
----------------------------------------------
-- to remove in 6.0
function deprecated_winning_team_celebration ( mod , arena , winners )
minetest.log ( " warning " , debug.traceback ( " [ARENA_LIB - " .. mod .. " ] passing a single winning team as a table made of one of its players is deprecated, "
.. " please pass the (integer) team ID instead " ) )
local winner = arena.players [ winners [ 1 ] ] . teamID
return S ( " Team @1 wins the game " , arena.teams [ winner ] . name )
end