v1.2.3.b1
Revive skills (Second Chance / Phoenix / Re-Zombie) — unified "on death" logic: - Intercept the lethal hit before it is applied. Previously they reacted after the death was already committed, so one-shots, fall damage and skill-based kills were missed (Phoenix and Re-Zombie were rewritten from a post-death handler to pre-damage interception). Killer Flash: - Kills through real damage instead of forcing a suicide, so revive skills can intercept. Baseball: - Fixed a rare server crash from decoy grenades: a freed decoy's entity index could be reused by another entity and written to (use-after-free). Decoy tracking is now validated per tick (DesignerName gate) and cleared every round. Native crash hardening: - Aimbot: guard the hit-group native pointer before writing (avoids writing to freed/null memory). - Wallhack: detach the glow when the target dies or disconnects (stale FollowEntity on a freed pawn). - Spectator / Cypher / FalconEye / ThirdEye: null-guard the camera SceneNode walk and re-validate the target before teleport/parent (cross-frame freed-entity deref). - CServerSideClient.ForceFullUpdate now bails on a null client handle. Performance: - Added a per-tick player/bomb cache (PlayerManager.GetTickPlayers / GetTickBomb). - Migrated 82 skills from per-skill Utilities.GetPlayers() to the one shared per-tick scan, and the HUD loop reuses it. Much lower per-tick cost at high player counts (verified 10v10). RayTrace: - Prints a single notice when the module is not installed; dependent skills (Long Zeus, Long Knife, Iana, Cypher, Noclip, Shade + the skill-use aim check) no-op instead of failing silently (#43).
This commit is contained in:
parent
c7ee500957
commit
0e86f54e0a
113 changed files with 717 additions and 437 deletions
|
|
@ -2,7 +2,6 @@
|
|||
using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Collections.Concurrent;
|
||||
using src.utils;
|
||||
using CounterStrikeSharp.API;
|
||||
|
||||
|
|
@ -11,7 +10,6 @@ namespace src.player.skills
|
|||
public class Aimbot : ISkill
|
||||
{
|
||||
private const Skills skillName = Skills.Aimbot;
|
||||
private static readonly ConcurrentDictionary<nint, int> hitGroups = [];
|
||||
|
||||
public static void LoadSkill()
|
||||
{
|
||||
|
|
@ -35,10 +33,11 @@ namespace src.player.skills
|
|||
var attackerController = attackerPawn.Controller.Value;
|
||||
if (attackerController == null || !attackerController.IsValid) return;
|
||||
|
||||
var attacker = PlayerManager.GetPlayerEvent(attackerController.As<CCSPlayerController>())!;
|
||||
var attacker = PlayerManager.GetPlayerEvent(attackerController.As<CCSPlayerController>());
|
||||
if (attacker == null) return;
|
||||
|
||||
var playerInfo = PlayerManager.GetPlayerByIndex(attacker.Index);
|
||||
if (playerInfo == null) return;
|
||||
if (playerInfo == null || playerInfo.Skill != skillName) return;
|
||||
|
||||
int offset = GameData.GetOffset("CTakeDamageInfo_HitGroup");
|
||||
if (offset <= 0) return;
|
||||
|
|
@ -46,32 +45,10 @@ namespace src.player.skills
|
|||
nint hitGroupPointer = Marshal.ReadIntPtr(param2.Handle, offset);
|
||||
if (hitGroupPointer == nint.Zero) return;
|
||||
|
||||
nint hitGroupOffset = Marshal.ReadIntPtr(hitGroupPointer, 16);
|
||||
if (hitGroupOffset == nint.Zero) return;
|
||||
nint hitGroupData = Marshal.ReadIntPtr(hitGroupPointer, 16);
|
||||
if (hitGroupData == nint.Zero) return;
|
||||
|
||||
if (playerInfo.Skill == skillName)
|
||||
{
|
||||
hitGroups.TryAdd(hitGroupOffset, Marshal.ReadInt32(hitGroupOffset, 56));
|
||||
Marshal.WriteInt32(hitGroupOffset, 56, (int)HitGroup_t.HITGROUP_HEAD);
|
||||
}
|
||||
else if (hitGroups.TryGetValue(hitGroupOffset, out var hitGroup))
|
||||
Marshal.WriteInt32(hitGroupOffset, 56, hitGroup);
|
||||
}
|
||||
|
||||
public static void NewRound()
|
||||
{
|
||||
hitGroups.Clear();
|
||||
}
|
||||
|
||||
public static void DisableSkill(CCSPlayerController _)
|
||||
{
|
||||
foreach (var hit in hitGroups)
|
||||
{
|
||||
if (hit.Key != nint.Zero)
|
||||
Marshal.WriteInt32(hit.Key, 56, hit.Value);
|
||||
}
|
||||
|
||||
hitGroups.Clear();
|
||||
Marshal.WriteInt32(hitGroupData, 56, (int)HitGroup_t.HITGROUP_HEAD);
|
||||
}
|
||||
|
||||
public class SkillConfig(Skills skill = skillName, bool active = true, string color = "#ff0000", 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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue