Проверка на убийство ножом, нужен совет.

BlackPro

Участник
Сообщения
75
Реакции
11
Доброго всем, попробую с ходу кратко обяснить.
Хукаю событие смерти, внутри получаю атакующего, и если это нож, то делаю что нибудь.
C-подобный:
public Event_PlayerDeath(Handle:hEvent, const String:sEvName[], bool:bDontBroadcast)
{
    int attacker = GetClientOfUserId(GetEventInt(hEvent, "attacker"));
   
    if (attacker > 0 && IsPlayerAlive(attacker) && attacker != GetClientOfUserId(GetEventInt(hEvent, "userid")))
    {
        decl String:sWeapon[32];
        GetEventString(hEvent, "weapon", sWeapon, sizeof(sWeapon));
       
        if (!strcmp(sWeapon, "knife"))
        {
            PrintToChat(attacker, "Ку-ку...");
        }
    }
}

Так вот если в CSGO сделать такой код, то он будет работать только для CT.
Ну думаю, посмотрю что передаёт Т и запускаю код:
C-подобный:
public void OnPluginStart()
{
    HookEventEx("player_death", Event_PlayerDeath, EventHookMode_Pre);
}

public Event_PlayerDeath(Handle:hEvent, const String:sEvName[], bool:bDontBroadcast)
{
    int attacker = GetClientOfUserId(GetEventInt(hEvent, "attacker"));
    if (attacker > 0 && IsPlayerAlive(attacker))
    {
        decl String:sWeapon[32];
        GetEventString(hEvent, "weapon", sWeapon, sizeof(sWeapon));
        PrintToServer("Weapons: %s", sWeapon);
    }
}
Оказывается для Терроров нужно чекать knife_t, а для контров как вы уже поняли просто knife,
соответсвенно проверку нужно делать не if (!strcmp(sWeapon, "knife")), а if (!strcmp(sWeapon, "knife") || !strcmp(sWeapon, "knife_t")).
Только тогда код код будет работать коректно для T/CT.

Так вот вопрос в том что есть же ещё ножи:
C-подобный:
        /*bayonet
        knife_gut
        knife_flip
        knife_m9_bayonet
        knife_karambit
        knife_tactical
        knife_butterfly
        knife_falchion
        knife_push
        knife_survival_bowie*/
Их тоже надо проверять? Т.е что будет если зайдут игроки со скинами, для них мой код не сработает и нужно проверять все ножи? Если да тогда где взять полный список?
Эти я взял с франфуркта, ещё видел в плагине csdm для ксго проверку на weapon_bayonet, тоже не понимаю почему.
Ещё нашёл этот список Расшифровка названий ножей. Weapons / knife, вот и не знаю что мне проверять.
 

Mr_panica

XenForo one 💖
Сообщения
921
Реакции
436
Я в этом е очень силён, но наверное можно использовать StrContains · string · SourceMod Scripting API Reference
Которая проверяет на то, находится ли одна строка, которую ты хочешь проверить, внутри другой, которую ты сравниваешь.

C-подобный:
public Event_PlayerDeath(Event hEvent, const char[] name, bool dontBroadcast)
{
    int attacker = GetClientOfUserId(GetEventInt(hEvent, "attacker"));
    int victim = GetClientOfUserId(GetEventInt(hEvent, "userid"));

    if (attacker > 0 && IsPlayerAlive(attacker) && attacker != victim)
    {
        char sWeapon[32];
        GetEventString(hEvent, "weapon", sWeapon, sizeof(sWeapon));
   
        if (StrContains(sWeapon, "knife",  false) != -1)
        {
            PrintToChat(attacker, "Ку-ку...");
        }
    }
}

Кхм, ну и да, Разные итемы ножей? - Форум

P.S
Ненавижу старый синтаксис, а почему - хз 🤔
 
Последнее редактирование:

BlackPro

Участник
Сообщения
75
Реакции
11
@Mr_panica, ну да чекнул, всё ты правильно говоришь, но ведь это всё надо делать если всё что я написал правда и нам надо проверять много ножей. Но нужно ли это делать вообще? Просто судя по тому как у меня изначально работает, то нужно.
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,521
Реакции
4,980
всё можно вообще проще сделать (если интересуют только одни ножи и ничего больше):
C-подобный:
public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
{
    int attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
    if(attacker && IsPlayerAlive(attacker) && attacker != GetClientOfUserId(GetEventInt(event, "userid")))
    {
        decl String:wpn[8];    // нам вполне достаточно 7 символов
        GetEventString(event, "weapon", wpn, sizeof(wpn));
        wpn[6] = 0;    // обрезаем строку после 5-го символа
        if(!strcmp(wpn, "knife") || !strcmp(wpn, "bayon"))
        {
            PrintToChat(attacker, "Ку-ку...");
        }
    }
}
 

BlackPro

Участник
Сообщения
75
Реакции
11
Сейчас в плагине KnifeAlert посмотрел там вообще так:
if(StrContains(weaponName, "knife", false) != -1 || (StrContains(weaponName, "bayonet", false) != -1))
Сообщения автоматически склеены:

В итоге сделал так:
C-подобный:
-подобный:
public Event_PlayerDeath(Handle:hEvent, const String:sEvName[], bool:bDontBroadcast)
{
    int attacker = GetClientOfUserId(GetEventInt(hEvent, "attacker"));
 
    if (attacker > 0 && IsPlayerAlive(attacker) && attacker != GetClientOfUserId(GetEventInt(hEvent, "userid")))
    {
        decl String:sWeapon[32];
        GetEventString(hEvent, "weapon", sWeapon, sizeof(sWeapon));
     
        if(StrContains(sWeapon, "knife", false) != -1 || (!strcmp(sWeapon, "bayonet")))
        {
            PrintToChat(attacker, "Ку-ку...");
        }
    }
}
Думаю будет норм.
 
Последнее редактирование:

_wS_

Участник
Сообщения
383
Реакции
760
Есть еще такая фгня, когда ждёшь в event'е "awp", но там оказывается "weapon_awp", и попробуй угадай как будет завтра. Если не ошибаюсь, то такие приколы есть с event'ом weapon_fire. В css там нет префикса weapon_, а в csgo есть (раньше вроде не было).
 

SAPSAN 隼

Не было б печали, если бы ключи мне дали!
Сообщения
820
Реакции
776
я улавливал так
if(szWeapon[0] == 'k' || !strcmp(szWeapon, "bayonet"))
 

BlackPro

Участник
Сообщения
75
Реакции
11
Дабы темы не плодить, спрошу здесь если можно.
Почему это не работает?
C-подобный:
Handle:hHUD;

public OnPluginStart()
{
    hHUD = CreateHudSynchronizer();
}

public Event_PlayerDeath(Handle:hEvent, const String:sEvName[], bool:bDontBroadcast)
{
    int attacker = GetClientOfUserId(GetEventInt(hEvent, "attacker"));
   
    if (attacker > 0 && IsPlayerAlive(attacker) && attacker != GetClientOfUserId(GetEventInt(hEvent, "userid")))
    {
        if (GetEventBool(hEvent, "headshot"))
        {
            GiveClientData(attacker, m_iHealth, g_iCvar_headshot_hp, g_iCvar_max_hp);
           
            SetHudTextParams(-1.0, -1.0, 1.0, 15, 63, 255, 255, _, 0.0, _, 0.1);
            for(int i = 1; i <= MaxClients; i++) if(IsClientInGame(i) && !IsFakeClient(i)) ShowSyncHudText(i, hHUD, "HP:%s", g_iCvar_headshot_hp);
           
            return;
        }
        GiveClientData(attacker, m_iHealth, g_iCvar_kill_hp, g_iCvar_max_hp);
       
        SetHudTextParams(-1.0, -1.0, 1.0, 15, 63, 255, 255, _, 0.0, _, 0.1);
        for(int i = 1; i <= MaxClients; i++) if(IsClientInGame(i) && !IsFakeClient(i)) ShowSyncHudText(i, hHUD, "HP:%i", g_iCvar_kill_hp);
    }
}

GiveClientData(attacker, m_Offset, Value, MaxValue)
{
    if(Value > 0)
    {
        Value += GetEntData(attacker, m_Offset);
        if(Value > MaxValue)
        {
            Value = MaxValue;
            //Хотел ещё выводить сообщение если достигнуто максимальное значение хп
        }

        SetEntData(attacker, m_Offset, Value);

        return 1;
    }
   
    return 0;
}

Пытаюсь взять значения g_iCvar_headshot_hp, g_iCvar_kill_hp и вывести их игроку в через ShowSyncHudText, по факту не выводит %i, только текст выводит HP: и всё, и ещё выводит даже если убийца другой игрок.
Если убрать цыкл, не чего не изменится, если в ShowSyncHudText юзать переменную attacker, тоже не чего не получается, а если ещё и цыкл attacker засунуть, то при компиляции варн что это локальная переменная, но как бы я так и хотел.
Нужно в зависимости от события вывести атакующему значение g_iCvar_headshot_hp или g_iCvar_kill_hp через ShowSyncHudText. Как делать правильно?
 

Kruzya

Участник
Сообщения
12,970
Реакции
10,914
  • Команда форума
  • #9
Дабы темы не плодить, спрошу здесь если можно.
Абсолютно плохая тактика, поддерживающая форум в засранном состоянии.

Я абсолютно не пойму, что за манера кидать обрезанные куски кода, да ещё порой настолько, что непонятно, что есть что.
Что такое g_iCvar_headshot_hp и g_iCvar_kill_hp? Это хоть не результаты вызова CreateCvar(), надеюсь?
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,521
Реакции
4,980
@BlackPro, не пойму код:
  • на кой выводить в HUD ВСЕМ игрокам значение кваров при убийстве одного из них?
  • на кой передавать в параметрах функции глобальные переменные и офсет здоровья, если можно передать только тип меняющегося параметра через bool?
    или ты сделал полностью универсальную функцию, через которую можно менять все целочисленные значения параметров?
  • ShowSyncHudText(i, hHUD, "HP:%s", g_iCvar_headshot_hp); ты уверен что там должно быть %s, а не %i?
И ещё вопрос: почему используется старый синтаксис?
Если пишется для КСГО, то в этом нет совершенно никакого смысла (да даже для CSSv34 нет особого, т.к. там на данный момент тоже можно использовать форки SM вплоть до версии 1.11).

Думаю будет норм.
Думаю, работать будет, но мой вариант будет работать быстрее и меньше нагружать проц сервера (хотя ты разницу и не заметишь).

Где-то на форуме была тема, где мы сравнивали производительность разных способов сравнения строк. Вот там можно почитать и понять почему я так сделал проверку.

В общем я бы написал вот так:
C-подобный:
Handle:hHUD;

public OnPluginStart()
{
    hHUD = CreateHudSynchronizer();
}

public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
{
    new client = GetClientOfUserId(GetEventInt(event, "attacker"));
    if(client && IsClientInGame(client) && IsPlayerAlive(client)
    && client != GetClientOfUserId(GetEventInt(event, "userid")))
    {
        new val = GetEventBool(event, "headshot") ? g_iCvar_headshot_hp : g_iCvar_kill_hp;
        GiveClientData(client, val);
        SetHudTextParams(-1.0, -1.0, 1.0, 15, 63, 255, 255, _, 0.0, _, 0.1);
        ShowSyncHudText(client, hHUD, "HP: %i", val);
    }
}

bool:GiveClientData(client, &value)
{
    if(value < 1) return false;

    value += GetEntData(client, m_iHealth);
    if(value > g_iCvar_max_hp)
    {
        value = g_iCvar_max_hp;
        //Хотел ещё выводить сообщение если достигнуто максимальное значение хп
    }
    SetEntData(client, m_iHealth, value);

    return true;
}
Вообще там надо бы проверка того, есть ли возможность увеличивать хп.

У меня такой плагин с изменением хп давно написан. И там тоже выводится инфа, что хп стало максимальным.

А чтобы выводить эту инфу, то нужно выводить её не после выполнения функции GiveClientData(), а прямо в ней.
Потому что вывод после неё перебьёт вывод из неё.

В общем если ты хочешь показать текущее ХП игрока сделавшего фраг, и показать, что выше ХП уже не станет то можно сделать примерно вот так:
C-подобный:
#include <entity_prop_stocks>

Handle:hHUD;

public OnPluginStart()
{
    hHUD = CreateHudSynchronizer();
}

public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
{
    new client = GetClientOfUserId(GetEventInt(event, "attacker")), health;
    if(client && IsClientInGame(client) && IsPlayerAlive(client) && (health = GetClientHealth(client)) < g_iCvar_max_hp
    && client != GetClientOfUserId(GetEventInt(event, "userid")))
    {
        SetHudTextParams(-1.0, -1.0, 1.0, 15, 63, 255, 255, _, 0.0, _, 0.1);
        new add = GetEventBool(event, "headshot") ? g_iCvar_headshot_hp : g_iCvar_kill_hp;
        if((health += add) >= g_iCvar_max_hp)
        {
            health = g_iCvar_max_hp;
            ShowSyncHudText(client, hHUD, "HP: %i (max)", health);
        }
        else ShowSyncHudText(client, hHUD, "HP: %i", health);
        SetEntityHealth(client, health);
    }
}
Если у игрока уже достигнуто максимальное ХП, то панель не будет отображаться.
 
Последнее редактирование:
Сверху Снизу