Add a HUD!

Looks *a lot* better with a monospaced font
master
upsilon 2017-04-16 16:43:40 +02:00
parent a41d62ea3d
commit cc2724d67b
No known key found for this signature in database
GPG Key ID: A80DAE1F266E1C3C
4 changed files with 137 additions and 12 deletions

View File

@ -45,12 +45,17 @@ pvpplus.remove_from_tournament(player_name) -- Remove a player from the current
pvpplus.add_to_tournament(player_name) -- Add a player to the current tournament
pvpplus.is_playing_tournament(player_name) -- Is this player playing in the current tournament ?
pvpplus.is_running_tournament() -- Is there a tournament currently running ?
pvpplus.get_score(player_name) -- Returns the player current score
-- Tournaments HUD:
pvpplus.tournament_hud_update_list() -- Updates the player list, as shown in the HUD
pvpplus.tournament_hud_update(player[, update_list]) -- Updates a player HUD, optionnaly updating the list (the default for update_list is true)
pvpplus.tournament_hud_update_all() -- Update the list and all player HUDs
```
## TODO
* Add a privilege for changing PvP state
* Add a HUD for the tournament score
* Make the dependence to unified_inventory optional by adding chat commands to change PvP state
* Add a formspec for managing tournaments, accessible from the inventory
* Testing

View File

@ -96,9 +96,9 @@ local tournament_on_punchplayer = pvpplus.tournament_on_punchplayer
pvpplus.tournament_on_punchplayer = nil
minetest.register_on_joinplayer(function(player)
localname = player:get_player_name()
pvptable[localname] = {state = false}
pvptable[localname].nopvppic = player:hud_add({
local name = player:get_player_name()
pvptable[name] = {state = false}
pvptable[name].nopvppic = player:hud_add({
hud_elem_type = "image",
position = {x = 1, y = 0},
offset = {x = -210, y = 20},
@ -106,7 +106,7 @@ minetest.register_on_joinplayer(function(player)
text = "nopvp.png"
})
pvptable[localname].pvpdisabled = player:hud_add({
pvptable[name].pvpdisabled = player:hud_add({
hud_elem_type = "text",
position = {x = 1, y = 0},
offset = {x=-125, y = 20},

View File

@ -53,6 +53,13 @@ function pvpplus.is_engaging_players()
return tournament.engaging_players
end
function pvpplus.get_score(name)
if not pvpplus.is_running_tournament() then
return false, "There is no running tournament."
end
return tournament.sent_damages[name] - tournament.received_damages[name] + tournament.kills[name] * 20
end
function pvpplus.start_tournament()
if tournament.running_tournament then
return false, "There is already a running tournament."
@ -75,6 +82,7 @@ function pvpplus.start_tournament()
local chat_message = "PVP TOURNAMENT BEGINS! Started by " .. (tournament.starting_infos.starter or "[unknown player]") .. "\nEngaged players: "
tournament.starting_infos.initially_engaged_players = {}
for player, _ in pairs(tournament.engaged_players) do
tournament.starting_infos.initially_engaged_players[player] = true
@ -116,6 +124,9 @@ function pvpplus.start_tournament()
-- Send the final chat message
minetest.chat_send_all(chat_message)
-- Update HUDs
pvpplus.tournament_hud_update_all()
-- Set the tournament flag
tournament.running_tournament = true
end
@ -127,7 +138,7 @@ function pvpplus.start_global_tournament()
for _, player in ipairs(players) do
local player_name = player:get_player_name()
if minetest.get_player_privs(player_name).interact then -- Well, don't engage players who don't have interact.
pvpplus.engage_player(player:get_player_name())
pvpplus.engage_player(player_name)
end
end
@ -147,7 +158,7 @@ function pvpplus.stop_tournament()
for name, _ in pairs(tournament.sent_damages) do
table.insert(rating, {
name = name,
score = tournament.sent_damages[name] - tournament.received_damages[name] + tournament.kills[name] * 20
score = pvpplus.get_score(name)
})
if tournament.sound_handles[name] then
@ -162,6 +173,11 @@ function pvpplus.stop_tournament()
if tournament.previous_pvp_states[name] then
pvpplus.pvp_set(name, tournament.previous_pvp_states[name])
end
local player = minetest.get_player_by_name(name)
if player then
pvpplus.tournament_hud_clear(player)
end
end
table.sort(rating, function(a, b) return a.score > b.score end)
@ -283,11 +299,14 @@ function pvpplus.remove_from_tournament(player_name)
if count <= 1 then -- 1 or less remaining players
pvpplus.stop_tournament()
else
pvpplus.tournament_hud_update_all()
end
end
function pvpplus.add_to_tournament(player_name)
if not pvpplus.is_running_tournament() or pvpplus.is_playing_tournament(player_name) then
local player = minetest.get_player_by_name(player_name)
if not pvpplus.is_running_tournament() or pvpplus.is_playing_tournament(player_name) or not player then
return false
end
@ -302,10 +321,10 @@ function pvpplus.add_to_tournament(player_name)
pvpplus.pvp_enable(player_name)
-- Send a chat message
if minetest.get_player_by_name(player_name) then
minetest.chat_send_player(player_name, "You joined the current tournament!")
end
minetest.chat_send_player(player_name, "You joined the current tournament!")
minetest.chat_send_all("Player "..player_name.." joined the current tournament!")
pvpplus.tournament_hud_update_all()
end
function pvpplus.is_playing_tournament(player_name)
@ -336,7 +355,9 @@ function pvpplus.tournament_on_punchplayer(player, hitter, damage)
if player:get_hp() - damage <= 0 then -- Killed
tournament.kills[hitter_name] = tournament.kills[hitter_name] + 1
minetest.chat_send_player(player_name, "You have been killed by " .. hitter_name)
-- Removing the player from the tournament is done by the on_dieplayer callback.
-- Removing the player from the tournament and updating HUDs is done by the on_dieplayer callback.
else
pvpplus.tournament_hud_update_all()
end
end
@ -372,3 +393,4 @@ minetest.register_on_dieplayer(function(player)
end)
dofile(minetest.get_modpath(minetest.get_current_modname()).."/tournament_commands.lua")
dofile(minetest.get_modpath(minetest.get_current_modname()).."/tournament_hud.lua")

98
tournament_hud.lua Normal file
View File

@ -0,0 +1,98 @@
local tournament = pvpplus.tournament -- Shortcut table
tournament.hud = {}
tournament.hud_list = {}
-- These values cannot be exact for all clients. Default values should be fine for most of them.
local margin = tonumber(minetest.setting_get("pvpplus.tournament_hud_margin")) or 10 -- pixels
local font_width = tonumber(minetest.setting_get("pvpplus.font_width")) or 5 -- pixels
local separation = tonumber(minetest.setting_get("pvpplus.tournament_hud_separation")) or 18 -- pixels
function pvpplus.tournament_hud_update_list()
tournament.hud_list = {}
for name, _ in pairs(tournament.sent_damages) do
table.insert(tournament.hud_list, {
name = name,
score = pvpplus.get_score(name),
status = pvpplus.is_playing_tournament(name)
})
end
table.sort(tournament.hud_list, function(a, b) return a.score > b.score end)
end
local function format_element(i, element, len)
if not len then
return tostring(i) .. " " .. element.name .. " " .. tostring(element.score)
else
local str = tostring(i) .. " " .. element.name .. " "
local score = tostring(element.score)
local score_len = #score
while #str + score_len < len do
str = str .. " "
end
str = str .. score
return str
end
end
function pvpplus.tournament_hud_update(player, update_list)
if update_list ~= false then
pvpplus.tournament_hud_update_list()
end
local name = player:get_player_name()
if not tournament.hud[name] then
tournament.hud[name] = {}
end
-- Compute x offset
local max_length = 0
for i, element in ipairs(tournament.hud_list) do
local len = string.len(format_element(i, element))
if len > max_length then
max_length = len
end
end
if max_length == 0 then
return
end
local x_offset = -(max_length * font_width + margin)
-- Remove the old HUD
pvpplus.tournament_hud_clear(player)
-- Add the new HUD
for i, element in ipairs(tournament.hud_list) do
tournament.hud[name][i] = player:hud_add({
name = "Tournament HUD section " .. tostring(i),
hud_elem_type = "text",
aligment = {x = 1, y = 0},
position = {x = 1, y = 0.2},
-- Colors: self is red, playing players are green, no-longer playing players are blue.
number = (element.name == name and 0xFF0000) or ((element.status and 0x00FF00) or 0x0000FF),
text = format_element(i, element, max_length),
offset = {x = x_offset, y = (i-1)*separation}
})
end
end
function pvpplus.tournament_hud_update_all()
pvpplus.tournament_hud_update_list()
for name, _ in pairs(tournament.sent_damages) do
local player = minetest.get_player_by_name(name)
if player then
pvpplus.tournament_hud_update(player, false)
end
end
end
function pvpplus.tournament_hud_clear(player)
local name = player:get_player_name()
if not tournament.hud[name] then -- Happens on first update
return
end
for _, id in ipairs(tournament.hud[name]) do
player:hud_remove(id)
end
end