Склад полезного кода [GoldSrc]

Сообщения
243
Реакции
74
Предупреждения
8
Помог
1 раз(а)
Парсинг значений для hud (жёсткое, без any).
Код:
stock UTIL_ReadHudSettings(szHud[], &iRed = 255, &iGreen = 255, &iBlue = 255, &Float: x = 0.01, &Float: y = 0.3, &effects,
    &Float: flFxTime, &Float: flHoldTime, &Float: flFadeInTime, &Float: flFadeOut)
{
    new iStart, iEnd;
    iRed = strtol(szHud, iEnd); iStart += iEnd;
    iGreen = strtol(szHud[iStart], iEnd); iStart += iEnd;
    iBlue = strtol(szHud[iStart], iEnd); iStart += iEnd;
    x = strtof(szHud[iStart], iEnd); iStart += iEnd;
    y = strtof(szHud[iStart], iEnd); iStart += iEnd;
    effects = strtol(szHud[iStart], iEnd); iStart += iEnd;
    flFxTime = strtof(szHud[iStart], iEnd); iStart += iEnd;
    flHoldTime = strtof(szHud[iStart], iEnd); iStart += iEnd;
    flFadeInTime = strtof(szHud[iStart], iEnd); iStart += iEnd;
    flFadeOut = strtof(szHud[iStart]);
}
Код:
szHud[] = "255 255 255 0.01 0.3 0 0.0 2.0 0.1 0.2"
new iRed, iGreen, iBlue, Float: x, Float: y, effects, Float: flFxTime, Float: flHoldTime, Float: flFadeInTime, Float: flFadeOut;
UTIL_ReadHudSettings(szHud, iRed, iGreen, iBlue, x, y, effects, flFxTime, flHoldTime, flFadeInTime, flFadeOut);
set_hudmessage(iRed, iGreen, iBlue, x, y, effects, flFxTime, flHoldTime, flFadeInTime, flFadeOut, -1);

Проверка на время в указанном промежутке (unix).
(Не знаю, если ли здесь)
Код:
stock bool: UTIL_IsTimeWithin(iStart, iEnd)
{
    new iSysTime = get_systime();

    if (!(iEnd <= iSysTime <= iStart))
    {
        return true;
    }

    return false;
}

Сравнение 2-х бит флагов. Получает строковую разницу. Возращает бит флаг разницы.
Код:
stock UTIL_GetOtherFlags(bitFlagsOne, bitFlagsTwo, szOther[])
{
    bitFlagsTwo &= ~bitFlagsOne;
    get_flags(bitFlagsTwo, szOther, 31);
    return bitFlagsTwo;
}
Код:
new szOther[32];
set_user_flags(iPlayer, "alm");
new bitFlags = UTIL_GetOtherFlags(get_user_flags(iPlayer), read_flags("abit"), szOther);
// szOther == "bit"
// bitFlags == read_flags("bit")

Являются ли группа флагов игнором (Если перед флагами стоит точка, то проверяется каждый флаг, иначе наличия хотя бы одного из них. Разделение групп через пробел).
Код:
stock bool: UTIL_IsIgnorFlags(bitFlags, szIgnor[])
{
    new iPos, szFlags[32];

    while (iPos != -1)
    {
        iPos = argparse(szIgnor, iPos, szFlags, charsmax(szFlags));
      
        if (replace(szFlags, charsmax(szFlags), ".", ""))
        {
            if (bitFlags == (bitFlags | read_flags(szFlags))) return true;
        }
        else
        {
            if (bitFlags & read_flags(szFlags)) return true;
        }
    }

    return false;
}
Код:
UTIL_IsIgnorFlags(read_flags("abit"), ".am t"); // Вернёт true т.к. есть флаг 't'
UTIL_IsIgnorFlags(read_flags("abit"), "z .at"); // Вернёт true т.к. есть и флаг 'a', и флаг 't'
UTIL_IsIgnorFlags(read_flags("abit"), ".am");    // Вернёт false т.к. есть только флаг 'a'
UTIL_IsIgnorFlags(read_flags("abit"), "z lf .am vt"); // Вернёт true т.к. есть флаг 't'
 
Последнее редактирование:
  • Нравится
Реакции: uMk0
Сообщения
39
Реакции
7
Флуд
Обратите внимание, если вы хотите заключить сделку с этим пользователем, он заблокирован
Сообщения
2,713
Реакции
2,993
Помог
59 раз(а)
Following the example from https://docs.unity3d.com/ScriptReference/
C++:
/**
 * Linearly interpolates between two values.
 *
 * Linearly interpolates between a and b by t.
 * When t = 0 returns a.
 * When t = 1 return b.
 * When t = 0.5 returns the midpoint of a and b.
 *
 * @param a         Start value, returned when t = 0.
 * @param b         End value, returned when t = 1.
 * @param t         Value used to interpolate between a and b.
 *
 * @return          The interpolated float result between the two float values.
 */
stock Float: _xs_lerp(const Float: a, const Float: b, const Float: t) {
    return a + (b - a) * t;
}

/**
 * Determines where a value lies between two points.
 * The a and b values define the start and end of a linear numeric range.
 * The "value" parameter you supply represents a value which might lie somewhere within that range.
 * This method calculates where, within the specified range, the "value" parameter falls.
 * If the "value" parameter is within the range, _xs_inverse_lerp() returns a value between zero and one,
 * proportional to the value's position within the range.
 * If the "value" parameter falls outside of the range, _xs_inverse_lerp() returns either zero or one,
 * depending on whether it falls before the start of the range or after the end of the range.
 *
 * @param a         The a of the range.
 * @param b         The b of the range.
 * @param t         The point within the range you want to calculate.
 *
 * @return          A value between zero and one,
 *                  representing where the "value" parameter
 *                  falls within the range defined by `a` and `b`.
 */
stock Float: _xs_inverse_lerp(const Float: a, const Float: b, const Float: value) {
    return (value - a) / (b - a)
}

/**
 * Linearly interpolates between two vectors.
 *
 * @param a         Start value, returned when t = 0.
 * @param b         End value, returned when t = 1.
 * @param out       The output vector. Can be one of the input vectors.
 * @param t         Value used to interpolate between a and b.
 *
 * @noreturn
 */
stock _xs_vec_lerp(Float: a[], Float: b[], Float: out[], const Float: t, const size = sizeof(out)) {
    for (new i; i < size; i++) {
        out[i] = a[i] + (b[i] - a[i]) * t;
    }
}

/**
 * Linearly interpolates between two angles.
 * This method returns the shortest path between the specified angles.
 * This method wraps around values that are outside the range [-180, 180].
 * For example, _xs_vec_lerp_angle(1.0, 190.0, 1.0) returns -170.0.
 * To find the longest path use xs_lerp().
 *
 * @param a         The a angle. A float expressed in degrees.
 * @param b         The b angle. A float expressed in degrees.
 * @param t         Value used to interpolate between a and b.
 *
 * @return          Returns the interpolated float result between angle `a` and angle `b`,
 *                  based on the interpolation value `t`.
 */
stock Float: _xs_vec_lerp_angle(Float: a, Float: b, const Float: t) {
    while (a < -180.0)
        a += 360.0;
    while (a > 180.0)
        a -= 360.0;

    while (b < -180.0)
        b += 360.0;
    while (b > 180.0)
        b -= 360.0;

    new Float: angleDiff = b - a;

    if (angleDiff > 180.0)
        angleDiff -= 360.0;
    else if (angleDiff < -180.0)
        angleDiff += 360.0;

    new Float: result = a + t * angleDiff;

    while (result < -180.0)
        result += 360.0;
    while (result > 180.0)
        result -= 360.0;

    return result;
}

/**
 * Converts a vector represented as an array of floats to a formatted string.
 *
 * @param vec       The vector represented as an array of floats.
 * @param output    The output string where the formatted vector will be stored.
 * @param len       The maximum length of the output string.
 * @param precision The number of decimal places for each vector component.
 * @param size      The size of the vector array.
 *
 * @return          Returns the number of characters written to the output string.
 *                  It is the length of the formatted vector string.
 */
stock _xs_vec_to_string(const Float: vec[], output[], const len, const precision = 1, const size = sizeof(vec)) {
    new _len = copy(output, len, "(");

    for (new i = 0; i < size && _len < len; ++i) {
        _len += format(output[_len], (len - _len),
            fmt("%%.%if%s", precision, (i < size - 1) ? ", " : ")"),
            vec[i]
        );
    }

    return _len;
}

stock const XS_X = 0;
stock const XS_Y = 1;
stock const XS_Z = 2;
using _xs_vec_to_string() sample:
1695695077241.png
 
Последнее редактирование:
Сообщения
874
Реакции
49
Помог
10 раз(а)
Не знаю пригодится кому такое, но всёже. Получаем рандомное не повторяющее число из массива. Повторение чисел будет, но после того когда все числа перебраты
Код:
/*
* With this function, you can get a non-repeating random number
*
* @param iNumbers - Array of numbers
* @param iNonRepeatNum - He resulting number
*
* @return Will return true - if there was a coincidence, false - if there were no coincidencesNumber of cells written to buffer
*/

stock bool:non_repeatable_random(const iNumbers[], &iNonRepeatNum) {
    static
        iAction,
        iBuffer[32],
        iSizeNumbers;

    if(!iSizeNumbers)
        iSizeNumbers = strlen(iNumbers)

    new
        bool:bReplay,
        iRandomNum = iNumbers[random(iSizeNumbers)];

    for(new i; i <= iSizeNumbers; ++i) {
        if(iBuffer[i] == iRandomNum)
            bReplay = true;
    }

    if(!bReplay) {
        iNonRepeatNum = iBuffer[iAction] = iRandomNum;

        if(iAction++ == iSizeNumbers -1) {
            iAction = 0;
            arrayset(iBuffer, 0, iSizeNumbers);
        }

        return bReplay;
    }

    non_repeatable_random(iNumbers, iNonRepeatNum);
    return bReplay;
}
Не большой пример использования
Код:
#include <amxmodx>
#include <reapi>

public plugin_init() {
    register_plugin("Non Repeat Random Number", "rz 0.1", "(: [C][O][D][E] x");

    RegisterHookChain(RG_CBasePlayer_Spawn, "CBasePlayer_Spawn", 1);
}

public CBasePlayer_Spawn(const id) {
    if(!is_user_alive(id))
        return;

    new
        iNumbers[] = {4, 7, 19, 1, 2},
        iNonRepeatNum;

    non_repeatable_random(iNumbers, iNonRepeatNum);
    server_print("****** %i", iNonRepeatNum);
}

stock bool:non_repeatable_random(const iNumbers[], &iNonRepeatNum) {
    static
        iAction,
        iBuffer[32],
        iSizeNumbers;

    if(!iSizeNumbers)
        iSizeNumbers = strlen(iNumbers)

    new
        bool:bReplay,
        iRandomNum = iNumbers[random(iSizeNumbers)];

    for(new i; i <= iSizeNumbers; ++i) {
        if(iBuffer[i] == iRandomNum)
            bReplay = true;
    }

    if(!bReplay) {
        iNonRepeatNum = iBuffer[iAction] = iRandomNum;

        if(iAction++ == iSizeNumbers -1) {
            iAction = 0;
            arrayset(iBuffer, 0, iSizeNumbers);
        }

        return bReplay;
    }

    non_repeatable_random(iNumbers, iNonRepeatNum);
    return bReplay;
}
 
Последнее редактирование модератором:
Сообщения
874
Реакции
49
Помог
10 раз(а)
Получаем количество русских и английских букв из строки.
Пример:
Код:
/*
* With this funktion we will get the number of Russian and English letters in the string
*
* @param szLine - The string being checked
* @param szBuffer - Array to write
* @param LenBuffer - Array size
*
* @return Will return true - Returns nothing
*/

stock get_count_letter(const szLine[], szBuffer[], const LenBuffer) {
    new
        En,
        Rus,
        Len = strlen(szLine);

    for(new i; i < Len; ++i) {
        if('A' <= szLine[i] <= 'Z' || 'a' <= szLine[i] <= 'z') {
            ++En;
            continue;
        }

        if(szLine[i] > 'z')
            ++Rus;
    }

    Rus = Rus/2;

    formatex(szBuffer, LenBuffer, "RUS - %i, EN - %i", Rus, En);
}
Не большой пример использования
Код:
#include <amxmodx>

public plugin_init() {
    register_plugin("Count letter", "rz 0.1", "(: [C][O][D][E] x");

    new szBuffer[191];
    get_count_letter("(: [C][O][D][E] x это и есть Виталик", szBuffer, charsmax(szBuffer));

    server_print("**** %s", szBuffer);
}

stock get_count_letter(const szLine[], szBuffer[], const LenBuffer) {
    new
        En,
        Rus,
        Len = strlen(szLine);

    for(new i; i < Len; ++i) {
        if('A' <= szLine[i] <= 'Z' || 'a' <= szLine[i] <= 'z') {
            ++En;
            continue;
        }

        if(szLine[i] > 'z')
            ++Rus;
    }

    Rus = Rus/2;

    formatex(szBuffer, LenBuffer, "RUS - %i, EN - %i", Rus, En);
}
 
Последнее редактирование модератором:
Сообщения
161
Реакции
67
Предупреждения
1
В основном это для работы с IP-адресами (uint)... Но я использую и для запаковки STEAM_ID и других значений в nvault.

Код:
#define ACS_MAX_BASIS               64
#define ACS_MAX_INT_STR_LENGTH      12

stock acs_str_to_num(const str[], const basis = 10) {
    if (basis > 1 && basis <= ACS_MAX_BASIS) {
        for (new num, i_i; str[i_i]; i_i++)
            if (basis > 36 && str[i_i] >= 'a' && str[i_i] < ('a' + 28))
                num = num * basis + (str[i_i] - 'a' + 36);
            else if (basis > 10 && str[i_i] >= 'A' && str[i_i] < ('A' + 26))
                num = num * basis + (str[i_i] - 'A' + 10);
            else if (str[i_i] >= '0' && str[i_i] < ('0' + basis))
                num = num * basis + (str[i_i] - '0');
            else {
                //log_acs(ACS_LOG_DEBUG, "[ACS] acs_num_to_str(), string %s has over basis symbol %c (!!!!! ERROR !!!!!)", str, str{i_i});
                num = 0;
                break;
            }
    }/* else
        log_acs("[ACS] acs_str_to_num(), basis error: %d", basis); */
    return num;
}

stock acs_num_to_str(const num, const basis = 10, const null_text[] = "") {
    new i_i, i_num = num, i_div, s_str[ACS_MAX_INT_STR_LENGTH];
    if (basis > 1 && basis <= ACS_MAX_BASIS) {
        while (i_num != 0 && i_i < ACS_MAX_INT_STR_LENGTH) {
            i_div = i_num % basis;
            if (i_num < 0) {
                i_num = (basis & 0x1) ? (floatround((2.0 * float(0x40000000) + float(i_num & 0x7FFFFFFF)) / float(basis), floatround_floor)) : ((i_num >>> 1) / (basis >> 1));
            } else {
                i_num /= basis;
            }
            s_str[i_i] = (i_div >= 36) ? ('a' + i_div - 36) : (i_div >= 10) ? ('A' + i_div - 10) : ('0' + i_div);
            i_i++;
        }
        if (i_i >= ACS_MAX_INT_STR_LENGTH)
            i_i = 0;
        s_str[i_i] = 0;
        if (i_i)
            acs_reverse_str(s_str, i_i);
        else if (null_text[0])
            copy(s_str, charsmax(s_str), null_text);
        // CHECK
        //log_acs(ACS_LOG_DEBUG, "[ACS] acs_num_to_str(), original num = %u, basis = %d, txt = %s, verify = %u", num, basis, s_str, acs_str_to_num(s_str, basis));
    }/* else
        log_acs("[ACS] acs_str_to_num(), basis %d (!!!!! ERROR !!!!!)", basis); */
    return s_str;
}

stock acs_reverse_str(str[], const str_len = 0) {
    new i_end = str_len ? str_len : strlen(str);
    for (new i_i, s_tmp; i_i < i_end >> 1; i_i++) {
        s_tmp = str[i_i];
        str[i_i] = str[(i_end - i_i - 1)];
        str[(i_end - i_i - 1)] = s_tmp;
    }
}

stock acs_pack_steam(const authid[]) {
    new s_s[3][ACS_MAX_INT_STR_LENGTH], s_tmp[MAX_AUTHID_LENGTH];
    if (strlen(authid) > 7) {
        strtok(authid[6], s_s[0], charsmax(s_s[]), s_tmp, charsmax(s_tmp), ':', 0);
        strtok(s_tmp, s_s[1], charsmax(s_s[]), s_s[2], charsmax(s_s[]), ':', 0);
        formatex(s_tmp, MAX_AUTHID_LENGTH, "%s:%s:%s", s_s[0], s_s[1], acs_num_to_str(acs_str_to_num(s_s[2]), ACS_MAX_BASIS, s_s[2]));
    }
    return s_tmp;
}
1 Дек 2023
Буферизированный вариант логов для отладки (примерно в 12 раз быстрее классического open/close):

Код:
stock log_acs(const message[], any:...) {
    static _PLUGIN_NAME[32];
    static _LOGPATH[PLATFORM_MAX_PATH];
    static s_log_data[1024];
    // FILL SYSTEM INFO
    if (!_PLUGIN_NAME[0]) {
        get_plugin(-1, _PLUGIN_NAME, charsmax(_PLUGIN_NAME));
        replace(_PLUGIN_NAME, charsmax(_PLUGIN_NAME), ".amxx", "");
    }
    if (!_LOGPATH[0]) {
        get_localinfo("amxx_logs", _LOGPATH, charsmax(_LOGPATH));
        format(_LOGPATH, charsmax(_LOGPATH), "%s/%s.log", _LOGPATH, _PLUGIN_NAME);
    }
    vformat(s_log_data, charsmax(s_log_data), message, 2);
    acs_log_to_file(_LOGPATH, s_log_data, true);
}

stock acs_log_to_file(const filename[], const message[], const bool:is_buffered = false) {
    static _MOD_NAME[32];
    static _AMXX_VERSION[32];
    static h_file, bool:b_file_exists, s_date[32];
    if (filename[0] && message[0]) {
        if (!_MOD_NAME[0])
            get_modname(_MOD_NAME, charsmax(_MOD_NAME));
        if (!_AMXX_VERSION[0])
            get_amxx_verstring(_AMXX_VERSION, charsmax(_AMXX_VERSION));
        format_time(s_date, charsmax(s_date), "%m/%d/%Y - %H:%M:%S");
        b_file_exists = h_file ? true : bool:file_exists(filename);
        if (!h_file)
            h_file = fopen(filename, "at");
        if (h_file) {
            if (!b_file_exists)
                fprintf(h_file, "L %s: Log file started (file ^"%s^") (game ^"%s^") (amx ^"%s^")^n", s_date, filename, _MOD_NAME, _AMXX_VERSION);
            fprintf(h_file, "L %s: %s^n", s_date, message);
        } else
            log_error(AMX_ERR_GENERAL, "[ACS] ERROR: acs_log_to_file(), can't open file %s", filename);
    }
    // WRITE BUFFER TO DISK
    if (h_file && !is_buffered) {
        fclose(h_file);
        h_file = 0;
    }
}

/*
public plugin_end() {
    // SAVE BUFFERED LOG DATA
    acs_log_to_file("", "");
}
*/
 
Последнее редактирование:
Сообщения
57
Реакции
5
Предупреждения
8
Начальная стадия кода - Play Music in Server (YandexMusic)

Код:
Веб-приложение на Node.js:

const express = require('express');
const axios = require('axios');
const bodyParser = require('body-parser');

const app = express();
app.use(bodyParser.json());

const YA_MUSIC_API_URL = 'https://api.music.yandex.net';

// Обработка запроса на управление воспроизведением
app.post('/play', async (req, res) => {
    const trackId = req.body.trackId;
    try {
        const response = await axios.post(${YA_MUSIC_API_URL}/tracks/${trackId}/play, null, {
        headers: {
            Authorization: 'Bearer YOUR_ACCESS_TOKEN',
        },
    });
    res.json({ message: 'Трек начал воспроизводиться' });
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

app.listen(3000, () => {
    console.log('Сервер запущен на порту 3000');
});
Код:
Плагин на AMXX:

#define WEB_REQUEST_URL "http://your-web-app-url.com"

public PlayTrack(client, const trackId[])
{
    new url[256];
    format(url, sizeof(url), "%s/play", WEB_REQUEST_URL);
    new result[512];
    new post_data[256];

    format(post_data, sizeof(post_data), "trackId=%s", trackId);
    if (http_post(url, post_data, result, sizeof(result)))
    {
    // Обработка ответа от веб-приложения
        client_print(client, print_chat, result);
    } else {
        client_print(client, print_chat, "Ошибка при выполнении запроса");
    }
}
В этой начальной стадии куска кода, сделан скрипт веб-приложения на Node.js который принимает POST-запросы на /play для управления воспроизведением музыки с использованием API Яндекс.Музыки.
В другую очередь, плагин на AMXX отправляет запросы на веб-приложение для управления воспроизведением треков.

Не забудьте заменить YOUR_ACCESS_TOKEN на ваш реальный токен доступа к API Яндекс.Музыки и http://your-web-app-url.com на реальный URL вашего веб-приложения.

p.s может кому-нибудь под дальнейшую разработку понадобиться, строго за структуру кода не губите меня)
 
Сообщения
451
Реакции
254
Помог
9 раз(а)
press2p, axios -> fetch, исключает необходимость установки доп библиотеки.
если вы хотите воспроизводить музыку на сервер, удобнее будет юзать ytdl для скачки музыки, на жс сервере у вас получится что-то вроде ftp сервера откуда можно будет скачать файл с помощью easyhttp, но помимо скачки на сервер, нужно еще и клиенту это прекешить. В целом удобнее просто скачать что нужно, обрезать как нужно, а так-же изменять битрейт и канал.
 

Albertio

скриптизёр
Сообщения
336
Реакции
392
Предупреждения
5
Помог
7 раз(а)
Функция SumStringNums позволяет складывать большие и отрицательные целые числа в строках. Нет пределов числа от -2147483647 до 2147483647.
Спасибо the_hunter
Код:
// Функция складывает большие и отрицательные целые числа в строках
stock SumStringNums(const szFirstNum[], const szSecondNum[], szResult[]) {
    szResult[0] = EOS;

    if(szFirstNum[0] == EOS || szSecondNum[0] == EOS)
        return 0;

    new iFirstNumLen = strlen(szFirstNum);
    new iSecondNumLen = strlen(szSecondNum);
    new bool:bFirstNumNegative = (szFirstNum[0] == '-');
    new bool:bSecondNumNegative = (szSecondNum[0] == '-');
    new iLargerNum = CompareNumStringsWithoutMinusSign(szFirstNum, szSecondNum);
    new iCarryOver, iFirstDigit, iSecondDigit, szSumDigits[4];

    for(new i = (iFirstNumLen - 1), j = (iSecondNumLen - 1), k;
    ((i >= 0) || (j >= 0) || (iCarryOver && !bFirstNumNegative && !bSecondNumNegative));
    i--, j--, k++) {
        if(((j <= 0) && (szFirstNum[i] == '-')) || ((i <= 0) && (szSecondNum[j] == '-'))) {
            szResult[k] = '-';
            break;
        }

        iFirstDigit = (i >= 0 && szFirstNum[i] != '-') ? szFirstNum[i] - '0' : 0;
        iSecondDigit = (j >= 0 && szSecondNum[j] != '-') ? szSecondNum[j] - '0' : 0;

        iCarryOver = szSumDigits[1] != EOS ? (szSumDigits[0] - '0') : 0;

        if(iCarryOver && ((bFirstNumNegative && iFirstDigit && !iSecondDigit) || (bSecondNumNegative && !iFirstDigit && iSecondDigit))) {
            k--;
            continue;
        }

        if((!bFirstNumNegative && !bSecondNumNegative) || (bFirstNumNegative && bSecondNumNegative))
            AddStringDigits(iFirstDigit, iSecondDigit, iCarryOver, szSumDigits);
        else if(bFirstNumNegative || bSecondNumNegative)
            SubtractStringDigits(iFirstDigit, iSecondDigit, iCarryOver, szSumDigits, iLargerNum);

        szResult[k] = (szSumDigits[1] != EOS) ? szSumDigits[1] : szSumDigits[0];
    }

    new iResLen = strlen(szResult);

    if((szResult[iResLen - 1] == '-') && (szResult[iResLen - 2] == '0')) {
        szResult[0] = '0';
        szResult[1] = EOS;

        return 1;
    }

    if(szResult[iResLen - 1] == '0')
        szResult[iResLen - 1] = EOS;

    return ReverseString(szResult);
}

// Функция записывает сумму чисел в строку
stock AddStringDigits(iFirstDigit, iSecondDigit, iCarryOver, szSumDigits[4]) {
    num_to_str(iFirstDigit + iSecondDigit + iCarryOver, szSumDigits, charsmax(szSumDigits));
}

// Функция записывает разницу чисел в строку
stock SubtractStringDigits(iFirstDigit, iSecondDigit, iCarryOver, szSumDigits[4], iLargerNum) {
    if(iLargerNum <= 0)
        num_to_str(iFirstDigit - iSecondDigit - iCarryOver + (((iFirstDigit - iSecondDigit - iCarryOver) < 0) ? 20 : 0),
        szSumDigits, charsmax(szSumDigits));
    else
        num_to_str(iSecondDigit - iFirstDigit - iCarryOver + (((iSecondDigit - iFirstDigit - iCarryOver) < 0) ? 20 : 0),
        szSumDigits, charsmax(szSumDigits));
}

// Функция сравнивает две числовые строки без знака минус
stock CompareNumStringsWithoutMinusSign(const szFirstNum[], const szSecondNum[]) {
    new iFirstNumNegative = (szFirstNum[0] == '-');
    new iSecondNumNegative = (szSecondNum[0] == '-');
    new iFirstNumLen = strlen(szFirstNum) - iFirstNumNegative;
    new iSecondNumLen = strlen(szSecondNum) - iSecondNumNegative;

    if(iFirstNumLen > iSecondNumLen)
        return -1;
    else if(iFirstNumLen < iSecondNumLen)
        return 1;

    for(new i = iFirstNumNegative, j = iSecondNumNegative; i < iFirstNumLen; i++, j++) {
        if(szFirstNum[i] > szSecondNum[j])
            return -1;
        else if(szFirstNum[i] < szSecondNum[j])
            return 1;
    }

    return 0;
}

// Функция переворачивает строку
stock ReverseString(szStr[]) {
    new iLen = strlen(szStr), iHalfLen = iLen / 2;

    for(new i, iTemp; i < iHalfLen; i++) {
        iTemp = szStr[i];
        szStr[i] = szStr[iLen - i - 1];
        szStr[iLen - i - 1] = iTemp;
    }

    return iLen;
}
1706815568647.png
Код:
#include <amxmodx>

new sSumNums[][][] = {
    {"-1111", "777"},
    {"777", "-1111"},
    {"99999", "1"},
    {"1", "99999"},
    {"100000", "-1"},
    {"-1", "100000"},
    {"10000", "-10000"},
    {"-10000", "10000"},
    {"12345", "12345"},
    {"-12345", "-12345"},
    {"-12345", "12345"},
    {"12345", "-12345"},
    {"1234567890987654321", "1234567890987654321"},
    {"1234567890987654321", "12345"},
    {"-1234567890987654321", "-12345"},
    {"12345", "1234567890987654321"},
    {"-1234567890987654321", "12345"},
    {"12345", "-1234567890987654321"},
    {"1234567890987654321", "-12345"},
    {"-12345", "1234567890987654321"}
};

public plugin_init() {
    register_plugin("Test", "Albertio", "0.0.1");

    for(new i; i < sizeof(sSumNums); i++) {
        new szResult[64];
        SumStringNums(sSumNums[i][0][0], sSumNums[i][1][0], szResult);
        log_amx("%s + %s | %s", sSumNums[i][0][0], sSumNums[i][1][0], szResult);
    }
}

// Функция складывает большие и отрицательные целые числа в строках
stock SumStringNums(const szFirstNum[], const szSecondNum[], szResult[]) {
    szResult[0] = EOS;

    if(szFirstNum[0] == EOS || szSecondNum[0] == EOS)
        return 0;

    new iFirstNumLen = strlen(szFirstNum);
    new iSecondNumLen = strlen(szSecondNum);
    new bool:bFirstNumNegative = (szFirstNum[0] == '-');
    new bool:bSecondNumNegative = (szSecondNum[0] == '-');
    new iLargerNum = CompareNumStringsWithoutMinusSign(szFirstNum, szSecondNum);
    new iCarryOver, iFirstDigit, iSecondDigit, szSumDigits[4];

    for(new i = (iFirstNumLen - 1), j = (iSecondNumLen - 1), k;
    ((i >= 0) || (j >= 0) || (iCarryOver && !bFirstNumNegative && !bSecondNumNegative));
    i--, j--, k++) {
        if(((j <= 0) && (szFirstNum[i] == '-')) || ((i <= 0) && (szSecondNum[j] == '-'))) {
            szResult[k] = '-';
            break;
        }

        iFirstDigit = (i >= 0 && szFirstNum[i] != '-') ? szFirstNum[i] - '0' : 0;
        iSecondDigit = (j >= 0 && szSecondNum[j] != '-') ? szSecondNum[j] - '0' : 0;

        iCarryOver = szSumDigits[1] != EOS ? (szSumDigits[0] - '0') : 0;

        if(iCarryOver && ((bFirstNumNegative && iFirstDigit && !iSecondDigit) || (bSecondNumNegative && !iFirstDigit && iSecondDigit))) {
            k--;
            continue;
        }

        if((!bFirstNumNegative && !bSecondNumNegative) || (bFirstNumNegative && bSecondNumNegative))
            AddStringDigits(iFirstDigit, iSecondDigit, iCarryOver, szSumDigits);
        else if(bFirstNumNegative || bSecondNumNegative)
            SubtractStringDigits(iFirstDigit, iSecondDigit, iCarryOver, szSumDigits, iLargerNum);

        szResult[k] = (szSumDigits[1] != EOS) ? szSumDigits[1] : szSumDigits[0];
    }

    new iResLen = strlen(szResult);

    if((szResult[iResLen - 1] == '-') && (szResult[iResLen - 2] == '0')) {
        szResult[0] = '0';
        szResult[1] = EOS;

        return 1;
    }

    if(szResult[iResLen - 1] == '0')
        szResult[iResLen - 1] = EOS;

    return ReverseString(szResult);
}

// Функция записывает сумму чисел в строку
stock AddStringDigits(iFirstDigit, iSecondDigit, iCarryOver, szSumDigits[4]) {
    num_to_str(iFirstDigit + iSecondDigit + iCarryOver, szSumDigits, charsmax(szSumDigits));
}

// Функция записывает разницу чисел в строку
stock SubtractStringDigits(iFirstDigit, iSecondDigit, iCarryOver, szSumDigits[4], iLargerNum) {
    if(iLargerNum <= 0)
        num_to_str(iFirstDigit - iSecondDigit - iCarryOver + (((iFirstDigit - iSecondDigit - iCarryOver) < 0) ? 20 : 0),
        szSumDigits, charsmax(szSumDigits));
    else
        num_to_str(iSecondDigit - iFirstDigit - iCarryOver + (((iSecondDigit - iFirstDigit - iCarryOver) < 0) ? 20 : 0),
        szSumDigits, charsmax(szSumDigits));
}

// Функция сравнивает две числовые строки без знака минус
stock CompareNumStringsWithoutMinusSign(const szFirstNum[], const szSecondNum[]) {
    new iFirstNumNegative = (szFirstNum[0] == '-');
    new iSecondNumNegative = (szSecondNum[0] == '-');
    new iFirstNumLen = strlen(szFirstNum) - iFirstNumNegative;
    new iSecondNumLen = strlen(szSecondNum) - iSecondNumNegative;

    if(iFirstNumLen > iSecondNumLen)
        return -1;
    else if(iFirstNumLen < iSecondNumLen)
        return 1;

    for(new i = iFirstNumNegative, j = iSecondNumNegative; i < iFirstNumLen; i++, j++) {
        if(szFirstNum[i] > szSecondNum[j])
            return -1;
        else if(szFirstNum[i] < szSecondNum[j])
            return 1;
    }

    return 0;
}

// Функция переворачивает строку
stock ReverseString(szStr[]) {
    new iLen = strlen(szStr), iHalfLen = iLen / 2;

    for(new i, iTemp; i < iHalfLen; i++) {
        iTemp = szStr[i];
        szStr[i] = szStr[iLen - i - 1];
        szStr[iLen - i - 1] = iTemp;
    }

    return iLen;
}
 
Последнее редактирование:

Albertio

скриптизёр
Сообщения
336
Реакции
392
Предупреждения
5
Помог
7 раз(а)

Albertio

скриптизёр
Сообщения
336
Реакции
392
Предупреждения
5
Помог
7 раз(а)
Функция NumberToRoman преобразовывает целые числа в римские. Поддерживаются числа от 0 до 3999.
Код:
#include <amxmodx>

new sNums[] = {
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
    11, 21, 31, 41, 51, 71, 81, 91, 101,
    1101, 1202, 1303, 1404, 1505, 1606,
    1707, 1808, 1909, 2020, 3999
};

public plugin_init() {
    register_plugin("Test", "0.0.1", "Albertio");

    for(new i; i < sizeof(sNums); i++) {
        new szResult[12];
        NumberToRoman(sNums[i], szResult, charsmax(szResult));
        log_amx("%d -> %s", sNums[i], szResult);
    }
}

stock NumberToRoman(const iNumber, szResult[], iResLen) {
    if(iNumber < 0 || iNumber > 3999)
        return 0;

    if(iNumber == 0) {
        szResult[0] = 'N';
        return 1;
    }

    static const iValues[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
    static const sNumerals[][] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};

    for(new i, iLen, iNum = iNumber; i < 13; i++) {
        while(iNum >= iValues[i]) {
            iNum -= iValues[i];
            iLen += formatex(szResult[iLen], iResLen - iLen, "%s", sNumerals[i]);
        }
    }

    return strlen(szResult);
}
1708683856055.png
 

Пользователи, просматривающие эту тему

Сейчас на форуме нет ни одного пользователя.
Сверху Снизу