• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

TFS 1.X+ Close channel after antibot verification

ralke

(҂ ͠❛ ෴ ͡❛)ᕤ
Joined
Dec 17, 2011
Messages
1,470
Solutions
27
Reaction score
844
Location
Santiago - Chile
GitHub
ralke23
Twitch
ralke23
Hi! I use Nekiro 8.6 1.4 tfs and need some help. I'm working with this code TFS 1.X+ - Problem with target:getMonster() function (https://otland.net/threads/problem-with-target-getmonster-function.277284/), it is working great. But I have a trouble, when you perform the verification correctly, the channel is not getting closed. I tried to add this function to the chatchannel/antibot.lua

Code:
 player:closeChannel(ANTI_BOT_SYSTEM.config.channelId)

After

Code:
player:sendChannelMessage("", ANTI_BOT_SYSTEM.messages.correct_answer.msg

In this way

Code:
    if message ~= ANTI_BOT_SYSTEM.questions[ANTI_BOT_SYSTEM.cache.question].answer then
       addEvent(function() player:sendChannelMessage("", ANTI_BOT_SYSTEM.messages.wrong_answer.msg, ANTI_BOT_SYSTEM.messages.wrong_answer.type, ANTI_BOT_SYSTEM.config.channelId) end, 300)
    else
        addEvent(function() player:sendChannelMessage("", ANTI_BOT_SYSTEM.messages.correct_answer.msg, ANTI_BOT_SYSTEM.messages.correct_answer.type, ANTI_BOT_SYSTEM.config.channelId) end, 300)
        player:closeChannel(ANTI_BOT_SYSTEM.config.channelId)
        ANTI_BOT_SYSTEM.cache.players[player:getId()] = nil
    end

But I have this error, how can I achieve this? If the channel doesn't get closed and it remain open the next verfication doesn't send the new question and that's why I need to close the channel as soon the verification is correct (the channel also has a system that doesn't allow to open it manually).

channel.png

expalination.png

The only thread I could find with this was Solved - close channel network message (https://otland.net/threads/close-channel-network-message.248417/) Hope you can help me!
Thanks in advance
 
did you try adding
Lua:
if ANTI_BOT_SYSTEM.cache.players[player:getId()] then
verification first?
Or just call the player:getId() before

Tried with
Lua:
addEvent(function() player:sendChannelMessage("", ANTI_BOT_SYSTEM.messages.correct_answer.msg, ANTI_BOT_SYSTEM.messages.correct_answer.type, ANTI_BOT_SYSTEM.config.channelId) end, 300)
ANTI_BOT_SYSTEM.cache.players[player:getId()] = nil
then
player:closeChannel(ANTI_BOT_SYSTEM.config.channelId)

And does nothing jajaja. Also:
Lua:
ANTI_BOT_SYSTEM.messages.correct_answer.type, ANTI_BOT_SYSTEM.config.channelId) end, 300)
ANTI_BOT_SYSTEM.cache.players[player:getId()] = nil
player:closeChannel(ANTI_BOT_SYSTEM.config.channelId)
And nope, if you could attach an example of how it should be would be great!

Also this happened when adding playerCloseChannel in sources:
1626585257219.png
 
Last edited:
This method already exist, it's just not added into the lua interface.

Try to add into luascript.cpp below the openChannel (line 2437):
C++:
registerMethod("Player", "closeChannel", LuaScriptInterface::luaPlayerCloseChannel);
Also into luascript.h below the luaPlayerOpenChannel (line 953):
C++:
static int luaPlayerCloseChannel(lua_State* L);

and then into luascript.cpp, down the int LuaScriptInterface::luaPlayerOpenChannel(lua_State* L) (line 9385):

C++:
int LuaScriptInterface::luaPlayerCloseChannel(lua_State* L)
{
    // player:closeChannel(channelId)
    uint16_t channelId = getNumber<uint16_t>(L, 2);
    Player* player = getUserdata<Player>(L, 1);
    if (player) {
        g_game.playerCloseChannel(player->getID(), channelId);
        pushBoolean(L, true);
    } else {
        lua_pushnil(L);
    }
    return 1;
}
 
This method already exist, it's just not added into the lua interface.

Try to add into luascript.cpp below the openChannel (line 2437):
C++:
registerMethod("Player", "closeChannel", LuaScriptInterface::luaPlayerCloseChannel);
Also into luascript.h below the luaPlayerOpenChannel (line 953):
C++:
static int luaPlayerCloseChannel(lua_State* L);

and then into luascript.cpp, down the int LuaScriptInterface::luaPlayerOpenChannel(lua_State* L) (line 9385):

C++:
int LuaScriptInterface::luaPlayerCloseChannel(lua_State* L)
{
    // player:closeChannel(channelId)
    uint16_t channelId = getNumber<uint16_t>(L, 2);
    Player* player = getUserdata<Player>(L, 1);
    if (player) {
        g_game.playerCloseChannel(player->getID(), channelId);
        pushBoolean(L, true);
    } else {
        lua_pushnil(L);
    }
    return 1;
}

Thanks a lot, I was able to compile the function, no errors. But still can't close the channel after responding with a correct answer to the anti-bot question. Also tried

Lua:
		addEvent(function() player:closeChannel(ANTI_BOT_SYSTEM.config.channelId)end,300)

Haven't worked. Any other ideas of where in the script I have to call this channel close and how to do it?
Regards!
 
CreatureEvent - [TFS 1.3] Best Free Anti-Bot System -- Notations & Auto-Ban (https://otland.net/threads/tfs-1-3-best-free-anti-bot-system-notations-auto-ban.272074/) i suggest to use this,because your current system will produce bugs when 2 players are asked to answer the antibot, lets say first player asked to enter 5 and second asked to enter 3 when first enters 5 it will tell him wrong answer, when he says 3 it will tellhim correct, so it doesn't give each player the corresponding answer, it works like once answer for the whole code not per player, sorry i couldn't find better way to explain
 
CreatureEvent - [TFS 1.3] Best Free Anti-Bot System -- Notations & Auto-Ban (https://otland.net/threads/tfs-1-3-best-free-anti-bot-system-notations-auto-ban.272074/) i suggest to use this,because your current system will produce bugs when 2 players are asked to answer the antibot, lets say first player asked to enter 5 and second asked to enter 3 when first enters 5 it will tell him wrong answer, when he says 3 it will tellhim correct, so it doesn't give each player the corresponding answer, it works like once answer for the whole code not per player, sorry i couldn't find better way to explain

I tested and it works! The system is great.

P.S: There's something I still have doubt, couldn't test it well. Is when you killing, for example, if I kill a rat and my code is 23567, then I kill another and my code now is 62451, does the timeStorage reset when a second code is sent?
Edit: Tested again, it has very little a bug. Happened exactly what I said in P.S, when I trigger the AntiBOT code for a second time, the timestorage get restarted. Fore sure this won't affect if I have an interval of 600-700 monsters, I tested it with a 2-4 monsters interval, but maybe is usefull to know, here's the recorded test:

By any chance, and if you have time to do it, can I request a modification to the script? I want it to work with chatchannels instead of talkactions, using the script of the post as reference for the chat channels, or this one:

Lua:
ANTIBOT = {
    prefix = "[AntiBot] ",
    questions = {
        {question = "Qual o ano que começou o COVID-19?", staticAnswer = true, answer = "2019"},
        {question = "Qual seu skill atual de Sword?", skill = true, answer = SKILL_SWORD},
        {question = "Qual seu skill atual de Club?", skill = true, answer = SKILL_CLUB},
        {question = "Qual seu skill atual de Distance?", skill = true, answer = SKILL_DISTANCE},
        {question = "Qual seu level atual?", answer = "level"},
        {question = "Qual o dia de hoje?", answer = "day"},
    },
    playerQuestion = {},
    messages = {
        time = "Você possui %s para responder a pergunta.",
        chat = "Esse chat só pode ser usado durante a verificação.",
        howAnswer = "Você deve responder somente a resposta, por exemplo: Qual o dia de hoje? Resposta: %d",
        correctAnswer = "Você acertou a pergunta. Obrigado.",
        incorrectAnswer = "Você errou a resposta, você ainda possui %d tentativas.",
        logout = "Você não pode deslogar enquanto hover uma verificação ativa.",
    },
    punishment = {
        try = {
            max = 3,
            reason = "Quantidade excessiva de tentativas.",
            timePunishment = 1, -- In days
            players = {},
        },
        time = {
            maxTime = 180, -- In seconds
            reason = "Não respondeu a pergunta dentro do tempo estipulado.",
            timePunishment = 2, -- In days
            players = {},
        },
    },
    verification = {40, 60}, -- in minutes
}

function ANTIBOT:addTry(playerId)

    local player = Player(playerId)

    if not player then
        return false
    end

    playerId = player:getId()

    if not ANTIBOT.punishment.try.players[playerId] then
        ANTIBOT.punishment.try.players[playerId] = 0
    end

    ANTIBOT.punishment.try.players[playerId] = ANTIBOT.punishment.try.players[playerId] + 1

    if ANTIBOT.punishment.try.players[playerId] and ANTIBOT.punishment.try.players[playerId] >= ANTIBOT.punishment.try.max then
        sendChannelMessage(13, TALKTYPE_CHANNEL_O, ANTIBOT.prefix .. ANTIBOT.punishment.try.reason)
        ANTIBOT:addPunishment(playerId)
    end
end

function ANTIBOT:time(playerId)
    local player = Player(playerId)

    if not player then
        ANTIBOT:reset(playerId)
        return false
    end

    playerId = player:getId()

    if not ANTIBOT.punishment.time.players[playerId] then
        ANTIBOT.punishment.time.players[playerId] = 0
        ANTIBOT:sendQuestions(playerId)
    end

    addEvent(function()
        if ANTIBOT.punishment.time.players[playerId] and ANTIBOT.punishment.time.players[playerId] >= 0 and ANTIBOT.punishment.time.players[playerId] < ANTIBOT.punishment.time.maxTime then
            ANTIBOT.punishment.time.players[playerId] = ANTIBOT.punishment.time.players[playerId] + 1
            player:sendCancelMessage(ANTIBOT.prefix .. ANTIBOT.messages.time:format(string.diff(ANTIBOT.punishment.time.maxTime - ANTIBOT.punishment.time.players[playerId], true)))
            ANTIBOT:time(playerId)
        end
    end, 1000)

    if ANTIBOT.punishment.time.players[playerId] and ANTIBOT.punishment.time.players[playerId] >= ANTIBOT.punishment.time.maxTime then
        ANTIBOT:addPunishment(playerId)
    end

end

function ANTIBOT:sendQuestions(playerId)

    local player = Player(playerId)

    if not player then
        return false
    end

    playerId = player:getId()

    random = math.random(#ANTIBOT.questions)

    ANTIBOT.playerQuestion[playerId] = random

    player:say("ANTIBOT", TALKTYPE_MONSTER_SAY)
    player:openChannel(13)
    addEvent(sendChannelMessage, 500, 13, TALKTYPE_CHANNEL_O, ANTIBOT.prefix .. ANTIBOT.messages.howAnswer:format(os.date("%d")))
    addEvent(sendChannelMessage, 800, 13, TALKTYPE_CHANNEL_O, ANTIBOT.prefix .. ANTIBOT.questions[random].question)
end

function ANTIBOT:reset(playerId)
    ANTIBOT.punishment.try.players[playerId] = nil
    ANTIBOT.punishment.time.players[playerId] = nil
    ANTIBOT.playerQuestion[playerId] = nil
end

function ANTIBOT:addPunishment(playerId)

    local player = Player(playerId)
    if not player then
        return false
    end

    playerId = player:getId()

    local accountId = getAccountNumberByPlayerName(player:getName())
    if accountId == 0 then
        return false
    end

    local resultId = db.storeQuery("SELECT 1 FROM `account_bans` WHERE `account_id` = " .. accountId)
    if resultId ~= false then
        result.free(resultId)
        return false
    end

    local timeNow = os.time()

    if ANTIBOT.punishment.try.players[playerId] and ANTIBOT.punishment.try.players[playerId] >= ANTIBOT.punishment.try.max then
        db.query("INSERT INTO `account_bans` (`account_id`, `reason`, `banned_at`, `expires_at`, `banned_by`) VALUES (" ..
            accountId .. ", " .. db.escapeString(ANTIBOT.prefix .. ANTIBOT.punishment.try.reason) .. ", " .. timeNow .. ", " .. timeNow + (ANTIBOT.punishment.try.timePunishment * 86400) .. ", " .. player:getGuid() .. ")")
    elseif ANTIBOT.punishment.time.players[playerId] and ANTIBOT.punishment.time.players[playerId] >= ANTIBOT.punishment.time.maxTime then
        db.query("INSERT INTO `account_bans` (`account_id`, `reason`, `banned_at`, `expires_at`, `banned_by`) VALUES (" ..
            accountId .. ", " .. db.escapeString(ANTIBOT.prefix .. ANTIBOT.punishment.time.reason) .. ", " .. timeNow .. ", " .. timeNow + (ANTIBOT.punishment.time.timePunishment * 86400) .. ", " .. player:getGuid() .. ")")
    end

    ANTIBOT:reset(playerId)
    player:save()
    player:getPosition():sendMagicEffect(CONST_ME_POFF)
    player:remove()
end
function onJoin(player)
if not ANTIBOT.playerQuestion[player:getId()] then
player:sendTextMessage(5, ANTIBOT.prefix .. ANTIBOT.messages.chat)
player:getPosition():sendMagicEffect(CONST_ME_POFF)
return false
end
return true
end

function onLeave(player)
if ANTIBOT.playerQuestion[player:getId()] then
return false
end
return true
end


function onSpeak(player, type, message)
if not ANTIBOT.playerQuestion[player:getId()] then
sendChannelMessage(13, TALKTYPE_CHANNEL_O, ANTIBOT.prefix .. ANTIBOT.messages.chat)
player:getPosition():sendMagicEffect(CONST_ME_POFF)
return false
end

local question = ANTIBOT.questions[ANTIBOT.playerQuestion[player:getId()]]

if question.skill then
correctAnswer = tonumber(player:getSkillLevel(question.answer))
message = tonumber(message)
elseif question.answer == "level" then
correctAnswer = tonumber(player:getLevel())
message = tonumber(message)
elseif question.answer == "day" then
correctAnswer = tonumber(os.date("%d"))
message = tonumber(message)
elseif question.staticAnswer then
message = message:lower()
correctAnswer = question.answer:lower()
end

verification = false

if message == correctAnswer then
verification = true
end

if verification then
addEvent(sendChannelMessage, 200, 13, TALKTYPE_CHANNEL_O, ANTIBOT.prefix .. ANTIBOT.messages.correctAnswer)
ANTIBOT:reset(player:getId())
else
ANTIBOT:addTry(player:getId())
addEvent(function()
if ANTIBOT.punishment.try.players[player:getId()] and ANTIBOT.punishment.try.players[player:getId()] < ANTIBOT.punishment.try.max and player then
sendChannelMessage(13, TALKTYPE_CHANNEL_O, ANTIBOT.prefix .. ANTIBOT.messages.incorrectAnswer:format(ANTIBOT.punishment.try.max - ANTIBOT.punishment.try.players[player:getId()]))
end
end, 100)
end

return true
end
<channel id="13" name="AntiBot" script="antibot.lua" />[/code]
Code:
function onLogin(player)

    if player:getAccountType() >= ACCOUNT_TYPE_GAMEMASTER then
        return true
    end

    player:registerEvent("AntiBot")
    checkAnti(player:getId())
 
    return true
end

function checkAnti(playerId)
    local player = Player(playerId)
    if not player then
        return false
    end

    min, max = ANTIBOT.verification[1], ANTIBOT.verification[2]
    random = math.random(min, max)

    addEvent(function()
        ANTIBOT:time(player:getId())
        checkAnti(player:getId())
    end, random * 60 * 1000)
end
<event type="login" name="AntiBot" script="antibot.lua" />

Lua:
if ANTIBOT.punishment.try.players[player:getId()] or ANTIBOT.punishment.time.players[player:getId()] then
    player:sendTextMessage(MESSAGE_INFO_DESCR, ANTIBOT.prefix .. ANTIBOT.messages.logout)
    player:getPosition():sendMagicEffect(CONST_ME_POFF)
    return false
end
ANTIBOT:reset(player:getId())

The main request would be that:
  • Open Anti Bot channel for confirmations
  • Close channel after correct answer
  • Automatically open Anti Bot channel if confirmation is requested
  • Don't allow to open Anti Bot channel if there's no confirmation request

Regards!
 
Last edited:
Back
Top