diff --git a/mod/Jailbreak.RTD/RewardGenerator.cs b/mod/Jailbreak.RTD/RewardGenerator.cs index 77b20062..c8cf143d 100644 --- a/mod/Jailbreak.RTD/RewardGenerator.cs +++ b/mod/Jailbreak.RTD/RewardGenerator.cs @@ -32,8 +32,8 @@ public class RewardGenerator(IZoneManager mgr, IC4Service bomb) (new WeaponReward("weapon_taser"), PROB_MEDIUM), (new HPReward(150), PROB_MEDIUM), (new HPReward(50), PROB_MEDIUM), (new ArmorReward(150), PROB_MEDIUM), (new HPReward(1), PROB_LOW), - (new ColorReward(Color.FromArgb(0, 255, 0)), PROB_LOW), - (new ColorReward(Color.FromArgb(255, 0, 0)), PROB_LOW), + (new ColorReward(Color.FromArgb(0, 255, 0), true), PROB_LOW), + (new ColorReward(Color.FromArgb(255, 0, 0), true), PROB_LOW), (new TransparentReward(), PROB_LOW), (new AmmoWeaponReward("weapon_glock", 2, 0), PROB_LOW), (new AmmoWeaponReward("weapon_negev", 0, 5), PROB_LOW), @@ -49,6 +49,7 @@ public void Start(BasePlugin basePlugin) { PROB_LOW)); rewards.Add((new CannotPickupReward(basePlugin, WeaponType.UTILITY), PROB_LOW)); + rewards.Add((new CannotScopeReward(basePlugin), PROB_LOW)); rewards.Add(( new CannotPickupReward(basePlugin, WeaponType.GRENADE | WeaponType.UTILITY), PROB_LOW)); @@ -67,10 +68,11 @@ public void Start(BasePlugin basePlugin) { private float totalWeight => rewards.Where(r => r.Item1.Enabled).Select(s => s.Item2).Sum(); - public IRTDReward GenerateReward(int slot) { + public IRTDReward GenerateReward(int? id) { var roll = rng.NextDouble() * totalWeight; foreach (var reward in rewards.Where(reward => reward.Item1.Enabled)) { + if (id != null && reward.Item1.CanGrantReward(id.Value)) continue; roll -= reward.Item2; if (roll <= 0) return reward.Item1; } diff --git a/mod/Jailbreak.RTD/Rewards/BombReward.cs b/mod/Jailbreak.RTD/Rewards/BombReward.cs index aa0c45e2..c5bbba06 100644 --- a/mod/Jailbreak.RTD/Rewards/BombReward.cs +++ b/mod/Jailbreak.RTD/Rewards/BombReward.cs @@ -1,5 +1,6 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Utils; using Jailbreak.Public.Mod.Rebel; using Jailbreak.Public.Mod.RTD; @@ -14,6 +15,10 @@ public bool PrepareReward(int userid) { return true; } + public bool CanGrantReward(CCSPlayerController player) { + return player.Team == CsTeam.Terrorist; + } + public bool GrantReward(CCSPlayerController player) { bombService.TryGiveC4ToPlayer(player); return true; diff --git a/mod/Jailbreak.RTD/Rewards/CannotScopeReward.cs b/mod/Jailbreak.RTD/Rewards/CannotScopeReward.cs new file mode 100644 index 00000000..06364a01 --- /dev/null +++ b/mod/Jailbreak.RTD/Rewards/CannotScopeReward.cs @@ -0,0 +1,72 @@ +using System.Collections.Immutable; +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using Jailbreak.Public.Extensions; +using Jailbreak.Public.Mod.RTD; + +namespace Jailbreak.RTD.Rewards; + +public class CannotScopeReward : IRTDReward { + private readonly BasePlugin plugin; + + public CannotScopeReward(BasePlugin plugin, WeaponType blocked) : this(plugin, + blocked.GetItems().ToArray()) { } + + public CannotScopeReward(BasePlugin plugin, params string[] weapons) { + this.plugin = plugin; + this.plugin.RegisterEventHandler(onRoundEnd); + } + + public string Name => "Cannot Scope"; + + public string Description + => $"You will not be able to pickup {Name} the next round."; + + private bool registered; + + private readonly HashSet blockedPlayerIDs = []; + + public bool GrantReward(CCSPlayerController player) { + if (player.UserId == null) return false; + if (!registered) { + plugin.RegisterListener(onTick); + registered = true; + } + + blockedPlayerIDs.Add(player.UserId.Value); + return true; + } + + private HookResult onRoundEnd(EventRoundEnd @event, GameEventInfo info) { + blockedPlayerIDs.Clear(); + plugin.RemoveListener(onTick); + registered = false; + return HookResult.Continue; + } + + private void onTick() { + registered = true; + if (blockedPlayerIDs.Count == 0) { + plugin.RemoveListener(onTick); + registered = false; + return; + } + + foreach (var player in blockedPlayerIDs.Select( + Utilities.GetPlayerFromUserid)) { + if (player == null || player.UserId == null || !player.IsValid) continue; + disableScope(player); + } + } + + private void disableScope(CCSPlayerController player) { + if (!player.IsReal()) return; + var pawn = player.PlayerPawn.Value; + if (pawn == null || !pawn.IsValid) return; + var weaponServices = pawn.WeaponServices; + if (weaponServices == null) return; + var activeWeapon = weaponServices.ActiveWeapon.Value; + if (activeWeapon == null || !activeWeapon.IsValid) return; + activeWeapon.NextSecondaryAttackTick = Server.TickCount + 500; + } +} \ No newline at end of file diff --git a/mod/Jailbreak.RTD/Rewards/ColorReward.cs b/mod/Jailbreak.RTD/Rewards/ColorReward.cs index 59c49cd9..e64ea3b6 100644 --- a/mod/Jailbreak.RTD/Rewards/ColorReward.cs +++ b/mod/Jailbreak.RTD/Rewards/ColorReward.cs @@ -6,7 +6,7 @@ namespace Jailbreak.RTD.Rewards; -public class ColorReward(Color color) : IRTDReward { +public class ColorReward(Color color, bool prisonerOnly) : IRTDReward { public virtual string Name => "Spawn " + ColorName; public virtual string Description @@ -36,6 +36,10 @@ public char ChatColor _ => ChatColors.White }; + public bool CanGrantReward(CCSPlayerController player) { + return player.Team == CsTeam.Terrorist || !prisonerOnly; + } + public bool GrantReward(CCSPlayerController player) { player.SetColor(color); return true; diff --git a/mod/Jailbreak.RTD/Rewards/GuaranteedWardenReward.cs b/mod/Jailbreak.RTD/Rewards/GuaranteedWardenReward.cs new file mode 100644 index 00000000..0ba4aa7c --- /dev/null +++ b/mod/Jailbreak.RTD/Rewards/GuaranteedWardenReward.cs @@ -0,0 +1,23 @@ +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Utils; +using Jailbreak.Public.Mod.RTD; +using Jailbreak.Public.Mod.Warden; + +namespace Jailbreak.RTD.Rewards; + +public class GuaranteedWardenReward(IWardenSelectionService service) + : IRTDReward { + public string Name => "Guaranteed Warden"; + + public string Description + => "You are guaranteed to be warden next round if you queue for it"; + + public bool CanGrantReward(CCSPlayerController player) { + return player.Team == CsTeam.CounterTerrorist; + } + + public bool GrantReward(CCSPlayerController player) { + service.SetGuaranteedWarden(player); + return true; + } +} \ No newline at end of file diff --git a/mod/Jailbreak.RTD/Rewards/RandomTeleportReward.cs b/mod/Jailbreak.RTD/Rewards/RandomTeleportReward.cs index 8cd38f4b..ef18125a 100644 --- a/mod/Jailbreak.RTD/Rewards/RandomTeleportReward.cs +++ b/mod/Jailbreak.RTD/Rewards/RandomTeleportReward.cs @@ -1,4 +1,5 @@ using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Utils; using Jailbreak.Public.Mod.RTD; using Jailbreak.Public.Mod.Zones; using Jailbreak.Public.Utils; @@ -11,6 +12,10 @@ public class RandomTeleportReward(IZoneManager zones) : IRTDReward { public string Description => "You will be teleported to a random location next round."; + public bool CanGrantReward(CCSPlayerController player) { + return player.Team == CsTeam.Terrorist; + } + public bool GrantReward(CCSPlayerController player) { var zone = MapUtil.GetRandomSpawns(1, zones).FirstOrDefault(); if (zone == null) return false; diff --git a/mod/Jailbreak.RTD/Rewards/TransparentReward.cs b/mod/Jailbreak.RTD/Rewards/TransparentReward.cs index 73b143ae..5390ad0f 100644 --- a/mod/Jailbreak.RTD/Rewards/TransparentReward.cs +++ b/mod/Jailbreak.RTD/Rewards/TransparentReward.cs @@ -7,7 +7,7 @@ namespace Jailbreak.RTD.Rewards; public class TransparentReward() - : ColorReward(Color.FromArgb(128, 255, 255, 255)) { + : ColorReward(Color.FromArgb(128, 255, 255, 255), false) { public override string Name => "Spawn Transparent"; public override string Description diff --git a/mod/Jailbreak.RTD/Rewards/WeaponReward.cs b/mod/Jailbreak.RTD/Rewards/WeaponReward.cs index 50d2ae08..73cf0b22 100644 --- a/mod/Jailbreak.RTD/Rewards/WeaponReward.cs +++ b/mod/Jailbreak.RTD/Rewards/WeaponReward.cs @@ -2,6 +2,7 @@ using System.Reflection; using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Utils; using Jailbreak.Public.Extensions; using Jailbreak.Public.Mod.RTD; @@ -22,6 +23,11 @@ public string Description + (weapon.GetFriendlyWeaponName()[0].IsVowel() ? "n" : "" + " ") + weapon.GetFriendlyWeaponName() + " next round."; + public bool CanGrantReward(CCSPlayerController player) { + // No point in giving a weapon to someone on CT + return player.Team == CsTeam.Terrorist; + } + public virtual bool GrantReward(CCSPlayerController player) { player.GiveNamedItem(weapon); return true; diff --git a/mod/Jailbreak.Warden/Selection/WardenSelectionBehavior.cs b/mod/Jailbreak.Warden/Selection/WardenSelectionBehavior.cs index 3ba0aac0..d90f1a9a 100644 --- a/mod/Jailbreak.Warden/Selection/WardenSelectionBehavior.cs +++ b/mod/Jailbreak.Warden/Selection/WardenSelectionBehavior.cs @@ -34,6 +34,8 @@ public class private readonly IWardenService warden; + private readonly HashSet guaranteedWarden = []; + /// /// Whether or not to use the queue. /// When true, the queue should be skipped and turn to first-come-first-serve. @@ -57,9 +59,18 @@ public void Start(BasePlugin basePlugin) { } public void Dispose() { } + public void SetGuaranteedWarden(CCSPlayerController player) { + guaranteedWarden.Add(player.UserId ?? -1); + } + public bool TryEnter(CCSPlayerController player) { if (!canEnterQueue(player)) return false; + if (guaranteedWarden.Contains(player.UserId ?? -1)) { + warden.TrySetWarden(player); + return true; + } + queue.Get(player).InQueue = true; return true; } @@ -100,6 +111,7 @@ public void ScheduleChooseWarden(float time = 7.0f) { /// Timer callback that states it's time to choose the warden. /// protected void OnChooseWarden() { + if (warden.HasWarden) return; var eligible = Utilities.GetPlayers() .Where(player => player.PawnIsAlive) .Where(player => player.Team == CsTeam.CounterTerrorist) diff --git a/public/Jailbreak.Public/Mod/RTD/IRTDReward.cs b/public/Jailbreak.Public/Mod/RTD/IRTDReward.cs index 16031d26..61a692a8 100644 --- a/public/Jailbreak.Public/Mod/RTD/IRTDReward.cs +++ b/public/Jailbreak.Public/Mod/RTD/IRTDReward.cs @@ -8,9 +8,20 @@ public interface IRTDReward { public string Description { get; } bool Enabled => true; - bool CanGrantReward(int userid) { return true; } + bool CanGrantReward(int userid) { + var player = Utilities.GetPlayerFromUserid(userid); + return player != null && player.IsValid && CanGrantReward(player); + } + + bool CanGrantReward(CCSPlayerController player) { return true; } + + bool PrepareReward(int userid) { + var player = Utilities.GetPlayerFromUserid(userid); + if (player == null || !player.IsValid) return false; + return PrepareReward(player); + } - bool PrepareReward(int userid) { return true; } + bool PrepareReward(CCSPlayerController player) { return true; } bool GrantReward(int userid) { var player = Utilities.GetPlayerFromUserid(userid); diff --git a/public/Jailbreak.Public/Mod/RTD/IRewardGenerator.cs b/public/Jailbreak.Public/Mod/RTD/IRewardGenerator.cs index 341b329b..a3e744e4 100644 --- a/public/Jailbreak.Public/Mod/RTD/IRewardGenerator.cs +++ b/public/Jailbreak.Public/Mod/RTD/IRewardGenerator.cs @@ -3,9 +3,9 @@ namespace Jailbreak.Public.Mod.RTD; public interface IRewardGenerator : IReadOnlyCollection<(IRTDReward, float)> { - IRTDReward GenerateReward(int slot); + IRTDReward GenerateReward(int? id); IRTDReward GenerateReward(CCSPlayerController player) { - return GenerateReward(player.UserId ?? -1); + return GenerateReward(player.UserId); } } \ No newline at end of file diff --git a/public/Jailbreak.Public/Mod/Warden/IWardenSelectionService.cs b/public/Jailbreak.Public/Mod/Warden/IWardenSelectionService.cs index 80ff3504..0c21349d 100644 --- a/public/Jailbreak.Public/Mod/Warden/IWardenSelectionService.cs +++ b/public/Jailbreak.Public/Mod/Warden/IWardenSelectionService.cs @@ -8,6 +8,14 @@ public interface IWardenSelectionService { /// bool Active { get; } + /// + /// Whether the player should be guaranteed warden if they enter the queue + /// this will act as a bypass to the queue. Thus, if multiple players are + /// applied with this, the first player to be apply for warden will receive it. + /// + /// + void SetGuaranteedWarden(CCSPlayerController player); + /// /// Enter this player into the warden queue ///