* Spectate: add "blind"
mode
* Spectate: add item to rotate between party members * Follow party members first when getting eliminated and joining spectate mode * Add utils `get_party_members_playing(..)` and `get_party_members_spectating(..)`
This commit is contained in:
parent
a1394e7499
commit
2291ec8e3b
15
DOCS.md
15
DOCS.md
@ -132,7 +132,7 @@ The second field, on the contrary, is a table of optional parameters: they defin
|
||||
* `end_when_too_few`: (bool) whether the minigame should end its matches when only one player/team is left. Default il `true`
|
||||
* `eliminate_on_death`: (bool) whether players are automatically eliminated when dying (both `on_death` and `on_eliminate` callbacks are called, in this order). Default is `false`
|
||||
* `join_while_in_progress`: (bool) whether the minigame allows to join an ongoing match. Default is `false`
|
||||
* `spectate_mode`: (bool) whether the minigame features the spectator mode. Default is `true`
|
||||
* `spectate_mode`: (string/bool) whether the minigame features the spectator mode. It can be `"all"`, `"blind"` or `false`. Default is `"all"`. See [2.5 Spectate mode](#25-spectate-mode) for further information
|
||||
* `regenerate_map`: (bool) whether to regenerate the maps of the minigame between a game and another. Default is `false`. Be sure to check [Map regeneration](#2231-map-regeneration) first
|
||||
* `can_build`: (bool) whether players are allowed to place or dig nodes during a match. Default is `false`
|
||||
* `can_drop`: (bool) whether players can drop items during a match. Default is `true`
|
||||
@ -435,6 +435,10 @@ There are also some other functions which might turn useful. They are:
|
||||
* `arena_lib.get_spectatable_areas(mod, arena_name)`: same as in `get_spectatable_entities(..)` but for areas. Entities returned in the table are the dummy ObjectRef entities put at the area coordinates
|
||||
* `arena_lib.get_player_in_edit_mode(arena_name)`: returns the name of the player who's editing `arena_name`, if any
|
||||
|
||||
Requiring `parties`:
|
||||
* `arena_lib.get_party_members_playing(p_name, arena)`: returns a table containing as value the names of all the party members of `p_name` currently playing in `arena`
|
||||
* `arena_lib.get_party_members_spectating(p_name, arena)`: returns a table containing as value the names of all the party members of `p_name` currently spectating in `arena`
|
||||
|
||||
### 1.10 Endless minigames
|
||||
As the name suggests, endless minigames have got no end. When the server starts, all the enabled arenas of an endless minigame are automatically loaded and the only way to stop them is to disable them (e.g. by entering the editor). Calling the end of an arena will also try to disable the arena (i.e. through `/arenas forceend` or the respective function `force_end`); in case the disabling process should fail, the arena will be automatically launched again.
|
||||
|
||||
@ -727,8 +731,13 @@ On the contrary, `on_assign_team(arena, p_name)` is only applied to `p_name` (an
|
||||
|
||||
|
||||
### 2.5 Spectate mode
|
||||
Every minigame has this mode enabled by default. As the name suggests, it allows people to spectate a match, and there are two ways to enter this mode: the first is by getting eliminated (`remove_player_from_arena` with `1` as a reason), whereas the other is through the very entrance of the arena (if implemented). While in this state, they can't interact in any way with the actual match: neither by hitting entities/blocks, nor by writing in chat. The latter, more precisely, is a separated chat that spectators and spectators only are able to read. Vice versa, they're not able to read the players one.
|
||||
By default, spectate mode allows to follow players, but it also allows modders to expand it to entities and areas. To do that, have a look at `arena_lib.add_spectate_entity(..)` and `arena_lib.add_spectate_area(..)`
|
||||
Every minigame has this mode enabled by default. As the name suggests, it allows people to spectate a match, and there are two ways to enter this mode: the first is by getting eliminated (`remove_player_from_arena` with `1` as a reason), whereas the other is through the very entrance of the arena (if implemented). While in this state, spectators are invisible and they can't interact in any way with the actual match: neither by hitting entities/blocks, nor by writing in chat. The latter, more precisely, is a separated chat that spectators and spectators only are able to read. Vice versa, players can only read players' chat.
|
||||
|
||||
Spectate mode comes in two variants: `"all"` and `"blind"`.
|
||||
* `"all"` allows to rotate between all the players in a match, and it also allows modders to expand the spectatable targets to entities and areas. To do that, have a look at `arena_lib.add_spectate_entity(..)` and `arena_lib.add_spectate_area(..)`. In this variant, people can join from outside.
|
||||
* `"blind"`, on the contrary, it doesn't support custom targets and it allows players to rotate only between their teams (if teams are supported) or their party members (if they're in a party). If they're in neither, they'll be stuck with the player assigned once eliminated. In this variant, people cannot join from outside.
|
||||
|
||||
No matter the variant, the priority to determine whom to automatically follow when entering spectate mode or when your target disappears is team/party -> executor -> random.
|
||||
<br>
|
||||
|
||||
|
||||
|
@ -140,6 +140,7 @@ There is no entrance to remove assigned to @1!=Es gibt keinen an @1 zugewiesenen
|
||||
##[ src/api/in_game.lua ]##
|
||||
No ongoing game!=Kein laufendes Spiel!
|
||||
Spectate mode not supported!=Zuschauermodus nicht unterstützt!
|
||||
This minigame doesn't allow spectators to join from outside!=
|
||||
There is nothing to spectate!=Es gibt nichts zum Zuschauen!
|
||||
The arena is loading, try again in a few seconds!=Die Arena lädt, bitte versuchen Sie es in ein paar Sekunden erneut!
|
||||
This minigame doesn't allow to join while in progress!=Dieses Minispiel erlaubt keinen Beitritt, während es läuft!
|
||||
|
@ -140,6 +140,7 @@ There is no entrance to remove assigned to @1!=
|
||||
##[ src/api/in_game.lua ]##
|
||||
No ongoing game!=¡Ninguna partida en curso!
|
||||
Spectate mode not supported!=¡Modo espectador no admitido!
|
||||
This minigame doesn't allow spectators to join from outside!=
|
||||
There is nothing to spectate!=¡No hay nada que asistir!
|
||||
The arena is loading, try again in a few seconds!=¡La arena está cargando, reinténtalo en unos pocos segundos!
|
||||
This minigame doesn't allow to join while in progress!=¡Este minijuego no permite entrar cuando la partida ha comenzado!
|
||||
|
@ -140,6 +140,7 @@ There is no entrance to remove assigned to @1!=
|
||||
##[ src/api/in_game.lua ]##
|
||||
No ongoing game!=Nincs folyamatban kévő menet!
|
||||
Spectate mode not supported!=Nézői mód nem támogatott!
|
||||
This minigame doesn't allow spectators to join from outside!=
|
||||
There is nothing to spectate!=Nincs mit nézni!
|
||||
The arena is loading, try again in a few seconds!=Az aréna tölt próbáld ujra pár másodperc mulva!
|
||||
This minigame doesn't allow to join while in progress!=Ez a minigame nem engedi a csatlakozást menet közben!
|
||||
|
@ -140,6 +140,7 @@ There is no entrance to remove assigned to @1!=Non c'è nessun'entrata da rimuov
|
||||
##[ src/api/in_game.lua ]##
|
||||
No ongoing game!=Nessuna partita in corso!
|
||||
Spectate mode not supported!=Modalità assisti non supportata!
|
||||
This minigame doesn't allow spectators to join from outside!=Questo minigioco non permette allɜ spettatorɜ di entrare da fuori!
|
||||
There is nothing to spectate!=Non c'è niente a cui assistere!
|
||||
The arena is loading, try again in a few seconds!=L'arena è in caricamento, riprova tra qualche secondo!
|
||||
This minigame doesn't allow to join while in progress!=Questo minigioco non permette di entrare a partita iniziata!
|
||||
|
@ -140,6 +140,7 @@ There is no entrance to remove assigned to @1!=Nie ma żadnego przypisanego do @
|
||||
##[ src/api/in_game.lua ]##
|
||||
No ongoing game!=Brak trwającej gry!
|
||||
Spectate mode not supported!=Tryb obserwatora nie jest wspierany!
|
||||
This minigame doesn't allow spectators to join from outside!=
|
||||
There is nothing to spectate!=Nie ma niczego do obserwowania!
|
||||
The arena is loading, try again in a few seconds!=Arena się ładuje, spróbuj ponownie po kilku sekundach!
|
||||
This minigame doesn't allow to join while in progress!=Nie można dołączyć do tej minigry, kiedy jest w toku!
|
||||
|
@ -140,6 +140,7 @@ There is no entrance to remove assigned to @1!=
|
||||
##[ src/api/in_game.lua ]##
|
||||
No ongoing game!=Игра не запущена!
|
||||
Spectate mode not supported!=Режим наблюдения не поддерживается!
|
||||
This minigame doesn't allow spectators to join from outside!=
|
||||
There is nothing to spectate!=Тут незачем наблюдать!
|
||||
The arena is loading, try again in a few seconds!=Арена загружается, попробуйте через несколько секунд!
|
||||
This minigame doesn't allow to join while in progress!=Эта мини-игра не позволяет входить во время игры!
|
||||
|
@ -140,6 +140,7 @@ There is no entrance to remove assigned to @1!=
|
||||
##[ src/api/in_game.lua ]##
|
||||
No ongoing game!=
|
||||
Spectate mode not supported!=
|
||||
This minigame doesn't allow spectators to join from outside!=
|
||||
There is nothing to spectate!=
|
||||
The arena is loading, try again in a few seconds!=
|
||||
This minigame doesn't allow to join while in progress!=
|
||||
|
@ -138,6 +138,11 @@ function arena_lib.register_minigame(mod, def)
|
||||
def.chat_settings.color_spectate = def.chat_spectate_color
|
||||
minetest.log("warning", "[ARENA_LIB] (" .. mod .. ") chat_spectate_color is deprecated. Use chat_settings = {color_spectate = \"some color\"} instead")
|
||||
end
|
||||
|
||||
if def.spectate_mode == true then
|
||||
def.spectate_mode = "all"
|
||||
minetest.log("warning", "[ARENA_LIB] (" .. mod .. ") spectate_mode = true is deprecated. Use spectate_mode = \"all\" instead")
|
||||
end
|
||||
--^------------------ LEGACY UPDATE, to remove in 9.0 -------------------^
|
||||
|
||||
arena_lib.mods[mod] = {}
|
||||
@ -197,7 +202,7 @@ function arena_lib.register_minigame(mod, def)
|
||||
mod_ref.end_when_too_few = true
|
||||
mod_ref.eliminate_on_death = false
|
||||
mod_ref.join_while_in_progress = false
|
||||
mod_ref.spectate_mode = true
|
||||
mod_ref.spectate_mode = "all"
|
||||
mod_ref.regenerate_map = false
|
||||
mod_ref.can_build = false
|
||||
mod_ref.can_drop = true
|
||||
@ -365,8 +370,16 @@ function arena_lib.register_minigame(mod, def)
|
||||
mod_ref.join_while_in_progress = true
|
||||
end
|
||||
|
||||
if def.spectate_mode == false then
|
||||
mod_ref.spectate_mode = false
|
||||
if def.spectate_mode then
|
||||
local spectate_mode = def.spectate_mode
|
||||
if spectate_mode == "blind" or spectate_mode == false then
|
||||
if spectate_mode == "blind" then
|
||||
assert(not mod_ref.endless, "[ARENA_LIB] Endless mode can't support \"blind\" spectate mode!")
|
||||
assert(not mod_ref.join_while_in_progress, "[ARENA_LIB] Join while in progress can't be `true` in \"blind\" spectate mode!")
|
||||
end
|
||||
|
||||
mod_ref.spectate_mode = spectate_mode
|
||||
end
|
||||
end
|
||||
|
||||
if def.regenerate_map == true then
|
||||
|
@ -20,6 +20,8 @@ local players_temp_storage = {} -- KEY: p_name, VALUE: {(int) hotbar_sl
|
||||
-- (table) player_aspect, (int) fov, (table) camera_offset, (table) armor_groups, (string) inventory_fs,
|
||||
-- (table) attachments, (table) nametag, (table) celvault_sky, (table) celvault_sun, (table) celvault_moon,
|
||||
-- (table) celvault_stars, (table) celvault_clouds, (int) weather_ID}
|
||||
local is_parties_enabled = minetest.get_modpath("parties")
|
||||
|
||||
|
||||
|
||||
function arena_lib.load_arena(mod, arena_ID)
|
||||
@ -165,10 +167,14 @@ function arena_lib.join_arena(mod, p_name, arena_ID, as_spectator)
|
||||
-- se prova a entrare come spettante
|
||||
if as_spectator then
|
||||
-- se non supporta la spettatore
|
||||
if not arena_lib.mods[mod].spectate_mode then
|
||||
if mod_ref.spectate_mode == false then
|
||||
arena_lib.print_error(p_name, S("Spectate mode not supported!"))
|
||||
return end
|
||||
|
||||
if mod_ref.spectate_mode == "blind" then
|
||||
arena_lib.print_error(p_name, S("This minigame doesn't allow spectators to join from outside!"))
|
||||
return end
|
||||
|
||||
-- se l'arena non è abilitata
|
||||
if not arena.enabled then
|
||||
arena_lib.print_error(p_name, S("The arena is not enabled!"))
|
||||
@ -490,9 +496,9 @@ function arena_lib.remove_player_from_arena(p_name, reason, xc_name, elim_msg)
|
||||
-- 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!")
|
||||
assert(reason, "[ARENA_LIB] 'remove_player_from_arena': a reason must be specified!")
|
||||
|
||||
-- se lə giocatorə non è in partita, annullo
|
||||
-- se lə giocante 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)
|
||||
@ -500,7 +506,7 @@ function arena_lib.remove_player_from_arena(p_name, reason, xc_name, elim_msg)
|
||||
local arena = arena_lib.get_arena_by_player(p_name)
|
||||
local p_properties -- copia da passare ai richiami
|
||||
|
||||
-- se lə giocatorə era in spettatore
|
||||
-- se lə giocante era in spettatore
|
||||
if mod_ref.spectate_mode and arena_lib.is_player_spectating(p_name) then
|
||||
p_properties = table.copy(arena.spectators[p_name])
|
||||
arena_lib.leave_spectate_mode(p_name)
|
||||
@ -518,29 +524,81 @@ function arena_lib.remove_player_from_arena(p_name, reason, xc_name, elim_msg)
|
||||
|
||||
p_properties = table.copy(arena.players[p_name])
|
||||
|
||||
local p_team_ID = arena.players[p_name].teamID
|
||||
|
||||
-- rimuovo
|
||||
arena.players_amount = arena.players_amount - 1
|
||||
if arena.teams_enabled then
|
||||
local p_team_ID = arena.players[p_name].teamID
|
||||
|
||||
if p_team_ID then
|
||||
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
|
||||
-- se ha abbandonato mentre aveva dellɜ spettanti, lɜ riassegno
|
||||
if arena_lib.is_player_spectated(p_name) then
|
||||
-- se è "blind", ci son squadre e la sua squadra == 0, prendi tutta la gente e mettila su altra squadra
|
||||
if mod_ref.spectate_mode == "blind" and arena.teams_enabled and arena.players_amount_per_team[p_team_ID] == 0 then
|
||||
local target_name = xc_name
|
||||
-- se è mortə da solə, cerca una squadra a caso
|
||||
if not target_name or reason ~= 1 then
|
||||
for team_id, amnt in ipairs(arena.players_amount_per_team) do
|
||||
if amnt > 0 then
|
||||
for pl_name, pl_data in pairs(arena.players) do
|
||||
if pl_data.teamID == team_id then
|
||||
target_name = pl_name
|
||||
break
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for sp_name, _ in pairs(arena_lib.get_player_spectators(p_name)) do
|
||||
if reason == 1 and xc_name and minetest.get_player_by_name(xc_name) and sp_name ~= xc_name then -- sp_name ~= xc_name in caso si uccidano più o meno nello stesso istante
|
||||
arena_lib.spectate_target(mod, arena, sp_name, "player", target_name)
|
||||
end
|
||||
|
||||
-- sennò riassegna normalmente
|
||||
else
|
||||
-- aggiornamenti vari barra delle azioni per spettanti che non vengono spostatɜ
|
||||
-- TODO: togli ruota giocante se a squadre e squadra p_name ora ha solo 1 membro rimasto
|
||||
-- se era in gruppo, controlla se va aggiornata la barra delle azioni
|
||||
if is_parties_enabled and parties.is_player_in_party(p_name) then
|
||||
for _, spp_name in ipairs(arena_lib.get_party_members_spectating(p_name, arena)) do
|
||||
if spp_name ~= p_name then
|
||||
arena_lib.update_spec_hotbar_party(mod, arena, spp_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- calcolo se spettanti p_name erano in gruppo e se c'è un membro del gruppo da seguire
|
||||
for sp_name, _ in pairs(arena_lib.get_player_spectators(p_name)) do
|
||||
local party_member_in_game
|
||||
|
||||
if is_parties_enabled and parties.is_player_in_party(sp_name) then
|
||||
local pt_members = arena_lib.get_party_members_playing(sp_name, arena)
|
||||
|
||||
if next(pt_members) then
|
||||
party_member_in_game = pt_members[1]
|
||||
end
|
||||
end
|
||||
|
||||
-- priorità: membro gruppo -> esecutre -> casuale
|
||||
if party_member_in_game then
|
||||
arena_lib.spectate_target(mod, arena, sp_name, "player", party_member_in_game)
|
||||
elseif reason == 1 and xc_name and arena_lib.is_player_playing(xc_name, mod) and sp_name ~= xc_name then -- sp_name ~= xc_name in caso si uccidano nello stesso istante
|
||||
arena_lib.spectate_target(mod, arena, sp_name, "player", xc_name)
|
||||
else
|
||||
arena_lib.find_and_spectate_player(sp_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- se è stato eliminato e c'è la spettatore, non va rimosso, bensì solo spostato in spettatore
|
||||
if reason == 1 and mod_ref.spectate_mode and arena.players_amount > 0 then
|
||||
eliminate_player(mod, arena, p_name, xc_name, p_properties, elim_msg)
|
||||
arena_lib.enter_spectate_mode(p_name, arena, xc_name)
|
||||
arena_lib.enter_spectate_mode(p_name, arena, p_team_ID, xc_name)
|
||||
|
||||
-- sennò procedo a rimuoverlo normalmente
|
||||
else
|
||||
|
@ -44,3 +44,29 @@ parties.register_on_pre_party_join(function(party_leader, p_name)
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
|
||||
|
||||
function arena_lib.get_party_members_playing(p_name, arena)
|
||||
local pt_members = {}
|
||||
for _, pl_name in ipairs(parties.get_party_members(p_name, true)) do
|
||||
if arena.players[pl_name] then
|
||||
pt_members[#pt_members +1] = pl_name
|
||||
end
|
||||
end
|
||||
|
||||
return pt_members
|
||||
end
|
||||
|
||||
|
||||
|
||||
function arena_lib.get_party_members_spectating(p_name, arena)
|
||||
local pt_members = {}
|
||||
for _, pl_name in ipairs(parties.get_party_members(p_name, true)) do
|
||||
if arena.spectators[pl_name] then
|
||||
pt_members[#pt_members +1] = pl_name
|
||||
end
|
||||
end
|
||||
|
||||
return pt_members
|
||||
end
|
@ -335,7 +335,7 @@ function get_infobox_formspec(mod, arenaID, player)
|
||||
play_tip = NS("Play (you can also left-click the sign)")
|
||||
end
|
||||
-- tasto "assisti"
|
||||
if not mod_ref.spectate_mode then
|
||||
if mod_ref.spectate_mode ~= "all" then
|
||||
spec_btn = "arenalib_infobox_spectate_off.png"
|
||||
spec_tip = NS("Spectate mode not supported")
|
||||
elseif arena.in_game then
|
||||
|
@ -1,5 +1,8 @@
|
||||
local S = minetest.get_translator("arena_lib")
|
||||
|
||||
local function follow_executioner_or_random() end
|
||||
local function calc_p_amount_teams() end
|
||||
local function calc_spec_id() end
|
||||
local function override_hotbar() end
|
||||
local function set_spectator() end
|
||||
|
||||
@ -10,6 +13,7 @@ local entities_spectated = {} -- KEY: [mod][arena_name][entity nam
|
||||
local areas_spectated = {} -- KEY: [mod][arena_name][area_name], VALUE: {(string) spectator(s) = true}
|
||||
local entities_storage = {} -- KEY: [mod][arena_name][entity_name], VALUE: entity
|
||||
local areas_storage = {} -- KEY: [mod][arena_name][area_name], VALUE: dummy entity
|
||||
local is_parties_enabled = minetest.get_modpath("parties")
|
||||
|
||||
|
||||
|
||||
@ -74,20 +78,21 @@ end
|
||||
-- entering / leaving
|
||||
----------------------------
|
||||
|
||||
function arena_lib.enter_spectate_mode(p_name, arena, xc_name)
|
||||
function arena_lib.enter_spectate_mode(p_name, arena, p_team_ID, xc_name)
|
||||
local mod = arena_lib.get_mod_by_player(p_name)
|
||||
local arena_ID = arena_lib.get_arenaID_by_player(p_name)
|
||||
local team_ID = #arena.teams > 1 and 1 or nil
|
||||
local player = minetest.get_player_by_name(p_name)
|
||||
local hand = player:get_inventory():get_list("hand")
|
||||
|
||||
players_in_spectate_mode[p_name] = { minigame = mod, arenaID = arena_ID, teamID = team_ID, hand = hand}
|
||||
players_in_spectate_mode[p_name] = { minigame = mod, arenaID = arena_ID, teamID = p_team_ID, hand = hand}
|
||||
arena.spectators[p_name] = {}
|
||||
arena.players_and_spectators[p_name] = true
|
||||
arena.spectators_amount = arena.spectators_amount + 1
|
||||
|
||||
local mod_ref = arena_lib.mods[mod]
|
||||
|
||||
-- eventuali proprietà aggiuntive
|
||||
for k, v in pairs(arena_lib.mods[mod].spectator_properties) do
|
||||
for k, v in pairs(mod_ref.spectator_properties) do
|
||||
if type(v) == "table" then
|
||||
arena.spectators[p_name][k] = table.copy(v)
|
||||
else
|
||||
@ -140,10 +145,30 @@ function arena_lib.enter_spectate_mode(p_name, arena, xc_name)
|
||||
minetest.chat_send_player(p_name, minetest.colorize("#cfc6b8", S("Spectators inside: @1", curr_spectators)))
|
||||
|
||||
-- inizia a seguire
|
||||
if xc_name and p_name ~= xc_name and minetest.get_player_by_name(xc_name) then
|
||||
arena_lib.spectate_target(mod, arena, p_name, "player", xc_name)
|
||||
if mod_ref.spectate_mode == "blind" then
|
||||
local found = false
|
||||
if p_team_ID and arena.players_amount_per_team[p_team_ID] > 0 then
|
||||
for _, pl_name in pairs(arena_lib.get_players_in_team(arena, p_team_ID)) do
|
||||
arena_lib.spectate_target(mod, arena, p_name, "player", pl_name)
|
||||
found = true
|
||||
break
|
||||
end
|
||||
|
||||
elseif is_parties_enabled and parties.is_player_in_party(p_name) then
|
||||
local pt_members = arena_lib.get_party_members_playing(p_name, arena)
|
||||
|
||||
if #pt_members > 0 then
|
||||
arena_lib.spectate_target(mod, arena, p_name, "player", pt_members[1])
|
||||
found = true
|
||||
end
|
||||
end
|
||||
|
||||
if not found then
|
||||
follow_executioner_or_random(mod, arena, p_name, "player", xc_name)
|
||||
end
|
||||
|
||||
else
|
||||
arena_lib.find_and_spectate_player(p_name)
|
||||
follow_executioner_or_random(mod, arena, p_name, "player", xc_name)
|
||||
end
|
||||
|
||||
override_hotbar(player, mod, arena)
|
||||
@ -209,21 +234,28 @@ end
|
||||
-- find next spectatable target
|
||||
----------------------------
|
||||
|
||||
function arena_lib.find_and_spectate_player(sp_name, change_team, go_counterwise)
|
||||
function arena_lib.find_and_spectate_player(sp_name, change_team, go_counterwise, rotate_in_party)
|
||||
local arena = arena_lib.get_arena_by_player(sp_name)
|
||||
|
||||
-- se l'ultimo rimasto ha abbandonato (es. alt+f4), rispedisco subito fuori senza che cada all'infinito con rischio di crash
|
||||
-- se l'ultimə rimastə ha abbandonato (es. alt+f4), rispedisco subito fuori senza che cada all'infinito con rischio di crash
|
||||
if arena.players_amount == 0 then
|
||||
arena_lib.remove_player_from_arena(sp_name, 3)
|
||||
return end
|
||||
|
||||
local prev_spectated = players_in_spectate_mode[sp_name].spectating
|
||||
|
||||
-- se c'è rimasto solo un giocatore e già lo si seguiva, annullo
|
||||
-- se c'è rimastə solo unə giocante e già lə si seguiva, annullo
|
||||
if arena.players_amount == 1 and prev_spectated and arena.players[prev_spectated] then return end
|
||||
|
||||
local mod = arena_lib.get_mod_by_player(sp_name)
|
||||
local spectator = minetest.get_player_by_name(sp_name)
|
||||
|
||||
-- aggiornamenti vari della barra delle azioni
|
||||
-- TODO: aggiornare icona persona singola quando squadre e 1vN
|
||||
if is_parties_enabled and parties.is_player_in_party(sp_name) then
|
||||
arena_lib.update_spec_hotbar_party(mod, arena, sp_name)
|
||||
end
|
||||
|
||||
if players_in_spectate_mode[sp_name].type ~= "player" then
|
||||
spectator:get_meta():set_int("arenalib_watchID", 0)
|
||||
end
|
||||
@ -231,57 +263,23 @@ function arena_lib.find_and_spectate_player(sp_name, change_team, go_counterwise
|
||||
local team_ID = players_in_spectate_mode[sp_name].teamID
|
||||
local players_amount
|
||||
|
||||
-- calcolo giocatori massimi tra cui ruotare
|
||||
-- calcolo giocanti massimɜ tra cui ruotare
|
||||
-- squadre:
|
||||
if #arena.teams > 1 then
|
||||
-- se è l'unico rimasto nella squadra e già lo si seguiva, annullo
|
||||
if arena.players_amount_per_team[team_ID] == 1 and not change_team and prev_spectated and arena.players[prev_spectated] then return end
|
||||
|
||||
-- se il giocatore seguito era l'ultimo membro della sua squadra, la imposto da cambiare
|
||||
if arena.players_amount_per_team[team_ID] == 0 then
|
||||
change_team = true
|
||||
end
|
||||
|
||||
-- eventuale cambio squadra sul quale eseguire il calcolo
|
||||
if change_team then
|
||||
arena.spectators_amount_per_team[team_ID] = arena.spectators_amount_per_team[team_ID] - 1
|
||||
|
||||
local active_teams = arena_lib.get_active_teams(arena)
|
||||
|
||||
if team_ID >= active_teams[#active_teams] then
|
||||
team_ID = active_teams[1]
|
||||
else
|
||||
for i = team_ID + 1, #arena.teams do
|
||||
if arena.players_amount_per_team[i] ~= 0 then
|
||||
team_ID = i
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
players_in_spectate_mode[sp_name].teamID = team_ID
|
||||
arena.spectators_amount_per_team[team_ID] = arena.spectators_amount_per_team[team_ID] + 1
|
||||
end
|
||||
|
||||
players_amount = arena.players_amount_per_team[team_ID]
|
||||
|
||||
if arena.teams_enabled and not rotate_in_party then
|
||||
players_amount = calc_p_amount_teams(arena, sp_name, team_ID, change_team, prev_spectated)
|
||||
elseif rotate_in_party then
|
||||
players_amount = #arena_lib.get_party_members_playing(sp_name, arena)
|
||||
-- no squadre:
|
||||
else
|
||||
players_amount = arena.players_amount
|
||||
end
|
||||
|
||||
local mod = arena_lib.get_mod_by_player(sp_name)
|
||||
local current_ID = spectator:get_meta():get_int("arenalib_watchID")
|
||||
local new_ID
|
||||
local curr_ID = spectator:get_meta():get_int("arenalib_watchID")
|
||||
local new_ID = calc_spec_id(curr_ID, players_amount, go_counterwise)
|
||||
|
||||
if go_counterwise then
|
||||
new_ID = current_ID == 1 and players_amount or current_ID - 1
|
||||
else
|
||||
new_ID = players_amount <= current_ID and 1 or current_ID + 1
|
||||
end
|
||||
|
||||
-- trovo il giocatore da seguire
|
||||
-- trovo giocante da seguire
|
||||
-- squadre:
|
||||
if #arena.teams > 1 then
|
||||
if arena.teams_enabled then
|
||||
local players_team = arena_lib.get_players_in_team(arena, team_ID)
|
||||
for i = 1, #players_team do
|
||||
|
||||
@ -291,11 +289,39 @@ function arena_lib.find_and_spectate_player(sp_name, change_team, go_counterwise
|
||||
end
|
||||
end
|
||||
|
||||
-- no squadre:
|
||||
-- gruppo:
|
||||
elseif rotate_in_party then
|
||||
local pt_members = arena_lib.get_party_members_playing(sp_name, arena)
|
||||
for i, pl_name in ipairs(pt_members) do
|
||||
if i == new_ID then
|
||||
-- evita che alternando tra singolo e gruppo riselezioni la stessa persona
|
||||
if prev_spectated and prev_spectated == pl_name then
|
||||
i = calc_spec_id(new_ID, players_amount, go_counterwise)
|
||||
pl_name = pt_members[i]
|
||||
end
|
||||
set_spectator(mod, arena.name, spectator, "player", pl_name, i)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- singolo:
|
||||
else
|
||||
local i = 1
|
||||
for pl_name, _ in pairs(arena.players) do
|
||||
if i == new_ID then
|
||||
-- evita che alternando tra singolo e gruppo riselezioni la stessa persona
|
||||
if prev_spectated and prev_spectated == pl_name then
|
||||
new_ID = calc_spec_id(new_ID, players_amount, go_counterwise)
|
||||
i = 1
|
||||
for pla_name, _ in pairs(arena.players) do
|
||||
if i == new_ID then
|
||||
set_spectator(mod, arena.name, spectator, "player", pla_name, i)
|
||||
return true
|
||||
end
|
||||
i = i +1
|
||||
end
|
||||
end
|
||||
|
||||
set_spectator(mod, arena.name, spectator, "player", pl_name, i)
|
||||
return true
|
||||
end
|
||||
@ -513,7 +539,7 @@ function arena_lib.spectate_target(mod, arena, sp_name, type, t_name)
|
||||
end
|
||||
|
||||
-- sì, potrei richiedere direttamente 'spectator', ma per coesione con il resto dell'API e con il fatto che
|
||||
-- arena_lib salva lɜ spettatorɜ indicizzandolɜ per nome, tanto vale una conversione in più qui
|
||||
-- arena_lib salva lɜ spettanti indicizzandolɜ per nome, tanto vale una conversione in più qui
|
||||
local spectator = minetest.get_player_by_name(sp_name)
|
||||
local i = spectator:get_meta():get_int("arenalib_watchID") -- non c'è bisogno di calcolare l'ID, riapplico quello che già ha
|
||||
set_spectator(mod, arena.name, spectator, type, t_name, i, true)
|
||||
@ -521,6 +547,20 @@ end
|
||||
|
||||
|
||||
|
||||
function arena_lib.update_spec_hotbar_party(mod, arena, sp_name)
|
||||
local pt_members_amnt = #arena_lib.get_party_members_playing(sp_name, arena)
|
||||
local spectator = minetest.get_player_by_name(sp_name)
|
||||
local spectate_mode = arena_lib.mods[mod].spectate_mode
|
||||
|
||||
if ((spectate_mode == "blind" and pt_members_amnt <= 1) or
|
||||
(spectate_mode ~= "blind" and pt_members_amnt == 0)) and
|
||||
spectator:get_inventory():contains_item("main", "arena_lib:spectate_changeplayerparty") then
|
||||
override_hotbar(spectator, mod, arena)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
----------------------------------------------
|
||||
@ -600,6 +640,62 @@ end
|
||||
---------------FUNZIONI LOCALI----------------
|
||||
----------------------------------------------
|
||||
|
||||
function follow_executioner_or_random(mod, arena, p_name, xc_name)
|
||||
if xc_name and arena.players[xc_name] then
|
||||
arena_lib.spectate_target(mod, arena, p_name, "player", xc_name)
|
||||
else
|
||||
arena_lib.find_and_spectate_player(p_name)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- viene chiamata solo una volta ma a tenerla nella funzione principale rendeva il
|
||||
-- codice pressoché illeggibile. Da qui la funzione locale a parte
|
||||
function calc_p_amount_teams(arena, sp_name, team_ID, change_team, prev_spectated)
|
||||
-- se è l'unico rimasto nella squadra e già lo si seguiva, annullo
|
||||
if arena.players_amount_per_team[team_ID] == 1 and not change_team and prev_spectated and arena.players[prev_spectated] then return end
|
||||
|
||||
-- se il giocatore seguito era l'ultimo membro della sua squadra, la imposto da cambiare
|
||||
if arena.players_amount_per_team[team_ID] == 0 then
|
||||
change_team = true
|
||||
end
|
||||
|
||||
-- eventuale cambio squadra sul quale eseguire il calcolo
|
||||
if change_team then
|
||||
arena.spectators_amount_per_team[team_ID] = arena.spectators_amount_per_team[team_ID] - 1
|
||||
|
||||
local active_teams = arena_lib.get_active_teams(arena)
|
||||
|
||||
if team_ID >= active_teams[#active_teams] then
|
||||
team_ID = active_teams[1]
|
||||
else
|
||||
for i = team_ID + 1, #arena.teams do
|
||||
if arena.players_amount_per_team[i] ~= 0 then
|
||||
team_ID = i
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
players_in_spectate_mode[sp_name].teamID = team_ID
|
||||
arena.spectators_amount_per_team[team_ID] = arena.spectators_amount_per_team[team_ID] + 1
|
||||
end
|
||||
|
||||
return arena.players_amount_per_team[team_ID]
|
||||
end
|
||||
|
||||
|
||||
|
||||
function calc_spec_id(curr_ID, players_amount, go_counterwise)
|
||||
if go_counterwise then
|
||||
return curr_ID == 1 and players_amount or curr_ID - 1
|
||||
else
|
||||
return players_amount <= curr_ID and 1 or curr_ID + 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function set_spectator(mod, arena_name, spectator, type, name, i, is_forced)
|
||||
local sp_name = spectator:get_player_name()
|
||||
local prev_spectated = players_in_spectate_mode[sp_name].spectating
|
||||
@ -622,7 +718,7 @@ function set_spectator(mod, arena_name, spectator, type, name, i, is_forced)
|
||||
players_spectated[name][sp_name] = true
|
||||
target = minetest.get_player_by_name(name)
|
||||
|
||||
spectator:set_attach(target, "", {x=0, y=-5, z=-20}, {x=0, y=0, z=0})
|
||||
spectator:set_attach(target, "", {x=0, y=-5, z=-20}, {x=0, y=0, z=0}) -- TODO: si può portare fuori
|
||||
spectator:set_hp(target:get_hp() > 0 and target:get_hp() or 1)
|
||||
|
||||
elseif type == "entity" then
|
||||
@ -661,27 +757,46 @@ function override_hotbar(player, mod, arena)
|
||||
player:get_inventory():set_list("main", {})
|
||||
player:get_inventory():set_list("craft",{})
|
||||
|
||||
local sp_name = player:get_player_name()
|
||||
local mod_ref = arena_lib.mods[mod]
|
||||
local tools = {
|
||||
"arena_lib:spectate_changeplayer", -- TODO: 6.0, with endless arenas I could have a situation where I have entities/areas to spectate but no players. Still hardcoded?
|
||||
"arena_lib:spectate_quit"
|
||||
}
|
||||
local spectate_mode = mod_ref.spectate_mode
|
||||
local tools = {}
|
||||
local pt_members_playing_amnt = 0
|
||||
|
||||
if is_parties_enabled and parties.is_player_in_party(sp_name) then
|
||||
pt_members_playing_amnt = #arena_lib.get_party_members_playing(sp_name, arena)
|
||||
end
|
||||
|
||||
if spectate_mode ~= "blind" or arena.teams_enabled then
|
||||
-- TODO: se è a squadre e c'è solo una persona nella tal squadra, non metterlo
|
||||
-- Poi ridallo però se nell'altra ce n'è più di una
|
||||
tools[1] = "arena_lib:spectate_changeplayer" -- TODO: with endless arenas I could have a situation where I have entities/areas to spectate but no players. Dehardcode it?
|
||||
end
|
||||
|
||||
if (spectate_mode == "blind" and pt_members_playing_amnt > 1) or
|
||||
(spectate_mode ~= "blind" and pt_members_playing_amnt > 0) then
|
||||
tools[#tools +1] = "arena_lib:spectate_changeplayerparty"
|
||||
end
|
||||
|
||||
if spectate_mode == "all" then
|
||||
if #arena.teams > 1 then
|
||||
table.insert(tools, 2, "arena_lib:spectate_changeteam")
|
||||
tools[#tools +1] = "arena_lib:spectate_changeteam"
|
||||
end
|
||||
|
||||
if arena.spectate_entities_amount > 0 then
|
||||
table.insert(tools, #tools, "arena_lib:spectate_changeentity")
|
||||
tools[#tools +1] = "arena_lib:spectate_changeentity"
|
||||
end
|
||||
|
||||
if arena.spectate_areas_amount > 0 then
|
||||
table.insert(tools, #tools, "arena_lib:spectate_changearea")
|
||||
tools[#tools +1] = "arena_lib:spectate_changearea"
|
||||
end
|
||||
|
||||
if mod_ref.join_while_in_progress then
|
||||
table.insert(tools, #tools, "arena_lib:spectate_join")
|
||||
tools[#tools +1] = "arena_lib:spectate_join"
|
||||
end
|
||||
end
|
||||
|
||||
tools[#tools +1] = "arena_lib:spectate_quit"
|
||||
|
||||
player:hud_set_hotbar_image("arenalib_gui_hotbar" .. #tools .. ".png")
|
||||
player:hud_set_hotbar_itemcount(#tools)
|
||||
|
@ -24,6 +24,28 @@ minetest.register_tool("arena_lib:spectate_changeplayer", {
|
||||
|
||||
|
||||
|
||||
minetest.register_tool("arena_lib:spectate_changeplayerparty", {
|
||||
|
||||
description = S("Change player"),
|
||||
inventory_image = "arenalib_spectate_changeplayerparty.png",
|
||||
groups = {not_in_creative_inventory = 1},
|
||||
on_drop = function() end,
|
||||
|
||||
on_use = function(itemstack, user)
|
||||
arena_lib.find_and_spectate_player(user:get_player_name(), false, false, true)
|
||||
end,
|
||||
|
||||
on_secondary_use = function(itemstack, user)
|
||||
arena_lib.find_and_spectate_player(user:get_player_name(), false, true, true)
|
||||
end,
|
||||
|
||||
on_place = function(itemstack, user)
|
||||
arena_lib.find_and_spectate_player(user:get_player_name(), false, true, true)
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
|
||||
minetest.register_tool("arena_lib:spectate_changeteam", {
|
||||
|
||||
description = S("Change team"),
|
||||
|
BIN
textures/arenalib_gui_hotbar1.png
Normal file
BIN
textures/arenalib_gui_hotbar1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 117 B |
BIN
textures/arenalib_spectate_changeplayerparty.png
Normal file
BIN
textures/arenalib_spectate_changeplayerparty.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 191 B |
Loading…
x
Reference in New Issue
Block a user