8.2.5.32028 Object Manager menu

User Tag List

Results 1 to 3 of 3
  1. #1
    counted's Avatar Contributor Authenticator enabled
    Reputation
    203
    Join Date
    Mar 2008
    Posts
    183
    Thanks G/R
    11/108
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    8.2.5.32028 Object Manager

    I think I figured out the 0x8 object manger list.

    Basically it is similar in format to the PlayerNameCache.

    You have an array of object chains.

    An array entry can be empty, Address = 0;
    An array entry can contain a single object, object.next = 0;
    An array entry can contain a chain of objects, object.next > 0;

    The reason that blizzard did this is because they use an index algorithm based on the object guid to put the objects into the array.

    So when you want to retrieve an object, if you know the guid, you do NOT have to traverse the entire list.

    You use the index to get to the correct chain and only have to traverse the short chain at that array entry location.

    The algorithm is :

    Code:
                    UInt64 arrayIndex = ( UInt64 ) ( ArraySize - 1 ) & ( 0xA2AA033B * guid.Lo + 0xD6D018F5 * guid.Hi);
    
                    Int64 entryAddress = Bot.Mem64.Read<Int64>( ArrayListBase + 8 * (Int64) arrayIndex );
    This makes finding ActivePlayer, Target, MouseOver, Focus .... faster cause you already know the guid of what you are looking for:

    So the complete ObjectManager ( TomRuss88 Code Base ) is

    Code:
      [StructLayout( LayoutKind.Explicit, Pack = 4 )]
        public struct CurMgr
        {
            [FieldOffset(0x0)]
            public Int64 ArraySize;
            [FieldOffset(0x8)]
            public Int64 ArrayListBase;
            [FieldOffset(0x10)]
            public Int64 ObjectCount;
            [FieldOffset(0x120)]
            public Int64 VisibileListBase;
            [FieldOffset(Offsets.ActivePlayerGuid)]
            public WowGuid ActivePlayer;
            [FieldOffset(Offsets.MapId)]
            public int MapId;
            [FieldOffset(0x160)]
            public Int64 MovementGlobals;
        }
    
        [StructLayout( LayoutKind.Explicit, Pack = 4 )]
        public struct CurMgr0x8Entry
        {
            [FieldOffset(0x0)]
            public Int64 Next;
            [FieldOffset(0x8)]
            public WowGuid WowGuid;
            [FieldOffset(0x18)]
            public Int64 ObjectBase;
        }
    
        public class ObjectManager : IEnumerable<WowData>
        {
            public Int64 BaseAddress
            {
                get { return Bot.Mem64.Read<Int64>( Bot.Mem64.Rebase( Offsets.pCurMgr ) ); }
            }
    
            public bool IsValid
            {
                get
                {
                    return BaseAddress != 0;
                }
            }
    
            public WowGuid ActivePlayerGuid
            {
    
                get { return Bot.Mem64.Read<CurMgr>( BaseAddress ).ActivePlayer; }
            }
    
            public int MapId
            {
                get { return Bot.Mem64.Read<CurMgr>( BaseAddress ).MapId; }
            }
    
            public Int64 MovementGlobals
            {
                get { return Bot.Mem64.Read<CurMgr>( BaseAddress ).MovementGlobals; }
            }
    
            public WowData this[ WowGuid guid ]
            {
                get
                {
                    if ( guid == WowGuid.Zero )
                        return null;
    
                    UInt64 arrayIndex = ( UInt64 ) ( ArraySize - 1 ) & ( 0xA2AA033B * guid.Lo + 0xD6D018F5 * guid.Hi);
    
                    Int64 entryAddress = Bot.Mem64.Read<Int64>( ArrayListBase + 8 * (Int64) arrayIndex );
    
                    while ( entryAddress > 0 )
                    {
                        CurMgr0x8Entry entry = Bot.Mem64.Read<CurMgr0x8Entry>( entryAddress);
    
                        ObjectHeader header = Bot.Mem64.Read<ObjectHeader>( entry.ObjectBase );
    
                        if ( header.WowGuid == guid )
                        {
                            WowData data = new WowData
                            {
                                Address = entry.ObjectBase,
                                Header = header,
                            };
    
                            return data;
                        }
    
                        entryAddress = entry.Next;
                        
                    }
    
                    return null;
                }
            }
    
            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
    
            public Int64 ArrayListBase
            {
                get { return Bot.Mem64.Read<CurMgr>( BaseAddress ).ArrayListBase; }
            }
    
            public Int64 ObjectCount
            {
                // number of objects in the current list
                get { return Bot.Mem64.Read<CurMgr>( BaseAddress ).ObjectCount; }
            }
    
            public Int64 ArraySize
            {
                // number of Array Entries
                get { return Bot.Mem64.Read<CurMgr>( BaseAddress ).ArraySize; }
            }
    
            public IEnumerator<WowData> GetEnumerator()
            {    
                // first entry 
                Int64 currentAddress = Bot.Mem64.Read<Int64>( ArrayListBase );
    
                // need to traverse through all of the entry chains in the array
                // array entries can be emtpy
                // array entries can point to one entry, if next == 0
                // array entries can point to a chain of entries while ( next != 0 )
    
                for ( Int32 x = 0; x < ArraySize; )
                {
                    if ( currentAddress == 0 )
                    {
                        // current entry is empty, go to the next one
                        x++;
                        currentAddress = Bot.Mem64.Read<Int64>( ArrayListBase + 0x8 * x );
                        continue;
                    }
    
                    CurMgr0x8Entry entry = Bot.Mem64.Read<CurMgr0x8Entry>( currentAddress );
    
                    ObjectHeader header = Bot.Mem64.Read<ObjectHeader>( entry.ObjectBase );
    
                    WowData data = new WowData
                    {
                        Address = entry.ObjectBase,
                        Header = header,
                    };
    
                    yield return data;
    
                    if ( entry.Next == 0 )
                    {
                        // end of the current chain, go to next entry
                        x++;
                        currentAddress = Bot.Mem64.Read<Int64>( ArrayListBase + 0x8 * x );
                    }
                    else
                    {
                        // go to next cache entry in this chain, do not increment x
                        currentAddress = entry.Next;
                    }
                }
            }
        }
    You can see the public WowData this[ WowGuid guid ] method does not traverse the entire ObjectManager List, only the sub chain that the index says that guid should be in.

    You can also use this same index algorythim in the PlayerNameCache so you do not have to look through the entire list, only specific index

    8.2.5.32028 Object Manager
  2. Thanks CrimeTime, xalcon, evil2, carnifex_v2, ensirius, mustafa58 (6 members gave Thanks to counted for this useful post)
  3. #2
    xalcon's Avatar Contributor ふたなり
    Authenticator enabled
    Reputation
    198
    Join Date
    Oct 2008
    Posts
    291
    Thanks G/R
    20/58
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Thank you for posting this, this will become really handy in the near future for me.

    The reason that blizzard did this is because they use an index algorithm based on the object guid to put the objects into the array.
    I might be wrong, but this sounds like a simple hash-table implementation. If i recall correctly, hash tables are frequently implemented as arrays and the array slots are linked lists (for key collisions).
    "Threads should always commit suicide - they should never be murdered" - DirectX SDK

  4. #3
    counted's Avatar Contributor Authenticator enabled
    Reputation
    203
    Join Date
    Mar 2008
    Posts
    183
    Thanks G/R
    11/108
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Yea I figured it is some kind of hash algo, but I am not an expert on that stuff so just reported what I knew.

Similar Threads

  1. [APP] - Malu05's Ingame Object Manager.
    By UnknOwned in forum WoW ME Tools & Guides
    Replies: 16
    Last Post: 05-30-2009, 01:42 PM
  2. Mobs missing from object manager.
    By RawrSnarl in forum WoW Memory Editing
    Replies: 23
    Last Post: 12-31-2008, 01:31 PM
  3. Object Manager
    By Shamun in forum WoW Memory Editing
    Replies: 11
    Last Post: 11-28-2008, 02:06 PM
  4. WoW Object Manager ?
    By discorly in forum WoW ME Questions and Requests
    Replies: 4
    Last Post: 07-28-2007, 06:34 PM
All times are GMT -5. The time now is 10:56 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search