ZerØ Network

Developer Technical Documentation — ZerØ Target

Version: 1.0.0 | Author: ZerØ Network (Core Overextended) | Frameworks: QBCore, ESX Legacy, OX Core, Standalone
Resmon Usage: 0.00 ms (Idle) / 0.01 ms (Active Scanning) | Engine: Lua 5.4 / Cerulean


1. Architecture & Design Philosophy

ZerØ Target was engineered to definitively resolve ecosystem fragmentation within FiveM targeting systems. Server developers traditionally face an either/or dilemma between qb-target and ox_target, often resulting in runtime breaks when integrating third-party resources designed for different target interfaces.

The architecture of zero_target rests upon four design pillars:

  1. Seamless Unification: Intercepts export invocations targeting ox_target, qb-target, and qtarget dynamically at runtime via metatables and __cfx_export_* handlers.
  2. Type Safety & Invocation Normalization: Normalizes signature discrepancies across APIs (e.g., adapting legacy action(entity) callbacks so they do not receive unexpected composite response tables, preventing native parameter errors in GTA V).
  3. Adaptive Scan-Loop Throttling: The primary camera raycast thread employs dynamic sleep intervals (from 25 ms to 200 ms) when aiming at passive geometry (asphalt, sky, empty walls) and drops to 0 ms exclusively when interactable entities with valid options are detected.
  4. Decoupled Framework Bridge: framework/bridge.lua isolates all framework-specific mechanics (jobs, gangs, inventories, citizen IDs), allowing the targeting engine to function identically across QBCore, ESX, or Standalone environments without spaghetti dependencies.

2. Project Directory Structure

zero_target/
├── fxmanifest.lua
├── shared/
│   ├── config.lua
│   └── config_locales.lua
├── framework/
│   └── bridge.lua
├── server/
│   ├── main.lua
│   └── version.lua
├── client/
│   ├── main.lua
│   ├── api.lua
│   ├── utils.lua
│   ├── state.lua
│   ├── defaults.lua
│   ├── debug.lua
│   └── compat/
│       ├── qb-target.lua
│       ├── ox_target.lua
│       └── qtarget.lua
├── ui/
│   ├── index.html
│   ├── style.css
│   ├── js/
│   └── sprite/
│       └── pin.png
└── readme/
    ├── Documentacion_ES.md
    ├── Documentation_EN.md
    ├── Instrucciones_ES.md
    └── Instructions_EN.md

3. Framework Abstraction Layer (framework/bridge.lua)

The bridge automatically detects the server environment or adheres to the forced framework set in Config.Framework.

Real-Time Session Synchronization

  • Qbox (qbx_core):
    • Automatically identifies native qbx_core or explicit Config.Framework = "qbox".
    • Listens to qbx_core:client:playerLoaded, qbx_core:client:setPlayerData, qbx_core:client:onJobUpdate, qbx_core:client:onGangUpdate, and qbx_core:client:onPlayerUnload.
    • Syncs PlayerData.groups, PlayerData.job, PlayerData.gang, and PlayerData.citizenid.
    • Supports native exports.qbx_core:HasGroup(filter) permission checks.
  • QBCore (qb-core):
    • Listens to QBCore:Player:SetPlayerData, QBCore:Client:OnJobUpdate, and QBCore:Client:OnGangUpdate.
    • Listens to QBCore:Client:OnPlayerLoaded to initialize state after multicharacter selection.
    • Listens to QBCore:Client:OnPlayerUnload to clear group and item caches upon logout.
  • ESX Legacy (es_extended):
    • Listens to esx:playerLoaded and esx:onPlayerLogout for player lifecycle management.
    • Listens to esx:setJob, esx:setJob2 (secondary job/gang), esx:setPlayerData, esx:addInventoryItem, and esx:removeInventoryItem.
  • Supported Inventories:
    • ox_inventory: Direct reactive queries via exports.ox_inventory:Search('count', item) and event updates via ox_inventory:itemCount.
    • qb-inventory: Real-time synchronization via QBCore:Client:OnPlayerUpdated (key 'items') and native exports['qb-inventory']:HasItem(items, amount) verification.
    • Default Inventories: Safe parsing and counting of PlayerData.items or PlayerData.inventory into an indexed internal dictionary.

Bridge Methods

-- Checks if the player has a specific group/job with an optional minimum grade
Bridge.HasGroup(filter)

-- Checks if the player possesses the required items (supports anyItem or all)
Bridge.HasItem(filter, hasAny)

4. Scan Engine & Resmon Optimization

The central raycast scanning thread resides in client/main.lua and operates on the following flow:

[Start of Frame Cycle]
          │
          ▼
Is Targeting Active? (Continuous = true OR Key Pressed = true)
          ├── NO ──► Sleep = 200 ms (Resmon 0.00 ms)
          │
          └── YES
               │
               ▼
     Camera Raycast (Flag 511)
               │
               ▼
      Hit within DrawDistance (7.0m)?
               ├── NO ──► Sleep = 100 ms to 150 ms
               │
               └── YES
                    │
                    ▼
          Evaluate entity options and nearby zones
                    │
                    ▼
          Are options visible after permission/distance filters?
                    ├── YES ──► Sleep = 0 ms (Instant 60 FPS responsive UI)
                    └── NO  ──► Sleep = 60 ms (No target: CPU idles)

Through this adaptive sleeping model:

  • 0.00 ms at idle (driving, walking, or unpressed key mode).
  • 0.01 ms in continuous mode when looking at roads, floors, or plain walls.
  • 0.03 ms - 0.05 ms only during the brief moment when an interaction menu is actively rendered on screen.

5. Universal Compatibility Layer (client/compat/)

5.1. qb-target.lua

Converts qb-target options into zero_target's internal format:

  1. Resolution of action Callback Signature: In qb-target, the action callback signature expects action(entity). Modern ox-derived targets pass a composite table response = { entity = ..., coords = ... }.
    To prevent legacy scripts from passing a table to natives such as DeleteEntity(entity) or NetworkGetNetworkIdFromEntity(entity), zero_target wraps the callback:
    local action = v.action
    if action then
        v.onSelect = function(data)
            return action(data and data.entity or data, data)
        end
    end
    
  2. Group and Gang Normalization: Translates diverse properties (v.job, v.gang, v.citizenid)—whether supplied as strings, arrays, or grade-keyed tables—into a unified lookup table validated by Bridge.HasGroup.
  3. Plural Aliases: Exposes both singular and plural export names for all standard calls:
    • AddTargetBone / AddTargetBones
    • AddTargetEntity / AddTargetEntities / RemoveTargetEntity / RemoveTargetEntities
    • AddTargetModel / AddTargetModels / RemoveTargetModel / RemoveTargetModels
    • RemoveBoxZone / RemovePolyZone / RemoveCircleZone -> RemoveZone
  4. Network Event Interceptors: Handles legacy client events such as qb-target:client:AddBoxZone.

5.2. qtarget.lua

Provides the simplified qtarget interface:

  • exports.qtarget:Ped(options)
  • exports.qtarget:Vehicle(options)
  • exports.qtarget:Object(options)
  • exports.qtarget:Player(options)
  • And their corresponding removal functions RemovePed, RemoveVehicle, etc.

6. Core API Reference (client/api.lua)

Modern resources can interface directly with zero_target (or via ox_target aliases):

6.1. Creating Spatial Zones

-- Box Zone
local zoneId = exports.zero_target:addBoxZone({
    coords = vec3(x, y, z),
    size = vec3(2.0, 2.0, 2.0),
    rotation = 45.0,
    debug = false,
    options = {
        {
            name = 'my_option',
            icon = 'fas fa-box',
            label = 'Open Crate',
            groups = 'police',
            onSelect = function(data)
                print("Crate opened at", data.coords)
            end
        }
    }
})

-- Poly Zone
local zoneId = exports.zero_target:addPolyZone({
    points = { vec3(x1, y1, z), vec3(x2, y2, z), vec3(x3, y3, z) },
    thickness = 3.0,
    options = { ... }
})

-- Sphere Zone
local zoneId = exports.zero_target:addSphereZone({
    coords = vec3(x, y, z),
    radius = 2.5,
    options = { ... }
})

-- Remove any zone by ID or name
exports.zero_target:removeZone(zoneId)

6.2. Models, Entities, and Globals

-- Register options on models (hash or model name)
exports.zero_target:addModel({'prop_atm_01', 'prop_atm_02'}, {
    {
        name = 'atm_use',
        icon = 'fas fa-credit-card',
        label = 'Use ATM',
        distance = 1.5,
        onSelect = function(data)
            -- ATM logic
        end
    }
})

-- Global Options by Type
exports.zero_target:addGlobalPed(options)
exports.zero_target:addGlobalVehicle(options)
exports.zero_target:addGlobalObject(options)
exports.zero_target:addGlobalPlayer(options)

-- Targeted or complete removal
exports.zero_target:removeGlobalVehicle({'option_name'})
exports.zero_target:removeModel('prop_atm_01', {'atm_use'})

7. Server Architecture & Version Management

server/main.lua

  • Maintains synchronized networked entity state flags (ox_target:setEntityHasOptions).
  • Runs a 10-second garbage-collection loop to unregister entities deleted from server memory (ox_target:removeEntity).
  • Synchronizes vehicle door states between the interacting client and the network entity owner (ox_target:toggleEntityDoor).

server/version.lua

  • Complies strictly with ZerØ Network enterprise standards:
    • Non-blocking asynchronous query against the remote GitHub manifest.
    • JSON schema integrity verification (schema == 1).
    • Formatted console banner indicating detected framework, version, and 0.00ms idle resmon target.
    • Clean lifecycle teardown on resource stop (onResourceStop).

8. Interaction & Selection Modes (Config.InteractionType)

The resource supports three option-confirmation modalities managed centrally by the server in shared/config.lua:

Mode Key Code Screen Icon Confirmation Mechanics
Hold (E) 'hold' Static E with radar shockwave The user holds the E key for 800ms until the radial border completes 100%.
Tap (E) 'press' Static E with radar shockwave A single fast press on the E key triggers the action instantly without any waiting time.
Click (Mouse) 'click' Pointing Hand Icon (fa-hand-pointer) The pointing hand is shown with its radar shockwave and the selected action is triggered upon Left Clicking the mouse (or pressing E).

[!IMPORTANT] The interaction mode is configured strictly by developers on the server (Config.InteractionType). In the player UI (/targetmenu), players are restricted to customizing only their personal visual appearance: Accent Color, Typography, and Eye Shape, which persist in local client KVP (zero_target_shape, zero_target_color, zero_target_font).