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

FiveM Судебная и правовая система: скрипт реалистичных судебных процессов

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

Agency Scripts

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

Архитектура юридической системы

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

Схема базы данных для юридических записей

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

CREATE TABLE IF NOT EXISTS warrants (
    id INT AUTO_INCREMENT PRIMARY KEY,
    type ENUM('arrest', 'search', 'bench') NOT NULL,
    target_citizenid VARCHAR(50) NOT NULL,
    target_name VARCHAR(100) NOT NULL,
    reason TEXT NOT NULL,
    issued_by VARCHAR(50) NOT NULL,
    approved_by VARCHAR(50) DEFAULT NULL,
    status ENUM('pending', 'active', 'executed', 'expired', 'revoked') DEFAULT 'pending',
    issued_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    expires_at TIMESTAMP NULL,
    executed_at TIMESTAMP NULL,
    INDEX idx_target (target_citizenid),
    INDEX idx_status (status)
);

CREATE TABLE IF NOT EXISTS court_cases (
    id INT AUTO_INCREMENT PRIMARY KEY,
    case_number VARCHAR(20) UNIQUE NOT NULL,
    defendant_citizenid VARCHAR(50) NOT NULL,
    defendant_name VARCHAR(100) NOT NULL,
    prosecutor_citizenid VARCHAR(50) DEFAULT NULL,
    defense_citizenid VARCHAR(50) DEFAULT NULL,
    judge_citizenid VARCHAR(50) DEFAULT NULL,
    charges TEXT NOT NULL,
    status ENUM('filed', 'arraignment', 'pretrial', 'trial', 'verdict', 'closed', 'dismissed') DEFAULT 'filed',
    plea ENUM('not_guilty', 'guilty', 'no_contest') DEFAULT NULL,
    verdict ENUM('guilty', 'not_guilty', 'mistrial', 'dismissed') DEFAULT NULL,
    sentence TEXT DEFAULT NULL,
    fine_amount INT DEFAULT 0,
    jail_minutes INT DEFAULT 0,
    filed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    hearing_scheduled TIMESTAMP NULL,
    closed_at TIMESTAMP NULL,
    INDEX idx_defendant (defendant_citizenid),
    INDEX idx_status (status)
);

CREATE TABLE IF NOT EXISTS evidence (
    id INT AUTO_INCREMENT PRIMARY KEY,
    case_id INT DEFAULT NULL,
    type ENUM('physical', 'digital', 'testimony', 'document', 'photo') NOT NULL,
    label VARCHAR(200) NOT NULL,
    description TEXT DEFAULT NULL,
    collected_by VARCHAR(50) NOT NULL,
    collected_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    chain_of_custody TEXT DEFAULT NULL,
    is_admitted BOOLEAN DEFAULT FALSE,
    FOREIGN KEY (case_id) REFERENCES court_cases(id)
);

CREATE TABLE IF NOT EXISTS legal_records (
    id INT AUTO_INCREMENT PRIMARY KEY,
    citizenid VARCHAR(50) NOT NULL,
    record_type ENUM('conviction', 'acquittal', 'fine', 'warning', 'restraining_order') NOT NULL,
    description TEXT NOT NULL,
    case_id INT DEFAULT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    expunged BOOLEAN DEFAULT FALSE,
    INDEX idx_citizen (citizenid),
    FOREIGN KEY (case_id) REFERENCES court_cases(id)
);

Система ордеров

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

-- Warrant request by police
RegisterNetEvent('legal:server:requestWarrant', function(data)
    local src = source
    local Officer = QBCore.Functions.GetPlayer(src)
    if not Officer or Officer.PlayerData.job.name ~= 'police' then return end

    local warrant = {
        type = data.type,
        target_citizenid = data.targetCitizenid,
        target_name = data.targetName,
        reason = data.reason,
        issued_by = Officer.PlayerData.citizenid,
    }

    local id = MySQL.insert.await(
        'INSERT INTO warrants (type, target_citizenid, target_name, reason, issued_by) VALUES (?, ?, ?, ?, ?)',
        { warrant.type, warrant.target_citizenid, warrant.target_name, warrant.reason, warrant.issued_by }
    )

    -- Notify judges
    local players = QBCore.Functions.GetQBPlayers()
    for _, player in pairs(players) do
        if player.PlayerData.job.name == 'judge' then
            TriggerClientEvent('legal:client:warrantPending', player.PlayerData.source, {
                id = id,
                type = warrant.type,
                targetName = warrant.target_name,
                reason = warrant.reason,
                officerName = Officer.PlayerData.charinfo.firstname .. ' ' .. Officer.PlayerData.charinfo.lastname,
            })
        end
    end

    TriggerClientEvent('QBCore:Notify', src, 'Warrant request submitted for judicial review', 'success')
end)

-- Judge approval
RegisterNetEvent('legal:server:approveWarrant', function(warrantId)
    local src = source
    local Judge = QBCore.Functions.GetPlayer(src)
    if not Judge or Judge.PlayerData.job.name ~= 'judge' then return end

    local warrant = MySQL.single.await('SELECT * FROM warrants WHERE id = ? AND status = "pending"', { warrantId })
    if not warrant then return end

    local expiryHours = warrant.type == 'search' and 48 or 168
    local expiresAt = os.date('!%Y-%m-%d %H:%M:%S', os.time() + (expiryHours * 3600))

    MySQL.update('UPDATE warrants SET status = "active", approved_by = ?, expires_at = ? WHERE id = ?',
        { Judge.PlayerData.citizenid, expiresAt, warrantId })

    -- Notify requesting officer if online
    TriggerClientEvent('QBCore:Notify', src, 'Warrant #' .. warrantId .. ' approved', 'success')
end)

Рабочий процесс судебных слушаний

Судебные слушания следуют структурированному процессу, который переводит дела через предъявление обвинений, предварительные ходатайства, судебное разбирательство и вынесение приговора. Когда дело открывается, система генерирует уникальный номер дела и присваивает статус «открыто». Судья рассматривает дело и назначает слушание по предъявлению обвинений, где обвиняемый заявляет о своей вине. Если обвиняемый признаёт себя невиновным, дело переходит к предварительному слушанию, где адвокаты могут подавать ходатайства и представлять доказательства, затем к суду, где обе стороны излагают свои аргументы. Судья управляет ходом слушания с помощью команд, которые меняют статус дела и обновляют интерфейс для всех участников. Реализуйте NUI для зала суда, отображающий информацию о деле, текущую фазу и предоставляющий роль-специфичные элементы управления для судьи, прокурора и защитника. Судья получает кнопки вердикта и поля для ввода приговора, а адвокаты , кнопки возражений и управления представлением доказательств.

Роль адвоката и система защиты

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

Config.LawyerSystem = {
    barExamQuestions = 15,
    passingScore = 11,       -- 73% to pass
    examCooldown = 86400,    -- 24 hours between attempts
    maxActiveClients = 5,
    consultationFee = 500,   -- base fee for initial consultation
    trialFeeRange = { min = 2000, max = 25000 },

    motionTypes = {
        { id = 'suppress_evidence', label = 'Motion to Suppress Evidence', description = 'Request exclusion of illegally obtained evidence' },
        { id = 'dismiss_charges', label = 'Motion to Dismiss', description = 'Request dismissal due to insufficient evidence' },
        { id = 'continuance', label = 'Motion for Continuance', description = 'Request to postpone the hearing' },
        { id = 'change_venue', label = 'Motion for Change of Venue', description = 'Request trial at different location' },
        { id = 'bail_reduction', label = 'Motion for Bail Reduction', description = 'Request lower bail amount' },
        { id = 'expungement', label = 'Motion for Expungement', description = 'Request to clear prior conviction' },
    },
}

-- Hire a lawyer from jail
RegisterNetEvent('legal:server:hireLawyer', function(lawyerCitizenid)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    if not Player then return end

    local citizenid = Player.PlayerData.citizenid

    -- Find active case for this player
    local activeCase = MySQL.single.await(
        'SELECT * FROM court_cases WHERE defendant_citizenid = ? AND status NOT IN ("closed", "dismissed") ORDER BY filed_at DESC LIMIT 1',
        { citizenid }
    )
    if not activeCase then
        TriggerClientEvent('QBCore:Notify', src, 'No active case found', 'error')
        return
    end

    -- Assign lawyer to case
    MySQL.update('UPDATE court_cases SET defense_citizenid = ? WHERE id = ?',
        { lawyerCitizenid, activeCase.id })

    -- Notify lawyer
    local lawyerPlayer = QBCore.Functions.GetPlayerByCitizenId(lawyerCitizenid)
    if lawyerPlayer then
        TriggerClientEvent('QBCore:Notify', lawyerPlayer.PlayerData.source,
            'New client: ' .. Player.PlayerData.charinfo.firstname .. ' ' .. Player.PlayerData.charinfo.lastname ..
            ' | Case #' .. activeCase.case_number, 'success')
    end

    TriggerClientEvent('QBCore:Notify', src, 'Attorney assigned to your case', 'success')
end)

Система управления доказательствами

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

Механика штрафов и залога

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

Команды судьи и вынесение приговоров

Судьям необходим полный набор команд для управления судебными процессами и обеспечения работы правовой системы. Основные команды включают /case для просмотра и управления кейсами, /warrant одобрять или отклонять запросы на ордер, /sentence назначать тюремное заключение и штрафы, /bail для установки сумм залога, /gag заглушать нарушающих игроков во время слушаний, и /contempt садить игроков в тюрьму за неуважение к суду. Команда вынесения приговора должна ссылаться на конфигурацию уголовного кодекса, которая определяет минимальные и максимальные сроки для каждого обвинения, обеспечивая согласованность между разными судьями. Реализуйте систему руководящих принципов вынесения приговоров, которая предлагает соответствующие наказания на основе обвинений и криминальной истории обвиняемого, при этом позволяя судьям отклоняться с обоснованием. Храните все судебные решения в таблице юридических записей, чтобы сервер формировал прецеденты, к которым опытные игроки могли бы обращаться в будущих процессах. Добавьте процесс судебного пересмотра, где приговоры могут быть обжалованы у судьи более высокого ранга или коллегии, создавая дополнительные уровни юридической ролевой игры для преданных игроков.

Интеграция с полицией, тюрьмой и MDT

Юридическая система должна бесшовно интегрироваться с существующими ресурсами полиции, тюрьмы и MDT, формируя единый поток правосудия. Когда полиция подает обвинения через MDT, система должна автоматически создавать судебное дело с соответствующим номером и связывать любые доказательства, уже собранные в ходе расследования. Когда судья приговаривает обвиняемого к тюремному заключению, система должна напрямую вызывать экспорт функции заключения тюрьмы, чтобы приговор автоматически исполнялся без необходимости вручную выполнять команду заключения офицером полиции. Активные ордера должны отображаться в MDT полиции при поиске гражданина с четкими индикаторами типа ордера, выдавшего органа и даты истечения. Уголовные записи, созданные судебными решениями, должны быть доступны в MDT в профиле гражданина, показывая всю его юридическую историю, включая осуждения, оправдания, активные дела и непогашенные штрафы. Экспортируйте все функции юридической системы, чтобы другие ресурсы могли проверять статус ордеров, подтверждать квалификацию юристов, просматривать уголовные записи и взаимодействовать с судебной системой программно.

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

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