Лимит на использование микрофона

Сообщения
1,032
Реакции
828
Помог
10 раз(а)
SISA, та я о другом немного подумал, каша в голове уже
 
Сообщения
1,032
Реакции
828
Помог
10 раз(а)
SISA, сейчас вроде работает, протестировал правда поверхностно.

C++:
public CSGameRules_CanPlayerHearPlayer(const iListener, const iSender) {
    if(iSender != iListener) {
        if(g_bCantTalk[iSender]) {
            SetHookChainReturn(ATYPE_INTEGER, false);
            return HC_BREAK;
        }
      
        if(g_bCantHearDead[iListener]) {
            if(g_bAlive[iListener] && !g_bAlive[iSender]) {
                SetHookChainReturn(ATYPE_INTEGER, false);
                return HC_BREAK;
            }
        }
    }

    return HC_CONTINUE;
}

public VTC_OnClientStartSpeak(const id) {
    if(VTC_IsClientMuted(id)) {
        return PLUGIN_CONTINUE;
    }
  
    if(g_iNumSpeakers >= VOICE_LIMIT) {
        g_bCantTalk[id] = true;
      
        static aPlayersID[MAX_PLAYERS], iPlayersNum;
        get_players_ex(aPlayersID, iPlayersNum, GetPlayers_ExcludeBots | GetPlayers_ExcludeHLTV);
      
        static iListener, iSender; iSender = id;
        for(new i; i < iPlayersNum; i++) {
            iListener = aPlayersID[i];
          
            if(iListener == id) continue;
          
            engfunc(EngFunc_SetClientListening, iListener, iSender, false);
        }
    }
  
    g_iNumSpeakers++;
  
    return PLUGIN_CONTINUE;
}

public VTC_OnClientStopSpeak(const id) {
    if(g_bCantTalk[id]) {
        g_bCantTalk[id] = false;
    }
  
    g_iNumSpeakers--;
}

Код:
#include <amxmodx>
#include <fakemeta>
#include <amxmisc>
#include <nvault>
#include <reapi>

#pragma semicolon 1

const INACTIVITY_DAYS                = 7;                    // Удалять неактивных игроков через 'n' дней
const SECONDS_IN_DAY                = 86400;                    // Количество секунд в одном дне
const Float:TIME_AFTER_DEATH        = 5.0;                    // Время после смерти, через которое живые не услышат мертвого игрока
const VOICE_LIMIT                    = 1;                    // Лимит на одновременное использование микрофона

const AUTHID_STRLEN                    = 24;
const NAME_STRLEN                    = 32;
const MESSAGE_STRLEN                = 512;
const TIME_STRLEN                    = 32;
const PATH_STRLEN                    = 64;
const ELLIPSES_ARG                    = 4;
const START_TIME                    = 0;

new g_iVaultID;
new g_iNumSpeakers;
new g_sLogsDir[PATH_STRLEN];

new bool:g_bAlive[MAX_PLAYERS + 1];
new bool:g_bCantHearDead[MAX_PLAYERS + 1];
new bool:g_bCantTalk[MAX_PLAYERS + 1];

public plugin_init() {
    register_plugin("Voice Manager", "1.0", "Javekson");
  
    RegisterHookChain(RG_CBasePlayer_Spawn, "CBasePlayer_Spawn", .post = true);
    RegisterHookChain(RG_CBasePlayer_Killed, "CBasePlayer_Killed", .post = true);
    RegisterHookChain(RG_CSGameRules_CanPlayerHearPlayer, "CSGameRules_CanPlayerHearPlayer", .post = false);
  
    register_clcmd("say /vc", "ClCmdVoice");
}

public plugin_cfg() {
    get_localinfo("amxx_logs", g_sLogsDir, charsmax(g_sLogsDir));
    add(g_sLogsDir, charsmax(g_sLogsDir), "/voice_manager");
    if(!dir_exists(g_sLogsDir)) mkdir(g_sLogsDir);
  
    g_iVaultID = nvault_open("voice_manager");
    nvault_prune(g_iVaultID, START_TIME, get_systime() - SECONDS_IN_DAY * INACTIVITY_DAYS);
}

public client_putinserver(id) {
    new sAuthID[AUTHID_STRLEN];
    get_user_authid(id, sAuthID, charsmax(sAuthID));
  
    if((g_bCantHearDead[id] = bool:nvault_get(g_iVaultID, sAuthID))) {
        nvault_touch(g_iVaultID, sAuthID);
    }
}

public plugin_end() {
    nvault_close(g_iVaultID);
}

public CBasePlayer_Spawn(id) {
    g_bAlive[id] = true;
}

public CBasePlayer_Killed(id) {
    set_task_ex(TIME_AFTER_DEATH, "task_AfterDeath", .flags = SetTask_Once);
}

public CSGameRules_CanPlayerHearPlayer(const iListener, const iSender) {
    if(iSender != iListener) {
        if(g_bCantTalk[iSender]) {
            SetHookChainReturn(ATYPE_INTEGER, false);
            return HC_BREAK;
        }
      
        if(g_bCantHearDead[iListener]) {
            if(g_bAlive[iListener] && !g_bAlive[iSender]) {
                SetHookChainReturn(ATYPE_INTEGER, false);
                return HC_BREAK;
            }
        }
    }
  
    return HC_CONTINUE;
}

public VTC_OnClientStartSpeak(const id) {
    if(VTC_IsClientMuted(id)) {
        return PLUGIN_CONTINUE;
    }
  
    if(g_iNumSpeakers >= VOICE_LIMIT) {
        g_bCantTalk[id] = true;
      
        static aPlayersID[MAX_PLAYERS], iPlayersNum;
        get_players_ex(aPlayersID, iPlayersNum, GetPlayers_ExcludeBots | GetPlayers_ExcludeHLTV);
      
        static iListener, iSender; iSender = id;
        for(new i; i < iPlayersNum; i++) {
            iListener = aPlayersID[i];
          
            if(iListener == id) continue;
          
            engfunc(EngFunc_SetClientListening, iListener, iSender, false);
        }
    }
  
    g_iNumSpeakers++;
  
    return PLUGIN_CONTINUE;
}

public VTC_OnClientStopSpeak(const id) {
    if(g_bCantTalk[id]) {
        g_bCantTalk[id] = false;
    }
  
    g_iNumSpeakers--;
}

public ClCmdVoice(const id) {
    new sAuthID[AUTHID_STRLEN], sName[NAME_STRLEN];
    get_user_authid(id, sAuthID, charsmax(sAuthID));
    get_user_name(id, sName, charsmax(sName));
  
    if(g_bCantHearDead[id]) {
        g_bCantHearDead[id] = false;
        nvault_remove(g_iVaultID, sAuthID);
      
        client_print_color(id, print_team_default, "^4* ^1[^4GMF^1] Теперь ^4Вы ^1слышите всех ^4игроков");
        logging(g_sLogsDir, "voice_manager_", "^"%-32s %-32s Слышит всех игроков^"", sAuthID, sName);
      
        return PLUGIN_CONTINUE;
    }
  
    g_bCantHearDead[id] = true;
    nvault_set(g_iVaultID, sAuthID, "1");
  
    client_print_color(id, print_team_default, "^4* ^1[^4GMF^1] Теперь ^4Вы ^1слышите только ^4живых игроков");
    logging(g_sLogsDir, "voice_manager_", "^"%-32s %-32s Слышит только живых игроков^"", sAuthID, sName);
  
    return PLUGIN_CONTINUE;
}

public task_AfterDeath(id) {
    g_bAlive[id] = false;
}

stock logging(const sLogsDir[], const sFileName[], const sMessage[], any:...) {
    new sFmtMsg[MESSAGE_STRLEN], sTime[TIME_STRLEN], sLogFile[PATH_STRLEN + 32], iFileID;
    vformat(sFmtMsg, charsmax(sFmtMsg), sMessage, ELLIPSES_ARG);
    get_time("%m.%Y.log", sTime, charsmax(sTime));
    formatex(sLogFile, charsmax(sLogFile), "%s/%s%s", sLogsDir, sFileName, sTime);
    iFileID = fopen(sLogFile, "at");
    get_time("%d.%m.%Y - %H:%M:%S", sTime, charsmax(sTime));
    fprintf(iFileID, "^"%s^" %s^n", sTime, sFmtMsg);
    fclose(iFileID);
}
 
Сообщения
1,293
Реакции
2,294
Помог
57 раз(а)
Javekson, а зачем делать инкремент g_iNumSpeakers, если игрок не получает право говорить (ну и декремент по той же схеме) ? Допустим, лимит одновременно говорящих = 1. Начинаешь говорить ты = тебе позволяется. Начинаю говорить я = мне не позволяется. При этом g_iNumSpeakers уже 2. Ты отпустил кнопку = g_iNumSpeakers стал 1. Я держу кнопку (вообще не отпускаю), меня не слышно, но и никто не может говорить. Тут логичнее менять счётчик только тогда, когда это необходимо. Тогда уже те, кто начал говорить во время действия лимита, просто не будут услышаны, пока не отпустят кнопку, и не нажмут её заново. Чтобы игроки не терялись в этой "магии", можно по центру выдавать поясняющую инфу тем, кто пытается говорить вне очереди.
 
Последнее редактирование:
Сообщения
1,032
Реакции
828
Помог
10 раз(а)
а зачем делать инкремент g_iNumSpeakers, если игрок не получает право говорить (ну и декремент по той же схеме) ?
А как я еще сверю, есть лимит или нет? Лимит в 1 я поставил для теста, а так будет стоять возможность говорить трем людям, или я тебя не правильно понимаю сейчас.

Тогда уже те, кто начал говорить во время действия лимита, просто не будут услышаны
Я это заметил, потому думаю как исправить, что бы в режиме реального времени я мог его услышать

можно по центру выдавать поясняющую инфу тем
Разумеется будет, пока только тестирую
 

Ayk

Сообщения
763
Реакции
478
Помог
19 раз(а)
if(iSender != iListener) {
А когда игрок сам себя может слышать?
 
Сообщения
1,032
Реакции
828
Помог
10 раз(а)
В общем ребят, провозился дня два с этим лимитом, исправил один баг, нашел два других.

В целом ситуация следующая. Проблема именно в клиенте Steam. Удалось понять благодаря BlackSignature
VTC_OnClientStartSpeak на нем срабатывает только тогда, когда я начинаю издавать звук(слова), а не по факту нажатия клавиши.
Тоже самое и с VTC_OnClientStopSpeak сработает тогда, когда я перестану издавать звук, ему все ровно что зажата клавиша.

В любой пиратской версии, включая ReClient, такой проблемы нету, форварды работают только при нажатии/отжатии клавиши и никак иначе.

Поэтому лимит должным образом реализовать не получается, я могу случайно перебить человека, который зевнул в микрофон тихонько и толкнуть его в лимит благодаря кривой работе клиента. Связался с простотемой, костылить он не хочет, да и действительно это глупо будет, посоветовал просто написать на гитхаб с просьбой добавить возможность перехватывать нажатие клавиши микрофона.

Собственно в этом проблема, меня там нету и англ я от слова совсем не знаю, потому буду признателен если кто-то поможет с этим.

Артем:
и типа предложи чтобы можно было перехватывать когда K нажимается
через какой-нибудь IN_* в entvars_t::buttons
На бета-клиенте стима не тестировал
 
Сообщения
198
Реакции
16
Помог
1 раз(а)
интересно, я тоже думал что-то подобное сделать. автор, будьте добры, поделитесь в итоге конечным кодом, вам сочтется.
кстати, не совсем понимаю, зачем создавать массив на всех игроков, если можно обойтись глобальной переменной? пока один говорит, для остальных = 1 (назовем это запретом) и вызов мута. в любом случае, я буду следить за темой, благодарю всех за ответы и автору за полезную для меня тему.
 
Сообщения
1,032
Реакции
828
Помог
10 раз(а)
kucklovod, как я выше написал, что не могу реализовать нормальный лимит, так-как стим не совсем корректно ловиться, отсюда вытекают неприятные моменты. Глобальная переменная у меня будет ровняться двум-трем, что значит, только два-три человека смогут одновременно разговаривать, а массив нужен, что бы функция понимала через условие чей поток необходимо отсеивать.
 

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

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