Writing Bots with Robot-js menu

User Tag List

Page 1 of 7 12345 ... LastLast
Results 1 to 15 of 97
  1. #1
    Torpedoes's Avatar ★ Elder ★ Doomsayer
    Authenticator enabled
    Reputation
    1147
    Join Date
    Sep 2013
    Posts
    956
    Thanks G/R
    148/415
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Writing Bots with Robot-js

    ABOUT
    To celebrate the release of Robot, I have created some quick demos to show off its capabilities. Each day for the next eight days, I'll be showing practical examples of code which implements a part of a WoW bot. Obviously, this is nothing we haven't seen before, but it'll still be a good learning experience for many wishing to write bots. All code here will be written in JavaScript (nothing to do with Java) and is compatible with WoW 6.2.4.21463 for Windows (not being kept up to date). Hopefully by the end, you will see the benefits of writing bots in JavaScript and maybe even develop some of your own to showcase here! I look forward to your feedback and suggestions.

    WHY JAVASCRIPT?
    Traditionally, bots have been written in C++, C#, VB.net and AutoIt. And that's been fine for many years. The problem is that some of these languages are really complicated for beginners (C++). Some are not entirely platform-independent (C#, VB.net, and AutoIt). Some are antiquated (VB.net). And some lack the power of other programming languages (AutoIt). Furthermore, all of these languages suffer from the fact that you have to write a lot of things yourself, things like libraries to write a bot.

    All these problems have been plaguing the botting community for years. But how can we fix them? Well, since the introduction of Node.js in 2009, we've seen a massive explosion of interest in JavaScript. Thousands of libraries doing all sorts of neat things have been written, and with the new language specifications, JavaScript has never looked more attractive. Some advantages of JavaScript include that it's very easy to pick up, a lot of developers already know how to use it, it has a thriving community and it's completely cross-platform. Furthermore, because there is no compile step you can just write your program and run it!

    Sounds great right? But how can you use it to write bots? The answer is to use robot-js. This library is the final missing link enabling everyone to write system automating bots for any purpose. And in keeping with the JavaScript tradition, no compiler is needed. Just write and run!

    SAFETY
    Exactly how safe are these bots? Well, since this is the first time we've seen something like this, I have no idea. But I suspect writing bots in JavaScript is arguably the safest method to use. All code is run by the V8 interpreter running within "Node.exe" and if ran in admin mode, regular applications will have no idea what code is actually being ran. The only way to detect it is if you were to directly modify some code in the target application.

    GET STARTED
    Start by downloading Node.js, as of the time of this writing I recommend getting 6.0. Then create a folder to contain the project. With the command line, cd into your folder and type "npm install robot-js" (no quotes). You're now ready to write bots. You can download any other library you wish but for the purposes of these demo's, only robot-js is required.

    For these demo's, there are three files which are used by all eight demos, think of it as a primitive library for implementing common functionality. The code for these files is below. Each demo consists of a single file which is ran with "node <name_of_demo>.js" (no quotes). All demo's are console applications and have no UI associated with them.

    DISCLAIMER
    None of the code in the demos infringe on anybody's copyright. The demos should also only be used for educational purposes, specifically for the purposes of learning robot-js. You should never use these demos to break the terms of service of any software. The author(s) of these demos cannot be held liable for any damages caused by the code. By downloading and using the code, you agree to do so at your own risk. All these demos are licensed under the ZLib license.

    DEMOS

    COMMON CODE
    Includes three files implementing common functionality used by all eight demos. app_controller.js implements the main event loop. game_instance.js represents an instance of WoW, along with helpers to select it. offsets.js represents common memory offsets used by all eight demos.

    app_controller.js
    Code:
    "use strict";
    
    //----------------------------------------------------------------------------//
    // Constants                                                                  //
    //----------------------------------------------------------------------------//
    
    const GameInstance = require ("./game_instance");
    
    
    
    //----------------------------------------------------------------------------//
    // Export                                                                     //
    //----------------------------------------------------------------------------//
    
    module.exports = class
    {
        ////////////////////////////////////////////////////////////////////////////////
        /// Creates a new application controller
    
        constructor (updateRate, updateFunc)
        {
            this._updateRate = updateRate;
            this._updateFunc = updateFunc;
    
            this._gameInstance = new GameInstance();
            console.log ("Select a WoW Window...");
    
            this._heartbeat();
        }
    
        ////////////////////////////////////////////////////////////////////////////////
        /// Main event loop executed by the heartbeat
    
        _eventLoop()
        {
            // Waits for a game to get selected
            if (!this._gameInstance.isSelected())
            {
                this._gameInstance.selectByActiveWindow();
                return;
            }
    
            // Ensures the game is still running
            if (!this._gameInstance.isRunning())
            {
                console.log ("Select a WoW Window...");
                this._gameInstance.deselect(); return;
            }
    
            // Checks whether the player is in-game
            if (!this._gameInstance.memory.readBool
                (this._gameInstance.offsets.GameState +
                 this._gameInstance.module)) return;
    
            // Call the specified update function
            this._updateFunc (this._gameInstance);
    
            // Don't forget to reset memory cache
            this._gameInstance.memory.clearCache();
        }
    
        ////////////////////////////////////////////////////////////////////////////////
        /// Performs heartbeat and enqueues the next one
    
        _heartbeat()
        {
            this._eventLoop();
            setTimeout (() =>
                this._heartbeat(),
                this._updateRate);
        }
    };
    game_instance.js
    Code:
    "use strict";
    
    //----------------------------------------------------------------------------//
    // Constants                                                                  //
    //----------------------------------------------------------------------------//
    
    const Robot   = require ("robot-js" );
    const Offsets = require ("./offsets");
    
    // Shortcuts to Robot classes
    const Process = Robot.Process;
    const Module  = Robot.Module;
    const Memory  = Robot.Memory;
    const Window  = Robot.Window;
    
    
    
    //----------------------------------------------------------------------------//
    // Export                                                                     //
    //----------------------------------------------------------------------------//
    
    module.exports = class
    {
        ////////////////////////////////////////////////////////////////////////////////
        /// Creates a new unselected game instance object
    
        constructor() { this.deselect(); }
    
        ////////////////////////////////////////////////////////////////////////////////
        /// Deselects any currently selected game instance
    
        deselect()
        {
            this._window  = null;       // The game window
    
            this._process = null;       // The game process
            this._is64Bit = false;      // If game is 64Bit
    
            this._memory  = null;       // The game memory
            this._module  = null;       // Main module addr
    
            this._offsets = null;       // Correct offsets
        }
    
        ////////////////////////////////////////////////////////////////////////////////
        /// Selects a game instance using the specified process
    
        selectByProcess (process)
        {
            // Check if arguments are correct
            if (!(process instanceof Process))
                throw new TypeError ("Invalid arguments");
    
            // Attempt to select the main window
            let window = process.getWindows()[0];
    
            return window &&
                // Perform window selection
                this.selectByWindow (window);
        }
    
        ////////////////////////////////////////////////////////////////////////////////
        /// Selects a game instance using the specified window
    
        selectByWindow (window)
        {
            // Check if arguments are correct
            if (!(window instanceof Window))
                throw new TypeError ("Invalid arguments");
    
            // Check if the window title correctly matches
            if (window.getTitle() !== "World of Warcraft")
                return false;
    
            let process = window.getProcess();
            // Ensure that the process was opened
            if (!process.isValid()) return false;
    
            let module =
                // Get the main executable module
                process.getModules (".*\.exe")[0];
            if (!module) return false;
            module = module.getBase();
    
            // Determine if game is 64Bit
            let is64Bit = process.is64Bit();
            let offsets = is64Bit ?
                // Make sure to select correct offsets
                Offsets.Offsets64 : Offsets.Offsets32;
    
            // Create a new memory object
            let memory = Memory (process);
            if (memory.readString
                // Ensure game build is supported
                (module + offsets.GameBuild, 6) !==
                Offsets.GameBuild) return false;
    
            this._window  = window;
            this._process = process;
            this._is64Bit = is64Bit;
            this._memory  = memory;
            this._module  = module;
            this._offsets = offsets;
    
            // Create the memory cache
            this._memory.createCache
                (16384, 4096, 10485760);
    
            return true;
        }
    
        ////////////////////////////////////////////////////////////////////////////////
        /// Selects a game instance by scanning all open processes
    
        selectByFindProcess()
        {
            for (let p of Process.getList ("Wow.*\.exe"))
            {
                // Select the first suitable process value
                if (this.selectByProcess (p)) return true;
            }
    
            return false;
        }
    
        ////////////////////////////////////////////////////////////////////////////////
        /// Selects a game instance by scanning all open windows
    
        selectByFindWindow()
        {
            for (let w of Window.getList ("World of Warcraft"))
            {
                // Select the first suitable window value
                if (this.selectByWindow (w)) return true;
            }
    
            return false;
        }
    
        ////////////////////////////////////////////////////////////////////////////////
        /// Selects a game instance using the current active window
    
        selectByActiveWindow()
        {
            // Attempt to select the current active window
            return this.selectByWindow (Window.getActive());
        }
    
        ////////////////////////////////////////////////////////////////////////////////
        /// Returns true if a game instance is currently selected
    
        isSelected()
        {
            return this._window !== null;
        }
    
        ////////////////////////////////////////////////////////////////////////////////
        /// Returns true if the selected game instance is running
    
        isRunning()
        {
            // Ensure a game window is selected
            if (!this.isSelected()) return false;
    
            return !this._process.hasExited() &&
                    this._window .isValid  ();
        }
    
        ////////////////////////////////////////////////////////////////////////////////
        /// Various properties to extract game instance information
    
        get window () { return this._window;  }
    
        get process() { return this._process; }
        get is64Bit() { return this._is64Bit; }
    
        get memory () { return this._memory;  }
        get module () { return this._module;  }
    
        get offsets() { return this._offsets; }
    };
    offsets.js
    Code:
    "use strict";
    
    //----------------------------------------------------------------------------//
    // Offsets                                                                    //
    //----------------------------------------------------------------------------//
    
    module.exports =
    {
        GameBuild                       : "21463",
    
        Offsets32:
        {
            GameHash                    : 0xC7FEDA45,
            IconHash                    : 0xA118EC28,
            GameBuild                   : 0x9B24E4,
            GameState                   : 0xDA55B2,
    
            LocalPlayer                 : 0xD2E4C0,
            LocalCont                   : 0xBB3F7C,
            LocalZone                   : 0xBC0A64,
            IsLooting                   : 0xE165C8,
            IsTexting                   : 0xC1EB08,
             MouseGuid                  : 0xDA5988,
            TargetGuid                  : 0xDA59B8,
    
            Camera:
            {
                Struct                  : 0xDA5D58,
                Offset                  : 0x7610,
                Origin                  : 0x08,
                Matrix                  : 0x14,
                Fov                     : 0x38
            },
    
            Entity:
            {
                TableBase               : 0xC9D530,
                EntryFirst              : 0x0C,
                EntryNext               : 0x3C,
    
                Entry:
                {
                    Type                : 0x0C,
                    Descriptors         : 0x04,
    
                    Desc:
                    {
                        GlobalID        : 0x00,
                        EntityID        : 0x24,
                        DynFlags        : 0x28
                    }
                },
    
                Unit:
                {
                    Transport           : 0xAB0,
                    Origin              : 0xAC0,
                    Angle               : 0xAD0,
                    Casting             : 0xF98,
                    CastingStarted      : 0xFB0,
                    CastingWillEnd      : 0xFB4,
                    Channel             : 0xFB8,
                    ChannelStarted      : 0xFBC,
                    ChannelWillEnd      : 0xFC0,
    
                    Aura:
                    {
                        Count1          : 0x1588,
                        Count2          : 0x1108,
                        TableBase1      : 0x1108,
                        TableBase2      : 0x110C,
                        EntrySize       : 0x48,
    
                        Entry:
                        {
                            Owner       : 0x20,
                            SpellID     : 0x30,
                            Flags       : 0x38,
                            Stacks      : 0x39,
                            Level       : 0x3A,
                            EndTime     : 0x40
                        }
                    },
    
                    Desc:
                    {
                        Creator         : 0x080,
                        Health          : 0x0F0,
                        Power           : 0x0F4,
                        HealthMax       : 0x10C,
                         PowerMax       : 0x110,
                        Level           : 0x158,
                        Flags           : 0x17C
                    }
                },
    
                NPC:
                {
                    Name1               : 0xC38,
                    Name2               : 0x07C
                },
    
                Player:
                {
                    Money1              : 0x190C,
                    Money2              : 0x1890,
                    Arch                : 0x1910,
                    ArchCount           : 0x08,
                    ArchSites           : 0x10,
                    Target              : 0x41E8
                },
    
                Object:
                {
                    Bobbing             : 0x104,
                    Transport           : 0x130,
                    Origin              : 0x140,
                    Rotation            : 0x150,
                    Transform           : 0x278,
                    Name1               : 0x274,
                    Name2               : 0x0B4,
    
                    Desc:
                    {
                        Creator         : 0x030,
                        Display         : 0x040
                    }
                }
            },
    
            NameCache:
            {
                TableBase               : 0xC6043C,
                EntryNext               : 0x00,
    
                Entry:
                {
                    Guid                : 0x10,
                    Name                : 0x21,
                    Race                : 0x70,
                    Class               : 0x78
                }
            },
    
            Cooldown:
            {
                TableBase               : 0xC8AC88,
                EntryNext               : 0x04,
    
                Entry:
                {
                    SpellID             : 0x08,
                     ItemID             : 0x0C,
                    SpellStartTime      : 0x10,
                    SpellDuration       : 0x14,
                    GroupID             : 0x18,
                    GroupStartTime      : 0x1C,
                    GroupDuration       : 0x20,
                    IsActive            : 0x24,
                    GcdStartTime        : 0x28,
                    GcdDuration         : 0x30
                }
            },
    
            BMAH:
            {
                Count                   : 0xE536D0,
                TableBase               : 0xE536D4,
                EntrySize               : 0x70,
    
                Entry:
                {
                    MarketID            : 0x00,
                      ItemID            : 0x08,
                    MinimumBid          : 0x48,
                    MaximumInc          : 0x50,
                    CurrentBid          : 0x58,
                    TimeLeft            : 0x60,
                    BidCount            : 0x68
                }
            },
    
            Chat:
            {
                Position                : 0xE01894,
                TableBase               : 0xDA7518,
                EntrySize               : 0x17E8,
    
                Entry:
                {
                    SenderGuid          : 0x0000,
                    SenderName          : 0x0034,
                    FullMessage         : 0x0065,
                    OnlyMessage         : 0x0C1D,
                    ChannelNum          : 0x17D8,
                    TimeStamp           : 0x17E4
                }
            }
        },
    
        Offsets64:
        {
            GameHash                    : 0x64C90819,
            IconHash                    : 0xA118EC28,
            GameBuild                   : 0x0F415FC,
            GameState                   : 0x1519A7E,
    
            LocalPlayer                 : 0x147E680,
            LocalCont                   : 0x124B40C,
            LocalZone                   : 0x125F694,
            IsLooting                   : 0x158D1A4,
            IsTexting                   : 0x12CD4B0,
             MouseGuid                  : 0x151A0B8,
            TargetGuid                  : 0x151A0E8,
    
            Camera:
            {
                Struct                  : 0x151A520,
                Offset                  : 0x7768,
                Origin                  : 0x10,
                Matrix                  : 0x1C,
                Fov                     : 0x40
            },
    
            Entity:
            {
                TableBase               : 0x135D120,
                EntryFirst              : 0x18,
                EntryNext               : 0x68,
    
                Entry:
                {
                    Type                : 0x18,
                    Descriptors         : 0x08,
    
                    Desc:
                    {
                        GlobalID        : 0x00,
                        EntityID        : 0x24,
                        DynFlags        : 0x28
                    }
                },
    
                Unit:
                {
                    Transport           : 0x1538,
                    Origin              : 0x1548,
                    Angle               : 0x1558,
                    Casting             : 0x1B98,
                    CastingStarted      : 0x1BB0,
                    CastingWillEnd      : 0x1BB4,
                    Channel             : 0x1BB8,
                    ChannelStarted      : 0x1BBC,
                    ChannelWillEnd      : 0x1BC0,
    
                    Aura:
                    {
                        Count1          : 0x2390,
                        Count2          : 0x1D10,
                        TableBase1      : 0x1D10,
                        TableBase2      : 0x1D18,
                        EntrySize       : 0x68,
    
                        Entry:
                        {
                            Owner       : 0x40,
                            SpellID     : 0x50,
                            Flags       : 0x58,
                            Stacks      : 0x59,
                            Level       : 0x5A,
                            EndTime     : 0x60
                        }
                    },
    
                    Desc:
                    {
                        Creator         : 0x080,
                        Health          : 0x0F0,
                        Power           : 0x0F4,
                        HealthMax       : 0x10C,
                         PowerMax       : 0x110,
                        Level           : 0x158,
                        Flags           : 0x17C
                    }
                },
    
                NPC:
                {
                    Name1               : 0x16F0,
                    Name2               : 0x00A0
                },
    
                Player:
                {
                    Money1              : 0x2790,
                    Money2              : 0x1890,
                    Arch                : 0x2798,
                    ArchCount           : 0x08,
                    ArchSites           : 0x18,
                    Target              : 0x77E8,
                },
    
                Object:
                {
                    Bobbing             : 0x1E0,
                    Transport           : 0x238,
                    Origin              : 0x248,
                    Rotation            : 0x258,
                    Transform           : 0x4A0,
                    Name1               : 0x498,
                    Name2               : 0x0D8,
    
                    Desc:
                    {
                        Creator         : 0x030,
                        Display         : 0x040
                    }
                }
            },
    
            NameCache:
            {
                TableBase               : 0x1316E98,
                EntryNext               : 0x00,
    
                Entry:
                {
                    Guid                : 0x20,
                    Name                : 0x31,
                    Race                : 0x88,
                    Class               : 0x90
                }
            },
    
            Cooldown:
            {
                TableBase               : 0x1354D50,
                EntryNext               : 0x08,
    
                Entry:
                {
                    SpellID             : 0x10,
                     ItemID             : 0x14,
                    SpellStartTime      : 0x18,
                    SpellDuration       : 0x1C,
                    GroupID             : 0x20,
                    GroupStartTime      : 0x24,
                    GroupDuration       : 0x28,
                    IsActive            : 0x2C,
                    GcdStartTime        : 0x30,
                    GcdDuration         : 0x38
                }
            },
    
            BMAH:
            {
                Count                   : 0x15CE6E8,
                TableBase               : 0x15CE6F0,
                EntrySize               : 0xA8,
    
                Entry:
                {
                    MarketID            : 0x00,
                      ItemID            : 0x08,
                    MinimumBid          : 0x80,
                    MaximumInc          : 0x88,
                    CurrentBid          : 0x90,
                    TimeLeft            : 0x98,
                    BidCount            : 0xA0
                }
            },
    
            Chat:
            {
                Position                : 0x157627C,
                TableBase               : 0x151BD20,
                EntrySize               : 0x17F0,
    
                Entry:
                {
                    SenderGuid          : 0x0000,
                    SenderName          : 0x0034,
                    FullMessage         : 0x0065,
                    OnlyMessage         : 0x0C1D,
                    ChannelNum          : 0x17D8,
                    TimeStamp           : 0x17E8
                }
            }
        }
    };
    Last edited by Torpedoes; 06-21-2016 at 12:22 PM.

    Writing Bots with Robot-js
  2. Thanks Willy, kyperbelt, CrimeTime, IChangedMyUsername, Corthezz, Miksu, Ichiboo, iispyderii, lolp1, Confucius, chaisar, xxspokiixx, para_, N/A, StinkyTwitch, grayfm, Vachiusa, charly (18 members gave Thanks to Torpedoes for this useful post)
  3. #2
    Torpedoes's Avatar ★ Elder ★ Doomsayer
    Authenticator enabled
    Reputation
    1147
    Join Date
    Sep 2013
    Posts
    956
    Thanks G/R
    148/415
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    BMAH Monitor

    BMAH Monitor
    The first demo features a simple Black Market Auction House monitor. Assuming you set everything up correctly, just run the script "node bmah_monitor.js" (no quotes) and select your WoW window. Speaking with Madam Goya will update the game client, which in turn, prints the BMAH items to the console. This script has been tested on Windows 7 running Node 6.0.0 x64

    bmah_monitor.js
    Code:
    "use strict";
    
    //----------------------------------------------------------------------------//
    // BMAH Monitor                                                               //
    //----------------------------------------------------------------------------//
    
    // Create application controller
    new (require ("./app_controller"))
        (250, function (gameInstance)
    {
        // Some shortcuts to update the game
        const memory  = gameInstance.memory;
        const module  = gameInstance.module;
        const offsets = gameInstance.offsets;
    
        // Read BMAH count and table
        const count = memory.readInt32 (module + offsets.BMAH.Count    );
        const table = memory.readPtr   (module + offsets.BMAH.TableBase);
    
        // Make sure count and table are valid
        if (count <= 0 || table <= 0) return;
    
        let items = [ ];
        // Loop through all BMAH items
        for (let i = 0; i < count; ++i)
        {
            // Retrieve the current BMAH item offset in memory
            const slide = table + (offsets.BMAH.EntrySize * i);
    
            items.push
            ({
                marketID  : memory.readInt32 (slide + offsets.BMAH.Entry.MarketID  ),
                  itemID  : memory.readInt32 (slide + offsets.BMAH.Entry.  ItemID  ),
                minimumBid: memory.readInt64 (slide + offsets.BMAH.Entry.MinimumBid),
                maximumInc: memory.readInt64 (slide + offsets.BMAH.Entry.MaximumInc),
                currentBid: memory.readInt64 (slide + offsets.BMAH.Entry.CurrentBid),
                timeLeft  : memory.readInt32 (slide + offsets.BMAH.Entry.TimeLeft  ),
                bidCount  : memory.readInt32 (slide + offsets.BMAH.Entry.BidCount  )
            });
        }
    
        // Cheap way to clear the screen
        process.stdout.write ("\x1Bc");
    
        // Print each item
        items.map (item =>
        {
            // TIP: ItemID is an item so you can use the WowAPI
            // or WowHead to retrieve more information about it
    
            console.log (`Item=${item.itemID} Bid=${item.currentBid /
                10000} Bids=${item.bidCount} Time=${item.timeLeft}`);
        });
    });
    Last edited by Torpedoes; 04-27-2016 at 11:25 AM.

  4. #3
    kyperbelt's Avatar Corporal
    Reputation
    47
    Join Date
    Apr 2016
    Posts
    20
    Thanks G/R
    3/14
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    damn this is cool stuff. Been working on a project (in java) with the goal of making it easy to run scripts for automation purposes. Mind if i port some of your stuff on to my project @ a later date?

    man i just looked up the robot api its so good lol , my project seems a bit pointless now.. I guess ill still post it.
    Last edited by kyperbelt; 04-26-2016 at 03:40 PM.

  5. #4
    Torpedoes's Avatar ★ Elder ★ Doomsayer
    Authenticator enabled
    Reputation
    1147
    Join Date
    Sep 2013
    Posts
    956
    Thanks G/R
    148/415
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by kyperbelt View Post
    Mind if i port some of your stuff on to my project?
    Feel free to port Robot to any platform you wish, and help spread the word :-D

  6. #5
    kyperbelt's Avatar Corporal
    Reputation
    47
    Join Date
    Apr 2016
    Posts
    20
    Thanks G/R
    3/14
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Torpedoes View Post
    Feel free to port Robot to any platform you wish, and help spread the word :-D
    i just meant porting your specific scripts in particular, But might take a deeper look into robotjs. Thanks for the great post

  7. #6
    CrimeTime's Avatar Active Member
    Reputation
    20
    Join Date
    Dec 2007
    Posts
    83
    Thanks G/R
    16/4
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    looks pretty neat, will defently look at this!
    Thanks

  8. #7
    Torpedoes's Avatar ★ Elder ★ Doomsayer
    Authenticator enabled
    Reputation
    1147
    Join Date
    Sep 2013
    Posts
    956
    Thanks G/R
    148/415
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Chat Monitor
    The second demo features a simple chat monitor. Assuming you set everything up correctly, just run the script "node chat_monitor.js" (no quotes) and select your WoW window. If you're in a particularly chatty area of the game, everything said will be printed to the console. The script compensates for missed texts as well. This script has been tested on Windows 7 running Node 6.0.0 x64

    chat_monitor.js
    Code:
    "use strict";
    
    //----------------------------------------------------------------------------//
    // Chat Monitor                                                               //
    //----------------------------------------------------------------------------//
    
    // Old chat position
    let position = null;
    // Used to retrieve player guid
    let guidBuff = new Buffer (16);
    
    // Create application controller
    new (require ("./app_controller"))
        (250, function (gameInstance)
    {
        // Some shortcuts to update the game
        const memory  = gameInstance.memory;
        const module  = gameInstance.module;
        const offsets = gameInstance.offsets;
    
        // Read the new position of the chat
        const newPosition = memory.readInt32
            (module + offsets.Chat.Position);
    
        // Make sure the position is reasonable
        if (newPosition < 0 || newPosition > 60)
            return;
    
        if (position === null)
        {
            // First time this is being run
            position = newPosition; return;
        }
    
        let newMessages = [ ];
        // Read any new incoming messages
        while (position !== newPosition)
        {
            if (++position === 60) position = 0;
            // Get the current message offset in memory
            const slide = module + offsets.Chat.TableBase +
                (offsets.Chat.EntrySize * (position - 1));
    
            newMessages.push
            ({
                senderGuid : memory.readData (slide + offsets.Chat.Entry.SenderGuid, guidBuff, 16) ?
                                              guidBuff.toString ("hex").toUpperCase() : "",
    
                senderName : memory.readString (slide + offsets.Chat.Entry.SenderName,  40  ),
                fullMessage: memory.readString (slide + offsets.Chat.Entry.FullMessage, 3000),
                onlyMessage: memory.readString (slide + offsets.Chat.Entry.OnlyMessage, 3000),
    
                channelNum : memory.readInt32  (slide + offsets.Chat.Entry.ChannelNum),
                timeStamp  : memory.readInt32  (slide + offsets.Chat.Entry.TimeStamp )
            });
        }
    
        // Process each new message
        newMessages.map (message =>
        {
            // Convert the Unix timestamp into a normal Date
            const date = new Date (message.timeStamp * 1000);
            const hrs  = `0${date.getHours  ()}`.substr (-2);
            const min  = `0${date.getMinutes()}`.substr (-2);
            const sec  = `0${date.getSeconds()}`.substr (-2);
    
            console.log (`[${hrs}:${min}:${sec}] [${message.senderName}]: ${message.onlyMessage}`);
        });
    });

  9. #8
    karliky's Avatar Contributor Authenticator enabled
    Reputation
    112
    Join Date
    Jun 2007
    Posts
    69
    Thanks G/R
    6/27
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey Torpedoes,

    Thank you for putting all the effort of building a library like this, it's really impressive. I've tried to do it by myself for over the years but my lack of knowledge on macosx and linux made it impossible to achieve.

    It's great to see finally al real multiplatform library for manage processes. Back in the past I started a simple library with c++ <--> js bindings to the windows kernel using Node.js in order to manage processes trough node js, you can see it here:

    https://github.com/karliky/CrazinessJS

    And this is my intent of improve CrazinessJS with Blackbone (another excelent memory managment library but not crossplatform)
    https://github.com/karliky/CrazinessJS/tree/dev

    Here you can see some of the tools that I've made with CrazinessJS and node.js:

    https://www.youtube.com/watch?v=0ZTYTyp3Tuw
    https://www.youtube.com/watch?v=2fklKtVjfPw
    https://www.youtube.com/watch?v=AVkWeHqhPwo
    https://www.youtube.com/watch?v=fjrlAJumH1s
    https://www.youtube.com/watch?v=r8BAlc5fS0g

    I'll definitely use your library and I'll try to contribute to robot-js.

    Once again, amazing work!

    Cheers

  10. #9
    Torpedoes's Avatar ★ Elder ★ Doomsayer
    Authenticator enabled
    Reputation
    1147
    Join Date
    Sep 2013
    Posts
    956
    Thanks G/R
    148/415
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by karliky View Post
    In the past I started a simple library with c++ <--> js bindings to the windows kernel using Node.js in order to manage processes trough node js, you can see it here:

    https://github.com/karliky/CrazinessJS
    Nice! I'm glad I'm not the only one exploring this technology. But I'm guessing from the source that you only support Node 0.10 since the API changed so drastically in 0.12.

    Originally Posted by karliky View Post
    And this is my intent of improve CrazinessJS with Blackbone (another excelent memory managment library but not crossplatform)
    https://github.com/karliky/CrazinessJS/tree/dev
    Yes, I actually used BlackBone, among other libraries, for inspiration.

    Those are really cool videos man. Keep up the great work!

    Originally Posted by karliky View Post
    I'll definitely use your library and I'll try to contribute to robot-js.

    Once again, amazing work!
    Thanks for your support!

    I would love nothing more than to see people using my library. I don't know if people realize this but Robot is the library that's been powering Yeti-Bots for three years now.

    For contributing, keep in mind that robot-js is just a port of robot. So for new features, be sure to implement it there. The robot-js version will naturally be ported over. For more information about contributing, be sure to check out this guide!

  11. #10
    IChangedMyUsername's Avatar Contributor Dance! ;^) CoreCoins Purchaser
    Reputation
    169
    Join Date
    Mar 2013
    Posts
    720
    Thanks G/R
    257/65
    Trade Feedback
    5 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Very cool. Thanks for the posts

  12. #11
    ev0's Avatar ★ Elder ★ murlocs.com

    CoreCoins Purchaser Authenticator enabled
    Reputation
    1850
    Join Date
    Jul 2012
    Posts
    2,737
    Thanks G/R
    313/377
    Trade Feedback
    16 (100%)
    Mentioned
    7 Post(s)
    Tagged
    7 Thread(s)
    Whelp, I know what i'm doing this weekend. This is an amazing release. I can't wait to fiddle
    Need a guild in the US? Visit murlocs.com

  13. #12
    Torpedoes's Avatar ★ Elder ★ Doomsayer
    Authenticator enabled
    Reputation
    1147
    Join Date
    Sep 2013
    Posts
    956
    Thanks G/R
    148/415
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Entity Dumper
    The third demo features a small entity dumper. Assuming you set everything up correctly, just run the script "node entity_dumper.js" (no quotes) and select your WoW window. Standing in a moderately populated area will print the locations of all NPCs, Players and Objects. This script has been tested on Windows 7 running Node 6.0.0 x64

    entity_dumper.js
    Code:
    "use strict";
    
    //----------------------------------------------------------------------------//
    // Entity Dumper                                                              //
    //----------------------------------------------------------------------------//
    
    // Create application controller
    new (require ("./app_controller"))
        (250, function (gameInstance)
    {
        // Some shortcuts to update the game
        const memory  = gameInstance.memory;
        const module  = gameInstance.module;
        const offsets = gameInstance.offsets;
    
        let entry = memory.readPtr
            // Retrieve the entity list manager
            (module + offsets.Entity.TableBase);
    
        // Validate the pointer
        if (entry <= 0) return;
    
        entry = memory.readPtr
            // Retrieve the first entity entry
            (entry + offsets.Entity.EntryFirst);
    
        let entities = {
            npcs   : [ ],
            players: [ ],
            objects: [ ]
        };
        let repeater = { };
        let infinite = 0;
    
        // Read all entries from first to last
        while (entry > 0 && (entry & 1) === 0)
        {
            // Avoid repetition of entries
             if (repeater[entry]) break;
            else repeater[entry] = true;
    
            // Avoid possible infinite loop
            if (++infinite >= 20000) break;
    
            // Retrieve type and descriptor
            const type = memory.readInt32 (entry + offsets.Entity.Entry.Type       );
            const desc = memory.readPtr   (entry + offsets.Entity.Entry.Descriptors);
    
            if (desc > 0)
            {
                type === 3 && entities.npcs.push
                ({
                    entry,
                    x: memory.readReal32 (entry + offsets.Entity.Unit.Origin + 0),
                    y: memory.readReal32 (entry + offsets.Entity.Unit.Origin + 4),
                    z: memory.readReal32 (entry + offsets.Entity.Unit.Origin + 8)
                });
    
                type === 4 && entities.players.push
                ({
                    entry,
                    x: memory.readReal32 (entry + offsets.Entity.Unit.Origin + 0),
                    y: memory.readReal32 (entry + offsets.Entity.Unit.Origin + 4),
                    z: memory.readReal32 (entry + offsets.Entity.Unit.Origin + 8)
                });
    
                type === 5 && entities.objects.push
                ({
                    entry,
                    x: memory.readReal32 (entry + offsets.Entity.Object.Origin + 0),
                    y: memory.readReal32 (entry + offsets.Entity.Object.Origin + 4),
                    z: memory.readReal32 (entry + offsets.Entity.Object.Origin + 8)
                });
            }
    
            // Read the next entry in table
            entry = memory.readPtr (entry +
                offsets.Entity.EntryNext);
        }
    
        for (let e in entities)
        {
            console.log (`\n${e}`);
            // Print grouped entities
            entities[e].map (entity =>
            {
                console.log (`entry=${entity.entry.toString (16).toUpperCase()} x=${entity.x.toFixed (2)} y=${entity.y.toFixed (2)} z=${entity.z.toFixed (2)}`);
            });
        }
    
        // All finished
        process.exit();
    });

  14. #13
    karliky's Avatar Contributor Authenticator enabled
    Reputation
    112
    Join Date
    Jun 2007
    Posts
    69
    Thanks G/R
    6/27
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey Torpedoes,

    I've made an HTML5 desktop app, very simple, in order to show to the users of robot-js how to render information in the desktop instead of just the terminal using console.log.

    Here is an example of the app, it shows the chat messages using your script of above, I had to modify it to emit websockets everytime it processes a message:

    Writing Bots with Robot-js-robot-chat-jpg

    The repo is here:
    https://github.com/karliky/robotjs-desktop-wow

    How to use it:

    - clone de repo in local or download it as a zip https://github.com/karliky/robotjs-d...ive/master.zip
    - cd into the directory and then execute: "$ npm install"
    - open a terminal, execute "$ node examples\chat_monitor.js"
    - open a terminal, execute "$ node ./node_modules/.bin/electron ."

    You should see the chat messages in the desktop app.

    Will work on improving this soon.

    Great work with robot-js mate!

  15. Thanks ev0, Torpedoes, Corthezz (3 members gave Thanks to karliky for this useful post)
  16. #14
    Torpedoes's Avatar ★ Elder ★ Doomsayer
    Authenticator enabled
    Reputation
    1147
    Join Date
    Sep 2013
    Posts
    956
    Thanks G/R
    148/415
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by karliky View Post
    I've made an HTML5 desktop app, very simple, in order to show to the users of robot-js how to render information in the desktop instead of just the terminal using console.log!
    Super cool!! I'll have to check it out but I look forward to seeing more projects like this :-D

  17. Thanks karliky (1 members gave Thanks to Torpedoes for this useful post)
  18. #15
    Torpedoes's Avatar ★ Elder ★ Doomsayer
    Authenticator enabled
    Reputation
    1147
    Join Date
    Sep 2013
    Posts
    956
    Thanks G/R
    148/415
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Aura Monitor
    The fourth demo features an aura monitor. Assuming you set everything up correctly, just run the script "node aura_monitor.js" (no quotes) and select your WoW window. Any buffs and debuffs your character has will be displayed in the console. As a challenge, try to make this work with other players and NPCs. It should be easy if you combine this code with the code from the third demo. This script has been tested on Windows 7 running Node 6.0.0 x64

    aura_monitor.js
    Code:
    "use strict";
    
    //----------------------------------------------------------------------------//
    // Aura Monitor                                                               //
    //----------------------------------------------------------------------------//
    
    // Used to retrieve player guid
    let guidBuff = new Buffer (16);
    // We need timer to calculate aura times
    const Timer = require ("robot-js").Timer;
    
    // Create application controller
    new (require ("./app_controller"))
        (250, function (gameInstance)
    {
        // Some shortcuts to update the game
        const memory  = gameInstance.memory;
        const module  = gameInstance.module;
        const offsets = gameInstance.offsets;
        const auraOff = offsets.Entity.Unit.Aura;
    
        const player = memory.readPtr
            // Retrieve the player pointer
            (module + offsets.LocalPlayer);
    
        // Validate the pointer
        if (player <= 0) return;
    
        // When less than 16 Auras, they are stored in an array
        let count = memory.readInt32 (player + auraOff.Count1);
        let table =                   player + auraOff.TableBase1;
    
        // Using the heap
        if (count === -1)
        {
            // The auras were dynamically allocated on the heap
            count = memory.readInt32 (player + auraOff.Count2);
            table = memory.readPtr   (player + auraOff.TableBase2);
        }
    
        // Make sure count and table are valid
        if (count <= 0 || table <= 0) return;
    
        let auras = [ ];
        // Loop through all aura entries
        for (let i = 0; i < count; ++i)
        {
            // Get the current aura entry offset in memory
            const slide = table + (auraOff.EntrySize * i);
    
            // Skip the current entry if the aura spell ID is zero
            if (!memory.readInt32 (slide + auraOff.Entry.SpellID))
                continue;
    
            auras.push
            ({
                owner : memory.readData (slide + auraOff.Entry.Owner, guidBuff, 16) ?
                                         guidBuff.toString ("hex").toUpperCase() : "",
    
                spellID: memory.readInt32 (slide + auraOff.Entry.SpellID),
                flags  : memory.readInt8  (slide + auraOff.Entry.Flags  ),
                stacks : memory.readInt8  (slide + auraOff.Entry.Stacks ),
                level  : memory.readInt8  (slide + auraOff.Entry.Level  ),
                endTime: memory.readInt32 (slide + auraOff.Entry.EndTime)
            });
        }
    
        // Cheap way to clear the screen
        process.stdout.write ("\x1Bc");
    
        // Retrieve the current Cpu Time
        const now = Timer.getCpuTime();
    
        // Print each aura
        auras.map (aura =>
        {
            // TIP: SpellID is a spell so you can use the WowAPI
            // or WowHead to retrieve more information about it
    
            // Convert WoW's time using the current time
            const timeLeft = (aura.endTime - now) / 1000;
            console.log (`Spell=${aura.spellID} Flags=${aura.flags} Stack=${
                    aura.stacks} TimeLeft=${timeLeft > 0 ? timeLeft : 0}s`);
        });
    });

  19. Thanks karliky (1 members gave Thanks to Torpedoes for this useful post)
Page 1 of 7 12345 ... LastLast

Similar Threads

  1. Make your own Bot with Java Robot Class
    By whappit in forum Programming
    Replies: 19
    Last Post: 09-27-2015, 06:07 AM
  2. Making a bot with java (robot class) Help
    By ASDF4Ever in forum Programming
    Replies: 3
    Last Post: 09-10-2013, 01:50 AM
  3. Making an anti-afk bot with AutoIT the easy way.
    By Tsai in forum World of Warcraft Bots and Programs
    Replies: 13
    Last Post: 10-02-2007, 04:22 PM
  4. Easy AFK Bot with G15
    By husky003 in forum World of Warcraft Exploits
    Replies: 7
    Last Post: 01-13-2007, 12:42 AM
  5. anit afk bot with Cheat engine
    By thechosenone in forum World of Warcraft Bots and Programs
    Replies: 3
    Last Post: 09-11-2006, 03:44 PM
All times are GMT -5. The time now is 11:16 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