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

Сообщения
920
Реакции
158
Помог
26 раз(а)
Здравствуйте.
Сегодня хотелось бы затронуть такую тему, как плагины для меню с ножами.
Обычно они используются на серверах с 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                                                                
}
C++
Как видим, тут идет увеличение через 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++
Как мы можем наблюдать, тут идёт функция:
C++:
ExecuteHamB(Ham_TakeDamage, i, Ent, Attacker, float(DAMAGE) / random_float(1.25, 1.5), DMG_ACID)
C++
Тут хотелось бы уточнить, что есть два метода вызова Ham хуков, а конкретно
C++:
ExecuteHam // - Вызывается без кода из сторонних плагинов.
ExecuteHamB // - Он может вызвать хуки в других плагинах.
C++
У некоторых людей возникает вопрос:
Почему так происходит? Ответ прост.
1 - Если брать конкретно данное меню ножей, то мы можем увидить, что там есть проверка на то, есть ли в руке нож, и по факту - всё, дальше сторонние проверки от плагина. Так вот, у нас есть такая штука (5 параметр в Ham_TakeDamage) как damage_type.
Этот параметр позволяет проверять тип урона, к примеру, у гранаты тип урона DMG_GRENADE, следовательно, что бы исправить проблему, можно использовать проверку на тип урона конкретно от гранаты, но как же быть с кастомными оружиями?
На самом деле, можно обойтись проверкой на тип конкретно от гранаты, и сделать немного другим путём.
У оружия/ножей есть 2 бита аттаки, а именно DMG_NEVERGIB и DMG_BULLET, так вот, можно сделать проверку, что если игрок держит в руках нож и тип урона есть DMG_BULELT - мы можем увеличить урон в этот момент. Это избавит нас от проблем с увеличением урона от гранат и кастомных оружий, где используется
C++:
ExecuteHam/ExecuteHamB(Take_Damage, any...);
C++
По итогу, код будет следующим:
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                                                                
}
C++
Со всеми типами урона можно ознакомится тут.
Так же хотелось бы услышать мнение более опытных людей, возможно, они подскажут еще какие-то методы.
Кстати, на реапи есть такие мемберы (не знаю, на 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) * Множитель урона);
C++
Код взят отсюда.
Учту, что данный мембер вешается на предмет, можно как-то и с этим поиграться, и выставлять урон конкретно предмету, а не игроку.

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

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

Так что в любом случаи + только за потраченное время
 
Сообщения
920
Реакции
158
Помог
26 раз(а)
Еще такой вопрос, возможно кто подскажет, заметил что есть DMG_SLASH, но, с ним проверка не срабатывала, он проходит когда ножом по стенке ударяешь или как?
 
Сообщения
3,593
Реакции
1,579
Помог
141 раз(а)
Сообщения
723
Реакции
610
Помог
13 раз(а)
Еще можно проверить inflictor != attacker (это граната) а на оружиях инфликтор всегда равен аттакеру (ну на деф оружиях).

Ну так просто для инфы
 
Сообщения
24
Реакции
7
Помог
4 раз(а)
Спасибо за статью, очень полезно и помогло!
 
Сообщения
920
Реакции
158
Помог
26 раз(а)
Еще вопрос, если оружие использует DMG_BULLET при вызове ExecuteHam/ExecuteHamB, на что лучше заменить? на DMG_NEVERGIB?
 
Сообщения
723
Реакции
610
Помог
13 раз(а)
ImmortalAmxx, а зачем его заменить? Можно же добавить
 
Сообщения
920
Реакции
158
Помог
26 раз(а)
Vaqtincha, получается, если добавить, к примеру, DMG_NEVERGIB к DMG_BULLET, то проверка не должна срабатвыать в самих ножах, и бага с уроном быть не должно?
 

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

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