Назад к блогу
Tutorial8 мин чтения

FiveM News Reporter System: Скрипт прямых трансляций новостей

Добавьте работающую должность новостного репортера в FiveM. Живые камеры, интерфейс трансляции, подсказки и лучшие новостные скрипты для развития сюжетных линий в масштабах города.

Agency Scripts

Основатель и ведущий разработчик Agency Scripts

Роль новостных репортеров в ролевой игре

Работа репортёра добавляет уникальный социальный слой на ваш FiveM сервер, которого нет у других профессий. Репортёры служат связующим звеном между событиями сервера, документируя преступления, беря интервью у игроков и транслируя истории, формирующие нарратив вашего города. В отличие от большинства профессий, работа репортёра естественно пересекается со всеми фракциями сервера: полицейские погони становятся экстренными новостями, конфликты банд , расследовательскими сюжетами, решения городского совета , редакционными материалами. Это создаёт органичный межфракционный RP, который владельцы серверов постоянно пытаются стимулировать, но редко достигают только механиками. Хорошая новостная система даёт репортёрам инструменты для фиксации событий, написания статей, видимых всем игрокам, и трансляции живых репортажей на экранах по всей карте. Когда игроки видят свои действия в заголовках новостей, это усиливает ощущение значимости RP и мотивирует создавать более захватывающие истории.

Настройка новостной станции и структура работы

Новостная станция служит центром, где репортёры отмечаются на смену, получают оборудование, пишут статьи и координируются с командой. Определите расположение станции, склад оборудования и студию вещания в конфигурации. Структурируйте иерархию работы с ролями: стажёр, репортёр, ведущий и главный редактор, каждая с расширяющимися правами. Стажёры могут писать черновики, но для публикации нужна редакторская проверка. Репортёры могут публиковать статьи и использовать камеры. Ведущие получают доступ к студии для прямых эфиров. Главный редактор управляет командой и контролирует бегущую строку новостей, которая отображается на экране каждого игрока:

Config.NewsStation = {
    label = 'Weazel News',
    jobName = 'reporter',
    location = vector3(-598.97, -929.54, 23.89),
    studioRoom = vector3(-592.12, -924.88, 23.89),
    equipmentLocker = vector3(-601.33, -932.17, 23.89),
    grades = {
        [0] = { name = 'Intern',   canPublish = false, canBroadcast = false },
        [1] = { name = 'Reporter', canPublish = true,  canBroadcast = false },
        [2] = { name = 'Anchor',   canPublish = true,  canBroadcast = true  },
        [3] = { name = 'Editor',   canPublish = true,  canBroadcast = true,
                canManage = true },
    },
    equipment = {
        { item = 'news_camera',     label = 'News Camera' },
        { item = 'news_microphone', label = 'Microphone' },
        { item = 'press_badge',     label = 'Press Badge' },
        { item = 'news_notepad',    label = 'Notepad' },
    },
    vehicles = {
        { model = 'rumpo',  label = 'News Van',    grade = 1 },
        { model = 'frogger', label = 'News Chopper', grade = 2 },
    },
}

Новостной фургон необходим, так как служит мобильной станцией вещания. Оснастите его спутниковой антенной на крыше и разрешите репортёрам начинать прямые трансляции из любой точки, если они рядом с фургоном. Вертолёт предоставляет возможности для аэрофотосъёмки ведущим, освещающим крупные события, такие как погони полиции или чрезвычайные ситуации в городе. Каждый транспорт должен быть ограничен по должностному уровню, чтобы стажёры не могли управлять вертолётом в первый день.

Система камеры и записи

Система камеры , ключевой механизм, делающий новостные репортажи аутентичными. Когда репортёр экипирует предмет новостной камеры, переключается вид от первого лица с наложением записи, показывающим красный индикатор REC, таймер и уровень заряда батареи. Камера поддерживает управление зумом с помощью колёсика мыши и режим съёмки фото, который делает скриншот в игре и сохраняет его как вложение к статье. Используйте нативную систему камеры GTA для плавного ощущения ручной камеры с лёгкими колебаниями, делающими видео естественным, а не идеально статичным:

local isRecording = false
local recordingCam = nil
local recordTimer = 0

function StartCamera()
    if isRecording then return end
    isRecording = true

    local playerPed = PlayerPedId()
    recordingCam = CreateCam('DEFAULT_SCRIPTED_CAMERA', true)

    -- Position camera at player's head height
    local headBone = GetPedBoneCoords(playerPed, 31086, 0.0, 0.0, 0.0)
    SetCamCoord(recordingCam, headBone.x, headBone.y, headBone.z)
    SetCamRot(recordingCam, GetEntityRotation(playerPed, 2))
    SetCamFov(recordingCam, 50.0)
    SetCamActive(recordingCam, true)
    RenderScriptCams(true, true, 500, true, false)

    -- Show recording overlay via NUI
    SendNUIMessage({
        action = 'showRecordingOverlay',
        stationName = 'WEAZEL NEWS',
        reporterName = GetPlayerName(PlayerId())
    })

    -- Camera control thread
    CreateThread(function()
        local currentFov = 50.0
        while isRecording do
            -- Follow player head position
            local head = GetPedBoneCoords(playerPed, 31086, 0.0, 0.0, 0.0)
            SetCamCoord(recordingCam, head.x, head.y, head.z)

            -- Mouse look controls
            local pitch = GetDisabledControlNormal(0, 2) * -5.0
            local yaw = GetDisabledControlNormal(0, 1) * -8.0
            local rot = GetCamRot(recordingCam, 2)
            SetCamRot(recordingCam, rot.x + pitch, rot.y, rot.z + yaw, 2)

            -- Zoom with scroll wheel
            if IsDisabledControlPressed(0, 241) then
                currentFov = math.max(15.0, currentFov - 2.0)
            elseif IsDisabledControlPressed(0, 242) then
                currentFov = math.min(80.0, currentFov + 2.0)
            end
            SetCamFov(recordingCam, currentFov)

            -- Update timer
            recordTimer = recordTimer + 1
            SendNUIMessage({
                action = 'updateTimer',
                time = math.floor(recordTimer / 60)
            })

            DisableAllControlActions(0)
            EnableControlAction(0, 249, true) -- Allow push to talk
            Wait(0)
        end
    end)
end

Оверлей записи, отображаемый через NUI, должен имитировать профессиональный видоискатель новостной камеры с угловыми скобками, обрамляющими кадр, водяным знаком с логотипом станции и бегущей строкой в нижней трети экрана с именем репортера. Когда репортер прекращает запись, оверлей плавно исчезает, и камера возвращается к обычному игровому виду. Длительность записи и данные о местоположении сохраняются для последующего использования при написании связанной статьи.

Написание и публикация статей

Дайте репортёрам полноценный редактор статей, доступный из новостной станции или через их блокнот в поле. Редактор должен использовать NUI-интерфейс с расширенным текстом, где репортёры вводят заголовок, пишут тело статьи, выбирают категорию, например, преступность, политика, спорт или развлечения, и прикрепляют любые фотографии, сделанные с помощью системы камеры. Опубликованные статьи появляются в игровой газете, доступной из газетных ящиков, размещённых по городу, и из приложений телефона, если ваш сервер использует телефонную систему. Храните статьи в базе данных с отметками времени, информацией об авторе и количеством просмотров для отслеживания, какие истории вызывают наибольший интерес игроков:

RegisterNetEvent('news:server:publishArticle', function(articleData)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)

    -- Verify job and permissions
    if Player.PlayerData.job.name ~= 'reporter' then return end
    local grade = Config.NewsStation.grades[Player.PlayerData.job.grade.level]
    if not grade or not grade.canPublish then
        TriggerClientEvent('QBCore:Notify', src,
            'Your rank cannot publish articles', 'error')
        return
    end

    -- Sanitize input
    local headline = articleData.headline:sub(1, 120)
    local body = articleData.body:sub(1, 5000)
    local category = articleData.category or 'general'

    -- Insert into database
    local articleId = MySQL.insert.await(
        'INSERT INTO news_articles (author_id, author_name, headline, body, category, created_at) VALUES (?, ?, ?, ?, ?, NOW())',
        {Player.PlayerData.citizenid, Player.PlayerData.charinfo.firstname ..
         ' ' .. Player.PlayerData.charinfo.lastname,
         headline, body, category}
    )

    -- Broadcast notification to all players
    TriggerClientEvent('news:client:newArticle', -1, {
        id = articleId,
        headline = headline,
        category = category,
        author = Player.PlayerData.charinfo.firstname .. ' ' ..
                 Player.PlayerData.charinfo.lastname
    })

    -- Update news ticker
    TriggerClientEvent('news:client:updateTicker', -1,
        'BREAKING: ' .. headline)

    TriggerClientEvent('QBCore:Notify', src,
        'Article published successfully!', 'success')
end)

Система прямых трансляций

Прямые трансляции , самая захватывающая функция системы новостного репортера, поскольку они создают события на весь сервер, которые каждый игрок может наблюдать в реальном времени. Когда ведущий начинает прямую трансляцию из студии или рядом с новостным фургоном, его аудио через голосовой чат должно передаваться всем игрокам на сервере в пределах настраиваемого радиуса или по всему серверу в зависимости от ваших предпочтений. Отображайте баннер трансляции на экране каждого игрока с логотипом станции, именем ведущего и индикатором прямого эфира. По желанию трансляция может показывать видеопоток с камеры на игровых телевизорах, размещённых в интерьерах по карте, используя render targets. Реализуйте задержку между трансляциями, чтобы предотвратить спам, и требуйте роль ведущего, чтобы не позволять каждому стажёру выходить в эфир в первый же день. Система трансляций должна корректно обрабатывать крайние случаи: если ведущий отключается во время трансляции, автоматически завершайте её и показывайте сообщение о технических неполадках. Если ведущий слишком далеко уходит от новостного фургона во время выездной трансляции, предупреждайте его о потере сигнала и завершайте трансляцию, если он не вернётся в разумное расстояние.

Новостная бегущая строка и уведомления

Бегущая строка , это постоянный UI-элемент, который прокручивает заголовки внизу экрана каждого игрока, как на кабельных новостных каналах. Реализуйте её как NUI-слой, который читает самые свежие опубликованные статьи и циклично показывает заголовки по таймеру. Позвольте главному редактору отправлять срочные новости, которые заменяют обычную строку красным баннером с звуковым сигналом. Игроки могут отключать бегущую строку, если она мешает, с помощью настройки в телефоне или меню настроек. Ограничьте частоту обновлений на сервере, чтобы избежать злоупотреблений, и храните очередь из пяти последних заголовков, чтобы не перегружать игроков старыми новостями. При клике на заголовок открывайте полную статью в NUI-просмотрщике газеты, чтобы игрок мог прочитать её полностью без посещения физического газетного киоска.

Механика интервью и пресс-конференций

Добавьте специализированных механиков для проведения интервью, выходящих за рамки обычного разговора. Когда репортёр нацеливается на другого игрока с микрофоном, отправляется запрос на интервью, который цель может принять или отклонить. Принятое интервью создаёт видимое взаимодействие прессы, где оба игрока смотрят друг на друга, репортёр держит микрофон, а рядом находящиеся игроки видят индикатор прессы над их головами. Всё сказанное во время интервью может быть опционально записано в виде расшифровки, прикреплённой к блокноту репортёра для последующего написания статьи. Для пресс-конференций создайте специальные места с трибунами в мэрии, полицейском участке и больнице, где официальные лица могут одновременно обращаться к нескольким репортёрам. Место с трибуной усиливает радиус голоса выступающего и отображает его имя и должность на нижней трети экрана, видимой всем близлежащим игрокам, создавая аутентичную атмосферу пресс-мероприятия, стимулирующую политическую и институциональную ролевую игру.

Производительность и советы по интеграции

Новостная система охватывает всех игроков сервера через бегущую строку и трансляции, поэтому оптимизация производительности критична. Запускайте бегущую строку как лёгкий NUI-элемент с обновлением на длительном интервале, а не каждый кадр. Кэшируйте опубликованные статьи на клиенте после первого запроса и обновляйте только при открытии просмотрщика газеты или при появлении уведомления о новой статье. Для прямых трансляций направляйте аудио через существующую систему голосового чата, чтобы избежать лишней нагрузки на канал. Ограничьте количество хранимых статей в базе, архивируя записи старше тридцати дней в отдельную таблицу, доступную через меню архива газеты. Агрессивно очищайте сущности камер и NUI-оверлеи при смене работы репортёра, перезапуске ресурса или отключении игрока, чтобы избежать визуальных артефактов. Рассмотрите интеграцию с вашей телефонной системой, чтобы игроки могли читать новости прямо с телефона, подписываться на категории и получать push-уведомления о срочных новостях в интересующих их областях.

Готовы начать?

Возьмите скрипты в нашем магазине или заходите в Discord за поддержкой, обновлениями и анонсами.