[Guide-kind of] How I handle objects. menu

User Tag List

Page 1 of 6 12345 ... LastLast
Results 1 to 15 of 80
  1. #1
    jbrauman's Avatar Member
    Reputation
    65
    Join Date
    Dec 2007
    Posts
    72
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    [Guide-kind of] How I handle objects.

    I've got a bit of time up my sleeve so I thought I would post an (intermediate) guide to the way that I get data from the object manager, to give back to the community a little. The code in this guide is written in C# but it shouldn't be too hard to port to any other OOP language. Note that you should already know how to retrieve data out of the object manager. The thing I use to read memory is a library that I don't know the author of (If you are the author, tell me!) Also note that I say things such as 'all object have an XYZ value' - this is not true. For example, items and containers do not. But in this guide we're only going to be dealing with in-game objects.


    If you take a sit back and think about it, what is the Object Manager (from now on referred to as OM) in Wow? In the broadest terms possible, it is an object that handles other objects. We know that once we have the base address of an WowObject (the object that the OM handles), we can get different information about it depending on the type of object it is.

    So it makes sense then, to build one object to handle WowObjects, and then build the WowObjects themselves. Lets jot down some information here:
    - Our OM needs a way to 'load' and find the base address of the in-game Object Manager.
    - Our OM needs to iterate through the in-game Object Manager and get two peices of information about each object - the base address, and the type. Using this information, we can create a new "WowObject" and store it.
    - Our OM needs to be able to store all the objects (arrays of WowObjects anyone?)
    - Our WowObjects, given a base address and type, need to be able to get information about themselves and return it to whoever is asking, on the fly.

    WowObjects

    The first thing that I started out with was the WowObjects themselves. As you (should) know, the objects in the in-game Object Manager can be of seven different types:
    Code:
    1 -Items
    2 - Contains
    3 - NPC's
    4 - Players
    5 - GameObjects (Nodes etc)
    6 - DynamicObjects (Spells and stuff)
    7 - Corpses
    In this guide, we're only going to deal with 3 through 7.

    What you may not know, however is that each object has attributes that are common to 'all' objects. Note that XYZ isn't common to 'all', but in this guide we're only dealing with actual in-game objects (instead of items etc). Things that are common between all of these in-game objects are:
    - A GUID (Globally Unique Id)
    - A base address
    - A type
    - An X,Y,Z position
    - A rotation value
    - Descriptor fields
    There are actually more but these are all we are interested in for now. So if we have things in common, wouldn't it make sense to make a base class that all the other objects inherit from? I give you (very creatively named): WowObject

    Code:
    class WowObject
        {
            protected const uint GuidOffset = 0x30,
                NextObjectOffset = 0x3C,
                TypeOffset = 0x14,
                XPositionOffset = 0x7D0,
                YPositionOffset = 0x7D4,
                ZPositionOffset = 0x7D8,
                RotationOffset = 0x7DC,
                DescriptorFieldsOffset = 0x8;
            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.ReadUInt32((IntPtr)(BaseAddress + DescriptorFieldsOffset)); }
            }
            public int Type
            {
                get { return ObjectManager.WowReader.ReadInt32((IntPtr)(BaseAddress + TypeOffset)); }
            }
            public virtual ulong Guid
            {
                get { return ObjectManager.WowReader.ReadULong((IntPtr)(BaseAddress + GuidOffset)); }
                set { return; }
            }
            public virtual float XPosition
            {
                get { return ObjectManager.WowReader.ReadFloat((IntPtr)(BaseAddress + XPositionOffset)); }
            }
            public virtual float YPosition
            {
                get { return ObjectManager.WowReader.ReadFloat((IntPtr)(BaseAddress + YPositionOffset)); }
            }
            public virtual float ZPosition
            {
                get { return ObjectManager.WowReader.ReadFloat((IntPtr)(BaseAddress + ZPositionOffset)); }
            }
            public float Rotation
            {
                get { return ObjectManager.WowReader.ReadFloat((IntPtr)(BaseAddress + RotationOffset)); }
            }
        }
    You'll notice that, providing only the base address to this class, we are able to get some interesting information. Now we can do some really nifty stuff! For example, say in another part of our project we created a WowObject with the name George. If we want to know George's X position, all we'd have to write (assuming that George already knows his base address) is this:

    Code:
    MessageBox.Show(George.XPosition.ToString());
    George already knows how to get his XPosition, so he scrambles off and gets it and returns it to us whenever we need it!

    Note that the in-game Object Manager does not actually hold any of these types of objects. It holds more specific objects. It can be thought about in an OOP way like this:

    Code:
    WowObject[] ObjectList = new WowObject[5];
    ObjectList[0] = new NpcObject();
    ObjectList[1] = new GameObject();
    // and so on
    Speaking of more specific objects, our WowObject class isn't going to be useful on its own, since no object in our OM's array is going to be a plain old WowObject! We need it to hold more specific objects. What is the best way to describe this in an OOP language? Subclasses that inherit. Therefore, I'll give you the rest of our WowObject (and subclasses) declarations:

    Code:
    class CreatureObject : WowObject
        {
            protected const uint LevelOffset = 0x35 * 4,
                CurrentHealthOffset = 0x17 * 4,
                MaxHealthOffset = 0x1F * 4,
                CurrentManaOffset = 0x18 * 4,
                MaxManaOffset = 0x20 * 4,
                TargetGuidOffset = 0x12 * 4;
            public CreatureObject(uint BaseAddress)
                : base(BaseAddress)
            { }
            public float Pitch
            {
                get { return ObjectManager.WowReader.ReadFloat((IntPtr)(ObjectManager.WowReader.ReadUInt32((IntPtr)(baseAddress + 0x110)) + 0x20)); }
            }
            public ulong TargetGuid
            {
                get { return ObjectManager.WowReader.ReadULong((IntPtr)(DescriptorFields + TargetGuidOffset)); }
            }
            public int Level
            {
                get { return ObjectManager.WowReader.ReadInt32((IntPtr)(DescriptorFields + LevelOffset)); }
            }
            public int CurrentHealth
            {
                get { return ObjectManager.WowReader.ReadInt32((IntPtr)(DescriptorFields + CurrentHealthOffset)); }
            }
            public int MaxHealth
            {
                get { return ObjectManager.WowReader.ReadInt32((IntPtr)(DescriptorFields + MaxHealthOffset)); }
            }
            public int CurrentMana
            {
                get { return ObjectManager.WowReader.ReadInt32((IntPtr)(DescriptorFields + CurrentMana)); }
            }
            public int MaxMana
            {
                get { return ObjectManager.WowReader.ReadInt32((IntPtr)(DescriptorFields + MaxManaOffset)); }
            }
            public int HealthPercent
            {
                get
                {
                    double percentage = CurrentHealth / MaxHealth;
                    percentage = percentage * 100;
                    return (int)Math.Round(percentage);
                }
            }
        }
        class NpcObject : CreatureObject
        {
            protected const uint SummonedByOffset = 0xE * 4,
                AttackingGuidOffset = 0x0A38;
            public NpcObject(uint BaseAddress)
                : base(BaseAddress)
            { }
            public string Name
            {
                get { return ObjectManager.WowReader.ReadString((IntPtr)(ObjectManager.WowReader.ReadUInt32((IntPtr)(ObjectManager.WowReader.ReadUInt32((IntPtr)(baseAddress + 0x9B0)) + 0x3C)))); }
            }
            public ulong AttackingGuid
            {
                get { return ObjectManager.WowReader.ReadULong((IntPtr)(BaseAddress + AttackingGuidOffset)); }
            }
            public ulong SummonedBy
            {
                get { return ObjectManager.WowReader.ReadULong((IntPtr)(DescriptorFields + SummonedByOffset)); }
            }
            public int GetAggroRadius(CreatureObject LocalPlayer)
            {
                // if they are the same level as us, the aggro radius is roughly 20 yards
                int AggroRadius = 20;
                // aggro radius varies with level difference at a rate of roughly 1 yard/level
                if (LocalPlayer.Level > Level)
                    AggroRadius -= (int)BotControl.DifferenceBetween(LocalPlayer.Level, Level);
                if (LocalPlayer.Level < Level)
                    AggroRadius += (int)BotControl.DifferenceBetween(LocalPlayer.Level, Level);
                if (AggroRadius < 5)
                    AggroRadius = 5;
                AggroRadius += 3; // give us a bit of leeway
                return AggroRadius;
            }
        }
        class PlayerObject : CreatureObject
        {
            protected const uint CurrentRageOffset = 0x19 * 4,
                CurrentEnergyOffset = 0x1B * 4,
                MaxEnergyOffset = 0x23 * 4;
            public PlayerObject(uint BaseAddress)
                : base(BaseAddress)
            { }
            public int CurrentRage
            {
                get
                {
                    int RageTemp = ObjectManager.WowReader.ReadInt32((IntPtr)(DescriptorFields + CurrentRageOffset));
                    return (int)(Math.Floor((double)(RageTemp / 10)));
                }
            }
            public int MaxRage
            {
                get { return 100; }
            }
            public int CurrentEnergy
            {
                get { return ObjectManager.WowReader.ReadInt32((IntPtr)(DescriptorFields + CurrentEnergyOffset)); }
            }
            public int MaxEnergy
            {
                get { return ObjectManager.WowReader.ReadInt32((IntPtr)(DescriptorFields + MaxEnergyOffset)); }
            }
        }
        class GameObject : WowObject
        {
            protected const uint gameObject_XPosition = 0x10 * 4,
                gameObject_YPosition = 0x11 * 4,
                gameObject_ZPosition = 0x12 * 4,
                displayId = 0x8 * 4;
            public GameObject(uint BaseAddress)
                : base(BaseAddress)
            { }
            public string Print()
            {
                return "Name: " + Name + " X: " + XPosition.ToString() + " Y: " + YPosition.ToString() + " Z: " + ZPosition.ToString();
            }
            public string Name
            {
                get
                {
                    return ObjectManager.WowReader.ReadString((IntPtr)(ObjectManager.WowReader.ReadUInt32((IntPtr)(baseAddress + 0x1f4)) + 0x078));
                }
            }
            public override float XPosition
            {
                get { return ObjectManager.WowReader.ReadFloat((IntPtr)(DescriptorFields + gameObject_XPosition)); }
            }
            public override float YPosition
            {
                get { return ObjectManager.WowReader.ReadFloat((IntPtr)(DescriptorFields + gameObject_YPosition)); }
            }
            public override float ZPosition
            {
                get { return ObjectManager.WowReader.ReadFloat((IntPtr)(DescriptorFields + gameObject_ZPosition)); }
            }
            public int DisplayId
            {
                get { return ObjectManager.WowReader.ReadInt32((IntPtr)(DescriptorFields + displayId)); }
            }
        }
        class DynamicObject : WowObject
        {
            protected const uint dynamicObject_XPosition = 0xB * 4,
                dynamicObject_YPosition = 0xC * 4,
                dynamicObject_ZPosition = 0xD * 4;
            public DynamicObject(uint BaseAddress)
                : base(BaseAddress)
            { }
            public override float XPosition
            {
                get { return ObjectManager.WowReader.ReadFloat((IntPtr)(DescriptorFields + dynamicObject_XPosition)); }
            }
            public override float YPosition
            {
                get { return ObjectManager.WowReader.ReadFloat((IntPtr)(DescriptorFields + dynamicObject_YPosition)); }
            }
            public override float ZPosition
            {
                get { return ObjectManager.WowReader.ReadFloat((IntPtr)(DescriptorFields + dynamicObject_ZPosition)); }
            }
        }
        class CorpseObject : WowObject
        {
            protected const uint corpseObject_XPosition = 0xB * 4,
                    corpseObject_YPosition = 0xC * 4,
                    corpseObject_ZPosition = 0xD * 4;
            public CorpseObject(uint BaseAddress)
                : base(BaseAddress)
            { }
            public override float XPosition
            {
                get { return ObjectManager.WowReader.ReadFloat((IntPtr)(DescriptorFields + corpseObject_XPosition)); }
            }
            public override float YPosition
            {
                get { return ObjectManager.WowReader.ReadFloat((IntPtr)(DescriptorFields + corpseObject_YPosition)); }
            }
            public override float ZPosition
            {
                get { return ObjectManager.WowReader.ReadFloat((IntPtr)(DescriptorFields + corpseObject_ZPosition)); }
            }
        }
    Hopefully you can understand what is going on in the above code. Two things to note however. The first and simplest: in the GameObject, DynamicObject and CorpseObject classes, the X,Y,Z are retrieved in a different way. Therefore, we override the XYZ properties and retrieve them how they should be retrieved.

    Secondly, if you were thinking about concept of object inheritance in realation to our OM for the first time, this would be an appropriate diagram to draw:


    However, upon closer inspection of the descriptors, there are attributes that both NpcObject and PlayerObject both have, and they are obtained in exactly the same way (for example, health is obtained from UnitFields+HealthOffset). Why dont we make a base class for both of these two that incorporate this 'sameness'. Note: this class will never actually be used. An in game object can be a NpcObject, or a PlayerObject, which both inherit things from CreatureObject, however you can never be just a CreatureObject.

    Here is our updated diagram:


    Note that the code provided above already has these changes. Now if we have an NpcObject named John, we can write code like this:

    Code:
    MessageBox.Show("Johns health is: "+John.CurrentHealth.ToString());
    And Johns health would automatically be read and returned to us.

    Object Manager

    Now that we have the objects that we will be using downpat, lets look again at what our OM needs to do:

    - Our OM needs a way to 'load' and find the base address of the in-game Object Manager.
    - Our OM needs to iterate through the in-game Object Manager and get two peices of information about each object - the base address, and the type. Using this information, we can create a new "WowObject" and store it.
    - Our OM needs to be able to store all the objects (arrays of WowObjects anyone?)
    Before we start doing some coding, we need to think about who will be using this class. Do we need more than one of these OM's? It depends. Are we going to be getting information from multiple copies of WoW? In most cases, we're only going to be worrying about one copy of WoW at a time. Instead of having to make new copies of our OM, lets make it static. Thefore, instead of using this code:

    Code:
    ObjectManager myObjectManager = new ObjectManager();
    myObjectManager.DoSomething();
    We're able to just do this:
    Code:
    ObjectManager.DoSomething();
    If you look in the above code for the WowObjects, they are getting ObjectManager.WowReader to do something. What is WowReader? In this project, I decided the only memory reading I was going to need to do was to enumerate through the linked list of objects and pull data about them. So it seems reasonable then to include another object, a memory reading object inside of our Object Manager. I can't remember where I found this MemoryReader .dll, or whom the author is unfortunately.
    Edit: Seem's I have been using alek900's (perhaps private) memory reading dll by accident. But you should be able to apply the concepts to any decent memory reading class.

    So far, this is what our ObjectManager class looks like:
    Code:
    static class ObjectManager
    {
    
    public static Memory WowReader = new Memory();
    }
    Now, whenever we're doing any work with the in-game Object Manager, we need to find it's address. Granted, this isn't hard, but it is worth having a method for. Also, we need a place to store the base address of the in-game Object Manager, as well, and also have some meaningful constants that represent what addresses we're going to be working with.

    Code:
    static class ObjectManager
    {
    
    public static Memory WowReader = new Memory(); private const uint staticClientConnection = 0x011CB310, // client connection, same address every boot objectManagerOffset = 0x28A4, // offset from the ClientConnection to the object manager localGuidOffset = 0xC0, // offset from the object manager to the local guid firstObjectOffset = 0xAC, // 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 private ulong localGuid; // the local guid. public static void LoadAddresses() {
    WowReader.SetProcess("Wow", "read"); objectManagerBase = WowReader.ReadUInt32((IntPtr)(WowReader.ReadUInt32((IntPtr)(staticClientConnection)) + objectManagerOffset)); localGuid = WowReader.ReadUInt32((IntPtr)(objectManagerBase + localGuidOffset));
    }
    }
    I'll just quickly describe the method that we've added. It is the job of LoadAddresses to find out the base address of the object manager, and our local players guid. The first line lets our memory reading class know that we will be reading from WoW.exe.

    But why did we get our local players Guid? Can't we simply access it through our WowObjects properties (SomeObject.Guid)? We most certainly could do that, and that would work to get the guid of any object. But how do we know which object is ourselves? Say we load a list of 10 objects into an imaginary array. The only details about these objects that we know are the base address and type.

    Code:
    WowObject[] ImaginaryArray = new WowObject[9];
    ImaginaryArray.ImaginaryFill();
    Now that we've put that information in there, we can get the guid of any object. But how do we know which object is ourselves, just by our guid? That is why we retrieve our players guid beforehand. Basically, by storing our local guid before hand, we have a way to single out the object that references our local player in-game.

    No doubt that the object whose information we want to know most is the local player. Lets add in an easy way to access information about our local player. Just before LoadAddresses(), put this in:

    Code:
    public static PlayerObject LocalPlayer;
    Soon, we will able to access information about the local player from any part of our code, eg: ObjectManager.LocalPlayer.CurrentHealth;

    Now we need a way to store our objects. We're going to store all of our objects in different IDictionary's, one dictionary for each type of object we will be dealing with. We could have stored them all in one array of WowObjects, but then we would need to deal with complicated issues of downcasting.

    But what is an IDictionary? An IDictionary is basically an easy to use array. When declaring the IDictionary, you give it two values: the key for accessing, and the value it will hold. The keys for an IDictionary need to be unique, so we're going to use our WowObjects Guid's, and the values are going to be the WowObjects themselves. Just under "public static PlayerObject LocalPlayer", add this:

    Code:
    public static IDictionary<ulong, PlayerObject> PlayerObjectList = new Dictionary<ulong, PlayerObject>();
    public static IDictionary<ulong, NpcObject> NpcObjectList = new Dictionary<ulong, NpcObject>();
    public static IDictionary<ulong, GameObject> GameObjectList = new Dictionary<ulong, GameObject>();
    Of course, you can add an IDictionary for the missing objects yourself. Now pretend for a moment our IDictionary's were full of objects. We had the guid of a creature who was attacking us, and we wanted to find out its health. How would we do that? By the magic of IDictionarys!

    Code:
    ulong AttackingMonsterGuid = GetAttackingMonsterGuid();
    int MonsterHealth = ObjectManager.NpcObjectList[AttackingMonsterGuid].CurrentHealth;
    This is all fine and dandy, but we don't have any data to work with at the moment, all we have are empty IDictionarys. We need a way to populate our lists, and we should be able to do this whenever we want. Lets add a new method to our OM - PopulateLists

    Code:
    public static void PopulateLists()
    {
     
    }
    To start off we want to clear out all of our current lists - if we don't, we're going to end up with multiple copies of each object.

    Code:
    PlayerObjectList.Clear();
    NpcObjectList.Clear();
    GameObjectList.Clear();
    To iterate through the object list, we're going to need somewhere to store the data we need (base address and type) before we actually make a new object. Lets make a generic WowObject to handle this. We also know the base address of the first object in the in-game Object Manager, so thats where we will start reading from.

    Code:
    WowObject CurrentObject = new WowObject(WowReader.ReadUInt32((IntPtr)(objectManagerBase + firstObjectOffset)));
    Now we're going to loop through the in-game Object Manager from first object to last, so lets open a while loop. It should look something like this: while the object we're reading from is a valid object, read the base address and the type of the object, then add a new object to the list that corrosponds to the obejects type, giving it a base address. Doesn't seem too hard. Thus I give you:

    Code:
    public static void PopulateLists()
    {
        PlayerObjectList.Clear();
        NpcObjectList.Clear();
        GameObjectList.Clear();
     
        WowObject CurrentObject = new WowObject(WowReader.ReadUInt32((IntPtr)(objectManagerBase + firstObjectOffset)));
     
        while (CurrentObject.BaseAddress != 0 && CurrentObject.BaseAddress % 2 == 0)
        {
            if (CurrentObject.Type == 3)  // a npc
                NpcObjectList.Add(CurrentObject.Guid, new NpcObject(CurrentObject.BaseAddress);
            if (CurrentObject.Type == 4) // a player
                PlayerObjectList.Add(CurrentObject.Guid, new PlayerObject(CurrentObject.BaseAddress);
            if (CurrentObject.Type == 5) // a gameobject
                GameObjectList.Add(CurrentObject.Guid, new GameObject(CurrentObject.BaseAddress);
     
            CurrentObject.BaseAddress = WowReader.ReadUInt32((IntPtr)(CurrentObject.BaseAddress + nextObjectOffset));
        }
    }
    What the last line does is it changes the base address of CurrentObject to the base address of the next object in the list (effectively setting CurrentObject to equal the next object).

    A final thing...
    The most commonly accessed object in our OM is going to be the local player (to see our current health, our position, etc). We can now access the local player from any of our code doing this (assuming you have called PopulateLists() beforehand:

    Code:
    int OurHealth = ObjectManager.PlayerObjectList[ObjectManager.localGuid].CurrentHealth;
    However, lets add a a little extra goody to make our code easier to read, and easier to type. In our ObjectManager class, add this line up the top somewhere near the declarations:

    Code:
    public static PlayerObject LocalPlayer;
    Change this line in PopulateLists():

    Code:
    if (CurrentObject.Type == 4) // a player
        PlayerObjectList.Add(CurrentObject.Guid, new PlayerObject(CurrentObject.BaseAddress);
    to this:

    Code:
    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];
    }
    And you should be good to go! Happy hacking (or memory reading, enumerating, being nerdy, etc.) :wave:
    Last edited by jbrauman; 02-15-2009 at 12:47 AM. Reason: finishing guide

    [Guide-kind of] How I handle objects.
  2. Thanks someone_else (1 members gave Thanks to jbrauman for this useful post)
  3. #2
    SKU's Avatar Contributor
    Reputation
    306
    Join Date
    May 2007
    Posts
    565
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I hope my post isn't somehow destroying your well structured guide. Feel free to contact a mod to have this post deleted. This is going to be a very helpful look-up thread. +2rep 'cause I can.

  4. #3
    Pixion's Avatar Member
    Reputation
    59
    Join Date
    Jan 2008
    Posts
    289
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks to you.

  5. #4
    naa's Avatar Contributor
    Reputation
    100
    Join Date
    Oct 2006
    Posts
    63
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Nice guide, thank you +Rep

  6. #5
    jbrauman's Avatar Member
    Reputation
    65
    Join Date
    Dec 2007
    Posts
    72
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Hyru View Post
    Why do you have "Object" at the end of all your classes? Just because they are objects in WoW doesn't mean your naming convention has to suffer.
    This is just how I do it. Makes it clearer for me, other people can do it any way they want. Each to thier own. I'm using code that is actually in my projects, and that was the way I did it.

  7. #6
    jbrauman's Avatar Member
    Reputation
    65
    Join Date
    Dec 2007
    Posts
    72
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Finished the guide. Tell us if there are any mistakes.

  8. #7
    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)
    It's a matter of opinion, but I prefer to use the static pointer to the playerbase instead of looping through the object manager for it. 3 reads are faster than (num objects)*(2) (worst case scenario)
    "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

  9. #8
    RiseAndShine's Avatar Member
    Reputation
    18
    Join Date
    Jan 2009
    Posts
    27
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Yeah nice write-up! Reminded me that i'll desperately needed to refactor my code. I've been throwing everything in one big LinkedList, with every object being the same class. :> So now after not being able to successfully compile this mess for some hours, i got nice inheritance and HashTables, too! yay.
    Although I prefer to pre-read all fields of an object in a threaded loop, rather than reading them as you request them.

  10. #9
    jbrauman's Avatar Member
    Reputation
    65
    Join Date
    Dec 2007
    Posts
    72
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by RiseAndShine View Post
    Although I prefer to pre-read all fields of an object in a threaded loop, rather than reading them as you request them.
    This is what I was doing at first - but I found it was entirely unnecessary. You don't need ALL the information on ALL the objects at once - and reading so much from Wow, ALL the time, creates alot of in-game lag and unnecessary reading.

  11. #10
    g3gg0's Avatar Active Member
    Reputation
    32
    Join Date
    Mar 2008
    Posts
    86
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    some additional code to creatureobject

    Code:
        protected const int BuffCountOffset = 0xC58;
        protected const int BuffTypeOffset = 0xDE0;
        protected const int BuffTableOffset = 0xDE4;
        protected const int BuffBaseOffset = 0xC5C;
        protected const int BuffEntrySize = 24;
    
        public UnitBuffInfo GetUnitBuffInfo( int pos )
        {
            UnitBuffInfo result = null;
            int addr = 0;
    
            if (pos >= GetUnitBuffCount())
                return result;
            else
            {
                if (WoW.ReadInteger(baseAddress + BuffTypeOffset) != 0)
                    addr = WoW.ReadInteger(baseAddress + BuffTableOffset);
                else
                    addr = baseAddress + BuffBaseOffset;
            }
    
            return new UnitBuffInfo(WoW, addr + BuffEntrySize * pos);
        }
    
        public UnitBuffInfo[] GetUnitBuffInfo() /* didnt test since thats too expensive */
        {
            UnitBuffInfo[] result = null;
            int addr = 0;
            int entries = GetUnitBuffCount();
    
            result = new UnitBuffInfo[entries];
    
            if (WoW.ReadInteger(baseAddress + BuffTypeOffset) != 0)
                addr = WoW.ReadInteger(baseAddress + BuffTableOffset);
            else
                addr = baseAddress + BuffBaseOffset;
    
            for (int pos = 0; pos < entries; pos++)
                result[pos] = new UnitBuffInfo(WoW, addr + BuffEntrySize * pos);
    
            return result;
        }
    
        public int GetUnitBuffCount()
        {
            return WoW.ReadInteger(baseAddress + BuffCountOffset);
        }
    Last edited by g3gg0; 02-11-2009 at 09:04 PM.

  12. #11
    bugs181's Avatar Member
    Reputation
    5
    Join Date
    Feb 2009
    Posts
    6
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Great guide [Request]

    I know this guide is for learning purposes. But could I perhaps request you upload demo source code? By the way, great tut/guide!! +Rep

  13. #12
    SKU's Avatar Contributor
    Reputation
    306
    Join Date
    May 2007
    Posts
    565
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The entire source code is in the [.code] brackets.

  14. #13
    alek900's Avatar Contributor
    Reputation
    103
    Join Date
    Nov 2007
    Posts
    101
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    wow, I need to rewrite some of stuff now :P

    also,
    Code:
    int Aggro_Range= 17 - (Playerlvl - Creaturelvl);
    if (Aggro_Range > 45)
         Aggro_Range = 45;
    else if (Aggro_Range < 5)
         Aggro_Range = 5;
    19+4 that means i score

  15. #14
    bugs181's Avatar Member
    Reputation
    5
    Join Date
    Feb 2009
    Posts
    6
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    *Hits head*

    WOW! Dumb me.. I was requesting the source code because I didn't fully understand how this all fit together. After reading it, then re-reading it, and about 5 re-reads later, I understand it.

    It could be the fact that I don't understand the C# syntax all the much.
    I'm more of a C++ person. Yes, the two are similar, but their both different in various ways.

    However, I am finally grasping the concept to all this, mostly due to putting this together
    AND Kynox’s WoW Object Dumper source code together.

    You can then see the differences, and how it all comes together.
    The most confusing for me to understand was how the WoW reader was reading from memory.

    Anyways, sorry for the ramble. Definitely a great guide - keep up the amazing work.
    +Rep from me, sorry for the stupid request earlier.

    -Bugz

  16. #15
    jbrauman's Avatar Member
    Reputation
    65
    Join Date
    Dec 2007
    Posts
    72
    Thanks G/R
    0/1
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by bugs181 View Post
    WOW! Dumb me.. I was requesting the source code because I didn't fully understand how this all fit together. After reading it, then re-reading it, and about 5 re-reads later, I understand it.

    It could be the fact that I don't understand the C# syntax all the much.
    I'm more of a C++ person. Yes, the two are similar, but their both different in various ways.

    However, I am finally grasping the concept to all this, mostly due to putting this together
    AND Kynox’s WoW Object Dumper source code together.

    You can then see the differences, and how it all comes together.
    The most confusing for me to understand was how the WoW reader was reading from memory.

    Anyways, sorry for the ramble. Definitely a great guide - keep up the amazing work.
    +Rep from me, sorry for the stupid request earlier.

    -Bugz
    It took me a long time to understand how to do it as well, but once you get your head around the idea its easier. Just updated the static client connection offset to the 3.0.9 one
    Last edited by jbrauman; 02-15-2009 at 12:48 AM.

Page 1 of 6 12345 ... LastLast

Similar Threads

  1. [Guide] How I handle log files!
    By Viano in forum Programming
    Replies: 0
    Last Post: 01-09-2010, 03:36 PM
  2. [Guide]How to build Objects in your server [EASY FAST STEPS]
    By matafakas in forum WoW EMU Guides & Tutorials
    Replies: 26
    Last Post: 03-07-2009, 01:48 PM
  3. [Guide] How to handle beggers
    By manowarlock in forum World of Warcraft Guides
    Replies: 23
    Last Post: 11-08-2008, 09:55 PM
All times are GMT -5. The time now is 04:18 PM. 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