516 lines
16 KiB
Plaintext
516 lines
16 KiB
Plaintext
// ====================================================================================================
|
|
// v THIS IS THE JUNK YOU'LL WANT TO EDIT v
|
|
// Frendless leech starter setting (set to run with op gotv channel bot by default there will be no help on changing this)
|
|
// ====================================================================================================
|
|
var gamenames = ["EamPleGameWithouTTHENumbers-"]; // Game name to search for (CASE-SENSITIVE)
|
|
|
|
var gamepasswords = ["ExAmPlePassword"]; // Password for that game.
|
|
|
|
var maxRetriesPerGame = 3; // The # of times to try rejoining a *unique* game
|
|
var maxRetries = 3; // The # of *different* games to try joining, if all attempts fail, bot will exit to character selection screen and rejoin lobby
|
|
|
|
// ====================================================================================================
|
|
|
|
var gameMinLength = 180000; // time in milliseconds, minimum game length, 180 seconds default (1 game/3 minutes)
|
|
var unableToConnectRetry = 5; // time in minutes to retry connecting on connection fail (real value is +/- 1 min)
|
|
var realmDownRetry = 260; // time in minutes to retry connecting on a realm down (default is 120 minutes)
|
|
var disconnectedRetry = 5; // time in minutes to retry on a disconnection (usually ip ban related)
|
|
var cdkeyInUseRetry = 1; // time in minutes to retry on a cdkey in use error message (set to 0 to stop)
|
|
var connectingToBnetTimeout = 20000; // time in milliseconds to wait for a login to time out and click cancel and retry
|
|
var characterScreenTimeout = 5000; // time in milliseconds to wait for character screen to appear
|
|
var pleaseWaitTimeout = 2000; // time in milliseconds to wait for a please wait popup
|
|
var createGameThreshold = 2000; // time in milliseconds to wait between making games
|
|
var createGameThresholdRandom = 500; // time in milliseconds to randomly add +/- to the game create time
|
|
var createGameTimeout = 15000; // time in milliseconds to register a failed to create game
|
|
var waitInLineTimeout = 60000; // time in milliseconds to wait in lines for a create game (60 second default)
|
|
var characterSelectDelay = 1000; // time in milliseconds to wait before selecting a character on the char screen
|
|
var loginDelay = 1000; // time in milliseconds to wait before submitting login information
|
|
var clickDelay = 500; // wait X milliseconds before next action after a click event
|
|
var textDelay = 500; // wait X milliseconds before next action after inserting text into a textbox
|
|
var clickDelayRandom = 500; // random amount of time to add to a click
|
|
var textDelayRandom = 500; // random amount of time to add to a text set
|
|
var gameDoesNotExistDelayMin = 1000; // how long to wait when a Game Does Not Exist occurs - minimum - default 10 minutes
|
|
var gameDoesNotExistDelayMax = 2000; // how long to wait when a Game Does Not Exist occurs - maximum - default 15 minutes
|
|
var gameDoesNotExistTimeout = 50; // how long to wait for the dialog to disappear (default 30 seconds, don't change this)
|
|
var waitBeforeEnterChatMin = 1000; // min how long to wait before entering chat
|
|
var waitBeforeEnterChatMax = 2000; // max how long to wait before entering chat
|
|
var waitInChatBeforeActionsMin = 1000; // min how long to wait before joining channel
|
|
var waitInChatBeforeActionsMax = 2000; // max how long to wait before joining channel
|
|
|
|
// DONT EDIT ANYTHING BELOW THIS
|
|
var extrafilters = ["New game ", " started by"]; // The 2nd filter should be whatever the bot manager says right after the game name
|
|
// If the 2nd filter is empty, the rest of the line is used as the game name
|
|
var joinChannelInChat = "op gotv"; // leave blank to not join a private channel
|
|
|
|
// D2NT Manager Command
|
|
const D2NT_MGR_LOADING = 1;
|
|
const D2NT_MGR_READY = 2;
|
|
const D2NT_MGR_LOGIN = 3;
|
|
const D2NT_MGR_CREATE_GAME = 4;
|
|
const D2NT_MGR_INGAME = 5;
|
|
const D2NT_MGR_RESTART = 6;
|
|
const D2NT_MGR_CHICKEN = 7;
|
|
const D2NT_MGR_PRINT_STATUS = 8;
|
|
const D2NT_MGR_PRINT_LOG = 9;
|
|
|
|
var lastGameMade = GetTickCount();
|
|
var nextGameMake = 0;
|
|
var inGameAt = 0;
|
|
var chatActionsDone = false;
|
|
var lastGameStatus = 0; // 0 = OK, 1 = Processing, 2 = Ready for retry
|
|
var game = "";
|
|
var gamepassword = "";
|
|
var retry = 0;
|
|
var fullretry = maxRetries;
|
|
var samegame = new Array(gamenames.length); // Empty array for however many runs you might be following (default 6)
|
|
|
|
Include("libs/controlInfo.ntl");
|
|
Include("libs/common/NTColorConverter.ntl");
|
|
|
|
var controlData = new controlInfo();
|
|
|
|
function NTMain()
|
|
{
|
|
Delay(1000);
|
|
|
|
var _ingame = false;
|
|
|
|
controlData.clickDelay = clickDelay;
|
|
controlData.textDelay = textDelay;
|
|
controlData.clickDelayRandom = clickDelayRandom;
|
|
controlData.textDelayRandom = textDelayRandom;
|
|
|
|
while (1)
|
|
{
|
|
if (me.ingame)
|
|
{
|
|
if (!inGameAt)
|
|
inGameAt = GetTickCount();
|
|
|
|
if (!_ingame)
|
|
{
|
|
RunGC(); // run garbage collector between each game
|
|
|
|
if (Load("NTBot/NTBotGame.ntj"))
|
|
{
|
|
_ingame = true;
|
|
|
|
if (me.playtype > 0)
|
|
sendEventToOOG(D2NT_MGR_INGAME, "In Game.. [IP:" + me.gameserverip.split(".")[3] + "]", 0);
|
|
else
|
|
sendEventToOOG(D2NT_MGR_INGAME, "In Game..", 0);
|
|
|
|
fullretry = maxRetries;
|
|
lastGameStatus = 0;
|
|
game = "";
|
|
}
|
|
}
|
|
|
|
Delay(1000);
|
|
}
|
|
else
|
|
{
|
|
Delay(500);
|
|
if (_ingame)
|
|
{
|
|
_ingame = false;
|
|
|
|
// --------------------------
|
|
// Prevent NT from closing D2
|
|
// --------------------------
|
|
|
|
// Wait for lobby or lobby chat
|
|
var _location;
|
|
do
|
|
{
|
|
_location = controlData.getLocation();
|
|
Delay(50);
|
|
}
|
|
while (_location.id != 3 && _location.id != 1);
|
|
|
|
if (_location.id == 3) // Lobby Chat
|
|
{
|
|
// We need to go somewhere besides the lobby chat so NT can type crap and think its creating a game
|
|
Delay(100);
|
|
Say("/join " + getRandomString(Random(3,10)));
|
|
Delay(1000);
|
|
}
|
|
sendEventToOOG(D2NT_MGR_CREATE_GAME, _location.name, 0);
|
|
outputGameLength();
|
|
setNextGameMake();
|
|
// --------------------------
|
|
|
|
sendEventToOOG(D2NT_MGR_READY, "", 0);
|
|
}
|
|
|
|
locationAction(controlData.getLocation());
|
|
|
|
Delay(500);
|
|
}
|
|
}
|
|
}
|
|
|
|
function locationAction(location)
|
|
{
|
|
switch (location.id)
|
|
{
|
|
case 3: // Lobby Chat
|
|
|
|
// Not retrying anymore, clear the game name so that if user tries to do it themself, bot won't fill in with old game
|
|
if (lastGameStatus == 0 || retry == 0)
|
|
{
|
|
// Clear these flags just in case
|
|
retry = 0;
|
|
game = "";
|
|
}
|
|
|
|
// Handle non-existent or full games:
|
|
// When the join button is hit, lastGameStatus = 1.
|
|
// When in-game, lastGameStatus = 0.
|
|
// So this gets executed when NTMain() doesn't reset the flag to 0.
|
|
if (lastGameStatus == 1)
|
|
{
|
|
if (fullretry == 0) // If we have tried [maxRetries] different games ([maxRetriesPerGame] retries for each game)
|
|
{
|
|
lastGameStatus = 0;
|
|
fullretry = maxRetries;
|
|
|
|
// We need to close out of chat and come back
|
|
sendEventToOOG(D2NT_MGR_PRINT_LOG, COLOR_1 + "Game doesn't exist or its full. Rejoining chat.", 0);
|
|
controlData.click(controlData.controls.lobby.button.quit);
|
|
}
|
|
else
|
|
{
|
|
lastGameStatus = 2; // Ready for retry
|
|
|
|
if (retry == 0) // If we just failed [maxRetriesPerGame] times for joining this game
|
|
fullretry--; // Update flag
|
|
|
|
sendEventToOOG(D2NT_MGR_PRINT_LOG, COLOR_1 + "Game doesn't exist or its full. " + retry + " retries left.", 0);
|
|
|
|
inGameAt = Random(gameDoesNotExistDelayMin, gameDoesNotExistDelayMax);
|
|
setNextGameMake();
|
|
chatActionsDone = true; // Undo the flag set by setNextGameMake()
|
|
|
|
locationTimeout(gameDoesNotExistTimeout, location);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (!chatActionsDone || GetTickCount() > nextGameMake + 180000) // Need to join channel or its been 3 minutes and no action, possibly kicked from channel, rejoin
|
|
{
|
|
if (GetTickCount() > nextGameMake + 180000) // Reset this so that we don't keep joining channel over and over
|
|
nextGameMake = GetTickCount();
|
|
|
|
chatActionsDone = true;
|
|
Delay(Random(waitInChatBeforeActionsMin, waitInChatBeforeActionsMax));
|
|
|
|
Say("/join " + joinChannelInChat);
|
|
Delay(1000);
|
|
sendEventToOOG(D2NT_MGR_PRINT_LOG, "Looking for games..", 0);
|
|
}
|
|
|
|
// Time for action?
|
|
if (GetTickCount() >= nextGameMake)
|
|
{
|
|
sendEventToOOG(D2NT_MGR_PRINT_STATUS, location.name, 0);
|
|
|
|
// If we can retry and there is a game to retry
|
|
if (retry > 0 && game != "" && lastGameStatus == 2)
|
|
{
|
|
controlData.click(controlData.controls.lobby.button.join);
|
|
retry--;
|
|
break;
|
|
}
|
|
|
|
var chat = controlData.get(controlData.controls.lobby.chat.textBox.channelText);
|
|
if (chat)
|
|
{
|
|
var linewithname = "";
|
|
lines = chat.GetText();
|
|
if (lines)
|
|
{
|
|
for (var line = 0; line < lines.length; line++)
|
|
{
|
|
linewithname = lines[line];
|
|
|
|
for (var _filterindex = 0; _filterindex < extrafilters.length; _filterindex += 2)
|
|
{
|
|
// Check filters
|
|
if (linewithname.lastIndexOf(extrafilters[_filterindex]) != -1 && linewithname.lastIndexOf(extrafilters[_filterindex+1]) != -1)
|
|
{
|
|
for (var _gameindex = 0; _gameindex < gamenames.length; _gameindex++)
|
|
{
|
|
// Check for game name
|
|
var index = linewithname.lastIndexOf(gamenames[_gameindex]);
|
|
if (index > -1)
|
|
{
|
|
game = linewithname.substring(index, linewithname.lastIndexOf(extrafilters[_filterindex+1]));
|
|
gamepassword = gamepasswords[_gameindex];
|
|
|
|
if (game != "" && game != samegame[_gameindex])
|
|
{
|
|
sendEventToOOG(D2NT_MGR_PRINT_LOG, "Joining " + game + "..", 0);
|
|
samegame[_gameindex] = game;
|
|
controlData.click(controlData.controls.lobby.button.join);
|
|
retry = maxRetriesPerGame;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
sendEventToOOG(D2NT_MGR_PRINT_STATUS, location.name + " (" + parseInt((nextGameMake-GetTickCount())/1000) + "s)", 0);
|
|
break;
|
|
|
|
case 1: // Lobby
|
|
|
|
// Enter chat
|
|
Delay(Random(waitBeforeEnterChatMin, waitBeforeEnterChatMax));
|
|
controlData.click(controlData.controls.lobby.button.enterChat);
|
|
break;
|
|
|
|
case 2: // Waiting In Line
|
|
if (GetTickCount()-lastGameMade > waitInLineTimeout)
|
|
controlData.click(controlData.controls.lobby.inLine.button.cancel);
|
|
break;
|
|
|
|
case 4: // Create Game
|
|
break;
|
|
|
|
case 5: // Join Game
|
|
if (game != "")
|
|
{
|
|
sendEventToOOG(D2NT_MGR_PRINT_STATUS, location.name, 0);
|
|
|
|
controlData.setText( controlData.controls.lobby.join.editBox.gameName, game);
|
|
Delay (1250);
|
|
controlData.setText( controlData.controls.lobby.join.editBox.password, gamepassword);
|
|
Delay (1250);
|
|
controlData.click(controlData.controls.lobby.join.button.joinGame);
|
|
}
|
|
|
|
lastGameMade = GetTickCount();
|
|
lastGameStatus = 1;
|
|
break;
|
|
|
|
case 6: // Ladder
|
|
break;
|
|
|
|
case 7: // Channel List
|
|
break;
|
|
|
|
case 8: // Main Menu
|
|
if (controlData.getCurrentRealmIndex() == me.gatewayid)
|
|
{
|
|
outputGameLength();
|
|
controlData.click(controlData.gameTypes[me.playtype]);
|
|
}
|
|
else
|
|
controlData.click(controlData.controls.mainMenu.button.gateway);
|
|
break;
|
|
|
|
case 9: // Login
|
|
sendEventToOOG(D2NT_MGR_PRINT_STATUS, location.name, 0);
|
|
Delay(loginDelay);
|
|
|
|
controlData.setText(controlData.controls.login.editBox.accountName, me.account);
|
|
|
|
sendEventToOOG(D2NT_MGR_LOGIN, location.name, 0);
|
|
|
|
locationTimeout(5000, location);
|
|
break;
|
|
|
|
case 10: // Login Error (this is a fatal error, so stop)
|
|
sendEventToOOG(D2NT_MGR_RESTART, location.name, 10);
|
|
Delay(3500);
|
|
break;
|
|
|
|
case 11: // Unable To Connect
|
|
timeoutDelay(unableToConnectRetry*60*1000, location)
|
|
controlData.click(controlData.controls.login.unableToConnect.button.ok);
|
|
break;
|
|
|
|
case 12: // Character Select
|
|
var _time, _control;
|
|
|
|
sendEventToOOG(D2NT_MGR_PRINT_STATUS, location.name, 0);
|
|
|
|
for (_time = 0; _time < characterScreenTimeout; _time += 500)
|
|
{
|
|
_control = controlData.get(controlData.controls.characterSelect.textBox.characterInfo[me.charloc]);
|
|
if (_control && _control.GetText() != undefined)
|
|
break;
|
|
|
|
Delay(500);
|
|
}
|
|
|
|
if (_time < characterScreenTimeout)
|
|
{
|
|
Delay(characterSelectDelay);
|
|
|
|
controlData.click(controlData.controls.characterSelect.textBox.characters[me.charloc], 0, 0, 1);
|
|
controlData.click(controlData.controls.characterSelect.textBox.characterInfo[me.charloc], 0, 0, 1);
|
|
|
|
// reset last game made, so it doesnt make a game immediately
|
|
inGameAt = 0;
|
|
setNextGameMake();
|
|
}
|
|
else
|
|
{
|
|
controlData.click(controlData.controls.characterSelect.button.exit);
|
|
timeoutDelay(realmDownRetry*60*1000, location);
|
|
}
|
|
break;
|
|
|
|
case 13: // Realm Down - Character Select screen
|
|
controlData.click(controlData.controls.characterSelect.button.exit);
|
|
timeoutDelay(realmDownRetry*60*1000, location);
|
|
break;
|
|
|
|
case 14: // Character Select - Disconnected
|
|
timeoutDelay(disconnectedRetry*60*1000, location);
|
|
controlData.click(controlData.controls.characterSelect.disconnected.button.ok);
|
|
break;
|
|
|
|
case 15: // New Character
|
|
break;
|
|
|
|
case 16: // Character Select - Please Wait popup
|
|
if (!locationTimeout(pleaseWaitTimeout, location))
|
|
controlData.click(controlData.controls.characterSelect.pleaseWait.button.cancel);
|
|
break;
|
|
|
|
case 17: // Lobby - Lost Connection - just click okay, since we're toast anyway
|
|
controlData.click(controlData.controls.lobby.lostConnection.button.ok);
|
|
break;
|
|
|
|
case 18: // D2 Splash
|
|
controlData.click(controlData.controls.d2Splash.textBox.copyright);
|
|
break;
|
|
|
|
case 19: // Login - Cdkey In Use
|
|
timeoutDelay(cdkeyInUseRetry*60*1000, location);
|
|
controlData.click(controlData.controls.login.cdkeyInUse.button.ok);
|
|
break;
|
|
|
|
case 20: // Single Player - Select Difficulty
|
|
controlData.click(controlData.singlePlayerDifficulties[me.diff]);
|
|
break;
|
|
|
|
case 21: // Main Menu - Connecting
|
|
if (!locationTimeout(connectingToBnetTimeout, location))
|
|
controlData.click(controlData.controls.mainMenu.connecting.button.cancel);
|
|
break;
|
|
|
|
case 22: // Login - Invalid Cdkey (classic or xpac)
|
|
sendEventToOOG(D2NT_MGR_RESTART, location.name, 3600);
|
|
Delay(3500);
|
|
break;
|
|
|
|
case 23: // Character Select - Connecting
|
|
if (!locationTimeout(characterScreenTimeout, location))
|
|
controlData.click(controlData.controls.characterSelect.button.exit);
|
|
break;
|
|
|
|
case 24: // Server Down - not much to do but wait..
|
|
break;
|
|
|
|
case 25: // Lobby - Please Wait
|
|
if (!locationTimeout(pleaseWaitTimeout, location))
|
|
controlData.click(controlData.controls.lobby.pleaseWait.button.cancel);
|
|
break;
|
|
|
|
case 26: // Lobby - Game Name Exists
|
|
sendEventToOOG(D2NT_MGR_PRINT_LOG, COLOR_1 + "Game already exists.", 0);
|
|
|
|
inGameAt = 0;
|
|
setNextGameMake();
|
|
|
|
locationTimeout(15000, location);
|
|
break;
|
|
|
|
case 27: // Gateway Select
|
|
controlData.clickRealmEntry(me.gatewayid);
|
|
controlData.click(controlData.controls.gateway.button.ok);
|
|
break;
|
|
|
|
case 28: // Lobby - Game Does Not Exist
|
|
// This is handled in the lobby chat
|
|
|
|
// Get rid of the message (DNE/Full game) so the lobby chat can handle
|
|
controlData.click(controlData.controls.lobby.button.create);
|
|
Delay(200);
|
|
controlData.click(controlData.controls.lobby.create.button.cancel);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
function sendEventToOOG(locationId, statusString, pendingTime)
|
|
{
|
|
return SendCopyData("D2NT Manager", null, (locationId<<16)|pendingTime, statusString);
|
|
}
|
|
|
|
function setNextGameMake()
|
|
{
|
|
lastGameMade = GetTickCount();
|
|
nextGameMake = lastGameMade + createGameThreshold + Random(0-createGameThresholdRandom, createGameThresholdRandom) + inGameAt;
|
|
inGameAt = 0;
|
|
chatActionsDone = false;
|
|
}
|
|
|
|
function outputGameLength()
|
|
{
|
|
if (inGameAt)
|
|
{
|
|
duration = GetTickCount() - inGameAt;
|
|
|
|
inGameAt = (duration < gameMinLength ? gameMinLength - duration : 0);
|
|
}
|
|
}
|
|
|
|
function locationTimeout(time, location)
|
|
{
|
|
endtime = GetTickCount() + time;
|
|
|
|
while (controlData.getLocation().id == location.id && endtime > GetTickCount())
|
|
{
|
|
sendEventToOOG(D2NT_MGR_PRINT_STATUS, location.name + " (" + parseInt((endtime-GetTickCount())/1000) + "s)", 0);
|
|
Delay(500);
|
|
}
|
|
|
|
return (controlData.getLocation().id != location.id);
|
|
}
|
|
|
|
function timeoutDelay(time, location)
|
|
{
|
|
endtime = GetTickCount() + time;
|
|
|
|
while (endtime > GetTickCount())
|
|
{
|
|
sendEventToOOG(D2NT_MGR_PRINT_STATUS, location.name + " (" + parseInt((endtime-GetTickCount())/1000) + "s)", 0);
|
|
Delay(1000);
|
|
}
|
|
}
|
|
|
|
function getRandomString(_length)
|
|
{
|
|
_retString = "";
|
|
_charSet = "0123456789abcdefghijklmnopqrstuvwxyz";
|
|
|
|
while (_length--)
|
|
{
|
|
_retString += _charSet.charAt(Random(0, _charSet.length-1));
|
|
Delay(1);
|
|
}
|
|
|
|
return _retString;
|
|
} |