Лимит на покупку Щита

Сообщения
486
Реакции
89
Помог
5 раз(а)
И снова, Здравствуйте! Хотел бы уточнить, как отловить меню VGUI и Old Text. Ибо, я так понимаю, что проблема именно там. Щиты покупаются сколько угодно, но если ввести покупку через консоль (shield), то выводит инфо о лимите на покупку. На всякий случай, прикреплю код
Код:
#include <amxmodx>
#include <hamsandwich>
#include <fakemeta>

#define SHIELD_LIMIT 1                // Кол-во Щитов на одну команду :)
#define ACCESS_IMMUNITY    ADMIN_RCON    // Иммунитет к функциям плагина. Для отключения Пропишите ADMIN_ALL

new g_iShieldCount[3];
new bool:g_bUseShield[33];

public plugin_init()
{
    new sPref[][] = {"awp_", "aim_", "35hp", "fy_"};
    new map[32]; get_mapname(map, charsmax(map));
    for(new i; i < sizeof sPref; i++)
    {
        if(containi(map, sPref[i]) != -1)
        {
            pause("ad");
            return;
        }
    }
   
    register_menucmd(register_menuid("BuyItem", true), MENU_KEY_8, "HookBuyShield");
    register_menucmd(-34, MENU_KEY_8, "HookBuyShield");
   
    register_clcmd("drop", "ClCmdDrop");
    register_clcmd("shield", "CmdShield");

    RegisterHam(Ham_Touch, "weapon_shield", "HamHookTouchShield", true);
    register_event("DeathMsg", "eDeathMsg", "a");
    register_logevent("LeRoundStart", 2, "1=Round_Start");
}

public CmdShield(id)
{
#if ACCESS_IMMUNITY != ADMIN_ALL
    if(get_user_flags(id) & ACCESS_IMMUNITY)
        return PLUGIN_CONTINUE;
#endif
    return WeaponsHandler(id, get_user_team(id));
}

public HookBuyShield(id)
{
#if ACCESS_IMMUNITY != ADMIN_ALL
    if(get_user_flags(id) & ACCESS_IMMUNITY)
        return PLUGIN_CONTINUE;
#endif
    return WeaponsHandler(id, team);
}

public WeaponsHandler(id, team)
{
    if(g_iShieldCount[team] >= SHIELD_LIMIT)
    {
        client_print_color(id, print_team_default, "[^4Shield Limit^1] Достигнуто ^3максимальное ^1количество ^4Щитов ^1на команду [^3%d^1/^3%d^1]", g_iShieldCount[team], SHIELD_LIMIT);
        set_task(0.1, "DropWeapons", id);
        return PLUGIN_HANDLED;
    }
    return PLUGIN_CONTINUE;
}

public ClCmdDrop(id)
{
    new team = get_user_team(id);
    if(g_bUseShield[id])
    {
        if(g_iShieldCount[team])
            g_iShieldCount[team]--;
        g_bUseShield[id] = false;  
    }
}

public HamHookTouchShield(Ent, iClient)
{
    static team, sClassName[8]; pev(iClient, pev_classname, sClassName, charsmax(sClassName));
    if(equal(sClassName, "player"))
    {
        team = get_user_team(iClient);
       
        if(!g_bUseShield[iClient])
        {
#if ACCESS_IMMUNITY != ADMIN_ALL      
            if(~get_user_flags(iClient) & ACCESS_IMMUNITY && g_iShieldCount[team] >= SHIELD_LIMIT)
#else
            if(g_iShieldCount[team] >= SHIELD_LIMIT)
#endif
                WeaponsHandler(iClient, team);
            else
            {
                g_iShieldCount[team]++;
                g_bUseShield[iClient] = true;
            }
        }
        else
        {
            if(g_iShieldCount[team])
                g_iShieldCount[team]--;
            g_bUseShield[iClient] = false;
        }
    }
}

public eDeathMsg()
    FuncDiscDeath(read_data(2));

public client_disconnected(id)
    FuncDiscDeath(id);

FuncDiscDeath(id)
{
    if(!g_bUseShield[id]) return;
   
    new team = get_user_team(id);
    if(g_iShieldCount[team])
        g_iShieldCount[team]--;
    g_bUseShield[id] = false;
}

public DropWeapons(id)
    engclient_cmd(id, "drop", "weapon_shield");

public LeRoundStart()
{
    new players[32], pnum, i;
    arrayset(g_iShieldCount, 0, 3);

    get_players(players, pnum, "ae", "TERRORIST");
    for(i = 0; i < pnum; i++)
    {
        if(fm_get_user_shield(players[i]))
        {
            g_iShieldCount[1]++;
            g_bUseShield[players[i]] = true;
        } else g_bUseShield[players[i]] = false;
    }
    get_players(players, pnum, "ae", "CT");
    for(i = 0; i < pnum; i++)
    {
        if(fm_get_user_shield(players[i]))
        {
            g_iShieldCount[2]++;
            g_bUseShield[players[i]] = true;
        } else g_bUseShield[players[i]] = false;
    }
}

stock fm_get_user_shield(id) return get_pdata_int(id, 510) & (1<<24) ? 1 : 0;
 
Сообщения
486
Реакции
89
Помог
5 раз(а)
w0w, если я правильно понимаю, можно убирать данный участок кода:
Код:
register_menucmd(register_menuid("BuyItem", true), MENU_KEY_8, "HookBuyShield");
    register_menucmd(-34, MENU_KEY_8, "HookBuyShield");
17 Янв 2019
И блокировать через RG_CBasePlayer_HasRestrictItem
 
Сообщения
486
Реакции
89
Помог
5 раз(а)
w0w, и если я правильно понимаю, то и код WeaponsHandler тоже не нужен будет
17 Янв 2019
Примерно так, у меня получилось, впервые сталкиваюсь с RG_CBasePlayer_HasRestrictItem
Код:
public fwdHasRestrictItemPre(const id, const ItemID:item, ItemRestType:type)
{
    if((1 << any:item) && !g_bUseShield[id] && item != ITEM_C4)
    {
        if(type == ITEM_TYPE_BUYING)
        {
            new team = get_user_team(id);
            
            if(g_iShieldCount[team] >= SHIELD_LIMIT)
            {
                client_print_color(id, print_team_default, "[^4Shield Limit^1] Достигнуто ^3максимальное ^1количество ^4Щитов ^1на команду [^3%d^1/^3%d^1]", g_iShieldCount[team], SHIELD_LIMIT);
                set_task(0.1, "DropWeapons", id);
                return HC_CONTINUE;
            }
            return HC_SUPERCEDE;
        }
    }
    return HC_CONTINUE;
}
17 Янв 2019
Посмотрел на соседние коды, возможно так правильнее
Код:
public fwdHasRestrictItemPre(const id, const ItemID:item, ItemRestType:type)
{
    if((1 << any:item) && !g_bUseShield[id] && item != ITEM_C4)
    {
        if(type == ITEM_TYPE_BUYING)
        {
            new team = get_user_team(id);
            
            if(g_iShieldCount[team] >= SHIELD_LIMIT)
            {
                client_print_color(id, print_team_default, "[^4Shield Limit^1] Достигнуто ^3максимальное ^1количество ^4Щитов ^1на команду [^3%d^1/^3%d^1]", g_iShieldCount[team], SHIELD_LIMIT);
                SetHookChainReturn(ATYPE_INTEGER, 1)
                return HC_SUPERCEDE;
            }
        }
    }
    return HC_CONTINUE;
}
17 Янв 2019
Смысла только от кода 0. Как будто в пустую пишу :crazy:
 
Сообщения
1,293
Реакции
2,294
Помог
57 раз(а)
WILL_BE,
Код:
public plugin_init() {
	RegisterHookChain(RG_CBasePlayer_HasRestrictItem, "OnHasRestrictItem_Pre")
}

public OnHasRestrictItem_Pre(id, ItemID:iItem, ItemRestType:iRestType) {
	if(iRestType != ITEM_TYPE_BUYING) { // Не покупка
		return HC_CONTINUE
	}

	if(iItem == ITEM_SHIELDGUN) { // Щит
		client_print(id, print_chat, "Ты - нехороший человек. Уходи с сервера!")
		SetHookChainReturn(ATYPE_INTEGER, true)
		return HC_SUPERCEDE
	}

	return HC_CONTINUE
}
 
Сообщения
486
Реакции
89
Помог
5 раз(а)
BlackSignature, я также могу заменить:
Код:
public HamHookTouchShield(Ent, iClient)
{
    static team, sClassName[8]; pev(iClient, pev_classname, sClassName, charsmax(sClassName));
    if(equal(sClassName, "player"))
    {
        team = get_user_team(iClient);
       
        if(!g_bUseShield[iClient])
        {
#if ACCESS_IMMUNITY != ADMIN_ALL      
            if(~get_user_flags(iClient) & ACCESS_IMMUNITY && g_iShieldCount[team] >= SHIELD_LIMIT)
#else
            if(g_iShieldCount[team] >= SHIELD_LIMIT)
#endif
                WeaponsHandler(iClient, team);
            else
            {
                g_iShieldCount[team]++;
                g_bUseShield[iClient] = true;
            }
        }
        else
        {
            if(g_iShieldCount[team])
                g_iShieldCount[team]--;
            g_bUseShield[iClient] = false;
        }
    }
}
на
RegisterHookChain(RG_CSGameRules_CanHavePlayerItem, "CanHavePlayerItem_Pre")
Код:
public CanHavePlayerItem_Pre(const id, const pItem)
{
    if(get_member(pItem, m_iId) == ITEM_SHIELDGUN)
    {
        new team = get_user_team(id);

        if(!g_bUseShield[id])
        {
        #if ACCESS_IMMUNITY != ADMIN_ALL      
            if(~get_user_flags(iClient) & ACCESS_IMMUNITY && g_iShieldCount[team] >= SHIELD_LIMIT)
#else
            if(g_iShieldCount[team] >= SHIELD_LIMIT)
#endif
            {
                client_print_color(id, print_team_default, "[^4Shield Limit^1] Достигнуто ^3максимальное ^1количество ^4Щитов ^1на команду [^3%d^1/^3%d^1]", g_iShieldCount[team], SHIELD_LIMIT);
                SetHookChainReturn(ATYPE_INTEGER, false);
                return HC_SUPERCEDE;
            }
            else
            {
                g_iShieldCount[team]++;
                g_bUseShield[iClient] = true;
            }
        }
        else
        {
            if(g_iShieldCount[team])
                g_iShieldCount[team]--;
            g_bUseShield[iClient] = false;
        }
    }
    return HC_CONTINUE;
}
18 Янв 2019
Верно понимаю?
18 Янв 2019
И таким образом, я избавляюсь от
Код:
DropWeapons, ClCmdDrop, WeaponsHandler
18 Янв 2019
После манипуляций с RegisterHookChain(RG_CSGameRules_CanHavePlayerItem, "CanHavePlayerItem_Pre"), перестал работать лимит даже на закупку
 
Сообщения
2,491
Реакции
2,794
Помог
61 раз(а)
WILL_BE, RG_CBasePlayer_HasRestrictItem работает и на поднятие и на выдачу и на екипировку. Не сработает при выдаче сторонним плагином.
 
Сообщения
486
Реакции
89
Помог
5 раз(а)
fantom, только что это смотрел, что можно обойтись и HasRestrictItem
18 Янв 2019
Хотел бы уточнить, по поводу SetHookChainReturn(ATYPE_INTEGER, true);.
Его нужно где-то обнулять? (false)
Код:
public HasRestrictItem_Pre(id, ItemID:iItem, ItemRestType:iRestType)
{
    if(iRestType != ITEM_TYPE_BUYING) return HC_CONTINUE;
    
    new team = get_user_team(id);

    if(iItem == ITEM_SHIELDGUN)
    {
        #if ACCESS_IMMUNITY != ADMIN_ALL       
        if(~get_user_flags(id) & ACCESS_IMMUNITY && g_iShieldCount[team] >= SHIELD_LIMIT)
#else
        if(g_iShieldCount[team] >= SHIELD_LIMIT)
#endif
        {
            client_print_color(id, print_team_default, "[^4Shield Limit^1] Достигнуто ^3максимальное ^1количество ^4Щитов ^1на команду [^3%d^1/^3%d^1]", g_iShieldCount[team], SHIELD_LIMIT);
            SetHookChainReturn(ATYPE_INTEGER, true);
            return HC_SUPERCEDE;
        }
        else
        {
            g_iShieldCount[team]++;
            g_bUseShield[id] = true;
        }
    }
    else
    {
        if(g_iShieldCount[team])
            g_iShieldCount[team]--;
        g_bUseShield[id] = false;
    }
    return HC_CONTINUE;
}
18 Янв 2019
И можно ли, так же обойтись без <fakemeta> - конкретнее
Код:
stock fm_get_user_shield(id) return get_pdata_int(id, 510) & (1<<24) ? 1 : 0;
 
Сообщения
486
Реакции
89
Помог
5 раз(а)
То бишь:
Код:
stock fm_get_user_shield(id) return get_pdata_int(id, 510) & (1<<24) ? 1 : 0;
fm_get_user_shield(players[i])
->
Код:
rg_has_item_by_name(players[i], ITEM_SHIELDGUN)
 
Сообщения
1,293
Реакции
2,294
Помог
57 раз(а)
WILL_BE, ITEM_SHIELDGUN это целочисленное значение. А натив 2-ым аргументом принимает строку. Нужно rg_has_item_by_name(id, "weapon_shield")
 
Сообщения
486
Реакции
89
Помог
5 раз(а)
BlackSignature, Понял
18 Янв 2019
Осталось уточнить
fantom, только что это смотрел, что можно обойтись и HasRestrictItem
18 Янв 2019
Хотел бы уточнить, по поводу SetHookChainReturn(ATYPE_INTEGER, true);.
Его нужно где-то обнулять? (false)
Код:
public HasRestrictItem_Pre(id, ItemID:iItem, ItemRestType:iRestType)
{
    if(iRestType != ITEM_TYPE_BUYING) return HC_CONTINUE;
   
    new team = get_user_team(id);

    if(iItem == ITEM_SHIELDGUN)
    {
        #if ACCESS_IMMUNITY != ADMIN_ALL      
        if(~get_user_flags(id) & ACCESS_IMMUNITY && g_iShieldCount[team] >= SHIELD_LIMIT)
#else
        if(g_iShieldCount[team] >= SHIELD_LIMIT)
#endif
        {
            client_print_color(id, print_team_default, "[^4Shield Limit^1] Достигнуто ^3максимальное ^1количество ^4Щитов ^1на команду [^3%d^1/^3%d^1]", g_iShieldCount[team], SHIELD_LIMIT);
            SetHookChainReturn(ATYPE_INTEGER, true);
            return HC_SUPERCEDE;
        }
        else
        {
            g_iShieldCount[team]++;
            g_bUseShield[id] = true;
        }
    }
    else
    {
        if(g_iShieldCount[team])
            g_iShieldCount[team]--;
        g_bUseShield[id] = false;
    }
    return HC_CONTINUE;
}
18 Янв 2019
 
Сообщения
486
Реакции
89
Помог
5 раз(а)
BlackSignature, Я правильно понимаю,
Код:
SetHookChainReturn(ATYPE_INTEGER, true);
и есть тот самый "блокиратор"?
 
Сообщения
1,293
Реакции
2,294
Помог
57 раз(а)
WILL_BE, Да, всё правильно. См. HC_SUPERCEDE.

Код:
/**
* Hookchain return types
*/
enum
{
	HC_CONTINUE = 0, // Plugin didn't take any action
	HC_SUPERCEDE,    // Skip real function, use my return value
	HC_BREAK         // Skip all forwards and real function, use my return value
                     // @note Warning: Be very careful, using this type of return will skip calls for all following AMXX plugins
};
 
Сообщения
486
Реакции
89
Помог
5 раз(а)
Сегодня вечером проверю весь код. Всем, кто откликнулся, Огромное, Человеческое Спасибо (w0w, fantom, BlackSignature, d3m37r4). Теперь буду учить ReAPI :ok:
 
Последнее редактирование:
Сообщения
486
Реакции
89
Помог
5 раз(а)
fantom, Т.е. это
Код:
if(rg_has_item_by_name(players[i], "weapon_shield"))
Лучше заменить на это
Код:
if(get_member(players[i], m_bOwnsShield))
Хотелось бы пояснений, в чем разница?
 
Сообщения
1,293
Реакции
2,294
Помог
57 раз(а)
WILL_BE, разница в том что "weapon_shield" на стороне модуля ещё надо разрешить в индекс оружия, а в случае с get_member() ничего разрешать не надо, значение true когда щит есть, и false когда его нет.
 

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

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