Valhalla Legends Forums Archive | General Programming | D2 Stats

AuthorMessageTime
iago
I'm sure that more than one bot developer have worked on Diablo II statstrings, and, because I'm like that, I wrote a simple plugin to test things out. It requires my Buffer class, which can be found here:
http://www.backstab.ca/~rbowes/Buffer.rar

And the code (which you will have to fiddle with, but meh?) is here:
[code]#include <windows.h>
#include <strstream>
#include "Buffer.h"

// The following are dwId's for 0x0F packets:
const DWORD ID_USERINCHANNEL = 0x01;
const DWORD ID_USERJOINCHANNEL = 0x02;
const DWORD ID_USERLEAVECHANNEL = 0x03;
const DWORD ID_WHISPERFROM = 0x04;
const DWORD ID_INCOMING_CHAT = 0x05;
const DWORD ID_ERROR = 0x06;
const DWORD ID_CHANNELJOIN = 0x07;
const DWORD ID_CHANGEFLAGS = 0x09;
const DWORD ID_WHISPERTO = 0x0A;
const DWORD ID_INFORMATION = 0x12;
const DWORD ID_CHANNELFULL = 0x13;
const DWORD ID_IGNOREON = 0x15;
const DWORD ID_IGNOREOFF = 0x16;
const DWORD ID_EMOTE = 0x17;

void DoStuffs(BYTE EventID, string Name, string Statstring)
{
// FF 0F 3A 00 12 00 00 00 10 00 00 00 4E 00 00 00 ..:.........N...
// 00 00 00 00 0D F0 AD BA 0D F0 AD BA 46 75 78 44 ............FuxD
// 75 78 00 57 65 6C 63 6F 6D 65 20 74 6F 20 42 61 ux.Welcome to Ba
// 74 74 6C 65 2E 6E 65 74 21 00 ttle.net!.

   Buffer test;
   DWORD Addr = 0x6ff02040;
   DWORD Len = (WORD)(30 + Name.length() + Statstring.length());

   test << (BYTE) 0xff;
   test << (BYTE) 0x0f;
   test << (WORD) Len;

   test << (DWORD) EventID;
   test << (DWORD) 0x10;
   test << (DWORD) 0x4e;
   test << (DWORD) 0x00;
   test << (DWORD) 0xbaadf00d;
   test << (DWORD) 0xbaadf00d;
   test << Name << (BYTE) 0;
   test << Statstring << (BYTE) 0;

   char *str = (char*)test.c_str();
   __asm
   {
      mov ecx, str
      mov edx, Len
      call Addr
   }
}
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD dwReason,
LPVOID lpReserved
                )
{
   switch(dwReason)
   {
   case DLL_PROCESS_ATTACH:
      {
         // Clear out the channel
         DWORD UCode;
         UCode = GetTickCount();
         DoStuffs(ID_CHANNELJOIN, "FuxDux", (char*)&UCode);
         Buffer StatString;
         
         for(int i = 1; i <= 0xFF; i++)
         {
            strstream Name;
            StatString.ClearBuffer();
            Name << "iago-vL#";
            Name << i;
            Name << "*iago.";
            Name << i;
            Name << '\0';
      
            StatString << "PX2D";               // Product
            StatString << "Moo,";               // Realm
            StatString << "iagovL,";            // Character name, again, seems to do nothing
            StatString << (BYTE) 0x84; // 0x84 = nothing?
            StatString << (BYTE) 0x80; // 0x80 = nothing?
            StatString << (BYTE) 40; // 0x01 = Helmet
            StatString << (BYTE) 3; // Chest
            StatString << (BYTE) 3; // Legs
            StatString << (BYTE) 3; // Right Arm
            StatString << (BYTE) 3; // left arm
            StatString << (BYTE) 1; // weapon
            StatString << (BYTE) 1; // bow?
            StatString << (BYTE) 1; // shield
            StatString << (BYTE) 1; // right shoulder
            StatString << (BYTE) 1; // left shoulder
            StatString << (BYTE) i; // nothing

            StatString << (BYTE) 4; // Race - See notebook :)
            StatString << (BYTE) 1; // helmet color
            StatString << (BYTE) 1; // chest color
            StatString << (BYTE) 1; // leg color
            StatString << (BYTE) 1; // r arm color
            StatString << (BYTE) 1; // l arm color
            StatString << (BYTE) 1; // weapon color
            StatString << (BYTE) 1; // bow color
            StatString << (BYTE) 1; // shield color
            StatString << (BYTE) 166; // right shoulder color
            StatString << (BYTE) 169; // left shoulder color
            StatString << (BYTE) i;

            StatString << (BYTE) 0x63; // Level
            StatString << (BYTE) (0xa0); // 0xa0 = bit 0 = ?, bit 1 = ?, bit 2 = Hardcore, bit 3 = Dead
            StatString << (BYTE) 0x80; // 0x80 = Rank - see notebook :)
                                 
            StatString << (BYTE) 0xff; // ?
            StatString << (BYTE) 0xff; // ?
            StatString << (BYTE) 0xff; // ?
            StatString << (BYTE) 0x80; // Nothing?
            StatString << (BYTE) 0x80; // Nothing?
            StatString << (BYTE) 0x80; // Nothing?

            StatString << (BYTE) 0; // Null-terminator
            DoStuffs(ID_USERJOINCHANNEL, (char*) Name.str(), (char*)StatString.c_str());//(char*) StatString.c_str());
         }
      }
   }

return TRUE;
}
[/code]

I commented most of the stuff I know, but I didn't list specific weapons/armour/etc because I was writing it in my notebook, and I'm not too confident.

If you don't know how to use this (you need to attach this to diablo 2's memory), then don't.

This works with a diablo II loader that I use (because I don't like carrying around a cd-case with my laptop) called game_crk.exe. I don't know if the address is the same, and if it's not you can tell me the real address for that __fastcall function.

That's all I can think of saying, have fun! :-)
July 19, 2003, 2:52 PM
iago
Ok, I'll transcribe a couple:
Races:
1. Amazon
2. Sorceress
3. Necromancer
4. Paladin
5. Barbarian
6. Druid
7. Assassin
(the rest of these will never show up, except maybe on a hacked server)
8. Unknown (guy in brown cloak)
9/10. Unknown (guy in grey cloak)
11/12/13. Various diablo 1 guys, I think
14. Starcraft Marine
15. Medic
16. Warcraft 2 Grunt
17. Blizzard Rep
18. Moderator
19. Sysop
20. Referee
21. Chat
22. Speaker
All the rest - Uknown (guy in brown cloak)


Helmets (I'm not guarenteeing these):
1, 2, 3 - no helm
4, 57 - cap
5, 58 - skullcap
6, 59 - helm
7, 60 - full helm
8, 61 - greathelm
9, 62 - I don't know
10, 63 - mask
40 - bonehelm
86 - 91 - headless
I might have mixed these ones up, but only barbarians have them:
89 - fanged helm
90 - warhelm
91 - winged helm
All the rest - hatless
(I forgot to look for druid hats, but I'd guess they are 86, 87, and 88 since those graphics are missing)


Weapons (Again, I may have mixed these up. And I know I'm missing sorceress-only items):
4 - hatchet
5 - Axe
6 - doubleaxe
7 - large axe
8 - great axe
9/10/11/12 - various wands, not sure which is which
13 - mace
14 - hammer
15 - flail
16 - maul
17 - short sword
18 - schimitar
19 - broadsword
20 - crystal sword
21/22/23/24 - swords
25/26/27/28/29 - I don't know
30 - spear
31 - trident
32 - spetum
33 - pike
34 - glaive
35 - sickle
36 - poleaxe
37/38/39 - various staffs
40 - warstaff
49/50/56 - I don't know
121/122/123/124 - clubs
125 - 129 - coloured orbs



Shields (I know I'm missing paladin specific items)
79 - small shield
80 - buckler
81 - kite shield
82 - towershield
84 - bone shield
85 - spiked shield
July 19, 2003, 3:13 PM
Yoni
[quote author=iago link=board=5;threadid=1965;start=0#msg15294 date=1058627598]
86 - 91 - headless
[/quote]
IIRC, "headless" means the cap is class-specific, and you've specified it for the wrong class. Try it on other character classes, one of them shouldn't be headless.
July 19, 2003, 9:20 PM
iago
You're right, I have written down in my notebook "probably druid" but I forgot to fix that in my post :)
July 20, 2003, 1:04 AM
iago
[quote author=iago link=board=5;threadid=1965;start=0#msg15294 date=1058627598]
125 - 129 - coloured orbs
[/quote]

Those are potions :)
July 20, 2003, 3:47 AM
UserLoser
Cool, i was just telling someone the other day that i wanted to figure out gear/colors =) +1
July 20, 2003, 5:52 AM
iago
Go figure out the ones that I don't know :)
July 20, 2003, 7:12 PM
UserLoser
What's the number after (BYTE) mean? - I'm trying to get the values out of the statstrings in VB, and I don't know too much C++, nor am I well at converting C++ to VB.
July 20, 2003, 9:44 PM
K
(BYTE)0x01 casts the value to a byte; ie: (BYTE)1 = 0x01; (WORD)1 = 0x0100; (DWORD)1 = 0x01000000 etc.
July 21, 2003, 12:37 AM
iago
A byte is the same as a char, that helps.

Technically, an unsigned char, but who's counting? :-)
July 21, 2003, 2:19 AM
Yoni
[quote author=K link=board=5;threadid=1965;start=0#msg15431 date=1058747852]
(BYTE)0x01 casts the value to a byte; ie: (BYTE)1 = 0x01; (WORD)1 = 0x0100; (DWORD)1 = 0x01000000 etc.
[/quote]
Close enough

(WORD)1 = 0x0001, and (DWORD)1 = 0x00000001, but in the packet data, they are "01 00" and "01 00 00 00" respectively.
July 21, 2003, 2:20 AM
Camel
I once had a C teacher who tried to convince me to not include preceeding zeroes in hex as it "is misleading." Naturally, he lost that argument.
July 21, 2003, 2:32 AM

Search