Quick navigation

Go to

server runtime · Lua API

Open77.npcs

Runs on the dedicated server and is authoritative: state written here is the truth every client is told about.

server runtime38 functionsOpen in explorerMarkdown
On this page38 sections

all

NETWORK
Signaturelua
Open77.npcs.all([bucket])

Every authoritative NPC, optionally filtered to one routing bucket.

Requires world.npcs. Returns the whole registry, whichever resource created each NPC.

Parameters 1

Parameters of Open77.npcs.all
NameTypeUseDefault
bucketintegeroptional—

Returns

  • array of NPC snapshots

Example

example.lualua
-- /npcs: how many server NPCs are alive right now
RegisterCommand("npcs", function(source)
    local alive = 0
    for _, npc in ipairs(Open77.npcs.all()) do
        if npc.health > 0 then alive = alive + 1 end
    end
    Open77.chat.send(source, ("%d NPCs alive"):format(alive))
end, true)

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9336).

applyDamage

NETWORK
Signaturelua
Open77.npcs.applyDamage(id, amount, [source], [cause])

Applies authoritative damage to an NPC.

Requires world.npcs. source and cause are recorded with the hit so a kill can be attributed. The damage still passes the NPC's damage policy, so an invulnerable NPC takes nothing.

Parameters 4

Parameters of Open77.npcs.applyDamage
NameTypeUseDefault
idNPC idrequired—
amountnumberrequired—
sourceinteger|stringoptional—
causestringoptional—

Returns

  • boolean

Example

example.lualua
-- A trap deals 30 damage to the guard who stepped on it
Open77.npcs.applyDamage(guardId, 30, nil, "trap")

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9342).

capacity

NETWORK
Signaturelua
Open77.npcs.capacity()

Reads allocated NPC counts and admission limits.

Requires world.npcs. Takes no arguments. resourceUsed counts every NPC still owned by the calling resource, including retained corpses and persistent entries; globalUsed counts all allocated NPCs across resources. resourceLimit is 512 and globalLimit is 4096. These are allocation counts, not counts of living or currently visible NPCs. Returns nil, reason when permission or the NPC subsystem is unavailable.

Returns

  • { resourceUsed, resourceLimit, globalUsed, globalLimit }, or nil
  • reason: permission_denied:world.npcs, npcs_unavailable

Example

example.lualua
-- Check both allocation limits before admitting another NPC
local capacity, reason = Open77.npcs.capacity()
if capacity and capacity.resourceUsed < capacity.resourceLimit and capacity.globalUsed < capacity.globalLimit then
    admitNpc()
end

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9332).

create

NETWORK
Signaturelua
Open77.npcs.create(def)

Creates an authoritative NPC.

Requires world.npcs. Build one from record = "Character.*" directly -- no catalogue entry is needed -- or from the legacy template alias. Definition fields are record, template, position, yaw, bucket, appearance, loadout, behavior, aiMode, damagePolicy, health, maxHealth, streamingRadius, streamingHysteresis, despawnWhenUnobserved, persistent and authorityPolicy. aiMode and damagePolicy are integers from the constant tables Open77.npcs.ai (tasks = 0, frozen = 1, native = 2) and Open77.npcs.damage (mortal = 0, immortal = 1, invulnerable = 2; default immortal); a string such as "invulnerable" raises a Lua argument error (number expected, got string) in CreateNpc. authorityPolicy is "nearest" (default) or "balanced" (the client simulating the fewest NPCs, with a tenure-gated rebalance); anything else returns nil, "npc_authority_policy_invalid". behavior.observerReplay = true makes clients that do not simulate the NPC replay the simulator's motion on the shared server clock. The id comes back at once, but engine readiness is asynchronous: a freshly created NPC is not yet a body in the world. See NPCs.

Parameters 1

Parameters of Open77.npcs.create
NameTypeUseDefault
deftablerequired—

Returns

  • NPC id, or nil
  • reason

Example

example.lualua
-- A shopkeeper standing behind the counter, who never fights back
local shopkeeper, reason = Open77.npcs.create({
    record = "Character.Judy",
    position = { x = -1442.2, y = 127.4, z = 18.0 },
    yaw = 180.0,
    damagePolicy = Open77.npcs.damage.invulnerable,   -- an integer (2), never the string
    persistent = true,
})
if not shopkeeper then print("could not spawn the shopkeeper: " .. reason) end

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9266).

get

NETWORK
Signaturelua
Open77.npcs.get(id)

Reads one NPC's canonical snapshot.

Requires world.npcs. Answers nil for an unknown id. The snapshot is the server's record, so it is available before the body has streamed to anyone.

Parameters 1

Parameters of Open77.npcs.get
NameTypeUseDefault
idNPC idrequired—

Returns

  • NPC snapshot, or nil

Example

example.lualua
-- Is the boss still alive?
local boss = Open77.npcs.get(bossId)
if boss and boss.health <= 0 then
    Open77.chat.broadcast("The boss is down!")
end

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9331).

getAttitude

NETWORK
Signaturelua
Open77.npcs.getAttitude(id)

Reads back every attitude row an NPC states.

Requires world.npcs, and only for an NPC this resource created. Returns a table with default, players, npcs, groups and relations; relations is the row projected by setRelationship and is written by the platform, not by setAttitude.

Parameters 1

Parameters of Open77.npcs.getAttitude
NameTypeUseDefault
idNPC idrequired—

Returns

  • table, or nil

Example

example.lualua
-- Debug: print how the guard regards everyone
local attitude = Open77.npcs.getAttitude(guardId)
if attitude then print("default attitude:", attitude.default) end

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9319).

getBehavior

NETWORK
Signaturelua
Open77.npcs.getBehavior(id)

Reads the canonical behavior policy of an owned NPC.

Requires world.npcs. Returns a detached table with aiEnabled, combatEnabled, perceptionEnabled, voiceEnabled, vehicleContactEnabled and hitPricing. Client inspection uses Open77.npcs.get(id).behavior with npcs.read.

Parameters 1

Parameters of Open77.npcs.getBehavior
NameTypeUseDefault
idintegerrequired—

Returns

  • table behavior, or nil

Example

example.lualua
-- Only re-enable combat if it was actually off
local behavior = Open77.npcs.getBehavior(guardId)
if behavior and not behavior.combatEnabled then
    Open77.npcs.setCombatEnabled(guardId, true)
end

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9285).

getEquipment

NETWORK
Signaturelua
Open77.npcs.getEquipment(id)

The clothing set an owned NPC is dressed in, slot to record.

Requires world.npcs. Reads loadout.equipment back as a table; empty when the NPC wears nothing of ours, nil for an id this resource does not own. The same object is json.decode(Open77.npcs.get(id).loadout).equipment.

Parameters 1

Parameters of Open77.npcs.getEquipment
NameTypeUseDefault
idNPC idrequired—

Returns

  • slot-to-record table, or nil

Example

example.lualua
-- Swap the jacket, keep the rest.
local worn = Open77.npcs.getEquipment(clerkId) or {}
worn.OuterChest = "Items.Jacket_02_basic_01"
Open77.npcs.setEquipment(clerkId, worn)

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.Npcs6.cs as LuaResourceRuntime.Bootstrap (line 251).

getGroup

NETWORK
Signaturelua
Open77.npcs.getGroup(id)

The relationship group an NPC belongs to.

Requires world.npcs. Returns the combat.group string, or nil when the NPC has none.

Parameters 1

Parameters of Open77.npcs.getGroup
NameTypeUseDefault
idNPC idrequired—

Returns

  • string, or nil

Example

example.lualua
-- Gang members share loot with their own group only
if Open77.npcs.getGroup(npcId) == "maelstrom" then
    dropGangLoot(npcId)
end

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9321).

getRelationship

NETWORK
Signaturelua
Open77.npcs.getRelationship(groupA, groupB)

Reads back a declared group relationship.

Requires world.npcs. Returns the attitude token, or nil when this resource has declared nothing for the pair.

Parameters 2

Parameters of Open77.npcs.getRelationship
NameTypeUseDefault
groupAstringrequired—
groupBstringrequired—

Returns

  • string, or nil

Example

example.lualua
-- Check before declaring: are the two gangs already at war?
if Open77.npcs.getRelationship("maelstrom", "valentinos") ~= "hostile" then
    Open77.npcs.setRelationship("maelstrom", "valentinos", "hostile")
end

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9327).

kill

NETWORK
Signaturelua
Open77.npcs.kill(id)

Kills an NPC authoritatively.

Requires world.npcs. Goes through the NPC life authority rather than setting health to zero, so the death is replicated once and consistently.

Parameters 1

Parameters of Open77.npcs.kill
NameTypeUseDefault
idNPC idrequired—

Returns

  • boolean

Example

example.lualua
-- /killnpc <id>
RegisterCommand("killnpc", function(source, args)
    local npcId = tonumber(args[1])
    if npcId then Open77.npcs.kill(npcId) end
end, true)

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9340).

owner

NETWORK
Signaturelua
Open77.npcs.owner(id)

Who is simulating an NPC, and since when.

Requires world.npcs. The same shape as Open77.vehicles.owner, so a script reads both alike: authorityPlayerId and physicsOwner carry the same value and are 0 when nobody simulates the NPC; epoch is the authority epoch; since is when the authority last changed on the GetGameTimer() clock and ageMs how long ago; reason is why (projectionready, bettercandidate, leaseexpired, playerdisconnected, streamedout, npcremoved, validationfailed, serverrevoke, or none); leaseMs is how long the current lease still has, when there is one; readyClients is how many clients have reported a ready projection -- the election's candidates. There is no request counterpart on purpose: an NPC's authority is elected from the ready clients, and a script has no better information than the election about which of them should simulate a body; a grant to a client that never reported ready would be a lease nobody renews.

Parameters 1

Parameters of Open77.npcs.owner
NameTypeUseDefault
idNPC idrequired—

Returns

  • { authorityPlayerId, physicsOwner, epoch, readyClients, since, ageMs, reason, leaseMs? }, or nil
  • reason: invalid_npc_id, npc_not_found

Example

example.lualua
-- Why is the guard standing still? Nobody is simulating him yet.
local owner = Open77.npcs.owner(guardId)
if owner and owner.authorityPlayerId == 0 then
    print(("guard %d has no authority: %d ready client(s), last reason %s"):format(guardId, owner.readyClients, owner.reason))
end

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.Vehicles6.cs as LuaResourceRuntime.Bootstrap (line 276).

presence

NETWORK
Signaturelua
Open77.npcs.presence(id)

Where an NPC is and who simulates it, in one O(1) read.

Requires world.npcs, and npcs.foreign for an NPC another resource created (the same rule as Open77.npcs.all({ includeForeign = true }), because where somebody else's NPC stands is roster information). The read a rule needs when a client acts FOR an NPC: authorityPlayerId is the client simulating it (0 when nobody), epoch the authority epoch that client holds, and leaseMs how long its lease still has -- present only while there is a live lease. alive is the canonical life (alive flag and health above zero). x, y, z and bucket are the canonical place: the transform the simulator last reported and the server accepted under its anti-teleport budget. owned says whether the caller created it; resource names who did. Unlike get it builds one table, not a snapshot of the whole NPC, and unlike all it never walks the roster. The door service uses it to admit an NPC's passage only from the client that simulates that NPC.

Parameters 1

Parameters of Open77.npcs.presence
NameTypeUseDefault
idNPC idrequired—

Returns

  • { id, resource, owned, bucket, x, y, z, alive, authorityPlayerId, epoch, leaseMs? }, or nil
  • reason: invalid_npc_id, npc_not_found, npcs_unavailable, permission_denied:world.npcs, permission_denied:npcs.foreign

Example

example.lualua
-- Let a client speak for an NPC only while it simulates it, near the target.
local function speaksFor(player, npcId, target)
    local p = Open77.npcs.presence(npcId)
    if not p or not p.alive or p.authorityPlayerId ~= player or not p.leaseMs then return false end
    local dx, dy, dz = p.x - target.x, p.y - target.y, p.z - target.z
    return dx * dx + dy * dy + dz * dz <= 36
end

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.Vehicles6.cs as LuaResourceRuntime.Bootstrap (line 284).

remove

NETWORK
Signaturelua
Open77.npcs.remove(id)

Removes an authoritative NPC.

Requires world.npcs. Despawns the body for every viewer and drops the registry entry, including its queued tasks.

Parameters 1

Parameters of Open77.npcs.remove
NameTypeUseDefault
idNPC idrequired—

Returns

  • boolean

Example

example.lualua
-- Clean up every NPC this resource spawned when the event ends
AddEventHandler("event:ended", function()
    for _, npcId in ipairs(spawned) do Open77.npcs.remove(npcId) end
    spawned = {}
end)

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9330).

revive

NETWORK
Signaturelua
Open77.npcs.revive(id, [health])

Revives an NPC, at full health by default.

Requires world.npcs. health defaults to 100. Reviving an NPC that is alive is accepted and simply sets its health.

Parameters 2

Parameters of Open77.npcs.revive
NameTypeUseDefault
idNPC idrequired—
healthnumberoptional—

Returns

  • boolean

Example

example.lualua
-- The medic revives the fallen bodyguard at half health
Open77.npcs.revive(bodyguardId, 50)

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9341).

setAIEnabled

NETWORK
Signaturelua
Open77.npcs.setAIEnabled(id, enabled)

Pauses or resumes a server-owned NPC's native AI and Open77 tasks.

Requires world.npcs and ownership. Does not change aiMode or the other behavior options. Disabling revokes the simulation lease; enabling resumes according to the selected mode.

Parameters 2

Parameters of Open77.npcs.setAIEnabled
NameTypeUseDefault
idintegerrequired—
enabledbooleanrequired—

Returns

  • boolean success, optional string reason

Example

example.lualua
-- Pause every NPC while the round is paused, resume after
for _, npc in ipairs(Open77.npcs.all(ARENA_BUCKET)) do
    Open77.npcs.setAIEnabled(npc.id, false)
end

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9286).

setAiMode

NETWORK
Signaturelua
Open77.npcs.setAiMode(id, mode)

Chooses who drives an NPC.

Requires world.npcs. Modes are in Open77.npcs.ai: tasks (0, the Open77 task queue), frozen (1) and native (2, vanilla AI). This is a different axis from setAIEnabled, which pauses whichever driver is selected without changing the mode.

Parameters 2

Parameters of Open77.npcs.setAiMode
NameTypeUseDefault
idNPC idrequired—
modeinteger|stringrequired—

Returns

  • boolean
  • reason

Example

example.lualua
-- Let the engine's own AI drive this civilian instead of the task queue
Open77.npcs.setAiMode(npcId, "native")

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9280).

setAppearance

NETWORK
Signaturelua
Open77.npcs.setAppearance(id, appearance)

Convenience patch for an NPC's appearance.

Requires world.npcs. Exactly update(id, { appearance = appearance }).

Parameters 2

Parameters of Open77.npcs.setAppearance
NameTypeUseDefault
idNPC idrequired—
appearancestringrequired—

Returns

  • boolean
  • reason

Example

example.lualua
-- Swap the bartender's outfit for the night shift
Open77.npcs.setAppearance(bartenderId, "judy_night")

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9274).

setAttitude

NETWORK
Signaturelua
Open77.npcs.setAttitude(id, attitude, [options])

Makes an NPC hostile, neutral or friendly toward a target.

Requires world.npcs. Attitude is per NPC and per target, because that is the only shape the engine expresses per incarnation: gameAttitudeAgent.SetAttitudeTowards(agent, attitude) is a pair override. options.towards selects the row -- a player id, { npcId = n } (which must belong to this resource) or { group = "name" } -- and omitting it sets the default that covers everyone without a row. Resolution order is the per-entity row, then the per-group row, then the resource relationship row, then the default. Passing nil for attitude removes the row. An NPC that states nothing behaves exactly as it did before this call existed. Eligibility is a hard cap on players: a dead player, or one in another routing bucket, is never made a target by a directive. See the NPC guide.

Parameters 3

Parameters of Open77.npcs.setAttitude
NameTypeUseDefault
idNPC idrequired—
attitudestring `friendly`|`neutral`|`hostile`, or nil to clearrequired—
optionstable { towards? }optional—

Returns

  • boolean
  • reason

Example

example.lualua
-- The guard becomes hostile toward the one player who broke in
Open77.npcs.setAttitude(guardId, "hostile", { towards = intruderId })

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9305).

setBehavior

NETWORK
Signaturelua
Open77.npcs.setBehavior(id, behavior)

Changes a server-owned NPC's native AI, combat, perception and voice policy.

Requires world.npcs and ownership. Partial options: the booleans aiEnabled, combatEnabled, perceptionEnabled and voiceEnabled (default true) and vehicleContactEnabled (default false), and hitPricing ("resource", the default, or "platform"). The same object is accepted as behavior by create and update. Replicated to observers and late joiners. Malformed values return npc_behavior_invalid; unknown option names return npc_behavior_unknown_option. See NPC AI, combat and voice control for engine semantics and boundaries.

Parameters 2

Parameters of Open77.npcs.setBehavior
NameTypeUseDefault
idintegerrequired—
behaviortablerequired—

Returns

  • boolean success, optional string reason

Example

example.lualua
-- A passive quest giver: no combat, no barks, still walks
Open77.npcs.setBehavior(questGiverId, { combatEnabled = false, voiceEnabled = false })

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9281).

setBucket

NETWORK
Signaturelua
Open77.npcs.setBucket(id, bucket)

Moves an NPC to another routing bucket.

Requires world.npcs. Changes who can see it: only players in the same bucket stream the NPC.

Parameters 2

Parameters of Open77.npcs.setBucket
NameTypeUseDefault
idNPC idrequired—
bucketintegerrequired—

Returns

  • boolean

Example

example.lualua
-- Move the arena boss into the arena instance
Open77.npcs.setBucket(bossId, ARENA_BUCKET)

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9273).

setCombatEnabled

NETWORK
Signaturelua
Open77.npcs.setCombatEnabled(id, enabled)

Allows or suppresses a server-owned NPC's combat behavior.

Requires world.npcs and ownership. False clears threats, disables hostile acquisition/reactions and blocks outgoing hit processing without disabling scripted locomotion.

Parameters 2

Parameters of Open77.npcs.setCombatEnabled
NameTypeUseDefault
idintegerrequired—
enabledbooleanrequired—

Returns

  • boolean success, optional string reason

Example

example.lualua
-- Truce: the gang stops fighting during the negotiation
for _, npcId in ipairs(gang) do
    Open77.npcs.setCombatEnabled(npcId, false)
end

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9290).

setDamagePolicy

NETWORK
Signaturelua
Open77.npcs.setDamagePolicy(id, policy)

Sets whether an NPC can be hurt or killed.

Requires world.npcs. Policies are in Open77.npcs.damage: mortal (0), immortal (1, can be hurt but not killed) and invulnerable (2, takes nothing).

Parameters 2

Parameters of Open77.npcs.setDamagePolicy
NameTypeUseDefault
idNPC idrequired—
policyinteger|stringrequired—

Returns

  • boolean
  • reason

Example

example.lualua
-- The quest giver can be hurt but never killed
Open77.npcs.setDamagePolicy(questGiverId, "immortal")

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9279).

setEquipment

NETWORK
Signaturelua
Open77.npcs.setEquipment(id, set)

Sets the canonical clothing set of an owned NPC, slot to Items.* record. Whether a rig renders it is the client's answer, not this call's.

Requires world.npcs and ownership. FiveM's SetPedComponentVariation on a ped, through the same puppet equipment path the loadout's weapon key already uses. The table is the WHOLE desired set: keys are the nine clothing slots (Head, Face, InnerChest, OuterChest, Legs, Feet, Outfit, UnderwearTop, UnderwearBottom -- the held weapon stays on setLoadout), values are Items.* record names, and a slot left out is a slot you want empty; {} undresses. Only a slot Open77 itself filled is ever emptied, so a character's own look (its appearance) is never stripped. Published as one revision on loadout.equipment, reaches late joiners, and survives a later setLoadout that does not mention equipment. Existence of the record and whether the garment binds to that character's rig are decided on each client against the live game -- the client never runs InitializeSlots for clothing, and refuses a slot the Character.* record does not declare with a log line (slot_unavailable). Refusals: npc_equipment_invalid, npc_equipment_slot_invalid, npc_equipment_record_invalid, npc_not_found, npc_not_owned.

Parameters 2

Parameters of Open77.npcs.setEquipment
NameTypeUseDefault
idNPC idrequired—
settable { slot = "Items.*", ... }required—

Returns

  • true on success, otherwise nil
  • reason

Example

example.lualua
-- Canonical state, replicated and kept for late joiners. Whether the clerk is
-- SEEN in these clothes is decided per client against the live game: a
-- `Character.*` record that does not declare the slot refuses it with
-- `slot_unavailable`, and measured on 2.31 a Character rig renders none of it.
-- Read it back with getEquipment; do not treat a `true` here as a visible outfit.
local ok, reason = Open77.npcs.setEquipment(clerkId, {
    OuterChest = "Items.Jacket_01_basic_01",
    Legs = "Items.Pants_01_basic_01",
    Feet = "Items.Shoes_01_basic_01",
})
if not ok then print("could not dress the clerk: " .. reason) end

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.Npcs6.cs as LuaResourceRuntime.Bootstrap (line 246).

setGroup

NETWORK
Signaturelua
Open77.npcs.setGroup(id, group)

Puts an NPC in a relationship group.

Requires world.npcs. Writes the pre-existing combat.group loadout field, so it keeps its existing meaning -- two NPCs sharing a non-empty group are allies -- and additionally picks up whatever setRelationship has declared for that group. Group names are at most 64 characters of A-Z a-z 0-9 _ - .; nil removes the group. Unlike the attitude rows, a group does not survive a wholesale setLoadout, because it is an ordinary loadout field.

Parameters 2

Parameters of Open77.npcs.setGroup
NameTypeUseDefault
idNPC idrequired—
groupstring, or nil to clearrequired—

Returns

  • boolean
  • reason

Example

example.lualua
-- Two spawned gang members become allies through a shared group
Open77.npcs.setGroup(firstId, "maelstrom")
Open77.npcs.setGroup(secondId, "maelstrom")

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9320).

setHealth

NETWORK
Signaturelua
Open77.npcs.setHealth(id, health, [maxHealth])

Convenience patch for an NPC's health and maximum.

Requires world.npcs. Passing maxHealth raises or lowers the canonical maximum at the same time; omitting it leaves the maximum alone.

Parameters 3

Parameters of Open77.npcs.setHealth
NameTypeUseDefault
idNPC idrequired—
healthnumberrequired—
maxHealthnumberoptional—

Returns

  • boolean
  • reason

Example

example.lualua
-- The boss has 500 health, out of 500
Open77.npcs.setHealth(bossId, 500, 500)

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9276).

setLoadout

NETWORK
Signaturelua
Open77.npcs.setLoadout(id, loadout)

Convenience patch for an NPC's loadout.

Requires world.npcs. Exactly update(id, { loadout = loadout }).

Parameters 2

Parameters of Open77.npcs.setLoadout
NameTypeUseDefault
idNPC idrequired—
loadouttable|stringrequired—

Returns

  • boolean
  • reason

Example

example.lualua
-- Arm the guard with a Lexington
Open77.npcs.setLoadout(guardId, { weapon = "Items.Preset_Lexington_Default" })

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9275).

setPerceptionEnabled

NETWORK
Signaturelua
Open77.npcs.setPerceptionEnabled(id, enabled)

Controls autonomous sensory acquisition for a server-owned NPC.

Requires world.npcs and ownership. False disables senses, reactions and automatic threat seeding; does not cancel an existing explicit target. Combat or AI disabled takes precedence.

Parameters 2

Parameters of Open77.npcs.setPerceptionEnabled
NameTypeUseDefault
idintegerrequired—
enabledbooleanrequired—

Returns

  • boolean success, optional string reason

Example

example.lualua
-- A stealth mission: the guard only fights if a script tells it to
Open77.npcs.setPerceptionEnabled(guardId, false)

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9294).

setRagdoll

NETWORK
Signaturelua
Open77.npcs.setRagdoll(id, enabled)

Sets an NPC's canonical ragdoll state.

Requires world.npcs. Exactly update(id, { ragdoll = enabled == true }); the state is replicated, so every viewer agrees.

Parameters 2

Parameters of Open77.npcs.setRagdoll
NameTypeUseDefault
idNPC idrequired—
enabledbooleanrequired—

Returns

  • boolean
  • reason

Example

example.lualua
-- Knocked out by a punch: the body goes limp for three seconds
Open77.npcs.setRagdoll(npcId, true)
SetTimeout(3000, function() Open77.npcs.setRagdoll(npcId, false) end)

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9329).

setRelationship

NETWORK
Signaturelua
Open77.npcs.setRelationship(groupA, groupB, attitude)

Declares how two of this resource's groups regard each other.

Requires world.npcs. The matrix is per resource -- one resource's groups never reach another's bodies, exactly as its NPC reads and writes never do -- and it is symmetric: declaring a against b also declares b against a. The resulting row is projected onto every owned NPC in either group and replicated, so observers resolve it without asking the server; an NPC that joins the group later picks up the standing row. nil for attitude removes the declaration. The matrix dies with the resource that declared it. This is NOT the engine's global attitude matrix: gameCAttitudeManager.SetAttitudeRelation is process-wide and shared with vanilla content, and is deliberately not used -- see docs/research/npc-behavior-control.md.

Parameters 3

Parameters of Open77.npcs.setRelationship
NameTypeUseDefault
groupAstringrequired—
groupBstringrequired—
attitudestring `friendly`|`neutral`|`hostile`, or nil to clearrequired—

Returns

  • boolean
  • reason

Example

example.lualua
-- Gang war: every Maelstrom NPC this resource owns hates every Valentino
Open77.npcs.setRelationship("maelstrom", "valentinos", "hostile")

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9326).

setTransform

NETWORK
Signaturelua
Open77.npcs.setTransform(id, def)

Sets an NPC's canonical position and yaw.

Requires world.npcs. A teleport, not a walk: for movement that the AI performs, enqueue a moveTo task instead.

Parameters 2

Parameters of Open77.npcs.setTransform
NameTypeUseDefault
idNPC idrequired—
deftable { position, yaw? }required—

Returns

  • boolean
  • reason

Example

example.lualua
-- Teleport the shopkeeper back behind the counter
Open77.npcs.setTransform(shopkeeperId, { position = counter, yaw = 180.0 })

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9266).

setVoiceEnabled

NETWORK
Signaturelua
Open77.npcs.setVoiceEnabled(id, enabled)

Controls voice lines and barks of a server-owned NPC.

Requires world.npcs and ownership. Controls native voiceset lines/grunts (including combat/search barks), suppresses scripted voiceovers and filters native dialogue routed through subtitles. Replicated per NPC, not a global sound/SFX mute or a guarantee to stop audio already playing.

Parameters 2

Parameters of Open77.npcs.setVoiceEnabled
NameTypeUseDefault
idintegerrequired—
enabledbooleanrequired—

Returns

  • boolean success, optional string reason

Example

example.lualua
-- Silence the bartender's barks during the cutscene
Open77.npcs.setVoiceEnabled(bartenderId, false)

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9298).

speak

NETWORK
Signaturelua
Open77.npcs.speak(id, voice, options)

Queues one voice-over line from an NPC's own voiceset on every client streaming it. voice is a voContext name (greeting, fear_beg), never a sentence: the NPC cannot say arbitrary text. true is the line queued, not the line heard.

Requires world.npcs and ownership. FiveM's PlayPedAmbientSpeechNative: voice is a voContext name -- the same word vanilla passes to GameObject.PlayVoiceOver (greeting, fear_beg, rep_ask_to_leave) -- resolved by the engine against the puppet's voiceset (Character.*.voiceTag), not a Wwise event. Open77.npcs.voices() lists the generic barks that can be pointed at in the game's 2.31 sources; any identifier (letters, digits, underscore, at most 64) is accepted, because a record may carry lines no vanilla script calls. A name the voiceset does not have is silent and nothing can report it -- true means queued on every viewer, not heard. Audibility was not measured in the test loop (no audio capture; the plumbing is proven as far as the SoundPlayVo event reaching each viewer's puppet): test the lines you ship by ear, on the records you ship. Rides the existing effect one-shot to the NPC's routing bucket; the bundled open77_effects resource queues the engine's own SoundPlayVo event on each viewer's puppet through Open77.sfx.playVoice. options.ignoreFrustum (default true) speaks off-screen; options.ignoreDistance (default false) skips the engine's distance cull. Refusals: invalid_voice, invalid_npc_id, npc_not_found, npc_not_owned, npc_dead, voice_disabled (setVoiceEnabled(id, false) is in force), npc_not_streamed (no client has reported the body ready, so nobody could hear it), npc_voice_busy (a line was accepted on this NPC less than 400 ms ago).

Parameters 3

Parameters of Open77.npcs.speak
NameTypeUseDefault
idNPC idrequired—
voicestring (voContext name, not text)required—
optionstable { ignoreFrustum?, ignoreDistance? }required—

Returns

  • true on success, otherwise nil
  • reason

Example

example.lualua
-- The clerk greets whoever uses the counter prompt.
AddEventHandler("onNpcInteracted", function(npcId, playerId)
    if npcId == clerkId then
        local ok, reason = Open77.npcs.speak(clerkId, "greeting")
        if not ok then print("clerk stayed silent: " .. reason) end
    end
end)

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.Npcs6.cs as LuaResourceRuntime.Bootstrap (line 204).

target

NETWORK
Signaturelua
Open77.npcs.target(id)

Who an NPC is currently fighting.

Requires world.npcs, and only for an NPC this resource created. Returns { kind = "none"|"player"|"npc", id = n }, mirroring the last reading its lease holder reported. It is the engine's own target tracker, not a record of what a script asked for, so an NPC that acquires a target by perception shows up here too. onNpcTargetChanged fires on every change to this value.

Parameters 1

Parameters of Open77.npcs.target
NameTypeUseDefault
idNPC idrequired—

Returns

  • table { kind, id }, or nil

Example

example.lualua
-- Is the guard fighting a player right now?
local target = Open77.npcs.target(guardId)
if target and target.kind == "player" then
    Open77.chat.send(target.id, "The guard is after you!")
end

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9328).

templates

NETWORK
Signaturelua
Open77.npcs.templates()

The legacy alias catalogue of NPC templates.

Requires world.npcs. It is a convenience list, not a limit: create accepts any Character.* record whether or not it appears here.

Returns

  • array of template names

Example

example.lualua
-- Print the legacy alias list once at startup
for _, template in ipairs(Open77.npcs.templates()) do
    print(template.name, template.record)
end

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9343).

update

NETWORK
Signaturelua
Open77.npcs.update(id, def)

Patches an NPC's canonical state.

Requires world.npcs. Sparse: appearance, loadout, behavior, AI mode, damage policy, health and ragdoll can all be patched in one call, and everything omitted is left alone. The convenience setters below are thin wrappers over this.

Parameters 2

Parameters of Open77.npcs.update
NameTypeUseDefault
idNPC idrequired—
deftable (patch)required—

Returns

  • boolean
  • reason

Example

example.lualua
-- Change several things in one replicated patch
Open77.npcs.update(npcId, {
    health = 100,
    damagePolicy = "mortal",
    behavior = { combatEnabled = true },
})

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.cs as LuaResourceRuntime.Bootstrap (line 9252).

voices

NETWORK
Signaturelua
Open77.npcs.voices()

The documented bark vocabulary for speak, each name with the 2.31 source that plays it.

Requires nothing. Rows of { name, context, source } where source is a file and line in the game's own shipped REDscript (tools/redmod/scripts) or .tweak sources (tools/redmod/tweaks) -- names that can be re-read rather than believed. It is documentation, not an allowlist: speak accepts any identifier, and whether a given NPC's voiceset carries a line is up to its record's voiceTag.

Returns

  • array of { name, context, source }

Example

example.lualua
-- Pick a random documented bark for an idle vendor.
local rows = Open77.npcs.voices()
local pick = rows[math.random(#rows)]
Open77.npcs.speak(vendorId, pick.name)

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.Npcs6.cs as LuaResourceRuntime.Bootstrap (line 219).

whenReady

NETWORK
Signaturelua
Open77.npcs.whenReady(id, [timeoutMs])

A promise that resolves once at least one client has a ready body for an NPC.

Requires world.npcs. The server half of the preloading helpers: FiveM code waits on the streamer with RequestModel / HasModelLoaded loops; here the server's only honest question is "does some client have a body for this NPC yet", and the answer is already on the wire -- every client reports its projection ready, Open77.npcs.owner(id).readyClients counts them and the election publishes onNpcAuthorityChanged(id, player, epoch, "projectionready"). Resolves with the Open77.npcs.owner(id) table as soon as readyClients > 0 (before the call returns when one already has) and rejects with timeout after timeoutMs (default 15000, clamped to 1..120000); listens for the election event and polls the owner read every 250 ms as the safety net. The one-shot handler is removed on resolve, on timeout and with the resource. nil, reason only for a bad id, a bad timeout or a missing permission; an NPC the server does not know is waited for and times out, exactly like the client's vehicles.whenStreamed on an id it has never seen. There is deliberately no vehicle counterpart on the server: a vehicle's steward is elected by a driver's claim, never by a streamed report, so the server holds no signal that means "somebody has this car" -- Open77.vehicles.create already returns after the canonical create, and the client's Open77.vehicles.whenStreamed answers for its own projection.

Parameters 2

Parameters of Open77.npcs.whenReady
NameTypeUseDefault
idNPC idrequired—
timeoutMsnumberoptional—

Returns

  • Promise, or nil
  • reason: invalid_npc_id, invalid_timeout, permission_denied:world.npcs, task_limit_or_stopping

Example

example.lualua
-- Send the guard on patrol only once somebody can animate him
local guard = assert(Open77.npcs.create({ template = "civilian_female_relaxed_01", position = post }))
Open77.npcs.whenReady(guard, 10000):next(function(owner)
    Open77.npcs.tasks.patrol(guard, route, { loop = true })
end, function(reason)
    print(("guard %d never streamed: %s"):format(guard, reason))
end)

NPC AI, combat & voice guide · Registered in LuaResourceRuntime.Streaming6.cs as LuaResourceRuntime.Bootstrap (line 53).

// For agents & LLMsthis page as Markdownllms.txtllms-full.txt

// Guides · Lua API

Search the docs

1,905 guides and functions indexed

Try