WoW Classic 1.15.5.57638 Object Manager Changes menu

Shout-Out

User Tag List

Results 1 to 14 of 14
  1. #1
    dreadcraft's Avatar Member
    Reputation
    2
    Join Date
    Jun 2018
    Posts
    13
    Thanks G/R
    11/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    WoW Classic 1.15.5.57638 Object Manager Changes

    Got most of my pointers updated after the classic era/SOD client patch today but it seems like object manager must've had some changes following similar changes in the retail client last month.

    Code:
    # 1.15.5.57638
    object_manager = 0x38317F8 # not verified. big object manager changes? object array and max object count seem to have migrated... or my pointer is incorrect.
    player_guid = 0x3776F70
    mouseover_guid = 0x3891530
    chat_frame_open = 0x0 # no working ptr as of 1.15.4.x; BinDiff and ByteSigs failed to locate suitable replacement function
    zone_text = 0x3890778
    subzone_text = zone_text + 0x8
    minimap_zone_text = subzone_text + 0x8
    # target guid ptrs
    player_target_guid = 0x355D0B8
    # camera
    camera_manager = 0x3772B18
    Trying to go back and compare 1.15.4.x object manager code in IDA to the new stuff but not making much head way thus far.
    If anyone is willing to share their progress it would be muchly appreciated!

    Also it looks like some other offsets moved around. for player inventory fields I have "player_field_inventory = 0x138E8 + 0x8"
    UnitChannelInfo might've moved to 0x6F4, 0x6F8, 0x6FC (channel_spell, channel_start, channel_end)
    Need to verify both of those but can't do it until I have object base addresses to test with.
    Fortunately Camera stuff seems to be the same (0x3A48 offset for camera from camera manager ptr).
    I'm hoping object offsets haven't moved around too much but again, not there yet.
    Thanks again, folks.

    WoW Classic 1.15.5.57638 Object Manager Changes
  2. #2
    DreamingBeast's Avatar Member
    Reputation
    1
    Join Date
    Jan 2024
    Posts
    1
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Im on the same page as you, almost all my objMgr sigs from last patch are no longer usable except for one which leads me to 0x38317F8, however i can not find any useful imformation at this address, although it does reset to 0 when i logged out.

    const UINT64 OBJECT_MANAGER_OFFSET = 0x38317F8;
    const UINT64 MOUSEOVER_GUID_OFFSET = 0x3891530;
    const UINT64 CORPSE_POS_GUID_OFFSET = 0x3305280 + 0x40;
    const UINT64 LAST_TARGET_GUID_OFFSET = 0x355D0C8;
    const UINT64 TARGET_GUID_OFFSET = 0x355D0B8;

    Hope someone can clarify this, until then ill keep up my own research

  3. #3
    hackjoe8's Avatar Member
    Reputation
    1
    Join Date
    Jan 2022
    Posts
    4
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Following!

  4. #4
    qyte's Avatar Member
    Reputation
    25
    Join Date
    Aug 2013
    Posts
    6
    Thanks G/R
    1/13
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That is what i have come up thus far.

    Keep in mind that a very similar approach is being used on 11.0.7 PTR at the moment with an extra step of them using an int* IndexArray to get the index of the EntityEntry.

    Code:
    struct WowGUID
    {
    	uint64_t lo;
    	uint64_t hi;
    };
    
    struct WowObject
    {
      void** vftable;
      byte  object_type;    // 0x8
      char fill[7];
      uint64_t EntityIndex; // 0x10
      WowGUID guid;         // 0x18
    }
    
    // offsets[flags[0]] has the offset of the object ptr ( which is always 0x20 atm but the client always gets it from this array)
    // flags[0] != 0xFF means valid entry
    // flags[0x12] != 0xFF means Active Object
    // flags[0x13] != 0xFF means Visible Object
    struct EntityCategory // size 0xC0
    {
      int32_t *offsets;
      byte* flags;
      char fill[0xb0];
    }
    
    // (EntityIndex >> 54) == EntryHash  this determines on which ObjectManager the object belongs to
    // (EntityIndex & 0x3FFFFFFF) this gives the index of the ObjectEntity array
    struct ObjectEntity
    {
      int32_t CategoryIndex;
      int32_t gap;
      uint64_t EntityIndex;
      WowGUID guid;
      void* object;
    }
    
    // No longer a chained hash list, instead it goes through a linear expansion
    // previous ((guid->lo * 0xD6D018F5 + guid->hi * 0xA2AA033B) % EntitiesSize) can still be used to access the "first" index
    // and keep walking forward index = (++index % EntitiesSize) until we find an empty entry [0,0,?]
    // NOTE: Clients skips over [1,0x400000000000000,0] entries as they point to "none" unitID
    // (EntityIndex >> 54) == EntryHash  this determines on which ObjectManager the object belongs to
    // (EntityIndex & 0x3FFFFFFF) this gives the index of the ObjectEntity array
    struct HashEntry
    {
      WowGUID guid;
      uint64_t EntityIndex;
    }
    
    struct ObjectManager
    {
      int32_t EntryHash;
      uint32_t gap;
      ObjectEntity** entities; // 0x8
      uint64_t EntitiesSize;   // 0x10
      char fill[0x28];
      uint64_t HashSize;       // 0x40
      HashEntry* hashes;       // 0x48  // the hashes array seems to be shared across all ObjectManager objects
      uint64_t gap2;
      uint64_t IsUsingOld;     // 0x58 when EntryHash == -1 aka the previous Om is being used? / copied over?
      uint64_t gap3;
      EntityCategory* categories;  // 0x68
    }
    
    // EntryHash -1 means previous Om (Can be seen after logout)
    // EntryHash -2 means invalid entry
    // NOTE: The Client does AcquireSRWLockShared so the access to OmArray is multi-threaded
    // also it uses a new hashing algorithm for determining the index of the EntryHash inside the OmArray
    // but still keeps walking it "forward" (++index % OmArraySize) until it hits -2 EntryHash or a match
    struct ObjectManagerEntry
    {
      int32_t EntryHash;
      uint32_t gap;
      ObjectManager* entry;
    }
    
    // 1.15.5.57638
    // uint64_t*           OmArraySize = 0x32AA510
    // ObjectManagerEntry* OmArray     = 0x32AA518
    // ObjectManager*      WowCSMain   = 0x3831808
    // fGetObjectMatrix                = 0x1B36F70
    // fGetOmForObject                 = 0x0519080  // fGetOmForObject(EntityIndex >> 54) returns ObjectManager* entry or nullptr

    The ObjectTransformationMatrix can be constructed from the TransportAngle as well

    WorldMatrix.png

    Just keep in mind that Wow uses a Column Based array system for Matrixes ( CameraMatrix ObjectMatrix etc ) while the Image above i have no idea if it used a column or a Row based Matrix.

  5. Thanks dreadcraft, Mr.Sergey (2 members gave Thanks to qyte for this useful post)
  6. #5
    gdfsxwy's Avatar Active Member
    Reputation
    18
    Join Date
    Apr 2010
    Posts
    38
    Thanks G/R
    22/10
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    seek help.
    I missed the WowClassic.exe file for game version 1.15.5.57638 that I used for my IDA.
    If there is no original file, decrypted WowClassic.exe can be accepted.
    Please send the file to my email, thank you very much!
    My email [email protected]
    Last edited by gdfsxwy; 2 Weeks Ago at 08:03 PM.

  7. #6
    dreadcraft's Avatar Member
    Reputation
    2
    Join Date
    Jun 2018
    Posts
    13
    Thanks G/R
    11/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by gdfsxwy View Post
    seek help.
    I missed the WowClassic.exe file for game version 1.15.5.57638 that I used for my IDA.
    If there is no original file, decrypted WowClassic.exe can be accepted.
    Please send the file to my email, thank you very much!
    My email [email protected]
    I uploaded my copy of the 1.15.5.57638 to filebin for ya. It was unpacked with namreeb's wowdump. Hope this helps.

    Filebin | 4z8df3jngbbdopo0

  8. Thanks gdfsxwy (1 members gave Thanks to dreadcraft for this useful post)
  9. #7
    dreadcraft's Avatar Member
    Reputation
    2
    Join Date
    Jun 2018
    Posts
    13
    Thanks G/R
    11/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Even more fun! Blizzard just took the servers down for an hour (supposedly to increase the time between mob respawns for the crystal/AQ world event). When servers came back up we had another client update.

    Here is a 7zipped copy of the 1.15.5.57716 client, again unpacked with namreeb's tool:
    Filebin | vk31omgvlw8sms3j

    I haven't had a chance to look at anything in it yet. After looking at how badly obfuscated the "ObjectName" function was on the last build I'm definitely going to need some kind of non-free IDA build that will allow me to use the python api for de-obfuscating all of the non-sensical JMPs.
    IDA Free is awesome and I wish they had done it years ago but sometimes you need all the tools at your disposal.
    Not sure if anyone has been using Ghidra lately but it seems to take so much longer to auto-analyze than IDA does.

  10. #8
    gdfsxwy's Avatar Active Member
    Reputation
    18
    Join Date
    Apr 2010
    Posts
    38
    Thanks G/R
    22/10
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by dreadcraft View Post
    I uploaded my copy of the 1.15.5.57638 to filebin for ya. It was unpacked with namreeb's wowdump. Hope this helps.

    Filebin | 4z8df3jngbbdopo0
    thank you!

  11. #9
    Razzue's Avatar Contributor Avid Ailurophile

    CoreCoins Purchaser Authenticator enabled
    Reputation
    391
    Join Date
    Jun 2017
    Posts
    602
    Thanks G/R
    191/277
    Trade Feedback
    2 (100%)
    Mentioned
    14 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by dreadcraft View Post
    ~~
    Just use UnitFamily / UnitRank subs to get unit info offset, then npc name will be somewhere in there just slightly beyond family/rank offsets. Player names are grabbed from the name cache, and most everything else from the db2's

    For example: Here's the internal of UnitCreatureFamily from 57638
    Code:
    __int64 __fastcall sub_141BD1220(__int64 a1)
    {
      __int64 result; // rax
    
    
      result = *(_QWORD *)(a1 + 0x4E0);
      if ( result )
        result = *(unsigned int *)(result + 0x7C);
      return result;
    }
    So *(int*)((*(IntPtr*)(eb.Pointer + 0x4E0)) + 0x7C); should get you close to where the name is also located
    Code:
    *(IntPtr*)((*(IntPtr*)(eb.Pointer + 0x4E0)) + 0x168); -> Unit Name Pointer
    *(int*)((*(IntPtr*)(eb.Pointer + 0x4E0)) + 0x170); -> Unit Name Length
    UnitName.JPG
    Last edited by Razzue; 2 Weeks Ago at 11:25 AM.
    "May all your bacon burn"

  12. Thanks dreadcraft (1 members gave Thanks to Razzue for this useful post)
  13. #10
    Razzue's Avatar Contributor Avid Ailurophile

    CoreCoins Purchaser Authenticator enabled
    Reputation
    391
    Join Date
    Jun 2017
    Posts
    602
    Thanks G/R
    191/277
    Trade Feedback
    2 (100%)
    Mentioned
    14 Post(s)
    Tagged
    0 Thread(s)
    For anyone who may prefer c#... :P

    Code:
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct ExampleGuid
    {
        public long Value1;
        public long Value2;
    
        public long Hash 
            => unchecked((0xA2AA033B * Value2) + (0xD6D018F5 * Value1));
        public bool IsEmpty() 
            => Value2 == 0 && Value1 == 0;
        public bool IsValid() 
            => !(Value1 == 1 && Value2 == 0x400000000000000);
    }
    
    [StructLayout(LayoutKind.Explicit, Pack = 1)]
    public struct ActivePlayerData
    {
        [FieldOffset(0x10)]
        public ExampleGuid Guid;
    }
    Code:
    [StructLayout(LayoutKind.Sequential, Pack = 1)]public struct EntityHashEntry
    {
        public ExampleGuid Guid;
        public long EntityIndex;
    
        public long Hash 
            => EntityIndex >> 54;
        public long Index 
            => EntityIndex & 0x3FFFFFFF;
    }
    
    [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x50)]
    public struct EntityBuilder
    {
        [FieldOffset(0x4)]
        public int Index;
    
        [FieldOffset(0x10)]
        public ExampleGuid Guid;
    
        [FieldOffset(0x20)]
        public IntPtr Pointer;
    
        public int GuidType
            => (int)((Guid.Value2 >> 58) & 0x3F);
        public int EntityType
            => Memory.Read<byte>(Pointer + 0x8);
    }
    Code:
    [StructLayout(LayoutKind.Explicit, Pack = 1)]
    public struct ObjectManagerData
    {
        [FieldOffset(0x8)]
        public IntPtr EntityArrayPointer;
    
        [FieldOffset(0x10)]
        public int EntityArrayCount;
    
        public EntityBuilder GetEntityBuilder(EntityHashEntry entry)
        {
            try { return Memory.Read<EntityBuilder>(Memory.Read<IntPtr>(EntityArrayPointer + ((int)entry.Index * 0x8))); }
            catch (Exception e) { Console.WriteLine(e); }
            return default;
        }
    
    
        [FieldOffset(0x40)]
        public int HashArrayMaximum;
    
        [FieldOffset(0x48)]
        public IntPtr HashArrayPointer;
    
        [FieldOffset(0x50)]
        public int HashArrayCount;
    
        public EntityHashEntry GetHashEntry(ExampleGuid guid)
        {
            try
            {
                if (guid.IsEmpty() || !guid.IsValid()) return default;
                var index = guid.Hash & (HashArrayMaximum - 1);
                var result = Memory.Read<EntityHashEntry>(HashArrayPointer + ((int)index * Marshal.SizeOf<EntityHashEntry>()));
                return result;
            }
            catch (Exception e) { Console.WriteLine(e); }
            return default;
        }
    }
    
    [StructLayout(LayoutKind.Explicit, Pack = 1)]public struct ExampleObjectManager
    {
        [FieldOffset(0x0)]
        public IntPtr ActivePlayerPointer;
        public ActivePlayerData ActivePlayer
            => ActivePlayerPointer != IntPtr.Zero ? Memory.Read<ActivePlayerData>(ActivePlayerPointer) : default;
    
        public EntityBuilder GetActivePlayer()
        {
            try
            {
                var guid = ActivePlayer.Guid;
                if (guid.IsEmpty() || !guid.IsValid()) return default;
                var hashEntry = ManagerData.GetHashEntry(guid);
                return ManagerData.GetEntityBuilder(hashEntry);
            }
            catch (Exception e) { Console.WriteLine(e); }
            return default;
        }
    
    
        [FieldOffset(0x10)]
        public IntPtr ManagerDataPointer;
        public ObjectManagerData ManagerData
            => ActivePlayerPointer != IntPtr.Zero ? Memory.Read<ObjectManagerData>(ManagerDataPointer) : default;
    
        public EntityBuilder GetBuilder(ExampleGuid guid)
        {
            try
            {
                if (guid.IsEmpty() || !guid.IsValid()) return default;
                var hashEntry = ManagerData.GetHashEntry(guid);
                return hashEntry.Index < 0 ? default : 
                    ManagerData.GetEntityBuilder(hashEntry);
            }
            catch (Exception e) { Console.WriteLine(e); }
            return default;
        }
    }
    Usage: ( seems to work fine so far *knock on wood* )
    Code:
    var objectManager = Memory.Read<ExampleObjectManager>(address + omOffset);var player = objectManager.GetActivePlayer();
    Console.WriteLine($"Player [{player.Pointer.ToInt64():X}]: Entity Type: {player.EntityType} | Guid Type: {player.GuidType}");
    
    
    var tGuid = Memory.Read<ExampleGuid>(tGuidOffset);
    var target = objectManager.GetBuilder(tGuid);
    var targetName = target.GetUnitName();
    
    
    Console.WriteLine($"Target [{target.Pointer.ToInt64():X}]: Entity Type: {target.EntityType} | {targetName}");
    "May all your bacon burn"

  14. #11
    legbean's Avatar Member
    Reputation
    1
    Join Date
    Jun 2022
    Posts
    2
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Razzue View Post
    For anyone who may prefer c#... :P

    Code:
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct ExampleGuid
    {
        public long Value1;
        public long Value2;
    
        public long Hash 
            => unchecked((0xA2AA033B * Value2) + (0xD6D018F5 * Value1));
        public bool IsEmpty() 
            => Value2 == 0 && Value1 == 0;
        public bool IsValid() 
            => !(Value1 == 1 && Value2 == 0x400000000000000);
    }
    
    [StructLayout(LayoutKind.Explicit, Pack = 1)]
    public struct ActivePlayerData
    {
        [FieldOffset(0x10)]
        public ExampleGuid Guid;
    }
    Code:
    [StructLayout(LayoutKind.Sequential, Pack = 1)]public struct EntityHashEntry
    {
        public ExampleGuid Guid;
        public long EntityIndex;
    
        public long Hash 
            => EntityIndex >> 54;
        public long Index 
            => EntityIndex & 0x3FFFFFFF;
    }
    
    [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 0x50)]
    public struct EntityBuilder
    {
        [FieldOffset(0x4)]
        public int Index;
    
        [FieldOffset(0x10)]
        public ExampleGuid Guid;
    
        [FieldOffset(0x20)]
        public IntPtr Pointer;
    
        public int GuidType
            => (int)((Guid.Value2 >> 58) & 0x3F);
        public int EntityType
            => Memory.Read<byte>(Pointer + 0x8);
    }
    Code:
    [StructLayout(LayoutKind.Explicit, Pack = 1)]
    public struct ObjectManagerData
    {
        [FieldOffset(0x8)]
        public IntPtr EntityArrayPointer;
    
        [FieldOffset(0x10)]
        public int EntityArrayCount;
    
        public EntityBuilder GetEntityBuilder(EntityHashEntry entry)
        {
            try { return Memory.Read<EntityBuilder>(Memory.Read<IntPtr>(EntityArrayPointer + ((int)entry.Index * 0x8))); }
            catch (Exception e) { Console.WriteLine(e); }
            return default;
        }
    
    
        [FieldOffset(0x40)]
        public int HashArrayMaximum;
    
        [FieldOffset(0x48)]
        public IntPtr HashArrayPointer;
    
        [FieldOffset(0x50)]
        public int HashArrayCount;
    
        public EntityHashEntry GetHashEntry(ExampleGuid guid)
        {
            try
            {
                if (guid.IsEmpty() || !guid.IsValid()) return default;
                var index = guid.Hash & (HashArrayMaximum - 1);
                var result = Memory.Read<EntityHashEntry>(HashArrayPointer + ((int)index * Marshal.SizeOf<EntityHashEntry>()));
                return result;
            }
            catch (Exception e) { Console.WriteLine(e); }
            return default;
        }
    }
    
    [StructLayout(LayoutKind.Explicit, Pack = 1)]public struct ExampleObjectManager
    {
        [FieldOffset(0x0)]
        public IntPtr ActivePlayerPointer;
        public ActivePlayerData ActivePlayer
            => ActivePlayerPointer != IntPtr.Zero ? Memory.Read<ActivePlayerData>(ActivePlayerPointer) : default;
    
        public EntityBuilder GetActivePlayer()
        {
            try
            {
                var guid = ActivePlayer.Guid;
                if (guid.IsEmpty() || !guid.IsValid()) return default;
                var hashEntry = ManagerData.GetHashEntry(guid);
                return ManagerData.GetEntityBuilder(hashEntry);
            }
            catch (Exception e) { Console.WriteLine(e); }
            return default;
        }
    
    
        [FieldOffset(0x10)]
        public IntPtr ManagerDataPointer;
        public ObjectManagerData ManagerData
            => ActivePlayerPointer != IntPtr.Zero ? Memory.Read<ObjectManagerData>(ManagerDataPointer) : default;
    
        public EntityBuilder GetBuilder(ExampleGuid guid)
        {
            try
            {
                if (guid.IsEmpty() || !guid.IsValid()) return default;
                var hashEntry = ManagerData.GetHashEntry(guid);
                return hashEntry.Index < 0 ? default : 
                    ManagerData.GetEntityBuilder(hashEntry);
            }
            catch (Exception e) { Console.WriteLine(e); }
            return default;
        }
    }
    Usage: ( seems to work fine so far *knock on wood* )
    Code:
    var objectManager = Memory.Read<ExampleObjectManager>(address + omOffset);var player = objectManager.GetActivePlayer();
    Console.WriteLine($"Player [{player.Pointer.ToInt64():X}]: Entity Type: {player.EntityType} | Guid Type: {player.GuidType}");
    
    
    var tGuid = Memory.Read<ExampleGuid>(tGuidOffset);
    var target = objectManager.GetBuilder(tGuid);
    var targetName = target.GetUnitName();
    
    
    Console.WriteLine($"Target [{target.Pointer.ToInt64():X}]: Entity Type: {target.EntityType} | {targetName}");
    Thanks for this - but how do you walk the list? This is assuming you have a GUID to search for. How can you get the list of all object GUIDs?

  15. #12
    qyte's Avatar Member
    Reputation
    25
    Join Date
    Aug 2013
    Posts
    6
    Thanks G/R
    1/13
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It is quite clear at this point that hitting a [0,0] and returning leaves gaps and you end up with inaccessible objects if you search by guid.

    While the game does use sub_5C8D90 for getting the Hash Entry by GUID there is also sub_2B6560 that uses the old method with [next, WowGUID, ?Unknown] but i have yet to find where such a hash table is stored atm.

    All current cross references of sub_2B6560 that actually accept an offset are actually null while in -game.

    There is definitely a fallback somewhere if the first method fails.

    If anyone has an idea that would be awesome.

    Above offsets are for 1.15.5.57716.

  16. #13
    hackjoe8's Avatar Member
    Reputation
    1
    Join Date
    Jan 2022
    Posts
    4
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    When I summon a pet, I can traverse the pet's objects. But when I dismiss the pet, I can still traverse it. What's the problem?

  17. #14
    Razzue's Avatar Contributor Avid Ailurophile

    CoreCoins Purchaser Authenticator enabled
    Reputation
    391
    Join Date
    Jun 2017
    Posts
    602
    Thanks G/R
    191/277
    Trade Feedback
    2 (100%)
    Mentioned
    14 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by qyte View Post
    ~~
    Code:
    if(result.Guid.Equals(guid)) return result;
    for (var i = (int)index + 1; i < HashArrayMaximum; i++)
    {
        Memory.Read(HashArrayPointer + (i * Marshal.SizeOf<EntityHashEntry>()), ref result);
        if (result.Guid.Equals(guid))
            return result;
    }
    return default;
    Fixed the missing gaps pretty easily with no overhead so, chuck that in the GetHashEntry method and gg.
    run time is ~0.0015 ms on average, slower than I'd like but w/e, optimizations come later.
    "May all your bacon burn"

Similar Threads

  1. WoW Classic 1.15.4.56738 Bot and Offsets
    By Geneditor in forum WoW Memory Editing
    Replies: 11
    Last Post: 1 Day Ago, 08:50 AM
  2. WoW Classic 1.15.3.x - Trouble Locating Player Temporary Enchants
    By dreadcraft in forum WoW Memory Editing
    Replies: 5
    Last Post: 09-15-2024, 03:33 PM
  3. [Selling] WoW Classic GOLD - 15$ per 1000g - Server Kromcrush - US - Alliance
    By heyloor in forum World of Warcraft Buy Sell Trade
    Replies: 0
    Last Post: 09-16-2020, 09:27 AM
  4. PTR 8.2.5.31921 Object Manager changings
    By Kovrizha in forum WoW Memory Editing
    Replies: 1
    Last Post: 09-24-2019, 08:46 AM
All times are GMT -5. The time now is 09:43 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