e60f612f95
[iw4script] reworked balance to balance based on performance rating [stats] log penalty context to database
198 lines
8.2 KiB
C#
198 lines
8.2 KiB
C#
using SharedLibraryCore;
|
|
using SharedLibraryCore.Objects;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace IW4ScriptCommands.Commands
|
|
{
|
|
class Balance : Command
|
|
{
|
|
private class TeamAssignment
|
|
{
|
|
public IW4MAdmin.Plugins.Stats.IW4Info.Team CurrentTeam { get; set; }
|
|
public int Num { get; set; }
|
|
public IW4MAdmin.Plugins.Stats.Models.EFClientStatistics Stats { get; set; }
|
|
}
|
|
public Balance() : base("balance", "balance teams", "bal", Player.Permission.Trusted, false, null)
|
|
{
|
|
}
|
|
|
|
public override async Task ExecuteAsync(GameEvent E)
|
|
{
|
|
string teamsString = (await E.Owner.GetDvarAsync<string>("sv_iw4madmin_teams")).Value;
|
|
|
|
var scriptClientTeams = teamsString.Split(';', StringSplitOptions.RemoveEmptyEntries)
|
|
.Select(c => c.Split(','))
|
|
.Select(c => new TeamAssignment()
|
|
{
|
|
CurrentTeam = (IW4MAdmin.Plugins.Stats.IW4Info.Team)Enum.Parse(typeof(IW4MAdmin.Plugins.Stats.IW4Info.Team), c[1]),
|
|
Num = E.Owner.Players.FirstOrDefault(p => p?.NetworkId == c[0].ConvertLong())?.ClientNumber ?? -1,
|
|
Stats = IW4MAdmin.Plugins.Stats.Plugin.Manager.GetClientStats(E.Owner.Players.FirstOrDefault(p => p?.NetworkId == c[0].ConvertLong()).ClientId, E.Owner.GetHashCode())
|
|
})
|
|
.ToList();
|
|
|
|
// at least one team is full so we can't balance
|
|
if (scriptClientTeams.Count(ct => ct.CurrentTeam == IW4MAdmin.Plugins.Stats.IW4Info.Team.Axis) >= Math.Floor(E.Owner.MaxClients / 2.0)
|
|
|| scriptClientTeams.Count(ct => ct.CurrentTeam == IW4MAdmin.Plugins.Stats.IW4Info.Team.Allies) >= Math.Floor(E.Owner.MaxClients / 2.0))
|
|
{
|
|
await E.Origin?.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BALANCE_FAIL"]);
|
|
return;
|
|
}
|
|
|
|
List<string> teamAssignments = new List<string>();
|
|
|
|
var activeClients = E.Owner.GetPlayersAsList().Select(c => new TeamAssignment()
|
|
{
|
|
Num = c.ClientNumber,
|
|
Stats = IW4MAdmin.Plugins.Stats.Plugin.Manager.GetClientStats(c.ClientId, E.Owner.GetHashCode()),
|
|
CurrentTeam = IW4MAdmin.Plugins.Stats.Plugin.Manager.GetClientStats(c.ClientId, E.Owner.GetHashCode()).Team
|
|
})
|
|
.Where(c => scriptClientTeams.FirstOrDefault(sc => sc.Num == c.Num)?.CurrentTeam != IW4MAdmin.Plugins.Stats.IW4Info.Team.Spectator)
|
|
.Where(c => c.CurrentTeam != scriptClientTeams.FirstOrDefault(p => p.Num == c.Num)?.CurrentTeam)
|
|
.OrderByDescending(c => c.Stats.Performance)
|
|
.ToList();
|
|
|
|
var alliesTeam = scriptClientTeams
|
|
.Where(c => c.CurrentTeam == IW4MAdmin.Plugins.Stats.IW4Info.Team.Allies)
|
|
.Where(c => activeClients.Count(t => t.Num == c.Num) == 0)
|
|
.ToList();
|
|
|
|
var axisTeam = scriptClientTeams
|
|
.Where(c => c.CurrentTeam == IW4MAdmin.Plugins.Stats.IW4Info.Team.Axis)
|
|
.Where(c => activeClients.Count(t => t.Num == c.Num) == 0)
|
|
.ToList();
|
|
|
|
while (activeClients.Count() > 0)
|
|
{
|
|
int teamSizeDifference = alliesTeam.Count - axisTeam.Count;
|
|
double performanceDisparity = alliesTeam.Count > 0 ? alliesTeam.Average(t => t.Stats.Performance) : 0 -
|
|
axisTeam.Count > 0 ? axisTeam.Average(t => t.Stats.Performance) : 0;
|
|
|
|
if (teamSizeDifference == 0)
|
|
{
|
|
if (performanceDisparity == 0)
|
|
{
|
|
alliesTeam.Add(activeClients.First());
|
|
activeClients.RemoveAt(0);
|
|
}
|
|
else
|
|
{
|
|
if (performanceDisparity > 0)
|
|
{
|
|
axisTeam.Add(activeClients.First());
|
|
activeClients.RemoveAt(0);
|
|
}
|
|
else
|
|
{
|
|
alliesTeam.Add(activeClients.First());
|
|
activeClients.RemoveAt(0);
|
|
}
|
|
}
|
|
}
|
|
else if (teamSizeDifference > 0)
|
|
{
|
|
if (performanceDisparity > 0)
|
|
{
|
|
axisTeam.Add(activeClients.First());
|
|
activeClients.RemoveAt(0);
|
|
}
|
|
|
|
else
|
|
{
|
|
axisTeam.Add(activeClients.Last());
|
|
activeClients.RemoveAt(activeClients.Count - 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (performanceDisparity > 0)
|
|
{
|
|
alliesTeam.Add(activeClients.First());
|
|
activeClients.RemoveAt(0);
|
|
}
|
|
|
|
else
|
|
{
|
|
alliesTeam.Add(activeClients.Last());
|
|
activeClients.RemoveAt(activeClients.Count - 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
alliesTeam = alliesTeam.OrderByDescending(t => t.Stats.Performance)
|
|
.ToList();
|
|
|
|
axisTeam = axisTeam.OrderByDescending(t => t.Stats.Performance)
|
|
.ToList();
|
|
|
|
while (Math.Abs(alliesTeam.Count - axisTeam.Count) > 1)
|
|
{
|
|
int teamSizeDifference = alliesTeam.Count - axisTeam.Count;
|
|
double performanceDisparity = alliesTeam.Count > 0 ? alliesTeam.Average(t => t.Stats.Performance) : 0 -
|
|
axisTeam.Count > 0 ? axisTeam.Average(t => t.Stats.Performance) : 0;
|
|
|
|
if (teamSizeDifference > 0)
|
|
{
|
|
if (performanceDisparity > 0)
|
|
{
|
|
axisTeam.Add(alliesTeam.First());
|
|
alliesTeam.RemoveAt(0);
|
|
}
|
|
|
|
else
|
|
{
|
|
axisTeam.Add(alliesTeam.Last());
|
|
alliesTeam.RemoveAt(axisTeam.Count - 1);
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
if (performanceDisparity > 0)
|
|
{
|
|
alliesTeam.Add(axisTeam.Last());
|
|
axisTeam.RemoveAt(axisTeam.Count - 1);
|
|
}
|
|
|
|
else
|
|
{
|
|
alliesTeam.Add(axisTeam.First());
|
|
axisTeam.RemoveAt(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (var assignment in alliesTeam)
|
|
{
|
|
teamAssignments.Add($"{assignment.Num},2");
|
|
assignment.Stats.Team = IW4MAdmin.Plugins.Stats.IW4Info.Team.Allies;
|
|
}
|
|
foreach (var assignment in axisTeam)
|
|
{
|
|
teamAssignments.Add($"{assignment.Num},3");
|
|
assignment.Stats.Team = IW4MAdmin.Plugins.Stats.IW4Info.Team.Axis;
|
|
}
|
|
|
|
if (alliesTeam.Count(ac => scriptClientTeams.First(sc => sc.Num == ac.Num).CurrentTeam != ac.CurrentTeam) == 0 &&
|
|
axisTeam.Count(ac => scriptClientTeams.First(sc => sc.Num == ac.Num).CurrentTeam != ac.CurrentTeam) == 0)
|
|
{
|
|
await E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BALANCE_FAIL_BALANCED"]);
|
|
return;
|
|
}
|
|
|
|
if (E.Origin?.Level > Player.Permission.Administrator)
|
|
{
|
|
await E.Origin.Tell($"Allies Elo: {(alliesTeam.Count > 0 ? alliesTeam.Average(t => t.Stats.Performance) : 0)}");
|
|
await E.Origin.Tell($"Axis Elo: {(axisTeam.Count > 0 ? axisTeam.Average(t => t.Stats.Performance) : 0)}");
|
|
}
|
|
|
|
string args = string.Join(",", teamAssignments);
|
|
await E.Owner.ExecuteCommandAsync($"sv_iw4madmin_command \"balance:{args}\"");
|
|
await E.Origin.Tell("Balance command sent");
|
|
}
|
|
}
|
|
}
|