Xentales

Talk about stuff, and if you must, about Xenimus
It is currently 19 Nov 2017 02:36

All times are UTC - 5 hours [ DST ]




Post new topic Reply to topic  [ 75 posts ]  Go to page Previous  1, 2
Author Message
PostPosted: 25 Apr 2015 19:30 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
Bronson1365 wrote:
shame to see the only dude who picked up the old project is now selling the bot, 200$ for other peoples work

zzz


Thats the thing about nice code, if your good enough you can make money doing it. Its a shame he is selling it (i wasnt aware of this), but its his choice. Honestly, as a programmer it make me happy knowing i created something usefully and good enough to be continued by someone else. I still get PM's about one every few months asking me if i have do any work on this old code. But for the last year or so i havent been on xenimus or even be coding in C++, my work is strictly PHP and after i get off work i generally just vegg out on TV.

I just recently (like 2 days ago), re-downloaded xenimus and started messing around with some code again. Im a little interesting in learning Python, sofar i put together a start to a bot. Its clientless, which is much much harder in my mind to work with, but its fun to play around with and stuff. So far ive only be able to get it to login to the game, not much else. I havent put more then a few hours into this code yet though. (im also on linux so i figured id give python a shot instead of C++ which i am much more fluent in)

// Base.py
Code:
#!/usr/bin/env python

import thread
from Queue import Queue
import socket
import sys
import time
from inc import *

# 64.34.166.5
host = '64.34.163.8'
port = 5050
account = 12345678 # Replace with account
password = 'password' # Replace with password
packet_queue = Queue()
character = ''
char_id = 0
loggedin = False

####################################
# FUNCTIONS                        #
####################################
def recv_handler( sock ):
   while( 1 ):
      try:
         d = sock.recvfrom( 1024 )
         reply = crypto.decrypt( d[0], len( d[0] ))
         addr = d[1]
         packet_handler( reply )
      except socket.error, msg:
         print 'Error code: ' + str( msg[0] ) + ' Message: ' + msg[1]


def send_handler( sock, host, port ):
   while 1:
      if( not packet_queue.empty() ):
         message = packet_queue.get()
         print 'Send: '
         print ':'.join( '{:02x}'.format(x) for x in message )
         sock.sendto( message, ( host, port ))
         packet_queue.task_done()


def packet_handler( packet ):
   packet = bytearray( packet )
   global character, char_id, loggedin
   print 'Recv:'
   print ':'.join( '{:02x}'.format(x) for x in packet )
   # Login
   if( packet[0] == 0x0F ):
      char_id = [ packet[2], packet[3] ]
      pos = 6
      while( packet[ pos ] != 0 ):
         character += chr( packet[ pos ] )
         pos += 1
   # Entering the world
   elif( packet[0] == 0x1F ):
      loggedin = True
   # Update packet
   elif( packet[0] == 0x03 ):
      handle_update( packet )


def queue_packet( packet ):
   packet = bytearray( packet )
   packet = crypto.encrypt( packet, len( packet ))
   packet_queue.put( packet )

def do_login( account, password ):
   # Define an empty login packet
   login = [0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x00,0x00,0x00,0x00,0x00]
   # Place the account number into the packet
   login[2] = ( account & 0xFF )
   login[3] = ( account >> 8 ) & 0xFF
   login[4] = ( account >> 16 ) & 0xFF
   login[5] = ( account >> 24 ) & 0xFF
   # Place the password into the packet
   pos = 10
   for x in password:
      login[ pos ] = ord( x )
      pos += 1
   # Add to the queue
   queue_packet( login )

def enter_world( charid, password ):
   enter = [0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00]
   # Place character id into packet
   enter[2] = charid[0]
   enter[3] = charid[1]
   # Place the password into the packet
   pos = 10
   for x in password:
      enter[ pos ] = ord( x )
      pos += 1
   # Add to queue
   queue_packet( enter )

def handle_update( packet ):
   #TODO: handle the packet duh
   print ''

####################################
# MAIN THREAD                      #
####################################

# Create the socket
try:
   xSock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
except socket.error:
   print 'Failed to create socket'
   sys.exit()

# Create worker threads
try:
  thread.start_new_thread( recv_handler, ( xSock, ) )
  #rworker.deamon = True
 # rworker.start()

  thread.start_new_thread( send_handler, ( xSock, host, port, ) )
  #sworker.deamon = True
  #sworker.start()
except:
   print "Error: unable to start thread"


ping = "\x25\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"

#while 1:
time.sleep( 1 )
queue_packet( ping )
time.sleep( 2 )
do_login( account, password )
time.sleep( 2 )
print character
print char_id
time.sleep( 2 )
enter_world( char_id, password )
time.sleep( 15 )


// Crypto.py
Code:
from random import randint

m_key = [
   0x0B, 0xB3, 0x49, 0x4C, 0xA7, 0x53, 0x44, 0x09, 0xAA, 0xE4, 0x0A, 0x8D, 0xD9, 0x5D, 0xC5, 0x28,
   0xDA, 0x25, 0x4F, 0x25, 0xA0, 0xE2, 0x67, 0x69, 0x61, 0x73, 0x84, 0xEA, 0x97, 0xE2, 0x41, 0xD5,
   0xB6, 0x28, 0xC6, 0x7D, 0x53, 0xD5, 0x73, 0x98, 0x12, 0x9F, 0x80, 0xB0, 0x5A, 0xA1, 0x29, 0xE7,
   0x5E, 0xD0, 0x2A, 0x7F, 0x09, 0xBF, 0xD6, 0x4B, 0x6B, 0x83, 0x01, 0xAA, 0x7B, 0x67, 0x1B, 0x0D,
   0xBC, 0x0E, 0x26, 0x2E, 0xD5, 0x8F, 0x7E, 0xCE, 0x33, 0xF2, 0x1C, 0xD8, 0xAD, 0x03, 0xB4, 0xFC,
   0x40, 0x8D, 0x0B, 0xD0, 0x78, 0x01, 0x60, 0x26, 0xBB, 0x38, 0x36, 0x52, 0x6C, 0xBD, 0x1E, 0x6F,
   0xD2, 0x92, 0xC4, 0x4B, 0xFA, 0x25, 0x30, 0xDE, 0x16, 0x98, 0xC0, 0xAA, 0x79, 0x56, 0x10, 0x61,
   0xA1, 0x39, 0x9E, 0x57, 0x23, 0xCC, 0xD5, 0x19, 0x2A, 0xA7, 0xF4, 0x2A, 0xE3, 0x9C, 0xF5, 0xCF,
   0x3D, 0xF0, 0x12, 0x6A, 0xDD, 0x01, 0x49, 0xD0, 0xCE, 0x02, 0x0A, 0x7D, 0x10, 0x2D, 0x47, 0x11,
   0x15, 0xD7, 0x54, 0xFA, 0x63, 0x07, 0xB3, 0x58, 0x1E, 0xA6, 0xB0, 0x14, 0x0E, 0xA1, 0x93, 0x28,
   0xFE, 0x12, 0x3C, 0x02, 0x94, 0x1E, 0xEE, 0xA7, 0xAF, 0xED, 0x63, 0xDE, 0x8A, 0x1D, 0xD6, 0xC1,
   0x68, 0x34, 0xBF, 0xC0, 0x1E, 0x7B, 0x2C, 0x31, 0x86, 0x49, 0xE9, 0xC0, 0xC5, 0x06, 0x8B, 0x9A,
   0x3A, 0xE2, 0x85, 0x36, 0x10, 0xAB, 0x8A, 0x47, 0x0D, 0xE6, 0xFC, 0x43, 0x8A, 0x57, 0x36, 0x33,
   0x21, 0x9A, 0x95, 0xDB, 0x16, 0x33, 0xA2, 0x75, 0x49, 0xD5, 0x4E, 0xF8, 0x65, 0xCA, 0xCD, 0x9B,
   0x5B, 0x95, 0xA8, 0x95, 0x0F, 0xD6, 0x0F, 0x27, 0x51, 0x6F, 0x6C, 0xDA, 0x0E, 0xE5, 0x3D, 0x0D,
   0xC7, 0x09, 0x23, 0xAB, 0x43, 0xD7, 0x36, 0x3A, 0x81, 0x9E, 0x9B, 0x1A, 0xF0, 0x62, 0x59, 0x0A];

def decrypt( packet, size ):
   packet = bytearray( packet )

   key = packet[0] + packet[1]
   key &= 0xff
   
   packet[0] ^= 0xAA

   startkeyval = m_key[ key ]
   startkeyval &= 0x24
   startkeyval |= 1
   
   writepos = 2;
   while( writepos < size ):
      keyval = m_key[ key ]
      if( writepos & startkeyval ):
         if( (keyval & startkeyval) == 0 ):
            packet[ writepos ] = ( packet[ writepos ] - keyval ) & 0xff
         else:
            packet[ writepos ] = ( packet[ writepos ] ^ keyval ) & 0xff
      else:
         if( keyval & startkeyval ):
            packet[ writepos ] = ( ~packet[ writepos ] ) & 0xff
         else:
            packet[ writepos ] = ( packet[ writepos ] + keyval ) & 0xff
      key += 1
      key &= 0xff
      writepos += 1
   return packet

def encrypt( packet, size ):
   packet = bytearray( packet )

   packet[1] = randint( 0, 255 )

   packet[0] ^= 0xAA

   key = packet[0] + packet[1]
   key &= 0xff

   startkeyval = m_key[ key ]
   startkeyval &= 0x24
   startkeyval |= 1

   writepos = 2
   while( writepos < size ):
      keyval = m_key[ key ]
      if( writepos & startkeyval ):
         if( (keyval & startkeyval) == 0 ):
            packet[ writepos ] = ( packet[ writepos ] + keyval ) & 0xff
         else:
            packet[ writepos ] = ( packet[ writepos ] ^ keyval ) & 0xff
      else:
         if( (keyval & startkeyval) == 0 ):
            packet[ writepos ] = ( packet[ writepos ] - keyval ) & 0xff
         else:
            packet[ writepos ] = ( ~packet[ writepos ] ) & 0xff
      key += 1
      key &= 0xff
      writepos += 1
   return packet


Top
 Profile  
 
PostPosted: 03 Jun 2015 09:01 
Offline

Joined: 15 Sep 2006 04:18
Posts: 49
im happy to pay/donate for a working bot, but the money hes asking is just stupid


Top
 Profile  
 
PostPosted: 25 Jun 2015 19:15 
Offline

Joined: 03 Jan 2009 04:02
Posts: 107
He's actually not even selling it. He is sending something else and tries to steal your money. I think I sent the program clery sent to me to kev or Andy to look at. One of them said they recommend I don't use it. Don't trust that bot


Top
 Profile  
 
PostPosted: 30 Jun 2015 12:28 
Offline

Joined: 05 Nov 2007 11:14
Posts: 117
There's one I saw which was a working bot, but they added a line in to send a chat message just as you logged in before the map loaded, revealing your account number and password to anyone in range.

Because it was sent before the map load packet was received, the player knew nothing about it.


Top
 Profile  
 
PostPosted: 03 Jul 2015 02:32 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
Andy123456 wrote:
There's one I saw which was a working bot, but they added a line in to send a chat message just as you logged in before the map loaded, revealing your account number and password to anyone in range.

Because it was sent before the map load packet was received, the player knew nothing about it.


HA! Thats awesome. HAHAHA! Wow.

Hey everyone, i changed my mind about using python (not a fan of it) and went back to C\C++. Im in a linux environment (Xubuntu) which is a lot different for me then windows was. I really only spend about 30 minutes on this code so far, and havent had a chance to get back to working on since my previous post pretty much. My work right now has me pretty busy and i havent gotten back around to playing and/or coding at all. But i did put up the code i made on github so anyone can take a look at it, fork it, play with it. Whatever. Wont work on a windows computer though. It would be really fun if i could get it to be a fully working bot, and since its linux it would be a very simple thing to set up on any basic VPN/Server and have it play for you (since most servers run linux). Take a look, add to it if you want. Ill be updating it very very infrequently.

Right now it only checks to see if the server is up (ping it), tries to login, and then logs into the first character on the account. I put in the code to parse the update packet, but it might be a little off. I didnt spend too much time other then taking my old code and throwing it in there with a quick test.

https://github.com/toddwithers/Bot


Top
 Profile  
 
PostPosted: 05 Jul 2015 14:54 
Offline

Joined: 05 Nov 2007 11:14
Posts: 117
I hope you changed that password. I would just recreate the repo if you don't want people seeing it.


Top
 Profile  
 
PostPosted: 05 Jul 2015 18:08 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
Haha yeah I noticed I had left that info in after I had pushed everything. The account is an account with a level 1 on it and that's it. Password is a password that I don't normally use. So it's no worry to me lol


Top
 Profile  
 
PostPosted: 07 Jul 2015 00:34 
Offline

Joined: 15 Sep 2006 04:18
Posts: 49
Well, if anyone wants to develop a working bot or has one. PM me, id gladly buy it... i cbf leveling to 70 lol

I just dont have the time


Top
 Profile  
 
PostPosted: 11 Jul 2015 02:21 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
Bronson1365 wrote:
Well, if anyone wants to develop a working bot or has one. PM me, id gladly buy it... i cbf leveling to 70 lol

I just dont have the time


Your best bet is to learn programming. Even learning some basic programming and then taking some of the code from this thread will be a lot better then spending money on a bot program that someone made. The biggest reason i say this is because it will allow you to customize your bot to your character. If you learn the basics of C/C++ and then look over the code in this thread i can promise that you will be able to set up a pretty good "macro" program with some level of AI.

The other reason i strongly suggest making one yourself is that the Xen community has always had a bad reputation of scamming. You never know what someone is going to give you. You may end up paying $200 for a program that just steals your account.

All the tools to make a bot are seriously in this thread. The code may be slightly out of date, but that is why we are here. If you put together something and run into any issues, just post your code and tell us what isnt working about it. I may not check on here that often, but im always willing to help review code if i can.

Good luck


Top
 Profile  
 
PostPosted: 04 Sep 2015 16:59 
Offline

Joined: 04 Jan 2015 12:18
Posts: 26
Character(s): Zeig of X1
.


Last edited by Zeig on 24 Mar 2016 06:28, edited 1 time in total.

Top
 Profile  
 
PostPosted: 04 Jan 2016 20:23 
Offline

Joined: 05 Nov 2007 13:13
Posts: 3
Character(s): none at the moment
.

_________________
Roses are #FF0000, violets are #0000FF, and all my base are belong to you !

Postcount++;


Top
 Profile  
 
PostPosted: 24 Mar 2016 06:23 
Offline

Joined: 04 Jan 2015 12:18
Posts: 26
Character(s): Zeig of X1
Decided to come back to this, added a few thing which worked really nice. TBH I don't know why I never did this before, works really well. Never loses its place now.

Code:
      if (path[i].y != ups.positionY)
      {
         double startTime = GetTickCount();
         while (path[i].y != p_update.positionY)
         {
            double currentTime = GetTickCount() - startTime;

            if (currentTime >= 10000) //1 and a half seconds.
            {
               g_Log.Log("Out of time");
               return;
               //Reset the timer.
               startTime = GetTickCount();
            }
            UpdatePacketSelf ups = GetUpdateInfo();
            g_Log.Log("Not matching");
            PergereTrans(path[i].x, path[i].y);
            g_Log.Log("My position = %X", ((ups.positionY)));
            g_Log.Log("Path = %X", ((path[i].y)));
            Sleep(350);


Will now check the current position matches with the path, if it doesn't it will retry for 10seconds at which point it will just restart. Planning to use similar concept to check if dead and see if its safe to up and pop or to just Exit script.

Also now checks mana and will port to mana pool when low, High wait is becuase it goes server - DS, even if it fails the previous code will pick this up and re-start the path.

Code:
      if (GetCurrentMP() < 150)
      {
         g_Log.Log("Low Mana");
         Sleep(250);
         PraesentisTrans(6);
         Sleep(4000);
         Walk(15723, 47188);
         Sleep(4000);
         return;
      }


I've also now got functionality for accessing shops as well as well as selling items, collecting items and porting back to town when inventory full however having a small issue with the item types. My Inventory output is showing that all my inventory slots are empty when they are not and i cannot figure out why.

Collecting]
Code:
void Player::Collect()
{
uint16 x = 0, y = 0;
ItemMap::GetItemPos(x, y);

uint16 slotNum = 1000;
if (x != 0xFFFF && y != 0xFFFF)
{
   g_Log.Log("Selected Item Position (%d %d)", x, y);
   PickItem(x, y);
}

return;
}


Code:
void Player::PickItem(uint16 x, uint16 y)
{
   PergereTrans(x*20+10, y*20+10); Sleep(50);
   Walk(x*20+10, y*20+10); Sleep(150);
   UpdatePacketSelf ups = GetUpdateInfo();
   Sleep(300);
   if(UnitMap::UnitsAlive(p_update.positionX, p_update.positionY, 120) > 1)
   {
      Sleep(200);
      FragorIpsum(0);
   }
   return;
}


Accessing shop
Code:
void Player::OpenShopWindow()
{
   uint16 id = 7289;
   uint16 positionY = 0xFFFF;
   //UnitMap::LocateUnit(50, 2, 0, 0, 198, id, positionY);
   //UnitMap::LocateUnit(122, 22, 0, 0, 358, id, positionY);
   //UnitMap::LocateUnit(122, 22, 0, 0, 102, id, positionY);
   UnitMap::LocateUnit(61, 33, 0, 0, id, positionY);


   if (id != 0 && positionY != 0xFFFF)
   {
      g_Log.Log("NPC click");
      g_Log.Log("ID = %x, Y pos = %d", id, positionY);
      Attack(id, positionY);
      Packet other(0xC, 0xC);
      other << p_id;
      other << (uint16)0;
      other << (uint16)4;
      other << (uint16)0;
      other << id;
      other << (uint16)0;
      DWORD dword_10F4814 = 0x1AE6420;
      *(DWORD*)(dword_10F4814) = id;
      oSendPacket(other, other, other);
   }


and selling

Code:
void Player::SellItem(uint16 itemNumInInven, uint16 itemCntToSell, uint16 itemTypeOnInven)
{
   Packet sellItem(0x6, 0xC);
   sellItem << p_id;
   sellItem << (uint16)SELL;
   sellItem << itemNumInInven;
   sellItem << itemCntToSell;
   sellItem << itemTypeOnInven;
   sellItem << (uint16)0;

   oSendPacket(sellItem, sellItem, sellItem);
}

void Player::SellItem(uint16 itemNumInInven, uint16 itemCntToSell)
{
   
   Sleep(30);
      uint16 itemType = Inventory::GetItemType(itemNumInInven);
      SellItem(itemNumInInven, itemCntToSell, itemType); //sell 6th Item on Inventor
}



Image

As you can see from the image below, my issue is it is no longer recognizing any item types from the inventory and hence when i'm selling items it doesn't include the item type, the code looks fine to me though? Anyone want to give me a hand fixing this? I'll be happy to share the updated code


Top
 Profile  
 
PostPosted: 27 Mar 2016 06:52 
Offline

Joined: 05 Nov 2007 11:14
Posts: 117
You guys need to stop moving to the middle of each tile, it's so obvious you're botting when doing that.

This is why I wrote a navigation system into my bot.

Also when you cast a targetted spell, it sends X, Y, but X is the targetid. Y should still be relative to where the target is and not 0.

Really easy to catch.

Btw here is a quick example of detecting this bot ^^, you could put this into movement requests or spell cast requests on the server.

Quote:
int counter = 0;
int threshold = 5;

if ((x % 20) == 10 && (y % 20) == 10))
counter++
else
counter = 0;

if (counter > threshold)
//hey just detected your bot


Top
 Profile  
 
PostPosted: 13 Apr 2016 00:46 
Offline

Joined: 20 Mar 2007 04:37
Posts: 5
This is a really cool thread. I haven't been on xentales in such a long time. I haven't ever actually got to look at any bot code for xenimus before. I might tinker with some of these sometime if I have time. I think something like python would make it very easy to set up a bot, but there is already so much stuff in this thread for c/c++ that it would be much faster to get one working in c++. I wish you guys would have added in some comments so I could see what exactly each function you have is doing without much effort xD

Very cool stuff 10/10


Top
 Profile  
 
PostPosted: 11 May 2016 10:17 
Offline

Joined: 17 Mar 2016 20:33
Posts: 50
Very interesting thread. I can't believe I've never checked this subforum here.

I'm not interested in botting in the literal sense, but I want to make some tools to make things easier: manage my port mules, manage my buff mules, almus from my cleric, hold a button to spin & release the button to med, auto-log-off if my HP is below 25% in certain dungeons and not in PVP, things like that.

I'll peruse this thread some more after work :)


Top
 Profile  
 
PostPosted: 11 Jun 2016 01:27 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
Andy123456 wrote:
You guys need to stop moving to the middle of each tile, it's so obvious you're botting when doing that.

This is why I wrote a navigation system into my bot.

Also when you cast a targetted spell, it sends X, Y, but X is the targetid. Y should still be relative to where the target is and not 0.

Really easy to catch.


Along these same lines, i was looking at packets the other day and noticed EJ added a counter to the spell packets. Its just 1 byte, but i believe he placed it in there to make it easier to catch bots. The value is constant from character to character, and only resets to 0 once it passes 0xff or if the client is closed and re-opened.

This is the new layout from what i can see
[opcode] [key] [player_id] [unk] [counter] [type] [spell] [x/playerid] [y]
opcode - 1 byte
key - 1 byte
player_id - 2 bytes
unk - 1 byte (always 00)
counter - 1 byte (increases by 1 each time a spell is cast)
type - 2 bytes
spell - 2 bytes
x/playerid - 2 bytes
y - 2 bytes


Top
 Profile  
 
PostPosted: 11 Jun 2016 06:52 
Offline
Very Important Poster
User avatar

Joined: 28 Nov 2007 23:35
Posts: 186
Character(s): None.
That counter is very old I believe - was used to catch botters that were using that program... Commview or something like that... That captures and resends packets.


Top
 Profile  
 
PostPosted: 11 Jun 2016 22:20 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
Hmm i wonder if he had it disabled for awhile. I know the walk packet had a counter a long time ago, but 2 years ago (when i was making all the code in this thread) he had disabled the counter in the walk packet and it was always just 00. I never saw a counter in the spell packet either, it was always 00. So he possibly re-enabled it is my guess. No idea why he would ever disabled it in the first place, as it was a pretty good way to catch bots, but i know for sure when i was looking at packets a few years ago both those counters were not there.


Top
 Profile  
 
PostPosted: 13 Jun 2016 14:45 
Offline

Joined: 05 Nov 2007 11:14
Posts: 117
Wait what? Counter in spells?

That's new. Xenlua doesn't send the counter. Infact placing it there would break Xenluas buffing feature which worked last time I logged in.

Edit: I checked xenlua and XPS and can confirm neither have a counter in spells so this is relatively new.


Top
 Profile  
 
PostPosted: 13 Jun 2016 15:23 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
Andy123456 wrote:
Wait what? Counter in spells?

That's new. Xenlua doesn't send the counter. Infact placing it there would break Xenluas buffing feature which worked last time I logged in.

Edit: I checked xenlua and XPS and can confirm neither have a counter in spells so this is relatively new.


Yeah i had never seen it before. It was always just 2 empty bytes after the player id. Now its not. Has to be pretty new im guessing

Code:
struct Spell {
   uint16 player_id;
   uint8 unk;
   uint8 counter;
   uint16 type; // ground/unit/self or 0x30 + mark for instaport
   uint16 spellid;
   uint16 target; // either positionX or unit id
   uint16 y;
};


Top
 Profile  
 
PostPosted: 13 Jun 2016 20:46 
Offline

Joined: 05 Nov 2007 11:14
Posts: 117
It's strange though because EJ knows all of this stuff is reversed from previous bots releeased.

I guess he's just trying a method to catch the bots already out since no-one is really reversing Xen anymore.


Top
 Profile  
 
PostPosted: 14 Jun 2016 03:34 
Offline
Very Important Poster
User avatar

Joined: 28 Nov 2007 23:35
Posts: 186
Character(s): None.
There was a counter somewhere though, no? Maybe movement packet. Or my memory is just going down the shitter already.


Top
 Profile  
 
PostPosted: 14 Jun 2016 04:51 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
Andy123456 wrote:
It's strange though because EJ knows all of this stuff is reversed from previous bots releeased.

I guess he's just trying a method to catch the bots already out since no-one is really reversing Xen anymore.


Yeah there was a guy botting today that i talked to and turns out he is just using a packet recorder/sender to bot. Im surprised the server isnt catching him on its own, but with the added counter it definitely makes it easier for EJ to look at it and know the person was botting. Unless he was doing 255 spell packets each loop haha.

ubern00ber wrote:
There was a counter somewhere though, no? Maybe movement packet. Or my memory is just going down the shitter already.


Yes there was one in the walk packet probably 3-4 years back. It worked the same exact way, each click/walk caused it to increase by 1, and it was just 1 byte so would go from 0 to 255 and then reset. For some reason he disabled this atleast 2 years ago when i originally made all the code in this thread, and its still disabled as of yesterday when i checked.


Top
 Profile  
 
PostPosted: 15 Jun 2016 21:00 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
.


Last edited by lawn gnome on 28 Jun 2016 21:55, edited 1 time in total.

Top
 Profile  
 
PostPosted: 28 Jun 2016 21:49 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
The counter is also in the "use item" packet. The packets are identical, so my guess is he is literally using 1 function to generate spell/use item packets. use item is op code 0x07 and spells 0x08, both 14 bytes, both have same exact layout. So using an item increase the counter just like a spell does. Interesting.


Top
 Profile  
 
PostPosted: 23 Sep 2016 21:10 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
So i found a new packet i wasnt aware of recently. I might be late to the party, but figured i would make mention of it just incase anyone else was experiencing the same kind of issue i was.

I run my code clientless, which can at time be a bit tedious since i have to send each and every packet. I was starting to notice a trend while running my code. If i was in a normal, trans-able, area then my unit map was always 100% accurate. It didnt have anything missing and always looked good. But, if i was in a non-trans area, for some reason i would often find my unit map didnt contain the model data (model/weapon/shield/helm) for a lot of the units, it only contained the movement and animations usually. This was causing problems for me because i like to have some sense of what is on screen so i dont sit there and attack someone skelly over and over again or whatever. EJ, probably in some band-aid-fix-esque move, made it so in non-trans areas it will not send the model data for units until you request them.....Not sure of the reason for this, but its annoying to say the least. It was annoying because if i ran my code while hooked into the client my unit map was always correct, but move to clientless and then it had missing data. It was a pain to figure out.

Anyways long story short, in non-trans areas you have to request the onscreen units model data. This is done using the packet with the opcode 0x09. It has 2 possible formats.

Code:
Requesting 1 units model data:
uint16 your_player_id;
uint16 requesting_units_id;
uint16 blank;
uint16 blank;

Requesting 2 units model data:
uint16 your_player_id;
uint16 0xFDE8 (constant value, never changes)
uint16 requesting_unit1s_id;
uint16 requesting_unit2s_id;


Once you send this packet, the next update packet you get will contain the model data for that unit(s). Hope this is helpful for anyone out there experiencing the same issue.


Top
 Profile  
 
PostPosted: 08 Jan 2017 10:48 
Offline

Joined: 05 Nov 2007 11:14
Posts: 117
Strange. One would think this is to save bandwidth for things not in line of sight but it increases the bandwidth used for things visible.

An update that wasn't thought through, who would have thought.


Top
 Profile  
 
PostPosted: 21 Jan 2017 17:55 
Offline

Joined: 05 Nov 2007 11:14
Posts: 117
Just a bit of a nerdy look back I'm browsing some code and found this bot code I had for PVPing melee chars

Code:
bool Player::CalcBestTrans(float minrad, float maxrad)
{
   //get tile we're on
   int32 tilex = m_lastupdate.positionX / 20;
   int32 tiley = m_lastupdate.positionY / 20;
   //get tile of position + max radius
   int32 tilemaxx = (int32)((m_lastupdate.positionX + maxrad) / 20);

   std::vector<std::pair<int32, int32>> preferredTiles;
   std::vector<std::pair<int32, int32>> possibleTiles;

   int32 difftile = tilemaxx - tilex;

   for (int32 x = tilex - difftile; x <= tilex + difftile; ++x)
   {
      for (int32 y = tiley - difftile; y <= tiley + difftile; ++y)
      {
         float dist = GetDistance(float(x * 20 + 10), float(y * 20 + 10));

         if (dist < minrad)
            continue;
         if (dist > maxrad)
            continue;

         if (GetMapInterface()->GetMapLayer2(x, y) == 46) //safety square
            continue;

         //we need to be able to walk on it
         if (!GetMapInterface()->CanPass(x, y, PASS_FLAG_WALK))
            continue;
         //and teleport to it
         if (!Raycast(float(x * 20 + 10), float(y * 20 + 10), PASS_FLAG_GAS))
            continue;

         //if you can't walk to it, make it preferred spot :)
         if (!Raycast(float(x * 20 + 10), float(y * 20 + 10), PASS_FLAG_WALK))
            preferredTiles.push_back(std::make_pair(x, y));
         else
            possibleTiles.push_back(std::make_pair(x, y));
      }
   }

   if (possibleTiles.size() == 0 && preferredTiles.size() == 0)
      return false; //nowhere to teleport to, eek

   if (preferredTiles.size() > 0)
   {
      std::uniform_int_distribution<int> dist(0, preferredTiles.size() - 1);
      auto tile = preferredTiles[dist(g_mersenne)];

      m_bestTransX = tile.first * 20 + 10;
      m_bestTransY = tile.second * 20 + 10;
   }
   else
   {
      std::uniform_int_distribution<int> dist(0, possibleTiles.size() - 1);
      auto tile = possibleTiles[dist(g_mersenne)];

      m_bestTransX = tile.first * 20 + 10;
      m_bestTransY = tile.second * 20 + 10;
   }
   return true;
}


Searched around the char for somewhere to trans and preferred locations you couldn't walk to.


Top
 Profile  
 
PostPosted: 23 Jan 2017 09:17 
Offline

Joined: 05 Nov 2007 11:14
Posts: 117
Btw these incrementing counters are useless when using UDP as your protocol, I remember testing them on XPS when it was still UDP and people just randomly got errors "MoveCounter failed" and couldn't move.

Did not stay in XPS for long, completely useless for bot checking.


Top
 Profile  
 
PostPosted: 25 Jan 2017 18:30 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
Andy123456 wrote:
Btw these incrementing counters are useless when using UDP as your protocol, I remember testing them on XPS when it was still UDP and people just randomly got errors "MoveCounter failed" and couldn't move.

Did not stay in XPS for long, completely useless for bot checking.


Makes sense. The packets can be received out of order, making it useless. Classic EJ lol


Top
 Profile  
 
PostPosted: 06 Feb 2017 16:19 
Offline

Joined: 05 Nov 2007 11:14
Posts: 117
Here, have some item data: http://pastebin.com/JxRmEAVu


Top
 Profile  
 
PostPosted: 30 Apr 2017 14:29 
Offline

Joined: 17 Mar 2016 20:33
Posts: 50
I'm late to this party. I'm primarily a python dev so I'd love to get a headless bot working with the Python implementation started above.

My target is to just create a buff bot and/or gambling bot.


Top
 Profile  
 
PostPosted: 03 Sep 2017 09:22 
Offline

Joined: 05 Nov 2007 11:14
Posts: 117
XPS Source: https://github.com/andy012345/xps


Top
 Profile  
 
PostPosted: 03 Sep 2017 10:33 
Offline

Joined: 17 Mar 2016 20:33
Posts: 50
Nice. Downloaded in case it's not up long. I'll peruse this.


Top
 Profile  
 
PostPosted: 03 Sep 2017 11:04 
Offline

Joined: 05 Nov 2007 11:14
Posts: 117
I'm considering making a new XPS open source project where it essentially uses a format like google protobuf to communicate with a proxy, and the proxy would sit on peoples computer translating the server data to something xen could understand.

Just need to find some time to do it.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 75 posts ]  Go to page Previous  1, 2

All times are UTC - 5 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group