diabloIII

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 pointer
acd_data_start_ofs = MR.ReadInt(acd_data_list_ofs); //container.List
acd_sizeof = MR.ReadInt(addr_acds_container + 0x104); //container.SizeOf
acd_bits = MR.ReadInt(addr_acds_container + 0x18C); //container.Bits
acd_count_ofs = addr_acds_container + 0x108; //container.Count


addr_attrib_groups_container = MR.ReadInt(addr_attrib_groups + AttribGroupsContainer_ofs__FastAttribGroups); // AttribGroupsContainer.FastAttribGroups
attrib_data_list_ofs = MR.ReadInt(addr_attrib_groups_container + 0x148); //container.List, double pointer
attrib_sizeof = MR.ReadInt(addr_attrib_groups_container + 0x104); //container.SizeOf
attrib_bits = MR.ReadInt(addr_attrib_groups_container + 0x18C); //container.Bits


//Enumerating All Actors and their Attributes


ACDCount = 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;



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值