From 1cc4ebcb2b474d2ff006238e6ce9a1c4ab1274f2 Mon Sep 17 00:00:00 2001 From: MSWS Date: Fri, 1 Nov 2024 13:40:12 -0700 Subject: [PATCH 01/17] Add more stat tracking --- mod/Gangs.BaseImpl/Stats/LGStat.cs | 14 +++ mod/Gangs.BaseImpl/Stats/LRStat.cs | 16 +++ mod/Gangs.BaseImpl/Stats/WardenStat.cs | 17 +++ .../Jailbreak.LastGuard.csproj | 4 + mod/Jailbreak.LastGuard/LastGuard.cs | 40 ++++++- .../Jailbreak.LastRequest.csproj | 1 + .../LastRequestManager.cs | 33 +++++- mod/Jailbreak.RTD/Rewards/CreditReward.cs | 2 +- mod/Jailbreak.Warden/Global/WardenBehavior.cs | 110 +++++++++++++++++- mod/Jailbreak.Warden/Jailbreak.Warden.csproj | 3 + public/Jailbreak.Public/Mixin/GangsAPI.dll | Bin 68096 -> 69120 bytes 11 files changed, 228 insertions(+), 12 deletions(-) create mode 100644 mod/Gangs.BaseImpl/Stats/LGStat.cs create mode 100644 mod/Gangs.BaseImpl/Stats/LRStat.cs create mode 100644 mod/Gangs.BaseImpl/Stats/WardenStat.cs diff --git a/mod/Gangs.BaseImpl/Stats/LGStat.cs b/mod/Gangs.BaseImpl/Stats/LGStat.cs new file mode 100644 index 00000000..62d46138 --- /dev/null +++ b/mod/Gangs.BaseImpl/Stats/LGStat.cs @@ -0,0 +1,14 @@ +namespace Gangs.BaseImpl.Stats; + +public class LGStat : BaseStat { + public const string STAT_ID = "jb_lg_stat"; + public override string StatId => STAT_ID; + public override string Name => "LGs"; + public override string? Description => "LGs reached"; + public override LGData? Value { get; set; } +} + +public class LGData { + public int CtLgs { get; set; } + public int TLgs { get; set; } +} \ No newline at end of file diff --git a/mod/Gangs.BaseImpl/Stats/LRStat.cs b/mod/Gangs.BaseImpl/Stats/LRStat.cs new file mode 100644 index 00000000..85da5f15 --- /dev/null +++ b/mod/Gangs.BaseImpl/Stats/LRStat.cs @@ -0,0 +1,16 @@ +namespace Gangs.BaseImpl.Stats; + +public class LRStat : BaseStat { + public const string STAT_ID = "jb_lr_stat"; + public override string StatId => STAT_ID; + public override string Name => "LRs"; + public override string? Description => "LRs reached"; + public override LRData? Value { get; set; } +} + +public class LRData { + public int CtLrs { get; set; } + public int TLrs { get; set; } + + public override string ToString() { return $"{CtLrs}/{TLrs}"; } +} \ No newline at end of file diff --git a/mod/Gangs.BaseImpl/Stats/WardenStat.cs b/mod/Gangs.BaseImpl/Stats/WardenStat.cs new file mode 100644 index 00000000..c76c6147 --- /dev/null +++ b/mod/Gangs.BaseImpl/Stats/WardenStat.cs @@ -0,0 +1,17 @@ +namespace Gangs.BaseImpl.Stats; + +public class WardenStat : BaseStat { + public const string STAT_ID = "jb_warden_stat"; + public override string StatId => STAT_ID; + public override string Name => "Guard"; + public override string? Description => "Stats revolving CT specific info"; + public override WardenData? Value { get; set; } +} + +public class WardenData { + public int TimesWardened { get; set; } + public int WardenDeaths { get; set; } + public int WardensKilled { get; set; } + public int GuardDeathsAsWarden { get; set; } + public int WardenDeathsAsGuard { get; set; } +} \ No newline at end of file diff --git a/mod/Jailbreak.LastGuard/Jailbreak.LastGuard.csproj b/mod/Jailbreak.LastGuard/Jailbreak.LastGuard.csproj index 582d2260..efe45b90 100644 --- a/mod/Jailbreak.LastGuard/Jailbreak.LastGuard.csproj +++ b/mod/Jailbreak.LastGuard/Jailbreak.LastGuard.csproj @@ -10,9 +10,13 @@ + + + ..\..\public\Jailbreak.Public\Mixin\GangsAPI.dll + ..\..\public\Jailbreak.Public\Mixin\MStatsShared.dll diff --git a/mod/Jailbreak.LastGuard/LastGuard.cs b/mod/Jailbreak.LastGuard/LastGuard.cs index b0e0c1fb..dead9acd 100644 --- a/mod/Jailbreak.LastGuard/LastGuard.cs +++ b/mod/Jailbreak.LastGuard/LastGuard.cs @@ -4,6 +4,10 @@ using CounterStrikeSharp.API.Modules.Cvars; using CounterStrikeSharp.API.Modules.Cvars.Validators; using CounterStrikeSharp.API.Modules.Utils; +using Gangs.BaseImpl.Stats; +using GangsAPI.Data; +using GangsAPI.Services; +using GangsAPI.Services.Player; using Jailbreak.Formatting.Extensions; using Jailbreak.Formatting.Views; using Jailbreak.Public; @@ -12,6 +16,7 @@ using Jailbreak.Public.Mod.LastRequest; using Jailbreak.Public.Utils; using Jailbreak.Validator; +using Microsoft.Extensions.DependencyInjection; using MStatsShared; namespace Jailbreak.LastGuard; @@ -64,6 +69,14 @@ public class LastGuard(ILGLocale notifications, ILastRequestManager lrManager) private bool isLastGuard; private List lastGuardPrisoners = []; + public void Start(BasePlugin basePlugin, bool hotreload) { + if (API.Gangs == null) return; + + var stats = API.Gangs.Services.GetService(); + if (stats == null) return; + stats.Stats.Add(new LGStat()); + } + public void StartLastGuard(CCSPlayerController lastGuard) { var guardPlayerPawn = lastGuard.PlayerPawn.Value; @@ -71,6 +84,23 @@ public void StartLastGuard(CCSPlayerController lastGuard) { isLastGuard = true; + var stats = API.Gangs?.Services.GetService(); + if (stats != null) { + foreach (var player in PlayerUtil.GetAlive()) { + var wrapper = new PlayerWrapper(player); + Task.Run(async () => { + var (success, stat) = + await stats.GetForPlayer(wrapper, LGStat.STAT_ID); + if (!success || stat == null) stat = new LGData(); + if (wrapper.Team == CsTeam.CounterTerrorist) + stat.CtLgs++; + else + stat.TLgs++; + await stats.SetForPlayer(wrapper, LGStat.STAT_ID, stat); + }); + } + } + API.Stats?.PushStat(new ServerStat("JB_LASTGUARD", lastGuard.SteamID.ToString())); @@ -200,10 +230,12 @@ public HookResult OnRoundEnd(EventRoundEnd @event, GameEventInfo info) { [GameEventHandler] public HookResult OnRoundStartEvent(EventRoundStart @event, GameEventInfo info) { - canStart = Utilities.GetPlayers() - .Count(plr - => plr is { PawnIsAlive: true, Team: CsTeam.CounterTerrorist }) - >= CV_MINIMUM_CTS.Value; + Server.NextFrame(() => { + canStart = Utilities.GetPlayers() + .Count(plr + => plr is { PawnIsAlive: true, Team: CsTeam.CounterTerrorist }) + >= CV_MINIMUM_CTS.Value; + }); return HookResult.Continue; } diff --git a/mod/Jailbreak.LastRequest/Jailbreak.LastRequest.csproj b/mod/Jailbreak.LastRequest/Jailbreak.LastRequest.csproj index 7983d674..5808dd17 100644 --- a/mod/Jailbreak.LastRequest/Jailbreak.LastRequest.csproj +++ b/mod/Jailbreak.LastRequest/Jailbreak.LastRequest.csproj @@ -9,6 +9,7 @@ + diff --git a/mod/Jailbreak.LastRequest/LastRequestManager.cs b/mod/Jailbreak.LastRequest/LastRequestManager.cs index ce638cbc..d3ad37ac 100644 --- a/mod/Jailbreak.LastRequest/LastRequestManager.cs +++ b/mod/Jailbreak.LastRequest/LastRequestManager.cs @@ -5,8 +5,10 @@ using CounterStrikeSharp.API.Modules.Cvars.Validators; using CounterStrikeSharp.API.Modules.Menu; using CounterStrikeSharp.API.Modules.Utils; +using Gangs.BaseImpl.Stats; using GangsAPI.Data; using GangsAPI.Services; +using GangsAPI.Services.Player; using Jailbreak.Formatting.Extensions; using Jailbreak.Formatting.Views.LastRequest; using Jailbreak.Public; @@ -76,6 +78,12 @@ public bool ShouldBlockDamage(CCSPlayerController player, public void Start(BasePlugin basePlugin) { factory = provider.GetRequiredService(); + + if (API.Gangs == null) return; + + var stats = API.Gangs.Services.GetService(); + if (stats == null) return; + stats.Stats.Add(new LRStat()); } public bool IsLREnabled { get; set; } @@ -108,7 +116,28 @@ public void EnableLR(CCSPlayerController? died = null) { var players = Utilities.GetPlayers(); foreach (var player in players) { player.ExecuteClientCommand("play sounds/lr"); - if (player.Team != CsTeam.Terrorist || !player.PawnIsAlive) continue; + var wrapper = new PlayerWrapper(player); + + if (!player.PawnIsAlive) continue; + + if (API.Gangs != null) { + var playerStatMgr = API.Gangs.Services.GetService(); + if (playerStatMgr != null) { + Task.Run(async () => { + var (success, stat) = + await playerStatMgr.GetForPlayer(wrapper, LRStat.STAT_ID); + if (stat == null || !success) stat = new LRData(); + if (wrapper.Team == CsTeam.Terrorist) + stat.TLrs++; + else + stat.CtLrs++; + + await playerStatMgr.SetForPlayer(wrapper, LRStat.STAT_ID, stat); + }); + } + } + + if (player.Team != CsTeam.Terrorist) continue; if (died != null && player.SteamID == died.SteamID) continue; player.ExecuteClientCommandFromServer("css_lr"); } @@ -261,7 +290,7 @@ public HookResult OnPlayerDisconnect(EventPlayerDisconnect @event, } private void checkLR() { - Server.RunOnTick(Server.TickCount + 32, () => { + Server.RunOnTick(Server.TickCount + 2, () => { if (IsLREnabled) return; if (Utilities.GetPlayers().All(p => p.Team != CsTeam.CounterTerrorist)) return; diff --git a/mod/Jailbreak.RTD/Rewards/CreditReward.cs b/mod/Jailbreak.RTD/Rewards/CreditReward.cs index 1e97741d..1871d396 100644 --- a/mod/Jailbreak.RTD/Rewards/CreditReward.cs +++ b/mod/Jailbreak.RTD/Rewards/CreditReward.cs @@ -23,7 +23,7 @@ public bool PrepareReward(CCSPlayerController player) { var eco = API.Gangs?.Services.GetService(); if (eco == null) return false; var wrapper = new PlayerWrapper(player); - eco.Grant(wrapper, credits, true, "RTD"); + Task.Run(async () => await eco.Grant(wrapper, credits, true, "RTD")); if (Math.Abs(credits) >= 5000) { Server.PrintToChatAll( diff --git a/mod/Jailbreak.Warden/Global/WardenBehavior.cs b/mod/Jailbreak.Warden/Global/WardenBehavior.cs index 6dd15f3c..76e024e5 100644 --- a/mod/Jailbreak.Warden/Global/WardenBehavior.cs +++ b/mod/Jailbreak.Warden/Global/WardenBehavior.cs @@ -5,6 +5,10 @@ using CounterStrikeSharp.API.Modules.Cvars; using CounterStrikeSharp.API.Modules.Cvars.Validators; using CounterStrikeSharp.API.Modules.Utils; +using Gangs.BaseImpl.Stats; +using GangsAPI.Data; +using GangsAPI.Services; +using GangsAPI.Services.Player; using Jailbreak.Formatting.Extensions; using Jailbreak.Formatting.Views.Logging; using Jailbreak.Formatting.Views.Warden; @@ -39,9 +43,9 @@ public class WardenBehavior(ILogger logger, ISpecialTreatmentService specialTreatment, IRebelService rebels, IMuteService mute, IServiceProvider provider) : IPluginBehavior, IWardenService { - public static readonly FakeConVar CV_ARMOR_EQUAL = - new("css_jb_hp_equal", "Health points for when CTs have equal ratio", 50, - ConVarFlags.FCVAR_NONE, new RangeValidator(1, 200)); + public static readonly FakeConVar CV_ARMOR_EQUAL = new("css_jb_hp_equal", + "Health points for when CTs have equal ratio", 50, 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, @@ -98,7 +102,14 @@ public class WardenBehavior(ILogger logger, private PreWardenStats? preWardenStats; private Timer? unblueTimer, openCellsTimer; - public void Start(BasePlugin basePlugin) { parent = basePlugin; } + public void Start(BasePlugin basePlugin) { + parent = basePlugin; + if (API.Gangs != null) { + var stats = API.Gangs.Services.GetService(); + if (stats == null) return; + stats.Stats.Add(new WardenStat()); + } + } /// /// Get the current warden, if there is one. @@ -147,6 +158,22 @@ public bool TrySetWarden(CCSPlayerController controller) { }); } + if (API.Gangs != null) { + var wrapper = new PlayerWrapper(Warden); + var stats = API.Gangs.Services.GetService(); + if (stats != null) { + Task.Run(async () => { + var (success, stat) = + await stats.GetForPlayer(wrapper, WardenStat.STAT_ID); + + if (!success || stat == null) stat = new WardenData(); + + stat.TimesWardened++; + await stats.SetForPlayer(wrapper, WardenStat.STAT_ID, stat); + }); + } + } + foreach (var player in Utilities.GetPlayers()) player.ExecuteClientCommand($"play sounds/{CV_WARDEN_SOUND_NEW.Value}"); @@ -217,6 +244,15 @@ public bool TryRemoveWarden(bool isPass = false) { .SetTagColor(Warden, oldTagColor.Value, false); logs.Append(logs.Player(Warden), "is no longer the warden."); + + if (API.Gangs != null && !isPass) { + var stats = API.Gangs.Services.GetService(); + if (stats != null) { + var wardenSteam = Warden.SteamID; + var wrapper = new PlayerWrapper(Warden); + Task.Run(async () => await updateWardenDeathStats(wrapper)); + } + } } var wardenPawn = Warden!.PlayerPawn.Value; @@ -247,9 +283,40 @@ public bool TryRemoveWarden(bool isPass = false) { return true; } + private async Task updateWardenDeathStats(PlayerWrapper player) { + var stats = API.Gangs?.Services.GetService(); + if (stats == null) return; + + var (success, stat) = + await stats.GetForPlayer(player, WardenStat.STAT_ID); + if (!success || stat == null) stat = new WardenData(); + stat.WardenDeaths++; + + await stats.SetForPlayer(player, WardenStat.STAT_ID, stat); + } + [GameEventHandler] public HookResult OnDeath(EventPlayerDeath ev, GameEventInfo info) { - if (!((IWardenService)this).IsWarden(ev.Userid)) return HookResult.Continue; + var player = ev.Userid; + if (player == null || !player.IsValid) return HookResult.Continue; + var isWarden = ((IWardenService)this).IsWarden(ev.Userid); + if (API.Gangs != null) { + if (ev.Attacker != null && ev.Attacker.IsValid && isWarden) { + var wrapper = new PlayerWrapper(ev.Attacker); + Task.Run(async () => await incrementWardenKills(wrapper)); + } + + foreach (var guard in PlayerUtil.FromTeam(CsTeam.CounterTerrorist)) { + var wrapper = new PlayerWrapper(guard); + // If the guard is the warden, update all guards' stats + // If the guard is not the warden, only update the warden's stats + if (guard.SteamID == player.SteamID != isWarden) continue; + Task.Run( + async () => { await updateGuardDeathStats(wrapper, isWarden); }); + } + } + + if (!isWarden) return HookResult.Continue; API.Stats?.PushStat(new ServerStat("JB_WARDEN_DEATH")); @@ -258,6 +325,39 @@ public HookResult OnDeath(EventPlayerDeath ev, GameEventInfo info) { return HookResult.Continue; } + private async Task incrementWardenKills(PlayerWrapper attacker) { + var stats = API.Gangs?.Services.GetService(); + if (stats == null) return; + await Task.Run(async () => { + var (success, stat) = + await stats.GetForPlayer(attacker, WardenStat.STAT_ID); + + if (!success || stat == null) stat = new WardenData(); + + stat.WardensKilled++; + await stats.SetForPlayer(attacker, WardenStat.STAT_ID, stat); + }); + } + + private async Task + updateGuardDeathStats(PlayerWrapper player, bool isWarden) { + var stats = API.Gangs?.Services.GetService(); + if (stats == null) return; + + var (success, stat) = + await stats.GetForPlayer(player, WardenStat.STAT_ID); + + if (!success || stat == null) stat = new WardenData(); + + if (isWarden) { + // The warden let a guard die + stat.GuardDeathsAsWarden++; + } else { + // The guard let the warden die + stat.WardenDeathsAsGuard++; + } + } + [GameEventHandler] public HookResult OnChangeTeam(EventPlayerTeam @event, GameEventInfo info) { var player = @event.Userid; diff --git a/mod/Jailbreak.Warden/Jailbreak.Warden.csproj b/mod/Jailbreak.Warden/Jailbreak.Warden.csproj index 165ee9a3..40bcb195 100644 --- a/mod/Jailbreak.Warden/Jailbreak.Warden.csproj +++ b/mod/Jailbreak.Warden/Jailbreak.Warden.csproj @@ -13,6 +13,9 @@ + + ..\..\public\Jailbreak.Public\Mixin\GangsAPI.dll + ..\..\public\Jailbreak.Public\Mixin\MAULActainShared.dll diff --git a/public/Jailbreak.Public/Mixin/GangsAPI.dll b/public/Jailbreak.Public/Mixin/GangsAPI.dll index cf6da90789297b6c2c55068b7558b5d915930bd8..7e1f607a96da2f93468820f83582b8f33b28c97d 100644 GIT binary patch literal 69120 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%0D= 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 r;PP``<|B Date: Fri, 1 Nov 2024 14:23:35 -0700 Subject: [PATCH 02/17] Implement LR stats --- mod/Gangs.BaseImpl/Stats/LGStat.cs | 2 + mod/Gangs.BaseImpl/Stats/LRStat.cs | 8 ++- mod/Gangs.BaseImpl/Stats/WardenStat.cs | 8 +++ .../LastRequestManager.cs | 70 ++++++++++++++++--- 4 files changed, 79 insertions(+), 9 deletions(-) diff --git a/mod/Gangs.BaseImpl/Stats/LGStat.cs b/mod/Gangs.BaseImpl/Stats/LGStat.cs index 62d46138..4de7a69c 100644 --- a/mod/Gangs.BaseImpl/Stats/LGStat.cs +++ b/mod/Gangs.BaseImpl/Stats/LGStat.cs @@ -11,4 +11,6 @@ public class LGStat : BaseStat { public class LGData { public int CtLgs { get; set; } public int TLgs { get; set; } + + public override string ToString() { return $"{CtLgs}/{TLgs}"; } } \ No newline at end of file diff --git a/mod/Gangs.BaseImpl/Stats/LRStat.cs b/mod/Gangs.BaseImpl/Stats/LRStat.cs index 85da5f15..76c539ad 100644 --- a/mod/Gangs.BaseImpl/Stats/LRStat.cs +++ b/mod/Gangs.BaseImpl/Stats/LRStat.cs @@ -9,8 +9,14 @@ public class LRStat : BaseStat { } public class LRData { + public int LRsReachedAsCt { get; set; } + public int LRsReachedAsT { get; set; } public int CtLrs { get; set; } public int TLrs { get; set; } + public int CTLrsWon { get; set; } + public int TLrsWon { get; set; } - public override string ToString() { return $"{CtLrs}/{TLrs}"; } + public override string ToString() { + return $"{CtLrs}/{TLrs} {CTLrsWon}/{TLrsWon}"; + } } \ No newline at end of file diff --git a/mod/Gangs.BaseImpl/Stats/WardenStat.cs b/mod/Gangs.BaseImpl/Stats/WardenStat.cs index c76c6147..9d40909d 100644 --- a/mod/Gangs.BaseImpl/Stats/WardenStat.cs +++ b/mod/Gangs.BaseImpl/Stats/WardenStat.cs @@ -14,4 +14,12 @@ public class WardenData { public int WardensKilled { get; set; } public int GuardDeathsAsWarden { get; set; } public int WardenDeathsAsGuard { get; set; } + + public override string ToString() { + return $"WardenData:\n" + $" Times Wardened: {TimesWardened}\n" + + $" Warden Deaths: {WardenDeaths}\n" + + $" Wardens Killed: {WardensKilled}\n" + + $" Guard Deaths as Warden: {GuardDeathsAsWarden}\n" + + $" Warden Deaths as Guard: {WardenDeathsAsGuard}"; + } } \ No newline at end of file diff --git a/mod/Jailbreak.LastRequest/LastRequestManager.cs b/mod/Jailbreak.LastRequest/LastRequestManager.cs index d3ad37ac..bffb8b43 100644 --- a/mod/Jailbreak.LastRequest/LastRequestManager.cs +++ b/mod/Jailbreak.LastRequest/LastRequestManager.cs @@ -150,11 +150,64 @@ public void EnableLR(CCSPlayerController? died = null) { .Select(p => new PlayerWrapper(p)) .ToList(); Task.Run(async () => { - foreach (var survivor in survivors) + foreach (var survivor in survivors) { await eco.Grant(survivor, 100, reason: "LR Reached"); + await incrementLRReached(survivor); + } }); } + private async Task incrementLRReached(PlayerWrapper player) { + var stats = API.Gangs?.Services.GetService(); + if (stats == null) return; + var stat = await getStat(player); + if (stat == null) return; + + if (player.Team == CsTeam.Terrorist) + stat.LRsReachedAsT++; + else + stat.LRsReachedAsCt++; + + await stats.SetForPlayer(player, LRStat.STAT_ID, stat); + } + + private async Task incrementLRStart(PlayerWrapper player) { + var stats = API.Gangs?.Services.GetService(); + if (stats == null) return; + var stat = await getStat(player); + if (stat == null) return; + + if (player.Team == CsTeam.Terrorist) + stat.TLrs++; + else + stat.CtLrs++; + + await stats.SetForPlayer(player, LRStat.STAT_ID, stat); + } + + private async Task incrementLRWin(PlayerWrapper player) { + var stats = API.Gangs?.Services.GetService(); + if (stats == null) return; + var stat = await getStat(player); + if (stat == null) return; + + if (player.Team == CsTeam.Terrorist) + stat.TLrsWon++; + else + stat.CTLrsWon++; + + await stats.SetForPlayer(player, LRStat.STAT_ID, stat); + } + + private async Task getStat(PlayerWrapper player) { + var stats = API.Gangs?.Services.GetService(); + if (stats == null) return null; + var (success, data) = + await stats.GetForPlayer(player, LRStat.STAT_ID); + if (!success || data == null) data = new LRData(); + return data; + } + public bool InitiateLastRequest(CCSPlayerController prisoner, CCSPlayerController guard, LRType type) { var lr = factory!.CreateLastRequest(prisoner, guard, type); @@ -186,17 +239,18 @@ public bool EndLastRequest(AbstractLastRequest lr, LRResult result) { RoundUtil.AddTimeRemaining(CV_LR_BONUS_TIME.Value); messages.LastRequestDecided(lr, result).ToAllChat(); + var wrapper = + new PlayerWrapper(result == LRResult.GUARD_WIN ? + lr.Guard : + lr.Prisoner); if (shouldGrantCredits()) { var eco = API.Gangs?.Services.GetService(); if (eco == null) return false; - var wrapper = - new PlayerWrapper(result == LRResult.GUARD_WIN ? - lr.Guard : - lr.Prisoner); - Task.Run(async () => { - await eco.Grant(wrapper, 30, reason: "LR Win"); - }); + Task.Run(async () => await eco.Grant(wrapper, 30, reason: "LR Win")); } + + if (API.Gangs != null) + Task.Run(async () => await incrementLRWin(wrapper)); } API.Stats?.PushStat(new ServerStat("JB_LASTREQUEST_RESULT", From e1790d11271c905164e78c946e90d58ac05eedaa Mon Sep 17 00:00:00 2001 From: MSWS Date: Fri, 1 Nov 2024 14:54:45 -0700 Subject: [PATCH 03/17] Register LR stat --- mod/Jailbreak.LastRequest/LastRequestManager.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mod/Jailbreak.LastRequest/LastRequestManager.cs b/mod/Jailbreak.LastRequest/LastRequestManager.cs index bffb8b43..c630c6ac 100644 --- a/mod/Jailbreak.LastRequest/LastRequestManager.cs +++ b/mod/Jailbreak.LastRequest/LastRequestManager.cs @@ -46,6 +46,13 @@ public class LastRequestManager(ILRLocale messages, IServiceProvider provider) private ILastRequestFactory? factory; public bool IsLREnabledForRound { get; set; } = true; + public void Start(BasePlugin basePlugin, bool hotreload) { + var stats = API.Gangs?.Services.GetService(); + if (stats == null) return; + + stats.Stats.Add(new LRStat()); + } + public bool ShouldBlockDamage(CCSPlayerController player, CCSPlayerController? attacker, EventPlayerHurt @event) { if (!IsLREnabled) return false; From 85cf6d57764910ead568a9b898cc451be245174f Mon Sep 17 00:00:00 2001 From: MSWS Date: Fri, 1 Nov 2024 15:00:38 -0700 Subject: [PATCH 04/17] Mark everyone as rebel on last guard --- mod/Jailbreak.LastGuard/LastGuard.cs | 17 ++++++++++------- mod/Jailbreak.LastRequest/LastRequestManager.cs | 9 +++++++-- .../Mod/LastGuard/ILastGuardService.cs | 2 ++ 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/mod/Jailbreak.LastGuard/LastGuard.cs b/mod/Jailbreak.LastGuard/LastGuard.cs index dead9acd..6b057197 100644 --- a/mod/Jailbreak.LastGuard/LastGuard.cs +++ b/mod/Jailbreak.LastGuard/LastGuard.cs @@ -14,6 +14,7 @@ using Jailbreak.Public.Behaviors; using Jailbreak.Public.Mod.LastGuard; using Jailbreak.Public.Mod.LastRequest; +using Jailbreak.Public.Mod.Rebel; using Jailbreak.Public.Utils; using Jailbreak.Validator; using Microsoft.Extensions.DependencyInjection; @@ -21,8 +22,8 @@ namespace Jailbreak.LastGuard; -public class LastGuard(ILGLocale notifications, ILastRequestManager lrManager) - : ILastGuardService, IPluginBehavior { +public class LastGuard(ILGLocale notifications, ILastRequestManager lrManager, + IRebelService rebel) : ILastGuardService, IPluginBehavior { 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"); @@ -66,7 +67,7 @@ public class LastGuard(ILGLocale notifications, ILastRequestManager lrManager) private readonly Random rng = new(); private bool canStart; - private bool isLastGuard; + public bool IsLastGuardActive { get; private set; } private List lastGuardPrisoners = []; public void Start(BasePlugin basePlugin, bool hotreload) { @@ -82,7 +83,7 @@ public void StartLastGuard(CCSPlayerController lastGuard) { if (guardPlayerPawn == null || !guardPlayerPawn.IsValid) return; - isLastGuard = true; + IsLastGuardActive = true; var stats = API.Gangs?.Services.GetService(); if (stats != null) { @@ -134,6 +135,8 @@ public void StartLastGuard(CCSPlayerController lastGuard) { .ToAllCenter() .ToAllChat(); + foreach (var player in lastGuardPrisoners) rebel.MarkRebel(player); + if (string.IsNullOrEmpty(CV_LG_WEAPON.Value)) return; foreach (var player in lastGuardPrisoners) @@ -161,7 +164,7 @@ public HookResult OnPlayerDeathEvent(EventPlayerDeath @event, if (player == null) return HookResult.Continue; checkLastGuard(@event.Userid); - if (!isLastGuard) return HookResult.Continue; + if (!IsLastGuardActive) return HookResult.Continue; if (player.Team != CsTeam.Terrorist) return HookResult.Continue; @@ -204,7 +207,7 @@ private bool playerHasGun(CCSPlayerController player) { private void checkLastGuard(CCSPlayerController? poi) { if (poi == null) return; - if (isLastGuard) return; + if (IsLastGuardActive) return; lastGuardPrisoners.Remove(poi); if (poi.Team != CsTeam.CounterTerrorist) return; var aliveCts = Utilities.GetPlayers() @@ -223,7 +226,7 @@ private void checkLastGuard(CCSPlayerController? poi) { [GameEventHandler] public HookResult OnRoundEnd(EventRoundEnd @event, GameEventInfo info) { - isLastGuard = false; + IsLastGuardActive = false; return HookResult.Continue; } diff --git a/mod/Jailbreak.LastRequest/LastRequestManager.cs b/mod/Jailbreak.LastRequest/LastRequestManager.cs index c630c6ac..58219c73 100644 --- a/mod/Jailbreak.LastRequest/LastRequestManager.cs +++ b/mod/Jailbreak.LastRequest/LastRequestManager.cs @@ -14,15 +14,18 @@ using Jailbreak.Public; using Jailbreak.Public.Extensions; using Jailbreak.Public.Mod.Damage; +using Jailbreak.Public.Mod.LastGuard; using Jailbreak.Public.Mod.LastRequest; using Jailbreak.Public.Mod.LastRequest.Enums; +using Jailbreak.Public.Mod.Rebel; using Jailbreak.Public.Utils; using Microsoft.Extensions.DependencyInjection; using MStatsShared; namespace Jailbreak.LastRequest; -public class LastRequestManager(ILRLocale messages, IServiceProvider provider) +public class LastRequestManager(ILRLocale messages, IServiceProvider provider, + ILastGuardService lastGuard, IRebelService rebel) : ILastRequestManager, IDamageBlocker { public static readonly FakeConVar CV_LR_BASE_TIME = new("css_jb_lr_time_base", @@ -49,7 +52,7 @@ public class LastRequestManager(ILRLocale messages, IServiceProvider provider) public void Start(BasePlugin basePlugin, bool hotreload) { var stats = API.Gangs?.Services.GetService(); if (stats == null) return; - + stats.Stats.Add(new LRStat()); } @@ -146,6 +149,8 @@ public void EnableLR(CCSPlayerController? died = null) { if (player.Team != CsTeam.Terrorist) continue; if (died != null && player.SteamID == died.SteamID) continue; + + if (lastGuard.IsLastGuardActive) rebel.UnmarkRebel(player); player.ExecuteClientCommandFromServer("css_lr"); } diff --git a/public/Jailbreak.Public/Mod/LastGuard/ILastGuardService.cs b/public/Jailbreak.Public/Mod/LastGuard/ILastGuardService.cs index 38a0a698..5cf202c1 100644 --- a/public/Jailbreak.Public/Mod/LastGuard/ILastGuardService.cs +++ b/public/Jailbreak.Public/Mod/LastGuard/ILastGuardService.cs @@ -6,4 +6,6 @@ public interface ILastGuardService { void StartLastGuard(CCSPlayerController lastGuard); public void DisableLastGuardForRound(); + + bool IsLastGuardActive { get; } } \ No newline at end of file From a649be79f90e4c9dee4cf961d3f26395901b9dcb Mon Sep 17 00:00:00 2001 From: MSWS Date: Fri, 1 Nov 2024 15:09:59 -0700 Subject: [PATCH 05/17] Fix circular dependency --- mod/Jailbreak.LastRequest/LastRequestManager.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mod/Jailbreak.LastRequest/LastRequestManager.cs b/mod/Jailbreak.LastRequest/LastRequestManager.cs index 58219c73..50495795 100644 --- a/mod/Jailbreak.LastRequest/LastRequestManager.cs +++ b/mod/Jailbreak.LastRequest/LastRequestManager.cs @@ -24,8 +24,7 @@ namespace Jailbreak.LastRequest; -public class LastRequestManager(ILRLocale messages, IServiceProvider provider, - ILastGuardService lastGuard, IRebelService rebel) +public class LastRequestManager(ILRLocale messages, IServiceProvider provider) : ILastRequestManager, IDamageBlocker { public static readonly FakeConVar CV_LR_BASE_TIME = new("css_jb_lr_time_base", @@ -123,7 +122,9 @@ public void EnableLR(CCSPlayerController? died = null) { RoundUtil.AddTimeRemaining(CV_LR_GUARD_TIME.Value * cts); - var players = Utilities.GetPlayers(); + var players = Utilities.GetPlayers(); + var lastGuard = provider.GetService(); + var rebel = provider.GetService(); foreach (var player in players) { player.ExecuteClientCommand("play sounds/lr"); var wrapper = new PlayerWrapper(player); @@ -150,7 +151,7 @@ public void EnableLR(CCSPlayerController? died = null) { if (player.Team != CsTeam.Terrorist) continue; if (died != null && player.SteamID == died.SteamID) continue; - if (lastGuard.IsLastGuardActive) rebel.UnmarkRebel(player); + if (lastGuard is { IsLastGuardActive: true }) rebel?.UnmarkRebel(player); player.ExecuteClientCommandFromServer("css_lr"); } From 7d6ccf16420cc87a739808b4e674ed0e892c5b65 Mon Sep 17 00:00:00 2001 From: MSWS Date: Fri, 1 Nov 2024 15:13:21 -0700 Subject: [PATCH 06/17] Check LG next frame --- mod/Jailbreak.LastGuard/LastGuard.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mod/Jailbreak.LastGuard/LastGuard.cs b/mod/Jailbreak.LastGuard/LastGuard.cs index 6b057197..37ba6f34 100644 --- a/mod/Jailbreak.LastGuard/LastGuard.cs +++ b/mod/Jailbreak.LastGuard/LastGuard.cs @@ -162,7 +162,8 @@ public HookResult OnPlayerDeathEvent(EventPlayerDeath @event, GameEventInfo info) { var player = @event.Userid; if (player == null) return HookResult.Continue; - checkLastGuard(@event.Userid); + + Server.NextFrame(() => checkLastGuard(@event.Userid)); if (!IsLastGuardActive) return HookResult.Continue; From aa381d1fde082e1407068b57e2e6c838034a5d22 Mon Sep 17 00:00:00 2001 From: MSWS Date: Fri, 1 Nov 2024 15:23:27 -0700 Subject: [PATCH 07/17] More work --- mod/Gangs.BaseImpl/Stats/LGStat.cs | 2 +- mod/Gangs.BaseImpl/Stats/LRStat.cs | 2 +- mod/Jailbreak.Warden/Global/WardenBehavior.cs | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mod/Gangs.BaseImpl/Stats/LGStat.cs b/mod/Gangs.BaseImpl/Stats/LGStat.cs index 4de7a69c..0a1b9961 100644 --- a/mod/Gangs.BaseImpl/Stats/LGStat.cs +++ b/mod/Gangs.BaseImpl/Stats/LGStat.cs @@ -12,5 +12,5 @@ public class LGData { public int CtLgs { get; set; } public int TLgs { get; set; } - public override string ToString() { return $"{CtLgs}/{TLgs}"; } + public override string ToString() { return $"CT/T Last Guards: {CtLgs}/{TLgs}"; } } \ No newline at end of file diff --git a/mod/Gangs.BaseImpl/Stats/LRStat.cs b/mod/Gangs.BaseImpl/Stats/LRStat.cs index 76c539ad..188d71c0 100644 --- a/mod/Gangs.BaseImpl/Stats/LRStat.cs +++ b/mod/Gangs.BaseImpl/Stats/LRStat.cs @@ -17,6 +17,6 @@ public class LRData { public int TLrsWon { get; set; } public override string ToString() { - return $"{CtLrs}/{TLrs} {CTLrsWon}/{TLrsWon}"; + return $"CT/T LRs, CT/T LR Wins: {CtLrs}/{TLrs} {CTLrsWon}/{TLrsWon}"; } } \ No newline at end of file diff --git a/mod/Jailbreak.Warden/Global/WardenBehavior.cs b/mod/Jailbreak.Warden/Global/WardenBehavior.cs index 76e024e5..48ea5d8a 100644 --- a/mod/Jailbreak.Warden/Global/WardenBehavior.cs +++ b/mod/Jailbreak.Warden/Global/WardenBehavior.cs @@ -245,11 +245,10 @@ public bool TryRemoveWarden(bool isPass = false) { logs.Append(logs.Player(Warden), "is no longer the warden."); - if (API.Gangs != null && !isPass) { - var stats = API.Gangs.Services.GetService(); + if (!isPass) { + var stats = API.Gangs?.Services.GetService(); if (stats != null) { - var wardenSteam = Warden.SteamID; - var wrapper = new PlayerWrapper(Warden); + var wrapper = new PlayerWrapper(Warden); Task.Run(async () => await updateWardenDeathStats(wrapper)); } } @@ -301,7 +300,8 @@ public HookResult OnDeath(EventPlayerDeath ev, GameEventInfo info) { if (player == null || !player.IsValid) return HookResult.Continue; var isWarden = ((IWardenService)this).IsWarden(ev.Userid); if (API.Gangs != null) { - if (ev.Attacker != null && ev.Attacker.IsValid && isWarden) { + if (ev.Attacker != null && ev.Attacker != player && ev.Attacker.IsValid + && isWarden) { var wrapper = new PlayerWrapper(ev.Attacker); Task.Run(async () => await incrementWardenKills(wrapper)); } From a031f518a200281500ca0f03fb72ea127370ccfc Mon Sep 17 00:00:00 2001 From: MSWS Date: Fri, 1 Nov 2024 15:35:48 -0700 Subject: [PATCH 08/17] Disable death stats for debugging --- mod/Jailbreak.Warden/Global/WardenBehavior.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/Jailbreak.Warden/Global/WardenBehavior.cs b/mod/Jailbreak.Warden/Global/WardenBehavior.cs index 48ea5d8a..7bf099bb 100644 --- a/mod/Jailbreak.Warden/Global/WardenBehavior.cs +++ b/mod/Jailbreak.Warden/Global/WardenBehavior.cs @@ -249,7 +249,7 @@ public bool TryRemoveWarden(bool isPass = false) { var stats = API.Gangs?.Services.GetService(); if (stats != null) { var wrapper = new PlayerWrapper(Warden); - Task.Run(async () => await updateWardenDeathStats(wrapper)); + // Task.Run(async () => await updateWardenDeathStats(wrapper)); } } } From c5370fb4fd7e5ee7379fdea00c6256203c4c79d9 Mon Sep 17 00:00:00 2001 From: MSWS Date: Fri, 1 Nov 2024 15:43:14 -0700 Subject: [PATCH 09/17] Do valid check before equality --- mod/Jailbreak.Warden/Global/WardenBehavior.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mod/Jailbreak.Warden/Global/WardenBehavior.cs b/mod/Jailbreak.Warden/Global/WardenBehavior.cs index 7bf099bb..d681f8a2 100644 --- a/mod/Jailbreak.Warden/Global/WardenBehavior.cs +++ b/mod/Jailbreak.Warden/Global/WardenBehavior.cs @@ -249,7 +249,7 @@ public bool TryRemoveWarden(bool isPass = false) { var stats = API.Gangs?.Services.GetService(); if (stats != null) { var wrapper = new PlayerWrapper(Warden); - // Task.Run(async () => await updateWardenDeathStats(wrapper)); + Task.Run(async () => await updateWardenDeathStats(wrapper)); } } } @@ -300,7 +300,7 @@ public HookResult OnDeath(EventPlayerDeath ev, GameEventInfo info) { if (player == null || !player.IsValid) return HookResult.Continue; var isWarden = ((IWardenService)this).IsWarden(ev.Userid); if (API.Gangs != null) { - if (ev.Attacker != null && ev.Attacker != player && ev.Attacker.IsValid + if (ev.Attacker != null && ev.Attacker.IsValid && ev.Attacker != player && isWarden) { var wrapper = new PlayerWrapper(ev.Attacker); Task.Run(async () => await incrementWardenKills(wrapper)); @@ -311,8 +311,7 @@ public HookResult OnDeath(EventPlayerDeath ev, GameEventInfo info) { // If the guard is the warden, update all guards' stats // If the guard is not the warden, only update the warden's stats if (guard.SteamID == player.SteamID != isWarden) continue; - Task.Run( - async () => { await updateGuardDeathStats(wrapper, isWarden); }); + Task.Run(async () => await updateGuardDeathStats(wrapper, isWarden)); } } @@ -356,6 +355,8 @@ private async Task // The guard let the warden die stat.WardenDeathsAsGuard++; } + + await stats.SetForPlayer(player, WardenStat.STAT_ID, stat); } [GameEventHandler] From 56619ba59209636f1572a6fb2bd73da5ac128526 Mon Sep 17 00:00:00 2001 From: MSWS Date: Fri, 1 Nov 2024 15:46:24 -0700 Subject: [PATCH 10/17] Debug --- mod/Jailbreak.Warden/Global/WardenBehavior.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/mod/Jailbreak.Warden/Global/WardenBehavior.cs b/mod/Jailbreak.Warden/Global/WardenBehavior.cs index d681f8a2..ac6af2b6 100644 --- a/mod/Jailbreak.Warden/Global/WardenBehavior.cs +++ b/mod/Jailbreak.Warden/Global/WardenBehavior.cs @@ -298,19 +298,26 @@ private async Task updateWardenDeathStats(PlayerWrapper player) { public HookResult OnDeath(EventPlayerDeath ev, GameEventInfo info) { var player = ev.Userid; if (player == null || !player.IsValid) return HookResult.Continue; - var isWarden = ((IWardenService)this).IsWarden(ev.Userid); + var isWarden = ((IWardenService)this).IsWarden(player); if (API.Gangs != null) { + Server.PrintToConsole("WardenBehavior: OnDeath"); if (ev.Attacker != null && ev.Attacker.IsValid && ev.Attacker != player && isWarden) { + Server.PrintToConsole("WardenBehavior: OnDeath: Attacker is valid"); var wrapper = new PlayerWrapper(ev.Attacker); Task.Run(async () => await incrementWardenKills(wrapper)); } + Server.PrintToConsole( + "WardenBehavior: OnDeath: Updating guard death stats"); foreach (var guard in PlayerUtil.FromTeam(CsTeam.CounterTerrorist)) { + Server.PrintToConsole($"WardenBehavior: OnDeath: Guard: {guard}"); var wrapper = new PlayerWrapper(guard); // If the guard is the warden, update all guards' stats // If the guard is not the warden, only update the warden's stats if (guard.SteamID == player.SteamID != isWarden) continue; + Server.PrintToConsole( + $"WardenBehavior: OnDeath: Guard: {guard} is the warden"); Task.Run(async () => await updateGuardDeathStats(wrapper, isWarden)); } } From f5d3be4cad11807d7da66ba81ce0790e5c2c0e59 Mon Sep 17 00:00:00 2001 From: MSWS Date: Fri, 1 Nov 2024 15:55:25 -0700 Subject: [PATCH 11/17] Disable --- mod/Jailbreak.Warden/Global/WardenBehavior.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/Jailbreak.Warden/Global/WardenBehavior.cs b/mod/Jailbreak.Warden/Global/WardenBehavior.cs index ac6af2b6..8277c6ef 100644 --- a/mod/Jailbreak.Warden/Global/WardenBehavior.cs +++ b/mod/Jailbreak.Warden/Global/WardenBehavior.cs @@ -299,7 +299,7 @@ public HookResult OnDeath(EventPlayerDeath ev, GameEventInfo info) { var player = ev.Userid; if (player == null || !player.IsValid) return HookResult.Continue; var isWarden = ((IWardenService)this).IsWarden(player); - if (API.Gangs != null) { + if (API.Gangs != null && false) { Server.PrintToConsole("WardenBehavior: OnDeath"); if (ev.Attacker != null && ev.Attacker.IsValid && ev.Attacker != player && isWarden) { From 9fe42fffd28b3b6e68936c77891b062701324789 Mon Sep 17 00:00:00 2001 From: MSWS Date: Fri, 1 Nov 2024 16:04:35 -0700 Subject: [PATCH 12/17] Disable everything?? --- mod/Jailbreak.Warden/Global/WardenBehavior.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/Jailbreak.Warden/Global/WardenBehavior.cs b/mod/Jailbreak.Warden/Global/WardenBehavior.cs index 8277c6ef..e8941d17 100644 --- a/mod/Jailbreak.Warden/Global/WardenBehavior.cs +++ b/mod/Jailbreak.Warden/Global/WardenBehavior.cs @@ -245,7 +245,7 @@ public bool TryRemoveWarden(bool isPass = false) { logs.Append(logs.Player(Warden), "is no longer the warden."); - if (!isPass) { + if (!isPass && false) { var stats = API.Gangs?.Services.GetService(); if (stats != null) { var wrapper = new PlayerWrapper(Warden); From 9f38509d6e3a8c84bdc0f9f53132cd9c3338d2be Mon Sep 17 00:00:00 2001 From: MSWS Date: Fri, 1 Nov 2024 16:14:17 -0700 Subject: [PATCH 13/17] Gut --- mod/Jailbreak.Warden/Global/WardenBehavior.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/mod/Jailbreak.Warden/Global/WardenBehavior.cs b/mod/Jailbreak.Warden/Global/WardenBehavior.cs index e8941d17..75a6167e 100644 --- a/mod/Jailbreak.Warden/Global/WardenBehavior.cs +++ b/mod/Jailbreak.Warden/Global/WardenBehavior.cs @@ -296,6 +296,7 @@ private async Task updateWardenDeathStats(PlayerWrapper player) { [GameEventHandler] public HookResult OnDeath(EventPlayerDeath ev, GameEventInfo info) { + return HookResult.Continue; var player = ev.Userid; if (player == null || !player.IsValid) return HookResult.Continue; var isWarden = ((IWardenService)this).IsWarden(player); From 8e9b2c3f907b5b6ead95a0dde14f306cb8d98a42 Mon Sep 17 00:00:00 2001 From: MSWS Date: Fri, 1 Nov 2024 16:25:31 -0700 Subject: [PATCH 14/17] More work --- mod/Jailbreak.LastGuard/LastGuard.cs | 2 +- mod/Jailbreak.Warden/Global/WardenBehavior.cs | 12 ++---------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/mod/Jailbreak.LastGuard/LastGuard.cs b/mod/Jailbreak.LastGuard/LastGuard.cs index 37ba6f34..af6772c7 100644 --- a/mod/Jailbreak.LastGuard/LastGuard.cs +++ b/mod/Jailbreak.LastGuard/LastGuard.cs @@ -163,7 +163,7 @@ public HookResult OnPlayerDeathEvent(EventPlayerDeath @event, var player = @event.Userid; if (player == null) return HookResult.Continue; - Server.NextFrame(() => checkLastGuard(@event.Userid)); + checkLastGuard(@event.Userid); if (!IsLastGuardActive) return HookResult.Continue; diff --git a/mod/Jailbreak.Warden/Global/WardenBehavior.cs b/mod/Jailbreak.Warden/Global/WardenBehavior.cs index 75a6167e..2dddd5ec 100644 --- a/mod/Jailbreak.Warden/Global/WardenBehavior.cs +++ b/mod/Jailbreak.Warden/Global/WardenBehavior.cs @@ -245,7 +245,7 @@ public bool TryRemoveWarden(bool isPass = false) { logs.Append(logs.Player(Warden), "is no longer the warden."); - if (!isPass && false) { + if (!isPass) { var stats = API.Gangs?.Services.GetService(); if (stats != null) { var wrapper = new PlayerWrapper(Warden); @@ -296,29 +296,21 @@ private async Task updateWardenDeathStats(PlayerWrapper player) { [GameEventHandler] public HookResult OnDeath(EventPlayerDeath ev, GameEventInfo info) { - return HookResult.Continue; var player = ev.Userid; if (player == null || !player.IsValid) return HookResult.Continue; var isWarden = ((IWardenService)this).IsWarden(player); - if (API.Gangs != null && false) { - Server.PrintToConsole("WardenBehavior: OnDeath"); + if (API.Gangs != null) { if (ev.Attacker != null && ev.Attacker.IsValid && ev.Attacker != player && isWarden) { - Server.PrintToConsole("WardenBehavior: OnDeath: Attacker is valid"); var wrapper = new PlayerWrapper(ev.Attacker); Task.Run(async () => await incrementWardenKills(wrapper)); } - Server.PrintToConsole( - "WardenBehavior: OnDeath: Updating guard death stats"); foreach (var guard in PlayerUtil.FromTeam(CsTeam.CounterTerrorist)) { - Server.PrintToConsole($"WardenBehavior: OnDeath: Guard: {guard}"); var wrapper = new PlayerWrapper(guard); // If the guard is the warden, update all guards' stats // If the guard is not the warden, only update the warden's stats if (guard.SteamID == player.SteamID != isWarden) continue; - Server.PrintToConsole( - $"WardenBehavior: OnDeath: Guard: {guard} is the warden"); Task.Run(async () => await updateGuardDeathStats(wrapper, isWarden)); } } From b228723aa10304127e5d76086786aeebc46d92fb Mon Sep 17 00:00:00 2001 From: MSWS Date: Fri, 1 Nov 2024 16:39:00 -0700 Subject: [PATCH 15/17] Fix that --- mod/Jailbreak.Warden/Global/WardenBehavior.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/Jailbreak.Warden/Global/WardenBehavior.cs b/mod/Jailbreak.Warden/Global/WardenBehavior.cs index 2dddd5ec..97a5e6d7 100644 --- a/mod/Jailbreak.Warden/Global/WardenBehavior.cs +++ b/mod/Jailbreak.Warden/Global/WardenBehavior.cs @@ -310,7 +310,7 @@ public HookResult OnDeath(EventPlayerDeath ev, GameEventInfo info) { var wrapper = new PlayerWrapper(guard); // If the guard is the warden, update all guards' stats // If the guard is not the warden, only update the warden's stats - if (guard.SteamID == player.SteamID != isWarden) continue; + if (guard.SteamID == player.SteamID == isWarden) continue; Task.Run(async () => await updateGuardDeathStats(wrapper, isWarden)); } } From a2b6d3ec60e6ba8f3bb6e55b0b81f57c099d1b76 Mon Sep 17 00:00:00 2001 From: MSWS Date: Fri, 1 Nov 2024 16:54:22 -0700 Subject: [PATCH 16/17] Format --- mod/Gangs.BaseImpl/Stats/LGStat.cs | 4 +- .../Jailbreak.LastGuard.csproj | 4 +- mod/Jailbreak.LastGuard/LastGuard.cs | 21 ++-- .../Jailbreak.LastRequest.csproj | 2 +- .../LastRequestManager.cs | 116 ++++++++---------- mod/Jailbreak.RTD/Jailbreak.RTD.csproj | 2 +- mod/Jailbreak.RTD/Rewards/CreditReward.cs | 3 +- mod/Jailbreak.Warden/Global/WardenBehavior.cs | 8 +- mod/Jailbreak.Warden/Jailbreak.Warden.csproj | 2 +- .../Mod/LastGuard/ILastGuardService.cs | 3 +- 10 files changed, 76 insertions(+), 89 deletions(-) diff --git a/mod/Gangs.BaseImpl/Stats/LGStat.cs b/mod/Gangs.BaseImpl/Stats/LGStat.cs index 0a1b9961..95e04ab7 100644 --- a/mod/Gangs.BaseImpl/Stats/LGStat.cs +++ b/mod/Gangs.BaseImpl/Stats/LGStat.cs @@ -12,5 +12,7 @@ public class LGData { public int CtLgs { get; set; } public int TLgs { get; set; } - public override string ToString() { return $"CT/T Last Guards: {CtLgs}/{TLgs}"; } + public override string ToString() { + return $"CT/T Last Guards: {CtLgs}/{TLgs}"; + } } \ No newline at end of file diff --git a/mod/Jailbreak.LastGuard/Jailbreak.LastGuard.csproj b/mod/Jailbreak.LastGuard/Jailbreak.LastGuard.csproj index efe45b90..c5c2ea96 100644 --- a/mod/Jailbreak.LastGuard/Jailbreak.LastGuard.csproj +++ b/mod/Jailbreak.LastGuard/Jailbreak.LastGuard.csproj @@ -10,12 +10,12 @@ - + - ..\..\public\Jailbreak.Public\Mixin\GangsAPI.dll + ..\..\public\Jailbreak.Public\Mixin\GangsAPI.dll ..\..\public\Jailbreak.Public\Mixin\MStatsShared.dll diff --git a/mod/Jailbreak.LastGuard/LastGuard.cs b/mod/Jailbreak.LastGuard/LastGuard.cs index af6772c7..79c05899 100644 --- a/mod/Jailbreak.LastGuard/LastGuard.cs +++ b/mod/Jailbreak.LastGuard/LastGuard.cs @@ -67,16 +67,8 @@ public class LastGuard(ILGLocale notifications, ILastRequestManager lrManager, private readonly Random rng = new(); private bool canStart; - public bool IsLastGuardActive { get; private set; } private List lastGuardPrisoners = []; - - public void Start(BasePlugin basePlugin, bool hotreload) { - if (API.Gangs == null) return; - - var stats = API.Gangs.Services.GetService(); - if (stats == null) return; - stats.Stats.Add(new LGStat()); - } + public bool IsLastGuardActive { get; private set; } public void StartLastGuard(CCSPlayerController lastGuard) { var guardPlayerPawn = lastGuard.PlayerPawn.Value; @@ -86,7 +78,7 @@ public void StartLastGuard(CCSPlayerController lastGuard) { IsLastGuardActive = true; var stats = API.Gangs?.Services.GetService(); - if (stats != null) { + if (stats != null) foreach (var player in PlayerUtil.GetAlive()) { var wrapper = new PlayerWrapper(player); Task.Run(async () => { @@ -100,7 +92,6 @@ public void StartLastGuard(CCSPlayerController lastGuard) { await stats.SetForPlayer(wrapper, LGStat.STAT_ID, stat); }); } - } API.Stats?.PushStat(new ServerStat("JB_LASTGUARD", lastGuard.SteamID.ToString())); @@ -145,6 +136,14 @@ public void StartLastGuard(CCSPlayerController lastGuard) { public void DisableLastGuardForRound() { canStart = false; } + public void Start(BasePlugin basePlugin, bool hotreload) { + if (API.Gangs == null) return; + + var stats = API.Gangs.Services.GetService(); + if (stats == null) return; + stats.Stats.Add(new LGStat()); + } + private int calculateHealth() { var aliveTerrorists = Utilities.GetPlayers() .Where(plr => plr is { PawnIsAlive: true, Team: CsTeam.Terrorist }) diff --git a/mod/Jailbreak.LastRequest/Jailbreak.LastRequest.csproj b/mod/Jailbreak.LastRequest/Jailbreak.LastRequest.csproj index 5808dd17..72154361 100644 --- a/mod/Jailbreak.LastRequest/Jailbreak.LastRequest.csproj +++ b/mod/Jailbreak.LastRequest/Jailbreak.LastRequest.csproj @@ -9,7 +9,7 @@ - + diff --git a/mod/Jailbreak.LastRequest/LastRequestManager.cs b/mod/Jailbreak.LastRequest/LastRequestManager.cs index 50495795..e107e65d 100644 --- a/mod/Jailbreak.LastRequest/LastRequestManager.cs +++ b/mod/Jailbreak.LastRequest/LastRequestManager.cs @@ -48,13 +48,6 @@ public class LastRequestManager(ILRLocale messages, IServiceProvider provider) private ILastRequestFactory? factory; public bool IsLREnabledForRound { get; set; } = true; - public void Start(BasePlugin basePlugin, bool hotreload) { - var stats = API.Gangs?.Services.GetService(); - if (stats == null) return; - - stats.Stats.Add(new LRStat()); - } - public bool ShouldBlockDamage(CCSPlayerController player, CCSPlayerController? attacker, EventPlayerHurt @event) { if (!IsLREnabled) return false; @@ -91,8 +84,7 @@ public void Start(BasePlugin basePlugin) { if (API.Gangs == null) return; var stats = API.Gangs.Services.GetService(); - if (stats == null) return; - stats.Stats.Add(new LRStat()); + stats?.Stats.Add(new LRStat()); } public bool IsLREnabled { get; set; } @@ -100,7 +92,6 @@ public void Start(BasePlugin basePlugin) { public IList ActiveLRs { get; } = new List(); - public void DisableLR() { IsLREnabled = false; } public void DisableLRForRound() { @@ -133,7 +124,7 @@ public void EnableLR(CCSPlayerController? died = null) { if (API.Gangs != null) { var playerStatMgr = API.Gangs.Services.GetService(); - if (playerStatMgr != null) { + if (playerStatMgr != null) Task.Run(async () => { var (success, stat) = await playerStatMgr.GetForPlayer(wrapper, LRStat.STAT_ID); @@ -145,7 +136,6 @@ public void EnableLR(CCSPlayerController? died = null) { await playerStatMgr.SetForPlayer(wrapper, LRStat.STAT_ID, stat); }); - } } if (player.Team != CsTeam.Terrorist) continue; @@ -170,57 +160,6 @@ public void EnableLR(CCSPlayerController? died = null) { }); } - private async Task incrementLRReached(PlayerWrapper player) { - var stats = API.Gangs?.Services.GetService(); - if (stats == null) return; - var stat = await getStat(player); - if (stat == null) return; - - if (player.Team == CsTeam.Terrorist) - stat.LRsReachedAsT++; - else - stat.LRsReachedAsCt++; - - await stats.SetForPlayer(player, LRStat.STAT_ID, stat); - } - - private async Task incrementLRStart(PlayerWrapper player) { - var stats = API.Gangs?.Services.GetService(); - if (stats == null) return; - var stat = await getStat(player); - if (stat == null) return; - - if (player.Team == CsTeam.Terrorist) - stat.TLrs++; - else - stat.CtLrs++; - - await stats.SetForPlayer(player, LRStat.STAT_ID, stat); - } - - private async Task incrementLRWin(PlayerWrapper player) { - var stats = API.Gangs?.Services.GetService(); - if (stats == null) return; - var stat = await getStat(player); - if (stat == null) return; - - if (player.Team == CsTeam.Terrorist) - stat.TLrsWon++; - else - stat.CTLrsWon++; - - await stats.SetForPlayer(player, LRStat.STAT_ID, stat); - } - - private async Task getStat(PlayerWrapper player) { - var stats = API.Gangs?.Services.GetService(); - if (stats == null) return null; - var (success, data) = - await stats.GetForPlayer(player, LRStat.STAT_ID); - if (!success || data == null) data = new LRData(); - return data; - } - public bool InitiateLastRequest(CCSPlayerController prisoner, CCSPlayerController guard, LRType type) { var lr = factory!.CreateLastRequest(prisoner, guard, type); @@ -274,6 +213,57 @@ public bool EndLastRequest(AbstractLastRequest lr, LRResult result) { return true; } + private async Task incrementLRReached(PlayerWrapper player) { + var stats = API.Gangs?.Services.GetService(); + if (stats == null) return; + var stat = await getStat(player); + if (stat == null) return; + + if (player.Team == CsTeam.Terrorist) + stat.LRsReachedAsT++; + else + stat.LRsReachedAsCt++; + + await stats.SetForPlayer(player, LRStat.STAT_ID, stat); + } + + private async Task incrementLRStart(PlayerWrapper player) { + var stats = API.Gangs?.Services.GetService(); + if (stats == null) return; + var stat = await getStat(player); + if (stat == null) return; + + if (player.Team == CsTeam.Terrorist) + stat.TLrs++; + else + stat.CtLrs++; + + await stats.SetForPlayer(player, LRStat.STAT_ID, stat); + } + + private async Task incrementLRWin(PlayerWrapper player) { + var stats = API.Gangs?.Services.GetService(); + if (stats == null) return; + var stat = await getStat(player); + if (stat == null) return; + + if (player.Team == CsTeam.Terrorist) + stat.TLrsWon++; + else + stat.CTLrsWon++; + + await stats.SetForPlayer(player, LRStat.STAT_ID, stat); + } + + private async Task getStat(PlayerWrapper player) { + var stats = API.Gangs?.Services.GetService(); + if (stats == null) return null; + var (success, data) = + await stats.GetForPlayer(player, LRStat.STAT_ID); + if (!success || data == null) data = new LRData(); + return data; + } + private static bool shouldGrantCredits() { if (API.Gangs == null) return false; return Utilities.GetPlayers().Count >= CV_MIN_PLAYERS_FOR_CREDITS.Value; diff --git a/mod/Jailbreak.RTD/Jailbreak.RTD.csproj b/mod/Jailbreak.RTD/Jailbreak.RTD.csproj index 929c377d..0388e8c9 100644 --- a/mod/Jailbreak.RTD/Jailbreak.RTD.csproj +++ b/mod/Jailbreak.RTD/Jailbreak.RTD.csproj @@ -14,7 +14,7 @@ - ..\..\public\Jailbreak.Public\Mixin\GangsAPI.dll + ..\..\public\Jailbreak.Public\Mixin\GangsAPI.dll ..\..\public\Jailbreak.Public\Mixin\MAULActainShared.dll diff --git a/mod/Jailbreak.RTD/Rewards/CreditReward.cs b/mod/Jailbreak.RTD/Rewards/CreditReward.cs index 1871d396..6cab7dcc 100644 --- a/mod/Jailbreak.RTD/Rewards/CreditReward.cs +++ b/mod/Jailbreak.RTD/Rewards/CreditReward.cs @@ -25,10 +25,9 @@ public bool PrepareReward(CCSPlayerController player) { var wrapper = new PlayerWrapper(player); Task.Run(async () => await eco.Grant(wrapper, credits, true, "RTD")); - if (Math.Abs(credits) >= 5000) { + if (Math.Abs(credits) >= 5000) Server.PrintToChatAll( $"{PREFIX} {ChatColors.Yellow}{wrapper.Name} {ChatColors.Default}won the jackpot of {ChatColors.Green}{credits} {ChatColors.Default}credits!"); - } return true; } diff --git a/mod/Jailbreak.Warden/Global/WardenBehavior.cs b/mod/Jailbreak.Warden/Global/WardenBehavior.cs index 97a5e6d7..a0f4e7fe 100644 --- a/mod/Jailbreak.Warden/Global/WardenBehavior.cs +++ b/mod/Jailbreak.Warden/Global/WardenBehavior.cs @@ -161,7 +161,7 @@ public bool TrySetWarden(CCSPlayerController controller) { if (API.Gangs != null) { var wrapper = new PlayerWrapper(Warden); var stats = API.Gangs.Services.GetService(); - if (stats != null) { + if (stats != null) Task.Run(async () => { var (success, stat) = await stats.GetForPlayer(wrapper, WardenStat.STAT_ID); @@ -171,7 +171,6 @@ public bool TrySetWarden(CCSPlayerController controller) { stat.TimesWardened++; await stats.SetForPlayer(wrapper, WardenStat.STAT_ID, stat); }); - } } foreach (var player in Utilities.GetPlayers()) @@ -348,13 +347,12 @@ private async Task if (!success || stat == null) stat = new WardenData(); - if (isWarden) { + if (isWarden) // The warden let a guard die stat.GuardDeathsAsWarden++; - } else { + else // The guard let the warden die stat.WardenDeathsAsGuard++; - } await stats.SetForPlayer(player, WardenStat.STAT_ID, stat); } diff --git a/mod/Jailbreak.Warden/Jailbreak.Warden.csproj b/mod/Jailbreak.Warden/Jailbreak.Warden.csproj index 40bcb195..a149ba86 100644 --- a/mod/Jailbreak.Warden/Jailbreak.Warden.csproj +++ b/mod/Jailbreak.Warden/Jailbreak.Warden.csproj @@ -14,7 +14,7 @@ - ..\..\public\Jailbreak.Public\Mixin\GangsAPI.dll + ..\..\public\Jailbreak.Public\Mixin\GangsAPI.dll ..\..\public\Jailbreak.Public\Mixin\MAULActainShared.dll diff --git a/public/Jailbreak.Public/Mod/LastGuard/ILastGuardService.cs b/public/Jailbreak.Public/Mod/LastGuard/ILastGuardService.cs index 5cf202c1..34615010 100644 --- a/public/Jailbreak.Public/Mod/LastGuard/ILastGuardService.cs +++ b/public/Jailbreak.Public/Mod/LastGuard/ILastGuardService.cs @@ -3,9 +3,8 @@ namespace Jailbreak.Public.Mod.LastGuard; public interface ILastGuardService { + bool IsLastGuardActive { get; } void StartLastGuard(CCSPlayerController lastGuard); public void DisableLastGuardForRound(); - - bool IsLastGuardActive { get; } } \ No newline at end of file From 60fe936323ea88d2618e6c506f382434f852a347 Mon Sep 17 00:00:00 2001 From: MSWS Date: Fri, 1 Nov 2024 17:04:17 -0700 Subject: [PATCH 17/17] Disable transparent rtd --- mod/Jailbreak.RTD/Rewards/ColorReward.cs | 2 ++ mod/Jailbreak.RTD/Rewards/TransparentReward.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/mod/Jailbreak.RTD/Rewards/ColorReward.cs b/mod/Jailbreak.RTD/Rewards/ColorReward.cs index fea84d08..14efbc5c 100644 --- a/mod/Jailbreak.RTD/Rewards/ColorReward.cs +++ b/mod/Jailbreak.RTD/Rewards/ColorReward.cs @@ -37,6 +37,8 @@ public char ChatColor public virtual string Description => $"You will spawn {ChatColor}{ColorName}{ChatColors.Grey} next round."; + public virtual bool Enabled => true; + public bool CanGrantReward(CCSPlayerController player) { return player.Team == CsTeam.Terrorist || !prisonerOnly; } diff --git a/mod/Jailbreak.RTD/Rewards/TransparentReward.cs b/mod/Jailbreak.RTD/Rewards/TransparentReward.cs index f316eaec..9c5739fe 100644 --- a/mod/Jailbreak.RTD/Rewards/TransparentReward.cs +++ b/mod/Jailbreak.RTD/Rewards/TransparentReward.cs @@ -8,4 +8,6 @@ public class TransparentReward() public override string Description => "You will spawn transparent next round."; + + public override bool Enabled => false; } \ No newline at end of file