There are some kinds of bots:
1. Spawnbot
2. ug/og Movebot
3. Playerlike bot
4. splash/healbot
The spawn bot is probably the fastest when it comes to killing but very limited in spots and classes. Very easy to write. Letting the bot move, makes it harder but still easy. Playerlike is hard
Well, first you need a working Send and Recv. Being able to sniff Send packets makes it easier in some points, but isn't needed.
Send:
Code:
__declspec(naked) int __cdecl SendPacket (BYTE Header , LPCSTR Format , ... ){ __asm{ push ebp mov ebp, esp sub esp, 18h } __asm{JMP SendBack}; }
Code:
int (__stdcall *PacketRecv)(SOCKET Socket, char *Buffer, int Length, int Flags); void MyPacketRecv(SOCKET Socket, char *Buffer, int Length, int Flags) { switch(Buffer[2]) { } return PacketRecv(Socket, Buffer, Length, Flags); } void InitDetours() { PacketRecv = (int (__stdcall *)(SOCKET, char *, int, int))DetourFunction((PBYTE)recv, (PBYTE)MyPacketRecv); }
There are 2 ways how to write the bot-part of your source. Either in a thread or directly into your recv detour. Putting everything into a thread would probably be the better solution. You can't use Sleeps when writing a recv based bot(well, you can but I wouldn't recommend it )
Spawnbot
Let's start with the spawn bot first. There are basicly 2 recv packets you need to pay attention to when doing this 0x3E and 0x3F. 0x3E packet is sent from the server, when something attacks something. Doesn't matter if it's a player or a monster. 0x3F is for skills. For all skills, not only attacks.
Code:
case 0x3e: DWORD target = *(DWORD*)&Buffer[7]; DWORD attacker = *(DWORD*)&Buffer[3];
Now you compare the target with your player ID. Obtained with the Playerappear packet 0x32. The first one you get is normaly yours.
Code:
case 0x32: PlayerID = *(DWORD*)&Buffer[3];
Code:
if(PlayerID == 0)
Whenever a 0x3E/3F packet with your ID appears, you send a LA-Skillpacket. Don't forget, that this kind of bot only works as IC.
Code:
SendPacket(0x0D,"bbd",18,1,attacker);
Checking for misses:
Code:
case 0x3f: BYTE hitornot = *(BYTE*)&Buffer[18]; // 0 = miss WORD damage = *(WORD*)&Buffer[14]; BYTE skill = *(BYTE*)&Buffer[3]; // skillid
Since LA can't kill, you need another skill/normal attack to finish the mob. Sending them too fast -> 0 damage. This is the function I used to check if I can use a skill or not.
Code:
int Skillchoose() { if(timerNormalArrow < GetTickCount()-400) { timerNormalArrow = GetTickCount(); return 0; } else if(timerPassive < GetTickCount()-400) { timerPassive = GetTickCount(); return 4; } else if(timerFlamy < GetTickCount()-400) { timerFlamy = GetTickCount(); return 6; } else if(timerBlow < GetTickCount()-400) { timerBlow = GetTickCount(); return 14; } else if(timerHeart < GetTickCount()-2000) { timerHeart = GetTickCount(); return 9; } else return 3; }
Behead and picking left, both easy.
Behead:
Code:
case 0x3d: DWORD beheadID = *(DWORD*)&Buffer[3]; SendPacket(0x0D,"bbd",1,1,beheadID);
Pick:
Code:
case 0x36: DWORD dwIID = *(DWORD*)&Buffer[5]; DWORD iX = *(DWORD*)&Buffer[5+4]; DWORD iY = *(DWORD*)&Buffer[5+4+4]; SendPacket(0x1D,"ddd",dwIID,iX/32,iY/32);
While botting I got kinda pissed off with all that useless noob stuff you find.
Code:
int blacklist[] = {331,330,318,327,328,329,316,282,290,298,306,314,276,284,292,300,308,1495/*monsterarm*/}; case 0x36://Item Drop { bool abbruch = false; WORD Index = *(WORD*)&Buffer[3]; for(int i = 0;i<sizeof(blacklist)/sizeof(blacklist[0]);i++) { if(Index == blacklist[i]) { abbruch = true; break; } } if(abbruch == false) { //pick it
Another thing I would suggest you, is destroying nearly every item that gives revision stones. Things you should keep are g53+ dagger and g59+ waepons, g55+ armor and stuff you need for further bots. Destroying stuff is less money than selling it to npc/player but it takes about 2hours to get a full inventory in d2. Ofcoz you could autosell it to npc(you need to be near the npc to make it work),send it to other accounts etc but destroying is the easiest thing
The packetheader you need to take a look at is 0x07, it appears every time you get something into ur inventory, no matter where it comes from. Maybe it also does something else, no idea
You can either instant destroy them or store them to destroy after some time. If you kill mobs at spawn and move to drops, you should store them otherwise just destroy.
Code:
WORD itemtype = *(WORD*)&Buffer[3]; DWORD itemid = *(DWORD*)&Buffer[5]; SendPacket(0x51,"bd",0,itemid);
It is a huge speed increase to kill mobs when they spawn. The mob appear packet is 0x33.
Code:
DWORD mobID = *(DWORD*)&Buffer[5]; WORD mobIndex = *(WORD*)&Buffer[3];
After writing(and testing) your move function, you need to do a few additions. At 0x36(itemdrop) you have to check, whether the item is in pick range or not when dropping. A range of 65 or lower is fine, otherwise save the item into an array. I used to pick all items, once I reached a specified limit. Move to first item in array -> pick it -> check if any other item is in range, if yes pick it -> move to next not picked item. Here are my functions, will help you to understand it
Code:
void Pick() { for(int i = 0; i<itemcount;i++) { //printf("Searching item...\n"); if(Items[i].dwIID != 0) { Move(Items[i].iX,Items[i].iY); SendPacket(0x1D,"ddd",Items[i].dwIID,Items[i].iX/32,Items[i].iY/32); Items[i].dwIID = 0; PickIt(); } } Move(startx,starty); } void PickIt() { //printf("Pick all...\n"); for(int i = 0;i<itemcount;i++) { if(Items[i].dwIID != 0) { int xrange = ownx - Items[i].iX; int yrange = owny - Items[i].iY; if(sqrt((float)((xrange*xrange)+(yrange*yrange)))<=65) { //printf("Found item to pick \n"); SendPacket(0x1D,"ddd",Items[i].dwIID,Items[i].iX/32,Items[i].iY/32); Items[i].dwIID = 0; } } } }
There are some improvements that can be done. This is just a very basic version.
Here is a little list(I will add some of those things from time to time):
-Kill mobs at appear(you need to move to drops for this, do not do this nonstop, move like once every 30sec, depends on serverlag, gear, mobs and your computer )(added 25.07.2011)
-Do not pick everything, noone needs crap talis(added 24.07.2011)
-Destroy rings,belts, low grade waepons/armor for revision stones(added 24.07.2011)
-Auto party leave when forced
-Protection against reporters
Splash/Healbot
Nothing is more annoying than spawnsplash partys. So why shouldn't we write a bot for that?
Source:
Code:
void SplashBot(void*) { while(true) { if(heal == 1) { //SkillAni 28 SendPacket(0x28,"b",28); Sleep(1200); //SkillExecute 28 SendPacket(0x0D,"b",28); } else if(splash == 1) { //SkillAni 24 SendPacket(0x28,"b",24); Sleep(900); //SkillExecute 24 SendPacket(0x0D,"b",24); } Sleep(600); Sleep(200); // realistic reason } }
Just run the thread, add an autobehead. There are a few things you have to care about:
-just behead when you really need mana
-take care mob is in range!
-don't move while splashing or ppl will notice, best is to stand in other ppl
Either you do range check to the dead mob or you just behead mobs which were attacked by you or attacked you. Most of the time they should be in range. Best would be to combine the ways.
To check your mana, use the State-change packet(0x45). Buffer[3] is the thing which needs to be checked, if it's 0x08 your mana changed.
Code:
WORD curmp = *(WORD*)&Buffer[4];
Credits: The usual people