AI Skill Report Card

Developing FiveM Framework Scripts

A-84·Oct 23, 2026·Source: Web

Writes and reviews FiveM resource code enforcing this developer's custom framework conventions, which deliberately diverge from common FiveM community patterns.

14 / 15
JavaScript
// Proximity-gated loop for a supermarket interaction let supermarketTick = null; AddEventHandler('onClientResourceStart', (resourceName) => { if (GetCurrentResourceName() !== resourceName) return; startSupermarketCheck(); }); function startSupermarketCheck() { setTick(() => { const ped = PlayerPedId(); const playerCoords = GetEntityCoords(ped); const storeCoords = [100.0, 200.0, 30.0]; const dist = exports.Misc.distanceVector(playerCoords, storeCoords); if (dist < 20.0) { if (!supermarketTick) { supermarketTick = setInterval(() => { // supermarket proximity logic here }, 1000); } } else { if (supermarketTick) { clearInterval(supermarketTick); supermarketTick = null; } } }); }
Recommendation▾
Show a 'bad outcome' example where a wrong native is used and flagged, not just correct conversions, to reinforce review use-case
13 / 15

Progress:

  • Identify all native calls and flag disallowed ones (GetGameTimer, onNet, resourceKvp natives)
  • Replace timing calls with Date.now()
  • Replace onNet event registration with AddEvent / AddEventHandler
  • Remove any resourceKvp usage; use in-memory state or framework-provided storage instead
  • Wrap location-based intervals with a setTick proximity check using exports.Misc.distanceVector
  • Add exports.Misc.canExecute guard on any player-triggered event to prevent spam
  • Verify clearInterval/clearTick cleanup happens when player leaves proximity or resource stops
Recommendation▾
Clarify what exports.Misc.canExecute signature expects (params/return) since it's used without definition
Don't UseUse InsteadWhy
GetGameTimer()Date.now()Framework standardizes on JS native timing
onNet(...)AddEvent(...) + AddEventHandler(...)Framework's event system wraps these for consistency
resourceKvp nativesIn-memory objects / framework storageUnnecessary persistence layer for most use cases
Unconditional setInterval for proximity logicsetTick check + conditional setIntervalAvoid wasting cycles when player isn't near the relevant location
Raw event handlers with no throttlingexports.Misc.canExecute guardPrevents event spam / exploit abuse
Manual distance math (Math.sqrt etc.)exports.Misc.distanceVectorCentralized, tested distance helper
17 / 20

Example 1: Input:

JavaScript
onNet('shop:buyItem', (itemId) => { const time = GetGameTimer(); // process purchase });

Output:

JavaScript
AddEvent('shop:buyItem'); AddEventHandler('shop:buyItem', (itemId) => { if (!exports.Misc.canExecute(source, 'shop:buyItem', 1000)) return; const time = Date.now(); // process purchase });

Example 2: Input: "Check if player is near the bank every frame and open a menu interval while close." Output:

JavaScript
let bankTick = null; setTick(() => { const ped = PlayerPedId(); const coords = GetEntityCoords(ped); const bankCoords = [150.0, -100.0, 29.0]; const dist = exports.Misc.distanceVector(coords, bankCoords); if (dist < 15.0 && !bankTick) { bankTick = setInterval(() => { // bank menu prompt logic }, 500); } else if (dist >= 15.0 && bankTick) { clearInterval(bankTick); bankTick = null; } });

Example 3: Input: "Store player's last login time persistently." Output: Don't use resourceKvp. Store it via the framework's player data object (e.g., player.data.lastLogin = Date.now()) and persist through the framework's existing database/save layer instead.

Recommendation▾
Add a brief note on Lua equivalents since the skill mentions FiveM Lua/JS but all examples are JS only
  • Always null-check and clear interval/tick handles on resource stop (onResourceStop) to avoid orphaned loops.
  • Keep proximity thresholds as named constants, not magic numbers, when a script has multiple zones.
  • Apply exports.Misc.canExecute on every client-to-server event that can be triggered repeatedly by the player (purchases, interactions, item use).
  • Prefer one setTick per logical zone/feature rather than one giant tick checking everything — easier to clear independently.
  • Use Date.now() differences (Date.now() - lastActionTime) for cooldown logic instead of frame-based counters.
  • Forgetting to clear the setInterval when the player walks away — causes stacked intervals re-running logic.
  • Using onNet out of habit from tutorials/other frameworks — always convert to AddEvent/AddEventHandler.
  • Reaching for resourceKvp for "quick persistence" — it's banned in this framework regardless of convenience.
  • Skipping canExecute on events because "it's just a menu open" — spam protection should be the default, not the exception.
  • Running distance checks manually instead of exports.Misc.distanceVector, causing inconsistent threshold behavior across scripts.
0
Grade A-AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
14/15
Workflow
13/15
Examples
17/20
Completeness
17/20
Format
14/15
Conciseness
14/15