diff --git a/README.md b/README.md index dd4689f7..64c79ba4 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,13 @@ The config file is located in the plugin folder under `config/config.json`. - `RoundTypePercentages`: The frequency of each type of round. The values must add up to `100`. - `UsableWeapons`: The weapons that can be allocated. Any weapon removed from this list cannot be used. - `EnableNextRoundTypeVoting`: Whether to allow voting for the next round type via `!nextround`. `false` by default. +- `NumberOfExtraVipChancesForPreferredWeapon`: When randomly selecting preferred weapons per team (ie. "AWP queue"), how + many extra chances should VIPs get. + - The default is 1, meaning VIPs will get 1 extra chance. For example, lets say + there are 3 players on the team and this config is set to 1. Normally each person would have a 33% chance of getting + the AWP, but in this case, since one of the players is a VIP, the VIP will get a 50% chance of getting the AWP, and + the other two players will each have 25% chance of getting the AWP. + - If you set this to 0, there will be no preference for VIPs. - `AllowedWeaponSelectionTypes`: The types of weapon allocation that are allowed. - Choices: - `PlayerChoice` - Allow players to choose their preferences for the round type @@ -101,7 +108,8 @@ The config file is located in the plugin folder under `config/config.json`. - The connection string for `Sqlite` probably doesnt need to be changed from the default, but you can change it if you want the db file to be in a different location. - More info on formatting the string here: https://www.connectionstrings.com/sqlite/ - - The connection string for `MySql` should be configured per instructions here: https://www.connectionstrings.com/mysql/ + - The connection string for `MySql` should be configured per instructions + here: https://www.connectionstrings.com/mysql/ - `MigrateOnStartup`: Whether or not to migrate the database on startup. This defaults to yes for now, but production servers may want to change this to false so they can control when database migrations are applied. @@ -119,7 +127,8 @@ You can use the following commands to select specific weapon preferences per-use provided - For example, if you previously did `!gun galil` while a terrorist, and you do `!removegun galil` while a terrorist, you will no longer prefer the galil, and will instead get a random weapon -- `!nextround` - Vote for the next round type. Can be enabled with the `EnableNextRoundTypeVoting` config, which is `false` by default. +- `!nextround` - Vote for the next round type. Can be enabled with the `EnableNextRoundTypeVoting` config, which + is `false` by default. - `!setnextround ` - For admins only. Force the next round to be the selected type. - `!reload_allocator_config` - For admins only. Reload the JSON config in-place. diff --git a/RetakesAllocator/Helpers.cs b/RetakesAllocator/Helpers.cs index f38b70f2..e8e79804 100644 --- a/RetakesAllocator/Helpers.cs +++ b/RetakesAllocator/Helpers.cs @@ -1,5 +1,6 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Admin; using CounterStrikeSharp.API.Modules.Commands; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; @@ -189,4 +190,6 @@ public static int GetNumPlayersOnTeam() .Where(player => player.Team is CsTeam.Terrorist or CsTeam.CounterTerrorist).ToList() .Count; } + + public static bool IsVip(CCSPlayerController player) => AdminManager.PlayerHasPermissions(player, "@css/vip"); } diff --git a/RetakesAllocator/RetakesAllocator.cs b/RetakesAllocator/RetakesAllocator.cs index 3b545560..14244cb2 100644 --- a/RetakesAllocator/RetakesAllocator.cs +++ b/RetakesAllocator/RetakesAllocator.cs @@ -6,7 +6,6 @@ using CounterStrikeSharp.API.Modules.Commands; using CounterStrikeSharp.API.Modules.Entities; using CounterStrikeSharp.API.Modules.Entities.Constants; -using CounterStrikeSharp.API.Modules.Utils; using RetakesAllocator.Managers; using RetakesAllocator.Menus; using RetakesAllocatorCore; @@ -437,6 +436,7 @@ public HookResult OnRoundPostStart(EventRoundPoststart @event, GameEventInfo inf Helpers.GetTeam, GiveDefuseKit, AllocateItemsForPlayer, + Helpers.IsVip, out var currentRoundType ); RoundTypeManager.GetInstance().SetCurrentRoundType(currentRoundType); diff --git a/RetakesAllocatorCore/Config/Configs.cs b/RetakesAllocatorCore/Config/Configs.cs index 9cfc27d6..33862825 100644 --- a/RetakesAllocatorCore/Config/Configs.cs +++ b/RetakesAllocatorCore/Config/Configs.cs @@ -119,6 +119,7 @@ public record ConfigData public bool AllowAllocationAfterFreezeTime { get; set; } = false; public bool EnableRoundTypeAnnouncement { get; set; } = true; public bool EnableNextRoundTypeVoting { get; set; } = false; + public int NumberOfExtraVipChancesForPreferredWeapon = 1; public DatabaseProvider DatabaseProvider { get; set; } = DatabaseProvider.Sqlite; public string DatabaseConnectionString { get; set; } = "Data Source=data.db"; diff --git a/RetakesAllocatorCore/OnRoundPostStartHelper.cs b/RetakesAllocatorCore/OnRoundPostStartHelper.cs index b2a21b4b..c59bdce5 100644 --- a/RetakesAllocatorCore/OnRoundPostStartHelper.cs +++ b/RetakesAllocatorCore/OnRoundPostStartHelper.cs @@ -1,7 +1,5 @@ -using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Entities.Constants; +using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; -using RetakesAllocatorCore.Config; using RetakesAllocatorCore.Db; namespace RetakesAllocatorCore; @@ -15,6 +13,7 @@ public static void Handle( Func getTeam, Action giveDefuseKit, Action, string?> allocateItemsForPlayer, + Func isVip, out RoundType currentRoundType ) { @@ -56,12 +55,14 @@ HashSet FilterByPreferredWeaponPreference(IEnumerable ps) => userSetting.GetWeaponPreference(getTeam(p), WeaponAllocationType.Preferred) is not null) .ToHashSet(); - ICollection tPreferredPlayers = new HashSet(); - ICollection ctPreferredPlayers = new HashSet(); + ICollection tPreferredPlayers = new List(); + ICollection ctPreferredPlayers = new List(); if (roundType == RoundType.FullBuy) { - tPreferredPlayers = WeaponHelpers.SelectPreferredPlayers(FilterByPreferredWeaponPreference(tPlayers)); - ctPreferredPlayers = WeaponHelpers.SelectPreferredPlayers(FilterByPreferredWeaponPreference(ctPlayers)); + tPreferredPlayers = + WeaponHelpers.SelectPreferredPlayers(FilterByPreferredWeaponPreference(tPlayers), isVip); + ctPreferredPlayers = + WeaponHelpers.SelectPreferredPlayers(FilterByPreferredWeaponPreference(ctPlayers), isVip); } foreach (var player in allPlayers) diff --git a/RetakesAllocatorCore/PluginInfo.cs b/RetakesAllocatorCore/PluginInfo.cs index e76173ae..01d52e6f 100644 --- a/RetakesAllocatorCore/PluginInfo.cs +++ b/RetakesAllocatorCore/PluginInfo.cs @@ -4,7 +4,7 @@ namespace RetakesAllocatorCore; public static class PluginInfo { - public const string Version = "1.2.7"; + public const string Version = "1.2.8"; public static readonly string LogPrefix = $"[RetakesAllocator {Version}] "; public static readonly string MessagePrefix = $"[{ChatColors.Green}Retakes{ChatColors.White}] "; diff --git a/RetakesAllocatorCore/WeaponHelpers.cs b/RetakesAllocatorCore/WeaponHelpers.cs index 4ed9d5b3..bd6e5728 100644 --- a/RetakesAllocatorCore/WeaponHelpers.cs +++ b/RetakesAllocatorCore/WeaponHelpers.cs @@ -1,4 +1,5 @@ using System.Collections; +using CounterStrikeSharp.API.Modules.Admin; using CounterStrikeSharp.API.Modules.Entities.Constants; using CounterStrikeSharp.API.Modules.Utils; using RetakesAllocatorCore.Config; @@ -12,6 +13,7 @@ public enum WeaponAllocationType HalfBuyPrimary, Secondary, PistolRound, + // eg. AWP is a preferred gun - you cant always get it even if its your preference // Right now its only snipers, but if we make this configurable, we need to change: // - CoercePreferredTeam @@ -62,7 +64,7 @@ public static class WeaponHelpers // Shotgun CsItem.XM1014, CsItem.Nova, - + // Sniper CsItem.Scout, }; @@ -163,7 +165,9 @@ private static readonly Dictionary> { RoundType.FullBuy, new HashSet - {WeaponAllocationType.Secondary, WeaponAllocationType.FullBuyPrimary, WeaponAllocationType.Preferred} + { + WeaponAllocationType.Secondary, WeaponAllocationType.FullBuyPrimary, WeaponAllocationType.Preferred + } }, }; @@ -249,6 +253,7 @@ public static bool IsAllocationTypeValidForRound(WeaponAllocationType? allocatio { return false; } + return _validAllocationTypesForRound[roundType.Value].Contains(allocationType.Value); } @@ -262,16 +267,29 @@ public static bool IsPreferred(CsTeam team, CsItem weapon) }; } - // TODO In the future this will be more complex based on sniper/preferred config and VIP status - public static ICollection SelectPreferredPlayers(ICollection players) + public static IList SelectPreferredPlayers(IEnumerable players, Func isVip) { - var player = Utils.Choice(players); + var choicePlayers = new List(); + foreach (var p in players) + { + choicePlayers.Add(p); + // VIPs get extra chances to be selected + if (isVip(p)) + { + for (var i = 0; i < Configs.GetConfigData().NumberOfExtraVipChancesForPreferredWeapon; i++) + { + choicePlayers.Add(p); + } + } + } + + var player = Utils.Choice(choicePlayers); if (player is null) { - return new HashSet(); + return new List(); } - return new HashSet {player}; + return new List {player}; } public static bool IsUsableWeapon(CsItem weapon) @@ -327,7 +345,7 @@ public static ICollection FindValidWeaponsByName(string needle) .Where(item => _allWeapons.Contains(item)) .ToList(); } - + public static WeaponAllocationType? GetWeaponAllocationTypeForWeaponAndRound(RoundType? roundType, CsTeam team, CsItem weapon) { @@ -352,6 +370,7 @@ public static ICollection FindValidWeaponsByName(string needle) { return potentialAllocationTypes.First(); } + if (potentialAllocationTypes.Count == 0) { return null; @@ -449,6 +468,7 @@ private static ICollection FindItemsByName(string needle) { return null; } + return _defaultWeaponsByTeamAndAllocationType[team][allocationType]; }