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 victory_particles() end local function show_victory_particles() end local function time_start() end local function deprecated_winning_team_celebration() end 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, -- (int) bgm_handle, (int) fov, (table) camera_offset, (table) armor_groups} -- 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 squadre 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 squadra 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 squadra 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 -- se supporta la spettatore, inizializzo le varie tabelle if mod_ref.spectate_mode then arena.spectate_entities_amount = 0 arena.spectate_areas_amount = 0 arena_lib.init_spectate_containers(mod, arena.name) end -- eventuale codice aggiuntivo if mod_ref.on_load then mod_ref.on_load(arena) end -- avvio la partita 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 -- `winners` può essere stringa (giocatore singolo), intero (squadra) o tabella di uno di questi (più giocatori o squadre) function arena_lib.load_celebration(mod, arena, winners) -- se era già in celebrazione if arena.in_celebration then 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...")) 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 -- 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 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, winners) end -- l'arena finisce dopo tot secondi minetest.after(mod_ref.celebration_time, function() arena_lib.end_arena(mod_ref, mod, arena, winners) end) end function arena_lib.end_arena(mod_ref, mod, arena, winners, 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 -- 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 -- 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 squadra 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 victory_particles(arena, players, winners) -- eventuale codice aggiuntivo if mod_ref.on_end then mod_ref.on_end(arena, players, winners, 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--------------------- ---------------------------------------------- -- 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) 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 è a squadre e sono rimasti solo i giocatori di una squadra, la loro squadra vince elseif arena.teams_enabled and #arena_lib.get_active_teams(arena) == 1 then local winning_team_id = arena_lib.get_active_teams(arena)[1] 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, winning_team_id) -- 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, nil, 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 arena_lib.get_mod_by_queuing_player(p_name) end end function arena_lib.get_arena_by_player(p_name) if arena_lib.is_player_in_arena(p_name) then -- è in partita local mod = players_in_game[p_name].minigame local arenaID = players_in_game[p_name].arenaID 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 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) -- 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 -- cambio eventuale volta celeste if 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 -- 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 -- aggiungo eventuale contenitore mod spettatore if mod_ref.spectate_mode then arena_lib.add_spectate_p_container(p_name) end 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 -- li sgancio da eventuali entità (non lo faccio agli spettatori perché sono già -- agganciati al giocatore, sennò cadono nel vuoto) player:set_detach() -- 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 -- li curo player:set_hp(minetest.PLAYER_MAX_HP_DEFAULT) -- 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) -- disattivo eventuale musica di sottofondo if arena.bgm then minetest.sound_stop(players_temp_storage[p_name].bgm_handle) end local player = minetest.get_player_by_name(p_name) -- reimposto eventuale illuminazione if arena.lighting then player:override_day_night_ratio(players_temp_storage[p_name].lighting.light) end -- reimposto eventuale volta celeste if 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 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 -- 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) -- 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) -- 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 -- rimuovo eventuale contenitore mod spettatore if mod_ref.spectate_mode then arena_lib.remove_spectate_p_container(p_name) end -- ripristino 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 -- ripristino 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}}) -- 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 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 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 ---------------------------------------------- ------------------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