ObjectManager troubles menu

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 15 of 21
  1. #1
    Require's Avatar Sergeant
    Reputation
    2
    Join Date
    Dec 2011
    Posts
    40
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    ObjectManager troubles

    Hello everyone,

    I have been following some tutorials and now I'm trying to work with an ObjectManager to get some more understanding of the whole process.
    After some reading I'm quite understanding the architecture of the WoWObjects and with some help of sample code I made a little program which should return (my) player object.

    There is going something wrong (I think with the player base), because the WowObject that I'm creating has some invalid values. For example, the WoWobject carries a (int) Type to see which type of object it is. It has to be something like 1,2,3,4 but it returns something like 899283829. There COULD be an offset wrong, but I went through the dump and couldn't find my mistake. Hopefully you guys can see my problem so I can (finally) move on.

    ObjectManager class:

    Code:
        static class ObjectManager
        {
            public static BlackMagic WowReader = new BlackMagic();
    
            private const uint staticClientConnection = 0x009BE678, // client connection, same address every boot
            objectManagerOffset = 0x463C,                                  // offset from the ClientConnection to the object manager
            localGuidOffset = 0xC8,                                             // offset from the object manager to the local guid
            firstObjectOffset = 0xC0,                                          // offset from the object manager to the first object
            nextObjectOffset = 0x3C;                                          // offset from one object to the next
            static private uint objectManagerBase;                       // the address off the object manager
            static public ulong localGuid;                                   // the local guid.
            public static PlayerObject LocalPlayer;
            public static IDictionary<ulong, PlayerObject> PlayerObjectList = new Dictionary<ulong, PlayerObject>();
    
            public static void LoadAddresses()
            {
                WowReader.OpenProcessAndThread(SProcess.GetProcessFromProcessName("Wow"));
                objectManagerBase = WowReader.ReadUInt(WowReader.ReadUInt(staticClientConnection + (uint)WowReader.MainModule.BaseAddress) + objectManagerOffset);
                localGuid = (uint)WowReader.ReadInt64((uint)(objectManagerBase + localGuidOffset));
            }
    
            public static void PopulateLists()
            {
                PlayerObjectList.Clear();
                WowObject CurrentObject = new WowObject(WowReader.ReadUInt((objectManagerBase + firstObjectOffset)));
     
                while (CurrentObject.BaseAddress != 0 && CurrentObject.BaseAddress % 2 == 0)
                {
                    if (CurrentObject.Type == 4) { // a player
                        PlayerObjectList.Add(CurrentObject.Guid, new PlayerObject(CurrentObject.BaseAddress));
                        if (CurrentObject.Guid == localGuid) // it is the local player
                            LocalPlayer = PlayerObjectList[localGuid];
                    }
     
                    CurrentObject.BaseAddress = WowReader.ReadUInt((CurrentObject.BaseAddress + nextObjectOffset));
                }
            }
        }

    WoWObjects
    Code:
        class WowObject
        {
            protected const uint GuidOffset = 0x0,
                NextObjectOffset = 0x3C,
                TypeOffset = 0x10,
                XPositionOffset = 0x790,
                YPositionOffset = 0x794,
                ZPositionOffset = 0x798,
                RotationOffset = XPositionOffset + 0x10,
                DescriptorFieldsOffset = 0xc;
            protected uint baseAddress;
            public WowObject(uint baseAddress)
            {
                this.baseAddress = baseAddress;
            }
            public uint BaseAddress
            {
                get { return baseAddress; }
                set { baseAddress = value; }
            }
            public uint DescriptorFields
            {
                get { return ObjectManager.WowReader.ReadUInt((BaseAddress + DescriptorFieldsOffset)); }
            }
            public int Type
            {
                get { return ObjectManager.WowReader.ReadInt((BaseAddress + TypeOffset)); }
            }
            public virtual UInt64 Guid
            {
                get { return ObjectManager.WowReader.ReadUInt64((BaseAddress + GuidOffset)); }
                set { return; }
            }
            public virtual float XPosition
            {
                get { return ObjectManager.WowReader.ReadFloat((BaseAddress + XPositionOffset)); }
            }
            public virtual float YPosition
            {
                get { return ObjectManager.WowReader.ReadFloat((BaseAddress + YPositionOffset)); }
            }
            public virtual float ZPosition
            {
                get { return ObjectManager.WowReader.ReadFloat((BaseAddress + ZPositionOffset)); }
            }
            public float Rotation
            {
                get { return ObjectManager.WowReader.ReadFloat((BaseAddress + RotationOffset)); }
            }
        }
    
        class CreatureObject : WowObject
        {
            protected const uint LevelOffset = 0x20 + 0xA0 * 4,
                CurrentHealthOffset = 0x20 + 0x48 * 4,
                MaxHealthOffset = 0x20 + 0x60 * 4,
                CurrentManaOffset = 0x20 + 0x1AC * 4,
                MaxManaOffset = 0x20 * 4,
                TargetGuidOffset = 0x20 + 0x30 * 4;
            public CreatureObject(uint BaseAddress)
                : base(BaseAddress)
            { }
            public UInt64 TargetGuid
            {
                get { return ObjectManager.WowReader.ReadUInt64((DescriptorFields + TargetGuidOffset)); }
            }
            public int Level
            {
                get { return ObjectManager.WowReader.ReadInt((DescriptorFields + LevelOffset)); }
            }
            public int CurrentHealth
            {
                get { return ObjectManager.WowReader.ReadInt((DescriptorFields + CurrentHealthOffset)); }
            }
            public int MaxHealth
            {
                get { return ObjectManager.WowReader.ReadInt((DescriptorFields + MaxHealthOffset)); }
            }
            public int CurrentMana
            {
                get { return ObjectManager.WowReader.ReadInt((DescriptorFields + CurrentManaOffset)); }
            }
            public int MaxMana
            {
                get { return ObjectManager.WowReader.ReadInt((DescriptorFields + MaxManaOffset)); }
            }
            public int HealthPercent
            {
                get
                {
                    double percentage = CurrentHealth / MaxHealth;
                    percentage = percentage * 100;
                    return (int)Math.Round(percentage);
                }
            }
        }
    There could be an offset wrong, but I am not sure.. I hope someone is able to assist me with this problem. And I do have one question; how are you able to debug with Memory editing? How do you know what you're doing wrong, like having a wrong offset? You're not getting an exception, just wrong data.

    Thanks alot,
    Require

    ObjectManager troubles
  2. #2
    lanman92's Avatar Active Member
    Reputation
    50
    Join Date
    Mar 2007
    Posts
    1,033
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The type is at [ObjBase + 0x14]. You're reading part of the GUID at offset 0x10.

  3. #3
    Require's Avatar Sergeant
    Reputation
    2
    Join Date
    Dec 2011
    Posts
    40
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by lanman92 View Post
    The type is at [ObjBase + 0x14]. You're reading part of the GUID at offset 0x10.
    Weird, saw 0x10 few times in the dump thanks that was my Type problem hehe

    ---------- Post added at 11:53 PM ---------- Previous post was at 11:29 PM ----------

    How am I able to see if the localGuid I'm retrieving is correct? Because I'm getting 2 times a playerobject with the same Guid. But I do not get my localGuid :/

  4. #4
    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)
    You are reading the GUID at the wrong place
    the GUID is located at [[objectBase + descriptorOffset] + GUIDOffset], not at [objectBase + GUIDOffset]
    Last edited by xalcon; 01-06-2012 at 09:24 PM.
    "Threads should always commit suicide - they should never be murdered" - DirectX SDK

  5. #5
    Robske's Avatar Contributor
    Reputation
    305
    Join Date
    May 2007
    Posts
    1,062
    Thanks G/R
    3/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by xalcon View Post
    You are reading the GUID at the wrong place
    the GUID is located at [[objectBase + descriptorOffset] + GUIDOffset], not at [objectBase + GUIDOffset]
    It (was/is) stored in both locations iirc, there was however some discussion as to wether these 2 guids were always equal. I can't imagine why this wouldn't be the case though.
    "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live." - Martin Golding
    "I cried a little earlier when I had to poop" - Sku

  6. #6
    Require's Avatar Sergeant
    Reputation
    2
    Join Date
    Dec 2011
    Posts
    40
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @xalcon: Hmm that didn't help. I am getting localGuid = 1 back.. plus again it adds 2 objects with same Guid and never comes inside the localPlayer if statement.
    @Robske + xalcon: Could there be something else wrong? because I seem to have the offsets right and even with the feedback of xalcon I'm still experiencing this problem.

    private const uint staticClientConnection = 0x009BE678, // client connection, same address every boot

    This one is the objectManagerPointer offset right? or am I using the wrong one here, because this was the only one I wasn't certain about to be honest.

    Thanks for your help guys

  7. #7
    boredevil's Avatar Active Member
    Reputation
    46
    Join Date
    Feb 2008
    Posts
    166
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    try this:

    GuidOffset = 0x30; // not sure if 100% correct may have changed.
    get { return ObjectManager.WowReader.ReadUInt64((BaseAddress + GuidOffset)); }

    or read from from descriptors:
    GuidOffset = 0x0;
    et { return ObjectManager.WowReader.ReadUInt64((DescriptorFields() + GuidOffset));

    just as robske wrote. your guid is stored in two different places. that can be a bit confusing if you are looking at different sources and you don´t know about it.
    if something is in the descriptors, always try to read from there, because every read from somewhere other is one offset more to maintain.
    Last edited by boredevil; 01-07-2012 at 12:04 PM.

  8. #8
    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)
    Originally Posted by Robske View Post
    It (was/is) stored in both locations iirc, there was however some discussion as to wether these 2 guids were always equal. I can't imagine why this wouldn't be the case though.
    ooh...kay... good to know :< My code is very similar to require's, but I don't use a Dictionary to store my references. Might be better ofc, but I was lazy on my first implementation :P


    and well... after I've found the bug, I had to use my Stress reduction kit... such a simple problem

    @require: there is some 'u' missing in your code... and in addition (and this is the main problem) you are casting an uint64 to an uint32 which causes your problem... so please STOP using unnecessary casts! the ReadXXXX-Methods already return the desired data type in the most cases!


    localGuid = (uint)WowReader.ReadInt64((uint)(objectManagerBase + localGuidOffset));

    ||
    \/

    localGuid = WowReader.ReadUInt64((uint)(objectManagerBase + localGuidOffset));
    Last edited by xalcon; 01-07-2012 at 12:55 PM.
    "Threads should always commit suicide - they should never be murdered" - DirectX SDK

  9. #9
    Require's Avatar Sergeant
    Reputation
    2
    Join Date
    Dec 2011
    Posts
    40
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks alot guys I really appreciate your help.. I am at my girlfriends place now so I will give it a try tomorrow. Xalcon I indeed read somewhere that I should use an Uint, you are 100% correct on that. Thanks again for helping me out in such detail, both of you. Is it indeed true that the staticClient equals the object manager offset in the dump? Because I was rather confused about that.

  10. #10
    Require's Avatar Sergeant
    Reputation
    2
    Join Date
    Dec 2011
    Posts
    40
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by xalcon View Post
    ooh...kay... good to know :< My code is very similar to require's, but I don't use a Dictionary to store my references. Might be better ofc, but I was lazy on my first implementation :P


    and well... after I've found the bug, I had to use my Stress reduction kit... such a simple problem

    @require: there is some 'u' missing in your code... and in addition (and this is the main problem) you are casting an uint64 to an uint32 which causes your problem... so please STOP using unnecessary casts! the ReadXXXX-Methods already return the desired data type in the most cases!


    localGuid = (uint)WowReader.ReadInt64((uint)(objectManagerBase + localGuidOffset));

    ||
    \/

    localGuid = WowReader.ReadUInt64((uint)(objectManagerBase + localGuidOffset));
    This didn't help either. I am still having the problem that my code finds 2 times the same object(same GUID) so it crashes. And it NEVER finds my localPlayer for some reason.

    Edit: Hmm something clearly goes wrong. The two objects it tries to add everytime is actually my playerobject. But in the property: MaxMana it shows my MaxHealth lol, so that offset isn't right. Because in my MaxHealth property it gives me a value that I can't recall to any value ingame:S So with those 2 objects which I know is my playerObject I was able to get the guid and it was far different from what I try to calculate with localGuid. Still don't know where it's going wrong though
    Last edited by Require; 01-08-2012 at 01:23 PM.

  11. #11
    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)
    Originally Posted by Require View Post
    This didn't help either. I am still having the problem that my code finds 2 times the same object(same GUID) so it crashes. And it NEVER finds my localPlayer for some reason.

    Edit: Hmm something clearly goes wrong. The two objects it tries to add everytime is actually my playerobject. But in the property: MaxMana it shows my MaxHealth lol, so that offset isn't right. Because in my MaxHealth property it gives me a value that I can't recall to any value ingame:S So with those 2 objects which I know is my playerObject I was able to get the guid and it was far different from what I try to calculate with localGuid. Still don't know where it's going wrong though
    Well, I've fired up my testproject and copy'n'pasted your code. I can reproduce your problem and it seems it is as I said in my first post. When I change your WoWObject.GUID-getter to code to the following:
    Code:
    public virtual UInt64 Guid
            {
                get { return ObjectManager.WowReader.ReadUInt64(ObjectManager.WowReader.ReadUInt(BaseAddress + DescriptorFieldsOffset) + GuidOffset ); }
                set { return; }
            }
    everything is working as intended o.O" Either blizzard has changed something or the code is still wrong. Anyway... use this GUID getter code or try to find the GUID with only one memory read instead of two. Do it as you like.
    Last edited by xalcon; 01-08-2012 at 05:38 PM.
    "Threads should always commit suicide - they should never be murdered" - DirectX SDK

  12. #12
    Require's Avatar Sergeant
    Reputation
    2
    Join Date
    Dec 2011
    Posts
    40
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by xalcon View Post
    Well, I've fired up my testproject and copy'n'pasted your code. I can reproduce your problem and it seems it is as I said in my first post. When I change your WoWObject.GUID-getter to code to the following:
    Code:
    public virtual UInt64 Guid
            {
                get { return ObjectManager.WowReader.ReadUInt64(ObjectManager.WowReader.ReadUInt(BaseAddress + DescriptorFieldsOffset) + GuidOffset ); }
                set { return; }
            }
    everything is working as intended o.O" Either blizzard has changed something or the code is still wrong. Anyway... use this GUID getter code or try to find the GUID with only one memory read instead of two. Do it as you like.
    So wait a minute.. Instead of that I was getting my localGuid wrong I actually was getting the object Guid wrong? so my localGuid was correct all the time ?oO

  13. #13
    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)
    jep.

    Here is a full explanation about the WoW GUID: (Maybe a bit outdated, but the way how the GUID works should be well explained)
    All entities in World of Warcraft are identified by a unique 64-bit number; generally presented as a string containing a hexadecimal representation of the number (e.g. "0xF530007EAC083004"). (Note that Lua in WoW does not support 64-bit integers, so this value cannot be converted with tonumber.)
    The type of unit represented by a GUID can be determined by using bit.band() to mask the first three digits with 0x00F: - 0x000 - A player - 0x003 - An NPC - 0x004 - A player's pet (i.e. hunter/warlock pets and similar; non-combat pets count as NPCs) - 0x005 - A vehicle
    Further content of the GUID varies by unit type:

    • Players - The remaining thirteen digits are unique to a player character at least within that character's battlegroup (that is, they remain unique and constant even in cross-server battlegrounds). This number is also semi-permanent -- it persists from character creation until deletion, renaming, or server transfer.
    • NPCs - Remaining digits can be broken down as follows:
      • Digits 4-6 - Unused.
      • Digits 7-10 - NPC creature ID: identifies the specific named NPC (e.g. Hogger, Loque'nahak) or type of NPC (e.g. Sunfury Nethermancer, Shattertusk Mammoth). Converting to decimal results in the ID found on database sites such as wowhead.com; can also be used with [[docs/widgets/PlayerModel/SetCreature|PlayerModel:SetCreature]] to view the NPC's model.
      • Digits 11-16 - Spawn counter: identifies the individual NPC (i.e. differentiates between the Gamon you recently killed and the Gamon that respawned a few minutes later, or between one Ymirheim Defender and another).

    • Pets - Hunter pets immediately after taming retain the GUID they had as a wild creature; after resummoning or logout/login, their GUID changes to the pet format. Remaining digits can be broken down as follows:
      • Digits 4-10 - A constant value unique to the individual pet: like a player's unique ID it is constant across multiple sessions.
      • Digits 11-16 - Spawn counter: changes when the pet is dismissed and re-summoned.

    • Vehicles - Same format and content as NPCs.

    For example, the GUID 0xF530007EAC083004 can be deconstructed as follows:

    • digits 1-3 are "F53"; bit.band(0xF53, 0x00F) == 0x003, so this is an NPC
    • digits 7-10 are "7EAC"; 0x7EAC == 32428, which we can look up to find the NPC is a Underbelly Rat.
    • digits 11-16 have no intrinsic meaning, but distinguish this Underbelly Rat from all others spawned since the last server reset.
    Source: API Meta-Types - World of Warcraft Programming: A Guide and Reference for Creating WoW Addons
    Last edited by xalcon; 01-08-2012 at 06:52 PM.
    "Threads should always commit suicide - they should never be murdered" - DirectX SDK

  14. #14
    Require's Avatar Sergeant
    Reputation
    2
    Join Date
    Dec 2011
    Posts
    40
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks Xalcon, I have been able to create a basic UI showing basic stuff about the player and because of reading a lot I was able to do this. Of course you helped me a lot by fixing that localGuid and I would like to thank you for that. There is just one thing I don't understand. I wanted to get the playersname in my WoWObject : PlayerObject, but in the tutorials I saw it gets the playersName from the WoWBaseaddress(process) why isn't this from the descriptors? and am I able to get the playersName from the descriptors? that would be much better regarding I am getting all my information from the descriptors.

  15. #15
    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)
    The username of a player is not inside the object description, because of its dynamic length. (Well, atleast I think so )
    To get the Name of the playerobject, you need to do some calculations and lookups. All playernames are stored in a temporary linked list. You will need a mask which you can apply on the players guid and then read the name out of the list... well, after you've done some magic :3
    Code:
    get
                {
                    string cname = "";
                    int mask = Sirenia.Memory.ReadInt((uint)Offsets.Name.NameStorePtr + (uint)Sirenia.Memory.MainModule.BaseAddress + (uint)Offsets.Name.NameMaskOffset);
                    if (mask == -1)
                    {
                        cname = "UNKNOWN";
                    }
                    else
                    {
                        UInt64 guid = this.GUID;
    
                        int nameStoreBasePtr = Sirenia.Memory.ReadInt((uint)Offsets.Name.NameBaseOffset + (uint)Offsets.Name.NameStorePtr + (uint)Sirenia.Memory.MainModule.BaseAddress);
                        int maskedGUID = mask & (int)guid;
                        maskedGUID += maskedGUID * 2;
                        int ptr = Sirenia.Memory.ReadInt((uint)(nameStoreBasePtr + (maskedGUID * 4) + 4) + 4);
    
                        while (Sirenia.Memory.ReadUInt((uint)ptr) != (uint)guid)
                        {
                            int maskedGUID2 = (int)this.GUID & mask;
                            maskedGUID2 += maskedGUID2 * 2;
                            int ptr2 = Sirenia.Memory.ReadInt((uint)nameStoreBasePtr + ((uint)maskedGUID2 * 4));
                            ptr2 += ptr;
                            ptr = Sirenia.Memory.ReadInt((uint)ptr2 + 4);
                        }
    
                        cname = Sirenia.Memory.ReadASCIIString((uint)ptr + (uint)Offsets.Name.NameStringOffset, 64);
                    }
                    return cname;
                }
    This is my PlayerName getter function. If you want to know how it works, try to reverse the Lua function "UnitName()" using IDA. To read the Name for a gameobject or a unit (monster, npc), the code differs.
    "Threads should always commit suicide - they should never be murdered" - DirectX SDK

Page 1 of 2 12 LastLast

Similar Threads

  1. Objectmanager - Some offset trouble
    By Ploski in forum WoW Memory Editing
    Replies: 10
    Last Post: 08-13-2009, 10:07 AM
  2. Glider trouble
    By Kirin in forum World of Warcraft Bots and Programs
    Replies: 0
    Last Post: 01-04-2007, 06:00 PM
  3. trouble finding .blp
    By yellowsn in forum WoW ME Questions and Requests
    Replies: 5
    Last Post: 11-23-2006, 12:06 AM
  4. Blizz is in some trouble. youll love this :)
    By WoWLegend in forum World of Warcraft General
    Replies: 23
    Last Post: 09-26-2006, 08:01 AM
All times are GMT -5. The time now is 04:04 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Google Authenticator verification provided by Two-Factor Authentication (Free) - vBulletin Mods & Addons Copyright © 2025 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search