From 5643fdf8027768d3042554af971f20deec5d2c30 Mon Sep 17 00:00:00 2001 From: ANAND Date: Sun, 17 Mar 2019 07:05:51 +0530 Subject: [PATCH] Add `hud_score` mod API Fixes #72 --- mods/ctf/ctf_bounties/depends.txt | 2 +- mods/ctf/ctf_bounties/init.lua | 33 +++++----- mods/ctf/ctf_stats/init.lua | 8 +++ mods/pvp/hud_score/README.md | 47 ++++++++++++++ mods/pvp/hud_score/init.lua | 102 ++++++++++++++++++++++++++++++ mods/pvp/hud_score/mod.conf | 3 + 6 files changed, 178 insertions(+), 17 deletions(-) create mode 100644 mods/pvp/hud_score/README.md create mode 100644 mods/pvp/hud_score/init.lua create mode 100644 mods/pvp/hud_score/mod.conf diff --git a/mods/ctf/ctf_bounties/depends.txt b/mods/ctf/ctf_bounties/depends.txt index 62e8aba..6eb6f15 100644 --- a/mods/ctf/ctf_bounties/depends.txt +++ b/mods/ctf/ctf_bounties/depends.txt @@ -1,3 +1,3 @@ ctf ctf_stats -irc? +hud_score diff --git a/mods/ctf/ctf_bounties/init.lua b/mods/ctf/ctf_bounties/init.lua index 35cc524..7fb7568 100644 --- a/mods/ctf/ctf_bounties/init.lua +++ b/mods/ctf/ctf_bounties/init.lua @@ -86,26 +86,27 @@ minetest.register_on_joinplayer(function(player) end) ctf.register_on_killedplayer(function(victim, killer) - -- Suicide is not encouraged here at CTF - if victim == killer then + if victim ~= bountied_player or victim == killer then return end - if victim == bountied_player then - local main, match = ctf_stats.player(killer) - if main and match then - main.score = main.score + bounty_score - match.score = match.score + bounty_score - ctf.needs_save = true - end - bountied_player = nil - local msg = killer .. " has killed " .. victim .. " and received the prize!" - minetest.chat_send_all(msg) - - local pstats, mstats = ctf_stats.player(killer) - pstats.bounty_kills = pstats.bounty_kills + 1 - mstats.bounty_kills = mstats.bounty_kills + 1 + local main, match = ctf_stats.player(killer) + if main and match then + main.score = main.score + bounty_score + match.score = match.score + bounty_score + main.bounty_kills = main.bounty_kills + 1 + match.bounty_kills = match.bounty_kills + 1 + ctf.needs_save = true end + bountied_player = nil + + local msg = killer .. " has killed " .. victim .. " and received the prize!" + minetest.chat_send_all(msg) + hud_score.new(killer, { + name = "ctf_bounty:prize", + color = 0x4444FF, + value = bounty_score + }) end) minetest.register_privilege("bounty_admin") diff --git a/mods/ctf/ctf_stats/init.lua b/mods/ctf/ctf_stats/init.lua index a6a7471..28fa63d 100644 --- a/mods/ctf/ctf_stats/init.lua +++ b/mods/ctf/ctf_stats/init.lua @@ -299,6 +299,14 @@ ctf.register_on_killedplayer(function(victim, killer) match.score = match.score + reward match.kills_since_death = match.kills_since_death + 1 ctf.needs_save = true + + reward = math.floor(reward * 100) / 100 + + hud_score.new(killer, { + name = "ctf_stats:kill_score", + color = "0x00FF00", + value = reward + }) end end) diff --git a/mods/pvp/hud_score/README.md b/mods/pvp/hud_score/README.md new file mode 100644 index 0000000..df65d90 --- /dev/null +++ b/mods/pvp/hud_score/README.md @@ -0,0 +1,47 @@ +# `hud_score` + +`hud_score` provides an API to display HUD score elements which can be used to +display kill scores, bounty scores, etc. + +## Methods + +- `hud_score.new(name, score_def)`: Adds a new HUD score element to player `name`. + - `name` [string]: Player name + - `score_def` [table]: HUD score element definition. See below. + +## HUD score element definition + +HUD score element definition table, passed to `hud_score.new`. + +Example definition: + +```lua +{ + name = "ctf_stats:kill_score", -- Can be any arbitrary string + color = "0x00FF00", -- Should be compatible with Minetest's HUD def + value = 50, -- The actual number to be displayed + -- Field `time` is automatically added by `hud_score.new` + -- to keep track of element expiry +} +``` + +## `players` table + +This is a table of tables, indexed by player names. This table holds the HUD +data of all online players. Each sub-table is a list of score tables, which +are added by `hud_score.new`. + +```lua +local players = { + ["name"] = { + [1] = , + [2] = , + [3] = + ... + }, + ["name2"] = { + ... + }, + ... +} +``` diff --git a/mods/pvp/hud_score/init.lua b/mods/pvp/hud_score/init.lua new file mode 100644 index 0000000..2328480 --- /dev/null +++ b/mods/pvp/hud_score/init.lua @@ -0,0 +1,102 @@ +hud_score = {} +local hud = hudkit() + +local players = {} +local duration = 5 +local max = 6 + +local function update(name) + local player = minetest.get_player_by_name(name) + if not player then + return + end + + -- Handle all elements marked for deletion + -- and rebuild table + local temp = {} + for _, def in ipairs(players[name]) do + if def.delete then + if hud:exists(player, def.name) then + hud:remove(player, def.name) + end + else + table.insert(temp, def) + end + end + + for i, def in ipairs(temp) do + -- If not the top-most element, prefix with "+ " + local text = def.value + if i > 1 then + text = "+ " .. text + end + + if hud:exists(player, def.name) then + hud:change(player, def.name, "text", text) + hud:change(player, def.name, "offset", {x = 0, y = i * 20}) + else + hud:add(player, def.name, { + hud_elem_type = "text", + alignment = {x = 0, y = 0}, + position = {x = 0.5, y = 0.6}, + offset = {x = 0, y = i * 20}, + number = def.color, + text = text + }) + end + end + players[name] = temp +end + +function hud_score.new(name, def) + local player = minetest.get_player_by_name(name) + if not player then + return + end + + -- Verify HUD score element def + if not name or not def or type(def) ~= "table" or + not def.name or not def.value or not def.color then + error("hud_score: Invalid HUD score element definition", 2) + end + + -- Store element expiration time in def.time + -- and append score element def to players[name] + def.time = os.time() + duration + table.insert(players[name], def) + + -- If more than `max` active elements, mark oldest element for deletion + if #players[name] > max then + players[name][1].delete = true + end + + update(name) +end + +local modified +minetest.register_globalstep(function(dtime) + -- Loop through HUD score elements of all players + -- and remove them if they've expired + for name, hudset in pairs(players) do + modified = false + for i, def in pairs(hudset) do + if def.time < os.time() then + def.delete = true + modified = true + end + end + + -- If a player's hudset was modified, update player's HUD + if modified then + update(name) + end + end +end) + +minetest.register_on_joinplayer(function(player) + players[player:get_player_name()] = {} +end) + +minetest.register_on_leaveplayer(function(player) + players[player:get_player_name()] = nil +end) diff --git a/mods/pvp/hud_score/mod.conf b/mods/pvp/hud_score/mod.conf new file mode 100644 index 0000000..4436ddb --- /dev/null +++ b/mods/pvp/hud_score/mod.conf @@ -0,0 +1,3 @@ +name = hud_score +description = API for displaying scores on HUD +depends = hudkit