JS Аренда скутеров

Всем привет! Сегодня мы напишем скрипт аренды транспорта для сервера Rage MP. В нашем случае это будет аренда скутеров. Скрипт будет полностью серверный.
Аренда.png

Сам процесс подготовки и написания кода вы можете посмотреть в записи моего стрима. Там больше размышлений и более подробно можно отследить ход мыслей в процессе создания этого скрипта.


Для начал выберем места где можно будет взять транспорт в аренду.
JavaScript:
const rentPoints = [
    {x: -1048.4658203125, y: -2548.270263671875, z: 12.954665184020996},
    {x: -1043.396728515625, y: -2539.602294921875, z: 12.954659461975098},
];

На каждой из указанных точек мы поставим маркер и напишем 3Д текст "Аренда транспорта".

JavaScript:
mp.events.add('packagesLoaded', () =>
{
    rentPoints.forEach( createRentPoint );
    console.log('Аренда скутеров загружена');
});

function createRentPoint(point){
    const markerSize = 2;
    mp.markers.new(1, point, markerSize);
    mp.labels.new("Аренда скутеров", {x: point.x, y: point.y, z: point.z + 1}, {los: true, font: 1, drawDistance: 100,});
}

rent.png

Чтобы при входе в маркеры аренды у нас срабатывало начало аренды мы добавим еще колшейп.
JavaScript:
function createRentPoint(point){
    const markerSize = 2;
    mp.markers.new(1, point, markerSize);
    mp.labels.new("Аренда скутеров", {x: point.x, y: point.y, z: point.z + 1}, {los: true, font: 1, drawDistance: 100,});
    const colshape = mp.colshapes.newSphere(point.x, point.y, point.z, markerSize);
    colshape.isRent = true;
}

Для колшейпа мы задаем свойство isRent, чтобы его можно было отличить от других колшейпов которые могут быть на сервере.
JavaScript:
mp.events.add('playerEnterColshape', (player, colshape) => {
    if( colshape.isRent){
        playerRentStart(player);
    }
});

Функция playerRentStart будет выдавать игроку арендный транспорт и делать все необходимые проверки. Например, если игрок уже имеет активную аренду, то больше транспорта мы ему не будем выдавать.
JavaScript:
function playerRentStart(player){
    if(player.rentVehicle) return player.outputChatBox("ОШИБКА: У Вас уже есть арендованный транспорт");

    const vehicle = mp.vehicles.new(mp.joaat("faggio"), player.position);
    player.rentVehicle = vehicle;
}

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

JavaScript:
const rentTime = 50; // seconds

function playerRentStart(player){
    // ...
    vehicle.playerId = player.id;
    vehicle.rentSeconds = rentTime;
}

Почему именно так? Мы будем отслеживать аренду не по игрокам, а по арендованному транспорту. Для этого создадим массив в котором будем хранить все арендованные скутеры.

JavaScript:
const rentVehicles = [];

При начале аренды мы помещаем туда наш объект и потом сможет легко работать с ним.
JavaScript:
function playerRentStart(player){
    // ...
    rentVehicles.push(vehicle);
}

Теперь нам осталось создать таймер в котором мы будем пробегать по всем арендованным скутерам и находить те, у которых закончилось время аренды.
JavaScript:
mp.events.add('packagesLoaded', () =>
{
    // ...
    setInterval( rentCheck, 1000);
});

function rentCheck(){
    rentVehicles.forEach( (vehicle, index) => {
        vehicle.rentSeconds = vehicle.rentSeconds - 1; // Отнимаем 1 секунду от времени аренды
        if(vehicle.rentSeconds < 1){ // Если время вышло, то заканчиваем аренду
            vehicleRentStop(vehicle);
            rentVehicles.splice(index, 1); // удаляем из массива этот транспорт
        }
    });
}

Сама функция vehicleRentStop будет выполнять два действия:
1. Физически удалять транспорт.
2. Уведомлять игрока об окончании аренды и убирать у него свойство rentVehicle, чтобы он смог снова арендовать транспорт.

JavaScript:
function vehicleRentStop(vehicle){
    const { playerId } = vehicle;
    vehicle.destroy();

    let player = mp.players.at(playerId);
    player.rentVehicle = false;
    player.outputChatBox("Срок аренды закончился. Транспорт доставлен на стоянку.");
}

Здесь есть один нюанс. Ко времени окончания аренды игрок мог уже выйти с сервере. Поэтому в свойствах машины мы храним его player.id, а не ссылку на сам объект player. Т. к. проще проверить есть ли игрок онлайн по его id. Сам объект player к этому времени становится просроченным и это приводит к ошибке. Короче нам нужно проверить что игрок все еще есть на сервере и если нет, то никого уведомлять не нужно.
JavaScript:
function vehicleRentStop(vehicle){
    const { playerId } = vehicle;
    vehicle.destroy();

    if( mp.players.exists(playerId) ){
        let player = mp.players.at(playerId);
        player.rentVehicle = false;
        player.outputChatBox("Срок аренды закончился. Транспорт доставлен на стоянку.");
    }
}

На этом все. Мы получили работоспособную систему аренды, которую можно развивать дальше.

1622010092560.png

Примечания:
1. За время пока закончилась аренда конечно од этим ID мог зайти другой игрок. И ему придет уведомление. Это не правильно. Возможно нужно отслеживать выход игрока с сервера и принудительно завершать аренду.
2. Аренда полностью бесплатна. Поскольку в rage mp нет стандартного api для работы с деньгами и скорее всего в каждом моде оно будет сделано по своему. Поэтому в туториале и нет упоминания денег. При необходимости это можно легко добавить. В функции playerRentStart нужно будет проверять наличие необходимой суммы и снимать деньги.
 
Яндекс.Метрика
Верх