В этом уроке мы с нуля напишем работу дальнобойщика для сервера rage mp. Как обычно используем только javascript.
Для лучшего результата предлагаю параллельно с просмотром видео повторять код своими руками. Тогда лучше запомнится
Видео получилось длинным, но если сделать его коротким, то получается слишком поверхностно и многие вещи будут непонятны. Основная его цель это помочь новичкам самим начать писать свои скрипты.
Ниже приведу финальную версию кода скрипта с комментариями. Полный архив с исходным кодом скрипта можно также скачать в приложении в конце поста. Для установки скопируйте в папку сервера и подключите клиентскую часть в
Серверная часть (packages/tw/index.js)
Клиентская часть (client_packages/tw/index.js)
В итоге получился полностью функциональный скрипт. Но если вы захотите использовать его на реальном сервере, то нужно будет доделать некоторые вещи самостоятельно.
Для лучшего результата предлагаю параллельно с просмотром видео повторять код своими руками. Тогда лучше запомнится
Видео получилось длинным, но если сделать его коротким, то получается слишком поверхностно и многие вещи будут непонятны. Основная его цель это помочь новичкам самим начать писать свои скрипты.
Ниже приведу финальную версию кода скрипта с комментариями. Полный архив с исходным кодом скрипта можно также скачать в приложении в конце поста. Для установки скопируйте в папку сервера и подключите клиентскую часть в
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;
}
В итоге получился полностью функциональный скрипт. Но если вы захотите использовать его на реальном сервере, то нужно будет доделать некоторые вещи самостоятельно.
- Вознаграждение за работу. Самое простое - это давать деньги после завершения работы в
playerReachDestPoint()
. Пригодится Player::setMoney. Размер вознаграждения можно делать фиксированным, но интереснее будет если он будет привязан к расстоянию между точкой старта и назначения. - Расставить транспорт и трейлеры в нужных местах.
- Подумать о респавне грузовиков и трейлеров когда они давно не используются.
- Возможно поменять логику начала работы, чтобы не приходилось каждый раз прописывать команду. Например, после завершения одной работы сразу стартовать другую. Но в таком случае нужна будет команда остановить работу, чтобы игрок смог как-то закончить ее.
- Останавливать работу при смерти игрока.