diff --git a/RetakesAllocator/CounterStrikeSharpImpl.cs b/RetakesAllocator/CounterStrikeSharpImpl.cs new file mode 100644 index 0000000..b8c7fc5 --- /dev/null +++ b/RetakesAllocator/CounterStrikeSharpImpl.cs @@ -0,0 +1,306 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Entities.Constants; +using CounterStrikeSharp.API.Modules.Utils; +using RetakesAllocatorCore; +using RetakesAllocatorCore.CounterStrikeSharpInterfaces; + +namespace RetakesAllocator; + +public class NativeApiImpl : INativeAPIAdapter +{ + public void IssueClientCommand(int clientIndex, string command) + { + NativeAPI.IssueClientCommand(clientIndex, command); + } +} + +public class ServerImpl : IServerAdapter +{ + public void PrintToChatAll(string message) + { + Server.PrintToChatAll(message); + } +} + +public class PlayerWeaponImpl : IPlayerWeaponAdapter +{ + private readonly CHandle _weapon; + + public PlayerWeaponImpl(CHandle weapon) + { + _weapon = weapon; + } + + public bool IsValid => _weapon.IsValid && (_weapon.Value?.IsValid ?? false); + public string DesignerName => _weapon.Value?.DesignerName ?? ""; + + public CsItem? Item => + _weapon.Value is not null + ? Utils.ToEnum(DesignerName) + : null; + + public nint? Handle => _weapon.Value?.Handle; + + public void Remove() + { + _weapon.Value?.Remove(); + } +} + +public class WeaponServicesImpl : IWeaponServicesAdapter +{ + private readonly CPlayer_WeaponServices _weaponServices; + + public WeaponServicesImpl(CPlayer_WeaponServices weaponServices) + { + _weaponServices = weaponServices; + } + + public ICollection MyWeapons => + _weaponServices + .MyWeapons + .Select(w => new PlayerWeaponImpl(w)) + .Cast() + .ToList(); +} + +public class CCSPlayerPawnImpl : ICCSPlayerPawnAdapter +{ + private readonly CHandle _pawn; + + public CCSPlayerPawnImpl(CHandle pawn) + { + _pawn = pawn; + } + + public IWeaponServicesAdapter? WeaponServices => + _pawn.Value?.WeaponServices is not null + ? new WeaponServicesImpl(_pawn.Value.WeaponServices) + : null; + + public void RemovePlayerItem(IPlayerWeaponAdapter weapon) + { + if (weapon.Handle is not null) + { + _pawn.Value?.RemovePlayerItem(new CBasePlayerWeapon(weapon.Handle.Value)); + } + } +} + +public class CCSPlayer_ItemServicesImpl : ICCSPlayer_ItemServicesAdapter +{ + private readonly CCSPlayer_ItemServices? _itemServices; + + public CCSPlayer_ItemServicesImpl(CPlayer_ItemServices? itemServices) + { + _itemServices = itemServices is not null + ? new CCSPlayer_ItemServices(itemServices.Handle) + : null; + } + + public bool HasDefuser + { + get => _itemServices?.HasDefuser ?? false; + set + { + if (_itemServices is not null) + { + _itemServices.HasDefuser = value; + } + } + } + + public bool IsValid => _itemServices?.Handle is not null; +} + +public class CCSPlayerControllerImpl : ICCSPlayerControllerAdapter +{ + private readonly CCSPlayerController? _player; + + public CCSPlayerControllerImpl(CCSPlayerController? player) + { + _player = player; + } + + public int? UserId => _player?.UserId; + public bool IsValid => _player?.IsValid ?? false; + + public ulong SteamId => _player is not null + ? _player.AuthorizedSteamID?.SteamId64 ?? 0 + : 0; + + public CsTeam Team => _player?.Team ?? CsTeam.None; + + public ICCSPlayerPawnAdapter? PlayerPawn => _player is not null + ? new CCSPlayerPawnImpl(_player.PlayerPawn) + : null; + + public ICCSPlayer_ItemServicesAdapter? ItemServices => + new CCSPlayer_ItemServicesImpl(_player?.PlayerPawn.Value?.ItemServices); + + public void GiveNamedItem(CsItem item) + { + _player?.GiveNamedItem(item); + } +} + +public class UtilitiesImpl : IUtilitiesAdapter +{ + public List GetPlayers() + { + return Utilities + .GetPlayers() + .Select(player => new CCSPlayerControllerImpl(player)) + .Cast().ToList(); + } +} + +public class CounterStrikeSharpImpl : ICounterStrikeSharpAdapter +{ + public INativeAPIAdapter NativeApi => new NativeApiImpl(); + public IServerAdapter Server => new ServerImpl(); + public IUtilitiesAdapter Utilities => new UtilitiesImpl(); + public string MessagePrefix => PluginInfo.MessagePrefix; + + private readonly RetakesAllocator _plugin; + + public CounterStrikeSharpImpl(RetakesAllocator plugin) + { + _plugin = plugin; + } + + public void AllocateItemsForPlayer(ICCSPlayerControllerAdapter player, ICollection items, string? slotToSelect) + { + // Log.Write($"Allocating items: {string.Join(",", items)}"); + AddTimer(0.1f, () => + { + if (!player.IsValid) + { + // Log.Write($"Player is not valid when allocating item"); + return; + } + + foreach (var item in items) + { + player.GiveNamedItem(item); + } + + if (slotToSelect is not null) + { + AddTimer(0.1f, () => + { + if (player.IsValid && player.UserId is not null) + { + NativeApi.IssueClientCommand((int) player.UserId, slotToSelect); + } + }); + } + }); + } + + public void GiveDefuseKit(ICCSPlayerControllerAdapter player) + { + _plugin.AddTimer(0.1f, () => + { + var itemServices = player.ItemServices; + if ((itemServices?.IsValid ?? false) && player.IsValid) + { + itemServices.HasDefuser = true; + } + }); + } + + public void AddTimer(float interval, Action callback) + { + _plugin.AddTimer(interval, callback); + } + + public bool PlayerIsValid(ICCSPlayerControllerAdapter? player) + { + return (player?.IsValid ?? false) && player.SteamId != 0; + } + + public ICollection CommandInfoToArgList(ICommandInfoAdapter commandInfo, bool includeFirst = false) + { + var result = new List(); + + for (var i = includeFirst ? 0 : 1; i < commandInfo.ArgCount; i++) + { + result.Add(commandInfo.GetArg(i)); + } + + return result; + } + + public bool RemoveWeapons(ICCSPlayerControllerAdapter player, Func? where = null) + { + if (!PlayerIsValid(player) || player.PlayerPawn?.WeaponServices is null) + { + return false; + } + + var removed = false; + + foreach (var weapon in player.PlayerPawn.WeaponServices.MyWeapons) + { + // Log.Write($"want to remove wep {weapon.Value?.DesignerName} {weapon.IsValid}"); + if (!weapon.IsValid) + { + continue; + } + + // Log.Write($"item to remove: {item}"); + var item = weapon.Item; + if ( + where is not null && + (item is null || !where(item.Value)) + ) + { + continue; + } + + // Log.Write($"Removing weapon {weapon.Value.DesignerName} {weapon.IsValid}"); + + player.PlayerPawn.RemovePlayerItem(weapon); + weapon.Remove(); + + removed = true; + } + + return removed; + } + + private CCSGameRules GetGameRules() + { + var gameRulesEntities = CounterStrikeSharp.API.Utilities.FindAllEntitiesByDesignerName("cs_gamerules"); + var gameRules = gameRulesEntities.First().GameRules; + + if (gameRules is null) + { + const string message = "Game rules were null."; + Log.Write(message); + throw new Exception(message); + } + + return gameRules; + } + + public bool IsWarmup() + { + return GetGameRules().WarmupPeriod; + } + + public bool IsWeaponAllocationAllowed() + { + return WeaponHelpers.IsWeaponAllocationAllowed(GetGameRules().FreezePeriod); + } + + public double GetVectorDistance(IVector v1, IVector v2) + { + var dx = v1.X - v2.X; + var dy = v1.Y - v2.Y; + + return Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2)); + } +} diff --git a/RetakesAllocator/Helpers.cs b/RetakesAllocator/Helpers.cs index 958461b..318dd93 100644 --- a/RetakesAllocator/Helpers.cs +++ b/RetakesAllocator/Helpers.cs @@ -14,14 +14,6 @@ public static bool PlayerIsValid(CCSPlayerController? player) return player is not null && player.IsValid && player.AuthorizedSteamID is not null; } - public static void WriteNewlineDelimited(string message, Action writer) - { - foreach (var line in message.Split("\n")) - { - writer($"{PluginInfo.MessagePrefix}{line}"); - } - } - public static ICollection CommandInfoToArgList(CommandInfo commandInfo, bool includeFirst = false) { var result = new List(); diff --git a/RetakesAllocator/RetakesAllocator.cs b/RetakesAllocator/RetakesAllocator.cs index db53607..3427282 100644 --- a/RetakesAllocator/RetakesAllocator.cs +++ b/RetakesAllocator/RetakesAllocator.cs @@ -1,4 +1,6 @@ -using CounterStrikeSharp.API; +using System.Collections; +using System.Drawing; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes; using CounterStrikeSharp.API.Core.Attributes.Registration; @@ -6,11 +8,11 @@ using CounterStrikeSharp.API.Modules.Commands; using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Entities.Constants; -using CounterStrikeSharp.API.Modules.Utils; using RetakesAllocatorCore; using RetakesAllocatorCore.Config; using RetakesAllocatorCore.Db; using RetakesAllocator.Menus; +using RetakesAllocatorCore.Helpers; using SQLitePCL; using static RetakesAllocatorCore.PluginInfo; @@ -146,7 +148,7 @@ private void HandleWeaponCommand(CCSPlayerController? player, CommandInfo comman false, out var selectedWeapon ); - Helpers.WriteNewlineDelimited(result, l => commandInfo.ReplyToCommand(l)); + Utils.WriteNewlineDelimited(result, l => commandInfo.ReplyToCommand(l)); if (Helpers.IsWeaponAllocationAllowed() && selectedWeapon is not null) { @@ -170,7 +172,7 @@ out var selectedWeapon WeaponAllocationType.Preferred => "slot1", _ => throw new ArgumentOutOfRangeException() }; - AllocateItemsForPlayer(player, new List {selectedWeapon.Value}, slot); + new CounterStrikeSharpImpl(this).AllocateItemsForPlayer(new CCSPlayerControllerImpl(player), new List {selectedWeapon.Value}, slot); } } } @@ -198,7 +200,7 @@ public void OnAwpCommand(CCSPlayerController? player, CommandInfo commandInfo) currentPreferredSetting is not null, out _ ); - Helpers.WriteNewlineDelimited(result, l => commandInfo.ReplyToCommand(l)); + Utils.WriteNewlineDelimited(result, l => commandInfo.ReplyToCommand(l)); } [ConsoleCommand("css_removegun")] @@ -333,7 +335,7 @@ purchasedAllocationType is not null if (replacementItem is not null) { replacedWeapon = true; - AllocateItemsForPlayer(player, new List + new CounterStrikeSharpImpl(this).AllocateItemsForPlayer(new CCSPlayerControllerImpl(player), new List { replacementItem.Value }, slotToSelect); @@ -397,7 +399,7 @@ p.AbsOrigin is null false, out _ ); - Helpers.WriteNewlineDelimited(message, player.PrintToChat); + Utils.WriteNewlineDelimited(message, player.PrintToChat); } } @@ -407,35 +409,8 @@ out _ [GameEventHandler] public HookResult OnRoundPostStart(EventRoundPoststart @event, GameEventInfo info) { - if (Helpers.IsWarmup()) - { - return HookResult.Continue; - } - - var allPlayers = Utilities.GetPlayers() - .Where(Helpers.PlayerIsValid) - .ToList(); - - OnRoundPostStartHelper.Handle( - _nextRoundType, - allPlayers, - Helpers.GetSteamId, - Helpers.GetTeam, - GiveDefuseKit, - AllocateItemsForPlayer, - out var currentRoundType - ); - _currentRoundType = currentRoundType; - _nextRoundType = null; - - if (Configs.GetConfigData().EnableRoundTypeAnnouncement) - { - Server.PrintToChatAll( - $"{MessagePrefix}{Enum.GetName(_currentRoundType.Value)} Round" - ); - } - - return HookResult.Continue; + var css = new CounterStrikeSharpImpl(this); + return OnRoundPostStartHelper.Handle(_nextRoundType, css, out _currentRoundType); } #endregion @@ -444,31 +419,7 @@ out var currentRoundType private void AllocateItemsForPlayer(CCSPlayerController player, ICollection items, string? slotToSelect) { - // Log.Write($"Allocating items: {string.Join(",", items)}"); - AddTimer(0.1f, () => - { - if (!Helpers.PlayerIsValid(player)) - { - // Log.Write($"Player is not valid when allocating item"); - return; - } - - foreach (var item in items) - { - player.GiveNamedItem(item); - } - - if (slotToSelect is not null) - { - AddTimer(0.1f, () => - { - if (Helpers.PlayerIsValid(player) && player.UserId is not null) - { - NativeAPI.IssueClientCommand((int) player.UserId, slotToSelect); - } - }); - } - }); + // TODO refactor to CounterStrikeSharpImpl } private void GiveDefuseKit(CCSPlayerController player) diff --git a/RetakesAllocatorCore/CounterStrikeSharpInterfaces/ICCSPlayerControllerAdapter.cs b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/ICCSPlayerControllerAdapter.cs new file mode 100644 index 0000000..c87deda --- /dev/null +++ b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/ICCSPlayerControllerAdapter.cs @@ -0,0 +1,18 @@ +using CounterStrikeSharp.API.Modules.Entities.Constants; +using CounterStrikeSharp.API.Modules.Utils; + +namespace RetakesAllocatorCore.CounterStrikeSharpInterfaces; + +public interface ICCSPlayerControllerAdapter +{ + public int? UserId { get; } + public bool IsValid { get; } + public ulong SteamId { get; } + public CsTeam Team { get; } + + public ICCSPlayerPawnAdapter? PlayerPawn { get; } + + public ICCSPlayer_ItemServicesAdapter? ItemServices { get; } + + public void GiveNamedItem(CsItem item); +} diff --git a/RetakesAllocatorCore/CounterStrikeSharpInterfaces/ICCSPlayerPawnAdapter.cs b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/ICCSPlayerPawnAdapter.cs new file mode 100644 index 0000000..3be3425 --- /dev/null +++ b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/ICCSPlayerPawnAdapter.cs @@ -0,0 +1,8 @@ +namespace RetakesAllocatorCore.CounterStrikeSharpInterfaces; + +public interface ICCSPlayerPawnAdapter +{ + public IWeaponServicesAdapter? WeaponServices { get; } + + public void RemovePlayerItem(IPlayerWeaponAdapter weapon); +} \ No newline at end of file diff --git a/RetakesAllocatorCore/CounterStrikeSharpInterfaces/ICCSPlayer_ItemServicesAdapter.cs b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/ICCSPlayer_ItemServicesAdapter.cs new file mode 100644 index 0000000..aaf6708 --- /dev/null +++ b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/ICCSPlayer_ItemServicesAdapter.cs @@ -0,0 +1,7 @@ +namespace RetakesAllocatorCore.CounterStrikeSharpInterfaces; + +public interface ICCSPlayer_ItemServicesAdapter +{ + public bool HasDefuser { get; set; } + public bool IsValid { get; } +} diff --git a/RetakesAllocatorCore/CounterStrikeSharpInterfaces/ICommandInfoAdapter.cs b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/ICommandInfoAdapter.cs new file mode 100644 index 0000000..3d2256a --- /dev/null +++ b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/ICommandInfoAdapter.cs @@ -0,0 +1,7 @@ +namespace RetakesAllocatorCore.CounterStrikeSharpInterfaces; + +public interface ICommandInfoAdapter +{ + public string GetArg(int index); + public int ArgCount { get; } +} diff --git a/RetakesAllocatorCore/CounterStrikeSharpInterfaces/ICounterStrikeSharpAdapter.cs b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/ICounterStrikeSharpAdapter.cs new file mode 100644 index 0000000..a072e8d --- /dev/null +++ b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/ICounterStrikeSharpAdapter.cs @@ -0,0 +1,30 @@ +using CounterStrikeSharp.API.Modules.Entities.Constants; + +namespace RetakesAllocatorCore.CounterStrikeSharpInterfaces; + +public interface ICounterStrikeSharpAdapter +{ + public INativeAPIAdapter NativeApi { get; } + public IServerAdapter Server { get; } + public IUtilitiesAdapter Utilities { get; } + + public string MessagePrefix { get; } + + void AllocateItemsForPlayer(ICCSPlayerControllerAdapter player, ICollection items, string? slotToSelect); + + public void GiveDefuseKit(ICCSPlayerControllerAdapter player); + + public void AddTimer(float interval, Action callback); + + public bool PlayerIsValid(ICCSPlayerControllerAdapter? player); + + public ICollection CommandInfoToArgList(ICommandInfoAdapter commandInfo, bool includeFirst = false); + + public bool RemoveWeapons(ICCSPlayerControllerAdapter playerController, Func? where = null); + + public bool IsWarmup(); + + public bool IsWeaponAllocationAllowed(); + + public double GetVectorDistance(IVector v1, IVector v2); +} diff --git a/RetakesAllocatorCore/CounterStrikeSharpInterfaces/INativeAPIAdapter.cs b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/INativeAPIAdapter.cs new file mode 100644 index 0000000..cea5560 --- /dev/null +++ b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/INativeAPIAdapter.cs @@ -0,0 +1,6 @@ +namespace RetakesAllocatorCore.CounterStrikeSharpInterfaces; + +public interface INativeAPIAdapter +{ + public void IssueClientCommand(int clientIndex, string command); +} diff --git a/RetakesAllocatorCore/CounterStrikeSharpInterfaces/IPlayerWeaponAdapter.cs b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/IPlayerWeaponAdapter.cs new file mode 100644 index 0000000..32d6609 --- /dev/null +++ b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/IPlayerWeaponAdapter.cs @@ -0,0 +1,14 @@ +using CounterStrikeSharp.API.Modules.Entities.Constants; + +namespace RetakesAllocatorCore.CounterStrikeSharpInterfaces; + +public interface IPlayerWeaponAdapter +{ + public bool IsValid { get; } + public string DesignerName { get; } + public CsItem? Item { get; } + + public nint? Handle { get; } + + public void Remove(); +} diff --git a/RetakesAllocatorCore/CounterStrikeSharpInterfaces/IServerAdapter.cs b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/IServerAdapter.cs new file mode 100644 index 0000000..fae5881 --- /dev/null +++ b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/IServerAdapter.cs @@ -0,0 +1,6 @@ +namespace RetakesAllocatorCore.CounterStrikeSharpInterfaces; + +public interface IServerAdapter +{ + public void PrintToChatAll(string message); +} diff --git a/RetakesAllocatorCore/CounterStrikeSharpInterfaces/IUtilitiesAdapter.cs b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/IUtilitiesAdapter.cs new file mode 100644 index 0000000..ce74198 --- /dev/null +++ b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/IUtilitiesAdapter.cs @@ -0,0 +1,6 @@ +namespace RetakesAllocatorCore.CounterStrikeSharpInterfaces; + +public interface IUtilitiesAdapter +{ + List GetPlayers(); +} diff --git a/RetakesAllocatorCore/CounterStrikeSharpInterfaces/IVector.cs b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/IVector.cs new file mode 100644 index 0000000..7a0a09f --- /dev/null +++ b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/IVector.cs @@ -0,0 +1,7 @@ +namespace RetakesAllocatorCore.CounterStrikeSharpInterfaces; + +public interface IVector +{ + public float X { get; } + public float Y { get; } +} diff --git a/RetakesAllocatorCore/CounterStrikeSharpInterfaces/IWeaponServicesAdapter.cs b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/IWeaponServicesAdapter.cs new file mode 100644 index 0000000..54608d3 --- /dev/null +++ b/RetakesAllocatorCore/CounterStrikeSharpInterfaces/IWeaponServicesAdapter.cs @@ -0,0 +1,6 @@ +namespace RetakesAllocatorCore.CounterStrikeSharpInterfaces; + +public interface IWeaponServicesAdapter +{ + public ICollection MyWeapons { get; } +} \ No newline at end of file diff --git a/RetakesAllocatorCore/OnRoundPostStartHelper.cs b/RetakesAllocatorCore/Helpers/OnRoundPostStartHelper.cs similarity index 62% rename from RetakesAllocatorCore/OnRoundPostStartHelper.cs rename to RetakesAllocatorCore/Helpers/OnRoundPostStartHelper.cs index b2a21b4..958f041 100644 --- a/RetakesAllocatorCore/OnRoundPostStartHelper.cs +++ b/RetakesAllocatorCore/Helpers/OnRoundPostStartHelper.cs @@ -2,37 +2,40 @@ using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using RetakesAllocatorCore.Config; +using RetakesAllocatorCore.CounterStrikeSharpInterfaces; using RetakesAllocatorCore.Db; -namespace RetakesAllocatorCore; +namespace RetakesAllocatorCore.Helpers; public class OnRoundPostStartHelper { - public static void Handle( + public static HookResult Handle( RoundType? nextRoundType, - ICollection allPlayers, - Func getSteamId, - Func getTeam, - Action giveDefuseKit, - Action, string?> allocateItemsForPlayer, - out RoundType currentRoundType + ICounterStrikeSharpAdapter counterStrikeSharp, + out RoundType? currentRoundType ) { var roundType = nextRoundType ?? RoundTypeHelpers.GetRandomRoundType(); currentRoundType = roundType; - var tPlayers = new List(); - var ctPlayers = new List(); + if (counterStrikeSharp.IsWarmup()) + { + return HookResult.Continue; + } + + var allPlayers = counterStrikeSharp.Utilities.GetPlayers(); + var tPlayers = new List(); + var ctPlayers = new List(); var playerIds = new List(); foreach (var player in allPlayers) { - var steamId = getSteamId(player); + var steamId = player.SteamId; if (steamId != 0) { playerIds.Add(steamId); } - var playerTeam = getTeam(player); + var playerTeam = player.Team; if (playerTeam == CsTeam.Terrorist) { tPlayers.Add(player); @@ -43,21 +46,21 @@ out RoundType currentRoundType } } - Log.Write($"#T Players: {string.Join(",", tPlayers.Select(getSteamId))}"); - Log.Write($"#CT Players: {string.Join(",", ctPlayers.Select(getSteamId))}"); + Log.Write($"#T Players: {string.Join(",", tPlayers.Select(p => p.SteamId))}"); + Log.Write($"#CT Players: {string.Join(",", ctPlayers.Select(p => p.SteamId))}"); var userSettingsByPlayerId = Queries.GetUsersSettings(playerIds); var defusingPlayer = Utils.Choice(ctPlayers); - HashSet FilterByPreferredWeaponPreference(IEnumerable ps) => + HashSet FilterByPreferredWeaponPreference(IEnumerable ps) => ps.Where(p => - userSettingsByPlayerId.TryGetValue(getSteamId(p), out var userSetting) && - userSetting.GetWeaponPreference(getTeam(p), WeaponAllocationType.Preferred) is not null) + userSettingsByPlayerId.TryGetValue(p.SteamId, out var userSetting) && + userSetting.GetWeaponPreference(p.Team, WeaponAllocationType.Preferred) is not null) .ToHashSet(); - ICollection tPreferredPlayers = new HashSet(); - ICollection ctPreferredPlayers = new HashSet(); + ICollection tPreferredPlayers = new HashSet(); + ICollection ctPreferredPlayers = new HashSet(); if (roundType == RoundType.FullBuy) { tPreferredPlayers = WeaponHelpers.SelectPreferredPlayers(FilterByPreferredWeaponPreference(tPlayers)); @@ -66,8 +69,8 @@ HashSet FilterByPreferredWeaponPreference(IEnumerable ps) => foreach (var player in allPlayers) { - var team = getTeam(player); - var playerSteamId = getSteamId(player); + var team = player.Team; + var playerSteamId = player.SteamId; userSettingsByPlayerId.TryGetValue(playerSteamId, out var userSetting); var items = new List { @@ -96,15 +99,15 @@ HashSet FilterByPreferredWeaponPreference(IEnumerable ps) => // On non-pistol rounds, everyone gets defuse kit and util if (roundType != RoundType.Pistol) { - giveDefuseKit(player); + counterStrikeSharp.GiveDefuseKit(player); items.AddRange(RoundTypeHelpers.GetRandomUtilForRoundType(roundType, team)); } else { // On pistol rounds, you get util *or* a defuse kit - if (getSteamId(defusingPlayer) == getSteamId(player)) + if (defusingPlayer?.SteamId == player.SteamId) { - giveDefuseKit(player); + counterStrikeSharp.GiveDefuseKit(player); } else { @@ -117,7 +120,16 @@ HashSet FilterByPreferredWeaponPreference(IEnumerable ps) => items.AddRange(RoundTypeHelpers.GetRandomUtilForRoundType(roundType, team)); } - allocateItemsForPlayer(player, items, team == CsTeam.Terrorist ? "slot5" : "slot1"); + counterStrikeSharp.AllocateItemsForPlayer(player, items, team == CsTeam.Terrorist ? "slot5" : "slot1"); + } + + if (Configs.GetConfigData().EnableRoundTypeAnnouncement) + { + counterStrikeSharp.Server.PrintToChatAll( + $"{counterStrikeSharp.MessagePrefix}{Enum.GetName(roundType)} Round" + ); } + + return HookResult.Continue; } } diff --git a/RetakesAllocatorCore/Utils.cs b/RetakesAllocatorCore/Utils.cs index 184e143..fbda08f 100644 --- a/RetakesAllocatorCore/Utils.cs +++ b/RetakesAllocatorCore/Utils.cs @@ -72,4 +72,12 @@ public static void SetupSqlite(string connectionString, DbContextOptionsBuilder { optionsBuilder.UseSqlite(connectionString); } + + public static void WriteNewlineDelimited(string message, Action writer) + { + foreach (var line in message.Split("\n")) + { + writer($"{PluginInfo.MessagePrefix}{line}"); + } + } }