Доступ к готовым решениям

Переход в группу "Пользователь"

300.00
Одноразовый платёж
Быстрый переход в группу "Пользователи", без надобности написания постов и ожидания.

Покупка дает возможность:
Быть полноправным участником форума
Нормальное копирование кода
Создавать темы
Скачивать файлы
Доступ к архиву Pawno-Info

Рабочая и dependency-free система промокодов (SQLite)

oxygenium

Изучающий
Professional
Пользователь
Регистрация
5 Ноя 2013
Сообщения
957
Лучшие ответы
18
Репутация
445
Награды
3
Доброго времени суток. Вы наверное уже видели тему с системой промокодов. Создана она была давно, код кривой и в целом никто не может заставить ее работать. Представляю Вам свою систему. Она написана без использования зависимостей, даже таких идиотских как SCM, SPD, и обычных плагинов и инклудов (sscanf) и прочее. Это означает то, что Вы можете вшить ее в свой мод без головной боли. И так как это готовое решение, а не мануал - подробно расписывать что и как работает я не буду. Система использует SQLite для хранения промокодов, Вам не нужно подключать базы данных и что-либо настраивать - все работает из коробки и автономно. И так, начнем.

Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!
Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!
Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!
Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!


Чтобы видеть скрытое содержание Зарегистрируйтесь на форуме!


Для начала в начало мода впишем #define

C-like:
#define PLAYER_DATA_DONATE                    gPlayerData[playerid][gPlayerDonate]        // Переменная с очками доната
#define PLAYER_DATA_MONEY                    gPlayerData[playerid][gPlayerMoney]            // Переменная с деньгами
#define PLAYER_DATA_EXP                        gPlayerData[playerid][gPlayerExp]            // Переменная с опытом
#define PLAYER_DATA_ADMIN                    gPlayerData[playerid][gPlayerAdmin]            // Переменная с уровнем админки
            
#define NEEDED_ADMIN_LEVEL                    10                                            // Необходимый уровень для создания промокода

#define MAX_DONATE                            1000                                        // Максимальное количество доната
#define MAX_MONEY                            500000                                        // Максимальное количество денег
#define MAX_EXP                              10                                            // Максимальное количество exp

#define DIALOG_ID_CREATE_PROMO_CODE            10000
#define DIALOG_ID_CREATE_PROMO_DONATE        10001
#define DIALOG_ID_CREATE_PROMO_MONEY        10002
#define DIALOG_ID_CREATE_PROMO_EXP            10003
#define DIALOG_ID_CREATE_PROMO_INPUT        10004
#define DIALOG_ID_DELETE_PROMO_CODE            10005
Максимальные значения меняйте на свое усмотрение, а так же замените названия переменных с донатом, деньгами, exp и админкой на свои. Это единственное, что Вам нужно поменять.

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

C-like:
new DB:dbHandle; // Для базы данных
new promoStatus[MAX_PLAYERS]; // Активирован ли промокод
Далее в OnGameModeInit Вам необходимо подключить базу данных и инициализировать ее. Таблица и база данных создается автоматически при первом запуске.

C-like:
    if((dbHandle = db_open("promo.db")) == DB:0) print("Не удалось найти базу данных с промокодами");
    else
    {
        print("Инициализация промокодов...");
        db_free_result(db_query(dbHandle, "CREATE TABLE IF NOT EXISTS `promos` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, \
            `code` TEXT, \
            `donate` INTEGER, \
            `money` INTEGER, \
            `exp` INTEGER, \
            `status` INTEGER DEFAULT 1)"
        ));
        print("Промокоды инициализированны");
    }
В OnGameModeExit добавим отключение от бд

C-like:
if(dbHandle) db_close(dbHandle);
Далее - команды. Тут представлены на стандартном командном движке, переделать под свой - дело одной минуты.

C-like:
    if (strcmp("/createpromo", cmdtext, true) == 0)
    {
        if(PLAYER_DATA_ADMIN < NEEDED_ADMIN_LEVEL)
            return SendClientMessage(playerid, -1, "Вам необходим определенный уровень администрирования для создания промокодов");
        ShowPlayerDialog(playerid, DIALOG_ID_CREATE_PROMO_CODE, DIALOG_STYLE_INPUT, "Создание промокода", "Введите промокод:", "Далее", "Отмена");
        return 1;
    }
    if (strcmp("/deletepromo", cmdtext, true) == 0)
    {
        if(PLAYER_DATA_ADMIN < NEEDED_ADMIN_LEVEL)
            return SendClientMessage(playerid, -1, "Вам необходим определенный уровень администрирования для удаления промокодов");
        ShowPlayerDialog(playerid, DIALOG_ID_DELETE_PROMO_CODE, DIALOG_STYLE_INPUT, "Удаление промокода", "Введите промокод:", "Далее", "Отмена");
        return 1;
    }
    if (strcmp("/usepromo", cmdtext, true) == 0)
    {
        if(promoStatus[playerid]) return SendClientMessage(playerid, -1, "Вы уже активировали промокод");
        ShowPlayerDialog(playerid, DIALOG_ID_CREATE_PROMO_INPUT, DIALOG_STYLE_INPUT, "Активация промокода", "Введите промокод:", "Активировать", "Отмена");
        return 1;
    }
/createpromo, /deletepromo - создать и удалить промокод (только для админов)
/usepromo - ввести промокод

В OnDialogResponse добавляем диалоги и на этом все

C-like:
    switch(dialogid)
    {
        case DIALOG_ID_CREATE_PROMO_CODE:
        {
            // Проверка на пустой inputtext (баг SA:MP)
            if(strlen(inputtext) == 39 && strval(inputtext) == 0)
                return ShowPlayerDialog(playerid, DIALOG_ID_CREATE_PROMO_CODE, DIALOG_STYLE_INPUT, "Создание промокода", "Введите промокод:", "Далее", "Отмена");

            if(strlen(inputtext) > 32)
                return     ShowPlayerDialog(playerid, DIALOG_ID_CREATE_PROMO_CODE, DIALOG_STYLE_INPUT,
                        "Создание промокода", "Введите промокод (макс. 32 символа):", "Далее", "Отмена");

            new query[49 + 32];
            format(query, sizeof query, "SELECT * FROM `promos` WHERE `code` = '%q'", inputtext);

            new DBResult:dbResult;
            dbResult = db_query(dbHandle, query);

            if(db_num_rows(dbResult)) return SendClientMessage(playerid, -1, "Такой промокод уже существует");

            SetPVarString(playerid, "promoCodeCode", inputtext); // Запишем промокод

            ShowPlayerDialog(playerid, DIALOG_ID_CREATE_PROMO_DONATE, DIALOG_STYLE_INPUT, "Создание промокода",
                "Введите количество донат-очков\nкоторое будет выдано игроку", "Далее", "Отмена");
        }
        case DIALOG_ID_CREATE_PROMO_DONATE:
        {
            // Проверка на пустой inputtext (баг SA:MP)
            if(strlen(inputtext) == 39 && strval(inputtext) == 0)
                return ShowPlayerDialog(playerid, DIALOG_ID_CREATE_PROMO_DONATE, DIALOG_STYLE_INPUT, "Создание промокода",
                "Введите количество донат-очков\nкоторое будет выдано игроку", "Далее", "Отмена");

            new donateMoneyCount = strval(inputtext);

            if(donateMoneyCount < 1 || donateMoneyCount > MAX_DONATE)
            {
                new maxDonateCountMessage[53 + 12];
                format(maxDonateCountMessage, sizeof maxDonateCountMessage, "Вы превысили максимальное количество донат-очков (%i)", MAX_DONATE);
                return ShowPlayerDialog(playerid, DIALOG_ID_CREATE_PROMO_DONATE, DIALOG_STYLE_INPUT, "Создание промокода",
                maxDonateCountMessage, "Далее", "Отмена");
            }

            SetPVarInt(playerid, "promoCodeDonate", donateMoneyCount);
            ShowPlayerDialog(playerid, DIALOG_ID_CREATE_PROMO_MONEY, DIALOG_STYLE_INPUT, "Создание промокода",
                "Введите количество денег\nкоторое будет выдано игроку", "Далее", "Отмена");
        }
        case DIALOG_ID_CREATE_PROMO_MONEY:
        {
            // Проверка на пустой inputtext (баг SA:MP)
            if(strlen(inputtext) == 39 && strval(inputtext) == 0)
                return ShowPlayerDialog(playerid, DIALOG_ID_CREATE_PROMO_MONEY, DIALOG_STYLE_INPUT, "Создание промокода",
                "Введите количество денег\nкоторое будет выдано игроку", "Далее", "Отмена");

            new moneyCount = strval(inputtext);

            if(moneyCount < 1 || moneyCount > MAX_MONEY)
            {
                new maxMoneyMessage[47 + 12];
                format(maxMoneyMessage, sizeof maxMoneyMessage, "Вы превысили максимальное количество денег (%i)", MAX_MONEY);
                return ShowPlayerDialog(playerid, DIALOG_ID_CREATE_PROMO_MONEY, DIALOG_STYLE_INPUT, "Создание промокода", maxMoneyMessage, "Далее", "Отмена");
            }

            SetPVarInt(playerid, "promoCodeMoney", moneyCount);
            ShowPlayerDialog(playerid, DIALOG_ID_CREATE_PROMO_EXP, DIALOG_STYLE_INPUT, "Создание промокода",
                "Введите количество exp\nкоторое будет выдано игроку", "Далее", "Отмена");
        }
        case DIALOG_ID_CREATE_PROMO_EXP:
        {
            // Проверка на пустой inputtext (баг SA:MP)
            if(strlen(inputtext) == 39 && strval(inputtext) == 0)
                return ShowPlayerDialog(playerid, DIALOG_ID_CREATE_PROMO_EXP, DIALOG_STYLE_INPUT, "Создание промокода",
                "Введите количество exp\nкоторое будет выдано игроку", "Далее", "Отмена");

            new expCount = strval(inputtext);


            if(expCount < 1 || expCount > MAX_EXP)
            {
                new maxExpMessage[45 + 8];
                format(maxExpMessage, sizeof maxExpMessage, "Вы превысили максимальное количество exp (%i)", MAX_EXP);
                return ShowPlayerDialog(playerid, DIALOG_ID_CREATE_PROMO_EXP, DIALOG_STYLE_INPUT, "Создание промокода", maxExpMessage, "Далее", "Отмена");
            }

            new promoCode[32 + 1];
            GetPVarString(playerid, "promoCodeCode", promoCode, sizeof promoCode);

            new donateCount = GetPVarInt(playerid, "promoCodeDonate");
            new moneyCount = GetPVarInt(playerid, "promoCodeMoney");

            DeletePVar(playerid, "promoCodeCode");
            DeletePVar(playerid, "promoCodeDonate");
            DeletePVar(playerid, "promoCodeMoney");

            new query[81 + 32 + 12 + 12 + 8];
            format(query, sizeof query, "INSERT INTO `promos` (`code`, `donate`, `money`, `exp`) VALUES ('%q', %i, %i, %i)",
                promoCode,
                donateCount,
                moneyCount,
                expCount
            );

            db_free_result(db_query(dbHandle, query));
        }
        case DIALOG_ID_CREATE_PROMO_INPUT:
        {
            // Проверка на пустой inputtext (баг SA:MP)
            if(strlen(inputtext) == 39 && strval(inputtext) == 0)
                return ShowPlayerDialog(playerid, DIALOG_ID_CREATE_PROMO_INPUT, DIALOG_STYLE_INPUT, "Активация промокода", "Введите промокод:", "Активировать", "Отмена");
            if(strlen(inputtext) > 32)
                return     ShowPlayerDialog(playerid, DIALOG_ID_CREATE_PROMO_INPUT, DIALOG_STYLE_INPUT, "Активация промокода",
                        "Введите промокод (макс. 32 символа):", "Активировать", "Отмена");

            new query[49 + 32];
            format(query, sizeof query, "SELECT * FROM `promos` WHERE `code` = '%q'", inputtext);

            new DBResult:dbResult;
            dbResult = db_query(dbHandle, query);

            if(db_num_rows(dbResult))
            {
                new promoCodeStatus = db_get_field_assoc_int(dbResult, "status");
                if(!promoCodeStatus) return SendClientMessage(playerid, -1, "Промокод не действителен");

                promoStatus[playerid] = 1; // Не забываем сохранить в Вашей бд

                new donateCount, moneyCount, expCount;
                donateCount = db_get_field_assoc_int(dbResult, "donate");
                moneyCount = db_get_field_assoc_int(dbResult, "money");
                expCount = db_get_field_assoc_int(dbResult, "exp");

                PLAYER_DATA_DONATE += donateCount;
                PLAYER_DATA_MONEY += moneyCount;
                PLAYER_DATA_EXP += expCount;

                new message[60 + 12 + 12 + 8];
                format(message, sizeof message, "За активацию промокода вы получаете %i доната, $%i и %i exp!", donateCount, moneyCount, expCount);
                SendClientMessage(playerid, -1, message);
            }
            else SendClientMessage(playerid, -1, "Промокод не найден");
            db_free_result(dbResult);
        }
        case DIALOG_ID_DELETE_PROMO_CODE:
        {
            // Проверка на пустой inputtext (баг SA:MP)
            if(strlen(inputtext) == 39 && strval(inputtext) == 0)
                return ShowPlayerDialog(playerid, DIALOG_ID_DELETE_PROMO_CODE, DIALOG_STYLE_INPUT, "Удаление промокода", "Введите промокод:", "Далее", "Отмена");

            new query[49 + 32];
            format(query, sizeof query, "SELECT * FROM `promos` WHERE `code` = '%q'", inputtext);

            new DBResult:dbResult;
            dbResult = db_query(dbHandle, query);

            if(db_num_rows(dbResult))
            {
                new promoCodeStatus = db_get_field_assoc_int(dbResult, "status");
                if(!promoCodeStatus) return SendClientMessage(playerid, -1, "Промокод уже не действителен");
                new updateQuery[50 + 32];
                format(updateQuery, sizeof updateQuery, "UPDATE `promos` SET status = 0 WHERE `code` = '%q'", inputtext);
                db_free_result(db_query(dbHandle, updateQuery));
                SendClientMessage(playerid, -1, "Промокод удален");
            }
            else SendClientMessage(playerid, -1, "Промокод не найден");
            db_free_result(dbResult);       
        }   
    }
Мод с уже вшитой системой:
 
Сверху Снизу