Page 1 of 2 1 2 LastLast
Results 1 to 15 of 21
  1. #1
    Member
    Reputation
    1
    Join Date
    Dec 2011
    Posts
    40
    CoreCoins
    0

    Trade Feedbacks

    Positive
    0
    Negative
    0

    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

  2. #2
    Marshal
    Reputation
    49
    Join Date
    Mar 2007
    Posts
    1,033
    CoreCoins
    4

    Trade Feedbacks

    Positive
    0
    Negative
    0
    The type is at [ObjBase + 0x14]. You're reading part of the GUID at offset 0x10.

  3. #3
    Member
    Reputation
    1
    Join Date
    Dec 2011
    Posts
    40
    CoreCoins
    0

    Trade Feedbacks

    Positive
    0
    Negative
    0
    Quote 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
    Site Donator xalcon's Avatar
    Reputation
    31
    Join Date
    Oct 2008
    Location
    Germany
    Posts
    94
    CoreCoins
    36

    Trade Feedbacks

    Positive
    0
    Negative
    0
    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.

  5. #5
    Contributor Robske's Avatar
    Reputation
    285
    Join Date
    May 2007
    Location
    Dragon Shores
    Posts
    1,056
    CoreCoins
    85

    Trade Feedbacks

    Positive
    0
    Negative
    0
    Quote 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
    Member
    Reputation
    1
    Join Date
    Dec 2011
    Posts
    40
    CoreCoins
    0

    Trade Feedbacks

    Positive
    0
    Negative
    0
    @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
    Sergeant Major
    Reputation
    46
    Join Date
    Feb 2008
    Posts
    164
    CoreCoins
    111

    Trade Feedbacks

    Positive
    0
    Negative
    0
    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
    Site Donator xalcon's Avatar
    Reputation
    31
    Join Date
    Oct 2008
    Location
    Germany
    Posts
    94
    CoreCoins
    36

    Trade Feedbacks

    Positive
    0
    Negative
    0
    Quote 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.

  9. #9
    Member
    Reputation
    1
    Join Date
    Dec 2011
    Posts
    40
    CoreCoins
    0

    Trade Feedbacks

    Positive
    0
    Negative
    0
    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
    Member
    Reputation
    1
    Join Date
    Dec 2011
    Posts
    40
    CoreCoins
    0

    Trade Feedbacks

    Positive
    0
    Negative
    0
    Quote 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
    Site Donator xalcon's Avatar
    Reputation
    31
    Join Date
    Oct 2008
    Location
    Germany
    Posts
    94
    CoreCoins
    36

    Trade Feedbacks

    Positive
    0
    Negative
    0
    Quote 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.

  12. #12
    Member
    Reputation
    1
    Join Date
    Dec 2011
    Posts
    40
    CoreCoins
    0

    Trade Feedbacks

    Positive
    0
    Negative
    0
    Quote 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
    Site Donator xalcon's Avatar
    Reputation
    31
    Join Date
    Oct 2008
    Location
    Germany
    Posts
    94
    CoreCoins
    36

    Trade Feedbacks

    Positive
    0
    Negative
    0
    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.

  14. #14
    Member
    Reputation
    1
    Join Date
    Dec 2011
    Posts
    40
    CoreCoins
    0

    Trade Feedbacks

    Positive
    0
    Negative
    0
    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
    Site Donator xalcon's Avatar
    Reputation
    31
    Join Date
    Oct 2008
    Location
    Germany
    Posts
    94
    CoreCoins
    36

    Trade Feedbacks

    Positive
    0
    Negative
    0
    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.

 

 
Page 1 of 2 1 2 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
All times are GMT -4. The time now is 12:06 AM. Powered by vBulletin® Version 4.2.0
Copyright © 2013 vBulletin Solutions, Inc. All rights reserved.
Content Relevant URLs by vBSEO
vBulletin Optimisation by vB Optimise. Digital Point modules: Sphinx-based search

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198