Allow more than two teams in a match at once (#724)

* Fix bugs with more than two teams

* Fix team allocation

* Fix bugz

* Fix crash

* Fix crash with crash fix
This commit is contained in:
LoneWolfHT 2020-12-25 10:37:02 -08:00 committed by GitHub
parent 0ef16edb23
commit fbf0126599
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 87 additions and 30 deletions

View file

@ -116,6 +116,8 @@ function ctf.chat_send_team(team, msg)
team = ctf.team(team)
end
if not team then return end
for pname, _ in pairs(team.players) do
minetest.chat_send_player(pname, msg)
end
@ -199,6 +201,7 @@ function ctf.join(name, team, force, by)
end
end
local prevteam = player.team
player.team = team
team_data.players[player.name] = player
ctf.player_last_team[name] = team
@ -219,7 +222,7 @@ function ctf.join(name, team, force, by)
minetest.log("action", name .. " joined team " .. team)
for i = 1, #ctf.registered_on_join_team do
ctf.registered_on_join_team[i](name, team)
ctf.registered_on_join_team[i](name, team, prevteam)
end
return true
end
@ -421,6 +424,7 @@ minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
if ctf.team(ctf.player(name).team) then
minetest.log("action", name.." already in team so not allocating")
return
end

View file

@ -52,9 +52,11 @@ local function update_lowest()
-- Update lowest.score and lowest.team
lowest = {}
for tname, score in pairs(scores) do
if not lowest.score or score <= lowest.score then
lowest.score = score
lowest.team = tname
if tname == "red" or tname == "blue" then
if not lowest.score or score <= lowest.score then
lowest.score = score
lowest.team = tname
end
end
end
end

View file

@ -75,7 +75,7 @@ minetest.register_chatcommand("team", {
string.match(create, "([%a%b_]-)")
and create ~= ""
and create ~= nil
and ctf.team({name=create, add_team=true})
and ctf.team({name=create, add_team=true, color=create, allow_joins=false})
) then
return true, "Added team '"..create.."'"
else

View file

@ -52,12 +52,6 @@ function ctf_classes.register_on_changed(func)
table.insert(registered_on_changed, func)
end
function ctf_classes.set_skin(player, color, class)
player:set_properties({
textures = {"ctf_classes_skin_" .. class.name .. "_" .. (color or "blue") .. ".png"}
})
end
function ctf_classes.get(player)
if type(player) == "string" then
player = minetest.get_player_by_name(player)

View file

@ -48,9 +48,17 @@ minetest.register_chatcommand("class", {
end
})
ctf_colors.set_skin = function(player, color)
ctf_classes.set_skin(player, color, ctf_classes.get(player))
local old_set_skin = ctf_colors.set_skin
ctf_colors.set_skin = function(player, color, ...)
if color == "blue" or color == "red" then
player:set_properties({
textures = {"ctf_classes_skin_" .. ctf_classes.get(player).name .. "_" .. (color or "blue") .. ".png"}
})
elseif color then
old_set_skin(player, color, ...)
end
end
ctf_classes.set_skin = ctf_colors.set_skin
ctf_classes.register_on_changed(function(player, old, new)
if not old then

View file

@ -11,6 +11,9 @@ local function regen_update()
local pname = player:get_player_name()
local class = get(player)
local tname = ctf.player(pname).team
if medic_by_team[tname] == nil then return end
tnames[pname] = tname
if class.properties.nearby_hpregen then
if tname then

View file

@ -55,11 +55,11 @@ function ctf_colors.update(player, name, tplayer)
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")
if tcolor.css then
player:hud_set_hotbar_image("gui_hotbar.png^[colorize:"..tcolor.css..":180")
player:hud_set_hotbar_selected_image("gui_hotbar_selected.png^[colorize:"..tcolor.css..":180")
else
ctf.error("ctf_colors", "Hint color not supported for " .. tcolor.text)
ctf.error("ctf_colors", "css color not found!")
end
end

View file

@ -237,8 +237,9 @@ if minetest.get_modpath("ctf") then
for _, player in pairs(minetest.get_connected_players()) do
if ctf_map.get_team_relative_z(player) < 0 and not ctf_map.can_cross(player) then
local name = player:get_player_name()
minetest.chat_send_player(name, "Match hasn't started yet!")
ctf.move_to_spawn(name)
if ctf.move_to_spawn(name) then
minetest.chat_send_player(name, "Match hasn't started yet!")
end
end
end

View file

@ -89,6 +89,8 @@ ctf_flag.register_on_prepick_up(function(name, flag)
minetest.chat_send_player(name, "Match hasn't started yet!")
ctf.move_to_spawn(name)
return false
elseif not ctf.get_spawn(ctf.player(name).team) then
return false
else
return true
end

View file

@ -51,7 +51,7 @@ end
local game_won = false
function ctf_match.check_for_winner()
local winner
for name, team in pairs(ctf.teams) do
for name, team in pairs({red = ctf.teams.red, blue = ctf.teams.blue}) do
if winner then
return
end

View file

@ -0,0 +1,23 @@
minetest.register_on_respawnplayer(function(player)
local name = player:get_player_name()
if not ctf.get_spawn(ctf.player(name).team) then
local pos
if math.random(1, 2) == 1 then
local team = ctf.team("red")
if team and team.flags[1] then
pos = vector.new(team.flags[1])
end
else
local team = ctf.team("blue")
if team and team.flags[1] then
pos = vector.new(team.flags[1])
end
end
if pos then
player:set_pos(pos)
end
end
end)

View file

@ -0,0 +1,2 @@
name = ctf_otherteams
depends = ctf

View file

@ -210,7 +210,15 @@ function ctf_stats.is_pro(name)
return stats.score >= 10000 and kd >= 1.5
end
ctf.register_on_join_team(function(name, tname)
ctf.register_on_join_team(function(name, tname, oldteam)
if not ctf_stats.current[tname] then
ctf_stats.current[tname] = {}
end
if oldteam and ctf_stats.current[oldteam] then
ctf_stats.current[oldteam][name] = nil
end
ctf_stats.current[tname][name] = ctf_stats.current[tname][name] or {
kills = 0,
kills_since_death = 0,
@ -226,16 +234,16 @@ ctf_stats.winner_team = "-"
ctf_stats.winner_player = "-"
table.insert(ctf_flag.registered_on_capture, 1, function(name, flag)
local score = 0
for i, pstat in pairs(ctf_stats.current.red) do
local score = 0
for i, pstat in pairs(ctf_stats.current.red) do
score = score + pstat.score
end
for i, pstat in pairs(ctf_stats.current.blue) do
for i, pstat in pairs(ctf_stats.current.blue) do
score = score + pstat.score
end
local capturereward = math.floor(score * 10) / 100
if capturereward < 50 then capturereward = 50 end
if capturereward > 750 then capturereward = 750 end
local capturereward = math.floor(score * 10) / 100
if capturereward < 50 then capturereward = 50 end
if capturereward > 750 then capturereward = 750 end
local main, match = ctf_stats.player(name)
if main and match then
@ -368,6 +376,8 @@ end
local function calculateKillReward(victim, killer)
local vmain, victim_match = ctf_stats.player(victim)
if not vmain or not victim_match then return 5 end
-- +5 for every kill they've made since last death in this match.
local reward = victim_match.kills_since_death * 5
ctf.log("ctf_stats", "Player " .. victim .. " has made " .. reward ..

View file

@ -153,9 +153,12 @@ function _doors.door_toggle(pos, node, clicker)
-- If team door, check clicker's team
if node.name:find("doors:door_steel") then
local tname = ctf.player(clicker:get_player_name()).team
local owner_team = meta:get_string("owner_team")
if clicker and tname ~= owner_team then
return false
if tname == "red" or tname == "blue" then
local owner_team = meta:get_string("owner_team")
if clicker and tname ~= owner_team then
return false
end
end
end
@ -303,6 +306,11 @@ function doors.register(name, def)
-- Get placer's team
local tname = ctf.player(pn).team or ""
if tname ~= "red" and tname ~= "blue" then
minetest.chat_send_player(pn, "Your team can't place doors!")
return itemstack
end
-- Prevent door placement if within 40 nodes of enemy base
local enemy_team = tname == "red" and "blue" or "red"
local enemy_base = ctf_map.map.teams[enemy_team].pos