Dissolve ctf_pvp_engine modpack into other modpacks

This commit is contained in:
rubenwardy 2019-08-28 18:38:28 +01:00
parent 9f05af002e
commit 450027c3b7
78 changed files with 0 additions and 269 deletions

203
mods/ctf/ctf/core.lua Normal file
View file

@ -0,0 +1,203 @@
-- Awaiting core support.
local function __genOrderedIndex( t )
local orderedIndex = {}
for key in pairs(t) do
table.insert( orderedIndex, key )
end
table.sort( orderedIndex )
return orderedIndex
end
local function orderedNext(t, state)
-- Equivalent of the next function, but returns the keys in the alphabetic
-- order. We use a temporary ordered key table that is stored in the
-- table being iterated.
local key = nil
if state == nil then
t.__orderedIndex = __genOrderedIndex( t )
key = t.__orderedIndex[1]
else
for i = 1,table.getn(t.__orderedIndex) do
if t.__orderedIndex[i] == state then
key = t.__orderedIndex[i+1]
end
end
end
if key then
return key, t[key]
end
-- no more value to return, cleanup
t.__orderedIndex = nil
return
end
function orderedPairs(t)
-- Equivalent of the pairs() function on tables. Allows to iterate
-- in order
return orderedNext, t, nil
end
-- Registered
ctf.registered_on_load = {}
function ctf.register_on_load(func)
if ctf._mt_loaded then
error("You can't register callbacks at game time!")
end
table.insert(ctf.registered_on_load, func)
if ctf._loaddata then
func(ctf._loaddata)
end
end
ctf.registered_on_init = {}
function ctf.register_on_init(func)
if ctf._mt_loaded then
error("You can't register callbacks at game time!")
end
table.insert(ctf.registered_on_init, func)
if ctf._inited then
func()
end
end
ctf.registered_on_new_team = {}
function ctf.register_on_new_team(func)
if ctf._mt_loaded then
error("You can't register callbacks at game time!")
end
table.insert(ctf.registered_on_new_team, func)
end
ctf.registered_on_territory_query = {}
function ctf.register_on_territory_query(func)
if ctf._mt_loaded then
error("You can't register callbacks at game time!")
end
table.insert(ctf.registered_on_territory_query, func)
end
ctf.registered_on_new_game = {}
function ctf.register_on_new_game(func)
if ctf._mt_loaded then
error("You can't register callbacks at game time!")
end
table.insert(ctf.registered_on_new_game, func)
if ctf._new_game then
func()
end
end
function vector.distanceSQ(p1, p2)
local x = p1.x - p2.x
local y = p1.y - p2.y
local z = p1.z - p2.z
return x*x + y*y + z*z
end
-- Debug helpers
function ctf.error(area, msg)
minetest.log("error", "CTF::" .. area .. " - " ..msg)
end
function ctf.log(area, msg)
if area and area ~= "" then
print("[CaptureTheFlag] (" .. area .. ") " .. msg)
else
print("[CaptureTheFlag] " .. msg)
end
end
function ctf.action(area, msg)
if area and area ~= "" then
minetest.log("action", "[CaptureTheFlag] (" .. area .. ") " .. msg)
else
minetest.log("action", "[CaptureTheFlag] " .. msg)
end
end
function ctf.warning(area, msg)
print("WARNING: [CaptureTheFlag] (" .. area .. ") " .. msg)
end
function ctf.init()
ctf._inited = true
ctf.log("init", "Initialising!")
-- Set up structures
ctf._defsettings = {}
ctf.teams = {}
ctf.players = {}
-- See minetest.conf.example in the root of this subgame
ctf.log("init", "Creating Default Settings")
ctf._set("diplomacy", true)
ctf._set("players_can_change_team", true)
ctf._set("allocate_mode", 0)
ctf._set("maximum_in_team", -1)
ctf._set("default_diplo_state", "war")
ctf._set("hud", true)
ctf._set("autoalloc_on_joinplayer", true)
ctf._set("friendly_fire", true)
ctf._set("spawn_offset", "0,0,0")
for i = 1, #ctf.registered_on_init do
ctf.registered_on_init[i]()
end
ctf.load()
end
function ctf.reset()
ctf.log("io", "Deleting CTF save data...")
os.remove(minetest.get_worldpath().."/ctf.txt")
ctf.player_last_team = {}
ctf.init()
end
-- Set default setting value
function ctf._set(setting, default)
if ctf._defsettings[setting] then
ctf.warning("settings", "Setting " .. dump(setting) .. " redeclared!")
ctf.warning("settings", debug.traceback())
end
ctf._defsettings[setting] = default
if minetest.settings:get("ctf."..setting) then
ctf.log("settings", "- " .. setting .. ": " .. minetest.settings:get("ctf."..setting))
elseif minetest.settings:get("ctf_"..setting) then
ctf.log("settings", "- " .. setting .. ": " .. minetest.settings:get("ctf_"..setting))
ctf.warning("settings", "deprecated setting ctf_"..setting..
" used, use ctf."..setting.." instead.")
end
end
function ctf.setting(name)
local set = minetest.settings:get("ctf."..name) or
minetest.settings:get("ctf_"..name)
local dset = ctf._defsettings[name]
if dset == nil then
ctf.error("setting", "No such setting - " .. name)
return nil
end
if set ~= nil then
if type(dset) == "number" then
return tonumber(set)
elseif type(dset) == "boolean" then
return minetest.is_yes(set)
else
return set
end
else
return dset
end
end
function ctf.load()
ctf._new_game = true
for i = 1, #ctf.registered_on_new_game do
ctf.registered_on_new_game[i]()
end
end

2
mods/ctf/ctf/depends.txt Normal file
View file

@ -0,0 +1,2 @@
chatplus?
hudkit

50
mods/ctf/ctf/hud.lua Normal file
View file

@ -0,0 +1,50 @@
ctf.hud = hudkit()
ctf.hud.parts = {}
function ctf.hud.register_part(func)
table.insert(ctf.hud.parts, func)
end
minetest.register_on_leaveplayer(function(player)
ctf.hud.players[player:get_player_name()] = nil
end)
ctf.register_on_join_team(function(name, tname)
if ctf.setting("hud") then
ctf.hud.update(minetest.get_player_by_name(name))
end
end)
function ctf.hud.update(player)
if not player then
return
end
local name = player:get_player_name()
local tplayer = ctf.player(name)
if not tplayer or not tplayer.team or not ctf.team(tplayer.team) then
return
end
-- Team Identifier
for i = 1, #ctf.hud.parts do
ctf.hud.parts[i](player, name, tplayer)
end
end
function ctf.hud.updateAll()
if not ctf.setting("hud") then
return
end
local players = minetest.get_connected_players()
for i = 1, #players do
ctf.hud.update(players[i])
end
end
local function tick()
ctf.hud.updateAll()
minetest.after(10, tick)
end
minetest.after(1, tick)

23
mods/ctf/ctf/init.lua Normal file
View file

@ -0,0 +1,23 @@
-- CAPTURE THE FLAG
-- by Andrew "rubenwardy" Ward
-----------------------------------------
ctf = {}
-- Privs
minetest.register_privilege("ctf_team_mgr", {
description = "Team manager",
})
minetest.register_privilege("ctf_admin", {
description = "Can create teams, manage players, assign team owners.",
})
-- Modules
dofile(minetest.get_modpath("ctf") .. "/core.lua")
dofile(minetest.get_modpath("ctf") .. "/teams.lua")
dofile(minetest.get_modpath("ctf") .. "/hud.lua")
-- Init
ctf.init()
ctf.clean_player_lists()

506
mods/ctf/ctf/teams.lua Normal file
View file

@ -0,0 +1,506 @@
-- Get or add a team
function ctf.team(name)
if name == nil then
return nil
end
if type(name) == "table" then
if not name.add_team then
ctf.error("team", "Invalid table given to ctf.team")
return
end
return ctf.create_team(name.name, name)
else
local team = ctf.teams[name]
if team then
if not team.data or not team.players then
ctf.warning("team", "Assertion failed, data{} or players{} not " ..
"found in team{}")
end
return team
else
if name and name:trim() ~= "" then
ctf.warning("team", dump(name) .. " does not exist!")
end
return nil
end
end
end
function ctf.create_team(name, data)
ctf.log("team", "Creating team " .. name)
ctf.teams[name] = {
data = data,
spawn = nil,
players = {}
}
for i = 1, #ctf.registered_on_new_team do
ctf.registered_on_new_team[i](ctf.teams[name])
end
return ctf.teams[name]
end
function ctf.remove_team(name)
local team = ctf.team(name)
if team then
for username, player in pairs(team.players) do
player.team = nil
end
for i = 1, #team.flags do
team.flags[i].team = nil
end
ctf.teams[name] = nil
return true
else
return false
end
end
function ctf.list_teams(name)
minetest.chat_send_player(name, "Teams:")
for tname, team in pairs(ctf.teams) do
if team and team.players then
local details = ""
local numPlayers = ctf.count_players_in_team(tname)
details = numPlayers .. " members"
if team.flags then
local numFlags = 0
for flagid, flag in pairs(team.flags) do
numFlags = numFlags + 1
end
details = details .. ", " .. numFlags .. " flags"
end
minetest.chat_send_player(name, ">> " .. tname ..
" (" .. details .. ")")
end
end
end
-- Count number of players in a team
function ctf.count_players_in_team(team)
local count = 0
for name, player in pairs(ctf.team(team).players) do
count = count + 1
end
return count
end
function ctf.new_player(name)
if name then
ctf.players[name] = {
name = name
}
else
ctf.error("team", "Can't create a blank player")
ctf.log("team", debug.traceback())
end
end
-- get a player
function ctf.player(name)
if not ctf.players[name] then
ctf.new_player(name)
end
return ctf.players[name]
end
function ctf.player_or_nil(name)
return ctf.players[name]
end
function ctf.chat_send_team(team, msg)
if type(team) == "string" then
team = ctf.team(team)
end
for pname, _ in pairs(team.players) do
minetest.chat_send_player(pname, msg)
end
end
function ctf.remove_player(name)
ctf.log("team", "Removing player ".. dump(name))
local player = ctf.players[name]
if player then
local team = ctf.team(player.team)
if team then
team.players[name] = nil
end
ctf.players[name] = nil
return true
else
return false
end
end
ctf.registered_on_join_team = {}
function ctf.register_on_join_team(func)
if ctf._mt_loaded then
error("You can't register callbacks at game time!")
end
table.insert(ctf.registered_on_join_team, func)
end
ctf.player_last_team = {}
-- Player joins team
-- Called by /join, /team join or auto allocate.
function ctf.join(name, team, force, by)
if not name or name == "" or not team or team == "" then
ctf.log("team", "Missing parameters to ctf.join")
return false
end
local player = ctf.player(name)
if not force and not ctf.setting("players_can_change_team")
and player.team and ctf.team(player.team) then
if by then
if by == name then
ctf.action("teams", name .. " attempted to change to " .. team)
minetest.chat_send_player(by, "You are not allowed to switch teams, traitor!")
else
ctf.action("teams", by .. " attempted to change " .. name .. " to " .. team)
minetest.chat_send_player(by, "Failed to add " .. name .. " to " .. team ..
" as players_can_change_team = false")
end
else
ctf.log("teams", "failed to add " .. name .. " to " .. team ..
" as players_can_change_team = false")
end
return false
end
local team_data = ctf.team(team)
if not team_data then
if by then
minetest.chat_send_player(by, "No such team.")
ctf.list_teams(by)
if by == name then
minetest.log("action", by .. " tried to move " .. name .. " to " .. team .. ", which doesn't exist")
else
minetest.log("action", name .. " attempted to join " .. team .. ", which doesn't exist")
end
else
ctf.log("teams", "failed to add " .. name .. " to " .. team ..
" as team does not exist")
end
return false
end
if player.team then
local oldteam = ctf.team(player.team)
if oldteam then
oldteam.players[player.name] = nil
end
end
player.team = team
team_data.players[player.name] = player
ctf.player_last_team[name] = team
minetest.log("action", name .. " joined team " .. team)
minetest.chat_send_all(name.." has joined team "..team)
for i = 1, #ctf.registered_on_join_team do
ctf.registered_on_join_team[i](name, team)
end
return true
end
-- Cleans up the player lists
function ctf.clean_player_lists()
ctf.log("utils", "Cleaning player lists")
for _, str in pairs(ctf.players) do
if str and str.team and ctf.teams[str.team] then
ctf.log("utils", " - Adding player "..str.name.." to team "..str.team)
ctf.teams[str.team].players[str.name] = str
else
ctf.log("utils", " - Skipping player "..str.name)
end
end
end
-- Sees if the player can change stuff in a team
function ctf.can_mod(player,team)
local privs = minetest.get_player_privs(player)
if privs then
if privs.ctf_admin == true then
return true
end
end
if player and ctf.teams[team] and ctf.teams[team].players and ctf.teams[team].players[player] then
if ctf.teams[team].players[player].auth == true then
return true
end
end
return false
end
-- post a message to a team board
function ctf.post(team, msg)
if not ctf.team(team) then
return false
end
if not ctf.team(team).log then
ctf.team(team).log = {}
end
ctf.log("team", "message posted to team board")
table.insert(ctf.team(team).log, 1, msg)
return true
end
-- Automatic Allocation
function ctf.autoalloc(name, alloc_mode)
alloc_mode = alloc_mode or ctf.setting("allocate_mode")
if alloc_mode == 0 then
return
end
local last_team = ctf.player_last_team[name]
if last_team then
return last_team
end
local max_players = ctf.setting("maximum_in_team")
local mtot = false -- more than one team
for key, team in pairs(ctf.teams) do
mtot = true
break
end
if not mtot then
ctf.error("autoalloc", "No teams to allocate " .. name .. " to!")
return
end
if alloc_mode == 1 then
local index = {}
for key, team in pairs(ctf.teams) do
if team.data.allow_joins ~= false and (max_players == -1 or
ctf.count_players_in_team(key) < max_players) then
table.insert(index, key)
end
end
if #index == 0 then
ctf.error("autoalloc", "No teams to join!")
else
return index[math.random(1, #index)]
end
elseif alloc_mode == 2 then
local one = nil
local one_count = -1
local two = nil
local two_count = -1
for key, team in pairs(ctf.teams) do
local count = ctf.count_players_in_team(key)
if team.data.allow_joins ~= false and
(max_players == -1 or count < max_players) then
if count > one_count then
two = one
two_count = one_count
one = key
one_count = count
end
if count > two_count then
two = key
two_count = count
end
end
end
if not one and not two then
ctf.error("autoalloc", "No teams to join!")
elseif one and two then
if math.random() > 0.5 then
return one
else
return two
end
else
if one then
return one
else
return two
end
end
elseif alloc_mode == 3 then
local smallest = nil
local smallest_count = 1000
for key, team in pairs(ctf.teams) do
local count = ctf.count_players_in_team(key)
if team.data.allow_joins ~= false and
(not smallest or count < smallest_count) then
smallest = key
smallest_count = count
end
end
if not smallest then
ctf.error("autoalloc", "No teams to join!")
else
return smallest
end
elseif alloc_mode == 4 then
return ctf.custom_alloc(name)
else
ctf.error("autoalloc",
"Unknown allocation mode: " .. alloc_mode)
end
end
-- Custom team allocation function. Throws error
-- if unimplemented, and autoalloc mode 4 is selected
function ctf.custom_alloc()
error("Allocation mode set to custom while " ..
"ctf.custom_alloc hasn't been overridden!")
end
-- updates the spawn position for a team
function ctf.get_spawn(team)
if ctf.team(team) then
local spawn = ctf.team(team).spawn
if not spawn then
return nil
end
return vector.add(spawn, minetest.string_to_pos(ctf.setting("spawn_offset")))
else
return nil
end
end
function ctf.move_to_spawn(name)
local player = minetest.get_player_by_name(name)
local tplayer = ctf.player(name)
if ctf.team(tplayer.team) then
local spawn = ctf.get_spawn(tplayer.team)
if spawn then
player:move_to(spawn, false)
return true
end
end
return false
end
minetest.register_on_respawnplayer(function(player)
if not player then
return false
end
return ctf.move_to_spawn(player:get_player_name())
end)
function ctf.get_territory_owner(pos)
local largest = nil
local largest_weight = 0
for i = 1, #ctf.registered_on_territory_query do
local team, weight = ctf.registered_on_territory_query[i](pos)
if team and weight then
if weight == -1 then
return team
end
if weight > largest_weight then
largest = team
largest_weight = weight
end
end
end
return largest
end
minetest.register_on_newplayer(function(player)
local name = player:get_player_name()
local team = ctf.autoalloc(name)
if team then
ctf.log("autoalloc", name .. " was allocated to " .. team)
ctf.join(name, team)
ctf.move_to_spawn(player:get_player_name())
end
end)
minetest.register_on_joinplayer(function(player)
if not ctf.setting("autoalloc_on_joinplayer") then
return
end
local name = player:get_player_name()
if ctf.team(ctf.player(name).team) then
return
end
local team = ctf.autoalloc(name)
if team then
ctf.log("autoalloc", name .. " was allocated to " .. team)
ctf.join(name, team)
ctf.move_to_spawn(player:get_player_name())
end
end)
-- Disable friendly fire.
ctf.registered_on_killedplayer = {}
function ctf.register_on_killedplayer(func)
if ctf._mt_loaded then
error("You can't register callbacks at game time!")
end
table.insert(ctf.registered_on_killedplayer, func)
end
local dead_players = {}
minetest.register_on_respawnplayer(function(player)
dead_players[player:get_player_name()] = nil
end)
minetest.register_on_joinplayer(function(player)
dead_players[player:get_player_name()] = nil
end)
minetest.register_on_punchplayer(function(player, hitter,
time_from_last_punch, tool_capabilities, dir, damage)
if player and hitter then
local pname = player:get_player_name()
local hname = hitter:get_player_name()
local to = ctf.player(pname)
local from = ctf.player(hname)
if dead_players[pname] then
return
end
if to.team == from.team and to.team ~= "" and
to.team ~= nil and to.name ~= from.name then
minetest.chat_send_player(hname, pname .. " is on your team!")
if not ctf.setting("friendly_fire") then
return true
end
end
local hp = player:get_hp()
if hp == 0 then
return false
end
if hp - damage <= 0 then
dead_players[pname] = true
local wielded = hitter:get_wielded_item()
for i = 1, #ctf.registered_on_killedplayer do
ctf.registered_on_killedplayer[i](pname, hname,
wielded, tool_capabilities)
end
return false
end
end
end)

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

View file

@ -0,0 +1,4 @@
ctf
ctf_colors
chatplus?
irc?

395
mods/ctf/ctf_chat/init.lua Normal file
View file

@ -0,0 +1,395 @@
ctf.register_on_init(function()
ctf.log("chat", "Initialising...")
-- Settings: Chat
ctf._set("chat.team_channel", true)
ctf._set("chat.global_channel", true)
ctf._set("chat.default", "global")
end)
function minetest.is_player_name_valid(name)
return name:match("^[%a%d_-]+$")
end
local function team_console_help(name)
minetest.chat_send_player(name, "Try:")
minetest.chat_send_player(name, "/team - show team panel")
minetest.chat_send_player(name, "/team all - list all teams")
minetest.chat_send_player(name, "/team <team> - show details about team 'name'")
minetest.chat_send_player(name, "/team <name> - get which team 'player' is in")
minetest.chat_send_player(name, "/team player <name> - get which team 'player' is in")
local privs = minetest.get_player_privs(name)
if privs and privs.ctf_admin == true then
minetest.chat_send_player(name, "/team add <team> - add a team called name (ctf_admin only)")
minetest.chat_send_player(name, "/team remove <team> - add a team called name (ctf_admin only)")
end
if privs and privs.ctf_team_mgr == true then
minetest.chat_send_player(name, "/team lock <team> - closes a team to new players (ctf_team_mgr only)")
minetest.chat_send_player(name, "/team unlock <team> - opens a team to new players (ctf_team_mgr only)")
minetest.chat_send_player(name, "/team bjoin <team> <commands> - Command is * for all players, playername for one, !playername to remove (ctf_team_mgr only)")
minetest.chat_send_player(name, "/team join <name> <team> - add 'player' to team 'team' (ctf_team_mgr only)")
minetest.chat_send_player(name, "/team removeply <name> - add 'player' to team 'team' (ctf_team_mgr only)")
end
end
minetest.register_chatcommand("team", {
description = "Open the team console, or run team command (see /team help)",
func = function(name, param)
local test = string.match(param, "^player ([%a%d_-]+)")
local create = string.match(param, "^add ([%a%d_-]+)")
local remove = string.match(param, "^remove ([%a%d_-]+)")
local lock = string.match(param, "^lock ([%a%d_-]+)")
local unlock = string.match(param, "^unlock ([%a%d_-]+)")
local j_name, j_tname = string.match(param, "^join ([%a%d_-]+) ([%a%d_]+)")
local b_tname, b_pattern = string.match(param, "^bjoin ([%a%d_-]+) ([%a%d_-%*%! ]+)")
local l_name = string.match(param, "^removeplr ([%a%d_-]+)")
if create then
local privs = minetest.get_player_privs(name)
if privs and privs.ctf_admin then
if (
string.match(create, "([%a%b_]-)")
and create ~= ""
and create ~= nil
and ctf.team({name=create, add_team=true})
) then
return true, "Added team '"..create.."'"
else
return false, "Error adding team '"..create.."'"
end
else
return false, "You are not a ctf_admin!"
end
elseif remove then
local privs = minetest.get_player_privs(name)
if privs and privs.ctf_admin then
if ctf.remove_team(remove) then
return true, "Removed team '" .. remove .. "'"
else
return false, "Error removing team '" .. remove .. "'"
end
else
return false, "You are not a ctf_admin!"
end
elseif lock then
local privs = minetest.get_player_privs(name)
if privs and privs.ctf_team_mgr then
local team = ctf.team(lock)
if team then
team.data.allow_joins = false
return true, "Locked team to new members"
else
return false, "Unable to find that team!"
end
else
return false, "You are not a ctf_team_mgr!"
end
elseif unlock then
local privs = minetest.get_player_privs(name)
if privs and privs.ctf_team_mgr then
local team = ctf.team(unlock)
if team then
team.data.allow_joins = true
return true, "Unlocked team to new members"
else
return false, "Unable to find that team!"
end
else
return false, "You are not a ctf_team_mgr!"
end
elseif param == "all" then
ctf.list_teams(name)
elseif ctf.team(param) then
minetest.chat_send_player(name, "Team "..param..":")
local count = 0
for _, value in pairs(ctf.team(param).players) do
count = count + 1
if value.auth then
minetest.chat_send_player(name, count .. ">> " .. value.name
.. " (team owner)")
else
minetest.chat_send_player(name, count .. ">> " .. value.name)
end
end
elseif ctf.player_or_nil(param) or test then
if not test then
test = param
end
if ctf.player(test).team then
if ctf.player(test).auth then
return true, test ..
" is in team " .. ctf.player(test).team.." (team owner)"
else
return true, test ..
" is in team " .. ctf.player(test).team
end
else
return true, test.." is not in a team"
end
elseif j_name and j_tname then
local privs = minetest.get_player_privs(name)
if privs and privs.ctf_team_mgr then
if ctf.join(j_name, j_tname, true, name) then
return true, "Successfully added " .. j_name .. " to " .. j_tname
else
return false, "Failed to add " .. j_name .. " to " .. j_tname
end
else
return true, "You are not a ctf_team_mgr!"
end
elseif b_pattern and b_tname then
local privs = minetest.get_player_privs(name)
if privs and privs.ctf_team_mgr then
local tokens = string.split(b_pattern, " ")
local players = {}
for _, token in pairs(tokens) do
print(token)
if token == "*" then
for _, player in pairs(minetest.get_connected_players()) do
players[player:get_player_name()] = true
end
elseif token:sub(1, 1) == "!" then
players[token:sub(2, #token)] = nil
elseif minetest.is_player_name_valid(token) then
players[token] = true
else
return false, "Invalid token: " .. token .. "\nExpecting *, playername, or !playername."
end
end
for pname, _ in pairs(players) do
ctf.join(pname, b_tname, true, name)
end
return true, "Success!"
else
return false, "You are not a ctf_team_mgr!"
end
elseif l_name then
local privs = minetest.get_player_privs(name)
if privs and privs.ctf_team_mgr then
if ctf.remove_player(l_name) then
return true, "Removed player " .. l_name
else
return false, "Failed to remove player."
end
else
return false, "You are not a ctf_team_mgr!"
end
elseif param=="help" then
team_console_help(name)
else
if param ~= "" and param ~= nil then
minetest.chat_send_player(name, "'"..param.."' is an invalid parameter to /team")
team_console_help(name)
end
end
return false, "Nothing could be done"
end
})
minetest.register_chatcommand("join", {
params = "team name",
description = "Add to team",
func = function(name, param)
if ctf.join(name, param, false, name) then
return true, "Joined team " .. param .. "!"
else
return false, "Failed to join team!"
end
end
})
minetest.register_chatcommand("ctf_clean", {
description = "Do admin cleaning stuff",
privs = {ctf_admin=true},
func = function(name, param)
ctf.log("chat", "Cleaning CTF...")
ctf.clean_player_lists()
if ctf_flag and ctf_flag.assert_flags then
ctf_flag.assert_flags()
end
return true, "CTF cleaned!"
end
})
minetest.register_chatcommand("ctf_reset", {
description = "Delete all CTF saved states and start again.",
privs = {ctf_admin=true},
func = function(name, param)
minetest.chat_send_all("The CTF core was reset by the admin. All team memberships," ..
"flags, land ownerships etc have been deleted.")
ctf.reset()
return true, "Reset CTF core."
end,
})
minetest.register_chatcommand("ctf_reload", {
description = "reload the ctf main frame and get settings",
privs = {ctf_admin=true},
func = function(name, param)
ctf.init()
return true, "CTF core reloaded!"
end
})
minetest.register_chatcommand("ctf_ls", {
description = "ctf: list settings",
privs = {ctf_admin=true},
func = function(name, param)
minetest.chat_send_player(name, "Settings:")
for set, def in orderedPairs(ctf._defsettings) do
minetest.chat_send_player(name, " - " .. set .. ": " .. dump(ctf.setting(set)))
print("\"" .. set .. "\" " .. dump(ctf.setting(set)))
end
return true
end
})
minetest.register_chatcommand("team_owner", {
params = "player name",
description = "Make player team owner",
privs = {ctf_admin=true},
func = function(name, param)
if ctf and ctf.players and ctf.player(param) and ctf.player(param).team and ctf.team(ctf.player(param).team) then
if ctf.player(param).auth == true then
ctf.player(param).auth = false
return true, param.." was downgraded from team admin status"
else
ctf.player(param).auth = true
return true, param.." was upgraded to an admin of "..ctf.player(name).team
end
else
return false, "Unable to do that :/ "..param.." does not exist, or is not part of a valid team."
end
end
})
minetest.register_chatcommand("post", {
params = "message",
description = "Post a message on your team's message board",
func = function(name, param)
if ctf and ctf.players and ctf.players[name] and ctf.players[name].team and ctf.teams[ctf.players[name].team] then
if not ctf.player(name).auth then
minetest.chat_send_player(name, "You do not own that team")
end
if not ctf.teams[ctf.players[name].team].log then
ctf.teams[ctf.players[name].team].log = {}
end
table.insert(ctf.teams[ctf.players[name].team].log,{msg=param})
minetest.chat_send_player(name, "Posted: "..param)
else
minetest.chat_send_player(name, "Could not post message")
end
end,
})
minetest.register_chatcommand("all", {
params = "msg",
description = "Send a message on the global channel",
func = function(name, param)
if not ctf.setting("chat.global_channel") then
minetest.chat_send_player(name, "The global channel is disabled")
return
end
if ctf.player(name).team then
local tosend = ctf.player(name).team ..
" <" .. name .. "> " .. param
minetest.chat_send_all(tosend)
if minetest.global_exists("chatplus") then
chatplus.log(tosend)
end
else
minetest.chat_send_all("<"..name.."> "..param)
end
end
})
minetest.register_chatcommand("t", {
params = "msg",
description = "Send a message on the team channel",
func = function(name, param)
if not ctf.setting("chat.team_channel") then
minetest.chat_send_player(name, "The team channel is disabled.")
return
end
local tname = ctf.player(name).team
local team = ctf.team(tname)
if team then
minetest.log("action", tname .. "<" .. name .. "> ** ".. param .. " **")
if minetest.global_exists("chatplus") then
chatplus.log("<" .. name .. "> ** ".. param .. " **")
end
tcolor = ctf_colors.get_color(ctf.player(name))
for username, to in pairs(team.players) do
minetest.chat_send_player(username,
minetest.colorize(tcolor.css, "<" .. name .. "> ** " .. param .. " **"))
end
if minetest.global_exists("irc") and irc.feature_mod_channel then
irc:say(irc.config.channel, tname .. "<" .. name .. "> ** " .. param .. " **", true)
end
else
minetest.chat_send_player(name,
"You're not in a team, so you have no team to talk to.")
end
end
})
if minetest.global_exists("irc") then
function irc.playerMessage(name, message)
local tname = ctf.player(name).team
local color = ctf_colors.get_irc_color(ctf.player(name))
local clear = "\x0F"
if color then
color = "\x03" .. color
else
color = ""
clear = ""
end
local abrace = color .. "<" .. clear
local bbrace = color .. ">" .. clear
return ("%s%s%s %s"):format(abrace, name, bbrace, message)
end
end
local handler
handler = function(name, message)
if ctf.player(name).team then
for i = 1, #minetest.registered_on_chat_messages do
local func = minetest.registered_on_chat_messages[i]
if func ~= handler and func(name, message) then
return true
end
end
if not minetest.check_player_privs(name, {shout = true}) then
minetest.chat_send_player(name, "-!- You don't have permission to shout.")
return true
end
local tcolor = ctf_colors.get_color(ctf.player(name))
minetest.chat_send_all(minetest.colorize(tcolor.css,
"<" .. name .. "> ") .. message)
return true
else
return nil
end
end
table.insert(minetest.registered_on_chat_messages, 1, handler)
minetest.registered_chatcommands["me"].func = function(name, param)
if ctf.player(name).team then
local tcolor = ctf_colors.get_color(ctf.player(name))
name = minetest.colorize(tcolor.css, "* " .. name)
else
name = "* ".. name
end
minetest.chat_send_all(name .. " " .. param)
end

View file

@ -0,0 +1,2 @@
ctf
3d_armor?

View file

@ -0,0 +1,88 @@
function ctf_colors.get_color(tplayer)
local team = ctf.team(tplayer.team)
local tcolor_text = nil
if team then
tcolor_text = team.data.color
end
local tcolor_hex = ctf.flag_colors[tcolor_text]
if not tcolor_hex then
tcolor_hex = "0x000000"
end
local tcolor_css = "#" .. tcolor_hex:sub(3, 8)
return {
text = tcolor_text,
hex = tcolor_hex,
css = tcolor_css
}
end
function ctf_colors.get_irc_color(tplayer)
local team = ctf.team(tplayer.team)
local tcolor_text = nil
if team then
tcolor_text = team.data.color
end
return ctf_colors.irc_colors[tcolor_text]
end
function ctf_colors.get_nametag_color(name, tplayer, tcolor_text, tcolor_hex)
if ctf.setting("colors.nametag.tcolor") then
return "0xFF" .. string.sub(tcolor_hex, 3)
else
return "0xFFFFFFFF"
end
end
function ctf_colors.set_skin(player, color)
if minetest.global_exists("armor") then
-- TODO: how should support for skin mods be done?
armor.textures[name].skin = "ctf_colors_skin_" .. color .. ".png"
armor:update_player_visuals(player)
else
player:set_properties({
textures = {"ctf_colors_skin_" .. color .. ".png"}
})
end
end
function ctf_colors.update(player, name, tplayer)
if not player then
player = minetest.get_player_by_name(name)
end
local tcolor = ctf_colors.get_color(tplayer)
if ctf.setting("colors.hudtint") then
if tcolor.text == "red" or tcolor.text == "blue" then
player:hud_set_hotbar_image("ctf_colors_hotbar_" .. tcolor.text .. ".png")
player:hud_set_hotbar_selected_image("ctf_colors_hotbar_selected_" .. tcolor.text .. ".png")
else
ctf.error("ctf_colors", "Hint color not supported for " .. tcolor.text)
end
end
if ctf.setting("colors.skins") and tcolor.text then
ctf_colors.set_skin(player, tcolor.text)
end
if ctf.setting("hud.teamname") then
if not ctf.hud:exists(player, "ctf:hud_team") then
ctf.hud:add(player, "ctf:hud_team", {
hud_elem_type = "text",
position = {x = 1, y = 0},
scale = {x = 100, y = 100},
text = "Team " .. tplayer.team,
number = tcolor.hex,
offset = {x = -20, y = 20},
alignment = {x = -1, y = 0}
})
else
ctf.hud:change(player, "ctf:hud_team", "text", "Team " .. tplayer.team)
ctf.hud:change(player, "ctf:hud_team", "number", tcolor.hex)
end
end
end
ctf.hud.register_part(ctf_colors.update)

View file

@ -0,0 +1,30 @@
-- Supported colors
ctf_colors = {}
ctf_colors.colors = {
red = "0xFF4444",
cyan = "0x00FFFF",
blue = "0x4466FF",
purple = "0x800080",
yellow = "0xFFFF00",
green = "0x00FF00",
pink = "0xFF00FF",
silver = "0xC0C0C0",
gray = "0x808080",
black = "0x000000",
orange = "0xFFA500",
gold = "0x808000"
}
ctf_colors.irc_colors = {
red = "4",
blue = "2",
}
ctf.flag_colors = ctf_colors.colors
ctf.register_on_init(function()
ctf.log("colors", "Initialising...")
ctf._set("colors.skins", false)
ctf._set("colors.hudtint", true)
ctf._set("hud.teamname", false)
end)
dofile(minetest.get_modpath("ctf_colors") .. "/hud.lua")

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

240
mods/ctf/ctf_flag/api.lua Normal file
View file

@ -0,0 +1,240 @@
ctf_flag.registered_on_capture = {}
function ctf_flag.register_on_capture(func)
if ctf._mt_loaded then
error("You can't register callbacks at game time!")
end
table.insert(ctf_flag.registered_on_capture, func)
end
ctf_flag.registered_on_pick_up = {}
function ctf_flag.register_on_pick_up(func)
if ctf._mt_loaded then
error("You can't register callbacks at game time!")
end
table.insert(ctf_flag.registered_on_pick_up, func)
end
ctf_flag.registered_on_drop = {}
function ctf_flag.register_on_drop(func)
if ctf._mt_loaded then
error("You can't register callbacks at game time!")
end
table.insert(ctf_flag.registered_on_drop, func)
end
ctf_flag.registered_on_precapture = {}
function ctf_flag.register_on_precapture(func)
if ctf._mt_loaded then
error("You can't register callbacks at game time!")
end
table.insert(ctf_flag.registered_on_precapture, func)
end
ctf_flag.registered_on_prepick_up = {}
function ctf_flag.register_on_prepick_up(func)
if ctf._mt_loaded then
error("You can't register callbacks at game time!")
end
table.insert(ctf_flag.registered_on_prepick_up, func)
end
function ctf_flag.collect_claimed()
local claimed = {}
for _, team in pairs(ctf.teams) do
for i = 1, #team.flags do
if team.flags[i].claimed then
table.insert(claimed, team.flags[i])
end
end
end
return claimed
end
function ctf_flag.get_claimed_by_player(name)
local claimed = ctf_flag.collect_claimed()
for _, flag in pairs(claimed) do
if flag.claimed.player == name then
return name
end
end
end
function ctf_flag.player_drop_flag(name)
if not name then
return
end
local claimed = ctf_flag.collect_claimed()
for i = 1, #claimed do
local flag = claimed[i]
if flag.claimed.player == name then
flag.claimed = nil
local flag_name = ""
if flag.name then
flag_name = flag.name .. " "
end
flag_name = flag.team .. "'s " .. flag_name .. "flag"
ctf.hud.updateAll()
ctf.action("flag", name .. " dropped " .. flag_name)
minetest.chat_send_all(flag_name.." has returned.")
for i = 1, #ctf_flag.registered_on_drop do
ctf_flag.registered_on_drop[i](name, flag)
end
end
end
end
-- add a flag to a team
function ctf_flag.add(team, pos)
if not team or team == "" then
return
end
ctf.log("flag", "Adding flag to " .. team .. " at (" .. pos.x ..
", " .. pos.y .. ", " .. pos.z .. ")")
if not ctf.team(team).flags then
ctf.team(team).flags = {}
end
pos.team = team
table.insert(ctf.team(team).flags,pos)
end
function ctf_flag.update(pos)
if minetest.get_node(pos).name ~= "ctf_flag:flag" then
return
end
local top = {x=pos.x,y=pos.y+1,z=pos.z}
local flagmeta = minetest.get_meta(pos)
if not flagmeta then
return
end
local flag_team_data = ctf_flag.get(pos)
if not flag_team_data or not ctf.team(flag_team_data.team)then
ctf.log("flag", "Flag does not exist! Deleting nodes. "..dump(pos))
minetest.set_node(pos,{name="air"})
minetest.set_node(top,{name="air"})
return
end
local topmeta = minetest.get_meta(top)
local flag_name = flag_team_data.name
if flag_name and flag_name ~= "" then
flagmeta:set_string("infotext", flag_name.." - "..flag_team_data.team)
else
flagmeta:set_string("infotext", flag_team_data.team.."'s flag")
end
if not ctf.team(flag_team_data.team).data.color then
ctf.team(flag_team_data.team).data.color = "red"
end
if flag_team_data.claimed then
minetest.set_node(top,{name="ctf_flag:flag_captured_top"})
else
minetest.set_node(top,{name="ctf_flag:flag_top_"..ctf.team(flag_team_data.team).data.color})
end
topmeta = minetest.get_meta(top)
if flag_name and flag_name ~= "" then
topmeta:set_string("infotext", flag_name.." - "..flag_team_data.team)
else
topmeta:set_string("infotext", flag_team_data.team.."'s flag")
end
end
function ctf_flag.flag_tick(pos)
ctf_flag.update(pos)
minetest.get_node_timer(pos):start(5)
end
-- get a flag from a team
function ctf_flag.get(pos)
if not pos then
return
end
local result = nil
for _, team in pairs(ctf.teams) do
for i = 1, #team.flags do
if (
team.flags[i].x == pos.x and
team.flags[i].y == pos.y and
team.flags[i].z == pos.z
) then
if result then
minetest.chat_send_all("[CTF ERROR] Multiple teams have same flag. Please report this to the server operator / admin")
print("CTF ERROR DATA")
print("Multiple teams have same flag.")
print("This is a sign of ctf.txt corruption.")
print("----------------")
print(dump(result))
print(dump(team.flags[i]))
print("----------------")
else
result = team.flags[i]
end
end
end
end
return result
end
-- delete a flag from a team
function ctf_flag.delete(team, pos)
if not team or team == "" then
return
end
ctf.log("flag", "Deleting flag from " .. team .. " at (" .. pos.x ..
", " .. pos.y .. ", " .. pos.z .. ")")
for i = 1, #ctf.team(team).flags do
if (
ctf.team(team).flags[i].x == pos.x and
ctf.team(team).flags[i].y == pos.y and
ctf.team(team).flags[i].z == pos.z
) then
table.remove(ctf.team(team).flags,i)
return
end
end
end
function ctf_flag.assert_flag(flag)
minetest.get_voxel_manip(flag, { x = flag.x + 1, y = flag.y + 1, z = flag.z + 1})
local nodename = minetest.get_node(flag).name
if nodename ~= "ctf_flag:flag" then
ctf.log("flag", flag.team .. " has wrong node at flag position, " .. nodename .. ", correcting...")
minetest.set_node(flag, { name = "ctf_flag:flag"})
ctf_flag.update(flag)
end
end
function ctf_flag.assert_flags()
for tname, team in pairs(ctf.teams) do
ctf_flag.assert_flags_team(tname)
end
end
function ctf_flag.assert_flags_team(tname)
local team = ctf.team(tname)
if not tname or not team then
return false
end
if not team.flags then
team.flags = {}
end
for i=1, #team.flags do
ctf_flag.assert_flag(team.flags[i])
end
end

View file

@ -0,0 +1,3 @@
ctf
ctf_colors
chatplus?

View file

@ -0,0 +1,238 @@
local function do_capture(attname, flag, returned)
local team = flag.team
local attacker = ctf.player(attname)
local flag_name = ""
if flag.name then
flag_name = flag.name .. " "
end
flag_name = team .. "'s " .. flag_name .. "flag"
if ctf.setting("flag.capture_take") and not returned then
for i = 1, #ctf_flag.registered_on_prepick_up do
if not ctf_flag.registered_on_prepick_up[i](attname, flag) then
return
end
end
minetest.chat_send_all(flag_name.." has been picked up by "..
attname.." (team "..attacker.team..")")
ctf.action("flag", attname .. " picked up " .. flag_name)
-- Post to flag owner's board
ctf.post(team, {
msg = flag_name .. " has been taken by " .. attname .. " of ".. attacker.team,
icon="flag_red" })
-- Post to attacker's board
ctf.post(attacker.team, {
msg = attname .. " snatched '" .. flag_name .. "' from " .. team,
icon="flag_green"})
-- Add to claimed list
flag.claimed = {
team = attacker.team,
player = attname
}
ctf.hud.updateAll()
ctf_flag.update(flag)
for i = 1, #ctf_flag.registered_on_pick_up do
ctf_flag.registered_on_pick_up[i](attname, flag)
end
else
for i = 1, #ctf_flag.registered_on_precapture do
if not ctf_flag.registered_on_precapture[i](attname, flag) then
return
end
end
minetest.chat_send_all(flag_name.." has been captured "..
" by "..attname.." (team "..attacker.team..")")
ctf.action("flag", attname .. " captured " .. flag_name)
-- Post to flag owner's board
ctf.post(team, {
msg = flag_name .. " has been captured by " .. attacker.team,
icon="flag_red"})
-- Post to attacker's board
ctf.post(attacker.team, {
msg = attname .. " captured '" .. flag_name .. "' from " .. team,
icon="flag_green"})
-- Take flag
if ctf.setting("flag.allow_multiple") then
ctf_flag.delete(team, vector.new(flag))
ctf_flag.add(attacker.team, vector.new(flag))
else
minetest.set_node(pos,{name="air"})
ctf_flag.delete(team,pos)
end
for i = 1, #ctf_flag.registered_on_capture do
ctf_flag.registered_on_capture[i](attname, flag)
end
end
end
local function player_drop_flag(player)
return ctf_flag.player_drop_flag(player:get_player_name())
end
minetest.register_on_dieplayer(player_drop_flag)
minetest.register_on_leaveplayer(player_drop_flag)
ctf_flag = {
on_punch_top = function(pos, node, puncher)
pos.y = pos.y - 1
ctf_flag.on_punch(pos, node, puncher)
end,
on_rightclick_top = function(pos, node, clicker)
pos.y = pos.y - 1
ctf_flag.on_rightclick(pos, node, clicker)
end,
on_rightclick = function(pos, node, clicker)
local name = clicker:get_player_name()
local flag = ctf_flag.get(pos)
if not flag then
return
end
if flag.claimed then
if ctf.setting("flag.capture_take") then
minetest.chat_send_player(name, "This flag has been taken by "..flag.claimed.player)
minetest.chat_send_player(name, "who is a member of team "..flag.claimed.team)
return
else
minetest.chat_send_player(name, "Oops! This flag should not be captured. Reverting...")
flag.claimed = nil
end
end
end,
on_punch = function(pos, node, puncher)
local name = puncher:get_player_name()
if not puncher or not name then
return
end
local flag = ctf_flag.get(pos)
if not flag then
return
end
if flag.claimed then
if ctf.setting("flag.capture_take") then
minetest.chat_send_player(name, "This flag has been taken by " .. flag.claimed.player)
minetest.chat_send_player(name, "who is a member of team " .. flag.claimed.team)
return
else
minetest.chat_send_player(name, "Oops! This flag should not be captured. Reverting.")
flag.claimed = nil
end
end
local team = flag.team
if not team then
return
end
if ctf.team(team) and ctf.player(name).team then
if ctf.player(name).team == team then
-- Clicking on their team's flag
if ctf.setting("flag.capture_take") then
ctf_flag._flagret(name)
end
else
do_capture(name, flag)
end
else
minetest.chat_send_player(name, "You are not part of a team!")
end
end,
_flagret = function(name)
local claimed = ctf_flag.collect_claimed()
for i = 1, #claimed do
local flag = claimed[i]
if flag.claimed.player == name then
do_capture(name, flag, true)
end
end
end,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("infotext", "Unowned flag")
minetest.get_node_timer(pos):start(5)
end,
after_place_node = function(pos, placer)
local name = placer:get_player_name()
if not pos or not name then
minetest.set_node(pos, {name="air"})
return
end
local meta = minetest.get_meta(pos)
if not meta then
minetest.set_node(pos, {name="air"})
return
end
local tplayer = ctf.player_or_nil(name)
if tplayer and ctf.team(tplayer.team) then
if not minetest.check_player_privs(name, {ctf_place_flag=true}) then
minetest.chat_send_player(name, "You're not allowed to place flags! Reported to admin for investigation.")
minetest.set_node(pos, {name="air"})
if minetest.global_exists("chatplus") then
chatplus.send_mail("*SERVER*", minetest.settings:get("name"),
"player " .. name .. " attempted to place flag!")
end
return
end
local tname = tplayer.team
local team = ctf.team(tplayer.team)
meta:set_string("infotext", tname.."'s flag")
-- add flag
ctf_flag.add(tname, pos)
-- TODO: fix this hackiness
if team.spawn and not ctf.setting("flag.allow_multiple") and
minetest.get_node(team.spawn).name == "ctf_flag:flag" then
-- send message
minetest.chat_send_all(tname .. "'s flag has been moved")
minetest.set_node(team.spawn, {name="air"})
minetest.set_node({
x = team.spawn.x,
y = team.spawn.y+1,
z = team.spawn.z
}, {name="air"})
team.spawn = pos
end
local pos2 = {
x = pos.x,
y = pos.y + 1,
z = pos.z
}
if not team.data.color then
team.data.color = "red"
end
minetest.set_node(pos2, {name="ctf_flag:flag_top_"..team.data.color})
local meta2 = minetest.get_meta(pos2)
meta2:set_string("infotext", tname.."'s flag")
else
minetest.chat_send_player(name, "You are not part of a team!")
minetest.set_node(pos, {name="air"})
end
end
}

View file

@ -0,0 +1,90 @@
-- The flag
minetest.register_node("ctf_flag:flag", {
description = "Flag",
drawtype="nodebox",
paramtype = "light",
walkable = false,
inventory_image = "flag_silver2.png",
tiles = {
"default_wood.png",
"default_wood.png",
"default_wood.png",
"default_wood.png",
"default_wood.png",
"default_wood.png"
},
node_box = {
type = "fixed",
fixed = {
{0.250000,-0.500000,0.000000,0.312500,0.500000,0.062500}
}
},
groups = {immortal=1,is_flag=1,flag_bottom=1},
on_punch = ctf_flag.on_punch,
on_rightclick = ctf_flag.on_rightclick,
on_construct = ctf_flag.on_construct,
after_place_node = ctf_flag.after_place_node,
on_timer = ctf_flag.flag_tick
})
for color, _ in pairs(ctf.flag_colors) do
minetest.register_node("ctf_flag:flag_top_"..color,{
description = "You are not meant to have this! - flag top",
drawtype="nodebox",
paramtype = "light",
walkable = false,
tiles = {
"default_wood.png",
"default_wood.png",
"default_wood.png",
"default_wood.png",
"flag_"..color.."2.png",
"flag_"..color..".png"
},
node_box = {
type = "fixed",
fixed = {
{0.250000,-0.500000,0.000000,0.312500,0.500000,0.062500},
{-0.5,0,0.000000,0.250000,0.500000,0.062500}
}
},
groups = {immortal=1,is_flag=1,flag_top=1,not_in_creative_inventory=1},
on_punch = ctf_flag.on_punch_top,
on_rightclick = ctf_flag.on_rightclick_top
})
end
minetest.register_node("ctf_flag:flag_captured_top",{
description = "You are not meant to have this! - flag captured",
drawtype = "nodebox",
paramtype = "light",
walkable = false,
tiles = {
"default_wood.png",
"default_wood.png",
"default_wood.png",
"default_wood.png",
"default_wood.png",
"default_wood.png"
},
node_box = {
type = "fixed",
fixed = {
{0.250000,-0.500000,0.000000,0.312500,0.500000,0.062500}
}
},
groups = {immortal=1,is_flag=1,flag_top=1,not_in_creative_inventory=1},
on_punch = ctf_flag.on_punch_top,
on_rightclick = ctf_flag.on_rightclick_top
})
if ctf.setting("flag.crafting") then
minetest.register_craft({
output = "ctf_flag:flag",
recipe = {
{"default:stick", "group:wool"},
{"default:stick", "",},
{"default:stick", ""}
}
})
end

102
mods/ctf/ctf_flag/hud.lua Normal file
View file

@ -0,0 +1,102 @@
-- TODO: delete flags if they are removed (ctf.next, or captured)
ctf.hud.register_part(function(player, name, tplayer)
if ctf.setting("flag.waypoints") then
for tname, team in pairs(ctf.teams) do
for _, flag in pairs(team.flags) do
local hud = "ctf:hud_" .. tname
local flag_name = flag.name or tname .. "'s base"
local color = ctf.flag_colors[team.data.color]
if not color then
color = "0x000000"
end
if ctf.hud:exists(player, hud) then
ctf.hud:change(player, hud, "world_pos", {
x = flag.x,
y = flag.y,
z = flag.z
})
else
ctf.hud:add(player, hud, {
hud_elem_type = "waypoint",
name = flag_name,
number = color,
world_pos = {
x = flag.x,
y = flag.y,
z = flag.z
}
})
end
end
end
end
end)
ctf.hud.register_part(function(player, name, tplayer)
-- Check all flags
local alert = nil
local color = "0xFFFFFF"
if ctf.setting("flag.alerts") then
if ctf.setting("flag.alerts.neutral_alert") then
alert = "Punch the enemy flag! Protect your flag!"
end
local claimed = ctf_flag.collect_claimed()
local enemyHolder = nil
local teamHolder = nil
for _, flag in pairs(claimed) do
if flag.team == tplayer.team then
enemyHolder = flag.claimed.player
else
teamHolder = flag.claimed.player
end
end
if teamHolder == name then
if enemyHolder then
alert = "You can't capture the flag until " .. enemyHolder .. " is killed!"
color = "0xFF0000"
else
alert = "You've got the flag! Run back and punch your flag!"
color = "0xFF0000"
end
elseif teamHolder then
if enemyHolder then
alert = "Kill " .. enemyHolder .. " to allow " .. teamHolder .. " to capture the flag!"
color = "0xFF0000"
else
alert = "Protect " .. teamHolder .. ", they've got the enemy flag!"
color = "0xFF0000"
end
elseif enemyHolder then
alert = "Kill " .. enemyHolder .. ", they've got your flag!"
color = "0xFF0000"
end
end
-- Display alert
if alert then
if ctf.hud:exists(player, "ctf:hud_team_alert") then
ctf.hud:change(player, "ctf:hud_team_alert", "text", alert)
ctf.hud:change(player, "ctf:hud_team_alert", "number", color)
else
local y
if ctf.setting("hud.teamname") then
y = 50
else
y = 20
end
ctf.hud:add(player, "ctf:hud_team_alert", {
hud_elem_type = "text",
position = {x = 1, y = 0},
scale = {x = 100, y = 100},
text = alert,
number = color,
offset = {x = -10, y = y},
alignment = {x = -1, y = 0}
})
end
else
ctf.hud:remove(player, "ctf:hud_team_alert")
end
end)

146
mods/ctf/ctf_flag/init.lua Normal file
View file

@ -0,0 +1,146 @@
-- Initialise
ctf.register_on_init(function()
ctf.log("flag", "Initialising...")
ctf._set("flag.allow_multiple", true)
ctf._set("flag.capture_take", false)
ctf._set("flag.names", true)
ctf._set("flag.waypoints", true)
ctf._set("flag.protect_distance", 25)
ctf._set("flag.nobuild_radius", 3)
ctf._set("flag.drop_time", 7*60)
ctf._set("flag.drop_warn_time", 60)
ctf._set("flag.crafting", false)
ctf._set("flag.alerts", true)
ctf._set("flag.alerts.neutral_alert", true)
end)
minetest.register_privilege("ctf_place_flag", {
description = "can place flag"
})
dofile(minetest.get_modpath("ctf_flag") .. "/hud.lua")
dofile(minetest.get_modpath("ctf_flag") .. "/flag_func.lua")
dofile(minetest.get_modpath("ctf_flag") .. "/api.lua")
dofile(minetest.get_modpath("ctf_flag") .. "/flags.lua")
ctf.register_on_new_team(function(team)
team.flags = {}
end)
function ctf_flag.get_nearest(pos)
local closest = nil
local closest_distSQ = 1000000
local pd = ctf.setting("flag.protect_distance")
local pdSQ = pd * pd
for tname, team in pairs(ctf.teams) do
for i = 1, #team.flags do
local distSQ = vector.distanceSQ(pos, team.flags[i])
if distSQ < pdSQ and distSQ < closest_distSQ then
closest = team.flags[i]
closest_distSQ = distSQ
end
end
end
return closest, closest_distSQ
end
function ctf_flag.get_nearest_team_dist(pos)
local flag, distSQ = ctf_flag.get_nearest(pos)
if flag then
return flag.team, distSQ
end
end
ctf.register_on_territory_query(ctf_flag.get_nearest_team_dist)
function ctf.get_spawn(team)
if not ctf.team(team) then
return nil
end
if ctf.team(team).spawn then
return ctf.team(team).spawn
end
-- Get spawn from first flag
ctf_flag.assert_flags(team)
if #ctf.team(team).flags > 0 then
return ctf.team(team).flags[1]
else
return nil
end
end
-- Add minimum build range
local old_is_protected = minetest.is_protected
local r = ctf.setting("flag.nobuild_radius")
local rs = r * r
function minetest.is_protected(pos, name)
if r <= 0 or rs == 0 then
return old_is_protected(pos, name)
end
local flag, distSQ = ctf_flag.get_nearest(pos)
if flag and pos.y >= flag.y - 1 and distSQ < rs then
minetest.chat_send_player(name,
"Too close to the flag to build! Leave at least " .. r .. " blocks around the flag.")
return true
else
return old_is_protected(pos, name)
end
end
-- Play sound
ctf_flag.register_on_pick_up(function(attname, flag)
local vteam = ctf.team(flag.team)
for name, player in pairs(vteam.players) do
minetest.sound_play({name="trumpet_lose"}, {
to_player = name,
gain = 1.0, -- default
})
end
local ateam = ctf.team(ctf.player(attname).team)
for name, player in pairs(ateam.players) do
minetest.sound_play({name="trumpet_win"}, {
to_player = name,
gain = 1.0, -- default
})
end
end)
-- Drop after time
local pickup_times = {}
ctf_flag.register_on_pick_up(function(attname, flag)
pickup_times[attname] = minetest.get_gametime()
end)
ctf_flag.register_on_drop(function(attname, flag)
pickup_times[attname] = nil
end)
ctf_flag.register_on_capture(function(attname, flag)
pickup_times[attname] = nil
end)
ctf.register_on_new_game(function()
pickup_times = {}
end)
local function update_flag_drops()
local time = minetest.get_gametime()
local drop_time = ctf.setting("flag.drop_time")
for name, start in pairs(pickup_times) do
local remaining = drop_time - time + start
if remaining < 0 then
ctf_flag.player_drop_flag(name)
minetest.chat_send_player(name, "You took too long to capture the flag, so it returned!")
elseif remaining < ctf.setting("flag.drop_warn_time") then
minetest.chat_send_player(name, "You have " .. remaining ..
" seconds to capture the flag before it returns.")
end
end
ctf_flag.assert_flags()
minetest.after(5, update_flag_drops)
end
minetest.after(5, update_flag_drops)

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 776 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 732 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 571 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 826 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 775 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 690 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 688 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 616 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 874 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 567 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 657 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 671 B