EndCore Framework

Streaming and world helpers

Client helpers for loading models, animations and effects safely, finding nearby players, peds, vehicles and objects, spawning vehicles, and reading locations.

These client-only helpers cover the chores most scripts repeat: loading an asset before using it, finding the closest vehicle or player, spawning and deleting vehicles, and turning coordinates into a street name.

Loading assets

Each loader requests an asset and yields until it is ready.

FunctionReturns on successChecks the asset exists first
encore.requestModel(model, timeout?)the model hashyes (IsModelInCdimage)
encore.requestAnimDict(dict, timeout?)dictyes (DoesAnimDictExist)
encore.requestAnimSet(set, timeout?)set (a movement clipset)no
encore.requestPtfx(asset, timeout?)asset (a named particle asset)no
encore.requestTextureDict(dict, timeout?)dict (a streamed texture dictionary)no

Behaviour:

  • model may be a name or a hash. A name is hashed with joaat.
  • If the asset is already loaded, the loader returns straight away.
  • If the asset doesn't exist, the loader returns nil and warns once, for example model "x" does not exist.
  • If the asset doesn't load within timeout (default 10000 ms), the loader returns nil and logs ... did not load within 10000ms.
  • None of them throw. Always check for nil.
  • Anim sets, particle assets and texture dictionaries have no existence check, so a typo waits for the full timeout before returning nil.
Note

The loaders don't release assets. When you are done, call SetModelAsNoLongerNeeded, RemoveAnimDict, RemoveAnimSet, RemoveNamedPtfxAsset or SetStreamedTextureDictAsNoLongerNeeded yourself.

lua
local hash = encore.requestModel('u_m_y_zombie_01')
if not hash then return end

local ped = CreatePed(4, hash, coords.x, coords.y, coords.z, 0.0, true, false)
SetModelAsNoLongerNeeded(hash)

if encore.requestAnimDict('move_m@drunk@verydrunk') then
    TaskPlayAnim(ped, 'move_m@drunk@verydrunk', 'idle', 3.0, 3.0, -1, 1, 0, false, false, false)
    RemoveAnimDict('move_m@drunk@verydrunk')
end

Nearby entities

All distances are in metres from coords.

FunctionReturns
encore.getNearbyPlayers(coords, maxDistance, includeSelf?)A list of { id, serverId, ped, coords, distance }
encore.getClosestPlayer(coords, maxDistance, includeSelf?)playerId?, ped?, coords?, distance?
encore.getNearbyVehicles(coords, maxDistance, includePlayerVehicle?)A list of { entity, coords, distance }
encore.getClosestVehicle(coords, maxDistance, includePlayerVehicle?)vehicle?, coords?, distance?
encore.getClosestPed(coords, maxDistance)ped?, coords?, distance?
encore.getClosestObject(coords, maxDistance)object?, coords?, distance?
  • Player lists come from the players your client currently knows about. id is the client player index, serverId is the id the server uses.
  • Your own player is left out unless includeSelf is true.
  • The vehicle you are sitting in is left out unless includePlayerVehicle is true.
  • getClosestPed only considers non-player peds, which makes it the right call for zombies and NPCs.
  • The getClosest* functions return nil when nothing is in range.
lua
local myCoords = GetEntityCoords(PlayerPedId())

local target, targetPed = encore.getClosestPlayer(myCoords, 3.0)
if not target then
    return encore.notify({ description = 'Nobody nearby', type = 'error' })
end
TriggerServerEvent('my-medical:revive', GetPlayerServerId(target))

for _, entry in ipairs(encore.getNearbyVehicles(myCoords, 25.0)) do
    SetVehicleDoorsLocked(entry.entity, 2)
end

Vehicles

FunctionReturnsNotes
encore.spawnVehicle(model, cb?, coords?, heading?, networked?)vehicle?Yields while the model loads. Returns nil if the model can't load
encore.deleteVehicle(vehicle)noneMarks it as a mission entity, then deletes it
encore.getVehiclePlate(vehicle)stringThe plate text with surrounding spaces trimmed

encore.spawnVehicle arguments:

ArgumentDefaultMeaning
modelrequiredName or hash
cbnoneCalled with the vehicle once it exists
coordsyour positionA vector3 or vector4
headingcoords.w, then your headingHeading in degrees
networkedtrueWhether other players see it

The model is released for you after the vehicle is created.

lua
local vehicle = encore.spawnVehicle('rebel', nil, vec4(1730.2, 3310.5, 41.2, 195.0))
if vehicle then
    SetVehicleFuelLevel(vehicle, 20.0)
    encore.notify({ description = 'Plate ' .. encore.getVehiclePlate(vehicle) })
end
Warning

Anything spawned from the client happens because a client decided to. For vehicles that players own or that cost money, decide on the server whether the spawn is allowed.

On-screen text

These draw GTA text for a single frame, so call them every frame from a loop. They are meant for debugging and simple world labels. Player-facing interface belongs in en-ui, see UI services.

FunctionNotes
encore.drawText2d(text, x, y, scale?, font?)Screen position from 0 to 1. scale defaults to 0.5, font to 4. Centred
encore.drawText3d(coords, text)Draws at a world position, scaled by camera distance and field of view
lua
CreateThread(function()
    while DebugZones do
        for _, zone in ipairs(Zones) do
            encore.drawText3d(zone.coords, zone.name)
        end
        Wait(0)
    end
end)

Location

FunctionReturnsNotes
encore.getCardinalDirection(heading)'North', 'West', 'South' or 'East'GTA headings run counter-clockwise, so 90 is West
encore.getStreetName(coords)street, crossing?crossing is nil when there is no cross street
encore.getZoneName(coords)stringThe zone's display label, such as a district name
lua
local coords = GetEntityCoords(PlayerPedId())
local street, crossing = encore.getStreetName(coords)
local where = crossing and (street .. ' / ' .. crossing) or street

TriggerServerEvent('my-radio:distress', where .. ', ' .. encore.getZoneName(coords))