Стрельба по n-ое количество патронов на ПКМ.

Сообщения
67
Реакции
18
Доброго времени, захотелось улучшить некоторое кастомное оружие, не имеющего активного действия на ПКМ возможностью менять режим огня, как у автомата FAMAS у КТ или пистолета Glock-19 у ТТ. Начал искать реализацию, наткнулся на один плагин пулемёта ПКМ из CSO, где ввинтили следующую реализацию (буду комментировать, чтобы проверить своё понимание):

Код:
//Создание переменной смена режима стрельбы
new g_mode[33]

//Собственно, функция, отвечающая за смену режима стрельба (через старый, добрый и немножечко тяжёлый форвард FM_CmdStart)

public fw_CmdStart(id, uc_handle, seed)
{
    if(!g_isalive[id] || !g_has_pkm[id] || get_user_weapon(id) != CSW_M249)
        return PLUGIN_HANDLED

    static button; button = get_uc(uc_handle, UC_Buttons)
    static oldbutton; oldbutton = pev(id, pev_oldbuttons)

    if((button & IN_ATTACK2) && !(oldbutton & IN_ATTACK2))
    {
        switch(g_mode[id])
        {
            case 0: g_mode[id] = 1   //Полуавтоматика 3 патрона
            case 1: g_mode[id] = 0     //Автомат
        }
        mode_message(id) // Сообщение о смене режима
    }
    return PLUGIN_HANDLED
}

//Сама стрельба пулемёта
public fw_pkm_PrimaryAttack_Post(Weapon)
{
    g_IsInPrimaryAttack = 0
    new Player = get_pdata_cbase(Weapon, 41, 4)
    
    new szClip, szAmmo
    get_user_weapon(Player, szClip, szAmmo)
    
    if(!g_isalive[Player])
        return

    if(g_has_pkm[Player])
    {
        if (!g_clip_ammo[Player])
            return
        //Подозреваю, что это имитация отдачи (тряски) при стрельбе
        new Float:push[3]
        pev(Player,pev_punchangle,push)
        xs_vec_sub(push,cl_pushangle[Player],push)
        xs_vec_mul_scalar(push,cvar_recoil_pkm,push)
        xs_vec_add(push,cl_pushangle[Player],push)
        set_pev(Player,pev_punchangle,push)
        //Собсна начало стрельбы тремя патронами
        if(g_mode[Player] == 1)
        {
            switch(szClip)
            {
                case 148: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 145: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 142: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 139: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 136: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 133: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 130: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 127: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 124: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 121: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 118: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 115: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 112: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 109: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 106: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 103: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 100: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 97: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 94: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 91: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 88: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 85: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 82: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 79: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 76: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 73: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 70: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 67: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 64: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 61: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 58: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 55: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 52: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 49: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 46: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 43: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 40: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 37: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 34: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 31: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 28: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 25: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 22: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 19: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 16: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 13: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 10: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 7: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
                case 4: set_pdata_float(Player, m_flNextAttack, 0.6, PLAYER_LINUX_XTRA_OFF)
            }
        }
        emit_sound(Player, CHAN_WEAPON, Fire_Sounds[0], VOL_NORM, ATTN_NORM, 0, PITCH_NORM)
        UTIL_PlayWeaponAnimation(Player, random_num(pkm_SHOOT1, pkm_SHOOT2))
    }
}
Как я понял, здесь улавливается количество патронов в строгой верхней ограниченности (150 по исходному квару) и уже от этого числа начинаются танцы по мере отсчёта трёх пуль. Реализация, конечно, мне понравилась, но всё же кажется немного дубовой.
Вопрос: Есть ли ещё варианты реализации стрельбы по три/два патрона, кроме как в приведённом выше примере? Может уже есть какой нибудь форвард в ReAPI для этого?
 
Сообщения
336
Реакции
414
Помог
7 раз(а)
У меня есть незаконченный плагин на реапи, хотел сделать фамас режим для всех винтовок(мка, калаш, ауг, галил). Удалось только сделать стрельбу по 3 птр, если зажата лкм, если один раз нажать, то не стреляло 3 раза, я вроде не смог полноценно имитировать адекватную стрельбу по 3 птр
 
Сообщения
67
Реакции
18
Albertio, звучит неплохо, как реализовывал стрельбу по три патрона?
 
Сообщения
336
Реакции
414
Помог
7 раз(а)
R1ner,
Код:
#include <amxmodx>
#include <engine>
#include <hamsandwich>
#include <reapi>
#include <xs>

new g_aRifles[][] = {
    "weapon_aug",
    "weapon_galil",
    "weapon_m4a1",
    "weapon_sg552",
    "weapon_ak47"
};  // Оружия на которых будет работать серийная стрельба -- Weapons on which serial shooting will work

new Float:cl_pushangle[MAX_PLAYERS + 1][3], Float:g_DelayBursts;
new g_iClip[MAX_PLAYERS + 1], g_iBurstFire[MAX_PLAYERS + 1], g_FlashLightState;
new bool:m_bUsing[MAX_PLAYERS + 1];

public plugin_init()
{
    register_plugin("Burst-Fire For Rifles", "0.0.1", "Albertio");

    register_dictionary("burst_fire_rifles.txt");
    
    for(new i = 0; i < sizeof(g_aRifles); i++)
    {
        RegisterHam(Ham_Weapon_PrimaryAttack, g_aRifles[i], "Weapon_PrimaryAttack_Post", true);
        RegisterHam(Ham_Weapon_Reload, g_aRifles[i], "Weapon_Reload_Pre", false);
    }

    register_impulse(100, "EngineHook_Impulse");

    bind_pcvar_float(create_cvar("delay_between_bursts", "0.4", FCVAR_NONE, fmt("%L", LANG_SERVER, "DELAY_BETWEEN_BURSTS_CVAR"),
    true, 0.1, true, 1.0), g_DelayBursts); // Время между очередями стрельбы -- Time between bursts of shooting
    bind_pcvar_num(create_cvar("flashlight_state", "1", FCVAR_NONE, fmt("%L", LANG_SERVER, "FLASHLIGHT_STATE"),
    true, 0.0, true, 1.0), g_FlashLightState); // Выключать фонарик при использовании серийной стрельбы -- Turn off the flashlight when using serial shooting

    AutoExecConfig(true, "burst_fire_rifles");
}

public client_putinserver(id)
{
    g_iBurstFire[id] = 0;
    g_iClip[id] = 0;
    m_bUsing[id] = false;
}

// Отлов использования фонарика -- Catching the use of a flashlight
public EngineHook_Impulse(const iIndex)
{
    for(new i = 0; i < sizeof(g_aRifles); i++)
    {
        if(get_user_weapon(iIndex) == get_weaponid(g_aRifles[i][0]))
        {
            g_iBurstFire[iIndex] = !g_iBurstFire[iIndex];
            client_print(iIndex, print_center, "%L %s", iIndex, "SWITCHED_TO", g_iBurstFire[iIndex] ? fmt("%L", iIndex, "BF_MODE") : fmt("%L", iIndex, "FA_MODE"));
            return g_FlashLightState ? PLUGIN_HANDLED : PLUGIN_CONTINUE;
        }
    }

    return PLUGIN_CONTINUE;
}

// Отлов выстрелов -- Catching shots
public Weapon_PrimaryAttack_Post(weapon)
{
    new Float:push[3], iPlayer = get_member(weapon, m_pPlayer);
    
    if(!g_iBurstFire[iPlayer] || !is_user_alive(iPlayer))
    {
        return;
    }
    
    if(m_bUsing[iPlayer])
    {
        get_entvar(iPlayer, var_punchangle, push);
        xs_vec_sub(push, cl_pushangle[iPlayer], push);
        xs_vec_mul_scalar(push, g_DelayBursts, push);
        xs_vec_add(push, cl_pushangle[iPlayer], push);
        set_entvar(iPlayer, var_punchangle, push);
        
        g_iClip[iPlayer]++;
        
        if(g_iClip[iPlayer] == 3)
        {
            set_member(iPlayer, m_flNextAttack, g_DelayBursts);
            g_iClip[iPlayer] = 0;
            return;
        }
    }
}

// Отлов перезарядки -- Catching a recharge
public Weapon_Reload_Pre(weapon)
{
    new iPlayer = get_member(weapon, m_pPlayer);

    if(!g_iBurstFire[iPlayer] || !is_user_alive(iPlayer))
    {
        return;
    }

    g_iClip[iPlayer] = 0;
}
 
Последнее редактирование:
Сообщения
67
Реакции
18
Albertio, внушительно. А что вообще думаешь по реализации в первом сообщении?
 
Сообщения
336
Реакции
414
Помог
7 раз(а)
R1ner, не знаю даже что сказать, да, может быть у меня не идеальный код, но то, что ты скинул уверенно херня и неоптимизированно, начиная от использования нагрузочной функции FM_CmdStart, заканчивая кейсами в 50 штук....
 
Сообщения
67
Реакции
18
Albertio, ну, FM_CmdStart дело поправимое с ReAPI, в курсе про её нагрузку, а вот стрельба по три...
Ладно, для пулемёта на 150 патронов, а если скажем обойма на 30 патронов = 10 кейсов, сильно большая нагрузка на сервер, если скажем, человек 15-20 будет использовать такое оружие?
 
Сообщения
336
Реакции
414
Помог
7 раз(а)
R1ner, дак я писал выше, столько кейсов = говнокод
 
Сообщения
1,304
Реакции
2,303
Помог
57 раз(а)
Код фамаса в регейме смотрели?
 
Сообщения
67
Реакции
18
Код фамаса в регейме смотрели?
Нет, даже не догадывался искать в том направлении, поскольку не знаю что там может быть и как с ним работать.
Но готов изучить и понять вашу мысль, если вы мне её объясните подробнее, поскольку свободный поиск мне ничего не дал.
Хочу уточнить, что мне нужна не подстановка режима огня фамаса под кастомное оружие, а возможность сделать режим на два-три-четыре выстрела у различного оружия (к примеру есть АН-94, которому я бы сделал возможность режима стрельбы по 2 патрона а не по три).

За прошедшее время появилась только идея с созданием короткого таймера стрельбы после которого оружие бы делало паузу, подогнав значения таймера к скорострельности оружия так чтобы успевало выстрелить 2-3-4-5 патронов.
 

iPlague

♿️
Сообщения
230
Реакции
130
Помог
2 раз(а)
Albertio, что мне пришло в голову - сделать nextattack 0.3, в curweapon считать выстрелы, после 2 выстрелов выставлять nextattack 1.0
получится 2 выстрела сразу, пауза, 2 выстрела, это при зажатой ЛКМ.

а можно executeHam(primary_atack..) и выставлять nextattack для паузы?

имхо дичь я предлагаю, но на изучение фамаса в регейме мозгов не хватает.
 
Сообщения
106
Реакции
222
Помог
1 раз(а)
+

Все основные проверки тут -

Просто в итемфрейме проверяем на необходимость автоматических выстрелов

Что интересно, к слову у фамаса
2 выстрел идёт через m_flFamasShoot = gpGlobals->time + 0.05f;
а 3 выстрел через float nexttime = 0.1f; shootTime = gpGlobals->time + nexttime
Не знаю с чем связано:)
 
Сообщения
857
Реакции
532
Помог
13 раз(а)
Что интересно, к слову у фамаса
2 выстрел идёт через m_flFamasShoot = gpGlobals->time + 0.05f;
а 3 выстрел через float nexttime = 0.1f; shootTime = gpGlobals->time + nexttime
Не знаю с чем связано:)
 

hajimura

Е777КХ05
Сообщения
290
Реакции
228
Помог
6 раз(а)
2 выстрел идёт через
Это не совсем так. Код
Код:
m_flFamasShoot = gpGlobals->time + 0.05f;
выполнится только для первого выстрела. Остальные 2 патрона выстреливаются через функцию FireRemaining, которая вызывается в ItemPostFrame до тех пор, пока m_flFamasShoot больше значения gpGlobals->time или не обнулится. А этот мембер обнуляется в момент спавна Фамаса, либо в момент, когда игрок его достает
 
Последнее редактирование:
Сообщения
106
Реакции
222
Помог
1 раз(а)
hajimura, Я имею в виду, что получается так: 1 выстрел идет в момент нажатия на кнопку атаки, следующий через 0.05 секунд после первого выстрела, последний после 0.15 после первого выстрела, хотя вроде бы как логично было что 3 выстрел идет через 0.1 после первого, но возможно это специальная механика фамаса.
Поскольку у того же глока второй выстрел идет через 0.1 и третий тоже через 0.1
А тут разница.
 

hajimura

Е777КХ05
Сообщения
290
Реакции
228
Помог
6 раз(а)
Faktor, там все три выстрела Фамаса выполнятся за 0.05 сек. PrimaryAttack вызывается лишь в момент нажатия ЛКМ
И так, разберем один цикл выстрела в режиме по три патрона: ПКМ (Вызовем SecondaryAttack(), переключив Фамас в режим по три патрона) -> ЛКМ (Вызовем PrimaryAttack()) -> в PrimaryAttack() выставляется m_flFamasShoot значение gpGlobals->time + 0.05f -> Далее работает ItemPostFrame(), который, в свою очередь, при условии будет запускать FireRemaining() -> Остальные 2 выстрела выполняются в функции FireRemaining()
 
Сообщения
106
Реакции
222
Помог
1 раз(а)
hajimura, Я честно не понимаю, почему все три выстрела за 0.05 будут.
Я понимаю, что Вы описываете и скидывал это в своём первом сообщении, но насколько можно видеть по коду это выглядит так:
ЛКМ (Вызовем PrimaryAttack()) -> Делаем первый выстрел ->выставляется m_flFamasShoot значение gpGlobals->time + 0.05f -> Далее работает ItemPostFrame(), который через 0.05f после первого выстрела вызовет FireRemaining()-> в FireRemaining() совершится выстрел(на текущий момент отстреляно 2/3) и выставится следующий выстрел через shootTime = gpGlobals->time + nexttime где nexttime это float nexttime = 0.1f; поскольку он нигде не изменяется и выставляется единоразово в начале FireRemaining()
В итоге получается выстрел+выстрел через 0.05+выстрел через 0.1, вся очередь за 0.15сек
Я не прав?)
 

hajimura

Е777КХ05
Сообщения
290
Реакции
228
Помог
6 раз(а)
Faktor, да, Вы правы. Не обратил внимание, что в FireRemaining() передаются не значения аргументов, а адреса этих переменных. Все верно, я ошибся. Только три патрона выстрелятся за 0.25 только, не за 0.15. FireRemaining() вызовется дважды, поэтому 0.05 + 0.1 + 0.1 = 0.25
 

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

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