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

Сообщения
443
Реакции
319
Помог
13 раз(а)
Кстати. Наверное многие некоторые я и Mistrick замечали что иногда пишешь правильный код с timer'ом в menu, а меню не исчезает, так вот. Это вот тоже можно исправить.
 
Сообщения
443
Реакции
319
Помог
13 раз(а)
При разработке плагина столкнулись (уже не впервые) с проблемами не своевременной доставки сообщений на клиент (десинхронизация).

1584625607900.png

Правильнее конечно перехватывать всё это в netchan, но и так должно работать.
Правильное закрытие меню вызывающееся несколько раз (например меню с отсчетом, отсылающееся клиенту на основе set_task):

Код:
public menuh(id, menu, item){
    if(item == MENU_EXIT||!is_user_connected(id)){
        //menu_destroy(menu)...
        return;
    }
    if(sometypeofcondition)
        //menu_destroy(menu)
        return;
    }
    // menu_item_getinfo(...)
    // menu_destroy(menu)
    switch(item){
        case ...
        case ...
        case ...
    }
 
    message_begin(MSG_ONE, SVC_NOP, {0,0,0}, id);
    message_end();

    // Оставьте то, что вам нравится, например show_menu(index,0,"",0);
    show_menu(index,0,"^n",0);
    show_menu(index,0,"^n",-1);
    show_menu(index,0,"^n",1);

    show_menu(index,0,"",0);
    show_menu(index,0,"",-1);
    show_menu(index,0,"",1);
}
Либо отсылайте через set_task 0.1-5.0 пустое меню.
 

Garey

ninjaCow
Сообщения
422
Реакции
1,056
Помог
10 раз(а)
Макрос для однотипных операций for с игроками.
Код:
#define GETPLAYERS(%1,%2,%3,%4) \
new %1[MAX_PLAYERS], %2; \
get_players_ex(%1, %2, %3, %4)

#define FORPLAYERS(%1,%2,%3,%4,%5) \
GETPLAYERS(%2,%3,%4,%5); \
for(new %1 = 0; %1 < %3; %1++)
Пример использования:
Код:
FORPLAYERS(i, iPlayers, iAliveCount, GetPlayers_ExcludeDead, "")
{
    rg_set_user_team(iPlayers[i], TEAM_CT);
}
аналогичный код без макроса:
Код:
new iPlayers[MAX_PLAYERS], iAliveCount;
get_players_ex(iPlayers, iAliveCount, GetPlayers_ExcludeDead, "")
for(new i = 0; i < iAliveCount; i++)
{
    rg_set_user_team(iPlayers[i], TEAM_CT);
}
 
Сообщения
1,698
Реакции
1,510
Помог
26 раз(а)
Garey, ещё бы перемееную под индекс игрока чтобы каждый раз не писать взятие из массива.
 
Последнее редактирование модератором:
  • Нравится
Реакции: Ayk

Garey

ninjaCow
Сообщения
422
Реакции
1,056
Помог
10 раз(а)
Nordic Warrior, Этот макрос писал года 2 назад (https://amx-x.ru/viewtopic.php?t=38746&p=304006#p304009) попросили выложить сюда. А так да практически идентичен только непонятно зачем Kaido создает пустой stock и вызывает его.
 
Последнее редактирование модератором:
Сообщения
443
Реакции
319
Помог
13 раз(а)
непонятно зачем
Там есть проблема с подобными макросами на любом языке, поэтому суют беск. цикл либо еще какую-нибудь функцию которая вызовется 1 раз.
 
Последнее редактирование модератором:
Сообщения
147
Реакции
29
  • Нравится
Реакции: Ayk
Сообщения
1,698
Реакции
1,510
Помог
26 раз(а)
jocasrb, it's def info
 
Последнее редактирование модератором:
Сообщения
147
Реакции
29
fl0wer что вы имеете в виду?
 
Последнее редактирование модератором:
Сообщения
271
Реакции
348
Помог
15 раз(а)
Функция IsLineBlockedBySmokeпроверяет пересекает ли линия облако дыма (определяет длину линии обзора покрытой каждым облаком и суммирует их - если оно переходит порог то возвращает true т.е. линия заблокирована облаком дыма)

Код:
#include <amxmodx>
#include <fakemeta>
#include <reapi>
#include <xs>

enum _:SmokeData_s
{
    SMOKE_ENTITY_ID,
    Float:SMOKE_ORIGIN[3]
};

new Array:g_aSmokes;

public plugin_init()
{
    g_aSmokes = ArrayCreate(SmokeData_s);

    register_forward(FM_Think, "Think_Post", true);
    RegisterHookChain(RG_CSGameRules_RestartRound, "CSGameRules_RestartRound_Post", true);
    RegisterHookChain(RG_CGrenade_ExplodeSmokeGrenade, "CGrenade_ExplodeSmokeGrenade_Post", true);
}

public Think_Post(iEnt)
{
    new index = FindSmokeId(iEnt);

    if (index != -1)
    {
        if (get_entvar(iEnt, var_flags) & FL_KILLME)
        {
            ArrayDeleteItem(g_aSmokes, index);
        }
    }
}

public CSGameRules_RestartRound_Post()
{
    ArrayClear(g_aSmokes);
}

public CGrenade_ExplodeSmokeGrenade_Post(const this)
{
    new eTempSmoke[SmokeData_s];

    eTempSmoke[SMOKE_ENTITY_ID] = this;
    get_entvar(this, var_origin, eTempSmoke[SMOKE_ORIGIN]);

    // https://github.com/s1lentq/ReGameDLL_CS/blob/46f697fb4697ffbbf51ac70cb8f3d41a5ae89922/regamedll/dlls/ggrenade.cpp#L578
    ArrayPushArray(g_aSmokes, eTempSmoke);
}

stock bool:IsLineBlockedBySmoke(const Float:from[3], const Float:to[3])
{
    const Float:smokeRadius = 115.0;

    new const Float:smokeRadiusSq = smokeRadius * smokeRadius;

    new Float:totalSmokedLength;

    new Float:sightDir[3];
    xs_vec_sub(to, from, sightDir);

    new Float:sightLength = NormalizeInPlace(sightDir);

    new iSize = ArraySize(g_aSmokes);

    for (new i; i < iSize; i++)
    {
        new eTempSmoke[SmokeData_s]; ArrayGetArray(g_aSmokes, i, eTempSmoke);

        new Float:smokeOrigin[3]; xs_vec_copy(eTempSmoke[SMOKE_ORIGIN], smokeOrigin);

        new Float:toGrenade[3]; xs_vec_sub(smokeOrigin, from, toGrenade);

        new Float:alongDist = DotProduct(toGrenade, sightDir);

        new Float:close[3];

        if (alongDist < 0.0)
        {
            xs_vec_copy(from, close);
        }
        else if (alongDist >= sightLength)
        {
            xs_vec_copy(to, close);
        }
        else
        {
            new Float:tempsightDir[3]; xs_vec_add_scaled(Float:{0.0, 0.0, 0.0}, sightDir, alongDist, tempsightDir);
            xs_vec_add(from, tempsightDir, close);
        }

        new Float:toClose[3]; xs_vec_sub(close, smokeOrigin, toClose);

        new Float:lengthSq = LengthSquared(toClose);

        if (lengthSq < smokeRadiusSq)
        {
            new Float:fromSq = LengthSquared(toGrenade);
            new Float:tempSq[3]; xs_vec_sub(smokeOrigin, to, tempSq);
            new Float:toSq = LengthSquared(tempSq);

            if (fromSq < smokeRadiusSq)
            {
                if (toSq < smokeRadiusSq)
                {
                    new Float:temp_totalSmokedLength[3]; xs_vec_sub(to, from, temp_totalSmokedLength);
                    totalSmokedLength += xs_vec_len(temp_totalSmokedLength);
                }
                else
                {
                    new Float:halfSmokedLength = floatsqroot(smokeRadiusSq - lengthSq);

                    new Float:temp_totalSmokedLength[3]; xs_vec_sub(close, from, temp_totalSmokedLength);

                    if (alongDist > 0.0)
                    {
                        totalSmokedLength += halfSmokedLength + xs_vec_len(temp_totalSmokedLength);
                    }
                    else
                    {
                        totalSmokedLength += halfSmokedLength - xs_vec_len(temp_totalSmokedLength);
                    }
                }
            }
            else if (toSq < smokeRadiusSq)
            {
                new Float:halfSmokedLength = floatsqroot(smokeRadiusSq - lengthSq);

                new Float:temp_totalSmokedLength[3]; xs_vec_sub(close, to, temp_totalSmokedLength);

                new Float:v[3]; xs_vec_sub(to, smokeOrigin, v);

                if (DotProduct(v, sightDir) > 0.0)
                {
                    totalSmokedLength += halfSmokedLength + xs_vec_len(temp_totalSmokedLength);
                }
                else
                {
                    totalSmokedLength += halfSmokedLength - xs_vec_len(temp_totalSmokedLength);
                }
            }
            else
            {
                new Float:smokedLength = 2.0 * floatsqroot(smokeRadiusSq - lengthSq);
                totalSmokedLength += smokedLength;
            }
        }
    }

    new const Float:maxSmokedLength = 0.7 * smokeRadius;

    return (totalSmokedLength > maxSmokedLength);
}

stock Float:NormalizeInPlace(Float:a[])
{
    new Float:flLen = xs_vec_len(a);
    if (flLen > 0)
    {
        a[0] /= flLen;
        a[1] /= flLen;
        a[2] /= flLen;
    }
    else
    {
        a[0] = 0.0;
        a[1] = 0.0;
        a[2] = 1.0;
    }
    return flLen;
}

stock Float:DotProduct(const Float:a[], const Float:b[])
{
    return (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
}

stock Float:LengthSquared(const Float:a[])
{
    return (a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
}

FindSmokeId(smoke_id)
{
    new iSize = ArraySize(g_aSmokes);

    for (new i; i < iSize; i++)
    {
        new eTempSmoke[SmokeData_s]; ArrayGetArray(g_aSmokes, i, eTempSmoke);

        if (eTempSmoke[SMOKE_ENTITY_ID] == smoke_id)
        {
            return i;
        }
    }

    return -1;
}


credits: fl0wer
 
Последнее редактирование:
Сообщения
443
Реакции
319
Помог
13 раз(а)
Будет работать так же криво как и любой другой non ray based intersect.
C++:
// SmdParentBoneMoover.cpp : Этот файл содержит функцию "main". Здесь начинается и заканчивается выполнение программы.
//
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <TCHAR.h>
#include <fstream>
#include <iomanip>
#include <windows.h>
#include <strsafe.h>

using namespace std;
struct cords {
    int bone;
    long double x, y, z, xx, yy, zz;
};
int _tmain(int argc, TCHAR *argv[]){
    setlocale(LC_ALL, "");  TCHAR* Dir = argv[1];
    TCHAR            tStr[_MAX_PATH] = { 0 }; //memset(tStr, 0, MAX_PATH * 2);
    TCHAR            tStrOut[_MAX_PATH] = { 0 }; //memset(tStr, 0, MAX_PATH * 2);
    wprintf(_T("%ws file\n"), argv[0]);
    wprintf(_T("%ws file\n"), argv[1]);

    WIN32_FIND_DATA ffd;
    TCHAR szDir[MAX_PATH] = { 0 };
    size_t length_of_arg;
    HANDLE hFind = INVALID_HANDLE_VALUE;
    HRESULT res = StringCchLength(Dir, MAX_PATH - (sizeof("*.smd") + 1), &length_of_arg);
    if (!SUCCEEDED(res)) { return NULL; }
    StringCchCopy(szDir, MAX_PATH, Dir);

    if (Dir[0])StringCchCat(szDir, MAX_PATH, _T("\\"));

    StringCchCat(szDir, MAX_PATH, _T("*.smd"));
    hFind = FindFirstFile(szDir, &ffd);
    if (INVALID_HANDLE_VALUE == hFind) return NULL;

    do {
        if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)continue;
        if (ffd.cFileName[0] == '_')break;
        if (Dir[0]) {
            _tcscat(tStr, Dir);
            _tcscat(tStr, _T("\\"));
        }
        if (Dir[0]) {
            _tcscat(tStrOut, Dir);
            _tcscat(tStrOut, _T("\\"));
        }
        _tcscat(tStr, ffd.cFileName);
        std::wifstream infile(tStr);
        _tcscat(tStrOut, _T("_")); // i don't wanna use vector for saving current file list.
        _tcscat(tStrOut, ffd.cFileName);
        wofstream file(tStrOut);
        wprintf(_T("%s file\n"), tStrOut);
        wprintf(_T("%s file\n"), tStr);
        tStr[0] = 0;
        tStrOut[0] = 0;
        wstring Current;
        vector <wstring> Output;

        cords A, B;

        wstring line;
        while (getline(infile, line)) {
            static unsigned char parsing = 0;
            size_t pos = line.find(_T("time "), 0);
            wistringstream FirstBone;
            wstringstream FirstBoneO;
            if (pos == 0) {
                //wprintf(_T("Found time on %d pos %s\n"), pos, line.c_str());
                parsing = 2;
                Output.push_back(line);
            }
            
            else if (line.find(_T("end"), 0) != -1) { parsing = 0; Output.push_back(line); }
            else if (parsing) {
                cords temp2;
                FirstBone.str(line);
                FirstBone >> temp2.bone;
                if (!temp2.bone){
                    FirstBone.str(line);
                    FirstBone >> A.bone >> fixed >> std::setprecision(6) >> A.x >> A.y >> A.z >> A.xx >> A.yy >> A.zz;
                    FirstBoneO.clear();
                    FirstBoneO << _T("  ") << A.bone << _T("   ") << _T("0.000000") << _T(" ") << _T("0.000000") << _T(" ") << _T("0.000000") << _T(" ") << _T("0.000000") << _T(" ") << _T("0.000000") << _T(" ") << _T("0.000000");
                    wstring temp = FirstBoneO.str();
                    Output.push_back(temp);
                }
                else if (temp2.bone == 1) {
                    FirstBone.str(line);
                    FirstBone >> B.bone >> fixed >> std::setprecision(6) >> B.x >> B.y >> B.z >> B.xx >> B.yy >> B.zz;
                    FirstBoneO << _T("  ") << B.bone << _T("   ") << fixed << std::setprecision(6) << B.x + A.x << _T(" ") << B.y + A.y << _T(" ") << B.z + A.z << _T(" ") << B.xx + A.xx << _T(" ") << B.yy + A.yy << _T(" ") << B.zz + A.zz;
                    wstring temp = FirstBoneO.str();
                    Output.push_back(temp);
                }
                else {
                    Output.push_back(line);
                }
            }
            else {
                Output.push_back(line);
                continue;
            }

            // process pair (a,b)
        }
        infile.close();


        for (unsigned int i = 0; i < Output.size(); i++) file << Output[i] << endl;
        file.close();

    } while (FindNextFile(hFind, &ffd) != 0);
    if (GetLastError() != ERROR_NO_MORE_FILES);
    FindClose(hFind);

    //file.close();
}
 
Последнее редактирование:
Сообщения
1,698
Реакции
1,510
Помог
26 раз(а)
Denzer, можно оптимизировать. Это register_forward(FM_Think, "Think_Post", true) жестко)
 
Последнее редактирование модератором:

d3m37r4

111111
Сообщения
1,451
Реакции
1,177
Помог
10 раз(а)
Получение координат точки находящейся на определенном расстоянии от игрока относительно его взгляда.
Код:
stock get_CoordPointInDirView(const index, const Float:dist, Float:output[3]) {
    new Float:start_origins[3];
    pev(index, pev_origin, start_origins);

    new Float:angles[3];
    pev(index, pev_v_angle, angles);

    new Float:end_origins[3];
    end_origins[0] = start_origins[0] + dist * floatcos(angles[1], degrees) * floatabs(floatcos(angles[0], degrees));
    end_origins[1] = start_origins[1] + dist * floatsin(angles[1], degrees) * floatabs(floatcos(angles[0], degrees));
    end_origins[2] = start_origins[2];

    engfunc(EngFunc_TraceLine, start_origins, end_origins, DONT_IGNORE_MONSTERS, index, 0);
    get_tr2(0, TR_vecEndPos, end_origins);

    output[0] = end_origins[0];
    output[1] = end_origins[1];
    output[2] = end_origins[2];
}

Спавн энтити перед игроком, на расстоянии 200 юнитов.
Код:
#include <amxmodx>
#include <fakemeta>
#include <reapi>

new const ENT_NAME[]  = "info_target";
new const ENT_MODEL[]  = "models/2_zombie.mdl";
new const ENT_CLASSNAME[] = "ZommbieEnt";

const Float:ENT_HEALTH = 200.0;

enum {
    ANIM_IDLE,
    ANIM_WALK,
    ANIM_ATTACK,
    ANIM_DIE
};

#define F_VEC_ZOMBIE_HULL_MIN      Float:{ -10.0, -10.0, 0.0 }
#define F_VEC_ZOMBIE_HULL_MAX      Float:{ 10.0, 10.0, 62.0 }

new g_EntCount;

public plugin_precache() {
    precache_model(ENT_MODEL);
}

public plugin_init() {
    register_clcmd("say spawn", "CmdEntSPawn");
}

public CmdEntSPawn(const id) {
    new Float:origin_start[3];
    get_entvar(id, var_origin, origin_start);

    new Float:origin_end[3]
    get_CoordPointInDirView(id, 200.0, origin_end);

    new ent = createEntity(origin_end);
    if(ent != NULLENT) {
        client_print_color(id, 0, "Created ent: %d, entity count: %d", ent, ++g_EntCount);
    }
}

createEntity(const Float:origin[3]) {
    new ent = rg_create_entity(ENT_NAME, false);

    if(is_nullent(ent)) {
        return NULLENT;
    }

    set_entvar(ent, var_classname, ENT_CLASSNAME);
    set_entvar(ent, var_solid, SOLID_BBOX);
    set_entvar(ent, var_movetype, MOVETYPE_NONE);
    set_entvar(ent, var_sequence, ANIM_IDLE);
    set_entvar(ent, var_framerate, 1.0);

    engfunc(EngFunc_SetOrigin, ent, origin);
    engfunc(EngFunc_SetModel, ent, ENT_MODEL);
    engfunc(EngFunc_SetSize, ent, F_VEC_ZOMBIE_HULL_MIN, F_VEC_ZOMBIE_HULL_MAX);

    return ent;
}

stock get_CoordPointInDirView(const index, const Float:dist, Float:output[3]) {
    new Float:start_origins[3];
    pev(index, pev_origin, start_origins);

    new Float:angles[3];
    pev(index, pev_v_angle, angles);

    new Float:end_origins[3];
    end_origins[0] = start_origins[0] + dist * floatcos(angles[1], degrees) * floatabs(floatcos(angles[0], degrees));
    end_origins[1] = start_origins[1] + dist * floatsin(angles[1], degrees) * floatabs(floatcos(angles[0], degrees));
    end_origins[2] = start_origins[2];

    engfunc(EngFunc_TraceLine, start_origins, end_origins, DONT_IGNORE_MONSTERS, index, 0);
    get_tr2(0, TR_vecEndPos, end_origins);

    output[0] = end_origins[0];
    output[1] = end_origins[1];
    output[2] = end_origins[2];
}

1586890831218.png
 
Последнее редактирование модератором:
Сообщения
2,491
Реакции
2,794
Помог
61 раз(а)
d3m37r4, trace хендл можно указать 0 вместо каждый раз создавать.
 
Последнее редактирование модератором:

d3m37r4

111111
Сообщения
1,451
Реакции
1,177
Помог
10 раз(а)
fantom, поправил.
 
Последнее редактирование модератором:
Сообщения
1,698
Реакции
1,510
Помог
26 раз(а)
d3m37r4, флоаткосинусы быстрее, чем брать glb_v_forward?
 
Последнее редактирование модератором:

d3m37r4

111111
Сообщения
1,451
Реакции
1,177
Помог
10 раз(а)
fl0wer, оптимизации?
 
Последнее редактирование модератором:
Сообщения
1,698
Реакции
1,510
Помог
26 раз(а)
d3m37r4, ну ты их сделал потому что быстрее или потому что форвард проще?
 
Последнее редактирование модератором:
Сообщения
2,491
Реакции
2,794
Помог
61 раз(а)
fl0wer, я вот лично не знаю об glb_v_forward. Думаю будет очень круто если появится хотя бы краткое руководство или целый мануал. Но это займет очень много времени, а данная инфа нужна двум с половиной калекам.
 
Последнее редактирование модератором:

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

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