Combat Detection Modules

3 Modules

Server-authoritative attack range, weapon damage rates, fire rate intervals, and line-of-sight validation.

# Overview

In multiplayer combat games, exploiters often manipulate weapon scripts to hit enemies from across the map (Reach Hack), shoot through concrete walls (Wallbang Hack), or fire 50 bullets per frame (Rapid Fire / Kill-All).

RAC provides 3 server-side combat validators that intercept hit signals before damage is applied to any humanoid:

  1. ReachValidator: Enforces strict spatial boundaries between attacker and target.
  2. FireRateValidator: Enforces minimum time intervals between consecutive attacks.
  3. WeaponDamageValidator: Enforces maximum allowable damage caps and line-of-sight geometry.

# 1. ReachValidator (ReachValidator.luau)

Validates the physical distance between the attacker's weapon origin and the victim's hitbox.

# Validation Formula

For any attack event: $$\text{Distance} = |\mathbf{p}{\text{attacker}} - \mathbf{p}{\text{victim}}|$$

  • Melee Weapons: Allowed distance $\le 18.0$ studs (configurable via Config.Detectors.Combat.MaxMeleeReachStuds).
  • Ranged Weapons: Allowed distance $\le 500.0$ studs (configurable via Config.Detectors.Combat.MaxRangedReachStuds).
  • Dynamic tolerance is granted for moving targets based on the combined relative velocities of both characters.

If $\text{Distance} > \text{MaxReach}$, the hit is immediately rejected and zero damage is dealt.


# 2. FireRateValidator (FireRateValidator.luau)

Prevents script executors from bypassing weapon animation cooldowns or auto-clicker spam.

# Cooldown Tracking

  • The server maintains a timestamp table for each player: LastAttackTimestamps[userId].
  • When an attack event arrives: $$\Delta t_{\text{attack}} = \text{currentTime} - \text{LastAttackTimestamps}[userId]$$
  • If $\Delta t_{\text{attack}} < \text{MinAttackIntervalSeconds}$ (default $0.08\text{s}$), the attack is flagged as a rapid-fire exploit.

# 3. WeaponDamageValidator (WeaponDamageValidator.luau)

Audits the amount of damage requested and performs a server-side Line-of-Sight (LoS) raycast.

# Line-of-Sight Raycasting

Before damage is accepted:

  1. Origin: Attacker HumanoidRootPart.Position (or weapon muzzle).
  2. Direction: Vector towards Victim HumanoidRootPart.Position.
  3. Raycast params: Exclude attacker character, victim character, and non-collidable transparent parts.
  4. If the ray intersects a solid wall or obstacle before reaching the victim, the hit is classified as an illegal Wallbang Exploit.

# Damage Cap Validation

If a client claims to have dealt $5,000$ damage with a standard weapon, RAC checks: $$\text{Damage} \le \text{MaxDamagePerHit} \quad (\text{default: } 150)$$ Attacks exceeding this threshold are clamped to zero and flagged as critical threats.


# Integrating Combat Checks into Your Weapons

To integrate RAC with your existing weapon scripts, invoke Engine:ValidateCombatHit:

-- Server weapon script
local RAC = require(game.ServerScriptService.RAC.Engine)

local function OnWeaponHit(attacker: Player, victimCharacter: Model, requestedDamage: number)
    local isValid, reason = RAC:ValidateCombatHit(attacker, victimCharacter, requestedDamage, "Melee")
    if not isValid then
        warn(string.format("[Combat Reject] %s hit rejected: %s", attacker.Name, reason))
        return
    end
    
    -- Safe to apply damage
    local victimHumanoid = victimCharacter:FindFirstChildOfClass("Humanoid")
    if victimHumanoid then
        victimHumanoid:TakeDamage(requestedDamage)
    end
end

# Next Steps