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:
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.
e Route Recording System para o bot executar esses movimentos
Mirror para estes arquivos, caso o blast.hk caia: Drive OneDrive Dropbox
Finalmente, um script mais completo para o BPS:
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, ""},
-- Trocar o inventario para diálogo, muito mais fácil de lidar
["Com o selecionador ao lado do inventario"] = {1, 3, ""},
["Inventario Novo"] = {1, 11, ""},
-- Chat /noob
["Este chat e exclusivamente para duvidas e re"] = {1, -1, ""},
-- Outros
["Informe o dispositivo que esta usando"] = {1, -1, ""},
["Voce deseja ir ao evento?"] = {1, -1, ""},
["Voce acumulou os respeitos necessario e passou"] = {0, -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
--[[
não dá pra confiar na saida do print
precisa debugar o texto
print(string.format("%q", text))
--]]
-- Inventário: Abrir caixa e juntar respeitos
if title:find("Item Selecionado") and title:find("Respeito") and btn1 == "Juntar" then
print("Juntando")
local index = 0
local respeitos = {}
-- Coletar todos os respeitos
for nome, quantidade in text:gmatch("Item: ([^%c\9]+)\9(%d+)") do
if nome:find("Respeito") then
table.insert(respeitos, {index = index, quantidade = tonumber(quantidade)})
end
index = index + 1
end
-- Se tem pelo menos 2 respeitos, encontrar o de maior quantidade
if #respeitos >= 2 then
-- Encontrar o respeito com maior quantidade
local maiorRespeito = respeitos[1]
for i = 2, #respeitos do
if respeitos[i].quantidade > maiorRespeito.quantidade then
maiorRespeito = respeitos[i]
end
end
sendDialogResponse(id, 1, maiorRespeito.index, "")
return false
end
end
if title:find("Item Selecionado:") then
if title:find("Caixa") or title:find("Dinheiro") then
sendDialogResponse(id, 1, 0, "")
return false
end
if title:find("Respeito") then
sendDialogResponse(id, 1, 2, "")
end
end
if title:find("Inventario de") then
local index = 0
local respeitos = {}
local temOutrasRecompensas = false
for nome, quantidade in text:gmatch("([^%c\9]+)\9[^%c\9]+\9(%d+)") do
print("Index: " .. index .. " - " .. nome .. " - Quantidade: " .. quantidade)
-- Coletar informações dos respeitos
if nome:find("Respeito") then
table.insert(respeitos, {index = index, quantidade = tonumber(quantidade)})
end
-- Verificar se tem outras recompensas além da atual
if nome:find("Caixa Bronze") or nome:find("Caixa Ouro") or nome:find("Caixa Prata") or nome:find("Dinheiro") then
-- Contar quantos outros itens de recompensa existem
local count = 0
for outroNome in text:gmatch("([^%c\9]+)\9[^%c\9]+\9%d+") do
if outroNome:find("Caixa Bronze") or outroNome:find("Caixa Ouro") or outroNome:find("Caixa Prata") or outroNome:find("Dinheiro") then
count = count + 1
end
end
if count > 1 then
temOutrasRecompensas = true
end
sendDialogResponse(id, 1, index, "")
if temOutrasRecompensas then
newTask(function()
wait(1000)
sendSpecialKey(2)
end)
end
return false
end
index = index + 1
end
-- Verificar se tem 2 ou mais respeitos
if #respeitos >= 2 then
-- Encontrar o respeito com menor quantidade
local menorRespeito = respeitos[1]
for i = 2, #respeitos do
if respeitos[i].quantidade < menorRespeito.quantidade then
menorRespeito = respeitos[i]
end
end
sendDialogResponse(id, 1, menorRespeito.index, "")
return false
end
end
print("Title:", title, "btn1:", btn1, "btn2:", btn2, "Text:", text)
return false
end
function sampev.onShowTextDraw(id, data)
print(id, 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")
sendSpecialKey(2)
end
-- Quando loga, abre o menu de configurações para verificar se o inventario é dialogo
if text:find("Seu ultimo login foi:") then
queueInput("/configuracoes")
end
end
newTask(function()
while true do
if #commandQueue > 0 then
local cmd = table.remove(commandQueue, 1)
sendInput(cmd)
wait(2000 + (getBotPing() * 1.5))
else
wait(100)
end
end
end)
function queueInput(cmd)
table.insert(commandQueue, cmd)
end
--[[
Código para enviar teclas via script
Exemplo de uso:
sendKey(16) -- https://sampwiki.blast.hk/wiki/Keys
sendSpecialKey(1) -- Y/N/H -> 1/2/3
--]]
function sendKey(id)
key = id
updateSync()
end
function sendSpecialKey(id)
skey = id
updateSync()
end
function applyKeys(data)
if key then
data.keysData = key
key = nil
end
if skey then
data.specialKey = skey
skey = nil
end
end
function sampev.onSendPlayerSync(data)
applyKeys(data)
end
function sampev.onSendVehicleSync(data)
applyKeys(data)
end








Postar um comentário