├── MarkdownEditorHelp.md ├── README.md ├── d2bot ├── Autoupdate.md ├── Download.md ├── Keylist.md ├── ManagerSetup.md ├── README.md └── assets │ ├── d2bot-autoupdate1.png │ ├── d2bot-autoupdate2.png │ ├── d2bot-autoupdate3.png │ ├── d2bot-compatibility.png │ ├── d2bot-keyclaimedonbattlenet.png │ ├── d2bot-keylist1.jpg │ ├── d2bot-keylist2.png │ ├── d2bot-keylist3.png │ ├── d2bot-keylist4.png │ ├── d2bot-keylist5.png │ ├── d2bot-keylist6.png │ ├── d2bot-keylist7.png │ ├── d2bot-keylist8.png │ ├── d2bot-keylistcdkeyinuse.png │ ├── d2bot-managersetup1-1.png │ ├── d2bot-managersetup1.png │ ├── d2bot-managersetup2.jpg │ ├── d2bot-managersetup3.jpg │ ├── d2bot-managersetup4.png │ ├── d2bot-managersetup5.png │ ├── d2bot-managersetup6.png │ ├── d2bot-setup.jpg │ ├── d2bot-tortoise1.png │ ├── d2bot-tortoise2.png │ ├── d2bot-tortoise3.png │ ├── d2bot-tortoise4.png │ └── d2bot-tortoise5.png ├── d2bs └── README.md ├── kolbot ├── Automule.md ├── CharacterConfig.md ├── Cubing.md ├── D2BotMuleLog.md ├── FAQ.md ├── GamblingSystem.md ├── Hotkeys.md ├── IDES.md ├── ManualPlay.md ├── MiscellaneousOptions.md ├── MultiBotting.md ├── PermingOptions.md ├── README.md ├── TCP-IP games.md ├── assets │ ├── ManualPlayScriptWithPacketSniffingToolsAndMore.html │ ├── kolbot-TcpIp-host.png │ ├── kolbot-TcpIp-join.png │ ├── kolbot-automule1.png │ ├── kolbot-automule2.png │ ├── kolbot-automule3.png │ ├── kolbot-automule4.png │ ├── kolbot-d2botmulelog1.png │ ├── kolbot-d2botmulelog2.png │ ├── kolbot-d2botmulelog3.png │ ├── kolbot-d2botmulelog4.png │ ├── kolbot-d2botmulelog5.png │ ├── kolbot-d2botmulelog6.png │ ├── kolbot-d2botmulelog7.png │ ├── kolbot-manualplayD2BotMapEx1.JPG │ ├── kolbot-manualplayD2BotMapEx2.JPG │ ├── kolbot-manualplayMiscScript.jpg │ ├── kolbot-multibotCreatorProfile.png │ ├── kolbot-multibotD2BotFollow.png │ ├── kolbot-multibotFollower1Profile.png │ ├── kolbot-multibotFollower2Profile.png │ ├── kolbot-np++styleconfigurator.png │ └── kolbot-taiwan-disclaimer.png └── custom-scripts │ ├── CowOpen.js │ ├── D2BotFollow.dbj │ ├── D2BotLead.dbj │ ├── D2BotLeadStagger.dbj │ ├── D2BotTimerRefresh.dbj │ ├── FollowerSilent.js │ ├── Manual.js │ └── Party.js └── limedrop ├── README.md └── assets ├── limedrop-addaccount1.png ├── limedrop-addaccount2.png ├── limedrop-addprofile.png ├── limedrop-extract.png ├── limedrop-general.png ├── limedrop-login.png ├── limedrop-serverconfigedit.png └── limedrop-serverconfigfile.png /MarkdownEditorHelp.md: -------------------------------------------------------------------------------- 1 | # Markdown Editor Help 2 | 3 | --- 4 | 5 | * additional guides can be found on: 6 | * https://github.github.com/gfm/ 7 | * http://docutils.sourceforge.net/docs/ref/rst/ 8 | 9 | --- 10 | [Block Elements](#block-elements) 11 | 12 | * [Paragraphs & Breaks](#paragraphs-&-breaks) 13 | 14 | * [Headers](#headers) 15 | 16 | * [Blockquotes](#blockquotes) 17 | 18 | * [Lists](#lists) 19 | 20 | * [Code Blocks](#code-blocks) 21 | 22 | * [Horizontal rules](#horizontal-rules) 23 | --- 24 | [Span Elements](#span-elements) 25 | 26 | * [Links](#links) 27 | 28 | * [Emphasis](#emphasis) 29 | 30 | * [Code](#code) 31 | 32 | * [Images](#images) 33 | --- 34 | [Miscellaneous](#miscellaneous) 35 | 36 | * [Automatic Links](#automatic-links) 37 | 38 | * [Escaping](#escaping) 39 | 40 | --- 41 | 42 | ## Block Elements 43 | 44 | #### Paragraphs & Breaks 45 | To create a paragraph, simply create a block of text that is not separated by one or more blank lines. Blocks of text separated by one or more blank lines will be parsed as paragraphs. 46 | 47 | If you want to create a line break, end a line with two or more spaces, then hit Return/Enter. 48 | 49 | #### Headers 50 | Markdown supports two header formats. The wiki editor uses the “atx”-style headers. Simply prefix your header text with the number of # characters to specify heading depth. For example: # Header 1, ## Header 2 and ### Header 3 will be progressively smaller headers. You may end your headers with any number of hashes. 51 | 52 | #### Blockquotes 53 | Markdown creates blockquotes email-style by prefixing each line with the >. This looks best if you decide to hard-wrap text and prefix each line with a > character, but Markdown supports just putting > before your paragraph. 54 | 55 | #### Lists 56 | Markdown supports both ordered and unordered lists. To create an ordered list, simply prefix each line with a number (any number will do — this is why the editor only uses one number.) To create an unordered list, you can prefix each line with *, + or -. 57 | 58 | List items can contain multiple paragraphs, however each paragraph must be indented by at least 4 spaces or a tab. 59 | 60 | #### Code Blocks 61 | Markdown wraps code blocks in pre-formatted tags to preserve indentation in your code blocks. To create a code block, indent the entire block by at least 4 spaces or one tab. Markdown will strip the extra indentation you’ve added to the code block. 62 | 63 | #### Horizontal rules 64 | Horizontal rules are created by placing three or more hyphens, asterisks or underscores on a line by themselves. Spaces are allowed between the hyphens, asterisks or underscores. 65 | 66 | ## Span Elements 67 | 68 | #### Links 69 | Markdown has two types of links: inline and reference. For both types of links, the text you want to display to the user is placed in square brackets. For example, if you want your link to display the text “GitHub”, you write [GitHub]. 70 | 71 | To create an inline link, create a set of parentheses immediately after the brackets and write your URL within the parentheses. (e.g., [GitHub](https://github.com/)). Relative paths are allowed in inline links. 72 | 73 | To create a reference link, use two sets of square brackets. [[my internal link|internal-ref]] will link to the internal reference internal-ref. 74 | 75 | #### Emphasis 76 | Asterisks (*) and underscores (_) are treated as emphasis and are wrapped with an tag, which usually displays as italics in most browsers. Double asterisks (**) or double underscores (__) are treated as bold using the tag. To create italic or bold text, simply wrap your words in single/double asterisks/underscores. For example, **My double emphasis text** becomes My double emphasis text, and *My single emphasis text* becomes My single emphasis text. 77 | 78 | #### Code 79 | To create inline spans of code, simply wrap the code in backticks (`). Markdown will turn `myFunction` into myFunction. 80 | 81 | #### Images 82 | Markdown image syntax looks a lot like the syntax for links; it is essentially the same syntax preceded by an exclamation point (!). For example, if you want to link to an image at https://github.com/unicorn.png with the alternate text My Unicorn, you would write ![My Unicorn] (https://github.com/unicorn.png), and the result will be ![](https://github.com/unicorn.png). 83 | 84 | ## Miscellaneous 85 | 86 | #### Automatic Links 87 | If you want to create a link that displays the actual URL, markdown allows you to quickly wrap the URL in < and > to do so. For example, the link https://github.com/ is easily produced by writing . 88 | 89 | #### Escaping 90 | If you want to use a special Markdown character in your document (such as displaying literal asterisks), you can escape the character with the backslash (\). Markdown will ignore the character directly after a backslash. 91 | 92 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Diablo 2 Botting System (D2BS) 2 | 3 | * [d2bs core](#d2bs-d2bs-core-by-view-developers) 4 | * [d2bot manager](#d2bot-d2bot-manager-by-noah-) 5 | * [kolbot library scripts](#kolbot-library-scripts-by-kolton) 6 | * [limedrop dropper](#limedrop-limedrop-dropper-by-noah-) 7 | 8 | --- 9 | 10 | * [video guides](#video-guides) 11 | * [d2bot-with-kolbot history](#d2bsd2bot-with-kolbot-history) 12 | 13 | --- 14 | 15 | ### [d2bs](d2bs/#d2bs): d2bs core by [view developers](https://app.assembla.com/spaces/d2bs/team) 16 | 17 | * [API Reference](https://github.com/noah-/d2bs/blob/master/README.md) 18 | * [Current Source](https://github.com/noah-/d2bs) 19 | * [Original Source](https://app.assembla.com/spaces/d2bs/subversion/source) 20 | 21 | --- 22 | 23 | ### [d2bot](d2bot/#d2bot): d2bot manager by [@noah-](https://github.com/noah-) 24 | 25 | * [Download](d2bot/Download.md): how to download files and to keep them updated 26 | * [Manager Setup](d2bot/ManagerSetup.md/#manager-setup): how to set-up d2bot manager 27 | * [Keylist Configuration](d2bot/Keylist.md/#keylist): additional info for key list management 28 | * [Autoupdate](d2bot/Autoupdate.md/#autoupdate): project monitor, commit monitor 29 | 30 | --- 31 | 32 | ### [kolbot](kolbot/#kolbot): library scripts by [@kolton](https://github.com/kolton) 33 | 34 | * [FAQ](kolbot/FAQ.md/#faq) 35 | * [IDE-Setup](kolbot/IDES.md/#code-editors-ides): How to set up your IDE for syntax highlighting 36 | * [Character Configuration](kolbot/CharacterConfig.md/#character-configuration): options for configuring the bot 37 | * [Cubing](kolbot/Cubing.md/#cubing): using the horadric cube recipes 38 | * [Manual Play](kolbot/ManualPlay.md/#manual-playing): D2BotMap, Manual.js script 39 | * [Multi Botting](kolbot/MultiBotting.md/#multi-botting): game creator, joining games, ... 40 | * [TCP/IP Games](kolbot/TCP-IP%20games.md#tcpip-games): host and join TCP/IP games 41 | * [D2BotMuleLog](kolbot/D2BotMuleLog.md/#d2botmulelog): log muled items 42 | * [Perming Options](kolbot/PermingOptions.md/#perming-options): options to perm chars or to refresh the countdown timer 43 | * [Automule](kolbot/Automule.md/#automule): Automuling and torch muling 44 | * [Gambling System](kolbot/GamblingSystem.md#gambling-system): how to configure gambling teams 45 | * [Hotkeys](kolbot/Hotkeys.md/#hotkeys): d2bs hotkeys, how to change them, console commands 46 | * [Miscellaneous Options](kolbot/MiscellaneousOptions.md/#miscellaneous-options): autosmurf, autochaos, modded BattleOrders, how to define your own party, hardcore loot corpses, baal ads for hdin on wave2, ... 47 | 48 | --- 49 | 50 | ### [limedrop](limedrop/#limedrop-guide): limedrop dropper by [@noah-](https://github.com/noah-) 51 | 52 | * [About](limedrop/#about-limedrop) 53 | * [Setup](limedrop/#setup-limedrop) 54 | * [Usage](limedrop/#using-limedrop) 55 | * [FAQ](limedrop/#frequently-asked-questions) 56 | 57 | --- 58 | 59 | ### video guides: 60 | 61 | * 62 | * 63 | 64 | --- 65 | 66 | ### D2BS(d2bot-with-kolbot) history 67 | 68 | * [D2BS Release](https://web.archive.org/web/20170813084150/http://www.blizzhackers.cc/viewforum.php?f=228&sid=923d6d1f4fb72bbe94aa7cb14600e0c1) = [d2bs core](https://github.com/noah-/d2bs) + [d2bot manager](https://github.com/d2botsharp/d2bot/) by [noah-](https://github.com/noah-) (aka @D3STROY3R) + kolbot library scripts by [@kolton](https://github.com/kolton). 69 | 70 | * d2bot-with-kolbot was released on 24th Apr 2012 on [blizzhackers](https://web.archive.org/web/20171030004307/http://www.blizzhackers.cc/viewtopic.php?f=206&t=489091&sid=076b6f411e98d938f4568c448d3f5845) , and it was announced a bit later on [projectetal forum](https://web.archive.org/web/20170215101441/http://www.projectetal.com:80/forums/threads/kolbot-and-d2bot.8698/). 71 | 72 | * it was updated on June 2017 for 1.14d d2 patch according to [blizzhackers announce](https://web.archive.org/web/20171115131230/http://www.blizzhackers.cc/viewtopic.php?f=204&t=545178&sid=ffa80262b1692f21eaea19109146c071&start=0) 73 | 74 | * it was updated on March 2018 with fixes for 12th December's 2017 d2 server patches. 75 | 76 | * use TortoiseSVN Update option from time to time, or any other methods to keep it updated. 77 | -------------------------------------------------------------------------------- /d2bot/Autoupdate.md: -------------------------------------------------------------------------------- 1 | [general table of content](https://github.com/blizzhackers/documentation/#diablo-2-botting-system) 2 | 3 | [d2bot table of content](https://github.com/blizzhackers/documentation/tree/master/d2bot/#d2bot) 4 | 5 | --- 6 | 7 | # Autoupdate 8 | 9 | --- 10 | 11 | ### tortoiseSVN project monitor 12 | 13 | [TortoiseSVN](https://tortoisesvn.net/), version 1.9 and later, has a project monitor included, which has similar features as the [CommitMonitor](#commit-monitor). 14 | You should start ...\TortoiseSVN\bin\TortoiseProc.exe. By default the interval for monitoring is set to 30 minutes, and can have a maximum value of 1000 minutes. 15 | 16 | ![autoupdate1](assets/d2bot-autoupdate1.png) 17 | 18 | * you should also check the options: 19 | 20 | ![autoupdate2](assets/d2bot-autoupdate2.png) 21 | 22 | * you could update the monitorized repositories using this utility, with a single R-click: 23 | 24 | ![autoupdate3](assets/d2bot-autoupdate3.png) 25 | 26 | ### commit monitor 27 | 28 | An additional tool which will help you to be informed about the new changes on repositories is [CommitMonitor](https://tools.stefankueng.com/CommitMonitor.html) 29 | 30 | If you want to be notified thrrough [Snarl](http://snarl.fullphat.net/content/download/) you should install/download the zip. 31 | Check the [guide](https://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-projectmonitor.html). 32 | -------------------------------------------------------------------------------- /d2bot/Download.md: -------------------------------------------------------------------------------- 1 | [General Table of Contents](https://github.com/blizzhackers/documentation/#diablo-2-botting-system) 2 | 3 | [D2Bot Table of Contents](https://github.com/blizzhackers/documentation/#d2bot) 4 | 5 | --- 6 | 7 | # Download 8 | 9 | --- 10 | 11 | * [Requirements](#requirements) 12 | * [Download with Github Desktop](#download-with-github-desktop) 13 | * [Compatibility](#compatibility) 14 | * [Keep bot files updated](#keep-bot-files-updated) 15 | 16 | --- 17 | 18 | ### Requirements 19 | **These MUST be installed before you continue.** 20 | * [Microsoft Visual C++ 2010 Redistributable Package (x86)](https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x86.exe) 21 | * [Microsoft .NET Framework 4.0 (or higher)](https://dotnet.microsoft.com/download/dotnet-framework) (Windows 10 and newer may have this installed) 22 | 23 | ### Download with Github Desktop 24 | * Install [Github Desktop](https://desktop.github.com/) 25 | * Open GitHub desktop and select "file" then "clone repository" or click CTRL + SHIFT + O 26 | * Select URL and enter the following: "https://github.com/blizzhackers/kolbot/" 27 | * Select a local path you want to save to. I selected "C:\Users\dom\Desktop\kolbot\kolbot" 28 | * Click Clone and you have successfully downloaded kolbot. 29 | 30 | ![image](https://github.com/magace/documentation/assets/7795098/d3915428-b25e-4e3e-9a3f-889f6d8f203f) 31 | 32 | 33 | 34 | ### Keep bot files updated 35 | The Kolbot scripting library gets regular updates. There is no auto-updater for security reasons so it will be up to you to regularly check for updates. 36 | * Open GitHub Desktop and it should automatically fetch any updates if there are any. 37 | * If there are any new updates you should see a button "Pull origin" Click on that to pull all the latest updates! 38 | 39 | ![image](https://github.com/magace/documentation/assets/7795098/33fb2bbf-ea28-42aa-b204-ead487757e9a) 40 | 41 | 42 | * If you don't see anything you are fully updated. 43 | * Other places to check for updates: https://github.com/blizzhackers/kolbot/commits/ 44 | * The blizzhackers discord development channel will also post any new updates. https://discord.gg/69W7twTm5K 45 | 46 | ### Compatibility 47 | If you run into any issues with D2Bot.exe launching you can try running it in compatibility mode. 48 | * Right-click D2Bot.exe and select properties. From there click compatibility. 49 | * For Win 8 if you get issues, try to "Run this program in compatibility mode for Windows 7" 50 | * Note compatibility will not fix the "D2BS is not responding error" For that make sure you install the [Requirements](#requirements) 51 | 52 | ![d2bot compatibility](assets/d2bot-compatibility.png) 53 | 54 | ### What's Next? 55 | [D2Bot Manager Setup](https://github.com/blizzhackers/documentation/blob/master/d2bot/ManagerSetup.md/#manager-setup) 56 | -------------------------------------------------------------------------------- /d2bot/Keylist.md: -------------------------------------------------------------------------------- 1 | [general table of content](https://github.com/blizzhackers/documentation/#diablo-2-botting-system) 2 | 3 | [d2bot table of content](https://github.com/blizzhackers/documentation/tree/master/d2bot/#d2bot) 4 | 5 | --- 6 | 7 | # Keylist 8 | 9 | --- 10 | 11 | * [info](#info) 12 | * [keylist creation](#keylist-creation) 13 | * [manual edit](#manual-edit) 14 | * [adding raw/loader keys](#adding-raw-loader-keys) 15 | * [set keys](#set-keys) 16 | * [using loader keys](#using-loader-keys) 17 | * [creating loader keys](#creating-loader-keys) 18 | * [creating keylist using loader keys](#creating-keylist-using-loader-keys) 19 | 20 | --- 21 | 22 | ## info 23 | Since 14th Aug 2018 patch you cannot use the keys with 16 alphanumeric strings on d2 server, until you register and [claim them on d2 server account](https://us.battle.net/account/management/claim-code.html), getting the converted 26 strings. 24 | 25 | ## keylist creation 26 | ![keylist1](assets/d2bot-keylist1.jpg) 27 | 28 | * Create a new list by typing in the text box in the bottom left corner and press the '+' button 29 | * Type "file.mpq" in the name column to load keys from *.mpq, leave the other columns blank -- *.mpq files must be placed in the D2 folder 30 | * Use raw cdkeys by giving it a name ex: key1, and filling out the 'Classic' and 'Expansion' columns with the keys 31 | * Import a batch of cdkeys by clicking the folder button and choosing a [list name].csv file, a csv file can be made with excel or text editor -- Ex: File name: keys.csv, Content: key1, 123456790, 123456790 -- This adds a Key List named 'keys' (left hand side) with the key 'key1' (right hand side) 32 | 33 | ## manual edit 34 | You are still able to edit ...\data\cdkeys.json with your code editor of choice. See [IDE-Setup](kolbot/IDES.md/#code-editors-ides) for code editors. 35 | 36 | ### adding raw/loader keys 37 | There are 2 kind of lines: 38 | ```javascript 39 | {"CDKeys":[{"Name":"raw1","Classic":"1234567890","Expansion":"1234567890"}],"Name":"k1"} 40 | {"CDKeys":[{"Name":"key2.mpq","Classic":"","Expansion":""}],"Name":"k2"} 41 | ``` 42 | First line is including raw keys classic and xpac, and second line has a loader key. 43 | 44 | 1st field "Name":"xxx" is the field with name of loader key (it should be located in Diablo II botting folder), but also only the name for raw key that will be shown in manager line on key column when profile is running 45 | 46 | 2nd field "Name":"yyy" is the name of key in the list 47 | 48 | This list will have 2 entries k1 and k2, selectable from drop-down Key List in the profile. When those profiles are running in key column you'll see "raw1", or "key2.mpq". 49 | Your cdkeys.json file can have multiple lines like those, simply edited in np++. 50 | 51 | ### set keys 52 | you don't need more keys to be added into a set of keys, because key switching is worthless in getting R/D (S/D) since June 2017. So one key into a keylist entry is enough. 53 | 54 | even is not required (& recommended) after June 2017, an entry with multiple keys associated have to be something like: 55 | ```javascript 56 | {"CDKeys":[{key1 info}, {key2 info}, {key3 info}], "Name":"set1"} 57 | ``` 58 | case of raw d2lod keys with **set1** entry from key list with "raw1", "raw2", "raw3" sub-keys: 59 | ```javascript 60 | {"CDKeys":[{"Name":"raw1","Classic":"1234567890","Expansion":"1234567890"}, {"Name":"raw2","Classic":"1234567890","Expansion":"1234567890"}, {"Name":"raw3","Classic":"1234567890","Expansion":"1234567890"}],"Name":"set1"} 61 | ``` 62 | 63 | case of loader keys in a set list, **set1** including key1.mpq, key2.mpq, key3.mpq 64 | ```javascript 65 | {"CDKeys":[{"Name":"key1.mpq","Classic":"","Expansion":""},{"Name":"key2.mpq","Classic":"","Expansion":""},{"Name":"key3.mpq","Classic":"","Expansion":""}],"Name":"set1"} 66 | ``` 67 | ## using loader keys 68 | 69 | ### creating loader keys 70 | 71 | Since June 2017 the key switching/swapping not help you at all in d2 server counting. So it's ok to use only 1 cdkeyset/bot. 72 | 73 | * download https://github.com/blizzhackers/D2LoD-files/tree/master/D2LoD-key-utilities. 74 | * read ...\loaderkey-creator\loaderkey-creator-Readme.txt. 75 | * run ...\loaderkey-creator\keyCreator26.exe for 26 digits keys. 76 | * create your keysets d2key.mpq (807 B) and rename them in key1.mpq, key2.mpq, ... 77 | * choose the parent folder of Diablo II, the creator will add /Diablo II at the end of path, but you can manually edit it. 78 | * place the loader keys into your ...\Diablo II\ folder. 79 | 80 | ### creating keylist using loader keys 81 | 82 | follow these steps: 83 | 1. L-click Keys on the manager 84 | 85 | ![keylist2](assets/d2bot-keylist2.png) 86 | 87 | 2. write the name of key set (k1), then click add \+ 88 | 89 | ![keylist3](assets/d2bot-keylist3.png) 90 | 91 | 3. L-click the Name box 92 | 93 | ![keylist4](assets/d2bot-keylist4.png) 94 | 95 | 4. write key1.mpq , then click Apply 96 | 97 | ![keylist5](assets/d2bot-keylist5.png) 98 | 99 | 5. k1 entry with key1.mpq is done 100 | 101 | ![keylist6](assets/d2bot-keylist6.png) 102 | 103 | 6. on bottom left write the name of next key set (k2), then click add \+ 104 | 105 | ![keylist7](assets/d2bot-keylist7.png) 106 | 107 | 7. L-click the Name box, write key2.mpq, then click Apply 108 | 109 | ![keylist8](assets/d2bot-keylist8.png) 110 | 111 | 8. k2 entry with key2.mpq is done 112 | 113 | -------------------------------------------------------------------------------- /d2bot/ManagerSetup.md: -------------------------------------------------------------------------------- 1 | [general table of content](https://github.com/blizzhackers/documentation/#diablo-2-botting-system) 2 | 3 | [d2bot table of content](https://github.com/blizzhackers/documentation/tree/master/d2bot/#d2bot) 4 | 5 | --- 6 | 7 | # Manager Setup 8 | 9 | ### Install Dependencies 10 | 11 | [Microsoft Visual C++ 2010 Redistributable Package (x86)](https://www.microsoft.com/en-us/download/details.aspx?id=26999) 12 | 13 | [Microsoft .NET Framework 4.0 (or higher)](https://dotnet.microsoft.com/download/dotnet-framework) 14 | 15 | ### Launch D2Bot.exe in Administrator Mode 16 | 17 | If you use Windows 8/8.1, run D2Bot.exe in Windows 7 Compatibility Mode + Administrator Mode 18 | 19 | ![managersetup1](assets/d2bot-managersetup1.png) 20 | 21 | 1. Start selected profile(s) 22 | 2. Stop selected profile(s) 23 | 3. Show selected profile(s) D2 window 24 | 4. Hide selected profile(s) D2 window 25 | 5. Add profile 26 | 6. Delete profile 27 | 7. Edit profile 28 | 8. Clone profile 29 | 9. Add IRC Profile (IRC Bot) 30 | 10. D2 CDKey Editor 31 | 11. Schedule Editor 32 | 12. Save current config and state 33 | 13. About cointains suport links and shows if an update is available (don't use this kind of update, but update your entire repository d2bot-with-kolbot using tortoiseSVN or other tools). 34 | 35 | ![managersetup1-1](assets/d2bot-managersetup1-1.png) 36 | 37 | 14. Console prints messages from Kolbot and shows items found 38 | 15. Char Viewer shows items located on mule accounts 39 | 16. Key Wizard shows information about keys 40 | 41 | ### Adding D2 CDKeys 42 | 43 | ![managersetup2](assets/d2bot-managersetup2.jpg) 44 | 45 | * Create a new list by typing in the text box in the bottom left corner and press the '+' button 46 | * Type [file].mpq in the name column to load keys from *.mpq, leave the other columns blank -- *.mpq files must be placed in the D2 folder 47 | * Use raw cdkeys by giving it a name ex: key1, and filling out the 'Classic' and 'Expansion' columns with the keys 48 | * Import a batch of cdkeys by clicking the folder button and choosing a [list name].csv file, a csv file can be made with excel or text editor -- Ex: File name: keys.csv, Content: key1, 123456790, 123456790 -- This adds a Key List named 'keys' (left hand side) with the key 'key1' (right hand side) 49 | 50 | * additional info for managing [key list](https://github.com/blizzhackers/documentation/blob/master/d2bot/Keylist.md#keylist) 51 | 52 | ### Create a Profile 53 | 54 | ![managersetup3](assets/d2bot-managersetup3.jpg) 55 | 56 | 1. Profile Name (use a unique name without special characters or spaces) 57 | 2. Account (D2 account name) 58 | 3. Password (D2 account password) 59 | 4. Character Name (cAsE SenSiTive!) 60 | 5. Game Name and Password (Leave password empty for public games) 61 | 6. Difficulty 62 | 7. Realm 63 | 8. Mode: 64 | 65 | - Single player 66 | - Battle.net 67 | - Open Battle.net 68 | - Host TCP/IP game 69 | - Join TCP/IP game 70 | 71 | 9. Parameters: 72 | 73 | **-w** = windowed mode (don't change this option, it is needed for D2BS) 74 | 75 | **-sleepy** = saves resources by inserting sleep call to game loop 76 | 77 | **-lq** = Low Quality (low quality graphics uses less resources) 78 | 79 | **-ns** = Disables ingame sound (uses less resources) 80 | 81 | **-ftj** = Fail-to-join 82 | 83 | **-L** = Loader only mode (does NOT load any scripts) 84 | 85 | 10. Path to Game.exe (or any copy of Game.exe if you use proxies) 86 | 11. Entry Point - select starter script from the kolbot folder 87 | 88 | **D2BotBlank.dbj** - blank starter used for testing 89 | 90 | **D2BotChannel.dbj** - using a chat channel 91 | 92 | **D2BotFollow.dbj** - start as follower, join leader defined in character config 93 | 94 | **D2BotGameAction.dbj** - used for limedrop 95 | 96 | **D2BotLead.dbj** - start as leader/single mf char 97 | 98 | **D2BotMap.dbj** - manual play with maphack enabled 99 | 100 | **D2BotMule.dbj** - used by the mule profile 101 | 102 | **D2BotMuleLog.dbj** - runs the mule logging script 103 | 104 | **D2BotPubJoin.dbj** - joining public games 105 | 106 | 12. Select a cd key list previous created. (leave blank to use original key with D2 installation) 107 | 13. Select schedule (optional) 108 | 14. Set how many runs per key Recommended value is 0, do not switch keys at this time 109 | 15. Location where D2 Window will position on your screen (if Visible [18] is checked). -- ex. 0,0 = top left of desktop 110 | 16. Send custom data to scripts (optional, use if you know how to) 111 | 17. Enable selected schedule [13] 112 | 18. Launches visible D2 Window (by default it will be minimized) 113 | 19. Enables RD Block (don't enable unless you know what you are doing) 114 | 115 | ### Menu 116 | 117 | ![managersetup4](assets/d2bot-managersetup4.png) 118 | 119 | 1. Start all profiles DON'T RUN MORE THAN WHAT YOUR PC CAN HANDLE! 120 | 2. Stop all profiles 121 | 3. Show all running D2 Windows 122 | 4. Hide all running D2 Windows 123 | 5. Save current D2Bot Manager state 124 | 6. Exit program 125 | 7. Hide program to tray 126 | 127 | ### Settings 128 | 129 | ![managersetup5](assets/d2bot-managersetup5.png) 130 | 131 | 1. D2 Version - 1.14d (note that the trunk/master isn't working with 1.13d without some files from branches/1.13d) 132 | 2. For low resource PC or running MANY profiles, higher response time will work better but detect failures slower 133 | 3. Sets the delay (in MS) between starting multiple profiles 134 | 4. Start D2 Windows in hidden mode (default is minimized) 135 | 5. Use the system font 136 | 6. Show item header (shows account and character information in the 'Char Viewer' tab) 137 | 7. Reloads mule files in 'Char Viewer' tab 138 | 8. Close all instances of Game.exe (useful for rogue or crashed clients) 139 | 9. Run API Server 140 | 10. Developer Mode (ignore, will not work if this is enabled) 141 | 142 | ### Scheduler (optional) 143 | 144 | Allow profiles to start and stop automatically based on a designated daily schedule When the scheduler is enabled under the profile config, D2Bot will automatically start and stop the profiles if the current local time is between the 'Start Time' and 'End Time' 145 | 146 | ![managersetup6](assets/d2bot-managersetup6.png) 147 | 148 | * Create a new Schedule by typing in the text box in the bottom left corner and press the '+' button 149 | * Add a timespan by typing a consecutive 'Start' and 'End' time in their respective columns (note this uses 24 hour time) 150 | * Import a schedule by clicking the folder button and choosing a [schedule name].csv file, a csv file can be made with excel or text editor -- Ex: File name: schedule.csv, Content: 01:00, 06:00 -- This adds a Schedule named 'schedule' (left hand side) that runs between 1 AM and 6 AM 151 | -------------------------------------------------------------------------------- /d2bot/README.md: -------------------------------------------------------------------------------- 1 | [general table of content](https://github.com/blizzhackers/documentation/#diablo-2-botting-system) 2 | 3 | [kolbot table of content](https://github.com/blizzhackers/documentation/tree/master/kolbot/#kolbot) 4 | 5 | --- 6 | 7 | # D2Bot 8 | 9 | d2bot manager by [@noah-](https://github.com/noah-) 10 | 11 | --- 12 | 13 | * [Download](Download.md/#download): how to download files and to keep them updated 14 | 15 | * [ManagerSetup](ManagerSetup.md/#manager-setup): how to set-up d2bot manager 16 | 17 | * [Keylist Configuration](Keylist.md/#keylist): additional info for key list management 18 | 19 | * [Autoupdate](Autoupdate.md/#autoupdate): project monitor, commit monitor 20 | -------------------------------------------------------------------------------- /d2bot/assets/d2bot-autoupdate1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-autoupdate1.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-autoupdate2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-autoupdate2.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-autoupdate3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-autoupdate3.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-compatibility.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-compatibility.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-keyclaimedonbattlenet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-keyclaimedonbattlenet.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-keylist1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-keylist1.jpg -------------------------------------------------------------------------------- /d2bot/assets/d2bot-keylist2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-keylist2.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-keylist3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-keylist3.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-keylist4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-keylist4.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-keylist5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-keylist5.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-keylist6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-keylist6.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-keylist7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-keylist7.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-keylist8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-keylist8.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-keylistcdkeyinuse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-keylistcdkeyinuse.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-managersetup1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-managersetup1-1.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-managersetup1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-managersetup1.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-managersetup2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-managersetup2.jpg -------------------------------------------------------------------------------- /d2bot/assets/d2bot-managersetup3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-managersetup3.jpg -------------------------------------------------------------------------------- /d2bot/assets/d2bot-managersetup4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-managersetup4.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-managersetup5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-managersetup5.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-managersetup6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-managersetup6.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-setup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-setup.jpg -------------------------------------------------------------------------------- /d2bot/assets/d2bot-tortoise1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-tortoise1.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-tortoise2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-tortoise2.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-tortoise3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-tortoise3.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-tortoise4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-tortoise4.png -------------------------------------------------------------------------------- /d2bot/assets/d2bot-tortoise5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/d2bot/assets/d2bot-tortoise5.png -------------------------------------------------------------------------------- /d2bs/README.md: -------------------------------------------------------------------------------- 1 | # D2BS 2 | 3 | d2bs core by [view developers](https://app.assembla.com/spaces/d2bs/team) 4 | 5 | * [API Reference](https://github.com/noah-/d2bs/blob/master/README.md) 6 | * [Current Source](https://github.com/noah-/d2bs) 7 | * [Original Source](https://app.assembla.com/spaces/d2bs/subversion/source) 8 | 9 | -------------------------------------------------------------------------------- /kolbot/Automule.md: -------------------------------------------------------------------------------- 1 | [General Table of Contents](../README.md#diablo-2-botting-system) 2 | 3 | [Kolbot Table of Contents](README.md#kolbot) 4 | 5 | --- 6 | 7 | # Automule 8 | 9 | --- 10 | 11 | * [Step-by-Step Guide to Muling in Kolbot](#step-by-step-guide-to-muling-in-kolbot) 12 | * [Multiple Mules and Multiple Realm Muling](#multiple-mules-and-multiple-realm-muling) 13 | * [Torch & Anni Muling](#torch-anni-muling) 14 | 15 | --- 16 | 17 | ## Step-by-Step Guide to Muling in Kolbot 18 | 19 | 1. Open and configure MuleConfig.js found in kolbot/libs/systems/automule/config folder 20 | **These are examples corresponding to the manger image below. Your settings should be different.** 21 | 22 | ![image](https://github.com/magace/documentation/assets/7795098/3e3afe6f-997f-4953-a8fb-fd4ff7bd51bb) 23 | 24 | 2. Open D2Bot# and click Add Profile icon 25 | 26 | 3. Input Profile Name, Diablo Path and use D2BotMule.dbj as Entry Script. Profile Name should match muleProfile in MuleConfig.js 27 | 28 | Click OK. You're done. 29 | ![image](https://github.com/magace/documentation/assets/7795098/d9c97db9-6120-43b7-be07-24e5f941d4b5) 30 | 31 | **Notes:** 32 | 33 | You must have at least 2 CD Keys to use kolbot AutoMule. 34 | 35 | The mule profile is automatically started and stopped so you don't need to do that yourself. 36 | 37 | You can test muling by running one of the enabledProfiles and pressing Numpad 5 when in a game or right-clicking on a profile and select "mule profile". 38 | 39 | 40 | ## Multiple Mules and Multiple Realm Muling 41 | 42 | The Mules object can take multiple sub-entries which are separated by a comma. 43 | 44 | This makes it possible to use AutoMule on multiple realms or create custom muling rules (ie. which profile will use which mule). 45 | 46 | Example config for muling on two realms: 47 | 48 | ![image](https://github.com/magace/documentation/assets/7795098/e2f6a76d-9987-4e6d-b759-8d77853266a7) 49 | 50 | 51 | The names of each sub-entry, must be different ("Mule1" and "Mule2" in the example). 52 | 53 | The settings for each sub-entry should use differnt names if they are on the running on the same same realm, muleProfile, accountPrefix, charPrfix. 54 | 55 | 56 | 57 | ## Torch Anni Muling 58 | 59 | TorchAnniMule is used in conjunction with a profile running OrgTorch or CloneKilla script to exclusively mule Hellfire or Annihilius unique charms. 60 | 61 | ![image](https://github.com/magace/documentation/assets/7795098/85e146bf-df17-460c-9508-180f6a5760aa) 62 | 63 | 64 | Configuration is the same as standard automule. 65 | TorchAnniMules.js can be found in kolbot/libs/systems/automule/config folder. 66 | 67 | ## Final Notes 68 | It is not recommended to mix torch mule accounts with regular automule accounts. For best results use a separate profile. 69 | 70 | Continuous mule will greatly reduce the times the mule logs in reducing the chance of realm down. 71 | 72 | -------------------------------------------------------------------------------- /kolbot/Cubing.md: -------------------------------------------------------------------------------- 1 | [General Table of Contents](../README.md#diablo-2-botting-system) 2 | 3 | [Kolbot Table of Contents](README.md#kolbot) 4 | 5 | --- 6 | 7 | # Cubing 8 | 9 | You should enable the cubing. If your toon hasn't the horadric cube, at the game's beginning he will travel to act 2 to get it. 10 | ```javascript 11 | /* 12 | * All recipe names are available in Templates/Cubing.txt. For item names/classids check core/GameData/NTItemAlias.js 13 | * The format is Config.Recipes.push([recipe_name, item_name_or_classid, etherealness]). 14 | * Etherealness is optional and only applies to some recipes. 15 | */ 16 | Config.Cubing = true; // Set to true to enable cubing. 17 | ``` 18 | --- 19 | 20 | ### gems 21 | 22 | - for cubing the gems with lower quality than flawless, check https://github.com/blizzhackers/documentation/blob/master/kolbot/MiscellaneousOptions.md/#cubing-all-kind-of-gems 23 | ```javascript 24 | // Ingredients for the following recipes will be auto-picked, for classids check libs/core/GameData/NTItemAlias.js 25 | 26 | // Config.Recipes.push([Recipe.Gem, "Flawed Amethyst"]); // make Flawed Amethyst 27 | // Config.Recipes.push([Recipe.Gem, "Flawed Topaz"]); // make Flawed Topaz 28 | // Config.Recipes.push([Recipe.Gem, "Flawed Sapphire"]); // make Flawed Sapphire 29 | // Config.Recipes.push([Recipe.Gem, "Flawed Emerald"]); // make Flawed Emerald 30 | // Config.Recipes.push([Recipe.Gem, "Flawed Ruby"]); // make Flawed Ruby 31 | // Config.Recipes.push([Recipe.Gem, "Flawed Diamond"]); // make Flawed Diamond 32 | // Config.Recipes.push([Recipe.Gem, "Flawed Skull"]); // make Flawed Skull 33 | 34 | // Config.Recipes.push([Recipe.Gem, "Amethyst"]); // make Amethyst 35 | // Config.Recipes.push([Recipe.Gem, "Topaz"]); // make Topaz 36 | // Config.Recipes.push([Recipe.Gem, "Sapphire"]); // make Sapphire 37 | // Config.Recipes.push([Recipe.Gem, "Emerald"]); // make Emerald 38 | // Config.Recipes.push([Recipe.Gem, "Ruby"]); // make Ruby 39 | // Config.Recipes.push([Recipe.Gem, "Diamond"]); // make Diamond 40 | // Config.Recipes.push([Recipe.Gem, "Skull"]); // make Skull 41 | 42 | // Config.Recipes.push([Recipe.Gem, "Flawless Amethyst"]); // make Flawless Amethyst 43 | // Config.Recipes.push([Recipe.Gem, "Flawless Topaz"]); // make Flawless Topaz 44 | // Config.Recipes.push([Recipe.Gem, "Flawless Sapphire"]); // make Flawless Sapphire 45 | // Config.Recipes.push([Recipe.Gem, "Flawless Emerald"]); // make Flawless Emerald 46 | // Config.Recipes.push([Recipe.Gem, "Flawless Ruby"]); // make Flawless Ruby 47 | // Config.Recipes.push([Recipe.Gem, "Flawless Diamond"]); // make Flawless Diamond 48 | // Config.Recipes.push([Recipe.Gem, "Flawless Skull"]); // make Flawless Skull 49 | 50 | Config.Recipes.push([Recipe.Gem, "Perfect Amethyst"]); // Make Perfect Amethyst 51 | Config.Recipes.push([Recipe.Gem, "Perfect Topaz"]); // Make Perfect Topaz 52 | Config.Recipes.push([Recipe.Gem, "Perfect Sapphire"]); // Make Perfect Sapphire 53 | Config.Recipes.push([Recipe.Gem, "Perfect Emerald"]); // Make Perfect Emerald 54 | Config.Recipes.push([Recipe.Gem, "Perfect Ruby"]); // Make Perfect Ruby 55 | Config.Recipes.push([Recipe.Gem, "Perfect Diamond"]); // Make Perfect Diamond 56 | Config.Recipes.push([Recipe.Gem, "Perfect Skull"]); // Make Perfect Skull 57 | ``` 58 | 59 | ### essences 60 | ```javascript 61 | // Ingredients for the following recipes will be auto-picked, for classids check libs/core/GameData/NTItemAlias.js 62 | 63 | // Config.Recipes.push([Recipe.Token]); // Make Token of Absolution 64 | ``` 65 | 66 | ### runes 67 | 68 | ```javascript 69 | // Ingredients for the following recipes will be auto-picked, for classids check libs/core/GameData/NTItemAlias.js 70 | 71 | // Config.Recipes.push([Recipe.Rune, "Eld Rune"]); // Upgrade El to Eld 72 | // Config.Recipes.push([Recipe.Rune, "Tir Rune"]); // Upgrade Eld to Tir 73 | // Config.Recipes.push([Recipe.Rune, "Nef Rune"]); // Upgrade Tir to Nef 74 | // Config.Recipes.push([Recipe.Rune, "Eth Rune"]); // Upgrade Nef to Eth 75 | // Config.Recipes.push([Recipe.Rune, "Ith Rune"]); // Upgrade Eth to Ith 76 | // Config.Recipes.push([Recipe.Rune, "Tal Rune"]); // Upgrade Ith to Tal 77 | // Config.Recipes.push([Recipe.Rune, "Ral Rune"]); // Upgrade Tal to Ral 78 | // Config.Recipes.push([Recipe.Rune, "Ort Rune"]); // Upgrade Ral to Ort 79 | 80 | // Config.Recipes.push([Recipe.Rune, "Thul Rune"]); // Upgrade Ort to Thul 81 | // Config.Recipes.push([Recipe.Rune, "Amn Rune"]); // Upgrade Thul to Amn 82 | // Config.Recipes.push([Recipe.Rune, "Sol Rune"]); // Upgrade Amn to Sol 83 | // Config.Recipes.push([Recipe.Rune, "Shael Rune"]); // Upgrade Sol to Shael 84 | // Config.Recipes.push([Recipe.Rune, "Dol Rune"]); // Upgrade Shael to Dol 85 | // Config.Recipes.push([Recipe.Rune, "Hel Rune"]); // Upgrade Dol to Hel 86 | // Config.Recipes.push([Recipe.Rune, "Io Rune"]); // Upgrade Hel to Io 87 | // Config.Recipes.push([Recipe.Rune, "Lum Rune"]); // Upgrade Io to Lum 88 | // Config.Recipes.push([Recipe.Rune, "Ko Rune"]); // Upgrade Lum to Ko 89 | // Config.Recipes.push([Recipe.Rune, "Fal Rune"]); // Upgrade Ko to Fal 90 | // Config.Recipes.push([Recipe.Rune, "Lem Rune"]); // Upgrade Fal to Lem 91 | 92 | Config.Recipes.push([Recipe.Rune, "Pul Rune"]); // Upgrade Lem to Pul 93 | Config.Recipes.push([Recipe.Rune, "Um Rune"]); // Upgrade Pul to Um 94 | Config.Recipes.push([Recipe.Rune, "Mal Rune"]); // Upgrade Um to Mal 95 | Config.Recipes.push([Recipe.Rune, "Ist Rune"]); // Upgrade Mal to Ist 96 | Config.Recipes.push([Recipe.Rune, "Gul Rune"]); // Upgrade Ist to Gul 97 | Config.Recipes.push([Recipe.Rune, "Vex Rune"]); // Upgrade Gul to Vex 98 | ``` 99 | 100 | ### crafting 101 | 102 | In your pickit file you may specify the level for the base items: 103 | ```javascript 104 | // Crafting gear 105 | [name] == vampirebonegloves && [quality] == magic && [level] >= 94 # // Diablo/Baal 106 | [name] == mithrilcoil && [quality] == magic && [level] >= 94 # // Diablo/Baal 107 | [type] == ring && [quality] == magic && [level] >= 94 # // Diablo/Baal 108 | [type] == amulet && [quality] == magic && [level] >= 94 # // Diablo/Baal 109 | ``` 110 | Blood - Caster - Hit Power - Safety Recipes 111 | ```javascript 112 | // Ingredients for the following recipes will be auto-picked, for classids check libs/core/GameData/NTItemAlias.js 113 | 114 | //Config.Recipes.push([Recipe.Blood.Helm, "Armet"]); // Craft Blood Helm 115 | //Config.Recipes.push([Recipe.Blood.Boots, "Mirrored Boots"]); // Craft Blood Boots 116 | //Config.Recipes.push([Recipe.Blood.Gloves, "Vampirebone Gloves"]); // Craft Blood Gloves 117 | //Config.Recipes.push([Recipe.Blood.Belt, "Mithril Coil"]); // Craft Blood Belt 118 | //Config.Recipes.push([Recipe.Blood.Shield, "Blade Barrier"]); // Craft Blood Shield 119 | //Config.Recipes.push([Recipe.Blood.Body, "Hellforge Plate"]); // Craft Blood Armor 120 | //Config.Recipes.push([Recipe.Blood.Amulet]); // Craft Blood Amulet 121 | //Config.Recipes.push([Recipe.Blood.Ring]); // Craft Blood Ring 122 | //Config.Recipes.push([Recipe.Blood.Weapon, "Berserker Axe"]); // Craft Blood Weapon 123 | 124 | //Config.Recipes.push([Recipe.Caster.Helm, "Demonhead Mask"]); // Craft Caster Helm 125 | //Config.Recipes.push([Recipe.Caster.Boots, "Wyrmhide Boots"]); // Craft Caster Boots 126 | //Config.Recipes.push([Recipe.Caster.Gloves, "Bramble Mitts"]); // Craft Caster Gloves 127 | //Config.Recipes.push([Recipe.Caster.Belt, "Vampirefang Belt"]); // Craft Caster Belt 128 | //Config.Recipes.push([Recipe.Caster.Shield, "Luna"]); // Craft Caster Shield 129 | //Config.Recipes.push([Recipe.Caster.Body, "Archon Plate"]); // Craft Caster Armor 130 | //Config.Recipes.push([Recipe.Caster.Amulet]); // Craft Caster Amulet 131 | //Config.Recipes.push([Recipe.Caster.Ring]); // Craft Caster Ring 132 | //Config.Recipes.push([Recipe.Caster.Weapon, "Seraph Rod"]); // Craft Caster Weapon 133 | 134 | //Config.Recipes.push([Recipe.HitPower.Helm, "Giant Conch"]); // Craft Hit Power Helm 135 | //Config.Recipes.push([Recipe.HitPower.Boots, "Boneweave Boots"]); // Craft Hit Power Boots 136 | //Config.Recipes.push([Recipe.HitPower.Gloves, "Vambraces"]); // Craft Hit Power Gloves 137 | //Config.Recipes.push([Recipe.HitPower.Belt, "Troll Belt"]); // Craft Hit Power Belt 138 | //Config.Recipes.push([Recipe.HitPower.Shield, "Ward"]); // Craft Hit Power Shield 139 | //Config.Recipes.push([Recipe.HitPower.Body, "Kraken Shell"]); // Craft Hit Power Armor 140 | //Config.Recipes.push([Recipe.HitPower.Amulet]); // Craft Hit Power Amulet 141 | //Config.Recipes.push([Recipe.HitPower.Ring]); // Craft Hit Power Ring 142 | //Config.Recipes.push([Recipe.HitPower.Weapon, "Scourge"]); // Craft Hit Power Weapon | "Blunt" = All maces, rods (+50% Undead), excepting orbs 143 | 144 | //Config.Recipes.push([Recipe.Safety.Helm, "Corona"]); // Craft Safety Helm 145 | //Config.Recipes.push([Recipe.Safety.Boots, "Myrmidon Boots"]); // Craft Safety Boots 146 | //Config.Recipes.push([Recipe.Safety.Gloves, "Ogre Gauntlets"]); // Craft Safety Gloves 147 | //Config.Recipes.push([Recipe.Safety.Belt, "Spiderweb Sash"]); // Craft Safety Belt 148 | //Config.Recipes.push([Recipe.Safety.Shield, "Monarch"]); // Craft Safety Shield 149 | //Config.Recipes.push([Recipe.Safety.Body, "Great Hauberk"]); // Craft Safety Armor 150 | //Config.Recipes.push([Recipe.Safety.Amulet]); // Craft Safety Amulet 151 | //Config.Recipes.push([Recipe.Safety.Ring]); // Craft Safety Ring 152 | //Config.Recipes.push([Recipe.Safety.Weapon, "Matriarchal Javelin"]); // Craft Safety Weapon 153 | //Config.Recipes.push([Recipe.Safety.Weapon, "Matriarchal Spear"]); // Craft Safety Weapon 154 | 155 | ``` 156 | The required status for crafted items should also be added in the pickit, like in [default lines 741-771 of kolton.nip](https://github.com/blizzhackers/kolbot/blob/master/d2bs/kolbot/pickit/kolton.nip#L741-L771) 157 | 158 | If you wanna sell the crafted items, instead default dropping, check https://github.com/blizzhackers/documentation/blob/master/kolbot/MiscellaneousOptions.md/#sell-cubing-items 159 | 160 | ### reroll magic/rare items 161 | 162 | ```javascript 163 | // The gems not used by other recipes will be used for magic item rerolling. 164 | 165 | //Config.Recipes.push([Recipe.Reroll.Magic, "Diadem"]); // Reroll magic Diadem 166 | //Config.Recipes.push([Recipe.Reroll.Magic, "Grand Charm"]); // Reroll magic Grand Charm (ilvl 91+) 167 | 168 | 169 | // the cubing formula: 6 Perfect Skulls + 1 Rare Item = 1 random low quality rare item of the same type 170 | //Config.Recipes.push([Recipe.Reroll.Rare, "Diadem"]); // Reroll rare Diadem 171 | 172 | 173 | // the cubing formula: 1 Perfect Skull + 1 Rare Item + Stone of Jordan = 1 high quality new rare item of the same type 174 | //Config.Recipes.push([Recipe.Reroll.HighRare, "Diadem"]); // Reroll high rare Diadem 175 | ``` 176 | 177 | ### socketing 178 | 179 | ```javascript 180 | /* Base item for the following recipes must be in pickit. The rest of the ingredients will be auto-picked. 181 | * Use Roll.Eth, Roll.NonEth or Roll.All to determine what kind of base item to roll - ethereal, non-ethereal or all. 182 | */ 183 | //Config.Recipes.push([Recipe.Socket.Weapon, "Thresher", Roll.Eth]); // Socket ethereal Thresher 184 | //Config.Recipes.push([Recipe.Socket.Weapon, "Cryptic Axe", Roll.Eth]); // Socket ethereal Cryptic Axe 185 | //Config.Recipes.push([Recipe.Socket.Armor, "Sacred Armor", Roll.Eth]); // Socket ethereal Sacred Armor 186 | //Config.Recipes.push([Recipe.Socket.Armor, "Archon Plate", Roll.Eth]); // Socket ethereal Archon Plate 187 | ``` 188 | 189 | ### unique upgrades 190 | 191 | ```javascript 192 | /* Base item for the following recipes must be in pickit. The rest of the ingredients will be auto-picked. 193 | * Use Roll.Eth, Roll.NonEth or Roll.All to determine what kind of base item to roll - ethereal, non-ethereal or all. 194 | */ 195 | 196 | //Config.Recipes.push([Recipe.Unique.Armor.ToExceptional, "Heavy Gloves", Roll.NonEth]); // Upgrade Bloodfist to Exceptional 197 | //Config.Recipes.push([Recipe.Unique.Armor.ToExceptional, "Light Gauntlets", Roll.NonEth]); // Upgrade Magefist to Exceptional 198 | //Config.Recipes.push([Recipe.Unique.Armor.ToElite, "Sharkskin Gloves", Roll.NonEth]); // Upgrade Bloodfist or Grave Palm to Elite (ladder) 199 | //Config.Recipes.push([Recipe.Unique.Armor.ToElite, "Battle Gauntlets", Roll.NonEth]); // Upgrade Magefist or Lavagout to Elite (ladder) 200 | //Config.Recipes.push([Recipe.Unique.Armor.ToElite, "War Boots", Roll.NonEth]); // Upgrade Gore Rider to Elite (ladder) 201 | ``` 202 | 203 | --- 204 | 205 | ## runeword 206 | You should enable the making of runewords. 207 | 208 | ```javascript 209 | /* Runeword config. All recipes are available in Templates/Runewords.txt 210 | * Keep lines follow pickit format and any given runeword is tested vs ALL lines so you don't need to repeat them 211 | */ 212 | Config.MakeRunewords = true; // Set to true to enable runeword making/rerolling 213 | 214 | Config.Runewords.push([Runeword.Insight, "Thresher", Roll.Eth]); // Make ethereal Insight Thresher 215 | Config.Runewords.push([Runeword.Insight, "Cryptic Axe", Roll.Eth]); // Make ethereal Insight Cryptic Axe 216 | //Config.Runewords.push([Runeword.Insight, "Great Poleaxe"]); // Make Insight Great Poleaxe 217 | //Config.Runewords.push([Runeword.Insight, "Giant Thresher"]); // Make Insight Giant Thresher 218 | Config.Runewords.push([Runeword.Insight, "Colossus Voulge"]); // Make Insight Colossus Voulge 219 | Config.KeepRunewords.push("[type] == polearm # [meditationaura] == 17"); // medium Insight 220 | //Config.KeepRunewords.push("[type] == polearm # [meditationaura] == 17 && [enhanceddamage] >= 260 && [attackrate] >= 250"); // perfect Insight 221 | 222 | Config.Runewords.push([Runeword.Grief, "Phase Blade"]); // Make Grief Phase Blade 223 | //Config.Runewords.push([Runeword.Grief, "Berserker Axe"]); // Make Grief Berserker Axe 224 | Config.KeepRunewords.push("([type] == sword || [type] == axe) # [plusmaxdamage] >= 390"); // medium Grief 225 | //Config.KeepRunewords.push("([type] == sword || [type] == axe) # [itemfasterattackrate] >= 40 && [plusmaxdamage] >= 400"); // perfect Grief and *optional [itempiercepois] >= 25 226 | 227 | Config.Runewords.push([Runeword.CallToArms, "Crystal Sword"]); // Make CTA Crystal Sword 228 | Config.Runewords.push([Runeword.CallToArms, "Phase Blade"]); // Make CTA Phase Blade 229 | //Config.Runewords.push([Runeword.CallToArms, "Flail"]); // Make CTA Flail 230 | //Config.KeepRunewords.push("[name] == crystalsword || [name] == phaseblade || [name] == flail # [plusskillbattlecommand] >= 3 && [plusskillbattleorders] >=3"); 231 | Config.KeepRunewords.push("[name] == crystalsword || [name] == phaseblade || [name] == flail # [plusskillbattlecommand] >= 6 && [plusskillbattleorders] >=6 && ["plusskillbattlecry"] >= 4"); // perfect CTA and *optional [enhanceddamage] = 290% 232 | 233 | Config.Runewords.push([Runeword.Spirit, "Crystal Sword"]); // Make Spirit Crystal Sword 234 | Config.Runewords.push([Runeword.Spirit, "Broad Sword"]); // Make Spirit Broad Sword 235 | //Config.Runewords.push([Runeword.Spirit, "Battle Sword"]); // Make Spirit Battle Sword 236 | //Config.Runewords.push([Runeword.Spirit, "Phase Blade"]); // Make Spirit Phase Blade 237 | Config.Runewords.push([Runeword.Spirit, "Monarch", Roll.NonEth]); // Make Spirit Monarch 238 | Config.Runewords.push([Runeword.Spirit, "Sacred Targe", Roll.NonEth]); // Make Spirit Sacred Targe 239 | Config.Runewords.push([Runeword.Spirit, "Kurast Shield"]); // Make Spirit Kurast Shield 240 | //Config.Runewords.push([Runeword.Spirit, "Vortex Shield"]); // Make Spirit Vortex Shield 241 | Config.KeepRunewords.push("[type] == sword || [type] == shield || [type] == auricshields # [fcr] == 35"); // middle spirit 242 | //Config.KeepRunewords.push("[type] == sword || [type] == shield || [type] == auricshields # [fcr] == 35") && [maxmana] >= 112 && [itemabsorbmagic] >=8; // perfect spirit 243 | 244 | //Config.Runewords.push([Runeword.Prudence, "Sacred Armor", Roll.Eth]); // Make ethereal Prudence Sacred Armor 245 | //Config.KeepRunewords.push("[type] == Armor # [enhanceddefense] == 170 && [fireresist] == 35"); 246 | ``` -------------------------------------------------------------------------------- /kolbot/D2BotMuleLog.md: -------------------------------------------------------------------------------- 1 | [General Table of Contents](../README.md#diablo-2-botting-system) 2 | 3 | [Kolbot Table of Contents](README.md#kolbot) 4 | 5 | --- 6 | 7 | # D2BotMuleLog 8 | 9 | --- 10 | 11 | * [info](#info) 12 | * [how to set up](#how-to-set-up) 13 | * [searching for items](#searching-for-items) 14 | * [optional mule viewer](#optional-mule-viewer) 15 | * [dropper](#dropper) 16 | * [diabase & d2bs](#diabase--d2bs) 17 | 18 | --- 19 | 20 | ### Info 21 | It's a D2BS starter script which allow to log the items from inventory, stash and the equipped ones (including merc) to text files, then to show them in the tab of the manager. 22 | 23 | ### How to set up 24 | In kolbot/libs/systems/mulelogger/LoggerConfig.js fill out `LogAccounts` 25 | ```javascript 26 | LogAccounts: { 27 | /* Format: 28 | "account1/password1/realm": ["charname1", "charname2 etc"], 29 | "account2/password2/realm": ["charnameX", "charnameY etc"], 30 | "account3/password3/realm": ["all"] 31 | 32 | To log a full account, put "account/password/realm": ["all"] 33 | 34 | realm = useast, uswest, europe or asia 35 | 36 | Enter Individual entries are separated with a comma below 37 | */ 38 | "exampleAcc/pa33word3/realm": ["all"], 39 | }, 40 | ``` 41 | ! the realm should be written with lowercase letters (see line 16), otherwise you'll get an error in OOG.js 42 | ```javascript 43 | LogGame: ["", ""], // ["gamename", "password"] 44 | ``` 45 | 46 | 47 | At the first run set the next variables (lines 10-17): 48 | ```javascript 49 | LogNames: true, // Put account/character name on the picture 50 | ``` 51 | ! set false if you wanna use your item images ...(related to SaveScreenShot: true) 52 | ```javascript 53 | LogItemLevel: true, // Add item level to the picture 54 | LogEquipped: false, // include equipped items 55 | LogMerc: false, // include items merc has equipped (if alive) 56 | SaveScreenShot: false, // Save pictures in jpg format (saved in 'Images' folder) 57 | AutoPerm: true, // override InGameTime to perm character 58 | IngameTime: rand(180, 210), // (180, 210) to avoid RD, increase it to (7230, 7290) for mule perming 59 | ``` 60 | 61 | LogEquipped - will be logged all items, but the potions/tomes or other low level items will be skipped from log - see **skipItem** function from core/Item.js. 62 | 63 | In case of logging all the chars (the visible 8), at the end the d2 will be reset to main screen, re-login and after rechecking the first char it will be closed automatically by the manager and the related profile, too. This isn't working in case of setting a single mule char, when you have to stop that profile manually. 64 | 65 | The profile doesn't need all fields completed: 66 | 67 | ![d2botmulelog1](assets/kolbot-d2botmulelog1.png) 68 | * Location coordinates only if Visible is checked 69 | 70 | there will be automatically created in ...\mules\ the "Realm\Account\" subfolders. Charnames will be ordered alphabetically. 71 | 72 | ![d2botmulelog2](assets/kolbot-d2botmulelog2.png) 73 | 74 | the logging info for items includes the shapes and other details and you'll see on mouse over the image of the item (other than the screenshots from Images folder): 75 | 76 | ![d2botmulelog3](assets/kolbot-d2botmulelog3.png) 77 | 78 | and with R-click you have these option for saved items: 79 | 80 | ![d2botmulelog4](assets/kolbot-d2botmulelog4.png) 81 | 82 | You'll have that info in the "Char Viewer" tab of the manager console as long as you keep those log files in ...\mules\ folder. Those will be automatically loaded at every D2Bot.exe start, but there is an option in Settings > Refresh Char View, to reload the logging files. 83 | Every item is saved on different line, so you can edit those logging files easily with any txt/code editor of choice. See [IDE-Setup](kolbot/IDES.md/#code-editors-ides) for code editors. 84 | 85 | It will be saved in ...\logs\MuleLog.json the current account and the current charname. This have to be edited or removed in case of crashes when some chars were omitted from logging. At the end of full account logging, that file is deleted automatically. 86 | 87 | ### searching for items 88 | In the left box of tab, select the branch (Realm or Account) where you are trying to find the item. Use the right-bottom search box. It accepts regular expressions, so you can search for just about anything as long as the query is correctly written. 89 | 90 | ![d2botmulelog5](assets/kolbot-d2botmulelog5.png) 91 | 92 | The account/charname will be logged automatically (and help you in searching items) and you'll see on mouse over the item list, the "account / charname" in top-left of that image if in the manager Settings is activated the option 93 | 94 | ![d2botmulelog6](assets/kolbot-d2botmulelog6.png) 95 | 96 | If you wanna save the image (check R-click options) of an item without having this info, 97 | 98 | ![deactivate the Item Header](assets/kolbot-d2botmulelog7.png). 99 | 100 | You will find the images near D2Bot.exe in the subfolder \images , the same location for screenshots made during the logging. 101 | 102 | ### optional mule viewer 103 | 104 | Check [@rivx mule view project](http://www.rivsoft.net/projects/other/muleview/) and download [MuleView-v0.3.zip](http://www.rivsoft.net/download/other/MuleView-v0.3.zip) which allows you to view the logged files saved with d2bs. 105 | [original shared topic](https://web.archive.org/web/20150613144010/http://www.blizzhackers.cc:80/viewtopic.php?f=172&t=500047) 106 | 107 | ### dropper 108 | It's a free public dropper - limedrop, included in the default branch (master = trunk) of repository 109 | - browser link 110 | - download link for TortoiseSVN 111 | - check the [discord limedrop channel](https://discordapp.com/channels/430522386253611018/482930024681439242): 112 | 113 | * [About limedrop](https://github.com/blizzhackers/documentation/tree/master/limedrop#about-limedrop) 114 | * [Setup Limedrop](https://github.com/blizzhackers/documentation/tree/master/limedrop#setup-limedrop) 115 | * [Using Limedrop](https://github.com/blizzhackers/documentation/tree/master/limedrop#using-limedrop) 116 | * [FAQ](https://github.com/blizzhackers/documentation/tree/master/limedrop#frequently-asked-questions) 117 | 118 | 119 | ### diabase & d2bs 120 | [@Ned](https://github.com/Nedkali/)added some changes to Diabase to work with D2BS 121 | 122 | * download using SVN Checkout... -> (https://github.com/Nedkali/DiaBaseV1/trunk) 123 | * create a subfolder ...\d2bs\kolbot\MuleInventory\ 124 | * you have the option to not use the Diabase function which overwrite the files, using Utilities > Verify logging files, and it's enough to replace the default libs\MuleLogger.js with [Mulelogger on gist](https://gist.github.com/mf022/a0ee6d71d071dc45635650cef4bc8afd) - which will create the both log files for the default D2BS Char Viewer (in mules\realm\account) and Diabase(in MuleInventory\). -------------------------------------------------------------------------------- /kolbot/FAQ.md: -------------------------------------------------------------------------------- 1 | [General Table of Contents](../README.md#diablo-2-botting-system) 2 | 3 | [Kolbot Table of Contents](README.md#kolbot) 4 | 5 | --- 6 | 7 | # FAQ 8 | 9 | --- 10 | 11 | * [how to avoid "checking versions"?](#how-to-avoid-checking-versions) 12 | * [how to avoid "connecting to the fastest server"?](#how-to-avoid-connecting-to-the-fastest-server) 13 | * [how much I have to wait for an answer?](#how-much-i-have-to-wait-for-an-answer) 14 | * [I have an issue with my bot](#i-have-an-issue-with-my-bot) 15 | * [best version of d2bs](#best-version-of-d2bs) 16 | * [how to change the pause button?](#how-to-change-the-pause-button) 17 | * [pickit issue](#pickit-issue) 18 | * [using d2bs only multiloader](#using-d2bs-only-multiloader) 19 | * [win 8 crash](#win-8-crash) 20 | * [leeching from the same account](#leeching-from-the-same-account) 21 | * [how to add own script](#how-to-add-own-script) 22 | * [mpq or raw keys?](#mpq-or-raw-keys) 23 | * [how many bots in one game](#how-many-bots-in-one-game) 24 | * [fastmod config](#fastmod-config) 25 | * [d2bs sandboxed](#d2bs-sandboxed) 26 | * [D2BS is not responding ... starting profile](#d2bs-is-not-responding--starting-profile) 27 | * [window has unexpectedly exited... starting profile](#window-has-unexpectedly-exited-starting-profile) 28 | * [you were disconnected from d2 server](#you-were-disconnected-from-d2-server) 29 | * [game with that name already exists](#game-with-that-name-already-exists) 30 | * [how can I stop the bot in game, in case of error](#how-can-i-stop-the-bot-in-game-in-case-of-error) 31 | * [the login button is gray](#the-login-button-is-gray) 32 | * [I cannot change account](#I-cannot-change-account) 33 | * [how can I reset the game counter](#how-can-I-reset-the-game-counter) 34 | * [how do I stop hidden d2 windows?](#how-do-I-stop-hidden-d2-windows) 35 | 36 | --- 37 | 38 | ## Q / A 39 | 40 | ### how to avoid "checking versions"? 41 | 1. **Q:** Diablo II login screen is showing "Checking versions..." on every try 42 | 2. **A:** you have to add some extra lines in windows hosts file: 43 | * run notepad in admin mode. 44 | * click Open and browse to C:\Windows\System32\drivers\etc\ 45 | * choose to see All files in the drop-down list 46 | * open hosts file 47 | * add the line corresponding to your d2 server 48 | ``` 49 | 34.223.227.224 uswest.battle.net 50 | 44.194.80.159 useast.battle.net 51 | 13.124.4.20 asia.battle.net 52 | 3.66.69.82 europe.battle.net 53 | ``` 54 | * [@Darkvigilante video guide](https://www.youtube.com/watch?v=vK3jaNttWAU) 55 | * [additional guide](https://www.howtogeek.com/howto/27350/beginner-geek-how-to-edit-your-hosts-file/) 56 | * in case of servers changes, use the [sysinternal tool](https://docs.microsoft.com/en-us/sysinternals/downloads/tcpview) and search inside this app for **Game** 57 | 58 | ### how to avoid "connecting to the fastest server"? 59 | 1. **Q:** Diablo II login screen is showing "Connecting to the fastest server" on every try 60 | 2. **A:** check your extra lines in windows C:\Windows\System32\drivers\etc\hosts file, see [previous issue](#how-to-avoid-checking-versions) 61 | * use the [sysinternal tool](https://docs.microsoft.com/en-us/sysinternals/downloads/tcpview) and with Diablo II running, search inside TCPview app for **Game**, and write down the Remote Adress of Game.exe, coresponding to the server you have connected. 62 | * if you wanna play d2 only directly, without d2bs, you could also delete those extra lines from C:\Windows\System32\drivers\etc\hosts file 63 | 64 | ### how much I have to wait for an answer? 65 | 1. **Q:** I've posted a question on forum 5 minutes ago and I still haven't got any answer!!! 66 | 2. **A:** remember that we spend our precious time to help you and it's very often impossible to do it immediately. Please try to use the search button and check if your question hasn't been answered before. If not, please wait patiently. 67 | 68 | ### I have an issue with my bot 69 | 1. **Q:** I have a problem with my bot. What should i do?? 70 | 2. **A:** please [pastebin](https://pastebin.com/) your config and write your current bot version. Explain all issues carefully. It's important to keep your bot up to date using latest version (every update fixes a lot of bugs). 71 | Here you can find [latest kolbot](https://github.com/blizzhackers/kolbot/). Learn [how to keep it updated](https://github.com/blizzhackers/documentation/blob/master/d2bot/Download.md#keep-bot-files-updated). 72 | 73 | ### best version of d2bs 74 | 1. **Q:** which version of D2BS should i use ?? 75 | 2. **A:** trunk is the latest **stable** version. 76 | * you can use [TortoiseSVN](https://tortoisesvn.net/downloads.html) on 77 | check [download guide](https://github.com/blizzhackers/documentation/tree/master/d2bot/Download.md) 78 | 79 | ### how to change the pause button? 80 | 1. **Q:** I don't have numeric keyboard. Where can I change my pause button ?? 81 | 2. **A:** you can use this site for new [keys](http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes). Now edit tools/toolsthread.js and find this.keyEvent function. 82 | * check [Hotkeys guide](https://github.com/blizzhackers/documentation/tree/master/kolbot/Hotkeys.md#changing-the-default-keys) 83 | 84 | ### pickit issue 85 | 1. **Q:** I have a problem with my pickit. 86 | 2. **A:** please check this page about - 87 | 88 | ### using d2bs only multiloader 89 | 1. **Q:** How I can use the dbs only as multiloader, without loading any scripts? 90 | 2. **A:** use the **-L -w** parameters in the profile. 91 | 92 | ### win 8 crash 93 | 1. **Q:** win8 crash issue 94 | 2. **A:** you need to run d2bot# manager as admin and in compatibility mode. Windows 7 compatibility mode is tested and works. Try to either start hidden (tools menu) or start without minimizing (visible tick in profile editor). The win8 issue is with how the window is minimized. 95 | 96 | ### leeching from the same account 97 | 1. **Q:** leeching from the same account. 98 | 2. **A:** leeching from same account isn't supported, and it's a bad idea. You cannot have in the same time 2 characters from the same account on d2 server lobby screen. 99 | 100 | ### how to add own script 101 | 1. **Q:** I want to run my own script. 102 | 2. **A:** you need 3 things to match in order for script to work: 103 | * Myownscript.js in bots folder 104 | * function Myownscript() in the script 105 | * Scripts.Myownscript = true; in char config 106 | 107 | ### mpq or raw keys? 108 | 1. **Q:** can I use mpq or raw keys in profle manager? 109 | 2. **A:** you can use them both i.e raw keys and mpq for the same list or profile. - see [d2bs Keylist](https://github.com/blizzhackers/documentation/tree/master/d2bot/Keylist.md) 110 | 111 | ### how many bots in one game 112 | 1. **Q:** is it possible to run more than 4 bots in one game? 113 | 2. **A:** yes it is. Even on d2 main server, since 1st June 2017 are allowed 8 players in the same game, with same IP. 114 | 115 | ### fastmod config 116 | 1. **Q:** fastmod config or packet casting. 117 | 2. **A:** read carefully explanations in [Character config](https://github.com/blizzhackers/documentation/blob/master/kolbot/CharacterConfig.md/#fastmod-config) 118 | 119 | ### d2bs sandboxed 120 | 1. **Q:** Sandboxie 121 | 2. **A:** it's not working with d2bs manager anymore. 122 | 123 | ### D2BS is not responding ... starting profile 124 | 1. **Q:** I get all the time "D2BS is not responding... starting profile" 125 | 2. **A:** update D2BS to latest version. 126 | 127 | * check if you run the 1.14d patch of Diablo II. Try to run D2LoD directly, using a Diablo II shortcut with windowed (-w) parameter. 128 | * check the installed MS dependencies (VC++ 2005, 2008, 2010 and .NET Framework 3.5, 4 or higher installed). try to re-install those MS dependencies https://github.com/blizzhackers/documentation/blob/master/d2bot/ManagerSetup.md/#install-dependencies 129 | * you can get this error and several crashes when there are differences between ...\d2bs\d2bs.ini and ...\data\profile.json. When the manager correct the errors that profile will start just fine. 130 | 131 | * previous versions of d2bs released before the current with utf-8 encoding had other issues like: 132 | * if you have TeamViewer installed and you have **<->** icon. click ok it and disable. 133 | * check if the parent folders of D2BS should not have special character like accents in their names (if d2bs folder it's located on Desktop, maybe the username have them). Move the d2bs folder to root of drive C:\, D:\ . Place on desktop only the shortcut to D2Bot.exe. 134 | 135 | ### window has unexpectedly exited... starting profile 136 | 1. **Q:** I see on d2bs console "Window has unexpectedly exited... starting profile" when I start a profile 137 | 2. **A:** you must run Diablo II windowed (-w parameter) on windows 8 or 10, otherwise the d2 game will crash. 138 | 139 | * check your Diablo II folder. It should have the 1.14d patch, Try to connect directly on d2 server using a shortcut to Diablo.exe with -w parameter. If your d2 folder it's ok, you should have no issues to connect manually on the d2 server. 140 | * remove the "-3dfx" parameter from the profile, maybe it's causing the d2 crash (the crash is when enter in the game with glide activated). 141 | * recheck your starter script, use [Esprima: Syntax Validator](http://esprima.org/demo/validate.html) if you edited that. 142 | * if it's the first run and you get this issue, you can try to move your Diablo II folder, and update the d2bs profile with that path 143 | ``` 144 | D2BS is not responding... starting profile 145 | Crash Info: Script: none Area: out of game 146 | Window has unexpectedly exited... starting profile 147 | Crash Info: Script: none Area: out of game 148 | ``` 149 | * check ...\d2bs\d2bs.log file to find the error 150 | * check ...\d2bs\kolbot\logs\ScriptErrorLog.txt if any 151 | * check windows Event Viewer > Windows Logs > Application and filter it for critical and error events. look for game.exe error events. you can find some descriptions of error like: 152 | * Exception code: 0xc0000005 (Access Violation error) 153 | * Exception code: 0xc000000d 154 | * increase the value of this variable from starter script 155 | ``` 156 | CrashDelay: 5, // Seconds to wait after a d2 window crash 157 | ``` 158 | * run D2Maintenance - CCleaner or batch file. use CCleaner registry tool. 159 | * for **Exception code: 0xc0000005**, see some guides (or use google to find): 160 | * https://compfreakstars.blogspot.com/2011/11/0xc0000005-error-every-day-many.html 161 | * https://stackoverflow.com/questions/14949904/what-do-i-do-when-my-program-crashes-with-exception-0xc0000005-at-address-0 162 | * http://www.errorlive.com/exception-code-0xc0000005 163 | 164 | ### you were disconnected from d2 server 165 | 1. **Q:** I get all the time d2 error when it's opened by D2BS: "You were disconnected from d2 server. Please reconnect" 166 | 2. **A:** clone your profile, and in the Key List field of cloned profile set none, and the default (installation) keyset will be loaded. Set properly your [d2bs Keylist](https://github.com/blizzhackers/documentation/tree/master/d2bot/Keylist.md). 167 | 168 | ### game with that name already exists 169 | 1. **Q:** The leader get "Game With That Name Already Exists" on d2 server, but all followers get "the game does not exist" message when they attempt to join. 170 | 2. **A:** Remove the spaces from the name of the game on leader's profile. 171 | 172 | ### how can I stop the bot in game, in case of error 173 | 1. **Q:** the bot enters in the game and I saw some lines indicating errors on the white console layer 174 | 2. **A:** press < HOME > or < ESC > to cancel the console, then press Pause/Break key. 175 | 176 | * Press in-game command < M > to see messages 177 | * check your scripts related to the errors, recheck the data fields you have entered on last untested edit. 178 | * when you finished the editing, type .reload , and the scripts will be stopped then reloaded. this command will also look for the configuration file, and cannot be used in mule logging games, by example. 179 | 180 | ### the login button is gray 181 | 1. **Q:** I got it to start but when it types in user and password fields it wont login. The login button is gray. 182 | 2. **A:** it's something wrong in your accountname/password fields. Maybe the password is too long, or the account name isn't spelled correctly, case sensitive. 183 | 184 | ### I cannot change account 185 | 1. **Q:** I'm playing manually and I cannot change the first account with I did the first log in. Even I enter other account the character screen will be for the first account, or in the worst case an empty character selection screen with Connecting ... 186 | 2. **A:** Uncheck the "RD Blocker" box, because that is causing it. In the [guide](https://github.com/blizzhackers/documentation/blob/master/d2bot/ManagerSetup.md/#create-a-profile) is written: 187 | > 19. Enables RD Block (**don't enable unless you know what you are doing**) 188 | * it does nothing useful for most people 189 | 190 | ### how can I reset the game counter 191 | 1. **Q:** the auto reset is set to 999 (ResetCount: 999) in the starter script (D2BotLead.dbj), but how I can reset this manually to start again with 1 192 | 2. **A:** select that profile and R-click it. Choose "Reset Stats". If this isn't working, you can try other method: stop bots and close the manager. edit in np++ the profile.json file, changing the values for a several fields with 0 193 | 194 | ### how do I stop hidden d2 windows? 195 | 1. **Q:** bot crashed but I think that the d2 is still running in the background 196 | 2. **A:** on the manager click Settings > Close Game.exe. You'll get a confirmation message. Other method is to use windows task manager, and if you are seeing Game.exe, R-click and choose End task 197 | 198 | ## support 199 | * https://github.com/blizzhackers/kolbot/issues 200 | * [discord #support](https://discordapp.com/channels/430522386253611018/430522508026839051) 201 | * [blizzhackers.discourse.group #support](https://blizzhackers.discourse.group/c/support/14) 202 | -------------------------------------------------------------------------------- /kolbot/GamblingSystem.md: -------------------------------------------------------------------------------- 1 | [General Table of Contents](../README.md#diablo-2-botting-system) 2 | 3 | [Kolbot Table of Contents](README.md#kolbot) 4 | 5 | --- 6 | 7 | # Gambling System 8 | 9 | --- 10 | 11 | ### Notes: 12 | 13 | * Allows lower level characters to get a steady income of gold to gamble LLD/VLLD items 14 | 15 | * Not recommended for rings/amulets because of their high price (unless you want 3 gold finders to supply one gambler). 16 | 17 | * It's possible to have multiple teams of gamblers/gold finders. Individual entries are separated by commas. 18 | 19 | ### Steps: 20 | 21 | 1. Open and configure .../kolbot/libs/systems/gambling/TeamsConfig.js 22 | ```js 23 | module.exports = { 24 | /** 25 | Setting up: 26 | 27 | "Gamble Team 1": { // Put a unique team name here. 28 | 29 | goldFinders: ["GF Profile 1", "GF Profile 2"], // List of gold finder PROFILE names. They will join gamble games to drop gold 30 | 31 | gamblers: ["Gambler 1", "Gambler 2"], // List of gambler PROFILE names. They will keep gambling and picking up gold from gold finders. 32 | 33 | gambleGames: ["Gambling-", "HeyIGamble-"], // Games that gold finders will join, don't use numbers. 34 | 35 | goldTrigger: 2500000, // Minimum amount of gold before giving it to gamblers. 36 | 37 | goldReserve: 200000 // Amount of gold to keep after dropping. 38 | } 39 | 40 | Once set up properly, the gold finders will run their own games and join gamblers' games when they're out of gold. 41 | */ 42 | "Gamble Team 1": { 43 | goldFinders: ["gf1","gf2","gf3","gf4","gf5","gf6"], 44 | gamblers: ["gambler1", "gambler2"], 45 | gambleGames: ["Mygamblegame"], 46 | 47 | goldTrigger: 2000000, 48 | goldReserve: 100000 49 | }, 50 | }; 51 | ``` 52 | 53 | * "Gamble Team 1" - Put your disired name here in our example. 54 | 55 | * goldFinders = PROFILE NAMES that will enter games and drop gold (profile names match window titles) in our example: goldFinders: ["gf1","gf2","gf3","gf4","gf5","gf6"], 56 | 57 | * gamblers = PROFILE NAMES that gamble and pick up gold dropped by gold finders in our example: gamblers: ["gambler1", "gambler2"], 58 | 59 | * gambleGames = games that gold finders will join, don't use numbers. NOTE: d2 always makes first letter of game name uppercase in our example: gambleGames: ["Mygamblegame"], 60 | 61 | * goldTrigger: 2000000, // Minimum amount of gold before giving it to gamblers. 62 | 63 | * goldReserve: 100000 // Amount of gold to keep after dropping. 64 | 65 | Once you set those properly, the gold finders will run their own games and they will join gambler games when they're out of gold. 66 | Save the changes. 67 | 68 | 2. Open D2Bot# and [create a new profile](https://github.com/blizzhackers/documentation/blob/master/d2bot/ManagerSetup.md/#create-a-profile) for gamblers 69 | 3. Open your gambler character config and set what you want to gamble. 70 | 71 | -------------------------------------------------------------------------------- /kolbot/Hotkeys.md: -------------------------------------------------------------------------------- 1 | [General Table of Contents](../README.md#diablo-2-botting-system) 2 | 3 | [Kolbot Table of Contents](README.md#kolbot) 4 | 5 | --- 6 | 7 | # Hotkeys 8 | 9 | --- 10 | 11 | * [default keys](#default-keys) 12 | * [changing the default keys](#changing-the-default-keys) 13 | * [d2bs core commands](#d2bs-core-commands) 14 | * [chat commands](#chat-commands) 15 | * [white console(layer)](#white-consolelayer) 16 | --- 17 | 18 | ## default keys 19 | Here is just a quick run through of what each current key is, and what it will do for bot 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 |
Javacode - KeyToolsThread.jsother scripts
variableactionvariableaction
17 - Ctrl
19 - Pause/BreaktogglePause()Pause/Resume bot
32 - SpaceFileTools.copy (UserAddon.js)copy the charconfig with name of char included
33 - Page Up
34 - Page Down
35 - EndMuleLogger.logChar(); D2Bot.stop(me.profile, true);mulelog the current char and stop that profile
36 - Home
45 - InsertrevealLevel(true)show/hide mapc (Test.js)print ...
46 - Delete
96 - Num 0getHook("Next Area") (MapThread.js)move to next area
97 - Num 1getHook("Previous Area") (MapThread.js)move to previous area
98 - Num 2getHook("Waypoint") (MapThread.js)move to wp
99 - Num 3getHook("POI") (MapThread.js)move to Point of Interest
100 - Num 4getHook("Side Area") (MapThread.js)move to side area
101 - Num 5scriptBroadcast("mule")Automuling
102 - Num 6MuleLogger.logChar()
103 - Num 7Hooks.monsters.enabled (MapThread.js)show/hide monsters
104 - Num 8Hooks.vector.enabled (MapThread.js)show/hide vectors
105 - Num 9print(this.getNearestPreset())
106 - Num *Precast.doPrecast(true)activate the precast/buff
107 - Num +showConsole() ...print real FCR IAS FBR FHR
109 - Num -Misc.spy(me.name)Log someone's geargo (CrushTele.js)autoteleport in strategic areas
110 - Num decimal .say("/fps")shows frames/sec
111 - Num /this.stopDefault()Stop threads and reload
201 | 202 | ## changing the default keys 203 | 204 | If you need to change these keys, look to: 205 | 206 | * ...\d2bs\kolbot\tools\ToolsThread.js check \\Event functions section lines 342-409 207 | 208 | * pause/resume key is also defined in line 37 of ...\d2bs\kolbot\tools\Heartbeat.js for pausing the starter script (before entering in a game) 209 | 210 | * ...\d2bs\kolbot\tools\MapThread.js lines 721-724 211 | 212 | 213 | For a reference on what these can be changed to, visit [javascriptkeycode.com](http://www.javascriptkeycode.com/) or [keycode.info](http://keycode.info/) webpages. Those are all the possible keycodes. 214 | 215 | This is just a simple run through, to truly know what each key does, you'll need to test each one out in game. 216 | 217 | ## d2bs core commands 218 | 219 | ### chat commands 220 | press < Enter > and type: 221 | * .start - 222 | * .stop - will stop the current scripts. the profile will crash and it will be restarted in few seconds 223 | * .reload - will stop and reload the scripts. you are able to change config while in game. Don't use as it crashes after the game is done, Use Numpad / 224 | * .flushcache - 225 | * .load - 226 | 227 | ### white console(layer) 228 | display status messages out of game as well as in game: 229 | * < HOME > to show/hide console just for viewing 230 | * < ALT > + < HOME > to open the console for input, allows you to type commands into it 231 | * < Page up >/< Page down > scrolls console text when it's open for input. 232 | * the same chat commands without . prefix: 233 | * start - 234 | * stop - will stop the current scripts. the profile will crash and it will be restarted in few seconds 235 | * reload - will stop and reload the scripts. you are able to change config while in game. Don't use as it crashes after the game is done. Use Numpad / 236 | * flushcache - 237 | * load 238 | * include - other scripts can be loaded: include("common/prototypes.js"); 239 | * any other command is interpreted as a javascript string and will be executed (as per the old .exec). 240 | * all output is directed to the console instead of to the screen. 241 | * < Up arrow > will show the latest command that you typed in the console. Up/Down arrows will show different commands entered in the console 242 | * you can type on the console different javascript lines: 243 | ```javascript 244 | var ip = Number(me.gameserverip.split(".")[3]); 245 | print("IP of the game: " + ip); 246 | ``` 247 | and the result will be: 248 | ```javascript 249 | IP of the game: ... (the last part of the IP) 250 | ``` 251 | * one defined variable (like ip) remains defined in that game, even you type reload in the meantime. 252 | * to find the mouse coordinates type: 253 | ```javascript 254 | getMouseCoords(1); 255 | ``` 256 | and you'll get the X, Y coordinates. 257 | -------------------------------------------------------------------------------- /kolbot/IDES.md: -------------------------------------------------------------------------------- 1 | [General Table of Contents](../README.md#diablo-2-botting-system) 2 | 3 | [Kolbot Table of Contents](README.md#kolbot) 4 | 5 | --- 6 | 7 | ## Code Editors (IDEs) 8 | 9 | * [VSCode](https://code.visualstudio.com/) 10 | * [Sublime Text](https://www.sublimetext.com/download) 11 | 12 | --- 13 | 14 | ## Syntax highlighting in VSCode (recommended) 15 | - By default .js files are recognized and have syntax highlighting. 16 | - Enable syntax highlighting for .dbj files: 17 | 1) Open settings 18 | 2) Search `Files: Associations` 19 | 3) Click `Add Item` 20 | 4) Enter `*.dbj` for the key and `javascript` for the value 21 | 5) Click `OK` 22 | 23 | - Also highly recommended to install [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) 24 | --- 25 | 26 | ## Syntax highlighting in Sublime Text 27 | - By default .js files are recognized and have syntax highlighting. 28 | - Enable syntax highlighting for .dbj files: 29 | 1) Open one of the .dbj files 30 | 2) Selecte `View` from the tabs 31 | 3) Go down to `Syntax` 32 | 4) Select `Open all with current extension as` then select `Javascript` 33 | --- 34 | 35 | ## Syntax highlighting in np++ (Not recommended) 36 | 37 | Kolbot scripts are written in Javascript language. **.js** files are automatically highlighted for easier editing in [Notepad++](https://notepad-plus-plus.org/downloads/). 38 | Specific kolbot .dbj and .dbl files have to be added to javascript style 39 | 40 | * press **Settings** in Notepad++ toolbar and select **Style Configurator...** 41 | 42 | * find Javascript in Language column 43 | 44 | * add **dbl dbj nip** in User ext. field 45 | 46 | * press **Save & Close** button 47 | 48 | * restart Notepad++ 49 | 50 | 51 | ![np++](assets/kolbot-np++styleconfigurator.png) -------------------------------------------------------------------------------- /kolbot/ManualPlay.md: -------------------------------------------------------------------------------- 1 | [General Table of Contents](../README.md#diablo-2-botting-system) 2 | 3 | [Kolbot Table of Contents](README.md#kolbot) 4 | 5 | --- 6 | 7 | # Manual Playing 8 | 9 | --- 10 | 11 | * [Info](#info) 12 | * [D2BotMap](#d2botmap) 13 | * [Multi Loader](#multi-loader) 14 | * [Manual Misc Script](#manualjs) 15 | * [Using Followers](#using-followers) 16 | 17 | --- 18 | 19 | ## info 20 | 21 | * [d2bs](https://github.com/blizzhackers/kolbot) allows manual playing 22 | 23 | ## multi loader 24 | 25 | * use these parameters in the profile, and no script will be loaded. 26 | ``` 27 | -L -w 28 | ``` 29 | 30 | ## D2BotMap 31 | 32 | 1. it's a starter script for manual play. 33 | 2. you have to manually login into account and create or join game. 34 | 3. it gives you some improvements like: 35 | 36 | * reveals map 37 | * loads character config 38 | * shows ping 39 | * shows game time 40 | * displays IP 41 | * shows vectors/area names/shrines/monsters/items 42 | * with numpad key 0 - goes to next area 43 | * with numpad key 1 - goes to previous area 44 | * with numpad key 2 - goes to wp and grab it (if possible) 45 | * with numpad key 3 - goes to point of interest (if possible) 46 | * with numpad key 4 - goes to side area (if possible) 47 | * with numpad key (5 - 8) - goes to point of interest (if possible) 48 | * with shift < - goes to previous act (if possible) 49 | * with shift > - goes to next act (if possible) 50 | * with key 5 - (in town will go to healer)(out of town it will make a portal if possible) 51 | * with key 6 - (in town will open stash)(out of town it will go to town if possible) 52 | * with key 7 - disables item filter 53 | * with key 8 - disables vectors 54 | * with key 9 - disables vectors 55 | * with numpad key - (toggle item filter between default and custom) 56 | * with alt key while hovering over item will - (move item to next location)(stash <-> inventory)(cube <-> inventory) 57 | (tradescreen <-> inventory)(inventory -> sell to npc in menu) 58 | * chat commands, to see available commands type .help into chat to display a clickable menu 59 | 60 | ![D2BotMap](assets/kolbot-manualplayD2BotMapEx1.JPG) 61 | 62 | ### D2BotMap help menu 63 | ![D2BotMap](assets/kolbot-manualplayD2BotMapEx2.JPG) 64 | 65 | 66 | ## Manual.js 67 | 68 | 1. it's another script written by [@Laz](https://github.com/laztheripper) for manual play, with description in this saved [html file](assets/ManualPlayScriptWithPacketSniffingToolsAndMore.html) or [pdf format](https://github.com/blizzhackers/bhfiles/blob/master/pdf%20saved%20pages/d2bs%20script%20development/Manual%20play%20script%20with%20packet%20sniffing%20tools%20and%20more.pdf). 69 | 2. How to use (from bh topic): 70 | * copy the script [Manual.js](https://raw.githubusercontent.com/blizzhackers/documentation/master/kolbot/custom-scripts/Manual.js) and save it as ...\libs\scripts\Manual.js 71 | * in your character's config add "Scripts.Manual = true;" (that can be near the line "Scripts.Follower = ...") 72 | * use D2BotBlank.dbj as starter script(entry point) for the profile. 73 | * in d2bs.ini (located in ...\kolbot\d2bs) you should set "UseGamePrint=true", otherwise you won't see anything useful in game. 74 | 75 | ![Manual.js](assets/kolbot-manualplayMiscScript.jpg) 76 | 77 | ## using followers 78 | 79 | you can run your leader and to have up to other 7 followers in your game. 80 | check [multibotting - joining games](./MultiBotting.md/#joining-games) 81 | -------------------------------------------------------------------------------- /kolbot/MultiBotting.md: -------------------------------------------------------------------------------- 1 | [General Table of Contents](../README.md#diablo-2-botting-system) 2 | 3 | [Kolbot Table of Contents](README.md#kolbot) 4 | 5 | --- 6 | 7 | # Multi Botting 8 | 9 | --- 10 | 11 | * [Info](#info) 12 | * [Game Creator](#game-creator) 13 | * [create/edit the profile](#createedit-the-profile) 14 | * [randomize the timers](#randomize-the-timers) 15 | * [Joining Games](#joining-games) 16 | * [D2BotFollow](#d2botfollow) 17 | * [the joiners profiles](#the-joiners-profiles) 18 | * [randomize the timers](#randomize-the-timers-1) 19 | * [edit the joining info](#edit-the-joining-info) 20 | * [D2BotChannel](#d2botchannel) 21 | * [Team Games](#team-games) 22 | * [using MFTeam](#using-mfteam) 23 | * [MFLeader](#mfleader) 24 | * [MFHelper](#mfhelper) 25 | * [silenced MFTeam](#silenced-mfteam) 26 | * [using Followers](#using-followers) 27 | * [followers exit delays](#followers-exit-delays) 28 | * [dia-baal teams](#dia-baal-teams) 29 | 30 | --- 31 | 32 | ## Info 33 | [d2bs](https://github.com/blizzhackers/kolbot) allows multi-botting. 34 | 35 | ## StarterConfig 36 | Centralized location for shared config options. Entry script specific options are located at the top of the `*.dbj` file 37 | ### randomize the timers [libs/starter/StarterConfig.js](https://github.com/blizzhackers/kolbot/blob/69b48b27bb6b4b437edf7d3873a41cbbca09f6e7/d2bs/kolbot/libs/starter/StarterConfig.js#L10-L43) 38 | ```javascript 39 | module.exports = { 40 | MinGameTime: rand(150, 180), // Minimum game length in seconds. If a game is ended too soon, the rest of the time is waited in the lobby 41 | PingQuitDelay: rand(30, 40), // Time in seconds to wait in lobby after quitting due to high ping 42 | CreateGameDelay: rand(5, 15), // Seconds to wait before creating a new game 43 | ResetCount: 999, // Reset game count back to 1 every X games. 44 | CharacterDifference: 99, // Character level difference. Set to false to disable character difference. 45 | MaxPlayerCount: 8, // Max amount of players in game between 1 and 8 46 | GameDescription: "", // Game description when creating a game 47 | StopOnDeadHardcore: true, // Stop profile character has died on hardcore mode 48 | 49 | // ChannelConfig can override these options for individual profiles. 50 | JoinChannel: "", // Default channel. Can be an array of channels - ["channel 1", "channel 2"] 51 | FirstJoinMessage: "", // Default join message. Can be an array of messages 52 | ChatActionsDelay: rand(2, 5), // Seconds to wait in lobby before entering a channel 53 | AnnounceGames: false, // Default value 54 | AfterGameMessage: "", // Default message after a finished game. Can be an array of messages 55 | 56 | InvalidPasswordDelay: rand(10, 15), // Minutes to wait after getting Invalid Password message 57 | VersionErrorDelay: rand(5, 30), // Seconds to wait after 'unable to identify version' message 58 | SwitchKeyDelay: rand(5, 15), // Seconds to wait before switching a used/banned key or after realm down 59 | CrashDelay: rand(60, 120), // Seconds to wait after a d2 window crash 60 | FTJDelay: rand(20, 30), // Seconds to wait after failing to create a game 61 | RealmDownDelay: rand(3, 7), // Minutes to wait after getting Realm Down message 62 | UnableToConnectDelay: rand(5, 10), // Minutes to wait after Unable To Connect message 63 | TCPIPNoHostDelay: rand(5, 30), // Seconds to wait after Cannot Connect To Server message 64 | CDKeyInUseDelay: rand(5, 10), // Minutes to wait before connecting again if CD-Key is in use. 65 | ConnectingTimeout: rand(20, 30), // Seconds to wait before cancelling the 'Connecting...' screen 66 | PleaseWaitTimeout: rand(10, 20), // Seconds to wait before cancelling the 'Please Wait...' screen 67 | WaitInLineTimeout: rand(60, 90), // Seconds to wait before cancelling the 'Waiting in Line...' screen 68 | WaitOutQueueRestriction: true, // Wait out queue if we are restricted, queue time > 10000 69 | WaitOutQueueExitToMenu: false, // Wait out queue restriction at D2 Splash screen if true, else wait out in lobby 70 | GameDoesNotExistTimeout: rand(30, 40) // Seconds to wait before cancelling the 'Game does not exist.' screen 71 | }; 72 | ``` 73 | * if you don't wanna join a chat channel, you don't have to edit anything more. 74 | * the game creator can be also a manual played char, see [d2bs manual play](https://github.com/documentation/kolbot/ManualPlay.md/#manual-playing) page. 75 | 76 | ## AdvancedConfig 77 | [libs/starter/AdvancedConfig.js](https://github.com/blizzhackers/kolbot/blob/69b48b27bb6b4b437edf7d3873a41cbbca09f6e7/d2bs/kolbot/libs/starter/AdvancedConfig.js#L39-L44) is used for overriding StarterConfig options for specific profiles. 78 | ```js 79 | "Test": { 80 | JoinChannel: "op nnqry", 81 | JoinDelay: 3, 82 | AnnounceGames: true, 83 | AnnounceMessage: "Joining game" // output: Joining game Baals-23 84 | }, 85 | ``` 86 | 87 | ## Game creator 88 | * D2BotLead is the starter script that you will use to create games. It can announce games in channels when used for public runs. You have to set D2BotLead for your profile as a entry script. Now edit starter with your IDE of choice. First part of starter is self-explanatory. 89 | * the creator of the game doesn't necessarily to be set as the leader in game. 90 | 91 | ### Create/edit the profile 92 | * you can also use the [D2BotLeadStagger](https://github.com/blizzhackers/documentation/blob/master/kolbot/MiscellaneousOptions.md/#staggered-delays-for-creating-games)- a staggered version of D2BotLead 93 | 94 | ![CreatorProfile](assets/kolbot-multibotCreatorProfile.png) 95 | 96 | 97 | ## Joining games 98 | There are different starter scripts for joining games: 99 | 100 | * D2BotFollow.dbj - based on locally shared info between different profiles of the same d2bs manager 101 | 102 | * D2BotChannel.dbj - based on info shared on chat channels 103 | 104 | * D2BotPubJoin.dbj - based on scanning game list 105 | 106 | ### D2BotFollow 107 | * joining chat channel isn't needed. 108 | * the game name & password are shared locally through d2bs. 109 | 110 | #### The joiners profiles 111 | 112 | ![follower1](./assets/kolbot-multibotFollower1Profile.png) 113 | ![follower2](./assets/kolbot-multibotFollower2Profile.png) 114 | 115 | #### Randomize the join delay 116 | replace the default line 12 of [D2BotFollow.dbj](https://github.com/blizzhackers/kolbot/blob/69b48b27bb6b4b437edf7d3873a41cbbca09f6e7/d2bs/kolbot/D2BotFollow.dbj#L12) with: 117 | ```javascript 118 | // D2BotFollow specific settings - for global settings see libs/starter/StarterConfig.js 119 | Starter.Config.JoinDelay = rand(5, 15); // Time in seconds to wait before join attempt 120 | ``` 121 | 122 | ##### Edit the joining info 123 | Edit [libs/systems/follow/FollowConfig.js](https://github.com/blizzhackers/kolbot/blob/69b48b27bb6b4b437edf7d3873a41cbbca09f6e7/d2bs/kolbot/libs/systems/follow/FollowConfig.js#L21C3-L23C5) and complete the JoinSettings 124 | 125 | ```js 126 | /** 127 | * @description Join game settings 128 | * - Format: "leader's profile": ["leecher 1 profile", "leecher 2 profile", ...] 129 | * - If you want everyone to join the same leader, use "leader's profile": ["all"] 130 | * - NOTE: Use *PROFILE* names (profile matches window title), NOT character/account names 131 | * - leader:leecher groups need to be divided by a comma 132 | * @example 133 | * const JoinSettings = { 134 | * "lead1": ["follow1", "follow2"], 135 | * "lead2": ["follow3", "follow4"] 136 | * }; 137 | */ 138 | const JoinSettings = { 139 | "Leader": ["Leecher"], 140 | }; 141 | ``` 142 | 143 | ### D2BotChannel 144 | * D2BotChannel, is used to join games from both channel announcements and friend list announcements. That means that you can use this starter when want to join games that are runned on other computer. 145 | * edit [libs/systems/channel/ChannelConfig](https://github.com/blizzhackers/kolbot/blob/69b48b27bb6b4b437edf7d3873a41cbbca09f6e7/d2bs/kolbot/libs/systems/channel/ChannelConfig.js#L9) with the required settings 146 | 147 | ```js 148 | const ChannelConfig = { 149 | SkipMutedKey: true, 150 | MutedKeyTrigger: "Your account has had all chat privileges suspended.", 151 | JoinDelay: 10, // Seconds to wait between announcement and clicking join 152 | JoinRetry: 5, // Amount of times to re-attempt joining game 153 | // watch for whisper event instead? 154 | FriendListQuery: 0, // Seconds between "/f l" retries. 0 = disable. To prevent spamming when using set time rand(80, 160) 155 | /** 156 | * @typedef {Object} GameInfo 157 | * @property {string} game 158 | * @property {string} password 159 | * 160 | * @type {GameInfo[]} 161 | * @example 162 | * Games: [ 163 | * { game: "baal-", password: "" }, 164 | * ], 165 | */ 166 | Games: [ 167 | { game: "FASTBAAL-", password: "" }, 168 | { game: "csRun-", password: "password" }, 169 | { game: "Kolbot-Runs", password: "otherpassword" }, 170 | ], 171 | /** 172 | * @description excludeFilter format 173 | * @example Multiple entries in the same array mean AND 174 | * // ignores games that contain "baal" and "-" 175 | * const includeFilter = ["baal", "-"]; 176 | * 177 | * @example Multiple entries in different arrays mean OR 178 | * // will ignore games with either "baal" or "diablo" in their name 179 | * const includeFilter = [ 180 | * ["baal"], 181 | * ["diablo"] 182 | * ]; 183 | * @type {Array>} 184 | */ 185 | excludeFilter: [], 186 | /** 187 | * Leaders in game character name, only use this if the leader is using announce in the chat. 188 | * Can be an array or names ["somename", "somename2"] 189 | * @type {string[]} 190 | */ 191 | Follow: [], 192 | }; 193 | ``` 194 | 195 | * in this example we will join channel "MyChannel" and our first message will be "I'm from other dimension", in lines 2, 3 : 196 | ```javascript 197 | JoinChannel: "MyChannel", // Name of the channel to join 198 | FirstJoinMessage: "I'm from other dimension", // Message to say when first joining a channel, usually ".login" 199 | ``` 200 | * in `Games: [],` we have to set what games we are seeking, in this example "FASTBAAL-", "csRun-", "Kolbot-Runs". If games have password we need to supply it, if not please leave it blank. 201 | * to use friend list you need to set a delay between retries in seconds, to disable it set to "0". 202 | 203 | ## Team games 204 | Note: the game creator isn't necessarily to be set as the leader in game. 205 | 206 | you have to complete these fields for your leechers/helpers/followers 207 | ``` 208 | Config.Leader = "xXxX"; // Leader's ingame character name. 209 | Config.QuitList = ["xXxX"]; // List of character names to quit with. 210 | ``` 211 | 212 | 213 | ### Using MFTeam 214 | 215 | * script allows multiple characters to do the same boss/area runs in sync. 216 | * the leader will open a town portal and give commands to the helpers. Because it uses town portals, it's possible for walking characters to run the same bosses as teleporting characters. 217 | * in case of clearing, MFHelper will do the area clearing on his own, independent from leader. 218 | * unfortunately the commands are based on d2 server chat, so the leader key can be muted. To avoid these, check the [local chat](https://github.com/blizzhackers/documentation/kolbot/CharacterConfig.md/#local-chat) section. Choose mode 1, or 2 if you are playing also manually. 219 | ```javascript 220 | Config.LocalChat.Enabled = true; // enable the LocalChat system 221 | Config.LocalChat.Mode = 1; // 0 = disabled, 1 = chat from 'say' (recommended), 2 = all chat (for manual play) 222 | ``` 223 | 224 | #### MFLeader 225 | * in the leader config you have to set 226 | ```javascript 227 | // Team MF system 228 | Config.MFLeader = true; // Set to true if you have one or more MFHelpers. Opens TP and gives commands when doing normal MF runs. 229 | ``` 230 | and to enable the scripts you wanna run. 231 | 232 | #### MFHelper 233 | * the helper needs to have as the only running script 234 | ```javascript 235 | Scripts.MFHelper = true; // Run the same MF run as the MFLeader. 236 | ``` 237 | * the MFHelper script will end if the leader enters in Chaos Sanctuary or Throne of Destruction, because it's better to run the related DiabloHelper or BaalHelper after the MFHelper script. 238 | 239 | ### Using Followers 240 | * the leader can be played manually with Manual.js(the whole config should be loaded and also the LocalChat - see [manual play](https://github.com/blizzhackers-d2/documentation/blob/master/kolbot/ManualPlay.md/#manualjs) 241 | * you should use the [local chat](https://github.com/blizzhackers/documentation/blob/master/kolbot/CharacterConfig.md/#local-chat) with the settings 242 | ```javascript 243 | Config.LocalChat.Enabled = true; // enable the LocalChat system 244 | Config.LocalChat.Mode = 2; // 0 = disabled, 1 = chat from 'say' (recommended), 2 = all chat (for manual play) 245 | ``` 246 | * the follower characters need only this line to be activated: 247 | ```javascript 248 | Scripts.Follower = true; // Script that follows a manually played leader around like a merc. For a list of commands, see Follower.js 249 | ``` 250 | * the leeching section should be completed 251 | ``` 252 | Config.Leader = "MyLeader"; // Leader's ingame character name. Leave blank to try auto-detection (works in AutoBaal, Wakka, MFHelper) 253 | Config.QuitList = ["MyLeader"]; // List of character names to quit with. Example: Config.QuitList = ["MySorc", "MyDin"]; 254 | Config.QuitListMode = 0; // 0 = use character names; 1 = use profile names (all profiles must run on the same computer). 255 | Config.QuitListDelay = [x, y]; // Quit the game with random delay in case of using Config.QuitList. Example: Config.QuitListDelay = [1, 10]; will exit with random delay between 1 and 10 seconds. 256 | ``` 257 | * Follower.js is using chat commands like: 1, 2, wp, bo, ... and you can find the full list on [3rd-46th lines of Follower.js](https://github.com/blizzhackers-d2/d2bot-with-kolbot/blob/master/d2bs/kolbot/libs/bots/Follower.js#L3-L46) 258 | * the alternative is a semi-automated [silenced Follower](https://github.com/blizzhackers-d2/documentation/blob/master/kolbot/MiscellaneousOptions.md/#silenced-follower) which have nice addons. 259 | 260 | ### Followers exit delays 261 | To avoid issues like "Please Wait" when you quit the game with all chars at the same time, you should set diferent delays for followers to exit game 262 | 263 | Add time intervals for each follower. 264 | ```javascript 265 | Config.QuitListDelay = [1, 10]; // Quit the game with random delay in case of using Config.QuitList. Example: Config.QuitListDelay = [1, 10]; will exit with random delay between 1 and 10 seconds. 266 | ``` 267 | 268 | ### Dia-baal teams 269 | * leader and leechers can have other scripts activated before Diablo, or Baal, in the same areas using MFTeam, or separated areas on their own. 270 | * order for the scripts is top to bottom in character configuration file. To facilitate the meeting on the same time you can cut and paste the scripts, mixing the default order to get that scope. 271 | * leader will run the main scripts Diablo.js and Baal.js 272 | * leecher will have DiabloHelper and BaalHelper activated (true). -------------------------------------------------------------------------------- /kolbot/PermingOptions.md: -------------------------------------------------------------------------------- 1 | [General Table of Contents](../README.md#diablo-2-botting-system) 2 | 3 | [Kolbot Table of Contents](README.md#kolbot) 4 | 5 | --- 6 | 7 | # Perming Options 8 | 9 | --- 10 | 11 | * [Perming with D2BotMuleLog](#perming-with-d2botmulelog) 12 | * [D2BotTimerRefresh](#d2bottimerrefresh) 13 | 14 | 15 | --- 16 | 17 | ### Perming with D2BotMuleLog 18 | 19 | For perming the chars with staying 2h in game, you should use the starter script [D2BotMuleLog](D2BotMuleLog.md/#d2botmulelog) like for muling purpose. 20 | 21 | Edit `kolbot/libs/systems/mulelogger/LoggerConfig.js` with required info and set the value: 22 | 23 | ```javascript 24 | IngameTime: rand(7230, 7290), 25 | ``` 26 | 27 | or 28 | 29 | ```javascript 30 | AutoPerm: true, // override InGameTime to perm character 31 | ``` 32 | 33 | ### D2BotTimerRefresh 34 | 35 | If you need only to refresh the countdown timer for your chars, a better choice can be [D2BotTimerRefresh.dbj on github](./custom-scripts/D2BotTimerRefresh.dbj) saved as D2BotTimerRefresh.dbj in your ~\d2bs\kolbot\ folder. 36 | 37 | This will log on accounts/chars and will keep every char for random 15-25 seconds (line 185) in the lobby, without creating games. 38 | 39 | Edit the lines 27-29 with the required info 40 | ```javascript 41 | "account1/password/realm": ["all"], 42 | "account2/password/realm": ["all"], 43 | "account3/password/realm": ["all"] 44 | ``` -------------------------------------------------------------------------------- /kolbot/README.md: -------------------------------------------------------------------------------- 1 | [general table of content](https://github.com/blizzhackers/documentation/#diablo-2-botting-system) 2 | 3 | [d2bot content](https://github.com/blizzhackers/documentation/d2bot/#d2bot) 4 | 5 | --- 6 | 7 | # Kolbot 8 | 9 | library scripts by [@kolton](https://github.com/kolton) 10 | 11 | --- 12 | 13 | * [FAQ](FAQ.md/#faq) 14 | 15 | * [IDE-Setup](IDES.md/#code-editors-ides): How to set up your IDE for syntax highlighting 16 | 17 | * [Character Configuration](CharacterConfig.md/#character-configuration): options for configuring the bot 18 | 19 | * [Cubing](Cubing.md/#cubing): using the horadric cube recipes 20 | 21 | * [Manual Play](ManualPlay.md/#manual-playing): D2BotMap, Manual.js script 22 | 23 | * [Multi Botting](MultiBotting.md/#multi-botting): game creator, joining games, ... 24 | 25 | * [TCP/IP Games](TCP-IP%20games.md#tcpip-games): host and join TCP/IP games 26 | 27 | * [D2BotMuleLog](D2BotMuleLog.md/#d2botmulelog): log muled items 28 | 29 | * [Perming Options](PermingOptions.md/#perming-options): options to perm chars or to refresh the countdown timer 30 | 31 | * [Automule](Automule.md/#automule): Automuling and torch muling 32 | 33 | * [Gambling System](GamblingSystem.md#gambling-system): how to configure gambling teams 34 | 35 | * [Hotkeys](Hotkeys.md/#hotkeys): d2bs hotkeys, how to change them, console commands 36 | 37 | * [Miscellaneous Options](MiscellaneousOptions.md/#miscellaneous-options): autosmurf, autochaos, modded BattleOrders, how to define your own party, hardcore loot corpses, baal ads for hdin on wave2, ... -------------------------------------------------------------------------------- /kolbot/TCP-IP games.md: -------------------------------------------------------------------------------- 1 | [General Table of Contents](../README.md#diablo-2-botting-system) 2 | 3 | [Kolbot Table of Contents](README.md#kolbot) 4 | 5 | --- 6 | 7 | # TCP/IP games 8 | 9 | --- 10 | 11 | * [Info](#info) 12 | * [Host config](#host-config) 13 | * [Join config](#join-config) 14 | 15 | --- 16 | 17 | ## info 18 | 19 | * [d2bs](https://github.com/blizzhackers/kolbot) allows botting in TCP/IP created games 20 | 21 | ## Host config 22 | 23 | 1. Create and edit a new profile in your D2Bot manager, set the mode to `Host TCP/IP Game` 24 | 25 | ![Host config](assets/kolbot-TcpIp-host.png) 26 | 27 | ## Join config 28 | 29 | 1. Create and edit a new profile in your D2Bot manager, set the mode to `Join TCP/IP Game` 30 | 31 | ![Join config](assets/kolbot-TcpIp-join.png) 32 | -------------------------------------------------------------------------------- /kolbot/assets/kolbot-TcpIp-host.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-TcpIp-host.png -------------------------------------------------------------------------------- /kolbot/assets/kolbot-TcpIp-join.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-TcpIp-join.png -------------------------------------------------------------------------------- /kolbot/assets/kolbot-automule1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-automule1.png -------------------------------------------------------------------------------- /kolbot/assets/kolbot-automule2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-automule2.png -------------------------------------------------------------------------------- /kolbot/assets/kolbot-automule3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-automule3.png -------------------------------------------------------------------------------- /kolbot/assets/kolbot-automule4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-automule4.png -------------------------------------------------------------------------------- /kolbot/assets/kolbot-d2botmulelog1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-d2botmulelog1.png -------------------------------------------------------------------------------- /kolbot/assets/kolbot-d2botmulelog2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-d2botmulelog2.png -------------------------------------------------------------------------------- /kolbot/assets/kolbot-d2botmulelog3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-d2botmulelog3.png -------------------------------------------------------------------------------- /kolbot/assets/kolbot-d2botmulelog4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-d2botmulelog4.png -------------------------------------------------------------------------------- /kolbot/assets/kolbot-d2botmulelog5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-d2botmulelog5.png -------------------------------------------------------------------------------- /kolbot/assets/kolbot-d2botmulelog6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-d2botmulelog6.png -------------------------------------------------------------------------------- /kolbot/assets/kolbot-d2botmulelog7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-d2botmulelog7.png -------------------------------------------------------------------------------- /kolbot/assets/kolbot-manualplayD2BotMapEx1.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-manualplayD2BotMapEx1.JPG -------------------------------------------------------------------------------- /kolbot/assets/kolbot-manualplayD2BotMapEx2.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-manualplayD2BotMapEx2.JPG -------------------------------------------------------------------------------- /kolbot/assets/kolbot-manualplayMiscScript.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-manualplayMiscScript.jpg -------------------------------------------------------------------------------- /kolbot/assets/kolbot-multibotCreatorProfile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-multibotCreatorProfile.png -------------------------------------------------------------------------------- /kolbot/assets/kolbot-multibotD2BotFollow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-multibotD2BotFollow.png -------------------------------------------------------------------------------- /kolbot/assets/kolbot-multibotFollower1Profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-multibotFollower1Profile.png -------------------------------------------------------------------------------- /kolbot/assets/kolbot-multibotFollower2Profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-multibotFollower2Profile.png -------------------------------------------------------------------------------- /kolbot/assets/kolbot-np++styleconfigurator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-np++styleconfigurator.png -------------------------------------------------------------------------------- /kolbot/assets/kolbot-taiwan-disclaimer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/kolbot/assets/kolbot-taiwan-disclaimer.png -------------------------------------------------------------------------------- /kolbot/custom-scripts/CowOpen.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @filename CowOpen.js 3 | * @author part of Cows.js by kolton 4 | * @desc open cows portal 5 | */ 6 | 7 | function CowOpen() { 8 | this.getLeg = function () { 9 | let i, portal, wirt, leg, gid; 10 | 11 | if (me.getItem(88)) { 12 | return me.getItem(88); 13 | } 14 | 15 | Pather.useWaypoint(4); 16 | Precast.doPrecast(true); 17 | Pather.moveToPreset(me.area, 1, 737, 8, 8); 18 | 19 | for (i = 0; i < 6; i += 1) { 20 | portal = Pather.getPortal(38); 21 | 22 | if (portal) { 23 | Pather.usePortal(null, null, portal); 24 | 25 | break; 26 | } 27 | 28 | delay(500); 29 | } 30 | 31 | if (!portal) { 32 | throw new Error("Tristram portal not found"); 33 | } 34 | 35 | Pather.moveTo(25048, 5177); 36 | 37 | wirt = getUnit(2, 268); 38 | 39 | for (i = 0; i < 8; i += 1) { 40 | wirt.interact(); 41 | delay(500); 42 | 43 | leg = getUnit(4, 88); 44 | 45 | if (leg) { 46 | gid = leg.gid; 47 | 48 | Pickit.pickItem(leg); 49 | Town.goToTown(); 50 | 51 | return me.getItem(-1, -1, gid); 52 | } 53 | } 54 | 55 | throw new Error("Failed to get the leg"); 56 | }; 57 | 58 | this.getTome = function () { 59 | let tome, 60 | myTome = me.findItem("tbk", 0, 3), 61 | akara = Town.initNPC("Shop", "buy tome"); 62 | 63 | tome = me.getItem("tbk"); 64 | 65 | if (tome) { 66 | do { 67 | if (!myTome || tome.gid !== myTome.gid) { 68 | return copyUnit(tome); 69 | } 70 | } while (tome.getNext()); 71 | } 72 | 73 | if (!akara) { 74 | throw new Error("Failed to buy tome"); 75 | } 76 | 77 | tome = akara.getItem("tbk"); 78 | 79 | if (tome.buy()) { 80 | tome = me.getItem("tbk"); 81 | 82 | if (tome) { 83 | do { 84 | if (!myTome || tome.gid !== myTome.gid) { 85 | return copyUnit(tome); 86 | } 87 | } while (tome.getNext()); 88 | } 89 | } 90 | 91 | throw new Error("Failed to buy tome"); 92 | }; 93 | 94 | this.openPortal = function (leg, tome) { 95 | let i; 96 | 97 | if (!Town.openStash()) { 98 | throw new Error("Failed to open stash"); 99 | } 100 | 101 | if (!Cubing.emptyCube()) { 102 | throw new Error("Failed to empty cube"); 103 | } 104 | 105 | if (!Storage.Cube.MoveTo(leg) || !Storage.Cube.MoveTo(tome) || !Cubing.openCube()) { 106 | throw new Error("Failed to cube leg and tome"); 107 | } 108 | 109 | transmute(); 110 | delay(500); 111 | 112 | for (i = 0; i < 10; i += 1) { 113 | if (Pather.getPortal(39)) { 114 | return true; 115 | } 116 | 117 | delay(200); 118 | } 119 | 120 | throw new Error("Portal not found"); 121 | }; 122 | 123 | let leg, tome; 124 | 125 | // start 126 | if (me.getQuest(4, 10)) { // already killed the cow king 127 | throw new Error("Already killed the Cow King."); 128 | } 129 | 130 | if (!me.getQuest(4, 0)) { 131 | throw new Error("Cain quest incomplete"); 132 | } 133 | 134 | switch (me.gametype) { 135 | case 0: // classic 136 | if (!me.getQuest(26, 0)) { // diablo not completed 137 | throw new Error("Diablo quest incomplete."); 138 | } 139 | 140 | break; 141 | case 1: // expansion 142 | if (!me.getQuest(40, 0)) { // baal not completed 143 | throw new Error("Baal quest incomplete."); 144 | } 145 | 146 | break; 147 | } 148 | 149 | Town.goToTown(1); 150 | Town.doChores(); 151 | 152 | leg = this.getLeg(); 153 | tome = this.getTome(); 154 | 155 | this.openPortal(leg, tome); 156 | 157 | return true; 158 | } 159 | -------------------------------------------------------------------------------- /kolbot/custom-scripts/D2BotFollow.dbj: -------------------------------------------------------------------------------- 1 | var StarterConfig = { 2 | JoinChannel: "", // Name of the channel to join 3 | FirstJoinMessage: "", // Message to say when first joining a channel, usually ".login" 4 | ChatActionsDelay: rand(2e3, 7e3), // Milliseconds to wait in lobby before entering a channel 5 | 6 | JoinRetryDelay: rand(10e3, 15e3), // Time in milliseconds to wait before next join attempt 7 | SwitchKeyDelay: rand(10e3, 15e3), // Milliseconds to wait before switching a used/banned key or after realm down 8 | 9 | CrashDelay: rand(120e3, 150e3), // Milliseconds to wait after a d2 window crash 10 | RealmDownDelay: rand(5 * 6e4, 10 * 6e4), // Minutes to wait after getting Realm Down message 11 | UnableToConnectDelay: rand(2 * 6e4, 7 * 6e4), // Minutes to wait after Unable To Connect message 12 | CDKeyInUseDelay: rand(2 * 6e4, 7 * 6e4), // Minutes to wait before connecting again if CD-Key is in use. SwitchKeys overrides this! 13 | ConnectingTimeout: rand(25e3, 30e3), // Milliseconds to wait before cancelling the 'Connecting...' screen 14 | PleaseWaitTimeout: rand(30e3, 40e3), // Milliseconds to wait before cancelling the 'Please Wait...' screen 15 | WaitInLineTimeout: rand(60e3, 120e3), // Milliseconds to wait before cancelling the 'Waiting in Line...' screen 16 | GameDoesNotExistTimeout: rand(30e3, 60e3) // Milliseconds to wait before cancelling the 'Game does not exist.' screen 17 | }; 18 | 19 | /* Join game settings 20 | Format: "leader's profile": ["leecher 1 profile", "leecher 2 profile", ...] 21 | If you want everyone to join the same leader, use "leader's profile": ["all"] 22 | NOTE: Use PROFILE names (profile matches window title), NOT character/account names 23 | leader:leecher groups need to be divided by a comma 24 | example: 25 | var JoinSettings = { 26 | "lead1": ["follow1", "follow2"], 27 | "lead2": ["follow3", "follow4"] 28 | }; 29 | */ 30 | 31 | var JoinSettings = { 32 | "Leader": ["Leecher"] 33 | }; 34 | 35 | // Advanced config - you don't have to edit this unless you need some of the features provided 36 | var AdvancedConfig = { 37 | /* Features: Override join delay for each profile 38 | 39 | * Format *: 40 | "Profile Name": {JoinDelay: number_of_seconds} 41 | 42 | * Example * (don't edit this - it's just an example): 43 | "MyProfile1": {JoinDelay: rand(3e3, 5e3)}, 44 | "MyProfile2": {JoinDelay: rand(6e3, 9e3)} 45 | */ 46 | 47 | // Put your lines under this one. Multiple entries are separated by commas. No comma after the last one. 48 | 49 | }; 50 | 51 | 52 | 53 | // No touchy! 54 | include("json2.js"); 55 | include("OOG.js"); 56 | include("automule.js"); 57 | include("gambling.js"); 58 | include("craftingsystem.js"); 59 | include("torchsystem.js"); 60 | include("common/misc.js"); 61 | include("common/util.js"); 62 | 63 | var i, j, gameInfo, joinInfo, gameStart, ingame, handle, 64 | firstLogin, chatActionsDone, lastGameTick, connectFail, 65 | gameCount = DataFile.getStats().runs + 1, 66 | ftj = 0, 67 | wait = 0, 68 | loginRetry = 0, 69 | lastGameStatus = "ready", 70 | leader = "", 71 | lastGame = []; 72 | 73 | if (!FileTools.exists("data/" + me.profile + ".json")) { 74 | DataFile.create(); 75 | } 76 | 77 | function locationTimeout (time, location) { 78 | let endtime = getTickCount() + time; 79 | 80 | while (!me.ingame && getLocation() === location && endtime > getTickCount()) { 81 | delay(500); 82 | } 83 | 84 | return (getLocation() !== location); 85 | } 86 | 87 | function updateCount () { 88 | D2Bot.updateCount(); 89 | delay(1000); 90 | ControlAction.click(6, 264, 366, 272, 35); 91 | 92 | try { 93 | login(me.profile); 94 | } catch (e) { 95 | 96 | } 97 | 98 | delay(1000); 99 | ControlAction.click(6, 33, 572, 128, 35); 100 | } 101 | 102 | function ScriptMsgEvent (msg) { 103 | switch (msg) { 104 | case "mule": 105 | AutoMule.check = true; 106 | 107 | break; 108 | case "muleTorch": 109 | AutoMule.torchCheck = true; 110 | 111 | break; 112 | case "torch": 113 | TorchSystem.check = true; 114 | 115 | break; 116 | case "crafting": 117 | CraftingSystem.check = true; 118 | 119 | break; 120 | case "getMuleMode": 121 | if (AutoMule.torchAnniCheck === 2) { 122 | scriptBroadcast("2"); 123 | } else if (AutoMule.torchAnniCheck === 1) { 124 | scriptBroadcast("1"); 125 | } else if (AutoMule.check) { 126 | scriptBroadcast("0"); 127 | } 128 | 129 | break; 130 | } 131 | } 132 | 133 | function ReceiveCopyData (mode, msg) { 134 | let obj; 135 | 136 | switch (msg) { 137 | case "Handle": 138 | handle = mode; 139 | 140 | break; 141 | } 142 | 143 | switch (mode) { 144 | case 1: // JoinInfo 145 | //print("Got Join Info"); 146 | 147 | joinInfo = JSON.parse(msg); 148 | 149 | break; 150 | case 2: // Game info 151 | print("Recieved Game Info"); 152 | 153 | gameInfo = JSON.parse(msg); 154 | 155 | break; 156 | case 3: // Game request 157 | // Don't let others join mule/torch/key/gold drop game 158 | if (AutoMule.inGame || Gambling.inGame || TorchSystem.inGame || CraftingSystem.inGame) { 159 | break; 160 | } 161 | 162 | if (gameInfo) { 163 | obj = JSON.parse(msg); 164 | 165 | D2Bot.joinMe(obj.profile, me.gamename || "", "", me.gamepassword || "", me.gameReady ? "yes" : "no"); 166 | } 167 | 168 | break; 169 | case 4: 170 | // Heartbeat ping 171 | if (msg === "pingreq") { 172 | sendCopyData(null, me.windowtitle, 4, "pingrep"); 173 | } 174 | 175 | break; 176 | } 177 | } 178 | 179 | function timer (tick) { 180 | return " (" + new Date(getTickCount() - tick).toISOString().slice(11, -5) + ")"; 181 | } 182 | 183 | function main () { 184 | debugLog(me.profile); 185 | addEventListener("copydata", ReceiveCopyData); 186 | addEventListener("scriptmsg", ScriptMsgEvent); 187 | 188 | while (!handle) { 189 | delay(100); 190 | } 191 | 192 | DataFile.updateStats("handle", handle); 193 | D2Bot.init(); 194 | load("tools/heartbeat.js"); 195 | 196 | while (!gameInfo) { 197 | D2Bot.requestGameInfo(); 198 | delay(500); 199 | } 200 | 201 | if (gameInfo.error) { 202 | //D2Bot.retrieve(); 203 | delay(200); 204 | 205 | if (!!DataFile.getStats().debugInfo) { 206 | gameInfo.crashInfo = DataFile.getStats().debugInfo; 207 | 208 | D2Bot.printToConsole("Crash Info: Script: " + JSON.parse(gameInfo.crashInfo).currScript + " Area: " + JSON.parse(gameInfo.crashInfo).area, 10); 209 | } 210 | 211 | /*if (gameInfo.crashInfo) { 212 | D2Bot.printToConsole("Crash Info: Script: " + gameInfo.crashInfo.currScript + " Area: " + gameInfo.crashInfo.area + (gameInfo.crashInfo.hasOwnProperty("lastAction") ? " " + gameInfo.crashInfo.lastAction : ""), 10); 213 | }*/ 214 | 215 | ControlAction.timeoutDelay("Crash Delay", StarterConfig.CrashDelay); 216 | D2Bot.updateRuns(); 217 | } 218 | 219 | //D2Bot.store(JSON.stringify({currScript: "none", area: "out of game"})); 220 | DataFile.updateStats("debugInfo", JSON.stringify({ currScript: "none", area: "out of game" })); 221 | 222 | while (true) { 223 | while (me.ingame) { // returns true before actually in game so we can't only use this check 224 | if (me.gameReady) { // returns false when switching acts so we can't use while 225 | if (!ingame) { 226 | print("ÿc4Updating Status"); 227 | //D2Bot.updateStatus("Game: " + me.gamename); 228 | 229 | lastGameStatus = "ingame"; 230 | ingame = true; 231 | gameStart = getTickCount(); 232 | 233 | DataFile.updateStats("runs", gameCount); 234 | } 235 | 236 | D2Bot.updateStatus("Game: " + me.gamename + timer(gameStart) + " IP: " + (me.gameserverip.length > 0 ? me.gameserverip.split(".")[3] : "0")); 237 | } 238 | 239 | delay(1000); 240 | } 241 | 242 | locationAction(); 243 | delay(1000); 244 | } 245 | } 246 | 247 | function joinCheck (leader) { 248 | D2Bot.requestGame(leader); 249 | delay(500); 250 | 251 | //print(leader + " " + joinInfo.inGame + " " + lastGame.toSource() + " " + joinInfo.gameName); 252 | 253 | if (!joinInfo.inGame || (lastGame.length && lastGame.indexOf(joinInfo.gameName) === -1)) { 254 | D2Bot.printToConsole("Game is finished. Stopping join delay."); 255 | 256 | return true; 257 | } 258 | 259 | return false; 260 | } 261 | 262 | function locationAction () { 263 | if (me.ingame) { 264 | return; 265 | } 266 | 267 | let i, string, control, text, location; 268 | 269 | location = getLocation(); 270 | 271 | MainSwitch: 272 | switch (location) { 273 | case 0: 274 | ControlAction.click(); 275 | 276 | break; 277 | case 1: // Lobby 278 | D2Bot.updateStatus("Lobby"); 279 | 280 | me.blockKeys = false; 281 | loginRetry = 0; 282 | 283 | if (!firstLogin) { 284 | firstLogin = true; 285 | } 286 | 287 | if (StarterConfig.JoinChannel !== "") { 288 | ControlAction.click(6, 27, 480, 120, 20); 289 | 290 | break; 291 | } 292 | 293 | if (ingame) { 294 | if (AutoMule.outOfGameCheck() || TorchSystem.outOfGameCheck() || Gambling.outOfGameCheck() || CraftingSystem.outOfGameCheck()) { 295 | break; 296 | } 297 | 298 | print("updating runs"); 299 | D2Bot.updateRuns(); 300 | 301 | lastGameTick = getTickCount(); 302 | gameCount += 1; 303 | lastGameStatus = "ready"; 304 | ingame = false; 305 | } 306 | 307 | if (!ControlAction.click(6, 652, 469, 120, 20)) { // Join 308 | break; 309 | } 310 | 311 | if (!locationTimeout(5000, location)) { // in case join button gets bugged 312 | if (!ControlAction.click(6, 533, 469, 120, 20)) { // Create 313 | break; 314 | } 315 | 316 | if (!ControlAction.click(6, 652, 469, 120, 20)) { // Join 317 | break; 318 | } 319 | } 320 | 321 | break; 322 | case 2: // Waiting In Line 323 | D2Bot.updateStatus("Waiting..."); 324 | wait++; 325 | 326 | if (wait > 2) { 327 | D2Bot.printToConsole(me.profile + " - Waiting in line"); 328 | D2Bot.stop(me.profile, true); 329 | } 330 | 331 | locationTimeout(StarterConfig.WaitInLineTimeout, location); 332 | ControlAction.click(6, 433, 433, 96, 32); 333 | 334 | break; 335 | case 3: // Lobby Chat 336 | D2Bot.updateStatus("Lobby Chat"); 337 | 338 | if (ingame) { 339 | if (AutoMule.outOfGameCheck() || TorchSystem.outOfGameCheck() || Gambling.outOfGameCheck() || CraftingSystem.outOfGameCheck()) { 340 | break; 341 | } 342 | 343 | print("updating runs"); 344 | D2Bot.updateRuns(); 345 | 346 | lastGameTick = getTickCount(); 347 | gameCount += 1; 348 | lastGameStatus = "ready"; 349 | ingame = false; 350 | } 351 | 352 | if (!chatActionsDone) { 353 | chatActionsDone = true; 354 | 355 | ControlAction.timeoutDelay("Chat delay", StarterConfig.ChatActionsDelay); 356 | say("/j " + StarterConfig.JoinChannel); 357 | delay(1000); 358 | 359 | if (StarterConfig.FirstJoinMessage !== "") { 360 | say(StarterConfig.FirstJoinMessage); 361 | delay(500); 362 | } 363 | } 364 | 365 | if (!ControlAction.click(6, 652, 469, 120, 20)) { // Join 366 | break; 367 | } 368 | 369 | if (!locationTimeout(5000, location)) { // in case join button gets bugged 370 | if (!ControlAction.click(6, 533, 469, 120, 20)) { // Create 371 | break; 372 | } 373 | 374 | if (!ControlAction.click(6, 652, 469, 120, 20)) { // Join 375 | break; 376 | } 377 | } 378 | 379 | break; 380 | case 4: // Create Game 381 | break; 382 | case 5: // Join Game 383 | D2Bot.updateStatus("Join Game"); 384 | 385 | if (!leader) { 386 | leader = []; 387 | 388 | for (i in JoinSettings) { 389 | if (JoinSettings.hasOwnProperty(i) && typeof i === "string") { 390 | for (j = 0; j < JoinSettings[i].length; j += 1) { 391 | if (JoinSettings[i][j] === me.profile || JoinSettings[i][j] === "all") { 392 | leader.push(i); 393 | } 394 | } 395 | } 396 | } 397 | } 398 | 399 | if (!leader || !leader.length) { 400 | break; 401 | } 402 | 403 | JoinLoop2: 404 | for (i = 0; i < 5; i += 1) { 405 | for (j = 0; j < leader.length; j += 1) { 406 | joinInfo = false; 407 | 408 | D2Bot.requestGame(leader[j]); 409 | delay(100); 410 | 411 | if (joinInfo && joinInfo.gameName !== "" && (lastGame.indexOf(joinInfo.gameName) === -1 || lastGameStatus === "pending")) { 412 | ControlAction.setText(1, 606, 148, 155, 20, joinInfo.gamePass); 413 | ControlAction.setText(1, 432, 148, 155, 20, joinInfo.gameName); 414 | 415 | if (lastGameStatus === "pending" || (gameInfo.error && DataFile.getStats().gameName === joinInfo.gameName)) { 416 | D2Bot.printToConsole("Failed to join game"); 417 | ControlAction.timeoutDelay("Join Delay", StarterConfig.JoinRetryDelay, joinCheck, leader[j]); 418 | D2Bot.updateRuns(); 419 | D2Bot.requestGame(leader[j]); 420 | delay(200); 421 | 422 | if (!joinInfo.inGame) { 423 | lastGameStatus = "ready"; 424 | 425 | break; 426 | } 427 | } 428 | 429 | if (!joinInfo.inGame) { 430 | continue; 431 | } 432 | 433 | // Don't join immediately after previous game to avoid FTJ 434 | if (getTickCount() - lastGameTick < 5000) { 435 | ControlAction.timeoutDelay("Game Delay", (lastGameTick - getTickCount() + 5000)); 436 | } 437 | 438 | print("joining game " + joinInfo.gameName); 439 | 440 | if (typeof AdvancedConfig[me.profile] === "object" && typeof AdvancedConfig[me.profile].JoinDelay === "number") { 441 | ControlAction.timeoutDelay("Custom Join Delay", AdvancedConfig[me.profile].JoinDelay); 442 | } 443 | 444 | me.blockMouse = true; 445 | 446 | DataFile.updateStats("gameName", joinInfo.gameName); 447 | ControlAction.click(6, 594, 433, 172, 32); 448 | 449 | me.blockMouse = false; 450 | 451 | lastGame.push(joinInfo.gameName); 452 | 453 | if (lastGame.length > leader.length) { // Might need a fixed number. Right now it stores 1 game per leader. 454 | lastGame.shift(); 455 | } 456 | 457 | lastGameStatus = "pending"; 458 | 459 | locationTimeout(15000, location); 460 | 461 | break JoinLoop2; 462 | } 463 | } 464 | } 465 | 466 | break; 467 | case 6: // Ladder 468 | break; 469 | case 7: // Channel List 470 | break; 471 | case 8: // Main Menu 472 | case 9: // Login 473 | case 12: // Character Select 474 | case 18: // D2 Splash 475 | // Single Player screen fix 476 | if (getLocation() === 12 && !getControl(4, 626, 100, 151, 44)) { 477 | ControlAction.click(6, 33, 572, 128, 35); 478 | 479 | break; 480 | } 481 | 482 | if (firstLogin && getLocation() === 9) { // multiple realm botting fix in case of R/D or disconnect 483 | ControlAction.click(6, 33, 572, 128, 35); 484 | } 485 | 486 | D2Bot.updateStatus("Logging In"); 487 | 488 | try { 489 | login(me.profile); 490 | } catch (e) { 491 | if (getLocation() === 12 && loginRetry < 2) { 492 | if (loginRetry === 0) { 493 | // start from beginning of the char list 494 | sendKey(0x24); 495 | } 496 | 497 | control = getControl(4, 237, 457, 72, 93); // char on 1st column, 4th row 498 | 499 | if (control) { 500 | me.blockMouse = true; 501 | me.blockKeys = true; 502 | 503 | control.click(); 504 | sendKey(0x28); 505 | sendKey(0x28); 506 | sendKey(0x28); 507 | sendKey(0x28); 508 | 509 | me.blockMouse = false; 510 | } 511 | 512 | loginRetry++; 513 | } else { 514 | me.blockKeys = false; 515 | print(e + " " + getLocation()); 516 | } 517 | } 518 | 519 | break; 520 | case 10: // Login Error 521 | string = ""; 522 | text = ControlAction.getText(4, 199, 377, 402, 140); 523 | 524 | if (text) { 525 | for (i = 0; i < text.length; i += 1) { 526 | string += text[i]; 527 | 528 | if (i !== text.length - 1) { 529 | string += " "; 530 | } 531 | } 532 | 533 | switch (string) { 534 | case getLocaleString(5207): 535 | D2Bot.updateStatus("Invalid Password"); 536 | D2Bot.printToConsole("Invalid Password"); 537 | 538 | break; 539 | case getLocaleString(5208): 540 | D2Bot.updateStatus("Invalid Account"); 541 | D2Bot.printToConsole("Invalid Account"); 542 | 543 | break; 544 | case getLocaleString(5202): // cd key intended for another product 545 | case getLocaleString(10915): // lod key intended for another product 546 | D2Bot.updateStatus("Invalid CDKey"); 547 | D2Bot.printToConsole("Invalid CDKey: " + gameInfo.mpq, 6); 548 | D2Bot.CDKeyDisabled(); 549 | 550 | if (gameInfo.switchKeys) { 551 | ControlAction.timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay); 552 | D2Bot.restart(true); 553 | } else { 554 | D2Bot.stop(); 555 | } 556 | 557 | break; 558 | case getLocaleString(5199): 559 | D2Bot.updateStatus("Disabled CDKey"); 560 | D2Bot.printToConsole("Disabled CDKey: " + gameInfo.mpq, 6); 561 | D2Bot.CDKeyDisabled(); 562 | 563 | if (gameInfo.switchKeys) { 564 | ControlAction.timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay); 565 | D2Bot.restart(true); 566 | } else { 567 | D2Bot.stop(); 568 | } 569 | 570 | break; 571 | case getLocaleString(10913): 572 | D2Bot.updateStatus("Disabled LoD CDKey"); 573 | D2Bot.printToConsole("Disabled LoD CDKey: " + gameInfo.mpq, 6); 574 | D2Bot.CDKeyDisabled(); 575 | 576 | if (gameInfo.switchKeys) { 577 | ControlAction.timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay); 578 | D2Bot.restart(true); 579 | } else { 580 | D2Bot.stop(); 581 | } 582 | 583 | break; 584 | case getLocaleString(5347): 585 | D2Bot.updateStatus("Disconnected"); 586 | D2Bot.printToConsole("Disconnected"); 587 | ControlAction.click(6, 335, 412, 128, 35); 588 | 589 | break MainSwitch; 590 | default: 591 | D2Bot.updateStatus("Login Error"); 592 | D2Bot.printToConsole("Login Error - " + string); 593 | 594 | if (gameInfo.switchKeys) { 595 | ControlAction.timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay); 596 | D2Bot.restart(true); 597 | } else { 598 | D2Bot.stop(); 599 | } 600 | 601 | break; 602 | } 603 | } 604 | 605 | ControlAction.click(6, 335, 412, 128, 35); 606 | 607 | while (true) { 608 | delay(1000); 609 | } 610 | 611 | break; 612 | case 11: // Unable To Connect 613 | D2Bot.updateStatus("Unable To Connect"); 614 | 615 | if (connectFail) { 616 | ControlAction.timeoutDelay("Unable to Connect", StarterConfig.UnableToConnectDelay); 617 | 618 | connectFail = false; 619 | } else { 620 | connectFail = true; 621 | } 622 | 623 | if (!ControlAction.click(6, 335, 450, 128, 35)) { 624 | break; 625 | } 626 | 627 | break; 628 | case 13: // Realm Down - Character Select screen 629 | D2Bot.updateStatus("Realm Down"); 630 | delay(1000); 631 | 632 | if (!ControlAction.click(6, 33, 572, 128, 35)) { 633 | break; 634 | } 635 | 636 | updateCount(); 637 | ControlAction.timeoutDelay("Realm Down", StarterConfig.RealmDownDelay); 638 | D2Bot.CDKeyRD(); 639 | 640 | if (gameInfo.switchKeys && !gameInfo.rdBlocker) { 641 | D2Bot.printToConsole("Realm Down - Changing CD-Key"); 642 | ControlAction.timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay); 643 | D2Bot.restart(true); 644 | } else { 645 | D2Bot.printToConsole("Realm Down - Restart"); 646 | D2Bot.restart(); 647 | } 648 | 649 | break; 650 | case 14: // Character Select - Disconnected 651 | D2Bot.updateStatus("Disconnected"); 652 | delay(500); 653 | ControlAction.click(6, 351, 337, 96, 32); 654 | 655 | break; 656 | case 16: // Character Select - Please Wait popup 657 | if (!locationTimeout(StarterConfig.PleaseWaitTimeout, location)) { 658 | ControlAction.click(6, 351, 337, 96, 32); 659 | } 660 | 661 | break; 662 | case 17: // Lobby - Lost Connection - just click okay, since we're toast anyway 663 | delay(1000); 664 | ControlAction.click(6, 351, 337, 96, 32); 665 | 666 | break; 667 | case 19: // Login - Cdkey In Use 668 | D2Bot.printToConsole(gameInfo.mpq + " is in use by " + ControlAction.getText(4, 158, 310, 485, 40), 6); 669 | D2Bot.CDKeyInUse(); 670 | 671 | if (gameInfo.switchKeys) { 672 | ControlAction.timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay); 673 | D2Bot.restart(true); 674 | } else { 675 | ControlAction.timeoutDelay("CD-Key in use", StarterConfig.CDKeyInUseDelay); 676 | ControlAction.click(6, 335, 450, 128, 35); 677 | } 678 | 679 | break; 680 | case 20: // Single Player - Select Difficulty 681 | break; 682 | case 21: // Main Menu - Connecting 683 | if (!locationTimeout(StarterConfig.ConnectingTimeout, location)) { 684 | ControlAction.click(6, 330, 416, 128, 35); 685 | } 686 | 687 | break; 688 | case 22: // Login - Invalid Cdkey (classic or xpac) 689 | text = ControlAction.getText(4, 162, 270, 477, 50); 690 | string = ""; 691 | 692 | if (text) { 693 | for (i = 0; i < text.length; i += 1) { 694 | string += text[i]; 695 | 696 | if (i !== text.length - 1) { 697 | string += " "; 698 | } 699 | } 700 | } 701 | 702 | switch (string) { 703 | case getLocaleString(10914): 704 | D2Bot.printToConsole(gameInfo.mpq + " LoD key in use by " + ControlAction.getText(4, 158, 310, 485, 40), 6); 705 | D2Bot.CDKeyInUse(); 706 | 707 | if (gameInfo.switchKeys) { 708 | ControlAction.timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay); 709 | D2Bot.restart(true); 710 | } else { 711 | ControlAction.click(6, 335, 450, 128, 35); 712 | ControlAction.timeoutDelay("LoD key in use", StarterConfig.CDKeyInUseDelay); 713 | } 714 | 715 | break; 716 | default: 717 | if (gameInfo.switchKeys) { 718 | D2Bot.printToConsole("Invalid CD-Key"); 719 | ControlAction.timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay); 720 | D2Bot.restart(true); 721 | } else { 722 | ControlAction.click(6, 335, 450, 128, 35); 723 | ControlAction.timeoutDelay("Invalid CD-Key", StarterConfig.CDKeyInUseDelay); 724 | } 725 | 726 | break; 727 | } 728 | 729 | break; 730 | case 23: // Character Select - Connecting 731 | case 42: // Empty character screen 732 | string = ""; 733 | text = ControlAction.getText(4, 45, 318, 531, 140); 734 | 735 | if (text) { 736 | for (i = 0; i < text.length; i += 1) { 737 | string += text[i]; 738 | 739 | if (i !== text.length - 1) { 740 | string += " "; 741 | } 742 | } 743 | 744 | if (string === getLocaleString(11161)) { // CDKey disabled from realm play 745 | D2Bot.updateStatus("Realm Disabled CDKey"); 746 | D2Bot.printToConsole("Realm Disabled CDKey: " + gameInfo.mpq, 6); 747 | D2Bot.CDKeyDisabled(); 748 | 749 | if (gameInfo.switchKeys) { 750 | ControlAction.timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay); 751 | D2Bot.restart(true); 752 | } else { 753 | D2Bot.stop(); 754 | } 755 | } 756 | } 757 | 758 | if (!locationTimeout(StarterConfig.ConnectingTimeout, location)) { 759 | ControlAction.click(6, 33, 572, 128, 35); 760 | 761 | if (gameInfo.rdBlocker) { 762 | D2Bot.restart(); 763 | } 764 | } 765 | 766 | break; 767 | case 24: // Server Down - not much to do but wait.. 768 | break; 769 | case 25: // Lobby - Please Wait 770 | if (!locationTimeout(StarterConfig.PleaseWaitTimeout, location)) { 771 | ControlAction.click(6, 351, 337, 96, 32); 772 | } 773 | 774 | break; 775 | case 26: // Lobby - Game Name Exists 776 | break; 777 | case 27: // Gateway Select 778 | ControlAction.click(6, 436, 538, 96, 32); 779 | 780 | break; 781 | case 28: // Lobby - Game Does Not Exist 782 | D2Bot.printToConsole("Game doesn't exist"); 783 | ftj++; 784 | 785 | if (ftj > 4) { 786 | D2BotFollow.update("done", "D2BotFollow failed to join game!"); 787 | D2Bot.stop(me.profile, true); 788 | } 789 | 790 | if (gameInfo.rdBlocker) { 791 | D2Bot.printToConsole(gameInfo.mpq + " is probably flagged.", 6); 792 | 793 | if (gameInfo.switchKeys) { 794 | ControlAction.timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay); 795 | D2Bot.restart(true); 796 | } 797 | } else { 798 | locationTimeout(StarterConfig.GameDoesNotExistTimeout, location); 799 | } 800 | 801 | lastGameStatus = "ready"; 802 | 803 | break; 804 | case 38: // Game is full 805 | D2Bot.printToConsole("Game is full"); 806 | ControlAction.click(6, 652, 469, 120, 20); 807 | lastGame.push(joinInfo.gameName); 808 | 809 | lastGameStatus = "ready"; 810 | 811 | break; 812 | default: 813 | if (location !== undefined) { 814 | D2Bot.printToConsole("Unhandled location " + location); 815 | //takeScreenshot(); 816 | delay(500); 817 | D2Bot.restart(); 818 | } 819 | 820 | break; 821 | } 822 | } 823 | -------------------------------------------------------------------------------- /kolbot/custom-scripts/D2BotTimerRefresh.dbj: -------------------------------------------------------------------------------- 1 | var StarterConfig = { 2 | MinGameTime: rand(150, 180), // Minimum game length in seconds. If a game is ended too soon, the rest of the time is waited in the lobby 3 | CreateGameDelay: rand(5, 15), // Seconds to wait before creating a new game 4 | 5 | SwitchKeyDelay: 0, // Seconds to wait before switching a used/banned key or after realm down 6 | 7 | CrashDelay: rand(60, 120), // Seconds to wait after a d2 window crash 8 | RealmDownDelay: rand(3, 6), // Minutes to wait after getting Realm Down message 9 | UnableToConnectDelay: rand(5, 8), // Minutes to wait after Unable To Connect message 10 | CDKeyInUseDelay: rand(5, 8), // Minutes to wait before connecting again if CD-Key is in use. SwitchKeys overrides this! 11 | ConnectingTimeout: rand(20, 30), // Seconds to wait before cancelling the 'Connecting...' screen 12 | PleaseWaitTimeout: rand(10, 20), // Seconds to wait before cancelling the 'Please Wait...' screen 13 | WaitInLineTimeout: rand(30, 60) // Seconds to wait before cancelling the 'Waiting in Line...' screen 14 | }; 15 | 16 | var RefreshAccounts = { 17 | /* Format: 18 | "account1/password1/realm": ["charname1", "charname2 etc"], 19 | "account2/password2/realm": ["charnameX", "charnameY etc"], 20 | "account3/password3/realm": ["all"] 21 | 22 | To log a full account, put "account/password/realm": ["all"] 23 | 24 | realm = useast, uswest, europe or asia 25 | 26 | Individual entries are separated with a comma. 27 | */ 28 | 29 | "account1/password/realm": ["all"], 30 | "account2/password/realm": ["all"], 31 | "account3/password/realm": ["all"] 32 | 33 | }; 34 | 35 | // No touchy! 36 | include("json2.js"); 37 | include("OOG.js"); 38 | include("common/misc.js"); 39 | include("common/util.js"); 40 | 41 | if (!FileTools.exists("data/" + me.profile + ".json")) { 42 | DataFile.create(); 43 | } 44 | 45 | var handle, gameInfo, connectFail, currAcc, charList, 46 | accounts = [], 47 | chars = []; 48 | 49 | function save(hash, data) { 50 | let filename = "data/secure/" + hash + ".txt"; 51 | FileTools.writeText(filename, data); 52 | } 53 | 54 | function parseInfo() { 55 | let i; 56 | 57 | for (i in RefreshAccounts) { 58 | if (RefreshAccounts.hasOwnProperty(i) && typeof i === "string") { 59 | accounts.push(i); 60 | chars.push(RefreshAccounts[i]); 61 | } 62 | } 63 | } 64 | 65 | function ReceiveCopyData(mode, msg) { 66 | switch (msg) { 67 | case "Handle": 68 | handle = mode; 69 | 70 | break; 71 | } 72 | 73 | switch (mode) { 74 | case 2: // game info 75 | print("Recieved Game Info"); 76 | 77 | gameInfo = JSON.parse(msg); 78 | 79 | break; 80 | case 4: 81 | // Heartbeat ping 82 | if (msg === "pingreq") { 83 | sendCopyData(null, me.windowtitle, 4, "pingrep"); 84 | } 85 | 86 | break; 87 | } 88 | } 89 | 90 | function timeoutDelay(text, time) { 91 | let endTime = getTickCount() + time; 92 | 93 | while (getTickCount() < endTime) { 94 | D2Bot.updateStatus(text + " (" + Math.floor((endTime - getTickCount()) / 1000) + "s)"); 95 | delay(500); 96 | } 97 | } 98 | 99 | function locationTimeout(time, location) { 100 | let endtime = getTickCount() + time; 101 | 102 | while (getLocation() === location && endtime > getTickCount()) { 103 | delay(500); 104 | } 105 | 106 | return (getLocation() !== location); 107 | } 108 | 109 | function updateCount() { 110 | D2Bot.updateCount(); 111 | delay(1000); 112 | ControlAction.click(6, 264, 366, 272, 35); 113 | 114 | try { 115 | login(me.profile); 116 | } catch (e) { 117 | 118 | } 119 | 120 | delay(1000); 121 | ControlAction.click(6, 33, 572, 128, 35); 122 | } 123 | 124 | function countdowntimer (tick) { 125 | return " (" + new Date(tick - getTickCount()).toISOString().slice(11, -5) + ")"; 126 | } 127 | 128 | function main() { 129 | addEventListener("copydata", ReceiveCopyData); 130 | 131 | while (!handle) { 132 | delay(100); 133 | } 134 | 135 | DataFile.updateStats("handle", handle); 136 | D2Bot.init(); 137 | load("tools/heartbeat.js"); 138 | 139 | while (!gameInfo) { 140 | D2Bot.requestGameInfo(); 141 | delay(500); 142 | } 143 | 144 | if (gameInfo.rdBlocker) { 145 | D2Bot.printToConsole("You must disable RD Blocker for Timer Refresh to work properly. Stopping."); 146 | D2Bot.stop(me.profile, true); 147 | 148 | return; 149 | } 150 | 151 | parseInfo(); 152 | 153 | if (gameInfo.error) { 154 | if (!!DataFile.getStats().debugInfo) { 155 | gameInfo.crashInfo = DataFile.getStats().debugInfo; 156 | 157 | D2Bot.printToConsole("Crash Info: Script: " + JSON.parse(gameInfo.crashInfo).currScript + " Area: " + JSON.parse(gameInfo.crashInfo).area, 10); 158 | } 159 | 160 | ControlAction.timeoutDelay("Crash Delay", StarterConfig.CrashDelay * 1e3); 161 | D2Bot.updateRuns(); 162 | } 163 | 164 | DataFile.updateStats("debugInfo", JSON.stringify({ currScript: "none", area: "out of game" })); 165 | 166 | while (true) { 167 | locationAction(getLocation()); 168 | delay(1000); 169 | } 170 | } 171 | 172 | function locationAction(location) { 173 | let i, control, string, text, currChar, 174 | obj = {}; 175 | 176 | MainSwitch: 177 | switch (location) { 178 | case 0: 179 | break; 180 | case 1: // Lobby 181 | case 3: // Lobby Chat 182 | D2Bot.updateStatus("Lobby"); 183 | 184 | // delay and show remaining lobby time 185 | var tick, 186 | tick = getTickCount() + rand(15000, 25000); 187 | 188 | D2Bot.printToConsole(" char: " + me.charname); 189 | 190 | while (getTickCount() - tick < 0) { 191 | D2Bot.updateStatus("Lobby: " + countdowntimer(tick)); 192 | delay(1000); 193 | } 194 | 195 | ControlAction.click(6, 693, 490, 80, 20); // Quit from Lobby 196 | delay(rand(1500, 3000)); 197 | 198 | break; 199 | case 2: // Waiting In Line 200 | D2Bot.updateStatus("Waiting..."); 201 | locationTimeout(StarterConfig.WaitInLineTimeout * 1e3, location); 202 | ControlAction.click(6, 433, 433, 96, 32); 203 | 204 | break; 205 | case 4: // Create Game 206 | D2Bot.updateStatus("Creating Game"); 207 | 208 | break; 209 | case 5: // Join Game 210 | break; 211 | case 6: // Ladder 212 | break; 213 | case 7: // Channel List 214 | break; 215 | case 8: // Main Menu 216 | case 9: // Login 217 | case 18: // D2 Splash 218 | if (!accounts.length) { 219 | FileTools.remove("logs/CharLog.json"); 220 | FileTools.remove("data/" + me.profile + ".json"); 221 | delay(1000); 222 | D2Bot.printToConsole("Done refreshing countdown timer!"); 223 | D2Bot.stop(me.profile, true); 224 | 225 | break; 226 | } 227 | 228 | if (FileTools.exists("logs/CharLog.json")) { 229 | obj = JSON.parse(FileTools.readText("logs/CharLog.json")); 230 | 231 | if (obj.currAcc) { 232 | for (i = 0; i < accounts.length; i += 1) { 233 | if (accounts[i].split("/")[0] === obj.currAcc) { 234 | accounts.splice(0, i); 235 | chars.splice(0, i); 236 | 237 | i -= 1; 238 | 239 | break; 240 | } 241 | } 242 | } 243 | } 244 | 245 | currAcc = accounts[0]; 246 | currAcc = currAcc.split("/"); 247 | charList = chars[0]; 248 | obj.currAcc = currAcc[0]; 249 | 250 | FileTools.writeText("logs/CharLog.json", JSON.stringify(obj)); 251 | save(md5(currAcc[2].toLowerCase() + currAcc[0].toLowerCase()), currAcc[1]); 252 | D2Bot.printToConsole("account: " + currAcc[0]); 253 | delay(rand(500, 1500)); 254 | ControlAction.loginAccount({ account: currAcc[0], password: currAcc[1], realm: currAcc[2] }); 255 | delay(rand(500, 1500)); 256 | accounts.shift(); // remove current account from the list 257 | 258 | break; 259 | case 10: // Login Error 260 | string = ""; 261 | text = ControlAction.getText(4, 199, 377, 402, 140); 262 | 263 | if (text) { 264 | for (i = 0; i < text.length; i += 1) { 265 | string += text[i]; 266 | 267 | if (i !== text.length - 1) { 268 | string += " "; 269 | } 270 | } 271 | 272 | switch (string) { 273 | case getLocaleString(5207): 274 | D2Bot.updateStatus("Invalid Password"); 275 | D2Bot.printToConsole("Invalid Password"); 276 | 277 | break; 278 | case getLocaleString(5208): 279 | D2Bot.updateStatus("Invalid Account"); 280 | D2Bot.printToConsole("Invalid Account"); 281 | 282 | break; 283 | case getLocaleString(5202): // cd key intended for another product 284 | case getLocaleString(10915): // lod key intended for another product 285 | D2Bot.updateStatus("Invalid CDKey"); 286 | D2Bot.printToConsole("Invalid CDKey: " + gameInfo.mpq, 6); 287 | D2Bot.CDKeyDisabled(); 288 | 289 | if (gameInfo.switchKeys) { 290 | ControlAction.timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay * 1000); 291 | D2Bot.restart(true); 292 | } else { 293 | D2Bot.stop(me.profile, true); 294 | } 295 | 296 | break; 297 | case getLocaleString(5199): 298 | D2Bot.updateStatus("Disabled CDKey"); 299 | D2Bot.printToConsole("Disabled CDKey: " + gameInfo.mpq, 6); 300 | D2Bot.CDKeyDisabled(); 301 | 302 | if (gameInfo.switchKeys) { 303 | ControlAction.timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay * 1000); 304 | D2Bot.restart(true); 305 | } else { 306 | D2Bot.stop(me.profile, true); 307 | } 308 | 309 | break; 310 | case getLocaleString(10913): 311 | D2Bot.updateStatus("Disabled LoD CDKey"); 312 | D2Bot.printToConsole("Disabled LoD CDKey: " + gameInfo.mpq, 6); 313 | D2Bot.CDKeyDisabled(); 314 | 315 | if (gameInfo.switchKeys) { 316 | ControlAction.timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay * 1000); 317 | D2Bot.restart(true); 318 | } else { 319 | D2Bot.stop(me.profile, true); 320 | } 321 | 322 | break; 323 | case getLocaleString(5347): 324 | D2Bot.updateStatus("Disconnected"); 325 | D2Bot.printToConsole("Disconnected"); 326 | ControlAction.click(6, 335, 412, 128, 35); 327 | 328 | break MainSwitch; 329 | default: 330 | D2Bot.updateStatus("Login Error"); 331 | D2Bot.printToConsole("Login Error - " + string); 332 | 333 | if (gameInfo.switchKeys) { 334 | ControlAction.timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay * 1000); 335 | D2Bot.restart(true); 336 | } else { 337 | D2Bot.stop(me.profile, true); 338 | } 339 | 340 | break; 341 | } 342 | } 343 | 344 | ControlAction.click(6, 335, 412, 128, 35); 345 | 346 | while (true) { 347 | delay(1000); 348 | } 349 | 350 | break; 351 | case 11: // Unable To Connect 352 | D2Bot.updateStatus("Unable To Connect"); 353 | 354 | if (connectFail) { 355 | timeoutDelay("Unable to Connect", StarterConfig.UnableToConnectDelay * 6e4); 356 | 357 | connectFail = false; 358 | } 359 | 360 | if (!ControlAction.click(6, 335, 450, 128, 35)) { 361 | break; 362 | } 363 | 364 | connectFail = true; 365 | 366 | break; 367 | case 12: // Character Select 368 | // Single Player screen fix 369 | if (getLocation() === 12 && !getControl(4, 626, 100, 151, 44)) { 370 | ControlAction.click(6, 33, 572, 128, 35); 371 | 372 | break; 373 | } 374 | 375 | if (!charList.length) { 376 | ControlAction.click(6, 33, 572, 128, 35); 377 | 378 | break; 379 | } 380 | 381 | if (charList[0] === "all") { 382 | charList = ControlAction.getCharacters(); 383 | } 384 | 385 | if (FileTools.exists("logs/CharLog.json")) { 386 | obj = JSON.parse(FileTools.readText("logs/CharLog.json")); 387 | 388 | if (obj.currChar) { 389 | for (i = 0; i < charList.length; i += 1) { 390 | if (charList[i] === obj.currChar) { 391 | charList.splice(0, i + 1); // Remove the previous currChar as well 392 | 393 | break; 394 | } 395 | } 396 | } 397 | } 398 | 399 | // last char in acc = trigger next acc 400 | if (!charList.length) { 401 | accounts.shift(); // remove current account from the list 402 | chars.shift(); 403 | 404 | break; 405 | } 406 | 407 | currChar = charList.shift(); 408 | obj.currChar = currChar; 409 | 410 | FileTools.writeText("logs/CharLog.json", JSON.stringify(obj)); 411 | ControlAction.loginCharacter({ charName: currChar }); 412 | 413 | break; 414 | case 13: // Realm Down - Character Select screen 415 | D2Bot.updateStatus("Realm Down"); 416 | delay(1000); 417 | 418 | if (!ControlAction.click(6, 33, 572, 128, 35)) { 419 | break; 420 | } 421 | 422 | updateCount(); 423 | timeoutDelay("Realm Down", StarterConfig.RealmDownDelay * 6e4); 424 | 425 | if (gameInfo.switchKeys) { 426 | D2Bot.printToConsole("Realm Down - Changing CD-Key"); 427 | timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay * 1000); 428 | D2Bot.restart(true); 429 | } else { 430 | D2Bot.restart(); 431 | } 432 | 433 | break; 434 | case 14: // Character Select / Main Menu - Disconnected 435 | D2Bot.updateStatus("Disconnected"); 436 | delay(500); 437 | ControlAction.click(6, 351, 337, 96, 32); 438 | break; 439 | case 15: // New Character 440 | break; 441 | case 16: // Character Select - Please Wait popup 442 | if (!locationTimeout(StarterConfig.PleaseWaitTimeout * 1e3, location)) { 443 | ControlAction.click(6, 351, 337, 96, 32); 444 | } 445 | 446 | break; 447 | case 17: // Lobby - Lost Connection - just click okay, since we're toast anyway 448 | delay(1000); 449 | ControlAction.click(6, 351, 337, 96, 32); 450 | break; 451 | case 19: // Login - Cdkey In Use 452 | D2Bot.printToConsole(gameInfo.mpq + " is in use by " + ControlAction.getText(4, 158, 310, 485, 40), 6); 453 | D2Bot.CDKeyInUse(); 454 | 455 | if (gameInfo.switchKeys) { 456 | ControlAction.timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay * 1000); 457 | D2Bot.restart(true); 458 | } else { 459 | ControlAction.click(6, 335, 450, 128, 35); 460 | ControlAction.timeoutDelay("CD-Key in use", StarterConfig.CDKeyInUseDelay * 6e4); 461 | } 462 | 463 | break; 464 | case 20: // Single Player - Select Difficulty 465 | break; 466 | case 21: // Main Menu - Connecting 467 | if (!locationTimeout(StarterConfig.ConnectingTimeout * 1e3, location)) { 468 | ControlAction.click(6, 330, 416, 128, 35); 469 | } 470 | 471 | break; 472 | case 22: // Login - Invalid Cdkey (classic or xpac) 473 | text = ControlAction.getText(4, 162, 270, 477, 50); 474 | string = ""; 475 | 476 | if (text) { 477 | for (i = 0; i < text.length; i += 1) { 478 | string += text[i]; 479 | 480 | if (i !== text.length - 1) { 481 | string += " "; 482 | } 483 | } 484 | } 485 | 486 | switch (string) { 487 | case getLocaleString(10914): 488 | D2Bot.printToConsole(gameInfo.mpq + " LoD key in use by " + ControlAction.getText(4, 158, 310, 485, 40), 6); 489 | D2Bot.CDKeyInUse(); 490 | 491 | if (gameInfo.switchKeys) { 492 | ControlAction.timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay * 1000); 493 | D2Bot.restart(true); 494 | } else { 495 | ControlAction.click(6, 335, 450, 128, 35); 496 | ControlAction.timeoutDelay("LoD key in use", StarterConfig.CDKeyInUseDelay * 6e4); 497 | } 498 | 499 | break; 500 | default: 501 | if (gameInfo.switchKeys) { 502 | D2Bot.printToConsole("Invalid CD-Key"); 503 | ControlAction.timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay * 1000); 504 | D2Bot.restart(true); 505 | } else { 506 | ControlAction.click(6, 335, 450, 128, 35); 507 | ControlAction.timeoutDelay("Invalid CD-Key", StarterConfig.CDKeyInUseDelay * 6e4); 508 | } 509 | 510 | break; 511 | } 512 | 513 | break; 514 | case 23: // Character Select - Connecting 515 | if (!locationTimeout(StarterConfig.ConnectingTimeout * 1e3, location)) { 516 | ControlAction.click(6, 33, 572, 128, 35); 517 | } 518 | 519 | break; 520 | case 24: // Server Down - not much to do but wait.. 521 | break; 522 | case 25: // Lobby - Please Wait 523 | if (!locationTimeout(StarterConfig.PleaseWaitTimeout * 1e3, location)) { 524 | ControlAction.click(6, 351, 337, 96, 32); 525 | } 526 | 527 | break; 528 | case 26: // Lobby - Game Name Exists 529 | ControlAction.click(6, 533, 469, 120, 20); 530 | 531 | break; 532 | case 27: // Gateway Select 533 | ControlAction.click(6, 436, 538, 96, 32); 534 | 535 | break; 536 | case 28: // Lobby - Game Does Not Exist 537 | ControlAction.click(6, 533, 469, 120, 20); 538 | 539 | break; 540 | case 38: // Game is full 541 | D2Bot.printToConsole("Game is full"); 542 | 543 | break; 544 | case 42: // Empty character screen 545 | // TODO: see if this is needed in case 12 too 546 | string = ""; 547 | text = ControlAction.getText(4, 45, 318, 531, 140); 548 | 549 | if (text) { 550 | for (i = 0; i < text.length; i += 1) { 551 | string += text[i]; 552 | 553 | if (i !== text.length - 1) { 554 | string += " "; 555 | } 556 | } 557 | 558 | if (string === getLocaleString(11161)) { // CDKey disabled from realm play 559 | D2Bot.updateStatus("Realm Disabled CDKey"); 560 | D2Bot.printToConsole("Realm Disabled CDKey: " + gameInfo.mpq, 6); 561 | D2Bot.CDKeyDisabled(); 562 | 563 | if (gameInfo.switchKeys) { 564 | ControlAction.timeoutDelay("Key switch delay", StarterConfig.SwitchKeyDelay * 1000); 565 | D2Bot.restart(true); 566 | } else { 567 | D2Bot.stop(me.profile, true); 568 | } 569 | } 570 | } 571 | 572 | if (!locationTimeout(5000, location)) { 573 | accounts.shift(); // remove current account from the list 574 | chars.shift(); 575 | 576 | ControlAction.click(6, 33, 572, 128, 35); 577 | } 578 | 579 | break; 580 | default: 581 | if (location !== undefined) { 582 | D2Bot.printToConsole("Unhandled location " + location); 583 | delay(500); 584 | D2Bot.restart(); 585 | } 586 | 587 | break; 588 | } 589 | } 590 | -------------------------------------------------------------------------------- /kolbot/custom-scripts/Manual.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @filename Manual.js 3 | * @author laz 4 | * @desc manual play script with some extra tools 5 | * @credits dzik for his hookHandler, securitycat, kolton libs 6 | */ 7 | 8 | function Manual () { 9 | var activeAction, end, block, wp, resfix, lifehook, watch, 10 | i, unit, title, dummy, keydown, currentlife, currentmana, 11 | classes = ["Amazon", "Sorceress", "Necromancer", "Paladin", "Barbarian", "Druid", "Assassin"], 12 | flags = [0x1, 0x2, 0x3, 0x4, 0x5, 0xf, 0x18, 0x19, 0xc, 0x9], 13 | resolution = me.screensize, 14 | info = new UnitInfo(), 15 | channel = "#d2bs", // default 16 | hide = false, 17 | list = true, 18 | chat = 0, 19 | hooks = [], 20 | decor = [], 21 | box = [], 22 | life = [], 23 | mana = [], 24 | watchSent = [], 25 | watchRecv = [], 26 | blockSent = [], 27 | blockRecv = []; 28 | 29 | // Received packet handler 30 | let PacketReceived = function(pBytes) { 31 | let ID = pBytes[0].toString(16); 32 | 33 | if (blockRecv.indexOf(ID) > -1) { //Block received packets from list 34 | return true; 35 | } 36 | 37 | if (watchRecv.indexOf(ID) > -1) { 38 | let size = pBytes.length; 39 | let array = [].slice.call(pBytes); 40 | array.shift(); 41 | print("ÿc2S ÿc8" + ID + "ÿc0 " + array.join(" ") + " ÿc5(" + size + " Bytes)"); 42 | } 43 | 44 | return false; 45 | }; 46 | 47 | // Sent packet handler 48 | let PacketSent = function(pBytes) { 49 | let ID = pBytes[0].toString(16); 50 | 51 | if (ID == "15") { //Block all commands or irc chat from being sent to server 52 | if (pBytes[3] == 46 || chat == 1) { 53 | let str = ""; 54 | 55 | for (let b = 3; b < pBytes.length - 3; b++) { 56 | str += String.fromCharCode(pBytes[b]); 57 | } 58 | 59 | if (pBytes[3] == 46) { 60 | runCommand(str); 61 | return true; 62 | } 63 | 64 | if (chat == 1 && str[0] !== "/") { 65 | print("ÿc4" + me.name + "ÿc0: " + str); 66 | D2Bot.postToIRC("IRC", channel, str); 67 | return true; 68 | } 69 | } 70 | } 71 | 72 | if (blockSent.indexOf(ID) > -1) { //Block sent packets from list 73 | return true; 74 | } 75 | 76 | if (watchSent.indexOf(ID) > -1) { 77 | let size = pBytes.length; 78 | let array = [].slice.call(pBytes); 79 | array.shift(); 80 | print("ÿc2C ÿc8" + ID + "ÿc0 " + array.join(" ") + " ÿc5(" + size + " Bytes)"); 81 | } 82 | 83 | return false; 84 | }; 85 | 86 | // IRC > ingame chat 87 | let ircHandler = function(mode, msg) { 88 | if (mode == 0x411) { 89 | let message = JSON.parse(msg); 90 | print("ÿc4" + message.Nick + "ÿc0: " + message.Message); 91 | } 92 | }; 93 | 94 | //Run commands from chat 95 | function runCommand(msg) { 96 | if (msg.length <= 1) return true; 97 | 98 | let cmd = msg.split(" ")[0].split(".")[1]; 99 | let msgList = msg.split(" "); 100 | 101 | switch (cmd.toLowerCase()) { 102 | case "send": 103 | case "recv": 104 | if (msgList.length < 2) { 105 | print("ÿc1Missing arguments"); 106 | break; 107 | } 108 | 109 | let args = []; 110 | msgList.shift(); 111 | 112 | for (let b = 0; b < msgList.length; b++) { 113 | args[b * 2] = 1; 114 | args[b * 2 + 1] = parseInt(msgList[b]); 115 | } 116 | 117 | args[1] = parseInt("0x" + msgList[0], 16); 118 | 119 | if (cmd.toLowerCase() == "send") { 120 | eval("sendPacket(" + args.join(", ") + ")"); 121 | } else { 122 | eval("getPacket(" + args.join(", ") + ")"); 123 | } 124 | 125 | break; 126 | 127 | case "watch": 128 | if (msgList.length < 3) { 129 | print("ÿc1Missing arguments"); 130 | break; 131 | } 132 | 133 | switch (msgList[1].toLowerCase()) { 134 | case "sent": 135 | if (msgList[2] == "list") { 136 | print("Watching sent packets : ÿc8" + watchSent.join(", ")); 137 | break; 138 | } 139 | 140 | watchSent.push(msgList[2]); 141 | print("Added ÿc80x" + msgList[2] + "ÿc0 (sent) to watch list"); 142 | break; 143 | 144 | case "recv": 145 | if (msgList[2] == "list") { 146 | print("Watching received packets : ÿc8" + watchRecv.join(", ")); 147 | break; 148 | } 149 | 150 | watchRecv.push(msgList[2]); 151 | print("Added ÿc80x" + msgList[2] + "ÿc0 (recv) to watch list"); 152 | break; 153 | 154 | default: 155 | print("ÿc1Invalid argument : " + msgList[1]); 156 | break; 157 | } 158 | 159 | break; 160 | 161 | case "!watch": 162 | if (msgList.length < 3) { 163 | print("ÿc1Missing arguments"); 164 | break; 165 | } 166 | 167 | switch (msgList[1].toLowerCase()) { 168 | case "sent": 169 | if (watchSent.indexOf(msgList[2]) > -1) watchSent.splice(watchSent.indexOf(msgList[2]), 1); 170 | print("Removed packet ÿc80x" + msgList[2] + "ÿc0 (sent) from watch list"); 171 | break; 172 | 173 | case "recv": 174 | if (watchRecv.indexOf(msgList[2]) > -1) watchRecv.splice(watchRecv.indexOf(msgList[2]), 1); 175 | print("Removed packet ÿc80x" + msgList[2] + "ÿc0 (recv) from watch list"); 176 | break; 177 | 178 | default: 179 | print("ÿc1Invalid argument : " + msgList[1]); 180 | break; 181 | } 182 | 183 | break; 184 | 185 | case "block": 186 | if (msgList.length < 3) { 187 | print("ÿc1Missing arguments"); 188 | break; 189 | } 190 | 191 | switch (msgList[1].toLowerCase()) { 192 | case "sent": 193 | if (msgList[2] == "list") { 194 | print("Blocking sent packets : ÿc8" + blockSent.join(", ")); 195 | break; 196 | } 197 | 198 | blockSent.push(msgList[2]); 199 | print("Added ÿc80x" + msgList[2] + "ÿc0 (sent) to block list"); 200 | break; 201 | 202 | case "recv": 203 | if (msgList[2] == "list") { 204 | print("Blocking received packets : ÿc8" + blockRecv.join(", ")); 205 | break; 206 | } 207 | 208 | blockRecv.push(msgList[2]); 209 | print("Added ÿc80x" + msgList[2] + "ÿc0 (recv) to block list"); 210 | break; 211 | 212 | default: 213 | print("ÿc1Invalid argument : " + msgList[1]); 214 | break; 215 | } 216 | 217 | break; 218 | 219 | case "!block": 220 | if (msgList.length < 3) { 221 | print("ÿc1Missing arguments"); 222 | break; 223 | } 224 | 225 | switch (msgList[1].toLowerCase()) { 226 | case "sent": 227 | if (blockSent.indexOf(msgList[2]) > -1) blockSent.splice(blockSent.indexOf(msgList[2]), 1); 228 | print("Removed packet ÿc80x" + msgList[2] + "ÿc0 (sent) from block list"); 229 | break; 230 | 231 | case "recv": 232 | if (blockRecv.indexOf(msgList[2]) > -1) blockRecv.splice(blockRecv.indexOf(msgList[2]), 1); 233 | print("Removed packet ÿc80x" + msgList[2] + "ÿc0 (recv) from block list"); 234 | break; 235 | 236 | default: 237 | print("ÿc1Invalid argument : " + msgList[1]); 238 | break; 239 | } 240 | 241 | break; 242 | 243 | case "reload": 244 | reload(); 245 | break; 246 | 247 | case "chat": 248 | if (msgList.length < 2) { 249 | print("ÿc1Missing arguments"); 250 | break; 251 | } 252 | 253 | switch (msgList[1].toLowerCase()) { 254 | case "game": 255 | case "0": 256 | print("Chat mode set to : ÿc8in-game"); 257 | chat = 0; 258 | break; 259 | 260 | case "irc": 261 | case "1": 262 | print("Chat mode set to : ÿc8irc"); 263 | chat = 1; 264 | break; 265 | 266 | default: 267 | print("ÿc1Invalid chat mode : " + msgList[1]); 268 | break; 269 | } 270 | 271 | break; 272 | 273 | case "msg": 274 | if (msgList.length < 3) { 275 | print("ÿc1Missing arguments"); 276 | break; 277 | } 278 | 279 | D2Bot.postToIRC("IRC", msgList[1], msg.split(".msg " + msgList[1] + " ")[1]); 280 | print("ÿc2to " + msgList[1] + "ÿc0: " + msg.split(".msg " + msgList[1] + " ")[1]); 281 | break; 282 | 283 | case "channel": 284 | if (msgList.length < 2) { 285 | print("ÿc1Missing arguments"); 286 | break; 287 | } 288 | 289 | if (msgList[1][0] !== "#") { 290 | print("ÿc1Invalid channel : " + msgList[1]); 291 | break; 292 | } 293 | 294 | channel = msgList[1]; 295 | print("Set channel to : ÿc8" + msgList[1]); 296 | break; 297 | 298 | case "commands": 299 | case "help": 300 | print("Help -------------------------------------------------------------"); 301 | 302 | print(".watch sent id ÿc5Adds a sent packet to watch list"); 303 | print(".watch recv id ÿc5Adds a received packet to watch list"); 304 | 305 | print(".!watch sent id ÿc5Removes a sent packet from watch list"); 306 | print(".!watch recv id ÿc5Removes a received packet from watch list"); 307 | 308 | print(".watch sent list ÿc5Lists all packets from sent watch list"); 309 | print(".watch recv list ÿc5Lists all packets from received watch list"); 310 | 311 | print(".block sent id ÿc5Adds a sent packet to block list"); 312 | print(".block recv id ÿc5Adds a received packet to block list"); 313 | 314 | print(".!block sent id ÿc5Removes a sent packet from block list"); 315 | print(".!block recv id ÿc5Removes a received packet from block list"); 316 | 317 | print(".block sent list ÿc5Lists all packets from sent block list"); 318 | print(".block recv list ÿc5Lists all packets from received block list"); 319 | 320 | print(".send id bytes ÿc5Sends a packet, example .send 13 2 0 0 0 17 0 0 0"); 321 | print(".recv id bytes ÿc5Receive a packet, example .recv 77 16"); 322 | 323 | print(".chat mode ÿc5Sets chat mode. 0 = game, 1 = irc"); 324 | print(".channel #name ÿc5Sets irc channel name. Default = #d2bs"); 325 | print(".msg nick msg ÿc5Whisper a specific user on irc"); 326 | print(".reload ÿc5Reloads in-game script"); 327 | 328 | //print("--------------------------------------------------------------------") 329 | break; 330 | 331 | default: 332 | print("ÿc1Invalid command : " + cmd); 333 | break; 334 | } 335 | 336 | return true; 337 | } 338 | 339 | function UpdateLife() { 340 | if (!box.length) { // Add boxes and frames for life and mana 341 | box.push(new Box (71, 541, 34, 16, 0, 100, 2)); 342 | box.push(new Box (732, 541, 34, 16, 0, 100, 2)); 343 | box.push(new Frame (70, 541, 34, 16, 2)); 344 | box.push(new Frame (731, 541, 34, 16, 2)); 345 | box[0].zorder = 0; 346 | box[1].zorder = 0; 347 | } 348 | 349 | currentlife = (Math.round((me.hp * 100) / me.hpmax)).toString(); 350 | currentmana = (Math.round((me.mp * 100) / me.mpmax)).toString(); 351 | 352 | if (!life.length) { 353 | life.push(new Text(currentlife, 71, 555, 0, 1, 2)); 354 | } 355 | 356 | if (life[0].text !== currentlife) { 357 | life[0].remove(); 358 | life.shift(); 359 | life.push(new Text(currentlife, 71, 555, 0, 1, 2)); 360 | } 361 | 362 | if (!mana.length) { 363 | mana.push(new Text(currentmana, 732, 555, 0, 1, 2)); 364 | } 365 | 366 | if (mana[0].text !== currentmana) { 367 | mana[0].remove(); 368 | mana.shift(); 369 | mana.push(new Text(currentmana, 732, 555, 0, 1, 2)); 370 | } 371 | } 372 | 373 | function UnitInfo() { 374 | this.x = 684; 375 | this.y = 157; 376 | this.hooks = []; 377 | this.cleared = true; 378 | 379 | this.createInfo = function (unit) { 380 | if (typeof unit === "undefined") { 381 | this.remove(); 382 | 383 | return; 384 | } 385 | 386 | switch (unit.type) { 387 | case 0: 388 | this.playerInfo(unit); 389 | 390 | break; 391 | case 1: 392 | this.monsterInfo(unit); 393 | 394 | break; 395 | case 4: 396 | this.itemInfo(unit); 397 | 398 | break; 399 | } 400 | }; 401 | 402 | this.playerInfo = function (unit) { 403 | let i, items, string, 404 | frameXsize = 20, 405 | frameYsize = 20, 406 | quality = ["ÿc0", "ÿc0", "ÿc0", "ÿc0", "ÿc3", "ÿc2", "ÿc9", "ÿc4", "ÿc8"]; 407 | 408 | if (!this.currentGid) { 409 | this.currentGid = unit.gid; 410 | } 411 | 412 | if (this.currentGid === unit.gid && !this.cleared) { 413 | return; 414 | } 415 | 416 | if (this.currentGid !== unit.gid) { 417 | this.remove(); 418 | this.currentGid = unit.gid; 419 | } 420 | 421 | this.hooks.push(new Text("ÿc0" + unit.name + " (" + unit.charlvl + " " + classes[unit.classid] + ")", this.x, this.y, 4, 13, 2)); 422 | 423 | items = unit.getItems(); 424 | 425 | if (items) { 426 | this.hooks.push(new Text("Equipped items:", this.x, this.y + 15, 4, 13, 2)); 427 | frameYsize += 15; 428 | 429 | for (i = 0; i < items.length; i += 1) { 430 | if (items[i].getFlag(0x4000000)) { 431 | string = items[i].fname.split("\n")[1] + "ÿc0 " + items[i].fname.split("\n")[0]; 432 | } else { 433 | string = quality[items[i].quality] + (items[i].quality > 4 && items[i].getFlag(0x10) ? items[i].fname.split("\n").reverse()[0].replace("ÿc4", "") : items[i].name); 434 | } 435 | 436 | this.hooks.push(new Text(string, this.x, this.y + (i + 2) * 15, 0, 13, 2)); 437 | 438 | if (string.length > frameXsize) { 439 | frameXsize = string.length; 440 | } 441 | 442 | frameYsize += 15; 443 | } 444 | } 445 | 446 | frameXsize = 30; // always same size, delete if needed 447 | 448 | frameYsize += 145; 449 | 450 | this.hooks.push(new Text("Fire Resist: ÿc1" + (unit.getStat(39) - 30) + " / " + (unit.getStat(40) + 75), this.x, this.y + (i + 2) * 15 + 10, 4, 13, 2)); 451 | this.hooks.push(new Text("Cold Resist: ÿc3" + (unit.getStat(43) - 30) + " / " + (unit.getStat(44) + 75), this.x, this.y + (i + 2) * 15 + 25, 4, 13, 2)); 452 | this.hooks.push(new Text("Light Resist: ÿc9" + (unit.getStat(41) - 30) + " / " + (unit.getStat(42) + 75), this.x, this.y + (i + 2) * 15 + 40, 4, 13, 2)); 453 | this.hooks.push(new Text("Poison Resist: ÿc2" + (unit.getStat(45) - 30) + " / " + (unit.getStat(46) + 75), this.x, this.y + (i + 2) * 15 + 55, 4, 13, 2)); 454 | this.hooks.push(new Text("Physical resist: ÿc0" + unit.getStat(36), this.x, this.y + (i + 2) * 15 + 70, 4, 13, 2)); 455 | 456 | //Sorb 457 | this.hooks.push(new Text("Fire Absorb: ÿc1" + unit.getStat(142), this.x, this.y + (i + 2) * 15 + 85, 4, 13, 2)); 458 | this.hooks.push(new Text("Cold Absorb: ÿc3" + unit.getStat(148), this.x, this.y + (i + 2) * 15 + 100, 4, 13, 2)); 459 | this.hooks.push(new Text("Light Absorb: ÿc9" + unit.getStat(144), this.x, this.y + (i + 2) * 15 + 115, 4, 13, 2)); 460 | 461 | this.hooks.push(new Text("Faster Cast Rate: ÿc0" + unit.getStat(105), this.x, this.y + (i + 2) * 15 + 130, 4, 13, 2)); 462 | 463 | this.cleared = false; 464 | 465 | this.hooks.push(new Box(this.x + 2, this.y - 15, Math.round(frameXsize * 7.5) - 4, frameYsize, 0x0, 1, 2)); 466 | this.hooks.push(new Frame(this.x, this.y - 15, Math.round(frameXsize * 7.5), frameYsize, 2)); 467 | 468 | this.hooks[this.hooks.length - 2].zorder = 0; 469 | }; 470 | 471 | this.monsterInfo = function (unit) { 472 | let frameYsize = 125; 473 | 474 | if (!this.currentGid) { 475 | this.currentGid = unit.gid; 476 | } 477 | 478 | if (this.currentGid === unit.gid && !this.cleared) { 479 | return; 480 | } 481 | 482 | if (this.currentGid !== unit.gid) { 483 | this.remove(); 484 | this.currentGid = unit.gid; 485 | } 486 | 487 | this.hooks.push(new Text("Classid: ÿc0" + unit.classid, this.x, this.y, 4, 13, 2)); 488 | this.hooks.push(new Text("HP percent: ÿc0" + Math.round(unit.hp * 100 / 128), this.x, this.y + 15, 4, 13, 2)); 489 | this.hooks.push(new Text("Fire resist: ÿc1" + unit.getStat(39), this.x, this.y + 30, 4, 13, 2)); 490 | this.hooks.push(new Text("Cold resist: ÿc3" + unit.getStat(43), this.x, this.y + 45, 4, 13, 2)); 491 | this.hooks.push(new Text("Lightning resist: ÿc9" + unit.getStat(41), this.x, this.y + 60, 4, 13, 2)); 492 | this.hooks.push(new Text("Poison resist: ÿc2" + unit.getStat(45), this.x, this.y + 75, 4, 13, 2)); 493 | this.hooks.push(new Text("Physical resist: ÿc0" + unit.getStat(36), this.x, this.y + 90, 4, 13, 2)); 494 | this.hooks.push(new Text("Magic resist: ÿc0" + unit.getStat(37), this.x, this.y + 105, 4, 13, 2)); 495 | 496 | this.cleared = false; 497 | 498 | this.hooks.push(new Box(this.x + 2, this.y - 15, 136 + 85, frameYsize, 0x0, 1, 2)); 499 | this.hooks.push(new Frame(this.x, this.y - 15, 140 + 85, frameYsize, 2)); 500 | 501 | this.hooks[this.hooks.length - 2].zorder = 0; 502 | }; 503 | 504 | this.itemInfo = function (unit) { 505 | let i = 0, 506 | frameYsize = 50; 507 | 508 | if (!this.currentGid) { 509 | this.currentGid = unit.gid; 510 | } 511 | 512 | if (this.currentGid === unit.gid && !this.cleared) { 513 | return; 514 | } 515 | 516 | if (this.currentGid !== unit.gid) { 517 | this.remove(); 518 | this.currentGid = unit.gid; 519 | } 520 | 521 | this.hooks.push(new Text("Classid: ÿc0" + unit.classid, this.x, this.y, 4, 13, 2)); 522 | this.hooks.push(new Text("Code: ÿc0" + unit.code, this.x, this.y + 15, 4, 13, 2)); 523 | this.hooks.push(new Text("Item level: ÿc0" + unit.ilvl, this.x, this.y + 30, 4, 13, 2)); 524 | 525 | this.cleared = false; 526 | this.socketedItems = unit.getItems(); 527 | 528 | if (this.socketedItems[0]) { 529 | this.hooks.push(new Text("Socketed with:", this.x, this.y + 45, 4, 13, 2)); 530 | frameYsize += 15; 531 | 532 | for (i = 0; i < this.socketedItems.length; i += 1) { 533 | this.hooks.push(new Text(this.socketedItems[i].fname.split("\n").reverse().join(" "), this.x, this.y + (i + 4) * 15, 0, 13, 2)); 534 | 535 | frameYsize += 15; 536 | } 537 | } 538 | 539 | // Get prefix and suffix from identified magic items 540 | if (unit.quality === 4 && unit.getFlag(0x10)) { 541 | this.hooks.push(new Text("Prefix: ÿc0" + unit.prefixnum, this.x, this.y + frameYsize - 5, 4, 13, 2)); 542 | this.hooks.push(new Text("Suffix: ÿc0" + unit.suffixnum, this.x, this.y + frameYsize + 10, 4, 13, 2)); 543 | 544 | frameYsize += 30; 545 | } 546 | 547 | // Get prefixes and suffixes from rare items 548 | if (unit.quality === 6) { 549 | let prefixes = unit.prefixes; 550 | var n = 0; 551 | while (n < prefixes.length) { 552 | this.hooks.push(new Text("Prefix: ÿc0" + prefixes[n], this.x, this.y + frameYsize - 5, 4, 13, 2)); 553 | frameYsize += 15; 554 | n += 1; 555 | } 556 | 557 | let suffixes = unit.suffixes; 558 | var n = 0; 559 | while (n < suffixes.length) { 560 | this.hooks.push(new Text("Suffix: ÿc0" + suffixes[n], this.x, this.y + frameYsize - 5, 4, 13, 2)); 561 | frameYsize += 15; 562 | n += 1; 563 | } 564 | //this.hooks.push(new Text("Suffix: ÿc0" + unit.suffixes, this.x, this.y + frameYsize + 10, 4, 13, 2)); 565 | } 566 | 567 | this.hooks.push(new Box(this.x + 2, this.y - 15, 116 + 105, frameYsize, 0x0, 1, 2)); 568 | this.hooks.push(new Frame(this.x, this.y - 15, 120 + 105, frameYsize, 2)); 569 | 570 | this.hooks[this.hooks.length - 2].zorder = 0; 571 | }; 572 | 573 | this.remove = function () { 574 | while (this.hooks.length > 0) { 575 | this.hooks.shift().remove(); 576 | } 577 | 578 | this.cleared = true; 579 | }; 580 | } 581 | 582 | // Sort items by size to pick biggest first 583 | function sortPickList(a, b) { 584 | 585 | // Same size - sort by distance 586 | if (b.sizex === a.sizex && b.sizey === a.sizey) { 587 | return getDistance(me, a) - getDistance(me, b); 588 | 589 | } 590 | return b.sizex * b.sizey - a.sizex * a.sizey; 591 | } 592 | 593 | // Sort items by size to move biggest first 594 | function sortMoveList(a, b) { 595 | return b.sizex * b.sizey - a.sizex * a.sizey; 596 | } 597 | 598 | function hookHandler (click, x, y) { 599 | // Get the hook closest to the clicked location 600 | function sortHooks(h1, h2) { 601 | return Math.abs(h1.y - y) - Math.abs(h2.y - y); 602 | } 603 | 604 | // Left click 605 | if (click === 0) { 606 | // Sort hooks 607 | hooks.sort(sortHooks); 608 | 609 | // Don't start new action until the current one finishes 610 | if (activeAction && activeAction !== hooks[0].text) { 611 | return true; 612 | } 613 | 614 | // Toggle current action on/off 615 | activeAction = activeAction ? false : hooks[0].text; 616 | 617 | hooks[0].color = hooks[0].color === 4 ? 1 : 4; 618 | 619 | // Block click 620 | return true; 621 | } 622 | 623 | return false; 624 | } 625 | 626 | function showHooks () { 627 | 628 | resfix = me.screensize ? 0 : -120; 629 | 630 | if (hooks.length) { 631 | if (resolution != me.screensize || hide) { 632 | resolution = me.screensize; 633 | 634 | while (hooks.length) { 635 | var kill = hooks.shift(); 636 | kill.remove(); 637 | } 638 | 639 | while (decor.length) { 640 | var kill = decor.shift(); 641 | kill.remove(); 642 | } 643 | 644 | list = !list; 645 | 646 | } else { 647 | return false; 648 | } 649 | } 650 | 651 | if (list) { 652 | var commands = [ 653 | "Show", 654 | ]; 655 | } else { 656 | var commands = [ 657 | "Toggle info", 658 | "Drop from inventory", 659 | "Drop from stash", 660 | //"Drop from cube", 661 | "Drop gold", 662 | "Pick to inventory", 663 | //"Move inv to trade", 664 | "Move inv to stash", 665 | "Log char", 666 | "End", 667 | "Hide", 668 | ]; 669 | } 670 | 671 | for (let i = commands.length; i; i--) { 672 | addHook (commands[i - 1]); 673 | } 674 | 675 | hide = false; 676 | 677 | return true; 678 | 679 | } 680 | 681 | function addHook (text) { 682 | //decor.push (new Frame (6, 466 - hooks.length * 19 + resfix + 7, 160, 16)); 683 | 684 | if (text === "Show" || text === "Hide") { 685 | hooks.push (new Text (text, 5, 480 - hooks.length * 16 + resfix + 116, 2, 1, 0, false, hookHandler)); 686 | decor.push (new Box (1, 466 - hooks.length * 16 + resfix + 116, 50, 16)); 687 | } else { 688 | hooks.push (new Text (text, 9, 480 - hooks.length * 16 + resfix + 23, 4, 1, 0, false, hookHandler)); 689 | } 690 | } 691 | 692 | addEventListener("gamepacketsent", PacketSent); 693 | addEventListener("gamepacket", PacketReceived); 694 | //addEventListener("copydata", ircHandler); 695 | load("tools/mapthread.js"); 696 | //D2Bot.ircEvent(true); 697 | 698 | while (true) { 699 | 700 | if (keydown) { 701 | unit = getUnit(101); 702 | info.createInfo(unit); 703 | delay(20); 704 | } 705 | 706 | UpdateLife(); 707 | if (end) break; 708 | 709 | switch (activeAction) { 710 | case "Toggle info": 711 | 712 | if (!keydown) { 713 | me.overhead(" Unit info ÿc2ON"); 714 | keydown = true; 715 | } else { 716 | me.overhead(" Unit info ÿc1OFF"); 717 | keydown = false; 718 | } 719 | 720 | activeAction = false; 721 | break; 722 | 723 | case "Log char": 724 | include("MuleLogger.js"); 725 | MuleLogger.logChar(); 726 | 727 | activeAction = false; 728 | break; 729 | 730 | case "Drop from inventory": 731 | if (!me.inTown || !Town.openStash()) { 732 | me.overhead("Failed to open stash"); 733 | 734 | activeAction = false; 735 | 736 | break; 737 | } 738 | 739 | var items = me.findItems(-1, 0, 3); 740 | 741 | if (items) { 742 | while (activeAction && items.length > 0) { 743 | let item = items.shift(); 744 | item.drop(); 745 | } 746 | } 747 | 748 | me.cancel(); 749 | 750 | activeAction = false; 751 | break; 752 | 753 | case "Drop from stash": 754 | case "Drop from cube": 755 | if (!me.inTown || !Town.openStash()) { 756 | me.overhead("Failed to open stash"); 757 | 758 | activeAction = false; 759 | 760 | break; 761 | } 762 | 763 | items = me.findItems(-1, 0, activeAction === "Drop from stash" ? 7 : 6); 764 | 765 | if (items) { 766 | while (activeAction && items.length > 0) { 767 | var item = items.shift(); 768 | 769 | if (item.classid !== 549) { // Don't drop the cube 770 | item.drop(); 771 | } 772 | } 773 | } 774 | 775 | me.cancel(); 776 | 777 | activeAction = false; 778 | break; 779 | 780 | case "Drop gold": 781 | if (!me.inTown || !Town.openStash()) { 782 | me.overhead("Failed to open stash"); 783 | 784 | activeAction = false; 785 | break; 786 | } 787 | 788 | while (me.gold && activeAction) { 789 | print(me.gold); 790 | if (me.getStat (15) > 0 && me.getStat (14) < me.getStat (12) * 10000) { 791 | let stashg = me.getStat (15) == 0 ? 0 : me.getStat (15); 792 | let invg = me.getStat (14) == 0 ? 0 : me.getStat (14); 793 | let missing = me.getStat (12) * 10000 - me.getStat(14); 794 | 795 | let difference = Math.min(stashg, missing); 796 | 797 | gold (difference, 4); 798 | 799 | while (invg === me.getStat(14)) { 800 | delay (100); 801 | } 802 | } 803 | 804 | let invg = me.getStat (14); 805 | 806 | gold (invg); 807 | 808 | while (invg === me.getStat(14)) { 809 | delay (100); 810 | } 811 | } 812 | 813 | me.cancel(); 814 | 815 | activeAction = false; 816 | break; 817 | 818 | case "Pick to inventory": 819 | item = getUnit(4, -1, 3); 820 | items = []; 821 | var cancelFlags = [0x01, 0x02, 0x04, 0x08, 0x14, 0x16, 0x0c, 0x0f, 0x19, 0x1a]; 822 | 823 | for (var i = 0; i < cancelFlags.length; i++) { 824 | if (getUIFlag (cancelFlags[i])) { 825 | me.cancel(); 826 | } 827 | } 828 | 829 | if (item) { 830 | do { 831 | items.push (copyUnit (item)); 832 | } while (item.getNext ()); 833 | } 834 | 835 | while (activeAction && items.length > 0) { 836 | items.sort (sortPickList); 837 | 838 | item = items.shift (); 839 | 840 | if (Town.ignoredItemTypes.indexOf (item.itemType) === -1 && Storage.Inventory.CanFit (item)) { 841 | Pickit.pickItem (item); 842 | } 843 | } 844 | 845 | activeAction = false; 846 | break; 847 | 848 | case "Move inv to trade": 849 | var inv = me.findItems (-1, 0, 3); 850 | inv.sort(sortMoveList); 851 | 852 | while (activeAction && inv.length) { 853 | var that = inv.shift(); 854 | 855 | if (getUIFlag(0x17) && Storage.TradeScreen.CanFit(that)) { 856 | Storage.TradeScreen.MoveTo(that); 857 | } 858 | } 859 | 860 | activeAction = false; 861 | break; 862 | 863 | case "Move inv to stash": 864 | var inv = me.findItems (-1, 0, 3); 865 | inv.sort(sortMoveList); 866 | 867 | while (activeAction && inv.length) { 868 | var that = inv.shift(); 869 | 870 | if (Storage.Stash.CanFit(that)) { 871 | Storage.Stash.MoveTo(that); 872 | } 873 | } 874 | 875 | activeAction = false; 876 | break; 877 | 878 | case "End": 879 | end = true; 880 | 881 | D2Bot.stop(me.profile, true); 882 | activeAction = false; 883 | break; 884 | 885 | case "Hide": 886 | case "Show": 887 | hide = true; 888 | 889 | activeAction = false; 890 | break; 891 | 892 | default: 893 | showHooks (); 894 | 895 | for (var i = 0; i < hooks.length; i++) { 896 | if (hooks[i].color === 1) { 897 | hooks[i].color = 4; 898 | } 899 | } 900 | 901 | break; 902 | } 903 | delay (10); 904 | } 905 | 906 | return true; 907 | } 908 | -------------------------------------------------------------------------------- /kolbot/custom-scripts/Party.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @filename Party.js 3 | * @author kolton 4 | * @desc handle party procedure ingame 5 | * 6 | * updated 2020: define MyOwnParty + loot hardcore player corpses (https://github.com/blizzhackers/documentation/blob/master/kolbot/MiscellaneousOptions.md/#how-to-define-your-own-party-and-permit-hardcore-loot-corpses) 7 | */ 8 | 9 | function main() { 10 | include("OOG.js"); 11 | include("json2.js"); 12 | include("common/Config.js"); 13 | include("common/Cubing.js"); 14 | include("common/Runewords.js"); 15 | include("common/Misc.js"); 16 | include("common/Util.js"); 17 | include("common/Prototypes.js"); 18 | include("common/Town.js"); 19 | 20 | Config.init(); 21 | 22 | var i, myPartyId, player, otherParty, shitList, currScript, scriptList, 23 | classes = ["Amazon", "Sorceress", "Necromancer", "Paladin", "Barbarian", "Druid", "Assassin"], 24 | playerLevels = {}, 25 | partyTick = getTickCount(), 26 | loot = []; 27 | 28 | addEventListener("gameevent", 29 | function (mode, param1, param2, name1, name2) { 30 | let player; 31 | 32 | switch (mode) { 33 | case 0x02: // "%Name1(%Name2) joined our world. Diablo's minions grow stronger." 34 | if (Config.Greetings.length > 0) { 35 | try { 36 | player = getParty(name1); 37 | } catch (e1) { 38 | 39 | } 40 | 41 | if (player && player.name !== me.name) { 42 | say(Config.Greetings[rand(0, Config.Greetings.length - 1)].replace("$name", player.name).replace("$level", player.level).replace("$class", classes[player.classid])); 43 | } 44 | } 45 | 46 | break; 47 | case 0x06: // "%Name1 was Slain by %Name2" 48 | if (Config.DeathMessages.length > 0) { 49 | try { 50 | player = getParty(name1); 51 | } catch (e2) { 52 | 53 | } 54 | 55 | if (player && player.name !== me.name) { 56 | say(Config.DeathMessages[rand(0, Config.DeathMessages.length - 1)].replace("$name", player.name).replace("$level", player.level).replace("$class", classes[player.classid]).replace("$killer", name2)); 57 | } 58 | } 59 | 60 | break; 61 | case 0x00: // "%Name1(%Name2) dropped due to time out." 62 | case 0x01: // "%Name1(%Name2) dropped due to errors." 63 | case 0x03: // "%Name1(%Name2) left our world. Diablo's minions weaken." 64 | if (me.playertype == 1 && loot.indexOf(name1) > -1) { // hardcore leaving char is removed from loot 65 | loot.splice(loot.indexOf(name1), 1); 66 | } 67 | 68 | break; 69 | } 70 | }); 71 | addEventListener("scriptmsg", 72 | function (msg) { 73 | let obj; 74 | 75 | try { 76 | obj = JSON.parse(msg); 77 | 78 | if (obj && obj.hasOwnProperty("currScript")) { 79 | currScript = obj.currScript; 80 | } 81 | } catch (e3) { 82 | 83 | } 84 | }); 85 | 86 | if (Config.PublicMode === 4 || Config.PublicMode === 5) { 87 | print("ÿc2Party thread loaded. ÿc0Mode: ÿc2MyOwnParty - " + ((Config.PublicMode === 5) ? "Accept" : "Invite")); 88 | } else print("ÿc2Party thread loaded. ÿc0Mode: ÿc2" + (Config.PublicMode === 2 ? "Accept" : "Invite")); 89 | 90 | if (Config.ShitList || Config.UnpartyShitlisted) { 91 | shitList = ShitList.read(); 92 | 93 | print(shitList.length + " entries in shit list."); 94 | } 95 | 96 | if (Config.PartyAfterScript) { 97 | scriptList = []; 98 | 99 | for (i in Scripts) { 100 | if (Scripts.hasOwnProperty(i) && !!Scripts[i]) { 101 | scriptList.push(i); 102 | } 103 | } 104 | } 105 | 106 | // Main loop 107 | while (true) { 108 | if (me.gameReady && (!Config.PartyAfterScript || scriptList.indexOf(currScript) > scriptList.indexOf(Config.PartyAfterScript))) { 109 | player = getParty(); 110 | 111 | if (player) { 112 | myPartyId = player.partyid; 113 | 114 | while (player.getNext()) { 115 | switch (Config.PublicMode) { 116 | case 1: // Invite others 117 | case 3: // Invite others but never accept 118 | if (getPlayerFlag(me.gid, player.gid, 8)) { 119 | if (Config.ShitList && shitList.indexOf(player.name) === -1) { 120 | say(player.name + " has been shitlisted."); 121 | shitList.push(player.name); 122 | ShitList.add(player.name); 123 | } 124 | 125 | if (player.partyflag === 4) { 126 | clickParty(player, 2); // cancel invitation 127 | delay(100); 128 | } 129 | 130 | break; 131 | } 132 | 133 | if (Config.ShitList && shitList.indexOf(player.name) > -1) { 134 | break; 135 | } 136 | 137 | if (player.partyflag !== 4 && (Config.PublicMode === 1 || player.partyflag !== 2) && player.partyid === 65535) { 138 | clickParty(player, 2); 139 | delay(100); 140 | } 141 | 142 | break; 143 | case 2: // Accept invites 144 | if (Config.Leader && player.name !== Config.Leader) { 145 | break; 146 | } 147 | 148 | if (player.partyid !== 65535 && player.partyid !== myPartyId) { 149 | otherParty = player.partyid; 150 | } 151 | 152 | if (player.partyflag === 2 && (!otherParty || player.partyid === otherParty) && (getTickCount() - partyTick >= 2000 || Config.FastParty)) { 153 | clickParty(player, 2); 154 | delay(100); 155 | } 156 | 157 | break; 158 | case 4: // MyOwnParty invite 159 | if (Config.MyOwnParty.indexOf(player.name) === -1) { 160 | break; 161 | } 162 | 163 | if (Config.MyOwnParty.length > 0) { 164 | var i; 165 | 166 | for (i = 0; i < Config.MyOwnParty.length; i += 1) { 167 | if (player.name == Config.MyOwnParty[i] && player.name !== me.name) { 168 | if (player.partyflag !== 4 && player.partyflag !== 2 && player.partyid === 65535) { 169 | clickParty(player, 2); 170 | 171 | if (me.playertype == 1) { // hardcore permit loot of leader to other char who is invited in the party 172 | clickParty(player, 0); 173 | } 174 | 175 | delay(500); 176 | } 177 | } 178 | } 179 | 180 | } else if (Config.MyOwnParty.length === 0 || Config.MyOwnParty.length === undefined) { 181 | Config.PublicMode = 1; 182 | } 183 | 184 | break; 185 | case 5: // MyOwnParty accept 186 | if (Config.MyOwnParty.indexOf(player.name) === -1) { 187 | break; 188 | } 189 | 190 | if (Config.MyOwnParty.length > 0) { 191 | var i; 192 | 193 | for (i = 0; i < Config.MyOwnParty.length; i += 1) { 194 | if (player.name == Config.MyOwnParty[i] && player.name !== me.name) { 195 | if (player.partyflag === 2) { 196 | clickParty(player, 2); 197 | 198 | if (me.playertype == 1) { // hardcore permit loot to leader 199 | clickParty(player, 0); 200 | loot.push(player.name); 201 | } 202 | 203 | delay(500); 204 | } 205 | 206 | if (loot.indexOf(player.name) === -1 && me.playertype == 1) { // hardcore permit loot to other chars 207 | clickParty(player, 0); 208 | loot.push(player.name); 209 | delay(500); 210 | } 211 | } 212 | } 213 | 214 | } else if (Config.MyOwnParty.length === 0 || Config.MyOwnParty.length === "undefined") { 215 | Config.PublicMode = 2; 216 | } 217 | 218 | break; 219 | } 220 | 221 | if (Config.UnpartyShitlisted) { 222 | // Add new hostile players to temp shitlist, leader should have Config.ShitList set to true to update the permanent list. 223 | if (getPlayerFlag(me.gid, player.gid, 8) && shitList.indexOf(player.name) === -1) { 224 | shitList.push(player.name); 225 | } 226 | 227 | if (shitList.indexOf(player.name) > -1 && myPartyId !== 65535 && player.partyid === myPartyId) { 228 | // Only the one sending invites should say this. 229 | if ([1, 3].indexOf(Config.PublicMode) > -1) { 230 | say(player.name + " is shitlisted. Do not invite them."); 231 | } 232 | 233 | clickParty(player, 3); 234 | delay(100); 235 | } 236 | } 237 | } 238 | } 239 | 240 | if (Config.Congratulations.length > 0) { 241 | player = getParty(); 242 | 243 | if (player) { 244 | do { 245 | if (player.name !== me.name) { 246 | if (!playerLevels[player.name]) { 247 | playerLevels[player.name] = player.level; 248 | } 249 | 250 | if (player.level > playerLevels[player.name]) { 251 | say(Config.Congratulations[rand(0, Config.Congratulations.length - 1)].replace("$name", player.name).replace("$level", player.level).replace("$class", classes[player.classid])); 252 | 253 | playerLevels[player.name] = player.level; 254 | } 255 | } 256 | } while (player.getNext()); 257 | } 258 | } 259 | } 260 | 261 | delay(500); 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /limedrop/README.md: -------------------------------------------------------------------------------- 1 | # Limedrop Guide 2 | 3 | * [About](#about-limedrop) 4 | * [Setup](#setup-limedrop) 5 | * [Usage](#using-limedrop) 6 | * [FAQ](#frequently-asked-questions) 7 | 8 | ----- 9 | 10 | ### About Limedrop 11 | ##### What is it? 12 | Limedrop is a web-based item **dropper**; it is a program that will manage joining games and dropping specific items. 13 | 14 | ##### How do I install it? 15 | Limedrop is an API added to D2Bot # and a web-based frontend. The d2bot-with-kolbot [kolbot](https://github.com/blizzhackers/kolbot) has Limedrop built in. 16 | 17 | ##### How does it work? 18 | There are two parts to Limedrop. One part is the API, and one part is a web page that calls the API. The web page can be accessed at www.limedrop.org 19 | 20 | When the web page requests an item, Limedrop will launch the configured profile, join the game specified, and drop the item(s) selected. 21 | 22 | ##### Self-hosting 23 | If you want to access the latest version, use www.limedrop.org, if you would like to host the static front-end yourself, you can download it [blizzhackers/limedrop](https://github.com/blizzhackers/limedrop) and copy it to the "Limedrop" folder of your d2bot-with-kolbot download. To access locally use http://localhost:8080. 24 | 25 | If you're using Git to clone d2bot-with-kolbot it will ask you if you want to automatically download the sub-repository. 26 | 27 | ##### Hosted (recommended) 28 | You can also use the externally hosted version here: [http://www.limedrop.org](http://www.Limedrop.org) 29 | 30 | The benefit of this version is that it is always up-to-date 31 | 32 | **Note:** If you want to access Limedrop from an external network you will need to open router ports. The frontend only delivers the static site, it uses your instance of D2Bot to power the API. Note, the Limedrop API has not been security tested so if you choose to open your network externally, you need to assume all risks associated with that. 33 | 34 | ### Setup Limedrop 35 | 1. Download the Limedrop version from [here](https://github.com/blizzhackers/kolbot/archive/master.zip) or clone from: _https://github.com/blizzhackers/kolbot.git_ 36 | 37 | 1. Extract to a folder: 38 | ![Extracted Files](assets/limedrop-extract.png) 39 | 40 | 1. Edit the server.json config file: 41 | * ![Server Config File](assets/limedrop-serverconfigfile.png) 42 | * ![Server Config Edit](assets/limedrop-serverconfigedit.png) 43 | * This default config says to: 44 | * Use the D2BS profile called "GameAction" 45 | * Create a user with the name "public", password "public" who **is not** able to drop items 46 | * Create a user with the name "test", password "test" who **is** able to drop items 47 | * The path to the web page files are in the "\limedrop" folder underneath the D2BS directory 48 | * The IP we will respond on is "localhost" (also known as 127.0.0.1) 49 | * If you want to access from another computer, you will need to use your real local IP like 192.168.1.100 50 | * The Port we will listen on is 8080 51 | 52 | 1. Turn on D2Bot and enable the Limedrop API by going to "Settings" and clicking the enable API option. 53 | 54 | 1. Follow the standard setup guide for adding cdkeys. 55 | 56 | 1. Create a new profile, we will use GameAction for an example - this needs to match what is in server.json 57 | * Make sure you set your own game name to avoid conflicts with other people 58 | * ![Add Profile](assets/limedrop-addprofile.png) 59 | * Make sure you use the D2BotGameAction.dbj as the Entry Script 60 | 61 | 62 | ### Using Limedrop 63 | To start Limedrop, just open D2BS.exe . You DO NOT have to launch the profile manually. 64 | Limedrop will launch the profile on its own when it needs to do something. 65 | 66 | #### Logging In 67 | * To login, either go to [http://www.limedrop.org](http://www.Limedrop.org) or your self-hosted page 68 | * At the upper right, click the profile icon to log in: 69 | * ![Login](assets/limedrop-login.png) 70 | * Enter your server address (including port) according to your server config 71 | * Enter your username 72 | * Enter your password 73 | * **Click Login** 74 | * Right now you have to manually click Login. You cannot just press enter. 75 | 76 | #### Muling Options 77 | * You can create a profile using the standard [MuleLogger profile](https://github.com/blizzhackers/documentation/blob/master/kolbot/D2BotMuleLog.md) 78 | * All mules logged this way will appear in the Limedrop web page 79 | 80 | **The creation of games was removed from limedrop, so don't try to log mules/accounts with it**, because in some cases limedrop was creating a new game and it was dropping items, then left that game. 81 | 82 | 106 | #### Emergency Stop 107 | You may notice that if you "stop" the GameAction profile that it immediately starts up again. 108 | 109 | If you need to force the profile to stop you need to open the profile and erase the "tag" information. 110 | 111 | * Edit Profile 112 | * Erase information in Tag 113 | * Click Apply 114 | * Stop the profile 115 | 116 | **Note:** If you have queued many drops, you will need to clear it for each drop, or you will need to restart D2BSharp. 117 | 118 | ### Frequently Asked Questions 119 | 120 | #### Will Limedrop steal my information? 121 | No. The web page part of Limedrop only makes calls to the API running on your D2BS. Your account passwords are not stored directly in the web page. Also, it's open source so if you don't trust it you can always take a look at the code yourself! 122 | 123 | #### Can it run side-by-side with my existing bots? 124 | Yes. If you want to quickly try Limedrop you can copy it to a separate folder and configure it 125 | 126 | #### Can I use my existing mule logs with Limedrop? 127 | No. You will have to re-scan your existing mules in order to add them to the Limedrop Inventory 128 | 129 | #### Will Limedrop automatically update my inventory after dropping items? 130 | Yes. 131 | 132 | #### How to select all items in limedrop? 133 | Just type this in your address bar on the limedrop page: 134 | ```javascript 135 | javascript:document.querySelectorAll('#items-list>div').forEach(el => el.click()) 136 | ``` 137 | Works in chrome, but might take a while depending on item count. 138 | Make sure that all items are loaded beforehand (scroll to the end as long as new items are loaded) 139 | (thanks discord/@ToDoWaldi#8021) 140 | -------------------------------------------------------------------------------- /limedrop/assets/limedrop-addaccount1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/limedrop/assets/limedrop-addaccount1.png -------------------------------------------------------------------------------- /limedrop/assets/limedrop-addaccount2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/limedrop/assets/limedrop-addaccount2.png -------------------------------------------------------------------------------- /limedrop/assets/limedrop-addprofile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/limedrop/assets/limedrop-addprofile.png -------------------------------------------------------------------------------- /limedrop/assets/limedrop-extract.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/limedrop/assets/limedrop-extract.png -------------------------------------------------------------------------------- /limedrop/assets/limedrop-general.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/limedrop/assets/limedrop-general.png -------------------------------------------------------------------------------- /limedrop/assets/limedrop-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/limedrop/assets/limedrop-login.png -------------------------------------------------------------------------------- /limedrop/assets/limedrop-serverconfigedit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/limedrop/assets/limedrop-serverconfigedit.png -------------------------------------------------------------------------------- /limedrop/assets/limedrop-serverconfigfile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blizzhackers/documentation/7018fde9139fc001e3bf697da1fd3a98a2d87836/limedrop/assets/limedrop-serverconfigfile.png --------------------------------------------------------------------------------