• 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!

Lua Anti-Aimbot script, not working as intended.

Demnish

Tibian Hero
Joined
Sep 28, 2011
Messages
402
Solutions
2
Reaction score
65
Location
Sweden
TFS 1.2 (Client 10.98)

This is my script:
Code:
function onSay(player, words, param)
    if not player:getGroup():getAccess() then
        return true
    end

    if player:getAccountType() < ACCOUNT_TYPE_GOD then
        return false
    end

    local target = Player(param)
    local position = target:getPosition()
    local monster = Game.createMonster("Antibot Monster", position)
    if target == nil then
        player:sendCancelMessage("A player with that name is not online.")
        return false
    end
    monster:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
    target:setTarget(monster)
    target:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)
end
Currently I am able to manipulate the player by changing its "autoattack target".
But the player is still able to shoot runes on their last target, while that target is also "red squared".

Is there anyway to actually use client targeting code in the lua script?
So it forces a target switch on a client level? The way the bots do it.
Or if there is there another way that I don't see, a method?
Preferably a solution in LUA.

Any help would be appreciated!

(This script will help me tell who is botting and who is not, so it is really important for me)
 
Last edited:
This is my script:
Code:
-
It is currently not working as intended; when the script runs the player stops autoattacking its current target(which is progress) but it still retains the red square and is able to shoot runes at it with hotkeys. It won't switch to the target I assigned in the script..
The magic effect also shows and no errors in the console.

Any help would be appreciated!


Nvm, I think I solved it.
Now it actually targeted the monster and autoattacked it.
However, the player is still able to shoot SD's on the current squared target while autoattacking the new target.

Is there anyway to actually use client targeting code in the lua script?
So it forces a target switch in a client level? The way the bots do it.
If you want to do it in client OTC and opcodes is the way to go.
Otherwise depending on your distro version something like creature:setTarget(target) could work.
 
If you want to do it in client OTC and opcodes is the way to go.
Otherwise depending on your distro version something like creature:setTarget(target) could work.
I've been looking into OTC and I'd love to use it, but never got around to compile it.
I will give it a shot though!

Anyway I managed to get it "partly" to work.
Autoattack switched to my assigned target, however the player could still shoot runes on their last target since that one was still "red squared".
It's really wierd, it's like I can manipulate the target of a player, but at the same time I can't?
It switches target, but at the same time it doesn't?

I'm so confused.. o_O
 
Last edited:
I managed to get it "partly" to work.
Autoattack switched to my assigned target, however the player could still shoot runes on their last target since that one was still "red squared".
It's really wierd, it's like I can manipulate the target of a player, but at the same time I can't?
It switches target, but at the same time it doesn't?

I'm so confused.. o_O
Maybe this can help. Use it before you set a new target.

LUA:
function Player.sendCancelTarget(self)
   local msg = NetworkMessage()
   msg:addByte(0xA3)
   msg:addU32(0x00)
   msg:sendToPlayer(self)
   msg:delete()
end
 
I set it like this:
Code:
function onSay(player, words, param)
    if not player:getGroup():getAccess() then
        return true
    end

    if player:getAccountType() < ACCOUNT_TYPE_GOD then
        return false
    end

    local target = Player(param)
    local position = target:getPosition()
    local monster = Game.createMonster("Training Monk", position)
    if target == nil then
        player:sendCancelMessage("A player with that name is not online.")
        return false
    end
 
function Player.sendCancelTarget(target)
    local msg = NetworkMessage()
        msg:addByte(0xA3)
        msg:addU32(0x00)
        msg:sendToPlayer(target)
        msg:delete()
    end
    monster:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
    target:setTarget(monster)
    target:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)
end
But it don't seem to work, it's the same as it was before.
 
Last edited:
I set it like this:
Code:
function onSay(player, words, param)
    if not player:getGroup():getAccess() then
        return true
    end

    if player:getAccountType() < ACCOUNT_TYPE_GOD then
        return false
    end

    local target = Player(param)
    local position = target:getPosition()
    local monster = Game.createMonster("Training Monk", position)
    if target == nil then
        player:sendCancelMessage("A player with that name is not online.")
        return false
    end
 
function Player.sendCancelTarget(target)
    local msg = NetworkMessage()
        msg:addByte(0xA3)
        msg:addU32(0x00)
        msg:sendToPlayer(target)
        msg:delete()
    end
    monster:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
    target:setTarget(monster)
    target:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)
end
But it don't seem to work, it's the same as it was before.
f48WIcf.png
LUA:
function Player.sendCancelTarget(self)
    local msg = NetworkMessage()
    msg:addByte(0xA3)
    msg:addU32(0x00)
    msg:sendToPlayer(self)
    msg:delete()
end

function onSay(player, words, param)
    if not player:getGroup():getAccess() then
        return true
    end
    if player:getAccountType() < ACCOUNT_TYPE_GOD then
        return false
    end
    local target = Player(param)
    if target == nil then
        player:sendCancelMessage("A player with that name is not online.")
        return false
    end

    local position = target:getPosition()
    local monster = Game.createMonster("Training Monk", position)
  
    if not monster then return false end

    target:sendCancelMessage()
    target:setTarget(monster)

    monster:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
    target:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)
    return false
end
Function should be separate and called within the onSay function like this.

Some things to consider is, you tried to check target position before you confirmed target existed which could have potentially caused errors. Also it's a good idea to make sure monster exists since you let force be false within Game.createMonster.
 
Thanks for helping me mate.

However, the script works the same as before.
The player keeps their red squared target and is still able to shoot SD's on it, while their autoattack target changes to the one set in the script.

I mean, looking at the code it should work, but might it have to do with limitation in the distro?

Should this really be this way though? (self)
Code:
function Player.sendCancelTarget(self)
    local msg = NetworkMessage()
    msg:addByte(0xA3)
    msg:addU32(0x00)
    msg:sendToPlayer(self)
    msg:delete()
end
Shouldn't it be (target)?
Since the talkaction is /aimbotcheck "<playername>
 
Thanks for helping me mate.

However, the script works the same as before.
The player keeps their red squared target and is still able to shoot SD's on it, while their autoattack target changes to the one set in the script.

I mean, looking at the code it should work, but might it have to do with limitation in the distro?

Should this really be this way though? (self)
Code:
function Player.sendCancelTarget(self)
    local msg = NetworkMessage()
    msg:addByte(0xA3)
    msg:addU32(0x00)
    msg:sendToPlayer(self)
    msg:delete()
end
Shouldn't it be (target)?
Since the talkaction is /aimbotcheck "<playername>
Its just a parameter you can name it whatever you want as long as when you call it like with target:sendCancelMessage() you're using the correct player.

But yeah I had the same issue before I think I ended up doing some ghetto fix like teleport them away to a remote location and then back to the initial place so it cancels the target that way. Not the way to do it though, hopefully someone knows better than I do. It's probably a source edit required, good luck.
 
iirc bots (advanced ones that's it IE: xeno and wind) can't really be tell what to do by the server, so even if you tell the client to attack X creature the bot will persist with the other one till it dies.

What @Apollos suggested sounds about right, save position of player then teleport it away in a set location, teleport it back and set target immediately, still not guaranteed to work if the bot is configured with Target name.

If that's the case then you'll need to make an script to check monster name and then create an immortal monster with that name (C++ setName required, is in the forum) and tell the client to attack that one, but, then again modern mods have scripts to "if attacking more than 5 secs ignore that monster", so in TL;DR I don't think is really possible in Cip client.
 
Yeah that was what I was worried about.
I guess the old system really is the way to go when catching aimbotters. (Having the players themselves record them shooting runes under roofs and sending me the evidence)

I was sorta planning on abandoning this script because it felt like it would've solved nothing in the long run, with the more advanced bots that you were mentioning.
At least I have a healbot detection script, should catch most of them anyway and with some luck the players themselves record or printscreens the cheaters.


Thanks guys, I appreciate you, keep helping the community! :)

EDIT: Lets keep going for awhile longer, maybe we'll solve it somehow.
 
Last edited:
LUA:
function Player.sendCancelTarget(self)
    local msg = NetworkMessage()
    msg:addByte(0xA3)
    msg:addU32(0x00)
    msg:sendToPlayer(self)
    msg:delete()
end

function onSay(player, words, param)
    if not player:getGroup():getAccess() then
        return true
    end
    if player:getAccountType() < ACCOUNT_TYPE_GOD then
        return false
    end
    local target = Player(param)
    if target == nil then
        player:sendCancelMessage("A player with that name is not online.")
        return false
    end

    local position = target:getPosition()
    local monster = Game.createMonster("Training Monk", position)
 
    if not monster then return false end

    target:sendCancelMessage()
    target:setTarget(monster)

    monster:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
    target:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)
    return false
end
Function should be separate and called within the onSay function like this.

Some things to consider is, you tried to check target position before you confirmed target existed which could have potentially caused errors. Also it's a good idea to make sure monster exists since you let force be false within Game.createMonster.

Thanks for helping me mate.

However, the script works the same as before.
The player keeps their red squared target and is still able to shoot SD's on it, while their autoattack target changes to the one set in the script.

I mean, looking at the code it should work, but might it have to do with limitation in the distro?

Should this really be this way though? (self)
Code:
function Player.sendCancelTarget(self)
    local msg = NetworkMessage()
    msg:addByte(0xA3)
    msg:addU32(0x00)
    msg:sendToPlayer(self)
    msg:delete()
end
Shouldn't it be (target)?
Since the talkaction is /aimbotcheck "<playername>

did anyone of you even notice he wrote
Code:
    target:sendCancelMessage()
    target:setTarget(monster)

instead of

Code:
    target:sendCancelTarget()
    target:setTarget(monster)
 
did anyone of you even notice he wrote
Code:
    target:sendCancelMessage()
    target:setTarget(monster)

instead of

Code:
    target:sendCancelTarget()
    target:setTarget(monster)
It actually works, as far as completely removing the target (Red Square) and the ability to shoot SD runes on the players current target
However, it does not really switch target to the assigned one, it still just autoattacks it.
This does not however prove that the bots won't be able to, but nothing will so that doesn't matter.

It feels like "target:setTarget(monster)" it's not sufficient enough, or that it only manipulates autoattack.

I keep the thread alive, just incase we do manage to find something that solves it. :)


EDIT: I found this piece of code in player.h:
Code:
        void sendCreatureSquare(const Creature* creature, SquareColor_t color) {
            if (client) {
                client->sendCreatureSquare(creature, color);
            }
        }

Maybe we got something here?
 
Last edited:
Indeed, however I still need to add the NetworkMessage for the "square change" but I have no knowledge at all in network messages.
Well it's worth a shot to try. It works fine on my OTC client at least, i just tested it.

EDIT: Oh i see what you're saying now. I'll test some more stuff out when I get home and maybe i can come up with something.

LUA:
function Player.sendCancelTarget(self)
    local msg = NetworkMessage()
    msg:addByte(0xA3)
    msg:addU32(0x00)
    msg:sendToPlayer(self)
    msg:delete()
end
function onSay(player, words, param)
    if not player:getGroup():getAccess() then
        return true
    end

    if player:getAccountType() < ACCOUNT_TYPE_GOD then
        return false
    end
  
    local target = Player(param)
    if not target then
        player:sendCancelMessage("A player with that name is not online.")
        return false
    end
    local position = target:getPosition()
    local monster = Game.createMonster("Training Monk", position)
    if not monster then return false end
    target:sendCancelTarget()
    target:setTarget(monster)
    monster:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
    target:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN)
    return false
end
 
Well it's worth a shot to try. It works fine on my OTC client at least, i just tested it.

EDIT: Oh i see what you're saying now. I'll test some more stuff out when I get home and maybe i can come up with something.
I appreciate it mate, I'm thankful for your time. :)
I wouldn't manage this on my own, my skills in LUA and OT overall is not at the required level that it needs to be for this task.
 
I appreciate it mate, I'm thankful for your time. :)
I wouldn't manage this on my own, my skills in LUA and OT overall is not at the required level that it needs to be for this task.
Looks to me like the reason it doesn't work is because hotkeys are client sided. When you setTarget the server knows that's your target but the client does not, so when you click the hotkey button, there isn't a creature for it to send to. So if you want to do this then you need to use OTC and send an extended opcode for client to read and then assign the target within client. Sorry bro.
 
But isn't it wierd how "target:sendCancelTarget()" actually removes the Red Square on the client?
Could it just be that "setTarget" is incomplete and can be improved in the sources?
 
Back
Top