Update readme & Rework NoRecoil
This commit is contained in:
parent
f73dd5a4df
commit
c58bff7150
7 changed files with 174 additions and 44 deletions
20
.github/en.md
vendored
20
.github/en.md
vendored
|
|
@ -425,6 +425,26 @@ This plugin uses content from the following projects:
|
||||||
|
|
||||||
## 📋 Changelog
|
## 📋 Changelog
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><b>v1.2.4.b2</b></summary>
|
||||||
|
|
||||||
|
- #### 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!**
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><b>v1.2.4.b1</b></summary>
|
<summary><b>v1.2.4.b1</b></summary>
|
||||||
|
|
||||||
|
|
|
||||||
20
.github/pl.md
vendored
20
.github/pl.md
vendored
|
|
@ -425,6 +425,26 @@ Plugin korzysta z zawartości następujących projektów:
|
||||||
|
|
||||||
## 📋 Lista Zmian
|
## 📋 Lista Zmian
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><b>v1.2.4.b2</b></summary>
|
||||||
|
|
||||||
|
- #### 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!**
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><b>v1.2.4.b1</b></summary>
|
<summary><b>v1.2.4.b1</b></summary>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -487,7 +487,7 @@
|
||||||
"returntosender": "Zwrot do Nadawcy",
|
"returntosender": "Zwrot do Nadawcy",
|
||||||
"returntosender_desc": "Pierwsze trafienie wroga powoduje, że wraca on na swój resp",
|
"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_desc": "Naciśnij [css_useSkill], aby zostawić znacznik i wkrótce do niego wrócić",
|
||||||
"rewind_pending_info": "POWRÓT: {0}",
|
"rewind_pending_info": "POWRÓT: {0}",
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using CounterStrikeSharp.API;
|
||||||
using CounterStrikeSharp.API.Core;
|
using CounterStrikeSharp.API.Core;
|
||||||
using CounterStrikeSharp.API.Modules.Utils;
|
using CounterStrikeSharp.API.Modules.Utils;
|
||||||
using src.utils;
|
using src.utils;
|
||||||
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using static src.jRandomSkills;
|
using static src.jRandomSkills;
|
||||||
|
|
||||||
|
|
@ -11,75 +12,164 @@ namespace src.player.skills
|
||||||
{
|
{
|
||||||
private const Skills skillName = Skills.NoRecoil;
|
private const Skills skillName = Skills.NoRecoil;
|
||||||
|
|
||||||
private static readonly ConcurrentDictionary<uint, byte> holders = [];
|
private const string NoSpreadConVar = "weapon_accuracy_nospread";
|
||||||
private static bool noSpreadActive;
|
|
||||||
|
|
||||||
private static bool defaultNoSpread;
|
private static readonly ConcurrentDictionary<uint, byte> holders = [];
|
||||||
|
private static readonly ConcurrentDictionary<uint, string> originalNoSpreadValues = [];
|
||||||
|
|
||||||
public static void LoadSkill()
|
public static void LoadSkill()
|
||||||
{
|
{
|
||||||
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
|
SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue<string>(skillName, "color"));
|
||||||
defaultNoSpread = SkillUtils.CvarValue("weapon_accuracy_nospread", false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void NewRound()
|
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();
|
holders.Clear();
|
||||||
ApplyNoSpread(false);
|
originalNoSpreadValues.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void EnableSkill(CCSPlayerController player)
|
public static void EnableSkill(CCSPlayerController player)
|
||||||
{
|
{
|
||||||
if (player == null || !player.IsValid) return;
|
if (player == null || !player.IsValid) return;
|
||||||
|
if (!holders.TryAdd(player.Index, 0)) return;
|
||||||
|
|
||||||
holders.TryAdd(player.Index, 0);
|
try
|
||||||
ApplyNoSpread(true);
|
{
|
||||||
|
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)
|
public static void DisableSkill(CCSPlayerController player)
|
||||||
{
|
{
|
||||||
if (player == null || !player.IsValid) return;
|
if (player == null || !player.IsValid) return;
|
||||||
|
|
||||||
holders.TryRemove(player.Index, out _);
|
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;
|
try {
|
||||||
bool value = enabled || defaultNoSpread;
|
player.ReplicateConVar(NoSpreadConVar, value);
|
||||||
Server.ExecuteCommand($"weapon_accuracy_nospread {(value ? 1 : 0)}");
|
originalNoSpreadValues.TryRemove(player.Index, out _);
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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<CCSWeaponBase>();
|
||||||
|
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)
|
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)
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -487,7 +487,7 @@
|
||||||
"returntosender": "Zwrot do Nadawcy",
|
"returntosender": "Zwrot do Nadawcy",
|
||||||
"returntosender_desc": "Pierwsze trafienie wroga powoduje, że wraca on na swój resp",
|
"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_desc": "Naciśnij [css_useSkill], aby zostawić znacznik i wkrótce do niego wrócić",
|
||||||
"rewind_pending_info": "POWRÓT: {0}",
|
"rewind_pending_info": "POWRÓT: {0}",
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue