diff --git a/Jailbreak.sln b/Jailbreak.sln index 9570efb8..30f97c74 100644 --- a/Jailbreak.sln +++ b/Jailbreak.sln @@ -22,6 +22,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lang", "lang", "{CDCDE44E-0 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jailbreak.English", "lang\Jailbreak.English\Jailbreak.English.csproj", "{FC2D6F50-BCFF-41E6-A965-6C73CC01C3BF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jailbreak.Rebel", "mod\Jailbreak.Rebel\Jailbreak.Rebel.csproj", "{CB2391A1-6CDD-496F-B8D6-674FD6268038}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -56,6 +58,10 @@ Global {FC2D6F50-BCFF-41E6-A965-6C73CC01C3BF}.Debug|Any CPU.Build.0 = Debug|Any CPU {FC2D6F50-BCFF-41E6-A965-6C73CC01C3BF}.Release|Any CPU.ActiveCfg = Release|Any CPU {FC2D6F50-BCFF-41E6-A965-6C73CC01C3BF}.Release|Any CPU.Build.0 = Release|Any CPU + {CB2391A1-6CDD-496F-B8D6-674FD6268038}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CB2391A1-6CDD-496F-B8D6-674FD6268038}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CB2391A1-6CDD-496F-B8D6-674FD6268038}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CB2391A1-6CDD-496F-B8D6-674FD6268038}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {9135CCC9-66C5-4A9C-AE3C-91475B5F0437} = {177DA48D-8306-4102-918D-992569878581} @@ -65,5 +71,6 @@ Global {28EE05E4-8FE3-4CC6-AA03-0C533EFBFBF2} = {36BA84C0-291C-4930-A7C6-97CDF8F7F0D7} {446E0B6F-E4FE-45E6-BD9B-BD943698327A} = {59311734-3648-43C2-B43C-385718B0D103} {FC2D6F50-BCFF-41E6-A965-6C73CC01C3BF} = {CDCDE44E-01D2-4B76-99DA-A57E1E956038} + {CB2391A1-6CDD-496F-B8D6-674FD6268038} = {36BA84C0-291C-4930-A7C6-97CDF8F7F0D7} EndGlobalSection EndGlobal diff --git a/lang/Jailbreak.English/Rebel/RebelNotifications.cs b/lang/Jailbreak.English/Rebel/RebelNotifications.cs new file mode 100644 index 00000000..53ffd2ad --- /dev/null +++ b/lang/Jailbreak.English/Rebel/RebelNotifications.cs @@ -0,0 +1,22 @@ +using CounterStrikeSharp.API.Modules.Utils; +using Jailbreak.Formatting.Base; +using Jailbreak.Formatting.Core; +using Jailbreak.Formatting.Logistics; +using Jailbreak.Formatting.Objects; +using Jailbreak.Formatting.Views; + +namespace Jailbreak.English.Rebel; + +public class RebelNotifications : IRebelNotifications, ILanguage +{ + public static FormatObject PREFIX = new HiddenFormatObject( $" {ChatColors.Darkred}[{ChatColors.LightRed}Rebel{ChatColors.Darkred}]" ) + { + // Hide in panorama and center text + Plain = false, + Panorama = false, + Chat = true, + }; + public IView NO_LONGER_REBEL => new SimpleView(writer => + writer + .Line(PREFIX, "You are no longer a rebel.")); +} \ No newline at end of file diff --git a/mod/Jailbreak.Rebel/Jailbreak.Rebel.csproj b/mod/Jailbreak.Rebel/Jailbreak.Rebel.csproj new file mode 100644 index 00000000..128ff34e --- /dev/null +++ b/mod/Jailbreak.Rebel/Jailbreak.Rebel.csproj @@ -0,0 +1,14 @@ + + + + net7.0 + enable + enable + + + + + + + + diff --git a/mod/Jailbreak.Rebel/RebelListener.cs b/mod/Jailbreak.Rebel/RebelListener.cs new file mode 100644 index 00000000..a8f82b8b --- /dev/null +++ b/mod/Jailbreak.Rebel/RebelListener.cs @@ -0,0 +1,41 @@ +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Modules.Utils; +using Jailbreak.Public.Behaviors; +using Jailbreak.Public.Extensions; +using Jailbreak.Public.Mod.Rebel; + +namespace Jailbreak.Teams; + +public class RebelListener : IPluginBehavior +{ + private IRebelService _rebelService; + + public RebelListener(IRebelService rebelService) + { + _rebelService = rebelService; + } + + public void Start(BasePlugin parent) + { + parent.RegisterEventHandler(OnPlayerHurt); + } + + HookResult OnPlayerHurt(EventPlayerHurt @event, GameEventInfo info) + { + var player = @event.Userid; + if (!player.IsValid) + return HookResult.Continue; + if (player.GetTeam() != CsTeam.CounterTerrorist) + return HookResult.Continue; + + var attacker = @event.Attacker; + if (!attacker.IsValid) + return HookResult.Continue; + + if (attacker.GetTeam() != CsTeam.Terrorist) + return HookResult.Continue; + + _rebelService.MarkRebel(attacker, 120); + return HookResult.Continue; + } +} \ No newline at end of file diff --git a/mod/Jailbreak.Rebel/RebelManager.cs b/mod/Jailbreak.Rebel/RebelManager.cs new file mode 100644 index 00000000..5fc69f91 --- /dev/null +++ b/mod/Jailbreak.Rebel/RebelManager.cs @@ -0,0 +1,127 @@ +using System.Drawing; +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core.Attributes.Registration; +using CounterStrikeSharp.API.Modules.Timers; +using Jailbreak.Formatting.Extensions; +using Jailbreak.Formatting.Views; +using Jailbreak.Public.Behaviors; +using Jailbreak.Public.Mod.Rebel; + +namespace Jailbreak.Teams; + +public class RebelManager : IPluginBehavior, IRebelService +{ + private Dictionary rebelTimes = new(); + private IRebelNotifications notifs; + + public RebelManager(IRebelNotifications notifs) + { + this.notifs = notifs; + } + + public void Start(BasePlugin parent) + { + parent.RegisterEventHandler(OnPlayerDisconnect); + parent.RegisterEventHandler(OnRoundStart); + + parent.AddTimer(1f, () => + { + foreach (var player in GetActiveRebels()) + { + if (!player.IsValid) + continue; + + if (GetRebelTimeLeft(player) <= 0) + { + UnmarkRebel(player); + continue; + } + + ApplyRebelColor(player); + } + }, TimerFlags.REPEAT); + } + + private HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info) + { + rebelTimes.Clear(); + foreach (var player in Utilities.GetPlayers()) + { + if (!player.IsValid) + continue; + ApplyRebelColor(player); + } + + return HookResult.Continue; + } + + HookResult OnPlayerDisconnect(EventPlayerDisconnect @event, GameEventInfo info) + { + if (rebelTimes.ContainsKey(@event.Userid)) + { + rebelTimes.Remove(@event.Userid); + } + + return HookResult.Continue; + } + + public ISet GetActiveRebels() + { + return rebelTimes.Keys.ToHashSet(); + } + + public long GetRebelTimeLeft(CCSPlayerController player) + { + if (rebelTimes.TryGetValue(player, out long time)) + { + return time - DateTimeOffset.Now.ToUnixTimeSeconds(); + } + + return 0; + } + + public bool MarkRebel(CCSPlayerController player, long time) + { + rebelTimes[player] = DateTimeOffset.Now.ToUnixTimeSeconds() + time; + ApplyRebelColor(player); + return true; + } + + public void UnmarkRebel(CCSPlayerController player) + { + notifs.NO_LONGER_REBEL.ToPlayerChat(player); + + rebelTimes.Remove(player); + ApplyRebelColor(player); + } + + // https://www.desmos.com/calculator/g2v6vvg7ax + private float GetRebelTimePercentage(CCSPlayerController player) + { + long x = GetRebelTimeLeft(player); + if (x > 120) + return 1; + if (x <= 0) + return 0; + return (float)(100 - (120 - x) * (Math.Sqrt(120 - x)) / 13f) / 100; + } + + private void ApplyRebelColor(CCSPlayerController player) + { + if (!player.IsValid || player.Pawn.Value == null) + return; + var percent = GetRebelTimePercentage(player); + var percentRGB = 255 - (int)Math.Round(percent * 255.0); + var color = Color.FromArgb(254, 255, percentRGB, percentRGB); + if (percent <= 0) + { + color = Color.FromArgb(254, 255, 255, 255); + } + + player.PrintToConsole("Color: " + color); + player.Pawn.Value.RenderMode = RenderMode_t.kRenderTransColor; + player.Pawn.Value.Render = color; + Utilities.SetStateChanged(player.Pawn.Value, "CBaseModelEntity", "m_clrRender"); + } +} \ No newline at end of file diff --git a/mod/Jailbreak.Rebel/RebelServiceExtension.cs b/mod/Jailbreak.Rebel/RebelServiceExtension.cs new file mode 100644 index 00000000..057552e1 --- /dev/null +++ b/mod/Jailbreak.Rebel/RebelServiceExtension.cs @@ -0,0 +1,16 @@ +using Jailbreak.Public.Extensions; +using Jailbreak.Public.Mod.Rebel; +using Jailbreak.Public.Mod.Teams; + +using Microsoft.Extensions.DependencyInjection; + +namespace Jailbreak.Teams; + +public static class RebelServiceExtension +{ + public static void AddJailbreakRebel(this IServiceCollection collection) + { + collection.AddPluginBehavior(); + collection.AddPluginBehavior(); + } +} diff --git a/mod/Jailbreak.Warden/Global/WardenBehavior.cs b/mod/Jailbreak.Warden/Global/WardenBehavior.cs index be888ffd..a0ae3d87 100644 --- a/mod/Jailbreak.Warden/Global/WardenBehavior.cs +++ b/mod/Jailbreak.Warden/Global/WardenBehavior.cs @@ -62,6 +62,7 @@ public bool TrySetWarden(CCSPlayerController controller) { _warden.Pawn.Value.RenderMode = RenderMode_t.kRenderTransColor; _warden.Pawn.Value.Render = Color.Blue; + Utilities.SetStateChanged(_warden.Pawn.Value, "CBaseModelEntity", "m_clrRender"); } _notifications.NEW_WARDEN(_warden) @@ -77,9 +78,12 @@ public bool TryRemoveWarden() return false; _hasWarden = false; - + if (_warden != null && _warden.Pawn.Value != null) + { _warden.Pawn.Value.Render = Color.FromArgb(254, 255, 255, 255); + Utilities.SetStateChanged(_warden.Pawn.Value, "CBaseModelEntity", "m_clrRender"); + } _warden = null; diff --git a/public/Jailbreak.Formatting/Logistics/LanguageConfig.cs b/public/Jailbreak.Formatting/Logistics/LanguageConfig.cs index 47cc15be..bc07c36a 100644 --- a/public/Jailbreak.Formatting/Logistics/LanguageConfig.cs +++ b/public/Jailbreak.Formatting/Logistics/LanguageConfig.cs @@ -22,4 +22,8 @@ public void WithRatio() public void WithWarden() where TWarden : class, ILanguage, IWardenNotifications => _collection.AddSingleton(); + + public void WithRebel() + where TRebel : class, ILanguage, IRebelNotifications + => _collection.AddSingleton(); } diff --git a/public/Jailbreak.Formatting/Views/IRebelNotifications.cs b/public/Jailbreak.Formatting/Views/IRebelNotifications.cs new file mode 100644 index 00000000..4631baec --- /dev/null +++ b/public/Jailbreak.Formatting/Views/IRebelNotifications.cs @@ -0,0 +1,8 @@ +using Jailbreak.Formatting.Base; + +namespace Jailbreak.Formatting.Views; + +public interface IRebelNotifications +{ + public IView NO_LONGER_REBEL { get; } +} \ No newline at end of file diff --git a/public/Jailbreak.Public/Mod/Rebel/IRebelService.cs b/public/Jailbreak.Public/Mod/Rebel/IRebelService.cs new file mode 100644 index 00000000..87363d8c --- /dev/null +++ b/public/Jailbreak.Public/Mod/Rebel/IRebelService.cs @@ -0,0 +1,19 @@ +using CounterStrikeSharp.API.Core; + +namespace Jailbreak.Public.Mod.Rebel; + +public interface IRebelService +{ + ISet GetActiveRebels(); + + bool IsRebel(CCSPlayerController player) + { + return GetRebelTimeLeft(player) > 0; + } + + long GetRebelTimeLeft(CCSPlayerController player); + + bool MarkRebel(CCSPlayerController player, long time); + + void UnmarkRebel(CCSPlayerController player); +} \ No newline at end of file diff --git a/src/Jailbreak/Jailbreak.csproj b/src/Jailbreak/Jailbreak.csproj index 0a0c71f4..212d15e7 100644 --- a/src/Jailbreak/Jailbreak.csproj +++ b/src/Jailbreak/Jailbreak.csproj @@ -35,6 +35,7 @@ + diff --git a/src/Jailbreak/JailbreakServiceCollection.cs b/src/Jailbreak/JailbreakServiceCollection.cs index 30322612..a74e08fb 100644 --- a/src/Jailbreak/JailbreakServiceCollection.cs +++ b/src/Jailbreak/JailbreakServiceCollection.cs @@ -3,6 +3,7 @@ using CounterStrikeSharp.API.Core; using Jailbreak.Config; +using Jailbreak.English.Rebel; using Jailbreak.English.Teams; using Jailbreak.English.Warden; using Jailbreak.Formatting.Languages; @@ -32,12 +33,14 @@ public void ConfigureServices(IServiceCollection serviceCollection) serviceCollection.AddJailbreakGeneric(); serviceCollection.AddJailbreakWarden(); serviceCollection.AddJailbreakTeams(); + serviceCollection.AddJailbreakRebel(); // Add in english localization serviceCollection.AddLanguage(config => { config.WithRatio(); config.WithWarden(); + config.WithRebel(); }); } }