Kill_Assist

Сообщения
59
Реакции
6
Обратите внимание, если вы хотите заключить сделку с этим пользователем, он заблокирован
Привет всем , ребята подскажите где изменить значение , сколько нужно нанести урона противнику что бы засчитали фраг , то тут не понятно не чего , хочу поставить 50% урона

Код:
#include <amxmodx>
#include <reapi>

#if AMXX_VERSION_NUM < 183
    #include <colorchat>
#endif

#define MONEY 50        // Выдавать $$
#define FRAG            // +1 фраг
//#define SUPPORT_CSSTATS_MYSQL    // Защитать фраг в статистику плагина от скальпеля
//#define SUPPORT_AES_EXP    // Выдавать опыт

#if !defined MAX_PLAYERS
    const MAX_PLAYERS = 32;
#endif
#if !defined MAX_NAME_SIZE
    const MAX_NAME_SIZE = 32;
#endif
#if defined SUPPORT_CSSTATS_MYSQL
    native csstats_set_user_value(index, ident, value);
    native csstats_get_user_value(index, ident);
#endif
#if defined SUPPORT_AES_EXP
    native aes_add_player_exp(id,exp,override = 0);
#endif
    
//                            who's             whom
new Float:g_playerDamage[MAX_PLAYERS + 1][MAX_PLAYERS + 1];
new HookChain:g_deathNoticePostHook;

public plugin_init() {
    register_plugin("KiLL Assist", "0.1", "PRoSToTeM@ | sweden"); // edited by neugomon
    
//    if(!is_regamedll() || !is_rehlds())
//        set_fail_state("Needs CS ReGameDLL and ReHLDS");
  
    RegisterHookChain(RG_CBasePlayer_Spawn, "OnPlayerSpawn_Post", true);
    RegisterHookChain(RG_CBasePlayer_TakeDamage, "OnPlayerTakeDamage_Post", true);
    RegisterHookChain(RG_CSGameRules_DeathNotice, "OnDeathNotice", false);
    DisableHookChain((g_deathNoticePostHook = RegisterHookChain(RG_CSGameRules_DeathNotice, "OnDeathNotice_Post", true)));
}

public client_connect(playerEntIndex)
    arrayset(_:g_playerDamage[playerEntIndex], 0, sizeof(g_playerDamage[]));

public OnPlayerSpawn_Post(playerEntIndex)
    for(new i = 1; i <= MAX_PLAYERS; i++)
        g_playerDamage[i][playerEntIndex] = 0.0;

public OnPlayerTakeDamage_Post(playerEntIndex, inflictorEntIndex, attackerEntIndex, Float:damage, damageType)
{
    if(
        attackerEntIndex != playerEntIndex &&
        is_user_connected(attackerEntIndex) &&
        rg_is_player_can_takedamage(attackerEntIndex, playerEntIndex)
    ) g_playerDamage[attackerEntIndex][playerEntIndex] += damage;
}

public OnDeathNotice(victimEntIndex, killerEntIndex, inflictorEntIndex)
{
    if(
        killerEntIndex != victimEntIndex &&
        is_user_connected(killerEntIndex) &&
        rg_is_player_can_takedamage(killerEntIndex, victimEntIndex)
    )
    {
        new bestAttackerEntIndex = 0;
        for (new i = 1, Float:maxDamage; i <= MAX_PLAYERS; i++) {
            if (g_playerDamage[i][victimEntIndex] > maxDamage) {
                maxDamage = g_playerDamage[i][victimEntIndex];
                bestAttackerEntIndex = i;
            }
        }
        // Assistant must have more damage than killer
        if(
            bestAttackerEntIndex != killerEntIndex &&
            is_user_connected(bestAttackerEntIndex) &&
            rg_is_player_can_takedamage(bestAttackerEntIndex, victimEntIndex) &&
            get_member(bestAttackerEntIndex, m_iTeam) != TEAM_SPECTATOR
        )
        {
            new name1[MAX_NAME_SIZE], name2[MAX_NAME_SIZE], name3[MAX_NAME_SIZE], name[MAX_NAME_SIZE];
            get_entvar(killerEntIndex, var_netname, name1, charsmax(name1));
            get_entvar(bestAttackerEntIndex, var_netname, name2, charsmax(name2));
            get_entvar(victimEntIndex, var_netname, name3, charsmax(name3));
        #if defined MONEY
            rg_add_account(bestAttackerEntIndex, MONEY);
        #endif
        #if defined FRAG
            set_entvar(bestAttackerEntIndex, var_frags, Float:get_entvar(bestAttackerEntIndex, var_frags) + 1.0);
        #endif
        #if defined SUPPORT_CSSTATS_MYSQL       
            csstats_set_user_value(bestAttackerEntIndex, 0, csstats_get_user_value(bestAttackerEntIndex, 0) + 1);
        #endif
        #if defined SUPPORT_AES_EXP
            aes_add_player_exp(bestAttackerEntIndex, 1);
        #endif
            // TODO: cut nicknames if big length (> 14) and add ...
            // TODO: UTF-8 cut correctly
            if(strlen(name1) + strlen(name2) > 28) {
                formatex(name, charsmax(name), "%.14s + %.14s", name1, name2);
            } else {
                formatex(name, charsmax(name), "%s + %s", name1, name2);
            }
          
            //client_print_color(bestAttackerEntIndex, 0, "^1Вы помогли ^3%s ^1убить ^3%s ^1ваш бонус ^3%d$^1.", name1, name3, MONEY);

            message_begin(MSG_ALL, SVC_UPDATEUSERINFO);
            write_byte(killerEntIndex - 1);
            write_long(get_user_userid(killerEntIndex));
            write_char('\');
            write_char('n');
            write_char('a');
            write_char('m');
            write_char('e');
            write_char('\');
            write_string(name);
            for(new i = 0; i < 16; i++)
                write_byte(0);
            message_end();

            EnableHookChain(g_deathNoticePostHook);
        }
    }
}

public OnDeathNotice_Post(victimEntIndex, killerEntIndex, inflictorEntIndex)
{
    rh_update_user_info(killerEntIndex);
    DisableHookChain(g_deathNoticePostHook);
}
 
Сообщения
957
Реакции
1,185
Помог
52 раз(а)
C++:
new bestAttackerEntIndex = 0;
new allDamage = 0;
        for (new i = 1, Float:maxDamage; i <= MAX_PLAYERS; i++) {
            allDamage += g_playerDamage[i][victimEntIndex];
            if (g_playerDamage[i][victimEntIndex] > maxDamage) {
                maxDamage = g_playerDamage[i][victimEntIndex];
                bestAttackerEntIndex = i;
            }
        }
Код:
if (g_playerDamage[bestAttackerEntIndex][victimEntIndex] >= allDamage/2)
{
  set_entvar(bestAttackerEntIndex, var_frags, Float:get_entvar(bestAttackerEntIndex, var_frags) + 1.0);
}
 
Последнее редактирование:
Сообщения
59
Реакции
6
Обратите внимание, если вы хотите заключить сделку с этим пользователем, он заблокирован
Sonyx, Это будет 50 % ??
 
Сообщения
957
Реакции
1,185
Помог
52 раз(а)
andrei123123, скорректировал пост выше - теперь прям самые честные 50%)
 
Сообщения
453
Реакции
79
Помог
4 раз(а)
Sonyx , а можно поподробнее:
Код:
#if defined FRAG
if (g_playerDamage[bestAttackerEntIndex][victimEntIndex] >= allDamage/2)
{
  set_entvar(bestAttackerEntIndex, var_frags, Float:get_entvar(bestAttackerEntIndex, var_frags) + 1.0);
}
 
Сообщения
29
Реакции
62
Sonyx, для процентного соотношения allDamage лучше сделать глобальной для каждого игрока, и прибавлять в хуке получения дамага.
И еще момент. Если я конечно сейчас тупняки не ловлю...
К примеру игрок потеряет самостоятельно (от своей гранаты или упадет) большое кол-во хп в самом начале раунда. У него скажем останется 10 хп. И вот в таком случае при условии if (g_playerDamage[bestAttackerEntIndex][victimEntIndex] >= allDamage/2) лучшему помощнику будет достаточно нанести 5 хп. Не знаю, хорошо это или плохо :)

Поэтому можно обойтись и статическим значением.
C++:
-for (new i = 1, Float:maxDamage; i <= MAX_PLAYERS; i++) {
+for (new i = 1, Float:maxDamage = 49.0; i <= MAX_PLAYERS; i++) {
Тогда помощнику защитается фраг, если он нанес 50 и больше хп.
И если на сервере нету плагинов, которые выдают игроку ХП свыше 100 (и минимально заданному значении maxDamage >= 49), то можно прекратить сравнение дамага на первой удачной проверке:
C++:
        new bestAttackerEntIndex = 0;
        for (new i = 1, Float:maxDamage = 49.0; i <= MAX_PLAYERS; i++) {
            if (g_playerDamage[i][victimEntIndex] > maxDamage) {
                maxDamage = g_playerDamage[i][victimEntIndex];
                bestAttackerEntIndex = i;
+break;
            }
        }
В идеале, все бы это положить под макрос.
 
Последнее редактирование:
Сообщения
957
Реакции
1,185
Помог
52 раз(а)
SerGrib, не спешите, вы не разобрались в коде на этот раз

@Sonyx, для процентного соотношения allDamage лучше сделать глобальной для каждого игрока, и прибавлять в хуке получения дамага.
Она дефакто глобальна, просто хранится по частям с массиве g_playerDamage. В хуке смерти идет пробежка по всем игрокам и суммируем.


Поэтому можно обойтись и статическим значением.
C++:
-for (new i = 1, Float:maxDamage; i <= MAX_PLAYERS; i++) {
+for (new i = 1, Float:maxDamage = 49.0; i <= MAX_PLAYERS; i++) {
Тогда помощнику защитается фраг, если он нанес 50 и больше хп.
И если на сервере нету плагинов, которые выдают игроку ХП свыше 100 (и минимально заданному значении maxDamage >= 49), то можно прекратить сравнение дамага на первой удачной проверке:
вот тут вы путаете переменные allDamage и maxDamage
26 Апр 2018
Внимательнее мои куски кода посмотрите
 
Сообщения
29
Реакции
62
вы не разобрались в коде на этот раз
Почему же? Мне достаточно было бегло пробежаться по коду, а ваши правки не настолько огромные)
Я не совсем понимаю, к какому моему ответу-абзацу это было сказано, поэтому постараюсь все описать единым сообщением.

Она дефакто глобальна, просто хранится по частям с массиве g_playerDamage.
А вы задумывались, что носит g_playerDamage? Попробую объяснить суть выше описанной баги по другому, а то я не совсем уверен в том, что вы поняли то, что я хотел донести..

В TakeDamage для g_playerDamage не будет суммироваться значение полученного дамага, когда attacker == victim. А еще есть проверка на коннект (без нее никак в данном случае).
Это нам все портит.
Тут отсекается и момент, когда жертва бросит себе под ноги гранату, и когда она упадет, и когда например, админ воспользуется командой amx_slap (для решения последнего наверно не обойтись без ГК, хотя кому оно надо :crazy:).
Исходя из этого использование g_playerDamage нам не подходит, и вот тут глобальная allDamage[iVictim] ох как была бы кстати. В том же TakeDamage мы могли бы суммировать жертве весь ей полученный урон вне проверок, которые нам все портят. Это был не только вопрос оптимизации.
Хотя... я не знаю ваших конечных целей, может так и задумано.

Но опять момент :(

Если OnDeathNotice в Pre вызывается позже TakeDamage_Post, то стоить заметить, что в TakeDamage_Post передается значение дамага, которое не зависит от значения максимального кол-ва ХП игрока. Поэтому, при смерти жертвы будет передан damage, который в сумме с предыдущим значением allDamage будет превышать стандартное значение хп игрока. На ум пала такая ситуация:
Игрок А нанес игроку Б - 99% урона. Другой атакующий С убьет игрока Б в голову с АВП... какой там дамаг, 450?
Все это суммируется, и в итоге игрок А ничего не получит с того, что почти убил игрока Б по тому, что он должен был нанести (99+450)/2 (или больше) хп.

Если же TakeDamage_Post дергается позже OnDeathNotice, то зачастую в allDamage будет занесено значение намного меньше потерянного хп игрока. А если убийца убьет выстрелом в хед, так там вообще могут быть числа ближе к нулю (с учетом дамага "лучшего" помощника)...

Получается, что в allDamage (она кстати у вас еще не типа float, это чревато проблемами (опечатка?)) попадет либо не весь дамаг, либо переменная будет носить значение выше стандартного значения хп игрока...

А теперь подумайте, отработает ли условие if (g_playerDamage[bestAttackerEntIndex][victimEntIndex] >= allDamage/2) так, как вы задумали. Простите, но никакими "честными 50%" тут не пахнет.

Вот, уже нашли пожалуй два бага, над которыми придется заморочиться, чтобы исправить. Но может все таки мы идем не тем путем?)
Получать и суммировать нанесенный дамаг в качестве получения ХП жертвы это, по моему, извращение. Так что ничего из того, что я описал выше - не подходит. Для процентного соотношения вообще правильно было бы получать максимальное кол-во хп игрока, но его надо где-то еще установить...

Да и реально полезным процентное соотношение наверно было бы только на картах, подобных 35hp (ох, для этой опять извращаться), и на серверах, где выдается дополнительное здоровье отдельным игрокам далеко за 100.
Для первого и остальных случаев можно спокойно обойтись и вариантом, который я предложил ранее, только изменить значение на необходимое. Во втором случае, в качестве решения первое, что пришло на ум, это получать хп каждого игрока где-то в пост спавне и заносить полученное значение в еще один глобальный массив, потом отнимать (при необходимости) урон "от самого себя" (he, падения). Или, как я уже упомянул, воспользоваться чем-то подобным (get_user_maxhealth(id) - damage)/2 в качестве замены allDamage/2 в качестве значения по умолчанию при объявлении maxDamage, и никакой allDamage не нужен (+так избавимся от доп. проверок).
damage - кол-во HP которое игрок потерял не от соперников (своя граната, упал), если первый баг вовсе не баг :)
Только я бы наверно поставил порог: floatmax((get_user_maxhealth(id) - damage)/2, 49.0)
Ну и set_user_maxhealth (или его аналог на том же реапи) в плагинах, где выдается доп. здоровье (ибо я сомневаюсь, что это учтено), или в этом же плагине при спавне в ПОСТ задавать set_user_maxhealth(id, get_user_health(id)), но тут уже нужно плагин ассистов подключать после плагинов выдачи хп, если без тасков. Если подумать, может можно еще решение найти какое-то...

В хуке смерти идет пробежка по всем игрокам и суммируем.
Такую задачу можно делать вне цикла, и в другом событии. Впрочем, у каждого свое мнение.
Доказывать, почему 1 итерация лучше 32 (ов шит, цикл носит MAX_PLAYERS итераций...) в какой-то промежуток времени, и почему в каждой итерации лучше выполнять наименьшее кол-во задач... ну наверно, в этом нету необходимости.
Да, я прекрасно понимаю что это никаких процентов с цп не снимет, но разделы о помощи на подобных форумах (да и не только), по моему и созданы для поиска лучших решений.

вот тут вы путаете переменные allDamage и maxDamage
Вовсе ничего не путаю. Я предложил правку в оригинальном исходном коде. И может вы не заметили, но это никак не касается ваших кусков кода.
28 Апр 2018
Да уж, убил свободное время...
 
Сообщения
2,491
Реакции
2,791
Помог
61 раз(а)
SerGrib, вот что что, а я и не задумывался об таких ньюансах. Наверно стоит в предамаге запоминать хп виктима, а в пост текущее отнимать от того, что запомнили ранее. Также вместо дамага хранить уже нужно будет отнятое хп. Ну и не забыть убирать проверку на виктим равно атакер. Теперь сумируем все отнятое хп, и получаем то хп которое игрок имел за время жизни. Потому как есть еще ньюансы в виде вампирика, бонусов хп, монеток и лечащих гранат
 

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

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