Мануал Урок Работа Дальнобойщика . урок [ RAGE 1.1 ]

nettkom

Активный участник
Автор темы
56
20
27
В этом уроке мы с нуля напишем работу дальнобойщика для сервера rage mp. Как обычно используем только javascript.


Для лучшего результата предлагаю параллельно с просмотром видео повторять код своими руками. Тогда лучше запомнится :)
Видео получилось длинным, но если сделать его коротким, то получается слишком поверхностно и многие вещи будут непонятны. Основная его цель это помочь новичкам самим начать писать свои скрипты.



Ниже приведу финальную версию кода скрипта с комментариями. Полный архив с исходным кодом скрипта можно также скачать в приложении в конце поста. Для установки скопируйте в папку сервера и подключите клиентскую часть в client_packages/index.js.

Серверная часть (packages/tw/index.js)


JavaScript:
// Спавны грузовиков, трейлеров и точек загрузки/разгрузки
const truckSpawns = [
    { x: -422.77093505859375, y: 1166.211669921875, z: 325.973876953125, heading: -18.22724151611328},
    { x: -404.05560302734375, y: 1161.9130859375, z: 325.98529052734375, heading: -12.60693359375}
];

const trailerSpawns = [
    { x: -410.40142822265625, y: 1134.956298828125, z: 325.9732971191406, heading: -13.243707656860352},
    { x: -428.8808288574219, y: 1138.2325439453125, z: 325.9739685058594, heading: -16.17988395690918}
];

const pickPoints = [
    { x: -412.3080749511719, y: 1218.32763671875, z: 324.7181396484375},
    { x: -457.32415771484375, y: 1152.080810546875, z: 324.9734802246094},
    { x: -511.28912353515625, y: 1184.92919921875, z: 323.9432373046875},
    { x: -368.6314392089844, y: 1255.5517578125, z: 327.6026916503906},
    { x: -347.2783203125, y: 1152.3865966796875, z: 324.71673583984375}
];


mp.events.add('packagesLoaded', () => { // при старте сервера спавним транспорт для миссии
    spawnWorkVehicles("phantom3", truckSpawns);
    spawnWorkVehicles("trailers", trailerSpawns);
});


function spawnWorkVehicles(modelName, spawnPoints){ // функция позволяет заспавнить транспорт по координатам переданным в массиве spawnPoints
    spawnPoints.forEach( spawn => {
        mp.vehicles.new(mp.joaat(modelName), spawn, { heading: spawn.heading});
    });
}


mp.events.addCommand('tw', (player) => { // команда старта работы
    let loadPoint = getRandomPoint();
    let destPoint;

    do{
        destPoint = getRandomPoint();
    } while(loadPoint.x == destPoint.x && loadPoint.y == destPoint.y); // проверяем чтобы точки старта и финиша не совпадали

    player.call('playerStartTruckWork', [loadPoint, destPoint]);
});


function getRandomPoint(){ // получаем случайную точку из массива pickPoints
    return pickPoints[ Math.floor( Math.random() * pickPoints.length ) ];
}
Клиентская часть (client_packages/tw/index.js)


JavaScript:
const markerType = 1; // тип маркера
const markerSize = 5; // размер маркера
const markerColor = [255, 0, 0, 100]; // цвет маркера
const blipType = 67; // тип иконки на радаре

const freezeTime = 3; // время на сколько замораживать игрока при загрузке/разгрузке, в секундах

const localPlayer = mp.players.local; // локальный игрок

let loadPoint = false; // точка загрузки
let destPoint = false; // точка выгрузки

let workMarker = false; // маркер
let workMarkerColshape = false; // колшейп
let workBlip = false; // иконка на радаре

let missionStatus = 0; // Статус миссии: 0 - не начато, 1 - идем к точке загрзки, 2 - едем к точке разгрузки

mp.events.add('playerStartTruckWork', (startPoint, finishPoint)=> { // запуск миссии

    if( missionStatus !== 0){
        return mp.gui.chat.push("ОШИБКА: Вы уже начали работу Дальнобойщика!");
    }

    if ( !checkPlayerInVehicleWithTrailer() ) return false;

    // запонимаем точки старта и назначения
    loadPoint = startPoint;
    destPoint = finishPoint;

    setMarker(startPoint);
    missionStatus = 1;

    mp.gui.chat.push("Вы начали работу Дальнобойщика!");
});

mp.events.add('playerEnterColshape', (colshape) => { // попадание игрока в колшейп
    if( colshape == workMarkerColshape){ // проверяем что это наш колшейп
        pickLocation();
    }
});


function pickLocation(){ // игрок наехал на маркер
   
    if ( !checkPlayerInVehicleWithTrailer() ) return false;

    clearMarker();
    freezePlayer();

    if( missionStatus == 1){
        playerReachLoadingPoint(); // загружаем груз
    } else if ( missionStatus == 2){
        playerReachDestPoint(); // выгружаем груз
    }

}

function playerReachLoadingPoint(){ // игрок доехал до точки загрузки
    mp.gui.chat.push("Вы прибыли на место загрузки. Ожидайте...");

    setTimeout( () => {
        unfreezePlayer();
        mp.gui.chat.push("Отправляйтесь к месту разгрузки");
        missionStatus = 2;
        setMarker(destPoint);
    }, freezeTime * 1000);
}

function playerReachDestPoint(){ // игрок доехал до точки разгрузки
    mp.gui.chat.push("Вы прибыли на место разгрузки. Ожидайте...");
   
    setTimeout( () => {
        unfreezePlayer();
        mp.gui.chat.push("Груз доставлен. Спасибо за работу!");
        missionStatus = 0;
    }, freezeTime * 1000);
}


function setMarker(point){ // ставим маркер в точку point
    workMarker = mp.markers.new(markerType, point, markerSize, { color: markerColor});
    workMarkerColshape = mp.colshapes.newSphere(point.x, point.y, point.z, markerSize);
    workBlip = mp.blips.new(blipType, point, {shorRange: false});
    workBlip.setRoute(true); // включаем отображение маршрута на карте
}


function clearMarker(){ // убираем маркер
    workMarker.destroy();
    workMarkerColshape.destroy();
    workBlip.setRoute(false);
    workBlip.destroy();
}

function freezePlayer(){
    localPlayer.vehicle.freezePosition(true);
}

function unfreezePlayer(){
    localPlayer.vehicle.freezePosition(false);
}


function checkPlayerInVehicleWithTrailer(){ // проверяем нахождение игрока в грузовике с трейлером
    if( !localPlayer.vehicle){
        mp.gui.chat.push("ОШИБКА: Вы должны быть в транспорте!");
        return false;
    }

    if( !localPlayer.vehicle.isAttachedToTrailer() ){
        mp.gui.chat.push("ОШИБКА: У вас должен быть прицеплен трейлер!");
        return false;
    }

    return true;
}

JavaScript:
function random(max) {
    return Math.floor(Math.random() * max);
}

let loadIndex = random(pickPoints.length);
let loadPoint = pickPoints[loadIndex];

let restPickPoints = pickPoints.filter((item, index) => index !== loadIndex);

let destIndex = random(restPickPoints.length)
let destPoint = restPickPoints[destIndex];
В итоге получился полностью функциональный скрипт. Но если вы захотите использовать его на реальном сервере, то нужно будет доделать некоторые вещи самостоятельно.
  • Вознаграждение за работу. Самое простое - это давать деньги после завершения работы в playerReachDestPoint(). Пригодится Player::setMoney. Размер вознаграждения можно делать фиксированным, но интереснее будет если он будет привязан к расстоянию между точкой старта и назначения.
  • Расставить транспорт и трейлеры в нужных местах.
  • Подумать о респавне грузовиков и трейлеров когда они давно не используются.
  • Возможно поменять логику начала работы, чтобы не приходилось каждый раз прописывать команду. Например, после завершения одной работы сразу стартовать другую. Но в таком случае нужна будет команда остановить работу, чтобы игрок смог как-то закончить ее.
  • Останавливать работу при смерти игрока.
    Там в коде есть небольшая опечатка. Когда создаем blip неправильно указано название опции shortRange. Оно как бы не критично, поэтому уже не буду перезаливать ничего.

    Автор
 

Вложения

  • Like
Реакции: Piska, JJIGolem и taga