HZ Scripts

Exports & Events

HZ-Television exposes a set of client and server exports covering TV control, playlist automation, streamer mode, local media, and the abandon-cleanup tooling. Everything below is under the HZ-Television resource name — usage is exports['HZ-Television']:(...).


TV Control

StartTelevision(coords)

Powers on the TV at the given coords.

exports['HZ-Television']:StartTelevision(vector3(215.7, -810.1, 30.9))

StopTelevision(coords)

Powers off the TV at the given coords.

exports['HZ-Television']:StopTelevision(vector3(215.7, -810.1, 30.9))

PlayVideoOnTelevision(coords, url, mode?)

Plays arbitrary content on a powered TV.

exports['HZ-Television']:PlayVideoOnTelevision(coords, 'https://www.youtube.com/watch?v=dQw4w9WgXcQ')
exports['HZ-Television']:PlayVideoOnTelevision(coords, 'https://example.com', 'browser')
exports['HZ-Television']:PlayVideoOnTelevision(coords, 'https://i.imgur.com/alert.png', 'image')
modeBehavior
'play' (default)native video (YouTube / Twitch / Kick / MP4 / HLS / …)
'browser'load as a browser iframe
'image'load as a static image

StopContentOnTelevision(coords)

Clears content but leaves the TV powered on.

exports['HZ-Television']:StopContentOnTelevision(coords)

SetVolumeOnTelevision(coords, volume)

Volume is an integer in 0..100.

exports['HZ-Television']:SetVolumeOnTelevision(coords, 40)

SetChannelOnTelevision(coords, channelIndex)

Switches to a pre-recorded channel by 1-based index in Config.Channels.

exports['HZ-Television']:SetChannelOnTelevision(coords, 2)  -- 2nd entry in Config.Channels

Personal Playlist (v3.1)

Programmatically start a looping playlist on a specific TV. Useful for automated billboard campaigns triggered from other scripts.

StartPlaylistOnTelevision(coords, items)

exports['HZ-Television']:StartPlaylistOnTelevision(coords, {
    { url = 'https://youtu.be/abc', type = 'video', title = 'Clip 1', duration = 30 },
    { url = 'https://i.imgur.com/x.png', type = 'image', title = 'Menu',   duration = 10 },
    { url = 'https://youtu.be/xyz', type = 'video', title = 'Clip 2', duration = 45 },
})

The server cycles through items in order, honoring each item's duration (seconds). Loops forever until StopPlaylistOnTelevision is called or a player manually changes the content.

StopPlaylistOnTelevision(coords)

exports['HZ-Television']:StopPlaylistOnTelevision(coords)

Streamer Mode

Mutes all nearby TVs for the local player — designed for content creators who need to cut game audio from their stream without touching other players' experience.

SetStreamerMode(enabled)

exports['HZ-Television']:SetStreamerMode(true)   -- mute
exports['HZ-Television']:SetStreamerMode(false)  -- unmute (restores previous volumes)

IsStreamerMode()

Returns boolean.

if exports['HZ-Television']:IsStreamerMode() then
    print('Streamer mode active')
end

Local Media

GetLocalMedia()

Returns the list of local media files declared in Config.LocalMedia.

local media = exports['HZ-Television']:GetLocalMedia()
for _, item in ipairs(media) do
    print(item.title, item.file, item.type)
end

CarPlay Helpers (v3.2)

GetCarplayOnVehicle(vehicle)

Returns the CarPlay prop entity currently attached to vehicle, or nil.

local carplayEntity = exports['HZ-Television']:GetCarplayOnVehicle(vehicle)
if carplayEntity then
    print('CarPlay attached at entity #' .. carplayEntity)
end

IsCarplayPoweredOn(vehicle)

if exports['HZ-Television']:IsCarplayPoweredOn(vehicle) then
    -- CarPlay is currently on
end

Admin / Abandon Cleanup (v3.4)

RunHZTVCleanup()

Triggers the auto-cleanup pass on demand (server-side). Honors Config.Placer.AutoCleanupDays. Returns true when started.

-- Server-side, from a custom admin script:
exports['HZ-Television']:RunHZTVCleanup()

Also exposed as a server-side command: /tvclean run (ACE-gated via Config.Placer.CleanupAdminPermission).

/tvclean command

Sub-commandAction
/tvclean listTop 20 owners by inactivity — identifier, placement count, days inactive
/tvclean runTrigger cleanup immediately
/tvclean purge Wipe ALL placements (TVs + CarPlays) for a specific identifier

Events

Client → Server

HZ-Television:placeTV

Fires when a player places a static TV from their inventory.

-- Server-side
AddEventHandler('HZ-Television:placeTV', function(model, coords, heading)
    local src = source
    -- custom logs, gates, property checks, etc.
end)

HZ-Television:placeCarplay

Fires when a player places a CarPlay in a vehicle (v3.2). Payload includes the vehicle plate, bone index, and per-axis offsets / rotations.

AddEventHandler('HZ-Television:placeCarplay', function(data)
    -- data = { plate, bone, offset_x, offset_y, offset_z, rot_x, rot_y, rot_z }
end)

HZ-Television:pickupTV

Fires when a player picks up a placed TV.

AddEventHandler('HZ-Television:pickupTV', function(tvId)
    local src = source
end)

HZ-Television:removeCarplay

Fires when a player removes a CarPlay from their vehicle.

AddEventHandler('HZ-Television:removeCarplay', function(plate)
    local src = source
end)

Server → Client

HZ-Television:updateTV

Force-update a TV on the client side.

TriggerClientEvent('HZ-Television:updateTV', -1, tvEntity, {
    url    = 'https://youtu.be/xxx',
    power  = true,
    volume = 0.8,
})

HZ-Television:powerOff

Turn off a TV for all clients.

TriggerClientEvent('HZ-Television:powerOff', -1, tvEntity)

Integration Examples

Cinema automation

-- Server-side: play a movie on a billboard at a scheduled time
RegisterCommand('startmovie', function(source, args)
    if not IsPlayerAceAllowed(source, 'admin') then return end
    local billboardCoords = vector3(...)
    exports['HZ-Television']:PlayVideoOnTelevision(
        billboardCoords,
        'https://www.youtube.com/watch?v=' .. (args[1] or 'dQw4w9WgXcQ')
    )
    TriggerClientEvent('chat:addMessage', -1, { args = { 'Cinema', 'The show is starting!' } })
end, false)

Property gating

-- Only allow placing TVs inside an owned property
AddEventHandler('HZ-Television:placeTV', function(model, coords, heading)
    local src = source
    local inOwned = exports['esx_property']:IsPlayerInOwnedProperty(src)
    if not inOwned then
        TriggerClientEvent('esx:showNotification', src, 'Must be in your property')
        CancelEvent()
    end
end)

Emergency broadcast

RegisterCommand('emergency', function(source, args)
    if not IsPlayerAceAllowed(source, 'admin') then return end
    local msg = table.concat(args, ' ')
    -- Push an image alert to every placed TV
    local tvs = exports['HZ-Television']:GetAllPlacedTVs()
    for _, tv in ipairs(tvs or {}) do
        exports['HZ-Television']:PlayVideoOnTelevision(tv.coords, 'https://i.imgur.com/alert.png', 'image')
    end
    TriggerClientEvent('chat:addMessage', -1, { color = { 255, 0, 0 }, args = { 'ALERT', msg } })
end, false)

Reporter / news job

-- QBCore: reporter job can broadcast live to all billboards
RegisterNetEvent('reporter:broadcastNews', function(url)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    if Player.PlayerData.job.name ~= 'reporter' then
        TriggerClientEvent('QBCore:Notify', src, 'Not a reporter', 'error')
        return
    end
    local tvs = exports['HZ-Television']:GetAllPlacedTVs()
    for _, tv in ipairs(tvs or {}) do
        if tv.type == 'billboard' then
            exports['HZ-Television']:PlayVideoOnTelevision(tv.coords, url)
        end
    end
end)

Need help integrating? Join our Discord and open a ticket in #support.