Portal SAMP
[Ajuda] Frequencias de voice - Versão de Impressão

+- Portal SAMP (https://portalsamp.com)
+-- Fórum: SA-MP (https://portalsamp.com/forumdisplay.php?fid=5)
+--- Fórum: Área de suporte (https://portalsamp.com/forumdisplay.php?fid=6)
+--- Tópico: [Ajuda] Frequencias de voice (/showthread.php?tid=2393)

Páginas: 1 2


Frequencias de voice - hiwyn - 16/05/2022

Então galera eu rodei o samp voice (https://github.com/CyberMor/sampvoice) simplesmente com o código da documentação

Ele local daquele jeito é bem legal pra servidor RP, eu tava pensando em fazer um modo diferente então voice local não funciona muito bem


Queria fazer algumas frequencias do voice, e quem tivesse nessas frequencias ouviria/falaria com todo mundo que também está nessa frequencia, tipo:

Código:
new voice_frequencia[MAX_PLAYERS];

Código:
if(frequency_id > 9999 || frequency_id < 1) return SendClientMessage(playerid, -1, "O numero deve ser entre 1 e 9999");


É viavel de fazer algo assim? 9999 frequencias do voice? Como fazer?


RE: Frequencias de voice - xbruno1000x - 16/05/2022

Tem um outro tópico que deve ajudá-lo:
https://portalsamp.com/thread-2049.html

O código de voip por frequencia pode ser retirado também do gamemode Nacional RP, também disponível aqui no fórum:
https://portalsamp.com/thread-2040.html


RE: Frequencias de voice - hiwyn - 16/05/2022

Tentei isso aqui, a principio funcionou, mas logo depois de um tempo com os players jogando depois dessa alteração o servidor crashou Sad

E parece que mesmo trocando de frequencia os players ainda estavam se ouvindo Sad


variaveis globais
Código:
#define MAX_RADIOS 9999
forward ConnectRadioVoice(playerid);
forward DisconnectRadioVoice(playerid);
new SV_GSTREAM:StreamFreq[MAX_RADIOS] = SV_NULL;
new players_in_radiofrequency[MAX_RADIOS];

funções
Código:
public ConnectRadioVoice(playerid) {
    new rfid = radio_frequency[playerid];
    if(StreamFreq[rfid] == SV_NULL)
    {
        new string[128];
        format(string, sizeof(string), "Radio %i", rfid);
        StreamFreq[rfid] = SvCreateGStream(0xFF00FFFF, string);
        SvAttachListenerToStream(StreamFreq[rfid], playerid);
    }
    else
    {
        SvAttachListenerToStream(StreamFreq[rfid], playerid);
    }
    players_in_radiofrequency[rfid] += 1;
    return 1;
}
public DisconnectRadioVoice(playerid) {
    new rfid = radio_frequency[playerid];
    players_in_radiofrequency[rfid] -= 1;
    if(players_in_radiofrequency[rfid] <= 0) {
       StreamFreq[rfid] = SV_NULL;
    }
    return 1;
}

botão pra falar
Código:
if(keyid == 0x42 && rstream[radio_frequency[playerid]]) {
            SvAttachSpeakerToStream(rstream[radio_frequency[playerid]], playerid);
        }

Código:
CMD:radio(playerid, params[]) {
    new frequency_id;
    if(sscanf(params,"i", frequency_id)) return SendClientMessage(playerid, -1, "Use: /testid [id]");
    if(frequency_id > MAX_RADIOS || frequency_id < 1) return SendClientMessage(playerid, -1, "O numero deve ser entre 1 e MAX_RADIOS");
    radio_frequency[playerid] = frequency_id;
    if(frequency_id == 0) DisconnectRadioVoice(playerid);
    else ConnectRadioVoice(playerid);
    return 1;
}



RE: Frequencias de voice - xbruno1000x - 16/05/2022

Acredito estar faltando um SvDetachSpeakerFromStream ao sair.


RE: Frequencias de voice - hiwyn - 17/05/2022

Não consegui Sad

2 problemas:

1- Você consegue ouvir e falar com qualquer frequencia, se vc se conecta em uma é como se tivesse em todas
2- Servidor Crasha algum tempo depois da galera usar o radio, trocar de frequencia (não sei exatamente o que ta fazendo crashar, mas é algo assim)


Vê se você consegue me dizer o pq, código:

variaveis globais
Código:
#define MAX_RADIOS 9999
forward ConnectRadioVoice(playerid);
forward DisconnectRadioVoice(playerid);
new SV_GSTREAM:StreamFreq[MAX_RADIOS] = SV_NULL;
new players_in_radiofrequency[MAX_RADIOS];

OnPlayerActivationKeyPress
Código:
// radio voice
if(radio_frequency[playerid] == 0) {
    SvAttachSpeakerToStream(StreamFreq[radio_frequency[playerid]], playerid);
}
// voice local
else {
    SvAttachSpeakerToStream(lstream[playerid], playerid);
}

OnPlayerActivationKeyRelease
Código:
// Detach the player from the local stream if the 'B' key is released
    if (keyid == 0x42 && lstream[playerid]) {
        SvDetachSpeakerFromStream(lstream[playerid], playerid);
    }
    // Detach the player from the local stream if the 'B' key is released
    if (keyid == 0x42 && StreamFreq[radio_frequency[playerid]]) {
        SvDetachSpeakerFromStream(StreamFreq[radio_frequency[playerid]], playerid);
    }

funções do comando
Código:
public ConnectRadioVoice(playerid) {
    new rfid = radio_frequency[playerid];
    if(StreamFreq[rfid] == SV_NULL)
    {
        new string[128];
        format(string, sizeof(string), "Radio %i", rfid);
        StreamFreq[rfid] = SvCreateGStream(0xFF00FFFF, string);
        SvAttachListenerToStream(StreamFreq[rfid], playerid);
    }
    else
    {
        SvAttachListenerToStream(StreamFreq[rfid], playerid);
    }
    players_in_radiofrequency[rfid] += 1;
    return 1;
}
public DisconnectRadioVoice(playerid) {
    new rfid = radio_frequency[playerid];
    players_in_radiofrequency[rfid] -= 1;
    if(players_in_radiofrequency[rfid] <= 0) {
       StreamFreq[rfid] = SV_NULL;
    }
    return 1;
}

comando
Código:
CMD:radio(playerid, params[]) {
    new frequency_id;
    if(sscanf(params,"i", frequency_id)) return SendClientMessage(playerid, -1, "Use: /testid [id]");
    if(frequency_id > MAX_RADIOS || frequency_id < 1) return SendClientMessage(playerid, -1, "O numero deve ser entre 1 e MAX_RADIOS");
    radio_frequency[playerid] = frequency_id;
    if(frequency_id == 0) DisconnectRadioVoice(playerid);
    else ConnectRadioVoice(playerid);
    return 1;
}



RE: Frequencias de voice - hiwyn - 19/05/2022

Entrei em um servidor que tinha essa feature, estou fazendo algo errado Sad
Tem alguma ideia do que é?


RE: Frequencias de voice - hiwyn - 08/06/2022

alguém tem alguma ideia? não sei mais o que fazer Sad


RE: Frequencias de voice - OTAKEIRO - 13/06/2022

Num testei... Afinal voip é meio complicado de mexer, mas acho que deve funcionar, tudo o que voce precisa fazer pra complementar é ativar o microfone quando o jogador pressionar para falar e usar DisconnectPlayer em OnPlayerDisconnect, em OnGameModeExit e em OnFilterScriptInit para prevenir que um canal não usado permaneça ocupando a memoria

Código:
enum SERVER_RADIO
{
Channel,
Listener,
SV_PTR:Audio
}

new
P_Radio[MAX_PLAYERS],
S_Radio[MAX_PLAYERS][SERVER_RADIO];

new Iterator:I_Radio<MAX_PLAYERS>;

CMD:radio(playerid, params[])
{
new string[255], integer;
if(sscanf(params, "d", integer))
{
if(P_Radio[playerid])
{
format(string, sizeof(string), "[RADIO] Seu canal atual: %d", P_Radio[playerid]);
SendClientMessage(playerid, -1, string);
}

SendClientMessage(playerid, -1, "[RADIO] Utilize /radio [1 a 9999] para alterar o canal");
SendClientMessage(playerid, -1, "[RADIO] Utilize /radio 0 para desligar o radio");
}
else
{
if(P_Radio[playerid] != integer)
{
if(integer == 0)
{
integer = FindChannel(integer);
DisconnectPlayer(playerid, integer);
SendClientMessage(playerid, -1, "[RADIO] O seu radio foi desligado!");
}
else if(1 <= integer <= 9999)
{
DisconnectPlayer(playerid);
P_Radio[playerid] = integer;

if(!FindChannel(integer))
{
integer = Iter_Free(I_Radio);
Iter_Add(I_Radio, integer);

S_Radio[integer][Channel] = P_Radio[playerid];
S_Radio[integer][Audio] = SvCreateGStream(0, "Radio");
}

SvAttachListenerToStream(S_Radio[channel][Audio], playerid);
SvAttachSpeakerToStream(S_Radio[channel][Audio], playerid);
S_Radio[channel][Listener]++;

format(string, sizeof(string), "[RADIO] Voce foi conectado ao canal: %d", P_Radio[playerid]);
SendClientMessage(playerid, -1, string);
}
else CallLocalFunction("OnPlayerCommandText", "ds", playerid, "/radio");
}
else
{
if(integer == 0) SendClientMessage(playerid, -1, "[ERRO] O seu radio nao esta ligado!");
else SendClientMessage(playerid, -1, "[ERRO] Voce ja esta ouvindo esse canal!");
}
}
return 1;
}

FindChannel(&dest)
{
foreach(new i : I_Radio)
{
if(S_Radio[i][Channel] == dest)
{
dest = i;
return 1;
}
}
return 0;
}

DisconnectPlayer(playerid, channel = P_Radio[playerid])
{
SvDetachListenerFromStream(S_Radio[channel][Audio], playerid);
SvDetachSpeakerFromStream(S_Radio[channel][Audio], playerid);
P_Radio[playerid] = 0;

if(0 == --S_Radio[channel][Listener])
{
Iter_Remove(I_Radio, channel);
SvDeleteStream(S_Radio[channel][Audio]);
}
}

Fiz com que o canal fosse deletado se nao tivesse ouvintes
E usei iterador pra pesquisar um campo livre no array pq o array é de 1000 caracters (padrão do MAX_PLAYERS), acho desnecessário um array de 9999


RE: Frequencias de voice - hiwyn - 18/10/2022

(13/06/2022 05:03)OTAKEIRO Escreveu: Num testei... Afinal voip é meio complicado de mexer, mas acho que deve funcionar, tudo o que voce precisa fazer pra complementar é ativar o microfone quando o jogador pressionar para falar e usar DisconnectPlayer em OnPlayerDisconnect, em OnGameModeExit e em OnFilterScriptInit para prevenir que um canal não usado permaneça ocupando a memoria

Código:
enum SERVER_RADIO
{
Channel,
Listener,
SV_PTR:Audio
}

new
P_Radio[MAX_PLAYERS],
S_Radio[MAX_PLAYERS][SERVER_RADIO];

new Iterator:I_Radio<MAX_PLAYERS>;

CMD:radio(playerid, params[])
{
new string[255], integer;
if(sscanf(params, "d", integer))
{
if(P_Radio[playerid])
{
format(string, sizeof(string), "[RADIO] Seu canal atual: %d", P_Radio[playerid]);
SendClientMessage(playerid, -1, string);
}

SendClientMessage(playerid, -1, "[RADIO] Utilize /radio [1 a 9999] para alterar o canal");
SendClientMessage(playerid, -1, "[RADIO] Utilize /radio 0 para desligar o radio");
}
else
{
if(P_Radio[playerid] != integer)
{
if(integer == 0)
{
integer = FindChannel(integer);
DisconnectPlayer(playerid, integer);
SendClientMessage(playerid, -1, "[RADIO] O seu radio foi desligado!");
}
else if(1 <= integer <= 9999)
{
DisconnectPlayer(playerid);
P_Radio[playerid] = integer;

if(!FindChannel(integer))
{
integer = Iter_Free(I_Radio);
Iter_Add(I_Radio, integer);

S_Radio[integer][Channel] = P_Radio[playerid];
S_Radio[integer][Audio] = SvCreateGStream(0, "Radio");
}

SvAttachListenerToStream(S_Radio[channel][Audio], playerid);
SvAttachSpeakerToStream(S_Radio[channel][Audio], playerid);
S_Radio[channel][Listener]++;

format(string, sizeof(string), "[RADIO] Voce foi conectado ao canal: %d", P_Radio[playerid]);
SendClientMessage(playerid, -1, string);
}
else CallLocalFunction("OnPlayerCommandText", "ds", playerid, "/radio");
}
else
{
if(integer == 0) SendClientMessage(playerid, -1, "[ERRO] O seu radio nao esta ligado!");
else SendClientMessage(playerid, -1, "[ERRO] Voce ja esta ouvindo esse canal!");
}
}
return 1;
}

FindChannel(&dest)
{
foreach(new i : I_Radio)
{
if(S_Radio[i][Channel] == dest)
{
dest = i;
return 1;
}
}
return 0;
}

DisconnectPlayer(playerid, channel = P_Radio[playerid])
{
SvDetachListenerFromStream(S_Radio[channel][Audio], playerid);
SvDetachSpeakerFromStream(S_Radio[channel][Audio], playerid);
P_Radio[playerid] = 0;

if(0 == --S_Radio[channel][Listener])
{
Iter_Remove(I_Radio, channel);
SvDeleteStream(S_Radio[channel][Audio]);
}
}

Fiz com que o canal fosse deletado se nao tivesse ouvintes
E usei iterador pra pesquisar um campo livre no array pq o array é de 1000 caracters (padrão do MAX_PLAYERS), acho desnecessário um array de 9999

Opa desculpa a demora, não vi sua resposta

Tentei adaptar sua sugestão pra FilterScript pra todo mundo aqui do fórum conseguir usar, já que muitos pedem esse sistema, mas quando um jogador da /radio 1 o servidor crasha

Código:
#include <a_samp>
#include <sampvoice>

#include <sscanf2>
#include <zcmd>

// global chat adm 1
new SV_GSTREAM:gstream = SV_NULL;

// local chat player 1
new SV_LSTREAM:lstream[MAX_PLAYERS] = { SV_NULL, ... };

// radio 1
enum SERVER_RADIO
{
  Channel,
  Listener,
  SV_PTR:Audio,
}
new P_Radio[MAX_PLAYERS];
new S_Radio[MAX_PLAYERS][SERVER_RADIO];
forward DisconnectPlayerFromRadio(playerid, channel);
forward FindChannelFromRadio(dest);
new Last_Iter_Radio = 0;

// GM 1
// new GetPVarInt(playerid,"hasVoiceOnClient")
// 0 = sem voice, 1 = com voice, 2 = com voice, sem mic

// GM 2
// GetPVarInt(playerid,"talkStats")
// tipo de fala pra verificar se ta falando no chat ou no radio

// GM 3
// GetPVarInt(playerid,"admin")
// pra dizer se é admin

public SV_VOID:OnPlayerActivationKeyPress(SV_UINT:playerid, SV_UINT:keyid)
{
    // Press 'B'
    if (keyid == 0x42) {
        // radio voice 2
        new rfid = GetPVarInt(playerid,"radio_frequency");
        if(GetPVarInt(playerid,"talkStats") == 3) {
            if(S_Radio[rfid][Audio]) SvAttachSpeakerToStream(S_Radio[rfid][Audio], playerid);
        }
        // local chat player 2
        else {
            if(lstream[playerid]) SvAttachSpeakerToStream(lstream[playerid], playerid);
        }
    }
    // Press 'Z' (admins)
    if(GetPVarInt(playerid,"admin") >= 6) {
        if (keyid == 0x5A && gstream) SvAttachSpeakerToStream(gstream, playerid);
    }
}

public SV_VOID:OnPlayerActivationKeyRelease(SV_UINT:playerid, SV_UINT:keyid)
{
    // Release 'B'
    if (keyid == 0x42) {
        if(lstream[playerid]) SvDetachSpeakerFromStream(lstream[playerid], playerid);
        new rfid = GetPVarInt(playerid,"radio_frequency");
        if (S_Radio[rfid][Audio]) SvDetachSpeakerFromStream(S_Radio[rfid][Audio], playerid);
    }
    // Release 'Z'
    if (keyid == 0x5A) {
        if(gstream) SvDetachSpeakerFromStream(gstream, playerid);
    }
}

public OnPlayerConnect(playerid) {
    // Checking for plugin availability
    if (SvGetVersion(playerid) == SV_NULL)
    {
        SendClientMessage(playerid, -1, "Could not find plugin sampvoice.");
        SetPVarInt(playerid,"hasVoiceOnClient",0);
    }
    // Checking for a microphone
    else if (SvHasMicro(playerid) == SV_FALSE)
    {
        SendClientMessage(playerid, -1, "The microphone could not be found.");
        SetPVarInt(playerid,"hasVoiceOnClient",2);
    }
    // Create a local stream with an audibility distance of 40.0, an unlimited number of listeners
    // and the name 'Local' (the name 'Local' will be displayed in red in the players' speakerlist)
    else if ((lstream[playerid] = SvCreateDLStreamAtPlayer(40.0, SV_INFINITY, playerid, 0xff0000ff, "Local")))
    {
        // Attach the player to the global stream as a listener
        if (gstream) SvAttachListenerToStream(gstream, playerid);

        // Assign microphone activation keys to the player
        SvAddKey(playerid, 0x42);
        SvAddKey(playerid, 0x5A);

        //
        SetPVarInt(playerid,"hasVoiceOnClient",1);
    }
}
public OnPlayerDisconnect(playerid, reason) {
    // Removing the player's local stream after disconnecting
    if (lstream[playerid])
    {
        SvDeleteStream(lstream[playerid]);
        lstream[playerid] = SV_NULL;
    }
    // remove radio stream after disconnecting
    new rfid = GetPVarInt(playerid,"radio_frequency");
    if(S_Radio[rfid][Audio]) {
        SvDeleteStream(S_Radio[rfid][Audio]);
        S_Radio[rfid][Audio] = SV_NULL;
    }
}
public OnFilterScriptInit() {
    // samp voice 5
    gstream = SvCreateGStream(0xffff0000, "Global");
    // radio, prevenir que um canal não usado permaneça ocupando a memoria
    for(new i = 0; i < Last_Iter_Radio; i++)
    {
      if(S_Radio[i][Audio]) {
        SvDeleteStream(S_Radio[i][Audio]);
      }
    }
}
public OnFilterScriptExit() {
    // samp voice 6
    if (gstream) SvDeleteStream(gstream);
    // radio, prevenir que um canal não usado permaneça ocupando a memoria
    for(new i = 0; i < Last_Iter_Radio; i++)
    {
      if(S_Radio[i][Audio]) {
        SvDeleteStream(S_Radio[i][Audio]);
      }
    }
}



// radio voice 5
public DisconnectPlayerFromRadio(playerid, channel)
{
  P_Radio[playerid] = 0;
  if(channel != 0)
  {
      SvDetachListenerFromStream(S_Radio[channel][Audio], playerid);
      SvDetachSpeakerFromStream(S_Radio[channel][Audio], playerid);
      if(0 == --S_Radio[channel][Listener])
      {
        Last_Iter_Radio--;
        SvDeleteStream(S_Radio[channel][Audio]);
      }
  }
}
public FindChannelFromRadio(dest)
{
  for(new i = 0; i < Last_Iter_Radio; i++)
  {
    if(S_Radio[i][Channel] == dest)
    {
      dest = i;
      return 1;
    }
  }
  return 0;
}
CMD:radio(playerid, params[])
{
  new string[255], integer;
  if(sscanf(params, "d", integer))
  {
    if(P_Radio[playerid])
    {
      format(string, sizeof(string), "[RADIO] Seu canal atual: %d", P_Radio[playerid]);
      SendClientMessage(playerid, -1, string);
    }
    SendClientMessage(playerid, -1, "[RADIO] Utilize /radio [1 a 9999] para alterar o canal");
    SendClientMessage(playerid, -1, "[RADIO] Utilize /radio 0 para desligar o radio");
    return true;
  }

  if(P_Radio[playerid] != integer)
  {
    // invalido
    if(integer < 1 || integer > 9999) {
      SendClientMessage(playerid, -1, "As frequencias so vao de 1 a 9999!");
      return true;
    }
    // 0 = desligar radio
    if(integer == 0)
    {
      DisconnectPlayerFromRadio(playerid, P_Radio[playerid]);
      SendClientMessage(playerid, -1, "[RADIO] O seu radio foi desligado!");
    }
    // trocar de frequencia
    else if(1 <= integer <= 9999)
    {
      if(P_Radio[playerid] != 0) DisconnectPlayerFromRadio(playerid, P_Radio[playerid]);
      P_Radio[playerid] = integer;

      if(!FindChannelFromRadio(integer))
      {
          Last_Iter_Radio++;
          S_Radio[integer][Channel] = P_Radio[playerid];
          S_Radio[integer][Audio] = SvCreateGStream(0, "Radio");
      }

      SvAttachListenerToStream(S_Radio[integer][Audio], playerid);
      S_Radio[integer][Listener]++;

      format(string, sizeof(string), "[RADIO] Voce foi conectado ao canal: %d", P_Radio[playerid]);
      SendClientMessage(playerid, -1, string);
    }
  }
  else
  {
    if(integer == 0) SendClientMessage(playerid, -1, "[ERRO] O seu radio nao esta ligado!");
    else SendClientMessage(playerid, -1, "[ERRO] Voce ja esta ouvindo esse canal!");
  }
  return 1;
}

fiz algo errado ou tem algo errado no script mesmo?


RE: Frequencias de voice - hiwyn - 21/10/2022

(18/10/2022 21:10)hiwyn Escreveu:
(13/06/2022 05:03)OTAKEIRO Escreveu: Num testei... Afinal voip é meio complicado de mexer, mas acho que deve funcionar, tudo o que voce precisa fazer pra complementar é ativar o microfone quando o jogador pressionar para falar e usar DisconnectPlayer em OnPlayerDisconnect, em OnGameModeExit e em OnFilterScriptInit para prevenir que um canal não usado permaneça ocupando a memoria

Código:
enum SERVER_RADIO
{
Channel,
Listener,
SV_PTR:Audio
}

new
P_Radio[MAX_PLAYERS],
S_Radio[MAX_PLAYERS][SERVER_RADIO];

new Iterator:I_Radio<MAX_PLAYERS>;

CMD:radio(playerid, params[])
{
new string[255], integer;
if(sscanf(params, "d", integer))
{
if(P_Radio[playerid])
{
format(string, sizeof(string), "[RADIO] Seu canal atual: %d", P_Radio[playerid]);
SendClientMessage(playerid, -1, string);
}

SendClientMessage(playerid, -1, "[RADIO] Utilize /radio [1 a 9999] para alterar o canal");
SendClientMessage(playerid, -1, "[RADIO] Utilize /radio 0 para desligar o radio");
}
else
{
if(P_Radio[playerid] != integer)
{
if(integer == 0)
{
integer = FindChannel(integer);
DisconnectPlayer(playerid, integer);
SendClientMessage(playerid, -1, "[RADIO] O seu radio foi desligado!");
}
else if(1 <= integer <= 9999)
{
DisconnectPlayer(playerid);
P_Radio[playerid] = integer;

if(!FindChannel(integer))
{
integer = Iter_Free(I_Radio);
Iter_Add(I_Radio, integer);

S_Radio[integer][Channel] = P_Radio[playerid];
S_Radio[integer][Audio] = SvCreateGStream(0, "Radio");
}

SvAttachListenerToStream(S_Radio[channel][Audio], playerid);
SvAttachSpeakerToStream(S_Radio[channel][Audio], playerid);
S_Radio[channel][Listener]++;

format(string, sizeof(string), "[RADIO] Voce foi conectado ao canal: %d", P_Radio[playerid]);
SendClientMessage(playerid, -1, string);
}
else CallLocalFunction("OnPlayerCommandText", "ds", playerid, "/radio");
}
else
{
if(integer == 0) SendClientMessage(playerid, -1, "[ERRO] O seu radio nao esta ligado!");
else SendClientMessage(playerid, -1, "[ERRO] Voce ja esta ouvindo esse canal!");
}
}
return 1;
}

FindChannel(&dest)
{
foreach(new i : I_Radio)
{
if(S_Radio[i][Channel] == dest)
{
dest = i;
return 1;
}
}
return 0;
}

DisconnectPlayer(playerid, channel = P_Radio[playerid])
{
SvDetachListenerFromStream(S_Radio[channel][Audio], playerid);
SvDetachSpeakerFromStream(S_Radio[channel][Audio], playerid);
P_Radio[playerid] = 0;

if(0 == --S_Radio[channel][Listener])
{
Iter_Remove(I_Radio, channel);
SvDeleteStream(S_Radio[channel][Audio]);
}
}

Fiz com que o canal fosse deletado se nao tivesse ouvintes
E usei iterador pra pesquisar um campo livre no array pq o array é de 1000 caracters (padrão do MAX_PLAYERS), acho desnecessário um array de 9999

Opa desculpa a demora, não vi sua resposta

Tentei adaptar sua sugestão pra FilterScript pra todo mundo aqui do fórum conseguir usar, já que muitos pedem esse sistema, mas quando um jogador da /radio 1 o servidor crasha

Código:
#include <a_samp>
#include <sampvoice>

#include <sscanf2>
#include <zcmd>

// global chat adm 1
new SV_GSTREAM:gstream = SV_NULL;

// local chat player 1
new SV_LSTREAM:lstream[MAX_PLAYERS] = { SV_NULL, ... };

// radio 1
enum SERVER_RADIO
{
  Channel,
  Listener,
  SV_PTR:Audio,
}
new P_Radio[MAX_PLAYERS];
new S_Radio[MAX_PLAYERS][SERVER_RADIO];
forward DisconnectPlayerFromRadio(playerid, channel);
forward FindChannelFromRadio(dest);
new Last_Iter_Radio = 0;

// GM 1
// new GetPVarInt(playerid,"hasVoiceOnClient")
// 0 = sem voice, 1 = com voice, 2 = com voice, sem mic

// GM 2
// GetPVarInt(playerid,"talkStats")
// tipo de fala pra verificar se ta falando no chat ou no radio

// GM 3
// GetPVarInt(playerid,"admin")
// pra dizer se é admin

public SV_VOID:OnPlayerActivationKeyPress(SV_UINT:playerid, SV_UINT:keyid)
{
    // Press 'B'
    if (keyid == 0x42) {
        // radio voice 2
        new rfid = GetPVarInt(playerid,"radio_frequency");
        if(GetPVarInt(playerid,"talkStats") == 3) {
            if(S_Radio[rfid][Audio]) SvAttachSpeakerToStream(S_Radio[rfid][Audio], playerid);
        }
        // local chat player 2
        else {
            if(lstream[playerid]) SvAttachSpeakerToStream(lstream[playerid], playerid);
        }
    }
    // Press 'Z' (admins)
    if(GetPVarInt(playerid,"admin") >= 6) {
        if (keyid == 0x5A && gstream) SvAttachSpeakerToStream(gstream, playerid);
    }
}

public SV_VOID:OnPlayerActivationKeyRelease(SV_UINT:playerid, SV_UINT:keyid)
{
    // Release 'B'
    if (keyid == 0x42) {
        if(lstream[playerid]) SvDetachSpeakerFromStream(lstream[playerid], playerid);
        new rfid = GetPVarInt(playerid,"radio_frequency");
        if (S_Radio[rfid][Audio]) SvDetachSpeakerFromStream(S_Radio[rfid][Audio], playerid);
    }
    // Release 'Z'
    if (keyid == 0x5A) {
        if(gstream) SvDetachSpeakerFromStream(gstream, playerid);
    }
}

public OnPlayerConnect(playerid) {
    // Checking for plugin availability
    if (SvGetVersion(playerid) == SV_NULL)
    {
        SendClientMessage(playerid, -1, "Could not find plugin sampvoice.");
        SetPVarInt(playerid,"hasVoiceOnClient",0);
    }
    // Checking for a microphone
    else if (SvHasMicro(playerid) == SV_FALSE)
    {
        SendClientMessage(playerid, -1, "The microphone could not be found.");
        SetPVarInt(playerid,"hasVoiceOnClient",2);
    }
    // Create a local stream with an audibility distance of 40.0, an unlimited number of listeners
    // and the name 'Local' (the name 'Local' will be displayed in red in the players' speakerlist)
    else if ((lstream[playerid] = SvCreateDLStreamAtPlayer(40.0, SV_INFINITY, playerid, 0xff0000ff, "Local")))
    {
        // Attach the player to the global stream as a listener
        if (gstream) SvAttachListenerToStream(gstream, playerid);

        // Assign microphone activation keys to the player
        SvAddKey(playerid, 0x42);
        SvAddKey(playerid, 0x5A);

        //
        SetPVarInt(playerid,"hasVoiceOnClient",1);
    }
}
public OnPlayerDisconnect(playerid, reason) {
    // Removing the player's local stream after disconnecting
    if (lstream[playerid])
    {
        SvDeleteStream(lstream[playerid]);
        lstream[playerid] = SV_NULL;
    }
    // remove radio stream after disconnecting
    new rfid = GetPVarInt(playerid,"radio_frequency");
    if(S_Radio[rfid][Audio]) {
        SvDeleteStream(S_Radio[rfid][Audio]);
        S_Radio[rfid][Audio] = SV_NULL;
    }
}
public OnFilterScriptInit() {
    // samp voice 5
    gstream = SvCreateGStream(0xffff0000, "Global");
    // radio, prevenir que um canal não usado permaneça ocupando a memoria
    for(new i = 0; i < Last_Iter_Radio; i++)
    {
      if(S_Radio[i][Audio]) {
        SvDeleteStream(S_Radio[i][Audio]);
      }
    }
}
public OnFilterScriptExit() {
    // samp voice 6
    if (gstream) SvDeleteStream(gstream);
    // radio, prevenir que um canal não usado permaneça ocupando a memoria
    for(new i = 0; i < Last_Iter_Radio; i++)
    {
      if(S_Radio[i][Audio]) {
        SvDeleteStream(S_Radio[i][Audio]);
      }
    }
}



// radio voice 5
public DisconnectPlayerFromRadio(playerid, channel)
{
  P_Radio[playerid] = 0;
  if(channel != 0)
  {
      SvDetachListenerFromStream(S_Radio[channel][Audio], playerid);
      SvDetachSpeakerFromStream(S_Radio[channel][Audio], playerid);
      if(0 == --S_Radio[channel][Listener])
      {
        Last_Iter_Radio--;
        SvDeleteStream(S_Radio[channel][Audio]);
      }
  }
}
public FindChannelFromRadio(dest)
{
  for(new i = 0; i < Last_Iter_Radio; i++)
  {
    if(S_Radio[i][Channel] == dest)
    {
      dest = i;
      return 1;
    }
  }
  return 0;
}
CMD:radio(playerid, params[])
{
  new string[255], integer;
  if(sscanf(params, "d", integer))
  {
    if(P_Radio[playerid])
    {
      format(string, sizeof(string), "[RADIO] Seu canal atual: %d", P_Radio[playerid]);
      SendClientMessage(playerid, -1, string);
    }
    SendClientMessage(playerid, -1, "[RADIO] Utilize /radio [1 a 9999] para alterar o canal");
    SendClientMessage(playerid, -1, "[RADIO] Utilize /radio 0 para desligar o radio");
    return true;
  }

  if(P_Radio[playerid] != integer)
  {
    // invalido
    if(integer < 1 || integer > 9999) {
      SendClientMessage(playerid, -1, "As frequencias so vao de 1 a 9999!");
      return true;
    }
    // 0 = desligar radio
    if(integer == 0)
    {
      DisconnectPlayerFromRadio(playerid, P_Radio[playerid]);
      SendClientMessage(playerid, -1, "[RADIO] O seu radio foi desligado!");
    }
    // trocar de frequencia
    else if(1 <= integer <= 9999)
    {
      if(P_Radio[playerid] != 0) DisconnectPlayerFromRadio(playerid, P_Radio[playerid]);
      P_Radio[playerid] = integer;

      if(!FindChannelFromRadio(integer))
      {
          Last_Iter_Radio++;
          S_Radio[integer][Channel] = P_Radio[playerid];
          S_Radio[integer][Audio] = SvCreateGStream(0, "Radio");
      }

      SvAttachListenerToStream(S_Radio[integer][Audio], playerid);
      S_Radio[integer][Listener]++;

      format(string, sizeof(string), "[RADIO] Voce foi conectado ao canal: %d", P_Radio[playerid]);
      SendClientMessage(playerid, -1, string);
    }
  }
  else
  {
    if(integer == 0) SendClientMessage(playerid, -1, "[ERRO] O seu radio nao esta ligado!");
    else SendClientMessage(playerid, -1, "[ERRO] Voce ja esta ouvindo esse canal!");
  }
  return 1;
}

fiz algo errado ou tem algo errado no script mesmo?

alguém tem alguma ideia?