Xentales

Talk about stuff, and if you must, about Xenimus
It is currently 19 Aug 2017 16:29

All times are UTC - 5 hours [ DST ]




Post new topic Reply to topic  [ 72 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: 21 Aug 2013 00:48 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
Well got my computer working again. I want to get around to making an opensource mod for xenimus, basically improve upon what i learned by making my previous one (xenScan). Ill probably be posting random code here, maybe writing explanations on how im doing things, ect ect.


Anyways, what im just now playing around with it the FindPattern function that i see all across modding forums. Ive found you can use this function to locate the Sendpacket, encrypt, and decrypt addresses. I tested the code on 1.145 & 1.191 and it returns the correct addresses. This may not sound that exciting, but what it means is no more need to decompile the client every update and find the addresses. The mod would be able to work through updates with little need to modify it.

Code:
#include "main.h"

//These two functions have been posted across forums everywhere, not sure who i could give credit to on these
bool Compare(const BYTE* pData, const BYTE* bMask, const char* szMask)
{
   for(;*szMask;++szMask,++pData,++bMask)
      if(*szMask=='x' && *pData!=*bMask)   return 0;
   return (*szMask) == NULL;
}
DWORD FindPattern(DWORD dwAddress, DWORD dwLen, BYTE *bMask, char * szMask)
{
   for(DWORD i=0; i<dwLen; i++)
      if (Compare((BYTE*)(dwAddress+i),bMask,szMask))  return (DWORD)(dwAddress+i);
   return 0;
}

BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    if(fdwReason == DLL_PROCESS_ATTACH)
   {
      setupConsole();

      uint8 SendPacketNeedle[] = {0x81, 0x3D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x96,
                           0x00, 0x00, 0x0F, 0x85, 0xAC, 0x00, 0x00, 0x00,
                           0xA1, 0x00, 0x00, 0x00, 0x01, 0xC1, 0xE0, 0x06,
                           0x0F, 0xB7, 0x88, 0x00, 0x00, 0x00, 0x00, 0x56};
      char SendPacketMask[] = "xx???x?x??xxxxxxx???xxxxxxx???xx";

      uint8 EncryptNeedle[] = {0x8B, 0x44, 0x24, 0x04, 0x56, 0x8B, 0xF1, 0x89,
                         0x46, 0x10, 0x80, 0x30, 0xAA, 0x8B, 0x46, 0x10,
                         0x80, 0x38, 0xAA, 0x0F, 0x84, 0xA5, 0x00, 0x00,
                         0x00, 0x57, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x25};
      char EncryptMask[] = "xxxxxxxxxxxxxxxxxxxxxxxxxx????xx";

      uint8 DecryptNeedle[] = {0x56, 0x8B, 0x74, 0x24, 0x08, 0x89, 0x71, 0x10,
                         0x0F, 0xB6, 0x16, 0x0F, 0xB6, 0x46, 0x01, 0x03,
                         0xC2, 0x8B, 0x51, 0x28, 0x25, 0xFF, 0x00, 0x00,
                         0x00, 0x89, 0x41, 0x04, 0x0F, 0xB6, 0x04, 0x10};
      char DecryptMask[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";


      //dwModuleStartAddr is set as the encrypt address for 1.191
      //sendpacket/encrypt/decrypt should never be before this address ever again
      //Between 1.145 & 1.191, addresses shifted about 0xB320
      DWORD  dwModuleStartAddr = (DWORD)GetModuleHandle("Xenimus.exe") + 0x26600;

      DWORD addrSendPacket   = FindPattern(dwModuleStartAddr, 0xA000, SendPacketNeedle, SendPacketMask);
      printf("SendPacket: %X\n", addrSendPacket);

      DWORD addrEncrypt      = FindPattern(dwModuleStartAddr, 0xA000, EncryptNeedle, EncryptMask);
      printf("Encrypt: %X\n", addrEncrypt);

      DWORD addrDecrypt      = FindPattern(dwModuleStartAddr, 0xA000, DecryptNeedle, DecryptMask);
      printf("Decrypt: %X\n", addrDecrypt);
   }
   if(fdwReason == DLL_PROCESS_DETACH)
   {
    }
    return TRUE;
}



Was pretty happy that this worked out as well as i had hoped. I have seen people use the FindPattern function to hook directx, and i may end up going that route.

Feel free to post comments, questions, blablabla, code, whatever.


Top
 Profile  
 
PostPosted: 21 Aug 2013 17:47 
Offline

Joined: 05 Nov 2007 11:14
Posts: 108
This is the method we used in an old WoW packet sniffer.

Unfortunately it doesn't work for long. Misc optimisations tend to break it.


Top
 Profile  
 
PostPosted: 21 Aug 2013 17:57 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
Andy123456 wrote:
This is the method we used in an old WoW packet sniffer.

Unfortunately it doesn't work for long. Misc optimisations tend to break it.


I would assume in WoW that would be true, but from what i saw in 1.145 and 1.191 (i could only find 1.145 as an old reference) the functions barely changed at all. EJ doesnt seem to work much on optimization of old code.

Spoiler:
Code:
Decrypt 1.145
56 8B 74 24 08 89 71 10 0F B6 16 0F B6 46 01 03 C2 8B 51 28 25 FF 00 00 00 89 41 04 0F B6 04 10
83 E0 24 83 C8 01 89 01 80 36 AA 8B 51 10 80 3A 00 74 6B 57 8B 7C 24 10 83 FF 02 C7 41 08 02 00
00 00 7E 59 53 8B 59 04 8B 51 28 8B 41 08 8B 31 85 F0 8A 14 1A 0F BE DA 74 13 85 DE 8B 71 10 74
06 03 C6 30 10 EB 1E 03 C6 28 10 EB 18 85 DE 74 0D 8B 51 10 03 C2 8A 10 F6 D2 88 10 EB 07 8B 71
10 03 C6 00 10 8B 41 04 83 41 08 01 83 C0 01 25 FF 00 00 00 89 41 04 39 79 08 7C A9 5B 5F 5E C2
08 00

Encrypt 1.145
8B 44 24 04 56 8B F1 89 46 10 80 30 AA 8B 46 10 80 38 AA 0F 84 A5 00 00 00 57 E8 C2 C4 06 00 25
FF 00 00 80 79 07 48 0D 00 FF FF FF 40 8B 4E 10 8B 7C 24 10 88 41 01 8B 46 10 0F B6 50 01 0F B6
00 8B 4E 28 03 C2 25 FF 00 00 00 89 46 04 0F B6 14 08 83 E2 24 83 CA 01 83 FF 02 89 16 C7 46 08
02 00 00 00 7E 57 55 8B 6E 04 8B 4E 28 8B 46 08 8B 16 85 D0 8A 0C 29 0F BE E9 74 13 85 EA 8B 56
10 74 06 03 C2 30 08 EB 1C 03 C2 00 08 EB 16 85 EA 8B 56 10 74 0B 8A 0C 10 03 C2 F6 D1 88 08 EB
04 03 C2 28 08 8B 46 04 83 46 08 01 83 C0 01 25 FF 00 00 00 89 46 04 39 7E 08 7C AB 5D 5F 5E C2
08 00


SendPacket 1.145
81 3D F0 33 82 03 7F 96 7A 67 0F 85 AC 00 00 00 A1 60 3C 04 01 C1 E0 06 0F B7 88 D0 72 51 00 56
51 66 C7 05 80 3C 04 01 02 00 E8 7F 4B 06 00 8B 15 60 3C 04 01 8A 4C 24 08 66 A3 82 3C 04 01 8B
04 95 B0 E7 5C 05 88 0D 90 BA 40 02 8B 4C 24 10 A3 84 3C 04 01 33 C0 85 C9 7E 29 8B 74 24 0C 81
EE 92 BA 40 02 EB 09 8D A4 24 00 00 00 00 8B FF 8A 94 06 92 BA 40 02 88 90 92 BA 40 02 83 C0 01
3B C1 7C EC 8D 71 02 56 68 90 BA 40 02 B9 04 40 52 00 E8 89 B6 FF FF A1 30 63 65 00 6A 10 68 80
3C 04 01 6A 00 56 68 90 BA 40 02 50 E8 F7 4A 06 00 83 F8 FF 5E 75 05 E9 E6 4A 06 00 C3


Decrypt 1.191
56 8B 74 24 08 89 71 10 0F B6 16 0F B6 46 01 03 C2 8B 51 28 25 FF 00 00 00 89 41 04 0F B6 04 10
83 E0 24 83 C8 01 89 01 80 36 AA 8B 51 10 80 3A 00 74 6B 57 8B 7C 24 10 83 FF 02 C7 41 08 02 00
00 00 7E 59 53 8B 59 04 8B 51 28 8B 41 08 8B 31 85 F0 8A 14 1A 0F BE DA 74 13 85 DE 8B 71 10 74
06 03 C6 30 10 EB 1E 03 C6 28 10 EB 18 85 DE 74 0D 8B 51 10 03 C2 8A 10 F6 D2 88 10 EB 07 8B 71
10 03 C6 00 10 8B 41 04 83 41 08 01 83 C0 01 25 FF 00 00 00 89 41 04 39 79 08 7C A9 5B 5F 5E C2
08 00

Encrypt 1.191
8B 44 24 04 56 8B F1 89 46 10 80 30 AA 8B 46 10 80 38 AA 0F 84 A5 00 00 00 57 E8 52 52 08 00 25
FF 00 00 80 79 07 48 0D 00 FF FF FF 40 8B 4E 10 8B 7C 24 10 88 41 01 8B 46 10 0F B6 50 01 0F B6
00 8B 4E 28 03 C2 25 FF 00 00 00 89 46 04 0F B6 14 08 83 E2 24 83 CA 01 83 FF 02 89 16 C7 46 08
02 00 00 00 7E 57 55 8B 6E 04 8B 4E 28 8B 46 08 8B 16 85 D0 8A 0C 29 0F BE E9 74 13 85 EA 8B 56
10 74 06 03 C2 30 08 EB 1C 03 C2 00 08 EB 16 85 EA 8B 56 10 74 0B 8A 0C 10 03 C2 F6 D1 88 08 EB
04 03 C2 28 08 8B 46 04 83 46 08 01 83 C0 01 25 FF 00 00 00 89 46 04 39 7E 08 7C AB 5D 5F 5E C2
08 00

SendPacket 1.191
81 3D 2C E3 8C 03 E2 96 4C D6 0F 85 AC 00 00 00 A1 94 6B 0F 01 C1 E0 06 0F B7 88 C8 E6 53 00 56
51 66 C7 05 F8 8C 0F 01 02 00 E8 4F C8 07 00 8B 15 94 6B 0F 01 8A 4C 24 08 66 A3 FA 8C 0F 01 8B
04 95 E0 99 67 05 88 0D 70 0A 4C 02 8B 4C 24 10 A3 FC 8C 0F 01 33 C0 85 C9 7E 29 8B 74 24 0C 81
EE 72 0A 4C 02 EB 09 8D A4 24 00 00 00 00 8B FF 8A 94 06 72 0A 4C 02 88 90 72 0A 4C 02 83 C0 01
3B C1 7C EC 8D 71 02 56 68 70 0A 4C 02 B9 00 5F 54 00 E8 89 A1 FF FF A1 44 5B 55 00 6A 10 68 F8
8C 0F 01 6A 00 56 68 70 0A 4C 02 50 E8 C7 C7 07 00 83 F8 FF 5E 75 05 E9 B6 C7 07 00 C3


Top
 Profile  
 
PostPosted: 21 Aug 2013 18:05 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
Found a good example that used the FindPattern to located d3d9 pointer, which i can then use the vtable to hook the EndScene/Reset functions.

For anyone interested in making a mod, this is really an empty shell that can be used. This example has access to the raw packets & access to the directx functions to render to the game

Code:
#include "main.h"

//These two functions have been posted across forums everywhere, not sure who i could give credit to on these
bool Compare(const BYTE* pData, const BYTE* bMask, const char* szMask)
{
   for(;*szMask;++szMask,++pData,++bMask)
      if(*szMask=='x' && *pData!=*bMask)   return 0;
   return (*szMask) == NULL;
}
DWORD FindPattern(DWORD dwAddress, DWORD dwLen, BYTE *bMask, char * szMask)
{
   for(DWORD i=0; i<dwLen; i++)
      if (Compare((BYTE*)(dwAddress+i),bMask,szMask))  return (DWORD)(dwAddress+i);
   return 0;
}

BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    if(fdwReason == DLL_PROCESS_ATTACH)
   {
      DisableThreadLibraryCalls(hinstDLL);

      //Xenimus loads d3d9.dll after it launches, not sure if he did this
      //in an attempt to make hooking the directx harder or what
      //but either way, we can just load it into the game now
      LoadLibrary("d3d9.dll");

      createConsole();

      uint8 SendPacketNeedle[] = {0x81, 0x3D, 0x00, 0x00, 0x00, 0x03, 0x00, 0x96,
                           0x00, 0x00, 0x0F, 0x85, 0xAC, 0x00, 0x00, 0x00,
                           0xA1, 0x00, 0x00, 0x00, 0x01, 0xC1, 0xE0, 0x06,
                           0x0F, 0xB7, 0x88, 0x00, 0x00, 0x00, 0x00, 0x56};
      char SendPacketMask[] = "xx???x?x??xxxxxxx???xxxxxxx???xx";

      uint8 EncryptNeedle[] = {0x8B, 0x44, 0x24, 0x04, 0x56, 0x8B, 0xF1, 0x89,
                         0x46, 0x10, 0x80, 0x30, 0xAA, 0x8B, 0x46, 0x10,
                         0x80, 0x38, 0xAA, 0x0F, 0x84, 0xA5, 0x00, 0x00,
                         0x00, 0x57, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x25};
      char EncryptMask[] = "xxxxxxxxxxxxxxxxxxxxxxxxxx????xx";

      uint8 DecryptNeedle[] = {0x56, 0x8B, 0x74, 0x24, 0x08, 0x89, 0x71, 0x10,
                         0x0F, 0xB6, 0x16, 0x0F, 0xB6, 0x46, 0x01, 0x03,
                         0xC2, 0x8B, 0x51, 0x28, 0x25, 0xFF, 0x00, 0x00,
                         0x00, 0x89, 0x41, 0x04, 0x0F, 0xB6, 0x04, 0x10};
      char DecryptMask[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";


      //dwModuleStartAddr is set as the encrypt address for 1.191
      //sendpacket/encrypt/decrypt should never be before this address ever again
      //Between 1.145 & 1.191, addresses shifted about 0xB320
      DWORD  dwModuleStartAddr = (DWORD)GetModuleHandle("Xenimus.exe") + 0x26600;

      DWORD addrSendPacket   = FindPattern(dwModuleStartAddr, 0xA000, SendPacketNeedle, SendPacketMask);
      oSendPacket = (tSendPacket)addrSendPacket;

      DWORD addrEncrypt      = FindPattern(dwModuleStartAddr, 0xA000, EncryptNeedle, EncryptMask);
      oEncrypt = (tEncrypt)addrEncrypt;

      DWORD addrDecrypt      = FindPattern(dwModuleStartAddr, 0xA000, DecryptNeedle, DecryptMask);
      oDecrypt = (tDecrypt)addrDecrypt;

      DWORD *vtable;
      DWORD addrD3D9   =  FindPattern((DWORD)GetModuleHandle("d3d9.dll"), 0x128000, (PBYTE)"\xC7\x06\x00\x00\x00\x00\x89\x86\x00\x00\x00\x00\x89\x86", "xx????xx????xx") + 2;
      
      memcpy(&vtable, (void *)addrD3D9, 4);
      oEndScene = (tEndScene)vtable[42];
      oReset = (tReset)vtable[16];

      DetourTransactionBegin();
      DetourUpdateThread(GetCurrentThread());
      printf("creating encrypt detour %x -> %x\n", addrEncrypt, encryptHook);
      DetourAttach(&(PVOID&)oEncrypt, encryptHook);
      printf("creating decrypt detour %x -> %x\n", addrDecrypt, decryptHook);
      DetourAttach(&(PVOID&)oDecrypt, decryptHook);
      printf("creating EndScene detour %x -> %x\n", vtable[42], EndSceneHook);
      DetourAttach(&(PVOID&)oEndScene, EndSceneHook);
      printf("creating Reset detour %x -> %x\n", vtable[16], ResetHook);
      DetourAttach(&(PVOID&)oReset, ResetHook);
      DetourTransactionCommit();
   }
   if(fdwReason == DLL_PROCESS_DETACH)
   {
      DetourTransactionBegin();
      DetourUpdateThread(GetCurrentThread());
      DetourDetach(&(PVOID&)oEncrypt, encryptHook);
      DetourDetach(&(PVOID&)oDecrypt, decryptHook);
      DetourDetach(&(PVOID&)oEndScene, EndSceneHook);
      DetourDetach(&(PVOID&)oReset, ResetHook);
      DetourTransactionCommit();
    }
    return TRUE;
}

int __fastcall encryptHook(void *pthis, void* unk, uint8* packet, int len)
{
   return oEncrypt(pthis, packet, len);
}

int __fastcall decryptHook(void *pthis, void* unk, uint8* packet, int len)
{
   int decryptres = oDecrypt(pthis, packet, len);

   if (packet[0] == 0x00)
      return decryptres;

   return decryptres;
}

HRESULT WINAPI EndSceneHook(LPDIRECT3DDEVICE9 pDevice)
{
   HRESULT res = oEndScene(pDevice);

    return res;
}

HRESULT WINAPI ResetHook(LPDIRECT3DDEVICE9 pDevice, D3DPRESENT_PARAMETERS* pPresentationParameters)
{
    HRESULT res = oReset(pDevice, pPresentationParameters);

    return res;
}

void createConsole()
{
   AllocConsole();
   int hCrt, i;
   FILE *hf;
   hCrt = _open_osfhandle((long) GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
   hf = _fdopen( hCrt, "w" );
   *stdout = *hf;
   i = setvbuf( stdout, NULL, _IONBF, 0 );
}


Code:
#ifndef __MAIN_H__
#define __MAIN_H__

#include <windows.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <d3d9.h>
#include <d3dx9.h>

#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")

#include "detours\detours.h"
#pragma comment(lib, "detours\\detours.lib")

typedef unsigned char   uint8;
typedef unsigned short   uint16;
typedef unsigned int   uint32;

//These are the function prototypes
typedef int (__thiscall* tDecrypt)(void* pthis, uint8* packet, int length);
typedef int (__thiscall* tEncrypt)(void* pthis, uint8* packet, int len);
typedef int (__cdecl *tSendPacket)(uint8 opcode, uint8* packet, int len);
typedef HRESULT (WINAPI* tEndScene)(LPDIRECT3DDEVICE9 pDevice);
typedef HRESULT(WINAPI* tReset)(LPDIRECT3DDEVICE9 pDevice, D3DPRESENT_PARAMETERS* pPresentationParameters);

tDecrypt oDecrypt = NULL;
tEncrypt oEncrypt = NULL;

tSendPacket oSendPacket = NULL;
tEndScene oEndScene = NULL;
tReset oReset = NULL;

int __fastcall encryptHook(void *pthis, void* unk, uint8* packet, int len);
int __fastcall decryptHook(void *pthis, void* unk, uint8* packet, int len);

HRESULT WINAPI ResetHook(LPDIRECT3DDEVICE9 pDevice, D3DPRESENT_PARAMETERS* pPresentationParameters);
HRESULT WINAPI EndSceneHook(LPDIRECT3DDEVICE9 pDevice);

void createConsole();

//For some reason my compiler is being difficult, and i have to export my main function.
//Really shouldnt have to do this, but meh it works
#ifdef BUILD_DLL
    #define DLL_EXPORT __declspec(dllexport)
#else
    #define DLL_EXPORT __declspec(dllimport)
#endif


#ifdef __cplusplus
extern "C"
{
#endif

BOOL DLL_EXPORT APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);

#ifdef __cplusplus
}
#endif

#endif // __MAIN_H__


Top
 Profile  
 
PostPosted: 21 Aug 2013 21:28 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
Onto the next logical step, for anyone looking to make a mod. We need to be able to process the packets WITHOUT lagging up the game. If we try to process all the packets right as they come in, the game will be slowed down alot.

My method may not be the best, but it works (always enjoy seeing how others do stuff, if anyone posts).

So the goal is to create a Queue, thank god C++ already has a Queue library. Then we just need to create a background thread that will process the queue.

Simple add the queue library
Code:
#include <queue>
using namespace std;



then lets define our queue and our queue thread
Code:
queue<uint8*> inPackets;
DWORD WINAPI InPacketsProcesser(LPVOID lpBuffer);


Then we have to pass the incoming packets to our queue, so we add this to our decrypt hook
Code:
uint8* data = new uint8[len];
memcpy(data, packet, len);
inPackets.push(data);


Because the variable "packet" is a pointer, if we pass that to our queue, when we read it from the queue processer we will have an encrypted packet. So we have to create our own variable and copy the info from "packet" to our new pointer and then pass that pointer to our queue.


Now we set up our Queue Processer thread
Code:
DWORD WINAPI InPacketsProcesser(LPVOID lpBuffer)
{
   while(bRunning)
   {
      if(!inPackets.empty()) //If there are packets in the queue
      {
         uint8* packet = inPackets.front();

         //Do whatever with packet here

         free(packet);
         inPackets.pop();
      }
      Sleep(10);
   }
   return 0;
}





Now we can work with the incoming packets without lagging the game up. Next, when i get around to it, ill post some basic info about a few of the packets that we want to analyze,


Top
 Profile  
 
PostPosted: 22 Aug 2013 18:15 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
Was very happy to see that the program found the correct addresses after the update today.


So lets talk about the Update packet (op code 0x03). The update packet contains a lot of useful data. The layout is as follows
Code:
<character info> //22 bytes, always sent
<objects>
<spells>
<units>


Andy has created a structure already that is very useful, its a great wrapper for the first 22 bytes of the update packet
Code:
struct UpdatePacketSelf
{
   uint16 positionX; //0
   uint16 positionY; //2
   uint16 spellflags; //4
   uint16 colorbits; //6
   uint16 numInRangeDynamicObjects; //8
   uint8 numInRangeUnits; //10
   uint8 unklol; //11
   uint8 flags; //12 if & 1, expect self say text at end, if & 2, spellflags contain cooldown data, & 4 you're in pvp mode
   uint8 rotation; //13
   uint8 animation; //14
   uint8 spellEffect; //15
   uint8 numInRangeSpellEffects; //16
   uint8 curentLight; //17
   uint8 unklol3; //18
   uint8 currentHPPct; //19
   uint8 currentMPPct; //20 for hp mp and exp, 0 = 0%, 255 = 100%
   uint8 currentExpPct; //21
};


From the first 22 bytes you can already learn a lot about the game. Now, when making an item scanner the only thing we really need is the "numInRangeDynamicObjects". The dynamic objects come in 3 different ways, each has its own opcode. This is how they are laid out

Code:
//<uint8 opcode><uint16 x><uint16 y><data>
01 - single item on ground
> sample data: 01 00 01 00 01 00 01
That would mean there is a dagger on the ground at -loc 1,1

02 - pile of items on ground (only top 3 visible)
> sample data: 02 00 01 00 01 00 01 00 02 00 03
This would show a dagger, staff, and mace in a pile on the ground at -loc 1,1

03 - uses for objects like fires, dropwalls, chests, ect
> sample data: 03 00 01 00 01 00
This would mean that object at -loc 1,1 has the flag 0x00. I believe for things like chest/drop walls, that means they are open



To run through the objects, this would be a basic example of pseudo-code that should work (just wrote this without testing)
Code:
for(int i = 0; i < numInRangeDynamicObjects; i++)
{
   uint8 opcode;
   uint16 x,y;

   opcode = *(uint8*)&packet[offset];
   offset++;

   x = *(uint16*)&packet[offset];
   offset += 2;

   y = *(uint16*)&packet[offset];
   offset += 2;

   if(opcode == 0x01)
   {
      uint16 itemid = *(uint16*)&packet[offset];
      offset += 2;
   }
   else if(opcode == 0x02)
   {
      uint16 itemid1, itemid2, itemid3;
      itemid1 = *(uint16*)&packet[offset];
      offset += 2;
      itemid2 = *(uint16*)&packet[offset];
      offset += 2;
      itemid3 = *(uint16*)&packet[offset];
      offset += 2;
   }
   else if(opcode == 0x03)
   {
      uint8 flag = *(uint8*)&packet[offset];
      offset++;
   }
}


So there you have it. Pretty simple to extract the items/objects that are on the ground from the packets. Ill get around to putting that into the code i posted above, and then post that source so people can see it.


Top
 Profile  
 
PostPosted: 24 Aug 2013 22:38 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
Might as well post about the drop screen packet, as i was just using it to display all the items in game. viewtopic.php?f=1&t=94342


Anyways, the drop/inventory/use/storage/trade screens all use very similar structures. The drop screen packet is 0x11. Here is the structure i created for the drop screen

Code:
struct InventorySlot{
   uint16 itemId;
   uint16 flags; //Usually the quantity of the item
};

struct DropScreen{
   InventorySlot slots[50];
   uint32 money;
   uint16 unk; //Just a blank buffer from what ive seen
   uint16 checksum;
};


Everything is pretty easy to understand, the checksum is the only thing that takes a small amount of explaining. The checksum is used by EJ as an attempt to prevent people from changing the items in their inventory. But he uses the dumbest method, and its the same method he uses every single time there is a checksum. The checksum is the value of all the bytes in the packet added up (minus the checksum obviously, and the packets opcode/encrypt key).


This is the method i used to display all the items in game. It shows how i create the checksum as well.

Code:
   if(packet[0] == 0x11)
   {
      DropScreen *inven = (DropScreen*)&packet[2];

      for(uint16 i = 0; i < 50; i++)
      {
         inven->slots[i].itemId = i + start; //start is the first ID i want to start at. its set at 0 currently
         inven->slots[i].flags = 1;
      }

      int16 checksum = 0;
      for (uint32 i=0; i<50; ++i)
      {
         checksum += (int8)(inven->slots[i].itemId);
         checksum += (int8)(inven->slots[i].itemId >> 8);
         checksum += (int8)(inven->slots[i].flags);
         checksum += (int8)(inven->slots[i].flags >> 8);
      }
      checksum += (int8)inven->money;
      checksum += (int8)(inven->money >> 8);
      checksum += (int8)(inven->money >> 16);
      checksum += (int8)(inven->money >> 24);

      inven->checksum = (uint16)checksum;
   }


Top
 Profile  
 
PostPosted: 25 Aug 2013 16:11 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
Again, ive gotten side tracked. Decided to create a class to handle the onscreen units. This is a small step in....you know...understanding where units are onscreen. It can be used for a few different reasons, of which i wont say. So i decided to create a class to wrap my hash_map, and put a mutex in use for it. For those that dont know, a mutex is an object that declears ownership. The best example i can give is like the game where everyone passes a ball around to eachother, and the person holding the ball is the only person that can talk. So the person talks, then passes the ball to someone else, and now that person can talk. This is how a mutex works. The reason i implemented a mutex is because in earlier coding i had done, my program would sometimes crash due to variables being accesses from multiple threads; as in, one thread would be trying to read and the other would be trying to write to the same variable.


Onto the code. Again, i have to thank andy for the structs i use (and understanding the unit structure)


Here is the code for the UnitMap class
Spoiler:
Code:
//UnitMap.h
#ifndef __UNITMAP_H__
#define __UNITMAP_H__

#include <windows.h>
#include <stdio.h>
#include <hash_map>
#include <vector>
using namespace std;

typedef unsigned char   uint8;
typedef unsigned short   uint16;
typedef unsigned int   uint32;
typedef signed char      int8;
typedef signed short   int16;
typedef signed int      int32;

struct UpdatePacketUnitMovement
{
   uint16 positionX;
   uint16 positionY;
   uint8 rotation;
};

struct UpdatePacketUnitAuras
{
   uint16 auraflags; //(&0x08 = invis)
   uint8 auraflagsextra; //calv head glow, only time seen in use
};

struct UpdatePacketUnitModels
{
   uint16 model;
   uint16 weapon;
   uint8 shield;
   uint8 helmet;
   uint16 colorbits;
};

struct UpdatePacketUnitAnim
{
   uint8 anim;
};

struct UpdatePacketUnitSpellEffect
{
   uint8 spelleff;
};

struct UpdatePacketUnitChat
{
   uint8 stringsize;
};

struct Unit
{
   uint16 id;
   UpdatePacketUnitMovement movement;
   UpdatePacketUnitAuras auras;
   UpdatePacketUnitModels models;
   UpdatePacketUnitAnim anim;
   UpdatePacketUnitSpellEffect spelleffect;


   BOOL inrange;
   BOOL alive;
};

class UnitMap{
private:
   static HANDLE ghMutex;
   static hash_map<int, Unit*> map;
public:
   static void Initialize();
   static void Destroy();
   static void SetAllOutOfRange();
   static void CheckExsists(uint16 id);
   static void SetUnitInRange(uint16 id);
   static void UpdateUnitsMovement(uint16 id, UpdatePacketUnitMovement movement);
   static void UpdateUnitsAuras(uint16 id, UpdatePacketUnitAuras auras);
   static void UpdateUnitsModel(uint16 id, UpdatePacketUnitModels models);
   static void UpdateUnitsAnim(uint16 id, UpdatePacketUnitAnim anim);
   static void UpdateUnitsSpellEffect(uint16 id, UpdatePacketUnitSpellEffect spelleffect);
   static void CleanUnits();

   static void OutputUnitMap();
};


#endif

Code:
//UnitMap.cpp
#include "UnitMap.h"

HANDLE UnitMap::ghMutex;
hash_map<int, Unit*> UnitMap::map;

void UnitMap::Initialize()
{
   ghMutex = CreateMutex(NULL, FALSE, NULL);
}

void UnitMap::Destroy()
{
   CloseHandle(ghMutex);
}

void UnitMap::SetAllOutOfRange()
{
   DWORD dwWaitResult;
   
   dwWaitResult = WaitForSingleObject(ghMutex, INFINITE);
   switch (dwWaitResult)
   {
   case WAIT_OBJECT_0:
      __try {
         hash_map<int, Unit*>::iterator iter;
         for(iter = map.begin(); iter != map.end(); iter++)
            iter->second->inrange = false;
      }
      __finally {
         if(!ReleaseMutex(ghMutex))
         {
            printf("Failed to release mutex: %d\n", GetLastError());
         }
      }
      break;
   case WAIT_ABANDONED:
      break;
   }
}


void UnitMap::SetUnitInRange(uint16 id)
{
   DWORD dwWaitResult;
   
   dwWaitResult = WaitForSingleObject(ghMutex, INFINITE);
   switch (dwWaitResult)
   {
   case WAIT_OBJECT_0:
      __try {
         if(map[id] == NULL)
         {
            Unit* tmp = new Unit;
            tmp->id = id;
            map[id] = tmp;
         }
         map[id]->inrange = true;
      }
      __finally {
         if(!ReleaseMutex(ghMutex))
         {
            printf("Failed to release mutex: %d\n", GetLastError());
         }
      }
      break;
   case WAIT_ABANDONED:
      break;
   }
}

void UnitMap::UpdateUnitsMovement(uint16 id, UpdatePacketUnitMovement movement)
{
   DWORD dwWaitResult;
   
   dwWaitResult = WaitForSingleObject(ghMutex, INFINITE);
   switch (dwWaitResult)
   {
   case WAIT_OBJECT_0:
      __try {
         map[id]->movement = movement;
      }
      __finally {
         if(!ReleaseMutex(ghMutex))
         {
            printf("Failed to release mutex: %d\n", GetLastError());
         }
      }
      break;
   case WAIT_ABANDONED:
      break;
   }
}

void UnitMap::UpdateUnitsAuras(uint16 id, UpdatePacketUnitAuras auras)
{
   DWORD dwWaitResult;
   
   dwWaitResult = WaitForSingleObject(ghMutex, INFINITE);
   switch (dwWaitResult)
   {
   case WAIT_OBJECT_0:
      __try {
         map[id]->auras = auras;
      }
      __finally {
         if(!ReleaseMutex(ghMutex))
         {
            printf("Failed to release mutex: %d\n", GetLastError());
         }
      }
      break;
   case WAIT_ABANDONED:
      break;
   }
}

void UnitMap::UpdateUnitsModel(uint16 id, UpdatePacketUnitModels models)
{
   DWORD dwWaitResult;
   
   dwWaitResult = WaitForSingleObject(ghMutex, INFINITE);
   switch (dwWaitResult)
   {
   case WAIT_OBJECT_0:
      __try {
         map[id]->models = models;
      }
      __finally {
         if(!ReleaseMutex(ghMutex))
         {
            printf("Failed to release mutex: %d\n", GetLastError());
         }
      }
      break;
   case WAIT_ABANDONED:
      break;
   }
}

void UnitMap::UpdateUnitsAnim(uint16 id, UpdatePacketUnitAnim anim)
{
   DWORD dwWaitResult;
   
   dwWaitResult = WaitForSingleObject(ghMutex, INFINITE);
   switch (dwWaitResult)
   {
   case WAIT_OBJECT_0:
      __try {
         map[id]->anim = anim;
         if(anim.anim == 21 || anim.anim == 45)
                  map[id]->alive = false;
               else
                  map[id]->alive = true;
      }
      __finally {
         if(!ReleaseMutex(ghMutex))
         {
            printf("Failed to release mutex: %d\n", GetLastError());
         }
      }
      break;
   case WAIT_ABANDONED:
      break;
   }
}

void UnitMap::UpdateUnitsSpellEffect(uint16 id, UpdatePacketUnitSpellEffect spelleffect)
{
   DWORD dwWaitResult;
   
   dwWaitResult = WaitForSingleObject(ghMutex, INFINITE);
   switch (dwWaitResult)
   {
   case WAIT_OBJECT_0:
      __try {
         map[id]->spelleffect = spelleffect;
      }
      __finally {
         if(!ReleaseMutex(ghMutex))
         {
            printf("Failed to release mutex: %d\n", GetLastError());
         }
      }
      break;
   case WAIT_ABANDONED:
      break;
   }
}

void UnitMap::CleanUnits()
{
   DWORD dwWaitResult;
   
   dwWaitResult = WaitForSingleObject(ghMutex, INFINITE);
   switch (dwWaitResult)
   {
   case WAIT_OBJECT_0:
      __try {
         hash_map<int, Unit*>::iterator iter;
         hash_map<int, Unit*>::iterator start = map.begin();
         hash_map<int, Unit*>::iterator end = map.end();
         for(iter = start; iter != end; iter++)
         {
            if(!iter->second->inrange)
            {
               free(map[iter->first]);
               map.erase(iter->first);
            }
         }
      }
      __finally {
         if(!ReleaseMutex(ghMutex))
         {
            printf("Failed to release mutex: %d\n", GetLastError());
         }
      }
      break;
   case WAIT_ABANDONED:
      break;
   }
}

void UnitMap::OutputUnitMap()
{
   DWORD dwWaitResult;

   FILE* out = fopen("UnitMap.log", "a+");
   fprintf(out, "-----------------------------------------------------------------------\n");
   fprintf(out, "| Units On Screen: %i                                                 |\n", map.size());
   fprintf(out, "-----------------------------------------------------------------------\n");
   
   dwWaitResult = WaitForSingleObject(ghMutex, INFINITE);
   switch (dwWaitResult)
   {
   case WAIT_OBJECT_0:
      __try {
         hash_map<int, Unit*>::iterator iter;
         for(iter = map.begin(); iter != map.end(); iter++)
         {
            fprintf(out, "ID: %i | Model: %i | Weapon: %i | Sheild: %i | Helmet: %i | Colorbits: %i | X/Y: %i, %i\n", iter->second->id, iter->second->models.model, iter->second->models.weapon, iter->second->models.shield, iter->second->models.helmet, iter->second->models.colorbits, iter->second->movement.positionX, iter->second->movement.positionY);
         }
      }
      __finally {
         if(!ReleaseMutex(ghMutex))
         {
            printf("Failed to release mutex: %d\n", GetLastError());
         }
      }
      break;
   case WAIT_ABANDONED:
      break;
   }
   fprintf(out, "\n");
   fclose(out);
}



Then my handleUpdatePacket
Spoiler:
Code:
void handleUpdatePacket(uint8* data, int len)
{
   UpdatePacketSelf *update = (UpdatePacketSelf*)&data[2];
   int offset = 24;

   if(update->numInRangeDynamicObjects > 0)
   {
      for(int i = 0; i < update->numInRangeDynamicObjects; i++)
      {
         if(data[offset] == 0x01) offset += 8;
         else if(data[offset] == 0x02) offset += 12;
         else if(data[offset] == 0x03) offset += 6;
      }
   }

   if(update->numInRangeSpellEffects > 0)
   {
      for(int x = 0; x < update->numInRangeSpellEffects; x++)
      {
         if(data[offset] >= 240) offset += 12;
         else offset += 8;
      }
   }

   UnitMap::SetAllOutOfRange();
   if(update->numInRangeUnits > 0)
   {
      for(int i = 0; i < update->numInRangeUnits; i++)
      {
         uint16 id = (data[offset+1] << 8) + data[offset];
         uint16 trueid = id & 0x7FFF;
         UnitMap::SetUnitInRange(trueid);
         offset += 2;

         if(id & 0x8000)
            continue;
         else
         {
            uint8 updateflag = data[offset];
            offset += 1;

            if(updateflag & 0x01)
            {
               UnitMap::UpdateUnitsMovement(trueid, *(UpdatePacketUnitMovement*)&data[offset]);
               offset += 5;
            }
            if(updateflag & 0x02)
            {
               UnitMap::UpdateUnitsAuras(trueid, *(UpdatePacketUnitAuras*)&data[offset]);
               offset += 3;
            }
            if(updateflag & 0x04)
            {
               UnitMap::UpdateUnitsModel(trueid, *(UpdatePacketUnitModels*)&data[offset]);
               offset += 8;
            }
            if(updateflag & 0x08)
            {
               UnitMap::UpdateUnitsAnim(trueid, *(UpdatePacketUnitAnim*)&data[offset]);
               offset += 1;
            }
            if(updateflag & 0x10)
            {
               UnitMap::UpdateUnitsSpellEffect(trueid, *(UpdatePacketUnitSpellEffect*)&data[offset]);
               offset += 1;
            }
            if(updateflag & 0x20)
            {
               offset += 1 + data[offset];
            }
         }
      }
   }
   UnitMap::CleanUnits();
   UnitMap::OutputUnitMap();
}



and here is the output i dumped using it
Spoiler:
Code:
-----------------------------------------------------------------------
| Units On Screen: 27                                                 |
-----------------------------------------------------------------------
ID: 81 | Model: 128 | Weapon: 103 | Sheild: 16 | Helmet: 11 | Colorbits: 1651 | X/Y: 988, 1115
ID: 7633 | Model: 493 | Weapon: 345 | Sheild: 0 | Helmet: 15 | Colorbits: 798 | X/Y: 1015, 1140
ID: 307 | Model: 19 | Weapon: 0 | Sheild: 0 | Helmet: 0 | Colorbits: 87 | X/Y: 744, 990
ID: 11123 | Model: 94 | Weapon: 90 | Sheild: 16 | Helmet: 23 | Colorbits: 0 | X/Y: 751, 1005
ID: 827 | Model: 8 | Weapon: 387 | Sheild: 0 | Helmet: 32 | Colorbits: 143 | X/Y: 1006, 1180
ID: 6467 | Model: 387 | Weapon: 413 | Sheild: 21 | Helmet: 12 | Colorbits: 594 | X/Y: 969, 1108
ID: 1341 | Model: 289 | Weapon: 103 | Sheild: 28 | Helmet: 20 | Colorbits: 1453 | X/Y: 898, 1129
ID: 3421 | Model: 450 | Weapon: 82 | Sheild: 0 | Helmet: 12 | Colorbits: 495 | X/Y: 891, 1105
ID: 1368 | Model: 491 | Weapon: 103 | Sheild: 28 | Helmet: 26 | Colorbits: 693 | X/Y: 938, 1080
ID: 7000 | Model: 525 | Weapon: 32 | Sheild: 0 | Helmet: 0 | Colorbits: 66 | X/Y: 1176, 1358
ID: 8088 | Model: 133 | Weapon: 125 | Sheild: 21 | Helmet: 27 | Colorbits: 198 | X/Y: 997, 1150
ID: 5186 | Model: 361 | Weapon: 413 | Sheild: 14 | Helmet: 22 | Colorbits: 594 | X/Y: 929, 1051
ID: 5710 | Model: 132 | Weapon: 345 | Sheild: 16 | Helmet: 19 | Colorbits: 575 | X/Y: 927, 1106
ID: 6498 | Model: 465 | Weapon: 50 | Sheild: 10 | Helmet: 24 | Colorbits: 143 | X/Y: 1119, 1272
ID: 8162 | Model: 114 | Weapon: 468 | Sheild: 0 | Helmet: 28 | Colorbits: 699 | X/Y: 960, 1120
ID: 15266 | Model: 65 | Weapon: 125 | Sheild: 0 | Helmet: 24 | Colorbits: 0 | X/Y: 844, 1153
ID: 6506 | Model: 369 | Weapon: 83 | Sheild: 0 | Helmet: 27 | Colorbits: 1552 | X/Y: 884, 1049
ID: 6859 | Model: 387 | Weapon: 416 | Sheild: 29 | Helmet: 19 | Colorbits: 845 | X/Y: 1027, 1193
ID: 6999 | Model: 101 | Weapon: 48 | Sheild: 8 | Helmet: 6 | Colorbits: 66 | X/Y: 1189, 1171
ID: 7117 | Model: 64 | Weapon: 18 | Sheild: 0 | Helmet: 0 | Colorbits: 0 | X/Y: 1054, 1324
ID: 8153 | Model: 354 | Weapon: 239 | Sheild: 5 | Helmet: 23 | Colorbits: 210 | X/Y: 885, 1154
ID: 8614 | Model: 363 | Weapon: 104 | Sheild: 30 | Helmet: 19 | Colorbits: 132 | X/Y: 873, 1128
ID: 9639 | Model: 126 | Weapon: 61 | Sheild: 0 | Helmet: 26 | Colorbits: 483 | X/Y: 866, 1078
ID: 9726 | Model: 361 | Weapon: 445 | Sheild: 0 | Helmet: 32 | Colorbits: 987 | X/Y: 976, 1178
ID: 10911 | Model: 281 | Weapon: 500 | Sheild: 0 | Helmet: 29 | Colorbits: 1816 | X/Y: 945, 1095
ID: 12080 | Model: 126 | Weapon: 103 | Sheild: 16 | Helmet: 22 | Colorbits: 891 | X/Y: 921, 1126
ID: 14079 | Model: 78 | Weapon: 82 | Sheild: 0 | Helmet: 11 | Colorbits: 416 | X/Y: 976, 1153

-----------------------------------------------------------------------
| Units On Screen: 27                                                 |
-----------------------------------------------------------------------
ID: 81 | Model: 128 | Weapon: 103 | Sheild: 16 | Helmet: 11 | Colorbits: 1651 | X/Y: 988, 1115
ID: 7633 | Model: 493 | Weapon: 345 | Sheild: 0 | Helmet: 15 | Colorbits: 798 | X/Y: 1015, 1140
ID: 307 | Model: 19 | Weapon: 0 | Sheild: 0 | Helmet: 0 | Colorbits: 87 | X/Y: 744, 991
ID: 11123 | Model: 94 | Weapon: 90 | Sheild: 16 | Helmet: 23 | Colorbits: 0 | X/Y: 751, 1005
ID: 827 | Model: 8 | Weapon: 387 | Sheild: 0 | Helmet: 32 | Colorbits: 143 | X/Y: 1006, 1180
ID: 6467 | Model: 387 | Weapon: 413 | Sheild: 21 | Helmet: 12 | Colorbits: 594 | X/Y: 969, 1108
ID: 1341 | Model: 289 | Weapon: 103 | Sheild: 28 | Helmet: 20 | Colorbits: 1453 | X/Y: 898, 1129
ID: 3421 | Model: 450 | Weapon: 82 | Sheild: 0 | Helmet: 12 | Colorbits: 495 | X/Y: 891, 1105
ID: 1368 | Model: 491 | Weapon: 103 | Sheild: 28 | Helmet: 26 | Colorbits: 693 | X/Y: 938, 1080
ID: 7000 | Model: 525 | Weapon: 32 | Sheild: 0 | Helmet: 0 | Colorbits: 66 | X/Y: 1175, 1357
ID: 8088 | Model: 133 | Weapon: 125 | Sheild: 21 | Helmet: 27 | Colorbits: 198 | X/Y: 997, 1150
ID: 5186 | Model: 361 | Weapon: 413 | Sheild: 14 | Helmet: 22 | Colorbits: 594 | X/Y: 929, 1051
ID: 5710 | Model: 132 | Weapon: 345 | Sheild: 16 | Helmet: 19 | Colorbits: 575 | X/Y: 927, 1106
ID: 6498 | Model: 465 | Weapon: 50 | Sheild: 10 | Helmet: 24 | Colorbits: 143 | X/Y: 1119, 1272
ID: 8162 | Model: 114 | Weapon: 468 | Sheild: 0 | Helmet: 28 | Colorbits: 699 | X/Y: 960, 1120
ID: 15266 | Model: 65 | Weapon: 125 | Sheild: 0 | Helmet: 24 | Colorbits: 0 | X/Y: 844, 1153
ID: 6506 | Model: 369 | Weapon: 83 | Sheild: 0 | Helmet: 27 | Colorbits: 1552 | X/Y: 884, 1049
ID: 6859 | Model: 387 | Weapon: 416 | Sheild: 29 | Helmet: 19 | Colorbits: 845 | X/Y: 1027, 1193
ID: 6999 | Model: 101 | Weapon: 48 | Sheild: 8 | Helmet: 6 | Colorbits: 66 | X/Y: 1189, 1171
ID: 7117 | Model: 64 | Weapon: 18 | Sheild: 0 | Helmet: 0 | Colorbits: 0 | X/Y: 1054, 1324
ID: 8153 | Model: 354 | Weapon: 239 | Sheild: 5 | Helmet: 23 | Colorbits: 210 | X/Y: 885, 1154
ID: 8614 | Model: 363 | Weapon: 104 | Sheild: 30 | Helmet: 19 | Colorbits: 132 | X/Y: 873, 1128
ID: 9639 | Model: 126 | Weapon: 61 | Sheild: 0 | Helmet: 26 | Colorbits: 483 | X/Y: 866, 1078
ID: 9726 | Model: 361 | Weapon: 445 | Sheild: 0 | Helmet: 32 | Colorbits: 987 | X/Y: 976, 1178
ID: 10911 | Model: 281 | Weapon: 500 | Sheild: 0 | Helmet: 29 | Colorbits: 1816 | X/Y: 945, 1095
ID: 12080 | Model: 126 | Weapon: 103 | Sheild: 16 | Helmet: 22 | Colorbits: 891 | X/Y: 921, 1126
ID: 14079 | Model: 78 | Weapon: 82 | Sheild: 0 | Helmet: 11 | Colorbits: 416 | X/Y: 976, 1153

-----------------------------------------------------------------------
| Units On Screen: 27                                                 |
-----------------------------------------------------------------------
ID: 81 | Model: 128 | Weapon: 103 | Sheild: 16 | Helmet: 11 | Colorbits: 1651 | X/Y: 988, 1115
ID: 7633 | Model: 493 | Weapon: 345 | Sheild: 0 | Helmet: 15 | Colorbits: 798 | X/Y: 1015, 1140
ID: 307 | Model: 19 | Weapon: 0 | Sheild: 0 | Helmet: 0 | Colorbits: 87 | X/Y: 743, 996
ID: 11123 | Model: 94 | Weapon: 90 | Sheild: 16 | Helmet: 23 | Colorbits: 0 | X/Y: 751, 1005
ID: 827 | Model: 8 | Weapon: 387 | Sheild: 0 | Helmet: 32 | Colorbits: 143 | X/Y: 1006, 1180
ID: 6467 | Model: 387 | Weapon: 413 | Sheild: 21 | Helmet: 12 | Colorbits: 594 | X/Y: 969, 1108
ID: 1341 | Model: 289 | Weapon: 103 | Sheild: 28 | Helmet: 20 | Colorbits: 1453 | X/Y: 898, 1129
ID: 3421 | Model: 450 | Weapon: 82 | Sheild: 0 | Helmet: 12 | Colorbits: 495 | X/Y: 891, 1105
ID: 1368 | Model: 491 | Weapon: 103 | Sheild: 28 | Helmet: 26 | Colorbits: 693 | X/Y: 938, 1080
ID: 7000 | Model: 525 | Weapon: 32 | Sheild: 0 | Helmet: 0 | Colorbits: 66 | X/Y: 1167, 1355
ID: 8088 | Model: 133 | Weapon: 125 | Sheild: 21 | Helmet: 27 | Colorbits: 198 | X/Y: 997, 1150
ID: 5186 | Model: 361 | Weapon: 413 | Sheild: 14 | Helmet: 22 | Colorbits: 594 | X/Y: 929, 1051
ID: 5710 | Model: 132 | Weapon: 345 | Sheild: 16 | Helmet: 19 | Colorbits: 575 | X/Y: 927, 1106
ID: 6498 | Model: 465 | Weapon: 50 | Sheild: 10 | Helmet: 24 | Colorbits: 143 | X/Y: 1119, 1272
ID: 8162 | Model: 114 | Weapon: 468 | Sheild: 0 | Helmet: 28 | Colorbits: 699 | X/Y: 960, 1120
ID: 15266 | Model: 65 | Weapon: 125 | Sheild: 0 | Helmet: 24 | Colorbits: 0 | X/Y: 844, 1153
ID: 6506 | Model: 369 | Weapon: 83 | Sheild: 0 | Helmet: 27 | Colorbits: 1552 | X/Y: 884, 1049
ID: 6859 | Model: 387 | Weapon: 416 | Sheild: 29 | Helmet: 19 | Colorbits: 845 | X/Y: 1027, 1193
ID: 6999 | Model: 101 | Weapon: 48 | Sheild: 8 | Helmet: 6 | Colorbits: 66 | X/Y: 1189, 1171
ID: 7117 | Model: 64 | Weapon: 18 | Sheild: 0 | Helmet: 0 | Colorbits: 0 | X/Y: 1054, 1324
ID: 8153 | Model: 354 | Weapon: 239 | Sheild: 5 | Helmet: 23 | Colorbits: 210 | X/Y: 885, 1154
ID: 8614 | Model: 363 | Weapon: 104 | Sheild: 30 | Helmet: 19 | Colorbits: 132 | X/Y: 873, 1128
ID: 9639 | Model: 126 | Weapon: 61 | Sheild: 0 | Helmet: 26 | Colorbits: 483 | X/Y: 866, 1078
ID: 9726 | Model: 361 | Weapon: 445 | Sheild: 0 | Helmet: 32 | Colorbits: 987 | X/Y: 976, 1178
ID: 10911 | Model: 281 | Weapon: 500 | Sheild: 0 | Helmet: 29 | Colorbits: 1816 | X/Y: 945, 1095
ID: 12080 | Model: 126 | Weapon: 103 | Sheild: 16 | Helmet: 22 | Colorbits: 891 | X/Y: 921, 1126
ID: 14079 | Model: 78 | Weapon: 82 | Sheild: 0 | Helmet: 11 | Colorbits: 416 | X/Y: 976, 1153

-----------------------------------------------------------------------
| Units On Screen: 26                                                 |
-----------------------------------------------------------------------
ID: 81 | Model: 128 | Weapon: 103 | Sheild: 16 | Helmet: 11 | Colorbits: 1651 | X/Y: 988, 1115
ID: 7633 | Model: 493 | Weapon: 345 | Sheild: 0 | Helmet: 15 | Colorbits: 798 | X/Y: 1015, 1140
ID: 11123 | Model: 94 | Weapon: 90 | Sheild: 16 | Helmet: 23 | Colorbits: 0 | X/Y: 751, 1005
ID: 827 | Model: 8 | Weapon: 387 | Sheild: 0 | Helmet: 32 | Colorbits: 143 | X/Y: 1006, 1180
ID: 6467 | Model: 387 | Weapon: 413 | Sheild: 21 | Helmet: 12 | Colorbits: 594 | X/Y: 969, 1108
ID: 1341 | Model: 289 | Weapon: 103 | Sheild: 28 | Helmet: 20 | Colorbits: 1453 | X/Y: 898, 1129
ID: 3421 | Model: 450 | Weapon: 82 | Sheild: 0 | Helmet: 12 | Colorbits: 495 | X/Y: 891, 1105
ID: 1368 | Model: 491 | Weapon: 103 | Sheild: 28 | Helmet: 26 | Colorbits: 693 | X/Y: 938, 1080
ID: 7000 | Model: 525 | Weapon: 32 | Sheild: 0 | Helmet: 0 | Colorbits: 66 | X/Y: 1158, 1352
ID: 8088 | Model: 133 | Weapon: 125 | Sheild: 21 | Helmet: 27 | Colorbits: 198 | X/Y: 997, 1150
ID: 5186 | Model: 361 | Weapon: 413 | Sheild: 14 | Helmet: 22 | Colorbits: 594 | X/Y: 929, 1051
ID: 5710 | Model: 132 | Weapon: 345 | Sheild: 16 | Helmet: 19 | Colorbits: 575 | X/Y: 927, 1106
ID: 6498 | Model: 465 | Weapon: 50 | Sheild: 10 | Helmet: 24 | Colorbits: 143 | X/Y: 1119, 1272
ID: 8162 | Model: 114 | Weapon: 468 | Sheild: 0 | Helmet: 28 | Colorbits: 699 | X/Y: 960, 1120
ID: 15266 | Model: 65 | Weapon: 125 | Sheild: 0 | Helmet: 24 | Colorbits: 0 | X/Y: 844, 1153
ID: 6506 | Model: 369 | Weapon: 83 | Sheild: 0 | Helmet: 27 | Colorbits: 1552 | X/Y: 884, 1049
ID: 6859 | Model: 387 | Weapon: 416 | Sheild: 29 | Helmet: 19 | Colorbits: 845 | X/Y: 1027, 1193
ID: 6999 | Model: 101 | Weapon: 48 | Sheild: 8 | Helmet: 6 | Colorbits: 66 | X/Y: 1189, 1171
ID: 7117 | Model: 64 | Weapon: 18 | Sheild: 0 | Helmet: 0 | Colorbits: 0 | X/Y: 1054, 1324
ID: 8153 | Model: 354 | Weapon: 239 | Sheild: 5 | Helmet: 23 | Colorbits: 210 | X/Y: 885, 1154
ID: 8614 | Model: 363 | Weapon: 104 | Sheild: 30 | Helmet: 19 | Colorbits: 132 | X/Y: 873, 1128
ID: 9639 | Model: 126 | Weapon: 61 | Sheild: 0 | Helmet: 26 | Colorbits: 483 | X/Y: 866, 1078
ID: 9726 | Model: 361 | Weapon: 445 | Sheild: 0 | Helmet: 32 | Colorbits: 987 | X/Y: 976, 1178
ID: 10911 | Model: 281 | Weapon: 500 | Sheild: 0 | Helmet: 29 | Colorbits: 1816 | X/Y: 945, 1095
ID: 12080 | Model: 126 | Weapon: 103 | Sheild: 16 | Helmet: 22 | Colorbits: 891 | X/Y: 921, 1126
ID: 14079 | Model: 78 | Weapon: 82 | Sheild: 0 | Helmet: 11 | Colorbits: 416 | X/Y: 976, 1153

-----------------------------------------------------------------------
| Units On Screen: 26                                                 |
-----------------------------------------------------------------------
ID: 81 | Model: 128 | Weapon: 103 | Sheild: 16 | Helmet: 11 | Colorbits: 1651 | X/Y: 988, 1115
ID: 7633 | Model: 493 | Weapon: 345 | Sheild: 0 | Helmet: 15 | Colorbits: 798 | X/Y: 1015, 1140
ID: 11123 | Model: 94 | Weapon: 90 | Sheild: 16 | Helmet: 23 | Colorbits: 0 | X/Y: 751, 1005
ID: 827 | Model: 8 | Weapon: 387 | Sheild: 0 | Helmet: 32 | Colorbits: 143 | X/Y: 1006, 1180
ID: 6467 | Model: 387 | Weapon: 413 | Sheild: 21 | Helmet: 12 | Colorbits: 594 | X/Y: 969, 1108
ID: 1341 | Model: 289 | Weapon: 103 | Sheild: 28 | Helmet: 20 | Colorbits: 1453 | X/Y: 898, 1129
ID: 3421 | Model: 450 | Weapon: 82 | Sheild: 0 | Helmet: 12 | Colorbits: 495 | X/Y: 891, 1105
ID: 1368 | Model: 491 | Weapon: 103 | Sheild: 28 | Helmet: 26 | Colorbits: 693 | X/Y: 938, 1080
ID: 7000 | Model: 525 | Weapon: 32 | Sheild: 0 | Helmet: 0 | Colorbits: 66 | X/Y: 1151, 1350
ID: 8088 | Model: 133 | Weapon: 125 | Sheild: 21 | Helmet: 27 | Colorbits: 198 | X/Y: 997, 1150
ID: 5186 | Model: 361 | Weapon: 413 | Sheild: 14 | Helmet: 22 | Colorbits: 594 | X/Y: 929, 1051
ID: 5710 | Model: 132 | Weapon: 345 | Sheild: 16 | Helmet: 19 | Colorbits: 575 | X/Y: 927, 1106
ID: 6498 | Model: 465 | Weapon: 50 | Sheild: 10 | Helmet: 24 | Colorbits: 143 | X/Y: 1119, 1272
ID: 8162 | Model: 114 | Weapon: 468 | Sheild: 0 | Helmet: 28 | Colorbits: 699 | X/Y: 960, 1120
ID: 15266 | Model: 65 | Weapon: 125 | Sheild: 0 | Helmet: 24 | Colorbits: 0 | X/Y: 844, 1153
ID: 6506 | Model: 369 | Weapon: 83 | Sheild: 0 | Helmet: 27 | Colorbits: 1552 | X/Y: 884, 1049
ID: 6859 | Model: 387 | Weapon: 416 | Sheild: 29 | Helmet: 19 | Colorbits: 845 | X/Y: 1027, 1193
ID: 6999 | Model: 101 | Weapon: 48 | Sheild: 8 | Helmet: 6 | Colorbits: 66 | X/Y: 1189, 1171
ID: 7117 | Model: 64 | Weapon: 18 | Sheild: 0 | Helmet: 0 | Colorbits: 0 | X/Y: 1054, 1324
ID: 8153 | Model: 354 | Weapon: 239 | Sheild: 5 | Helmet: 23 | Colorbits: 210 | X/Y: 885, 1154
ID: 8614 | Model: 363 | Weapon: 104 | Sheild: 30 | Helmet: 19 | Colorbits: 132 | X/Y: 873, 1128
ID: 9639 | Model: 126 | Weapon: 61 | Sheild: 0 | Helmet: 26 | Colorbits: 483 | X/Y: 866, 1078
ID: 9726 | Model: 361 | Weapon: 445 | Sheild: 0 | Helmet: 32 | Colorbits: 987 | X/Y: 976, 1178
ID: 10911 | Model: 281 | Weapon: 500 | Sheild: 0 | Helmet: 29 | Colorbits: 1816 | X/Y: 945, 1095
ID: 12080 | Model: 126 | Weapon: 103 | Sheild: 16 | Helmet: 22 | Colorbits: 891 | X/Y: 921, 1126
ID: 14079 | Model: 78 | Weapon: 82 | Sheild: 0 | Helmet: 11 | Colorbits: 416 | X/Y: 976, 1153

-----------------------------------------------------------------------
| Units On Screen: 26                                                 |
-----------------------------------------------------------------------
ID: 81 | Model: 128 | Weapon: 103 | Sheild: 16 | Helmet: 11 | Colorbits: 1651 | X/Y: 988, 1115
ID: 7633 | Model: 493 | Weapon: 345 | Sheild: 0 | Helmet: 15 | Colorbits: 798 | X/Y: 1015, 1140
ID: 11123 | Model: 94 | Weapon: 90 | Sheild: 16 | Helmet: 23 | Colorbits: 0 | X/Y: 751, 1005
ID: 827 | Model: 8 | Weapon: 387 | Sheild: 0 | Helmet: 32 | Colorbits: 143 | X/Y: 1006, 1180
ID: 6467 | Model: 387 | Weapon: 413 | Sheild: 21 | Helmet: 12 | Colorbits: 594 | X/Y: 969, 1108
ID: 1341 | Model: 289 | Weapon: 103 | Sheild: 28 | Helmet: 20 | Colorbits: 1453 | X/Y: 898, 1129
ID: 3421 | Model: 450 | Weapon: 82 | Sheild: 0 | Helmet: 12 | Colorbits: 495 | X/Y: 891, 1105
ID: 1368 | Model: 491 | Weapon: 103 | Sheild: 28 | Helmet: 26 | Colorbits: 693 | X/Y: 941, 1077
ID: 7000 | Model: 525 | Weapon: 32 | Sheild: 0 | Helmet: 0 | Colorbits: 66 | X/Y: 1151, 1350
ID: 8088 | Model: 133 | Weapon: 125 | Sheild: 21 | Helmet: 27 | Colorbits: 198 | X/Y: 997, 1150
ID: 5186 | Model: 361 | Weapon: 413 | Sheild: 14 | Helmet: 22 | Colorbits: 594 | X/Y: 929, 1051
ID: 5710 | Model: 132 | Weapon: 345 | Sheild: 16 | Helmet: 19 | Colorbits: 575 | X/Y: 927, 1106
ID: 6498 | Model: 465 | Weapon: 50 | Sheild: 10 | Helmet: 24 | Colorbits: 143 | X/Y: 1119, 1272
ID: 8162 | Model: 114 | Weapon: 468 | Sheild: 0 | Helmet: 28 | Colorbits: 699 | X/Y: 960, 1120
ID: 15266 | Model: 65 | Weapon: 125 | Sheild: 0 | Helmet: 24 | Colorbits: 0 | X/Y: 844, 1153
ID: 6506 | Model: 369 | Weapon: 83 | Sheild: 0 | Helmet: 27 | Colorbits: 1552 | X/Y: 884, 1049
ID: 6859 | Model: 387 | Weapon: 416 | Sheild: 29 | Helmet: 19 | Colorbits: 845 | X/Y: 1027, 1193
ID: 6999 | Model: 101 | Weapon: 48 | Sheild: 8 | Helmet: 6 | Colorbits: 66 | X/Y: 1189, 1171
ID: 7117 | Model: 64 | Weapon: 18 | Sheild: 0 | Helmet: 0 | Colorbits: 0 | X/Y: 1054, 1324
ID: 8153 | Model: 354 | Weapon: 239 | Sheild: 5 | Helmet: 23 | Colorbits: 210 | X/Y: 885, 1154
ID: 8614 | Model: 363 | Weapon: 104 | Sheild: 30 | Helmet: 19 | Colorbits: 132 | X/Y: 873, 1128
ID: 9639 | Model: 126 | Weapon: 61 | Sheild: 0 | Helmet: 26 | Colorbits: 483 | X/Y: 866, 1078
ID: 9726 | Model: 361 | Weapon: 445 | Sheild: 0 | Helmet: 32 | Colorbits: 987 | X/Y: 976, 1178
ID: 10911 | Model: 281 | Weapon: 500 | Sheild: 0 | Helmet: 29 | Colorbits: 1816 | X/Y: 945, 1095
ID: 12080 | Model: 126 | Weapon: 103 | Sheild: 16 | Helmet: 22 | Colorbits: 891 | X/Y: 921, 1126
ID: 14079 | Model: 78 | Weapon: 82 | Sheild: 0 | Helmet: 11 | Colorbits: 416 | X/Y: 976, 1153

-----------------------------------------------------------------------
| Units On Screen: 26                                                 |
-----------------------------------------------------------------------
ID: 81 | Model: 128 | Weapon: 103 | Sheild: 16 | Helmet: 11 | Colorbits: 1651 | X/Y: 988, 1115
ID: 7633 | Model: 493 | Weapon: 345 | Sheild: 0 | Helmet: 15 | Colorbits: 798 | X/Y: 1015, 1140
ID: 11123 | Model: 94 | Weapon: 90 | Sheild: 16 | Helmet: 23 | Colorbits: 0 | X/Y: 751, 1005
ID: 827 | Model: 8 | Weapon: 387 | Sheild: 0 | Helmet: 32 | Colorbits: 143 | X/Y: 1006, 1180
ID: 6467 | Model: 387 | Weapon: 413 | Sheild: 21 | Helmet: 12 | Colorbits: 594 | X/Y: 969, 1108
ID: 1341 | Model: 289 | Weapon: 103 | Sheild: 28 | Helmet: 20 | Colorbits: 1453 | X/Y: 898, 1129
ID: 3421 | Model: 450 | Weapon: 82 | Sheild: 0 | Helmet: 12 | Colorbits: 495 | X/Y: 891, 1105
ID: 1368 | Model: 491 | Weapon: 103 | Sheild: 28 | Helmet: 26 | Colorbits: 693 | X/Y: 948, 1072
ID: 7000 | Model: 525 | Weapon: 32 | Sheild: 0 | Helmet: 0 | Colorbits: 66 | X/Y: 1151, 1350
ID: 8088 | Model: 133 | Weapon: 125 | Sheild: 21 | Helmet: 27 | Colorbits: 198 | X/Y: 997, 1150
ID: 5186 | Model: 361 | Weapon: 413 | Sheild: 14 | Helmet: 22 | Colorbits: 594 | X/Y: 929, 1051
ID: 5710 | Model: 132 | Weapon: 345 | Sheild: 16 | Helmet: 19 | Colorbits: 575 | X/Y: 927, 1106
ID: 6498 | Model: 465 | Weapon: 50 | Sheild: 10 | Helmet: 24 | Colorbits: 143 | X/Y: 1119, 1272
ID: 8162 | Model: 114 | Weapon: 468 | Sheild: 0 | Helmet: 28 | Colorbits: 699 | X/Y: 960, 1120
ID: 15266 | Model: 65 | Weapon: 125 | Sheild: 0 | Helmet: 24 | Colorbits: 0 | X/Y: 844, 1153
ID: 6506 | Model: 369 | Weapon: 83 | Sheild: 0 | Helmet: 27 | Colorbits: 1552 | X/Y: 884, 1049
ID: 6859 | Model: 387 | Weapon: 416 | Sheild: 29 | Helmet: 19 | Colorbits: 845 | X/Y: 1027, 1193
ID: 6999 | Model: 101 | Weapon: 48 | Sheild: 8 | Helmet: 6 | Colorbits: 66 | X/Y: 1189, 1171
ID: 7117 | Model: 64 | Weapon: 18 | Sheild: 0 | Helmet: 0 | Colorbits: 0 | X/Y: 1054, 1324
ID: 8153 | Model: 354 | Weapon: 239 | Sheild: 5 | Helmet: 23 | Colorbits: 210 | X/Y: 885, 1154
ID: 8614 | Model: 363 | Weapon: 104 | Sheild: 30 | Helmet: 19 | Colorbits: 132 | X/Y: 873, 1128
ID: 9639 | Model: 126 | Weapon: 61 | Sheild: 0 | Helmet: 26 | Colorbits: 483 | X/Y: 866, 1078
ID: 9726 | Model: 361 | Weapon: 445 | Sheild: 0 | Helmet: 32 | Colorbits: 987 | X/Y: 976, 1178
ID: 10911 | Model: 281 | Weapon: 500 | Sheild: 0 | Helmet: 29 | Colorbits: 1816 | X/Y: 945, 1095
ID: 12080 | Model: 126 | Weapon: 103 | Sheild: 16 | Helmet: 22 | Colorbits: 891 | X/Y: 921, 1126
ID: 14079 | Model: 78 | Weapon: 82 | Sheild: 0 | Helmet: 11 | Colorbits: 416 | X/Y: 976, 1153

-----------------------------------------------------------------------
| Units On Screen: 26                                                 |
-----------------------------------------------------------------------
ID: 81 | Model: 128 | Weapon: 103 | Sheild: 16 | Helmet: 11 | Colorbits: 1651 | X/Y: 988, 1115
ID: 7633 | Model: 493 | Weapon: 345 | Sheild: 0 | Helmet: 15 | Colorbits: 798 | X/Y: 1015, 1140
ID: 11123 | Model: 94 | Weapon: 90 | Sheild: 16 | Helmet: 23 | Colorbits: 0 | X/Y: 751, 1005
ID: 827 | Model: 8 | Weapon: 387 | Sheild: 0 | Helmet: 32 | Colorbits: 143 | X/Y: 1006, 1180
ID: 6467 | Model: 387 | Weapon: 413 | Sheild: 21 | Helmet: 12 | Colorbits: 594 | X/Y: 969, 1108
ID: 1341 | Model: 289 | Weapon: 103 | Sheild: 28 | Helmet: 20 | Colorbits: 1453 | X/Y: 898, 1129
ID: 3421 | Model: 450 | Weapon: 82 | Sheild: 0 | Helmet: 12 | Colorbits: 495 | X/Y: 891, 1105
ID: 1368 | Model: 491 | Weapon: 103 | Sheild: 28 | Helmet: 26 | Colorbits: 693 | X/Y: 955, 1067
ID: 7000 | Model: 525 | Weapon: 32 | Sheild: 0 | Helmet: 0 | Colorbits: 66 | X/Y: 1151, 1350
ID: 8088 | Model: 133 | Weapon: 125 | Sheild: 21 | Helmet: 27 | Colorbits: 198 | X/Y: 997, 1150
ID: 5186 | Model: 361 | Weapon: 413 | Sheild: 14 | Helmet: 22 | Colorbits: 594 | X/Y: 929, 1051
ID: 5710 | Model: 132 | Weapon: 345 | Sheild: 16 | Helmet: 19 | Colorbits: 575 | X/Y: 927, 1106
ID: 6498 | Model: 465 | Weapon: 50 | Sheild: 10 | Helmet: 24 | Colorbits: 143 | X/Y: 1119, 1272
ID: 8162 | Model: 114 | Weapon: 468 | Sheild: 0 | Helmet: 28 | Colorbits: 699 | X/Y: 960, 1120
ID: 15266 | Model: 65 | Weapon: 125 | Sheild: 0 | Helmet: 24 | Colorbits: 0 | X/Y: 844, 1153
ID: 6506 | Model: 369 | Weapon: 83 | Sheild: 0 | Helmet: 27 | Colorbits: 1552 | X/Y: 884, 1049
ID: 6859 | Model: 387 | Weapon: 416 | Sheild: 29 | Helmet: 19 | Colorbits: 845 | X/Y: 1027, 1193
ID: 6999 | Model: 101 | Weapon: 48 | Sheild: 8 | Helmet: 6 | Colorbits: 66 | X/Y: 1189, 1171
ID: 7117 | Model: 64 | Weapon: 18 | Sheild: 0 | Helmet: 0 | Colorbits: 0 | X/Y: 1054, 1324
ID: 8153 | Model: 354 | Weapon: 239 | Sheild: 5 | Helmet: 23 | Colorbits: 210 | X/Y: 885, 1154
ID: 8614 | Model: 363 | Weapon: 104 | Sheild: 30 | Helmet: 19 | Colorbits: 132 | X/Y: 873, 1128
ID: 9639 | Model: 126 | Weapon: 61 | Sheild: 0 | Helmet: 26 | Colorbits: 483 | X/Y: 866, 1078
ID: 9726 | Model: 361 | Weapon: 445 | Sheild: 0 | Helmet: 32 | Colorbits: 987 | X/Y: 976, 1178
ID: 10911 | Model: 281 | Weapon: 500 | Sheild: 0 | Helmet: 29 | Colorbits: 1816 | X/Y: 945, 1095
ID: 12080 | Model: 126 | Weapon: 103 | Sheild: 16 | Helmet: 22 | Colorbits: 891 | X/Y: 921, 1126
ID: 14079 | Model: 78 | Weapon: 82 | Sheild: 0 | Helmet: 11 | Colorbits: 416 | X/Y: 976, 1153

-----------------------------------------------------------------------
| Units On Screen: 26                                                 |
-----------------------------------------------------------------------
ID: 81 | Model: 128 | Weapon: 103 | Sheild: 16 | Helmet: 11 | Colorbits: 1651 | X/Y: 988, 1115
ID: 7633 | Model: 493 | Weapon: 345 | Sheild: 0 | Helmet: 15 | Colorbits: 798 | X/Y: 1015, 1140
ID: 11123 | Model: 94 | Weapon: 90 | Sheild: 16 | Helmet: 23 | Colorbits: 0 | X/Y: 751, 1005
ID: 827 | Model: 8 | Weapon: 387 | Sheild: 0 | Helmet: 32 | Colorbits: 143 | X/Y: 1006, 1180
ID: 6467 | Model: 387 | Weapon: 413 | Sheild: 21 | Helmet: 12 | Colorbits: 594 | X/Y: 969, 1108
ID: 1341 | Model: 289 | Weapon: 103 | Sheild: 28 | Helmet: 20 | Colorbits: 1453 | X/Y: 898, 1129
ID: 3421 | Model: 450 | Weapon: 82 | Sheild: 0 | Helmet: 12 | Colorbits: 495 | X/Y: 891, 1105
ID: 1368 | Model: 491 | Weapon: 103 | Sheild: 28 | Helmet: 26 | Colorbits: 693 | X/Y: 962, 1063
ID: 7000 | Model: 525 | Weapon: 32 | Sheild: 0 | Helmet: 0 | Colorbits: 66 | X/Y: 1151, 1350
ID: 8088 | Model: 133 | Weapon: 125 | Sheild: 21 | Helmet: 27 | Colorbits: 198 | X/Y: 997, 1150
ID: 5186 | Model: 361 | Weapon: 413 | Sheild: 14 | Helmet: 22 | Colorbits: 594 | X/Y: 929, 1051
ID: 5710 | Model: 132 | Weapon: 345 | Sheild: 16 | Helmet: 19 | Colorbits: 575 | X/Y: 927, 1106
ID: 6498 | Model: 465 | Weapon: 50 | Sheild: 10 | Helmet: 24 | Colorbits: 143 | X/Y: 1119, 1272
ID: 8162 | Model: 114 | Weapon: 468 | Sheild: 0 | Helmet: 28 | Colorbits: 699 | X/Y: 960, 1120
ID: 15266 | Model: 65 | Weapon: 125 | Sheild: 0 | Helmet: 24 | Colorbits: 0 | X/Y: 844, 1153
ID: 6506 | Model: 369 | Weapon: 83 | Sheild: 0 | Helmet: 27 | Colorbits: 1552 | X/Y: 884, 1049
ID: 6859 | Model: 387 | Weapon: 416 | Sheild: 29 | Helmet: 19 | Colorbits: 845 | X/Y: 1027, 1193
ID: 6999 | Model: 101 | Weapon: 48 | Sheild: 8 | Helmet: 6 | Colorbits: 66 | X/Y: 1189, 1171
ID: 7117 | Model: 64 | Weapon: 18 | Sheild: 0 | Helmet: 0 | Colorbits: 0 | X/Y: 1054, 1324
ID: 8153 | Model: 354 | Weapon: 239 | Sheild: 5 | Helmet: 23 | Colorbits: 210 | X/Y: 885, 1154
ID: 8614 | Model: 363 | Weapon: 104 | Sheild: 30 | Helmet: 19 | Colorbits: 132 | X/Y: 873, 1128
ID: 9639 | Model: 126 | Weapon: 61 | Sheild: 0 | Helmet: 26 | Colorbits: 483 | X/Y: 866, 1078
ID: 9726 | Model: 361 | Weapon: 445 | Sheild: 0 | Helmet: 32 | Colorbits: 987 | X/Y: 976, 1178
ID: 10911 | Model: 281 | Weapon: 500 | Sheild: 0 | Helmet: 29 | Colorbits: 1816 | X/Y: 945, 1095
ID: 12080 | Model: 126 | Weapon: 103 | Sheild: 16 | Helmet: 22 | Colorbits: 891 | X/Y: 921, 1126
ID: 14079 | Model: 78 | Weapon: 82 | Sheild: 0 | Helmet: 11 | Colorbits: 416 | X/Y: 976, 1153

-----------------------------------------------------------------------
| Units On Screen: 26                                                 |
-----------------------------------------------------------------------
ID: 81 | Model: 128 | Weapon: 103 | Sheild: 16 | Helmet: 11 | Colorbits: 1651 | X/Y: 988, 1115
ID: 7633 | Model: 493 | Weapon: 345 | Sheild: 0 | Helmet: 15 | Colorbits: 798 | X/Y: 1015, 1140
ID: 11123 | Model: 94 | Weapon: 90 | Sheild: 16 | Helmet: 23 | Colorbits: 0 | X/Y: 751, 1005
ID: 827 | Model: 8 | Weapon: 387 | Sheild: 0 | Helmet: 32 | Colorbits: 143 | X/Y: 1006, 1180
ID: 6467 | Model: 387 | Weapon: 413 | Sheild: 21 | Helmet: 12 | Colorbits: 594 | X/Y: 969, 1108
ID: 1341 | Model: 289 | Weapon: 103 | Sheild: 28 | Helmet: 20 | Colorbits: 1453 | X/Y: 898, 1129
ID: 3421 | Model: 450 | Weapon: 82 | Sheild: 0 | Helmet: 12 | Colorbits: 495 | X/Y: 891, 1105
ID: 1368 | Model: 491 | Weapon: 103 | Sheild: 28 | Helmet: 26 | Colorbits: 693 | X/Y: 970, 1060
ID: 7000 | Model: 525 | Weapon: 32 | Sheild: 0 | Helmet: 0 | Colorbits: 66 | X/Y: 1151, 1350
ID: 8088 | Model: 133 | Weapon: 125 | Sheild: 21 | Helmet: 27 | Colorbits: 198 | X/Y: 997, 1150
ID: 5186 | Model: 361 | Weapon: 413 | Sheild: 14 | Helmet: 22 | Colorbits: 594 | X/Y: 929, 1051
ID: 5710 | Model: 132 | Weapon: 345 | Sheild: 16 | Helmet: 19 | Colorbits: 575 | X/Y: 927, 1106
ID: 6498 | Model: 465 | Weapon: 50 | Sheild: 10 | Helmet: 24 | Colorbits: 143 | X/Y: 1119, 1272
ID: 8162 | Model: 114 | Weapon: 468 | Sheild: 0 | Helmet: 28 | Colorbits: 699 | X/Y: 960, 1120
ID: 15266 | Model: 65 | Weapon: 125 | Sheild: 0 | Helmet: 24 | Colorbits: 0 | X/Y: 844, 1153
ID: 6506 | Model: 369 | Weapon: 83 | Sheild: 0 | Helmet: 27 | Colorbits: 1552 | X/Y: 884, 1049
ID: 6859 | Model: 387 | Weapon: 416 | Sheild: 29 | Helmet: 19 | Colorbits: 845 | X/Y: 1027, 1193
ID: 6999 | Model: 101 | Weapon: 48 | Sheild: 8 | Helmet: 6 | Colorbits: 66 | X/Y: 1189, 1171
ID: 7117 | Model: 64 | Weapon: 18 | Sheild: 0 | Helmet: 0 | Colorbits: 0 | X/Y: 1054, 1324
ID: 8153 | Model: 354 | Weapon: 239 | Sheild: 5 | Helmet: 23 | Colorbits: 210 | X/Y: 885, 1154
ID: 8614 | Model: 363 | Weapon: 104 | Sheild: 30 | Helmet: 19 | Colorbits: 132 | X/Y: 873, 1128
ID: 9639 | Model: 126 | Weapon: 61 | Sheild: 0 | Helmet: 26 | Colorbits: 483 | X/Y: 866, 1078
ID: 9726 | Model: 361 | Weapon: 445 | Sheild: 0 | Helmet: 32 | Colorbits: 987 | X/Y: 976, 1178
ID: 10911 | Model: 281 | Weapon: 500 | Sheild: 0 | Helmet: 29 | Colorbits: 1816 | X/Y: 945, 1095
ID: 12080 | Model: 126 | Weapon: 103 | Sheild: 16 | Helmet: 22 | Colorbits: 891 | X/Y: 921, 1126
ID: 14079 | Model: 78 | Weapon: 82 | Sheild: 0 | Helmet: 11 | Colorbits: 416 | X/Y: 976, 1153

-----------------------------------------------------------------------
| Units On Screen: 26                                                 |
-----------------------------------------------------------------------
ID: 81 | Model: 128 | Weapon: 103 | Sheild: 16 | Helmet: 11 | Colorbits: 1651 | X/Y: 988, 1115
ID: 7633 | Model: 493 | Weapon: 345 | Sheild: 0 | Helmet: 15 | Colorbits: 798 | X/Y: 1015, 1140
ID: 11123 | Model: 94 | Weapon: 90 | Sheild: 16 | Helmet: 23 | Colorbits: 0 | X/Y: 751, 1005
ID: 827 | Model: 8 | Weapon: 387 | Sheild: 0 | Helmet: 32 | Colorbits: 143 | X/Y: 1006, 1180
ID: 6467 | Model: 387 | Weapon: 413 | Sheild: 21 | Helmet: 12 | Colorbits: 594 | X/Y: 969, 1108
ID: 1341 | Model: 289 | Weapon: 103 | Sheild: 28 | Helmet: 20 | Colorbits: 1453 | X/Y: 898, 1129
ID: 3421 | Model: 450 | Weapon: 82 | Sheild: 0 | Helmet: 12 | Colorbits: 495 | X/Y: 891, 1105
ID: 1368 | Model: 491 | Weapon: 103 | Sheild: 28 | Helmet: 26 | Colorbits: 693 | X/Y: 976, 1054
ID: 7000 | Model: 525 | Weapon: 32 | Sheild: 0 | Helmet: 0 | Colorbits: 66 | X/Y: 1151, 1350
ID: 8088 | Model: 133 | Weapon: 125 | Sheild: 21 | Helmet: 27 | Colorbits: 198 | X/Y: 997, 1150
ID: 5186 | Model: 361 | Weapon: 413 | Sheild: 14 | Helmet: 22 | Colorbits: 594 | X/Y: 929, 1051
ID: 5710 | Model: 132 | Weapon: 345 | Sheild: 16 | Helmet: 19 | Colorbits: 575 | X/Y: 927, 1106
ID: 6498 | Model: 465 | Weapon: 50 | Sheild: 10 | Helmet: 24 | Colorbits: 143 | X/Y: 1119, 1272
ID: 8162 | Model: 114 | Weapon: 468 | Sheild: 0 | Helmet: 28 | Colorbits: 699 | X/Y: 960, 1120
ID: 15266 | Model: 65 | Weapon: 125 | Sheild: 0 | Helmet: 24 | Colorbits: 0 | X/Y: 844, 1153
ID: 6506 | Model: 369 | Weapon: 83 | Sheild: 0 | Helmet: 27 | Colorbits: 1552 | X/Y: 884, 1049
ID: 6859 | Model: 387 | Weapon: 416 | Sheild: 29 | Helmet: 19 | Colorbits: 845 | X/Y: 1027, 1193
ID: 6999 | Model: 101 | Weapon: 48 | Sheild: 8 | Helmet: 6 | Colorbits: 66 | X/Y: 1189, 1171
ID: 7117 | Model: 64 | Weapon: 18 | Sheild: 0 | Helmet: 0 | Colorbits: 0 | X/Y: 1054, 1324
ID: 8153 | Model: 354 | Weapon: 239 | Sheild: 5 | Helmet: 23 | Colorbits: 210 | X/Y: 885, 1154
ID: 8614 | Model: 363 | Weapon: 104 | Sheild: 30 | Helmet: 19 | Colorbits: 132 | X/Y: 873, 1128
ID: 9639 | Model: 126 | Weapon: 61 | Sheild: 0 | Helmet: 26 | Colorbits: 483 | X/Y: 866, 1078
ID: 9726 | Model: 361 | Weapon: 445 | Sheild: 0 | Helmet: 32 | Colorbits: 987 | X/Y: 976, 1178
ID: 10911 | Model: 281 | Weapon: 500 | Sheild: 0 | Helmet: 29 | Colorbits: 1816 | X/Y: 945, 1095
ID: 12080 | Model: 126 | Weapon: 103 | Sheild: 16 | Helmet: 22 | Colorbits: 891 | X/Y: 921, 1126
ID: 14079 | Model: 78 | Weapon: 82 | Sheild: 0 | Helmet: 11 | Colorbits: 416 | X/Y: 976, 1153

-----------------------------------------------------------------------
| Units On Screen: 26                                                 |
-----------------------------------------------------------------------
ID: 81 | Model: 128 | Weapon: 103 | Sheild: 16 | Helmet: 11 | Colorbits: 1651 | X/Y: 988, 1115
ID: 7633 | Model: 493 | Weapon: 345 | Sheild: 0 | Helmet: 15 | Colorbits: 798 | X/Y: 1015, 1140
ID: 11123 | Model: 94 | Weapon: 90 | Sheild: 16 | Helmet: 23 | Colorbits: 0 | X/Y: 751, 1005
ID: 827 | Model: 8 | Weapon: 387 | Sheild: 0 | Helmet: 32 | Colorbits: 143 | X/Y: 1006, 1180
ID: 6467 | Model: 387 | Weapon: 413 | Sheild: 21 | Helmet: 12 | Colorbits: 594 | X/Y: 969, 1108
ID: 1341 | Model: 289 | Weapon: 103 | Sheild: 28 | Helmet: 20 | Colorbits: 1453 | X/Y: 898, 1129
ID: 3421 | Model: 450 | Weapon: 82 | Sheild: 0 | Helmet: 12 | Colorbits: 495 | X/Y: 891, 1105
ID: 1368 | Model: 491 | Weapon: 103 | Sheild: 28 | Helmet: 26 | Colorbits: 693 | X/Y: 978, 1053
ID: 7000 | Model: 525 | Weapon: 32 | Sheild: 0 | Helmet: 0 | Colorbits: 66 | X/Y: 1151, 1350
ID: 8088 | Model: 133 | Weapon: 125 | Sheild: 21 | Helmet: 27 | Colorbits: 198 | X/Y: 997, 1150
ID: 5186 | Model: 361 | Weapon: 413 | Sheild: 14 | Helmet: 22 | Colorbits: 594 | X/Y: 929, 1051
ID: 5710 | Model: 132 | Weapon: 345 | Sheild: 16 | Helmet: 19 | Colorbits: 575 | X/Y: 927, 1106
ID: 6498 | Model: 465 | Weapon: 50 | Sheild: 10 | Helmet: 24 | Colorbits: 143 | X/Y: 1119, 1272
ID: 8162 | Model: 114 | Weapon: 468 | Sheild: 0 | Helmet: 28 | Colorbits: 699 | X/Y: 960, 1120
ID: 15266 | Model: 65 | Weapon: 125 | Sheild: 0 | Helmet: 24 | Colorbits: 0 | X/Y: 844, 1153
ID: 6506 | Model: 369 | Weapon: 83 | Sheild: 0 | Helmet: 27 | Colorbits: 1552 | X/Y: 884, 1049
ID: 6859 | Model: 387 | Weapon: 416 | Sheild: 29 | Helmet: 19 | Colorbits: 845 | X/Y: 1027, 1193
ID: 6999 | Model: 101 | Weapon: 48 | Sheild: 8 | Helmet: 6 | Colorbits: 66 | X/Y: 1189, 1171
ID: 7117 | Model: 64 | Weapon: 18 | Sheild: 0 | Helmet: 0 | Colorbits: 0 | X/Y: 1054, 1324
ID: 8153 | Model: 354 | Weapon: 239 | Sheild: 5 | Helmet: 23 | Colorbits: 210 | X/Y: 885, 1154
ID: 8614 | Model: 363 | Weapon: 104 | Sheild: 30 | Helmet: 19 | Colorbits: 132 | X/Y: 873, 1128
ID: 9639 | Model: 126 | Weapon: 61 | Sheild: 0 | Helmet: 26 | Colorbits: 483 | X/Y: 866, 1078
ID: 9726 | Model: 361 | Weapon: 445 | Sheild: 0 | Helmet: 32 | Colorbits: 987 | X/Y: 976, 1178
ID: 10911 | Model: 281 | Weapon: 500 | Sheild: 0 | Helmet: 29 | Colorbits: 1816 | X/Y: 945, 1095
ID: 12080 | Model: 126 | Weapon: 103 | Sheild: 16 | Helmet: 22 | Colorbits: 891 | X/Y: 921, 1126
ID: 14079 | Model: 78 | Weapon: 82 | Sheild: 0 | Helmet: 11 | Colorbits: 416 | X/Y: 976, 1153

-----------------------------------------------------------------------
| Units On Screen: 26                                                 |
-----------------------------------------------------------------------
ID: 81 | Model: 128 | Weapon: 103 | Sheild: 16 | Helmet: 11 | Colorbits: 1651 | X/Y: 988, 1115
ID: 7633 | Model: 493 | Weapon: 345 | Sheild: 0 | Helmet: 15 | Colorbits: 798 | X/Y: 1015, 1140
ID: 307 | Model: 19 | Weapon: 0 | Sheild: 0 | Helmet: 0 | Colorbits: 87 | X/Y: 714, 1036
ID: 11123 | Model: 94 | Weapon: 90 | Sheild: 16 | Helmet: 23 | Colorbits: 0 | X/Y: 751, 1005
ID: 827 | Model: 8 | Weapon: 387 | Sheild: 0 | Helmet: 32 | Colorbits: 143 | X/Y: 1006, 1180
ID: 6467 | Model: 387 | Weapon: 413 | Sheild: 21 | Helmet: 12 | Colorbits: 594 | X/Y: 969, 1108
ID: 1341 | Model: 289 | Weapon: 103 | Sheild: 28 | Helmet: 20 | Colorbits: 1453 | X/Y: 898, 1129
ID: 3421 | Model: 450 | Weapon: 82 | Sheild: 0 | Helmet: 12 | Colorbits: 495 | X/Y: 891, 1105
ID: 1368 | Model: 491 | Weapon: 103 | Sheild: 28 | Helmet: 26 | Colorbits: 693 | X/Y: 978, 1053
ID: 7000 | Model: 525 | Weapon: 32 | Sheild: 0 | Helmet: 0 | Colorbits: 66 | X/Y: 1151, 1350
ID: 8088 | Model: 133 | Weapon: 125 | Sheild: 21 | Helmet: 27 | Colorbits: 198 | X/Y: 997, 1150
ID: 5186 | Model: 361 | Weapon: 413 | Sheild: 14 | Helmet: 22 | Colorbits: 594 | X/Y: 846, 939
ID: 5710 | Model: 132 | Weapon: 345 | Sheild: 16 | Helmet: 19 | Colorbits: 575 | X/Y: 927, 1106
ID: 6498 | Model: 465 | Weapon: 50 | Sheild: 10 | Helmet: 24 | Colorbits: 143 | X/Y: 1119, 1272
ID: 8162 | Model: 114 | Weapon: 468 | Sheild: 0 | Helmet: 28 | Colorbits: 699 | X/Y: 960, 1120
ID: 15266 | Model: 65 | Weapon: 125 | Sheild: 0 | Helmet: 24 | Colorbits: 0 | X/Y: 844, 1153
ID: 6506 | Model: 369 | Weapon: 83 | Sheild: 0 | Helmet: 27 | Colorbits: 1552 | X/Y: 884, 1049
ID: 6859 | Model: 387 | Weapon: 416 | Sheild: 29 | Helmet: 19 | Colorbits: 845 | X/Y: 1027, 1193
ID: 7117 | Model: 64 | Weapon: 18 | Sheild: 0 | Helmet: 0 | Colorbits: 0 | X/Y: 1054, 1324
ID: 8153 | Model: 354 | Weapon: 239 | Sheild: 5 | Helmet: 23 | Colorbits: 210 | X/Y: 885, 1154
ID: 8614 | Model: 363 | Weapon: 104 | Sheild: 30 | Helmet: 19 | Colorbits: 132 | X/Y: 791, 1014
ID: 9639 | Model: 126 | Weapon: 61 | Sheild: 0 | Helmet: 26 | Colorbits: 483 | X/Y: 866, 1078
ID: 9726 | Model: 361 | Weapon: 445 | Sheild: 0 | Helmet: 32 | Colorbits: 987 | X/Y: 976, 1178
ID: 10911 | Model: 281 | Weapon: 500 | Sheild: 0 | Helmet: 29 | Colorbits: 1816 | X/Y: 945, 1095
ID: 12080 | Model: 126 | Weapon: 103 | Sheild: 16 | Helmet: 22 | Colorbits: 891 | X/Y: 921, 1126
ID: 14079 | Model: 78 | Weapon: 82 | Sheild: 0 | Helmet: 11 | Colorbits: 416 | X/Y: 976, 1153

-----------------------------------------------------------------------
| Units On Screen: 26                                                 |
-----------------------------------------------------------------------
ID: 81 | Model: 128 | Weapon: 103 | Sheild: 16 | Helmet: 11 | Colorbits: 1651 | X/Y: 988, 1115
ID: 7633 | Model: 493 | Weapon: 345 | Sheild: 0 | Helmet: 15 | Colorbits: 798 | X/Y: 1015, 1140
ID: 307 | Model: 19 | Weapon: 0 | Sheild: 0 | Helmet: 0 | Colorbits: 87 | X/Y: 708, 1029
ID: 11123 | Model: 94 | Weapon: 90 | Sheild: 16 | Helmet: 23 | Colorbits: 0 | X/Y: 751, 1005
ID: 827 | Model: 8 | Weapon: 387 | Sheild: 0 | Helmet: 32 | Colorbits: 143 | X/Y: 1006, 1180
ID: 6467 | Model: 387 | Weapon: 413 | Sheild: 21 | Helmet: 12 | Colorbits: 594 | X/Y: 969, 1108
ID: 1341 | Model: 289 | Weapon: 103 | Sheild: 28 | Helmet: 20 | Colorbits: 1453 | X/Y: 898, 1129
ID: 3421 | Model: 450 | Weapon: 82 | Sheild: 0 | Helmet: 12 | Colorbits: 495 | X/Y: 891, 1105
ID: 1368 | Model: 491 | Weapon: 103 | Sheild: 28 | Helmet: 26 | Colorbits: 693 | X/Y: 978, 1053
ID: 7000 | Model: 525 | Weapon: 32 | Sheild: 0 | Helmet: 0 | Colorbits: 66 | X/Y: 1151, 1350
ID: 8088 | Model: 133 | Weapon: 125 | Sheild: 21 | Helmet: 27 | Colorbits: 198 | X/Y: 997, 1150
ID: 5186 | Model: 361 | Weapon: 413 | Sheild: 14 | Helmet: 22 | Colorbits: 594 | X/Y: 846, 939
ID: 5710 | Model: 132 | Weapon: 345 | Sheild: 16 | Helmet: 19 | Colorbits: 575 | X/Y: 927, 1106
ID: 6498 | Model: 465 | Weapon: 50 | Sheild: 10 | Helmet: 24 | Colorbits: 143 | X/Y: 1119, 1272
ID: 8162 | Model: 114 | Weapon: 468 | Sheild: 0 | Helmet: 28 | Colorbits: 699 | X/Y: 960, 1120
ID: 15266 | Model: 65 | Weapon: 125 | Sheild: 0 | Helmet: 24 | Colorbits: 0 | X/Y: 844, 1153
ID: 6506 | Model: 369 | Weapon: 83 | Sheild: 0 | Helmet: 27 | Colorbits: 1552 | X/Y: 884, 1049
ID: 6859 | Model: 387 | Weapon: 416 | Sheild: 29 | Helmet: 19 | Colorbits: 845 | X/Y: 1027, 1193
ID: 7117 | Model: 64 | Weapon: 18 | Sheild: 0 | Helmet: 0 | Colorbits: 0 | X/Y: 1054, 1324
ID: 8153 | Model: 354 | Weapon: 239 | Sheild: 5 | Helmet: 23 | Colorbits: 210 | X/Y: 885, 1154
ID: 8614 | Model: 363 | Weapon: 104 | Sheild: 30 | Helmet: 19 | Colorbits: 132 | X/Y: 786, 1007
ID: 9639 | Model: 126 | Weapon: 61 | Sheild: 0 | Helmet: 26 | Colorbits: 483 | X/Y: 866, 1078
ID: 9726 | Model: 361 | Weapon: 445 | Sheild: 0 | Helmet: 32 | Colorbits: 987 | X/Y: 976, 1178
ID: 10911 | Model: 281 | Weapon: 500 | Sheild: 0 | Helmet: 29 | Colorbits: 1816 | X/Y: 945, 1095
ID: 12080 | Model: 126 | Weapon: 103 | Sheild: 16 | Helmet: 22 | Colorbits: 891 | X/Y: 921, 1126
ID: 14079 | Model: 78 | Weapon: 82 | Sheild: 0 | Helmet: 11 | Colorbits: 416 | X/Y: 976, 1153

-----------------------------------------------------------------------
| Units On Screen: 25                                                 |
-----------------------------------------------------------------------
ID: 81 | Model: 128 | Weapon: 103 | Sheild: 16 | Helmet: 11 | Colorbits: 1651 | X/Y: 988, 1115
ID: 7633 | Model: 493 | Weapon: 345 | Sheild: 0 | Helmet: 15 | Colorbits: 798 | X/Y: 1015, 1140
ID: 307 | Model: 19 | Weapon: 0 | Sheild: 0 | Helmet: 0 | Colorbits: 87 | X/Y: 702, 1023
ID: 11123 | Model: 94 | Weapon: 90 | Sheild: 16 | Helmet: 23 | Colorbits: 0 | X/Y: 751, 1005
ID: 827 | Model: 8 | Weapon: 387 | Sheild: 0 | Helmet: 32 | Colorbits: 143 | X/Y: 1006, 1180
ID: 6467 | Model: 387 | Weapon: 413 | Sheild: 21 | Helmet: 12 | Colorbits: 594 | X/Y: 969, 1108
ID: 1341 | Model: 289 | Weapon: 103 | Sheild: 28 | Helmet: 20 | Colorbits: 1453 | X/Y: 898, 1129
ID: 3421 | Model: 450 | Weapon: 82 | Sheild: 0 | Helmet: 12 | Colorbits: 495 | X/Y: 891, 1105
ID: 1368 | Model: 491 | Weapon: 103 | Sheild: 28 | Helmet: 26 | Colorbits: 693 | X/Y: 978, 1053
ID: 7000 | Model: 525 | Weapon: 32 | Sheild: 0 | Helmet: 0 | Colorbits: 66 | X/Y: 1151, 1354
ID: 8088 | Model: 133 | Weapon: 125 | Sheild: 21 | Helmet: 27 | Colorbits: 198 | X/Y: 997, 1150
ID: 5710 | Model: 132 | Weapon: 345 | Sheild: 16 | Helmet: 19 | Colorbits: 575 | X/Y: 927, 1106
ID: 6498 | Model: 465 | Weapon: 50 | Sheild: 10 | Helmet: 24 | Colorbits: 143 | X/Y: 1119, 1272
ID: 8162 | Model: 114 | Weapon: 468 | Sheild: 0 | Helmet: 28 | Colorbits: 699 | X/Y: 960, 1120
ID: 15266 | Model: 65 | Weapon: 125 | Sheild: 0 | Helmet: 24 | Colorbits: 0 | X/Y: 844, 1153
ID: 6506 | Model: 369 | Weapon: 83 | Sheild: 0 | Helmet: 27 | Colorbits: 1552 | X/Y: 884, 1049
ID: 6859 | Model: 387 | Weapon: 416 | Sheild: 29 | Helmet: 19 | Colorbits: 845 | X/Y: 1027, 1193
ID: 7117 | Model: 64 | Weapon: 18 | Sheild: 0 | Helmet: 0 | Colorbits: 0 | X/Y: 1054, 1324
ID: 8153 | Model: 354 | Weapon: 239 | Sheild: 5 | Helmet: 23 | Colorbits: 210 | X/Y: 885, 1154
ID: 8614 | Model: 363 | Weapon: 104 | Sheild: 30 | Helmet: 19 | Colorbits: 132 | X/Y: 781, 999
ID: 9639 | Model: 126 | Weapon: 61 | Sheild: 0 | Helmet: 26 | Colorbits: 483 | X/Y: 866, 1078
ID: 9726 | Model: 361 | Weapon: 445 | Sheild: 0 | Helmet: 32 | Colorbits: 987 | X/Y: 976, 1178
ID: 10911 | Model: 281 | Weapon: 500 | Sheild: 0 | Helmet: 29 | Colorbits: 1816 | X/Y: 945, 1095
ID: 12080 | Model: 126 | Weapon: 103 | Sheild: 16 | Helmet: 22 | Colorbits: 891 | X/Y: 921, 1126
ID: 14079 | Model: 78 | Weapon: 82 | Sheild: 0 | Helmet: 11 | Colorbits: 416 | X/Y: 976, 1153

-----------------------------------------------------------------------
| Units On Screen: 24                                                 |
-----------------------------------------------------------------------
ID: 81 | Model: 128 | Weapon: 103 | Sheild: 16 | Helmet: 11 | Colorbits: 1651 | X/Y: 988, 1115
ID: 7633 | Model: 493 | Weapon: 345 | Sheild: 0 | Helmet: 15 | Colorbits: 798 | X/Y: 1015, 1140
ID: 11123 | Model: 94 | Weapon: 90 | Sheild: 16 | Helmet: 23 | Colorbits: 0 | X/Y: 751, 1005
ID: 827 | Model: 8 | Weapon: 387 | Sheild: 0 | Helmet: 32 | Colorbits: 143 | X/Y: 1006, 1180
ID: 6467 | Model: 387 | Weapon: 413 | Sheild: 21 | Helmet: 12 | Colorbits: 594 | X/Y: 969, 1108
ID: 1341 | Model: 289 | Weapon: 103 | Sheild: 28 | Helmet: 20 | Colorbits: 1453 | X/Y: 898, 1129
ID: 3421 | Model: 450 | Weapon: 82 | Sheild: 0 | Helmet: 12 | Colorbits: 495 | X/Y: 891, 1105
ID: 1368 | Model: 491 | Weapon: 103 | Sheild: 28 | Helmet: 26 | Colorbits: 693 | X/Y: 978, 1053
ID: 7000 | Model: 525 | Weapon: 32 | Sheild: 0 | Helmet: 0 | Colorbits: 66 | X/Y: 1150, 1364
ID: 8088 | Model: 133 | Weapon: 125 | Sheild: 21 | Helmet: 27 | Colorbits: 198 | X/Y: 997, 1150
ID: 5710 | Model: 132 | Weapon: 345 | Sheild: 16 | Helmet: 19 | Colorbits: 575 | X/Y: 927, 1106
ID: 6498 | Model: 465 | Weapon: 50 | Sheild: 10 | Helmet: 24 | Colorbits: 143 | X/Y: 1119, 1272
ID: 8162 | Model: 114 | Weapon: 468 | Sheild: 0 | Helmet: 28 | Colorbits: 699 | X/Y: 960, 1120
ID: 15266 | Model: 65 | Weapon: 125 | Sheild: 0 | Helmet: 24 | Colorbits: 0 | X/Y: 844, 1153
ID: 6506 | Model: 369 | Weapon: 83 | Sheild: 0 | Helmet: 27 | Colorbits: 1552 | X/Y: 884, 1049
ID: 6859 | Model: 387 | Weapon: 416 | Sheild: 29 | Helmet: 19 | Colorbits: 845 | X/Y: 1027, 1193
ID: 7117 | Model: 64 | Weapon: 18 | Sheild: 0 | Helmet: 0 | Colorbits: 0 | X/Y: 1054, 1324
ID: 8153 | Model: 354 | Weapon: 239 | Sheild: 5 | Helmet: 23 | Colorbits: 210 | X/Y: 885, 1154
ID: 8614 | Model: 363 | Weapon: 104 | Sheild: 30 | Helmet: 19 | Colorbits: 132 | X/Y: 767, 960
ID: 9639 | Model: 126 | Weapon: 61 | Sheild: 0 | Helmet: 26 | Colorbits: 483 | X/Y: 866, 1078
ID: 9726 | Model: 361 | Weapon: 445 | Sheild: 0 | Helmet: 32 | Colorbits: 987 | X/Y: 976, 1178
ID: 10911 | Model: 281 | Weapon: 500 | Sheild: 0 | Helmet: 29 | Colorbits: 1816 | X/Y: 945, 1095
ID: 12080 | Model: 126 | Weapon: 103 | Sheild: 16 | Helmet: 22 | Colorbits: 891 | X/Y: 921, 1126
ID: 14079 | Model: 78 | Weapon: 82 | Sheild: 0 | Helmet: 11 | Colorbits: 416 | X/Y: 976, 1153

-----------------------------------------------------------------------
| Units On Screen: 24                                                 |
-----------------------------------------------------------------------
ID: 81 | Model: 128 | Weapon: 103 | Sheild: 16 | Helmet: 11 | Colorbits: 1651 | X/Y: 988, 1115
ID: 7633 | Model: 493 | Weapon: 345 | Sheild: 0 | Helmet: 15 | Colorbits: 798 | X/Y: 1015, 1140
ID: 11123 | Model: 94 | Weapon: 90 | Sheild: 16 | Helmet: 23 | Colorbits: 0 | X/Y: 751, 1005
ID: 827 | Model: 8 | Weapon: 387 | Sheild: 0 | Helmet: 32 | Colorbits: 143 | X/Y: 1006, 1180
ID: 6467 | Model: 387 | Weapon: 413 | Sheild: 21 | Helmet: 12 | Colorbits: 594 | X/Y: 969, 1108
ID: 1341 | Model: 289 | Weapon: 103 | Sheild: 28 | Helmet: 20 | Colorbits: 1453 | X/Y: 898, 1129
ID: 3421 | Model: 450 | Weapon: 82 | Sheild: 0 | Helmet: 12 | Colorbits: 495 | X/Y: 891, 1105
ID: 1368 | Model: 491 | Weapon: 103 | Sheild: 28 | Helmet: 26 | Colorbits: 693 | X/Y: 978, 1053
ID: 7000 | Model: 525 | Weapon: 32 | Sheild: 0 | Helmet: 0 | Colorbits: 66 | X/Y: 1150, 1368
ID: 8088 | Model: 133 | Weapon: 125 | Sheild: 21 | Helmet: 27 | Colorbits: 198 | X/Y: 997, 1150
ID: 5710 | Model: 132 | Weapon: 345 | Sheild: 16 | Helmet: 19 | Colorbits: 575 | X/Y: 927, 1106
ID: 6498 | Model: 465 | Weapon: 50 | Sheild: 10 | Helmet: 24 | Colorbits: 143 | X/Y: 1119, 1272
ID: 8162 | Model: 114 | Weapon: 468 | Sheild: 0 | Helmet: 28 | Colorbits: 699 | X/Y: 960, 1120
ID: 15266 | Model: 65 | Weapon: 125 | Sheild: 0 | Helmet: 24 | Colorbits: 0 | X/Y: 844, 1153
ID: 6506 | Model: 369 | Weapon: 83 | Sheild: 0 | Helmet: 27 | Colorbits: 1552 | X/Y: 884, 1049
ID: 6859 | Model: 387 | Weapon: 416 | Sheild: 29 | Helmet: 19 | Colorbits: 845 | X/Y: 1027, 1193
ID: 7117 | Model: 64 | Weapon: 18 | Sheild: 0 | Helmet: 0 | Colorbits: 0 | X/Y: 1054, 1324
ID: 8153 | Model: 354 | Weapon: 239 | Sheild: 5 | Helmet: 23 | Colorbits: 210 | X/Y: 885, 1154
ID: 8614 | Model: 363 | Weapon: 104 | Sheild: 30 | Helmet: 19 | Colorbits: 132 | X/Y: 751, 908
ID: 9639 | Model: 126 | Weapon: 61 | Sheild: 0 | Helmet: 26 | Colorbits: 483 | X/Y: 866, 1078
ID: 9726 | Model: 361 | Weapon: 445 | Sheild: 0 | Helmet: 32 | Colorbits: 987 | X/Y: 976, 1178
ID: 10911 | Model: 281 | Weapon: 500 | Sheild: 0 | Helmet: 29 | Colorbits: 1816 | X/Y: 945, 1095
ID: 12080 | Model: 126 | Weapon: 103 | Sheild: 16 | Helmet: 22 | Colorbits: 891 | X/Y: 921, 1126
ID: 14079 | Model: 78 | Weapon: 82 | Sheild: 0 | Helmet: 11 | Colorbits: 416 | X/Y: 976, 1153

-----------------------------------------------------------------------
| Units On Screen: 24                                                 |
-----------------------------------------------------------------------
ID: 81 | Model: 128 | Weapon: 103 | Sheild: 16 | Helmet: 11 | Colorbits: 1651 | X/Y: 988, 1115
ID: 7633 | Model: 493 | Weapon: 345 | Sheild: 0 | Helmet: 15 | Colorbits: 798 | X/Y: 1015, 1140
ID: 11123 | Model: 94 | Weapon: 90 | Sheild: 16 | Helmet: 23 | Colorbits: 0 | X/Y: 751, 1005
ID: 827 | Model: 8 | Weapon: 387 | Sheild: 0 | Helmet: 32 | Colorbits: 143 | X/Y: 1006, 1180
ID: 6467 | Model: 387 | Weapon: 413 | Sheild: 21 | Helmet: 12 | Colorbits: 594 | X/Y: 969, 1108
ID: 1341 | Model: 289 | Weapon: 103 | Sheild: 28 | Helmet: 20 | Colorbits: 1453 | X/Y: 898, 1129
ID: 3421 | Model: 450 | Weapon: 82 | Sheild: 0 | Helmet: 12 | Colorbits: 495 | X/Y: 891, 1105
ID: 1368 | Model: 491 | Weapon: 103 | Sheild: 28 | Helmet: 26 | Colorbits: 693 | X/Y: 977, 1053
ID: 7000 | Model: 525 | Weapon: 32 | Sheild: 0 | Helmet: 0 | Colorbits: 66 | X/Y: 1150, 1368
ID: 8088 | Model: 133 | Weapon: 125 | Sheild: 21 | Helmet: 27 | Colorbits: 198 | X/Y: 997, 1150
ID: 5710 | Model: 132 | Weapon: 345 | Sheild: 16 | Helmet: 19 | Colorbits: 575 | X/Y: 927, 1106
ID: 6498 | Model: 465 | Weapon: 50 | Sheild: 10 | Helmet: 24 | Colorbits: 143 | X/Y: 1119, 1272
ID: 8162 | Model: 114 | Weapon: 468 | Sheild: 0 | Helmet: 28 | Colorbits: 699 | X/Y: 960, 1120
ID: 15266 | Model: 65 | Weapon: 125 | Sheild: 0 | Helmet: 24 | Colorbits: 0 | X/Y: 844, 1153
ID: 6506 | Model: 369 | Weapon: 83 | Sheild: 0 | Helmet: 27 | Colorbits: 1552 | X/Y: 884, 1049
ID: 6859 | Model: 387 | Weapon: 416 | Sheild: 29 | Helmet: 19 | Colorbits: 845 | X/Y: 1027, 1193
ID: 7117 | Model: 64 | Weapon: 18 | Sheild: 0 | Helmet: 0 | Colorbits: 0 | X/Y: 1054, 1324
ID: 8153 | Model: 354 | Weapon: 239 | Sheild: 5 | Helmet: 23 | Colorbits: 210 | X/Y: 885, 1154
ID: 8614 | Model: 363 | Weapon: 104 | Sheild: 30 | Helmet: 19 | Colorbits: 132 | X/Y: 751, 908
ID: 9639 | Model: 126 | Weapon: 61 | Sheild: 0 | Helmet: 26 | Colorbits: 483 | X/Y: 866, 1078
ID: 9726 | Model: 361 | Weapon: 445 | Sheild: 0 | Helmet: 32 | Colorbits: 987 | X/Y: 976, 1178
ID: 10911 | Model: 281 | Weapon: 500 | Sheild: 0 | Helmet: 29 | Colorbits: 1816 | X/Y: 945, 1095
ID: 12080 | Model: 126 | Weapon: 103 | Sheild: 16 | Helmet: 22 | Colorbits: 891 | X/Y: 921, 1126
ID: 14079 | Model: 78 | Weapon: 82 | Sheild: 0 | Helmet: 11 | Colorbits: 416 | X/Y: 976, 1153


Top
 Profile  
 
PostPosted: 28 Aug 2013 01:41 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
I Feel obligated to post more code, so here is a simple Packet Structure.

Code:
#ifndef __PACKET_H__
#define __PACKET_H__

#include <Windows.h>
#include <stdio.h>

typedef unsigned char   uint8;
typedef unsigned short   uint16;
typedef unsigned int   uint32;

class Packet{
private:
   uint8 op;
   uint8* data;
   uint16 len;
   uint16 index;
public:
   Packet(uint8 opcode, uint16 length);

   Packet operator<<(uint8 byte);
   Packet operator<<(uint16 bytes);
   Packet operator<<(uint32 bytes);

   uint8 operator[](int i);

   operator uint8();
   operator uint8*();
   operator int();
};


#endif

Code:
#include "Packet.h"

Packet::Packet(uint8 opcode, uint16 length)
{
   index = 0;
   op = opcode;
   len = length;
   data = new uint8[len];
   memset(data, 0x00, len);
}

Packet Packet::operator<<(uint8 byte)
{
   data[index] = byte;
   index++;
   return *this;
}
Packet Packet::operator<<(uint16 bytes)
{
   data[index] = (uint8)bytes;
   index++;
   data[index] = (uint8)(bytes >> 8);
   index++;
   return *this;
}
Packet Packet::operator<<(uint32 bytes)
{
   data[index] = (uint8)bytes;
   index++;
   data[index] = (uint8)(bytes >> 8);
   index++;
   data[index] = (uint8)(bytes >> 16);
   index++;
   data[index] = (uint8)(bytes >> 24);
   index++;
   return *this;
}
uint8 Packet::operator[](int i)
{
   return data[i];
}

Packet::operator uint8()
{
   return op;
}
Packet::operator uint8*()
{
   return data;
}
Packet::operator int()
{
   return len;
}



Simple example
Code:
void Player::CastSpell(uint16 type, uint16 id, uint16 x, uint16 y)
{
   Packet spell(0x08, 12);
   spell << p_id;
   spell << (uint16)0;
   spell << type;
   spell << id;
   spell << x;
   spell << y;

   //Send Packet
   oSendPacket(spell, spell, spell);

   free((uint8*)spell);
}



Yup. Could probably do things better, but its a learning experience.


Top
 Profile  
 
PostPosted: 29 Aug 2013 02:17 
Offline
User avatar

Joined: 03 Sep 2006 16:54
Posts: 8
Do you use GitHub?

----

I recently put my old projects up:
https://github.com/MartinMReed/XenDLL
https://github.com/MartinMReed/xenimus-calc-cplusplus
https://github.com/MartinMReed/xenimus-calc-jplusplus


Top
 Profile  
 
PostPosted: 29 Aug 2013 14:21 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
I have for a few small projects when i was applying for a job. But no not really. I probably should, as it would of prevented me from losing my source for xenScan. Ill probably get around to uploading some stuff. Thanks for posting your XenDLL, i personally LOVE the idea behind it and everything.


Top
 Profile  
 
PostPosted: 30 Aug 2013 17:12 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
I think ill get around to posting this stuff up on GitHub soon, that way people can see everything put together. But heres a simple Player class that i made for a druid. I am still getting crash bugs, but not sure why, so i used mutex's for a few variables that i write/read from alot. Anyways, heres the code (if you havent caught on by not, this code is the basics for a bot...)


Code:
#ifndef __PLAYER_H__
#define __PLAYER_H__

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <hash_map>
using namespace std;


typedef unsigned char   uint8;
typedef unsigned short   uint16;
typedef unsigned int   uint32;
typedef signed char      int8;
typedef signed short   int16;
typedef signed int      int32;

typedef int (__cdecl *tSendPacket)(uint8 opcode, uint8* packet, int len);

enum SpellTypes{
   SELF = 0x004E,
   CAST = 0x0050,
   ATK  = 0x004C
};

enum MoveTypes{
   MOVE   = 0x4D,
   ATTACK   = 0x41
};
enum QuestOptions{
   THANKS      = 0x01,
   OK         = 0x02,
   GUARDIANS   = 0x04,
};

struct UpdatePacketSelf
{
   uint16 positionX; //0
   uint16 positionY; //2
   uint16 spellflags; //4
   uint16 colorbits; //6
   uint16 numInRangeDynamicObjects; //8
   uint8 numInRangeUnits; //10
   uint8 unklol; //11
   uint8 flags; //12 if & 1, expect self say text at end, if & 2, spellflags contain cooldown data, if & 4 you're in pvp mode
   uint8 rotation; //13
   uint8 animation; //14
   uint8 spellEffect; //15
   uint8 numInRangeSpellEffects; //16
   uint8 unklol2; //17
   uint8 unklol3; //18
   uint8 currentHPPct; //19
   uint8 currentMPPct; //20 for hp mp and exp, 0 = 0%, 255 = 100%
   uint8 currentExpPct; //21
};
struct InitialLoginData
{
   int32 positionX; //0
   int32 positionY; //4
   uint32 mapId; //8
   uint16 serverId; //12
   uint16 unk; //14 high bits of serverid, seems to be 32bit, unused
   uint16 unk2; //16 seems to be initial login (show tutorial if 1)
   uint16 unk3; //18
   uint16 serverId2; //20 if this != previous id, do not login, don't know why this is here, maybe an old hack by that hollow guy
   uint16 unk4; //22 high bits of serverid, unused
   float time_current; //24 time as of login
   float time_roc; //28 rate of change (every 50 milliseconds passing, rate value changes)
   uint8 unk7; //32
};
struct InitialQuestData
{
   uint8 strings;
   uint8 choices;
};
struct QuestText
{
   uint8 text[44];
};
struct QuestLog{
   uint32 unk;
   uint32 unk2;
   uint16 unk3;
   uint32 unk4;
   uint32 unk5;
   uint16 unk6;
   uint16 reqkills;
   uint16 curkills;
   uint32 curquest;
};
struct _POINT{
   uint16 x;
   uint16 y;
};

class Player{
private:
   uint16 p_id;
   UpdatePacketSelf p_update;
   QuestLog p_log;
   tSendPacket oSendPacket;
   uint32 QuestFlags;
   HANDLE ghMutex, ghMutexLog;
public:
   Player(){ srand(time(0)); QuestFlags = 0; ghMutex = CreateMutex(NULL, FALSE, NULL); ghMutexLog = CreateMutex(NULL, FALSE, NULL); }
   ~Player(){ CloseHandle(ghMutex); CloseHandle(ghMutexLog); }
   void Initialize(DWORD addr);
   void LoginData(InitialLoginData ild);
   void Update(UpdatePacketSelf upt);
   void ParseQuestText(uint8* packet);
   void ParseQuestLog(QuestLog ulog);
   UpdatePacketSelf GetUpdateInfo();
   QuestLog GetQuestLog();

   //Buffs
   void Turi(uint8 level);
   void Extrudere(uint8 level);
   void Velocitas(uint8 level);
   void Robur(uint8 level);

   //Helping/Aid
   void Mederi(uint8 level);
   void NocteVisus();
   void ContraVisus();

   //Damage
   void GlacialisViscera(uint8 level, uint16 x, uint16 y);
   void Fulgur(uint8 level, uint16 x, uint16 y);
   void GlacialisVentus(uint8 level, uint16 x, uint16 y);
   void FragorIpsum(uint8 level);
   void Freeze(uint8 level, uint16 x, uint16 y);
   void Sidus(uint8 level, uint16 x, uint16 y);

   //Others
   void MutatioNimbus();
   void PergereTrans(uint16 x, uint16 y);
   void PraesentisTrans(uint8 mark);
   void Star();

   //Base Function
   void CastSpell(uint16 type, uint16 id, uint16 x, uint16 y);

   //Misc Actions
   void StopAction();
   void SwitchWeapons();
   void Walk(uint16 x, uint16 y);
   void Attack(uint16 who, uint16 y);
   void WalkTo(uint16 x, uint16 y);
   void Say(char *chat, int len);


   //Misc Functions
   uint16 genMoveChecksum(uint16 id, uint16 x, uint16 y, uint8 type);
   BOOL CheckRadius(int px, int py, int mx, int my, int r);

   //Macro Stuff
   void RequestQuestLog();
   void TransAndMultiPath(_POINT* path, int size);
};



Code:
#include "Player.h"
#include "Packet.h"
#include "UnitMap.h"

void Player::Initialize(DWORD addr)
{
   oSendPacket = (tSendPacket)addr;
}
void Player::LoginData(InitialLoginData ild)
{
   p_id = ild.serverId;
}
void Player::Update(UpdatePacketSelf upt)
{
   DWORD dwWaitResult;
   
   dwWaitResult = WaitForSingleObject(ghMutex, INFINITE);
   switch (dwWaitResult)
   {
   case WAIT_OBJECT_0:
      __try {
         p_update = upt;
      }
      __finally {
         if(!ReleaseMutex(ghMutex))
         {
            printf("Failed to release mutex: %d\n", GetLastError());
         }
      }
      break;
   case WAIT_ABANDONED:
      break;
   }
}
void Player::ParseQuestText(uint8* packet)
{
   InitialQuestData iqd = *(InitialQuestData*)&packet[2];
   QuestText *qt = new QuestText[iqd.strings];
   qt = (QuestText*)&packet[4];

   for(int i = 0; i < iqd.strings; i++)
   {
      if(strcmp((char*)qt[i].text, "~OK") == 0)
         QuestFlags |= OK;
      else if(strcmp((char*)qt[i].text, "~Thanks") == 0)
         QuestFlags |= THANKS;
      else if(strcmp((char*)qt[i].text, "~Guardian task") == 0)
         QuestFlags |= GUARDIANS;
   }

   delete[] qt;
}
void Player::ParseQuestLog(QuestLog ulog)
{
   DWORD dwWaitResult;
   
   dwWaitResult = WaitForSingleObject(ghMutexLog, INFINITE);
   switch (dwWaitResult)
   {
   case WAIT_OBJECT_0:
      __try {
         p_log = ulog;
      }
      __finally {
         if(!ReleaseMutex(ghMutexLog))
         {
            printf("Failed to release mutex: %d\n", GetLastError());
         }
      }
      break;
   case WAIT_ABANDONED:
      break;
   }
}
UpdatePacketSelf Player::GetUpdateInfo()
{
   UpdatePacketSelf ret;
   DWORD dwWaitResult;    
   dwWaitResult = WaitForSingleObject(ghMutex, INFINITE);
   switch (dwWaitResult)
   {
   case WAIT_OBJECT_0:
      __try {
         ret = p_update;
      }
      __finally {
         if(!ReleaseMutex(ghMutex))
         {
            printf("Failed to release mutex: %d\n", GetLastError());
         }
      }
      break;
   case WAIT_ABANDONED:
      break;
   }

   return ret;
}

QuestLog Player::GetQuestLog()
{
   QuestLog ret;
   DWORD dwWaitResult;
   
   dwWaitResult = WaitForSingleObject(ghMutexLog, INFINITE);
   switch (dwWaitResult)
   {
   case WAIT_OBJECT_0:
      __try {
         ret = p_log;
      }
      __finally {
         if(!ReleaseMutex(ghMutexLog))
         {
            printf("Failed to release mutex: %d\n", GetLastError());
         }
      }
      break;
   case WAIT_ABANDONED:
      break;
   }
   return ret;
}


//Buff
void Player::Turi(uint8 level)
{
   //0xD2 0x2C 0x00 0x00 0x4E 0x00 0x35 0x00 0xD2 0x2C 0x00 0x00
   CastSpell(SELF, (0x0034 + level), p_id, 0);
}
void Player::Extrudere(uint8 level)
{
   //0xD2 0x2C 0x00 0x00 0x4E 0x00 0x40 0x00 0xD2 0x2C 0x00 0x00
   CastSpell(SELF, (0x003F + level), p_id, 0);
}
void Player::Velocitas(uint8 level)
{
   //0xD2 0x2C 0x00 0x00 0x50 0x00 0x59 0x00 0xD2 0x2C 0x16 0x1F
   CastSpell(CAST, (0x0058 + level), p_id, p_update.positionY);
}
void Player::Robur(uint8 level)
{
   //0xD2 0x2C 0x00 0x00 0x50 0x00 0x81 0x00 0xD2 0x2C 0x16 0x1F
   CastSpell(CAST, (0x0080 + level), p_id, p_update.positionY);
}

//Helping/Aid
void Player::Mederi(uint8 level)
{
   //0xD2 0x2C 0x00 0x00 0x50 0x00 0x01 0x00 0xD2 0x2C 0x15 0x1F
   CastSpell(CAST, (0x0000 + level), p_id, p_update.positionY);
}
void Player::NocteVisus()
{
   //0xD2 0x2C 0x00 0x00 0x4E 0x00 0x29 0x00 0xD2 0x2C 0x19 0x1F
   CastSpell(SELF, 0x0029, p_id, 0);
}
void Player::ContraVisus()
{
   //0xD2 0x2C 0x00 0x00 0x50 0x00 0xA6 0x00 0xD2 0x2C 0x11 0x1F
   CastSpell(SELF, 0x00A6, p_id, 0);
}

//Damage
void Player::GlacialisViscera(uint8 level, uint16 x, uint16 y)
{
   //0xD2 0x2C 0x00 0x00 0x4C 0x00 0x8C 0x00 0xB7 0x04 0x4E 0x1F
   CastSpell(ATK, (0x008B + level), x, y);
}
void Player::Fulgur(uint8 level, uint16 x, uint16 y)
{
   //0xD2 0x2C 0x00 0x00 0x4C 0x00 0xA7 0x00 0xAD 0x04 0x58 0x1F
   CastSpell(ATK, (0x00A6 + level), x, y);
}
void Player::GlacialisVentus(uint8 level, uint16 x, uint16 y)
{
   //0xD2 0x2C 0x00 0x00 0x4C 0x00 0xB4 0x00 0xAC 0x04 0x5A 0x1F
   CastSpell(ATK, (0x00B3 + level), x, y);
}
void Player::FragorIpsum(uint8 level)
{
   //0xD2 0x2C 0x00 0x00 0x4E 0x00 0xFA 0x00 0xD2 0x2C 0x5A 0x1F
   CastSpell(SELF, (0x00F9 + level), p_id, 0);
}
void Player::Freeze(uint8 level, uint16 x, uint16 y)
{
   //0xD2 0x2C 0x00 0x00 0x4C 0x00 0x4A 0x01 0xAA 0x04 0x50 0x1F
   CastSpell(ATK, (0x0049 + level), x, y);
}
void Player::Sidus(uint8 level, uint16 x, uint16 y)
{
   //0xD2 0x2C 0x00 0x00 0x4C 0x00 0x55 0x01 0xB5 0x04 0x59 0x1F
   CastSpell(ATK, (0x0154 + level), x, y);
}

//Others
void Player::MutatioNimbus()
{
   //0xD2 0x2C 0x00 0x00 0x4E 0x00 0x5F 0x00 0xD2 0x2C 0x3A 0x1F
   CastSpell(SELF, 0x005F, p_id, 0);
}
void Player::PergereTrans(uint16 x, uint16 y)
{
   //0xD2 0x2C 0x00 0x00 0x4C 0x00 0xBF 0x00 0xA6 0x04 0x3E 0x1F
   CastSpell(ATK, 0x00BF, x, y);
}
void Player::PraesentisTrans(uint8 mark)
{
   //0xAE 0x00 0x00 0x00 0x31 0x00 0x1B 0x01 0x00 0x00 0x00 0x00
   CastSpell((0x0030 + mark), 0x011B, 0, 0);
}
void Player::Star()
{
   //0xD2 0x2C 0x00 0x00 0x4E 0x00 0x24 0x01 0xD2 0x2C 0x3E 0x1F
   CastSpell(SELF, 0x0124, p_id, 0);
}

void Player::CastSpell(uint16 type, uint16 id, uint16 x, uint16 y)
{
   Packet spell(0x08, 12);
   spell << p_id;
   spell << (uint16)0;
   spell << (uint16)type;
   spell << (uint16)id;
   spell << (uint16)x;
   spell << (uint16)y;

   //Send Packet
   oSendPacket(spell, spell, spell);

   free((uint8*)spell);
}

void Player::StopAction()
{
   //0xAE 0x00 0x00 0x00 0x07 0x00 0x00 0x00 0x00 0x00 0x00 0x00
   Packet stop(0x0C, 12);
   stop << p_id;
   stop << (uint16)0;
   stop << (uint16)0x0007;

   oSendPacket(stop, stop, stop);

   free((uint8*)stop);
}

void Player::SwitchWeapons()
{
   //0xAE 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00
   Packet swap(0x0C, 12);
   swap << p_id;
   swap << (uint16)0;
   swap << (uint16)0x0001;

   oSendPacket(swap, swap, swap);

   free((uint8*)swap);
}

void Player::Walk(uint16 x, uint16 y)
{
   //0xAE 0x00 0x00 0x00 0x64 0x2E 0x00 0x00 0x42 0x31 0x00 0x00 0x4D 0xA1 0x00 0x00
   Packet move(0x01, 16);
   move << p_id;
   move << (uint16)0;
   move << x;
   move << (uint16)0;
   move << y;
   move << (uint16)0;
   move << genMoveChecksum(p_id, x, y, MOVE);

   oSendPacket(move, move, move);

   free((uint8*)move);
}

void Player::Attack(uint16 who, uint16 y)
{
   //0xAE 0x00 0x00 0x00 0xAB 0x1A 0x00 0x00 0xB6 0x30 0x00 0x00 0x41 0x50 0x00 0x00
   Packet move(0x01, 16);
   move << p_id;
   move << (uint16)0;
   move << who;
   move << (uint16)0;
   move << y;
   move << (uint16)0;
   move << genMoveChecksum(p_id, who, y, ATTACK);

   oSendPacket(move, move, move);

   free((uint8*)move);
}

void Player::WalkTo(uint16 x, uint16 y)
{
   UpdatePacketSelf ups = GetUpdateInfo();
   while(!CheckRadius(ups.positionX, ups.positionY, x, y, 40))
   {
      uint16 movex, movey;
      if(x > ups.positionX) //Moving to the right
      {
         int m = rand()%20+80;
         if(ups.positionX + m < x)
            movex = ups.positionX + m;
         else
            movex = x;
      }
      else //Moving to the left
      {
         int m = rand()%20+80;
         if(ups.positionX - m > x)
            movex = ups.positionX - m;
         else
            movex = x;
      }
      if(y > ups.positionY) //Moving up
      {
         int m = rand()%20+80;
         if(ups.positionY + m < y)
            movey = ups.positionY + m;
         else
            movey = y;
      }
      else //Moving down
      {
         int m = rand()%20+80;
         if(ups.positionY - m > y)
            movey = ups.positionY - m;
         else
            movey = y;
      }

      Walk(movex, movey);
      Sleep(300);

      ups = GetUpdateInfo();
   }
}

void Player::Say(char *chat, int len)
{
   //0xAE 0x00 0x00 0x00 : 68
   Packet msg(0x0A, 68);
   msg << p_id;
   msg << (uint16)0;
   for(int i = 0; i < len; i++)
      msg << (uint8)chat[i];

   oSendPacket(msg, msg, msg);

   free((uint8*)msg);
}

uint16 Player::genMoveChecksum(uint16 id, uint16 x, uint16 y, uint8 type)
{
   uint16 checksum = 0;
   checksum += id;
   checksum += x;
   checksum += y;
   checksum += type;
   checksum = type | (checksum << 8);
   return checksum;
}

BOOL Player::CheckRadius(int px, int py, int mx, int my, int r)
{
   if( ((px - mx) * (px - mx)) + ((py - my) * (py - my)) <= (r * r))
      return true;
   return false;
}
void Player::RequestQuestLog()
{
   //0xAE 0x00 0x00 0x00 0x04 0x00 0x00 0x00 0x0F 0x35 0x00 0x00
   Packet log(0x25, 12);
   log << p_id;
   log << (uint16)0;
   log << (uint16)0x0004;

   oSendPacket(log, log, log);

   free((uint8*)log);
}

void Player::TransAndMultiPath(_POINT* path, int size)
{
   UpdatePacketSelf ups = GetUpdateInfo();
   for(int i = 0; i < size; i++)
   {
      RequestQuestLog();
      Sleep(100);
      if(UnitMap::UnitsAlive(ups.positionX, ups.positionY, 90) > 0)
      {
         Star(); Sleep(300);
         FragorIpsum(8); Sleep(600);
      }

      PergereTrans(path[i].x*20+10, path[i].y*20+10); Sleep(300);
      ups = GetUpdateInfo();
      if(GetQuestLog().curkills == GetQuestLog().reqkills)
         break;
   }
}


Top
 Profile  
 
PostPosted: 30 Aug 2013 17:41 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
Code is still a little messy, as im constantly adding/changing things to try and figure stuff out. But this is the current work i have with it

https://github.com/toddwithers/XenBot


Top
 Profile  
 
PostPosted: 30 Aug 2013 18:42 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
I think i should learn more about smart pointers, as they would probably fix most of the errors i have.

Anyways, manged to find and fix a few bugs i was having. I think my UnitMap::CleanMap() function still causes a crash sometimes, but i did fix an error in the code involving the iterator
Code:
hash_map<int, Unit*>::iterator iter = map.begin();
         while(iter != map.end())
         {
            if(!iter->second->inrange)
            {
               delete[] iter->second;
               iter = map.erase(iter);
            }
            else
               ++iter;
         }


and then my ParseQuestText was also throwing an error, so i changed it to this (though it never crashed on me until i changed the DLL to a debug DLL...)
Code:
void Player::ParseQuestText(uint8* packet)
{
   InitialQuestData iqd = *(InitialQuestData*)&packet[2];
   if(iqd.strings > 0)
   {
      for(int i = 0; i < iqd.strings; i++)
      {
         QuestText qt = *(QuestText*)&packet[4+(i*44)];
         if(strcmp((char*)qt.text, "~OK") == 0)
            QuestFlags |= OK;
         else if(strcmp((char*)qt.text, "~Thanks") == 0)
            QuestFlags |= THANKS;
         else if(strcmp((char*)qt.text, "~Guardian task") == 0)
            QuestFlags |= GUARDIANS;
      }
   }
}


Im hoping this fixes my crash bug, but ill know soon enough if its fixed or not. I do believe that any bugs i have are related to the pointers though, but i though i had cleaned all of them up correctly.


Edit:

In a moment of rational thinking, i realized i have no reason at all to be using a Unit pointer for my hash_map...So i changed it. The above code fix did not solve the problem. Now i am testing out the new code which gets rid of all the stupid pointers. Hope it works.


Top
 Profile  
 
PostPosted: 31 Aug 2013 11:03 
Offline

Joined: 05 Nov 2007 11:14
Posts: 108
Thought I would contribute to this. A lot of people asked me when they implemented their item sniffers how xenlua kept accuracy with text showing over the item.

Here is the code for it, it isn't perfect as it was the result of some branch mergers, the XPS is much better then this as it allows attaching elements to any units for things like health bars:

Code:
void UITextElement::Render(IDirect3DDevice9* dev)
{
   if (m_3d)
   {
      D3DVIEWPORT9 viewport;
      sUIController.GetD3DDevice()->GetViewport(&viewport);

      //local position is 0, 0, 0, therefore our vector should be at pos - local
      //world is scaled by 4 LOL
      float x = m_3dx;
      float y = m_3dy;
      float z = m_3dz;

      auto mapinter = GetMapInterface();

      if (mapinter != NULL)
         z = mapinter->GetZ(int32(x / 20), int32(y / 20));

      D3DXVECTOR3 pos((x - *sUIController.m_localPositionX) * 4, (y - *sUIController.m_localPositionY) * 4, z);

      if (sUIController.GetCurrentViewMode() == 2) //0 = top down, 2 = y stretched z units negative, 4 = first person mode
         pos.y -= pos.z; //stretched view, display in right location still

      D3DXVECTOR3 screen;

      D3DXMATRIX world, projection, view;
      sUIController.GetD3DDevice()->GetTransform(D3DTS_WORLD, &world);
      sUIController.GetD3DDevice()->GetTransform(D3DTS_PROJECTION, &projection);
      sUIController.GetD3DDevice()->GetTransform(D3DTS_VIEW, &view);

      D3DXVec3Project(&screen, &pos, &viewport, &projection, &view, &world);

      if (screen.z >= 1.0f) //the projection is beyond the screen, usually text that is behind the camera
         return;

      SetPositionX(screen.x);
      SetPositionY(screen.y);
   }
}


Top
 Profile  
 
PostPosted: 31 Aug 2013 11:04 
Offline

Joined: 05 Nov 2007 11:14
Posts: 108
And to get the land height of the tile is:

Code:
   float GetZ(int32 x, int32 y)
   {
      uint8 layer4 = GetMapLayer4(x, y);
      char layer4c = *(char*)&layer4;
      float z = layer4c;
      z = -z * 10;
      return z;
   }


Top
 Profile  
 
PostPosted: 31 Aug 2013 15:27 
Offline
Very Important Poster
User avatar

Joined: 28 Nov 2007 23:35
Posts: 186
Character(s): None.
This is basically a complete botting tool :D

I approve. EJ probably wont so be super careful that you do all the checksums/increments and shit correctly.


Top
 Profile  
 
PostPosted: 31 Aug 2013 20:39 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
ubern00ber wrote:
This is basically a complete botting tool :D

I approve. Cheeseguy probably wont so be super careful that you do all the checksums/increments and shit correctly.


Thats what im attempting to make atleast. Its a scripted macro basically. As in, instead of just transing around casting multi every time like some peoples bots do, this one has a small amount of AI and knows when monsters are around. I wish Andys old bot code was still on these forums so i could see how he did some stuff


Top
 Profile  
 
PostPosted: 31 Aug 2013 21:04 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
edit: blah nevermind.


Top
 Profile  
 
PostPosted: 01 Sep 2013 02:47 
Offline

Joined: 05 Nov 2007 11:14
Posts: 108
Some of the latest bot code that I had, all in lua.

Code:
function MoveToCell(x, y, method)
   return MoveTo(x * 20 + 5 + RandomInt(0, 10), y * 20 + 5 + RandomInt(0, 10), method);
end

function MoveTo(x, y, method)
   -- Methods we use to move
   if (method == "TELEPORT") then return MoveTeleport(x, y); end;
   if (method == "WALK") then return MoveWalk(x, y); end;
   if (method == "GAS") then return MoveGas(x, y); end
end

function MoveTeleport(x, y)
   local spell = GetPlayer():GetBestSpell("Pergere Trans", "");
   local numwands = GetPlayer():CountItem(207);
   
   if (numwands > 0) then spell = 207 + 10000; end
   
   if (spell == 0) then print(string.format("BOT: Cannot trans to %u, %u (no method)", x, y)); return; end
   
   --GetPlayer():QueueCastSpellGroundReal(50, spell, x, y);
   local ret = GetPlayer():CreatePathReal(x, y, -1);
   if (ret)
   then
      GetPlayer():SetPathFlags(PASS_FLAG_TELEPORT);
      GetPlayer():SetPathSpell(spell);
      GetPlayer():QueueUpdatePath(200);
      GetPlayer():QueueWaitMove(50, 1000);
      return true;
   end
   return false;
end

function MoveWalk(x, y)
   --GetPlayer():QueueMoveReal(200, x, y);
   
   local ret = GetPlayer():CreatePathReal(x, y, -1);
   if (ret)
   then
      GetPlayer():SetPathFlags(PASS_FLAG_WALK);
      GetPlayer():SetPathSpell(0);
      GetPlayer():QueueUpdatePath(200);
      return true;
   end
   return false;
end

function MoveGas(x, y)
   --GetPlayer():QueueMoveReal(200, x, y);
   local ret = GetPlayer():CreatePathReal(x, y, -1);
   if (ret)
   then
      if (GetPlayer():HasAura(AURA_MUTATIO_NUMBIS) == false)
      then
         GetPlayer():QueueCastSpellSelf(500, GetPlayer():GetBestSpell("Velocitas", ""));
         GetPlayer():QueueCastSpellSelf(200, GetPlayer():GetBestSpell("Mutatio Nimbus", ""));
      end
      
      GetPlayer():SetPathFlags(PASS_FLAG_GAS);
      GetPlayer():SetPathSpell(0);
      GetPlayer():QueueUpdatePath(200);
      return true;
   end
   return false;
end


Code:
PORT_FINISH_TIME = 0;

function PortToMark(mark, map)

   --Do we have insta port?
   local insta = GetPlayer():GetBestSpell("Praesentis Trans", "");
   --Do we have portals?
   local port = GetPlayer():GetBestSpell("Creare Porta", "");
   
   if (insta == 0 and port == 0) then print("BOT: cannot insta or port!"); return; end
   
   if (insta ~= 0) then GetPlayer():QueueCastSpellMark(1000, insta, mark, 0, 0, map); return; end
   
   --Portals, sigh
   if (port ~= 0)
   then
      -- Method of getting to portal?
      local portarriveflags = PASS_FLAG_WALK;
      if (GetPlayer():GetBestSpell("Pergere Trans", "") ~= 0) then portarriveflags = PASS_FLAG_TELEPORT; end
      local hasportloc = GetPlayer():CalcBestPort(portarriveflags);
      
      if (hasportloc == false) then print("BOT: No valid location to make portal") return; end
      
      GetPlayer():QueueCastSpellMark(500, port, mark, GetPlayer():GetBestTransX(), GetPlayer():GetBestTransY(), map);
      
      if (portarriveflags == PASS_FLAG_TELEPORT) then GetPlayer():QueueCastSpellGroundReal(200, GetPlayer():GetBestSpell("Pergere Trans", ""), GetPlayer():GetBestTransX(), GetPlayer():GetBestTransY());
      else GetPlayer():QueueMove(200, GetPlayer():GetBestTransX() / 20, GetPlayer():GetBestTransY() / 20);
      end
      
      PORT_FINISH_TIME = GetMSTime() + 7500;
   end
end

function IsPorting()
   local isporting = false;
   if (GetMSTime() < PORT_FINISH_TIME) then isporting = true; end
   return isporting;
end


Code:
QUEST_HANDIN_ACTIVE = false;
QUEST_NPC_FOUND = false;
QUEST_NPC_TALKED_TO = false;
RegisterEventHandler("EVENT_QUEST_UI_UPDATE", "BotQuestHandinUIUpdate");

function BotDoQuestHandIn()
   print("BOT: Handing in quest");
   --port to mark 9, this is t3
   local player = GetPlayer();
   
   if (IsPorting()) then SetBotAction("waithandin"); return; end
   PortToMark(QUEST_GIVER_MARK, 0);   
   
   --and move to spot
   --player:QueueMove(100, 624, 629);
   
   QUEST_HANDIN_ACTIVE = true;
   QUEST_NPC_FOUND = false;
   QUEST_NPC_TALKED_TO = false;
   SetBotAction("handin");
end

function BotDoQuestHandInTick()
   local player = GetPlayer();
   if (QUEST_HANDIN_ACTIVE == false) then return; end
   if (player:QueueReady() == false) then return; end
   if (IsPorting()) then return; end
   
   local questnpcserverid = QUEST_GIVER_ID; --this is the ominex dude in t3 castle
   local unit = GetUnit(questnpcserverid);
   
   if (unit == nil and player:GetCellX() == QUEST_GIVER_X and player:GetCellY() == QUEST_GIVER_Y)
   then
      PortToMark(1, 0);
      SetBotAction("CLOSEDFAGGTODRAGAWAY");
      return;
   end
   
   if (unit == nil and QUEST_GIVER_X ~= 0) then MoveToCell(QUEST_GIVER_X, QUEST_GIVER_Y, QUEST_MOVEMENT_METHOD); return; end
   
   if (unit == nil) then return; end
   
   if (QUEST_NPC_FOUND == false)
   then
      local dist = player:GetDistanceToUnit(questnpcserverid);
      
      if (dist < 60)
      then
         QUEST_NPC_FOUND = true;
      else
         local x = unit:GetPositionX();
         local y = unit:GetPositionY();
         if (x > 1 and y > 1)
         then
            if (QUEST_MOVEMENT_METHOD == "TELEPORT")
            then
               player:QueueCastSpellGround(300, player:GetBestSpell("Pergere Trans", ""), unit:GetPositionX() / 20, unit:GetPositionY() / 20);
            else
               MoveToCell(unit:GetPositionX() / 20, unit:GetPositionY() / 20, QUEST_MOVEMENT_METHOD);
            end
         end
      end
   else
      if (QUEST_NPC_TALKED_TO == false)
      then
         if (player:HasAura(AURA_MUTATIO_NUMBIS)) then player:QueueStop(200); end
         player:QueueAttack(1000, questnpcserverid);
      end
   end
end

function BotQuestHandinUIUpdate(step, text)
   if (text == nil) then return; end
   
   QUEST_NPC_TALKED_TO = true;
   
   local buttonquest = string.format("~%s", QUEST_NAME);
   
   if (text == buttonquest) then GetPlayer():QueueSay(1200, QUEST_NAME); end
   if (text == "~quests,items") then GetPlayer():QueueSay(1200, "quests"); end --This is to get into multi type NPCs like Harsad
   if (text == "~OK") then GetPlayer():QueueSay(1200, "OK"); BotDoQuestHandinComplete(); end
   if (text == "~Thanks") then GetPlayer():QueueSay(1200, "Thanks"); QUEST_NPC_TALKED_TO = false; end
end

function BotDoQuestHandinComplete()
   QUEST_HANDIN_ACTIVE = false;
   SetBotAction("handinwait");
end


Top
 Profile  
 
PostPosted: 01 Sep 2013 03:02 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
hahah love it :)


Top
 Profile  
 
PostPosted: 21 Sep 2013 18:45 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
man, ive been so busy with my new job i havent found any time to code anything new for this, or even play xenimus. Which may or may not be a good thing haha.


Top
 Profile  
 
PostPosted: 22 Sep 2013 23:15 
Offline

Joined: 20 Jun 2013 15:54
Posts: 13
Looking forward to seeing what you come up with if you continue this.


Top
 Profile  
 
PostPosted: 06 Dec 2013 20:28 
Offline

Joined: 05 Nov 2007 11:14
Posts: 108
So I just thought I would mention I did start working on my own scanner for the addreses for xenlua, progress is going ahead nicely.

Will post some source when I have things tidied up and stuff.

Image


Top
 Profile  
 
PostPosted: 07 Dec 2013 06:17 
Offline

Joined: 05 Nov 2007 11:14
Posts: 108
Ok tidied it up a bit, still a tonne left to look for.

Code:
uint8* PatternHandler::FindDecrypt()
{
   /*
   Decrypt

   .text:004274E0                 push    esi
   .text:004274E1                 mov     esi, [esp+4+arg_0]
   .text:004274E5                 mov     [ecx+10h], esi
   .text:004274E8                 movzx   edx, byte ptr [esi]
   .text:004274EB                 movzx   eax, byte ptr [esi+1]
   HEX: 56 8B 74 24 08 89 71  10 0F B6 16 0F B6 46 01
   MANUAL FIND: Is just after the call to recvfrom (IAT)
   */

   uint8 needle[] = { 0x56, 0x8B, 0x74, 0x24, 0x08, 0x89, 0x71, 0x10, 0x0F, 0xB6, 0x16, 0x0F, 0xB6, 0x46, 0x01 };
   char* mask = "xxxxxxxxxxxxxxx";

   return Find(needle, mask);
}


uint8* PatternHandler::FindEncrypt()
{
   /*
   Encrypt

   .text:00427410                 mov     eax, [esp+arg_0]
   .text:00427414                 push    esi
   .text:00427415                 mov     esi, ecx
   .text:00427417                 mov     [esi+10h], eax
   .text:0042741A                 xor     byte ptr [eax], 0AAh

   HEX: 8B 44 24 04 56 8B F1 89 46 10 80 30 AA
   MANUAL FIND: Is just before the call to sendto (IAT)
   */

   uint8 needle[] = { 0x8B, 0x44, 0x24, 0x04, 0x56, 0x8B, 0xF1, 0x89, 0x46, 0x10, 0x80, 0x30, 0xAA };
   char* mask = "xxxxxxxxxxxxx";

   return Find(needle, mask);
}


uint8* PatternHandler::FindSendPacket()
{
   /*
   SendPacket

   .text:0042CE20                 cmp     dword_38D0490, 0D64C96E2h
   .text:0042CE2A                 jnz     locret_42CEDC
   .text:0042CE30                 mov     eax, dword_10F8CF4
   .text:0042CE35                 shl     eax, 6

   HEX: 81 3D 90 04 8D 03 E2 96 4C D6 0F 85 AC 00 00 00 A1 F4 8C 0F 01 C1 E0 06
   HEX (AMBIG): HEX: 81 3D xx xx xx xx E2 96 4C D6 0F 85 xx xx xx xx A1 xx xx xx xx C1 E0 06
   MANUAL FIND: The call to sendto (IAT) is in this sub.

   Note: jnz is jump near of 0xAC bytes, the number of bytes has been removed to facilitate code structure changes
   */

   uint8 needle[] = { 0x81, 0x3D, 0x90, 0x04, 0x8D, 0x03, 0xE2, 0x96, 0x4C, 0xD6, 0x0F, 0x85, 0xAC, 0x00, 0x00, 0x00, 0xA1, 0xF4, 0x8C, 0x0F, 0x01, 0xC1, 0xE0, 0x06 };
   char* mask = "xx????xxxxxx????x????xxx";

   return Find(needle, mask);
}

uint8* PatternHandler::FindLocalPositionX()
{
   /*
   LocalPositionX (variable)

   .text:004A1AFD                 movzx   eax, word ptr [eax+0Ah]
   .text:004A1B01                 fild    [esp+40h+var_4]
   .text:004A1B05                 mov     [esp+40h+var_4], eax
   HEX:

   IMMEDIATELY AFTER
   .text:004A1B09                 fsub    flt_10FAE54 //this is our variable
   HEX D8 25 54 AE 0F 01

   */
   uint8 needle[] = {0x0F, 0xB7, 0x40, 0x0A, 0xDB, 0x44, 0x24, 0x3C, 0x89, 0x44, 0x24, 0x3C};
   char* mask = "xxxxxxxxxxxx";
   uint8* ptr = Find(needle, mask);
   XENLUA_LOG("TEST LOCALPOSX NEEDLE %p\n", ptr);

   if (ptr != NULL)
   {
      ptr += strlen(mask); //go past the search

//       //THIS SHOULD BE INSTRUCTION D8 (FSUB)
//       XENLUA_LOG("LOCALPOS INSTRUCTION TEST %x (SHOULD BE D8)\n", ptr[0]);

      ptr += 2; //instruction size 16bit

      //so ptr should be now be a pointer to the address of the variable
      return *(uint8**)ptr;
   }

   return NULL;
}


Top
 Profile  
 
PostPosted: 10 Dec 2013 21:26 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
very nice and clean andy :)

i was actually just over on the other boards for my weekly check in and was reading how you implemented the address scanning, sweet work.


Top
 Profile  
 
PostPosted: 11 Dec 2013 04:19 
Offline

Joined: 05 Nov 2007 11:14
Posts: 108
You have no idea how annoying one of them were. I had no idea there was an instruction for a call to relative address, and the compiler that EJ uses generates things like call (rel) -180


Top
 Profile  
 
PostPosted: 18 Jun 2014 14:52 
Offline

Joined: 12 Jun 2014 03:49
Posts: 10
Character(s): Weed wiz
I've changed the way the hooking process works so now it will hook into the wndproc and grab the handle, Seems to run alot better and allows me to run multiple clients without interfering with one another, I know you love code so enjoy ><


Also added a new class i've added on the end and a couple of functions to work with it. Was going to post this sooner but wanted to get things running a bit smoother.

Code:
DWORD WINAPI HookingThreadFunc( LPVOID lpParam )
{
   HWND   hMain = 0;
   DWORD   dwProcessID = 0;
   bool   bFind = false;

   while(!bFind)
   {
      Sleep (1000);

      HANDLE hProcessSnap;
      PROCESSENTRY32 pe32;
      hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

      if (hProcessSnap == INVALID_HANDLE_VALUE) {
         dwProcessID = 0;
      }
      else
      {
         pe32.dwSize = sizeof(PROCESSENTRY32);
         
         if (Process32First(hProcessSnap, &pe32))
         {
            if (_stricmp(pe32.szExeFile, "xenimus.exe") == 0)
            {
               bFind = true;
               dwProcessID = pe32.th32ProcessID;
            }
            else
            {
               while (Process32Next(hProcessSnap, &pe32)) {
                  if (_stricmp(pe32.szExeFile, "xenimus.exe") == 0)
                  {
                     bFind = true;
                     dwProcessID = pe32.th32ProcessID;
                     break;
                  }
               }
            }
            CloseHandle(hProcessSnap);
         }
      }
   }

   while (hMain == 0)
   {
      Sleep(100);
      hMain = find_main_window(dwProcessID);      
   }
   
   
   UnitMap::Initialize();
   ItemMap::Initialize();
   Inventory::Initialize();

   DWORD addrSendPacket = 0x0042DE50;
   oSendPacket = (tSendPacket)addrSendPacket;

   DWORD addrEncrypt  = 0x00427DE0;
   oEncrypt = (tEncrypt)addrEncrypt;

   DWORD addrDecrypt  = 0x00427EB0;
   oDecrypt = (tDecrypt)addrDecrypt;

   DetourTransactionBegin();
   DetourUpdateThread(GetCurrentThread());
   
   HANDLE hUser32DllEntry = ::GetModuleHandle("user32.dll");
   /*if (hUser32DllEntry != INVALID_HANDLE_VALUE)
   {
      DWORD   dwProtect = 0;
      DWORD   dwOldProtect = 0;
      DWORD   dwp = (DWORD)GetProcAddress((HMODULE)hUser32DllEntry, "PeekMessageW");
      dwPeekMsgHookJmp = dwp + 5;

      ::VirtualProtect((void*)dwp, 5, PAGE_EXECUTE_READWRITE, &dwProtect);
      *(BYTE*)(dwp) = 0xE9;
      *(DWORD*)(dwp + 1) = (DWORD)PeekMessageWHookFunc - dwp - 5;
      ::VirtualProtect((void*)dwp, 5, dwProtect, &dwOldProtect);
      g_Log.Log("creating PeekMessage Hook %x -> %x\n", dwp, PeekMessageWHookFunc);      
   }*/

   g_Log.Log("creating encrypt detour %x -> %x\n", addrEncrypt, encryptHook);
   DetourAttach(&(PVOID&)oEncrypt, encryptHook);
   g_Log.Log("creating decrypt detour %x -> %x\n", addrDecrypt, decryptHook);
   DetourAttach(&(PVOID&)oDecrypt, decryptHook);
   DetourTransactionCommit();

   bRunning = true;

   plr = new Player;
   plr->Initialize(addrSendPacket);
   CreateThread(0, 0, InPacketsProcesser, 0, 0, 0);

   
   g_Log.Log("Current Proccess ID = %x, Handle = %x", dwProcessID, hMain);

   pOrigProc = (WNDPROC)GetWindowLongW(hMain, GWL_WNDPROC);
   SetWindowLongW(hMain, GWL_WNDPROC, (LONG)HookWndProc);
   
    return 0;
}


Code:
HWND find_main_window(unsigned long process_id)
{
   handle_data data;
   data.process_id = process_id;
   data.best_handle = 0;
   EnumWindows(enum_windows_callback, (LPARAM)&data);
   return data.best_handle;
}


Code:
LRESULT CALLBACK HookWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
   //g_Log.Log("Message = %x", uMsg);
   switch(uMsg)
   {
   case WM_KEYDOWN:
      {
         switch (wParam)
         {
         case VK_NUMPAD1:
            {
               g_bIsSendPackLog = !g_bIsSendPackLog;
               if (g_bIsSendPackLog)
                  g_Log.Log("Send Packet Log Start");
               else
                  g_Log.Log("Send Packet Log Stop");
            }
            break;
         case VK_NUMPAD2:
            {
               g_bIsRecvPackLog = !g_bIsRecvPackLog;
               if (g_bIsRecvPackLog)
                  g_Log.Log("Recv Packet Log Start");
               else
                  g_Log.Log("Recv Packet Log Stop");
            }
            break;

         case VK_NUMPAD3:
            {
               plr->GetCurrentPos(g_TargetX, g_TargetY);
               g_Log.Log("Current Position X = %x, Y = %x, (%d, %d)", g_TargetX, g_TargetY, (g_TargetX - 10) / 20, (g_TargetY - 10) / 20);
               
            }
            break;

         case VK_NUMPAD4:
            {
               DWORD dwThreadId, dwThrdParam = 1;
               ::CreateThread(NULL, 0, TestThread, &dwThrdParam, 0, &dwThreadId);         
               /*g_Log.Log("Kill Guardians STart");
               
               g_Log.Log("Kill Guardians End");*/
            }
            break;

         case VK_NUMPAD5:
            {
               g_Log.Log("Item Information");
               ItemMap::OutputItemMap();               
            }
            break;
            
         case VK_NUMPAD6:
            {
               plr->Star();
            }
            break;

         case VK_NUMPAD7:
            {
               g_Log.Log("Open Item Shop");
               plr->OpenShopWindow();
               UnitMap::OutputUnitMap();
            }
            break;

         case VK_NUMPAD8:
            {
               g_Log.Log("Sell Item");
               plr->SellAllItem();
            }
            break;

         case VK_DELETE:
            {
               plr->GetCurrentPos(g_TargetX, g_TargetY);
               g_Log.Log("Current Position X = %x, Y = %x", g_TargetX, g_TargetY);
               char str[64] = {0,};
               sprintf_s(str, "{%d, %d}", g_TargetX, g_TargetY);
               path.push_back(str);
            }
            break;

         case VK_INSERT:
            {
               vector<string>::iterator it;
               string str = "{";

               for (it = path.begin(); it != (path.end() - 1); it++)
               {
                  str += *it + ", ";               
               }

               it = path.end() - 1;
               str += (*it + "}");

               g_Log.Log("Saved Path is ");
               g_Log.Log(str.c_str());
            }
            break;

         case VK_F11:
            {
               if (!g_bThreadCreated)
               {
                  g_Log.Log("Creating Bot Thread");
                  //CreateThread(0, 0, bot, 0, 0, 0);
                  g_bThreadCreated = true;
               }
            }
            break;
         default:
            break;
         }
      }
      break;

   default:
      break;
   }

   // Call main Window Proc
   return CallWindowProc(pOrigProc, hwnd, uMsg, wParam, lParam);
}


Code:
void ItemMap::OutputItemMap()
{
   DWORD dwWaitResult;

   /*FILE* out = fopen("UnitMap.log", "a+");
   fprintf(out, "-----------------------------------------------------------------------\n");
   fprintf(out, "| Units On Screen: %i                                                 |\n", map.size());
   fprintf(out, "-----------------------------------------------------------------------\n");*/

   dwWaitResult = WaitForSingleObject(ghMutex, INFINITE);
   switch (dwWaitResult)
   {
   case WAIT_OBJECT_0:
      //__try
      {
         list<Item*>::iterator iter;
         for(iter = item.begin(); iter != item.end(); iter++)
         {
            //fprintf(out, "ID: %i | Model: %i | Weapon: %i | Sheild: %i | Helmet: %i | Colorbits: %i | X/Y: %i, %i\n", iter->second->id, iter->second->models.model, iter->second->models.weapon, iter->second->models.shield, iter->second->models.helmet, iter->second->models.colorbits, iter->second->movement.positionX, iter->second->movement.positionY);
            Item* tmp = *iter;
            g_Log.Log("Item Pos = (%d, %d)", tmp->GetXPos(), tmp->GetYPos());
         }
      }
      //__finally
      {
         if(!ReleaseMutex(ghMutex))
         {
            printf("Failed to release mutex: %d\n", GetLastError());
         }
      }
      break;
   case WAIT_ABANDONED:
      break;
   }
   /*fprintf(out, "\n");
   fclose(out);*/
}


Code:
void ItemMap::GetItemPos(uint16& x, uint16& y)
{
   DWORD dwWaitResult;

   dwWaitResult = WaitForSingleObject(ghMutex, INFINITE);
   switch (dwWaitResult)
   {
   case WAIT_OBJECT_0:
      {
         Item* pTmp = NULL;
         list<Item*>::iterator findIter;
         x = -1;
         y = -1;

         for (findIter = item.begin(); findIter != item.end(); findIter++)
         {
            x = (*findIter)->GetXPos();
            y = (*findIter)->GetYPos();
            break;
         }
      }

      if(!ReleaseMutex(ghMutex))
      {
         printf("Failed to release mutex: %d\n", GetLastError());
      }
      break;
   case WAIT_ABANDONED:
      break;
   }
}


Code:
void ItemMap::SetItemInRange(uint16 x, uint16 y)
{
   DWORD dwWaitResult;

   dwWaitResult = WaitForSingleObject(ghMutex, INFINITE);
   switch (dwWaitResult)
   {
   case WAIT_OBJECT_0:
      {
         Item* pTmp = NULL;
         list<Item*>::iterator findIter;

         for (findIter = item.begin(); findIter != item.end(); findIter++)
         {
            if ((*findIter)->GetXPos() == x && (*findIter)->GetYPos() == y)
            {
               pTmp = *findIter;
               break;
            }
         }

         if (pTmp == NULL)
         {
            pTmp = new Item(x, y);
            item.push_back(pTmp);
         }

         if (pTmp != NULL)
            pTmp->SetRange(true);
      }
      
      if(!ReleaseMutex(ghMutex))
      {
         printf("Failed to release mutex: %d\n", GetLastError());
      }
      break;
   case WAIT_ABANDONED:
      break;
   }
}


Code:
void Inventory::OutputInventory()
{
   for (int i = 0; i < INVEN_SLOT_CNT; i++)
   {
      if (!IsEmptySlot(i))
      {
         uint16 itemType = GetItemType(i);
         g_Log.Log("[%d] - type = %d", i, itemType);
      }
      else
      {
         g_Log.Log("[%d] slot is empty", i);
      }
   }
}

uint16 Inventory::GetItemType(uint16 nSlotNumber)
{
   uint16 itemType;
   if (nSlotNumber < 0 || nSlotNumber >= INVEN_SLOT_CNT)
      return -1;

   itemType = *(uint16*)(m_Inven + nSlotNumber * 16);

   return itemType;
}

bool Inventory::IsEmptySlot(uint16 nSlotNumber)
{
   uint16 itemType;
   itemType = GetItemType(nSlotNumber);
   
   if (itemType <= 0)
      return true;
   
   return false;
}


Code:
void Player::OpenShopWindow()
{
   uint16 id = 0;
   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(443, 14, 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);
   }
   else
   {
      //UnitMap::LocateUnit(61, 14, 0, 0, 614, id, positionY);
      UnitMap::LocateUnit(61, 14, 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);
      }
   }
   Sleep(500);
}


/*
itemNumInInven : Item number on Inventory (this value is started from 0)
itemCntToSell : Item count to sell (1, 5, 10, 20)
itemTypeOnInven : Item type to sell (This value is type of item is indicated by itemNumInInven on Inventory)
*/
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);
}


Code:
unsigned __stdcall Player::ThreadFunc(void* pvParam)
{
   Player* me = (Player*)pvParam;
   DWORD dwWaitResult = WaitForSingleObject(me->ghMutextSell, INFINITE);
   g_Log.Log("ThreadFunc = %d", dwWaitResult);
   switch (dwWaitResult)
   {
   case WAIT_OBJECT_0:
      {
         __try
         {
            g_Log.Log("DDDDDDDDDDD");
            me->PraesentisTrans(1); //This spell teleports to shop
            Sleep(1500); //I did forget one.
            me->OpenShopWindow(); //This open
            Sleep(1500);
            g_Log.Log("I sell");
            //Test
            me->SellAllItem(); //This sell
            Sleep(1500);

            me->PraesentisTrans(3); //This teleport back to path
            g_Log.Log("PraesentisTrans(3)");
         }
         __finally
         {
            if(!ReleaseMutex(me->ghMutextSell))
            {
               printf("Failed to release mutex: %d\n", GetLastError());
            }
         }

      }
      break;
   }
   
   return 0;
}

void Player::StartSellThread()
{
   (HANDLE)_beginthreadex(
      (void *)NULL,
      (unsigned)0,
      (PTHREAD_START)Player::ThreadFunc,
      (PVOID)this,
      (unsigned)0,
      NULL
      );
}



Hope you were not jokin when you said you like code ;) Imight have went a bit overboard there just really pleased with my results.


Top
 Profile  
 
PostPosted: 18 Jun 2014 15:02 
Offline

Joined: 25 Feb 2010 11:07
Posts: 89
Did you seriously just post this, after you accused me of lying about you botting? Laughing so hard right now. Go away, clerythecleric.


Top
 Profile  
 
PostPosted: 19 Jun 2014 02:59 
Offline

Joined: 12 Jun 2014 03:49
Posts: 10
Character(s): Weed wiz
Assault wrote:
Did you seriously just post this, after you accused me of lying about you botting? Laughing so hard right now. Go away, clerythecleric.


Don't know what you're talkin about but oki! :)
<3 you too.

FYI this isn't for a bot its just a tool for collecting pinecones. :


Top
 Profile  
 
PostPosted: 19 Jun 2014 13:32 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
nice, very clean code. I like it. Good work bud!


Top
 Profile  
 
PostPosted: 07 Jul 2014 23:07 
Offline

Joined: 05 Nov 2007 13:13
Posts: 3
Character(s): none at the moment
I think I'm a bit late to the party....
Updated a few things from the original code:
Clean units
Code:
hash_map<int, Unit*>::iterator iter = map.begin();
            while (iter != map.end())
            {
               if (!iter->second->inrange)
               {      
                  map.erase(iter++);
               }
               else
               {
                  ++iter;   
               }
            }


SendPacketNeedle
Code:
uint8 SendPacketNeedle[] = {0x81, 0x3D, 0x00, 0x00, 0x00, 0x02, 0x00, 0x96,
                           0x00, 0x00, 0x0F, 0x85, 0xAC, 0x00, 0x00, 0x00,
                           0xA1, 0x00, 0x00, 0x00, 0x01, 0xC1, 0xE0, 0x06,
                           0x0F, 0xB7, 0x88, 0x00, 0x00, 0x00, 0x00, 0x56};
      char SendPacketMask[] = "xx???x?x??xxxxxxx???xxxxxxx???xx";


It's not much, but I am hoping to contribute in the long run.
I am a J2EE developer by trade, c/c++ is quite a bit different for me, but this project has been fun to learn and work on.
Thanks for the great set of base code to work from!


Top
 Profile  
 
PostPosted: 09 Jul 2014 01:36 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
thanks for the contribution! Im glad i have been able to make your learning experience a fun one. I always enjoyed messing around with xenimus when i was learning new code.


Top
 Profile  
 
PostPosted: 14 Jul 2014 14:34 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
@Big_Kal

Thanks for your sendpacket mask/needle. With the update today the one i had posted and the one andy had posted no longer work. but yours did!

Everyone on xen right now is crying cus LUA is down lol. Its just because the sendpacket mask/needle andy was using needs to be changed, is my guess.


Top
 Profile  
 
PostPosted: 01 Mar 2015 03:38 
Offline

Joined: 15 Sep 2006 04:18
Posts: 45
if only this was updated


Top
 Profile  
 
PostPosted: 05 Mar 2015 16:13 
Offline
User avatar

Joined: 30 Apr 2013 00:03
Posts: 221
Bronson1365 wrote:
if only this was updated


I check on here occasionally. I stopped playing and working on the code though due to a new job where i work in PHP all day. I still get PM's occasionally asking for help from people who are using my base code and modifying it to still work. Why do you think there are still bots in the game? I love going on the main form sometimes and seeing how there are aparently always bots in the +2 gold ogers. When i created the bot originally, i set him up at the ogers and made probably about 300p if not more just from farming those guys. Go learn C/C++ and you should be able to modify the bot code (or the hook code) pretty easily.


Top
 Profile  
 
PostPosted: 20 Mar 2015 14:03 
Offline

Joined: 05 Nov 2007 11:14
Posts: 108
Some code from xenlua

Code:
void UIController::OnRecvFrom(uint8* buffer, int32 len)
{
#ifdef _DEBUG
   if (buffer[0] != 0x03)
   {
      XENLUA_LOG("S -> C: OP %02X, len %u\n", buffer[0], len);
      fprintf(m_packetlog, "S -> C OP %02X len %u\n", buffer[0], len);

      WriteToFile(m_packetlog, buffer, len);
   }
#endif

   if (buffer[0] == 0x35)
   {
      ItemResponse data = *(ItemResponse*)&buffer[2];

      std::string itemname = data.name;
      replace(itemname, " ", "%20", 0);
      char tmp[1024];

      //Test item website thingy
      sprintf(tmp, "http://xenlua.com/item_data.php?id=%u&name=%s", data.itemid, itemname.c_str());
      g_httpNetwork.RequestHTTP(tmp, false, true);
   }

   if (buffer[0] == 0x17) //merchant open
   {
      printf("Merchant open type %u\n", buffer[2]);
      LUANumber arg(buffer[2]);
      sLuaMgr.FireEvent("EVENT_MERCHANT_OPEN", 1, &arg);

      uint8 merchtype = *(uint8*)&buffer[2];

      if (merchtype >= 3)
      {
         AuctionUpdate update = *(AuctionUpdate*)&buffer[2];
         sAuctionMgr.OnAuctionUpdate(&update);
      }
   }

   if (buffer[0] == 0x42)
   {
      size_t packetpos = 2;
      QuestUIUpdate* update = (QuestUIUpdate*)&buffer[packetpos];
      packetpos += sizeof(QuestUIUpdate);

      for (auto i = 0; i < update->updatenumlines; ++i)
      {
         QuestUILineUpdate* line = (QuestUILineUpdate*)&buffer[packetpos];
         packetpos += sizeof(QuestUILineUpdate);
         LUANumber arg(update->updatestep);
         LUAString arg2(line->text);
         sLuaMgr.FireEvent("EVENT_QUEST_UI_UPDATE", 2, &arg, &arg2);
      }
   }

   if (buffer[0] == 0x04)
   {
      LocalModelData* data = (LocalModelData*)&buffer[2];

#ifdef MAPGEN
      data->charmodel = 28;
      data->shield = 0;
      data->helmet = 0;
      data->weapon = 0;

      uint16 checksum = 0;
      //redo checksum
      for (uint32 i = 0; i < 6; ++i)
         checksum += *(int8*)&buffer[2 + i];
      data->checksum = checksum;
#endif
   }

   if (buffer[0] == 0x1E) //quest status update
   {
      QuestStatusUpdate* data = (QuestStatusUpdate*)&buffer[2];

      if (data->killquestnpcid != 0)
      {
         LUAString arg(g_npcnames[data->killquestnpcid]);
         LUANumber arg2(data->killquestnpcamount);
         LUANumber arg3(data->killquestnpcreqamount);
         sLuaMgr.FireEvent("EVENT_KILL_QUEST_UPDATE", 3, &arg, &arg2, &arg3);
      }
      else
      {
         LUANil arg, arg2, arg3;
         sLuaMgr.FireEvent("EVENT_KILL_QUEST_UPDATE", 3, &arg, &arg2, &arg3);
      }
      if (sPlayer.m_requestedquests < 0) //negative = player requested ui, positive or 0 = xenlua requested ui, so when above or equal 0 we do not let the ui pop up
         sPlayer.m_requestedquests++;
      else
         buffer[0] = 0xFF;
   }

   if (buffer[0] == 0x12) //inventory update
   {
      ItemUpdate* data = (ItemUpdate*)&buffer[2];

#ifdef _DEBUG
       /*for (auto i = 0; i < 50; ++i)
      {
         data->inventory[i].id = 500 + i;
         if (sPlayer.GetForceItem() !=  -1)
            data->inventory[i].id = sPlayer.GetForceItem();
      }
 
        int16 checksum = 0;
       for (auto i = 2; i < len - 4; ++i)
           checksum += *(int8*)&buffer[i];
        data->checksum = checksum;*/
#endif

      sPlayer.m_items = *data;
      sLuaMgr.FireEvent("EVENT_ITEM_UPDATE", 0);
   }

   if (buffer[0] == 0x13) //skills update
   {
      SkillUpdate* data = (SkillUpdate*)&buffer[2];

      sPlayer.m_skills = *data;
   }

   if (buffer[0] == 0x15)
   {
      LUANumber arg(GetMSTime() - sPlayer.m_requestStatTime);
      sLuaMgr.FireEvent("EVENT_LATENCY_UPDATE", 1, &arg);
      ExpUpdate* data = (ExpUpdate*)&buffer[2];
      sLuaMgr.FireEvent("EVENT_EXPERIENCE_UPDATE", 1, &LUANumber(data->experience));
      sPlayer.m_exps = *data;
   }

   if (buffer[0] == 0x14) //stat update
   {
      StatUpdate* data = (StatUpdate*)&buffer[2];

      XENLUA_LOG("TRUELEVEL %u LEVEL %u\n", data->stats[STAT_TRUELEVEL], data->stats[STAT_LEVEL]);

      //fire some updates
      sLuaMgr.FireEvent("EVENT_LEVEL_UPDATE", 1, &LUANumber(data->stats[STAT_LEVEL]));
      sLuaMgr.FireEvent("EVENT_ALIGN_UPDATE", 1, &LUANumber(data->stats[STAT_ALIGNMENT]));
      sLuaMgr.FireEvent("EVENT_CLASS_UPDATE", 1, &LUANumber(data->stats[STAT_CLASS]));

      sPlayer.m_stats = *data;
      sPlayer.UpdateKnownSpells();
   }

   if (buffer[0] == 0x0C) //client info update
   {
#ifdef MAPGEN
      //prevent client logging out during generation of maps
      buffer[0] = 0xFF;
      return;
#endif
      uint32 mes = *(uint32*)&buffer[2];

      if (mes == 0x15)
      {
         //logged out
         m_loginstatus = 0;
         masterel->visible = false;
         sPlayer.Reset();
      }
   }

   if (buffer[0] == 0x0F) //char list
   {
      CharList* data = (CharList*)&buffer[2];
      //Cache for later so we can get the name of the character chosen (client only reports ID to server)
      sPlayer.m_charlist = *data;

      for (auto i = 0; i < 5; ++i)
      {
         // Looks like it does nothing but it is setting flags for later.
         if (sPlayer.NameIsBanned(data->characters[i].name))
            return;
      }
   }

   if (buffer[0] == 0x1F) //enter world
   {
      InitialLoginData* data = (InitialLoginData*)&buffer[2];

      uint8 serverindex_tomapid[] = { 0, 1, 0, 1 };
      uint8 serverindex_max = 3;

      sPlayer.m_charid = data->serverId;
      sPlayer.m_mapid = 0; //default if fail

      if (data->mapId <= serverindex_max)
         sPlayer.m_mapid = serverindex_tomapid[data->mapId];

      LUANumber arg(sPlayer.m_mapid);
      sLuaMgr.FireEvent("EVENT_MAP_CHANGED", 1, &arg);
      g_mapid = sPlayer.m_mapid;
      g_mapswitchms = GetMSTime();
      sPlayer.ClearPath();
      StartFPSTotalCounter();

#ifdef MAPGEN
      data->time_current = 200;
      data->time_roc = 0; //NO CHANGEY TIME PLS SIT
#endif
   }

   if (buffer[0] == 0x03) //update thing
   {
      uint32 packetpos = 2;
      UpdatePacketSelf* updateself = (UpdatePacketSelf*)&buffer[packetpos];
      UpdatePacketSelf copylast = *updateself;

#ifdef MAPGEN
      updateself->currentTime = 200;
#endif
      if (m_ghost)
      {
         updateself->positionX = m_ghostX;
         updateself->positionY = m_ghostY;
      }

      if ((updateself->flags & 0x02) == 0)
      {
         uint32 newbuf = sPlayer.m_buffs;
         if (updateself->spellflags & 0x8000)
         {
            //remove upper
            newbuf = (newbuf << 16) >> 16;
            newbuf |= uint64(updateself->spellflags) << 16;
         }
         else
         {
            //remove lower
            newbuf = (newbuf >> 16) << 16;
            newbuf |= updateself->spellflags;
         }
         if (newbuf != sPlayer.m_buffs)
            sPlayer.OnBuffChange(newbuf);
      }
      else
      {
         sPlayer.m_auraFlags = updateself->spellflags;
      }

#ifdef MAPGEN
      if (g_recordFlags != 0)
      {
         updateself->positionX = g_recordX * 20 + 10;
         updateself->positionY = g_recordY * 20 + 10;
         updateself->numInRangeSpellEffects = 0;
         updateself->numInRangeDynamicObjects = 0;
         updateself->numInRangeUnits = 0;
         updateself->spellEffect = 0;
         //updateself->currentLight = 255;
      }
#endif
      packetpos += sizeof(UpdatePacketSelf);

      //out of date, expect current time and rate of change on login, then client updates it itself
      /*if (sPlayer.m_lastupdate.currentLight != updateself->currentLight)
      {
         LUANumber arg(updateself->currentLight);
         sLuaMgr.FireEvent("EVENT_LIGHT_UPDATE", 1, &arg);
      }*/

      if (sPlayer.m_lastupdate.currentExpPct != updateself->currentExpPct)
      {
         LUANumber arg(double(updateself->currentExpPct) / 255 * 100);
         sLuaMgr.FireEvent("EVENT_EXP_PCT_CHANGED", 1, &arg);
      }

      if (sPlayer.m_lastupdate.currentTime != updateself->currentTime)
      {
         LUANumber arg(updateself->currentTime);
         sLuaMgr.FireEvent("EVENT_LIGHT_UPDATE", 1, &arg);
      }

      if (updateself->positionX != sPlayer.m_positionX || updateself->positionY != sPlayer.m_positionY)
      {
         sPlayer.m_lastPositionChange = GetMSTime();
         sPlayer.m_positionX = updateself->positionX;
         sPlayer.m_positionY = updateself->positionY;
         GetMapInterface()->PositionChanged(updateself->positionX, updateself->positionY);
      }

      if (updateself->currentHPPct != sPlayer.m_lastupdate.currentHPPct)
      {
         sPlayer.m_healthpct = double(updateself->currentHPPct) / 255 * 100;
         LUANumber arg(sPlayer.m_healthpct);
         sLuaMgr.FireEvent("EVENT_HEALTH_CHANGED", 1, &arg);
      }

      if (updateself->currentMPPct != sPlayer.m_lastupdate.currentMPPct)
      {
         sPlayer.m_manapct = double(updateself->currentMPPct) / 255 * 100;
         LUANumber arg(sPlayer.m_manapct);
         sLuaMgr.FireEvent("EVENT_MANA_CHANGED", 1, &arg);
      }

      if (updateself->flags & 4 && (sPlayer.m_lastupdate.flags & 4) == 0)
         sLuaMgr.FireEvent("EVENT_PVP_MODE_ENABLED", 0);

      if ((updateself->flags & 4) == 0 && sPlayer.m_lastupdate.flags & 4)
         sLuaMgr.FireEvent("EVENT_PVP_MODE_DISABLED", 0);

      updateself->flags &= ~4; //disable xen pvp mode ui


      std::map<uint32, ItemStruct> itemtmps;

      //lets start enuming dynamic objects
      for (int i = 0; i < updateself->numInRangeDynamicObjects; ++i)
      {
         DynamicObjectHeader* hdr = (DynamicObjectHeader*)&buffer[packetpos];

         switch (hdr->type)
         {
            case 1:
            {
               DynamicObjectType1* dynobj = (DynamicObjectType1*)&buffer[packetpos];
               packetpos += sizeof(DynamicObjectType1);

               if (sPlayer.GetForceItem() != -1)
                  dynobj->itemid = sPlayer.GetForceItem();

               //fill itemtmp
               ItemStruct tmpslot;
               uint32 key = (uint32(dynobj->header.cellx) << 16) | dynobj->header.celly;
               tmpslot.cellx = dynobj->header.cellx;
               tmpslot.celly = dynobj->header.celly;
               tmpslot.itemid[0] = dynobj->itemid;
               tmpslot.itemid[1] = 0;
               tmpslot.itemid[2] = 0;
               itemtmps.insert(std::make_pair(key, tmpslot));
            } break;
            case 2:
            {
               DynamicObjectType2* dynobj = (DynamicObjectType2*)&buffer[packetpos];
               packetpos += sizeof(DynamicObjectType2);

               if (sPlayer.GetForceItem() != -1)
               {
                  dynobj->itemid[0] = sPlayer.GetForceItem();
                  dynobj->itemid[1] = sPlayer.GetForceItem();
                  dynobj->itemid[2] = sPlayer.GetForceItem();
               }

               //fill itemtmp
               ItemStruct tmpslot;
               uint32 key = (uint32(dynobj->header.cellx) << 16) | dynobj->header.celly;
               tmpslot.cellx = dynobj->header.cellx;
               tmpslot.celly = dynobj->header.celly;
               tmpslot.itemid[0] = dynobj->itemid[0];
               tmpslot.itemid[1] = dynobj->itemid[1];
               tmpslot.itemid[2] = dynobj->itemid[2];
               itemtmps.insert(std::make_pair(key, tmpslot));
            } break;
            case 3:
            {
               DynamicObjectType3* dynobj = (DynamicObjectType3*)&buffer[packetpos];
               packetpos += sizeof(DynamicObjectType3);
            } break;
         }
      }

      //this figures out new stuff
      for (auto itr = itemtmps.begin(); itr != itemtmps.end(); ++itr)
      {
         ItemStruct* itemtmp = &itr->second;
         uint32 key = itr->first;

         auto itemitrpos = m_grounditems.find(key);
         if (itemitrpos == m_grounditems.end())
         {
            //new item
            m_grounditems.insert(std::make_pair(key, itr->second));

            //make the key a string for lua tables
            char tmp[128];
            sprintf(tmp, "0x%08X", key);

            //fire event
            LUAString arg(tmp);
            LUANumber arg2(itemtmp->cellx);
            LUANumber arg3(itemtmp->celly);
            LUANumber arg4(itemtmp->itemid[0]);
            LUANumber arg5(itemtmp->itemid[1]);
            LUANumber arg6(itemtmp->itemid[2]);
            LUANumber arg7(1);
            sLuaMgr.FireEvent("EVENT_GROUND_ITEM_CREATE", 7, &arg, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7);
         }
         else
         {
            if (itemitrpos->second.itemid[0] != itemtmp->itemid[0] ||
                  itemitrpos->second.itemid[1] != itemtmp->itemid[1] ||
                  itemitrpos->second.itemid[2] != itemtmp->itemid[2])
            {
               //Fire a delete and create, hacky, but i cbf to implement update
               //make the key a string for lua tables
               char tmp[128];
               sprintf(tmp, "0x%08X", key);
               LUAString arg(tmp);
               LUANumber arg2(itemtmp->cellx);
               LUANumber arg3(itemtmp->celly);
               LUANumber arg4(itemtmp->itemid[0]);
               LUANumber arg5(itemtmp->itemid[1]);
               LUANumber arg6(itemtmp->itemid[2]);
               LUANumber arg7(0);
               sLuaMgr.FireEvent("EVENT_GROUND_ITEM_DESTROY", 1, &arg);
               sLuaMgr.FireEvent("EVENT_GROUND_ITEM_CREATE", 7, &arg, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7);
            }

            itemitrpos->second = *itemtmp;
         }
      }
      for (auto itr = m_grounditems.begin(); itr != m_grounditems.end();)
      {
         auto itr2 = itr++;
         uint32 key = itr2->first;
         if (itemtmps.find(key) == itemtmps.end())
         {
            char tmp[128];
            sprintf(tmp, "0x%08X", key);
            LUAString arg(tmp);
            sLuaMgr.FireEvent("EVENT_GROUND_ITEM_DESTROY", 1, &arg);
            m_grounditems.erase(itr2);
         }
      }

      //looking at spells
      for (auto i = 0; i < updateself->numInRangeSpellEffects; ++i)
      {
         UpdatePacketSpell* spell = (UpdatePacketSpell*)&buffer[packetpos];
         UpdatePacketSpellTarget* targets = NULL;

         packetpos += sizeof(*spell);
         if (spell->visual >= 245) // from disassembly
         {
            targets = (UpdatePacketSpellTarget*)&buffer[packetpos];
            packetpos += sizeof(*targets);
         }
      }

      sPlayer.MarkUnitsOOR();

      for (auto i = 0; i < updateself->numInRangeUnits; ++i)
      {
         UpdatePacketUnit* unit = (UpdatePacketUnit*)&buffer[packetpos];
         Unit* uptr = sPlayer.GetUnit(unit->id & 0x7FFF, true);
         ASSERT(uptr != NULL);

         uptr->MarkInRange();

         packetpos += sizeof(UpdatePacketUnit);

         if (unit->id & 0x8000)
            continue;
         uint8 updateflag = *(uint8*)&buffer[packetpos];
         packetpos += 1;

         if (updateflag & 0x01)
         {
            UpdatePacketUnitMovement* data = (UpdatePacketUnitMovement*)&buffer[packetpos];
            uptr->movement = *data;
            packetpos += sizeof(*data);
         }
         if (updateflag & 0x02)
         {
            UpdatePacketUnitAuras* data = (UpdatePacketUnitAuras*)&buffer[packetpos];
            uptr->auras = *data;
            packetpos += sizeof(*data);
         }
         if (updateflag & 0x04)
         {
            UpdatePacketUnitModels* data = (UpdatePacketUnitModels*)&buffer[packetpos];
            uptr->models = *data;
            packetpos += sizeof(*data);
         }
         if (updateflag & 0x08)
         {
            UpdatePacketUnitAnim* data = (UpdatePacketUnitAnim*)&buffer[packetpos];
            uptr->anim = *data;
            packetpos += sizeof(*data);
         }
         if (updateflag & 0x10)
         {
            UpdatePacketUnitSpellEffect* data = (UpdatePacketUnitSpellEffect*)&buffer[packetpos];
            uptr->spelleffect = *data;
            packetpos += sizeof(*data);
         }
         if (updateflag & 0x20)
         {
            UpdatePacketUnitChat* data = (UpdatePacketUnitChat*)&buffer[packetpos];
            uptr->chat = *data;
            packetpos += sizeof(*data) + data->stringsize;
            char* str = (char*)alloca(data->stringsize);
            memcpy(str, &buffer[packetpos], data->stringsize);
         }
      }

      sPlayer.ClearOutOfRangeUnits();

      sPlayer.m_lastupdate = copylast;
   }
}


Code:
void UIController::OnSendTo(uint8* buffer, int32 len)
{
   static uint16 s_mytargetid = 0;
#ifdef _DEBUG
   XENLUA_LOG("C -> S: OP %02X, len %u\n", buffer[0], len);
   fprintf(m_packetlog, "C -> S OP %02X len %u\n", buffer[0], len);

   WriteToFile(m_packetlog, buffer, len);
#endif
   if (buffer[0] == 0x34)
   {
      ItemRequest* req = (ItemRequest*)&buffer[2];
   }

   if (buffer[0] == 0x06) //open storage?
   {
      VendorAction data = *(VendorAction*)&buffer[2];
      //printf("VA action %u slot %u id %u\n", data.action, data.slot, data.id);
   }

   if (buffer[0] == 0x0A) //talk
   {
      uint32 uid;
      std::string chatmsg;

      uid = *(uint32*)&buffer[2];
      chatmsg = (char*)&buffer[6];

      if (chatmsg.size() > 0 && chatmsg[0] == '-')
         sPlayer.HandleChatCommand(chatmsg);
   }

   if (buffer[0] == 0x01) // movement
   {
      ForceFastClickOff();

      MoveRequest* data = (MoveRequest*)&buffer[2];

      if (m_ghost && data->action == 0x4D) //move request while ghost enabled
      {
         //we can't move
         m_ghostX = data->x;
         m_ghostY = data->y;
         data->x = sPlayer.m_lastupdate.positionX;
         data->y = sPlayer.m_lastupdate.positionY;
      }

      uint8 checksum = 0;
      checksum += *(uint8*)&data->charid;
      checksum += *(uint8*)&data->x;
      checksum += *(uint8*)&data->y;
      checksum += data->action;
      data->checksum = checksum;
   }


   if (buffer[0] == 0x08) //cast spell
   {
      CastSpell* data = (CastSpell*)&buffer[2];

      if (data->targettype == 0x50) //cast spell on unit
      {
         LUANumber arg(data->spellid); //targetid
         LUANumber arg2(data->x);
         sLuaMgr.FireEvent("EVENT_CAST_SPELL_TARGET", 2, &arg, &arg2);
      }

      LUANumber arg(data->spellid);
      LUANumber arg2(data->targettype);
      LUANumber arg3(data->x);
      LUANumber arg4(data->y);
      sLuaMgr.FireEvent("EVENT_CAST_SPELL", 4, &arg, &arg2, &arg3, &arg4);

      if (data->targettype == 0x4C) //target ground
      {
#ifdef DEBUG
         static FILE* file = fopen("HUNTINGSPOT.txt", "w");
         fprintf(file, "\tHuntingBotAddPoint(%u, %u);\n", data->x / 20, data->y / 20);

         bool raycast = sPlayer.Raycast(data->x, data->y, PASS_FLAG_TELEPORT);

         XENLUA_LOG("raycast: %s\n", raycast ? "true" : "false");

         //sPlayer.CreatePathReal(data->x, data->y);
#endif
      }


      ForceFastClickOff();

      if (m_autoaimenabled)
      {
         auto itr = m_autoaim.find(data->spellid);
         if (itr != m_autoaim.end())
         {
            if (data->targettype == 0x50)
            {
               //update
               itr->second = data->x;
            }
            else
            {
               data->targettype = 0x50;
               data->x = itr->second;
            }
         }
         else if (data->targettype == 0x50)
            m_autoaim.insert(std::make_pair(data->spellid, data->x));
      }
   }

   if (buffer[0] == 0x10) //login player to world
   {
      uint32 charid = *(uint32*)&buffer[2];
      //XENLUA_LOG("Logging into %u\n", charid);

      bool namefound = false;
      std::string name;

      sPlayer.m_charid = charid;

      //find the name from char list cache
      for (auto i = 0; i < 5; ++i)
      {
         if (sPlayer.m_charlist.characters[i].charid == charid)
         {
            namefound = true;
            name = sPlayer.m_charlist.characters[i].name;
            break;
         }
      }

      if (namefound)
      {
         sPlayer.SetName(name.c_str());
         sPlayer.CheckIsBanned();
         if (sPlayer.IsBanned())
            return;

         char configfile[1024];
         sprintf(configfile, "xenlua/config/%s.cfg", name.c_str());
         sConfigMgr.LoadConfig(configfile, name.c_str());
         LUANumber arg(charid);
         LUAString arg2(name.c_str());
         sLuaMgr.FireEvent("EVENT_CHARACTER_ENTER_WORLD", 2, &arg, &arg2);

         LoadCameraVariables();


         masterel->visible = true;
         m_loginstatus = 1;
      }

      sPlayer.OnLogin();
   }

   if (buffer[0] == 0x25) //request status
   {
      if (buffer[6] == 4) //requesting quests
         sPlayer.m_requestedquests--;
   }
}


Top
 Profile  
 
PostPosted: 22 Mar 2015 03:28 
Offline

Joined: 15 Sep 2006 04:18
Posts: 45
u got a repo with this stuff andy?


Top
 Profile  
 
PostPosted: 04 Apr 2015 08:52 
Offline

Joined: 15 Sep 2006 04:18
Posts: 45
shame to see the only dude who picked up the old project is now selling the bot, 200$ for other peoples work

zzz


Top
 Profile  
 
PostPosted: 19 Apr 2015 03:17 
Offline

Joined: 15 Sep 2006 04:18
Posts: 45
Clery your a pest


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

All times are UTC - 5 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 1 guest


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:  
Powered by phpBB® Forum Software © phpBB Group