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

Сообщения
704
Реакции
475
Помог
10 раз(а)
Нумерация объектов для их дальнейшей идентификации
Например, когда объекты нужно запихнуть в дин.массив для дальнейшей работы с этими объектами. В течении времени, после того как мы поместили объект в пул, с ним может произойти все что угодно. Поэтому в этом случае объекты лучше проиндексировать. Здесь я использую iuser4 для метки.

PHP:
#include <amxmodx>
#include <reapi>

new g_iKeyCounter = 1; // счетчик для нумерации объектов

public plugin_init() {
    RegisterHookChain(RH_ED_Alloc, "fw_Edict_Alloc", true);
    RegisterHookChain(RH_ED_Free, "fw_Edict_Free", false);
}

// удаление объекта
public fw_Edict_Free(iEnt)
{
    server_print("Remove entity(free) %d (%s) | iKey = %d", iEnt, !is_nullent(iEnt) ? "valid" : "invalid", get_entvar(iEnt, var_iuser4));
}

// Выделение памяти под объект, все еще невалидный
public fw_Edict_Alloc()
{
    new iEnt =  GetHookChainReturn(ATYPE_INTEGER);
    server_print("Created entity %d (%s)", iEnt, !is_nullent(iEnt) ? "valid" : "invalid");

    RequestFrame("@fw_NextFrame_CreateEntity", iEnt);
}
// на следующем кадре сервера проверяем что объект валидный и ставим ему метку
@fw_NextFrame_CreateEntity(iEnt)
{
    // Нумеруем объект, чтобы использовать номер как идентификатор
    if (!is_nullent(iEnt)) {
        new szClassName[32];
        get_entvar(iEnt, var_classname, szClassName, 31);
        server_print("Check entity %d [%s] | iKey = %d", iEnt, szClassName, g_iKeyCounter);

        set_entvar(iEnt, var_iuser4, g_iKeyCounter);
        g_iKeyCounter++;
    }
}
В следующем плагине используем нашу метку для идентификации
Код:
#include <amxmodx>
#include <reapi>
#include <fakemeta>

enum aArrData {
    aArrData_pIndex,
    aArrData_pOwner,
    aArrData_iKey
}

new Array:g_aArrayData;

public plugin_init()
{
    g_aArrayData = ArrayCreate(aArrData);
}

public RemoveHat(id) {
    new pHat;
    if (is_user_alive(id)) {
        pHat = FindUserHat(id);

        if (!is_nullent(pHat)) {
            set_entvar(pHat, var_flags, FL_KILLME);
        }
    }
}

public CreateHat(id)
{
    new pHat;

    if (is_user_alive(id)) {

        pHat = rg_create_entity("info_target");

        if (!is_nullent(pHat)) {
            set_entvar(pHat, var_classname, "hats");

            engfunc(EngFunc_SetModel, pHat, "models/p_ak47.mdl");
            set_entvar(pHat, var_owner, id);
            set_entvar(pHat, var_aiment, id);
            set_entvar(pHat, var_movetype, MOVETYPE_FOLLOW);

            new szData[aArrData];

            szData[aArrData_pIndex] = pHat;
            szData[aArrData_iKey] = get_entvar(pHat, var_iuser4);
            szData[aArrData_pOwner] = get_entvar(pHat, var_owner);

            ArrayPushArray(g_aArrayData, szData);
        }
    }
}

stock FindUserHat(id)
{
    for (new i, szData[aArrData], pIndex; i<ArraySize(g_aArrayData); i++) {
        ArrayGetArray(g_aArrayData, i, szData);

        pIndex = szData[aArrData_pIndex];

        // Если данные объекта из массива не совпадают с самим объектом, тогда очищаем этот элемент [это говорит о том, что объект подчищен или изменен]
        if (is_nullent(pIndex) || get_entvar(pIndex, var_owner) != szData[aArrData_pOwner] || szData[aArrData_iKey] != get_entvar(pIndex, var_iuser4)) {
            ArrayDeleteItem(g_aArrayData, i--);
            continue;
        }

        if (szData[aArrData_pOwner] == id) {
            return pIndex;
        }
    }

    return FM_NULLENT;
}
В боевом варианте с этим же примером, этот пул шапок можно копировать на фейковые модели игрока (плагины DanceMenu и т.д.), дабы отображать шапочки и на фейках.
 
Сообщения
704
Реакции
475
Помог
10 раз(а)
я бы вообще посоветовал не юзать пев'ы, так как в геймлибе они юзаются без разбора что и где - можно запросто сломать что-то и не понять что
по-хорошему сделать нужно в amxx модулях по дефолту вот это
 
Сообщения
704
Реакции
475
Помог
10 раз(а)
Про это говно нестабильное я знаю уже давно. Лучше аналог ищите.
аналог самому писать надо
про стабильность в курсе, последний пост темы - чел апдейтил неофф
 
Сообщения
91
Реакции
141
Помог
1 раз(а)
Нужен был код, чтобы повернуть вектор в другую сторону в зависимости от угла, долго мучаясь, нашел код в сурсах half life

Код преобразует угол в матрицу (3x4)
C-like:
#define PITCH        0 // up / down
#define YAW            1 // left / right
#define ROLL        2 // fall over

stock UTIL_AngleMatrix(const Float: angles[3], Float: matrix[3][4])
{
    new Float: angle;
    new Float: sr, Float: sp, Float: sy, Float: cr, Float: cp, Float: cy;

    angle = angles[YAW] * (M_PI * 2.0 / 360.0);
    sy = floatsin(angle);
    cy = floatcos(angle);
    angle = angles[PITCH] * (M_PI * 2.0 / 360.0);
    sp = floatsin(angle);
    cp = floatcos(angle);
    angle = angles[ROLL] * (M_PI * 2.0 / 360.0);
    sr = floatsin(angle);
    cr = floatcos(angle);

    // matrix = (YAW * PITCH) * ROLL
    matrix[0][0] = cp * cy;
    matrix[1][0] = cp * sy;
    matrix[2][0] = -sp;
    matrix[0][1] = sr * sp * cy + cr * -sy;
    matrix[1][1] = sr * sp * sy + cr * cy;
    matrix[2][1] = sr * cp;
    matrix[0][2] = (cr * sp * cy + -sr * -sy);
    matrix[1][2] = (cr * sp * sy + -sr * cy);
    matrix[2][2] = cr * cp;
    matrix[0][3] = 0.0;
    matrix[1][3] = 0.0;
    matrix[2][3] = 0.0;
}
Код поворота вектора
C-like:
stock UTIL_VectorRotate(const Float: in1[3], const Float: in2[3][4], Float: out[3])
{
    out[0] = xs_vec_dot(in1, in2[0]);
    out[1] = xs_vec_dot(in1, in2[1]);
    out[2] = xs_vec_dot(in1, in2[2]);
}
 

Albertio

скриптизёр
Сообщения
336
Реакции
393
Предупреждения
5
Помог
7 раз(а)
Пример, как восстановить здоровье без костылей с таском. Есть минус, нельзя указать, как быстро будет восстанавливаться здоровье.
Код:
#include <amxmodx>
#include <reapi>

public plugin_init()
{
    register_plugin("Restoring Health", "0.0.1", "Albertio");

    RegisterHookChain(RG_CBasePlayer_TakeDamage, "CBasePlayer_TakeDamage_Post", true);
}

public CBasePlayer_TakeDamage_Post(const iVictim, iInflictor, iAttacker, Float:flDamage, bitsDamageType)
{
    if(bitsDamageType & DMG_DROWN)
        return HC_CONTINUE;

    if(is_user_alive(iVictim))
    {
        set_member(iVictim, m_idrowndmg, get_member(iVictim, m_idrowndmg) - get_member(iVictim, m_idrownrestored) + floatround(flDamage));
        set_member(iVictim, m_idrownrestored, 0);
    }

    return HC_CONTINUE;
}
Можно восстановить здоровье только для некоторых типов урона.
Код:
#define DMG_GENERIC                     0           // Generic damage was done
#define DMG_CRUSH                       (1<<0)      // Crushed by falling or moving object
#define DMG_BULLET                      (1<<1)      // Shot
#define DMG_SLASH                       (1<<2)      // Cut, clawed, stabbed
#define DMG_BURN                        (1<<3)      // Heat burned
#define DMG_FREEZE                      (1<<4)      // Frozen
#define DMG_FALL                        (1<<5)      // Fell too far
#define DMG_BLAST                       (1<<6)      // Explosive blast damage
#define DMG_CLUB                        (1<<7)      // Crowbar, punch, headbutt
#define DMG_SHOCK                       (1<<8)      // Electric shock
#define DMG_SONIC                       (1<<9)      // Sound pulse shockwave
#define DMG_ENERGYBEAM                  (1<<10)     // Laser or other high energy beam
#define DMG_NEVERGIB                    (1<<12)     // With this bit OR'd in, no damage type will be able to gib victims upon death
#define DMG_ALWAYSGIB                   (1<<13)     // With this bit OR'd in, any damage type can be made to gib victims upon death.
#define DMG_DROWN                       (1<<14)     // Drowning
#define DMG_PARALYZE                    (1<<15)     // Slows affected creature down
#define DMG_NERVEGAS                    (1<<16)     // Nerve toxins, very bad
#define DMG_POISON                      (1<<17)     // Blood poisioning
#define DMG_RADIATION                   (1<<18)     // Radiation exposure
#define DMG_DROWNRECOVER                (1<<19)     // Drowning recovery
#define DMG_ACID                        (1<<20)     // Toxic chemicals or acid burns
#define DMG_SLOWBURN                    (1<<21)     // In an oven
#define DMG_SLOWFREEZE                  (1<<22)     // In a subzero freezer
#define DMG_MORTAR                      (1<<23)     // Hit by air raid (done to distinguish grenade from mortar)
#define DMG_GRENADE                     (1<<24)     // Counter-Strike only - Hit by HE grenade
#define DMG_TIMEBASED                   (~(0x3fff)) // Mask for time-based damage
 
Сообщения
203
Реакции
324
Помог
3 раз(а)
Есть минус, нельзя указать, как быстро будет восстанавливаться здоровье.
Не говоря уже об этом, твой вариант выглядит бОольшим костылем, чем вариант с таском/синком. Вдруг там под водой будет что-то не так работать, или резко DMG_PARALYZE пропадет. Мало контроля, вероятность сайд-эффектов, зачем это все? Чтобы производительность повысить, не создавая таски?
 
Сообщения
2,720
Реакции
2,997
Помог
60 раз(а)
Albertio, твой метод напомнил это: https://github.com/alliedmodders/am...6/plugins/include/fakemeta_util.inc#L255-L276

C++:
stock fm_fakedamage(victim, const classname[], Float:takedmgdamage, damagetype) {
    new class[] = "trigger_hurt";
    new entity = fm_create_entity(class);
    if (!entity)
        return 0;

    new value[16];
    float_to_str(takedmgdamage * 2, value, sizeof value - 1);
    fm_set_kvd(entity, "dmg", value, class);

    num_to_str(damagetype, value, sizeof value - 1);
    fm_set_kvd(entity, "damagetype", value, class);

    fm_set_kvd(entity, "origin", "8192 8192 8192", class);
    fm_DispatchSpawn(entity);

    set_pev(entity, pev_classname, classname);
    fm_fake_touch(entity, victim);
    fm_remove_entity(entity);

    return 1;
}
 
Сообщения
1,016
Реакции
818
Помог
10 раз(а)
Было немного скучно, может фигню наделал ))

Код:
/* substr_count - Возвращает число вхождений подстроки в строке */
stock substr_count(const string[], const substr[], const bool:ignorecase = false, start = 0, const end = 0) {
    new count;
    
    while ((start = strfind(string, substr, ignorecase, start)) != -1) {
        if (end > 0 && start > end) {
            break;
        }
        
        ++start;
        ++count;
    }
    
    return count;
}
Код:
/* strpos — Возвращает позицию первого вхождения подстроки в строке */
stock strpos(const string[], const substr[], const bool:ignorecase = false, start = 0, const end = 0) {
    new pos = strfind(string, substr, ignorecase, start);
    
    if (end > 0 && pos > end) {
        pos = -1;
    }
    
    return pos;
}
Код:
/* strrpos — Возвращает позицию последнего вхождения подстроки в строке */
stock strrpos(const string[], const substr[], const bool:ignorecase = false, start = 0, const end = 0) {
    new pos = -1;
    
    while ((start = strfind(string, substr, ignorecase, start)) != -1) {
        if (end > 0 && start > end) {
            break;
        }
        
        pos = start;
        ++start;
    }
    
    return pos;
}
Код:
/* str_contains — Определяет, содержит ли строка заданную подстроку */
stock bool:str_contains(const string[], const substr[], const bool:ignorecase = false, start = 0, const end = 0) {
    new pos = strfind(string, substr, ignorecase, start);
    
    if (pos == -1 || end > 0 && pos > end) {
        return false;
    }
    
    return true;
}
Код:
/* str_ends_with — Проверяет, заканчивается ли строка заданной подстрокой */
stock bool:str_ends_with(const string[], const substr[], const bool:ignorecase = false) {
    new pos = strlen(string) - strlen(substr);
    
    if (strcmp(string[pos], substr, ignorecase) == 0) {
        return true;
    }
    
    return false;
}
Код:
/* str_starts_with — Проверяет, начинается ли строка с заданной подстроки */
stock bool:str_starts_with(const string[], const substr[], const bool:ignorecase = false) {
    if (strncmp(string, substr, strlen(substr), ignorecase) == 0) {
        return true;
    }
    
    return false;
}
 
Сообщения
936
Реакции
186
Помог
4 раз(а)
Javekson, А грамотный strtotime сделать?
А то мой вариант с расчетами не оч работает
 
Сообщения
936
Реакции
186
Помог
4 раз(а)
Javekson, А он грамотно работает при получении секунд из бд?
 
Сообщения
1,016
Реакции
818
Помог
10 раз(а)
BiZaJe, смотря какую задачу преследуешь, а так все нормально работало у меня) в другой теме пиши лучше) а то варны получим)
 
Сообщения
1,016
Реакции
818
Помог
10 раз(а)
Перемешивает элементы или часть элементов массива в случайном порядке методом тасование Фишера - Йетса
Код:
stock shuffle(array[], const size, const start = 0, end = 0) {
    end = end > 0 ? end - 1 : size - 1;
    
    for (new i = start, rnd = 0; i < end; ++i) {
        while((rnd = i + random_num(start, end - i)) == i) {}
        
        array[i] ^= array[rnd];
        array[rnd] ^= array[i];
        array[i] ^= array[rnd];
    }
}
Пример:
Код:
new array[] = {1, 2, 3, 4, 5, 6, 7};
shuffle(array, sizeof(array));

Результат: 3 5 2 1 7 4 6
Код:
new array[] = {1, 2, 3, 4, 5, 6, 7};
shuffle(array, sizeof(array), 2, 4);

Результат: 1 2 5 4 3 6 7
Код:
new string[] = "privetik";
shuffle(string, charsmax(string));

Результат: ivpkreti
Код:
new string[] = "privetik";
shuffle(string, charsmax(string), 2, 4);

Результат: previtik
 

RockTheStreet

Саппорт года
Сообщения
1,743
Реакции
346
Помог
40 раз(а)
Обратите внимание, если вы хотите заключить сделку с этим пользователем, он заблокирован
Javekson, А вот это я заберу себе. Спасибо, самому лень было делать.
 
Сообщения
1,495
Реакции
1,496
Помог
2 раз(а)
Javekson,
С Арреями мне сразу вспомнился вариант рандома

К примеру - получение случайной модели из боди
Код:
    entity_set_model(ent, items_wc)
    {
        new array[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
        set_pev(ent, pev_body, array[random(sizeof(array))]);
    }
 
Сообщения
192
Реакции
148
Помог
1 раз(а)
Lerp
Код:
#define UTIL_LerpArray(%0,%1,%2,%3)                    for ( new i; i < min( sizeof %0, sizeof %1 ); i++ ) %3[ i ] = UTIL_Lerp( %3[ i ], %1[ i ], %2 )

stock Float: UTIL_Lerp( Float: flA, Float: flB, const Float: flT )
    return ( flA + ( flB - flA ) * floatclamp( flT, 0.0, 1.0 ) );
 
Сообщения
192
Реакции
148
Помог
1 раз(а)
Деление целых чисел с остатком.(Просто для своего удобства)
#define mod(%0,%1) ( %0 % %1 )
Деление вещественных чисел с остатком.
Код:
stock Float: fmod( Float: flNumerator, Float: flDenominator )
{
    if ( flDenominator == 0.0 )
        set_fail_state( "Trying to divide by 0" );

    return flNumerator - ( floatround( flNumerator / flDenominator, floatround_tozero ) * flDenominator );
}
 
Последнее редактирование:

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

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