From 9710049643fad8544543630692e3e686649a8527 Mon Sep 17 00:00:00 2001 From: Isaac Date: Tue, 27 Aug 2024 17:57:20 -0700 Subject: [PATCH 01/19] Cleaup/aug (#290) * Reformat * Add cvar config for HNS * Add more HNS customization support * Add customizations to noscope * Remove unused class var * More tidying up * Remove config infra * Add configurability to C4 * Add contributing, add config explanation in readme --- CONTRIBUTING.md | 20 ++ README.md | 45 ++--- .../Generic/GenericCmdLocale.cs | 9 +- .../LastRequest/CoinflipLocale.cs | 4 +- .../LastRequest/LastRequestLocale.cs | 55 ++---- .../LastRequest/RPSLocale.cs | 10 +- .../LastRequest/RaceLocale.cs | 12 +- .../Mute/WardenPeaceLocale.cs | 23 ++- lang/Jailbreak.English/Rebel/RebelLocale.cs | 2 +- .../SpecialDay/GunDayLocale.cs | 9 +- .../SpecialDay/HNSDayLocale.cs | 9 +- .../SpecialDay/InfectionDayLocale.cs | 4 +- lang/Jailbreak.English/SpecialDay/SDLocale.cs | 17 +- .../SpecialDay/SpeedrunDayLocale.cs | 8 +- .../Warden/WardenCmdOpenLocale.cs | 4 +- mod/Jailbreak.Debug/PlayerZoneCreator.cs | 2 +- mod/Jailbreak.LastGuard/LastGuard.cs | 71 ++++---- mod/Jailbreak.LastGuard/LastGuardConfig.cs | 7 - .../LastRequestManager.cs | 20 +- .../LastRequests/BulletForBullet.cs | 3 +- mod/Jailbreak.Rebel/C4Bomb/C4Behavior.cs | 36 +++- mod/Jailbreak.Rebel/RebelManager.cs | 14 +- mod/Jailbreak.SpecialDay/SpecialDayCommand.cs | 28 ++- .../SpecialDays/AbstractZoneRestrictedDay.cs | 2 +- .../SpecialDays/FFADay.cs | 1 - .../SpecialDays/HideAndSeekDay.cs | 171 ++++++++++++++---- .../SpecialDays/InfectionDay.cs | 22 +-- .../SpecialDays/NoScopeDay.cs | 44 ++++- .../SpecialDays/OneInTheChamberDay.cs | 47 +++-- .../SpecialDays/SpeedrunDay.cs | 155 ++++++++-------- .../Commands/WardenCommandsBehavior.cs | 7 +- .../Commands/WardenOpenCommandsBehavior.cs | 11 +- mod/Jailbreak.Warden/Global/WardenBehavior.cs | 79 ++++---- .../Markers/WardenMarkerBehavior.cs | 16 +- mod/Jailbreak.Warden/WardenConfig.cs | 8 - .../WardenServiceExtension.cs | 4 +- mod/Jailbreak.Zones/SqlZoneManager.cs | 16 +- .../Views/Warden/IWardenCmdOpenLocale.cs | 11 +- .../Configuration/IConfigService.cs | 14 -- .../Extensions/CollectionExtensions.cs | 4 +- .../Extensions/ServiceCollectionExtensions.cs | 21 --- .../Mod/SpecialDay/AbstractSpecialDay.cs | 1 + public/Jailbreak.Public/Utils/TeamUtil.cs | 19 ++ public/Jailbreak.Validator/ItemValidator.cs | 70 +++++++ .../NonZeroRangeValidator.cs | 21 +++ public/Jailbreak.Validator/TeamValidator.cs | 25 +++ public/Jailbreak.Validator/WeaponValidator.cs | 56 ------ src/Jailbreak/Config/ConfigService.cs | 63 ------- src/Jailbreak/JailbreakServiceCollection.cs | 3 - 49 files changed, 737 insertions(+), 566 deletions(-) create mode 100644 CONTRIBUTING.md delete mode 100644 mod/Jailbreak.LastGuard/LastGuardConfig.cs delete mode 100644 mod/Jailbreak.Warden/WardenConfig.cs delete mode 100644 public/Jailbreak.Public/Configuration/IConfigService.cs create mode 100644 public/Jailbreak.Public/Utils/TeamUtil.cs create mode 100644 public/Jailbreak.Validator/ItemValidator.cs create mode 100644 public/Jailbreak.Validator/NonZeroRangeValidator.cs create mode 100644 public/Jailbreak.Validator/TeamValidator.cs delete mode 100644 public/Jailbreak.Validator/WeaponValidator.cs delete mode 100644 src/Jailbreak/Config/ConfigService.cs diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..7d1e045d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,20 @@ +## Contributing + +The jail plugin is currently in heavy development and all contributions are welcome! +Please make sure all contributions use the dependency injection system, or ask to have your contribution +ported if you don't know how. + +> [!TIP] +> Microsoft has some good documentation on dependency injection here: +> [Overview](https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection), +> [Using Dependency Injection](https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-usage), +> [Dependency Injection Guidelines](https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-guidelines). + +All event handlers should derive from `IPluginBehavior` and be registered using +`IServiceCollection.AddPluginBehavior`. If your behavior also acts as a service, +make sure to use `IServiceCollection.AddPluginBehavior`. All `IPluginBehavior` objects +have their event handlers automatically registered. + +Code style should follow .NET conventions and use the formatting settings specified +in [Jailbreak.sln.DotSettings](./Jailbreak.sln.DotSettings) +(if you need help, make sure to check "enable edits from maintainers" and ask for a format) diff --git a/README.md b/README.md index d1d79780..7e187d9f 100644 --- a/README.md +++ b/README.md @@ -9,17 +9,20 @@ The classic Jail gamemode, ported to Counter-Strike 2. [![Release](https://img.shields.io/badge/Release-mediumseagreen?style=for-the-badge&logo=onlyoffice )](https://github.com/edgegamers/Jailbreak/releases/)⠀⠀ -[![Stable](https://img.shields.io/badge/Stable-orangered?style=for-the-badge&logo=onlyoffice)](https://nightly.link/edgegamers/Jailbreak/workflows/nightly/main/jailbreak-nightly)⠀⠀ +[![Stable](https://img.shields.io/badge/Stable-orangered?style=for-the-badge&logo=onlyoffice)](https://nightly.link/edgegamers/Jailbreak/workflows/nightly/main/jailbreak-nightly) +⠀⠀ [![Dev](https://img.shields.io/badge/Nightly-slateblue?style=for-the-badge&logo=onlyoffice )](https://nightly.link/edgegamers/Jailbreak/workflows/nightly/dev/jailbreak-nightly) **Release** builds are our full releases. We try to keep these high-quality and bug-free, when we can. -Our **Stable** builds run on EdgeGamers' own Jailbreak servers. +Our **Stable** builds run on EdgeGamers' own Jailbreak servers. Our **Nightly** builds are used exclusively for development and staging, and are likely to have problems. ## Versioning + Our release tags starting from 'v2.0.0' follow the [Semantic Versioning 2.0.0](https://semver.org/) standard, where `MAJOR.MINOR.PATCH` are incremented based on the following: + - `MAJOR` when we make incompatible API changes, - `MINOR` when we add functionality in a backwards-compatible manner. - `PATCH` when we make backwards-compatible bug fixes. @@ -27,46 +30,29 @@ where `MAJOR.MINOR.PATCH` are incremented based on the following: ## Status - **⚙️ Server** - - [ ] Stats/Analytics Sinks - - [ ] Error reporting - - [x] Configuration system - - Note: Passable, but in a terrible state. Needs TLC. + - [x] Stats/Analytics Sinks + - [x] Error reporting - [x] Logging + - [x] Zones - **👮 Guards** - [x] Warden Selection - [x] Warden Laser and Paint - - [ ] Special Days - - [x] Ratio Enforcement - - [ ] Bans/Punishments + - [x] Special Days - **🎃 Prisoners** - [x] Last Request - [x] Rebel System - **🛕 Maps** + - [x] Automagic Cell Opening - [ ] Custom Entities - [ ] Custom I/O - [ ] Warden/Guard/Prisoner Filters -## Contributing - -The jail plugin is currently in heavy development and all contributions are welcome! -Please make sure all contributions use the dependency injection system, or ask to have your contribution -ported if you don't know how. - -Ports to DI containers that have more verbose scoping systems for round-based or game-based scoping are welcome. - -> [!TIP] -> Microsoft has some good documentation on dependency injection here: -> [Overview](https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection), -> [Using Dependency Injection](https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-usage), -> [Dependency Injection Guidelines](https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-guidelines). +## Configuration -All event handlers should derive from `IPluginBehavior` and be registered using -`IServiceCollection.AddPluginBehavior`. If your behavior also acts as a service, -make sure to use `IServiceCollection.AddPluginBehavior`. All `IPluginBehavior` objects -have their event handlers automatically registered. +Configuration is done through CS#'s [FakeConVars](https://docs.cssharp.dev/examples/WithFakeConvars.html?q=fakeconvar). -Code style should follow .NET conventions -(if you need help, make sure to check "enable edits from maintainers" and ask for a format) +You can search for the list of configurable +convars [like so](https://github.com/search?q=repo%3Aedgegamers%2FJailbreak%20fakeconvar&type=code). ## Modding @@ -97,7 +83,8 @@ foreach (IPluginBehavior extension in _extensions) ## Building -The jailbreak plugin automatically builds to `build/Jailbreak` when using `dotnet publish src/Jailbreak/Jailbreak.csproj`. +The jailbreak plugin automatically builds to `build/Jailbreak` when +using `dotnet publish src/Jailbreak/Jailbreak.csproj`. Please use [SDK 8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) or higher. Note that only the `src/Jailbreak` project is intended to be built directly. diff --git a/lang/Jailbreak.English/Generic/GenericCmdLocale.cs b/lang/Jailbreak.English/Generic/GenericCmdLocale.cs index 27229240..c60c541a 100644 --- a/lang/Jailbreak.English/Generic/GenericCmdLocale.cs +++ b/lang/Jailbreak.English/Generic/GenericCmdLocale.cs @@ -4,6 +4,7 @@ using Jailbreak.Formatting.Logistics; using Jailbreak.Formatting.Objects; using Jailbreak.Formatting.Views; +using Jailbreak.Public.Extensions; namespace Jailbreak.English.Generic; @@ -36,21 +37,23 @@ public IView CommandOnCooldown(DateTime cooldownEndsAt) { PREFIX, $"{ChatColors.Grey}Command is on cooldown for", seconds, - $"{ChatColors.Grey}seconds!" + $"{ChatColors.Grey}second" + (seconds == 1 ? "" : "s") + "." }; } public IView InvalidParameter(string parameter, string expected) { return new SimpleView { PREFIX, - $"{ChatColors.Red}Invalid parameter '{ChatColors.LightBlue}{parameter}{ChatColors.Red}', expected a(n) {ChatColors.White}{expected}{ChatColors.Red}." + $"{ChatColors.Red}Invalid parameter '{ChatColors.LightBlue}{parameter}{ChatColors.Red}',", + "expected a" + (expected[0].IsVowel() ? "n" : ""), + $"{ChatColors.White}{expected}{ChatColors.Red}." }; } public IView NoPermissionMessage(string permission) { return new SimpleView { PREFIX, - $"{ChatColors.Red}This command requires the {ChatColors.White}{permission}{ChatColors.Red} permission." + $"{ChatColors.DarkRed}This requires the {ChatColors.White}{permission}{ChatColors.Red} permission." }; } diff --git a/lang/Jailbreak.English/LastRequest/CoinflipLocale.cs b/lang/Jailbreak.English/LastRequest/CoinflipLocale.cs index 1658beaf..1617bc33 100644 --- a/lang/Jailbreak.English/LastRequest/CoinflipLocale.cs +++ b/lang/Jailbreak.English/LastRequest/CoinflipLocale.cs @@ -26,7 +26,9 @@ public IView GuardChose(CCSPlayerController guard, bool choice) { public IView CoinLandsOn(bool heads) { return new SimpleView { - PREFIX, "The coin lands on" + ChatColors.Green, heads ? "Heads" : "Tails" + PREFIX, + "The coin landed on" + ChatColors.Green, + heads ? "Heads" : "Tails" + ChatColors.White + "." }; } } \ No newline at end of file diff --git a/lang/Jailbreak.English/LastRequest/LastRequestLocale.cs b/lang/Jailbreak.English/LastRequest/LastRequestLocale.cs index 209f79b9..84d2db9c 100644 --- a/lang/Jailbreak.English/LastRequest/LastRequestLocale.cs +++ b/lang/Jailbreak.English/LastRequest/LastRequestLocale.cs @@ -15,7 +15,7 @@ public class LastRequestLocale : ILRLocale, ILanguage { public static readonly FormatObject PREFIX = new HiddenFormatObject( - $" {ChatColors.DarkRed}[{ChatColors.LightRed}LR{ChatColors.DarkRed}]") { + $" {ChatColors.Green}[{ChatColors.Lime}LR{ChatColors.Green}]") { // Hide in panorama and center text Plain = false, Panorama = false, Chat = true }; @@ -24,7 +24,7 @@ public IView LastRequestEnabled() { return new SimpleView { { PREFIX, - $"Last Request has been enabled. {ChatColors.Grey}Type {ChatColors.LightBlue}!lr{ChatColors.Grey} to start a last request." + $"Last Request activated. {ChatColors.Grey}Type {ChatColors.LightBlue}!lr{ChatColors.Grey} to start a last request." } }; } @@ -33,7 +33,7 @@ public IView LastRequestDisabled() { return new SimpleView { { PREFIX, - $"{ChatColors.Grey}Last Request has been {ChatColors.Red}disabled{ChatColors.Grey}." + $"{ChatColors.Grey}Last Request {ChatColors.Red}disabled{ChatColors.Grey}." } }; } @@ -52,9 +52,9 @@ public IView InformLastRequest(AbstractLastRequest lr) { return new SimpleView { PREFIX, lr.Prisoner, - ChatColors.Grey + "is preparing a", + ChatColors.Grey + "is starting a", ChatColors.White + lr.Type.ToFriendlyString(), - ChatColors.Grey + "Last Request against", + ChatColors.Grey + "LR against", lr.Guard }; } @@ -74,36 +74,29 @@ public IView LastRequestDecided(AbstractLastRequest lr, LRResult result) { var tNull = !lr.Prisoner.IsReal(); var gNull = !lr.Guard.IsReal(); if (tNull && gNull) - return new SimpleView { PREFIX, "Last Request has been decided." }; + return new SimpleView { PREFIX, "Last Request decided." }; if (tNull && result == LRResult.PRISONER_WIN) return new SimpleView { - PREFIX, lr.Guard, "lost the LR, but the prisoner left the game." + PREFIX, lr.Guard, "lost the LR, but the prisoner left the game?" }; if (gNull && result == LRResult.GUARD_WIN) return new SimpleView { - PREFIX, lr.Prisoner, "lost the LR, but the guard left the game." + PREFIX, lr.Prisoner, "lost the LR, but the guard left the game?" }; - switch (result) { - case LRResult.TIMED_OUT: - return new SimpleView { - PREFIX, ChatColors.Grey.ToString(), "Last Request has timed out." - }; - case LRResult.INTERRUPTED: - return new SimpleView { - PREFIX, - ChatColors.Grey.ToString(), - "Last Request has been interrupted." - }; - default: - return new SimpleView { - PREFIX, - result == LRResult.PRISONER_WIN ? lr.Prisoner : lr.Guard, - "won the LR." - }; - } + return result switch { + LRResult.TIMED_OUT => new SimpleView { + PREFIX, ChatColors.Grey.ToString(), "Last Request timed out." + }, + LRResult.INTERRUPTED => new SimpleView { + PREFIX, ChatColors.Grey.ToString(), "Last Request interrupted." + }, + _ => new SimpleView { + PREFIX, result == LRResult.PRISONER_WIN ? lr.Prisoner : lr.Guard, "won." + } + }; } public IView CannotLR(string reason) { @@ -149,14 +142,4 @@ public IView DamageBlockedNotInSameLR => new SimpleView { PREFIX, "You are not in the same LR as them, damage blocked." }; - - public IView InvalidPlayerChoice(CCSPlayerController player, string reason) { - return new SimpleView { - PREFIX, - "Invalid player choice: ", - player, - " Reason: ", - reason - }; - } } \ No newline at end of file diff --git a/lang/Jailbreak.English/LastRequest/RPSLocale.cs b/lang/Jailbreak.English/LastRequest/RPSLocale.cs index ad3b6766..0d6aa4a8 100644 --- a/lang/Jailbreak.English/LastRequest/RPSLocale.cs +++ b/lang/Jailbreak.English/LastRequest/RPSLocale.cs @@ -11,7 +11,7 @@ public IView PlayerMadeChoice(CCSPlayerController player) { public IView BothPlayersMadeChoice() { return new SimpleView { - PREFIX, "Both players have rocked, papered, and scissored! (ew)" + PREFIX, "Both players rocked, papered, and scissored! (ew)" }; } @@ -23,13 +23,13 @@ public IView Results(CCSPlayerController guard, CCSPlayerController prisoner, int guardPick, int prisonerPick) { return new SimpleView { PREFIX, - "Results: ", + "Results:", guard, - " picked ", + "picked", toRPS(guardPick), - " and ", + "and", prisoner, - " picked ", + "picked", toRPS(prisonerPick) }; } diff --git a/lang/Jailbreak.English/LastRequest/RaceLocale.cs b/lang/Jailbreak.English/LastRequest/RaceLocale.cs index 1ea9220e..c008db9c 100644 --- a/lang/Jailbreak.English/LastRequest/RaceLocale.cs +++ b/lang/Jailbreak.English/LastRequest/RaceLocale.cs @@ -20,15 +20,14 @@ public IView EndRaceInstruction SimpleView.NEWLINE, { PREFIX, $"Type {ChatColors.Blue}!endrace{ChatColors.White} to set the end point!" - }, - SimpleView.NEWLINE + } }; public IView RaceStartingMessage(CCSPlayerController prisoner) { return new SimpleView { { PREFIX, prisoner, - " is starting a race. Pay attention to where they set the end point!" + "is racing you. Pay attention to where they set the end point!" } }; } @@ -37,14 +36,17 @@ public IView NotInRaceLR() { return new SimpleView { { PREFIX, - $"You must be in a race {ChatColors.Blue + "!lr" + ChatColors.White} to use this command" + $"{ChatColors.Red}You must be in a race {ChatColors.Blue + "!lr" + ChatColors.Red} to use this." } }; } public IView NotInPendingState() { return new SimpleView { - { PREFIX, "You must be in the pending state to use this command." } + { + PREFIX, + ChatColors.Red + "You must be in the pending state to use this command." + } }; } } \ No newline at end of file diff --git a/lang/Jailbreak.English/Mute/WardenPeaceLocale.cs b/lang/Jailbreak.English/Mute/WardenPeaceLocale.cs index bb5e9116..da428ae9 100644 --- a/lang/Jailbreak.English/Mute/WardenPeaceLocale.cs +++ b/lang/Jailbreak.English/Mute/WardenPeaceLocale.cs @@ -4,6 +4,7 @@ using Jailbreak.Formatting.Logistics; using Jailbreak.Formatting.Objects; using Jailbreak.Formatting.Views.Warden; +using Microsoft.Extensions.Primitives; namespace Jailbreak.English.Mute; @@ -17,32 +18,40 @@ public class WardenPeaceLocale : IWardenPeaceLocale, public IView PeaceEnactedByAdmin(int seconds) { return new SimpleView { - PREFIX, "An admin enacted peace for", seconds, "seconds." + PREFIX, + $"{ChatColors.Red}An admin {ChatColors.White}enacted peace for", + seconds, + "second" + (seconds == 1 ? "" : "s") + "." }; } public IView WardenEnactedPeace(int seconds) { return new SimpleView { - PREFIX, "Warden enacted peace for", seconds, "seconds." + PREFIX, + $"{ChatColors.Blue}The warden {ChatColors.White}enacted peace for", + seconds, + "seconds." }; } public IView GeneralPeaceEnacted(int seconds) { return new SimpleView { - PREFIX, "Peace has been enacted for", seconds, "seconds." + PREFIX, + "Peace was enacted for", + seconds, + "second" + (seconds == 1 ? "" : "s") + "." }; } public IView UnmutedGuards => new SimpleView { - { PREFIX, $"{ChatColors.Blue}Guards {ChatColors.Grey}have been unmuted." } + { PREFIX, $"{ChatColors.Blue}Guards {ChatColors.Grey}were unmuted." } }; public IView UnmutedPrisoners => new SimpleView { { - PREFIX, - $"{ChatColors.LightRed}Prisoners {ChatColors.Grey}have been unmuted." + PREFIX, $"{ChatColors.LightRed}Prisoners {ChatColors.Grey}were unmuted." } }; @@ -61,7 +70,7 @@ public IView PeaceReminder public IView DeadReminder => new SimpleView { - { PREFIX, $"{ChatColors.Red}You are dead and cannot speak!" } + { PREFIX, $"{ChatColors.Red}You are dead and cannot speak." } }; public IView AdminDeadReminder diff --git a/lang/Jailbreak.English/Rebel/RebelLocale.cs b/lang/Jailbreak.English/Rebel/RebelLocale.cs index 017ecca9..acc08f8f 100644 --- a/lang/Jailbreak.English/Rebel/RebelLocale.cs +++ b/lang/Jailbreak.English/Rebel/RebelLocale.cs @@ -17,5 +17,5 @@ public class RebelLocale : IRebelLocale, }; public IView NoLongerRebel - => new SimpleView { PREFIX, "You are no longer a rebel." }; + => new SimpleView { PREFIX, "You are no longer red." }; } \ No newline at end of file diff --git a/lang/Jailbreak.English/SpecialDay/GunDayLocale.cs b/lang/Jailbreak.English/SpecialDay/GunDayLocale.cs index 73bb4737..79784d64 100644 --- a/lang/Jailbreak.English/SpecialDay/GunDayLocale.cs +++ b/lang/Jailbreak.English/SpecialDay/GunDayLocale.cs @@ -19,15 +19,12 @@ public IView DemotedDueToKnife public IView PromotedTo(string weapon, int weaponsLeft) { if (weaponsLeft == 1) return new SimpleView { - PREFIX, - "You were promoted to", - weapon + ".", - ChatColors.Green + "LAST WEAPON!" + PREFIX, "Promoted to", weapon + ".", ChatColors.Green + "LAST WEAPON!" }; return new SimpleView { PREFIX, - "You were promoted to", + "Promoted to", weapon + ".", weaponsLeft, "weapons left." @@ -38,7 +35,7 @@ public IView PlayerOnLastPromotion(CCSPlayerController player) { return new SimpleView { PREFIX, player, - "is on their last weapon!", + "is on the last weapon!", ChatColors.LightRed + "Watch out!" }; } diff --git a/lang/Jailbreak.English/SpecialDay/HNSDayLocale.cs b/lang/Jailbreak.English/SpecialDay/HNSDayLocale.cs index 1cbe00a7..4f0bf57f 100644 --- a/lang/Jailbreak.English/SpecialDay/HNSDayLocale.cs +++ b/lang/Jailbreak.English/SpecialDay/HNSDayLocale.cs @@ -3,7 +3,7 @@ namespace Jailbreak.English.SpecialDay; public class HNSDayLocale() : TeamDayLocale("Hide and Seek", - "CTs must hide while the Ts seek!", "Ts have 250 HP!") { + "CTs must hide while the Ts seek!", "Ts have increased HP!") { public IView StayInArmory => new SimpleView { PREFIX, "Today is", Name, ", stay in the armory!" }; @@ -15,13 +15,16 @@ public override IView BeginsIn(int seconds) { Name, "begins in", seconds, - "seconds." + "second" + (seconds == 1 ? "" : "s") + "." }; } public IView DamageWarning(int seconds) { return new SimpleView { - PREFIX, "You will be vulnerable to damage in", seconds, "seconds." + PREFIX, + "You will be vulnerable to damage in", + seconds, + "second" + (seconds == 1 ? "" : "s") + "." }; } } \ No newline at end of file diff --git a/lang/Jailbreak.English/SpecialDay/InfectionDayLocale.cs b/lang/Jailbreak.English/SpecialDay/InfectionDayLocale.cs index 7f70b525..787e7d0a 100644 --- a/lang/Jailbreak.English/SpecialDay/InfectionDayLocale.cs +++ b/lang/Jailbreak.English/SpecialDay/InfectionDayLocale.cs @@ -25,13 +25,13 @@ public IView YouWereInfectedMessage(CCSPlayerController? player) { return player == null || !player.IsValid ? new SimpleView { PREFIX, - $"{ChatColors.Red}You were {ChatColors.DarkRed}infected{ChatColors.Red}! You are now a zombie!" + $"{ChatColors.Red}You were {ChatColors.DarkRed}infected{ChatColors.Red}!" } : new SimpleView { PREFIX, $"{ChatColors.Red}You were {ChatColors.DarkRed}infected{ChatColors.Red} by", player, - "! You are now a zombie!" + "!" }; } diff --git a/lang/Jailbreak.English/SpecialDay/SDLocale.cs b/lang/Jailbreak.English/SpecialDay/SDLocale.cs index b6c88209..09c9910f 100644 --- a/lang/Jailbreak.English/SpecialDay/SDLocale.cs +++ b/lang/Jailbreak.English/SpecialDay/SDLocale.cs @@ -16,11 +16,19 @@ public class SDLocale : ISDLocale, ILanguage { }; public IView SpecialDayRunning(string name) { - return new SimpleView { PREFIX, name, "is currently running!" }; + return new SimpleView { + PREFIX, + ChatColors.DarkRed + name, + ChatColors.Red + "is currently running." + }; } public IView InvalidSpecialDay(string name) { - return new SimpleView { PREFIX, name, "is not a valid special day!" }; + return new SimpleView { + PREFIX, + ChatColors.DarkRed + name, + ChatColors.Red + "is not a valid special day." + }; } public IView SpecialDayCooldown(int rounds) { @@ -28,7 +36,8 @@ public IView SpecialDayCooldown(int rounds) { PREFIX, "You must wait", rounds, - "more rounds before starting a special day." + "more round" + (rounds == 1 ? "" : "s") + + " before starting a special day." }; } @@ -37,7 +46,7 @@ public IView TooLateForSpecialDay(int maxTime) { PREFIX, "You must start a special day within", maxTime, - "seconds of the round start." + "second" + (maxTime == 1 ? "" : "s") + " of the round start." }; } } \ No newline at end of file diff --git a/lang/Jailbreak.English/SpecialDay/SpeedrunDayLocale.cs b/lang/Jailbreak.English/SpecialDay/SpeedrunDayLocale.cs index c5ff0498..e5e0a87b 100644 --- a/lang/Jailbreak.English/SpecialDay/SpeedrunDayLocale.cs +++ b/lang/Jailbreak.English/SpecialDay/SpeedrunDayLocale.cs @@ -39,7 +39,7 @@ public IView BeginRound(int round, int eliminationCount, int seconds) { return new SimpleView { { PREFIX, - $"Round #{ChatColors.Yellow}{round}{ChatColors.Default} begins! The slowest", + $"Round {ChatColors.Yellow}#{round}{ChatColors.Default} begins! The slowest", "player to reach the goal will be eliminated!" }, SimpleView.NEWLINE, @@ -74,7 +74,7 @@ public IView RunnerLeftAndReassigned(CCSPlayerController player) { PREFIX, "The original speedrunner left, so", player, - "is now the speedrunner!" + "is now the speedrunner." }; } @@ -83,7 +83,7 @@ public IView RunnerAFKAndReassigned(CCSPlayerController player) { PREFIX, "The original speedrunner isn't moving, so", player, - "is now the speedrunner!" + "is now the speedrunner." }; } @@ -145,7 +145,7 @@ public IView ImpossibleLocation(CsTeam team, CCSPlayerController player) { "reached the goal. Eliminating one player on each time." }, SimpleView.NEWLINE, - { PREFIX, "Randomly selected the path from ", player, "." } + { PREFIX, "Randomly selected the path from", player, "." } }; } } \ No newline at end of file diff --git a/lang/Jailbreak.English/Warden/WardenCmdOpenLocale.cs b/lang/Jailbreak.English/Warden/WardenCmdOpenLocale.cs index af0a2229..0c220712 100644 --- a/lang/Jailbreak.English/Warden/WardenCmdOpenLocale.cs +++ b/lang/Jailbreak.English/Warden/WardenCmdOpenLocale.cs @@ -30,7 +30,9 @@ public IView CellsOpenedBy(CCSPlayerController? player) { } public IView CellsOpened - => new SimpleView { WardenLocale.PREFIX, "Cells were auto-opened." }; + => new SimpleView { + WardenLocale.PREFIX, ChatColors.Grey + "Cells were auto-opened." + }; public IView OpeningFailed => new SimpleView { WardenLocale.PREFIX, "Failed to open the cells." }; diff --git a/mod/Jailbreak.Debug/PlayerZoneCreator.cs b/mod/Jailbreak.Debug/PlayerZoneCreator.cs index c7934e46..7c32b72e 100644 --- a/mod/Jailbreak.Debug/PlayerZoneCreator.cs +++ b/mod/Jailbreak.Debug/PlayerZoneCreator.cs @@ -48,7 +48,7 @@ private void tick() { } var pawn = player.PlayerPawn.Value; - if (pawn == null) { + if (pawn == null || !pawn.IsValid) { timer?.Kill(); return; } diff --git a/mod/Jailbreak.LastGuard/LastGuard.cs b/mod/Jailbreak.LastGuard/LastGuard.cs index f9d45ad3..b0e0c1fb 100644 --- a/mod/Jailbreak.LastGuard/LastGuard.cs +++ b/mod/Jailbreak.LastGuard/LastGuard.cs @@ -18,43 +18,46 @@ namespace Jailbreak.LastGuard; public class LastGuard(ILGLocale notifications, ILastRequestManager lrManager) : ILastGuardService, IPluginBehavior { - public readonly FakeConVar CvAlwaysOverrideCt = new( + public static readonly FakeConVar CV_ALWAYS_OVERRIDE_CT = new( "css_jb_lg_apply_lower_hp", "If true, the LG will be forced lower health if calculated"); - public readonly FakeConVar CvGuardHealthRatio = new( + public static readonly FakeConVar CV_GUARD_HEALTH_RATIO = new( "css_jb_lg_ct_hp_ratio", "Ratio of CT : T Health", 0.6, ConVarFlags.FCVAR_NONE, new RangeValidator(0.00001, 10)); - public readonly FakeConVar CvLGBaseRoundTime = new("css_jb_lg_time_base", - "Round time to set when LG is activated, 0 to disable", 60); + public static readonly FakeConVar CV_LG_BASE_ROUND_TIME = + new("css_jb_lg_time_base", + "Round time to set when LG is activated, 0 to disable", 60); - public readonly FakeConVar CvLGKillBonusTime = + public static readonly FakeConVar CV_LG_KILL_BONUS_TIME = new("css_jb_lg_time_per_kill", "Additional round time to add per prisoner kill", 10); - public readonly FakeConVar CvLGMaxTime = new("css_jb_lg_time_max", - "Max round time to give the LG regardless of bonuses", 120); + public static readonly FakeConVar CV_LG_MAX_TIME = + new("css_jb_lg_time_max", + "Max round time to give the LG regardless of bonuses", 120); - public readonly FakeConVar CvLGPerPrisonerTime = + public static readonly FakeConVar CV_LG_PER_PRISONER_TIME = new("css_jb_lg_time_per_prisoner", "Additional round time to add per prisoner", 10); - public readonly FakeConVar CvLGWeapon = new("css_jb_lg_t_weapon", - "Weapon to give remaining prisoners once LG activates", "", - ConVarFlags.FCVAR_NONE, new WeaponValidator()); + public static readonly FakeConVar CV_LG_WEAPON = + new("css_jb_lg_t_weapon", + "Weapon to give remaining prisoners once LG activates", "", + ConVarFlags.FCVAR_NONE, new ItemValidator()); - public readonly FakeConVar CvMaxCtHealth = new("css_jb_lg_max_hp", - "Max HP that the LG can have otherwise", 125, ConVarFlags.FCVAR_NONE, - new RangeValidator(1, 1000)); + public static readonly FakeConVar CV_MAX_CT_HEALTH = + new("css_jb_lg_max_hp", "Max HP that the LG can have otherwise", 125, + ConVarFlags.FCVAR_NONE, new RangeValidator(1, 1000)); - public readonly FakeConVar CvMaxTHealthContribution = new( + public static readonly FakeConVar CV_MAX_T_HEALTH_CONTRIBUTION = new( "css_jb_lg_t_max_hp", "Max HP to contribute per T to LG", 200, ConVarFlags.FCVAR_NONE, new RangeValidator(1, 1000)); - public readonly FakeConVar CvMinimumCts = new("css_jb_lg_min_cts", - "Minimum number of CTs to start last guard", 2, ConVarFlags.FCVAR_NONE, - new RangeValidator(1, 32)); + public static readonly FakeConVar CV_MINIMUM_CTS = + new("css_jb_lg_min_cts", "Minimum number of CTs to start last guard", 2, + ConVarFlags.FCVAR_NONE, new RangeValidator(1, 32)); private readonly Random rng = new(); private bool canStart; @@ -71,11 +74,11 @@ public void StartLastGuard(CCSPlayerController lastGuard) { API.Stats?.PushStat(new ServerStat("JB_LASTGUARD", lastGuard.SteamID.ToString())); - var calculated = CalculateHealth(); + var calculated = calculateHealth(); - if (calculated < guardPlayerPawn.Health && !CvAlwaysOverrideCt.Value) { - if (guardPlayerPawn.Health > CvMaxCtHealth.Value) - guardPlayerPawn.Health = CvMaxCtHealth.Value; + if (calculated < guardPlayerPawn.Health && !CV_ALWAYS_OVERRIDE_CT.Value) { + if (guardPlayerPawn.Health > CV_MAX_CT_HEALTH.Value) + guardPlayerPawn.Health = CV_MAX_CT_HEALTH.Value; } else { guardPlayerPawn.Health = calculated; } Utilities.SetStateChanged(guardPlayerPawn, "CBaseEntity", "m_iHealth"); @@ -87,11 +90,11 @@ public void StartLastGuard(CCSPlayerController lastGuard) { .Where(p => p is { PawnIsAlive: true, Team: CsTeam.Terrorist }) .ToList(); - if (CvLGBaseRoundTime.Value != 0) - RoundUtil.SetTimeRemaining(Math.Min(CvLGBaseRoundTime.Value, - CvLGMaxTime.Value)); - addRoundTimeCapped(CvLGPerPrisonerTime.Value * lastGuardPrisoners.Count, - CvLGMaxTime.Value); + if (CV_LG_BASE_ROUND_TIME.Value != 0) + RoundUtil.SetTimeRemaining(Math.Min(CV_LG_BASE_ROUND_TIME.Value, + CV_LG_MAX_TIME.Value)); + addRoundTimeCapped(CV_LG_PER_PRISONER_TIME.Value * lastGuardPrisoners.Count, + CV_LG_MAX_TIME.Value); var prisonerHp = lastGuardPrisoners.Sum(prisoner @@ -101,15 +104,15 @@ public void StartLastGuard(CCSPlayerController lastGuard) { .ToAllCenter() .ToAllChat(); - if (string.IsNullOrEmpty(CvLGWeapon.Value)) return; + if (string.IsNullOrEmpty(CV_LG_WEAPON.Value)) return; foreach (var player in lastGuardPrisoners) - player.GiveNamedItem(CvLGWeapon.Value); + player.GiveNamedItem(CV_LG_WEAPON.Value); } public void DisableLastGuardForRound() { canStart = false; } - public int CalculateHealth() { + private int calculateHealth() { var aliveTerrorists = Utilities.GetPlayers() .Where(plr => plr is { PawnIsAlive: true, Team: CsTeam.Terrorist }) .ToList(); @@ -117,8 +120,8 @@ public int CalculateHealth() { return (int)Math.Floor(aliveTerrorists .Select(player => player.PlayerPawn.Value?.Health ?? 0) .Select(playerHealth - => Math.Min(playerHealth, CvMaxTHealthContribution.Value)) - .Sum() * CvGuardHealthRatio.Value); + => Math.Min(playerHealth, CV_MAX_T_HEALTH_CONTRIBUTION.Value)) + .Sum() * CV_GUARD_HEALTH_RATIO.Value); } [GameEventHandler] @@ -132,7 +135,7 @@ public HookResult OnPlayerDeathEvent(EventPlayerDeath @event, if (player.Team != CsTeam.Terrorist) return HookResult.Continue; - addRoundTimeCapped(CvLGKillBonusTime.Value, CvLGMaxTime.Value); + addRoundTimeCapped(CV_LG_KILL_BONUS_TIME.Value, CV_LG_MAX_TIME.Value); giveGun(player); return HookResult.Continue; @@ -200,7 +203,7 @@ public HookResult OnRoundStartEvent(EventRoundStart @event, canStart = Utilities.GetPlayers() .Count(plr => plr is { PawnIsAlive: true, Team: CsTeam.CounterTerrorist }) - >= CvMinimumCts.Value; + >= CV_MINIMUM_CTS.Value; return HookResult.Continue; } diff --git a/mod/Jailbreak.LastGuard/LastGuardConfig.cs b/mod/Jailbreak.LastGuard/LastGuardConfig.cs deleted file mode 100644 index 73e460fd..00000000 --- a/mod/Jailbreak.LastGuard/LastGuardConfig.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Jailbreak.LastGuard; - -[Obsolete("No longer used, use FakeConvars")] -public class LastGuardConfig { - public string? LastGuardWeapon { get; } = ""; - public int MinimumCTs { get; } = 4; -} \ No newline at end of file diff --git a/mod/Jailbreak.LastRequest/LastRequestManager.cs b/mod/Jailbreak.LastRequest/LastRequestManager.cs index fd66438f..f2dfb250 100644 --- a/mod/Jailbreak.LastRequest/LastRequestManager.cs +++ b/mod/Jailbreak.LastRequest/LastRequestManager.cs @@ -20,16 +20,16 @@ namespace Jailbreak.LastRequest; public class LastRequestManager(ILRLocale messages, IServiceProvider provider) : ILastRequestManager, IDamageBlocker { - public readonly FakeConVar CvLRBaseTime = new("css_jb_lr_time_base", + public static readonly FakeConVar CV_LR_BASE_TIME = new("css_jb_lr_time_base", "Round time to set when LR is activated, 0 to disable", 60); - public readonly FakeConVar CvLRBonusTime = new("css_jb_lr_time_per_lr", + public static readonly FakeConVar CV_LR_BONUS_TIME = new("css_jb_lr_time_per_lr", "Additional round time to add per LR completion", 30); - public readonly FakeConVar CvLRGuardTime = + public static readonly FakeConVar CV_LR_GUARD_TIME = new("css_jb_lr_time_per_guard", "Additional round time to add per guard"); - public readonly FakeConVar CvPrisonerToLR = + public static readonly FakeConVar CV_PRISONER_TO_LR = new("css_jb_lr_activate_lr_at", "Number of prisoners to activate LR at", 2, ConVarFlags.FCVAR_NONE, new RangeValidator(1, 32)); @@ -92,12 +92,12 @@ public void EnableLR(CCSPlayerController? died = null) { var cts = Utilities.GetPlayers() .Count(p => p is { Team: CsTeam.CounterTerrorist, PawnIsAlive: true }); - if (CvLRBaseTime.Value != 0) RoundUtil.SetTimeRemaining(CvLRBaseTime.Value); + if (CV_LR_BASE_TIME.Value != 0) RoundUtil.SetTimeRemaining(CV_LR_BASE_TIME.Value); - RoundUtil.AddTimeRemaining(CvLRGuardTime.Value * cts); + RoundUtil.AddTimeRemaining(CV_LR_GUARD_TIME.Value * cts); foreach (var player in Utilities.GetPlayers()) { - player.ExecuteClientCommand($"play sounds/lr"); + player.ExecuteClientCommand("play sounds/lr"); if (player.Team != CsTeam.Terrorist || !player.PawnIsAlive) continue; if (died != null && player.SteamID == died.SteamID) continue; player.ExecuteClientCommandFromServer("css_lr"); @@ -132,7 +132,7 @@ public bool InitiateLastRequest(CCSPlayerController prisoner, public bool EndLastRequest(AbstractLastRequest lr, LRResult result) { if (result is LRResult.GUARD_WIN or LRResult.PRISONER_WIN) { - RoundUtil.AddTimeRemaining(CvLRBonusTime.Value); + RoundUtil.AddTimeRemaining(CV_LR_BONUS_TIME.Value); messages.LastRequestDecided(lr, result).ToAllChat(); } @@ -189,7 +189,7 @@ public HookResult OnPlayerDeath(EventPlayerDeath @event, GameEventInfo info) { if (player.Team != CsTeam.Terrorist) return HookResult.Continue; - if (countAlivePrisoners() - 1 > CvPrisonerToLR.Value) + if (countAlivePrisoners() - 1 > CV_PRISONER_TO_LR.Value) return HookResult.Continue; if (Utilities.GetPlayers().All(p => p.Team != CsTeam.CounterTerrorist)) @@ -222,7 +222,7 @@ public HookResult OnPlayerDisconnect(EventPlayerDisconnect @event, if (!IsLREnabledForRound) return HookResult.Continue; if (player.Team != CsTeam.Terrorist) return HookResult.Continue; - if (countAlivePrisoners() > CvPrisonerToLR.Value) + if (countAlivePrisoners() > CV_PRISONER_TO_LR.Value) return HookResult.Continue; EnableLR(); diff --git a/mod/Jailbreak.LastRequest/LastRequests/BulletForBullet.cs b/mod/Jailbreak.LastRequest/LastRequests/BulletForBullet.cs index d6c6888e..06e9b3a7 100644 --- a/mod/Jailbreak.LastRequest/LastRequests/BulletForBullet.cs +++ b/mod/Jailbreak.LastRequest/LastRequests/BulletForBullet.cs @@ -45,7 +45,8 @@ private void OnSelect(CCSPlayerController player, ChatMenuOption _, designerName = designer; MenuManager.CloseActiveMenu(player); - msg.WeaponSelected(player, designerName).ToChat(Prisoner, Guard); + msg.WeaponSelected(player, designerName.GetFriendlyWeaponName()) + .ToChat(Prisoner, Guard); State = LRState.ACTIVE; diff --git a/mod/Jailbreak.Rebel/C4Bomb/C4Behavior.cs b/mod/Jailbreak.Rebel/C4Bomb/C4Behavior.cs index fc3a3a35..19e74d3c 100644 --- a/mod/Jailbreak.Rebel/C4Bomb/C4Behavior.cs +++ b/mod/Jailbreak.Rebel/C4Bomb/C4Behavior.cs @@ -1,6 +1,8 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes.Registration; +using CounterStrikeSharp.API.Modules.Cvars; +using CounterStrikeSharp.API.Modules.Cvars.Validators; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Utils; using Jailbreak.Formatting.Extensions; @@ -25,11 +27,27 @@ private readonly MemoryFunctionVoid private BasePlugin? plugin; + public static readonly FakeConVar CV_GIVE_BOMB = new("css_jb_c4_give", + "Whether to give a random prisoner a bomb at the beginning of the round.", + true); + + public static readonly FakeConVar CV_C4_DELAY = new("css_jb_c4_delay", + "Time in seconds that the bomb takes to explode", .75f, + ConVarFlags.FCVAR_NONE, new RangeValidator(0, 2)); + + public static readonly FakeConVar CV_C4_RADIUS = + new("css_jb_c4_radius", "Bomb explosion radius", 350, + ConVarFlags.FCVAR_NONE, new RangeValidator(0, 10000)); + + public static readonly FakeConVar CV_C4_BASE_DAMAGE = + new("css_jb_c4_damage", "Base damage to apply", 340, ConVarFlags.FCVAR_NONE, + new RangeValidator(0, 10000)); + public void ClearActiveC4s() { bombs.Clear(); } public void TryGiveC4ToPlayer(CCSPlayerController player) { var bombEntity = new CC4(player.GiveNamedItem("weapon_c4")); - bombs.Add(bombEntity, new C4Metadata(0.75f, false)); + bombs.Add(bombEntity, new C4Metadata(false)); ic4Locale.JihadC4Received.ToChat(player); ic4Locale.JihadC4Usage1.ToChat(player); @@ -45,7 +63,6 @@ public void StartDetonationAttempt(CCSPlayerController player, float delay, tryEmitSound(player, "jb.jihad", 1, 1f, 0f); - bombs[bombEntity].Delay = delay; bombs[bombEntity].IsDetonating = true; rebelService.MarkRebel(player); @@ -95,14 +112,15 @@ private void playerUseC4ListenerCallback() { || activeWeapon.Handle != bomb.Handle) continue; - StartDetonationAttempt(bombCarrier, meta.Delay, bomb); + StartDetonationAttempt(bombCarrier, CV_C4_DELAY.Value, bomb); } } [GameEventHandler] public HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info) { ClearActiveC4s(); - TryGiveC4ToRandomTerrorist(); + + if (CV_GIVE_BOMB.Value) TryGiveC4ToRandomTerrorist(); return HookResult.Continue; } @@ -154,11 +172,10 @@ private void detonate(CCSPlayerController player, CC4 bomb) { var distanceFromBomb = ct.PlayerPawn.Value!.AbsOrigin!.Distance(player.PlayerPawn.Value .AbsOrigin!); - if (distanceFromBomb > 350f) continue; + if (distanceFromBomb > CV_C4_RADIUS.Value) continue; - // 350f = "bombRadius" - var damage = 340f; - damage *= (350f - distanceFromBomb) / 350f; + var damage = CV_C4_BASE_DAMAGE.Value; + damage *= (CV_C4_RADIUS.Value - distanceFromBomb) / CV_C4_RADIUS.Value; float healthRef = ct.PlayerPawn.Value.Health; if (healthRef <= damage) { ct.CommitSuicide(true, true); @@ -183,8 +200,7 @@ private void tryEmitSound(CBaseEntity entity, string soundEventName, volume, delay); } - private class C4Metadata(float delay, bool isDetonating) { - public float Delay { get; set; } = delay; + private class C4Metadata(bool isDetonating) { public bool IsDetonating { get; set; } = isDetonating; } } \ No newline at end of file diff --git a/mod/Jailbreak.Rebel/RebelManager.cs b/mod/Jailbreak.Rebel/RebelManager.cs index 24998c86..1fd76c33 100644 --- a/mod/Jailbreak.Rebel/RebelManager.cs +++ b/mod/Jailbreak.Rebel/RebelManager.cs @@ -20,9 +20,9 @@ public class RebelManager(IRebelLocale notifs, IRichLogService logs) [Obsolete("No longer used, use FakeConvar")] public static readonly int MAX_REBEL_TIME = 45; - public readonly FakeConVar CvRebelTime = new("css_jb_rebel_time", - "Time to mark a rebel for", 30, ConVarFlags.FCVAR_NONE, - new RangeValidator(0, 500)); + public static readonly FakeConVar CV_REBEL_TIME = + new("css_jb_rebel_time", "Time to mark a rebel for", 45, + ConVarFlags.FCVAR_NONE, new RangeValidator(0, 500)); private readonly Dictionary rebelTimes = new(); private bool enabled = true; @@ -71,7 +71,7 @@ public bool MarkRebel(CCSPlayerController player, long time = -1) { API.Stats?.PushStat(new ServerStat("JB_REBEL_STARTED", $"{player.SteamID} {pos.X:F2} {pos.Y:F2} {pos.Z:F2}")); - if (time == -1) time = CvRebelTime.Value; + if (time == -1) time = CV_REBEL_TIME.Value; rebelTimes[player] = DateTimeOffset.Now.ToUnixTimeSeconds() + time; applyRebelColor(player); @@ -128,10 +128,10 @@ private HookResult OnPlayerDeath(EventPlayerDeath @event, // https://www.desmos.com/calculator/g2v6vvg7ax private float getRebelTimePercentage(CCSPlayerController player) { var x = GetRebelTimeLeft(player); - if (x > CvRebelTime.Value) return 1; + if (x > CV_REBEL_TIME.Value) return 1; if (x <= 0) return 0; - return (float)(100 - (CvRebelTime.Value - x) - * Math.Sqrt(CvRebelTime.Value - x) / 3.8f) / 100; + return (float)(100 - (CV_REBEL_TIME.Value - x) + * Math.Sqrt(CV_REBEL_TIME.Value - x) / 3.8f) / 100; } private Color getRebelColor(CCSPlayerController player) { diff --git a/mod/Jailbreak.SpecialDay/SpecialDayCommand.cs b/mod/Jailbreak.SpecialDay/SpecialDayCommand.cs index 69b299d3..416c666b 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDayCommand.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDayCommand.cs @@ -20,15 +20,15 @@ namespace Jailbreak.SpecialDay; public class SpecialDayCommand(IWardenService warden, ISpecialDayFactory factory, IWardenLocale wardenMsg, ISDLocale sdMsg, ISpecialDayManager sd) : IPluginBehavior { - public static FakeConVar CvRoundsBetweenSD = new( + public static readonly FakeConVar CV_ROUNDS_BETWEEN_SD = new( "css_jb_sd_round_cooldown", "Rounds between special days", 4); - public static FakeConVar CvMaxElapsedTime = new( + public static readonly FakeConVar CV_MAX_ELAPSED_TIME = new( "css_jb_sd_max_elapsed_time", "Max time elapsed in a round to be able to call a special day", 30); - private SpecialDayMenuSelector? menuSelector; - private BasePlugin? plugin; + private SpecialDayMenuSelector menuSelector = null!; + private BasePlugin plugin = null!; // css_lr public void Start(BasePlugin basePlugin) { @@ -41,6 +41,17 @@ public void Start(BasePlugin basePlugin) { [ConsoleCommand("css_startday", "Start a special day as the warden")] public void Command_SpecialDay(CCSPlayerController? executor, CommandInfo info) { + if (executor != null && sd.IsSDRunning && info.ArgCount == 1) { + // SD is already running + if (sd.CurrentSD is ISpecialDayMessageProvider messaged) + sdMsg.SpecialDayRunning(messaged.Locale.Name).ToChat(executor); + else + sdMsg.SpecialDayRunning(sd.CurrentSD?.Type.ToString() ?? "Unknown") + .ToChat(executor); + + return; + } + if (executor != null && !AdminManager.PlayerHasPermissions(executor, "@css/rcon")) { if (!warden.IsWarden(executor) || RoundUtil.IsWarmup()) { @@ -59,14 +70,14 @@ public void Command_SpecialDay(CCSPlayerController? executor, return; } - var roundsToNext = sd.RoundsSinceLastSD - CvRoundsBetweenSD.Value; + var roundsToNext = sd.RoundsSinceLastSD - CV_ROUNDS_BETWEEN_SD.Value; if (roundsToNext < 0) { sdMsg.SpecialDayCooldown(Math.Abs(roundsToNext)).ToChat(executor); return; } - if (RoundUtil.GetTimeElapsed() > CvMaxElapsedTime.Value) { - sdMsg.TooLateForSpecialDay(CvMaxElapsedTime.Value); + if (RoundUtil.GetTimeElapsed() > CV_MAX_ELAPSED_TIME.Value) { + sdMsg.TooLateForSpecialDay(CV_MAX_ELAPSED_TIME.Value); return; } } @@ -77,8 +88,7 @@ public void Command_SpecialDay(CCSPlayerController? executor, return; } - MenuManager.OpenCenterHtmlMenu(plugin!, executor, - menuSelector!.GetMenu()); + MenuManager.OpenCenterHtmlMenu(plugin, executor, menuSelector.GetMenu()); return; } diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/AbstractZoneRestrictedDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/AbstractZoneRestrictedDay.cs index 0b11d323..57d7ef03 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/AbstractZoneRestrictedDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/AbstractZoneRestrictedDay.cs @@ -11,7 +11,7 @@ namespace Jailbreak.SpecialDay.SpecialDays; public abstract class AbstractZoneRestrictedDay : AbstractSpecialDay { - protected readonly CsTeam RestrictedTeam; + protected CsTeam RestrictedTeam; protected readonly IList Restrictors = new List(); diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/FFADay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/FFADay.cs index 06135f73..e7e64cd3 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/FFADay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/FFADay.cs @@ -23,7 +23,6 @@ public override void Setup() { base.Setup(); } - public override void Execute() { base.Execute(); Locale.BeginsIn(0).ToAllChat(); diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs index 08f63d44..19f914fb 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs @@ -1,4 +1,7 @@ -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Cvars; +using CounterStrikeSharp.API.Modules.Cvars.Validators; using CounterStrikeSharp.API.Modules.Utils; using Jailbreak.English.SpecialDay; using Jailbreak.Formatting.Base; @@ -8,6 +11,7 @@ using Jailbreak.Public.Mod.SpecialDay; using Jailbreak.Public.Mod.SpecialDay.Enums; using Jailbreak.Public.Utils; +using Jailbreak.Validator; namespace Jailbreak.SpecialDay.SpecialDays; @@ -15,68 +19,161 @@ public class HideAndSeekDay(BasePlugin plugin, IServiceProvider provider) : AbstractArmoryRestrictedDay(plugin, provider), ISpecialDayMessageProvider { public override SDType Type => SDType.HNS; - private HNSDayLocale msg => (HNSDayLocale)Locale; + private HNSDayLocale Msg => (HNSDayLocale)Locale; + public override SpecialDaySettings Settings => new HnsSettings(); + public override IView ArmoryReminder => Msg.StayInArmory; + public ISDInstanceLocale Locale => new HNSDayLocale(); - public override SpecialDaySettings Settings => new HNSSettings(); + // Set to -1 to not modify values + public static readonly FakeConVar CV_PRISONER_PRE_HEALTH = new( + "jb_sd_hns_hide_hp_t", "Health to give to prisoners during HNS hide time", + 300, ConVarFlags.FCVAR_NONE, new NonZeroRangeValidator(-1, 1000)); - public override IView ArmoryReminder => msg.StayInArmory; + public static readonly FakeConVar CV_GUARD_PRE_HEALTH = + new("jb_sd_hns_hide_hp_ct", "Health to give to guards during HNS hide time", + 150, ConVarFlags.FCVAR_NONE, new RangeValidator(-1, 1000)); - public ISDInstanceLocale Locale => new HNSDayLocale(); + public static readonly FakeConVar CV_PRISONER_PRE_ARMOR = new( + "jb_sd_hns_hide_armor_t", "Armor to give to prisoners during HNS hide time", + 200, ConVarFlags.FCVAR_NONE, new RangeValidator(-1, 1000)); + + public static readonly FakeConVar CV_GUARD_PRE_ARMOR = + new("jb_sd_hns_hide_armor_ct", + "Armor to give to guards during HNS hide time", 300, + ConVarFlags.FCVAR_NONE, new RangeValidator(-1, 1000)); + + public static readonly FakeConVar CV_PRISONER_POST_HEALTH = new( + "jb_sd_hns_seek_hp_t", "Health to give to prisoners during HNS seek time", + 300, ConVarFlags.FCVAR_NONE, new NonZeroRangeValidator(1, 1000)); + + public static readonly FakeConVar CV_GUARD_POST_HEALTH = new( + "jb_sd_hns_seek_hp_ct", "Health to give to guards during HNS seek time", 25, + ConVarFlags.FCVAR_NONE, new NonZeroRangeValidator(1, 1000)); + + public static readonly FakeConVar CV_PRISONER_POST_ARMOR = new( + "jb_sd_hns_seek_armor_t", "Armor to give to prisoners during HNS seek time", + 500, ConVarFlags.FCVAR_NONE, new RangeValidator(-1, 1000)); + + public static readonly FakeConVar CV_GUARD_POST_ARMOR = new( + "jb_sd_hns_seek_armor_ct", "Armor to give to guards during HNS seek time", + -1, ConVarFlags.FCVAR_NONE, new RangeValidator(-1, 1000)); + + public static readonly FakeConVar CV_GUARD_WEAPONS = new( + "jb_sd_hns_weapons_ct", + "List of weapons/items CTs may use, empty for no restrictions", + string.Join(",", Tag.PISTOLS.Union(Tag.UTILITY)), ConVarFlags.FCVAR_NONE, + new ItemValidator(allowMultiple: true)); + + public static readonly FakeConVar CV_PRISONER_WEAPONS = new( + "jb_sd_hns_weapons_t", + "List of weapons/items Ts may use, empty for no restrictions", "", + ConVarFlags.FCVAR_NONE, new ItemValidator(allowMultiple: true)); + + public static readonly FakeConVar CV_SEEKER_TEAM = + new("jb_sd_hns_seekers", "Team to assign as seekers and restrict to armory", + "t", ConVarFlags.FCVAR_NONE, new TeamValidator(false)); + + public static readonly FakeConVar CV_SEEK_TIME = + new("jb_sd_hns_seektime", + "Duration in seconds to give the hiders time to hide", 45, + ConVarFlags.FCVAR_NONE, new RangeValidator(5, 120)); + + private CsTeam? SeekerTeam => TeamUtil.FromString(CV_SEEKER_TEAM.Value); + + private CsTeam? HiderTeam + => (SeekerTeam ?? CsTeam.Terrorist) == CsTeam.Terrorist ? + CsTeam.CounterTerrorist : + CsTeam.Terrorist; public override void Setup() { - Timers[10] += () => { - foreach (var ct in PlayerUtil.FromTeam(CsTeam.CounterTerrorist)) - ct.SetSpeed(1.5f); - - msg.DamageWarning(15).ToTeamChat(CsTeam.CounterTerrorist); - - Locale.BeginsIn(35).ToAllChat(); - }; - Timers[25] += () => { - foreach (var ct in PlayerUtil.FromTeam(CsTeam.CounterTerrorist)) { - ct.SetSpeed(1.25f); - EnableDamage(ct); - } - }; - Timers[30] += () => { - foreach (var ct in PlayerUtil.FromTeam(CsTeam.CounterTerrorist)) - ct.SetSpeed(1.1f); - Locale.BeginsIn(15).ToAllChat(); - }; - Timers[45] += Execute; + if (SeekerTeam == null || HiderTeam == null) return; + RestrictedTeam = SeekerTeam.Value; + + if (CV_SEEK_TIME.Value >= 10) + Timers[10] += () => { + foreach (var ct in PlayerUtil.FromTeam(SeekerTeam.Value)) + ct.SetSpeed(1.5f); + + Msg.DamageWarning(15).ToTeamChat(SeekerTeam.Value); + }; + if (CV_SEEK_TIME.Value >= 25) + Timers[25] += () => { + foreach (var player in PlayerUtil.FromTeam(SeekerTeam.Value)) { + player.SetSpeed(1.25f); + EnableDamage(player); + } + }; + + if (CV_SEEK_TIME.Value >= 30) + Timers[30] += () => { + foreach (var ct in PlayerUtil.FromTeam(SeekerTeam.Value)) + ct.SetSpeed(1.1f); + }; + + for (var offset = 15; offset < CV_SEEK_TIME.Value; offset += 15) { + var beginsIn = CV_SEEK_TIME.Value - offset; + Timers[CV_SEEK_TIME.Value - offset] += + () => Locale.BeginsIn(beginsIn).ToAllChat(); + } + + Timers[CV_SEEK_TIME.Value] += Execute; base.Setup(); - foreach (var ct in PlayerUtil.FromTeam(CsTeam.CounterTerrorist)) - ct.SetSpeed(2f); + foreach (var player in PlayerUtil.FromTeam(SeekerTeam.Value)) + player.SetSpeed(2f); } public override void Execute() { + if (SeekerTeam == null || HiderTeam == null) return; base.Execute(); - foreach (var t in PlayerUtil.FromTeam(CsTeam.Terrorist)) t.SetArmor(100); - foreach (var ct in PlayerUtil.FromTeam(CsTeam.CounterTerrorist)) - ct.SetSpeed(1); + foreach (var player in PlayerUtil.GetAlive()) { + var hp = (player.Team == CsTeam.Terrorist ? + CV_PRISONER_POST_HEALTH : + CV_GUARD_POST_HEALTH).Value; + + var armor = (player.Team == CsTeam.Terrorist ? + CV_PRISONER_POST_ARMOR : + CV_GUARD_POST_ARMOR).Value; + + if (hp != -1) player.SetHealth(hp); + if (armor != -1) player.SetArmor(armor); + } + + foreach (var ct in PlayerUtil.FromTeam(SeekerTeam.Value)) ct.SetSpeed(1); } - public class HNSSettings : SpecialDaySettings { - public HNSSettings() { + public class HnsSettings : SpecialDaySettings { + private readonly ISet? cachedGuardWeapons, cachedPrisonerWeapons; + + public HnsSettings() { AllowLastRequests = true; TTeleport = TeleportType.ARMORY; CtTeleport = TeleportType.ARMORY; + + cachedGuardWeapons = CV_GUARD_WEAPONS.Value.Split(",").ToHashSet(); + cachedPrisonerWeapons = CV_PRISONER_WEAPONS.Value.Split(",").ToHashSet(); + + if (cachedGuardWeapons.Count == 0) cachedGuardWeapons = null; + if (cachedPrisonerWeapons.Count == 0) cachedPrisonerWeapons = null; } public override int InitialHealth(CCSPlayerController player) { - return player.Team == CsTeam.Terrorist ? 250 : 50; + return player.Team == CsTeam.Terrorist ? + CV_PRISONER_PRE_HEALTH.Value : + CV_GUARD_PRE_HEALTH.Value; } public override int InitialArmor(CCSPlayerController player) { - if (player.Team != CsTeam.Terrorist) return -1; - return 500; + return player.Team == CsTeam.Terrorist ? + CV_PRISONER_PRE_ARMOR.Value : + CV_GUARD_PRE_ARMOR.Value; } public override ISet? AllowedWeapons(CCSPlayerController player) { - if (player.Team != CsTeam.CounterTerrorist) return null; - return Tag.PISTOLS.Union(Tag.UTILITY).ToHashSet(); + return player.Team == CsTeam.Terrorist ? + cachedPrisonerWeapons : + cachedGuardWeapons; } } } \ No newline at end of file diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/InfectionDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/InfectionDay.cs index 65714458..9b5e567e 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/InfectionDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/InfectionDay.cs @@ -12,13 +12,11 @@ namespace Jailbreak.SpecialDay.SpecialDays; -public class InfectionDay : AbstractArmoryRestrictedDay, - ISpecialDayMessageProvider { +public class InfectionDay(BasePlugin plugin, IServiceProvider provider) + : AbstractArmoryRestrictedDay(plugin, provider, CsTeam.CounterTerrorist), + ISpecialDayMessageProvider { private readonly ICollection swappedPrisoners = new HashSet(); - public InfectionDay(BasePlugin Plugin, IServiceProvider provider) : base( - Plugin, provider, CsTeam.CounterTerrorist) { } - public override SDType Type => SDType.INFECTION; public override SpecialDaySettings Settings => new InfectionSettings(); @@ -40,12 +38,12 @@ public override void Setup() { foreach (var ct in PlayerUtil.FromTeam(CsTeam.CounterTerrorist)) ct.SetColor(Color.LimeGreen); - Plugin.RegisterEventHandler(OnPlayerDeath); - Plugin.RegisterEventHandler(OnRespawn); + Plugin.RegisterEventHandler(onPlayerDeath); + Plugin.RegisterEventHandler(onRespawn); } private HookResult - OnPlayerDeath(EventPlayerDeath @event, GameEventInfo info) { + onPlayerDeath(EventPlayerDeath @event, GameEventInfo info) { var player = @event.Userid; if (player == null || !player.IsValid) return HookResult.Continue; if (player.Team != CsTeam.Terrorist) return HookResult.Continue; @@ -101,7 +99,7 @@ private HookResult return HookResult.Continue; } - public HookResult OnRespawn(EventPlayerSpawn @event, GameEventInfo info) { + private HookResult onRespawn(EventPlayerSpawn @event, GameEventInfo info) { var player = @event.Userid; if (player == null || !player.IsValid) return HookResult.Continue; if (player.Team != CsTeam.CounterTerrorist) return HookResult.Continue; @@ -119,13 +117,13 @@ public HookResult OnRespawn(EventPlayerSpawn @event, GameEventInfo info) { override protected HookResult OnEnd(EventRoundEnd @event, GameEventInfo info) { var result = base.OnEnd(@event, info); - Plugin.DeregisterEventHandler(OnPlayerDeath); - Plugin.DeregisterEventHandler(OnRespawn); + Plugin.DeregisterEventHandler(onPlayerDeath); + Plugin.DeregisterEventHandler(onRespawn); Plugin.AddTimer(0.1f, () => { foreach (var index in swappedPrisoners) { var player = Utilities.GetPlayerFromSlot(index); - if (player == null) continue; + if (player == null || !player.IsValid) continue; player.SwitchTeam(CsTeam.Terrorist); } }); diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/NoScopeDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/NoScopeDay.cs index 484290e7..0f1f34da 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/NoScopeDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/NoScopeDay.cs @@ -1,11 +1,14 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Cvars; +using CounterStrikeSharp.API.Modules.Cvars.Validators; using Jailbreak.English.SpecialDay; using Jailbreak.Formatting.Views.SpecialDay; using Jailbreak.Public.Extensions; using Jailbreak.Public.Mod.SpecialDay; using Jailbreak.Public.Mod.SpecialDay.Enums; using Jailbreak.Public.Utils; +using Jailbreak.Validator; namespace Jailbreak.SpecialDay.SpecialDays; @@ -19,18 +22,42 @@ public override ISDInstanceLocale Locale public override SpecialDaySettings Settings => new NoScopeSettings(); + public static readonly FakeConVar CV_WEAPON = new( + "jb_sd_noscope_weapon", + "Weapon to give to all players, recommended it be a weapon with a scope (duh)", + "weapon_ssg08", ConVarFlags.FCVAR_NONE, + new ItemValidator(allowMultiple: true)); + + public static readonly FakeConVar CV_WEAPON_WHITELIST = new( + "jb_sd_noscope_allowedweapons", + "Weapons to allow players to use, empty for no restrictions", + string.Join(",", + Tag.UTILITY.Union(new[] { "weapon_ssg08", "weapon_knife" }.ToHashSet())), + ConVarFlags.FCVAR_NONE, new ItemValidator(allowMultiple: true)); + + public static readonly FakeConVar CV_KNIFE_DELAY = new( + "jb_sd_noscope_knife_delay", + "Time delay in seconds to give knives at, 0 to disable", 120, + ConVarFlags.FCVAR_NONE, new RangeValidator(0, 500)); + + public static readonly FakeConVar CV_GRAVITY = + new("jb_sd_noscope_gravity", + "Gravity to set during the special day, default is 800", 200f); + public override void Setup() { - Timers[120] += () => { - foreach (var player in PlayerUtil.GetAlive()) - player.GiveNamedItem("weapon_knife"); - }; + if (CV_KNIFE_DELAY.Value > 0) + Timers[CV_KNIFE_DELAY.Value] += () => { + foreach (var player in PlayerUtil.GetAlive()) + player.GiveNamedItem("weapon_knife"); + }; base.Setup(); } public override void Execute() { foreach (var player in PlayerUtil.GetAlive()) { player.RemoveWeapons(); - player.GiveNamedItem("weapon_ssg08"); + foreach (var weapon in CV_WEAPON.Value.Split(",")) + player.GiveNamedItem(weapon); } base.Execute(); @@ -50,8 +77,9 @@ private void disableScope(CCSPlayerController player) { if (activeWeapon == null || !activeWeapon.IsValid) return; activeWeapon.NextSecondaryAttackTick = Server.TickCount + 500; - if (activeWeapon.DesignerName is "weapon_ssg08" or "weapon_knife") return; - if (Tag.UTILITY.Contains(activeWeapon.DesignerName)) return; + if (CV_WEAPON_WHITELIST.Value.Contains(activeWeapon.DesignerName, + StringComparison.CurrentCultureIgnoreCase)) + return; activeWeapon.NextPrimaryAttackTick = Server.TickCount + 500; } @@ -61,7 +89,7 @@ public NoScopeSettings() { TTeleport = TeleportType.RANDOM; RestrictWeapons = true; - ConVarValues["sv_gravity"] = (float)200; + ConVarValues["sv_gravity"] = CV_GRAVITY.Value; ConVarValues["sv_infinite_ammo"] = 2; } diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs index 897a6a63..682ef3ab 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs @@ -1,10 +1,13 @@ +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Cvars; using Jailbreak.English.SpecialDay; using Jailbreak.Formatting.Views.SpecialDay; using Jailbreak.Public.Extensions; using Jailbreak.Public.Mod.SpecialDay; using Jailbreak.Public.Mod.SpecialDay.Enums; using Jailbreak.Public.Utils; +using Jailbreak.Validator; namespace Jailbreak.SpecialDay.SpecialDays; @@ -18,6 +21,15 @@ public override ISDInstanceLocale Locale public override SpecialDaySettings Settings => new OitcSettings(); + public static readonly FakeConVar CV_WEAPON = new("jb_sd_oitc_weapon", + "Weapon to give to players for the day", "weapon_deagle", + ConVarFlags.FCVAR_NONE, new ItemValidator(ItemValidator.WeaponType.GUNS)); + + public static readonly FakeConVar CV_ADDITIONAL_WEAPON = new( + "jb_sd_oitc_additionalweapon", + "Additional (non-ammo restricted) weapons to give for the day", + "weapon_knife", ConVarFlags.FCVAR_NONE, new ItemValidator()); + public override void Setup() { base.Setup(); Plugin.RegisterEventHandler(OnPlayerDamage); @@ -29,9 +41,12 @@ public override void Execute() { foreach (var player in PlayerUtil.GetAlive()) { player.RemoveWeapons(); - player.GiveNamedItem("weapon_knife"); - player.GiveNamedItem("weapon_deagle"); - player.GetWeaponBase("weapon_deagle")?.SetAmmo(1, 0); + if (CV_ADDITIONAL_WEAPON.Value.Length > 0) + player.GiveNamedItem(CV_ADDITIONAL_WEAPON.Value); + if (CV_WEAPON.Value.Length > 0) { + player.GiveNamedItem(CV_WEAPON.Value); + player.GetWeaponBase(CV_WEAPON.Value)?.SetAmmo(1, 0); + } } } @@ -46,7 +61,7 @@ private HookResult private HookResult OnPlayerDeath(EventPlayerDeath @event, GameEventInfo info) { if (@event.Attacker == null) return HookResult.Continue; - @event.Attacker.GetWeaponBase("weapon_deagle")?.AddBulletsToMagazine(1); + @event.Attacker.GetWeaponBase(CV_WEAPON.Value)?.AddBulletsToMagazine(1); return HookResult.Continue; } @@ -56,19 +71,21 @@ override protected HookResult Plugin.DeregisterEventHandler(OnPlayerDeath); return base.OnEnd(@event, info); } -} -public class OitcSettings : SpecialDaySettings { - public OitcSettings() { - CtTeleport = TeleportType.RANDOM; - TTeleport = TeleportType.RANDOM; - RestrictWeapons = true; - WithFriendlyFire(); + public class OitcSettings : SpecialDaySettings { + public OitcSettings() { + CtTeleport = TeleportType.RANDOM; + TTeleport = TeleportType.RANDOM; + RestrictWeapons = true; + WithFriendlyFire(); - ConVarValues["mp_death_drop_gun"] = 0; - } + ConVarValues["mp_death_drop_gun"] = 0; + } - public override ISet AllowedWeapons(CCSPlayerController player) { - return new HashSet { "weapon_deagle", "weapon_knife" }; + public override ISet AllowedWeapons(CCSPlayerController player) { + return new HashSet { + CV_WEAPON.Value, CV_ADDITIONAL_WEAPON.Value + }; + } } } \ No newline at end of file diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/SpeedrunDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/SpeedrunDay.cs index 8afa173c..fc77de84 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/SpeedrunDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/SpeedrunDay.cs @@ -26,56 +26,56 @@ public class SpeedrunDay(BasePlugin plugin, IServiceProvider provider) : AbstractSpecialDay(plugin, provider), ISpecialDayMessageProvider { private const int MAX_POINTS = 500; - public static readonly FakeConVar CvInitialSpeedrunTime = + public static readonly FakeConVar CV_INITIAL_SPEEDRUN_TIME = new("css_jb_speedrun_initial_time", "Duration in seconds to grant the speedrunner", 40); - public static readonly FakeConVar CvFirstRoundFreeze = + public static readonly FakeConVar CV_FIRST_ROUND_FREEZE = new("css_jb_speedrun_first_round_freeze", "Duration in seconds to give players time to read the rules of speedrun", 6); - public static readonly FakeConVar CvFreezeTime = + public static readonly FakeConVar CV_FREEZE_TIME = new("css_jb_speedrun_freeze_time", "Duration in seconds to freeze players before the speedrun starts", 2); - public static readonly FakeConVar CvWinTimeBase = + public static readonly FakeConVar CV_WIN_TIME_BASE = new("css_jb_speedrun_win_time_base", "Base duration in seconds to give the winner to kill other competitors", 25); - public static readonly FakeConVar CvWinTimeBonus = + public static readonly FakeConVar CV_WIN_TIME_BONUS = new("css_jb_speedrun_win_time_bonus", "Bonus duration in seconds to give the winner for every competitor", 5); - public static readonly FakeConVar CvWinTimeMax = + public static readonly FakeConVar CV_WIN_TIME_MAX = new("css_jb_speedrun_win_max", "Max time to give the winner regardless of bonus", 60); - public static readonly FakeConVar CvWinWeapon = new( + public static readonly FakeConVar CV_WIN_WEAPONS = new( "css_jb_speedrun_win_weapons", "Weapon(s) to give to the winner to kill other competitors", "weapon_knife,weapon_negev", - customValidators: new WeaponValidator(allowMultiple: true)); + customValidators: new ItemValidator(allowMultiple: true)); - public static readonly FakeConVar CvLosersWeapon = new( + public static readonly FakeConVar CV_LOSERS_WEAPONS = new( "css_jb_speedrun_loser_weapons", "Weapon(s) to give to the losers to use against the winner", "", - customValidators: new WeaponValidator(allowMultiple: true)); + customValidators: new ItemValidator(allowMultiple: true)); - public static readonly FakeConVar CvWinnerDamageable = new( + public static readonly FakeConVar CV_WINNER_DAMAGEABLE = new( "css_jb_speedrun_winner_damageable", "Whether the winner can be damaged"); - public static readonly FakeConVar CvLoserDamageable = new( + public static readonly FakeConVar CV_LOSER_DAMAGEABLE = new( "css_jb_speedrun_loser_damageable", "Whether the losers can be damaged", true); - public static readonly FakeConVar CvTeleportType = + public static readonly FakeConVar CV_TELEPORT_TYPE = new("css_jb_speedrun_teleport_type", "0 = Dont teleport at end, 1 = Teleport losers to winner, 2 = Teleport winner to loser(s)", 2); - public static readonly FakeConVar CvMaxPlayersToFinish = new( + public static readonly FakeConVar CV_MAX_PLAYERS_TO_FINISH = new( "css_jb_speedrun_finish_at", "Number of players required to declare a winner", 2, customValidators: new RangeValidator(2, 10)); @@ -88,7 +88,7 @@ private readonly Dictionary> /// Positive values represent players who are still alive, and the value /// being the distance they are from the target. /// - private readonly HashSet finishedPlayers = new(); + private readonly HashSet finishedPlayers = []; private readonly Random rng = new(); private float? bestTime; @@ -96,7 +96,7 @@ private readonly Dictionary> private AbstractTrail? bestTrail; - private LinkedList<(int, float)> finishTimestampList = new(); + private LinkedList<(int, float)> finishTimestampList = []; private IGenericCmdLocale generics = null!; private int round, playersAliveAtStart; @@ -107,9 +107,9 @@ private readonly Dictionary> private Vector? start; private Vector? target; private BeamCircle? targetCircle; - private ISpeedDayLocale msg => (ISpeedDayLocale)Locale; + private ISpeedDayLocale Msg => (ISpeedDayLocale)Locale; - private bool isRoundActive + private bool IsRoundActive => Provider.GetRequiredService().CurrentSD == this; public override SDType Type => SDType.SPEEDRUN; @@ -144,7 +144,7 @@ public override void Setup() { player.SetColor(Color.FromArgb(100, 255, 255, 255)); } }; - Timers[CvFirstRoundFreeze.Value - 4] += () => { + Timers[CV_FIRST_ROUND_FREEZE.Value - 4] += () => { if (!speedrunner.IsValid || speedrunner.Connected != PlayerConnectedState.PlayerConnected) speedrunner = getRunner(); @@ -153,11 +153,11 @@ public override void Setup() { return; } - msg.RunnerAssigned(speedrunner).ToAllChat(); + Msg.RunnerAssigned(speedrunner).ToAllChat(); speedrunner.SetColor(Color.DodgerBlue); - msg.YouAreRunner(CvInitialSpeedrunTime.Value).ToChat(speedrunner); + Msg.YouAreRunner(CV_INITIAL_SPEEDRUN_TIME.Value).ToChat(speedrunner); }; - Timers[CvFirstRoundFreeze.Value] += () => { + Timers[CV_FIRST_ROUND_FREEZE.Value] += () => { if (!speedrunner.IsValid || speedrunner.Connected != PlayerConnectedState.PlayerConnected) { speedrunner = getRunner(); @@ -168,8 +168,8 @@ public override void Setup() { } speedrunner.SetColor(Color.DodgerBlue); - msg.RunnerLeftAndReassigned(speedrunner).ToAllChat(); - msg.YouAreRunner(CvInitialSpeedrunTime.Value).ToChat(speedrunner); + Msg.RunnerLeftAndReassigned(speedrunner).ToAllChat(); + Msg.YouAreRunner(CV_INITIAL_SPEEDRUN_TIME.Value).ToChat(speedrunner); } start = speedrunner.PlayerPawn.Value!.AbsOrigin!.Clone(); @@ -177,8 +177,9 @@ public override void Setup() { bestTrail = createFirstTrail(speedrunner); }; - if (CvInitialSpeedrunTime.Value > 30) - Timers[CvInitialSpeedrunTime.Value + CvFirstRoundFreeze.Value - 30] += () + if (CV_INITIAL_SPEEDRUN_TIME.Value > 30) + Timers[ + CV_INITIAL_SPEEDRUN_TIME.Value + CV_FIRST_ROUND_FREEZE.Value - 30] += () => { if (target != null) return; if (!speedrunner.IsValid || speedrunner.Connected @@ -190,15 +191,16 @@ public override void Setup() { return; } - msg.RuntimeLeft(RoundUtil.GetTimeRemaining()).ToChat(speedrunner); + Msg.RuntimeLeft(RoundUtil.GetTimeRemaining()).ToChat(speedrunner); }; - Timers[CvInitialSpeedrunTime.Value + CvFirstRoundFreeze.Value - 10] += () - => { - if (target != null) return; - msg.RuntimeLeft(RoundUtil.GetTimeRemaining()).ToChat(speedrunner); - }; - Timers[CvInitialSpeedrunTime.Value + CvFirstRoundFreeze.Value] += Execute; + Timers[CV_INITIAL_SPEEDRUN_TIME.Value + CV_FIRST_ROUND_FREEZE.Value - 10] += + () => { + if (target != null) return; + Msg.RuntimeLeft(RoundUtil.GetTimeRemaining()).ToChat(speedrunner); + }; + Timers[CV_INITIAL_SPEEDRUN_TIME.Value + CV_FIRST_ROUND_FREEZE.Value] += + Execute; base.Setup(); } @@ -234,7 +236,7 @@ public override void Execute() { bestTime = timeSpent; - var minTime = CvInitialSpeedrunTime.Value * 0.5; + var minTime = CV_INITIAL_SPEEDRUN_TIME.Value * 0.5; startRound((int)Math.Ceiling(Math.Max(timeSpent * 1.1, minTime))); @@ -290,8 +292,8 @@ private ActivePlayerTrail createFirstTrail( furthest.Pawn.Value?.Teleport(end); furthest.SetColor(Color.DodgerBlue); - msg.RunnerAFKAndReassigned(furthest).ToAllChat(); - msg.YouAreRunner(RoundUtil.GetTimeRemaining()).ToChat(furthest); + Msg.RunnerAFKAndReassigned(furthest).ToAllChat(); + Msg.YouAreRunner(RoundUtil.GetTimeRemaining()).ToChat(furthest); trail.StartTracking(furthest); trail.DidntMoveTicks = 0; return; @@ -299,7 +301,7 @@ private ActivePlayerTrail createFirstTrail( if (trail.DidntMoveTicks < thresholdTicks) return; if (trail.DidntMoveTicks == thresholdTicks) - msg.StayStillToSpeedup.ToChat(trail.Player); + Msg.StayStillToSpeedup.ToChat(trail.Player); if (didntMoveSeconds % 2 == 0) RoundUtil.AddTimeRemaining(-1); if (RoundUtil.GetTimeRemaining() <= 0) Execute(); }; @@ -327,8 +329,8 @@ private ActivePlayerTrail createFirstTrail( speedrunner = nearest; nearest.Pawn.Value?.Teleport(end); nearest.SetColor(Color.DodgerBlue); - msg.RunnerLeftAndReassigned(nearest).ToAllChat(); - msg.YouAreRunner(RoundUtil.GetTimeRemaining()).ToChat(nearest); + Msg.RunnerLeftAndReassigned(nearest).ToAllChat(); + Msg.YouAreRunner(RoundUtil.GetTimeRemaining()).ToChat(nearest); trail.StartTracking(nearest); }; return trail; @@ -344,17 +346,17 @@ private ActivePlayerTrail createFirstTrail( private void startRound(int seconds) { roundStartTime = null; - if (!isRoundActive) { + if (!IsRoundActive) { panic("Round is not active but we are in startRound"); return; } var alive = PlayerUtil.GetAlive().ToArray(); playersAliveAtStart = PlayerUtil.GetAlive().Count(); - msg.BeginRound(++round, getEliminations(playersAliveAtStart), seconds) + Msg.BeginRound(++round, getEliminations(playersAliveAtStart), seconds) .ToAllChat(); - RoundUtil.SetTimeRemaining(seconds + CvFreezeTime.Value); + RoundUtil.SetTimeRemaining(seconds + CV_FREEZE_TIME.Value); foreach (var player in alive) { var pawn = player.PlayerPawn.Value; @@ -367,19 +369,19 @@ private void startRound(int seconds) { finishedPlayers.Clear(); finishTimestampList.Clear(); - Plugin.AddTimer(CvFreezeTime.Value, () => { - if (!isRoundActive) return; + Plugin.AddTimer(CV_FREEZE_TIME.Value, () => { + if (!IsRoundActive) return; foreach (var player in PlayerUtil.GetAlive()) player.UnFreeze(); roundStartTime = Server.CurrentTime; }, TimerFlags.STOP_ON_MAPCHANGE); - roundEndTimer = Plugin.AddTimer(seconds + CvFreezeTime.Value, endRound, + roundEndTimer = Plugin.AddTimer(seconds + CV_FREEZE_TIME.Value, endRound, TimerFlags.STOP_ON_MAPCHANGE); } private void checkFinishers() { if (target == null || roundStartTime == null) return; - if (!isRoundActive) { + if (!IsRoundActive) { panic("Round is not active but we are in checkFinishers"); return; } @@ -432,9 +434,9 @@ private void sendDistances(LinkedList<(int, float)> unfinished) { foreach (var (slot, dist) in unfinished) finishTimestampList.AddLast((slot, dist)); - const int TOTAL_LINES = 8; - var pos = 1; - var current = finishTimestampList.First; + const int totalLines = 8; + var pos = 1; + var current = finishTimestampList.First; string? top = null; while (current != null) { @@ -451,14 +453,14 @@ private void sendDistances(LinkedList<(int, float)> unfinished) { var playerLine = current; var d = 0; - while (playerLine != null && (display < TOTAL_LINES / 2 - || pos - d > finishTimestampList.Count - TOTAL_LINES - && display < TOTAL_LINES)) { + while (playerLine != null && (display < totalLines / 2 + || pos - d > finishTimestampList.Count - totalLines + && display < totalLines)) { var (slot, dist) = playerLine.Value; playerLine = playerLine.Previous; var p = Utilities.GetPlayerFromSlot(slot); if (p == null) continue; - lines = generateHTMLLine(p, pos - d++, dist) + (d == 1 ? "" : "
") + lines = generateHtmlLine(p, pos - d++, dist) + (d == 1 ? "" : "
") + lines; display++; } @@ -467,12 +469,12 @@ private void sendDistances(LinkedList<(int, float)> unfinished) { playerLine = current; d = 0; - while (playerLine != null && display < TOTAL_LINES) { + while (playerLine != null && display < totalLines) { var (slot, dist) = playerLine.Value; playerLine = playerLine.Next; var p = Utilities.GetPlayerFromSlot(slot); if (p == null) continue; - lines += "
" + generateHTMLLine(p, pos + ++d, dist); + lines += "
" + generateHtmlLine(p, pos + ++d, dist); display++; } @@ -488,7 +490,7 @@ private void sendDistances(LinkedList<(int, float)> unfinished) { finishTimestampList = originalCompletions; } - private string generateHTMLLine(CCSPlayerController player, int position, + private string generateHtmlLine(CCSPlayerController player, int position, float distance) { string color; var eliminations = getEliminations(playersAliveAtStart); @@ -541,10 +543,10 @@ private void onFinish(CCSPlayerController player) { if (bestTime == null || time < bestTime) { bestTime = time; bestTimePlayerSlot = player.Slot; - msg.BestTime(player, time).ToAllChat(); + Msg.BestTime(player, time).ToAllChat(); player.SetColor(Color.FromArgb(255, Color.Gold)); } else { - msg.PlayerTime(player, finishedPlayers.Count + 1, -time).ToAllChat(); + Msg.PlayerTime(player, finishedPlayers.Count + 1, -time).ToAllChat(); } finishTimestampList.AddLast((player.Slot, -Server.CurrentTime)); @@ -605,7 +607,7 @@ private void endRound() { return; } - if (!isRoundActive) { + if (!IsRoundActive) { panic("Round is not active but we are in endRound"); return; } @@ -642,7 +644,7 @@ private void endRound() { if (random != null && activeTrails.TryGetValue(random.Slot, out var randomTrail)) { - msg.ImpossibleLocation( + Msg.ImpossibleLocation( ctMade ? CsTeam.Terrorist : CsTeam.CounterTerrorist, random); bestTrail?.Kill(); @@ -657,7 +659,7 @@ private void endRound() { announceTimes(); - if (aliveCount <= CvMaxPlayersToFinish.Value) { + if (aliveCount <= CV_MAX_PLAYERS_TO_FINISH.Value) { if (finishTimestampList.Count == 0) { generics.Error("No slowest times found").ToAllChat(); return; @@ -678,29 +680,30 @@ private void endRound() { .Where(p => p.Slot != winner.Slot) .ToList(); - var timeToSet = CvWinTimeBase.Value + CvWinTimeBonus.Value * losers.Count; + var timeToSet = CV_WIN_TIME_BASE.Value + + CV_WIN_TIME_BONUS.Value * losers.Count; - msg.PlayerWon(winner).ToAllChat(); + Msg.PlayerWon(winner).ToAllChat(); foreach (var loser in losers) { loser.SetColor(Color.FromArgb(254, Color.White)); - if (CvTeleportType.Value == 1) + if (CV_TELEPORT_TYPE.Value == 1) loser.Teleport(winner); - else if (CvTeleportType.Value == 2) winner.Teleport(loser); - if (CvLoserDamageable.Value) EnableDamage(loser); + else if (CV_TELEPORT_TYPE.Value == 2) winner.Teleport(loser); + if (CV_LOSER_DAMAGEABLE.Value) EnableDamage(loser); } - if (CvWinnerDamageable.Value) EnableDamage(winner); + if (CV_WINNER_DAMAGEABLE.Value) EnableDamage(winner); - foreach (var weapon in CvLosersWeapon.Value.Split(',')) + foreach (var weapon in CV_LOSERS_WEAPONS.Value.Split(',')) foreach (var loser in losers) loser.GiveNamedItem(weapon); - foreach (var weapon in CvWinWeapon.Value.Split(',')) + foreach (var weapon in CV_WIN_WEAPONS.Value.Split(',')) winner.GiveNamedItem(weapon); Plugin.RemoveListener(checkFinishers); - RoundUtil.SetTimeRemaining(Math.Min(timeToSet, CvWinTimeMax.Value)); + RoundUtil.SetTimeRemaining(Math.Min(timeToSet, CV_WIN_TIME_MAX.Value)); Server.ExecuteCommand("mp_ignore_round_win_conditions 0"); return; } @@ -709,7 +712,7 @@ private void endRound() { var nextRoundTime = (int)Math.Ceiling((bestTime ?? 20) + 10 - round * 1.5); if (toEliminate <= 0) { - msg.NoneEliminated.ToAllChat(); + Msg.NoneEliminated.ToAllChat(); Plugin.AddTimer(3f, () => { startRound(nextRoundTime); }, TimerFlags.STOP_ON_MAPCHANGE); return; @@ -750,7 +753,7 @@ private void endRound() { if (player == null || !player.IsValid) continue; EnableDamage(player); player.CommitSuicide(false, true); - msg.PlayerEliminated(player).ToAllChat(); + Msg.PlayerEliminated(player).ToAllChat(); } Plugin.AddTimer(3f, () => { startRound(nextRoundTime); }, @@ -760,7 +763,7 @@ private void endRound() { private void eliminatePlayer(CCSPlayerController player) { EnableDamage(player); player.CommitSuicide(false, true); - msg.PlayerEliminated(player).ToAllChat(); + Msg.PlayerEliminated(player).ToAllChat(); } private void panic(string reason) { @@ -794,7 +797,7 @@ private void announceTimes() { var player = Utilities.GetPlayerFromSlot(slot); slowest = slowest.Previous; if (player == null) continue; - msg.PlayerTime(player, position--, dist).ToChat(player); + Msg.PlayerTime(player, position--, dist).ToChat(player); } } @@ -825,7 +828,7 @@ public SpeedrunSettings() { } public override Func RoundTime - => () => CvInitialSpeedrunTime.Value + CvFirstRoundFreeze.Value; + => () => CV_INITIAL_SPEEDRUN_TIME.Value + CV_FIRST_ROUND_FREEZE.Value; public override ISet AllowedWeapons(CCSPlayerController player) { // Return empty set to allow no weapons @@ -833,7 +836,7 @@ public override ISet AllowedWeapons(CCSPlayerController player) { } public override float FreezeTime(CCSPlayerController player) { - return CvFirstRoundFreeze.Value; + return CV_FIRST_ROUND_FREEZE.Value; } } } \ No newline at end of file diff --git a/mod/Jailbreak.Warden/Commands/WardenCommandsBehavior.cs b/mod/Jailbreak.Warden/Commands/WardenCommandsBehavior.cs index b0abd2de..e3cc2be5 100644 --- a/mod/Jailbreak.Warden/Commands/WardenCommandsBehavior.cs +++ b/mod/Jailbreak.Warden/Commands/WardenCommandsBehavior.cs @@ -10,12 +10,13 @@ using Jailbreak.Public.Behaviors; using Jailbreak.Public.Mod.Warden; using Jailbreak.Public.Utils; +using Jailbreak.Warden.Global; namespace Jailbreak.Warden.Commands; public class WardenCommandsBehavior(IWardenLocale locale, IWardenSelectionService queue, IWardenService warden, - IGenericCmdLocale generics, WardenConfig config) : IPluginBehavior { + IGenericCmdLocale generics) : IPluginBehavior { private readonly Dictionary lastPassCommand = new(); @@ -39,7 +40,7 @@ public void Command_Pass(CCSPlayerController? player, CommandInfo command) { // GetPlayers() returns valid players, no need to error check here. foreach (var clients in Utilities.GetPlayers()) clients.ExecuteClientCommand( - $"play sounds/{config.WardenPassedSoundName}"); + $"play sounds/{WardenBehavior.CV_WARDEN_SOUND_PASSED.Value}"); locale.BecomeNextWarden.ToAllChat(); @@ -71,7 +72,7 @@ public void Command_Fire(CCSPlayerController? player, CommandInfo command) { locale.FireWarden(warden.Warden).ToChat(client); client.ExecuteClientCommand( - $"play sounds/{config.WardenPassedSoundName}"); + $"play sounds/{WardenBehavior.CV_WARDEN_SOUND_PASSED.Value}"); } locale.BecomeNextWarden.ToAllChat(); diff --git a/mod/Jailbreak.Warden/Commands/WardenOpenCommandsBehavior.cs b/mod/Jailbreak.Warden/Commands/WardenOpenCommandsBehavior.cs index 5d9b050c..b7d815f3 100644 --- a/mod/Jailbreak.Warden/Commands/WardenOpenCommandsBehavior.cs +++ b/mod/Jailbreak.Warden/Commands/WardenOpenCommandsBehavior.cs @@ -17,7 +17,7 @@ namespace Jailbreak.Warden.Commands; public class WardenOpenCommandsBehavior(IWardenService warden, IWardenLocale msg, IWardenCmdOpenLocale wardenCmdOpenMsg, IZoneManager zoneManager) : IPluginBehavior, IWardenOpenCommand { - public static readonly FakeConVar CvOpenCommandCooldown = new( + public static readonly FakeConVar CV_OPEN_COMMAND_COOLDOWN = new( "css_jb_warden_open_cooldown", "Minimum seconds warden must wait before being able to open the cells.", 30, customValidators: new RangeValidator(0, 300)); @@ -40,8 +40,8 @@ public void Command_Open(CCSPlayerController? executor, CommandInfo info) { return; } - if (RoundUtil.GetTimeElapsed() < CvOpenCommandCooldown.Value) { - wardenCmdOpenMsg.CannotOpenYet(CvOpenCommandCooldown.Value) + if (RoundUtil.GetTimeElapsed() < CV_OPEN_COMMAND_COOLDOWN.Value) { + wardenCmdOpenMsg.CannotOpenYet(CV_OPEN_COMMAND_COOLDOWN.Value) .ToChat(executor); return; } @@ -56,9 +56,10 @@ public void Command_Open(CCSPlayerController? executor, CommandInfo info) { var result = MapUtil.OpenCells(zoneManager); IView message; if (result) { - if (executor != null && !warden.IsWarden(executor)) { + if (executor != null && !warden.IsWarden(executor)) message = wardenCmdOpenMsg.CellsOpenedBy(executor); - } else { message = wardenCmdOpenMsg.CellsOpenedBy(null); } + else + message = wardenCmdOpenMsg.CellsOpenedBy(null); } else { message = wardenCmdOpenMsg.OpeningFailed; } message.ToAllChat(); diff --git a/mod/Jailbreak.Warden/Global/WardenBehavior.cs b/mod/Jailbreak.Warden/Global/WardenBehavior.cs index bc19e38f..2b3b3a74 100644 --- a/mod/Jailbreak.Warden/Global/WardenBehavior.cs +++ b/mod/Jailbreak.Warden/Global/WardenBehavior.cs @@ -36,39 +36,54 @@ public struct PreWardenStats(int armorValue, int health, int maxHealth, public class WardenBehavior(ILogger logger, IWardenLocale locale, IRichLogService logs, ISpecialTreatmentService specialTreatment, IRebelService rebels, - WardenConfig config, IMuteService mute, IServiceProvider provider) + IMuteService mute, IServiceProvider provider) : IPluginBehavior, IWardenService { private readonly ISet bluePrisoners = new HashSet(); - public readonly FakeConVar CvArmorEqual = new("css_jb_hp_outnumbered", - "Health points for CTs have equal balance", 50, ConVarFlags.FCVAR_NONE, - new RangeValidator(1, 200)); + public static readonly FakeConVar CV_ARMOR_EQUAL = + new("css_jb_hp_outnumbered", "Health points for CTs have equal balance", 50, + ConVarFlags.FCVAR_NONE, new RangeValidator(1, 200)); - public readonly FakeConVar CvArmorOutnumber = new("css_jb_hp_outnumber", - "HP for CTs when outnumbering Ts", 25, ConVarFlags.FCVAR_NONE, - new RangeValidator(1, 200)); + public static readonly FakeConVar CV_ARMOR_OUTNUMBER = + new("css_jb_hp_outnumber", "HP for CTs when outnumbering Ts", 25, + ConVarFlags.FCVAR_NONE, new RangeValidator(1, 200)); - public readonly FakeConVar CvArmorOutnumbered = + public static readonly FakeConVar CV_ARMOR_OUTNUMBERED = new("css_jb_hp_outnumbered", "Health points for CTs when outnumbered by Ts", 100, ConVarFlags.FCVAR_NONE, new RangeValidator(1, 200)); - public readonly FakeConVar CvWardenArmor = new("css_jb_warden_armor", - "Armor for the warden", 125, ConVarFlags.FCVAR_NONE, - new RangeValidator(1, 200)); + public static readonly FakeConVar CV_WARDEN_ARMOR = + new("css_jb_warden_armor", "Armor for the warden", 125, + ConVarFlags.FCVAR_NONE, new RangeValidator(1, 200)); - public readonly FakeConVar CvWardenHealth = new("css_jb_warden_hp", - "HP for the warden", 125, ConVarFlags.FCVAR_NONE, - new RangeValidator(1, 200)); - - public readonly FakeConVar CvWardenMaxHealth = new("css_jb_warden_maxhp", - "Max HP for the warden", 100, ConVarFlags.FCVAR_NONE, - new RangeValidator(1, 200)); - - public readonly FakeConVar CvWardenAutoOpenCells = + public static readonly FakeConVar CV_WARDEN_AUTO_OPEN_CELLS = new("css_jb_warden_opencells_delay", "Delay in seconds to auto-open cells at, -1 to disable", 60); + public static readonly FakeConVar CV_WARDEN_HEALTH = + new("css_jb_warden_hp", "HP for the warden", 125, ConVarFlags.FCVAR_NONE, + new RangeValidator(1, 200)); + + public static readonly FakeConVar CV_WARDEN_MAX_HEALTH = + new("css_jb_warden_maxhp", "Max HP for the warden", 100, + ConVarFlags.FCVAR_NONE, new RangeValidator(1, 200)); + + public static readonly FakeConVar CV_WARDEN_SOUND_KILLED = + new("css_jb_warden_sound_killed", "Sound to play when the warden is killed", + "wardenKilled"); + + public static readonly FakeConVar CV_WARDEN_SOUND_PASSED = + new("css_jb_warden_sound_killed", "Sound to play when the warden passes", + "wardenPassed"); + + public static readonly FakeConVar CV_WARDEN_SOUND_NEW = + new("css_jb_warden_sound_killed", + "Sound to play when the warden is assigned", "wardenNew"); + + public static readonly FakeConVar CV_WARDEN_TERRORIST_RATIO = + new("css_jb_warden_t_ratio", "Ratio of T:CT to use for HP adjustments", 3); + private bool firstWarden; private string? oldTag; private char? oldTagColor; @@ -133,7 +148,7 @@ public bool TrySetWarden(CCSPlayerController controller) { } foreach (var player in Utilities.GetPlayers()) - player.ExecuteClientCommand($"play sounds/{config.WardenNewSoundName}"); + player.ExecuteClientCommand($"play sounds/{CV_WARDEN_SOUND_NEW.Value}"); logs.Append(logs.Player(Warden), "is now the warden."); @@ -157,10 +172,10 @@ public bool TrySetWarden(CCSPlayerController controller) { if (!hasHelmet) Warden.GiveNamedItem("item_assaultsuit"); var ctArmorValue = getBalance() switch { - 0 => CvArmorEqual.Value, // Balanced teams - 1 => CvArmorOutnumbered.Value, // Ts outnumber CTs - -1 => CvArmorOutnumber.Value, // CTs outnumber Ts - _ => CvArmorEqual.Value // default (should never happen) + 0 => CV_ARMOR_EQUAL.Value, // Balanced teams + 1 => CV_ARMOR_OUTNUMBERED.Value, // Ts outnumber CTs + -1 => CV_ARMOR_OUTNUMBER.Value, // CTs outnumber Ts + _ => CV_ARMOR_EQUAL.Value // default (should never happen) }; /* Round start CT buff */ @@ -173,8 +188,8 @@ public bool TrySetWarden(CCSPlayerController controller) { Utilities.SetStateChanged(guardPawn, "CCSPlayerPawn", "m_ArmorValue"); } - setWardenStats(wardenPawn, CvWardenArmor.Value, CvWardenHealth.Value, - CvWardenMaxHealth.Value); + setWardenStats(wardenPawn, CV_WARDEN_ARMOR.Value, CV_WARDEN_HEALTH.Value, + CV_WARDEN_MAX_HEALTH.Value); if (!hasHealthshot) Warden.GiveNamedItem("weapon_healthshot"); } else { preWardenStats = null; } @@ -282,7 +297,7 @@ private void processWardenDeath() { foreach (var player in Utilities.GetPlayers()) { if (!player.IsReal()) continue; player.ExecuteClientCommand( - $"play sounds/{config.WardenKilledSoundName}"); + $"play sounds/{CV_WARDEN_SOUND_KILLED.Value}"); } locale.BecomeNextWarden.ToAllChat(); @@ -333,7 +348,7 @@ private int getBalance() { var tCount = Utilities.GetPlayers().Count(p => p.Team == CsTeam.Terrorist); // Casting to a float ensures if we're diving by zero, we get infinity instead of an error. - var ratio = (float)tCount / config.TerroristRatio - ctCount; + var ratio = (float)tCount / CV_WARDEN_TERRORIST_RATIO.Value - ctCount; return ratio switch { > 0 => 1, @@ -403,14 +418,14 @@ public HookResult OnRoundStart(EventRoundStart ev, GameEventInfo info) { firstWarden = true; preWardenStats = null; - if (CvWardenAutoOpenCells.Value < 0 || RoundUtil.IsWarmup()) + if (CV_WARDEN_AUTO_OPEN_CELLS.Value < 0 || RoundUtil.IsWarmup()) return HookResult.Continue; var openCmd = provider.GetService(); if (openCmd == null) return HookResult.Continue; var cmdLocale = provider.GetRequiredService(); openCellsTimer?.Kill(); - openCellsTimer = parent.AddTimer(CvWardenAutoOpenCells.Value, () => { + openCellsTimer = parent.AddTimer(CV_WARDEN_AUTO_OPEN_CELLS.Value, () => { if (openCmd.OpenedCells) return; var zone = provider.GetService(); if (zone != null) @@ -436,7 +451,7 @@ public HookResult OnPlayerDisconnect(EventPlayerDisconnect ev, foreach (var player in Utilities.GetPlayers()) player.ExecuteClientCommand( - $"play sounds/{config.WardenPassedSoundName}"); + $"play sounds/{CV_WARDEN_SOUND_PASSED.Value}"); locale.BecomeNextWarden.ToAllChat(); return HookResult.Continue; diff --git a/mod/Jailbreak.Warden/Markers/WardenMarkerBehavior.cs b/mod/Jailbreak.Warden/Markers/WardenMarkerBehavior.cs index 2f46ddaf..7bc03cef 100644 --- a/mod/Jailbreak.Warden/Markers/WardenMarkerBehavior.cs +++ b/mod/Jailbreak.Warden/Markers/WardenMarkerBehavior.cs @@ -13,13 +13,13 @@ namespace Jailbreak.Warden.Markers; public class WardenMarkerBehavior(IWardenService warden) : IPluginBehavior { - public readonly FakeConVar CvMaxRadius = new( + public static readonly FakeConVar CV_MAX_RADIUS = new( "css_jb_warden_marker_max_radius", "Maximum radius for warden marker", 360); - public readonly FakeConVar CvMinRadius = new( + public static readonly FakeConVar CV_MIN_RADIUS = new( "css_jb_warden_marker_min_radius", "Minimum radius for warden marker", 60); - public readonly FakeConVar CvResizeTime = new( + public static readonly FakeConVar CV_RESIZE_TIME = new( "css_jb_warden_resize_time", "Milliseconds to wait for resizing marker", 800); @@ -30,7 +30,7 @@ public class WardenMarkerBehavior(IWardenService warden) : IPluginBehavior { private float radius; public void Start(BasePlugin basePlugin) { - marker = new BeamCircle(basePlugin, new Vector(), CvMinRadius.Value, + marker = new BeamCircle(basePlugin, new Vector(), CV_MIN_RADIUS.Value, (int)Math.PI * 15); basePlugin.AddCommandListener("player_ping", CommandListener_PlayerPing); } @@ -46,9 +46,9 @@ public HookResult OnPing(EventPlayerPing @event, GameEventInfo info) { var distance = currentPos.Distance(vec); var timeElapsed = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - placementTime; - if (timeElapsed < CvResizeTime.Value) { - if (distance <= CvMaxRadius.Value * 1.3) { - distance = Math.Clamp(distance, CvMinRadius.Value, CvMaxRadius.Value); + if (timeElapsed < CV_RESIZE_TIME.Value) { + if (distance <= CV_MAX_RADIUS.Value * 1.3) { + distance = Math.Clamp(distance, CV_MIN_RADIUS.Value, CV_MAX_RADIUS.Value); marker?.SetRadius(distance); marker?.Update(); radius = distance; @@ -60,7 +60,7 @@ public HookResult OnPing(EventPlayerPing @event, GameEventInfo info) { } } - radius = CvMinRadius.Value; + radius = CV_MIN_RADIUS.Value; currentPos = vec; placementTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); diff --git a/mod/Jailbreak.Warden/WardenConfig.cs b/mod/Jailbreak.Warden/WardenConfig.cs deleted file mode 100644 index ee680fd0..00000000 --- a/mod/Jailbreak.Warden/WardenConfig.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Jailbreak.Warden; - -public class WardenConfig { - public string WardenKilledSoundName { get; } = "wardenKilled"; - public string WardenPassedSoundName { get; } = "wardenPassed"; - public string WardenNewSoundName { get; } = "wardenNew"; - public int TerroristRatio { get; } = 3; -} \ No newline at end of file diff --git a/mod/Jailbreak.Warden/WardenServiceExtension.cs b/mod/Jailbreak.Warden/WardenServiceExtension.cs index 5f6fb1ff..07390ef3 100644 --- a/mod/Jailbreak.Warden/WardenServiceExtension.cs +++ b/mod/Jailbreak.Warden/WardenServiceExtension.cs @@ -13,13 +13,13 @@ namespace Jailbreak.Warden; public static class WardenServiceExtension { public static void AddJailbreakWarden( this IServiceCollection serviceCollection) { - serviceCollection.AddConfig("warden"); serviceCollection.AddPluginBehavior(); serviceCollection .AddPluginBehavior(); serviceCollection .AddPluginBehavior(); - serviceCollection.AddPluginBehavior(); + serviceCollection + .AddPluginBehavior(); serviceCollection.AddPluginBehavior(); serviceCollection.AddPluginBehavior(); diff --git a/mod/Jailbreak.Zones/SqlZoneManager.cs b/mod/Jailbreak.Zones/SqlZoneManager.cs index 0815cfea..21fbddc8 100644 --- a/mod/Jailbreak.Zones/SqlZoneManager.cs +++ b/mod/Jailbreak.Zones/SqlZoneManager.cs @@ -8,10 +8,10 @@ namespace Jailbreak.Zones; public class SqlZoneManager(IZoneFactory factory) : IZoneManager { - public static readonly FakeConVar CvSqlTable = new("css_jb_zonetable", + public static readonly FakeConVar CV_SQL_TABLE = new("css_jb_zonetable", "The table name for the zones", "cs2_jb_zones"); - public static readonly FakeConVar CvSqlConnectionString = + public static readonly FakeConVar CV_SQL_CONNECTION_STRING = new("css_jb_sqlconnection", "The connection string for the database", "", ConVarFlags.FCVAR_PROTECTED); @@ -22,7 +22,7 @@ public class SqlZoneManager(IZoneFactory factory) : IZoneManager { public void Start(BasePlugin basePlugin) { plugin = basePlugin; - CvSqlConnectionString.ValueChanged += async (_, _) => { + CV_SQL_CONNECTION_STRING.ValueChanged += async (_, _) => { await LoadZones(Server.MapName); }; @@ -56,7 +56,7 @@ public async Task DeleteZone(int zoneId, string map) { await conn.OpenAsync(); await using var cmd = conn.CreateCommand(); cmd.CommandText = $""" - DELETE FROM {CvSqlTable.Value.Trim('"')} + DELETE FROM {CV_SQL_TABLE.Value.Trim('"')} WHERE zoneid = @zoneid AND map = @map """; @@ -91,7 +91,7 @@ public async Task PushZoneWithID(IZone zone, ZoneType type, string map) { await conn.OpenAsync(); var insertPointCommand = $""" - INSERT INTO {CvSqlTable.Value.Trim('"')} (map, type, zoneid, pointid, X, Y, Z) + INSERT INTO {CV_SQL_TABLE.Value.Trim('"')} (map, type, zoneid, pointid, X, Y, Z) VALUES (@map, @type, @zoneid, @pointid, @X, @Y, @Z) """; var pointId = 0; @@ -160,7 +160,7 @@ private async Task createTable() { await conn.OpenAsync(); var cmdText = $""" - CREATE TABLE IF NOT EXISTS {CvSqlTable.Value.Trim('"')}( + CREATE TABLE IF NOT EXISTS {CV_SQL_TABLE.Value.Trim('"')}( zoneid INT NOT NULL, pointid INT NOT NULL, map VARCHAR(64) NOT NULL, @@ -188,7 +188,7 @@ private void OnMapStart(string mapname) { private MySqlCommand queryAllZones(MySqlConnection conn, string map, ZoneType type) { var cmdText = $""" - SELECT * FROM {CvSqlTable.Value.Trim('"')} + SELECT * FROM {CV_SQL_TABLE.Value.Trim('"')} WHERE map = '{map}' AND type = '{type}' ORDER BY zoneid, pointid DESC """; @@ -260,7 +260,7 @@ private void printNotClosedWarning(string map, int zoneId, int pointId, } private MySqlConnection? createConnection() { - var str = CvSqlConnectionString.Value.Trim('"'); + var str = CV_SQL_CONNECTION_STRING.Value.Trim('"'); return string.IsNullOrWhiteSpace(str) ? null : new MySqlConnection(str); } } \ No newline at end of file diff --git a/public/Jailbreak.Formatting/Views/Warden/IWardenCmdOpenLocale.cs b/public/Jailbreak.Formatting/Views/Warden/IWardenCmdOpenLocale.cs index 07ff0a6b..daf76bcd 100644 --- a/public/Jailbreak.Formatting/Views/Warden/IWardenCmdOpenLocale.cs +++ b/public/Jailbreak.Formatting/Views/Warden/IWardenCmdOpenLocale.cs @@ -5,19 +5,20 @@ namespace Jailbreak.Formatting.Views.Warden; public interface IWardenCmdOpenLocale { /// - /// The cells were auto-opened. + /// The cells were auto-opened. /// public IView CellsOpened { get; } + public IView OpeningFailed { get; } + public IView AlreadyOpened { get; } + /// - /// The cells were opened by the specified player. - /// If the player is null, the cells were opened by the warden. + /// The cells were opened by the specified player. + /// If the player is null, the cells were opened by the warden. /// /// /// public IView CellsOpenedBy(CCSPlayerController? player); - public IView OpeningFailed { get; } - public IView AlreadyOpened { get; } public IView CannotOpenYet(int seconds); } \ No newline at end of file diff --git a/public/Jailbreak.Public/Configuration/IConfigService.cs b/public/Jailbreak.Public/Configuration/IConfigService.cs deleted file mode 100644 index 9d1bca5e..00000000 --- a/public/Jailbreak.Public/Configuration/IConfigService.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Jailbreak.Public.Configuration; - -public interface IConfigService { - public const string CONFIG_PATH = "jailbreak.json"; - - /// - /// Get the configuration object with the provided name - /// - /// - /// If the configuration service would return the default value, fail instead. Loudly. - /// - /// - T Get(string path, bool failOnDefault = false) where T : class, new(); -} \ No newline at end of file diff --git a/public/Jailbreak.Public/Extensions/CollectionExtensions.cs b/public/Jailbreak.Public/Extensions/CollectionExtensions.cs index 5b78e4b9..25593960 100644 --- a/public/Jailbreak.Public/Extensions/CollectionExtensions.cs +++ b/public/Jailbreak.Public/Extensions/CollectionExtensions.cs @@ -1,13 +1,13 @@ namespace Jailbreak.Public.Extensions; public static class CollectionExtensions { - private static readonly Random Random = new(); + private static readonly Random RANDOM = new(); public static void Shuffle(this IList list) { var n = list.Count; while (n > 1) { n--; - var k = Random.Next(n + 1); + var k = RANDOM.Next(n + 1); (list[k], list[n]) = (list[n], list[k]); } } diff --git a/public/Jailbreak.Public/Extensions/ServiceCollectionExtensions.cs b/public/Jailbreak.Public/Extensions/ServiceCollectionExtensions.cs index 9fbd14cd..a22c30c0 100644 --- a/public/Jailbreak.Public/Extensions/ServiceCollectionExtensions.cs +++ b/public/Jailbreak.Public/Extensions/ServiceCollectionExtensions.cs @@ -1,5 +1,4 @@ using Jailbreak.Public.Behaviors; -using Jailbreak.Public.Configuration; using Microsoft.Extensions.DependencyInjection; namespace Jailbreak.Public.Extensions; @@ -44,24 +43,4 @@ public static void AddPluginBehavior( collection.AddTransient(provider => provider.GetRequiredService()); } - - /// - /// Add an object to be loaded from the configuration file - /// - /// - /// The section where the configuration object will be loaded from - /// The configuration object. Must auto-fill all default values! - [Obsolete( - "Conguration is up to each module, and should ideally be done through CVars")] - public static void AddConfig(this IServiceCollection collection, - string sectionName) where TConfig : class, new() { - // Get the object by resolving IConfigService - // and use the Get() method. - - // Not *really* important... but do we want to fail here or return default if section - // isn't available? - collection.AddTransient(provider => provider - .GetRequiredService() - .Get(sectionName)); - } } \ No newline at end of file diff --git a/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs b/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs index 18dcb513..49926d8f 100644 --- a/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs +++ b/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs @@ -48,6 +48,7 @@ public abstract class AbstractSpecialDay(BasePlugin plugin, /// know why you are not calling it. /// public virtual void Setup() { + Plugin.RegisterFakeConVars(this); Plugin.RegisterEventHandler(OnEnd); foreach (var entry in Settings.ConVarValues) { diff --git a/public/Jailbreak.Public/Utils/TeamUtil.cs b/public/Jailbreak.Public/Utils/TeamUtil.cs new file mode 100644 index 00000000..7c72e66d --- /dev/null +++ b/public/Jailbreak.Public/Utils/TeamUtil.cs @@ -0,0 +1,19 @@ +using CounterStrikeSharp.API.Modules.Utils; + +namespace Jailbreak.Public.Utils; + +public static class TeamUtil { + public static CsTeam? FromString(string team) { + return team.ToLower() switch { + "0" or "n" or "none" => CsTeam.None, + "1" or "s" or "spec" or "spectator" or "spectators" or "specs" => CsTeam + .Spectator, + "2" or "t" or "ts" or "terror" or "terrorist" or "terrorists" + or "prisoner" or "prisoners" => CsTeam.Terrorist, + "3" or "ct" or "cts" or "counter" or "counterterrorist" + or "counterterrorists" or "guard" + or "guards" => CsTeam.CounterTerrorist, + _ => null + }; + } +} \ No newline at end of file diff --git a/public/Jailbreak.Validator/ItemValidator.cs b/public/Jailbreak.Validator/ItemValidator.cs new file mode 100644 index 00000000..e6a73da9 --- /dev/null +++ b/public/Jailbreak.Validator/ItemValidator.cs @@ -0,0 +1,70 @@ +using CounterStrikeSharp.API.Modules.Cvars.Validators; + +namespace Jailbreak.Validator; + +public class ItemValidator( + ItemValidator.WeaponType type = ItemValidator.WeaponType.WEAPON + | ItemValidator.WeaponType.UTILITY, bool allowEmpty = true, + bool allowMultiple = false) : IValidator { + [Flags] + public enum WeaponType { + GRENADE, + UTILITY, + WEAPON, + SNIPERS, + RIFLES, + PISTOLS, + SHOTGUNS, + SMGS, + HEAVY, + GUNS + } + + public bool Validate(string value, out string? errorMessage) { + if (value.Contains(',') && !allowMultiple) { + errorMessage = "Value cannot contain multiple values"; + return false; + } + + if (string.IsNullOrWhiteSpace(value)) { + errorMessage = allowEmpty ? null : "weapon cannot be empty"; + return allowEmpty; + } + + foreach (var weapon in value.Split(',')) { + if (string.IsNullOrWhiteSpace(weapon)) { + if (!allowEmpty) { + errorMessage = allowEmpty ? null : "weapon cannot be empty"; + return allowEmpty; + } + + continue; + } + + errorMessage = $"invalid {nameof(type).ToLower()}: {weapon}"; + return Enum.GetValues() + .Where(t => (t & type) == type) + .Any(t => validateType(t, weapon)); + } + + errorMessage = null; + return true; + } + + private bool validateType(WeaponType current, string weapon) { + var result = current switch { + WeaponType.GRENADE => Tag.GRENADES.Contains(weapon), + WeaponType.UTILITY => Tag.UTILITY.Contains(weapon), + WeaponType.WEAPON => Tag.WEAPONS.Contains(weapon), + WeaponType.SNIPERS => Tag.SNIPERS.Contains(weapon), + WeaponType.RIFLES => Tag.RIFLES.Contains(weapon), + WeaponType.PISTOLS => Tag.PISTOLS.Contains(weapon), + WeaponType.SHOTGUNS => Tag.SHOTGUNS.Contains(weapon), + WeaponType.SMGS => Tag.SMGS.Contains(weapon), + WeaponType.HEAVY => Tag.HEAVY.Contains(weapon), + WeaponType.GUNS => Tag.GUNS.Contains(weapon), + _ => throw new ArgumentOutOfRangeException(nameof(weapon)) + }; + return result; + } +} \ No newline at end of file diff --git a/public/Jailbreak.Validator/NonZeroRangeValidator.cs b/public/Jailbreak.Validator/NonZeroRangeValidator.cs new file mode 100644 index 00000000..9b0d069b --- /dev/null +++ b/public/Jailbreak.Validator/NonZeroRangeValidator.cs @@ -0,0 +1,21 @@ +using CounterStrikeSharp.API.Modules.Cvars.Validators; + +namespace Jailbreak.Validator; + +public class NonZeroRangeValidator(T min, T max) + : IValidator where T : IComparable { + public bool Validate(T value, out string? errorMessage) { + if (value.Equals(default(T))) { + errorMessage = $"Value must be non-zero between {min} and {max}"; + return false; + } + + if (value.CompareTo(min) >= 0 && value.CompareTo(max) <= 0) { + errorMessage = null; + return true; + } + + errorMessage = $"Value must be between {min} and {max}"; + return false; + } +} \ No newline at end of file diff --git a/public/Jailbreak.Validator/TeamValidator.cs b/public/Jailbreak.Validator/TeamValidator.cs new file mode 100644 index 00000000..1de152a9 --- /dev/null +++ b/public/Jailbreak.Validator/TeamValidator.cs @@ -0,0 +1,25 @@ +using CounterStrikeSharp.API.Modules.Cvars.Validators; +using CounterStrikeSharp.API.Modules.Utils; +using Jailbreak.Public.Utils; + +namespace Jailbreak.Validator; + +public class TeamValidator(bool allowSpecs = true) : IValidator { + public bool Validate(string value, out string? errorMessage) { + errorMessage = null; + + var team = TeamUtil.FromString(value); + + if (team == null) { + errorMessage = $"Unknown team: \"{value}\""; + return false; + } + + if (team is CsTeam.None or CsTeam.Spectator && !allowSpecs) { + errorMessage = "Team must be CT or T"; + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/public/Jailbreak.Validator/WeaponValidator.cs b/public/Jailbreak.Validator/WeaponValidator.cs deleted file mode 100644 index edaf151e..00000000 --- a/public/Jailbreak.Validator/WeaponValidator.cs +++ /dev/null @@ -1,56 +0,0 @@ -using CounterStrikeSharp.API.Modules.Cvars.Validators; - -namespace Jailbreak.Validator; - -public class WeaponValidator( - WeaponValidator.WeaponType type = WeaponValidator.WeaponType.WEAPON, - bool allowEmpty = true, bool allowMultiple = false) : IValidator { - public enum WeaponType { - GRENADE, - UTILITY, - WEAPON, - SNIPERS, - RIFLES, - PISTOLS, - SHOTGUNS, - SMGS, - HEAVY - } - - public bool Validate(string value, out string? errorMessage) { - if (value.Contains(',') && !allowMultiple) { - errorMessage = "Value cannot contain multiple values"; - return false; - } - - if (string.IsNullOrWhiteSpace(value)) { - errorMessage = allowEmpty ? null : "weapon cannot be empty"; - return allowEmpty; - } - - foreach (var weapon in value.Split(',')) { - if (string.IsNullOrWhiteSpace(weapon)) { - errorMessage = allowEmpty ? null : "weapon cannot be empty"; - return allowEmpty; - } - - errorMessage = $"invalid {nameof(type).ToLower()}: {weapon}"; - var result = type switch { - WeaponType.GRENADE => Tag.GRENADES.Contains(weapon), - WeaponType.UTILITY => Tag.UTILITY.Contains(weapon), - WeaponType.WEAPON => Tag.WEAPONS.Contains(weapon), - WeaponType.SNIPERS => Tag.SNIPERS.Contains(weapon), - WeaponType.RIFLES => Tag.RIFLES.Contains(weapon), - WeaponType.PISTOLS => Tag.PISTOLS.Contains(weapon), - WeaponType.SHOTGUNS => Tag.SHOTGUNS.Contains(weapon), - WeaponType.SMGS => Tag.SMGS.Contains(weapon), - WeaponType.HEAVY => Tag.HEAVY.Contains(weapon), - _ => throw new ArgumentOutOfRangeException(nameof(weapon)) - }; - if (!result) return false; - } - - errorMessage = null; - return true; - } -} \ No newline at end of file diff --git a/src/Jailbreak/Config/ConfigService.cs b/src/Jailbreak/Config/ConfigService.cs deleted file mode 100644 index 60b572a1..00000000 --- a/src/Jailbreak/Config/ConfigService.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Nodes; -using CounterStrikeSharp.API; -using Jailbreak.Public.Configuration; -using Microsoft.Extensions.Logging; - -namespace Jailbreak.Config; - -/// -/// A service to load and parse configuration files. -/// -public class ConfigService : IConfigService { - private readonly ILogger logger; - - /// - /// Constructor - /// - /// - public ConfigService(ILogger logger) { this.logger = logger; } - - /// - /// - /// - /// - /// - /// - public T Get(string path, bool fail = false) where T : class, new() { - var jsonPath = - Path.Combine(Server.GameDirectory, IConfigService.CONFIG_PATH); - - if (!File.Exists(jsonPath)) - return fail(fail, "Config file does not exist"); - - var jsonText = File.ReadAllText(jsonPath); - - var jsonObject = JsonNode.Parse(jsonText); - if (jsonObject == null) - return fail(fail, $"Unable to parse configuration file at {jsonPath}"); - - var configObject = jsonObject[path]; - if (configObject == null) - return fail(fail, $"Unable to navigate to config section {path}"); - - var config = configObject.Deserialize(); - if (config == null) - return fail(fail, - $"Unable to deserialize ({configObject.ToJsonString()}) into {typeof(T).FullName}."); - - return config; - } - - // ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local - private T fail(bool fail, string message) where T : class, new() { - // We would be returning default. - // Check if caller wants us to cry and scream instead. - if (fail) throw new InvalidOperationException(message); - - logger.LogWarning( - "[Config] Tripped load fail state with message: {@Message}", message); - - return new T(); - } -} \ No newline at end of file diff --git a/src/Jailbreak/JailbreakServiceCollection.cs b/src/Jailbreak/JailbreakServiceCollection.cs index c7811e1c..90510926 100644 --- a/src/Jailbreak/JailbreakServiceCollection.cs +++ b/src/Jailbreak/JailbreakServiceCollection.cs @@ -1,5 +1,4 @@ using CounterStrikeSharp.API.Core; -using Jailbreak.Config; using Jailbreak.Debug; using Jailbreak.English.Generic; using Jailbreak.English.LastGuard; @@ -18,7 +17,6 @@ using Jailbreak.LastRequest; using Jailbreak.Logs; using Jailbreak.Mute; -using Jailbreak.Public.Configuration; using Jailbreak.Rebel; using Jailbreak.SpecialDay; using Jailbreak.Warden; @@ -52,7 +50,6 @@ public void ConfigureServices(IServiceCollection serviceCollection) { // Do we want to make this scoped? // Not sure how this will behave with multiple rounds and whatnot. - serviceCollection.AddTransient(); serviceCollection.AddJailbreakGeneric(); serviceCollection.AddJailbreakLogs(); serviceCollection.AddJailbreakRebel(); From dba8150b88472a04f060a209bbd20ebec86a2ebe Mon Sep 17 00:00:00 2001 From: MSWS Date: Tue, 27 Aug 2024 18:43:19 -0700 Subject: [PATCH 02/19] Fix WeaponType flag values --- public/Jailbreak.Validator/ItemValidator.cs | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/public/Jailbreak.Validator/ItemValidator.cs b/public/Jailbreak.Validator/ItemValidator.cs index e6a73da9..85414374 100644 --- a/public/Jailbreak.Validator/ItemValidator.cs +++ b/public/Jailbreak.Validator/ItemValidator.cs @@ -8,16 +8,16 @@ public class ItemValidator( bool allowMultiple = false) : IValidator { [Flags] public enum WeaponType { - GRENADE, - UTILITY, - WEAPON, - SNIPERS, - RIFLES, - PISTOLS, - SHOTGUNS, - SMGS, - HEAVY, - GUNS + GRENADE = 1, + UTILITY = 2, + WEAPON = 4, + SNIPERS = 8, + RIFLES = 16, + PISTOLS = 32, + SHOTGUNS = 64, + SMGS = 128, + HEAVY = 256, + GUNS = 512 } public bool Validate(string value, out string? errorMessage) { @@ -41,7 +41,7 @@ public bool Validate(string value, out string? errorMessage) { continue; } - errorMessage = $"invalid {nameof(type).ToLower()}: {weapon}"; + errorMessage = $"invalid {type.ToString()}: {weapon}"; return Enum.GetValues() .Where(t => (t & type) == type) .Any(t => validateType(t, weapon)); From 136ef360c18f4ace6266689d6cfc801c888c4d0f Mon Sep 17 00:00:00 2001 From: MSWS Date: Tue, 27 Aug 2024 18:43:59 -0700 Subject: [PATCH 03/19] Reduce speedrunner time to 30 --- mod/Jailbreak.SpecialDay/SpecialDays/SpeedrunDay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/SpeedrunDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/SpeedrunDay.cs index fc77de84..a1dc59bf 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/SpeedrunDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/SpeedrunDay.cs @@ -28,7 +28,7 @@ public class SpeedrunDay(BasePlugin plugin, IServiceProvider provider) public static readonly FakeConVar CV_INITIAL_SPEEDRUN_TIME = new("css_jb_speedrun_initial_time", - "Duration in seconds to grant the speedrunner", 40); + "Duration in seconds to grant the speedrunner", 30); public static readonly FakeConVar CV_FIRST_ROUND_FREEZE = new("css_jb_speedrun_first_round_freeze", From c2933c08d164472e2e083cb0111802df78ca4056 Mon Sep 17 00:00:00 2001 From: MSWS Date: Tue, 27 Aug 2024 18:49:40 -0700 Subject: [PATCH 04/19] Fix which team got speed during HNS --- mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs | 2 +- public/Jailbreak.Validator/ItemValidator.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs index 19f914fb..58351815 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs @@ -120,7 +120,7 @@ public override void Setup() { base.Setup(); - foreach (var player in PlayerUtil.FromTeam(SeekerTeam.Value)) + foreach (var player in PlayerUtil.FromTeam(HiderTeam.Value)) player.SetSpeed(2f); } diff --git a/public/Jailbreak.Validator/ItemValidator.cs b/public/Jailbreak.Validator/ItemValidator.cs index 85414374..708a04e2 100644 --- a/public/Jailbreak.Validator/ItemValidator.cs +++ b/public/Jailbreak.Validator/ItemValidator.cs @@ -43,7 +43,7 @@ public bool Validate(string value, out string? errorMessage) { errorMessage = $"invalid {type.ToString()}: {weapon}"; return Enum.GetValues() - .Where(t => (t & type) == type) + .Where(t => type.HasFlag(t)) .Any(t => validateType(t, weapon)); } From 3ff11de823a9a4605a417053ef1a79ed8487e7a9 Mon Sep 17 00:00:00 2001 From: MSWS Date: Tue, 27 Aug 2024 18:50:18 -0700 Subject: [PATCH 05/19] Fix hns message order --- mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs index 58351815..262662c6 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs @@ -112,8 +112,8 @@ public override void Setup() { for (var offset = 15; offset < CV_SEEK_TIME.Value; offset += 15) { var beginsIn = CV_SEEK_TIME.Value - offset; - Timers[CV_SEEK_TIME.Value - offset] += - () => Locale.BeginsIn(beginsIn).ToAllChat(); + Timers[CV_SEEK_TIME.Value] += () + => Locale.BeginsIn(CV_SEEK_TIME.Value - beginsIn).ToAllChat(); } Timers[CV_SEEK_TIME.Value] += Execute; From 750f62f5269ad5b392e4a4d91220694d55ad38e4 Mon Sep 17 00:00:00 2001 From: MSWS Date: Tue, 27 Aug 2024 18:56:15 -0700 Subject: [PATCH 06/19] Set proper teams speed --- .../SpecialDays/HideAndSeekDay.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs index 262662c6..6f0a016c 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs @@ -91,14 +91,14 @@ public override void Setup() { if (CV_SEEK_TIME.Value >= 10) Timers[10] += () => { - foreach (var ct in PlayerUtil.FromTeam(SeekerTeam.Value)) + foreach (var ct in PlayerUtil.FromTeam(HiderTeam.Value)) ct.SetSpeed(1.5f); Msg.DamageWarning(15).ToTeamChat(SeekerTeam.Value); }; if (CV_SEEK_TIME.Value >= 25) Timers[25] += () => { - foreach (var player in PlayerUtil.FromTeam(SeekerTeam.Value)) { + foreach (var player in PlayerUtil.FromTeam(HiderTeam.Value)) { player.SetSpeed(1.25f); EnableDamage(player); } @@ -106,14 +106,13 @@ public override void Setup() { if (CV_SEEK_TIME.Value >= 30) Timers[30] += () => { - foreach (var ct in PlayerUtil.FromTeam(SeekerTeam.Value)) + foreach (var ct in PlayerUtil.FromTeam(HiderTeam.Value)) ct.SetSpeed(1.1f); }; for (var offset = 15; offset < CV_SEEK_TIME.Value; offset += 15) { - var beginsIn = CV_SEEK_TIME.Value - offset; - Timers[CV_SEEK_TIME.Value] += () - => Locale.BeginsIn(CV_SEEK_TIME.Value - beginsIn).ToAllChat(); + var timeRemaining = CV_SEEK_TIME.Value - offset; + Timers[offset] += () => Locale.BeginsIn(timeRemaining).ToAllChat(); } Timers[CV_SEEK_TIME.Value] += Execute; @@ -140,7 +139,7 @@ public override void Execute() { if (armor != -1) player.SetArmor(armor); } - foreach (var ct in PlayerUtil.FromTeam(SeekerTeam.Value)) ct.SetSpeed(1); + foreach (var ct in PlayerUtil.FromTeam(HiderTeam.Value)) ct.SetSpeed(1); } public class HnsSettings : SpecialDaySettings { From e96dc013aa57ccadd6cea52f3275160b71a1e6ee Mon Sep 17 00:00:00 2001 From: MSWS Date: Tue, 27 Aug 2024 19:02:28 -0700 Subject: [PATCH 07/19] Use bitshift op for weapontype --- public/Jailbreak.Validator/ItemValidator.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/public/Jailbreak.Validator/ItemValidator.cs b/public/Jailbreak.Validator/ItemValidator.cs index 708a04e2..a0506b63 100644 --- a/public/Jailbreak.Validator/ItemValidator.cs +++ b/public/Jailbreak.Validator/ItemValidator.cs @@ -8,16 +8,16 @@ public class ItemValidator( bool allowMultiple = false) : IValidator { [Flags] public enum WeaponType { - GRENADE = 1, - UTILITY = 2, - WEAPON = 4, - SNIPERS = 8, - RIFLES = 16, - PISTOLS = 32, - SHOTGUNS = 64, - SMGS = 128, - HEAVY = 256, - GUNS = 512 + GRENADE = 1 << 0, // 1 + UTILITY = 1 << 1, // 2 + WEAPON = 1 << 2, // 4 + SNIPERS = 1 << 3, // 8 + RIFLES = 1 << 4, // 16 + PISTOLS = 1 << 5, // 32 + SHOTGUNS = 1 << 6, // 64 + SMGS = 1 << 7, // 128 + HEAVY = 1 << 8, // 256 + GUNS = 1 << 9 // 512 } public bool Validate(string value, out string? errorMessage) { From a0015ee9d082007c7e0f092e2a42260fdb31c640 Mon Sep 17 00:00:00 2001 From: Isaac Date: Tue, 27 Aug 2024 20:11:43 -0700 Subject: [PATCH 08/19] Smoke/24.08.27 (#292) * Include snipers in GUNS * Include snipers in GUNS * Switch to preventing pickups instead of listening ontick * Fix onTick case --- .../Mute/WardenPeaceLocale.cs | 1 - lang/Jailbreak.English/SpecialDay/SDLocale.cs | 4 +- .../SpecialDays/GunGameDay.cs | 9 +--- .../SpecialDays/InfectionDay.cs | 5 +- .../SpecialDays/NoScopeDay.cs | 16 +++++-- .../SpecialDays/OneInTheChamberDay.cs | 23 +++++++-- .../SpecialDays/SpeedrunDay.cs | 1 - mod/Jailbreak.Warden/Global/WardenBehavior.cs | 2 +- .../Mod/SpecialDay/AbstractSpecialDay.cs | 48 +++++++------------ .../Mod/SpecialDay/SpecialDaySettings.cs | 2 + public/Jailbreak.Tag/Tag.cs | 1 + 11 files changed, 59 insertions(+), 53 deletions(-) diff --git a/lang/Jailbreak.English/Mute/WardenPeaceLocale.cs b/lang/Jailbreak.English/Mute/WardenPeaceLocale.cs index da428ae9..7827257f 100644 --- a/lang/Jailbreak.English/Mute/WardenPeaceLocale.cs +++ b/lang/Jailbreak.English/Mute/WardenPeaceLocale.cs @@ -4,7 +4,6 @@ using Jailbreak.Formatting.Logistics; using Jailbreak.Formatting.Objects; using Jailbreak.Formatting.Views.Warden; -using Microsoft.Extensions.Primitives; namespace Jailbreak.English.Mute; diff --git a/lang/Jailbreak.English/SpecialDay/SDLocale.cs b/lang/Jailbreak.English/SpecialDay/SDLocale.cs index 09c9910f..69e1b91c 100644 --- a/lang/Jailbreak.English/SpecialDay/SDLocale.cs +++ b/lang/Jailbreak.English/SpecialDay/SDLocale.cs @@ -18,8 +18,8 @@ public class SDLocale : ISDLocale, ILanguage { public IView SpecialDayRunning(string name) { return new SimpleView { PREFIX, - ChatColors.DarkRed + name, - ChatColors.Red + "is currently running." + ChatColors.Grey + "The current special day is", + ChatColors.Gold + name }; } diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/GunGameDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/GunGameDay.cs index 7d07443c..f67b22fc 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/GunGameDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/GunGameDay.cs @@ -115,14 +115,7 @@ private HookResult OnDeath(EventPlayerDeath @event, GameEventInfo info) { if (!progressions.TryGetValue(player.Slot, out playerIndex)) playerIndex = 0; if (attacker == null || !attacker.IsValid) return HookResult.Continue; - if (attacker.Slot == player.Slot) { - if (playerIndex <= 0) return HookResult.Continue; - playerIndex--; - msg.DemotedDueToSuicide.ToChat(player); - progressions[player.Slot] = playerIndex; - - return HookResult.Continue; - } + if (attacker.Slot == player.Slot) return HookResult.Continue; var attackerProgress = progressions.TryGetValue(attacker.Slot, out var attackerIndex) ? diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/InfectionDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/InfectionDay.cs index 9b5e567e..cf5f5a6b 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/InfectionDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/InfectionDay.cs @@ -133,9 +133,8 @@ override protected HookResult public class InfectionSettings : SpecialDaySettings { public InfectionSettings() { - CtTeleport = TeleportType.ARMORY; - TTeleport = TeleportType.RANDOM; - RestrictWeapons = true; + CtTeleport = TeleportType.ARMORY; + TTeleport = TeleportType.RANDOM; WithRespawns(CsTeam.CounterTerrorist); } diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/NoScopeDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/NoScopeDay.cs index 0f1f34da..6f401815 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/NoScopeDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/NoScopeDay.cs @@ -60,10 +60,12 @@ public override void Execute() { player.GiveNamedItem(weapon); } + Plugin.RegisterListener(onTick); + base.Execute(); } - override protected void OnTick() { + private void onTick() { foreach (var player in PlayerUtil.GetAlive()) disableScope(player); } @@ -83,11 +85,17 @@ private void disableScope(CCSPlayerController player) { activeWeapon.NextPrimaryAttackTick = Server.TickCount + 500; } + override protected HookResult + OnEnd(EventRoundEnd @event, GameEventInfo info) { + var result = base.OnEnd(@event, info); + Plugin.RemoveListener(onTick); + return result; + } + private class NoScopeSettings : FFASettings { public NoScopeSettings() { - CtTeleport = TeleportType.RANDOM; - TTeleport = TeleportType.RANDOM; - RestrictWeapons = true; + CtTeleport = TeleportType.RANDOM; + TTeleport = TeleportType.RANDOM; ConVarValues["sv_gravity"] = CV_GRAVITY.Value; ConVarValues["sv_infinite_ammo"] = 2; diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs index 682ef3ab..610a28da 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs @@ -30,6 +30,8 @@ public override ISDInstanceLocale Locale "Additional (non-ammo restricted) weapons to give for the day", "weapon_knife", ConVarFlags.FCVAR_NONE, new ItemValidator()); + private bool started; + public override void Setup() { base.Setup(); Plugin.RegisterEventHandler(OnPlayerDamage); @@ -48,12 +50,28 @@ public override void Execute() { player.GetWeaponBase(CV_WEAPON.Value)?.SetAmmo(1, 0); } } + + started = true; + } + + override protected HookResult OnPickup(EventItemPickup @event, + GameEventInfo info) { + var result = base.OnPickup(@event, info); + if (!started) return result; + + var player = @event.Userid; + if (player == null || !player.IsValid) return result; + player.RemoveWeapons(); + player.SetHealth(1); + return result; } private HookResult OnPlayerDamage(EventPlayerHurt @event, GameEventInfo info) { if (@event.Userid == null || !@event.Userid.IsValid) return HookResult.Continue; + if (@event.Attacker == null || !@event.Attacker.IsValid) + return HookResult.Continue; @event.Userid?.SetHealth(0); return HookResult.Changed; } @@ -74,9 +92,8 @@ override protected HookResult public class OitcSettings : SpecialDaySettings { public OitcSettings() { - CtTeleport = TeleportType.RANDOM; - TTeleport = TeleportType.RANDOM; - RestrictWeapons = true; + CtTeleport = TeleportType.RANDOM; + TTeleport = TeleportType.RANDOM; WithFriendlyFire(); ConVarValues["mp_death_drop_gun"] = 0; diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/SpeedrunDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/SpeedrunDay.cs index a1dc59bf..0b6164dc 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/SpeedrunDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/SpeedrunDay.cs @@ -821,7 +821,6 @@ public SpeedrunSettings() { CtTeleport = TeleportType.RANDOM_STACKED; TTeleport = TeleportType.RANDOM_STACKED; StripToKnife = true; - RestrictWeapons = true; ConVarValues["mp_ignore_round_win_conditions"] = true; if (new Random().Next(5) == 0) WithAutoBhop(); WithFriendlyFire(); diff --git a/mod/Jailbreak.Warden/Global/WardenBehavior.cs b/mod/Jailbreak.Warden/Global/WardenBehavior.cs index 2b3b3a74..c7788dd2 100644 --- a/mod/Jailbreak.Warden/Global/WardenBehavior.cs +++ b/mod/Jailbreak.Warden/Global/WardenBehavior.cs @@ -152,7 +152,7 @@ public bool TrySetWarden(CCSPlayerController controller) { logs.Append(logs.Player(Warden), "is now the warden."); - unblueTimer = parent!.AddTimer(3, unmarkPrisonersBlue); + unblueTimer = parent.AddTimer(3, unmarkPrisonersBlue); mute.PeaceMute(firstWarden ? MuteReason.INITIAL_WARDEN : MuteReason.WARDEN_TAKEN); diff --git a/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs b/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs index 49926d8f..8597765b 100644 --- a/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs +++ b/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs @@ -50,6 +50,7 @@ public abstract class AbstractSpecialDay(BasePlugin plugin, public virtual void Setup() { Plugin.RegisterFakeConVars(this); Plugin.RegisterEventHandler(OnEnd); + Plugin.RegisterEventHandler(OnPickup); foreach (var entry in Settings.ConVarValues) { var cv = ConVar.Find(entry.Key); @@ -307,33 +308,7 @@ protected void SetConvarValue(ConVar? cvar, object value) { /// /// Called when the actual action begins for the special day. /// - public virtual void Execute() { - EnableDamage(); - if (Settings.RestrictWeapons) - Plugin.RegisterListener(OnTick); - } - - virtual protected void OnTick() { - foreach (var player in PlayerUtil.GetAlive()) { - var weapons = Settings.AllowedWeapons(player); - if (weapons == null) continue; - disableWeapon(player, weapons); - } - } - - private void disableWeapon(CCSPlayerController player, - ICollection allowed) { - 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; - if (allowed.Contains(activeWeapon.DesignerName)) return; - activeWeapon.NextSecondaryAttackTick = Server.TickCount + 500; - activeWeapon.NextPrimaryAttackTick = Server.TickCount + 500; - } + public virtual void Execute() { EnableDamage(); } virtual protected HookResult OnEnd(EventRoundEnd @event, GameEventInfo info) { foreach (var entry in previousConvarValues) { @@ -344,13 +319,26 @@ virtual protected HookResult OnEnd(EventRoundEnd @event, GameEventInfo info) { previousConvarValues.Clear(); - if (Settings.RestrictWeapons) - Plugin.RemoveListener(OnTick); - Plugin.DeregisterEventHandler(OnEnd); + Plugin.DeregisterEventHandler(OnPickup); return HookResult.Continue; } + virtual protected HookResult OnPickup(EventItemPickup @event, + GameEventInfo info) { + var player = @event.Userid; + if (player == null || !player.IsValid) return HookResult.Continue; + var allowed = Settings.AllowedWeapons(player); + var weapon = "weapon_" + @event.Item; + if (allowed == null || allowed.Contains(@event.Item)) + return HookResult.Continue; + player.RemoveItemByDesignerName(weapon, true); + return HookResult.Continue; + } + + [Obsolete("No longer used, you must manually register/unregister this")] + virtual protected void OnTick() { } + protected void DisableDamage() { foreach (var player in PlayerUtil.GetAlive()) DisableDamage(player); } diff --git a/public/Jailbreak.Public/Mod/SpecialDay/SpecialDaySettings.cs b/public/Jailbreak.Public/Mod/SpecialDay/SpecialDaySettings.cs index fdfa72b8..dbadcae0 100644 --- a/public/Jailbreak.Public/Mod/SpecialDay/SpecialDaySettings.cs +++ b/public/Jailbreak.Public/Mod/SpecialDay/SpecialDaySettings.cs @@ -56,6 +56,8 @@ public enum TeleportType { /// /// Used to avoid registring a costly OnTick listener if false /// + [Obsolete( + "With the new optimization, we now remove weapons if disallowed, making this obsolete.")] public bool RestrictWeapons = false; /// diff --git a/public/Jailbreak.Tag/Tag.cs b/public/Jailbreak.Tag/Tag.cs index 25254d19..3abffad6 100644 --- a/public/Jailbreak.Tag/Tag.cs +++ b/public/Jailbreak.Tag/Tag.cs @@ -53,6 +53,7 @@ public static class Tag { .Union(SHOTGUNS) .Union(SMGS) .Union(HEAVY) + .Union(SNIPERS) .ToHashSet(); public static readonly IReadOnlySet WEAPONS = From 8cb437a8b80011c07987cae8c72cbd5767c86a81 Mon Sep 17 00:00:00 2001 From: Isaac Date: Wed, 28 Aug 2024 00:17:58 -0700 Subject: [PATCH 09/19] Feat/rtd (#293) * Add RTD * Add noscope reward * Tidy up message * Auto Format --- Jailbreak.sln | 7 ++ lang/Jailbreak.English/RTD/RTDLocale.cs | 34 +++++++ .../LastRequestManager.cs | 13 +-- mod/Jailbreak.RTD/AutoRTDListener.cs | 21 +++++ mod/Jailbreak.RTD/Jailbreak.RTD.csproj | 14 +++ mod/Jailbreak.RTD/RTDCommand.cs | 68 ++++++++++++++ mod/Jailbreak.RTD/RTDRewarder.cs | 42 +++++++++ mod/Jailbreak.RTD/RTDServiceExtensions.cs | 15 ++++ mod/Jailbreak.RTD/RTDStatsCommand.cs | 28 ++++++ mod/Jailbreak.RTD/RewardGenerator.cs | 89 +++++++++++++++++++ mod/Jailbreak.RTD/Rewards/AmmoWeaponReward.cs | 24 +++++ mod/Jailbreak.RTD/Rewards/ArmorReward.cs | 15 ++++ mod/Jailbreak.RTD/Rewards/BombReward.cs | 25 ++++++ .../Rewards/CannotPickupReward.cs | 56 ++++++++++++ .../Rewards/CannotScopeReward.cs | 69 ++++++++++++++ mod/Jailbreak.RTD/Rewards/ColorReward.cs | 47 ++++++++++ mod/Jailbreak.RTD/Rewards/CreditReward.cs | 24 +++++ .../Rewards/GuaranteedWardenReward.cs | 23 +++++ mod/Jailbreak.RTD/Rewards/HPReward.cs | 15 ++++ mod/Jailbreak.RTD/Rewards/NoWeaponReward.cs | 14 +++ mod/Jailbreak.RTD/Rewards/NothingReward.cs | 10 +++ .../Rewards/RandomTeleportReward.cs | 25 ++++++ .../Rewards/TransparentReward.cs | 11 +++ mod/Jailbreak.RTD/Rewards/WeaponReward.cs | 33 +++++++ mod/Jailbreak.Rebel/C4Bomb/C4Behavior.cs | 32 ++++--- .../SpecialDays/AbstractZoneRestrictedDay.cs | 4 +- .../SpecialDays/GunGameDay.cs | 6 +- .../SpecialDays/HideAndSeekDay.cs | 15 ++-- .../SpecialDays/NoScopeDay.cs | 16 ++-- .../SpecialDays/OneInTheChamberDay.cs | 17 ++-- mod/Jailbreak.Warden/Global/WardenBehavior.cs | 6 +- .../Markers/WardenMarkerBehavior.cs | 3 +- .../Selection/WardenSelectionBehavior.cs | 12 +++ mod/Jailbreak.Zones/SqlZoneManager.cs | 4 +- .../Jailbreak.Formatting/Views/IRTDLocale.cs | 10 +++ .../Extensions/PlayerExtensions.cs | 1 + .../Extensions/WeaponExtensions.cs | 6 +- public/Jailbreak.Public/Mod/RTD/IRTDReward.cs | 33 +++++++ .../Jailbreak.Public/Mod/RTD/IRTDRewarder.cs | 42 +++++++++ .../Mod/RTD/IRewardGenerator.cs | 11 +++ .../Jailbreak.Public/Mod/Rebel/IC4Service.cs | 2 + .../Mod/SpecialDay/AbstractSpecialDay.cs | 61 +------------ .../Mod/Warden/IWardenSelectionService.cs | 8 ++ public/Jailbreak.Public/Utils/MapUtil.cs | 55 ++++++++++++ public/Jailbreak.Tag/WeaponType.cs | 52 +++++++++++ public/Jailbreak.Validator/ItemValidator.cs | 40 +-------- src/Jailbreak/Jailbreak.csproj | 1 + src/Jailbreak/JailbreakServiceCollection.cs | 4 + 48 files changed, 1018 insertions(+), 145 deletions(-) create mode 100644 lang/Jailbreak.English/RTD/RTDLocale.cs create mode 100644 mod/Jailbreak.RTD/AutoRTDListener.cs create mode 100644 mod/Jailbreak.RTD/Jailbreak.RTD.csproj create mode 100644 mod/Jailbreak.RTD/RTDCommand.cs create mode 100644 mod/Jailbreak.RTD/RTDRewarder.cs create mode 100644 mod/Jailbreak.RTD/RTDServiceExtensions.cs create mode 100644 mod/Jailbreak.RTD/RTDStatsCommand.cs create mode 100644 mod/Jailbreak.RTD/RewardGenerator.cs create mode 100644 mod/Jailbreak.RTD/Rewards/AmmoWeaponReward.cs create mode 100644 mod/Jailbreak.RTD/Rewards/ArmorReward.cs create mode 100644 mod/Jailbreak.RTD/Rewards/BombReward.cs create mode 100644 mod/Jailbreak.RTD/Rewards/CannotPickupReward.cs create mode 100644 mod/Jailbreak.RTD/Rewards/CannotScopeReward.cs create mode 100644 mod/Jailbreak.RTD/Rewards/ColorReward.cs create mode 100644 mod/Jailbreak.RTD/Rewards/CreditReward.cs create mode 100644 mod/Jailbreak.RTD/Rewards/GuaranteedWardenReward.cs create mode 100644 mod/Jailbreak.RTD/Rewards/HPReward.cs create mode 100644 mod/Jailbreak.RTD/Rewards/NoWeaponReward.cs create mode 100644 mod/Jailbreak.RTD/Rewards/NothingReward.cs create mode 100644 mod/Jailbreak.RTD/Rewards/RandomTeleportReward.cs create mode 100644 mod/Jailbreak.RTD/Rewards/TransparentReward.cs create mode 100644 mod/Jailbreak.RTD/Rewards/WeaponReward.cs create mode 100644 public/Jailbreak.Formatting/Views/IRTDLocale.cs create mode 100644 public/Jailbreak.Public/Mod/RTD/IRTDReward.cs create mode 100644 public/Jailbreak.Public/Mod/RTD/IRTDRewarder.cs create mode 100644 public/Jailbreak.Public/Mod/RTD/IRewardGenerator.cs create mode 100644 public/Jailbreak.Tag/WeaponType.cs diff --git a/Jailbreak.sln b/Jailbreak.sln index 698517b8..a4382dcf 100644 --- a/Jailbreak.sln +++ b/Jailbreak.sln @@ -42,6 +42,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jailbreak.Zones", "mod\Jail EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jailbreak.Trail", "mod\Jailbreak.Trail\Jailbreak.Trail.csproj", "{91F4EC7A-993A-4CA0-84C3-9F1100124A9C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jailbreak.RTD", "mod\Jailbreak.RTD\Jailbreak.RTD.csproj", "{C68D4760-7E1E-4633-995A-5EC1EF40E63B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -116,6 +118,10 @@ Global {91F4EC7A-993A-4CA0-84C3-9F1100124A9C}.Debug|Any CPU.Build.0 = Debug|Any CPU {91F4EC7A-993A-4CA0-84C3-9F1100124A9C}.Release|Any CPU.ActiveCfg = Release|Any CPU {91F4EC7A-993A-4CA0-84C3-9F1100124A9C}.Release|Any CPU.Build.0 = Release|Any CPU + {C68D4760-7E1E-4633-995A-5EC1EF40E63B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C68D4760-7E1E-4633-995A-5EC1EF40E63B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C68D4760-7E1E-4633-995A-5EC1EF40E63B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C68D4760-7E1E-4633-995A-5EC1EF40E63B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {9135CCC9-66C5-4A9C-AE3C-91475B5F0437} = {177DA48D-8306-4102-918D-992569878581} @@ -135,5 +141,6 @@ Global {A6249693-5B7E-4E14-A675-C292914F10F3} = {36BA84C0-291C-4930-A7C6-97CDF8F7F0D7} {C93A626A-BB44-4309-8DAD-4B28B2941870} = {36BA84C0-291C-4930-A7C6-97CDF8F7F0D7} {91F4EC7A-993A-4CA0-84C3-9F1100124A9C} = {36BA84C0-291C-4930-A7C6-97CDF8F7F0D7} + {C68D4760-7E1E-4633-995A-5EC1EF40E63B} = {36BA84C0-291C-4930-A7C6-97CDF8F7F0D7} EndGlobalSection EndGlobal diff --git a/lang/Jailbreak.English/RTD/RTDLocale.cs b/lang/Jailbreak.English/RTD/RTDLocale.cs new file mode 100644 index 00000000..3ff21b65 --- /dev/null +++ b/lang/Jailbreak.English/RTD/RTDLocale.cs @@ -0,0 +1,34 @@ +using CounterStrikeSharp.API.Modules.Utils; +using Jailbreak.Formatting.Base; +using Jailbreak.Formatting.Logistics; +using Jailbreak.Formatting.Views; +using Jailbreak.Public.Mod.RTD; + +namespace Jailbreak.English.RTD; + +public class RTDLocale : IRTDLocale, ILanguage { + public static readonly string PREFIX = + $" {ChatColors.Purple}[{ChatColors.LightPurple}RTD{ChatColors.Purple}]"; + + public IView RewardSelected(IRTDReward reward) { + return new SimpleView { + { PREFIX, "You rolled ", reward.Name + "." }, + SimpleView.NEWLINE, + { PREFIX, reward.Description } + }; + } + + public IView AlreadyRolled(IRTDReward reward) { + return new SimpleView { + PREFIX, + ChatColors.Red + "You already rolled " + ChatColors.DarkRed + reward.Name + + ChatColors.Red + "." + }; + } + + public IView CannotRollYet() { + return new SimpleView { + PREFIX, "You can only roll once the round ends or you die." + }; + } +} \ No newline at end of file diff --git a/mod/Jailbreak.LastRequest/LastRequestManager.cs b/mod/Jailbreak.LastRequest/LastRequestManager.cs index f2dfb250..492d31fb 100644 --- a/mod/Jailbreak.LastRequest/LastRequestManager.cs +++ b/mod/Jailbreak.LastRequest/LastRequestManager.cs @@ -20,11 +20,13 @@ namespace Jailbreak.LastRequest; public class LastRequestManager(ILRLocale messages, IServiceProvider provider) : ILastRequestManager, IDamageBlocker { - public static readonly FakeConVar CV_LR_BASE_TIME = new("css_jb_lr_time_base", - "Round time to set when LR is activated, 0 to disable", 60); + public static readonly FakeConVar CV_LR_BASE_TIME = + new("css_jb_lr_time_base", + "Round time to set when LR is activated, 0 to disable", 60); - public static readonly FakeConVar CV_LR_BONUS_TIME = new("css_jb_lr_time_per_lr", - "Additional round time to add per LR completion", 30); + public static readonly FakeConVar CV_LR_BONUS_TIME = + new("css_jb_lr_time_per_lr", + "Additional round time to add per LR completion", 30); public static readonly FakeConVar CV_LR_GUARD_TIME = new("css_jb_lr_time_per_guard", "Additional round time to add per guard"); @@ -92,7 +94,8 @@ public void EnableLR(CCSPlayerController? died = null) { var cts = Utilities.GetPlayers() .Count(p => p is { Team: CsTeam.CounterTerrorist, PawnIsAlive: true }); - if (CV_LR_BASE_TIME.Value != 0) RoundUtil.SetTimeRemaining(CV_LR_BASE_TIME.Value); + if (CV_LR_BASE_TIME.Value != 0) + RoundUtil.SetTimeRemaining(CV_LR_BASE_TIME.Value); RoundUtil.AddTimeRemaining(CV_LR_GUARD_TIME.Value * cts); diff --git a/mod/Jailbreak.RTD/AutoRTDListener.cs b/mod/Jailbreak.RTD/AutoRTDListener.cs new file mode 100644 index 00000000..f0194129 --- /dev/null +++ b/mod/Jailbreak.RTD/AutoRTDListener.cs @@ -0,0 +1,21 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core.Attributes.Registration; +using CounterStrikeSharp.API.Modules.Admin; +using Jailbreak.Public.Behaviors; +using Jailbreak.Public.Mod.RTD; + +namespace Jailbreak.RTD; + +public class AutoRTDListener(IRTDRewarder rewarder) : IPluginBehavior { + [GameEventHandler] + public HookResult OnRoundEnd(EventRoundEnd @event, GameEventInfo info) { + foreach (var player in Utilities.GetPlayers() + .Where(player + => AdminManager.PlayerHasPermissions(player, "@ego/dssilver")) + .Where(player => !rewarder.HasReward(player))) + player.ExecuteClientCommandFromServer("css_rtd"); + + return HookResult.Continue; + } +} \ No newline at end of file diff --git a/mod/Jailbreak.RTD/Jailbreak.RTD.csproj b/mod/Jailbreak.RTD/Jailbreak.RTD.csproj new file mode 100644 index 00000000..f430fd60 --- /dev/null +++ b/mod/Jailbreak.RTD/Jailbreak.RTD.csproj @@ -0,0 +1,14 @@ + + + + net8.0 + enable + enable + + + + + + + + diff --git a/mod/Jailbreak.RTD/RTDCommand.cs b/mod/Jailbreak.RTD/RTDCommand.cs new file mode 100644 index 00000000..27ca57f2 --- /dev/null +++ b/mod/Jailbreak.RTD/RTDCommand.cs @@ -0,0 +1,68 @@ +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core.Attributes.Registration; +using CounterStrikeSharp.API.Modules.Admin; +using CounterStrikeSharp.API.Modules.Commands; +using Jailbreak.Formatting.Extensions; +using Jailbreak.Formatting.Views; +using Jailbreak.Public.Behaviors; +using Jailbreak.Public.Mod.RTD; + +namespace Jailbreak.RTD; + +public class RTDCommand(IRTDRewarder rewarder, IRewardGenerator generator, + IRTDLocale locale, IGenericCmdLocale generic) : IPluginBehavior { + private bool inBetweenRounds; + + [ConsoleCommand("css_rtd", "Roll the dice!")] + public void Command_RTD(CCSPlayerController? executor, CommandInfo info) { + if (executor == null) return; + var bypass = AdminManager.PlayerHasPermissions(executor, "@css/root") + && info.ArgCount == 2; + + var old = rewarder.GetReward(executor); + if (!bypass && old != null) { + locale.AlreadyRolled(old).ToChat(executor); + return; + } + + if (!bypass && !inBetweenRounds && executor.PawnIsAlive) { + locale.CannotRollYet().ToChat(executor); + return; + } + + var reward = generator.GenerateReward(executor); + if (bypass) { + if (!int.TryParse(info.GetArg(1), out var slot)) { + generic.InvalidParameter(info.GetArg(1), "integer").ToChat(executor); + return; + } + + if (slot != -1) { + var rewards = generator.ToList(); + + if (slot < 0 || slot >= rewards.Count) { + generic.InvalidParameter(info.GetArg(1), "0-" + (rewards.Count - 1)) + .ToChat(executor); + return; + } + + reward = generator.ToList()[slot].Item1; + } + } + + rewarder.SetReward(executor, reward); + locale.RewardSelected(reward).ToChat(executor); + } + + [GameEventHandler] + public HookResult OnEnd(EventRoundEnd @event, GameEventInfo info) { + inBetweenRounds = true; + return HookResult.Continue; + } + + [GameEventHandler] + public HookResult OnStart(EventRoundStart @event, GameEventInfo info) { + inBetweenRounds = false; + return HookResult.Continue; + } +} \ No newline at end of file diff --git a/mod/Jailbreak.RTD/RTDRewarder.cs b/mod/Jailbreak.RTD/RTDRewarder.cs new file mode 100644 index 00000000..f9fe5ce9 --- /dev/null +++ b/mod/Jailbreak.RTD/RTDRewarder.cs @@ -0,0 +1,42 @@ +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core.Attributes.Registration; +using Jailbreak.Formatting.Views; +using Jailbreak.Formatting.Views.Logging; +using Jailbreak.Public.Behaviors; +using Jailbreak.Public.Mod.RTD; +using Jailbreak.Public.Utils; + +namespace Jailbreak.RTD; + +public class RTDRewarder(IRichLogService logs, IRTDLocale locale) + : IRTDRewarder, IPluginBehavior { + private readonly Dictionary rewards = new(); + + public bool HasReward(int id) { return GetReward(id) != null; } + + public IRTDReward? GetReward(int id) { + return rewards.TryGetValue(id, out var reward) ? reward : null; + } + + public bool SetReward(int id, IRTDReward reward) { + if (!reward.PrepareReward(id)) return false; + rewards[id] = reward; + return true; + } + + [GameEventHandler] + public HookResult OnStart(EventRoundStart @event, GameEventInfo info) { + foreach (var player in PlayerUtil.GetAlive()) { + var id = player.UserId ?? -1; + + var reward = GetReward(id); + if (reward == null) continue; + + logs.Append("Granted", reward.Name, "to", logs.Player(player)); + reward.GrantReward(id); + } + + rewards.Clear(); + return HookResult.Continue; + } +} \ No newline at end of file diff --git a/mod/Jailbreak.RTD/RTDServiceExtensions.cs b/mod/Jailbreak.RTD/RTDServiceExtensions.cs new file mode 100644 index 00000000..6e811be7 --- /dev/null +++ b/mod/Jailbreak.RTD/RTDServiceExtensions.cs @@ -0,0 +1,15 @@ +using Jailbreak.Public.Extensions; +using Jailbreak.Public.Mod.RTD; +using Microsoft.Extensions.DependencyInjection; + +namespace Jailbreak.RTD; + +public static class RTDServiceExtensions { + public static void AddDiceRoll(this IServiceCollection collection) { + collection.AddPluginBehavior(); + collection.AddPluginBehavior(); + collection.AddPluginBehavior(); + collection.AddPluginBehavior(); + collection.AddPluginBehavior(); + } +} \ No newline at end of file diff --git a/mod/Jailbreak.RTD/RTDStatsCommand.cs b/mod/Jailbreak.RTD/RTDStatsCommand.cs new file mode 100644 index 00000000..618dd184 --- /dev/null +++ b/mod/Jailbreak.RTD/RTDStatsCommand.cs @@ -0,0 +1,28 @@ +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core.Attributes.Registration; +using CounterStrikeSharp.API.Modules.Commands; +using CounterStrikeSharp.API.Modules.Utils; +using Jailbreak.Public.Behaviors; +using Jailbreak.Public.Mod.RTD; + +namespace Jailbreak.RTD; + +public class RTDStatsCommand(IRewardGenerator generator) : IPluginBehavior { + [ConsoleCommand("css_rtdstats", "View stats and probabilities of the die")] + public void + Command_RTDStats(CCSPlayerController? executor, CommandInfo info) { + if (executor == null) return; + var total = generator.Sum(r => r.Item2); + + var rewards = generator.ToList(); + rewards.Sort((a, b) => a.Item2.CompareTo(b.Item2)); + + var index = 0; + foreach (var (reward, prob) in rewards) { + var name = reward.Name; + var percent = prob / total * 100; + executor.PrintToChat( + $"{ChatColors.Orange}{index++}. {ChatColors.LightBlue}{name}{ChatColors.Grey}: {ChatColors.Yellow}{percent:0.00}%"); + } + } +} \ No newline at end of file diff --git a/mod/Jailbreak.RTD/RewardGenerator.cs b/mod/Jailbreak.RTD/RewardGenerator.cs new file mode 100644 index 00000000..33d6fe45 --- /dev/null +++ b/mod/Jailbreak.RTD/RewardGenerator.cs @@ -0,0 +1,89 @@ +using System.Collections; +using System.Drawing; +using CounterStrikeSharp.API.Core; +using Jailbreak.Public.Behaviors; +using Jailbreak.Public.Mod.Rebel; +using Jailbreak.Public.Mod.RTD; +using Jailbreak.Public.Mod.Zones; +using Jailbreak.RTD.Rewards; + +namespace Jailbreak.RTD; + +public class RewardGenerator(IZoneManager mgr, IC4Service bomb) + : IPluginBehavior, IRewardGenerator { + private static readonly float PROB_LOTTERY = 1 / 5000f; + private static readonly float PROB_EXTREMELY_LOW = 1 / 1000f; + private static readonly float PROB_VERY_LOW = 1 / 100f; + private static readonly float PROB_LOW = 1 / 20f; + private static readonly float PROB_MEDIUM = 1 / 10f; + private static readonly float PROB_OFTEN = 1 / 5f; + private static readonly float PROB_VERY_OFTEN = 1 / 2f; + + private readonly List<(IRTDReward, float)> rewards = [ + (new NothingReward(), PROB_OFTEN), + (new WeaponReward("weapon_healthshot"), PROB_OFTEN), + (new WeaponReward("weapon_decoy"), PROB_OFTEN), + (new CreditReward(1), PROB_MEDIUM), (new CreditReward(2), PROB_MEDIUM), + (new CreditReward(3), PROB_MEDIUM), + (new WeaponReward("weapon_flashbang"), PROB_MEDIUM), + (new WeaponReward("weapon_hegrenade"), PROB_MEDIUM), + (new WeaponReward("weapon_smokegrenade"), PROB_MEDIUM), + (new WeaponReward("weapon_molotov"), PROB_MEDIUM), + (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), 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), + (new NoWeaponReward(), PROB_VERY_LOW), + (new AmmoWeaponReward("weapon_deagle", 1, 0), PROB_VERY_LOW), + (new RandomTeleportReward(mgr), PROB_VERY_LOW), + (new BombReward(bomb), PROB_VERY_LOW), + (new AmmoWeaponReward("weapon_awp", 1, 0), PROB_EXTREMELY_LOW) + ]; + + private readonly Random rng = new(); + + private float totalWeight + => rewards.Where(r => r.Item1.Enabled).Select(s => s.Item2).Sum(); + + public void Start(BasePlugin basePlugin) { + rewards.Add((new CannotPickupReward(basePlugin, WeaponType.GRENADE), + 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)); + rewards.Add((new CannotPickupReward(basePlugin, WeaponType.PISTOLS), + PROB_VERY_LOW)); + rewards.Add((new CannotPickupReward(basePlugin, WeaponType.SNIPERS), + PROB_VERY_LOW)); + rewards.Add((new CannotPickupReward(basePlugin, WeaponType.HEAVY), + PROB_VERY_LOW)); + rewards.Add((new CannotPickupReward(basePlugin, WeaponType.RIFLES), + PROB_EXTREMELY_LOW)); + } + + 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; + } + + throw new InvalidOperationException("No reward was generated."); + } + + public IEnumerator<(IRTDReward, float)> GetEnumerator() { + return rewards.Where(r => r.Item1.Enabled).GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } + public int Count => rewards.Count(r => r.Item1.Enabled); +} \ No newline at end of file diff --git a/mod/Jailbreak.RTD/Rewards/AmmoWeaponReward.cs b/mod/Jailbreak.RTD/Rewards/AmmoWeaponReward.cs new file mode 100644 index 00000000..f961b291 --- /dev/null +++ b/mod/Jailbreak.RTD/Rewards/AmmoWeaponReward.cs @@ -0,0 +1,24 @@ +using System.Diagnostics; +using CounterStrikeSharp.API.Core; +using Jailbreak.Public.Extensions; + +namespace Jailbreak.RTD.Rewards; + +public class AmmoWeaponReward : WeaponReward { + private readonly int primary, secondary; + + public AmmoWeaponReward(string weapon, int primary, int secondary) : + base(weapon) { + Trace.Assert(Tag.GUNS.Contains(weapon)); + this.primary = primary; + this.secondary = secondary; + } + + public override bool GrantReward(CCSPlayerController player) { + var success = base.GrantReward(player); + if (!success) return false; + + player.GetWeaponBase(weapon).SetAmmo(primary, secondary); + return true; + } +} \ No newline at end of file diff --git a/mod/Jailbreak.RTD/Rewards/ArmorReward.cs b/mod/Jailbreak.RTD/Rewards/ArmorReward.cs new file mode 100644 index 00000000..c2e4413d --- /dev/null +++ b/mod/Jailbreak.RTD/Rewards/ArmorReward.cs @@ -0,0 +1,15 @@ +using CounterStrikeSharp.API.Core; +using Jailbreak.Public.Extensions; +using Jailbreak.Public.Mod.RTD; + +namespace Jailbreak.RTD.Rewards; + +public class ArmorReward(int armor) : IRTDReward { + public string Name => armor + " Armor"; + public string Description => "You won " + armor + " Armor next round."; + + public bool GrantReward(CCSPlayerController player) { + player.SetArmor(armor); + return true; + } +} \ No newline at end of file diff --git a/mod/Jailbreak.RTD/Rewards/BombReward.cs b/mod/Jailbreak.RTD/Rewards/BombReward.cs new file mode 100644 index 00000000..b005c93b --- /dev/null +++ b/mod/Jailbreak.RTD/Rewards/BombReward.cs @@ -0,0 +1,25 @@ +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Utils; +using Jailbreak.Public.Mod.Rebel; +using Jailbreak.Public.Mod.RTD; + +namespace Jailbreak.RTD.Rewards; + +public class BombReward(IC4Service bombService) : IRTDReward { + public string Name => "Bomb"; + public string Description => "You won the bomb next round."; + + public bool PrepareReward(int userid) { + bombService.DontGiveC4NextRound(); + return true; + } + + public bool CanGrantReward(CCSPlayerController player) { + return player.Team == CsTeam.Terrorist; + } + + public bool GrantReward(CCSPlayerController player) { + bombService.TryGiveC4ToPlayer(player); + return true; + } +} \ No newline at end of file diff --git a/mod/Jailbreak.RTD/Rewards/CannotPickupReward.cs b/mod/Jailbreak.RTD/Rewards/CannotPickupReward.cs new file mode 100644 index 00000000..9129cb27 --- /dev/null +++ b/mod/Jailbreak.RTD/Rewards/CannotPickupReward.cs @@ -0,0 +1,56 @@ +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 CannotPickupReward : IRTDReward { + private readonly HashSet blockedPlayerIDs = []; + private readonly ImmutableHashSet blockedWeapons; + private readonly BasePlugin plugin; + + public CannotPickupReward(BasePlugin plugin, WeaponType blocked) : this( + plugin, blocked.GetItems().ToArray()) { + Name = $"Cannot Pickup {blocked}"; + } + + public CannotPickupReward(BasePlugin plugin, params string[] weapons) { + this.plugin = plugin; + this.plugin.RegisterEventHandler(onPickup); + this.plugin.RegisterEventHandler(onRoundEnd); + + blockedWeapons = weapons.ToImmutableHashSet(); + Name = + $"Cannot Pickup {string.Join(", ", blockedWeapons.Select(s => s.GetFriendlyWeaponName()))}"; + } + + public string Name { get; } + + public string Description + => $"You will not be able to pickup {Name} next round."; + + public bool GrantReward(CCSPlayerController player) { + if (player.UserId == null) return false; + blockedPlayerIDs.Add(player.UserId.Value); + return true; + } + + private HookResult onRoundEnd(EventRoundEnd @event, GameEventInfo info) { + blockedPlayerIDs.Clear(); + return HookResult.Continue; + } + + private HookResult onPickup(EventItemPickup @event, GameEventInfo info) { + var player = @event.Userid; + if (player == null || !player.IsValid || player.UserId == null) + return HookResult.Continue; + if (!blockedPlayerIDs.Contains(player.UserId.Value)) + return HookResult.Continue; + var weapon = "weapon_" + @event.Item; + if (!blockedWeapons.Contains(weapon)) return HookResult.Continue; + player.RemoveItemByDesignerName(weapon, true); + return HookResult.Continue; + } +} \ No newline at end of file diff --git a/mod/Jailbreak.RTD/Rewards/CannotScopeReward.cs b/mod/Jailbreak.RTD/Rewards/CannotScopeReward.cs new file mode 100644 index 00000000..07f1cee1 --- /dev/null +++ b/mod/Jailbreak.RTD/Rewards/CannotScopeReward.cs @@ -0,0 +1,69 @@ +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 HashSet blockedPlayerIDs = []; + private readonly BasePlugin plugin; + + private bool registered; + + 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 scope next round."; + + 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 new file mode 100644 index 00000000..897e7e4f --- /dev/null +++ b/mod/Jailbreak.RTD/Rewards/ColorReward.cs @@ -0,0 +1,47 @@ +using System.Drawing; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Utils; +using Jailbreak.Public.Extensions; +using Jailbreak.Public.Mod.RTD; + +namespace Jailbreak.RTD.Rewards; + +public class ColorReward(Color color, bool prisonerOnly) : IRTDReward { + public string ColorName + => color.IsNamedColor ? + color.Name : + color.GetHue() switch { + 0 => "Red", + 60 => "Yellow", + 120 => "Green", + 180 => "Cyan", + 240 => "Blue", + 300 => "Magenta", + _ => "#" + color.ToArgb().ToString("X8") + }; + + public char ChatColor + => color.GetHue() switch { + 0 => ChatColors.Red, + 60 => ChatColors.Yellow, + 120 => ChatColors.Green, + 180 => ChatColors.LightBlue, + 240 => ChatColors.Blue, + 300 => ChatColors.Magenta, + _ => ChatColors.White + }; + + public virtual string Name => "Spawn " + ColorName; + + public virtual string Description + => $"You won spawning {ChatColor}{ColorName}{ChatColors.Grey} next round."; + + public bool CanGrantReward(CCSPlayerController player) { + return player.Team == CsTeam.Terrorist || !prisonerOnly; + } + + public bool GrantReward(CCSPlayerController player) { + player.SetColor(color); + return true; + } +} \ No newline at end of file diff --git a/mod/Jailbreak.RTD/Rewards/CreditReward.cs b/mod/Jailbreak.RTD/Rewards/CreditReward.cs new file mode 100644 index 00000000..327aaa80 --- /dev/null +++ b/mod/Jailbreak.RTD/Rewards/CreditReward.cs @@ -0,0 +1,24 @@ +using CounterStrikeSharp.API.Core; +using Jailbreak.Public.Mod.RTD; + +namespace Jailbreak.RTD.Rewards; + +public class CreditReward(int credits) : IRTDReward { + public string Name => credits + " Credit"; + + public string Description + => "You won " + credits + " credit" + (credits == 1 ? "" : "s") + + (credits > 500 ? "!" : "."); + + public bool Enabled => false; // TODO: Implement + + public bool PrepareReward(int userid) { + // TODO: When we do implement, set their credits here + return true; + } + + public bool GrantReward(CCSPlayerController player) { + // We would have already set their credits in PrepareReward, so do nothing here + return true; + } +} \ No newline at end of file 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/HPReward.cs b/mod/Jailbreak.RTD/Rewards/HPReward.cs new file mode 100644 index 00000000..bd2a8dd2 --- /dev/null +++ b/mod/Jailbreak.RTD/Rewards/HPReward.cs @@ -0,0 +1,15 @@ +using CounterStrikeSharp.API.Core; +using Jailbreak.Public.Extensions; +using Jailbreak.Public.Mod.RTD; + +namespace Jailbreak.RTD.Rewards; + +public class HPReward(int hp) : IRTDReward { + public string Name => hp + " HP"; + public string Description => "You won " + hp + " HP next round."; + + public bool GrantReward(CCSPlayerController player) { + player.SetHealth(hp); + return true; + } +} \ No newline at end of file diff --git a/mod/Jailbreak.RTD/Rewards/NoWeaponReward.cs b/mod/Jailbreak.RTD/Rewards/NoWeaponReward.cs new file mode 100644 index 00000000..b48b2f00 --- /dev/null +++ b/mod/Jailbreak.RTD/Rewards/NoWeaponReward.cs @@ -0,0 +1,14 @@ +using CounterStrikeSharp.API.Core; +using Jailbreak.Public.Mod.RTD; + +namespace Jailbreak.RTD.Rewards; + +public class NoWeaponReward : IRTDReward { + public string Name => "No Weapon"; + public string Description => "You will not spawn with a knife next round."; + + public bool GrantReward(CCSPlayerController player) { + player.RemoveWeapons(); + return true; + } +} \ No newline at end of file diff --git a/mod/Jailbreak.RTD/Rewards/NothingReward.cs b/mod/Jailbreak.RTD/Rewards/NothingReward.cs new file mode 100644 index 00000000..ff1aff1c --- /dev/null +++ b/mod/Jailbreak.RTD/Rewards/NothingReward.cs @@ -0,0 +1,10 @@ +using CounterStrikeSharp.API.Core; +using Jailbreak.Public.Mod.RTD; + +namespace Jailbreak.RTD.Rewards; + +public class NothingReward : IRTDReward { + public string Name => "Nothing"; + public string Description => "You won nothing."; + public bool GrantReward(CCSPlayerController 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 new file mode 100644 index 00000000..ef18125a --- /dev/null +++ b/mod/Jailbreak.RTD/Rewards/RandomTeleportReward.cs @@ -0,0 +1,25 @@ +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Utils; +using Jailbreak.Public.Mod.RTD; +using Jailbreak.Public.Mod.Zones; +using Jailbreak.Public.Utils; + +namespace Jailbreak.RTD.Rewards; + +public class RandomTeleportReward(IZoneManager zones) : IRTDReward { + public string Name => "Random Teleport"; + + 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; + player.Teleport(zone); + return true; + } +} \ No newline at end of file diff --git a/mod/Jailbreak.RTD/Rewards/TransparentReward.cs b/mod/Jailbreak.RTD/Rewards/TransparentReward.cs new file mode 100644 index 00000000..dfe54b7a --- /dev/null +++ b/mod/Jailbreak.RTD/Rewards/TransparentReward.cs @@ -0,0 +1,11 @@ +using System.Drawing; + +namespace Jailbreak.RTD.Rewards; + +public class TransparentReward() + : ColorReward(Color.FromArgb(128, 255, 255, 255), false) { + public override string Name => "Spawn Transparent"; + + public override string Description + => "You won spawning transparent next round."; +} \ No newline at end of file diff --git a/mod/Jailbreak.RTD/Rewards/WeaponReward.cs b/mod/Jailbreak.RTD/Rewards/WeaponReward.cs new file mode 100644 index 00000000..a4bbf1e4 --- /dev/null +++ b/mod/Jailbreak.RTD/Rewards/WeaponReward.cs @@ -0,0 +1,33 @@ +using System.Diagnostics; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Utils; +using Jailbreak.Public.Extensions; +using Jailbreak.Public.Mod.RTD; + +namespace Jailbreak.RTD.Rewards; + +public class WeaponReward : IRTDReward { + protected readonly string weapon; + + public WeaponReward(string weapon) { + this.weapon = weapon; + Trace.Assert(Tag.GUNS.Contains(weapon)); + } + + public string Name => weapon.GetFriendlyWeaponName(); + + public string Description + => "You won a" + + (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; + } +} \ No newline at end of file diff --git a/mod/Jailbreak.Rebel/C4Bomb/C4Behavior.cs b/mod/Jailbreak.Rebel/C4Bomb/C4Behavior.cs index 19e74d3c..0843c5ce 100644 --- a/mod/Jailbreak.Rebel/C4Bomb/C4Behavior.cs +++ b/mod/Jailbreak.Rebel/C4Bomb/C4Behavior.cs @@ -17,16 +17,6 @@ namespace Jailbreak.Rebel.C4Bomb; public class C4Behavior(IC4Locale ic4Locale, IRebelService rebelService) : IPluginBehavior, IC4Service { - private readonly Dictionary bombs = new(); - - // EmitSound(CBaseEntity* pEnt, const char* sSoundName, int nPitch, float flVolume, float flDelay) - private readonly MemoryFunctionVoid - // ReSharper disable once InconsistentNaming - CBaseEntity_EmitSoundParamsLinux = new( - "48 B8 ? ? ? ? ? ? ? ? 55 48 89 E5 41 55 41 54 49 89 FC 53 48 89 F3"); // LINUX ONLY. - - private BasePlugin? plugin; - public static readonly FakeConVar CV_GIVE_BOMB = new("css_jb_c4_give", "Whether to give a random prisoner a bomb at the beginning of the round.", true); @@ -43,6 +33,18 @@ private readonly MemoryFunctionVoid new("css_jb_c4_damage", "Base damage to apply", 340, ConVarFlags.FCVAR_NONE, new RangeValidator(0, 10000)); + private readonly Dictionary bombs = new(); + + // EmitSound(CBaseEntity* pEnt, const char* sSoundName, int nPitch, float flVolume, float flDelay) + private readonly MemoryFunctionVoid + // ReSharper disable once InconsistentNaming + CBaseEntity_EmitSoundParamsLinux = new( + "48 B8 ? ? ? ? ? ? ? ? 55 48 89 E5 41 55 41 54 49 89 FC 53 48 89 F3"); // LINUX ONLY. + + private bool giveNextRound = true; + + private BasePlugin? plugin; + public void ClearActiveC4s() { bombs.Clear(); } public void TryGiveC4ToPlayer(CCSPlayerController player) { @@ -90,6 +92,8 @@ public void TryGiveC4ToRandomTerrorist() { }); } + public void DontGiveC4NextRound() { giveNextRound = false; } + public void Start(BasePlugin basePlugin) { plugin = basePlugin; plugin.RegisterListener(playerUseC4ListenerCallback); @@ -120,7 +124,13 @@ private void playerUseC4ListenerCallback() { public HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info) { ClearActiveC4s(); - if (CV_GIVE_BOMB.Value) TryGiveC4ToRandomTerrorist(); + if (!CV_GIVE_BOMB.Value) return HookResult.Continue; + if (!giveNextRound) { + giveNextRound = true; + return HookResult.Continue; + } + + TryGiveC4ToRandomTerrorist(); return HookResult.Continue; } diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/AbstractZoneRestrictedDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/AbstractZoneRestrictedDay.cs index 57d7ef03..fbc4cb53 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/AbstractZoneRestrictedDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/AbstractZoneRestrictedDay.cs @@ -11,11 +11,11 @@ namespace Jailbreak.SpecialDay.SpecialDays; public abstract class AbstractZoneRestrictedDay : AbstractSpecialDay { - protected CsTeam RestrictedTeam; - protected readonly IList Restrictors = new List(); + protected CsTeam RestrictedTeam; + protected AbstractZoneRestrictedDay(BasePlugin plugin, IServiceProvider provider, CsTeam restrictedTeam = CsTeam.Terrorist) : base(plugin, provider) { diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/GunGameDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/GunGameDay.cs index f67b22fc..b768194a 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/GunGameDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/GunGameDay.cs @@ -7,7 +7,9 @@ using Jailbreak.Public.Extensions; using Jailbreak.Public.Mod.SpecialDay; using Jailbreak.Public.Mod.SpecialDay.Enums; +using Jailbreak.Public.Mod.Zones; using Jailbreak.Public.Utils; +using Microsoft.Extensions.DependencyInjection; namespace Jailbreak.SpecialDay.SpecialDays; @@ -57,8 +59,10 @@ public override void Setup() { Timers[10] += Execute; base.Setup(); + var mgr = Provider.GetService(); spawns = - new ShuffleBag(getAtLeastRandom(Utilities.GetPlayers().Count)); + new ShuffleBag( + MapUtil.GetRandomSpawns(Utilities.GetPlayers().Count, mgr)); Plugin.RegisterEventHandler(OnDeath, HookMode.Pre); Plugin.RegisterEventHandler(OnRespawn); diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs index 6f0a016c..512f590e 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs @@ -17,13 +17,6 @@ namespace Jailbreak.SpecialDay.SpecialDays; public class HideAndSeekDay(BasePlugin plugin, IServiceProvider provider) : AbstractArmoryRestrictedDay(plugin, provider), ISpecialDayMessageProvider { - public override SDType Type => SDType.HNS; - - private HNSDayLocale Msg => (HNSDayLocale)Locale; - public override SpecialDaySettings Settings => new HnsSettings(); - public override IView ArmoryReminder => Msg.StayInArmory; - public ISDInstanceLocale Locale => new HNSDayLocale(); - // Set to -1 to not modify values public static readonly FakeConVar CV_PRISONER_PRE_HEALTH = new( "jb_sd_hns_hide_hp_t", "Health to give to prisoners during HNS hide time", @@ -78,6 +71,12 @@ public class HideAndSeekDay(BasePlugin plugin, IServiceProvider provider) "Duration in seconds to give the hiders time to hide", 45, ConVarFlags.FCVAR_NONE, new RangeValidator(5, 120)); + public override SDType Type => SDType.HNS; + + private HNSDayLocale Msg => (HNSDayLocale)Locale; + public override SpecialDaySettings Settings => new HnsSettings(); + public override IView ArmoryReminder => Msg.StayInArmory; + private CsTeam? SeekerTeam => TeamUtil.FromString(CV_SEEKER_TEAM.Value); private CsTeam? HiderTeam @@ -85,6 +84,8 @@ private CsTeam? HiderTeam CsTeam.CounterTerrorist : CsTeam.Terrorist; + public ISDInstanceLocale Locale => new HNSDayLocale(); + public override void Setup() { if (SeekerTeam == null || HiderTeam == null) return; RestrictedTeam = SeekerTeam.Value; diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/NoScopeDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/NoScopeDay.cs index 6f401815..9496f27e 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/NoScopeDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/NoScopeDay.cs @@ -14,14 +14,6 @@ namespace Jailbreak.SpecialDay.SpecialDays; public class NoScopeDay(BasePlugin plugin, IServiceProvider provider) : FFADay(plugin, provider) { - public override SDType Type => SDType.NOSCOPE; - - public override ISDInstanceLocale Locale - => new SoloDayLocale("No Scope", - "Your scope broke! Fight against everyone else. No camping!"); - - public override SpecialDaySettings Settings => new NoScopeSettings(); - public static readonly FakeConVar CV_WEAPON = new( "jb_sd_noscope_weapon", "Weapon to give to all players, recommended it be a weapon with a scope (duh)", @@ -44,6 +36,14 @@ public override ISDInstanceLocale Locale new("jb_sd_noscope_gravity", "Gravity to set during the special day, default is 800", 200f); + public override SDType Type => SDType.NOSCOPE; + + public override ISDInstanceLocale Locale + => new SoloDayLocale("No Scope", + "Your scope broke! Fight against everyone else. No camping!"); + + public override SpecialDaySettings Settings => new NoScopeSettings(); + public override void Setup() { if (CV_KNIFE_DELAY.Value > 0) Timers[CV_KNIFE_DELAY.Value] += () => { diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs index 610a28da..8001a103 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs @@ -13,17 +13,9 @@ namespace Jailbreak.SpecialDay.SpecialDays; public class OneInTheChamberDay(BasePlugin plugin, IServiceProvider provider) : FFADay(plugin, provider) { - public override SDType Type => SDType.OITC; - - public override ISDInstanceLocale Locale - => new SoloDayLocale("One in the Chamber", "You only have one bullet.", - "Kill someone to get another bullet.", "One-Hit-Kills! No camping!"); - - public override SpecialDaySettings Settings => new OitcSettings(); - public static readonly FakeConVar CV_WEAPON = new("jb_sd_oitc_weapon", "Weapon to give to players for the day", "weapon_deagle", - ConVarFlags.FCVAR_NONE, new ItemValidator(ItemValidator.WeaponType.GUNS)); + ConVarFlags.FCVAR_NONE, new ItemValidator(WeaponType.GUNS)); public static readonly FakeConVar CV_ADDITIONAL_WEAPON = new( "jb_sd_oitc_additionalweapon", @@ -31,6 +23,13 @@ public override ISDInstanceLocale Locale "weapon_knife", ConVarFlags.FCVAR_NONE, new ItemValidator()); private bool started; + public override SDType Type => SDType.OITC; + + public override ISDInstanceLocale Locale + => new SoloDayLocale("One in the Chamber", "You only have one bullet.", + "Kill someone to get another bullet.", "One-Hit-Kills! No camping!"); + + public override SpecialDaySettings Settings => new OitcSettings(); public override void Setup() { base.Setup(); diff --git a/mod/Jailbreak.Warden/Global/WardenBehavior.cs b/mod/Jailbreak.Warden/Global/WardenBehavior.cs index c7788dd2..f8365c95 100644 --- a/mod/Jailbreak.Warden/Global/WardenBehavior.cs +++ b/mod/Jailbreak.Warden/Global/WardenBehavior.cs @@ -38,9 +38,6 @@ public class WardenBehavior(ILogger logger, ISpecialTreatmentService specialTreatment, IRebelService rebels, IMuteService mute, IServiceProvider provider) : IPluginBehavior, IWardenService { - private readonly ISet bluePrisoners = - new HashSet(); - public static readonly FakeConVar CV_ARMOR_EQUAL = new("css_jb_hp_outnumbered", "Health points for CTs have equal balance", 50, ConVarFlags.FCVAR_NONE, new RangeValidator(1, 200)); @@ -84,6 +81,9 @@ public class WardenBehavior(ILogger logger, public static readonly FakeConVar CV_WARDEN_TERRORIST_RATIO = new("css_jb_warden_t_ratio", "Ratio of T:CT to use for HP adjustments", 3); + private readonly ISet bluePrisoners = + new HashSet(); + private bool firstWarden; private string? oldTag; private char? oldTagColor; diff --git a/mod/Jailbreak.Warden/Markers/WardenMarkerBehavior.cs b/mod/Jailbreak.Warden/Markers/WardenMarkerBehavior.cs index 7bc03cef..3880eb1d 100644 --- a/mod/Jailbreak.Warden/Markers/WardenMarkerBehavior.cs +++ b/mod/Jailbreak.Warden/Markers/WardenMarkerBehavior.cs @@ -48,7 +48,8 @@ public HookResult OnPing(EventPlayerPing @event, GameEventInfo info) { - placementTime; if (timeElapsed < CV_RESIZE_TIME.Value) { if (distance <= CV_MAX_RADIUS.Value * 1.3) { - distance = Math.Clamp(distance, CV_MIN_RADIUS.Value, CV_MAX_RADIUS.Value); + distance = Math.Clamp(distance, CV_MIN_RADIUS.Value, + CV_MAX_RADIUS.Value); marker?.SetRadius(distance); marker?.Update(); radius = distance; diff --git a/mod/Jailbreak.Warden/Selection/WardenSelectionBehavior.cs b/mod/Jailbreak.Warden/Selection/WardenSelectionBehavior.cs index 3ba0aac0..20759e1d 100644 --- a/mod/Jailbreak.Warden/Selection/WardenSelectionBehavior.cs +++ b/mod/Jailbreak.Warden/Selection/WardenSelectionBehavior.cs @@ -22,6 +22,8 @@ public class private readonly IPlayerState favor; + private readonly HashSet guaranteedWarden = []; + private readonly IWardenLocale locale; private readonly ILogger logger; @@ -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/mod/Jailbreak.Zones/SqlZoneManager.cs b/mod/Jailbreak.Zones/SqlZoneManager.cs index 21fbddc8..df491d03 100644 --- a/mod/Jailbreak.Zones/SqlZoneManager.cs +++ b/mod/Jailbreak.Zones/SqlZoneManager.cs @@ -8,8 +8,8 @@ namespace Jailbreak.Zones; public class SqlZoneManager(IZoneFactory factory) : IZoneManager { - public static readonly FakeConVar CV_SQL_TABLE = new("css_jb_zonetable", - "The table name for the zones", "cs2_jb_zones"); + public static readonly FakeConVar CV_SQL_TABLE = + new("css_jb_zonetable", "The table name for the zones", "cs2_jb_zones"); public static readonly FakeConVar CV_SQL_CONNECTION_STRING = new("css_jb_sqlconnection", "The connection string for the database", "", diff --git a/public/Jailbreak.Formatting/Views/IRTDLocale.cs b/public/Jailbreak.Formatting/Views/IRTDLocale.cs new file mode 100644 index 00000000..0eb25539 --- /dev/null +++ b/public/Jailbreak.Formatting/Views/IRTDLocale.cs @@ -0,0 +1,10 @@ +using Jailbreak.Formatting.Base; +using Jailbreak.Public.Mod.RTD; + +namespace Jailbreak.Formatting.Views; + +public interface IRTDLocale { + public IView RewardSelected(IRTDReward reward); + public IView AlreadyRolled(IRTDReward reward); + public IView CannotRollYet(); +} \ No newline at end of file diff --git a/public/Jailbreak.Public/Extensions/PlayerExtensions.cs b/public/Jailbreak.Public/Extensions/PlayerExtensions.cs index 1fd967f0..4713d6c4 100644 --- a/public/Jailbreak.Public/Extensions/PlayerExtensions.cs +++ b/public/Jailbreak.Public/Extensions/PlayerExtensions.cs @@ -124,6 +124,7 @@ public static void SetColor(this CCSPlayerController player, Color color) { var pawn = player.PlayerPawn.Value; if (!player.IsValid || pawn == null || !pawn.IsValid) return; + // TODO: Don't always override to allow other plugins to show legs. if (color.A == 255) color = Color.FromArgb(254, color.R, color.G, color.B); pawn.RenderMode = RenderMode_t.kRenderTransColor; pawn.Render = color; diff --git a/public/Jailbreak.Public/Extensions/WeaponExtensions.cs b/public/Jailbreak.Public/Extensions/WeaponExtensions.cs index 104e24fa..e85f9484 100644 --- a/public/Jailbreak.Public/Extensions/WeaponExtensions.cs +++ b/public/Jailbreak.Public/Extensions/WeaponExtensions.cs @@ -125,8 +125,10 @@ public static string GetFriendlyWeaponName(this string designerName) { case "weapon_knife_t": case "weapon_knife": return "Knife"; - default: - return designerName.Replace("weapon_", "").ToUpper(); + default: { + var name = designerName.Replace("weapon_", ""); + return char.ToUpper(name[0]) + name[1..]; + } } } diff --git a/public/Jailbreak.Public/Mod/RTD/IRTDReward.cs b/public/Jailbreak.Public/Mod/RTD/IRTDReward.cs new file mode 100644 index 00000000..61a692a8 --- /dev/null +++ b/public/Jailbreak.Public/Mod/RTD/IRTDReward.cs @@ -0,0 +1,33 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; + +namespace Jailbreak.Public.Mod.RTD; + +public interface IRTDReward { + public string Name { get; } + public string Description { get; } + bool Enabled => 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(CCSPlayerController player) { return true; } + + bool GrantReward(int userid) { + var player = Utilities.GetPlayerFromUserid(userid); + if (player == null || !player.IsValid) return false; + return player.PawnIsAlive && GrantReward(player); + } + + bool GrantReward(CCSPlayerController player); +} \ No newline at end of file diff --git a/public/Jailbreak.Public/Mod/RTD/IRTDRewarder.cs b/public/Jailbreak.Public/Mod/RTD/IRTDRewarder.cs new file mode 100644 index 00000000..ce31d779 --- /dev/null +++ b/public/Jailbreak.Public/Mod/RTD/IRTDRewarder.cs @@ -0,0 +1,42 @@ +using CounterStrikeSharp.API.Core; + +namespace Jailbreak.Public.Mod.RTD; + +/// +/// A rewarder that manages rewards for players. +/// +public interface IRTDRewarder { + /// + /// True if the player currently has a reward. + /// + /// + /// + bool HasReward(int id) { return GetReward(id) != null; } + + bool HasReward(CCSPlayerController player) { + return HasReward(player.UserId ?? -1); + } + + /// + /// Gets the reward for the player. + /// + /// + /// + IRTDReward? GetReward(int id); + + IRTDReward? GetReward(CCSPlayerController player) { + return GetReward(player.UserId ?? -1); + } + + /// + /// Attempts to give a reward to the player. + /// + /// + /// + /// + bool SetReward(int id, IRTDReward reward); + + bool SetReward(CCSPlayerController player, IRTDReward reward) { + return SetReward(player.UserId ?? -1, reward); + } +} \ No newline at end of file diff --git a/public/Jailbreak.Public/Mod/RTD/IRewardGenerator.cs b/public/Jailbreak.Public/Mod/RTD/IRewardGenerator.cs new file mode 100644 index 00000000..a3e744e4 --- /dev/null +++ b/public/Jailbreak.Public/Mod/RTD/IRewardGenerator.cs @@ -0,0 +1,11 @@ +using CounterStrikeSharp.API.Core; + +namespace Jailbreak.Public.Mod.RTD; + +public interface IRewardGenerator : IReadOnlyCollection<(IRTDReward, float)> { + IRTDReward GenerateReward(int? id); + + IRTDReward GenerateReward(CCSPlayerController player) { + return GenerateReward(player.UserId); + } +} \ No newline at end of file diff --git a/public/Jailbreak.Public/Mod/Rebel/IC4Service.cs b/public/Jailbreak.Public/Mod/Rebel/IC4Service.cs index 56c3b63e..05660163 100644 --- a/public/Jailbreak.Public/Mod/Rebel/IC4Service.cs +++ b/public/Jailbreak.Public/Mod/Rebel/IC4Service.cs @@ -25,5 +25,7 @@ void StartDetonationAttempt(CCSPlayerController player, float delay, /// void TryGiveC4ToRandomTerrorist(); + void DontGiveC4NextRound() { } + void ClearActiveC4s(); } \ No newline at end of file diff --git a/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs b/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs index 8597765b..93714843 100644 --- a/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs +++ b/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs @@ -147,6 +147,7 @@ private void doTeleports(SpecialDaySettings.TeleportType type, var ctVectors = ctSpawns.ToArray(); ctVectors.Shuffle(); + var mgr = Provider.GetService(); IEnumerable spawnPositions; switch (type) { case SpecialDaySettings.TeleportType.CELL: @@ -162,10 +163,11 @@ private void doTeleports(SpecialDaySettings.TeleportType type, spawnPositions = [ctVectors.First()]; break; case SpecialDaySettings.TeleportType.RANDOM: - spawnPositions = getAtLeastRandom(PlayerUtil.GetAlive().Count()); + spawnPositions = + MapUtil.GetRandomSpawns(PlayerUtil.GetAlive().Count(), mgr); break; case SpecialDaySettings.TeleportType.RANDOM_STACKED: - spawnPositions = [getAtLeastRandom(1).First()]; + spawnPositions = [MapUtil.GetRandomSpawns(1, mgr).First()]; break; default: return; @@ -176,61 +178,6 @@ private void doTeleports(SpecialDaySettings.TeleportType type, player.PlayerPawn.Value?.Teleport(baggedSpawns.GetNext()); } - protected List getAtLeastRandom(int count) { - // Progressively get more lax with our "randomness quality" - var result = getRandomSpawns(false, false, false); - if (result.Count < count) result = getRandomSpawns(false, false); - if (result.Count < count) result = getRandomSpawns(false); - if (result.Count < count) result = getRandomSpawns(); - return result; - } - - protected List getRandomSpawns(bool includeSpawns = true, - bool includeTps = true, bool includeAuto = true) { - var result = new List(); - - if (includeTps) { - var worldTp = Utilities - .FindAllEntitiesByDesignerName( - "info_teleport_destination") - .Where(s => s.AbsOrigin != null) - .Select(s => s.AbsOrigin!); - result.AddRange(worldTp); - } - - if (includeSpawns) { - var tSpawns = Utilities - .FindAllEntitiesByDesignerName("info_player_terrorist") - .Where(s => s.AbsOrigin != null) - .Select(s => s.AbsOrigin!); - var ctSpawns = Utilities - .FindAllEntitiesByDesignerName< - SpawnPoint>("info_player_counterterrorist") - .Where(s => s.AbsOrigin != null) - .Select(s => s.AbsOrigin!); - result.AddRange(tSpawns); - result.AddRange(ctSpawns); - } - - var zoneManager = Provider.GetService(); - if (zoneManager != null) { - if (includeAuto) - result.AddRange(zoneManager - .GetZones(Server.MapName, ZoneType.SPAWN_AUTO) - .GetAwaiter() - .GetResult() - .Select(z => z.GetCenterPoint())); - - var zones = zoneManager.GetZones(Server.MapName, ZoneType.SPAWN) - .GetAwaiter() - .GetResult(); - result.AddRange(zones.Select(z => z.GetCenterPoint())); - } - - result.Shuffle(); - return result; - } - protected object GetConvarValue(ConVar? cvar) { try { if (cvar == null) return ""; diff --git a/public/Jailbreak.Public/Mod/Warden/IWardenSelectionService.cs b/public/Jailbreak.Public/Mod/Warden/IWardenSelectionService.cs index 80ff3504..e5d0b550 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 /// diff --git a/public/Jailbreak.Public/Utils/MapUtil.cs b/public/Jailbreak.Public/Utils/MapUtil.cs index 295d6801..baa6d394 100644 --- a/public/Jailbreak.Public/Utils/MapUtil.cs +++ b/public/Jailbreak.Public/Utils/MapUtil.cs @@ -121,6 +121,61 @@ private static bool IsCellButton(CBaseEntity ent, Sensitivity sen) { return false; } + + public static List GetRandomSpawns(int count, IZoneManager? zones) { + // Progressively get more lax with our "randomness quality" + var result = GetRandomSpawns(zones, false, false, false); + if (result.Count < count) result = GetRandomSpawns(zones, false, false); + if (result.Count < count) result = GetRandomSpawns(zones, false); + if (result.Count < count) result = GetRandomSpawns(zones); + return result; + } + + public static List GetRandomSpawns(IZoneManager? zoneManager = null, + bool includeSpawns = true, bool includeTps = true, + bool includeAuto = true) { + var result = new List(); + + if (includeTps) { + var worldTp = Utilities + .FindAllEntitiesByDesignerName( + "info_teleport_destination") + .Where(s => s.AbsOrigin != null) + .Select(s => s.AbsOrigin!); + result.AddRange(worldTp); + } + + if (includeSpawns) { + var tSpawns = Utilities + .FindAllEntitiesByDesignerName("info_player_terrorist") + .Where(s => s.AbsOrigin != null) + .Select(s => s.AbsOrigin!); + var ctSpawns = Utilities + .FindAllEntitiesByDesignerName< + SpawnPoint>("info_player_counterterrorist") + .Where(s => s.AbsOrigin != null) + .Select(s => s.AbsOrigin!); + result.AddRange(tSpawns); + result.AddRange(ctSpawns); + } + + if (zoneManager != null) { + if (includeAuto) + result.AddRange(zoneManager + .GetZones(Server.MapName, ZoneType.SPAWN_AUTO) + .GetAwaiter() + .GetResult() + .Select(z => z.GetCenterPoint())); + + var zones = zoneManager.GetZones(Server.MapName, ZoneType.SPAWN) + .GetAwaiter() + .GetResult(); + result.AddRange(zones.Select(z => z.GetCenterPoint())); + } + + result.Shuffle(); + return result; + } } public enum Sensitivity { diff --git a/public/Jailbreak.Tag/WeaponType.cs b/public/Jailbreak.Tag/WeaponType.cs new file mode 100644 index 00000000..9d965a73 --- /dev/null +++ b/public/Jailbreak.Tag/WeaponType.cs @@ -0,0 +1,52 @@ +[Flags] +public enum WeaponType { + GRENADE = 1 << 0, // 1 + UTILITY = 1 << 1, // 2 + WEAPON = 1 << 2, // 4 + SNIPERS = 1 << 3, // 8 + RIFLES = 1 << 4, // 16 + PISTOLS = 1 << 5, // 32 + SHOTGUNS = 1 << 6, // 64 + SMGS = 1 << 7, // 128 + HEAVY = 1 << 8, // 256 + GUNS = 1 << 9 // 512 +} + +public static class WeaponTypeExtensions { + public static IReadOnlySet GetItems(this WeaponType type) { + var result = new HashSet(); + + foreach (var t in Enum.GetValues()) + if (type.HasFlag(t)) + result.UnionWith(t.GetItems()); + + switch (type) { + case WeaponType.GUNS: + return Tag.GUNS; + case WeaponType.HEAVY: + return Tag.HEAVY; + case WeaponType.SMGS: + return Tag.SMGS; + case WeaponType.SHOTGUNS: + return Tag.SHOTGUNS; + case WeaponType.PISTOLS: + return Tag.PISTOLS; + case WeaponType.RIFLES: + return Tag.RIFLES; + case WeaponType.SNIPERS: + return Tag.SNIPERS; + case WeaponType.UTILITY: + return Tag.UTILITY; + case WeaponType.GRENADE: + return Tag.GRENADES; + case WeaponType.WEAPON: + return Tag.WEAPONS; + default: + foreach (var t in Enum.GetValues()) + if (type.HasFlag(t)) + result.UnionWith(t.GetItems()); + + return result; + } + } +} \ No newline at end of file diff --git a/public/Jailbreak.Validator/ItemValidator.cs b/public/Jailbreak.Validator/ItemValidator.cs index a0506b63..17bd6a5f 100644 --- a/public/Jailbreak.Validator/ItemValidator.cs +++ b/public/Jailbreak.Validator/ItemValidator.cs @@ -3,23 +3,8 @@ namespace Jailbreak.Validator; public class ItemValidator( - ItemValidator.WeaponType type = ItemValidator.WeaponType.WEAPON - | ItemValidator.WeaponType.UTILITY, bool allowEmpty = true, - bool allowMultiple = false) : IValidator { - [Flags] - public enum WeaponType { - GRENADE = 1 << 0, // 1 - UTILITY = 1 << 1, // 2 - WEAPON = 1 << 2, // 4 - SNIPERS = 1 << 3, // 8 - RIFLES = 1 << 4, // 16 - PISTOLS = 1 << 5, // 32 - SHOTGUNS = 1 << 6, // 64 - SMGS = 1 << 7, // 128 - HEAVY = 1 << 8, // 256 - GUNS = 1 << 9 // 512 - } - + WeaponType type = WeaponType.WEAPON | WeaponType.UTILITY, + bool allowEmpty = true, bool allowMultiple = false) : IValidator { public bool Validate(string value, out string? errorMessage) { if (value.Contains(',') && !allowMultiple) { errorMessage = "Value cannot contain multiple values"; @@ -42,29 +27,10 @@ public bool Validate(string value, out string? errorMessage) { } errorMessage = $"invalid {type.ToString()}: {weapon}"; - return Enum.GetValues() - .Where(t => type.HasFlag(t)) - .Any(t => validateType(t, weapon)); + return type.GetItems().Contains(weapon); } errorMessage = null; return true; } - - private bool validateType(WeaponType current, string weapon) { - var result = current switch { - WeaponType.GRENADE => Tag.GRENADES.Contains(weapon), - WeaponType.UTILITY => Tag.UTILITY.Contains(weapon), - WeaponType.WEAPON => Tag.WEAPONS.Contains(weapon), - WeaponType.SNIPERS => Tag.SNIPERS.Contains(weapon), - WeaponType.RIFLES => Tag.RIFLES.Contains(weapon), - WeaponType.PISTOLS => Tag.PISTOLS.Contains(weapon), - WeaponType.SHOTGUNS => Tag.SHOTGUNS.Contains(weapon), - WeaponType.SMGS => Tag.SMGS.Contains(weapon), - WeaponType.HEAVY => Tag.HEAVY.Contains(weapon), - WeaponType.GUNS => Tag.GUNS.Contains(weapon), - _ => throw new ArgumentOutOfRangeException(nameof(weapon)) - }; - return result; - } } \ No newline at end of file diff --git a/src/Jailbreak/Jailbreak.csproj b/src/Jailbreak/Jailbreak.csproj index 155877ae..5cc564de 100644 --- a/src/Jailbreak/Jailbreak.csproj +++ b/src/Jailbreak/Jailbreak.csproj @@ -61,6 +61,7 @@ + diff --git a/src/Jailbreak/JailbreakServiceCollection.cs b/src/Jailbreak/JailbreakServiceCollection.cs index 90510926..8107ecd2 100644 --- a/src/Jailbreak/JailbreakServiceCollection.cs +++ b/src/Jailbreak/JailbreakServiceCollection.cs @@ -6,6 +6,7 @@ using Jailbreak.English.Logs; using Jailbreak.English.Mute; using Jailbreak.English.Rebel; +using Jailbreak.English.RTD; using Jailbreak.English.SpecialDay; using Jailbreak.English.Warden; using Jailbreak.Formatting.Views; @@ -18,6 +19,7 @@ using Jailbreak.Logs; using Jailbreak.Mute; using Jailbreak.Rebel; +using Jailbreak.RTD; using Jailbreak.SpecialDay; using Jailbreak.Warden; using Jailbreak.Zones; @@ -47,6 +49,7 @@ public void ConfigureServices(IServiceCollection serviceCollection) { serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); // Do we want to make this scoped? // Not sure how this will behave with multiple rounds and whatnot. @@ -60,5 +63,6 @@ public void ConfigureServices(IServiceCollection serviceCollection) { serviceCollection.AddJailbreakLastGuard(); serviceCollection.AddJailbreakSpecialDay(); serviceCollection.AddJailbreakZones(); + serviceCollection.AddDiceRoll(); } } \ No newline at end of file From 938d2bb37bf53dd6c46c3e8f630e3afd52c2cb73 Mon Sep 17 00:00:00 2001 From: MSWS Date: Wed, 28 Aug 2024 00:22:33 -0700 Subject: [PATCH 10/19] Print stats to console --- mod/Jailbreak.RTD/RTDStatsCommand.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/mod/Jailbreak.RTD/RTDStatsCommand.cs b/mod/Jailbreak.RTD/RTDStatsCommand.cs index 618dd184..1db1009a 100644 --- a/mod/Jailbreak.RTD/RTDStatsCommand.cs +++ b/mod/Jailbreak.RTD/RTDStatsCommand.cs @@ -23,6 +23,7 @@ public void var percent = prob / total * 100; executor.PrintToChat( $"{ChatColors.Orange}{index++}. {ChatColors.LightBlue}{name}{ChatColors.Grey}: {ChatColors.Yellow}{percent:0.00}%"); + executor.PrintToConsole($"{index++}. {name}: {percent:0.00}%"); } } } \ No newline at end of file From faea1f86c375b92a683f251756e3615e43069205 Mon Sep 17 00:00:00 2001 From: MSWS Date: Wed, 28 Aug 2024 03:12:30 -0700 Subject: [PATCH 11/19] Fixes --- lang/Jailbreak.English/RTD/RTDLocale.cs | 19 ++- mod/Jailbreak.RTD/AutoRTDListener.cs | 15 ++- mod/Jailbreak.RTD/Jailbreak.RTD.csproj | 1 + mod/Jailbreak.RTD/RTDCommand.cs | 4 +- mod/Jailbreak.RTD/RTDRewarder.cs | 28 +++-- mod/Jailbreak.RTD/RTDStatsCommand.cs | 6 +- mod/Jailbreak.RTD/RewardGenerator.cs | 114 +++++++++++------- ...ScopeReward.cs => AbstractOnTickReward.cs} | 25 +--- mod/Jailbreak.RTD/Rewards/AmmoWeaponReward.cs | 11 +- mod/Jailbreak.RTD/Rewards/ArmorReward.cs | 4 +- mod/Jailbreak.RTD/Rewards/BombReward.cs | 8 +- .../Rewards/CannotPickupReward.cs | 19 ++- mod/Jailbreak.RTD/Rewards/CannotRightKnife.cs | 28 +++++ mod/Jailbreak.RTD/Rewards/CannotScope.cs | 25 ++++ mod/Jailbreak.RTD/Rewards/ColorReward.cs | 2 +- .../Rewards/GuaranteedWardenReward.cs | 2 +- mod/Jailbreak.RTD/Rewards/NoWeaponReward.cs | 11 +- .../Rewards/TransparentReward.cs | 2 +- mod/Jailbreak.RTD/Rewards/WeaponReward.cs | 16 ++- public/Jailbreak.Public/Mod/RTD/IRTDReward.cs | 2 +- public/Jailbreak.Tag/Tag.cs | 15 +-- public/Jailbreak.Tag/WeaponType.cs | 4 - 22 files changed, 230 insertions(+), 131 deletions(-) rename mod/Jailbreak.RTD/Rewards/{CannotScopeReward.cs => AbstractOnTickReward.cs} (60%) create mode 100644 mod/Jailbreak.RTD/Rewards/CannotRightKnife.cs create mode 100644 mod/Jailbreak.RTD/Rewards/CannotScope.cs diff --git a/lang/Jailbreak.English/RTD/RTDLocale.cs b/lang/Jailbreak.English/RTD/RTDLocale.cs index 3ff21b65..b9997875 100644 --- a/lang/Jailbreak.English/RTD/RTDLocale.cs +++ b/lang/Jailbreak.English/RTD/RTDLocale.cs @@ -11,11 +11,19 @@ public class RTDLocale : IRTDLocale, ILanguage { $" {ChatColors.Purple}[{ChatColors.LightPurple}RTD{ChatColors.Purple}]"; public IView RewardSelected(IRTDReward reward) { - return new SimpleView { - { PREFIX, "You rolled ", reward.Name + "." }, - SimpleView.NEWLINE, - { PREFIX, reward.Description } + var view = new SimpleView { + PREFIX, + ChatColors.Grey + "You rolled " + ChatColors.White + reward.Name + + ChatColors.Grey + "." }; + + if (reward.Description == null) return view; + + view.Add(SimpleView.NEWLINE); + view.Add(PREFIX); + view.Add(ChatColors.Grey + reward.Description); + + return view; } public IView AlreadyRolled(IRTDReward reward) { @@ -28,7 +36,8 @@ public IView AlreadyRolled(IRTDReward reward) { public IView CannotRollYet() { return new SimpleView { - PREFIX, "You can only roll once the round ends or you die." + PREFIX, + ChatColors.Red + "You can only roll once the round ends or you die." }; } } \ No newline at end of file diff --git a/mod/Jailbreak.RTD/AutoRTDListener.cs b/mod/Jailbreak.RTD/AutoRTDListener.cs index f0194129..5341946b 100644 --- a/mod/Jailbreak.RTD/AutoRTDListener.cs +++ b/mod/Jailbreak.RTD/AutoRTDListener.cs @@ -4,17 +4,22 @@ using CounterStrikeSharp.API.Modules.Admin; using Jailbreak.Public.Behaviors; using Jailbreak.Public.Mod.RTD; +using Jailbreak.Public.Utils; namespace Jailbreak.RTD; public class AutoRTDListener(IRTDRewarder rewarder) : IPluginBehavior { [GameEventHandler] public HookResult OnRoundEnd(EventRoundEnd @event, GameEventInfo info) { - foreach (var player in Utilities.GetPlayers() - .Where(player - => AdminManager.PlayerHasPermissions(player, "@ego/dssilver")) - .Where(player => !rewarder.HasReward(player))) - player.ExecuteClientCommandFromServer("css_rtd"); + if (RoundUtil.IsWarmup()) return HookResult.Continue; + + Server.NextFrame(() => { + foreach (var player in Utilities.GetPlayers() + .Where(player + => AdminManager.PlayerHasPermissions(player, "@ego/dssilver")) + .Where(player => !rewarder.HasReward(player))) + player.ExecuteClientCommandFromServer("css_rtd"); + }); return HookResult.Continue; } diff --git a/mod/Jailbreak.RTD/Jailbreak.RTD.csproj b/mod/Jailbreak.RTD/Jailbreak.RTD.csproj index f430fd60..a273b64a 100644 --- a/mod/Jailbreak.RTD/Jailbreak.RTD.csproj +++ b/mod/Jailbreak.RTD/Jailbreak.RTD.csproj @@ -9,6 +9,7 @@ + diff --git a/mod/Jailbreak.RTD/RTDCommand.cs b/mod/Jailbreak.RTD/RTDCommand.cs index 27ca57f2..634b6562 100644 --- a/mod/Jailbreak.RTD/RTDCommand.cs +++ b/mod/Jailbreak.RTD/RTDCommand.cs @@ -6,6 +6,7 @@ using Jailbreak.Formatting.Views; using Jailbreak.Public.Behaviors; using Jailbreak.Public.Mod.RTD; +using Jailbreak.Public.Utils; namespace Jailbreak.RTD; @@ -25,7 +26,8 @@ public void Command_RTD(CCSPlayerController? executor, CommandInfo info) { return; } - if (!bypass && !inBetweenRounds && executor.PawnIsAlive) { + if (!bypass && !inBetweenRounds && !RoundUtil.IsWarmup() + && executor.PawnIsAlive) { locale.CannotRollYet().ToChat(executor); return; } diff --git a/mod/Jailbreak.RTD/RTDRewarder.cs b/mod/Jailbreak.RTD/RTDRewarder.cs index f9fe5ce9..65478d56 100644 --- a/mod/Jailbreak.RTD/RTDRewarder.cs +++ b/mod/Jailbreak.RTD/RTDRewarder.cs @@ -1,6 +1,6 @@ -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Attributes.Registration; -using Jailbreak.Formatting.Views; using Jailbreak.Formatting.Views.Logging; using Jailbreak.Public.Behaviors; using Jailbreak.Public.Mod.RTD; @@ -8,8 +8,7 @@ namespace Jailbreak.RTD; -public class RTDRewarder(IRichLogService logs, IRTDLocale locale) - : IRTDRewarder, IPluginBehavior { +public class RTDRewarder(IRichLogService logs) : IRTDRewarder, IPluginBehavior { private readonly Dictionary rewards = new(); public bool HasReward(int id) { return GetReward(id) != null; } @@ -25,18 +24,23 @@ public bool SetReward(int id, IRTDReward reward) { } [GameEventHandler] - public HookResult OnStart(EventRoundStart @event, GameEventInfo info) { - foreach (var player in PlayerUtil.GetAlive()) { - var id = player.UserId ?? -1; + public HookResult OnSpawn(EventPlayerSpawn @event, GameEventInfo info) { + if (RoundUtil.IsWarmup()) return HookResult.Continue; + var player = @event.Userid; - var reward = GetReward(id); - if (reward == null) continue; + if (player == null || !player.IsValid) return HookResult.Continue; + var id = player.UserId ?? -1; + + var reward = GetReward(id); + if (reward == null) return HookResult.Continue; + if (!reward.CanGrantReward(player)) return HookResult.Continue; + + Server.RunOnTick(Server.TickCount + 2, () => { logs.Append("Granted", reward.Name, "to", logs.Player(player)); reward.GrantReward(id); - } - - rewards.Clear(); + rewards.Remove(id); + }); return HookResult.Continue; } } \ No newline at end of file diff --git a/mod/Jailbreak.RTD/RTDStatsCommand.cs b/mod/Jailbreak.RTD/RTDStatsCommand.cs index 1db1009a..6c3ca19b 100644 --- a/mod/Jailbreak.RTD/RTDStatsCommand.cs +++ b/mod/Jailbreak.RTD/RTDStatsCommand.cs @@ -15,15 +15,15 @@ public void var total = generator.Sum(r => r.Item2); var rewards = generator.ToList(); - rewards.Sort((a, b) => a.Item2.CompareTo(b.Item2)); var index = 0; foreach (var (reward, prob) in rewards) { var name = reward.Name; var percent = prob / total * 100; executor.PrintToChat( - $"{ChatColors.Orange}{index++}. {ChatColors.LightBlue}{name}{ChatColors.Grey}: {ChatColors.Yellow}{percent:0.00}%"); - executor.PrintToConsole($"{index++}. {name}: {percent:0.00}%"); + $"{ChatColors.Orange}{index}. {ChatColors.LightBlue}{name}{ChatColors.Grey}: {ChatColors.Yellow}{percent:0.00}%"); + executor.PrintToConsole($"{index}. {name}: {percent:0.00}%"); + index++; } } } \ No newline at end of file diff --git a/mod/Jailbreak.RTD/RewardGenerator.cs b/mod/Jailbreak.RTD/RewardGenerator.cs index 33d6fe45..37be80d2 100644 --- a/mod/Jailbreak.RTD/RewardGenerator.cs +++ b/mod/Jailbreak.RTD/RewardGenerator.cs @@ -1,16 +1,18 @@ using System.Collections; using System.Drawing; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Utils; using Jailbreak.Public.Behaviors; using Jailbreak.Public.Mod.Rebel; using Jailbreak.Public.Mod.RTD; +using Jailbreak.Public.Mod.Warden; using Jailbreak.Public.Mod.Zones; using Jailbreak.RTD.Rewards; namespace Jailbreak.RTD; -public class RewardGenerator(IZoneManager mgr, IC4Service bomb) - : IPluginBehavior, IRewardGenerator { +public class RewardGenerator(IZoneManager mgr, IC4Service bomb, + IWardenSelectionService warden) : IPluginBehavior, IRewardGenerator { private static readonly float PROB_LOTTERY = 1 / 5000f; private static readonly float PROB_EXTREMELY_LOW = 1 / 1000f; private static readonly float PROB_VERY_LOW = 1 / 100f; @@ -19,30 +21,7 @@ public class RewardGenerator(IZoneManager mgr, IC4Service bomb) private static readonly float PROB_OFTEN = 1 / 5f; private static readonly float PROB_VERY_OFTEN = 1 / 2f; - private readonly List<(IRTDReward, float)> rewards = [ - (new NothingReward(), PROB_OFTEN), - (new WeaponReward("weapon_healthshot"), PROB_OFTEN), - (new WeaponReward("weapon_decoy"), PROB_OFTEN), - (new CreditReward(1), PROB_MEDIUM), (new CreditReward(2), PROB_MEDIUM), - (new CreditReward(3), PROB_MEDIUM), - (new WeaponReward("weapon_flashbang"), PROB_MEDIUM), - (new WeaponReward("weapon_hegrenade"), PROB_MEDIUM), - (new WeaponReward("weapon_smokegrenade"), PROB_MEDIUM), - (new WeaponReward("weapon_molotov"), PROB_MEDIUM), - (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), 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), - (new NoWeaponReward(), PROB_VERY_LOW), - (new AmmoWeaponReward("weapon_deagle", 1, 0), PROB_VERY_LOW), - (new RandomTeleportReward(mgr), PROB_VERY_LOW), - (new BombReward(bomb), PROB_VERY_LOW), - (new AmmoWeaponReward("weapon_awp", 1, 0), PROB_EXTREMELY_LOW) - ]; + private readonly List<(IRTDReward, float)> rewards = []; private readonly Random rng = new(); @@ -50,34 +29,79 @@ private float totalWeight => rewards.Where(r => r.Item1.Enabled).Select(s => s.Item2).Sum(); public void Start(BasePlugin basePlugin) { - rewards.Add((new CannotPickupReward(basePlugin, WeaponType.GRENADE), - 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)); - rewards.Add((new CannotPickupReward(basePlugin, WeaponType.PISTOLS), - PROB_VERY_LOW)); - rewards.Add((new CannotPickupReward(basePlugin, WeaponType.SNIPERS), - PROB_VERY_LOW)); - rewards.Add((new CannotPickupReward(basePlugin, WeaponType.HEAVY), - PROB_VERY_LOW)); - rewards.Add((new CannotPickupReward(basePlugin, WeaponType.RIFLES), - PROB_EXTREMELY_LOW)); + rewards.AddRange([ + // Very often + (new NothingReward(), PROB_VERY_OFTEN), + + // Often + (new WeaponReward(basePlugin, "weapon_healthshot"), PROB_OFTEN), + (new WeaponReward(basePlugin, "weapon_decoy"), PROB_OFTEN), + + // Medium + (new CreditReward(1), PROB_MEDIUM), (new CreditReward(2), PROB_MEDIUM), + (new CreditReward(3), PROB_MEDIUM), + (new WeaponReward(basePlugin, "weapon_flashbang"), PROB_MEDIUM), + (new WeaponReward(basePlugin, "weapon_hegrenade"), PROB_MEDIUM), + (new WeaponReward(basePlugin, "weapon_smokegrenade"), PROB_MEDIUM), + (new WeaponReward(basePlugin, "weapon_molotov"), PROB_MEDIUM), + (new WeaponReward(basePlugin, "weapon_taser"), PROB_MEDIUM), + (new HPReward(150), PROB_MEDIUM), (new HPReward(50), PROB_MEDIUM), + (new ArmorReward(150), PROB_MEDIUM), + (new GuaranteedWardenReward(warden), PROB_MEDIUM), + (new WeaponReward(basePlugin, "weapon_g3sg1", CsTeam.CounterTerrorist), + PROB_MEDIUM), + + // Low + (new HPReward(1), PROB_LOW), + (new ColorReward(Color.FromArgb(0, 255, 0), true), PROB_LOW), + (new ColorReward(Color.FromArgb(255, 0, 0), true), PROB_LOW), + (new CannotPickupReward(basePlugin, WeaponType.GRENADE), PROB_LOW), + (new CannotPickupReward(basePlugin, WeaponType.UTILITY), PROB_LOW), + (new CannotPickupReward(basePlugin, WeaponType.GRENADE | WeaponType.UTILITY), + PROB_LOW), + (new CannotScope(basePlugin), PROB_LOW), + (new CannotRightKnife(basePlugin), PROB_LOW), + (new TransparentReward(), PROB_LOW), + (new AmmoWeaponReward(basePlugin, "weapon_glock", 2, 0), PROB_LOW), + (new AmmoWeaponReward(basePlugin, "weapon_negev", 0, 5), PROB_LOW), + + // Very low + (new NoWeaponReward(), PROB_VERY_LOW), + (new AmmoWeaponReward(basePlugin, "weapon_deagle", 1, 0), PROB_VERY_LOW), + (new CannotPickupReward(basePlugin, WeaponType.PISTOLS), PROB_VERY_LOW), + (new CannotPickupReward(basePlugin, WeaponType.SNIPERS), PROB_VERY_LOW), + (new CannotPickupReward(basePlugin, WeaponType.HEAVY), PROB_VERY_LOW), + (new RandomTeleportReward(mgr), PROB_VERY_LOW), + (new BombReward(bomb), PROB_VERY_LOW), + + // Extremely low + (new AmmoWeaponReward(basePlugin, "weapon_awp", 1, 0), + PROB_EXTREMELY_LOW), + (new CannotPickupReward(basePlugin, WeaponType.RIFLES), + PROB_EXTREMELY_LOW), + + // Lottery + (new CreditReward(10000), PROB_LOTTERY) + ]); } public IRTDReward GenerateReward(int? id) { - var roll = rng.NextDouble() * totalWeight; + var effectiveTotal = id == null ? + totalWeight : + rewards.Where(reward + => reward.Item1.Enabled && reward.Item1.CanGrantReward(id.Value)) + .Select(reward => reward.Item2) + .Sum(); + var roll = rng.NextDouble() * effectiveTotal; foreach (var reward in rewards.Where(reward => reward.Item1.Enabled)) { - if (id != null && reward.Item1.CanGrantReward(id.Value)) continue; + if (id != null && !reward.Item1.CanGrantReward(id.Value)) continue; roll -= reward.Item2; if (roll <= 0) return reward.Item1; } - throw new InvalidOperationException("No reward was generated."); + throw new InvalidOperationException("No reward was generated. (" + roll + + ")"); } public IEnumerator<(IRTDReward, float)> GetEnumerator() { diff --git a/mod/Jailbreak.RTD/Rewards/CannotScopeReward.cs b/mod/Jailbreak.RTD/Rewards/AbstractOnTickReward.cs similarity index 60% rename from mod/Jailbreak.RTD/Rewards/CannotScopeReward.cs rename to mod/Jailbreak.RTD/Rewards/AbstractOnTickReward.cs index 07f1cee1..dfa9e1f0 100644 --- a/mod/Jailbreak.RTD/Rewards/CannotScopeReward.cs +++ b/mod/Jailbreak.RTD/Rewards/AbstractOnTickReward.cs @@ -5,23 +5,19 @@ namespace Jailbreak.RTD.Rewards; -public class CannotScopeReward : IRTDReward { +public abstract class AbstractOnTickReward : IRTDReward { private readonly HashSet blockedPlayerIDs = []; private readonly BasePlugin plugin; private bool registered; - public CannotScopeReward(BasePlugin plugin, WeaponType blocked) : this(plugin, - blocked.GetItems().ToArray()) { } - - public CannotScopeReward(BasePlugin plugin, params string[] weapons) { + public AbstractOnTickReward(BasePlugin plugin) { this.plugin = plugin; this.plugin.RegisterEventHandler(onRoundEnd); } - public string Name => "Cannot Scope"; - - public string Description => "You will not be able to scope next round."; + public abstract string Name { get; } + public abstract string? Description { get; } public bool GrantReward(CCSPlayerController player) { if (player.UserId == null) return false; @@ -52,18 +48,9 @@ private void onTick() { foreach (var player in blockedPlayerIDs.Select( Utilities.GetPlayerFromUserid)) { if (player == null || player.UserId == null || !player.IsValid) continue; - disableScope(player); + tick(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; - } + abstract protected void tick(CCSPlayerController player); } \ No newline at end of file diff --git a/mod/Jailbreak.RTD/Rewards/AmmoWeaponReward.cs b/mod/Jailbreak.RTD/Rewards/AmmoWeaponReward.cs index f961b291..9856e45f 100644 --- a/mod/Jailbreak.RTD/Rewards/AmmoWeaponReward.cs +++ b/mod/Jailbreak.RTD/Rewards/AmmoWeaponReward.cs @@ -1,5 +1,7 @@ using System.Diagnostics; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Utils; using Jailbreak.Public.Extensions; namespace Jailbreak.RTD.Rewards; @@ -7,17 +9,16 @@ namespace Jailbreak.RTD.Rewards; public class AmmoWeaponReward : WeaponReward { private readonly int primary, secondary; - public AmmoWeaponReward(string weapon, int primary, int secondary) : - base(weapon) { + public AmmoWeaponReward(BasePlugin plugin, string weapon, int primary, + int secondary, CsTeam requiredTeam = CsTeam.Terrorist) : base(plugin, + weapon, requiredTeam) { Trace.Assert(Tag.GUNS.Contains(weapon)); this.primary = primary; this.secondary = secondary; } public override bool GrantReward(CCSPlayerController player) { - var success = base.GrantReward(player); - if (!success) return false; - + player.GiveNamedItem(weapon); player.GetWeaponBase(weapon).SetAmmo(primary, secondary); return true; } diff --git a/mod/Jailbreak.RTD/Rewards/ArmorReward.cs b/mod/Jailbreak.RTD/Rewards/ArmorReward.cs index c2e4413d..f1ddc218 100644 --- a/mod/Jailbreak.RTD/Rewards/ArmorReward.cs +++ b/mod/Jailbreak.RTD/Rewards/ArmorReward.cs @@ -6,7 +6,9 @@ namespace Jailbreak.RTD.Rewards; public class ArmorReward(int armor) : IRTDReward { public string Name => armor + " Armor"; - public string Description => "You won " + armor + " Armor next round."; + + public string Description + => "You will spawn with " + armor + " Armor next round."; public bool GrantReward(CCSPlayerController player) { player.SetArmor(armor); diff --git a/mod/Jailbreak.RTD/Rewards/BombReward.cs b/mod/Jailbreak.RTD/Rewards/BombReward.cs index b005c93b..13457719 100644 --- a/mod/Jailbreak.RTD/Rewards/BombReward.cs +++ b/mod/Jailbreak.RTD/Rewards/BombReward.cs @@ -1,4 +1,5 @@ -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using Jailbreak.Public.Mod.Rebel; using Jailbreak.Public.Mod.RTD; @@ -7,7 +8,7 @@ namespace Jailbreak.RTD.Rewards; public class BombReward(IC4Service bombService) : IRTDReward { public string Name => "Bomb"; - public string Description => "You won the bomb next round."; + public string Description => "You will receive the bomb next round."; public bool PrepareReward(int userid) { bombService.DontGiveC4NextRound(); @@ -19,7 +20,8 @@ public bool CanGrantReward(CCSPlayerController player) { } public bool GrantReward(CCSPlayerController player) { - bombService.TryGiveC4ToPlayer(player); + Server.RunOnTick(Server.TickCount + 64, + () => { bombService.TryGiveC4ToPlayer(player); }); return true; } } \ No newline at end of file diff --git a/mod/Jailbreak.RTD/Rewards/CannotPickupReward.cs b/mod/Jailbreak.RTD/Rewards/CannotPickupReward.cs index 9129cb27..21a2bb12 100644 --- a/mod/Jailbreak.RTD/Rewards/CannotPickupReward.cs +++ b/mod/Jailbreak.RTD/Rewards/CannotPickupReward.cs @@ -9,27 +9,26 @@ namespace Jailbreak.RTD.Rewards; public class CannotPickupReward : IRTDReward { private readonly HashSet blockedPlayerIDs = []; private readonly ImmutableHashSet blockedWeapons; - private readonly BasePlugin plugin; public CannotPickupReward(BasePlugin plugin, WeaponType blocked) : this( plugin, blocked.GetItems().ToArray()) { - Name = $"Cannot Pickup {blocked}"; + NameShort = blocked.ToString(); } public CannotPickupReward(BasePlugin plugin, params string[] weapons) { - this.plugin = plugin; - this.plugin.RegisterEventHandler(onPickup); - this.plugin.RegisterEventHandler(onRoundEnd); + plugin.RegisterEventHandler(onPickup); + plugin.RegisterEventHandler(onRoundEnd); blockedWeapons = weapons.ToImmutableHashSet(); - Name = - $"Cannot Pickup {string.Join(", ", blockedWeapons.Select(s => s.GetFriendlyWeaponName()))}"; + NameShort = string.Join(", ", + blockedWeapons.Select(s => s.GetFriendlyWeaponName())); } - public string Name { get; } + public virtual string Name => $"Cannot Pickup {NameShort}"; + public string NameShort { get; } - public string Description - => $"You will not be able to pickup {Name} next round."; + public virtual string Description + => $"You will not be able to pickup {NameShort} next round."; public bool GrantReward(CCSPlayerController player) { if (player.UserId == null) return false; diff --git a/mod/Jailbreak.RTD/Rewards/CannotRightKnife.cs b/mod/Jailbreak.RTD/Rewards/CannotRightKnife.cs new file mode 100644 index 00000000..3ccb5415 --- /dev/null +++ b/mod/Jailbreak.RTD/Rewards/CannotRightKnife.cs @@ -0,0 +1,28 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using Jailbreak.Public.Extensions; +using Jailbreak.Public.Mod.RTD; + +namespace Jailbreak.RTD.Rewards; + +public class CannotRightKnife(BasePlugin plugin) + : AbstractOnTickReward(plugin) { + private readonly HashSet blockedPlayerIDs = []; + + public override string Name => "Cannot Right-Knife"; + + public override string Description + => "You will not be able to right-click knife next round."; + + override protected void tick(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; + if (activeWeapon.DesignerName != "weapon_knife") return; + activeWeapon.NextSecondaryAttackTick = Server.TickCount + 500; + } +} \ No newline at end of file diff --git a/mod/Jailbreak.RTD/Rewards/CannotScope.cs b/mod/Jailbreak.RTD/Rewards/CannotScope.cs new file mode 100644 index 00000000..8621ceb6 --- /dev/null +++ b/mod/Jailbreak.RTD/Rewards/CannotScope.cs @@ -0,0 +1,25 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using Jailbreak.Public.Extensions; +using Jailbreak.Public.Mod.RTD; + +namespace Jailbreak.RTD.Rewards; + +public class CannotScope(BasePlugin plugin) : AbstractOnTickReward(plugin) { + public override string Name => "Cannot Scope"; + + public override string? Description + => "You will not be able to scope next round."; + + override protected void tick(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; + if (!Tag.SNIPERS.Contains(activeWeapon.DesignerName)) 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 897e7e4f..a727967d 100644 --- a/mod/Jailbreak.RTD/Rewards/ColorReward.cs +++ b/mod/Jailbreak.RTD/Rewards/ColorReward.cs @@ -34,7 +34,7 @@ public char ChatColor public virtual string Name => "Spawn " + ColorName; public virtual string Description - => $"You won spawning {ChatColor}{ColorName}{ChatColors.Grey} next round."; + => $"You will spawn {ChatColor}{ColorName}{ChatColors.Grey} next round."; public bool CanGrantReward(CCSPlayerController player) { return player.Team == CsTeam.Terrorist || !prisonerOnly; diff --git a/mod/Jailbreak.RTD/Rewards/GuaranteedWardenReward.cs b/mod/Jailbreak.RTD/Rewards/GuaranteedWardenReward.cs index 0ba4aa7c..53b9ed09 100644 --- a/mod/Jailbreak.RTD/Rewards/GuaranteedWardenReward.cs +++ b/mod/Jailbreak.RTD/Rewards/GuaranteedWardenReward.cs @@ -10,7 +10,7 @@ public class GuaranteedWardenReward(IWardenSelectionService service) public string Name => "Guaranteed Warden"; public string Description - => "You are guaranteed to be warden next round if you queue for it"; + => "You are guaranteed to be the warden next round if you queue for it."; public bool CanGrantReward(CCSPlayerController player) { return player.Team == CsTeam.CounterTerrorist; diff --git a/mod/Jailbreak.RTD/Rewards/NoWeaponReward.cs b/mod/Jailbreak.RTD/Rewards/NoWeaponReward.cs index b48b2f00..f2f47acb 100644 --- a/mod/Jailbreak.RTD/Rewards/NoWeaponReward.cs +++ b/mod/Jailbreak.RTD/Rewards/NoWeaponReward.cs @@ -1,4 +1,5 @@ -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; using Jailbreak.Public.Mod.RTD; namespace Jailbreak.RTD.Rewards; @@ -8,7 +9,13 @@ public class NoWeaponReward : IRTDReward { public string Description => "You will not spawn with a knife next round."; public bool GrantReward(CCSPlayerController player) { - player.RemoveWeapons(); + foreach (var offset in (int[]) [64, 128, 256]) { + Server.RunOnTick(Server.TickCount + offset, () => { + if (!player.IsValid) return; + player.RemoveWeapons(); + }); + } + return true; } } \ No newline at end of file diff --git a/mod/Jailbreak.RTD/Rewards/TransparentReward.cs b/mod/Jailbreak.RTD/Rewards/TransparentReward.cs index dfe54b7a..da618116 100644 --- a/mod/Jailbreak.RTD/Rewards/TransparentReward.cs +++ b/mod/Jailbreak.RTD/Rewards/TransparentReward.cs @@ -7,5 +7,5 @@ public class TransparentReward() public override string Name => "Spawn Transparent"; public override string Description - => "You won spawning transparent next round."; + => "You will spawn transparent next round."; } \ No newline at end of file diff --git a/mod/Jailbreak.RTD/Rewards/WeaponReward.cs b/mod/Jailbreak.RTD/Rewards/WeaponReward.cs index a4bbf1e4..b1257f9f 100644 --- a/mod/Jailbreak.RTD/Rewards/WeaponReward.cs +++ b/mod/Jailbreak.RTD/Rewards/WeaponReward.cs @@ -1,17 +1,22 @@ using System.Diagnostics; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using Jailbreak.Public.Extensions; using Jailbreak.Public.Mod.RTD; +using Jailbreak.Validator; namespace Jailbreak.RTD.Rewards; public class WeaponReward : IRTDReward { protected readonly string weapon; + protected CsTeam? requiredTeam; - public WeaponReward(string weapon) { - this.weapon = weapon; - Trace.Assert(Tag.GUNS.Contains(weapon)); + public WeaponReward(BasePlugin plugin, string weapon, + CsTeam? requiredTeam = CsTeam.Terrorist) { + this.requiredTeam = requiredTeam; + this.weapon = weapon; + Trace.Assert(new ItemValidator().Validate(weapon, out var error), error); } public string Name => weapon.GetFriendlyWeaponName(); @@ -22,11 +27,12 @@ public string Description + weapon.GetFriendlyWeaponName() + " next round."; public bool CanGrantReward(CCSPlayerController player) { - // No point in giving a weapon to someone on CT - return player.Team == CsTeam.Terrorist; + if (requiredTeam == null) return true; + return player.Team == requiredTeam; } public virtual bool GrantReward(CCSPlayerController player) { + if (!player.IsValid) return false; player.GiveNamedItem(weapon); return true; } diff --git a/public/Jailbreak.Public/Mod/RTD/IRTDReward.cs b/public/Jailbreak.Public/Mod/RTD/IRTDReward.cs index 61a692a8..a5fd017a 100644 --- a/public/Jailbreak.Public/Mod/RTD/IRTDReward.cs +++ b/public/Jailbreak.Public/Mod/RTD/IRTDReward.cs @@ -5,7 +5,7 @@ namespace Jailbreak.Public.Mod.RTD; public interface IRTDReward { public string Name { get; } - public string Description { get; } + public string? Description { get; } bool Enabled => true; bool CanGrantReward(int userid) { diff --git a/public/Jailbreak.Tag/Tag.cs b/public/Jailbreak.Tag/Tag.cs index 3abffad6..a1d1e389 100644 --- a/public/Jailbreak.Tag/Tag.cs +++ b/public/Jailbreak.Tag/Tag.cs @@ -25,11 +25,6 @@ public static class Tag { "weapon_awp", "weapon_ssg08", "weapon_scar20", "weapon_g3sg1" ]); - public static readonly IReadOnlySet RIFLES = new HashSet([ - "weapon_ak47", "weapon_aug", "weapon_famas", "weapon_galilar", - "weapon_m4a1", "weapon_m4a1_silencer", "weapon_sg556" - ]); - public static readonly IReadOnlySet PISTOLS = new HashSet([ "weapon_deagle", "weapon_elite", "weapon_fiveseven", "weapon_glock", "weapon_hkp2000", "weapon_p250", "weapon_usp_silencer", "weapon_tec9", @@ -49,11 +44,17 @@ public static class Tag { "weapon_negev", "weapon_m249" ]); - public static readonly IReadOnlySet GUNS = RIFLES.Union(PISTOLS) + public static readonly IReadOnlySet RIFLES = new HashSet([ + "weapon_ak47", "weapon_aug", "weapon_famas", "weapon_galilar", + "weapon_m4a1", "weapon_m4a1_silencer", "weapon_sg556" + ]).Union(SNIPERS) .Union(SHOTGUNS) .Union(SMGS) .Union(HEAVY) - .Union(SNIPERS) + .ToHashSet(); + + public static readonly IReadOnlySet GUNS = RIFLES.Union(PISTOLS) + .Union(RIFLES) .ToHashSet(); public static readonly IReadOnlySet WEAPONS = diff --git a/public/Jailbreak.Tag/WeaponType.cs b/public/Jailbreak.Tag/WeaponType.cs index 9d965a73..4fbbb4fd 100644 --- a/public/Jailbreak.Tag/WeaponType.cs +++ b/public/Jailbreak.Tag/WeaponType.cs @@ -16,10 +16,6 @@ public static class WeaponTypeExtensions { public static IReadOnlySet GetItems(this WeaponType type) { var result = new HashSet(); - foreach (var t in Enum.GetValues()) - if (type.HasFlag(t)) - result.UnionWith(t.GetItems()); - switch (type) { case WeaponType.GUNS: return Tag.GUNS; From c2b0f3026111f35d4249fd7aea65d3f23e14dcb0 Mon Sep 17 00:00:00 2001 From: MSWS Date: Wed, 28 Aug 2024 03:22:09 -0700 Subject: [PATCH 12/19] Fix tp --- mod/Jailbreak.RTD/Rewards/RandomTeleportReward.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mod/Jailbreak.RTD/Rewards/RandomTeleportReward.cs b/mod/Jailbreak.RTD/Rewards/RandomTeleportReward.cs index ef18125a..1e2c334b 100644 --- a/mod/Jailbreak.RTD/Rewards/RandomTeleportReward.cs +++ b/mod/Jailbreak.RTD/Rewards/RandomTeleportReward.cs @@ -19,7 +19,9 @@ public bool CanGrantReward(CCSPlayerController player) { public bool GrantReward(CCSPlayerController player) { var zone = MapUtil.GetRandomSpawns(1, zones).FirstOrDefault(); if (zone == null) return false; - player.Teleport(zone); + var pawn = player.Pawn.Value; + if (pawn == null || !pawn.IsValid) return false; + pawn.Teleport(zone); return true; } } \ No newline at end of file From caed34055d6ac1695e30b2ba1bf25fa13dd125fd Mon Sep 17 00:00:00 2001 From: MSWS Date: Wed, 28 Aug 2024 03:24:55 -0700 Subject: [PATCH 13/19] Add config for RTD --- lang/Jailbreak.English/RTD/RTDLocale.cs | 6 +++++- mod/Jailbreak.RTD/RTDCommand.cs | 9 +++++++++ public/Jailbreak.Formatting/Views/IRTDLocale.cs | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lang/Jailbreak.English/RTD/RTDLocale.cs b/lang/Jailbreak.English/RTD/RTDLocale.cs index b9997875..cf066f34 100644 --- a/lang/Jailbreak.English/RTD/RTDLocale.cs +++ b/lang/Jailbreak.English/RTD/RTDLocale.cs @@ -37,7 +37,11 @@ public IView AlreadyRolled(IRTDReward reward) { public IView CannotRollYet() { return new SimpleView { PREFIX, - ChatColors.Red + "You can only roll once the round ends or you die." + ChatColors.Red + "You can only roll when round ends or while dead." }; } + + public IView RollingDisabled() { + return new SimpleView { PREFIX, ChatColors.Red + "Rolling is disabled." }; + } } \ No newline at end of file diff --git a/mod/Jailbreak.RTD/RTDCommand.cs b/mod/Jailbreak.RTD/RTDCommand.cs index 634b6562..6ebebe84 100644 --- a/mod/Jailbreak.RTD/RTDCommand.cs +++ b/mod/Jailbreak.RTD/RTDCommand.cs @@ -2,6 +2,7 @@ using CounterStrikeSharp.API.Core.Attributes.Registration; using CounterStrikeSharp.API.Modules.Admin; using CounterStrikeSharp.API.Modules.Commands; +using CounterStrikeSharp.API.Modules.Cvars; using Jailbreak.Formatting.Extensions; using Jailbreak.Formatting.Views; using Jailbreak.Public.Behaviors; @@ -12,6 +13,9 @@ namespace Jailbreak.RTD; public class RTDCommand(IRTDRewarder rewarder, IRewardGenerator generator, IRTDLocale locale, IGenericCmdLocale generic) : IPluginBehavior { + public static readonly FakeConVar CV_RTD_ENABLED = + new("css_jb_rtd_enabled", "Whether to allow dice rolling", true); + private bool inBetweenRounds; [ConsoleCommand("css_rtd", "Roll the dice!")] @@ -26,6 +30,11 @@ public void Command_RTD(CCSPlayerController? executor, CommandInfo info) { return; } + if (!bypass && !CV_RTD_ENABLED.Value) { + locale.RollingDisabled().ToChat(executor); + return; + } + if (!bypass && !inBetweenRounds && !RoundUtil.IsWarmup() && executor.PawnIsAlive) { locale.CannotRollYet().ToChat(executor); diff --git a/public/Jailbreak.Formatting/Views/IRTDLocale.cs b/public/Jailbreak.Formatting/Views/IRTDLocale.cs index 0eb25539..f4ee3449 100644 --- a/public/Jailbreak.Formatting/Views/IRTDLocale.cs +++ b/public/Jailbreak.Formatting/Views/IRTDLocale.cs @@ -7,4 +7,5 @@ public interface IRTDLocale { public IView RewardSelected(IRTDReward reward); public IView AlreadyRolled(IRTDReward reward); public IView CannotRollYet(); + public IView RollingDisabled(); } \ No newline at end of file From 2e576a2e38595c4110e8d4b9548d47c442f77748 Mon Sep 17 00:00:00 2001 From: MSWS Date: Wed, 28 Aug 2024 03:41:02 -0700 Subject: [PATCH 14/19] Fine-tune transparency amount --- mod/Jailbreak.Debug/DebugCommand.cs | 1 + mod/Jailbreak.RTD/Rewards/TransparentReward.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mod/Jailbreak.Debug/DebugCommand.cs b/mod/Jailbreak.Debug/DebugCommand.cs index bf945f7a..dba884c8 100644 --- a/mod/Jailbreak.Debug/DebugCommand.cs +++ b/mod/Jailbreak.Debug/DebugCommand.cs @@ -28,6 +28,7 @@ public void Start(BasePlugin basePlugin) { commands.Add("settime", new DebugSetTime(serviceProvider)); commands.Add("centerhud", new DebugCenterHud(serviceProvider)); commands.Add("csay", new DebugCSay(serviceProvider)); + commands.Add("color", new DebugColor(serviceProvider)); } [RequiresPermissions("@css/root")] diff --git a/mod/Jailbreak.RTD/Rewards/TransparentReward.cs b/mod/Jailbreak.RTD/Rewards/TransparentReward.cs index da618116..f316eaec 100644 --- a/mod/Jailbreak.RTD/Rewards/TransparentReward.cs +++ b/mod/Jailbreak.RTD/Rewards/TransparentReward.cs @@ -3,7 +3,7 @@ namespace Jailbreak.RTD.Rewards; public class TransparentReward() - : ColorReward(Color.FromArgb(128, 255, 255, 255), false) { + : ColorReward(Color.FromArgb(70, 255, 255, 255), false) { public override string Name => "Spawn Transparent"; public override string Description From bc31dee3481ee5e44d87d1135c2a19c81a51b0d7 Mon Sep 17 00:00:00 2001 From: MSWS Date: Wed, 28 Aug 2024 04:00:41 -0700 Subject: [PATCH 15/19] Grey out stay in cells message --- .../SpecialDays/AbstractArmoryRestrictedDay.cs | 5 +++-- .../SpecialDays/AbstractCellRestrictedDay.cs | 5 +++-- mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs | 7 +++---- .../Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs | 5 ++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/AbstractArmoryRestrictedDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/AbstractArmoryRestrictedDay.cs index bc75c72a..221ec87a 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/AbstractArmoryRestrictedDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/AbstractArmoryRestrictedDay.cs @@ -24,9 +24,10 @@ protected AbstractArmoryRestrictedDay(BasePlugin plugin, public virtual IView ArmoryReminder => this is ISpecialDayMessageProvider messaged ? new SimpleView { - SDLocale.PREFIX, $"Today is {messaged.Locale.Name}, so stay in armory!" + SDLocale.PREFIX, + $"{ChatColors.Grey}Today is {ChatColors.White}{messaged.Locale.Name}{ChatColors.Grey}, so stay in armory!" } : - new SimpleView { SDLocale.PREFIX, "Stay in armory!" }; + new SimpleView { SDLocale.PREFIX, ChatColors.Grey + "Stay in armory!" }; override protected IZone GetZone() { diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/AbstractCellRestrictedDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/AbstractCellRestrictedDay.cs index ec58eaba..9245156e 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/AbstractCellRestrictedDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/AbstractCellRestrictedDay.cs @@ -24,9 +24,10 @@ protected AbstractCellRestrictedDay(BasePlugin plugin, public virtual IView CellReminder => this is ISpecialDayMessageProvider messaged ? new SimpleView { - SDLocale.PREFIX, $"Today is {messaged.Locale.Name}, so stay in cells!" + SDLocale.PREFIX, + $"{ChatColors.Grey}Today is {ChatColors.White}{messaged.Locale.Name}{ChatColors.Grey}, so stay in cells!" } : - new SimpleView { SDLocale.PREFIX, "Stay in cells!" }; + new SimpleView { SDLocale.PREFIX, ChatColors.Grey + "Stay in cells!" }; override protected IZone GetZone() { var manager = provider.GetRequiredService(); diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs index 8001a103..48948492 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs @@ -55,14 +55,13 @@ public override void Execute() { override protected HookResult OnPickup(EventItemPickup @event, GameEventInfo info) { - var result = base.OnPickup(@event, info); - if (!started) return result; + if (!started) return base.OnPickup(@event, info); var player = @event.Userid; - if (player == null || !player.IsValid) return result; + if (player == null || !player.IsValid) return HookResult.Continue; player.RemoveWeapons(); player.SetHealth(1); - return result; + return HookResult.Continue; } private HookResult diff --git a/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs b/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs index 93714843..4dcb133d 100644 --- a/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs +++ b/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs @@ -277,9 +277,8 @@ virtual protected HookResult OnPickup(EventItemPickup @event, if (player == null || !player.IsValid) return HookResult.Continue; var allowed = Settings.AllowedWeapons(player); var weapon = "weapon_" + @event.Item; - if (allowed == null || allowed.Contains(@event.Item)) - return HookResult.Continue; - player.RemoveItemByDesignerName(weapon, true); + if (allowed == null || allowed.Contains(weapon)) return HookResult.Continue; + Server.NextFrame(() => { player.RemoveItemByDesignerName(weapon); }); return HookResult.Continue; } From 08312e8ab8533e0c8324d6db138c6ec86e660cf8 Mon Sep 17 00:00:00 2001 From: MSWS Date: Wed, 28 Aug 2024 04:02:01 -0700 Subject: [PATCH 16/19] Increase LR start delay for weaponized requests --- mod/Jailbreak.LastRequest/LastRequests/WeaponizedRequest.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mod/Jailbreak.LastRequest/LastRequests/WeaponizedRequest.cs b/mod/Jailbreak.LastRequest/LastRequests/WeaponizedRequest.cs index f96f2146..b0d13682 100644 --- a/mod/Jailbreak.LastRequest/LastRequests/WeaponizedRequest.cs +++ b/mod/Jailbreak.LastRequest/LastRequests/WeaponizedRequest.cs @@ -21,13 +21,13 @@ public override void Setup() { Prisoner.RemoveWeapons(); Guard.RemoveWeapons(); var msgs = provider.GetRequiredService(); - for (var i = 3; i >= 1; i--) { + for (var i = 5; i >= 1; i--) { var copy = i; - Plugin.AddTimer(3 - i, + Plugin.AddTimer(5 - i, () => { msgs.LastRequestCountdown(copy).ToChat(Prisoner, Guard); }); } - Plugin.AddTimer(3, () => { + Plugin.AddTimer(5, () => { if (State != LRState.PENDING) return; Execute(); }); From c76daad172efcb2907378d31fba83adee7fb2f9f Mon Sep 17 00:00:00 2001 From: MSWS Date: Wed, 28 Aug 2024 04:35:57 -0700 Subject: [PATCH 17/19] Add rebel / st color overlay --- mod/Jailbreak.Rebel/RebelManager.cs | 25 ++--------------- .../SpecialTreatmentBehavior.cs | 4 +++ .../Extensions/PlayerExtensions.cs | 28 +++++++++++++++++++ .../Jailbreak.Public/Jailbreak.Public.csproj | 2 +- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/mod/Jailbreak.Rebel/RebelManager.cs b/mod/Jailbreak.Rebel/RebelManager.cs index 1fd76c33..00a170a3 100644 --- a/mod/Jailbreak.Rebel/RebelManager.cs +++ b/mod/Jailbreak.Rebel/RebelManager.cs @@ -31,7 +31,6 @@ public void Start(BasePlugin basePlugin) { basePlugin.RegisterEventHandler(OnPlayerDisconnect); basePlugin.RegisterEventHandler(OnPlayerDeath); basePlugin.RegisterEventHandler(OnRoundStart); - basePlugin.RegisterListener(OnTick); basePlugin.AddTimer(1f, () => { foreach (var player in GetActiveRebels()) { @@ -45,7 +44,6 @@ public void Start(BasePlugin basePlugin) { } applyRebelColor(player); - sendTimeLeft(player); } }, TimerFlags.REPEAT); } @@ -90,16 +88,6 @@ public void UnmarkRebel(CCSPlayerController player) { public void DisableRebelForRound() { enabled = false; } - private void OnTick() { - foreach (var player in GetActiveRebels()) { - if (!player.IsReal()) continue; - - if (GetRebelTimeLeft(player) <= 0) continue; - - sendTimeLeft(player); - } - } - private HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info) { enabled = true; rebelTimes.Clear(); @@ -151,16 +139,9 @@ private void applyRebelColor(CCSPlayerController player) { player.Pawn.Value.Render = color; Utilities.SetStateChanged(player.Pawn.Value, "CBaseModelEntity", "m_clrRender"); - } - - private void sendTimeLeft(CCSPlayerController player) { - // var timeLeft = GetRebelTimeLeft(player); - // var formattedTime = TimeSpan.FromSeconds(timeLeft).ToString(@"mm\:ss"); - var color = getRebelColor(player); - var formattedColor = - $""; - player.PrintToCenterHtml( - $"You are {formattedColor}rebelling"); + player.ColorScreen( + Color.FromArgb(8 + (int)Math.Round(getRebelTimePercentage(player) * 32), + Color.Red), 1f, 1.5f, PlayerExtensions.FadeFlags.FADE_OUT); } } \ No newline at end of file diff --git a/mod/Jailbreak.Warden/SpecialTreatment/SpecialTreatmentBehavior.cs b/mod/Jailbreak.Warden/SpecialTreatment/SpecialTreatmentBehavior.cs index 9cf2e9a8..73fdf8ca 100644 --- a/mod/Jailbreak.Warden/SpecialTreatment/SpecialTreatmentBehavior.cs +++ b/mod/Jailbreak.Warden/SpecialTreatment/SpecialTreatmentBehavior.cs @@ -4,6 +4,7 @@ using Jailbreak.Formatting.Extensions; using Jailbreak.Formatting.Views.Warden; using Jailbreak.Public.Behaviors; +using Jailbreak.Public.Extensions; using Jailbreak.Public.Generic; using Jailbreak.Public.Mod.Rebel; using Jailbreak.Public.Mod.Warden; @@ -28,6 +29,8 @@ public void Grant(CCSPlayerController player) { if (rebel.IsRebel(player)) rebel.UnmarkRebel(player); setSpecialColor(player, true); + player.ColorScreen(Color.FromArgb(16, 0, 255, 0), 999999, 0.2f, + PlayerExtensions.FadeFlags.FADE_OUT); notifications.Granted.ToChat(player).ToCenter(player); @@ -41,6 +44,7 @@ public void Revoke(CCSPlayerController player) { sts.Get(player).HasSpecialTreatment = false; setSpecialColor(player, false); + player.ColorScreen(Color.FromArgb(16, 0, 255, 0), 0f, 1.5f); notifications.Revoked.ToChat(player).ToCenter(player); diff --git a/public/Jailbreak.Public/Extensions/PlayerExtensions.cs b/public/Jailbreak.Public/Extensions/PlayerExtensions.cs index 4713d6c4..2afed6d6 100644 --- a/public/Jailbreak.Public/Extensions/PlayerExtensions.cs +++ b/public/Jailbreak.Public/Extensions/PlayerExtensions.cs @@ -2,6 +2,7 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Memory; +using CounterStrikeSharp.API.Modules.UserMessages; using CounterStrikeSharp.API.Modules.Utils; namespace Jailbreak.Public.Extensions; @@ -149,4 +150,31 @@ public static void SetColor(this CCSPlayerController player, Color color) { .FirstOrDefault(w => w.Value?.DesignerName == designerName) ?.Value; } + + public enum FadeFlags { + FADE_IN, FADE_OUT, FADE_STAYOUT + } + + public static void ColorScreen(this CCSPlayerController player, Color color, + float hold = 0.1f, float fade = 0.2f, FadeFlags flags = FadeFlags.FADE_IN, + bool withPurge = true) { + var fadeMsg = UserMessage.FromId(106); + + fadeMsg.SetInt("duration", Convert.ToInt32(fade * 512)); + fadeMsg.SetInt("hold_time", Convert.ToInt32(hold * 512)); + + var flag = flags switch { + FadeFlags.FADE_IN => 0x0001, + FadeFlags.FADE_OUT => 0x0002, + FadeFlags.FADE_STAYOUT => 0x0008, + _ => 0x0001 + }; + + if (withPurge) flag |= 0x0010; + + fadeMsg.SetInt("flags", flag); + fadeMsg.SetInt("color", + color.R | color.G << 8 | color.B << 16 | color.A << 24); + fadeMsg.Send(player); + } } \ No newline at end of file diff --git a/public/Jailbreak.Public/Jailbreak.Public.csproj b/public/Jailbreak.Public/Jailbreak.Public.csproj index 029c9835..ee3295a2 100644 --- a/public/Jailbreak.Public/Jailbreak.Public.csproj +++ b/public/Jailbreak.Public/Jailbreak.Public.csproj @@ -7,7 +7,7 @@ - + From ae68386f5adab9f089b40b3b4fe468ee40b49140 Mon Sep 17 00:00:00 2001 From: MSWS Date: Wed, 28 Aug 2024 04:52:35 -0700 Subject: [PATCH 18/19] Add soccer and chicken cmd --- .../Warden/WardenCmdChickenLocale.cs | 25 +++++++++ .../Warden/WardenCmdSoccerLocale.cs | 26 +++++++++ .../Commands/ChickenCommandBehavior.cs | 51 +++++++++++++++++ .../Commands/SoccerCommandBehavior.cs | 56 +++++++++++++++++++ .../WardenServiceExtension.cs | 2 + .../Views/Warden/IWardenCmdChickenLocale.cs | 9 +++ .../Views/Warden/IWardenCmdSoccerLocale.cs | 9 +++ src/Jailbreak/JailbreakServiceCollection.cs | 5 ++ 8 files changed, 183 insertions(+) create mode 100644 lang/Jailbreak.English/Warden/WardenCmdChickenLocale.cs create mode 100644 lang/Jailbreak.English/Warden/WardenCmdSoccerLocale.cs create mode 100644 mod/Jailbreak.Warden/Commands/ChickenCommandBehavior.cs create mode 100644 mod/Jailbreak.Warden/Commands/SoccerCommandBehavior.cs create mode 100644 public/Jailbreak.Formatting/Views/Warden/IWardenCmdChickenLocale.cs create mode 100644 public/Jailbreak.Formatting/Views/Warden/IWardenCmdSoccerLocale.cs diff --git a/lang/Jailbreak.English/Warden/WardenCmdChickenLocale.cs b/lang/Jailbreak.English/Warden/WardenCmdChickenLocale.cs new file mode 100644 index 00000000..3097b622 --- /dev/null +++ b/lang/Jailbreak.English/Warden/WardenCmdChickenLocale.cs @@ -0,0 +1,25 @@ +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Utils; +using Jailbreak.Formatting.Base; +using Jailbreak.Formatting.Logistics; +using Jailbreak.Formatting.Views.Warden; +using Jailbreak.Public.Mod.Warden; + +namespace Jailbreak.English.Warden; + +public class WardenCmdChickenLocale : IWardenCmdChickenLocale, + ILanguage { + public IView ChickenSpawned + => new SimpleView { + WardenLocale.PREFIX, + ChatColors.Blue + "The warden" + ChatColors.Grey + " spawned a chicken." + }; + + public IView SpawnFailed + => new SimpleView { + WardenLocale.PREFIX, ChatColors.Red + "Failed to spawn a chicken." + }; + + public IView TooManyChickens + => new SimpleView { WardenLocale.PREFIX, "Too many chickens." }; +} \ No newline at end of file diff --git a/lang/Jailbreak.English/Warden/WardenCmdSoccerLocale.cs b/lang/Jailbreak.English/Warden/WardenCmdSoccerLocale.cs new file mode 100644 index 00000000..aa0e0f3f --- /dev/null +++ b/lang/Jailbreak.English/Warden/WardenCmdSoccerLocale.cs @@ -0,0 +1,26 @@ +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Utils; +using Jailbreak.Formatting.Base; +using Jailbreak.Formatting.Logistics; +using Jailbreak.Formatting.Views.Warden; +using Jailbreak.Public.Mod.Warden; + +namespace Jailbreak.English.Warden; + +public class WardenCmdSoccerLocale : IWardenCmdSoccerLocale, + ILanguage { + public IView SoccerSpawned + => new SimpleView { + WardenLocale.PREFIX, + ChatColors.Blue + "The warden" + ChatColors.Grey + + " spawned a soccer ball." + }; + + public IView SpawnFailed + => new SimpleView { + WardenLocale.PREFIX, ChatColors.Red + "Failed to spawn a soccer ball." + }; + + public IView TooManySoccers + => new SimpleView { WardenLocale.PREFIX, "Too many soccer balls." }; +} \ No newline at end of file diff --git a/mod/Jailbreak.Warden/Commands/ChickenCommandBehavior.cs b/mod/Jailbreak.Warden/Commands/ChickenCommandBehavior.cs new file mode 100644 index 00000000..363c4a1a --- /dev/null +++ b/mod/Jailbreak.Warden/Commands/ChickenCommandBehavior.cs @@ -0,0 +1,51 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core.Attributes.Registration; +using CounterStrikeSharp.API.Modules.Commands; +using CounterStrikeSharp.API.Modules.Cvars; +using Jailbreak.Formatting.Extensions; +using Jailbreak.Formatting.Views.Warden; +using Jailbreak.Public.Behaviors; +using Jailbreak.Public.Mod.Warden; + +namespace Jailbreak.Warden.Commands; + +public class ChickenCommandBehavior(IWardenService warden, + IWardenLocale wardenLocale, IWardenCmdChickenLocale locale) + : IPluginBehavior { + public static readonly FakeConVar CV_MAX_CHICKENS = + new("css_jb_max_chickens", + "The maximum number of chickens that the warden can spawn", 5); + + private int chickens = 0; + + [GameEventHandler] + public HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info) { + chickens = 0; + return HookResult.Continue; + } + + [ConsoleCommand("css_chicken", "Spawn a chicken as the warden")] + public void Command_Toggle(CCSPlayerController? player, CommandInfo command) { + if (player == null) return; + + if (!warden.IsWarden(player)) { + wardenLocale.NotWarden.ToChat(player); + return; + } + + if (chickens >= CV_MAX_CHICKENS.Value) { + locale.TooManyChickens.ToChat(player); + return; + } + + var chicken = Utilities.CreateEntityByName("chicken"); + if (chicken == null || !chicken.IsValid) { + locale.SpawnFailed.ToChat(player); + return; + } + chicken.Teleport(player.AbsOrigin); + locale.ChickenSpawned.ToAllChat(); + chicken.DispatchSpawn(); + } +} \ No newline at end of file diff --git a/mod/Jailbreak.Warden/Commands/SoccerCommandBehavior.cs b/mod/Jailbreak.Warden/Commands/SoccerCommandBehavior.cs new file mode 100644 index 00000000..51554a62 --- /dev/null +++ b/mod/Jailbreak.Warden/Commands/SoccerCommandBehavior.cs @@ -0,0 +1,56 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core.Attributes.Registration; +using CounterStrikeSharp.API.Modules.Commands; +using CounterStrikeSharp.API.Modules.Cvars; +using Jailbreak.Formatting.Extensions; +using Jailbreak.Formatting.Views.Warden; +using Jailbreak.Public.Behaviors; +using Jailbreak.Public.Mod.Warden; + +namespace Jailbreak.Warden.Commands; + +public class SoccerCommandBehavior(IWardenService warden, + IWardenLocale wardenLocale, IWardenCmdSoccerLocale locale) : IPluginBehavior { + public static readonly FakeConVar CV_MAX_SOCCERS = + new("css_jb_max_soccers", + "The maximum number of soccer balls that the warden can spawn", 3); + + private int soccers = 0; + + [GameEventHandler] + public HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info) { + soccers = 0; + return HookResult.Continue; + } + + [ConsoleCommand("css_soccer", "Spawn a soccer ball as the warden")] + [ConsoleCommand("css_spawnball", "Spawn a soccer ball as the warden")] + public void Command_Toggle(CCSPlayerController? player, CommandInfo command) { + if (player == null) return; + + if (!warden.IsWarden(player)) { + wardenLocale.NotWarden.ToChat(player); + return; + } + + if (soccers >= CV_MAX_SOCCERS.Value) { + locale.TooManySoccers.ToChat(player); + return; + } + + var chicken = + Utilities.CreateEntityByName( + "prop_physics_multiplayer"); + if (chicken == null || !chicken.IsValid) { + locale.SpawnFailed.ToChat(player); + return; + } + + chicken.SetModel( + "models/props/de_dust/hr_dust/dust_soccerball/dust_soccer_ball001.vmdl"); + chicken.Teleport(player.AbsOrigin); + locale.SoccerSpawned.ToAllChat(); + chicken.DispatchSpawn(); + } +} \ No newline at end of file diff --git a/mod/Jailbreak.Warden/WardenServiceExtension.cs b/mod/Jailbreak.Warden/WardenServiceExtension.cs index 07390ef3..78165ffa 100644 --- a/mod/Jailbreak.Warden/WardenServiceExtension.cs +++ b/mod/Jailbreak.Warden/WardenServiceExtension.cs @@ -25,6 +25,8 @@ public static void AddJailbreakWarden( serviceCollection.AddPluginBehavior(); serviceCollection.AddPluginBehavior(); serviceCollection.AddPluginBehavior(); + serviceCollection.AddPluginBehavior(); + serviceCollection.AddPluginBehavior(); serviceCollection.AddPluginBehavior(); serviceCollection.AddPluginBehavior(); diff --git a/public/Jailbreak.Formatting/Views/Warden/IWardenCmdChickenLocale.cs b/public/Jailbreak.Formatting/Views/Warden/IWardenCmdChickenLocale.cs new file mode 100644 index 00000000..06fe11b1 --- /dev/null +++ b/public/Jailbreak.Formatting/Views/Warden/IWardenCmdChickenLocale.cs @@ -0,0 +1,9 @@ +using Jailbreak.Formatting.Base; + +namespace Jailbreak.Formatting.Views.Warden; + +public interface IWardenCmdChickenLocale { + public IView ChickenSpawned { get; } + public IView SpawnFailed { get; } + public IView TooManyChickens { get; } +} \ No newline at end of file diff --git a/public/Jailbreak.Formatting/Views/Warden/IWardenCmdSoccerLocale.cs b/public/Jailbreak.Formatting/Views/Warden/IWardenCmdSoccerLocale.cs new file mode 100644 index 00000000..0e154158 --- /dev/null +++ b/public/Jailbreak.Formatting/Views/Warden/IWardenCmdSoccerLocale.cs @@ -0,0 +1,9 @@ +using Jailbreak.Formatting.Base; + +namespace Jailbreak.Formatting.Views.Warden; + +public interface IWardenCmdSoccerLocale { + public IView SoccerSpawned { get; } + public IView SpawnFailed { get; } + public IView TooManySoccers { get; } +} \ No newline at end of file diff --git a/src/Jailbreak/JailbreakServiceCollection.cs b/src/Jailbreak/JailbreakServiceCollection.cs index 8107ecd2..5d1e6dfd 100644 --- a/src/Jailbreak/JailbreakServiceCollection.cs +++ b/src/Jailbreak/JailbreakServiceCollection.cs @@ -18,6 +18,7 @@ using Jailbreak.LastRequest; using Jailbreak.Logs; using Jailbreak.Mute; +using Jailbreak.Public.Mod.Warden; using Jailbreak.Rebel; using Jailbreak.RTD; using Jailbreak.SpecialDay; @@ -50,6 +51,10 @@ public void ConfigureServices(IServiceCollection serviceCollection) { serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + serviceCollection + .AddSingleton(); + serviceCollection + .AddSingleton(); // Do we want to make this scoped? // Not sure how this will behave with multiple rounds and whatnot. From 4cff50e1323d07f5417ba66323f299e5d6aa48bf Mon Sep 17 00:00:00 2001 From: MSWS Date: Wed, 28 Aug 2024 05:01:01 -0700 Subject: [PATCH 19/19] Fix tp and caps --- .../Commands/ChickenCommandBehavior.cs | 11 ++++++++++- .../Commands/SoccerCommandBehavior.cs | 8 +++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/mod/Jailbreak.Warden/Commands/ChickenCommandBehavior.cs b/mod/Jailbreak.Warden/Commands/ChickenCommandBehavior.cs index 363c4a1a..89b12ecb 100644 --- a/mod/Jailbreak.Warden/Commands/ChickenCommandBehavior.cs +++ b/mod/Jailbreak.Warden/Commands/ChickenCommandBehavior.cs @@ -6,6 +6,7 @@ using Jailbreak.Formatting.Extensions; using Jailbreak.Formatting.Views.Warden; using Jailbreak.Public.Behaviors; +using Jailbreak.Public.Extensions; using Jailbreak.Public.Mod.Warden; namespace Jailbreak.Warden.Commands; @@ -44,8 +45,16 @@ public void Command_Toggle(CCSPlayerController? player, CommandInfo command) { locale.SpawnFailed.ToChat(player); return; } - chicken.Teleport(player.AbsOrigin); + + var loc = player.Pawn.Value?.AbsOrigin; + if (loc == null) { + locale.SpawnFailed.ToChat(player); + return; + } + + chicken.Teleport(loc); locale.ChickenSpawned.ToAllChat(); chicken.DispatchSpawn(); + chickens++; } } \ No newline at end of file diff --git a/mod/Jailbreak.Warden/Commands/SoccerCommandBehavior.cs b/mod/Jailbreak.Warden/Commands/SoccerCommandBehavior.cs index 51554a62..7198e7d3 100644 --- a/mod/Jailbreak.Warden/Commands/SoccerCommandBehavior.cs +++ b/mod/Jailbreak.Warden/Commands/SoccerCommandBehavior.cs @@ -47,10 +47,16 @@ public void Command_Toggle(CCSPlayerController? player, CommandInfo command) { return; } + var loc = player.Pawn.Value?.AbsOrigin; + if (loc == null) { + locale.SpawnFailed.ToChat(player); + return; + } chicken.SetModel( "models/props/de_dust/hr_dust/dust_soccerball/dust_soccer_ball001.vmdl"); - chicken.Teleport(player.AbsOrigin); + chicken.Teleport(loc); locale.SoccerSpawned.ToAllChat(); chicken.DispatchSpawn(); + soccers++; } } \ No newline at end of file