diff --git a/lang/Jailbreak.English/Warden/OpenCommandNotifications.cs b/lang/Jailbreak.English/Warden/OpenCommandNotifications.cs index 2741af41..48eb28cf 100644 --- a/lang/Jailbreak.English/Warden/OpenCommandNotifications.cs +++ b/lang/Jailbreak.English/Warden/OpenCommandNotifications.cs @@ -1,7 +1,6 @@ using Jailbreak.Formatting.Base; using Jailbreak.Formatting.Logistics; using Jailbreak.Formatting.Views; -using Jailbreak.Public.Utils; namespace Jailbreak.English.Warden; @@ -16,22 +15,13 @@ public IView CannotOpenYet(int seconds) { }; } - public IView OpenResult(Sensitivity? sensitivity) { - return sensitivity switch { - Sensitivity.NAME_CELL_DOOR or Sensitivity.NAME_CELL => new SimpleView { - WardenNotifications.PREFIX, "The warden opened the cell doors." - }, - Sensitivity.TARGET_CELL_DOOR or Sensitivity.TARGET_CELL => new - SimpleView { - WardenNotifications.PREFIX, - "The warden attempted to open the cell door." - }, - Sensitivity.ANY_WITH_TARGET => new SimpleView { - WardenNotifications.PREFIX, "Attempting to open cell coors..." - }, - _ => new SimpleView { - WardenNotifications.PREFIX, "Could not open cell doors." - } + public IView CellsOpened + => new SimpleView { + WardenNotifications.PREFIX, "The warden opened cells." + }; + + public IView OpeningFailed + => new SimpleView { + WardenNotifications.PREFIX, "Failed to open the cells." }; - } } \ No newline at end of file diff --git a/lang/Jailbreak.English/Warden/WardenNotifications.cs b/lang/Jailbreak.English/Warden/WardenNotifications.cs index 77ad58ed..12dbb366 100644 --- a/lang/Jailbreak.English/Warden/WardenNotifications.cs +++ b/lang/Jailbreak.English/Warden/WardenNotifications.cs @@ -98,9 +98,8 @@ public IView CurrentWarden(CCSPlayerController? player) { new SimpleView { PREFIX, "There is no warden." }; } - public IView CannotWardenDuringWarmup => new SimpleView { - PREFIX, "You cannot warden during warmup." - }; + public IView CannotWardenDuringWarmup + => new SimpleView { PREFIX, "You cannot warden during warmup." }; public IView FireCommandSuccess(CCSPlayerController player) { return new SimpleView { diff --git a/mod/Jailbreak.Debug/Subcommands/OpenCells.cs b/mod/Jailbreak.Debug/Subcommands/OpenCells.cs index 47da6d86..d4e84282 100644 --- a/mod/Jailbreak.Debug/Subcommands/OpenCells.cs +++ b/mod/Jailbreak.Debug/Subcommands/OpenCells.cs @@ -1,11 +1,13 @@ using CounterStrikeSharp.API.Core; +using Jailbreak.Public.Mod.Zones; using Jailbreak.Public.Utils; +using Microsoft.Extensions.DependencyInjection; namespace Jailbreak.Debug.Subcommands; public class OpenCells(IServiceProvider services) : AbstractCommand(services) { public override void OnCommand(CCSPlayerController? executor, WrappedInfo info) { - MapUtil.OpenCells(); + MapUtil.OpenCells(Services.GetRequiredService()); } } \ No newline at end of file diff --git a/mod/Jailbreak.Debug/Subcommands/Zone.cs b/mod/Jailbreak.Debug/Subcommands/Zone.cs index 09d7a366..f7733fd2 100644 --- a/mod/Jailbreak.Debug/Subcommands/Zone.cs +++ b/mod/Jailbreak.Debug/Subcommands/Zone.cs @@ -198,7 +198,7 @@ await zoneManager.PushZoneWithID(innerZone, innerPair.Value.Item2, } tpDestinations.Sort((a, b) - => a.GetMinDistance(position) <= b.GetMinDistance(position) ? -1 : 1); + => a.GetMinDistanceSquared(position) <= b.GetMinDistanceSquared(position) ? -1 : 1); executor.PlayerPawn.Value.Teleport(tpDestinations.First() .GetCenterPoint()); diff --git a/mod/Jailbreak.LastRequest/LastRequests/BulletForBullet.cs b/mod/Jailbreak.LastRequest/LastRequests/BulletForBullet.cs index 774d798c..5eeddf14 100644 --- a/mod/Jailbreak.LastRequest/LastRequests/BulletForBullet.cs +++ b/mod/Jailbreak.LastRequest/LastRequests/BulletForBullet.cs @@ -1,4 +1,3 @@ -using System.Runtime.InteropServices.JavaScript; using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Menu; @@ -10,27 +9,27 @@ namespace Jailbreak.LastRequest.LastRequests; public class BulletForBullet : TeleportingRequest { + private static readonly string[] GUNS = [ + "weapon_deagle", "weapon_glock", "weapon_hkp2000", "weapon_tec9", + "weapon_cz75a" + ]; + + private static readonly string[] GUN_NAMES = [ + "Desert Eagle", "Glock 18", "USP-S", "Tec9", "CZ75" + ]; + private readonly ChatMenu chatMenu; private string? CHOSEN_PISTOL; + private readonly bool magForMag; private int? whosShot, magSize; - private bool magForMag = false; - - private static readonly string[] GUNS = new string[] { - "weapon_deagle", "weapon_glock", "weapon_hkp2000", "weapon_tec9", - "weapon_cz75a", "weapon_revolver" - }; - - private static readonly string[] GUN_NAMES = new string[] { - "Desert Eagle", "Glock 18", "USP-S", "Tec9", "CZ75", "Revolver" - }; public BulletForBullet(BasePlugin plugin, ILastRequestManager manager, CCSPlayerController prisoner, CCSPlayerController guard, bool magForMag) : base(plugin, manager, prisoner, guard) { - chatMenu = new ChatMenu(magForMag ? "Mag for Mag" : "Shot for Shot"); - foreach (var pistol in Tag.PISTOLS) { + this.magForMag = magForMag; + chatMenu = new ChatMenu(magForMag ? "Mag for Mag" : "Shot for Shot"); + foreach (var pistol in GUNS) chatMenu.AddMenuOption(pistol.GetFriendlyWeaponName(), OnSelect); - } } public override LRType Type => LRType.SHOT_FOR_SHOT; @@ -45,21 +44,26 @@ private void OnSelect(CCSPlayerController player, ChatMenuOption option) { + CHOSEN_PISTOL.GetFriendlyWeaponName()); State = LRState.ACTIVE; + Prisoner.RemoveWeapons(); + Guard.RemoveWeapons(); Prisoner.GiveNamedItem(CHOSEN_PISTOL); - Prisoner.GetWeaponBase(CHOSEN_PISTOL).SetAmmo(0, 0); Guard.GiveNamedItem(CHOSEN_PISTOL); - Guard.GetWeaponBase(CHOSEN_PISTOL).SetAmmo(0, 0); - //steal the VData of the prisoners gun for mag size - magSize = magForMag ? - Prisoner.GetWeaponBase(CHOSEN_PISTOL)!.VData!.MaxClip1 : - 1; + Server.NextFrame(() => { + magSize = magForMag ? + Prisoner.GetWeaponBase(CHOSEN_PISTOL)!.VData!.MaxClip1 : + 1; + Prisoner.GetWeaponBase(CHOSEN_PISTOL).SetAmmo(0, 0); + Guard.GetWeaponBase(CHOSEN_PISTOL).SetAmmo(0, 0); + //steal the VData of the prisoners gun for mag size - var shooter = new Random().Next(2) == 0 ? Prisoner : Guard; - whosShot = shooter.Slot; - PrintToParticipants(shooter.PlayerName + " gets to shoot first"); + var shooter = new Random().Next(2) == 0 ? Prisoner : Guard; + whosShot = shooter.Slot; + PrintToParticipants(shooter.PlayerName + + $" gets to shoot first {magSize} {magForMag}"); - shooter.GetWeaponBase(CHOSEN_PISTOL).SetAmmo(magSize.Value, 0); + shooter.GetWeaponBase(CHOSEN_PISTOL).SetAmmo(magSize.Value, 0); + }); } public override void Setup() { @@ -95,7 +99,7 @@ public override void Execute() { LRResult.GUARD_WIN : LRResult.PRISONER_WIN; if (Guard.Health == Prisoner.Health) { - var active = whosShot == Prisoner.Slot ? Guard : Prisoner; + var active = whosShot == Prisoner.Slot ? Prisoner : Guard; PrintToParticipants("Even health, since " + active.PlayerName + " had the shot, they lose."); result = whosShot == Prisoner.Slot ? @@ -111,7 +115,7 @@ public override void Execute() { } private void timeout() { - if (CHOSEN_PISTOL == String.Empty) + if (CHOSEN_PISTOL == string.Empty) Manager.EndLastRequest(this, LRResult.TIMED_OUT); } @@ -132,12 +136,14 @@ private HookResult OnPlayerShoot(EventBulletImpact @event, return HookResult.Handled; } - if (player.GetWeaponBase(CHOSEN_PISTOL).Clip1 != 0) - return HookResult.Continue; + var bullets = player.GetWeaponBase(CHOSEN_PISTOL!)?.Clip1 ?? 1; + if (bullets > 1) return HookResult.Continue; - var opponent = player.Slot == Prisoner.Slot ? Guard : Prisoner; - opponent.GetWeaponBase(CHOSEN_PISTOL).SetAmmo(magSize.Value, 0); - whosShot = opponent.Slot; + Server.NextFrame(() => { + var opponent = player.Slot == Prisoner.Slot ? Guard : Prisoner; + whosShot = opponent.Slot; + opponent.GetWeaponBase(CHOSEN_PISTOL!).SetAmmo(magSize.Value, 0); + }); return HookResult.Continue; } diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/ArmoryRestrictedDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/ArmoryRestrictedDay.cs index 8518f724..668bff3b 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/ArmoryRestrictedDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/ArmoryRestrictedDay.cs @@ -24,7 +24,7 @@ public virtual IView ArmoryReminder override protected IZone GetZone() { - var manager = provider.GetRequiredService(); + var manager = provider.GetRequiredService(); var zones = manager.GetZones(ZoneType.ARMORY).GetAwaiter().GetResult(); if (zones.Count > 0) return new MultiZoneWrapper(zones); diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/CellRestrictedDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/CellRestrictedDay.cs index 575ada85..c9c1d5d5 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/CellRestrictedDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/CellRestrictedDay.cs @@ -23,7 +23,7 @@ public virtual IView CellReminder new SimpleView { SpecialDayMessages.PREFIX, "Stay in cells!" }; override protected IZone GetZone() { - var manager = provider.GetRequiredService(); + var manager = provider.GetRequiredService(); var zones = manager.GetZones(ZoneType.CELL).GetAwaiter().GetResult(); if (zones.Count > 0) return new MultiZoneWrapper(zones); diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs index 0a9b9ec9..1afa9d4c 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/HideAndSeekDay.cs @@ -24,28 +24,27 @@ public class HideAndSeekDay(BasePlugin plugin, IServiceProvider provider) public ISpecialDayInstanceMessages Messages => new HNSDayMessages(); public override void Setup() { - Timers[5] += () => msg.DamageWarning(5).ToTeamChat(CsTeam.CounterTerrorist); Timers[10] += () => { foreach (var ct in PlayerUtil.FromTeam(CsTeam.CounterTerrorist)) { ct.SetSpeed(1.5f); - EnableDamage(ct); } - ((ISpecialDayMessageProvider)this).Messages.BeginsIn(25).ToAllChat(); + msg.DamageWarning(15).ToTeamChat(CsTeam.CounterTerrorist); + + Messages.BeginsIn(35).ToAllChat(); }; Timers[25] += () => { foreach (var ct in PlayerUtil.FromTeam(CsTeam.CounterTerrorist)) { ct.SetSpeed(1.25f); EnableDamage(ct); } - - Messages.BeginsIn(10).ToAllChat(); }; Timers[30] += () => { foreach (var ct in PlayerUtil.FromTeam(CsTeam.CounterTerrorist)) ct.SetSpeed(1.1f); + Messages.BeginsIn(15).ToAllChat(); }; - Timers[35] += Execute; + Timers[45] += Execute; base.Setup(); diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/InfectionDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/InfectionDay.cs index 8b1cc644..1f01844e 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/InfectionDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/InfectionDay.cs @@ -1,7 +1,6 @@ using System.Drawing; using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Commands; using CounterStrikeSharp.API.Modules.Utils; using Jailbreak.English.SpecialDay; using Jailbreak.Formatting.Extensions; @@ -114,7 +113,8 @@ public HookResult OnRespawn(EventPlayerSpawn @event, GameEventInfo info) { return HookResult.Continue; } - public override HookResult OnEnd(EventRoundEnd @event, GameEventInfo info) { + override protected HookResult + OnEnd(EventRoundEnd @event, GameEventInfo info) { var result = base.OnEnd(@event, info); plugin.DeregisterEventHandler(OnPlayerDeath); plugin.DeregisterEventHandler(OnRespawn); diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs index e0d7880d..efb5532f 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/OneInTheChamberDay.cs @@ -1,7 +1,4 @@ -using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Entities; -using CounterStrikeSharp.API.Modules.Entities.Constants; using Jailbreak.English.SpecialDay; using Jailbreak.Formatting.Views; using Jailbreak.Public.Extensions; @@ -53,7 +50,8 @@ private HookResult return HookResult.Continue; } - public override HookResult OnEnd(EventRoundEnd @event, GameEventInfo info) { + override protected HookResult + OnEnd(EventRoundEnd @event, GameEventInfo info) { plugin.DeregisterEventHandler(OnPlayerDamage); plugin.DeregisterEventHandler(OnPlayerDeath); return base.OnEnd(@event, info); diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/SpeedrunDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/SpeedrunDay.cs index 1a7e2013..8b59a7ee 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/SpeedrunDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/SpeedrunDay.cs @@ -1,7 +1,7 @@ using System.Drawing; using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Entities.Constants; +using CounterStrikeSharp.API.Modules.Cvars; using CounterStrikeSharp.API.Modules.Timers; using CounterStrikeSharp.API.Modules.Utils; using Jailbreak.English.SpecialDay; @@ -15,26 +15,28 @@ using Jailbreak.Public.Utils; using Jailbreak.Trail; using Microsoft.Extensions.DependencyInjection; -using Microsoft.VisualBasic.CompilerServices; using Timer = CounterStrikeSharp.API.Modules.Timers.Timer; namespace Jailbreak.SpecialDay.SpecialDays; public class SpeedrunDay(BasePlugin plugin, IServiceProvider provider) : AbstractSpecialDay(plugin, provider), ISpecialDayMessageProvider { - private const int FIRST_SPEEDRUNNER_TIME = 40; + private const int FIRST_SPEEDRUNNER_TIME = 30; private const int FIRST_ROUND_FREEZE = 8; private const int FREEZE_TIME = 2; private const int MAX_POINTS = 500; - private readonly Random rng = new(); + + public static readonly FakeConVar CvInitialSpeedrunTime = + new("css_jb_speedrun_initial_time", "Initial time for the speedrunner", 30); + + public static readonly FakeConVar CvFirstRoundFreeze = + new("css_jb_speedrun_first_round_freeze", + "Duration in seconds to give players time to read the rules of speedrun", + 8); private readonly IDictionary> activeTrails = new Dictionary>(); - private AbstractTrail? bestTrail; - private float? bestTime; - private Timer? finishCheckTimer; - /// /// Negative values represent players who finished. /// Positive values represent players who are still alive, and the value @@ -43,9 +45,15 @@ private readonly IDictionary> private readonly IDictionary finishTimestamps = new SortedDictionary(); + private readonly Random rng = new(); + private float? bestTime; + private int? bestTimePlayerSlot; + + private AbstractTrail? bestTrail; + private Timer? finishCheckTimer; + private IGenericCommandNotifications generics = null!; private int round, playersAliveAtStart; - private int? bestTimePlayerSlot; private Timer? roundEndTimer; private float? roundStartTime; @@ -91,7 +99,7 @@ public override void Setup() { start = speedrunner.PlayerPawn.Value!.AbsOrigin!.Clone(); speedrunner.UnFreeze(); bestTrail = new ActivePulsatingBeamPlayerTrail(plugin, speedrunner, 0f, - MAX_POINTS, updateRate: 0.15f); + MAX_POINTS, 0.15f); }; Timers[FIRST_SPEEDRUNNER_TIME + FIRST_ROUND_FREEZE - 30] += () @@ -179,8 +187,10 @@ private void checkFinishers() { if (finishTimestamps.ContainsKey(player.Slot)) continue; var pos = player.Pawn.Value?.AbsOrigin; if (pos == null) continue; + var hdist = pos.HorizontalDistanceSquared(target); + if (hdist >= required) continue; var dist = pos.DistanceSquared(target); - if (dist >= required) continue; + if (dist >= required * 1.25f) continue; onFinish(player); } } @@ -197,8 +207,9 @@ private void onFinish(CCSPlayerController player) { bestTimePlayerSlot = player.Slot; msg.BestTime(player, time).ToAllChat(); player.SetColor(Color.FromArgb(255, Color.Gold)); - } else + } else { msg.PlayerTime(player, finishTimestamps.Count + 1, -time).ToAllChat(); + } finishTimestamps[player.Slot] = -Server.CurrentTime; var eliminations = getEliminations(PlayerUtil.GetAlive().Count()); @@ -234,8 +245,7 @@ private void resetTrails() { activeTrails[bestPlayer].StopTracking(); // bestTrail = BeamTrail.FromTrail(plugin, activeTrails[bestPlayer]); bestTrail = PulsatingBeamTrail.FromTrail(plugin, - activeTrails[bestPlayer], pulseRate: 0.05f, pulseMin: 0.5f, - pulseMax: 1.5f); + activeTrails[bestPlayer]); } } } @@ -273,10 +283,9 @@ private void endRound() { var tMade = PlayerUtil.FromTeam(CsTeam.Terrorist).Count() < 4; foreach (var player in PlayerUtil.GetAlive()) { - if (finishTimestamps.ContainsKey(player.Slot)) { - if (player.Team == CsTeam.CounterTerrorist) ctMade = true; - if (player.Team == CsTeam.Terrorist) tMade = true; - } + if (player.Team == CsTeam.CounterTerrorist) ctMade = true; + if (player.Team == CsTeam.Terrorist) tMade = true; + if (finishTimestamps.ContainsKey(player.Slot)) continue; var dist = player.PlayerPawn.Value?.AbsOrigin?.Distance(target); if (dist == null) continue; @@ -297,9 +306,8 @@ private void endRound() { bestTrail?.Kill(); randomTrail.StopTracking(); // bestTrail = BeamTrail.FromTrail(plugin, activeTrails[bestPlayer]); - bestTrail = PulsatingBeamTrail.FromTrail(plugin, randomTrail, - pulseRate: 0.05f, pulseMin: 0.5f, pulseMax: 1.5f); - target = bestTrail!.GetEndSegment()!.GetEnd(); + bestTrail = PulsatingBeamTrail.FromTrail(plugin, randomTrail); + target = bestTrail!.GetEndSegment()!.GetEnd(); } toEliminate = 2; @@ -309,9 +317,6 @@ private void endRound() { announceTimes(); var slowTimes = SlowestTimes(finishTimestamps); var keyValuePairs = slowTimes.ToList(); - var fastTimestamp = keyValuePairs.Where(s => s.Value < 0) - .Select(s => s.Value) - .LastOrDefault(-(Server.CurrentTime - FIRST_SPEEDRUNNER_TIME)); if (aliveCount <= 2) { // Announce winners, end the round, etc. @@ -355,14 +360,17 @@ private void endRound() { winner.GiveNamedItem("weapon_knife"); winner.GiveNamedItem("weapon_negev"); + + plugin.RemoveListener(OnTick); + RoundUtil.SetTimeRemaining(30); Server.ExecuteCommand("mp_ignore_round_win_conditions 0"); return; } - var fastTime = MathF.Abs(fastTimestamp) - roundStartTime!; + // var fastTime = MathF.Abs(fastTimestamp) - roundStartTime!; var roundTimeWas = Math.Ceiling(Server.CurrentTime - roundStartTime!.Value); - var nextRoundTime = (int)Math.Ceiling(fastTime.Value + 10 - round * 2); + var nextRoundTime = (int)Math.Ceiling((bestTime ?? 20) + 10 - round * 2); if (toEliminate <= 0) { msg.NoneEliminated.ToAllChat(); @@ -434,7 +442,8 @@ private void announceTimes() { var (slot, time) = times[i]; var player = Utilities.GetPlayerFromSlot(slot); if (player == null) continue; - if (time > 0) msg.PlayerTime(player, i + 1, time).ToPlayerChat(player); + if (time > 0) + msg.PlayerTime(player, times.Length - i - 1, time).ToPlayerChat(player); } } @@ -445,7 +454,8 @@ public static IEnumerable> .ThenBy(entry => entry.Value < 0 ? entry.Value : float.MaxValue); } - public override HookResult OnEnd(EventRoundEnd @event, GameEventInfo info) { + override protected HookResult + OnEnd(EventRoundEnd @event, GameEventInfo info) { var id = 0; var result = base.OnEnd(@event, info); @@ -462,8 +472,8 @@ public override HookResult OnEnd(EventRoundEnd @event, GameEventInfo info) { public class SpeedrunSettings : SpecialDaySettings { public SpeedrunSettings() { - CtTeleport = TeleportType.ARMORY_STACKED; - TTeleport = TeleportType.ARMORY_STACKED; + CtTeleport = TeleportType.RANDOM_STACKED; + TTeleport = TeleportType.RANDOM_STACKED; RestrictWeapons = true; StripToKnife = true; ConVarValues["mp_ignore_round_win_conditions"] = true; diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/TeleportDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/TeleportDay.cs index ca390bb2..2165e91a 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/TeleportDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/TeleportDay.cs @@ -1,6 +1,5 @@ using CounterStrikeSharp.API.Core; using Jailbreak.English.SpecialDay; -using Jailbreak.Formatting.Extensions; using Jailbreak.Formatting.Views; using Jailbreak.Public.Extensions; using Jailbreak.Public.Mod.SpecialDay; @@ -40,7 +39,8 @@ private HookResult onDamage(EventPlayerHurt @event, GameEventInfo info) { return HookResult.Continue; } - public override HookResult OnEnd(EventRoundEnd @event, GameEventInfo info) { + override protected HookResult + OnEnd(EventRoundEnd @event, GameEventInfo info) { Plugin.DeregisterEventHandler(onDamage); return base.OnEnd(@event, info); } diff --git a/mod/Jailbreak.SpecialDay/SpecialDays/ZoneRestrictedDay.cs b/mod/Jailbreak.SpecialDay/SpecialDays/ZoneRestrictedDay.cs index 9521c549..0072f097 100644 --- a/mod/Jailbreak.SpecialDay/SpecialDays/ZoneRestrictedDay.cs +++ b/mod/Jailbreak.SpecialDay/SpecialDays/ZoneRestrictedDay.cs @@ -42,7 +42,8 @@ public override void Execute() { Restrictors.Clear(); } - public override HookResult OnEnd(EventRoundEnd @event, GameEventInfo info) { + override protected HookResult + OnEnd(EventRoundEnd @event, GameEventInfo info) { var result = base.OnEnd(@event, info); foreach (var restrictor in Restrictors) restrictor.Kill(); Restrictors.Clear(); diff --git a/mod/Jailbreak.Trail/ActivePlayerTrail.cs b/mod/Jailbreak.Trail/ActivePlayerTrail.cs index c8a01eb5..42b543ba 100644 --- a/mod/Jailbreak.Trail/ActivePlayerTrail.cs +++ b/mod/Jailbreak.Trail/ActivePlayerTrail.cs @@ -1,9 +1,6 @@ -using CounterStrikeSharp.API; -using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Timers; -using CounterStrikeSharp.API.Modules.Utils; using Jailbreak.Public.Extensions; -using Jailbreak.Public.Mod.Draw; using Jailbreak.Public.Mod.Trail; using Timer = CounterStrikeSharp.API.Modules.Timers.Timer; @@ -11,7 +8,6 @@ namespace Jailbreak.Trail; public abstract class ActivePlayerTrail : AbstractTrail where T : ITrailSegment { - public CCSPlayerController Player { get; protected set; } protected readonly Timer Timer; public ActivePlayerTrail(BasePlugin plugin, CCSPlayerController player, @@ -22,6 +18,8 @@ public ActivePlayerTrail(BasePlugin plugin, CCSPlayerController player, TimerFlags.REPEAT | TimerFlags.STOP_ON_MAPCHANGE); } + public CCSPlayerController Player { get; protected set; } + virtual protected void Tick() { if (!Player.IsValid) Kill(); var pos = Player.PlayerPawn.Value?.AbsOrigin; @@ -41,7 +39,7 @@ virtual protected void Tick() { public virtual void StopTracking() { Timer.Kill(); } public override void Kill() { - foreach (var segment in Segments) { segment.Remove(); } + foreach (var segment in Segments) segment.Remove(); StopTracking(); } diff --git a/mod/Jailbreak.Trail/ActivePulsatingBeamPlayerTrail.cs b/mod/Jailbreak.Trail/ActivePulsatingBeamPlayerTrail.cs index b34e5307..e70de8f8 100644 --- a/mod/Jailbreak.Trail/ActivePulsatingBeamPlayerTrail.cs +++ b/mod/Jailbreak.Trail/ActivePulsatingBeamPlayerTrail.cs @@ -1,7 +1,5 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; -using Jailbreak.Public.Extensions; -using Jailbreak.Public.Mod.Draw; namespace Jailbreak.Trail; @@ -12,7 +10,7 @@ public class ActivePulsatingBeamPlayerTrail(BasePlugin plugin, : ActivePlayerTrail(plugin, player, lifetime, maxPoints, updateRate) { private readonly PulsatingBeamTrail trail = new(plugin, lifetime, maxPoints, - updateRate, pulseRate, pulseMin, pulseMax); + updateRate); public override void Kill() { base.Kill(); diff --git a/mod/Jailbreak.Trail/BeamTrailSegment.cs b/mod/Jailbreak.Trail/BeamTrailSegment.cs index 7a71c5cf..2cb5e8d5 100644 --- a/mod/Jailbreak.Trail/BeamTrailSegment.cs +++ b/mod/Jailbreak.Trail/BeamTrailSegment.cs @@ -1,5 +1,4 @@ -using CounterStrikeSharp.API.Modules.Utils; -using Jailbreak.Public.Mod.Draw; +using Jailbreak.Public.Mod.Draw; namespace Jailbreak.Trail; diff --git a/mod/Jailbreak.Trail/PulsatingBeamTrail.cs b/mod/Jailbreak.Trail/PulsatingBeamTrail.cs index be8ea497..eafeb386 100644 --- a/mod/Jailbreak.Trail/PulsatingBeamTrail.cs +++ b/mod/Jailbreak.Trail/PulsatingBeamTrail.cs @@ -5,26 +5,18 @@ using CounterStrikeSharp.API.Modules.Utils; using Jailbreak.Public.Mod.Draw; using Jailbreak.Public.Mod.Trail; +using Timer = CounterStrikeSharp.API.Modules.Timers.Timer; namespace Jailbreak.Trail; public class PulsatingBeamTrail : AbstractTrail { - private readonly float pulseRate; - private readonly float pulseMin; - private readonly float pulseMax; - private readonly Func transform; private readonly BasePlugin plugin; - private readonly CounterStrikeSharp.API.Modules.Timers.Timer timer; + private readonly Timer timer; public PulsatingBeamTrail(BasePlugin plugin, float lifetime = 20, - int maxPoints = 100, float updateRate = 0.25f, float pulseRate = 0.5f, - float pulseMin = 0.5f, float pulseMax = 2.5f, + int maxPoints = 100, float updateRate = 0.25f, Func? transform = null) : base(lifetime, maxPoints) { - this.plugin = plugin; - this.pulseRate = pulseRate; - this.pulseMin = pulseMin; - this.pulseMax = pulseMax; - this.transform = transform ?? MathF.Sin; + this.plugin = plugin; timer = plugin.AddTimer(updateRate, Update, TimerFlags.REPEAT | TimerFlags.STOP_ON_MAPCHANGE); @@ -39,7 +31,7 @@ protected void Update() { line.SetColor(Color.FromArgb(0, 0, 0, 0)); else line.SetColor(Color.FromArgb( - (int)Math.Clamp((width / 2.5f) * 255, 0, 255), 255, 255, 255)); + (int)Math.Clamp(width / 2.5f * 255, 0, 255), 255, 255, 255)); line.SetWidth(width); line.Update(); i += 1; @@ -52,11 +44,10 @@ public override void Kill() { } public static PulsatingBeamTrail? FromTrail(BasePlugin plugin, - AbstractTrail trail, float updateRate = 0.25f, float pulseRate = 0.5f, - float pulseMin = 0.5f, float pulseMax = 1.5f, + AbstractTrail trail, float updateRate = 0.25f, Func? transform = null) where T : ITrailSegment { var beamTrail = new PulsatingBeamTrail(plugin, trail.Lifetime, - trail.MaxPoints, updateRate, pulseRate, pulseMin, pulseMax, transform); + trail.MaxPoints, updateRate, transform); foreach (var segment in trail) beamTrail.Segments.Add( beamTrail.CreateSegment(segment.GetStart(), segment.GetEnd())); diff --git a/mod/Jailbreak.Warden/Commands/OpenCommandsBehavior.cs b/mod/Jailbreak.Warden/Commands/OpenCommandsBehavior.cs index aff36984..f28f4dd3 100644 --- a/mod/Jailbreak.Warden/Commands/OpenCommandsBehavior.cs +++ b/mod/Jailbreak.Warden/Commands/OpenCommandsBehavior.cs @@ -8,12 +8,14 @@ using Jailbreak.Formatting.Views; using Jailbreak.Public.Behaviors; using Jailbreak.Public.Mod.Warden; +using Jailbreak.Public.Mod.Zones; using Jailbreak.Public.Utils; namespace Jailbreak.Warden.Commands; public class OpenCommandsBehavior(IWardenService warden, - IWardenNotifications msg, IOpenCommandMessages openMsg) : IPluginBehavior { + IWardenNotifications msg, IOpenCommandMessages openMsg, + IZoneManager zoneManager) : IPluginBehavior { public static readonly FakeConVar CvOpenCommandCooldown = new( "css_jb_warden_open_cooldown", "Minimum seconds warden must wait before being able to open the cells.", 30, @@ -34,7 +36,7 @@ public void Command_Open(CCSPlayerController? executor, CommandInfo info) { return; } - var result = MapUtil.OpenCells(); - openMsg.OpenResult(result).ToAllChat(); + var result = MapUtil.OpenCells(zoneManager); + (result ? openMsg.CellsOpened : openMsg.OpeningFailed).ToAllChat(); } } \ No newline at end of file diff --git a/mod/Jailbreak.Zones/DistanceZone.cs b/mod/Jailbreak.Zones/DistanceZone.cs index 5d3f2bc6..483ef729 100644 --- a/mod/Jailbreak.Zones/DistanceZone.cs +++ b/mod/Jailbreak.Zones/DistanceZone.cs @@ -18,12 +18,16 @@ public class DistanceZone(IList origins, float tolerance) : IZone { public bool IsInsideZone(Vector position) { if (ConvexHullUtil.IsInsideZone(position, cachedHull)) return true; - var minDistance = GetMinDistance(position); + var minDistance = GetMinDistanceSquared(position); return minDistance < tolerance; } + public float GetMinDistanceSquared(Vector position) { + return ConvexHullUtil.GetMinDistanceSquared(position, cachedHull); + } + public float GetMinDistance(Vector position) { - return ConvexHullUtil.GetMinDistance(position, cachedHull); + return (float)Math.Sqrt(GetMinDistanceSquared(position)); } public Vector GetCenterPoint() { diff --git a/mod/Jailbreak.Zones/MultiZoneWrapper.cs b/mod/Jailbreak.Zones/MultiZoneWrapper.cs index 5bd7b8c4..00f9f2c2 100644 --- a/mod/Jailbreak.Zones/MultiZoneWrapper.cs +++ b/mod/Jailbreak.Zones/MultiZoneWrapper.cs @@ -26,8 +26,8 @@ public bool IsInsideZone(Vector position) { return zones.Any(zone => zone.IsInsideZone(position)); } - public float GetMinDistance(Vector position) { - return zones.Min(zone => zone.GetMinDistance(position)); + public float GetMinDistanceSquared(Vector position) { + return zones.Min(zone => zone.GetMinDistanceSquared(position)); } public Vector GetCenterPoint() { @@ -53,7 +53,7 @@ public void AddPoint(Vector point) { return; } - var minZone = zones.OrderBy(zone => zone.GetMinDistance(point)).First(); + var minZone = zones.OrderBy(zone => zone.GetMinDistanceSquared(point)).First(); minZone.AddPoint(point); } diff --git a/mod/Jailbreak.Zones/RandomZoneGenerator.cs b/mod/Jailbreak.Zones/RandomZoneGenerator.cs new file mode 100644 index 00000000..e1a4e54f --- /dev/null +++ b/mod/Jailbreak.Zones/RandomZoneGenerator.cs @@ -0,0 +1,152 @@ +using CounterStrikeSharp.API; +using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core.Attributes.Registration; +using CounterStrikeSharp.API.Modules.Timers; +using CounterStrikeSharp.API.Modules.Utils; +using Jailbreak.Public.Behaviors; +using Jailbreak.Public.Extensions; +using Jailbreak.Public.Mod.Zones; +using Jailbreak.Public.Utils; +using Timer = CounterStrikeSharp.API.Modules.Timers.Timer; + +namespace Jailbreak.Zones; + +public class RandomZoneGenerator(IZoneManager zoneManager, IZoneFactory factory) + : IPluginBehavior { + private Timer timer; + private readonly BasePlugin? plugin; + private IZone? cells; + private IList? restrictedAreas; + private IList? randomPoints; + + public void Start(BasePlugin basePlugin) { + basePlugin.RegisterListener(OnNewMap); + } + + private void startTimer() { + timer?.Kill(); + timer = plugin.AddTimer(63f, tick, TimerFlags.REPEAT); + } + + private void OnNewMap(string mapname) { + cells = getCells(); + restrictedAreas = getRestrictedAreas(); + randomPoints = getRandomPoints(); + startTimer(); + } + + private void tick() { + foreach (var player in PlayerUtil.GetAlive()) tick(player); + } + + private void tick(CCSPlayerController player) { + var pawn = player.PlayerPawn.Value; + if (pawn == null) return; + if (!pawn.OnGroundLastTick) return; + var pos = pawn.AbsOrigin; + if (pos == null) return; + pos = pos.Clone(); + if (cells != null && cells.IsInsideZone(pos)) return; + if (restrictedAreas == null) return; + var dist = restrictedAreas.Min(a => a.GetMinDistanceSquared(pos)); + if (dist <= DistanceZone.WIDTH_MEDIUM_ROOM) return; + dist = restrictedAreas.Min(a => a.GetMinDistanceSquared(pos)); + if (dist <= DistanceZone.WIDTH_MEDIUM_ROOM) return; + + if (randomPoints?.Count > Server.MaxPlayers) { + var nearestPoint = randomPoints.OrderBy(z => z.GetMinDistanceSquared(pos)) + .First(); + var currentScore = zoneScore(randomPoints); + var newPoints = new List(randomPoints); + newPoints.Remove(nearestPoint); + if (!(zoneScore(newPoints) > currentScore)) return; + + randomPoints = newPoints; + var map = Server.MapName; + var zone = factory.CreateZone([pos]); + zone.Id = nearestPoint.Id; + Server.NextFrameAsync(async () => { + await zoneManager.DeleteZone(zone.Id, map); + await zoneManager.PushZoneWithID(zone, ZoneType.SPAWN, map); + randomPoints = getRandomPoints(); + }); + + return; + } + + var spawn = factory.CreateZone([pos]); + zoneManager.PushZone(spawn, ZoneType.SPAWN); + } + + private float zoneScore(IList? zones) { + var total = 0f; + var count = 0; + + switch (zones?.Count) { + case 1: + return float.NegativeInfinity; + case < 2: + return 0f; + } + + for (var i = 0; i < zones?.Count; i++) { + for (var j = i + 1; j < zones.Count; j++) { + total += zones[i] + .GetCenterPoint() + .DistanceSquared(zones[j].GetCenterPoint()); + count++; + } + } + + return total / count; + } + + void IDisposable.Dispose() { timer.Kill(); } + + private IList? getRandomPoints() { + var zones = zoneManager.GetZones(ZoneType.SPAWN).GetAwaiter().GetResult(); + return zones; + } + + private IZone? getCells() { + var result = zoneManager.GetZones(ZoneType.CELL).GetAwaiter().GetResult(); + if (result.Count > 0) return new MultiZoneWrapper(result); + + var bounds = new DistanceZone( + Utilities + .FindAllEntitiesByDesignerName("info_player_terrorist") + .Where(s => s.AbsOrigin != null) + .Select(s => s.AbsOrigin!) + .ToList(), DistanceZone.WIDTH_CELL); + return bounds; + } + + private IZone getArmory() { + var armory = zoneManager.GetZones(ZoneType.ARMORY).GetAwaiter().GetResult(); + if (armory.Count > 0) return new MultiZoneWrapper(armory); + + var bounds = new DistanceZone( + Utilities + .FindAllEntitiesByDesignerName("info_player_terrorist") + .Where(s => s.AbsOrigin != null) + .Select(s => s.AbsOrigin!) + .ToList(), DistanceZone.WIDTH_CELL); + return bounds; + } + + private IList? getRestrictedAreas() { + List result = []; + var tZones = zoneManager.GetZones(ZoneType.ZONE_LIMIT_T) + .GetAwaiter() + .GetResult(); + + var ctZones = zoneManager.GetZones(ZoneType.ZONE_LIMIT_CT) + .GetAwaiter() + .GetResult(); + + result.AddRange(tZones); + result.AddRange(ctZones); + result.Add(getArmory()); + return result; + } +} \ No newline at end of file diff --git a/mod/Jailbreak.Zones/SqlZoneManager.cs b/mod/Jailbreak.Zones/SqlZoneManager.cs index f07fa8c8..01eb04d7 100644 --- a/mod/Jailbreak.Zones/SqlZoneManager.cs +++ b/mod/Jailbreak.Zones/SqlZoneManager.cs @@ -41,6 +41,13 @@ public async Task DeleteZone(int zoneId, string map) { } } + foreach (var list in zones.Values) { + var zone = list.FirstOrDefault(z => z.Id == zoneId); + if (zone == null) continue; + list.Remove(zone); + break; + } + var conn = createConnection(); if (conn == null) return; await conn.OpenAsync(); @@ -59,7 +66,6 @@ public async Task DeleteZone(int zoneId, string map) { } public async Task PushZoneWithID(IZone zone, ZoneType type, string map) { - Server.NextFrame(() => { Server.PrintToConsole("Pushing zone to SQL"); }); if (!zones.TryGetValue(type, out var list)) { list = new List(); zones[type] = list; @@ -69,16 +75,12 @@ public async Task PushZoneWithID(IZone zone, ZoneType type, string map) { var conn = createConnection(); if (conn == null) return; - Server.NextFrame(() => { - Server.PrintToConsole("Successfully connect to sql"); - }); await conn.OpenAsync(); var insertPointCommand = $""" INSERT INTO {CvSqlTable.Value.Trim('"')} (map, type, zoneid, pointid, X, Y, Z) VALUES (@map, @type, @zoneid, @pointid, @X, @Y, @Z) """; - Server.NextFrame(() => { Server.PrintToConsole("Creating command"); }); var pointId = 0; foreach (var point in zone.GetAllPoints()) { diff --git a/mod/Jailbreak.Zones/ZoneMovementRestrictor.cs b/mod/Jailbreak.Zones/ZoneMovementRestrictor.cs index 5a5536af..b97c203d 100644 --- a/mod/Jailbreak.Zones/ZoneMovementRestrictor.cs +++ b/mod/Jailbreak.Zones/ZoneMovementRestrictor.cs @@ -14,7 +14,7 @@ public ZoneMovementRestrictor(BasePlugin plugin, CCSPlayerController player, } public override float DistanceFrom(Vector vec) { - return zone.GetMinDistance(vec); + return zone.GetMinDistanceSquared(vec); } public override Vector GetCenter() { return zone.GetCenterPoint(); } diff --git a/mod/Jailbreak.Zones/ZoneServiceExtension.cs b/mod/Jailbreak.Zones/ZoneServiceExtension.cs index a90dc7e2..1a87f52a 100644 --- a/mod/Jailbreak.Zones/ZoneServiceExtension.cs +++ b/mod/Jailbreak.Zones/ZoneServiceExtension.cs @@ -8,5 +8,6 @@ public static class ZoneServiceExtension { public static void AddJailbreakZones(this IServiceCollection service) { service.AddPluginBehavior(); service.AddPluginBehavior(); + service.AddPluginBehavior(); } } \ No newline at end of file diff --git a/public/Jailbreak.Formatting/Core/FormatObject.cs b/public/Jailbreak.Formatting/Core/FormatObject.cs index 123bbe46..e3f75b79 100644 --- a/public/Jailbreak.Formatting/Core/FormatObject.cs +++ b/public/Jailbreak.Formatting/Core/FormatObject.cs @@ -40,7 +40,7 @@ public static implicit operator FormatObject(int value) { public static implicit operator FormatObject(float value) { return new FloatFormatObject(value); } - + public static implicit operator FormatObject(CsTeam value) { return new TeamFormatObject(value); } diff --git a/public/Jailbreak.Formatting/Objects/TeamFormatObject.cs b/public/Jailbreak.Formatting/Objects/TeamFormatObject.cs index ce3a78de..2d6aa228 100644 --- a/public/Jailbreak.Formatting/Objects/TeamFormatObject.cs +++ b/public/Jailbreak.Formatting/Objects/TeamFormatObject.cs @@ -1,7 +1,5 @@ -using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Modules.Utils; +using CounterStrikeSharp.API.Modules.Utils; using Jailbreak.Formatting.Core; -using Jailbreak.Public.Extensions; namespace Jailbreak.Formatting.Objects; diff --git a/public/Jailbreak.Formatting/Views/IOpenCommandMessages.cs b/public/Jailbreak.Formatting/Views/IOpenCommandMessages.cs index 8b3dd8aa..39a5a08d 100644 --- a/public/Jailbreak.Formatting/Views/IOpenCommandMessages.cs +++ b/public/Jailbreak.Formatting/Views/IOpenCommandMessages.cs @@ -1,9 +1,9 @@ using Jailbreak.Formatting.Base; -using Jailbreak.Public.Utils; namespace Jailbreak.Formatting.Views; public interface IOpenCommandMessages { + public IView CellsOpened { get; } + public IView OpeningFailed { get; } public IView CannotOpenYet(int seconds); - public IView OpenResult(Sensitivity? sensitivity); } \ No newline at end of file diff --git a/public/Jailbreak.Formatting/Views/IWardenNotifications.cs b/public/Jailbreak.Formatting/Views/IWardenNotifications.cs index b4a3a9f9..09a4c683 100644 --- a/public/Jailbreak.Formatting/Views/IWardenNotifications.cs +++ b/public/Jailbreak.Formatting/Views/IWardenNotifications.cs @@ -16,6 +16,8 @@ public interface IWardenNotifications { public IView NotWarden { get; } public IView FireCommandFailed { get; } + public IView CannotWardenDuringWarmup { get; } + /// /// Create a view for when the specified player passes warden /// @@ -37,8 +39,6 @@ public interface IWardenNotifications { /// /// public IView CurrentWarden(CCSPlayerController? player); - - public IView CannotWardenDuringWarmup { get; } public IView FireCommandSuccess(CCSPlayerController player); diff --git a/public/Jailbreak.Public/Extensions/CollectionExtensions.cs b/public/Jailbreak.Public/Extensions/CollectionExtensions.cs index 84366626..e2f24e0c 100644 --- a/public/Jailbreak.Public/Extensions/CollectionExtensions.cs +++ b/public/Jailbreak.Public/Extensions/CollectionExtensions.cs @@ -1,7 +1,7 @@ namespace Jailbreak.Public.Extensions; public static class CollectionExtensions { - private static readonly Random Random = new Random(); + private static readonly Random Random = new(); public static void Shuffle(this IList list) { var n = list.Count; diff --git a/public/Jailbreak.Public/Extensions/PlayerExtensions.cs b/public/Jailbreak.Public/Extensions/PlayerExtensions.cs index f310a9d4..1d95522a 100644 --- a/public/Jailbreak.Public/Extensions/PlayerExtensions.cs +++ b/public/Jailbreak.Public/Extensions/PlayerExtensions.cs @@ -125,9 +125,11 @@ public static void SetColor(this CCSPlayerController player, Color color) { pawn.Render = color; Utilities.SetStateChanged(pawn, "CBaseModelEntity", "m_clrRender"); } - - public static CBasePlayerWeapon? GetWeaponBase(this CCSPlayerController player, string designerName) { - return player.PlayerPawn.Value?.WeaponServices?.MyWeapons. - FirstOrDefault(w => w.Value?.DesignerName == designerName)?.Value; + + public static CBasePlayerWeapon? + GetWeaponBase(this CCSPlayerController player, string designerName) { + return player.PlayerPawn.Value?.WeaponServices?.MyWeapons + .FirstOrDefault(w => w.Value?.DesignerName == designerName) + ?.Value; } } \ No newline at end of file diff --git a/public/Jailbreak.Public/Extensions/WeaponExtensions.cs b/public/Jailbreak.Public/Extensions/WeaponExtensions.cs index 460772b5..a1bcb7ec 100644 --- a/public/Jailbreak.Public/Extensions/WeaponExtensions.cs +++ b/public/Jailbreak.Public/Extensions/WeaponExtensions.cs @@ -130,14 +130,15 @@ public static string GetFriendlyWeaponName(this string designerName) { return "UNKNOWN: Please Contact Tech"; } } - public static void AddBulletsToMagazine(this CBasePlayerWeapon? weapon, + + public static void AddBulletsToMagazine(this CBasePlayerWeapon? weapon, int bullets) { if (weapon.Clip1 + bullets > weapon.VData!.MaxClip1) { - int overflowBullets = (weapon.Clip1 + bullets) - weapon.VData!.MaxClip1; - weapon.Clip1 = weapon.VData!.MaxClip1; + var overflowBullets = weapon.Clip1 + bullets - weapon.VData!.MaxClip1; + weapon.Clip1 = weapon.VData!.MaxClip1; weapon.ReserveAmmo[0] += overflowBullets; - } - else { weapon.Clip1 += bullets; } + } else { weapon.Clip1 += bullets; } + Utilities.SetStateChanged(weapon, "CBasePlayerWeapon", "m_iClip1"); Utilities.SetStateChanged(weapon, "CBasePlayerWeapon", "m_pReserveAmmo"); } diff --git a/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs b/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs index 03155f87..27607ffe 100644 --- a/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs +++ b/public/Jailbreak.Public/Mod/SpecialDay/AbstractSpecialDay.cs @@ -1,6 +1,5 @@ using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; -using CounterStrikeSharp.API.Core.Attributes.Registration; using CounterStrikeSharp.API.Modules.Cvars; using CounterStrikeSharp.API.Modules.Timers; using CounterStrikeSharp.API.Modules.Utils; @@ -32,6 +31,7 @@ public abstract class AbstractSpecialDay(BasePlugin plugin, /// Use for teleporting, stripping weapons, starting timers, etc. /// public virtual void Setup() { + Plugin.RegisterAllAttributes(this); Plugin.RegisterEventHandler(OnEnd); foreach (var entry in Settings.ConVarValues) { @@ -77,7 +77,8 @@ public virtual void Setup() { if (!Settings.AllowRebels) provider.GetRequiredService().DisableRebelForRound(); - if (Settings.OpenCells) MapUtil.OpenCells(); + if (Settings.OpenCells) + MapUtil.OpenCells(provider.GetRequiredService()); doTeleports(); @@ -139,12 +140,17 @@ private void doTeleports(SpecialDaySettings.TeleportType type, spawnPositions = getRandomSpawns(false, false).ToList(); // If we don't have enough manually specified spawns, // gradually pull from the other spawn types - if (spawnPositions.Count() < PlayerUtil.GetAlive().Count()) { - spawnPositions = getRandomSpawns(true, false).ToList(); - if (spawnPositions.Count() < PlayerUtil.GetAlive().Count()) - spawnPositions = getRandomSpawns().ToList(); - } - + if (spawnPositions.Count() < PlayerUtil.GetAlive().Count()) + spawnPositions = getRandomSpawns(false).ToList(); + if (spawnPositions.Count() < PlayerUtil.GetAlive().Count()) + spawnPositions = getRandomSpawns().ToList(); + break; + case SpecialDaySettings.TeleportType.RANDOM_STACKED: + spawnPositions = getRandomSpawns(false, false).Take(1).ToList(); + if (!spawnPositions.Any()) + spawnPositions = getRandomSpawns(false).Take(1).ToList(); + if (!spawnPositions.Any()) + spawnPositions = getRandomSpawns().Take(1).ToList(); break; default: return; @@ -155,7 +161,7 @@ private void doTeleports(SpecialDaySettings.TeleportType type, player.PlayerPawn.Value?.Teleport(baggedSpawns.GetNext()); } - private IEnumerable getRandomSpawns(bool includeSpawns = true, + private List getRandomSpawns(bool includeSpawns = true, bool includeTps = true) { var result = new List(); @@ -182,12 +188,11 @@ private IEnumerable getRandomSpawns(bool includeSpawns = true, result.AddRange(ctSpawns); } - var zoneManager = provider.GetRequiredService(); - var zones = zoneManager.GetZones(ZoneType.SPAWN).GetAwaiter().GetResult(); + var zoneManager = provider.GetRequiredService(); + var zones = zoneManager.GetZones(ZoneType.SPAWN).GetAwaiter().GetResult(); result.AddRange(zones.Select(z => z.GetCenterPoint())); result.Shuffle(); - return result; } @@ -219,8 +224,6 @@ protected object GetConvarValue(ConVar? cvar) { protected void SetConvarValue(ConVar? cvar, object value) { if (cvar == null) return; try { - cvar.Flags |= ConVarFlags.FCVAR_REPLICATED | ConVarFlags.FCVAR_NOTIFY - | ConVarFlags.FCVAR_PER_USER; switch (cvar.Type) { case ConVarType.Bool: cvar.SetValue((bool)value); @@ -253,13 +256,12 @@ protected void SetConvarValue(ConVar? cvar, object value) { Server.ExecuteCommand(cvar.Name + " " + value); if (cvar.Name == "mp_teammates_are_enemies") { - bool opposite = !((bool)value); + var opposite = !(bool)value; Server.ExecuteCommand("css_cvar mp_teammates_are_enemies " + opposite); - Plugin.AddTimer(0.1f, - () => { - Server.ExecuteCommand("css_cvar mp_teammates_are_enemies " + value); - }); + Server.NextFrame(() => { + Server.ExecuteCommand("css_cvar mp_teammates_are_enemies " + value); + }); } } catch (Exception e) { Server.PrintToChatAll( @@ -300,18 +302,17 @@ private void disableWeapon(CCSPlayerController player, activeWeapon.NextPrimaryAttackTick = Server.TickCount + 500; } - [GameEventHandler] - public virtual HookResult OnEnd(EventRoundEnd @event, GameEventInfo info) { + virtual protected HookResult OnEnd(EventRoundEnd @event, GameEventInfo info) { foreach (var entry in previousConvarValues) { var cv = ConVar.Find(entry.Key); if (cv == null || entry.Value == null) continue; - try { SetConvarValue(cv, entry.Value); } catch (InvalidOperationException - e) { Console.WriteLine(e); } + SetConvarValue(cv, entry.Value); } + previousConvarValues.Clear(); + if (Settings.RestrictWeapons) Plugin.RemoveListener(OnTick); - previousConvarValues.Clear(); Plugin.DeregisterEventHandler(OnEnd); return HookResult.Continue; diff --git a/public/Jailbreak.Public/Mod/SpecialDay/SpecialDaySettings.cs b/public/Jailbreak.Public/Mod/SpecialDay/SpecialDaySettings.cs index 0bfac3b8..fdfa72b8 100644 --- a/public/Jailbreak.Public/Mod/SpecialDay/SpecialDaySettings.cs +++ b/public/Jailbreak.Public/Mod/SpecialDay/SpecialDaySettings.cs @@ -33,7 +33,12 @@ public enum TeleportType { /// /// Teleport all players randomly across the map /// - RANDOM + RANDOM, + + /// + /// Pick a random teleport on the map and teleport all players to it + /// + RANDOM_STACKED } public bool AllowLastGuard = false; @@ -102,10 +107,10 @@ public virtual int InitialMaxHealth(CCSPlayerController player) { public virtual int InitialArmor(CCSPlayerController player) { return 0; } public SpecialDaySettings WithFriendlyFire() { - ConVarValues["mp_teammates_are_enemies"] = true; - ConVarValues["ff_damage_reduction_bullets"] = 1.0f; + ConVarValues["mp_teammates_are_enemies"] = true; + ConVarValues["ff_damage_reduction_bullets"] = 1.0f; ConVarValues["ff_damage_reduction_grenade"] = 1.0f; - ConVarValues["ff_damage_reduction_other"] = 1.0f; + ConVarValues["ff_damage_reduction_other"] = 1.0f; return this; } diff --git a/public/Jailbreak.Public/Mod/Trail/AbstractTrail.cs b/public/Jailbreak.Public/Mod/Trail/AbstractTrail.cs index 374893ce..f4eaefab 100644 --- a/public/Jailbreak.Public/Mod/Trail/AbstractTrail.cs +++ b/public/Jailbreak.Public/Mod/Trail/AbstractTrail.cs @@ -61,7 +61,8 @@ public virtual IList GetTrailPoints(int max) { public IList GetTrailPoints() { return GetTrailPoints(Lifetime); } - public virtual T? GetNearestSegment(Vector position, float since, int max = 0) { + public virtual T? + GetNearestSegment(Vector position, float since, int max = 0) { var nearest = default(T); var minDistance = double.MaxValue; foreach (var segment in GetTrail(since, max)) { diff --git a/public/Jailbreak.Public/Mod/Zones/ConvexHullUtil.cs b/public/Jailbreak.Public/Mod/Zones/ConvexHullUtil.cs index 49d9f49c..4455bbc8 100644 --- a/public/Jailbreak.Public/Mod/Zones/ConvexHullUtil.cs +++ b/public/Jailbreak.Public/Mod/Zones/ConvexHullUtil.cs @@ -25,7 +25,8 @@ public static bool IsInsideZone(Vector point, IList hull) { return inside; } - public static float GetMinDistance(Vector position, IList hull) { + public static float + GetMinDistanceSquared(Vector position, IList hull) { if (IsInsideZone(position, hull)) return 0; var minDistance = float.MaxValue; for (var i = 0; i < hull.Count; i++) { @@ -38,6 +39,10 @@ public static float GetMinDistance(Vector position, IList hull) { return minDistance; } + public static float GetMinDistance(Vector position, IList hull) { + return (float)Math.Sqrt(GetMinDistanceSquared(position, hull)); + } + public static IEnumerable ComputeConvexHull(IList points) { if (points.Count < 3) return points; points = points.OrderBy(p => p.X).ThenBy(p => p.Y).ToList(); diff --git a/public/Jailbreak.Public/Mod/Zones/IZone.cs b/public/Jailbreak.Public/Mod/Zones/IZone.cs index b3d53c08..938071ad 100644 --- a/public/Jailbreak.Public/Mod/Zones/IZone.cs +++ b/public/Jailbreak.Public/Mod/Zones/IZone.cs @@ -8,7 +8,7 @@ namespace Jailbreak.Public.Mod.Zones; public interface IZone { public int Id { get; set; } bool IsInsideZone(Vector position); - float GetMinDistance(Vector position); + float GetMinDistanceSquared(Vector position); /// /// Represents a valid center point that players are able to spawn into diff --git a/public/Jailbreak.Public/Mod/Zones/MovementRestrictor.cs b/public/Jailbreak.Public/Mod/Zones/MovementRestrictor.cs index ebb0f75a..30cfbe6a 100644 --- a/public/Jailbreak.Public/Mod/Zones/MovementRestrictor.cs +++ b/public/Jailbreak.Public/Mod/Zones/MovementRestrictor.cs @@ -59,7 +59,6 @@ private void tick() { } onTeleport?.Invoke(); - if (lastValid == null) return; player.PlayerPawn.Value?.Teleport(lastValid ?? GetCenter()); } diff --git a/public/Jailbreak.Public/Mod/Zones/ZoneType.cs b/public/Jailbreak.Public/Mod/Zones/ZoneType.cs index 57f8640e..0336e4e1 100644 --- a/public/Jailbreak.Public/Mod/Zones/ZoneType.cs +++ b/public/Jailbreak.Public/Mod/Zones/ZoneType.cs @@ -13,6 +13,11 @@ public enum ZoneType { /// CELL, + /// + /// This zone is a single point, and represents the cell button + /// + CELL_BUTTON, + /// /// This zone captures a secret area that Ts may try to access /// @@ -50,7 +55,8 @@ public enum ZoneType { ZONE_LIMIT_CT, /// - /// The center of the map (both vertically and horizontally) + /// This zone is a single point, and represents + /// the center of the map (both vertically and horizontally) /// CENTER } @@ -72,6 +78,11 @@ public static Color GetColor(this ZoneType type) { } public static bool IsSinglePoint(this ZoneType type) { - return type == ZoneType.SPAWN; + return type switch { + ZoneType.CELL_BUTTON => true, + ZoneType.SPAWN => true, + ZoneType.CENTER => true, + _ => false + }; } } \ No newline at end of file diff --git a/public/Jailbreak.Public/Utils/MapUtil.cs b/public/Jailbreak.Public/Utils/MapUtil.cs index 425e36f9..6bc740bb 100644 --- a/public/Jailbreak.Public/Utils/MapUtil.cs +++ b/public/Jailbreak.Public/Utils/MapUtil.cs @@ -3,6 +3,7 @@ using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using Jailbreak.Public.Extensions; +using Jailbreak.Public.Mod.Zones; namespace Jailbreak.Public.Utils; @@ -17,8 +18,20 @@ private static Vector getCtSpawn() { .First(); } - public static Sensitivity? OpenCells( - Sensitivity sensitivity = Sensitivity.NAME_CELL_DOOR) { + public static bool OpenCells(IZoneManager zoneManager) { + var zones = zoneManager.GetZones(ZoneType.CELL_BUTTON) + .GetAwaiter() + .GetResult(); + + if (zones.Count == 0) return OpenCells() <= Sensitivity.TARGET_CELL; + + return OpenCells(Sensitivity.ANY, zones[0].GetCenterPoint()) != null; + } + + private static Sensitivity? OpenCells( + Sensitivity sensitivity = Sensitivity.NAME_CELL_DOOR, + Vector? source = null) { + if (source == null) source = getCtSpawn(); var allButtons = Utilities .FindAllEntitiesByDesignerName("func_button") .ToHashSet(); @@ -52,11 +65,10 @@ private static Vector getCtSpawn() { } } - var ctSpawn = getCtSpawn(); - var sorted = entities.ToList(); + var sorted = entities.ToList(); sorted.Sort((a, b) => { - var aDist = a.AbsOrigin!.DistanceSquared(ctSpawn); - var bDist = b.AbsOrigin!.DistanceSquared(ctSpawn); + var aDist = a.AbsOrigin!.DistanceSquared(source); + var bDist = b.AbsOrigin!.DistanceSquared(source); return aDist.CompareTo(bDist); });