The NPC API provides read access to the NPC configuration synced from the server. Use it to look up voice settings, personality data, and traits for any ped entity or model — whether configured explicitly or using generated defaults.
Trait caching: Optional traits use probability rolls. Results are cached in entity state (Entity(entity).state.traitRolls) and are network-synced. Call clearTraitCache to force a re-roll.
Get complete NPC information for a ped entity or model name. Returns the configured data if a matching NPC entry exists, or generated defaults based on detected gender if not.
Syntaxexports['onex-voiceInteraction']:getNPCInfo(target)
| Name | Type | Description |
|---|---|---|
target | number | string | Ped entity handle, or model name string (e.g. "mp_m_freemode_01") |
Returns: { success = true, data = NPCInfo }
| Field | Type | Description |
|---|---|---|
config | table | Full NPC config entry (or generated default) |
voice | table | { voice, rate, pitch, volume } — TTS voice settings |
animation | table | { lipSync, gesture, returnToIdle } — animation defaults |
audio | table | { maxDistance, falloffCurve, spatialAudio, volumeMultiplier } |
personality | table | { mood, speechPattern, responseStyle, traits } |
traits | table | Array of trait objects from personality.traits |
gender | string | "male" or "female" |
isDefault | boolean | true if no explicit config matched — defaults were generated |
entity | number | Entity handle (when queried by handle) |
modelKey | string | Model hash string used as config key |
Your Script-- Query by entity handle local r = exports['onex-voiceInteraction']:getNPCInfo(pedHandle) if r.success then print("Voice:", r.data.voice.voice) print("Gender:", r.data.gender) print("Is default:", r.data.isDefault) print("Mood:", r.data.personality.mood) end -- Query by model name local r = exports['onex-voiceInteraction']:getNPCInfo("mp_m_freemode_01") if r.success then print("Default voice for freemode male:", r.data.voice.voice) end
When no NPC config matches, defaults are generated:
{ voice = { voice = "en-US-GuyNeural", rate = 1.0, pitch = 1.0, volume = 1.0 }, animation = { lipSync = true, gesture = true, returnToIdle = true }, audio = { maxDistance = 30, falloffCurve = "linear", spatialAudio = true, volumeMultiplier = 1.0 }, personality = { mood = "neutral", speechPattern = "casual", responseStyle = "brief", traits = {} }, gender = "male", -- or "female", detected from ped model category = "default", isDefault = true }
Voice selection from defaults uses a pool per gender, with the entity ID modulating which pool entry is chosen — so different peds of the same model get different voices.
Check whether an NPC has specific traits. Required traits always return hasTrait = true. Optional traits are probability-rolled on first check and cached.
Syntaxexports['onex-voiceInteraction']:checkNPCTraits(entity, traitIds)
| Name | Type | Description |
|---|---|---|
entity | number | Ped entity handle |
traitIds | string | string[] | Single trait ID string, or array of trait ID strings |
Returns: { success = true, data = { [traitId] = TraitCheckResult } }
| Field | Type | Description |
|---|---|---|
hasTrait | boolean | Whether the NPC has this trait |
isRequired | boolean | true if the trait is always active (probability = 100) |
probability | number | Configured probability (1–100) |
rolledProbability | number | The actual roll value used — present only on freshly rolled results |
cached | boolean | true if the result came from cache — present only on cached results |
Your Script-- Check a single trait local r = exports['onex-voiceInteraction']:checkNPCTraits(pedHandle, "drug_addict") if r.success and r.data.drug_addict.hasTrait then print("This NPC is a drug addict") end -- Check multiple traits at once local r = exports['onex-voiceInteraction']:checkNPCTraits(pedHandle, { "aggressive", "friendly", "drug_addict" }) if r.success then for traitId, result in pairs(r.data) do print(traitId, result.hasTrait, result.probability) end end
Query trait data by entity, tag, or definition. More flexible than checkNPCTraits — use when you need to search or inspect definitions rather than check a specific NPC.
Syntaxexports['onex-voiceInteraction']:queryNPCTraits(query)
The query table must contain exactly one of these fields (or combine entity + tag):
| Name | Type | Description |
|---|---|---|
query.entity | number | Get all traits configured for a specific ped |
query.tag | string | Filter by trait tag — combinable with entity |
query.definition | string | true | Get a specific trait definition by name, or true for all definitions |
Your Script-- Get all traits on a specific NPC local r = exports['onex-voiceInteraction']:queryNPCTraits({ entity = pedHandle }) if r.success then for _, trait in ipairs(r.data.traits) do print(trait.traitId, trait.isRequired, trait.probability) end end
| Query | Returns |
|---|---|
{ entity } | { traits = { ... } } |
{ entity, tag } | { hasTrait = bool, matchingTraits = { ... } } |
{ tag } | { npcs = { { modelHash, config, matchingTraits } } } |
{ definition = "name" } | { definition = { ... } } |
{ definition = true } | { definitions = { [id] = { ... } } } |
Clear the cached probability roll results for an entity. Forces fresh rolls on the next checkNPCTraits or queryNPCTraits call.
Syntaxexports['onex-voiceInteraction']:clearTraitCache(entity)
| Name | Type | Description |
|---|---|---|
entity | number | Ped entity handle — required |
Returns: { success = true, data = { cleared = 1 } }
Trait rolls are stored in entity state (Entity(entity).state.traitRolls) and are network-synced. Clearing the cache on one client affects all clients that read that entity's state.
Your Script-- Force re-roll for a specific ped exports['onex-voiceInteraction']:clearTraitCache(pedHandle)
Last updated 14 days ago