Исправить ошибки EmitSoundToClient

Тема в разделе "Программирование / Скриптинг", создана пользователем pokypka20, 17 окт 2014.

  1. pokypka20

    pokypka20

    Сообщения:
    250
    Симпатии:
    30
    Почему возникает такая ошибка и как её исправить?

    PHP:
    #include <sourcemod>
    #include <sdktools>
    new sec;

    #define ONE "music/zr/csgo/1.wav"
    #define TWO "music/zr/csgo/2.wav"
    #define THREE "music/zr/csgo/3.wav"

    public OnPluginStart() HookEvent("round_start"Event_RoundStartEventHookMode_PostNoCopy);

    public 
    OnMapStart()
    {
        
    PrecacheSound("music/zr/csgo/1.wav");
        
    PrecacheSound("music/zr/csgo/2.wav");
        
    PrecacheSound("music/zr/csgo/3.wav");
    }

    public 
    Event_RoundStart(Handle:event, const String:name[], bool:dontBroadcast)
    {
            
    sec GetConVarInt(FindConVar("mp_freezetime"));
            
    CreateTimer(1.0AreYouReady_TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
    }

    public 
    Action:AreYouReady(Handle:timer)
    {
        for (new 
    1<= MaxClientsi++)
        {
        if (--
    sec 0)
        {
            if (
    sec == 3
            {
                
    EmitSoundToClient(iTHREE);
            }
            else if (
    sec == 2
            {
                
    EmitSoundToClient(iTWO);
            }
            else if    (
    sec == 1
            {
                
    EmitSoundToClient(iONE);
            }
            return 
    Plugin_Continue;
        }
        }
        return 
    Plugin_Stop;
    }

    PHP:
    L 10/17/2014 13:34:40: [SMNative "EmitSound" reportedClient 1 is not connected
    L 10
    /17/2014 13:34:40: [SMDisplaying call stack trace for plugin "round_start_massage.smx":
    L 10/17/2014 13:34:40: [SM]   [0]  Line 379D:\Новая папка (155)\Новая папка\scripting\include\sdktools_sound.inc::EmitSoundToClient()
    L 10/17/2014 13:34:40: [SM]   [1]  Line 33D:\Новая папка (155)\Новая папка\scripting\round_start_massage.sp::AreYouReady()
    L 10/17/2014 13:34:41: [SMNative "EmitSound" reportedClient 1 is not connected
    L 10
    /17/2014 13:34:41: [SMDisplaying call stack trace for plugin "round_start_massage.smx":
    L 10/17/2014 13:34:41: [SM]   [0]  Line 379D:\Новая папка (155)\Новая папка\scripting\include\sdktools_sound.inc::EmitSoundToClient()
    L 10/17/2014 13:34:41: [SM]   [1]  Line 38D:\Новая папка (155)\Новая папка\scripting\round_start_massage.sp::AreYouReady()
     
  2. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.514
    Симпатии:
    1.967
    Потому что ты используешь цикл для получения индексов клиентов, а в нём всегда обязательно использование проверки if (IsClientInGame(i)) или if (IsClientConnected(i)) (гораздо реже).
    А вообще, у тебя бред в таймере - звуки будут лишь у единиц людей и разные.
    Если "mp_freezetime" будет 3, то звука 3 также не будет вовсе, даже при исправленном цикле таймера.
     
    Последнее редактирование: 17 окт 2014
    pokypka20 и R1KO нравится это.
  3. pokypka20

    pokypka20

    Сообщения:
    250
    Симпатии:
    30
    Покажи пожалуйста пример как правильно, я только понял что нужно добавить поверку IsClientInGame, но ошибки остались.
     
  4. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.975
    Симпатии:
    2.981
    Так наверное:
    PHP:
    #include <sourcemod> 
    #include <sdktools> 

    new const String:g_sSounds[][] =
    {
        
    "music/zr/csgo/1.wav",
        
    "music/zr/csgo/2.wav",
        
    "music/zr/csgo/3.wav" 
    };

    new 
    iSec;


    public 
    OnPluginStart() HookEvent("round_start"Event_RoundStartEventHookMode_PostNoCopy); 

    public 
    OnMapStart() 

        for (new 
    0iSize sizeof(g_sSounds); iSize; ++iPrecacheSound(g_sSounds[i]); 


    public 
    Event_RoundStart(Handle:event, const String:name[], bool:dontBroadcast)
    {
        
    iSec GetConVarInt(FindConVar("mp_freezetime"));
        if(
    iSec == 3CreateTimer(1.0AreYouReady_TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
        else if(
    iSec 3CreateTimer(float(iSec-3), Delay);
    }

    public 
    Action:Delay(Handle:timer
    {
        
    CreateTimer(1.0AreYouReady_TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
        return 
    Plugin_Stop
    }

    public 
    Action:AreYouReady(Handle:timer

        if(--
    iSec >= 0)
        {
            for (new 
    0iSize sizeof(g_sSounds); iSize; ++iEmitSoundToAll(g_sSounds[i]); 
            return 
    Plugin_Continue
        }
        return 
    Plugin_Stop

    P.S. Это только попытка, я даже компилировать не пробывал. Так что не наезжайте.
     
    Серый™ и pokypka20 нравится это.
  5. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.514
    Симпатии:
    1.967
    pokypka20, полный пример:
    PHP:
    #include <sdktools_sound>
    #include <sdktools_stringtables>

    #define NUM 3
    new const String:Path[NUM][] =
    {
        
    "music/zr/csgo/3.wav",
        
    "music/zr/csgo/2.wav",
        
    "music/zr/csgo/1.wav"
    };

    public 
    OnPluginStart()
    {
        new 
    Handle:mp_freezetime FindConVar("mp_freezetime");
        if (
    mp_freezetime != INVALID_HANDLE)
        {
            
    HookConVarChange(mp_freezetimeFreezeTime);
            
    CTM(mp_freezetime);
            
    CloseHandle(mp_freezetime);
            
    HookEvent("round_start"Event_RoundStartEventHookMode_PostNoCopy);
        }else 
    SetFailState("ConVar \"mp_freezetime\" not found!");
    }

    new 
    secsetFloat:wait;

    public 
    FreezeTime(Handle:convar, const String:oldValue[], const String:newValue[]) CTM(convar);

    public 
    OnConfigsExecuted()
    {
        
    decl String:buffer[100];
        for (new 
    iNUMi++)
        {
            
    PrecacheSound(Path[i]);
            
    Format(buffer100"sound/%s"Path[i]);
            
    AddFileToDownloadsTable(buffer);
        }
    }

    public 
    Event_RoundStart(Handle:event, const String:name[], bool:dontBroadcast)
    {
        
    CreateTimer(waitTimeWait_TIMER_FLAG_NO_MAPCHANGE);
        
    sec set;
    }

    public 
    Action:TimeWait(Handle:timerTriggerTimer(CreateTimer(1.0AreYouReady_TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE));

    public 
    Action:AreYouReady(Handle:timer
    {
        if (--
    sec >= 0)
        {
            for (new 
    1<= MaxClientsi++)
            {
                if (
    IsClientInGame(i) && !IsFakeClient(i)) EmitSoundToClient(iPath[sec]);
            }
            return 
    Plugin_Continue;
        }
        return 
    Plugin_Stop
    }

    CTM(Handle:convar)
    {
        new 
    Float:accurate GetConVarFloat(convar);
        if ((
    set RoundToFloor(accurate)) <= NUMwait accurate set;
        else
        {
            
    set NUM;
            
    wait accurate NUM;
        }

    Где CTM(Handle:convar) - функция синхронизации звука (включая любые нецелые значения mp_freezetime, например, mp_freezetime "3.8").
     
    pokypka20 нравится это.
  6. gibs

    gibs Фитиль народного волненья

    Сообщения:
    536
    Симпатии:
    133
    А нафига вам вообще цикл, если есть EmitSoundToAll() ?
    ТС такой не очень)))
     
  7. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.975
    Симпатии:
    2.981
    Оффтоп
     
  8. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.514
    Симпатии:
    1.967
    Это абсолютно такой же цикл + разные прибамбасы, вроде return и нет выбора, например, чтобы поставить IsFakeClient(client) (ботам звук воспроизводить не имеет смысла).
    R1KO, смотри API внимательнее - может быть хуже по ресурсам и нагрузке.

    Кстати, если раунд по каким-либо причинам закончится раньше (например, все убиты через админку), то это может иметь плохие последствия (нужно ещё убивать таймер).
    Оффтоп
     
  9. gibs

    gibs Фитиль народного волненья

    Сообщения:
    536
    Симпатии:
    133
    Нуу, вообще то ты в корне не прав.
    PHP:
    stock EmitSoundToAll(const String:sample[],
                     
    entity SOUND_FROM_PLAYER,
                     
    channel SNDCHAN_AUTO,
                     
    level SNDLEVEL_NORMAL,
                     
    flags SND_NOFLAGS,
                     
    Float:volume SNDVOL_NORMAL,
                     
    pitch SNDPITCH_NORMAL,
                     
    speakerentity = -1,
                     const 
    Float:origin[3] = NULL_VECTOR,
                     const 
    Float:dir[3] = NULL_VECTOR,
                     
    bool:updatePos true,
                     
    Float:soundtime 0.0)
    {
        new 
    clients[MaxClients];
        new 
    total 0;
        
        for (new 
    i=1i<=MaxClientsi++)
        {
            if (
    IsClientInGame(i))
            {
                
    clients[total++] = i;
            }
        }
        
        if (!
    total)
        {
            return;
        }
        
        
    EmitSound(clientstotalsampleentitychannel
            
    levelflagsvolumepitchspeakerentity,
            
    origindirupdatePossoundtime);
    }
    А теперь подумай, что напряжней: вызов одной функции, в которую просто передается массив пользователей, или же спам безсмысленным циклом.
     
  10. AlmazON

    AlmazON деревянный © yand3xmail

    Сообщения:
    4.514
    Симпатии:
    1.967
    То же самое почти передаётся:
    PHP:
    stock EmitSoundToClient(client,
                     const 
    String:sample[],
                     
    entity SOUND_FROM_PLAYER,
                     
    channel SNDCHAN_AUTO,
                     
    level SNDLEVEL_NORMAL,
                     
    flags SND_NOFLAGS,
                     
    Float:volume SNDVOL_NORMAL,
                     
    pitch SNDPITCH_NORMAL,
                     
    speakerentity = -1,
                     const 
    Float:origin[3] = NULL_VECTOR,
                     const 
    Float:dir[3] = NULL_VECTOR,
                     
    bool:updatePos true,
                     
    Float:soundtime 0.0)
    {
        new 
    clients[1];
        
    clients[0] = client;
        
    /* Save some work for SDKTools and remove SOUND_FROM_PLAYER references */
        
    entity = (entity == SOUND_FROM_PLAYER) ? client entity;
        
    EmitSound(clients1sampleentitychannel
            
    levelflagsvolumepitchspeakerentity,
            
    origindirupdatePossoundtime);
    }
    Плохо, что переменная пересоздаётся, но зато ботов можно отключать + забыл наблюдателей (их бы я тоже лучше выкинул).
    В идеале, конечно лучше просто вынесенная функция с All, куда подставляем своё.
    PrintToChatAll, например, точно будет хуже вместо такого же цикла.
    Оффтоп