From 53e7e53c9020fb3039c4f39f631999866904a975 Mon Sep 17 00:00:00 2001 From: tilderain Date: Sun, 13 Jul 2025 13:14:22 -0700 Subject: [PATCH 1/2] Add minigame parameter - assign players teams by score Add to hit_balls and boxing --- .../tf2ware_ultimate/api/minigame.nut | 3 ++ .../vscripts/tf2ware_ultimate/api/player.nut | 43 +++++++++++++++++++ scripts/vscripts/tf2ware_ultimate/main.nut | 3 ++ .../tf2ware_ultimate/minigames/boxing.nut | 1 + .../tf2ware_ultimate/minigames/hit_balls.nut | 4 +- 5 files changed, 53 insertions(+), 1 deletion(-) diff --git a/scripts/vscripts/tf2ware_ultimate/api/minigame.nut b/scripts/vscripts/tf2ware_ultimate/api/minigame.nut index 6971f7840..b97228fd6 100644 --- a/scripts/vscripts/tf2ware_ultimate/api/minigame.nut +++ b/scripts/vscripts/tf2ware_ultimate/api/minigame.nut @@ -22,6 +22,7 @@ class Ware_MinigameData boss = false show_scores = true end_delay = 0.0 + sort_teams = false convars = [] entities = [] cleanup_names = {} @@ -90,6 +91,8 @@ class Ware_MinigameData end_delay = null // Show player scores on scoreboard while minigame is active, default is true\ show_scores = null + // Sort teams by score for fairness in team-based minigames + sort_teams = null // Custom text overlay to show rather than the default implied from name // This can either be a string or an array of strings (when using missions) custom_overlay = null diff --git a/scripts/vscripts/tf2ware_ultimate/api/player.nut b/scripts/vscripts/tf2ware_ultimate/api/player.nut index 46e293b76..74cdcb752 100644 --- a/scripts/vscripts/tf2ware_ultimate/api/player.nut +++ b/scripts/vscripts/tf2ware_ultimate/api/player.nut @@ -782,6 +782,49 @@ function Ware_GetSortedScorePlayers(reverse) return players } +function Ware_AssignTeamsByScore() +{ + local red_players = [] + local blue_players = [] + local red_score = 0 + local blue_score = 0 + + local sorted = Ware_GetSortedScorePlayers(true) + + foreach (player in sorted) + { + local score = Ware_GetPlayerData(player).score + + if (red_players.len() < blue_players.len()) + { + red_players.append(player) + red_score += score + } + else if (blue_players.len() < red_players.len()) + { + blue_players.append(player) + blue_score += score + } + else + { + if (red_score <= blue_score) + { + red_players.append(player) + red_score += score + } + else + { + blue_players.append(player) + blue_score += score + } + } + } + foreach (player in red_players) + Ware_SetPlayerTeam(player, TF_TEAM_RED) + foreach (player in blue_players) + Ware_SetPlayerTeam(player, TF_TEAM_BLUE) +} + // Adds an attribute to the player // Given attributes are removed automatically when the minigame ends function Ware_AddPlayerAttribute(player, name, value, duration) diff --git a/scripts/vscripts/tf2ware_ultimate/main.nut b/scripts/vscripts/tf2ware_ultimate/main.nut index be00cf8e1..b3ac02694 100644 --- a/scripts/vscripts/tf2ware_ultimate/main.nut +++ b/scripts/vscripts/tf2ware_ultimate/main.nut @@ -1662,6 +1662,9 @@ function Ware_StartMinigameInternal(is_boss) player.RemoveFlag(FL_ATCONTROLS) }, Ware_Minigame.start_freeze) } + + if (Ware_Minigame.sort_teams) + Ware_AssignTeamsByScore() local custom_teleport = "OnTeleport" in Ware_MinigameScope if (location != Ware_MinigameLocation) diff --git a/scripts/vscripts/tf2ware_ultimate/minigames/boxing.nut b/scripts/vscripts/tf2ware_ultimate/minigames/boxing.nut index 497640d84..815309a2f 100644 --- a/scripts/vscripts/tf2ware_ultimate/minigames/boxing.nut +++ b/scripts/vscripts/tf2ware_ultimate/minigames/boxing.nut @@ -14,6 +14,7 @@ minigame <- Ware_MinigameData fail_on_death = true friendly_fire = false collisions = true + sort_teams = true }) start_sound <- "player/taunt_sfx_bell_single.wav" diff --git a/scripts/vscripts/tf2ware_ultimate/minigames/hit_balls.nut b/scripts/vscripts/tf2ware_ultimate/minigames/hit_balls.nut index b11bf1d91..9a48e568c 100644 --- a/scripts/vscripts/tf2ware_ultimate/minigames/hit_balls.nut +++ b/scripts/vscripts/tf2ware_ultimate/minigames/hit_balls.nut @@ -8,6 +8,7 @@ minigame <- Ware_MinigameData location = "boxarena" music = "knockout" min_players = 2 + sort_teams = true }) ball_model <- "models/player/items/scout/soccer_ball.mdl" @@ -33,6 +34,7 @@ function OnTeleport(players) { local red_players = [] local blue_players = [] + foreach (player in players) { local team = player.GetTeam() @@ -41,7 +43,7 @@ function OnTeleport(players) else if (team == TF_TEAM_BLUE) blue_players.append(player) } - + Ware_TeleportPlayersRow(red_players, Ware_MinigameLocation.center + Vector(0, 500.0, 0), QAngle(0, 270, 0), From c3ccf45cbe90ebe8aeac2cd7107d3c98b6f787ea Mon Sep 17 00:00:00 2001 From: tilderain Date: Sat, 20 Sep 2025 08:53:05 -0700 Subject: [PATCH 2/2] Improve the team sorting algorithm hopefully, add prints --- .../vscripts/tf2ware_ultimate/api/player.nut | 121 ++++++++++++------ 1 file changed, 82 insertions(+), 39 deletions(-) diff --git a/scripts/vscripts/tf2ware_ultimate/api/player.nut b/scripts/vscripts/tf2ware_ultimate/api/player.nut index 74cdcb752..af188e282 100644 --- a/scripts/vscripts/tf2ware_ultimate/api/player.nut +++ b/scripts/vscripts/tf2ware_ultimate/api/player.nut @@ -784,45 +784,88 @@ function Ware_GetSortedScorePlayers(reverse) function Ware_AssignTeamsByScore() { - local red_players = [] - local blue_players = [] - local red_score = 0 - local blue_score = 0 - - local sorted = Ware_GetSortedScorePlayers(true) - - foreach (player in sorted) - { - local score = Ware_GetPlayerData(player).score - - if (red_players.len() < blue_players.len()) - { - red_players.append(player) - red_score += score - } - else if (blue_players.len() < red_players.len()) - { - blue_players.append(player) - blue_score += score - } - else - { - if (red_score <= blue_score) - { - red_players.append(player) - red_score += score - } - else - { - blue_players.append(player) - blue_score += score - } - } - } - foreach (player in red_players) - Ware_SetPlayerTeam(player, TF_TEAM_RED) - foreach (player in blue_players) - Ware_SetPlayerTeam(player, TF_TEAM_BLUE) + local red_players = [] + local blue_players = [] + local red_score = 0 + local blue_score = 0 + local red_zero_score_count = 0 + local blue_zero_score_count = 0 + + local sorted_players = Ware_GetSortedScorePlayers(true) + + local scored_players = [] + local zero_score_players = [] + foreach (player in sorted_players) + { + local score = Ware_GetPlayerData(player).score + if (score == 0) + { + zero_score_players.append(player) + } + else + { + scored_players.append(player) + } + } + + foreach (player in scored_players) + { + local score = Ware_GetPlayerData(player).score + if (red_score <= blue_score) + { + red_players.append(player) + red_score += score + } + else + { + blue_players.append(player) + blue_score += score + } + } + + foreach (player in zero_score_players) + { + if (red_players.len() <= blue_players.len()) + { + red_players.append(player) + red_zero_score_count += 1 + } + else + { + blue_players.append(player) + blue_zero_score_count += 1 + } + } + + foreach (player in red_players) + { + Ware_SetPlayerTeam(player, TF_TEAM_RED) + } + foreach (player in blue_players) + { + Ware_SetPlayerTeam(player, TF_TEAM_BLUE) + } + + + //local all_player_scores_str = "All Player Scores (Sorted): [" + //local first_player = true + //foreach (player in sorted_players) + //{ + // if (!first_player) + // { + // all_player_scores_str += ", " + // } + // all_player_scores_str += Ware_GetPlayerData(player).score + // first_player = false + //} + //all_player_scores_str += "]" + //Ware_ChatPrint(null, all_player_scores_str) + + //Ware_ChatPrint(null, "RED Team - Players: " + red_players.len() + ", Total Score: " + red_score) + //Ware_ChatPrint(null, "BLUE Team - Players: " + blue_players.len() + ", Total Score: " + blue_score) + + //Ware_ChatPrint(null, "RED Team Zero Score Players: " + red_zero_score_count) + //Ware_ChatPrint(null, "BLUE Team Zero Score Players: " + blue_zero_score_count) } // Adds an attribute to the player