Caméra et timing
ScriptCamera, TickLoop, AreaFollower et ServerClock : caméras scriptées, tâches par frame qui ne tournent que lorsque c’est nécessaire, signalement de la zone du joueur au serveur, et l’horloge du serveur côté client.
Une caméra scriptée pour les showrooms et les scènes, une tâche par frame que vous n’activez que lorsqu’elle est nécessaire, la moitié client du streaming par zone du serveur, et l’horloge du serveur pour les comptes à rebours. Le travail périodique en général passe par every(ms, fn) (voir Lib : shared et fivem) ; jamais setInterval ni un setTick nu.
ScriptCamera
new ScriptCamera
Une caméra scriptée : la vue showroom d’une boutique, un éditeur, une scène, des jumelles. start la crée et l’affiche, les autres méthodes la déplacent et la modifient, stop revient en douceur à la caméra du jeu et la détruit. Une caméra encore active quand votre ressource s’arrête est rendue immédiatement, si bien que le joueur n’y reste jamais bloqué.
Côté : client · Attend : non
new ScriptCamera(type?: string)Pas d’équivalent Lua : les ressources Lua utilisent CreateCam, RenderScriptCams et DestroyCam.
Paramètres
Prop
Type
CameraView
Là où regarde une caméra, utilisé par start, move et glideTo :
Prop
Type
Membres
Prop
Type
Exemple
import { ScriptCamera } from "@aicore-fivem/lib/client";
const camera = new ScriptCamera();
const CAR = { x: -44.4, y: -1097.1, z: 26.4 };
export function openShowroom(): void {
camera.start({ x: -40.2, y: -1100.5, z: 27.6 }, { pointAt: CAR, fov: 50 }, 800);
}
export function frontView(): void {
camera.glideTo({ x: -47.5, y: -1093.8, z: 27.2 }, { pointAt: CAR, fov: 45 }, 1200);
}
export function closeShowroom(): void {
camera.stop(800);
}camera.start
Crée la caméra (quand elle n’existe pas encore), la place à un point et en fait la vue, avec une transition douce depuis la caméra du jeu.
Côté : client · Attend : non
camera.start(at: Vec3, view?: CameraView, easeMs?: number): voidParamètres
Prop
Type
Retour
void. Voir l’exemple de la classe.
camera.move
Déplace la caméra, immédiatement ou en glissant jusqu’au point (le jeu interpole). Ne fait rien quand elle est arrêtée.
Côté : client · Attend : non
camera.move(at: Vec3, view?: CameraView, ms?: number): voidParamètres
Prop
Type
Retour
void.
Exemple
camera.move({ x: -42.0, y: -1099.0, z: 28.5 }, { pointAt: CAR }, 600);camera.glideTo
Enchaîne vers un nouveau plan : une seconde caméra au nouvel endroit prend le relais de celle-ci, et l’ancienne est détruite après la transition. Le tremblement et le flou sont conservés. Démarre la caméra quand elle est arrêtée (ou quand ms vaut 0).
Côté : client · Attend : non
camera.glideTo(at: Vec3, view: CameraView, ms: number): voidParamètres
Prop
Type
Retour
void. Voir l’exemple de la classe.
camera.attach
Fait suivre une entité par la caméra, avec un décalage dans l’espace propre de l’entité.
Côté : client · Attend : non
camera.attach(entity: number, offset: Vec3, relative?: boolean): voidParamètres
Prop
Type
Retour
void.
Exemple
import { cache, ScriptCamera } from "@aicore-fivem/lib/client";
const chase = new ScriptCamera();
if (cache.vehicle !== false) {
chase.start({ x: 0, y: 0, z: 0 });
chase.attach(cache.vehicle, { x: 0, y: -6, z: 2 });
}camera.pointAt
Fait regarder un point en continu par la caméra.
Côté : client · Attend : non
camera.pointAt(target: Vec3): voidParamètres
Prop
Type
Retour
void.
camera.setFov
Change le champ de vision (zoom).
Côté : client · Attend : non
camera.setFov(fov: number): voidParamètres
Prop
Type
Retour
void.
Exemple
// Jumelles : zoom avec la molette de la souris.
let fov = 40;
export function zoom(step: number): void {
fov = Math.min(70, Math.max(5, fov + step));
camera.setFov(fov);
}camera.shake
Ajoute le tremblement de caméra du jeu. Une amplitude de 0 l’arrête.
Côté : client · Attend : non
camera.shake(type: string, amplitude: number): voidParamètres
Prop
Type
Retour
void.
Exemple
camera.shake("HAND_SHAKE", 0.3);camera.blur
Profondeur de champ : net entre deux distances, flou en dehors. Passez null pour aucun flou. Elle a besoin d’une native par frame, qui ne tourne que tant qu’un flou est défini.
Côté : client · Attend : non
camera.blur(dof: CameraBlur | null): voidParamètres
Prop
Type
Retour
void.
Exemple
camera.blur({ near: 2, far: 8, strength: 0.8 });camera.stop
Rend la vue à la caméra du jeu (avec une transition sur easeMs) et détruit la caméra. Le tremblement et le flou s’arrêtent aussi. Ne fait rien quand elle est arrêtée.
Côté : client · Attend : non
camera.stop(easeMs?: number): voidParamètres
Prop
Type
Retour
void. Voir l’exemple de la classe.
TickLoop
new TickLoop
Une tâche par frame (every(0, fn) sur l’unique planificateur de votre ressource) qui reste désactivée jusqu’à ce que vous l’activiez. Utilisez-la pour tout ce qui doit tourner à chaque frame mais seulement par moments : dessiner un marqueur quand on est proche, un aperçu de placement, désactiver le tir quand on vise un ami.
Côté : client · Attend : non
new TickLoop(onFrame: () => void, name?: string)Pas d’équivalent Lua : aiLib.every(0, fn, { active = false, name = name }) et job:set(active).
Paramètres
Prop
Type
Membres
Prop
Type
Exemple
import { TickLoop, Zones } from "@aicore-fivem/lib/client";
const SPOT = { x: 215.8, y: -810.1, z: 30.7 };
const light = new TickLoop(() => {
DrawLightWithRange(SPOT.x, SPOT.y, SPOT.z + 2, 61, 247, 158, 8, 4);
}, "garageLight");
const zones = new Zones();
zones.add("garage", {
shape: { type: "sphere", center: SPOT, radius: 25 },
onEnter: () => light.set(true),
onExit: () => light.set(false),
});Toutes les tâches de votre ressource tournent depuis un seul setTick qui n’existe que tant qu’une tâche est active. Créez la boucle une fois en haut du fichier et basculez-la, au lieu d’en créer une nouvelle à chaque démarrage.
AreaFollower
new AreaFollower
La moitié client d’un AreaStream serveur (Streaming par zone) : il indique au serveur la case de la grille où se tient le joueur chaque fois qu’elle change (vérifiée toutes les 2 secondes une fois démarré), si bien que le serveur n’envoie que les objets du monde (objets au sol, plantes, props posés) autour du joueur. Créez-en un en haut du fichier.
Côté : client · Attend : non
new AreaFollower(event: string, cellSize?: number)Pas d’équivalent Lua.
Paramètres
Prop
Type
Membres
Prop
Type
Exemple
import { AreaFollower, onServerEvent } from "@aicore-fivem/lib/client";
const follower = new AreaFollower("myplants:cell");
follower.start();
const plants = new Map<number, unknown>();
// Le stream envoie (reset, puts, removes) : un snapshot avec reset à true, puis seulement les changements.
onServerEvent(
"myplants:area",
{
args: ([reset, puts, removes]) =>
typeof reset === "boolean" && Array.isArray(puts) && Array.isArray(removes)
? ([reset, puts, removes] as const)
: null,
},
(reset, puts, removes) => {
if (reset) plants.clear();
for (const plant of puts as Array<{ id?: unknown } | null>)
if (typeof plant?.id === "number") plants.set(plant.id, plant);
for (const id of removes) if (typeof id === "number") plants.delete(id);
},
);Le serveur vérifie une case signalée par rapport à la position réelle du joueur (followReported n’accepte que les cases situées à une case au plus du ped), si bien qu’un tricheur ne peut pas demander une zone éloignée.
ServerClock
new ServerClock
L’horloge du serveur sur un client. Les horloges du client et du serveur peuvent différer, donc un compte à rebours vers une heure serveur (un délai de braquage, la fin d’une enchère) doit d’abord être converti en heure locale. Appelez sync avec le Date.now() du serveur chaque fois qu’un snapshot ou un message de démarrage arrive.
Côté : client (depuis @aicore-fivem/lib/shared) · Attend : non
new ServerClock()Pas d’équivalent Lua.
Membres
Prop
Type
Exemple
import { every, onServerEvent } from "@aicore-fivem/lib/client";
import { ServerClock } from "@aicore-fivem/lib/shared";
const clock = new ServerClock();
let endsAt = 0; // heure locale
onServerEvent(
"myauction:state",
{ args: ([now, ends]) => (typeof now === "number" && typeof ends === "number" ? [now, ends] : null) },
(now, ends) => {
clock.sync(now);
endsAt = clock.toLocal(ends);
},
);
every(1000, () => {
const left = Math.max(0, Math.round((endsAt - Date.now()) / 1000));
SendNUIMessage({ action: "countdown", data: left });
});Le serveur envoie l’heure de fin une seule fois ; le client fait le compte à rebours sur sa propre horloge. N’envoyez jamais le temps restant chaque seconde.
Sondes et chargement
raycast, groundZ, locationName, vehicleLabel, waypoint, pedHeadshot, onShot et les chargeurs request : interroger le jeu sur le monde et charger les assets du jeu.
Appartenance et données du joueur
hasJob, inGang, onDutyIn, allows, onMembershipChange, getPlayerData, onPlayerData et seedPlayerData : le personnage, l’argent, les métiers, le service et les gangs du joueur local tels qu’ai-core les pousse.