Delírios de um defunto

Isso não é algo novo, existem muita documentação e scripts em inglês, mas absolutamente nenhum conteúdo (que eu saiba) em português. Como existem uma quantidade formidável de brasileiros jogando SAMP atualmente, decidi então fazer este post.

Já faz mais de uma decada que aparecem diversos tipos de bots para samp, isso se deu graças a api pública do RakNet. Um em particular deu muito bom por conta de sua expansividade, facilidade e simplicidade, o RakSAMP Lite, e é com ele que que vamos criar um bot. Como o samp está, aparantemente, abandonado, este bot deverá funcionar indefinidamente, embora os servidores sempre tentem barrar.

Precisamos executar o RakSAMP Lite.exe a primeira vez para que ele possa criar o arquivo de configurações. Mudando o ip do servidor e o nome de usuário em settings/RakSAMP Lite.ini finalmente podemos tentar conectar:

A proposito, ele roda sem nenhuma dificuldades no Wine e, melhor ainda, tem o modo sem interface gráfica.

Agora vamos tentar automatizar tudo possível.

Primeiro precisamos responder a este diálogo, pois nada acontece enquanto ele não é respondido.

Começamos criando o arquivo bps.lua em scripts. Todos os arquivos dentro de scripts serão executados pelo programa.

Para a nossa sorte, temos um evento para quando recebemos um diálogo. Isso é importante porque o programa não é completo.

Como podemos ver em scripts/libs/samp/events.lua temos:

INCOMING_RPCS[RPC.SHOWDIALOG] = {
    'onShowDialog',
    { dialogId = 'uint16' },
    { style    = 'uint8'  },
    { title    = 'string8' },
    { button1  = 'string8' },
    { button2  = 'string8' },
    { text     = 'encodedString4096' }
}

Vamos fazer um teste simples:

local sampev = require("samp.events")

function sampev.onShowDialog(id, style, title, btn1, btn2, text)
	if text:find("Informe o dispositivo que esta usando: Android ou PC.") then
		print("Encontrei o diálogo que eu buscava")
	end
end


Funcionou.

Buscar o diálogo por texto se faz necessário porque o servidor que estou testando, bem como a maioria hoje em dia, ofusca o ID. Então, todos os diálogos tem o mesmo ID. Você deve verificar isso antes.

Agora precisamos responder ao diálogo. em scripts/libs/addon.lua tem a função sendDialogResponse(id, button, list, input). Depois de responder ao diálogo, devemos fazer um return para que o diálogo não seja exibido na interface do bot (isso interrompe o restante do onShowDialog no bot). O código fica assim:

require("addon")
local sampev = require("samp.events")

function sampev.onShowDialog(id, style, title, btn1, btn2, text)
	if text:find("Informe o dispositivo que esta usando: Android ou PC.") then
		print("Escolhando a opcao PC")
		sendDialogResponse(id, 1, -1, "")
		return false
	end
end

Registro e login

Os botões que vemos no jogo são exibidos de forma bastante técnica no BOT. Nós podemos obter as cordenadas no bot ou então exibir no jogo com algum script, mas eu vou por tentativa e erro (não recomendado, pois dificulta o dev).

Temos:

Que diz respeitos a estes botões:

Tento com o comando !seltd 108 e acerto de primeira o botão para a caixa de diálogo da senha:

Aqui também é uma boa parte para detectar se a conta está registrada ou não. Caso esteja registrada, o diálogo para inserir senha terá uma mensagem diferente, devemos então nos basear nela para decidir se clicamos em entrar ou registrar. Existe uma TD não selecionável que diz se é registrada ou não mas vamos nos basear neste diálogo. (É bom lembrar que o BOT só exibe na interface as TextDraws selecionáveis)

Vamos usar o evento onShowTextDraw e enviar o click na textdraw.

Ficando assim o código:

-- Variáveis globais
registrado = true

function sampev.onShowDialog(id, style, title, btn1, btn2, text)
	if text:find("Insira a senha abaixo") then
		if text:find("para registrar:") then
			registrado = false
		end
		sendDialogResponse(id, 1, -1, "123456")
		return false
	end
end

function sampev.onShowTextDraw(id, data)
	if data.text:find("SENHA INSERIDA") then
		if registrado then
			sendClickTextdraw(112)
		else
			sendClickTextdraw(111)
		end
	end
	if id == 108 then
		sendClickTextdraw(108)
	end
end

Com isso concluimos a parte da autenticação, tanto registro quanto login. O próximo passo é passar pelas etapas pós registro.

function sampev.onShowDialog(id, style, title, btn1, btn2, text)
	-- [Registro] Seleciona o gênero masculino
	if text:find("Selecione seu genero:") then
		sendDialogResponse(id, 1, -1, "")
		return false
	end
	-- [Registro] Pula a parte do email
	if text:find("mail valido para proteger sua conta:") then
		sendDialogResponse(id, 0, -1, "")
		return false
	end
	-- [Registro] Pula o tutorial
	if text:find("Deseja ler o nosso tutorial?") then
		sendDialogResponse(id, 0, -1, "")
		return false
	end
	-- [Registro] Ativa o sistema de fome e sede
	if text:find("Deseja manter o sistema de Fome e Sede") then
		sendDialogResponse(id, 1, -1, "")
		return false
	end
	-- [Registro] Finalização
	if text:find("Tutorial Concluido") then
		sendDialogResponse(id, 0, -1, "")
		return false
	end
end

function sampev.onShowTextDraw(id, data)
	-- [Registro] Seleciona a cidade de Los Santos
	if id == 2057 then
		sendClickTextdraw(2057)
	end
end

Com isso finalmente o bot nasce

Daqui em diante é com você. O bot tem potêncial ilimitado, basta ter paciência para codar.

Aqui está o código final completo, condensado e já com um sistema de atraso no sendinput para eventualmente você não ser barrado pelo "Você está digitando rápido demais":

require("addon")
local sampev = require("samp.events")

local registrado = true
local commandQueue = {}

local dialogActions = {
	-- Autenticação
	["Insira a senha abaixo"]                  = {1, -1, "123456"},

	-- Tutorial
    ["Selecione seu genero:"]                  = {1, -1, ""},
    ["mail valido para proteger sua conta:"]   = {0, -1, ""},
    ["Deseja ler o nosso tutorial?"]           = {0, -1, ""},
    ["Deseja manter o sistema de Fome e Sede"] = {1, -1, ""},
    ["Tutorial Concluido"]                     = {0, -1, ""},

	-- Outros
	["Informe o dispositivo que esta usando"]  = {1, -1, ""},
    ["Voce deseja ir ao evento?"]              = {1, -1, ""}
}

function sampev.onShowDialog(id, style, title, btn1, btn2, text)
    for k, v in pairs(dialogActions) do
        if text:find(k) then
            sendDialogResponse(id, table.unpack(v))
            return false
        end
    end
end

function sampev.onShowTextDraw(id, data)
	print(data.text)
    if id == 2048 then
        if data.text:find("CLIQUE EM REGISTRAR") then
            registrado = false
        elseif data.text:find("clique em ENTRAR") then
            registrado = true
        elseif data.text:find("SENHA INSERIDA") then
            sendClickTextdraw(registrado and 112 or 111)
        end
    elseif id == 108 or id == 2057 then
        sendClickTextdraw(id)
    end
end

function sampev.onServerMessage(color, text)
	if text:find("Saldo Bancario Atual") then
		queueInput("/caixinha")
	end
end

newTask(function()
    while true do
        if #commandQueue > 0 then
            local cmd = table.remove(commandQueue, 1)
            sendInput(cmd)
            wait(2000)
        else
            wait(100)
        end
    end
end)

function queueInput(cmd)
    table.insert(commandQueue, cmd)
end

Alguns plugins interessantes:

HitFix

WeaponFix

FakePing

Slapfix

interpolate camera fix

E com certeza um dos mais importântes para movimentações humanizadas:

OnFoot/InCar Route Recording System é um script Moonloader (requer SAMPFUNCS) para gravar movimentos do seu personagem, isso não é para o bot, é para o seu jogo.

Route Recording System para o bot executar esses movimentos

Mirror para estes arquivos, caso o blast.hk caia: Drive OneDrive Dropbox