O maior portal de MU Online do Brasil — desde 2003
Tutorial Intermediário Tutoriais

Como Criar Sistema de Voto e Recompensa no Servidor de MU Online

Aprenda a implementar um sistema de voto com recompensa automática no seu servidor de MU Online usando SQL Server, PHP e sites de votação como GTOP100 e Xtremetop100.

EQ Equipe ViciadosMU · Atualizado em 3 jul 2026 · ⏱ 12 min de leitura

Visão Geral do Sistema

Um sistema de voto e recompensa incentiva os jogadores a divulgarem seu servidor nos principais sites de ranking de servidores privados de MU Online, como GTOP100, Xtremetop100 e MuOnline.com.br. Cada voto contabiliza pontos no ranking e, em contrapartida, o jogador recebe itens, Zen, W-Coins ou resets automáticos.

O fluxo completo funciona assim:

Site de votação → Pingback HTTP para seu servidor → Script PHP recebe e valida → Registro no SQL Server → Stored Procedure entrega a recompensa

Nota: Este tutorial cobre servidores Season 6 com MuServer em SQL Server 2008/2012/2014. Para Season 13+, os nomes de tabelas podem variar — confirme consultando o esquema do seu banco antes de executar qualquer comando.

Passo 1: Criar a Tabela de Controle de Votos no SQL Server

Abra o SQL Server Management Studio (SSMS) e conecte ao banco MuOnline. Execute:

USE MuOnline;
GO

CREATE TABLE VoteLog (
    VoteID      INT IDENTITY(1,1) PRIMARY KEY,
    AccountID   VARCHAR(10)  NOT NULL,
    SiteID      VARCHAR(30)  NOT NULL,  -- 'gtop100', 'xtremetop100', etc.
    VoteKey     VARCHAR(64)  NOT NULL,  -- chave única retornada pelo site
    VoteDate    DATETIME     NOT NULL DEFAULT GETDATE(),
    VoteStatus  TINYINT      NOT NULL DEFAULT 0,  -- 0=pendente, 1=entregue
    IPAddress   VARCHAR(45)  NOT NULL DEFAULT ''
);
GO

-- Índice para consultas rápidas por conta
CREATE INDEX IX_VoteLog_AccountID ON VoteLog (AccountID, VoteStatus);
GO
Dica: O campo VoteKey armazena o token único que o site de votação envia no pingback. Ele serve como prova de voto legítimo e evita inserções duplicadas — crie uma constraint UNIQUE nele se quiser proteção extra: ALTER TABLE VoteLog ADD CONSTRAINT UQ_VoteKey UNIQUE (VoteKey);

Passo 2: Criar a Stored Procedure de Entrega de Recompensa

A stored procedure lê votos pendentes e insere os itens de recompensa na tabela de personagem. Ajuste ItemCode, ItemLevel e ItemOpt conforme a recompensa que deseja oferecer.

USE MuOnline;
GO

CREATE PROCEDURE SP_DeliverVoteReward
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @AccountID  VARCHAR(10)
    DECLARE @CharName   VARCHAR(10)
    DECLARE @VoteID     INT

    -- Cursor percorre todos os votos pendentes
    DECLARE cur CURSOR FOR
        SELECT VoteID, AccountID
        FROM VoteLog
        WHERE VoteStatus = 0
        ORDER BY VoteDate ASC

    OPEN cur
    FETCH NEXT FROM cur INTO @VoteID, @AccountID

    WHILE @@FETCH_STATUS = 0
    BEGIN
        -- Pega o personagem mais recente da conta
        SELECT TOP 1 @CharName = Name
        FROM Character
        WHERE AccountID = @AccountID
        ORDER BY ConnectStat DESC, ResetCount DESC

        IF @CharName IS NOT NULL
        BEGIN
            -- Entrega 200 W-Coins (ajuste WCoinP conforme seu sistema de coins)
            UPDATE MEMB_INFO
            SET WCoinP = ISNULL(WCoinP, 0) + 200
            WHERE memb___id = @AccountID

            -- Opcional: entregar item físico via tabela de depósito
            -- INSERT INTO ITEM_STORE (AccountID, ItemCode, ItemLevel, ItemDur, ItemOpt)
            -- VALUES (@AccountID, 7936, 0, 255, 0)  -- exemplo: Box of Kundun+5

            -- Marca voto como entregue
            UPDATE VoteLog
            SET VoteStatus = 1
            WHERE VoteID = @VoteID
        END

        FETCH NEXT FROM cur INTO @VoteID, @AccountID
    END

    CLOSE cur
    DEALLOCATE cur
END
GO
Atenção: A coluna de W-Coins varia por versão do MuServer. Em algumas versões é WCoinP, em outras é wcoin_p ou GoblinPoint. Execute SELECT TOP 1 * FROM MEMB_INFO no seu banco para confirmar o nome exato da coluna antes de rodar a procedure.

Passo 3: Configurar o Script PHP de Recebimento (Pingback)

Crie o arquivo vote_callback.php no diretório raiz do seu site (ex.: C:\AppServ\www\seusite\vote_callback.php ou C:\xampp\htdocs\seusite\vote_callback.php):

<?php
// vote_callback.php — Receptor de pingback de votos
// Coloque este arquivo em: /public_html/vote_callback.php ou equivalente

define('DB_SERVER', 'localhost');   // IP do SQL Server
define('DB_USER',   'sa');          // usuário do SQL Server
define('DB_PASS',   'SuaSenha123'); // senha do SQL Server
define('DB_NAME',   'MuOnline');

// Chave secreta configurada no painel do GTOP100 / Xtremetop100
define('VOTE_SECRET', 'minha_chave_secreta_aqui');

// Conecta ao SQL Server via PDO com driver SQLSRV
try {
    $dsn = "sqlsrv:Server=" . DB_SERVER . ";Database=" . DB_NAME;
    $pdo = new PDO($dsn, DB_USER, DB_PASS);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    http_response_code(500);
    exit('DB error');
}

// --- GTOP100 ---
if (isset($_GET['pingback']) && $_GET['pingback'] === VOTE_SECRET) {
    $accountID = preg_replace('/[^a-zA-Z0-9]/', '', $_GET['pingbackkey'] ?? '');
    $voteKey   = md5($_GET['pingbackkey'] . time());
    $ip        = $_SERVER['REMOTE_ADDR'];

    if (empty($accountID)) {
        http_response_code(400);
        exit('Invalid account');
    }

    // Verifica voto duplicado nas últimas 12 horas
    $stmt = $pdo->prepare("
        SELECT COUNT(*) FROM VoteLog
        WHERE AccountID = ? AND SiteID = 'gtop100'
          AND VoteDate > DATEADD(HOUR, -12, GETDATE())
    ");
    $stmt->execute([$accountID]);
    if ($stmt->fetchColumn() > 0) {
        http_response_code(200);
        exit('Already voted');
    }

    // Registra o voto
    $stmt = $pdo->prepare("
        INSERT INTO VoteLog (AccountID, SiteID, VoteKey, IPAddress)
        VALUES (?, 'gtop100', ?, ?)
    ");
    $stmt->execute([$accountID, $voteKey, $ip]);

    http_response_code(200);
    exit('OK');
}

// --- Xtremetop100 ---
if (isset($_POST['pingbackkey'])) {
    $accountID = preg_replace('/[^a-zA-Z0-9]/', '', $_POST['pingbackkey']);
    $voteKey   = $_POST['pingbackkey'] . '_xt_' . time();
    $ip        = $_SERVER['REMOTE_ADDR'];

    $stmt = $pdo->prepare("
        SELECT COUNT(*) FROM VoteLog
        WHERE AccountID = ? AND SiteID = 'xtremetop100'
          AND VoteDate > DATEADD(HOUR, -12, GETDATE())
    ");
    $stmt->execute([$accountID]);
    if ($stmt->fetchColumn() > 0) { exit('1'); }

    $stmt = $pdo->prepare("
        INSERT INTO VoteLog (AccountID, SiteID, VoteKey, IPAddress)
        VALUES (?, 'xtremetop100', ?, ?)
    ");
    $stmt->execute([$accountID, $voteKey, $ip]);
    exit('1'); // Xtremetop100 espera '1' como confirmação
}

http_response_code(400);
exit('Bad request');
?>
Dica: Para instalar o driver PDO do SQL Server no PHP, baixe o php_pdo_sqlsrv_XX_ts.dll compatível com sua versão do PHP em microsoft.com/sqlsrv e adicione ao php.ini: extension=php_pdo_sqlsrv_XX_ts.dll. Reinicie o Apache/IIS após alterar o arquivo.

Passo 4: Configurar o SQL Server Agent para Executar a Recompensa

A stored procedure precisa ser executada automaticamente a cada poucos minutos. No SQL Server Management Studio:

  1. Expanda SQL Server AgentJobs → clique direito → New Job
  2. Em General: Nome = EntregarRecompensaVoto
  3. Em StepsNew Step:
  • Step name: Executar SP
  • Type: Transact-SQL script (T-SQL)
  • Database: MuOnline
  • Command:

``sql EXEC SP_DeliverVoteReward; ``

  1. Em SchedulesNew Schedule:
  • Name: A cada 5 minutos
  • Frequency: Daily, Every 5 minutes
  1. Clique em OK para salvar o job.
Nota: O SQL Server Agent só funciona se o serviço estiver iniciado. Verifique em Services (services.msc) que SQL Server Agent (MSSQLSERVER) está como Running e com startup Automatic.

Passo 5: Configurar o Painel dos Sites de Votação

GTOP100

  1. Acesse seu painel em gtop100.com → seu servidor → Edit Listing
  2. Em Pingback URL insira: http://seudominio.com/vote_callback.php?pingback=minha_chave_secreta_aqui
  3. Em Pingback Variable Name coloque: pingbackkey
  4. O jogador acessa a URL de voto: http://gtop100.com/vote/SEUID?pingbackkey=nomeconta

Xtremetop100

  1. Acesse seu painel → Edit ServerIn-game Reward Voting
  2. Em Reward URL: http://seudominio.com/vote_callback.php
  3. Em Variable name: pingbackkey
Atenção: O IP do seu servidor (onde o PHP roda) precisa estar liberado no firewall para receber conexões HTTP na porta 80 ou 443. Se usar Windows Firewall, crie uma regra de entrada: netsh advfirewall firewall add rule name="HTTP Vote" protocol=TCP dir=in localport=80 action=allow

Passo 6: Criar a Página de Voto no Site do Servidor

Adicione ao site um formulário onde o jogador informa o nome de conta antes de ser redirecionado:

<!-- vote.php — Página de voto no site do servidor -->
<form action="vote.php" method="post">
    <label>Nome de Conta (Login):</label>
    <input type="text" name="account" maxlength="10" required>
    <button type="submit">Votar e Ganhar Recompensa</button>
</form>

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $account = preg_replace('/[^a-zA-Z0-9]/', '', $_POST['account'] ?? '');
    if (!empty($account)) {
        $gtop_url = "https://gtop100.com/topsites/MuOnline/SEUID/vote?pingbackkey=" . urlencode($account);
        $xt_url   = "https://www.xtremetop100.com/in.php?site=SEUID&postback=" . urlencode($account);
        echo "<p><a href='$gtop_url' target='_blank'>Votar no GTOP100 (+200 W-Coins)</a></p>";
        echo "<p><a href='$xt_url' target='_blank'>Votar no Xtremetop100 (+200 W-Coins)</a></p>";
    }
}
?>

Passo 7: Verificar e Monitorar o Sistema

Para checar votos recentes e status de entrega diretamente no SSMS:

-- Votos das últimas 24 horas
SELECT VoteID, AccountID, SiteID, VoteDate,
       CASE VoteStatus WHEN 0 THEN 'Pendente' ELSE 'Entregue' END AS Status
FROM VoteLog
WHERE VoteDate > DATEADD(HOUR, -24, GETDATE())
ORDER BY VoteDate DESC;

-- Total de votos por conta (ranking de votação)
SELECT AccountID, COUNT(*) AS TotalVotos
FROM VoteLog
WHERE VoteStatus = 1
GROUP BY AccountID
ORDER BY TotalVotos DESC;

-- Forçar entrega manual de um voto específico
EXEC SP_DeliverVoteReward;
Dica: Crie uma página /admin/votos.php protegida por senha que exibe essa consulta em tabela HTML — facilita monitorar reclamações de jogadores sem precisar abrir o SSMS toda vez.

Troubleshooting Rápido

ProblemaCausa provávelSolução
Pingback não chegaFirewall bloqueando porta 80Verificar regra no Windows Firewall e no painel do hosting
AccountID não encontradoNome de conta digitado erradoValidar contra tabela MEMB_INFO antes de aceitar o voto
W-Coins não somadosColuna errada na MEMB_INFOSELECT TOP 1 * FROM MEMB_INFO para checar colunas reais
Job do SQL Agent não rodaServiço Agent paradoservices.msc → iniciar SQL Server Agent
Voto duplicado aceitoFalta de verificação de tempoAdicionar WHERE VoteDate > DATEADD(HOUR, -12, GETDATE())
Nota: Muitos sites de votação enviam o pingback de um IP diferente do IP do jogador. Nunca use o IP do pingback para validar a identidade do votante — use exclusivamente o nome de conta enviado como parâmetro.

Perguntas frequentes

O jogador votou mas não recebeu a recompensa. O que verificar?

Primeiro confirme que o VoteKey retornou pelo pingback está sendo gravado corretamente na tabela VoteLog. Verifique se o campo AccountID bate exatamente com o nome de conta do jogador (case-sensitive no GTOP100). Em seguida rode: SELECT * FROM MuOnline.dbo.VoteLog WHERE AccountID = 'nomeconta' ORDER BY VoteDate DESC — se o registro existe mas a recompensa não chegou, o problema está no script PHP de delivery ou no agendamento da stored procedure.

Posso recompensar com mais de um item por voto?

Sim. Basta adicionar múltiplas linhas INSERT na stored procedure SP_DeliverVoteReward, uma para cada item. Use o mesmo CharacterName e ajuste os campos ItemCode, ItemLevel, ItemDur, ItemOpt conforme os itens desejados. Lembre que a tabela de itens no banco (geralmente MEMB_ITEMS ou equivalente) tem limite de slots — verifique se o personagem não está com inventário cheio.

Qual a diferença entre recompensar via banco de dados e via comando in-game?

Via banco de dados (INSERT direto ou stored procedure) o item é entregue mesmo com o servidor offline, mas exige que o personagem esteja desconectado no momento da entrega ou que você use a tabela de itens de 'delivery' do MuServer. Via comando in-game (/add_item ou similar) o GameServer executa imediatamente, mas o personagem precisa estar online e o servidor operacional.

Como evitar que o jogador vote várias vezes antes de receber a recompensa?

Adicione um campo VoteStatus na tabela VoteLog (0=pendente, 1=entregue). Antes de aceitar novo voto, faça: SELECT COUNT(*) FROM VoteLog WHERE AccountID = @AccountID AND VoteStatus = 0 — se retornar > 0, recuse o novo registro. Isso impede acúmulo de recompensas não coletadas e também detecta possíveis tentativas de explorar o sistema.

EQ

Equipe ViciadosMU

Equipe editorial do ViciadosMU — portal de MU Online no ar desde 2003.

Continue lendo

Artigos relacionados