capturetheflag/mods/ctf/ctf_marker/init.lua
2021-05-04 13:59:33 -07:00

178 lines
4.8 KiB
Lua

ctf_marker = {}
-- Locally cache list of team members when adding
-- marker, because the members in the team needn't
-- be the same within an extended duration of time
local teams = {}
local visibility_time = 30
-- Convenience function that returns passed
-- string enclosed by color escape codes
local function msg(str)
if not str then
return
end
return minetest.colorize("#ABCDEF", str)
end
-- Remove waypoint element for valid players in team tname
function ctf_marker.remove_marker(tname)
if not teams[tname] then return end
for name, hud in pairs(teams[tname].players) do
local player = minetest.get_player_by_name(name)
if player then
player:hud_remove(hud)
end
end
teams[tname] = nil
end
-- Add waypoint element to all players in the same team as name
function ctf_marker.add_marker(name, tname, pos, str)
local team = ctf.team(tname)
teams[tname] = {
players = {},
time = 0
}
for pname in pairs(team.players) do
local tplayer = minetest.get_player_by_name(pname)
if tplayer then
teams[tname].players[pname] = tplayer:hud_add({
hud_elem_type = "waypoint",
name = "[" .. name .. "'s marker" .. str,
number = tonumber(ctf.flag_colors[team.data.color]),
world_pos = pos
})
end
minetest.log("action", name .. " placed a marker at " ..
minetest.pos_to_string(pos) .. ": '" .. str .. "'")
minetest.chat_send_player(pname,
msg("* " .. name .. " placed a marker!"))
end
end
minetest.register_globalstep(function(dtime)
for tname, team in pairs(teams) do
-- Increment time of team marker
local time = team.time + dtime
teams[tname].time = time
-- If time > visibility_time, destroy team marker
if time >= visibility_time then
ctf_marker.remove_marker(tname)
end
end
end)
minetest.register_chatcommand("m", {
param = "[Optional description]",
description = "Allows players to share the location of where " ..
"they're looking at with their team-mates.",
privs = { interact = true },
func = function(name, param)
local player = minetest.get_player_by_name(name)
if not player then
return
end
-- Calculate marker pos
local dir = player:get_look_dir()
local p1 = vector.add(player:get_pos(),
{ x = 0, y = player:get_properties().eye_height, z = 0 })
p1 = vector.add(p1, dir)
local p2 = vector.add(p1, vector.multiply(dir, 500))
local pointed = minetest.raycast(p1, p2, true, true):next()
if not pointed then
minetest.chat_send_player(name, msg("Pointed thing out of range!"))
return
end
local tname = ctf.player(name).team
if not tname then -- can be nil during map change
return
end
-- Handle waypoint string
local str = (param and param:trim() ~= "") and ": " .. param or ""
if pointed.type == "object" then
local concat
local obj = pointed.ref
local entity = obj:get_luaentity()
-- If object is a player, append player name to display text
-- Else if obj is item entity, append item description and count to str.
if obj:is_player() then
concat = obj:get_player_name()
elseif entity then
if entity.name == "__builtin:item" then
local stack = ItemStack(entity.itemstring)
local itemdef = minetest.registered_items[stack:get_name()]
-- Fallback to itemstring if description doesn't exist
concat = itemdef.description or entity.itemstring
concat = concat .. " " .. stack:get_count()
else
-- Pointed thing is a trivial entity, abort
minetest.chat_send_player(name,
msg("Invalid marker position. Please try again."))
return
end
end
str = concat and str .. " <" .. concat .. ">"
end
str = str .. "]"
-- Remove existing marker if it exists
ctf_marker.remove_marker(tname)
ctf_marker.add_marker(name, tname, minetest.get_pointed_thing_position(pointed), str)
end
})
local function mr_command(name)
local tname = ctf.player(name).team
local player = minetest.get_player_by_name(name)
local mmsg = ""
local args = ""
local function hud_check()
if teams[tname].players[name] then
mmsg = player:hud_get(teams[tname].players[name]).name
args = mmsg:split("'")
end
end
if pcall(hud_check) then
if args[1] == "[" .. name then
ctf_marker.remove_marker(tname)
local team = ctf.team(tname)
for pname, _ in pairs(team.players) do
minetest.chat_send_player(pname, msg("* " .. name .. " removed their marker!"))
end
elseif args[1] == "" or nil then
minetest.chat_send_player(name, msg("No marker to remove"))
else
minetest.chat_send_player(name, msg("Not your marker!"))
end
else
minetest.chat_send_player(name, msg("No marker to remove"))
end
end
minetest.register_chatcommand("m_remove", {
description = "Remove your own marker (/mr)",
privs = {interact = true},
func = mr_command
})
minetest.register_chatcommand("mr", {
description = "Remove your own marker",
privs = {interact = true},
func = mr_command
})