diabloIII

来源:互联网 发布:网络管理是什么意思 编辑:程序博客网 时间:2024/04/26 01:22
public readonly int ObjectManager_ofs_storage = 0x7CC;public readonly int ObjectManagerStorage_ofs__local = 0x1B8;public readonly int ObjectManagerStorage_ofs__data = 0x0A8;public readonly int ObjectManagerStorage_ofs__attrib_groups = 0x0C8;public readonly int player_data_size = 0x8598;public readonly int player_ofs__area = 0x78F8;public readonly int player_ofs__seed = 0x7448;public readonly int player_ofs__name = 0x7450;public readonly int player_ofs__class = 0x78FC;public readonly int player_ofs__actor_id = 0x8;public readonly int acd_ofs__id = 0x000;public readonly int acd_ofs__gb_type = 0x0B0;public readonly int acd_ofs__gb_id = 0x0B4;public readonly int acd_ofs__attrib_group_id = 0x120;public readonly int acd_ofs__sno = 0x090;public readonly int acd_ofs__item_location = 0x114;public readonly int acd_ofs__item_x = 0x118;public readonly int acd_ofs__item_y = 0x11C;public readonly int acd_ofs__pos_x = 0x0D0;public readonly int acd_ofs__pos_y = 0x0D4;public readonly int acd_ofs__pos_z = 0x0D8;public readonly int acd_ofs__monster_type = 0x0B8;public readonly int attrib_link_ofs__next = 0x000;public readonly int attrib_link_ofs__id = 0x004;public readonly int attrib_link_ofs__value = 0x008;public readonly int AttribGroupsContainer_ofs__FastAttribGroups = 0x070;


Reading Player's Location:

int ObjectManagerPtr = MR.ReadInt(ObjectManagerAddress);int ObjectManagerStoragePtr = ObjectManagerPtr + ObjectManager_ofs_storage;int ObjectManagerStorageDataPtr = MR.ReadInt(ObjectManagerStoragePtr + ObjectManagerStorage_ofs__data);int ObjectManagerStorageLocalPtr = MR.ReadInt(ObjectManagerStoragePtr + ObjectManagerStorage_ofs__local);int MyPlayerIndex = MR.ReadInt(ObjectManagerStorageLocalPtr);for (int i = 0; i < 4; i++){       uint seed = MR.ReadUInt(ObjectManagerStorageDataPtr + i * player_data_size + 0x58 + player_ofs__seed);       if (seed == 0) continue;       string CharacterName = MR.ReadString(ObjectManagerStorageDataPtr + i * player_data_size + 0x58 + player_ofs__name, 12 + 1, Encoding.ASCII, true);       uint class_idx = MR.ReadUInt(ObjectManagerStorageDataPtr + i * player_data_size + 0x58 + player_ofs__class); // 0=DH, 1=barb, 2=wiz, 3=wd, 4=monk       uint levelarea_id = MR.ReadUInt(ObjectManagerStorageDataPtr + i * player_data_size + 0x58 + player_ofs__area);       if (MyPlayerIndex == i)       {              // tadamm: this is our player's levelarea_id and other stuff       }       uint ActorID = MR.ReadUInt(ObjectManagerStorageDataPtr + i * player_data_size + 0x58 + player_ofs__actor_id);       if ((ActorID == 0) || (ActorID == uint.MaxValue))       {              // our player's actor is always valid, but party members too far from us will "disappear"       }}






Reading an UI Component:
What you need:
- the UI component's path ("Name", don't ask me for it)


Note:
- figuring out the idiot internal coodinate -> screen coordinate conversion took me 4 days, and it is not working with letterbox, but pixel-perfect on every resolution and screen ratios


ObjectManagerPtr = MR.ReadInt(ObjectManagerAddress);ObjectManagerStoragePtr = ObjectManagerPtr + ObjectManager_ofs_storage;ui_mgr_ptr = MR.ReadInt(ObjectManagerStoragePtr + 0x1A8);ui_component_map_hashtable = MR.ReadInt(ui_mgr_ptr + 0x000);ui_component_table_start = MR.ReadInt(ui_component_map_hashtable + 0x008);ui_component_table_size = MR.ReadInt(ui_component_map_hashtable + 0x010);ui_component_table = new int[ui_component_table_size];ui_component_table_mask = MR.ReadInt(ui_component_map_hashtable + 0x040);MR.ReadMem(ui_component_table_start, ui_component_table, ui_component_table_size * 4); // blocked memory read




1) Dumping all components
for (int i = 0; i < ui_component_table_size; i++){int link = MR.ReadInt(ui_component_table_start + i * 4);while (link != 0){   int ui_component_ptr = MR.ReadInt(link + 0x210);   bool visible = MR.ReadInt(ui_component_ptr + 0x028) == 1;   ulong hash = MR.ReadULong(ui_component_ptr + 0x030 + 0x00);   string name = MR.ReadString(ui_component_ptr + 0x030 + 0x08, 256, Encoding.ASCII, true);   float X = MR.ReadFloat(ui_component_ptr + 0x508);   float Y = MR.ReadFloat(ui_component_ptr + 0x50C);   float R = MR.ReadFloat(ui_component_ptr + 0x510);   float B = MR.ReadFloat(ui_component_ptr + 0x514);   int TextPtr = MR.ReadInt(ui_component_ptr + 0xAE0);   string Text = null;   if (TextPtr != 0) Text = MR.ReadString(TextPtr, 256, Encoding.ASCII, true); // true means trimming at \0   if (visible)   {float fourthreewidth = (float)D3ClientWindowSize.Height / 3.0f * 4.0f;float mb_ratio = 600.0f / D3ClientWindowSize.Height;float mb = (D3ClientWindowSize.Width - fourthreewidth) * mb_ratio;float SX = (X + mb) / (1200.0f / D3ClientWindowSize.Height);float SR = (R + mb) / (1200.0f / D3ClientWindowSize.Height);float SY = Y * (D3ClientWindowSize.Height / 1200.0f);float SB = (B - 1) * (D3ClientWindowSize.Height / 1200.0f);Rect.X = Convert.ToInt32(SX);Rect.Y = Convert.ToInt32(SY);Rect.Width = Convert.ToInt32(SR - SX - 1);Rect.Height = Convert.ToInt32(SB - SY - 1);   }   // do something with the variables here...   link = MR.ReadInt(link + 0x000);}}




2. Reading an UI component with a specific path (Name)
Hash = FNVHash(Name.ToLower());Bucket = (int)(((Hash >> 32) ^ (uint)Hash) & (uint)ui_component_table_mask);pair_address = ui_component_table[Bucket];msUIPair pair = new msUIPair();int n = 0;while ((pair_address != 0) && (n < 10)){MR.ReadMem(pair_address, pair, 16);if (pair.UIReference_Hash == this.Hash){int ui_component_ptr = MR.ReadInt(pair_address + msUIPair.ValueOfs); // pair.value// found it, use this ptr to read and process UI component!return;}pair_address = pair.NextPair;n++;}The used structures:   [StructLayout(LayoutKind.Sequential, Pack = 1)]    public sealed class msUIPair    {        public int NextPair;    // 0x000:4        public int UIReference_Unknown; // 0x004:4        public ulong UIReference_Hash;  // 0x008:8        // char[200] UIReference_Path...  // 0x010:200        public static int ValueOfs = 0x210;    }//Hash generator:private ulong FNVHash(string s){       ulong FNVHash = 0xCBF29CE484222325;       for (int i = 0; i < s.Length; i++)       {           FNVHash = FNVHash ^ (byte)s[i];           FNVHash = FNVHash * 0x100000001B3;           FNVHash = FNVHash & 0xFFFFFFFFFFFFFFFF;       }       return FNVHash;     }



Reading Attributes


What you need:
- the attribute's ID and mask


The basics


You can find attributes by their Index (the number), and their mask.
Most attributes has no mask (no mask = 0xFFFFF).
Examples:
- Resistance_All has no mask, so it's "FullID" = 0xFFFFF << 12 | 99
- "lightning resist" is contained in "Resistance" attribute with mask 0x2, so it's FullID = 0x2 << 12 | 96


public readonly int ObjectManagerStorage_ofs__acds = 0xD4;ObjectManagerPtr = MR.ReadInt(ObjectManagerAddress);ObjectManagerStoragePtr = ObjectManagerPtr + ObjectManager_ofs_storage;addr_acds = MR.ReadInt(ObjectManagerStoragePtr + ObjectManagerStorage_ofs__acds);addr_attrib_groups = MR.ReadInt(ObjectManagerStoragePtr + ObjectManagerStorage_ofs__attrib_groups);addr_acds_container = MR.ReadInt(addr_acds);acd_data_list_ofs = MR.ReadInt(addr_acds_container + 0x148); //container.List, double pointeracd_data_start_ofs = MR.ReadInt(acd_data_list_ofs); //container.Listacd_sizeof = MR.ReadInt(addr_acds_container + 0x104); //container.SizeOfacd_bits = MR.ReadInt(addr_acds_container + 0x18C); //container.Bitsacd_count_ofs = addr_acds_container + 0x108; //container.Countaddr_attrib_groups_container = MR.ReadInt(addr_attrib_groups + AttribGroupsContainer_ofs__FastAttribGroups); // AttribGroupsContainer.FastAttribGroupsattrib_data_list_ofs = MR.ReadInt(addr_attrib_groups_container + 0x148); //container.List, double pointerattrib_sizeof = MR.ReadInt(addr_attrib_groups_container + 0x104); //container.SizeOfattrib_bits = MR.ReadInt(addr_attrib_groups_container + 0x18C); //container.Bits//Enumerating All Actors and their AttributesACDCount = MR.ReadInt(acd_count_ofs);for (int i = 0; i <= ACDCount; i++){                int acd_address = acd_data_start_ofs + i * acd_sizeof;                uint AcdID = MR.ReadUInt(acd_address + acd_ofs__id);                if (AcdID == uint.MaxValue) continue;                int gb_type = MR.ReadInt(acd_address + acd_ofs__gb_type); // gamebalance type                uint gb_id = MR.ReadUInt(acd_address + acd_ofs__gb_id); // gamebalance id                // gb_type = 2 means this is an item                int group_id = MR.ReadInt(acd_address + acd_ofs__attrib_group_id);                int full_id = group_id & 0xFFFF;                int a = full_id >> attrib_bits;                int b = full_id & ((1 << attrib_bits) - 1);                int dwFirst = MR.ReadInt((int)(attrib_data_list_ofs) + a * 4);                int group_ofs = (int)(dwFirst + attrib_sizeof * b);                int group_formula_ofs = MR.ReadInt(group_ofs + 0x010);                int acd_FormulaMapData = MR.ReadInt(group_formula_ofs + 0x008 + 0x000);                if (acd_FormulaMapData == 0) continue;                int acd_FormulaMapMask = MR.ReadInt(group_formula_ofs + 0x418);                uint SNO = MR.ReadUInt(acd_address + acd_ofs__sno);                int Location = MR.ReadInt(acd_address + acd_ofs__item_location);                // Inventory = 0, Head = 1, Torso = 2, RightHand = 3, LeftHand = 4, Hands = 5, Waist = 6, Feet = 7, Shoulders = 8, Legs = 9, Bracers = 10, LeftRing = 11, RightRing = 12, Neck = 13, Stash = 15, Merchant = 18                // regarding location you can read item_x (int), item_y (int) OR pos_x (float), pos_y (float), pos_z (float) values here                // item_x and item_y means the coordinates in stash or inventory                // pos_x, pos_y, pos_z are world coordinates for things on the floor                // if this is a monster, you can read the int @ acd_address + acd_ofs__monster_type                // monster types: normal = 0, elite = 1, yellow? = 2, purple? = 3, keywarden = 4                for (int link_index = 0; link_index <= 255; link_index++)                {                    int link_root_address = acd_FormulaMapData + link_index * 4;                    int link_address = MR.ReadInt(link_root_address);                    int n = 0; // safety counter against infinite loops                    while ((link_address != 0) && (n < 20))                    {                        uint id = MR.ReadUInt(link_address + attrib_link_ofs__id);                        int attribute_index = (int)(id & 0xFFF);                        if (attribute_index > 0)                        {                                uint mask = id >> 12;                                int value = MR.ReadInt(link_address + attrib_link_ofs__value);                                // do whatever you want with the attribute_index, mask, value here                                // NOTE: you have to cast float type attributes to float here                        }                        link_address = MR.ReadInt(link_address + attrib_link_ofs__next);                        n += 1;                    }                }}}

Fast reading a specific attribute:
public int GetAttribHelper(int acd_FormulaMapData, int acd_FormulaMapMask, int AttributeIndex, uint AttributeMask, int Default = -1)        {       uint full_id = AttributeIndex | (AttributeMask << 12);       uint idxmask = full_id ^ (full_id >> 16);        int idx = (int)(acd_FormulaMapMask & idxmask);       int link_root_address = acd_FormulaMapData + idx * 4;       int link_address = MR.ReadInt(link_root_address);       int n = 0;                while ((link_address != 0) && (n < 20))                {                    uint id = MR.ReadUInt(link_address + attrib_link_ofs__id);                    if (id == full_id)                    {                            int v = MR.ReadInt(link_address + attrib_link_ofs__value);                            return v;                    }                    link_address = MR.ReadInt(link_address + attrib_link_ofs__next);                    n += 1;                }       return Default;        }



Example of reading a skill's cooldown


First you need the current "time" of the current game:
public readonly int ObjectManagerStorage_ofs__ticks = 0x94;int CurrentTick = MR.ReadInt(ObjectManagerStoragePtr + ObjectManagerStorage_ofs__ticks);

Then you just read the Power_Cooldown (0x12D) attribute masked by the selected skill (sweeping wind = 96090)

int CooldownFinishTicks = GetAttribHelper(your_player_characters_acd_FormulaMapData, your_player_characters_acd_FormulaMapMask, 0x12D, 96090, 0);double seconds_left = (CooldownFinishTicks > CurrentTick) ? (CooldownFinishTicks - CurrentTick) / 60.0d : 0;