Что нового

Мануал Система Секретных Пакетов для Rage MP

Gregor

Участник
Владелец
R-Коины
395
logo.png
В этом уроке напишем с нуля систему секретных пакетов. Подобная система есть во всех играх серии GTA. Идея простая: по карте разбросаны пикапы и когда игрок подбирает их все, то получает какую-то награду.

Видео часть с подробным описанием:

Условия:
- Нужно запоминать какие пакеты уже нашел игрок и при перезаходе их больше уже не показывать ему
- Когда игрок подбирает пакет, нужно показывать ему уведомление в котором будет указано сколько пакетов он уже нашел и сколько их всего
- Когда игрок подбирает все пакеты - выдать награду и соответствующее уведомление

Для начала нам понадобится список координат для пикапов де будут размещаться секретные пакеты. Для урока я взял 4 точки, которые находятся недалеко друг от друга.

JavaScript:
JavaScript:
const packages = [
    { x: -422.77093505859375, y: 1166.211669921875, z: 325.973876953125},
    { x: -404.05560302734375, y: 1161.9130859375, z: 325.98529052734375},
    { x: -410.40142822265625, y: 1134.956298828125, z: 325.973297119140},
    { x: -428.8808288574219, y: 1138.2325439453125, z: 325.9739685058594}
];

При входе игрока на сервер будем отправлять ему этот список:

JavaScript:
mp.events.add("playerReady", player => {
    player.call('playerInitSecretPackages', [packages]);
});

На клиентской стороне будем создавать пикапы по этому списку координат. Кроме пикапа создаем еще и колшейп.

JavaScript:
const pickupHash = 3732468094;


mp.events.add('playerInitSecretPackages', (packages)=> {
    packages.forEach((package, id) => {
        let colshape = mp.colshapes.newSphere(package.x, package.y, package.z, 1);
        colshape.secretPackageId= id;
        colshape.secretPickup = mp.game.object.createPickupRotate(pickupHash, package.x, package.y, package.z, 0, 0, 0, 512, 0, 0, true, pickupHash);
    });
});

20210108124516_1.jpg

Благодаря наличию колшейпов мы можем определять когда игрок подбирает пикап.
Примечание: Возможно для этого есть более простой способ и без колшейпа, но я честно его не нашел. По логике должен быть event когда игрок подбирает пикап, но на вики ничего нет.

JavaScript:
mp.events.add("playerEnterColshape", (colshape) => {
    if(colshape.secretPickup){
        mp.events.callRemote('playerCollectedPackage', colshape.secretPackageId ); // отправляем id пакета на сервер
        mp.game.object.removePickup(colshape.secretPickup);
        colshape.destroy();
    }
});

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

JavaScript:
var fs = require('fs'); // подключим модуль для работы с файлами

В папке packages/secret-packages создадим папку data. В ней мы будем сохранять в файлах список id найденных пакетов для каждого игрока в отдельном файле. Название файла должно быть уникально и как-то связанно с игроком, чтобы при повторном заходе мы могли его найти и правильно определить. В этом уроке для простоты мы будем использовать ник игрока, но в реальном проекте советую использовать что-то другое, например, серийный номер клиента.
В самом файле мы будем хранить массив с id в виде JSON строки.

JavaScript:
mp.events.add("playerReady", player => {


    fs.readFile( __dirname + `/data/${player.name}.txt`, function(err,data){ // загружаем список найденный пакетов для игрока
        let collectedPackages = new Array();


        if(!err){
            collectedPackages = JSON.parse(data);
        }
        // если файла нет или возникла другая ошибка то collectedPackages будет просто пустым массивом


        player.packagesCollected = collectedPackages;


        let playerPackages = new Array(); // в этот массив запишем все координаты которые игрок еще не нашел


        packages.forEach((package, packageId) => {
            if (player.packagesCollected.indexOf(packageId) == -1){
                package.id = packageId // обязательно добавляем к координатам порядковый id пакета в массиве packages, т. к. в playerPackages порядок координат будет другой
                playerPackages.push(package);
            }
        });


        player.call('playerInitSecretPackages', [playerPackages]);


    });
});

Когда формируем массив playerPackages, то в него не попадут уже найденные ранее игроком координаты. Соответственно в самом playerPackages нумерация координат будет отличаться от исходной в packages. Когда мы сохраняем список id найденных игроком, то они соответствуют порядковым номерам в массиве packages. Поэтому чтобы с клиента нам приходили верные id - мы добавляем к координатам еще и id.
package.id = packageId

Клиентский код тоже немного модифицируем, чтобы учитывать наличие id в самом объекте с координатами.

JavaScript:
mp.events.add('playerInitSecretPackages', (packages)=> {
    packages.forEach((package) => {
        let colshape = mp.colshapes.newSphere(package.x, package.y, package.z, 1);
        colshape.secretPackageId= package.id;
        colshape.secretPickup = mp.game.object.createPickupRotate(pickupHash, package.x, package.y, package.z, 0, 0, 0, 512, 0, 0, true, pickupHash);
    });
});

Когда игрок подбирает пикам мы будем добавлять его в список найденных и сохранять его сразу в файл на сервере.

JavaScript:
mp.events.add("playerCollectedPackage", (player, packageId) => {
    player.packagesCollected.push(packageId);
    playerStorePackagesData(player);
    console.log(`${player.name} collected secret package id: ${packageId}`);
});




function playerStorePackagesData(player){
    fs.writeFile(__dirname + `/data/${player.name}.txt`, JSON.stringify(player.packagesCollected), () => {});
}

На клиент обратно будем слать событие с подтверждением. В нем мы отправим число - сколько всего пакетов и сколько из них нашел игрок

JavaScript:
mp.events.add("playerCollectedPackage", (player, packageId) => {
    ...
    
    player.call('playerSecretPackageInfo', [packages.length, player.packagesCollected.length]);
});

Для того чтобы показывать красивые уведомления мы будем использовать библиотеку scaleform_messages

JavaScript:
mp.events.add('playerSecretPackageInfo', (totalPackages, collectedPackages)=> {
    let title = "Секретный пакет найден";
    if(collectedPackages == totalPackages){
        title = "Вы нашли все Секретные пакеты";
    }


    mp.events.call("ShowShardMessage", title, `Найдено пакетов: ${collectedPackages}/${totalPackages} `);
});

2.jpg

Также на серверной стороне мы будем выдавать какую-то награду когда игрок найдет все секретные пакеты. В нашем случае это будет оружиме миниган :)

JavaScript:
mp.events.add("playerCollectedPackage", (player, packageId) => {
    ...


    if( player.packagesCollected.length == packages.length){
        playerCollectAllPackages(player);
    }
});




function playerCollectAllPackages(player){
    console.log(`${player.name} collected all secret packages`);
    player.giveWeapon(mp.joaat('weapon_minigun'), 10000);
}

3.jpg


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

Автор: Lev Angel

 
установил и собрал все пакеты норм но приза нету никакого и сообщения что все собрал тоже нет
 
Я вот новичок и я ниче не понял куда и что вставлять.
 
Назад
Верх