diff --git a/.github/en.md b/.github/en.md index 0d0dd0f..2befcd0 100644 --- a/.github/en.md +++ b/.github/en.md @@ -424,27 +424,6 @@ This plugin uses content from the following projects: ## 馃搵 Changelog -
-v1.2.4.b3 - -- #### General - - Updated compatibility with **CounterStrikeSharp v1.0.375**. - - **Removed RayTrace-CSS-API / RayTrace-MM** (ray tracing is now built into CounterStrikeSharp). - - **Updated gamedata** signatures and offsets for Windows/Linux. - - Skill distribution failures are now logged and retried. - - Spectators without a pawn are excluded from connected-player checks. - -- #### Skill Fixes - - **No Recoil** - Spread and inaccuracy are now disabled server-side for accurate shots. - - **Long Zeus** - Kills now correctly count as Zeus kills, including killfeed, sound and ragdoll effects. - - **Long Knife** - Long-range hits now show a tracer. - - **Fragile Bomb** - Planted bombs are detected reliably and bullet paths are checked correctly. - - **Tripwire** - Beams are now removed correctly when the skill changes. - -**Full update contributed by [@ByDexterTR](https://github.com/ByDexterTR) in pull request [#61](https://github.com/Juzlus/jRandomSkills/pull/61). Thanks to ByDexterTR!** - -
-
v1.2.4.b2 diff --git a/.github/pl.md b/.github/pl.md index aa26a1d..971c7c0 100644 --- a/.github/pl.md +++ b/.github/pl.md @@ -424,27 +424,6 @@ Plugin korzysta z zawarto艣ci nast臋puj膮cych projekt贸w: ## 馃搵 Lista Zmian -
-v1.2.4.b3 - -- #### Og贸lne - - Zaktualizowano kompatybilno艣膰 z **CounterStrikeSharp v1.0.375**. - - **Usuni臋to RayTrace-CSS-API / RayTrace-MM** (ray tracing jest teraz wbudowany w CounterStrikeSharp). - - **Zaktualizowano gamedata** - sygnatury i offsety dla Windows/Linux. - - Obserwatorzy bez pawna nie s膮 ju偶 uwzgl臋dniani podczas sprawdzania liczby po艂膮czonych graczy. - - B艂臋dy podczas przydzielania umiej臋tno艣ci s膮 teraz obserwowane i ponawiane. - -- #### Poprawki mocy - - **Skupienie** - Rozrzut i niecelno艣膰 s膮 teraz wy艂膮czane r贸wnie偶 po stronie serwera, zapewniaj膮c celniejsze strza艂y. - - **D艂ugi Zeus** - Zab贸jstwa s膮 teraz poprawnie zaliczane jako zab贸jstwa z Zeusa, wraz z killfeedem, d藕wi臋kiem i efektami ragdolla. - - **D艂ugi N贸偶** - Trafienia z du偶ego dystansu pokazuj膮 teraz 艣lad. - - **Krucha Bomba** - Pod艂o偶one bomby s膮 teraz wykrywane poprawnie, a trajektoria pocisku jest prawid艂owo sprawdzana. - - **"Linka z Drutu** - Wi膮zki s膮 teraz poprawnie usuwane po zmianie umiej臋tno艣ci. - -**Pe艂na aktualizacja zosta艂a przygotowana przez [@ByDexterTR](https://github.com/ByDexterTR) w ramach pull requesta [#61](https://github.com/Juzlus/jRandomSkills/pull/61). Dzi臋kujemy ByDexterTR!** - -
-
v1.2.4.b2 @@ -2013,4 +1992,4 @@ Plugin korzysta z zawarto艣ci nast臋puj膮cych projekt贸w: ## 馃摑 Kontakt -Je艣li masz jakie艣 pytanie, napisz na juzlus.biznes@gmail.com lub [jRandomSkills Discord](https://discord.gg/9H8EZYBpPF). +Je艣li masz jakie艣 pytanie, napisz na juzlus.biznes@gmail.com lub [jRandomSkills Discord](https://discord.gg/9H8EZYBpPF). \ No newline at end of file diff --git a/README-PL.md b/README-PL.md index 8899f1c..ae42a84 100644 --- a/README-PL.md +++ b/README-PL.md @@ -441,27 +441,6 @@ Plugin korzysta z zawarto艣ci nast臋puj膮cych projekt贸w: ## 馃搵 Lista Zmian -
-v1.2.4.b3 - -- #### Og贸lne - - Zaktualizowano kompatybilno艣膰 z **CounterStrikeSharp v1.0.375**. - - **Usuni臋to RayTrace-CSS-API / RayTrace-MM** (ray tracing jest teraz wbudowany w CounterStrikeSharp). - - **Zaktualizowano gamedata** - sygnatury i offsety dla Windows/Linux. - - Obserwatorzy bez pawna nie s膮 ju偶 uwzgl臋dniani podczas sprawdzania liczby po艂膮czonych graczy. - - B艂臋dy podczas przydzielania umiej臋tno艣ci s膮 teraz obserwowane i ponawiane. - -- #### Poprawki mocy - - **Skupienie** - Rozrzut i niecelno艣膰 s膮 teraz wy艂膮czane r贸wnie偶 po stronie serwera, zapewniaj膮c celniejsze strza艂y. - - **D艂ugi Zeus** - Zab贸jstwa s膮 teraz poprawnie zaliczane jako zab贸jstwa z Zeusa, wraz z killfeedem, d藕wi臋kiem i efektami ragdolla. - - **D艂ugi N贸偶** - Trafienia z du偶ego dystansu pokazuj膮 teraz 艣lad. - - **Krucha Bomba** - Pod艂o偶one bomby s膮 teraz wykrywane poprawnie, a trajektoria pocisku jest prawid艂owo sprawdzana. - - **"Linka z Drutu** - Wi膮zki s膮 teraz poprawnie usuwane po zmianie umiej臋tno艣ci. - -**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.b2 diff --git a/README.md b/README.md index 1c23bd9..308088d 100644 --- a/README.md +++ b/README.md @@ -441,27 +441,6 @@ This plugin uses content from the following projects: ## 馃搵 Changelog -
-v1.2.4.b3 - -- #### General - - Updated compatibility with **CounterStrikeSharp v1.0.375**. - - **Removed RayTrace-CSS-API / RayTrace-MM** (ray tracing is now built into CounterStrikeSharp). - - **Updated gamedata** signatures and offsets for Windows/Linux. - - Skill distribution failures are now logged and retried. - - Spectators without a pawn are excluded from connected-player checks. - -- #### Skill Fixes - - **No Recoil** - Spread and inaccuracy are now disabled server-side for accurate shots. - - **Long Zeus** - Kills now correctly count as Zeus kills, including killfeed, sound and ragdoll effects. - - **Long Knife** - Long-range hits now show a tracer. - - **Fragile Bomb** - Planted bombs are detected reliably and bullet paths are checked correctly. - - **Tripwire** - Beams are now removed correctly when the skill changes. - -**Full update contributed by [@ByDexterTR](https://github.com/ByDexterTR) in pull request [#61](https://github.com/Juzlus/jRandomSkills/pull/61). Thanks to ByDexterTR!** - -
-
v1.2.4.b2 diff --git a/jRandomSkills - SRC Files/jRandomSkills.csproj b/jRandomSkills - SRC Files/jRandomSkills.csproj index b553bd8..17a8785 100644 --- a/jRandomSkills - SRC Files/jRandomSkills.csproj +++ b/jRandomSkills - SRC Files/jRandomSkills.csproj @@ -21,7 +21,7 @@ - + @@ -30,6 +30,12 @@ + + + libs/RayTraceApi.dll + + + True diff --git a/jRandomSkills - SRC Files/libs/RayTraceApi.dll b/jRandomSkills - SRC Files/libs/RayTraceApi.dll new file mode 100644 index 0000000..584aea0 Binary files /dev/null and b/jRandomSkills - SRC Files/libs/RayTraceApi.dll differ diff --git a/jRandomSkills - SRC Files/src/gamedata/jRandomSkills.gamedata.json b/jRandomSkills - SRC Files/src/gamedata/jRandomSkills.gamedata.json index 0c2c147..bd817d6 100644 --- a/jRandomSkills - SRC Files/src/gamedata/jRandomSkills.gamedata.json +++ b/jRandomSkills - SRC Files/src/gamedata/jRandomSkills.gamedata.json @@ -3,20 +3,20 @@ "signatures": { "library": "server", "windows": "48 8B C4 48 89 58 ? 48 89 68 ? 48 89 70 ? 57 41 56 41 57 48 81 EC ? ? ? ? 48 8B B4 24 ? ? ? ? 4D 8B F8", - "linux": "55 4C 89 C1 48 89 E5 41 57 49 89 FF 41 56 45 89 CE 41 55 4D 89 C5 41 54 53 48 81 EC ? ? ? ? 48 89 95 ? ? ? ? 48 89 F2 48 89 FE 48 8D 3D" + "linux": "55 4C 89 C1 48 89 E5 41 57 49 89 FF 41 56 45 89 CE 41 55 4D 89 C5 41 54 53 48 83 EC ? 48 89 55 ? 48 89 F2 48 89 FE" } }, "HEGrenadeProjectile_CreateFunc": { "signatures": { "library": "server", - "windows": "48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC ? 48 8B AC 24 ? ? ? ? 49 8B F8 4C 8B C2 0F 29 74 24 ? 48 8B D1 0F 29 7C 24 ? 48 8B D9 4C 8B CD 48 8D 0D ? ? ? ? E8", + "windows": "48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC ? 48 8B 6C 24 ? 49 8B F8 4C 8B C2 0F 29 74 24 ? 48 8B D1 48 8B D9 48 8D 0D ? ? ? ? 4C 8B CD E8 ? ? ? ? F3 0F 10 0D ? ? ? ? 48 8B C8 48 8B F0 E8 ? ? ? ? 48 8B D7 48 8B CE", "linux": "55 4C 89 C1 48 89 E5 41 57 49 89 FF 41 56 49 89 D6 48 89 F2 48 89 FE 41 55 48 8D 3D ? ? ? ? 4D 89 C5 41 54 45 89 CC 53" } }, "CMolotovProjectile_CreateFunc": { "signatures": { "library": "server", - "windows": "48 8B C4 48 89 58 08 48 89 70 10 48 89 78 20 4C 89 40 18 55 41 54 41 55 41 56 41 57 48 8D 6C 24 ? 48 81 EC ? ? ? ? 45 33 FF", + "windows": "48 8B C4 48 89 58 10 4C 89 40 18 48 89 48 08", "linux": "55 48 8D 05 ? ? ? ? 48 89 E5 41 57 41 56 41 55 41 54 49 89 FC 53 48 81 EC ? ? ? ? 4C 8D 35" } }, @@ -30,7 +30,7 @@ "SnapViewAngles": { "signatures": { "library": "server", - "windows": "48 89 7C 24 ? 55 48 8B EC 48 81 EC ? ? ? ? 48 8B F9 48 8D 4D ? E8 ? ? ? ? F2 0F 10 87 ? ? ? ? 48 8B CF", + "windows": "48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 55 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B DA 48 8B F1 48 8D 55", "linux": "55 48 89 E5 41 57 49 89 FF 48 89 F7 41 56 41 55 41 54 53 48 81 EC ? ? ? ? E8" } }, @@ -42,8 +42,8 @@ }, "INetworkGameServer_Slots": { "offsets": { - "windows": 616, - "linux": 616 + "windows": 584, + "linux": 584 } }, "INetworkServerService_GetIGameServer": { diff --git a/jRandomSkills - SRC Files/src/jRandomSkills.cs b/jRandomSkills - SRC Files/src/jRandomSkills.cs index e3ad2b8..80ed317 100644 --- a/jRandomSkills - SRC Files/src/jRandomSkills.cs +++ b/jRandomSkills - SRC Files/src/jRandomSkills.cs @@ -44,7 +44,7 @@ namespace src public override string ModuleName => "[CS2] [ jRandomSkills ]"; public override string ModuleAuthor => "D3X (Original), Juzlus (Modifier), ByDexterTR (Contributor)"; public override string ModuleDescription => "Plugin adds random skills every round for CS2 by D3X. Modified by Juzlus."; - public override string ModuleVersion => "1.2.4.b3-panorama1"; + public override string ModuleVersion => "1.2.4.b2-panorama1"; public override void Load(bool hotReload) { @@ -303,6 +303,9 @@ namespace src { "Newtonsoft Json", "./Newtonsoft.Json.dll" }, { "MaxMind", "./MaxMind.Db.dll" }, { "GeoLite2", "./packages/GeoLite2-Country.mmdb" }, + { "RayTraceApi", "./../../shared/RayTraceApi/RayTraceApi.dll" }, + { "RayTraceImpl", "./../../plugins/RayTraceImpl/RayTraceImpl.dll" }, + { "RayTrace MetaMod", "./../../../metamod/RayTrace.vdf" }, { "jRandomSkills gamedata", "./../../gamedata/jRandomSkills.gamedata.json" } }; diff --git a/jRandomSkills - SRC Files/src/player/EntityEvents.cs b/jRandomSkills - SRC Files/src/player/EntityEvents.cs index 17c54e9..c98cc41 100644 --- a/jRandomSkills - SRC Files/src/player/EntityEvents.cs +++ b/jRandomSkills - SRC Files/src/player/EntityEvents.cs @@ -98,7 +98,6 @@ namespace src.player !Instance.SkillPlayer.Any(p => !p.IsDrawing && p.Skill == Skills.Fortnite)) Instance.SkillAction("Fortnite", "OnTakeDamage", args); - SkillUtils.ApplyNativeKill(entity, info); return HookResult.Continue; } } diff --git a/jRandomSkills - SRC Files/src/player/PlayerEvents.cs b/jRandomSkills - SRC Files/src/player/PlayerEvents.cs index 804d2f9..8214e42 100644 --- a/jRandomSkills - SRC Files/src/player/PlayerEvents.cs +++ b/jRandomSkills - SRC Files/src/player/PlayerEvents.cs @@ -6,6 +6,7 @@ using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.UserMessages; using CounterStrikeSharp.API.Modules.Utils; +using RayTraceAPI; using src.player.skills; using src.utils; using System.Collections.Concurrent; @@ -107,7 +108,6 @@ namespace src.player TryUnhook(() => VirtualFunctions.CCSPlayer_ItemServices_CanAcquireFunc.Unhook(OnWeaponCanAcquire, HookMode.Pre)); TryUnhook(() => Instance.UnhookUserMessage(208, PlayerMakeSound)); TryUnhook(() => Instance.RemoveListener(CheckTransmit)); - TryUnhook(NoRecoil.RestoreSpread); } private static void TryUnhook(Action unhook) @@ -507,7 +507,6 @@ namespace src.player private static void OnTick() { ReportStall(); - NoRecoil.RestoreSpread(); long perfStart = PerfLog.Start(); lock (setLock) @@ -795,7 +794,7 @@ namespace src.player Vector eyePos = new(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z); Vector endPos = eyePos + SkillUtils.GetForwardVector(pawn.EyeAngles) * 80; - ulong mask = (ulong)Masks.SolidBrushOnly | (ulong)(Contents.Player | Contents.Npc); + ulong mask = (ulong)(InteractionLayers.MASK_WORLD_ONLY | InteractionLayers.Player | InteractionLayers.NPC); ulong contents = 0; var result = RayTrace.TraceShape(player, eyePos, endPos, mask, contents); diff --git a/jRandomSkills - SRC Files/src/player/PlayerOnTick.cs b/jRandomSkills - SRC Files/src/player/PlayerOnTick.cs index e185820..437dec4 100644 --- a/jRandomSkills - SRC Files/src/player/PlayerOnTick.cs +++ b/jRandomSkills - SRC Files/src/player/PlayerOnTick.cs @@ -45,7 +45,6 @@ namespace src.player private static void OnMapStart(string mapName) { - skills.NoRecoil.ForgetSpread(); PlayerManager.SetServerActive(true); Instance.GameRules = null; Event.OnMapChange(); @@ -54,8 +53,6 @@ namespace src.player private static void OnMapEnd() { - skills.NoRecoil.RestoreSpread(); - skills.NoRecoil.ForgetSpread(); PerfLog.Info("===== MAP END (clean map change) ====="); Debug.WriteToDebug("===== MAP END (clean map change) ====="); BotManager.Stop(); diff --git a/jRandomSkills - SRC Files/src/player/RoundEvents.cs b/jRandomSkills - SRC Files/src/player/RoundEvents.cs index 7fa6628..c5c7769 100644 --- a/jRandomSkills - SRC Files/src/player/RoundEvents.cs +++ b/jRandomSkills - SRC Files/src/player/RoundEvents.cs @@ -7,6 +7,7 @@ using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.UserMessages; using CounterStrikeSharp.API.Modules.Utils; +using RayTraceAPI; using src.player.skills; using src.utils; using System.Collections.Concurrent; @@ -97,14 +98,14 @@ namespace src.player { lock (setLock) { - bool isWarmup = IsWarmupPeriod(); + bool isWarmup = Instance.GameRules == null || Instance.GameRules.WarmupPeriod == true; isTransmitRegistered = false; setSkillRetries = 0; SkillUtils.ClearKillCredits(); SkillUtils.ClearCurses(); Instance.AddTimer(.1f, () => DisableAll(), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); - foreach (var player in Utilities.GetPlayers().Where(p => p != null && p.IsValid && !p.IsHLTV && InPlayingTeam(p))) + foreach (var player in Utilities.GetPlayers().Where(p => p != null && p.IsValid && !p.IsHLTV && p.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist)) { var skillPlayer = PlayerManager.GetPlayerByIndex(player!.Index); if (skillPlayer == null) continue; @@ -114,21 +115,18 @@ namespace src.player Instance.RemoveListener(CheckTransmit); int freezetime = SkillUtils.CvarValue("mp_freezetime", 0); - int introDelay = IsTeamIntroPeriod() ? 7 : 0; - freezeTimeEnd = DateTime.Now.AddSeconds(freezetime + introDelay); + freezeTimeEnd = DateTime.Now.AddSeconds(freezetime + (Instance?.GameRules?.TeamIntroPeriod == true ? 7 : 0)); setSkillTimer?.Kill(); if (isWarmup) { setSkillTimer = Instance?.AddTimer(1f, SetSkill, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); - Debug.WriteToDebug("RoundStart: warmup, SetSkill scheduled in 1.00s.", DebugCategory.Round); return HookResult.Continue; } - float timeToDraw = introDelay + Math.Max(freezetime - Config.LoadedConfig.SkillTimeBeforeStart, 0) + .3f; + float timeToDraw = (Instance?.GameRules?.TeamIntroPeriod == true ? 7 : 0) + Math.Max(freezetime - Config.LoadedConfig.SkillTimeBeforeStart, 0) + .3f; setSkillTimer = Instance?.AddTimer(timeToDraw, SetSkill, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); - Debug.WriteToDebug($"RoundStart: SetSkill scheduled in {timeToDraw:F2}s (freezetime={freezetime}, intro={introDelay}, timer={(setSkillTimer == null ? "null" : "ok")}).", DebugCategory.Round); return HookResult.Continue; } } @@ -295,22 +293,7 @@ namespace src.player private static void SetSkill() { long perfStart = PerfLog.Start(); - - try - { - SetSkillCore(); - } - catch (Exception ex) - { - Debug.WriteToDebug($"SetSkill threw: {ex}", DebugCategory.Skill); - - if (setSkillRetries < MaxSetSkillRetries) - { - setSkillRetries++; - setSkillTimer = Instance?.AddTimer(.5f, SetSkill, CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); - } - } - + SetSkillCore(); PerfLog.End("SetSkill total", perfStart, 2.0); } @@ -489,46 +472,10 @@ namespace src.player private static int CountConnectedPlayers() { - try - { - return Utilities.GetPlayers().Count(p => - { - if (p == null || !p.IsValid || p.IsHLTV) return false; - var pawn = p.PlayerPawn?.Value; - return pawn != null && pawn.IsValid; - }); - } + try { return Utilities.GetPlayers().Count(p => p != null && p.IsValid && !p.IsHLTV); } catch { return 0; } } - private static bool InPlayingTeam(CCSPlayerController player) - { - try { return player.Team is CsTeam.CounterTerrorist or CsTeam.Terrorist; } - catch { return false; } - } - - private static bool IsWarmupPeriod() - { - try - { - var gameRules = Instance?.GameRules; - if (gameRules == null || gameRules.Handle == IntPtr.Zero) return true; - return gameRules.WarmupPeriod; - } - catch { return true; } - } - - private static bool IsTeamIntroPeriod() - { - try - { - var gameRules = Instance?.GameRules; - if (gameRules == null || gameRules.Handle == IntPtr.Zero) return false; - return gameRules.TeamIntroPeriod; - } - catch { return false; } - } - private static void SetSkillCore() { setSkillTimer = null; @@ -537,7 +484,7 @@ namespace src.player if (Instance == null) return; // GameRules null = not ready; keep polling so skills land right after warmup ends. - if (IsWarmupPeriod()) + if (Instance.GameRules == null || Instance.GameRules.WarmupPeriod == true) { if (++gameRulesPolls % 10 == 0) Debug.WriteToDebug($"SetSkill waiting: gameRules={(Instance.GameRules == null ? "null" : "warmup")}, poll {gameRulesPolls}.", DebugCategory.Skill); diff --git a/jRandomSkills - SRC Files/src/player/skills/Cypher.cs b/jRandomSkills - SRC Files/src/player/skills/Cypher.cs index df75b2b..152f113 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Cypher.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Cypher.cs @@ -4,6 +4,7 @@ using CounterStrikeSharp.API.Modules.Commands.Targeting; using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; using CounterStrikeSharp.API.Modules.Timers; using CounterStrikeSharp.API.Modules.Utils; +using RayTraceAPI; using src.utils; using System.Collections.Concurrent; using System.Drawing; @@ -340,7 +341,7 @@ namespace src.player.skills Vector eyePos = new(playerPawn.AbsOrigin.X, playerPawn.AbsOrigin.Y, playerPawn.AbsOrigin.Z + playerPawn.ViewOffset.Z); Vector endPos = eyePos + SkillUtils.GetForwardVector(playerPawn.V_angle) * 4096f; - ulong mask = (ulong)(Contents.Solid | Contents.Window | Contents.PassBullets); + ulong mask = (ulong)(InteractionLayers.Solid | InteractionLayers.Window | InteractionLayers.PassBullets); var result = RayTrace.TraceShape(player, eyePos, endPos, mask); if (result.HasValue && result.Value.HitWorld(out _)) @@ -369,7 +370,7 @@ namespace src.player.skills Vector endPos = cameraVector + SkillUtils.GetForwardVector(new QAngle(0, playerPawn.V_angle.Y + 180, 0)) * -5; cameraVector += SkillUtils.GetForwardVector(new QAngle(0, playerPawn.V_angle.Y + 180, 0)) * 5; - ulong mask = (ulong)(Contents.Solid | Contents.Window | Contents.PassBullets); + ulong mask = (ulong)(InteractionLayers.Solid | InteractionLayers.Window | InteractionLayers.PassBullets); var result = RayTrace.TraceShape(player, cameraVector, endPos, mask); if (result.HasValue && result.Value.HitWorld(out _)) diff --git a/jRandomSkills - SRC Files/src/player/skills/FragileBomb.cs b/jRandomSkills - SRC Files/src/player/skills/FragileBomb.cs index a0661ab..a46fa4e 100644 --- a/jRandomSkills - SRC Files/src/player/skills/FragileBomb.cs +++ b/jRandomSkills - SRC Files/src/player/skills/FragileBomb.cs @@ -29,16 +29,10 @@ namespace src.player.skills } public static void BombPlanted(EventBombPlanted _) - { - plantedC4 = FindPlantedC4(); - } - - private static Vector? FindPlantedC4() { var plantedBomb = Utilities.FindAllEntitiesByDesignerName("planted_c4").FirstOrDefault(); - if (plantedBomb == null || !plantedBomb.IsValid || plantedBomb.AbsOrigin == null) return null; - if (!plantedBomb.BombTicking || plantedBomb.BombDefused) return null; - return new(plantedBomb.AbsOrigin.X, plantedBomb.AbsOrigin.Y, plantedBomb.AbsOrigin.Z); + if (plantedBomb == null || !plantedBomb.IsValid || plantedBomb.AbsOrigin == null) return; + plantedC4 = new(plantedBomb.AbsOrigin.X, plantedBomb.AbsOrigin.Y, plantedBomb.AbsOrigin.Z); } private static void RemoveBomb() @@ -55,21 +49,14 @@ namespace src.player.skills if (lastTick == Server.TickCount) return; var player = PlayerManager.GetPlayerEvent(@event.Userid); - if (player == null || !player.IsValid) return; + if (player == null || !player.IsValid || plantedC4 == null) return; + + var pos = new Vector(@event.X, @event.Y, @event.Z); var playerInfo = PlayerManager.GetPlayerByIndex(player!.Index); if (playerInfo == null || playerInfo.Skill != skillName) return; - plantedC4 ??= FindPlantedC4(); - if (plantedC4 == null) return; - - var pawn = player.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return; - - var eyePos = new Vector(pawn.AbsOrigin.X, pawn.AbsOrigin.Y, pawn.AbsOrigin.Z + pawn.ViewOffset.Z); - var impactPos = new Vector(@event.X, @event.Y, @event.Z); - - if (DistanceToSegment(plantedC4, eyePos, impactPos) >= 8) + if (SkillUtils.Distance(plantedC4, pos) >= 8) return; lastTick = Server.TickCount; @@ -84,16 +71,6 @@ namespace src.player.skills Localization.PrintTranslationToChatAll($" {ChatColors.Gold}{{0}}: {ChatColors.Red}{bombHealth}{ChatColors.Gold}/{ChatColors.Green}{maxBombHealth}", ["fragilebomb_bomb_health"]); } - private static float DistanceToSegment(Vector point, Vector start, Vector end) - { - float lineX = end.X - start.X, lineY = end.Y - start.Y, lineZ = end.Z - start.Z; - float lengthSquared = lineX * lineX + lineY * lineY + lineZ * lineZ; - float t = lengthSquared <= .0001f ? 0f : Math.Clamp(((point.X - start.X) * lineX + (point.Y - start.Y) * lineY + (point.Z - start.Z) * lineZ) / lengthSquared, 0f, 1f); - - float dx = start.X + lineX * t - point.X, dy = start.Y + lineY * t - point.Y, dz = start.Z + lineZ * t - point.Z; - return MathF.Sqrt(dx * dx + dy * dy + dz * dz); - } - public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#5d00ff", CsTeam onlyTeam = CsTeam.CounterTerrorist, bool disableOnFreezeTime = false, bool needsTeammates = false, string requiredPermission = "", float? hudDuration = null, float? descriptionHudDuration = null, int maxPerServer = 1, Rarity rarity = Rarity.Common, int maxBombHealth = 1000) : SkillsInfo.DefaultSkillInfo(skill, active, color, onlyTeam, disableOnFreezeTime, needsTeammates, requiredPermission, hudDuration, descriptionHudDuration, maxPerServer, rarity) { public int MaxBombHealth { get; set; } = maxBombHealth; diff --git a/jRandomSkills - SRC Files/src/player/skills/LongKnife.cs b/jRandomSkills - SRC Files/src/player/skills/LongKnife.cs index 049314b..a15c9df 100644 --- a/jRandomSkills - SRC Files/src/player/skills/LongKnife.cs +++ b/jRandomSkills - SRC Files/src/player/skills/LongKnife.cs @@ -15,7 +15,6 @@ namespace src.player.skills private const string victimSound = "Player.DamageBody.Victim"; private const string heavyHitSound = "Weapon_Knife.Hit.Heavy.Flesh"; private const string lightHitSound = "Weapon_Knife.Hit.Light.Flesh"; - private const string tracerParticle = "particles/weapons/cs_weapon_fx/weapon_tracers_rifle_wisp.vpcf"; private static bool hooked = false; private const int actionCode = 503; @@ -31,7 +30,6 @@ namespace src.player.skills public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); - Instance.AddToManifest(tracerParticle); } public static void NewRound() @@ -115,9 +113,6 @@ namespace src.player.skills if (result == null || !result.HasValue) return; - if (result.Value.Distance() > 70) - SkillUtils.CreateTracer(player, tracerParticle, result.Value); - if (!result.Value.HitPlayer(out CCSPlayerController? target) || target == null) return; diff --git a/jRandomSkills - SRC Files/src/player/skills/LongZeus.cs b/jRandomSkills - SRC Files/src/player/skills/LongZeus.cs index 56f5dca..60f1efb 100644 --- a/jRandomSkills - SRC Files/src/player/skills/LongZeus.cs +++ b/jRandomSkills - SRC Files/src/player/skills/LongZeus.cs @@ -10,12 +10,10 @@ namespace src.player.skills public class LongZeus : ISkill { private const Skills skillName = Skills.LongZeus; - private const string shockParticle = "particles/blood_impact/impact_taser_bodyfx.vpcf"; public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); - Instance.AddToManifest(shockParticle); } public unsafe static void WeaponFire(EventWeaponFire @event) @@ -42,12 +40,7 @@ namespace src.player.skills if (target.Handle == player.Handle) return; if (!SkillsInfo.GetValue(skillName, "friendlyFire") && player.Team == target.Team) return; - var targetPawn = target.PlayerPawn.Value; - if (targetPawn == null || !targetPawn.IsValid) return; - - EntityManager.CreateEntityParticle(player.Index, shockParticle, targetPawn); - SkillUtils.RegisterNativeKill(targetPawn, pawn, activeWeapon, DamageTypes_t.DMG_SHOCK); - SkillUtils.TakeHealth(targetPawn, 9999); + SkillUtils.TakeHealth(target.PlayerPawn.Value, 9999, player, KillfeedIcons.Taser); } public static void EnableSkill(CCSPlayerController player) diff --git a/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs b/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs index ac5e5c1..f36f62c 100644 --- a/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs +++ b/jRandomSkills - SRC Files/src/player/skills/NoRecoil.cs @@ -17,27 +17,6 @@ namespace src.player.skills private static readonly ConcurrentDictionary holders = []; private static readonly ConcurrentDictionary originalNoSpreadValues = []; - private sealed class SpreadPatch(CCSWeaponBaseVData vdata) - { - public readonly CCSWeaponBaseVData VData = vdata; - public readonly CFiringModeFloat[] Fields = - [ - vdata.Spread, vdata.InaccuracyCrouch, vdata.InaccuracyStand, vdata.InaccuracyJump, - vdata.InaccuracyLand, vdata.InaccuracyLadder, vdata.InaccuracyFire, vdata.InaccuracyMove - ]; - public readonly float[] Values = new float[16]; - public int Count; - public float JumpInitial; - public float JumpApex; - public float Reload; - public bool Active; - } - - private static readonly Dictionary spreadPatches = []; - private static readonly List activePatches = []; - private static readonly Dictionary wantedVData = []; - private static readonly HashSet blockedVData = []; - public static void LoadSkill() { SkillUtils.RegisterSkill(skillName, SkillsInfo.GetValue(skillName, "color")); @@ -104,106 +83,6 @@ namespace src.player.skills catch { } } - public static void OnTick() - { - if (holders.IsEmpty) return; - - wantedVData.Clear(); - blockedVData.Clear(); - - foreach (var player in PlayerManager.GetTickPlayers()) - { - if (player == null || !player.IsValid || !player.PawnIsAlive) continue; - - var vdata = GetActiveWeaponVData(player); - if (vdata == null) continue; - - bool isHolder = holders.ContainsKey(player.Index) && PlayerManager.GetPlayerByIndex(player.Index)?.Skill == skillName; - if (isHolder) - wantedVData[vdata.Handle] = vdata; - else - blockedVData.Add(vdata.Handle); - } - - foreach (var (handle, vdata) in wantedVData) - { - if (!blockedVData.Contains(handle)) - PatchSpread(vdata); - } - } - - private static CCSWeaponBaseVData? GetActiveWeaponVData(CCSPlayerController player) - { - var weapon = player.PlayerPawn.Value?.WeaponServices?.ActiveWeapon.Value; - if (weapon == null || !weapon.IsValid) return null; - - var vdata = weapon.As().VData; - return vdata == null || vdata.Handle == IntPtr.Zero ? null : vdata; - } - - private static void PatchSpread(CCSWeaponBaseVData vdata) - { - if (!spreadPatches.TryGetValue(vdata.Handle, out var patch)) - { - patch = new SpreadPatch(vdata); - spreadPatches[vdata.Handle] = patch; - } - - if (patch.Active) return; - - int index = 0; - foreach (var field in patch.Fields) - { - var values = field.Values; - for (int i = 0; i < values.Length && index < patch.Values.Length; i++) - { - patch.Values[index++] = values[i]; - values[i] = 0f; - } - } - - patch.Count = index; - patch.JumpInitial = vdata.InaccuracyJumpInitial; - patch.JumpApex = vdata.InaccuracyJumpApex; - patch.Reload = vdata.InaccuracyReload; - - vdata.InaccuracyJumpInitial = 0f; - vdata.InaccuracyJumpApex = 0f; - vdata.InaccuracyReload = 0f; - - patch.Active = true; - activePatches.Add(patch); - } - - public static void RestoreSpread() - { - if (activePatches.Count == 0) return; - - foreach (var patch in activePatches) - { - int index = 0; - foreach (var field in patch.Fields) - { - var values = field.Values; - for (int i = 0; i < values.Length && index < patch.Count; i++) - values[i] = patch.Values[index++]; - } - - patch.VData.InaccuracyJumpInitial = patch.JumpInitial; - patch.VData.InaccuracyJumpApex = patch.JumpApex; - patch.VData.InaccuracyReload = patch.Reload; - patch.Active = false; - } - - activePatches.Clear(); - } - - public static void ForgetSpread() - { - activePatches.Clear(); - spreadPatches.Clear(); - } - public static void WeaponFire(EventWeaponFire @event) { var player = PlayerManager.GetPlayerEvent(@event.Userid); diff --git a/jRandomSkills - SRC Files/src/player/skills/Ricochet.cs b/jRandomSkills - SRC Files/src/player/skills/Ricochet.cs index b4ca260..1982f5f 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Ricochet.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Ricochet.cs @@ -1,7 +1,8 @@ -锘縰sing CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.utils; +using RayTraceAPI; using src.utils; using System.Collections.Concurrent; using System.Drawing; @@ -21,7 +22,7 @@ namespace src.player.skills private static readonly List flights = []; private static readonly object flightLock = new(); private static readonly Color tracerColor = Color.FromArgb(170, 255, 226, 140); - private static readonly ulong worldOnlyMask = (ulong)Masks.SolidBrushOnly; + private static readonly ulong worldOnlyMask = (ulong)InteractionLayers.MASK_WORLD_ONLY; public static void LoadSkill() { diff --git a/jRandomSkills - SRC Files/src/player/skills/Tripwire.cs b/jRandomSkills - SRC Files/src/player/skills/Tripwire.cs index d94b2cc..7fc5f34 100644 --- a/jRandomSkills - SRC Files/src/player/skills/Tripwire.cs +++ b/jRandomSkills - SRC Files/src/player/skills/Tripwire.cs @@ -1,6 +1,7 @@ -锘縰sing CounterStrikeSharp.API; +using CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Utils; +using RayTraceAPI; using src.utils; using System.Collections.Concurrent; using System.Drawing; @@ -103,7 +104,19 @@ namespace src.player.skills private static void DestroyWire(uint beamIndex) { - EntityManager.DestroyBeam(beamIndex); + var beam = Utilities.GetEntityFromIndex((int)beamIndex); + if (beam != null && beam.IsValid) + { + beam.Width = 0; + beam.EndWidth = 0; + beam.Render = Color.FromArgb(0, 0, 0, 0); + + Utilities.SetStateChanged(beam, "CBeam", "m_fWidth"); + Utilities.SetStateChanged(beam, "CBeam", "m_fEndWidth"); + Utilities.SetStateChanged(beam, "CBaseModelEntity", "m_clrRender"); + } + + EntityManager.DestroyEntity(beamIndex); } public static void UseSkill(CCSPlayerController player) @@ -162,7 +175,7 @@ namespace src.player.skills Vector rightDir = SkillUtils.GetForwardVector(new QAngle(0, yaw - 90, 0)); Vector leftDir = SkillUtils.GetForwardVector(new QAngle(0, yaw + 90, 0)); - ulong wallMask = (ulong)Masks.SolidBrushOnly; + ulong wallMask = (ulong)InteractionLayers.MASK_WORLD_ONLY; var rightHit = RayTrace.TraceShape(player, origin, origin + rightDir * maxDistance, wallMask, 0); var leftHit = RayTrace.TraceShape(player, origin, origin + leftDir * maxDistance, wallMask, 0); diff --git a/jRandomSkills - SRC Files/src/utils/CustomTraceResult.cs b/jRandomSkills - SRC Files/src/utils/CustomTraceResult.cs index 9ffd2b7..85ea933 100644 --- a/jRandomSkills - SRC Files/src/utils/CustomTraceResult.cs +++ b/jRandomSkills - SRC Files/src/utils/CustomTraceResult.cs @@ -1,55 +1,30 @@ -锘縰sing CounterStrikeSharp.API.Modules.Utils; +锘縰sing RayTraceAPI; using System.Numerics; using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; namespace jRandomSkills.src.utils { - public struct CustomTraceResult + public struct CustomTraceResult(TraceResult result, Vector startPos, ulong mask, ulong contents, bool drawBeam) { - public float StartPosX; - public float StartPosY; - public float StartPosZ; + public float StartPosX = startPos.X; + public float StartPosY = startPos.Y; + public float StartPosZ = startPos.Z; - public float EndPosX; - public float EndPosY; - public float EndPosZ; + public float EndPosX = result.EndPosX; + public float EndPosY = result.EndPosY; + public float EndPosZ = result.EndPosZ; - public nint HitEntity; - public float Fraction; - public int AllSolid; + public nint HitEntity = result.HitEntity; + public float Fraction = result.Fraction; + public int AllSolid = result.AllSolid; - public float NormalX; - public float NormalY; - public float NormalZ; + public float NormalX = result.NormalX; + public float NormalY = result.NormalY; + public float NormalZ = result.NormalZ; - public ulong InteractsWith; - public ulong InteractsExclude; - public bool DrawBeam; - - public CustomTraceResult(TraceResult result, Vector startPos, ulong mask, ulong contents, bool drawBeam) - { - StartPosX = startPos.X; - StartPosY = startPos.Y; - StartPosZ = startPos.Z; - - var end = result.EndPos; - EndPosX = end.X; - EndPosY = end.Y; - EndPosZ = end.Z; - - var normal = result.Normal; - NormalX = normal.X; - NormalY = normal.Y; - NormalZ = normal.Z; - - HitEntity = result.HitEntity().Handle; - Fraction = result.Fraction; - AllSolid = result.IsAllSolid ? 1 : 0; - - InteractsWith = mask; - InteractsExclude = contents; - DrawBeam = drawBeam; - } + public ulong InteractsWith = mask; + public ulong InteractsExclude = contents; + public bool DrawBeam = drawBeam; public readonly Vector3 StartPos => new(StartPosX, StartPosY, StartPosZ); public readonly Vector3 EndPos => new(EndPosX, EndPosY, EndPosZ); diff --git a/jRandomSkills - SRC Files/src/utils/EntityManager.cs b/jRandomSkills - SRC Files/src/utils/EntityManager.cs index 72ffa84..ec57874 100644 --- a/jRandomSkills - SRC Files/src/utils/EntityManager.cs +++ b/jRandomSkills - SRC Files/src/utils/EntityManager.cs @@ -1,12 +1,10 @@ 锘縰sing CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Modules.Entities.Constants; -using CounterStrikeSharp.API.Modules.Memory; using CounterStrikeSharp.API.Modules.Utils; using src.player; using System.Collections.Concurrent; using System.Drawing; -using System.Runtime.InteropServices; using static src.jRandomSkills; namespace src.utils @@ -138,67 +136,6 @@ namespace src.utils } } - public static CParticleSystem? CreateTracer(uint playerIndex, string particleName, Vector start, Vector end, float lifetime = 1f) - { - try - { - if (OverBudget()) return null; - var particle = Utilities.CreateEntityByName("info_particle_system"); - if (particle == null || !particle.IsValid) return null; - - particle.EffectName = particleName; - particle.StartActive = true; - particle.Teleport(start); - - var controlPoint = new Vector(particle.Handle + Schema.GetSchemaOffset("CParticleSystem", "m_vServerControlPoints")); - controlPoint.X = end.X; - controlPoint.Y = end.Y; - controlPoint.Z = end.Z; - particle.ServerControlPointAssignments[0] = 1; - - particle.DispatchSpawn(); - - RegisterEntity(particle.Index, playerIndex, "tracer"); - ScheduleAutoDestroy(particle.Index, lifetime); - return particle; - } - catch (Exception ex) - { - LogEntityError($"CreateTracer: {ex.Message}"); - return null; - } - } - - public static CParticleSystem? CreateEntityParticle(uint playerIndex, string particleName, CBaseEntity target, float lifetime = 5f) - { - try - { - if (OverBudget() || target.AbsOrigin == null) return null; - var particle = Utilities.CreateEntityByName("info_particle_system"); - if (particle == null || !particle.IsValid) return null; - - particle.EffectName = particleName; - particle.StartActive = true; - particle.Teleport(target.AbsOrigin); - - nint controlPointEnts = particle.Handle + Schema.GetSchemaOffset("CParticleSystem", "m_hControlPointEnts"); - Marshal.WriteInt32(controlPointEnts, (int)target.EntityHandle.Raw); - Marshal.WriteInt32(controlPointEnts + 4, (int)target.EntityHandle.Raw); - - particle.DispatchSpawn(); - particle.AcceptInput("SetParent", target, particle, "!activator"); - - RegisterEntity(particle.Index, playerIndex, "particle_system"); - ScheduleAutoDestroy(particle.Index, lifetime); - return particle; - } - catch (Exception ex) - { - LogEntityError($"CreateEntityParticle: {ex.Message}"); - return null; - } - } - public static CDynamicProp? CreateTrackedDynamicProp(uint playerIndex, string designerName = "prop_dynamic", string? trackAs = null) { try @@ -358,7 +295,7 @@ namespace src.utils public static bool SuppressKills = false; - public static bool DestroyEntity(uint entityIndex, float delay = 0.1f, bool hideFromTransmit = true) + public static bool DestroyEntity(uint entityIndex, float delay = 0.1f) { bool wasTracked = trackedEntities.TryRemove(entityIndex, out var removed); @@ -373,8 +310,7 @@ namespace src.utils var entity = Utilities.GetEntityFromIndex((int)entityIndex); if (entity != null && entity.IsValid) { - if (hideFromTransmit) - recentlyDestroyed[entityIndex] = new DyingEntity(DateTime.UtcNow.AddSeconds(delay + 0.5), entity.EntityHandle.Raw); + recentlyDestroyed[entityIndex] = new DyingEntity(DateTime.UtcNow.AddSeconds(delay + 0.5), entity.EntityHandle.Raw); // Detach first so no follower is left on a freed parent. entity.AcceptInput("ClearParent"); entity.AddEntityIOEvent("Kill", entity, delay: delay); @@ -410,7 +346,7 @@ namespace src.utils LogEntityError($"DestroyBeam {entityIndex}: {ex.Message}"); } - bool killed = DestroyEntity(entityIndex, hideFromTransmit: false); + bool killed = DestroyEntity(entityIndex); if (!SuppressKills) Server.NextFrame(() => @@ -467,7 +403,7 @@ namespace src.utils DestroyAllTracked(); } - public static void ScheduleAutoDestroy(uint entityIndex, float? seconds) + private static void ScheduleAutoDestroy(uint entityIndex, float? seconds) { if (seconds is not > 0) return; Instance?.AddTimer(seconds.Value, () => DestroyEntity(entityIndex), CounterStrikeSharp.API.Modules.Timers.TimerFlags.STOP_ON_MAPCHANGE); diff --git a/jRandomSkills - SRC Files/src/utils/RayTrace.cs b/jRandomSkills - SRC Files/src/utils/RayTrace.cs index 3066094..92f314f 100644 --- a/jRandomSkills - SRC Files/src/utils/RayTrace.cs +++ b/jRandomSkills - SRC Files/src/utils/RayTrace.cs @@ -1,43 +1,45 @@ 锘縰sing CounterStrikeSharp.API; using CounterStrikeSharp.API.Core; +using CounterStrikeSharp.API.Core.Capabilities; using CounterStrikeSharp.API.Modules.Utils; using jRandomSkills.src.utils; +using RayTraceAPI; using System.Drawing; using System.Numerics; +using TraceOptions = RayTraceAPI.TraceOptions; +using TraceResult = RayTraceAPI.TraceResult; using Vector = CounterStrikeSharp.API.Modules.Utils.Vector; namespace src.utils { public static class RayTrace { + private static PluginCapability RayTraceInterface { get; } = new("raytrace:craytraceinterface"); - private static bool traceFailureLogged; - - public static bool IsAvailable => true; + private static bool missingModuleLogged; - private static bool TryTraceHull(Vector startPos, Vector endPos, Vector mins, Vector maxs, CBaseEntity? ignore, ulong mask, ulong contents, out TraceResult result) + private static CRayTraceInterface? GetInterface() { try { - result = Trace.TraceHullShape(startPos, endPos, mins, maxs, ignore, new TraceOptions - { - InteractsWith = (Contents)mask, - InteractsExclude = (Contents)contents, - }); - return true; + var rayTrace = RayTraceInterface.Get(); + if (rayTrace != null) return rayTrace; } - catch (Exception ex) + catch { } + + if (!missingModuleLogged) { - result = default; - if (!traceFailureLogged) - { - traceFailureLogged = true; - Server.PrintToConsole($"[jRandomSkills] Native trace failed: {ex.Message}"); - } - return false; + missingModuleLogged = true; + Server.PrintToConsole("[jRandomSkills] RayTrace module not found - skills that need it do nothing: " + + "LongZeus, LongKnife, Iana, Cypher, Noclip, Shade (and the skill-use button's aim check). " + + "Install RayTrace-CSS-API and RayTrace-MM: https://github.com/FUNPLAY-pro-CS2/Ray-Trace/releases"); } + + return null; } + public static bool IsAvailable => GetInterface() != null; + public static CustomTraceResult? TraceShape(CCSPlayerController player, Vector startPos, Vector endPos, ulong? mask = null, ulong? contents = null) { if (player == null || !player.IsValid) return null; @@ -51,39 +53,54 @@ namespace src.utils playerPawn.CBodyComponent?.SceneNode == null) return null; + var rayTrace = GetInterface(); + if (rayTrace == null) + return null; + if (mask == null) { try { if (playerPawn.Collision?.CollisionAttribute != null) { - mask = playerPawn.Collision.CollisionAttribute.InteractsWith | (ulong)Contents.Hitbox; - mask &= ~(ulong)Contents.PlayerClip; + mask = playerPawn.Collision.CollisionAttribute.InteractsWith | (ulong)InteractionLayers.Hitboxes; + mask &= ~(ulong)InteractionLayers.PlayerClip; } else - mask = (ulong)(Contents.Solid | Contents.Hitbox); + mask = (ulong)(InteractionLayers.Solid | InteractionLayers.Hitboxes); } catch { - mask = (ulong)(Contents.Solid | Contents.Hitbox); + mask = (ulong)(InteractionLayers.Solid | InteractionLayers.Hitboxes); } } contents ??= 0; bool drawBeam = Config.LoadedConfig.TraceRayBeam; + TraceOptions options = new() + { + InteractsWith = (ulong)mask, + InteractsExclude = (ulong)contents, + DrawBeam = drawBeam == true ? 1 : 0, + }; + Vector mins = new(-0.5f, -0.5f, -0.5f); Vector maxs = new(0.5f, 0.5f, 0.5f); - if (!TryTraceHull(startPos, endPos, mins, maxs, playerPawn, (ulong)mask, (ulong)contents, out var result)) + TraceResult result = default; + + try + { + rayTrace.TraceHullShape(startPos, endPos, mins, maxs, playerPawn, options, out result); + } + catch (Exception ex) + { + Console.WriteLine($"[jRandomSkills] A memory error was caught during RayTrace: {ex.Message}"); return null; + } - var traced = new CustomTraceResult(result, startPos, (ulong)mask, (ulong)contents, drawBeam); - - if (drawBeam) - CreateBeamLine(startPos, new Vector(traced.EndPosX, traced.EndPosY, traced.EndPosZ), traced.DidHit ? Color.Red : Color.Green); - - return traced; + return new CustomTraceResult(result, startPos, (ulong)mask, (ulong)contents, drawBeam); } public static CustomTraceResult? EyeTrace(CCSPlayerController player) @@ -119,6 +136,10 @@ namespace src.utils playerPawn.CBodyComponent?.SceneNode == null) return null; + var rayTrace = GetInterface(); + if (rayTrace == null) + return null; + Vector safeMins = mins ?? playerPawn.Collision.Mins; Vector safeMaxs = maxs ?? playerPawn.Collision.Maxs; @@ -127,8 +148,26 @@ namespace src.utils bool drawBeam = Config.LoadedConfig.TraceRayBeam; - if (!TryTraceHull(startPos, endPos, safeMins, safeMaxs, playerPawn, safeMask, safeContents, out var result)) + TraceResult result = default; + TraceOptions options = new() + { + InteractsWith = safeMask, + InteractsExclude = safeContents, + DrawBeam = drawBeam == true ? 1 : 0, + }; + + CEntityInstance? entityToIgnore = (playerPawn.LifeState == (byte)LifeState_t.LIFE_ALIVE) + ? playerPawn + : null; + + try + { + rayTrace.TraceHullShape(startPos, endPos, safeMins, safeMaxs, entityToIgnore, options, out result); + } + catch (Exception) + { return null; + } if (drawBeam) { @@ -207,9 +246,6 @@ namespace src.utils beam.EndPos.Z = end.Z; beam.DispatchSpawn(); - - EntityManager.RegisterEntity(beam.Index, int.MaxValue, "beam"); - EntityManager.ScheduleAutoDestroy(beam.Index, 10); } public static float Distance(this CustomTraceResult result) @@ -224,12 +260,6 @@ namespace src.utils public static bool HitEntityByDesignerName(this CustomTraceResult result, out T? entity, string designerName, DesignerNameMatchType matchType = DesignerNameMatchType.Equals) where T : CEntityInstance { - if (result.HitEntity == IntPtr.Zero) - { - entity = null; - return false; - } - T? val = (T?)Activator.CreateInstance(typeof(T), result.HitEntity); if ((object?)val != null && matchType switch { @@ -249,12 +279,6 @@ namespace src.utils public static bool HitEntity(this CustomTraceResult result, out CBaseEntity? entity) { - if (result.HitEntity == IntPtr.Zero) - { - entity = null; - return false; - } - CEntityInstance entityInstance = new(result.HitEntity); if (string.IsNullOrEmpty(entityInstance.DesignerName)) { diff --git a/jRandomSkills - SRC Files/src/utils/SkillUtils.cs b/jRandomSkills - SRC Files/src/utils/SkillUtils.cs index bd2fe5d..18eebd5 100644 --- a/jRandomSkills - SRC Files/src/utils/SkillUtils.cs +++ b/jRandomSkills - SRC Files/src/utils/SkillUtils.cs @@ -480,48 +480,9 @@ namespace src.utils return true; } - public static void CreateTracer(CCSPlayerController player, string particleName, CustomTraceResult result) - { - var pawn = player.PlayerPawn.Value; - if (pawn == null || !pawn.IsValid || pawn.AbsOrigin == null) return; - - Vector forward = GetForwardVector(pawn.EyeAngles); - Vector start = new(pawn.AbsOrigin.X + forward.X * 16, pawn.AbsOrigin.Y + forward.Y * 16, pawn.AbsOrigin.Z + pawn.ViewOffset.Z - 6); - Vector end = new(result.EndPos.X, result.EndPos.Y, result.EndPos.Z); - - EntityManager.CreateTracer(player.Index, particleName, start, end); - } - public static void ClearKillCredits() { pendingKillCredits.Clear(); - pendingNativeKills.Clear(); - } - - private static readonly ConcurrentDictionary pendingNativeKills = []; - - public static void RegisterNativeKill(CCSPlayerPawn victimPawn, CBaseEntity attacker, CBaseEntity inflictor, DamageTypes_t damageType) - { - pendingNativeKills[victimPawn.Index] = (attacker.EntityHandle.Raw, inflictor.EntityHandle.Raw, damageType, Server.TickCount + 64); - } - - public static void ApplyNativeKill(CEntityInstance victim, CTakeDamageInfo info) - { - if (pendingNativeKills.IsEmpty) return; - if (!pendingNativeKills.TryGetValue(victim.Index, out var kill)) return; - - if (kill.ExpiryTick < Server.TickCount) - { - pendingNativeKills.TryRemove(victim.Index, out _); - return; - } - - if (info.Attacker.Value?.Handle != victim.Handle) return; - - pendingNativeKills.TryRemove(victim.Index, out _); - info.Attacker.Raw = kill.AttackerHandle; - info.Inflictor.Raw = kill.InflictorHandle; - info.BitsDamageType = kill.DamageType; } private static readonly HashSet bulletWeapons = new(StringComparer.Ordinal) diff --git a/release.sh b/release.sh deleted file mode 100755 index c02fb80..0000000 --- a/release.sh +++ /dev/null @@ -1,189 +0,0 @@ -#!/usr/bin/env bash -# Build jRandomSkills and its Panorama layouts, package them as one tarball and publish it as a -# Forgejo release. -# -# ./release.sh e.g. ./release.sh v1.2.4.b2-panorama1 -# -# Commit first: the plugin is rebuilt here from the committed source, so the release always matches -# the tag. The tag is created on HEAD and pushed to origin if it doesn't exist yet. Re-running with -# the same tag replaces that release's attachment. -# -# Asset: jRandomSkills-.tar.gz, laid out like the server's game/csgo/ - extract it there: -# tar -xzf jRandomSkills-.tar.gz -C /srv/cs2/game/csgo -# -# addons/counterstrikesharp/plugins/jRandomSkills/ plugin, deps, languages/, packages/ -# addons/counterstrikesharp/gamedata/ jRandomSkills.gamedata.json -# panorama/{layout,styles}/custom_game/ compiled skill_hud / jrs_menu (.vxml_c/.vcss_c) -# -# No configs/: the plugin writes config.json and skillsInfo.json itself when they are missing, so an -# upgrade never touches the server's config. The Panorama files are compiled from -# "jRandomSkills - SRC Files/panorama" with the CS2 client's resourcecompiler.exe (WSL interop). -# -# Players get the layouts from the Workshop, not from this tarball: the sources are compiled into -# the client's jrandomskills_hud Workshop Tools addon (Workshop item 3807837213, mounted for every -# player by the server's MultiAddonManager, mm_extra_addons). The panorama/ files in the tarball -# only land on the server. When the compiled layouts changed, the script says so at the end: -# re-upload the addon from Workshop Tools. That step stays manual. -set -euo pipefail - -FORGEJO_URL="https://git.zio.sh" -OWNER="cs2" -REPO="jRandomSkills" -# Placeholder - replace, or set FORGEJO_TOKEN in the environment instead. Needs write:repository. -# Only uploading needs it; downloading from the public repo doesn't. Don't commit a real token. -FORGEJO_TOKEN="${FORGEJO_TOKEN:-CHANGE_ME_FORGEJO_TOKEN}" - -# CS2 client used to compile the Panorama layouts, and the Workshop Tools addon compiled into. -CS2_CLIENT_DIR="${CS2_CLIENT_DIR:-/mnt/e/SteamLibrary/steamapps/common/Counter-Strike Global Offensive}" -CS2_ADDON="${CS2_ADDON:-jrandomskills_hud}" -WORKSHOP_ID="3807837213" -PANORAMA_FILES=( - layout/custom_game/skill_hud.xml - layout/custom_game/jrs_menu.xml - styles/custom_game/skill_hud.css - styles/custom_game/jrs_menu.css -) - -# Only these ship from the build output. bin/ also holds CounterStrikeSharp.API.dll, RayTraceApi.dll -# and framework DLLs, which the server already provides and which must not be duplicated per plugin. -PLUGIN_BINARIES=( - jRandomSkills.dll - jRandomSkills.pdb - MaxMind.Db.dll - Newtonsoft.Json.dll - PanoramaManager.dll -) - -TAG="${1:-}" -if [[ -z "$TAG" ]]; then - echo "usage: $0 (e.g. v1.2.4.b2-panorama1)" >&2 - exit 1 -fi -if [[ "$FORGEJO_TOKEN" == "CHANGE_ME_FORGEJO_TOKEN" ]]; then - echo "Set FORGEJO_TOKEN (edit release.sh or export it) first." >&2 - exit 1 -fi - -cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" - -SRC="jRandomSkills - SRC Files" - -if [[ -n "$(git status --porcelain --untracked-files=no)" ]]; then - echo "Tracked files have uncommitted changes; commit them so the tag matches the release." >&2 - exit 1 -fi - -# --- Build ----------------------------------------------------------------------- -BIN="$SRC/bin/Release/net10.0" -rm -rf "$SRC/bin" "$SRC/obj" -podman run --rm -v "$(pwd)":/src:Z -w "/src/$SRC" \ - mcr.microsoft.com/dotnet/sdk:10.0 dotnet build -c Release - -# --- Stage (layout of game/csgo/) -------------------------------------------------- -OUT="release-out" -STAGE="$OUT/stage" -rm -rf "$OUT" -PLUGIN_DIR="$STAGE/addons/counterstrikesharp/plugins/jRandomSkills" -mkdir -p "$PLUGIN_DIR/languages" "$PLUGIN_DIR/packages" "$STAGE/addons/counterstrikesharp/gamedata" - -for file in "${PLUGIN_BINARIES[@]}"; do - cp "$BIN/$file" "$PLUGIN_DIR/" -done -cp "$SRC"/src/lang/*.json "$PLUGIN_DIR/languages/" -cp -r "$SRC"/packages/. "$PLUGIN_DIR/packages/" -cp "$SRC"/src/gamedata/*.json "$STAGE/addons/counterstrikesharp/gamedata/" - -# --- Panorama: compile sources with the CS2 client --------------------------------- -RC_DIR="$CS2_CLIENT_DIR/game/bin/win64" -[[ -x "$RC_DIR/resourcecompiler.exe" ]] || { echo "resourcecompiler.exe not found in $RC_DIR (set CS2_CLIENT_DIR)." >&2; exit 1; } -CONTENT_ADDON="$CS2_CLIENT_DIR/content/csgo_addons/$CS2_ADDON/panorama" -GAME_ADDON="$CS2_CLIENT_DIR/game/csgo_addons/$CS2_ADDON/panorama" -WIN_CLIENT_DIR="$(wslpath -w "$CS2_CLIENT_DIR")" - -# Checksums of the addon's compiled layouts, to tell whether the Workshop item needs a re-upload. -compiled_sums() { - local file compiled - for file in "${PANORAMA_FILES[@]}"; do - case "$file" in - *.xml) compiled="${file%.xml}.vxml_c" ;; - *.css) compiled="${file%.css}.vcss_c" ;; - esac - if [[ -f "$GAME_ADDON/$compiled" ]]; then - sha256sum "$GAME_ADDON/$compiled" | cut -d' ' -f1 - else - echo "missing $compiled" - fi - done -} -sums_before="$(compiled_sums)" - -for file in "${PANORAMA_FILES[@]}"; do - mkdir -p "$CONTENT_ADDON/$(dirname "$file")" "$STAGE/panorama/$(dirname "$file")" - cp -f "$SRC/panorama/$file" "$CONTENT_ADDON/$file" - - log="$(cd "$RC_DIR" && ./resourcecompiler.exe -game "$WIN_CLIENT_DIR\\game\\csgo" -f \ - -i "$WIN_CLIENT_DIR\\content\\csgo_addons\\$CS2_ADDON\\panorama\\${file//\//\\}" 2>&1 | tr -d '\r')" - if ! grep -q 'OK: 1 compiled, 0 failed' <<<"$log"; then - echo "$log" >&2 - echo "Failed to compile $file" >&2 - exit 1 - fi - - case "$file" in - *.xml) compiled="${file%.xml}.vxml_c" ;; - *.css) compiled="${file%.css}.vcss_c" ;; - esac - cp -f "$GAME_ADDON/$compiled" "$STAGE/panorama/$compiled" - echo "Compiled $compiled" -done - -# --- Package ------------------------------------------------------------------------- -TARBALL="jRandomSkills-${TAG}.tar.gz" -tar -czf "$OUT/$TARBALL" -C "$STAGE" addons panorama -rm -rf "$STAGE" - -echo "Packaged $OUT/$TARBALL:" -tar -tzf "$OUT/$TARBALL" | grep -v '/$' - -# --- Tag ------------------------------------------------------------------------- -if ! git rev-parse -q --verify "refs/tags/$TAG" >/dev/null; then - git tag -a "$TAG" -m "$TAG" -fi -git push origin "refs/tags/$TAG" - -# --- Release --------------------------------------------------------------------- -API="$FORGEJO_URL/api/v1/repos/$OWNER/$REPO" -AUTH=(-H "Authorization: token $FORGEJO_TOKEN") - -release_json="$(curl -fsS "${AUTH[@]}" "$API/releases/tags/$TAG" 2>/dev/null || true)" -if [[ -z "$release_json" ]]; then - body="$(git log -1 --format=%B "$TAG")" - release_json="$(jq -n --arg tag "$TAG" --arg body "$body" \ - '{tag_name: $tag, name: $tag, body: $body, draft: false, prerelease: false}' | - curl -fsS "${AUTH[@]}" -H "Content-Type: application/json" -X POST --data @- "$API/releases")" - echo "Created release $TAG" -else - echo "Release $TAG already exists, replacing its attachment" -fi -release_id="$(jq -r '.id' <<<"$release_json")" - -existing_id="$(jq -r --arg n "$TARBALL" '.assets[]? | select(.name == $n) | .id' <<<"$release_json")" -if [[ -n "$existing_id" ]]; then - curl -fsS "${AUTH[@]}" -X DELETE "$API/releases/$release_id/assets/$existing_id" >/dev/null -fi -curl -fsS "${AUTH[@]}" -X POST -F "attachment=@$OUT/$TARBALL" \ - "$API/releases/$release_id/assets?name=$TARBALL" >/dev/null -echo "Uploaded $TARBALL" - -echo -echo "Download: $FORGEJO_URL/$OWNER/$REPO/releases/download/$TAG/$TARBALL" -echo "Install: tar -xzf $TARBALL -C /srv/cs2/game/csgo" - -echo -if [[ "$(compiled_sums)" != "$sums_before" ]]; then - echo "Workshop: the compiled Panorama layouts CHANGED. Players won't see the change until the" - echo " '$CS2_ADDON' addon is re-uploaded from Workshop Tools to item $WORKSHOP_ID:" - echo " https://steamcommunity.com/sharedfiles/filedetails/?id=$WORKSHOP_ID" -else - echo "Workshop: compiled Panorama layouts unchanged; no Workshop update needed." -fi