Урон у ножей и проблемы с ними.

Сообщения
867
Реакции
144
Помог
25 раз(а)
Здравствуйте.
Сегодня хотелось бы затронуть такую тему, как плагины для меню с ножами.
Обычно они используются на серверах с ZP 4.3/ZP 5.0/Biohazard модами.
Как правило, в старых кодах урон увеличивается в Ham_TakeDamage через SetHamParamFloat.
Для примера я взял данный плагин.
В нем есть следующий код:
C++:
public plugin_init()
{
    ...
    RegisterHam(Ham_TakeDamage, "player", "fw_TakeDamage")
}
public fw_TakeDamage(victim, inflictor, attacker, Float:damage, damage_type)
{
    if(!is_user_connected(attacker)) return HAM_IGNORED                                
    if(zp_get_user_zombie(attacker)) return HAM_IGNORED
   
    new weapon = get_user_weapon(attacker)
    if(weapon == CSW_KNIFE && g_knife6[attacker])                                                                
    {                                                                
        SetHamParamFloat(4, damage * get_pcvar_float(dmg_knife6))                                
        if(g_sp[attacker])
        {
            if( !task_exists( victim + TASK_FBURN ) )                                                          
            {                                                                                                            
                g_burning_duration[victim] += get_pcvar_num(g_fire_time) * 5                                        
                set_task(0.1, "CTask__BurningFlame", victim + TASK_FBURN, _, _, "b" )
            }                                                                                                        
        }
    }
    else
    {                                                                                                              
        if(!g_freeze_wait[attacker] && !zp_get_user_nemesis(victim))                                                
        {                                                          
            set_pev(victim, pev_flags, pev(victim, pev_flags) | FL_FROZEN)                              
            set_user_rendering(victim, kRenderFxGlowShell, 0, 206, 209, kRenderNormal, 25)                  
            g_frozen[victim] = true
            set_task(get_pcvar_float(g_time_freeze), "end", victim)                                                
            g_freeze_wait[attacker] = true                                                                                  
            set_task(get_pcvar_float(g_time_freeze_wait), "Freeze_Wait", attacker + 1233123)
        }                                                                    
    }
   
    // Конкретно тут уже идет увеличение урона.
    if(weapon == CSW_KNIFE && g_knife5[attacker])                                            
    {                                                                                              
        SetHamParamFloat(4, damage * get_pcvar_float(dmg_knife5))
    }                                                                                                        
    if(weapon == CSW_KNIFE && g_knife4[attacker])
    {  
        SetHamParamFloat(4, damage * get_pcvar_float(dmg_knife4))
    }
    if(weapon == CSW_KNIFE && g_knife3[attacker])
    {                                                                                      
        SetHamParamFloat(4, damage * get_pcvar_float(dmg_knife3))
    }                                              
    if(weapon == CSW_KNIFE && g_knife2[attacker])
    {    
        SetHamParamFloat(4, damage * get_pcvar_float(dmg_knife2))                            
    }                                                                                                      
    if(weapon == CSW_KNIFE && g_knife1[attacker])                                  
    {    
        SetHamParamFloat(4, damage * get_pcvar_float(dmg_knife1))
    }                                                        
    return HAM_IGNORED                                                                
}
Как видим, тут идет увеличение через SetHamParamFloat путём умножения значение урона (damage) на нужное число (к примеру это квар get_pcvar_float(dmg_knife1)).
Но, если кинуть гранату и в этот момент взять 1 из ножиков, то в момент взрыва гранаты урон у взрыва будет так-же увеличен.
Так же не стоит забывать и за кастомные оружия, к примеру, взять тот же плазма ган, который стреляет не пулями, а некими "шарами".
Ниже показан код одного из плазмаганов.
Код:
public Damage_Plasma(Ent, Id)
{
    static Owner; Owner = pev(Ent, pev_iuser1)
    static Attacker;
    if(!is_user_alive(Owner))
    {
        Attacker = 0
        return
    } else Attacker = Owner
   
    if(is_user_alive(Id) && is_user_zombie(Id))
    {
        ExecuteHamB(Ham_TakeDamage, Id, Ent, Attacker, float(DAMAGE), DMG_ACID)
    }
   
    for(new i = 0; i < g_MaxPlayers; i++)
    {
        if(!is_user_alive(i))
            continue
        if(entity_range(i, Ent) > PLASMA_RADIUS)
            continue
        if(!is_user_zombie(i))
            continue
           
        ExecuteHamB(Ham_TakeDamage, i, Ent, Attacker, float(DAMAGE) / random_float(1.25, 1.5), DMG_ACID)
    }
}
Как мы можем наблюдать, тут идёт функция:
C++:
ExecuteHamB(Ham_TakeDamage, i, Ent, Attacker, float(DAMAGE) / random_float(1.25, 1.5), DMG_ACID)
Тут хотелось бы уточнить, что есть два метода вызова Ham хуков, а конкретно
C++:
ExecuteHam // - Вызывается без кода из сторонних плагинов.
ExecuteHamB // - Он может вызвать хуки в других плагинах.
У некоторых людей возникает вопрос:
Почему так происходит? Ответ прост.
1 - Если брать конкретно данное меню ножей, то мы можем увидить, что там есть проверка на то, есть ли в руке нож, и по факту - всё, дальше сторонние проверки от плагина. Так вот, у нас есть такая штука (5 параметр в Ham_TakeDamage) как damage_type.
Этот параметр позволяет проверять тип урона, к примеру, у гранаты тип урона DMG_GRENADE, следовательно, что бы исправить проблему, можно использовать проверку на тип урона конкретно от гранаты, но как же быть с кастомными оружиями?
На самом деле, можно обойтись проверкой на тип конкретно от гранаты, и сделать немного другим путём.
У оружия/ножей есть 2 бита аттаки, а именно DMG_NEVERGIB и DMG_BULLET, так вот, можно сделать проверку, что если игрок держит в руках нож и тип урона есть DMG_BULELT - мы можем увеличить урон в этот момент. Это избавит нас от проблем с увеличением урона от гранат и кастомных оружий, где используется
C++:
ExecuteHam/ExecuteHamB(Take_Damage, any...);
По итогу, код будет следующим:
C++:
public fw_TakeDamage(victim, inflictor, attacker, Float:damage, damage_type)
{
    if(!is_user_connected(attacker)) return HAM_IGNORED                                
    if(zp_get_user_zombie(attacker)) return HAM_IGNORED
   
    new weapon = get_user_weapon(attacker)
    if(weapon == CSW_KNIFE && g_knife6[attacker])                                                                
    {                                                                
        SetHamParamFloat(4, damage * get_pcvar_float(dmg_knife6))                                
        if(g_sp[attacker])
        {
            if( !task_exists( victim + TASK_FBURN ) )                                                          
            {                                                                                                            
                g_burning_duration[victim] += get_pcvar_num(g_fire_time) * 5                                        
                set_task(0.1, "CTask__BurningFlame", victim + TASK_FBURN, _, _, "b" )
            }                                                                                                        
        }
    }
    else
    {                                                                                                              
        if(!g_freeze_wait[attacker] && !zp_get_user_nemesis(victim))                                                
        {                                                          
            set_pev(victim, pev_flags, pev(victim, pev_flags) | FL_FROZEN)                              
            set_user_rendering(victim, kRenderFxGlowShell, 0, 206, 209, kRenderNormal, 25)                  
            g_frozen[victim] = true
            set_task(get_pcvar_float(g_time_freeze), "end", victim)                                                
            g_freeze_wait[attacker] = true                                                                                  
            set_task(get_pcvar_float(g_time_freeze_wait), "Freeze_Wait", attacker + 1233123)
        }                                                                    
    }
   
    // проверяем на тип урона
    if(damage_type & DMG_BULLET)
    {
        // Конкретно тут уже идет увеличение урона.
        if(weapon == CSW_KNIFE && g_knife5[attacker])
        {
            SetHamParamFloat(4, damage * get_pcvar_float(dmg_knife5))
        }
        if(weapon == CSW_KNIFE && g_knife4[attacker])
        {
            SetHamParamFloat(4, damage * get_pcvar_float(dmg_knife4))
        }
        if(weapon == CSW_KNIFE && g_knife3[attacker])
        {
            SetHamParamFloat(4, damage * get_pcvar_float(dmg_knife3))
        }                                              
        if(weapon == CSW_KNIFE && g_knife2[attacker])
        {    
            SetHamParamFloat(4, damage * get_pcvar_float(dmg_knife2))
        }       
        if(weapon == CSW_KNIFE && g_knife1[attacker])
        {    
            SetHamParamFloat(4, damage * get_pcvar_float(dmg_knife1))
        }
    }                       
    return HAM_IGNORED                                                                
}
Со всеми типами урона можно ознакомится тут.
Так же хотелось бы услышать мнение более опытных людей, возможно, они подскажут еще какие-то методы.
Кстати, на реапи есть такие мемберы (не знаю, на fakemete есть они или нет), как:
C++:
set_member(iWeapon, m_Knife_flStabBaseDamage, Float: get_member(iWeapon, m_Knife_flStabBaseDamage) * Множитель урона);
set_member(iWeapon, m_Knife_flSwingBaseDamage, Float: get_member(iWeapon, m_Knife_flSwingBaseDamage) * Множитель урона);
set_member(iWeapon, m_Knife_flSwingBaseDamage_Fast, Float: get_member(iWeapon, m_Knife_flSwingBaseDamage_Fast) * Множитель урона);
Код взят отсюда.
Учту, что данный мембер вешается на предмет, можно как-то и с этим поиграться, и выставлять урон конкретно предмету, а не игроку.

UPD 03.10.2023 (thanx to Vaqutincha).
Еще можно проверить inflictor != attacker (это граната) а на оружиях инфликтор всегда равен аттакеру (ну на деф оружиях).
 
Последнее редактирование:
Сообщения
1,501
Реакции
1,499
Помог
2 раз(а)
Спасибо за статью,что написал
Более опытные поправят,вдруг что не так

На статьи всегда уходит куча времени,
Подробно всё написать,заскринить,снять и прочее

Так что в любом случаи + только за потраченное время
 
Сообщения
867
Реакции
144
Помог
25 раз(а)
Еще такой вопрос, возможно кто подскажет, заметил что есть DMG_SLASH, но, с ним проверка не срабатывала, он проходит когда ножом по стенке ударяешь или как?
 
Сообщения
3,411
Реакции
1,489
Помог
125 раз(а)
Сообщения
551
Реакции
470
Предупреждения
16
Помог
9 раз(а)
Еще можно проверить inflictor != attacker (это граната) а на оружиях инфликтор всегда равен аттакеру (ну на деф оружиях).

Ну так просто для инфы
 
Сообщения
20
Реакции
6
Помог
3 раз(а)
Спасибо за статью, очень полезно и помогло!
 
Сообщения
867
Реакции
144
Помог
25 раз(а)
Еще вопрос, если оружие использует DMG_BULLET при вызове ExecuteHam/ExecuteHamB, на что лучше заменить? на DMG_NEVERGIB?
 
Сообщения
551
Реакции
470
Предупреждения
16
Помог
9 раз(а)
ImmortalAmxx, а зачем его заменить? Можно же добавить
 
Сообщения
867
Реакции
144
Помог
25 раз(а)
Vaqtincha, получается, если добавить, к примеру, DMG_NEVERGIB к DMG_BULLET, то проверка не должна срабатвыать в самих ножах, и бага с уроном быть не должно?
 

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

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