Spectate areas

implements #101
master
Zughy 2022-05-27 21:12:15 +00:00
parent bb44b3bd9f
commit 244d272379
10 changed files with 289 additions and 130 deletions

21
DOCS.md
View File

@ -122,8 +122,10 @@ To customise your mod even more, there are a few empty callbacks you can use. Th
* `arena_lib.on_end(mod, function(arena, players, winners, spectators, is_forced))`: same as above. Players and spectators are given here because `end_arena` deleted them already - hence these are a copy. `is_forced` returns `true` when the match has been forcibly terminated (via `force_arena_ending`)
* `arena_lib.on_join(mod, function(p_name, arena, as_spectator))`: called when a player joins an ongoing match. If `as_spectator` is true, they'll be added as such
* `arena_lib.on_death(mod, function(arena, p_name, reason))`: called when a player dies
* `arena_lib.on_change_spectated_target(mod, function(arena, sp_name, target, prev_target))`: called when a spectator (`sp_name`) changes who or what they're spectating, including when they get assigned someone to spectate at entering the arena.
* `target` can only be the player name for now, the same goes for `prev_target` (if any). Entities and locations will be hopefully added in the future
* `arena_lib.on_change_spectated_target(mod, function(arena, sp_name, t_type, t_name, prev_type, prev_spectated))`: called when a spectator (`sp_name`) changes who or what they're spectating, including when they get assigned someone to spectate at entering the arena.
* `t_type` represents the type of the target (either `"player"`, `"entity"` or `"area"`)
* `t_name` its name. If it's an entity or an area, it'll be the name used to register it through the `arena_lib.add_spectate...` functions
* if they were following someone/something else earlier, `prev_type` and `prev_spectated` follow the same logic of the aforementioned parameters
* Beware: as this gets called also when entering, keep in mind that it gets called before the `on_join` callback
* `arena_lib.on_time_tick(mod, function(arena))`: called every second if `time_mode` is different from `"none"`
* `arena_lib.on_timeout(mod, function(arena))`: called when the timer of an arena, if exists (`time_mode = "decremental"`), reaches 0. Not declaring it will make the server crash when time runs out
@ -236,11 +238,14 @@ There are also some other functions which might turn useful. They are:
Default is 0 and these are mostly hardcoded in arena_lib already, so it's advised to not touch it and to use callbacks. The only exception is in case of manual elimination (i.e. in a murder minigame, so reason = 1).
Executioner can be passed to tell who removed the player. By default, this happens when someone uses `/arenakick` and `/forceend`, so that these commands can't be abused without consequences for the admin.
* `arena_lib.send_message_in_arena(arena, channel, msg, <teamID>, <except_teamID>)`: sends a message to all the players/spectators in that specific arena, according to what `channel` is: `"players"`, `"spectators"` or `"both"`. If `teamID` is specified, it'll be only sent to the players inside that very team. On the contrary, if `except_teamID` is `true`, it'll be sent to every player BUT the ones in the specified team. These last two fields are pointless if `channel` is equal to `"spectators"`
* `arena_lib.add_spectable_target(mod, arena_name, t_type, t_name, target)`: adds to the current ongoing match a spectable target, allowing spectators to spectate more than just players. `t_type` indicates the target type, and for now can only be `"entity"`. `t_name` is the name that will appear in the spectator info hotbar, and `target` is the entity itself. When the entity is removed/unloaded, automatically calls `remove_spectable_target(...)`
* `arena_lib.remove_spectable_target(mod, arena_name, t_type, t_name)`: removes a target from the spectable targets of an ongoing match
* `arena_lib.add_spectate_entity(mod, arena, e_name, entity)`: adds to the current ongoing match a spectatable entity, allowing spectators to spectate more than just players. `e_name` is the name that will appear in the spectator info hotbar, and `entity` the `luaentity` table. When the entity is removed/unloaded, automatically calls `remove_spectate_entity(...)`
* `arena_lib.add_spectate_area(mod, arena, pos_name, pos)`: same as `add_spectate_entity`, but it adds an area instead. `pos` is a table containing the coordinates of the area to spectate
* `arena_lib.remove_spectate_entity(mod, arena, e_name)`: removes an entity from the spectatable entities of an ongoing match
* `arena_lib.remove_spectate_area(mod, arena, pos_name)`: removes an area from the spectatable areas of an ongoing match
* `arena_lib.is_player_spectating(sp_name)`: returns whether a player is spectating a match, as a boolean
* `arena_lib.is_player_spectated(p_name)`: returns whether a player is being spectated
* `arena_lib.is_entity_spectated(mod, arena_name, e_name)`: returns whether an entity is being spectated
* `arena_lib.is_area_spectated(mod, arena_name, pos_name)`: returns whether an area is being spectated
* `arena_lib.is_arena_in_edit_mode(arena_name)`: returns whether the arena is in edit mode or not, as a boolean
* `arena_lib.is_player_in_edit_mode(p_name)`: returns whether a player is editing an arena, as a boolean
@ -258,8 +263,8 @@ Executioner can be passed to tell who removed the player. By default, this happe
* `arena_lib.get_active_teams(arena)`: returns an ordered table having as values the ID of teams that are not empty
* `arena_lib.get_player_spectators(p_name)`: returns a list containing all the people currently spectating `p_name`. Format `{sp_name = true}`
* `arena_lib.get_player_spectated(sp_name)`: returns the player `sp_name` is currently spectating, if any
* `arena_lib.get_spectable_entities(mod, arena_name)`: returns a table containing all the spectable entities of `arena_name`, if any. Format `{e_name = entity}`, where `e_name` is the name used to register the entity in `add_spectable_target(...)`
* `arena_lib.get_spectable_entities_amount(mod, arena_name)`: returns the amount of spectable entities currently present in `arena_name`, if any
* `arena_lib.get_spectate_entities(mod, arena_name)`: returns a table containing all the spectatable entities of `arena_name`, if any. Format `{e_name = entity}`, where `e_name` is the name used to register the entity in `add_spectate_entity(...)` and `entity` the `luaentity` table
* `arena_lib.get_spectate_areas(mod, arena_name)`: same as in `get_spectate_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
### 1.10 Things you don't want to do with a light heart
@ -290,6 +295,8 @@ An arena is a table having as a key an ID and as a value its parameters. They ar
* `players_amount_per_team`: (table) separately stores how many players currently are in a given team. Format `{[teamID] = amount}`. If teams are disabled, it's `nil`
* `spectators_amount`: (int) separately stores how many spectators are inside the arena
* `spectators_amount_per_team`: (table) like `players_amount_per_team`, but for spectators
* `spectate_entities_amount`: (int) the amount of entities that can be currently spectated in an ongoing game. If spectate mode is disabled, it's `nil`. Outside of ongoing games is always `nil`
* `spectate_areas_amount`: (int) like `spectate_entities_amount` but for areas
* `spawn_points`: (table) contains information about the spawn points. Format `{[spawnID] = {pos = coords, teamID = team ID}}`. If teams are disabled, `teamID` is `nil`
* `max_players`: (string) default is 4. When this value is reached, queue time decreases to 5 if it's not lower already
* `min_players`: (string) default is 2. When this value is reached, a queue starts
@ -466,7 +473,7 @@ An arena comes in 4 phases:
### 2.4 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), while the other is through the very sign of the arena. In this last case, users just need to right-click the sign and press the "eye" button to be turned into spectators (a game must be in progress). 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 (not currently implemented) areas. To do that, have a look at `arena_lib.add_spectable_target(...)`
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(...)`
<br>
## 3. About the author(s)

View File

@ -28,6 +28,7 @@ dofile(srcpath .. "/editor/tools_sky.lua")
dofile(srcpath .. "/editor/tools_spawner.lua")
dofile(srcpath .. "/hud/hud_main.lua")
dofile(srcpath .. "/hud/hud_waypoints.lua")
dofile(srcpath .. "/spectate/spectate_dummy.lua")
dofile(srcpath .. "/spectate/spectate_main.lua")
dofile(srcpath .. "/spectate/spectate_hand.lua")
dofile(srcpath .. "/spectate/spectate_tools.lua")

View File

@ -286,4 +286,5 @@ Currently spectating: @1=Stai seguendo: @1
Change player=Cambia giocatore
Change team=Cambia squadra
Change entity=Cambia entità
Change area=Cambia area
Enter the match=Entra in partita

View File

@ -286,4 +286,5 @@ Currently spectating: @1=
Change player=
Change team=
Change entity=
Change area=
Enter the match=

View File

@ -34,6 +34,8 @@ local arena_default = {
players_amount_per_team = nil,
spectators_amount = 0,
spectators_amount_per_team = nil,
spectate_entities_amount = nil,
spectate_areas_amount = nil,
spawn_points = {}, -- KEY: ids, VALUE: {pos, teamID}
max_players = 4,
min_players = 2,

View File

@ -88,6 +88,8 @@ function arena_lib.load_arena(mod, arena_ID)
-- 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
@ -272,7 +274,12 @@ function arena_lib.end_arena(mod_ref, mod, arena, winners, is_forced)
operations_before_leaving_arena(mod_ref, arena, pl_name)
end
arena_lib.unload_spectate_containers(mod, arena.name)
-- 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 = {}

View File

@ -0,0 +1,13 @@
-- used for areas
local dummy = {
initial_properties = {
physical = false,
visual = "sprite",
visual_size = {x = 0, y = 0, z = 0},
collisionbox = {0, 0, 0, 0, 0, 0},
textures = { "blank.png" }
}
}
minetest.register_entity("arena_lib:spectate_dummy", dummy)

View File

@ -6,9 +6,10 @@ local function set_spectator() end
local players_in_spectate_mode = {} -- KEY: player name, VALUE: {(string) minigame, (int) arenaID, (string) type, (string) spectating}
local spectate_temp_storage = {} -- KEY: player_name, VALUE: {(table) camera_offset}
local players_spectated = {} -- KEY: player name, VALUE: {(string) spectator(s) = true}
local entities_spectated = {} -- KEY: [mod][arena][entity name], VALUE: {(string) spectator(s) = true}
local areas_spectated = {}
local entities_storage = {} -- KEY: [mod][arena][entity_name], VALUE: entity
local entities_spectated = {} -- KEY: [mod][arena_name][entity name], VALUE: {(string) spectator(s) = true}
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
@ -31,18 +32,29 @@ function arena_lib.init_spectate_containers(mod, arena_name)
if not entities_storage[mod] then
entities_storage[mod] = {}
end
if not areas_storage[mod] then
areas_storage[mod] = {}
end
entities_spectated[mod][arena_name] = {}
areas_spectated[mod][arena_name] = {}
entities_storage[mod][arena_name] = {}
areas_storage[mod][arena_name] = {}
end
function arena_lib.unload_spectate_containers(mod, arena_name)
entities_spectated[mod][arena_name] = nil -- non c'è bisogno di cancellare X[mod], al massimo rimangono vuote
-- rimuovo tutte le entità fantoccio delle aree
for _, dummy_entity in pairs(arena_lib.get_spectate_areas(mod, arena_name)) do
dummy_entity:remove()
end
-- non c'è bisogno di cancellare X[mod], al massimo rimangono vuote
entities_spectated[mod][arena_name] = nil
areas_spectated[mod][arena_name] = nil
entities_storage[mod][arena_name] = nil
areas_storage[mod][arena_name] = nil
end
@ -58,10 +70,9 @@ function arena_lib.remove_spectate_p_container(p_name)
end
----------------------------------------------
---------------------CORE---------------------
----------------------------------------------
----------------------------
-- entering / leaving
----------------------------
function arena_lib.enter_spectate_mode(p_name, arena)
@ -213,94 +224,9 @@ end
function arena_lib.add_spectable_target(mod, arena_name, t_type, t_name, target)
local arena_ID, arena = arena_lib.get_arena_by_name(mod, arena_name)
if not arena.in_game then return end
if t_type == "entity" then
local old_deact = target.on_deactivate
-- aggiungo sull'on_deactivate la funzione per rimuoverla dalla spettatore
target.on_deactivate = function(...)
local ret = old_deact and old_deact(...)
arena_lib.remove_spectable_target(mod, arena_name, t_type, t_name)
return ret
end
-- la aggiungo
entities_spectated[mod][arena_name][t_name] = {}
entities_storage[mod][arena_name][t_name] = target
-- se è l'unica entità registrata, aggiungo lo slot per seguire le entità
if arena_lib.get_spectable_entities_amount(mod, arena_name) == 1 then
for sp_name, _ in pairs(arena.spectators) do
override_hotbar(minetest.get_player_by_name(sp_name), mod, arena)
end
end
elseif t_type == "area" then
-- TODO registrare aree
end
end
function arena_lib.remove_spectable_target(mod, arena_name, t_type, t_name)
local arenaID, arena = arena_lib.get_arena_by_name(mod, arena_name)
-- se l'entità viene rimossa quando la partita è già finita, interrompi o crasha
if not arena.in_game then return end
if t_type == "entity" then
entities_storage[mod][arena_name][t_name] = nil
-- se non ci sono più entità, fai sparire l'icona
if not next(entities_storage[mod][arena_name]) then
for sp_name, _ in pairs(arena.spectators) do
local spectator = minetest.get_player_by_name(sp_name)
override_hotbar(spectator, mod, arena)
end
end
for sp_name, _ in pairs(entities_spectated[mod][arena_name][t_name]) do
arena_lib.find_and_spectate_entity(mod, arena_name, sp_name)
end
elseif t_type == "area" then
--TODO
end
end
----------------------------------------------
--------------------UTILS---------------------
----------------------------------------------
function arena_lib.is_player_spectating(sp_name)
return players_in_spectate_mode[sp_name] ~= nil
end
function arena_lib.is_player_spectated(p_name)
return players_spectated[p_name] and next(players_spectated[p_name])
end
function arena_lib.is_entity_spectated(mod, arena_name, e_name)
return entities_spectated[mod][arena_name][e_name] and next(entities_spectated[mod][arena_name][e_name])
end
----------------------------
-- find next spectatatable target
----------------------------
function arena_lib.find_and_spectate_player(sp_name, change_team)
@ -365,6 +291,7 @@ function arena_lib.find_and_spectate_player(sp_name, change_team)
local watching_ID = spectator:get_meta():get_int("arenalib_watchID")
local new_ID = players_amount <= watching_ID and 1 or watching_ID + 1
local mod = arena_lib.get_mod_by_player(sp_name)
-- trovo il giocatore da seguire
-- squadre:
@ -373,7 +300,7 @@ function arena_lib.find_and_spectate_player(sp_name, change_team)
for i = 1, #players_team do
if i == new_ID then
set_spectator(spectator, "player", players_team[i], i)
set_spectator(mod, arena_name, spectator, "player", players_team[i], i)
return true
end
end
@ -384,7 +311,7 @@ function arena_lib.find_and_spectate_player(sp_name, change_team)
for pl_name, _ in pairs(arena.players) do
if i == new_ID then
set_spectator(spectator, "player", pl_name, i)
set_spectator(mod, arena.name, spectator, "player", pl_name, i)
return true
end
@ -395,14 +322,16 @@ end
function arena_lib.find_and_spectate_entity(mod, arena_name, sp_name)
function arena_lib.find_and_spectate_entity(mod, arena, sp_name)
local e_amount = arena.spectate_entities_amount
-- se non ci sono entità da seguire, segui un giocatore
if not next(entities_storage[mod][arena_name]) then
if e_amount == 0 then
arena_lib.find_and_spectate_player(sp_name)
return end
local e_amount = arena_lib.get_spectable_entities_amount(mod, arena_name)
local arena_name = arena.name
local prev_spectated = players_in_spectate_mode[sp_name].spectating
-- se è l'unica entità rimasta e la si stava già seguendo
@ -419,10 +348,10 @@ function arena_lib.find_and_spectate_entity(mod, arena_name, sp_name)
local new_ID = e_amount <= current_ID and 1 or current_ID + 1
local i = 1
for en_name, _ in pairs(entities_spectated[mod][arena_name]) do
for en_name, _ in pairs(entities_storage[mod][arena_name]) do
if i == new_ID then
set_spectator(spectator, "entity", en_name, i)
set_spectator(mod, arena_name, spectator, "entity", en_name, i)
return true
end
@ -432,6 +361,183 @@ end
function arena_lib.find_and_spectate_area(mod, arena, sp_name)
local ar_amount = arena.spectate_areas_amount
-- se non ci sono aree da seguire, segui un giocatore
if ar_amount == 0 then
arena_lib.find_and_spectate_player(sp_name)
return end
local arena_name = arena.name
local prev_spectated = players_in_spectate_mode[sp_name].spectating
-- se è l'unica area rimasta e la si stava già seguendo
if ar_amount == 1 and prev_spectated and next(areas_spectated[mod][arena_name])[sp_name] then
return end
local spectator = minetest.get_player_by_name(sp_name)
if players_in_spectate_mode[sp_name].type ~= "area" then
spectator:get_meta():set_int("arenalib_watchID", 0)
end
local current_ID = spectator:get_meta():get_int("arenalib_watchID")
local new_ID = ar_amount <= current_ID and 1 or current_ID + 1
local i = 1
for pos_name, _ in pairs(areas_storage[mod][arena_name]) do
if i == new_ID then
set_spectator(mod, arena_name, spectator, "area", pos_name, i)
return true
end
i = i +1
end
end
----------------------------------------------
---------------------CORE---------------------
----------------------------------------------
function arena_lib.add_spectate_entity(mod, arena, e_name, entity)
if not arena.in_game then return end
local arena_name = arena.name
local old_deact = entity.on_deactivate
-- aggiungo sull'on_deactivate la funzione per rimuoverla dalla spettatore
entity.on_deactivate = function(...)
local ret = old_deact and old_deact(...)
arena_lib.remove_spectate_entity(mod, arena, e_name)
return ret
end
-- la aggiungo
entities_spectated[mod][arena_name][e_name] = {}
entities_storage[mod][arena_name][e_name] = entity
arena.spectate_entities_amount = arena.spectate_entities_amount + 1
-- se è l'unica entità registrata, aggiungo lo slot per seguire le entità
if arena.spectate_entities_amount == 1 then
for sp_name, _ in pairs(arena.spectators) do
override_hotbar(minetest.get_player_by_name(sp_name), mod, arena)
end
end
end
function arena_lib.add_spectate_area(mod, arena, pos_name, pos)
if not arena.in_game then return end
minetest.forceload_block(pos, true)
local dummy_entity = minetest.add_entity(pos, "arena_lib:spectate_dummy")
local arena_name = arena.name
areas_spectated[mod][arena_name][pos_name] = {}
areas_storage[mod][arena_name][pos_name] = dummy_entity
arena.spectate_areas_amount = arena.spectate_areas_amount + 1
-- se è l'unica area registrata, aggiungo lo slot per seguire le aree
if arena.spectate_areas_amount == 1 then
for sp_name, _ in pairs(arena.spectators) do
override_hotbar(minetest.get_player_by_name(sp_name), mod, arena)
end
end
end
function arena_lib.remove_spectate_entity(mod, arena, e_name)
if not arena.in_game then return end -- nel caso il minigioco si sia scordata di cancellarla, all'ucciderla fuori dalla partita non crasha
local arena_name = arena.name
entities_storage[mod][arena_name][e_name] = nil
arena.spectate_entities_amount = arena.spectate_entities_amount - 1
-- se non ci sono più entità, fai sparire l'icona
if arena.spectate_entities_amount == 0 then
for sp_name, _ in pairs(arena.spectators) do
local spectator = minetest.get_player_by_name(sp_name)
override_hotbar(spectator, mod, arena)
end
end
for sp_name, _ in pairs(entities_spectated[mod][arena_name][e_name]) do
arena_lib.find_and_spectate_entity(mod, arena, sp_name)
end
end
function arena_lib.remove_spectate_area(mod, arena, pos_name)
local arena_name = arena.name
areas_storage[mod][arena_name][pos_name]:remove()
areas_storage[mod][arena_name][pos_name] = nil
arena.spectate_areas_amount = arena.spectate_areas_amount - 1
-- se non ci sono più aree, fai sparire l'icona
if arena.spectate_areas_amount == 0 then
for sp_name, _ in pairs(arena.spectators) do
local spectator = minetest.get_player_by_name(sp_name)
override_hotbar(spectator, mod, arena)
end
end
for sp_name, _ in pairs(areas_spectated[mod][arena_name][pos_name]) do
arena_lib.find_and_spectate_area(mod, arena, sp_name)
end
end
----------------------------------------------
--------------------UTILS---------------------
----------------------------------------------
function arena_lib.is_player_spectating(sp_name)
return players_in_spectate_mode[sp_name] ~= nil
end
function arena_lib.is_player_spectated(p_name)
return players_spectated[p_name] and next(players_spectated[p_name])
end
function arena_lib.is_entity_spectated(mod, arena_name, e_name)
return entities_spectated[mod][arena_name][e_name] and next(entities_spectated[mod][arena_name][e_name])
end
function arena_lib.is_area_spectated(mod, arena_name, pos_name)
return areas_spectated[mod][arena_name][pos_name] and next(areas_spectated[mod][arena_name][pos_name])
end
----------------------------------------------
@ -452,18 +558,14 @@ end
function arena_lib.get_spectable_entities(mod, arena_name)
function arena_lib.get_spectate_entities(mod, arena_name)
return entities_storage[mod][arena_name]
end
function arena_lib.get_spectable_entities_amount(mod, arena_name)
local i = 0
for k, v in pairs(entities_storage[mod][arena_name]) do
i = i + 1
end
return i
function arena_lib.get_spectate_areas(mod, arena_name)
return areas_storage[mod][arena_name]
end
@ -474,16 +576,14 @@ end
---------------FUNZIONI LOCALI----------------
----------------------------------------------
function set_spectator(spectator, type, name, i)
function set_spectator(mod, arena_name, spectator, type, name, i)
local sp_name = spectator:get_player_name()
local mod = arena_lib.get_mod_by_player(sp_name)
local arena_name = arena_lib.get_arena_by_player(sp_name).name
local prev_spectated = players_in_spectate_mode[sp_name].spectating
local prev_type = players_in_spectate_mode[sp_name].type
-- se stava già seguendo qualcuno, lo rimuovo da questo
if prev_spectated then
local prev_type = players_in_spectate_mode[sp_name].type
if prev_type == "player" then
players_spectated[prev_spectated][sp_name] = nil
elseif prev_type == "entity" then
@ -503,14 +603,18 @@ function set_spectator(spectator, type, name, i)
spectator:set_hp(target:get_hp() > 0 and target:get_hp() or 1)
elseif type == "entity" then
entities_spectated[mod][arena_name][name][sp_name] = true
target = entities_storage[mod][arena_name][name].object
spectator:set_attach(target, "", {x=0, y=-5, z=-20}, {x=0, y=0, z=0})
spectator:set_hp(target:get_hp() > 0 and target:get_hp() or 1)
elseif type == "area" then
-- TODO
areas_spectated[mod][arena_name][name][sp_name] = true
target = areas_storage[mod][arena_name][name]
spectator:set_attach(target, "", {x=0, y=-5, z=-20}, {x=0, y=0, z=0})
spectator:set_hp(minetest.PLAYER_MAX_HP_DEFAULT)
end
players_in_spectate_mode[sp_name].spectating = name
@ -524,9 +628,7 @@ function set_spectator(spectator, type, name, i)
-- eventuale codice aggiuntivo
if mod_ref.on_change_spectated_target then
local arena = arena_lib.get_arena_by_player(sp_name)
target = name
local prev_target = prev_spectated
mod_ref.on_change_spectated_target(arena, sp_name, target, prev_target)
mod_ref.on_change_spectated_target(arena, sp_name, type, name, prev_type, prev_spectated)
end
end
@ -547,10 +649,14 @@ function override_hotbar(player, mod, arena)
table.insert(tools, 2, "arena_lib:spectate_changeteam")
end
if next(arena_lib.get_spectable_entities(mod, arena.name)) then
if next(arena_lib.get_spectate_entities(mod, arena.name)) then
table.insert(tools, #tools, "arena_lib:spectate_changeentity")
end
if next(arena_lib.get_spectate_areas(mod, arena.name)) then
table.insert(tools, #tools, "arena_lib:spectate_changearea")
end
if mod_ref.join_while_in_progress then
table.insert(tools, #tools, "arena_lib:spectate_join")
end

View File

@ -53,9 +53,30 @@ minetest.register_tool("arena_lib:spectate_changeentity", {
local p_name = user:get_player_name()
local mod = arena_lib.get_mod_by_player(p_name)
local arena_name = arena_lib.get_arena_by_player(p_name).name
local arena = arena_lib.get_arena_by_player(p_name)
arena_lib.find_and_spectate_entity(mod, arena_name, p_name)
arena_lib.find_and_spectate_entity(mod, arena, p_name)
end
})
minetest.register_tool("arena_lib:spectate_changearea", {
description = S("Change area"),
inventory_image = "arenalib_spectate_changearea.png",
groups = {not_in_creative_inventory = 1, oddly_breakable_by_hand = "2"},
on_place = function() end,
on_drop = function() end,
on_use = function(itemstack, user)
local p_name = user:get_player_name()
local mod = arena_lib.get_mod_by_player(p_name)
local arena = arena_lib.get_arena_by_player(p_name)
arena_lib.find_and_spectate_area(mod, arena, p_name)
end
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B