Skip to content

Commit

Permalink
Feat: Performance score based on KDA, Damage, and Score + A lot of ch…
Browse files Browse the repository at this point in the history
…anges...
  • Loading branch information
Mesharsky committed Aug 22, 2024
1 parent 7d4127f commit 01718ef
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 49 deletions.
11 changes: 10 additions & 1 deletion Class/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,18 @@ public partial class Mesharsky_TeamBalance
{
public class Player
{
public string ?PlayerName { get; set; }
public string? PlayerName { get; set; }
public ulong PlayerSteamID { get; set; }
public int Team { get; set; }
public int Score { get; set; }
public int Kills { get; set; }
public int Deaths { get; set; }
public int Damage { get; set; }

// KDA Ratio: (Kills + Assists) / Deaths
public float KDA => Deaths == 0 ? Kills : (float)(Kills) / Deaths;

// Performance score based on KDA, Damage, and Score
public float PerformanceScore => KDA * 0.5f + Damage * 0.3f + Score * 0.2f;
}
}
47 changes: 31 additions & 16 deletions Config/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@ public void LoadConfiguration()
{
var minPlayers = int.Parse(pluginTable["minimum_players"]?.ToString() ?? "4");
var maxScoreBalanceRatio = float.Parse(pluginTable["score_balance_ratio"]?.ToString() ?? "1.6");
var usePerformanceScore = bool.Parse(pluginTable["use_performance_score"]?.ToString() ?? "true");
var maxTeamSizeDifference = int.Parse(pluginTable["max_team_size_difference"]?.ToString() ?? "1");

var pluginSettings = new PluginSettingsConfig
{
MinPlayers = minPlayers,
MaxScoreBalanceRatio = maxScoreBalanceRatio
MaxScoreBalanceRatio = maxScoreBalanceRatio,
UsePerformanceScore = usePerformanceScore,
MaxTeamSizeDifference = maxTeamSizeDifference
};

Config = new BalanceConfig
Expand All @@ -50,21 +54,32 @@ private static void GenerateDefaultConfigFile(string configPath)

var defaultConfig = new StringBuilder();

defaultConfig.AppendLine("# Team Balance Plugin Configuration")
.AppendLine("# Adjust these settings according to your server's needs.")
.AppendLine()
.AppendLine("[PluginSettings]")
.AppendLine("# The minimum number of players required on the server before the team balance")
.AppendLine("# feature activates. This prevents balancing when there are too few players,")
.AppendLine("# Default: 4")
.AppendLine("minimum_players = 4")
.AppendLine()
.AppendLine("# The maximum allowed ratio of scores between teams before triggering a balance.")
.AppendLine("# For example, if set to 1.6, the balance will trigger if one team's score is")
.AppendLine("# 60% higher than the other team's score. Adjust this value based on how strict")
.AppendLine("# you want the balancing to be.")
.AppendLine("# Default: 1.6")
.AppendLine("score_balance_ratio = 1.6");
defaultConfig.AppendLine("# Plugin Author - Mesharsky")
.AppendLine("# https://csowicze.pl/")
.AppendLine()
.AppendLine("# Team Balance Plugin Configuration")
.AppendLine("# Adjust these settings according to your server's needs.")
.AppendLine()
.AppendLine("[PluginSettings]")
.AppendLine("# The minimum number of players required on the server before the team balance")
.AppendLine("# feature activates. This prevents balancing when there are too few players.")
.AppendLine("# Default: 4")
.AppendLine("minimum_players = 4")
.AppendLine()
.AppendLine("# The maximum allowed ratio of scores between teams before triggering a balance.")
.AppendLine("# For example, if set to 1.6, the balance will trigger if one team's score is")
.AppendLine("# 60% higher than the other team's score. Adjust this value based on how strict")
.AppendLine("# you want the balancing to be.")
.AppendLine("# Default: 1.6")
.AppendLine("score_balance_ratio = 1.6")
.AppendLine()
.AppendLine("# Whether to use PerformanceScore for balancing.")
.AppendLine("# Default: true")
.AppendLine("use_performance_score = true")
.AppendLine()
.AppendLine("# Maximum allowed difference in team sizes.")
.AppendLine("# Default: 1")
.AppendLine("max_team_size_difference = 1");

File.WriteAllText(configPath, defaultConfig.ToString());

Expand Down
2 changes: 2 additions & 0 deletions Config/ConfigList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ public class PluginSettingsConfig
{
public int MinPlayers { get; set; } = 4;
public float MaxScoreBalanceRatio { get; set; } = 1.6f;
public bool UsePerformanceScore { get; set; } = true;
public int MaxTeamSizeDifference { get; set; } = 1;
}
}
62 changes: 50 additions & 12 deletions Events/Events.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,15 @@ public void Initialize_Events()
}

[GameEventHandler]
public HookResult OnRoundPreStart(EventRoundPrestart @event, GameEventInfo info)
public HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info)
{
UpdatePlayerStatsInCache();

AttemptBalanceTeams();
return HookResult.Continue;
}

[GameEventHandler]
public HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info)
{
if (BalanceHasBeenMade)
{
Server.PrintToChatAll($"{ChatColors.Red}[Balans Drużyn] {ChatColors.Default}Drużyny zostały zbalansowane");
Server.PrintToChatAll($" {ChatColors.Red}[Balans Drużyn] {ChatColors.Default}Drużyny zostały zbalansowane");
PrintDebugMessage("Teams have been balanced.");
}
return HookResult.Continue;
Expand All @@ -38,11 +35,14 @@ public void Event_PlayerJoin()
{
RegisterListener<Listeners.OnClientPutInServer>((slot) =>
{
var player = Utilities.GetPlayerFromSlot(slot);
if (player != null && player.IsValid && !player.IsBot)
AddTimer(3.0f, () =>
{
var player = Utilities.GetPlayerFromSlot(slot);
if (player == null || !player.IsValid || player.IsBot)
return;

ProcessUserInformation(player);
}
});
});
}

Expand Down Expand Up @@ -73,11 +73,49 @@ private static void ProcessUserInformation(CCSPlayerController player)
{
PlayerName = player.PlayerName,
PlayerSteamID = steamId,
Team = (int)player.Team,
Score = player.Score
Team = player.TeamNum,
Kills = 0,
Deaths = 0,
Damage = 0,
Score = 0,
};

playerCache.AddOrUpdate(steamId, cachedPlayer, (key, oldPlayer) => cachedPlayer);
PrintDebugMessage($"Player {player.PlayerName} with SteamID {steamId} added to cache.");
}

private static void UpdatePlayerStatsInCache()
{
PrintDebugMessage("Updating player stats in cache...");

var allPlayers = Utilities.GetPlayers();

foreach (var player in allPlayers.Where(p => p != null && p.IsValid && !p.IsBot && !p.IsHLTV && p.Connected == PlayerConnectedState.PlayerConnected))
{
if (playerCache.TryGetValue(player.SteamID, out var cachedPlayer))
{
cachedPlayer.Kills = player.ActionTrackingServices!.MatchStats.Kills;
cachedPlayer.Deaths = player.ActionTrackingServices.MatchStats.Deaths;
cachedPlayer.Damage = player.ActionTrackingServices.MatchStats.Damage;
cachedPlayer.Score = player.Score;
PrintDebugMessage($"Updated {cachedPlayer.PlayerName} stats in cache.");
}
else
{
var newPlayer = new Player
{
PlayerName = player.PlayerName,
PlayerSteamID = player.SteamID,
Team = player.TeamNum,
Kills = player.ActionTrackingServices!.MatchStats.Kills,
Deaths = player.ActionTrackingServices.MatchStats.Deaths,
Damage = player.ActionTrackingServices.MatchStats.Damage,
Score = player.Score,
};

playerCache.TryAdd(player.SteamID, newPlayer);
PrintDebugMessage($"Added {newPlayer.PlayerName} to cache with stats.");
}
}
}
}
25 changes: 13 additions & 12 deletions Helpers/BalanceFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ private static List<Player> GetPlayersForRebalance()
{
var players = playerCache.Values
.Where(p => p.Team == (int)CsTeam.CounterTerrorist || p.Team == (int)CsTeam.Terrorist)
.OrderBy(x => Guid.NewGuid())
.OrderByDescending(p => p.Score)
.OrderByDescending(p => Config?.PluginSettings.UsePerformanceScore == true ? p.PerformanceScore : p.Score)
.ToList();

players.Shuffle();

PrintDebugMessage($"Total valid players for rebalance: {players.Count}");
return players;
}
Expand All @@ -51,13 +52,13 @@ private static bool RebalancePlayers(List<Player> players)
List<Player> ctTeam = new List<Player>();
List<Player> tTeam = new List<Player>();

int ctTotalScore = 0;
int tTotalScore = 0;
float ctTotalScore = 0f;
float tTotalScore = 0f;

bool balanceMade = false;

PrintDebugMessage($"RebalancePlayers: totalPlayers={totalPlayers}, maxPerTeam={maxPerTeam}");

foreach (var player in players)
{
bool ctValidChoice = (tTeam.Count >= maxPerTeam || ctTotalScore <= tTotalScore) && ctTeam.Count < maxPerTeam;
Expand All @@ -67,31 +68,31 @@ private static bool RebalancePlayers(List<Player> players)
{
PrintDebugMessage($"Move {player.PlayerName} to CT (ctTotal={ctTotalScore}, ctCount={ctTeam.Count + 1})");
ChangePlayerTeam(player.PlayerSteamID, CsTeam.CounterTerrorist);

Server.PrintToChatAll($" {ChatColors.Green}{player.PlayerName} {ChatColors.Default} został przeniesiony do {ChatColors.Blue}Counter-Terrorists{ChatColors.Default} aby wyrównać drużyny.");
ctTeam.Add(player);
ctTotalScore += player.Score;
ctTotalScore += player.PerformanceScore;
balanceMade = true;
}
else if (tValidChoice && player.Team != (int)CsTeam.Terrorist)
{
PrintDebugMessage($"Move {player.PlayerName} to T (tTotal={tTotalScore}, tCount={tTeam.Count + 1})");
ChangePlayerTeam(player.PlayerSteamID, CsTeam.Terrorist);
Server.PrintToChatAll($"{ChatColors.Green}{player.PlayerName} {ChatColors.Default} został przeniesiony do {ChatColors.Red}Terrorists{ChatColors.Default} aby wyrównać drużyny.");
Server.PrintToChatAll($" {ChatColors.Green}{player.PlayerName} {ChatColors.Default} został przeniesiony do {ChatColors.Red}Terrorists{ChatColors.Default} aby wyrównać drużyny.");
tTeam.Add(player);
tTotalScore += player.Score;
tTotalScore += player.PerformanceScore;
balanceMade = true;
}
else
{
if (player.Team == (int)CsTeam.CounterTerrorist)
{
ctTeam.Add(player);
ctTotalScore += player.Score;
ctTotalScore += player.PerformanceScore;
}
else if (player.Team == (int)CsTeam.Terrorist)
{
tTeam.Add(player);
tTotalScore += player.Score;
tTotalScore += player.PerformanceScore;
}
}
}
Expand Down Expand Up @@ -129,7 +130,7 @@ private static bool ShouldTeamsBeRebalanced()
return true;
}

if (Math.Abs(ctPlayerCount - tPlayerCount) > 1)
if (Math.Abs(ctPlayerCount - tPlayerCount) > Config?.PluginSettings.MaxTeamSizeDifference)
{
PrintDebugMessage("Team sizes are not equal. Balance needed.");
return true;
Expand Down
6 changes: 0 additions & 6 deletions Helpers/Misc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@ namespace Mesharsky_TeamBalance;

public partial class Mesharsky_TeamBalance
{
public static int GetTeamScore(CsTeam team)
{
var allPlayers = Utilities.GetPlayers();
return allPlayers.Where(p => p.Team == team).Sum(p => p.Score);
}

private static void PrintDebugMessage(string message)
{
Console.WriteLine($"[Team Balance] {message}");
Expand Down
15 changes: 15 additions & 0 deletions Helpers/ShuffleExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
public static class ShuffleExtension
{
private static readonly Random rng = new();

public static void Shuffle<T>(this IList<T> list)
{
int n = list.Count;
while (n > 1)
{
n--;
int k = rng.Next(n + 1);
(list[n], list[k]) = (list[k], list[n]);
}
}
}
15 changes: 14 additions & 1 deletion Mesharsky_TeamBalance.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Cvars;

namespace Mesharsky_TeamBalance;

Expand All @@ -14,7 +15,19 @@ public override void Load(bool hotReload)
{
LoadConfiguration();
Initialize_Events();

AddCommandListener("jointeam", Command_JoinTeam);

AddTimer(7.0f, () =>
{
string conVarName = "mp_autoteambalance";
ConVar? cvar = ConVar.Find(conVarName);

if (cvar == null)
return;

cvar.SetValue(false);

PrintDebugMessage("Convar 'mp_autoteambalance' has been set to 'false'");
});
}
}
13 changes: 12 additions & 1 deletion TeamBalance.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Plugin Author - Mesharsky
# https://csowicze.pl/

# Team Balance Plugin Configuration
# Make sure to adjust these settings according to your server's needs.

Expand All @@ -12,4 +15,12 @@ minimum_players = 4
# 60% higher than the other team's score. Adjust this value based on how strict
# you want the balancing to be.
# Default: 1.6
score_balance_ratio = 1.6
score_balance_ratio = 1.6

# Whether to use PerformanceScore for balancing.
# Default: true
use_performance_score = true

# Maximum allowed difference in team sizes.
# Default: 1
max_team_size_difference = 1

0 comments on commit 01718ef

Please sign in to comment.