diff --git a/.github/en.md b/.github/en.md
index 9421630..8255b85 100644
--- a/.github/en.md
+++ b/.github/en.md
@@ -425,6 +425,26 @@ This plugin uses content from the following projects:
## 馃搵 Changelog
+
+v1.2.4.b2
+
+- #### General
+ - **Ninja, Ghost, C4 Camouflage** - Hidden players are now revealed in the `player_death` pre-hook, preventing `CopyExistingEntity: missing client entity` crashes.
+ - **DisableOnFreezeTime** - Passive damage skills (Cypher, Exploding Barrel, Explosive Shot, Fortnite, Iana, Illusionist and Replicator, etc.) now also respect the setting.
+ - **Skill distribution** - One disconnecting player can no longer stop skill assignment for everyone else; If no skills are assigned, the system retries up to 6 times every 0.5s and logs the reason for failure.
+
+- #### Skill Fixes
+ - **No Recoil** - Changed the way no recoil is applied to prevent it from affecting other players.
+ - **Falcon Eye** - Weapons no longer remain locked after a round ends while the camera is active.
+ - **Jump Ban** - Jumping is now fully blocked by clearing upward velocity and extending the effect duration; The message confirming that jumping is available again now displays correctly.
+ - **Blast Shot** - Grenades can no longer be thrown during freeze time.
+ - **Sound Maker** - Phantom screams no longer come from `0 0 0` and are only sent to living enemies.
+ - **Careful Bullets, Darkness, Deaf, Expensive Ammo, Giant, Glitch, Jammer, Jet Kick, Jump Curse, Magnifier, Nightmare, Poison, Primary Ban, Wild Throw** - The message confirming that the effect ended now displays correctly.
+
+**Full update contributed by [@ByDexterTR](https://github.com/ByDexterTR) in pull request [#58](https://github.com/Juzlus/jRandomSkills/pull/58). Thanks to ByDexterTR!**
+
+
+
v1.2.4.b1
diff --git a/.github/pl.md b/.github/pl.md
index cf1c61c..c7d5eaa 100644
--- a/.github/pl.md
+++ b/.github/pl.md
@@ -425,6 +425,26 @@ Plugin korzysta z zawarto艣ci nast臋puj膮cych projekt贸w:
## 馃搵 Lista Zmian
+
+v1.2.4.b2
+
+- #### Og贸lne
+ - **Ninja, Duszek, C4 Kamufla偶** - Ukryci gracze s膮 teraz ujawniani w `player_death` pre-hooku, co zapobiega crashom `CopyExistingEntity: missing client entity`.
+ - **DisableOnFreezeTime** - Umiej臋tno艣ci zadaj膮ce obra偶enia (Kamera, Wybuchowa Beczka, Strza艂 Wybuchowy, Fortnite, Hologram, Iluzjonista, Replikator itd.) teraz r贸wnie偶 respektuj膮 to ustawienie.
+ - **Skill distribution** - Roz艂膮czaj膮cy si臋 gracz nie mo偶e ju偶 przerwa膰 przydzielania mocy pozosta艂ym; je艣li 偶adna moc nie zostanie przydzielona, system ponawia pr贸b臋 do 6 razy co 0,5 s i zapisuje przyczyn臋 w logach.
+
+- #### Poprawki mocy
+ - **Skupienie** - Zmieniono spos贸b nak艂adania braku odrzutu, aby nie wp艂ywa艂 na innych graczy.
+ - **Oko Soko艂a** - Bro艅 nie pozostaje ju偶 zablokowana po zako艅czeniu rundy, gdy kamera jest aktywna.
+ - **Beznogi** - Skakanie jest teraz ca艂kowicie blokowane przez wyzerowanie pr臋dko艣ci pionowej i wyd艂u偶enie czasu dzia艂ania; wiadomo艣膰 o ponownym odblokowaniu skoku wy艣wietla si臋 poprawnie.
+ - **Mocne Uderzenie** - Granat贸w nie mo偶na ju偶 rzuca膰 podczas freeze time.
+ - **D藕wi臋kowiec** - Duchy krzyk贸w nie pojawiaj膮 si臋 ju偶 w `0 0 0` i s膮 wysy艂ane wy艂膮cznie do 偶ywych przeciwnik贸w.
+ - **Ostro偶ne Pociski, Mrok, G艂uchy, Droga Amunicja, Olbrzym, Glitch, Zak艂贸cacz, Odrzutowy Kop, Kl膮twa Skakania, Lupa, Koszmar, Trutka, Brak Karabin贸w, Dzikie Rzuty** - Wiadomo艣膰 informuj膮ca o zako艅czeniu efektu wy艣wietla si臋 teraz poprawnie.
+
+**Pe艂na aktualizacja zosta艂a przygotowana przez [@ByDexterTR](https://github.com/ByDexterTR) w ramach pull requesta [#58](https://github.com/Juzlus/jRandomSkills/pull/58). Dzi臋kujemy ByDexterTR!**
+
+
+
v1.2.4.b1
diff --git a/jRandomSkills - SRC Files/src/lang/pl.json b/jRandomSkills - SRC Files/src/lang/pl.json
index 883f2b5..0bfd105 100644
--- a/jRandomSkills - SRC Files/src/lang/pl.json
+++ b/jRandomSkills - SRC Files/src/lang/pl.json
@@ -487,7 +487,7 @@
"returntosender": "Zwrot do Nadawcy",
"returntosender_desc": "Pierwsze trafienie wroga powoduje, 偶e wraca on na sw贸j resp",
- "rewind": "Cofni臋cietruearmor",
+ "rewind": "Cofni臋cie",
"rewind_desc": "Naci艣nij [css_useSkill], aby zostawi膰 znacznik i wkr贸tce do niego wr贸ci膰",
"rewind_pending_info": "POWR脫T: {0}",
diff --git a/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs b/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs
index 14e1907..f36f62c 100644
--- a/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs
+++ b/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs
@@ -2,6 +2,7 @@ using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Utils;
using src.utils;
+
using System.Collections.Concurrent;
using static src.jRandomSkills;
@@ -11,75 +12,164 @@ namespace src.player.skills
{
private const Skills skillName = Skills.NoRecoil;
- private static readonly ConcurrentDictionary holders = [];
- private static bool noSpreadActive;
+ private const string NoSpreadConVar = "weapon_accuracy_nospread";
- private static bool defaultNoSpread;
+ private static readonly ConcurrentDictionary holders = [];
+ private static readonly ConcurrentDictionary originalNoSpreadValues = [];
public static void LoadSkill()
{
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color"));
- defaultNoSpread = SkillUtils.CvarValue("weapon_accuracy_nospread", false);
}
public static void NewRound()
{
+ foreach (var player in Utilities.GetPlayers())
+ {
+ if (player == null || !player.IsValid) continue;
+ if (!holders.ContainsKey(player.Index)) continue;
+ RestoreClientNoSpread(player);
+ }
+
holders.Clear();
- ApplyNoSpread(false);
+ originalNoSpreadValues.Clear();
}
public static void EnableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
+ if (!holders.TryAdd(player.Index, 0)) return;
- holders.TryAdd(player.Index, 0);
- ApplyNoSpread(true);
+ try
+ {
+ var currentValue = player.GetConVarValue(NoSpreadConVar);
+ originalNoSpreadValues[player.Index] = string.IsNullOrWhiteSpace(currentValue) ? "0" : currentValue;
+ }
+ catch
+ {
+ originalNoSpreadValues[player.Index] = "0";
+ }
+
+ try
+ {
+ player.ReplicateConVar(NoSpreadConVar, "1");
+ }
+ catch { }
+
+ ResetWeaponState(player);
+ ResetViewPunch(player);
}
public static void DisableSkill(CCSPlayerController player)
{
if (player == null || !player.IsValid) return;
-
holders.TryRemove(player.Index, out _);
- if (holders.IsEmpty)
- ApplyNoSpread(false);
+
+ RestoreClientNoSpread(player);
+ ResetWeaponState(player);
+ ResetViewPunch(player);
}
- private static void ApplyNoSpread(bool enabled)
+ private static void RestoreClientNoSpread(CCSPlayerController player)
{
- if (noSpreadActive == enabled) return;
+ if (player == null || !player.IsValid) return;
+ var value = originalNoSpreadValues.TryGetValue(player.Index, out var originalValue)
+ ? originalValue : "0";
- noSpreadActive = enabled;
- bool value = enabled || defaultNoSpread;
- Server.ExecuteCommand($"weapon_accuracy_nospread {(value ? 1 : 0)}");
- }
-
- public static void OnTick()
- {
- foreach (var player in PlayerManager.GetTickPlayers())
- {
- if (!Instance.IsPlayerValid(player)) continue;
- var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index);
-
- if (playerInfo?.Skill == skillName)
- {
- var pawn = player.PlayerPawn.Value;
- if (pawn == null || !pawn.IsValid) continue;
-
- if (pawn.AimPunchServices != null)
- {
- pawn.AimPunchServices.PredictableBaseTick = 0;
- pawn.AimPunchServices.PredictableBaseTickInterpAmount = 0;
- pawn.AimPunchServices.UnpredictableBaseTick = 0;
- }
-
- if (pawn.CameraServices != null)
- {
- pawn.CameraServices.CsViewPunchAngleTick = 0;
- pawn.CameraServices.CsViewPunchAngleTickRatio = 0f;
- }
- }
+ try {
+ player.ReplicateConVar(NoSpreadConVar, value);
+ originalNoSpreadValues.TryRemove(player.Index, out _);
}
+ catch { }
+ }
+
+ public static void WeaponFire(EventWeaponFire @event)
+ {
+ var player = PlayerManager.GetPlayerEvent(@event.Userid);
+ if (player == null || !player.IsValid) return;
+ if (!holders.ContainsKey(player.Index)) return;
+
+ var playerInfo = PlayerManager.GetPlayerByIndex(player.Index);
+ if (playerInfo?.Skill != skillName) return;
+
+ ResetWeaponState(player);
+ ResetViewPunch(player);
+ }
+
+ private static void ResetWeaponState(CCSPlayerController player)
+ {
+ if (player == null || !player.IsValid) return;
+
+ var pawn = player.PlayerPawn.Value;
+ if (pawn == null || !pawn.IsValid) return;
+
+ if (pawn.ShotsFired != 0)
+ {
+ pawn.ShotsFired = 0;
+ Utilities.SetStateChanged(pawn, "CCSPlayerPawn", "m_iShotsFired");
+ }
+
+ var weapon = pawn.WeaponServices?.ActiveWeapon.Value;
+ if (weapon == null || !weapon.IsValid) return;
+
+ var csWeapon = weapon.As();
+ if (csWeapon == null || !csWeapon.IsValid) return;
+
+ if (csWeapon.AccuracyPenalty != 0f)
+ {
+ csWeapon.AccuracyPenalty = 0f;
+ Utilities.SetStateChanged(weapon, "CCSWeaponBase", "m_fAccuracyPenalty");
+ }
+
+ if (csWeapon.FlRecoilIndex != 0f)
+ {
+ csWeapon.FlRecoilIndex = 0f;
+ Utilities.SetStateChanged(weapon, "CCSWeaponBase", "m_flRecoilIndex");
+ }
+
+ if (csWeapon.IRecoilIndex != 0)
+ {
+ csWeapon.IRecoilIndex = 0;
+ Utilities.SetStateChanged(weapon, "CCSWeaponBase", "m_iRecoilIndex");
+ }
+
+ if (csWeapon.TurningInaccuracy != 0f)
+ {
+ csWeapon.TurningInaccuracy = 0f;
+ Utilities.SetStateChanged(weapon, "CCSWeaponBase", "m_flTurningInaccuracy");
+ }
+ }
+
+ private static void ResetViewPunch(CCSPlayerController player)
+ {
+ if (player == null || !player.IsValid) return;
+
+ var pawn = player.PlayerPawn.Value;
+ if (pawn == null || !pawn.IsValid) return;
+
+ var aim = pawn.AimPunchServices;
+ if (aim != null)
+ {
+ Zero(aim.PredictableBaseAngle);
+ Zero(aim.PredictableBaseAngleVel);
+ Zero(aim.UnpredictableBaseAngle);
+ Utilities.SetStateChanged(pawn, "CCSPlayerPawn", "m_pAimPunchServices");
+ }
+
+ var camera = pawn.CameraServices;
+ if (camera != null)
+ {
+ Zero(camera.CsViewPunchAngle);
+ Utilities.SetStateChanged(pawn, "CBasePlayerPawn", "m_pCameraServices");
+ }
+ }
+
+ private static void Zero(QAngle? angle)
+ {
+ if (angle == null) return;
+ angle.X = 0f;
+ angle.Y = 0f;
+ angle.Z = 0f;
}
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#8a42f5", CsTeam onlyTeam = CsTeam.None, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = -1, Rarity rarity = Rarity.Common) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity)
diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll b/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll
index 5265c1b..ff1b24f 100644
Binary files a/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll and b/jRandomSkills - Server Files/plugins/jRandomSkills/WASDMenuAPI.dll differ
diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll b/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll
index e33d4b1..4dc173f 100644
Binary files a/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll and b/jRandomSkills - Server Files/plugins/jRandomSkills/jRandomSkills.dll differ
diff --git a/jRandomSkills - Server Files/plugins/jRandomSkills/languages/pl.json b/jRandomSkills - Server Files/plugins/jRandomSkills/languages/pl.json
index 883f2b5..0bfd105 100644
--- a/jRandomSkills - Server Files/plugins/jRandomSkills/languages/pl.json
+++ b/jRandomSkills - Server Files/plugins/jRandomSkills/languages/pl.json
@@ -487,7 +487,7 @@
"returntosender": "Zwrot do Nadawcy",
"returntosender_desc": "Pierwsze trafienie wroga powoduje, 偶e wraca on na sw贸j resp",
- "rewind": "Cofni臋cietruearmor",
+ "rewind": "Cofni臋cie",
"rewind_desc": "Naci艣nij [css_useSkill], aby zostawi膰 znacznik i wkr贸tce do niego wr贸ci膰",
"rewind_pending_info": "POWR脫T: {0}",