Задача: определить, что игрок находится на спавне.

iPlague

♿️
Сообщения
230
Реакции
129
Помог
2 раз(а)
Поскольку у меня было немного свободного времени, захотел доделать плагин Flag mode, а именно определить момент, когда игрок возвращается с флагом на свою базу.
Как мне подсказали, есть несколько способов, один из них я придумал сам.
Итак, первый способ самый простой, годится для стандартных карт, где есть buy_zone:
Код:
public msgBuyZoneIcon(msgid, msgdest, id){
     if(!isGameStarted) // проверка в плагине
        return PLUGIN_CONTINUE;
    if(!is_user_alive(id))
        return PLUGIN_CONTINUE;
    static szIcon[8];
    get_msg_arg_string(2, szIcon, 7);
    if(equal(szIcon, "buyzone") && get_msg_arg_int(1)){
//#define OFFSET_MAPZONE 235
//#define PLAYER_IN_BUYZONE (1<<0)
        if(hasflag[id] && is_entity(g_Flag2Ent)) // если у игрока есть флаг, то засчитываю его как доставленый на респ
            respawn_flag(id);
        set_pdata_int(id, 235, get_pdata_int(id, 235) & ~(1<<0)); // отключаю тут же байзону
        return PLUGIN_HANDLED;
    }
    return PLUGIN_CONTINUE;
}
Однако, такой способ исключает такие карты как aim_ awp_ etc. Так же в чате подсказали, что на de_ cs_ и прочих картах сложно играть в режим flag mod, т.к. карты не симметричны. К тому же, есть плагины которые удаляют/отключают байзоны.
Второй способ, как раз для таких карт - определить центральную точку на каждом респе и там размещать энтити. Отловив тач можно засчитывать флаг. Возможно я там сделал не всё верно в плане логичности, оптимизации и т.д., однако это работает, ниже много скринов.
-1.png
Код:
#include <amxmodx>
#include <reapi>
#include <fakemeta>

#define FLAG_MDL "models/warcraft3/flag.mdl"
new g_iModel_flag;
//#define AURA_MODEL "models/aura8.mdl"
#define BEAM_SPR "sprites/zbeam4.spr"
new g_iSprites;
#if defined AURA_MODEL
new g_iModel;
#endif

new g_EntCT[32], g_EntTT[32];

new Float:coordsCT[32][3];
new Float:coordsTT[32][3];

public plugin_init(){
    register_clcmd("say test", "create");
}

public plugin_precache(){
#if defined AURA_MODEL
    g_iModel = precache_model(AURA_MODEL);
#endif
    g_iSprites = precache_model(BEAM_SPR);
    g_iModel_flag = precache_model(FLAG_MDL);
}

public create(id){
    new Ent1 = NULLENT, numCT = 0;
    while((Ent1 = rg_find_ent_by_class(Ent1, "info_player_start")) != 0){ // Ищем спавны КТ, записываем координаты, пишем инфу в консоль.
        g_EntCT[numCT] = Ent1;
        new Float:forigin1[3]; get_entvar(g_EntCT[numCT], var_origin, forigin1);
// Ставим модель
        set_entvar(g_EntCT[numCT], var_model, FLAG_MDL);
        set_entvar(g_EntCT[numCT], var_modelindex, g_iModel_flag);
        set_entvar(g_EntCT[numCT], var_movetype, MOVETYPE_TOSS);
        set_entvar(g_EntCT[numCT], var_solid, SOLID_NOT);
        set_entvar(g_EntCT[numCT], var_body, 2);
//   
        server_print("%d. CT Entity ID: %d | Entity Origins: %f %f %f", numCT + 1, g_EntCT[numCT], forigin1[0],forigin1[1],forigin1[2]);
        coordsCT[numCT][0] = forigin1[0];
        coordsCT[numCT][1] = forigin1[1];
        coordsCT[numCT][2] = forigin1[2];
        numCT++;
    }
    Ent1 = NULLENT; new numTT = 0;
    while((Ent1 = rg_find_ent_by_class(Ent1, "info_player_deathmatch")) != 0){    // Ищем спавны ТТ, записываем координаты, пишем инфу в консоль.
        g_EntTT[numTT] = Ent1;
        new Float:forigin1[3]; get_entvar(g_EntTT[numTT], var_origin, forigin1);
// Ставим модель
        set_entvar(g_EntTT[numTT], var_model, FLAG_MDL);
        set_entvar(g_EntTT[numTT], var_modelindex, g_iModel_flag);
        set_entvar(g_EntTT[numTT], var_movetype, MOVETYPE_TOSS);
        set_entvar(g_EntTT[numTT], var_solid, SOLID_NOT);
        set_entvar(g_EntTT[numTT], var_body, 1);
//           
        server_print("%d. TT Entity ID: %d | Entity Origins: %f %f %f", numTT + 1, g_EntTT[numTT], forigin1[0],forigin1[1],forigin1[2]);
        coordsTT[numTT][0] = forigin1[0];
        coordsTT[numTT][1] = forigin1[1];
        coordsTT[numTT][2] = forigin1[2];
        numTT++;
    }
//{ Нужно найти средину куба, который задан двумя точками по аналогии с min/max
// Находим наименьшую координату, наибольшую координату, находим средину получившегося отрезка.
    // Для КТ
    new Float:MaxXCT = coordsCT[0][0], Float:MinXCT = coordsCT[0][0];
    new Float:MaxYCT = coordsCT[0][1], Float:MinYCT = coordsCT[0][1];
    new Float:MaxZCT = coordsCT[0][2], Float:MinZCT = coordsCT[0][2];
    // Находим наибольшее и наименьшее значение в массиве циклом для КТ
    for(new i = 0; i < numCT; i ++){
        // наибольшее
        if(coordsCT[i][0] > MaxXCT)
            MaxXCT = coordsCT[i][0];
        if(coordsCT[i][1] > MaxYCT)
            MaxYCT = coordsCT[i][1];
        if(coordsCT[i][2] > MaxZCT)
            MaxZCT = coordsCT[i][2];
        // наименьшее
        if(coordsCT[i][0] <= MinXCT)
            MinXCT = coordsCT[i][0];
        if(coordsCT[i][1] <= MinYCT)
            MinYCT = coordsCT[i][1];
        if(coordsCT[i][2] <= MinZCT)
            MinZCT = coordsCT[i][2];
    }
    // Для ТТ
    new Float:MaxXTT = coordsTT[0][0], Float:MinXTT = coordsTT[0][0]
    new Float:MaxYTT = coordsTT[0][1], Float:MinYTT = coordsTT[0][1];
    new Float:MaxZTT = coordsTT[0][2], Float:MinZTT = coordsTT[0][2];
    // Находим наибольшее и наименьшее значение в массиве циклом для ТТ
    for(new i = 0; i < numTT; i ++){
        // наибольшее
        if(coordsTT[i][0] > MaxXTT)
            MaxXTT = coordsTT[i][0];
        if(coordsTT[i][1] > MaxYTT)
            MaxYTT = coordsTT[i][1];
        if(coordsTT[i][2] > MaxZTT)
            MaxZTT = coordsTT[i][2];
        // наименьшее
        if(coordsTT[i][0] <= MinXTT)
            MinXTT = coordsTT[i][0];
        if(coordsTT[i][1] <= MinYTT)
            MinYTT = coordsTT[i][1];
        if(coordsTT[i][2] <= MinZTT)
            MinZTT = coordsTT[i][2];
    }
    // Пишем в консоль
    server_print("MinXCT %.0f MinYCT %.0f MinZCT %.0f", MinXCT, MinYCT,  MinZCT);
    server_print("MaxXCT %.0f MaxYCT %.0f MaxZCT %.0f", MaxXCT, MaxYCT,  MaxZCT);

    server_print("MinXTT %.0f MinYTT %.0f MinZTT %.0f", MinXTT, MinYTT,  MinZTT);
    server_print("MaxXTT %.0f MaxYTT %.0f MaxZTT %.0f", MaxXTT, MaxYTT,  MaxZTT);
    // находим центральную точку среди спавнов КТ
    new Float:CentralPointCT[3];
    CentralPointCT[0] = (MaxXCT + MinXCT) / 2.0;
    CentralPointCT[1] = (MaxYCT + MinYCT) / 2.0;
    CentralPointCT[2] = (MaxZCT + MinZCT) / 2.0;
    // находим центральную точку среди спавнов ТТ
    new Float:CentralPointTT[3];
    CentralPointTT[0] = (MaxXTT + MinXTT) / 2.0;
    CentralPointTT[1] = (MaxYTT + MinYTT) / 2.0;
    CentralPointTT[2] = (MaxZTT + MinZTT) / 2.0;
    // Выводим инфо о центральной точке в консоль
    server_print("CENTRAL CT %0.f %0.f %0.f CENTRAL TT %0.f %0.f %0.f", CentralPointCT[0], CentralPointCT[1], CentralPointCT[2], CentralPointTT[0], CentralPointTT[1],CentralPointTT[2]);

    //{ Поставим в центральной точке КТ белый флаг

    new ct_flag = rg_create_entity("info_target", false);    // создаем энтити
    if(!is_nullent(ct_flag)){
        set_entvar(ct_flag, var_origin, CentralPointCT);
        set_entvar(ct_flag, var_model, FLAG_MDL);
        set_entvar(ct_flag, var_modelindex, g_iModel_flag);
        set_entvar(ct_flag, var_movetype, MOVETYPE_TOSS);
        set_entvar(ct_flag, var_solid, SOLID_NOT);
        set_entvar(ct_flag, var_body, 0);
    
        set_entvar(ct_flag, var_renderfx, kRenderFxGlowShell);
        set_entvar(ct_flag, var_rendercolor, {0.0,0.0,255.0});
        set_entvar(ct_flag, var_rendermode, kRenderNormal);
        set_entvar(ct_flag, var_renderamt, 32);
    }
    //}

    //{ Поставим в центральной точке TТ белый флаг

    new tt_flag = rg_create_entity("info_target", false);    // создаем энтити
    if(!is_nullent(tt_flag)){
        set_entvar(tt_flag, var_origin, CentralPointTT);
        set_entvar(tt_flag, var_model, FLAG_MDL);
        set_entvar(tt_flag, var_modelindex, g_iModel_flag);
        set_entvar(tt_flag, var_movetype, MOVETYPE_TOSS);
        set_entvar(tt_flag, var_solid, SOLID_NOT);
        set_entvar(tt_flag, var_body, 0);
    
        set_entvar(tt_flag, var_renderfx, kRenderFxGlowShell);
        set_entvar(tt_flag, var_rendercolor, {255.0,0.0,0.0});
        set_entvar(tt_flag, var_rendermode, kRenderNormal);
        set_entvar(tt_flag, var_renderamt, 32);
    }
// }
    // Находим ближайший к центральной точке спавн КТ
    new Float:MidDistCT = get_distance_f(coordsCT[0], CentralPointCT);
    new NearestPointCT = 0;
    for(new i = 0; i < numCT; i++){
        if(get_distance_f(coordsCT[i], CentralPointCT) < MidDistCT){
            MidDistCT = get_distance_f(coordsCT[i], CentralPointCT);
            NearestPointCT = i;
        }
    }

    // Находим ближайший к центральной точке спавн ТТ
    new Float:MidDistTT = get_distance_f(coordsTT[0], CentralPointTT);
    new NearestPointTT = 0;
    for(new i = 0; i < numTT; i++){
        if(get_distance_f(coordsTT[i], CentralPointTT) < MidDistTT){
            MidDistTT = get_distance_f(coordsTT[i], CentralPointTT);
            NearestPointTT = i;
        }
    }
    // Напишем в консоль
    server_print("Nearest CT entity %d %.0f points away", g_EntCT[NearestPointCT], MidDistCT);
    server_print("Nearest TT entity %d %.0f points away", g_EntTT[NearestPointTT], MidDistTT);

    // set glowshell over nearest spawn point
    set_entvar(g_EntCT[NearestPointCT], var_renderfx, kRenderFxGlowShell);
    set_entvar(g_EntCT[NearestPointCT], var_rendercolor, {0.0,255.0,0.0});
    set_entvar(g_EntCT[NearestPointCT], var_rendermode, kRenderNormal);
    set_entvar(g_EntCT[NearestPointCT], var_renderamt, 32);

    set_entvar(g_EntTT[NearestPointTT], var_renderfx, kRenderFxGlowShell);
    set_entvar(g_EntTT[NearestPointTT], var_rendercolor, {0.0,255.0,0.0});
    set_entvar(g_EntTT[NearestPointTT], var_rendermode, kRenderNormal);
    set_entvar(g_EntTT[NearestPointTT], var_renderamt, 32);
}
0.png1.png2.png3.png4.png5.png6.png7.png8.png9.png10.png11.png12.png
Этот способ в принципе подходит для подавляющего большинства карт, но опять таки есть исключения:
  • 35hp - там на видимом респе нет спавнов, они находятся вне видимой карты, игрок попадает на респ через триггер_телепорт
  • какая то карта со спавнами в вертолёте
  • спецкарты типа gg_ zm_ где спавны расставляются плагинами.

Ну и третий способ, который настойчиво советовали в чате - руками расставлять боксы на респах, сохранять в файл и не иметь проблем.

Спасибо всем, кто помогал в тг чате форума, хотелось бы услышать мнения и советы на форуме.
 
Последнее редактирование:

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

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