ObjectManager, Learning is hard! My journey to learning how to make a WoW Bot. menu

User Tag List

Results 1 to 11 of 11
  1. #1
    asdfowkw92's Avatar Member
    Reputation
    9
    Join Date
    Feb 2019
    Posts
    6
    Thanks G/R
    1/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    ObjectManager, Learning is hard! My journey to learning how to make a WoW Bot.

    Hello OwnedCore!

    CURRENT STATE
    Currently I'm looking to learn how to cast a spell by hooking into the endscene, god I hope I'm on the right track here xD
    Introduction
    My name is Johnny and I have at multiple ocassions over the years thought about learning how to make a WoW bot, I've started many times and failed it just as many times.

    I'm older, wiser and now I know that it will take some serious time, but I have decided to actually learn it this time.

    What I realize is that I will need to learn how the objectmanager works and that I cannot jump straight into making something like honorbuddy straight away but I have also realized that I will need somewhere to ventilate and ask my questions so here I am.

    What I have decided to do is to work with the 2.4.3 client for various reasons and after reading pretty much all threads I could find while searching this forum I've decided to start off by trying to make an injected fishing bot in C#.

    But before I get to that I will need to get a better understanding about getting all objects etc, so I thought I'll make this thread and keep my questions in one place over the course of learning instead of spamming the forums.

    What I have so far is an account on a 2.4.3 realm to work with.
    I have found a version of BlackMagic 1.1 which seems to be working.
    And ive made my project and attached it to the WoW client.
    Now for my very first question, I've understood that everything needs to be relative to the BaseAdress of WoW, which is obvious when thinking about it.
    But when I try to get my health value from the Playerbase, which I get from adding the offset to the Baseadress (?) I dont get anything.
    This is my code so far

    Code:
                magic = new BlackMagic();
                if (magic.OpenProcessAndThread(SProcess.GetProcessFromProcessName("Wow")))
                {
                    Console.WriteLine("Attached to WoW!");
                    IntPtr BaseWoW = magic.MainModule.BaseAddress; //Get the baseadress of WoW
                    uint playerBase = magic.ReadUInt(magic.ReadUInt((uint)BaseWoW) + 0x00E29D28); //Get the playerbase - WRONG!
                    uint PlayerHealth = magic.ReadUInt(playerBase + 0x40); //Add Health offset to the playerbase to get the health value.
                }
    Now what I suspect is that I've gotten something completely around my backfoot and that the playerbasecode above is incorrect?

    Edit 1:

    Thanks to Jadd we know that this code is wrong because of an, may i say typo?, error where I put one to many ReadUInt so instead of adding the BaseAddress to the offset I added the uint located at the BaseAddress.

    So the correct code would've been.

    Code:
    magic = new BlackMagic();
                if (magic.OpenProcessAndThread(SProcess.GetProcessFromProcessName("Wow")))
                {
                    Console.WriteLine("Attached to WoW!");
                    IntPtr BaseWoW = magic.MainModule.BaseAddress; //Get the baseadress of WoW
                    uint playerBase = magic.ReadUInt((uint)BaseWoW + 0x00E29D28); //Get the playerbase - This is the line that was faulty
                    uint PlayerHealth = magic.ReadUInt(playerBase + 0x40); //Add Health offset to the playerbase to get the health value.
                }
    Now even when I change this I personally still get an error saying that ReadUInt failed. So, and I don't know if this is the correct way to do this, I figured out that instead of trying to access the playerbase like this and getting health from it I made a class which gets the uint of the objectmanager and then iterates through with the nextObject offset until it finds an object with the object type 4 (PLAYER).

    Code:
    uint ClientConnection = magic.ReadUInt((uint)Offsets.General.ClientConnection);
                ClientConnection = magic.ReadUInt(ClientConnection + (uint)Offsets.ObjectManagerOffsets.ObjectManagerOffset);
                uint nextObject = magic.ReadUInt(ClientConnection + (uint)Offsets.ObjectManagerOffsets.FirstObject);
                Objects.Clear();
                isPlayer = false;
                while ((nextObject != 0) && ((nextObject & 1) == 0))
                {
    
                    Player obj = new Player(nextObject, magic);
                    Objects.Add(obj);
                    nextObject = magic.ReadUInt(nextObject + (uint)Offsets.ObjectManagerOffsets.NextObject);
                    if (obj.Type == 4 && !isPlayer)
                    {
                        player = obj;
                        isPlayer = true;
                    }
                }
    Then with this player object I get the health by using the current nextObject value as a BaseAddress and adds the health offset to that like this

    Code:
    magic.ReadInt(magic.ReadUInt(BaseAddress + (uint)Offsets.ObjectManagerOffsets.FieldOffset) + (uint)Offsets.ObjectOffsets.Health);
    Where BaseAdress is the value of nextObject passed along from the objectmanager class.

    Is this the way to go or am I doing something wrong with the first code?

    Edit 2:

    After some more testing I realize that ALL players will be of type 4, and even if MY character will always be the first encounter of type 4 (not sure thats even true) there has to be a better way to get MYSELF.

    So back to the drawingboard and trying to figure out why my playerBase uint fails.

    Edit 3: Now the Journey truly begins!

    Okey! So up until now, all the above stuff, was basically just getting warm in the clothes. Just to get started and doing something.

    Now we are gonna start working on the real stuff! The goal in the future is to be able to make what I want to make when it comes to the WoW Bot. But for starters I've decided to go with a fishing bot cause I think this will force me to learn alot of good stuff that I will for sure need in the future.

    Things that I have to learn to be able to make a fishing bot (with injection, not pixelsearching or so)

    TODO LIST
    1. Find the local player in the object manager (I've got a solution for this without the playerbase for now, you'll see!)
    2. Need to figure out to see if the player is channeling fishing, if not, cast the fishing spell.
    3. Look for all fishing bobbers in the area.
    4. Look for the fishing bobber that is created by the player. (would be pretty dumb if we tried to steal someone elses fish right?)
    5. Find out if the bobber is splashing or not so we know when to interact with it.
    6. Interact with the fishing bobber when its splashing.
    So now when we got our "Base todo list" let's dive into it!

    1. Finding the local player in the object manager.

    To do this all I've done is iterate through the object managre and checking the objects for the TYPE and the GUID.

    If the type is 4 its a player object. If the GUID matches with our LocalGUID we know its the Local Player.
    2. Find out if we are currently channeling fishing otherwise do it.

    Now, this part is actually way ahead of me right now. The first part of it I've managed to do, to see if I'm currently channeling the fishing spell all I've done is reading from the local player objects base address + 0xF58 offset, and IF it is channeling it will return the spellID of the fishing skill as an integer. So that problem is solved.

    Now onto casting the fishing spell if its not already channeling, this is where it (for me) get's really tricky since its in unexplored waters. From the top of my head there's some different approaches to this. I can either just make it write in chat /cast Fishing not very sofisticated but would work for sure but thats not what I want to do, I want to be able to run this thing in background mode so it seems that the only way I should be approaching this is by hooking into endscene and using som ASM. The big problem now is that this I know absolutely NOTHING about ! So for now its off to searching and browsing these forums about hooking into endscene to cast the spell.


    Thankslist:
    I want to contribute a list of people that I'm thankful to for helping me during my journey.

    Jadd
    Last edited by asdfowkw92; 02-16-2019 at 10:56 AM. Reason: Cleanup the post

    ObjectManager, Learning is hard! My journey to learning how to make a WoW Bot.
  2. Thanks Nyarly, Kenneth, gustav10000 (3 members gave Thanks to asdfowkw92 for this useful post)
  3. #2
    Jadd's Avatar 🐸 Premium Seller
    Reputation
    1511
    Join Date
    May 2008
    Posts
    2,432
    Thanks G/R
    81/333
    Trade Feedback
    1 (100%)
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Congrats on beginning! That's always the hardest step.

    1. You have the mistake that you are not adding the *base address* of WoW, but instead adding the uint value contained at the base address (start of the PE header - ie. garbage.) See the difference?
    Code:
    *wrong*    uint playerBase = magic.ReadUInt(magic.ReadUInt((uint)BaseWoW) + 0x00E29D28);
    *right*    uint playerBase = magic.ReadUInt((uint)BaseWoW + 0x00E29D28);
    2. Descriptors. Always trips up the newcomers, don't fret. Read this: *click* (Explanation of release info dumps).

    Let me know how it goes.

  4. Thanks asdfowkw92, Nyarly (2 members gave Thanks to Jadd for this useful post)
  5. #3
    asdfowkw92's Avatar Member
    Reputation
    9
    Join Date
    Feb 2019
    Posts
    6
    Thanks G/R
    1/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Jadd View Post
    Congrats on beginning! That's always the hardest step.

    1. You have the mistake that you are not adding the *base address* of WoW, but instead adding the uint value contained at the base address (start of the PE header - ie. garbage.) See the difference?
    Code:
    *wrong*    uint playerBase = magic.ReadUInt(magic.ReadUInt((uint)BaseWoW) + 0x00E29D28);
    *right*    uint playerBase = magic.ReadUInt((uint)BaseWoW + 0x00E29D28);
    2. Descriptors. Always trips up the newcomers, don't fret. Read this: *click* (Explanation of release info dumps).

    Let me know how it goes.
    Thanks for reply! Yes, that makes alot of sense ! I'm still reading the link but just wanted to add in that even when adding the baseadress in the correct way I get an error saying "ReadUint failed". So Still gotta do some more tinkering and searching to try to figure this out !

    My first thought is that of "Is the baseadress from magic.MainModule.BaseAddress correct?" further research to be done!
    Last edited by asdfowkw92; 02-15-2019 at 10:19 AM.

  6. Thanks Nyarly (1 members gave Thanks to asdfowkw92 for this useful post)
  7. #4
    asdfowkw92's Avatar Member
    Reputation
    9
    Join Date
    Feb 2019
    Posts
    6
    Thanks G/R
    1/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So, if (IF!) I understand this correctly, I cannot just get the playerbase like this? I have to make a clientconnection and get the objectmanager and iterate through the objectmanager until i find an object that has the object type of a player?

    Edit: Not sure if its the correct way to go, but its working if I do it this way, updating mainpost until further replies
    Last edited by asdfowkw92; 02-15-2019 at 11:41 AM.

  8. #5
    asdfowkw92's Avatar Member
    Reputation
    9
    Join Date
    Feb 2019
    Posts
    6
    Thanks G/R
    1/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm really disoriented here now^^ Sometimes uint playerBase = magic.ReadUInt(BaseWoW + 0x00E29D2; does work after restarting the wow client a couple times, and then after restarting again it might not work but instead throw the "readUInt failed" error.

  9. #6
    Nyarly's Avatar ★ Elder ★ Lorekeeper of Exploration
    Reputation
    1090
    Join Date
    Aug 2007
    Posts
    1,650
    Thanks G/R
    367/314
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    nice, I'll be reading your journey, I also want to learn that. Keep faith, and have fun !

  10. #7
    Kenneth's Avatar ★ Elder ★ WTB XRP Authenticator enabled
    Reputation
    1642
    Join Date
    Aug 2012
    Posts
    1,527
    Thanks G/R
    1063/788
    Trade Feedback
    8 (100%)
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    this is a cool story, thanks for sharing ! Look forward to more

  11. #8
    asdfowkw92's Avatar Member
    Reputation
    9
    Join Date
    Feb 2019
    Posts
    6
    Thanks G/R
    1/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So have I understood this correctly, if I want to cast a spell for example, I can either emulate keyboard pressing (not backgroundmode friendly), or I can hook endscene and inject ASM code? or is there an easier way to do it and still keep it background mode?

    Things that I need to be able to do is ofcourse more than just casting a spell. Targeting, Interacting etc.

    Edit: And if ASM is the way to go, (i have no experience at all of it), will this give me a good enough understanding to start doing something? Assembly Programming Tutorial

  12. #9
    asdfowkw92's Avatar Member
    Reputation
    9
    Join Date
    Feb 2019
    Posts
    6
    Thanks G/R
    1/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Let's say like this, I have found out how to do this all. I have it on black & white, right infront of me, how to cast fishing, find my own bobber, find when it splashes, interact with it, everything. I have EVERYTHING I need to make a working fishing bot for starters =) But I do NOT fully understand it, so I will not update main post on how to do this until I understand it myself, but just wanted to post a quickie here that I havnt given up and that I'm close to understanding it =) ! But probably a few more days ^^

  13. #10
    ejt's Avatar Contributor
    Reputation
    209
    Join Date
    Mar 2008
    Posts
    166
    Thanks G/R
    3/111
    Trade Feedback
    0 (0%)
    Mentioned
    4 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by asdfowkw92 View Post
    So have I understood this correctly, if I want to cast a spell for example, I can either emulate keyboard pressing (not backgroundmode friendly), or I can hook endscene and inject ASM code? or is there an easier way to do it and still keep it background mode?
    You can either do it passively (out-of-process) by sending key presses (SendMessage) or writing ASM code-caves that execute WoW functions.

    Or you can do it actively (in-process/injected) by calling functions directly.

    The injected method is obviously much easier if you're unfamiliar with ASM and how to inject code-caves. Sending key presses is not hard but you need to figure out what keys to send so that gives you the option of either having a static list of keys for each spell (if you move keybind you need to edit this list) or reading the actionbar keybindings automatically but that requires some extra work.

    Injecting is more dangerous because this gives WoW the ability you detect you easier if your software is publicly available, however if you're doing this for yourself and not interested in sharing your code then I would chose to inject.

    If you go the injection route you need to have a method of "ticking" your software, calling your update functions and eventually execute some action (eg. casting spell). The easier solution for this is to hook EndScene, this is probably what you want.

    When you are inside the endscene you also have the option to directly call LUA code in WoW because these functions can only be called from the main thread of WoW, there are multiple examples of this on the forum.

    As for the fishing part, this is my fishing script that pretty must explains the steps. (LUA)

    Code:
    local lastCast = 0
    local castCounter = 0
    
    local SPELL_FISHING = Spell(131474)
    
    function Tick(event, player)
    	bobber = player:GetFishingBobber()
    
    	if not bobber then
    		if (os.clock() - lastCast > 1 or lastCast == 0) and SPELL_FISHING:CanCast() then
    			SPELL_FISHING:Cast(player)
    			lastCast = os.clock()
    			castCounter = castCounter + 1
    		end
    	else
    		if bobber:IsBobbing() then
    			bobber:Interact()
    		end
    	end
    end
    
    RegisterGameEvent(1, Tick)
    GetFishingBobber does this: (C++) where GO_FISHING_BOBBER is the entry id 35591 for normal fishing bobber.

    Code:
    std::shared_ptr<GameObject> ActivePlayer::GetFishingBobber()
    {
    	std::vector<GameObjectPtr> objects = sFramework.GetGameObjects();
    
    	for (GameObjectPtr obj : objects)
    		if (obj->GetCreatedBy() == GetGUID() && obj->GetEntry() == GO_FISHING_BOBBER)
    			return obj;
    
    	return nullptr;
    }
    CanCast does sanity checks like if the spell is on cooldown, if it is known by the player and some more things.
    Cast does some more sanity checks and casts the spell fishing
    IsBobbing reads the memory of [Object + 0xA4] and that is either 0 if the gameobject is not bobbing or 1 if the object is bobbing (splashing in water or whatever you want to call it).
    Interact does exactly what you thing, it interacts with the object.

    Obviously before anyone responds to me saying "You're wrong you can also do <insert complex method here>" and "Its easier to do <insert easier method here>", the things I explained here is not the end-all of things because you can do it in so many different ways but it should give you a better understanding on the process of getting a simple fishing bot working. The code given here also needs a working object manager, function offsets and a way to call them etc.

    As for the spell casting, this is where things get more complicated (or easier). You can do it by directly calling LUA (needs to be inside main thread as explained above) or you can call the spell cast functions directly if you're injected. If you're really adventurous you can do ASM code-caves to call the functions.

    The steps that wow takes when casting a spell is basicly this:

    * Gets the slot id based on spell id (slot id is related to spellbook slot)
    * if slot id < 0 then it is a pet spell
    * if slot id >= then call cast function

    Casting spells is not as easy as calling a function that takes spell id and optionally target as parameters, there is a lot more to it than this, if you'd like I can PM you some code that can help you understand it better.

    Pretty much:
    LUA easy
    Functions medium
    ASM hard

    Hope this helps.

  14. #11
    counted's Avatar Contributor Authenticator enabled
    Reputation
    203
    Join Date
    Mar 2008
    Posts
    183
    Thanks G/R
    11/108
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    what os are you is on your computer? if your code works sometimes you could be running into a x64 / x32 issue. If the wow.exe loads into the lower portion of the memory map a mistake that types an x64 address as x32 will actually work. next time you load wow and it loads into x64 high memory it will not.

    to figure out if this is your problem keep track of MainModuleBaseAddress for each run and if it is a low base address for working attempts and a high one for non working, this is your problem.

Similar Threads

  1. [Guide] How to make a Wow bot for complete newbs!
    By gononono64 in forum WoW Memory Editing
    Replies: 65
    Last Post: 11-18-2012, 03:12 AM
  2. Replies: 12
    Last Post: 06-12-2010, 12:39 PM
  3. What is the sinplest way to make a private server
    By Spitty305 in forum World of Warcraft Emulator Servers
    Replies: 7
    Last Post: 09-07-2007, 04:01 PM
  4. My journey to quel'thelas [hacks]
    By JuggaloDude in forum World of Warcraft Exploits
    Replies: 16
    Last Post: 07-05-2007, 04:50 PM
  5. My journey to quel'thelas [hacks]
    By JuggaloDude in forum World of Warcraft Exploration
    Replies: 12
    Last Post: 06-12-2007, 04:33 PM
All times are GMT -5. The time now is 06:37 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