Auto Exploration

Ease your exploration mission with automatic smart exploring logic for probing, in a single click

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Auto Exploration
// @namespace    github.com/odahviing/warfacts
// @version      3.03
// @description  Ease your exploration mission with automatic smart exploring logic for probing, in a single click
// @author       Odahviing
// @match        http://www.war-facts.com/fleet*
// @match        http://www.war-facts.com/player.php
// @exclude      http://www.war-facts.com/fleet.php?mtype*
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

// Version 1.0 - Base Exploring Support
// Version 2.0 - JavaScript V2 Support [New Exploring System]
// -- Support auto-click
// -- Support refueling only if needing, if you have system near by and the fuel enough, go for it
// -- Using only jsmap_postload_v2 function to load data
// -- Avoid systems that will lock the probe without fuel to reach the planets

// Version 2.1
// -- Bug fix when the button is not ready to load
// -- Design a different way to auto-press the button

// Version 2.2 - Fix a stupid bug that ignore places that had x value of aboue 300000 (so almost every galaxy outside Alpha)
// Version 2.3 - Code Beautifier
// Version 2.4 - Change settings so the closest system will be explored, but without duplicate systems

// Version 2.5
// -- Change to only one data cycle, too heavy otherwise
// -- Fix a bug that if the page is loaded to fast, its not pressing explore at time

// Version 2.6 - Bug fix that cause fleets to not avoiding reaching planets that are already on the way to be explored

// Version 2.7
// -- Auto move to next free explorer
// -- Alert if enemy fleet detected

// Version 2.8 - Connect "sent to planet" script to Auto-Exploration
// Version 2.9 - Restore Old internal explore planets (auto-explore)
// Version 3.0 - Management Panel

// Default Settings
var autoSwitchToNextFleet = true;
var fullAuto = false;
var safeDistance = 5000000; // If the system is 2m km from the fleet range, we won't go there (need to fix the math a-bit)
var whiteList = false;
var fleetsName = [];
var abortletter = '#';
var showEnemies = true;
var enemiesFactions = ['Jarnekk','Scaldarians'];
var minimumFuelAmount = 50000000; // Will go fuel if below

var settings = loadSettings();

(function() {
    'use strict';

    if (document.URL.indexOf('player.php') >= 0) {
        buildMenu();
        return;
    }

    var timers = (settings.fullAuto == true) ?
        {button : 600, mission : 500, explore : 1000, refresh: 10000, hookPlanet: 500} :
    {button : 600, mission : 400, hookPlanet: 300};

    setTimeout(loadButton, timers.button);
    setTimeout(addInternalButton, timers.button);
    setTimeout(addVerifyPlanetButton, timers.hookPlanet);
    setTimeout(pressTheButton, timers.mission);
    if (settings.fullAuto == true)
    {
        setTimeout(pressExplore, timers.explore);
        setTimeout(reloadPage, timers.refresh);
    }
})();

// On-Load Functions

function loadButton() {
    let newButton = document.createElement('input');
    newButton.type = 'button'
    newButton.value = 'System';
    newButton.id = 'ExploreButton';
    newButton.style = 'width: 80px;'
    newButton.className = 'darkbutton dangerbutton';
    newButton.addEventListener("click", run);
    var buttonPlace = document.getElementsByClassName('iBlock tbborder padding5 fullwidth light')[0];
    if (buttonPlace)
        buttonPlace.insertBefore(newButton, null);
}

function pressTheButton() {
    if (document.URL.indexOf('callback=1') > 0) {
        document.getElementById('objective').value='explore';
        getMission('launch');
        if (settings.nextAuto == true)
            nextFleet();
    }
}

function pressExplore() {
    if (document.URL.indexOf('auto=1') > 0) {
        let getButton = document.getElementById('ExploreButton');
        if (getButton)
            getButton.click();
        else
            nextFleet();
    }
}

function nextFleet() {
    var allFleets = document.getElementsByClassName('padding5 inlineblock light box');
    if (settings.whiteList == false) {
        window.location = allFleets[0].href + (settings.fullAuto == true ? "#auto=1" : "");
        return;
    }

    for (let i = 0; i < allFleets.length; i++)
    {
        let exists = settings.goodNames.findIndex(x => allFleets[i].innerHTML.indexOf(x) >= 0);
        if (exists >= 0) {
            if (allFleets[i].innerHTML.indexOf(settings.badLetter) >= 0) continue;

            window.location = allFleets[i].href + (settings.fullAuto == true ? "#auto=1" : "");
            return;
        }
    }
}

function reloadPage() {
    if (document.URL.indexOf('auto=1') > 0)
        location.reload();
}

// End On-Load Functions

// Fleet Functions

var fleetNumber;
var fleetRange;
var fleetFuel;

function getFleetNumber() {
    let tmpUrl = document.URL;
    return tmpUrl.indexOf('?') > 0 ?
        tmpUrl.split('?')[1].split('=')[1] :
        tmpUrl.split('/')[4];
}

function getFleetRange() {
    let elem = document.getElementById('fleetRange').innerHTML;
    return parseInt(elem.replace(',','').replace(',','').replace(',','')) - settings.safeDistance;
}

function getFuelAmount() {
    var spanItem = document.getElementById('fleetRange').innerHTML.replace(',','').replace(',','').replace(',','');
    return parseInt(spanItem);
}

function run() {
    fleetNumber = getFleetNumber();
    fleetRange = getFleetRange();
    fleetFuel = getFuelAmount();
    findWH().then(function(status) {
        var baseUrlLink = getMapUrl();
        findUnexploredJSV2(baseUrlLink).then(function(result) {
            if (result == false) {
                if (fleetFuel < minimumFuelAmount) {
                    console.log(`Auto-Exploration: Will Try to Refuel Probe, Only Has: ${fleetFuel.toString().replace(/(\d)(?=(\d{3})+$)/g, '$1,')} Left`);
                    let optionsElements = document.getElementById('target1').getElementsByTagName('option');
                    if (optionsElements.length == 2)
                        return alert('No Place To Re-fuel');
                    else {
                        let finalPlanet = optionsElements[2].value.split(',')[1]
                        document.getElementById('target1').value='tworld,' + finalPlanet;
                        getMission("verify", "target1")
                        setTimeout(getMission('launch'),250);
                        if (settings.nextAuto == true)
                            setTimeout(nextFleet(), 500);
                        return ;
                    }
                }
                else {
                    return alert('No System Were Found');
                }
            }
            else { // Found an Unexplored system
                window.location = result;
            }
        }).catch(function (reason) {
            console.log(reason);
        return false;
        })
    }).catch(function (reason) {
        console.log('Stopping: ' + reason);
        return false;
    });
}

function findWH(){
    var at100 = checkIf100x3();
    return new Promise(function (fulfill, reject){
        if (at100 == true)
        {
            checkForWH().then(function(isWH) {
                if (isWH == true){
                    alert('Wormhole! / Enemy');
                    return reject('Wormhole');
                }

                let fuelAmount = getFuelAmount();


                return fulfill(true);
            });
        }
        else
            return fulfill(true);
    });
}

function checkIf100x3() {
    var firstLine = document.getElementsByClassName('padding5 light tbborder')[0];
    if(firstLine.getElementsByTagName('span')[0].innerHTML == 'System: ')
        return true;
    else
        return false;
}

function checkForWH(){
    return new Promise(function (fulfill, reject){
        var link = document.getElementsByClassName('darkbutton')[3].onclick.toString();
        link = "http://www.war-facts.com/extras/scan.php" + link.substring(link.indexOf('?'), link.indexOf("')"));
        divAjaxRequest("GET", link, true, true, null).then(function(newDiv) {
            var All = newDiv.getElementsByTagName('i');
            for (let i = 0 ; i < All.length; i++)
            {
                if (All[i].innerHTML == 'Wormhole!')
                    return fulfill(true);
            }

            if (settings.alertEnemies == false)
                return fulfill(false);
            var fleets = newDiv.getElementsByClassName('tbborder padding5 light')
            for (let i =0 ; i < fleets.length; i++)
            {
                for (let j = 0; j < settings.enemiesFactions.length; j++)
                {
                    if (fleets[i].innerHTML.indexOf(settings.enemiesFactions[j]) > 0)
                        return fulfill(true);
                }
            }

            return fulfill(false);
        });
    });
}

// End Fleet Page Functions

// Javascript V2 - Functions

var mainCord;

function buildCordsObject(x,y,z) {
    return {X : parseInt(x), Y: parseInt(y), Z: parseInt(z)}
}

function getDistance(cordsA, cordsB) {
    let X = Math.pow(cordsA.X - cordsB.X, 2);
    let Y = Math.pow(cordsA.Y - cordsB.Y, 2);
    let Z = Math.pow(cordsA.Z - cordsB.Z, 2);
    let f = Math.sqrt(X + Y + Z);
    return 4000 * f;
}

function isEqule(cordsA, cordsB) {
    return (cordsA.X == cordsB.X && cordsA.Y == cordsB.Y && cordsA.Z == cordsB.Z);
}

function findUnexploredJSV2(url) {
    var newLink = extractLink(url);
    return new Promise(function (fulfill, reject){
        var allCurrentRoutes = [];
        var allOptions = [];
        sendAjaxRequest("GET", newLink, true, true, null).then(function(dom) {
            let eachLine = dom.split('\n');

            console.log(`Auto-Exploration: Got ${eachLine.length} Records To Check`);

            for (let i = 0; i < eachLine.length; i++)
            {
                let eachValue = eachLine[i].split('\t');
                if (eachValue[1] != 'f') continue;
                let cordsUsed = eachValue[7].split('');
                if (cordsUsed[0] == 0) continue;
                allCurrentRoutes.push(buildCordsObject(cordsUsed[0], cordsUsed[1], cordsUsed[2]));
            }

            console.log(`Auto-Exploration: Found ${allCurrentRoutes.length} Already Probes System`);

            for (let i = 0 ; i < eachLine.length; i++)
            {
                let eachValue = eachLine[i].split('\t');
                if (eachValue[6] != 'unexplored') continue;
                if (eachValue[1] == 'p') continue;

                let newCords = buildCordsObject(eachValue[3], eachValue[4], eachValue[5]);
                if (eachValue[3] > 1000000) continue;

                let distance = getDistance(newCords, mainCord);
                if (distance > fleetRange) continue;

                allOptions.push({C: newCords, D: distance});
            }

            console.log(`Auto-Exploration: Found ${allOptions.length} Possible Unexplored Systems To Explore`);
            allOptions.sort(function(a, b) {return a.D - b.D});

            for (let i = 0 ; i < allOptions.length; i++)
            {
                let exists = allCurrentRoutes.find(X => isEqule(X, allOptions[i].C));
                if (!exists)
                {
                    let newCords = allOptions[i].C;
                    console.log(`Auto-Exploration: Decided To Explore Option ${i+1}: (${newCords.X},${newCords.Y},${newCords.Z})`);
                    return fulfill(`http://www.war-facts.com/fleet.php?tpos=global&x=${newCords.X}&y=${newCords.Y}&z=${newCords.Z}&fleet=${fleetNumber}#callback=1`);
                }
            }
            return fulfill(false);
        });
    });
}

function getMapUrl() {
    var allNavs = document.getElementById('navData').getElementsByClassName('light tbborder padding5');
    var textItem = allNavs[allNavs.length - 1].innerHTML;
    let url = 'http://www.war-facts.com/extras/view_universe.php' + textItem.substring(textItem.indexOf('?'), textItem.indexOf("')")).replace('&amp;','&').replace('&amp;','&').replace('&amp;','&');
    return url;
}

function extractLink(url) {
    let values = url.split('?');
    let cords = values[1].split('&');
    let x = cords[0].split('=')[1];
    let y = cords[1].split('=')[1];
    let z = cords[2].split('=')[1];

    mainCord = buildCordsObject(x,y,z);
    return `http://www.war-facts.com/ajax/jsmap_postload_v2.php?centerX=${x}&centerY=${y}&centerZ=${z}&displayRange=25000`;
}

// End Find Unexplored System Functions

// Transfer to Planet Script

function addVerifyPlanetButton() {
    addOption();
    hookButton();
}

function addOption() {
    var fleetOption = document.getElementById('tpos');
    if (fleetOption)
        fleetOption.innerHTML = fleetOption.innerHTML + `<option value="planet">Planet</option>`;
}

function hookButton() {
    originalGetMission = getMission;
    getMission = function(str1, str2) {
        if (!document.getElementById('tpos') || document.getElementById('tpos').value != 'planet') {
            return originalGetMission(str1, str2);
        }
        else {
            let planetId = document.getElementById('xyz').value;
            let fleetId = getFleetNumber();
            window.location = `/fleet.php?tworld=${planetId}&fleet=${fleetId}#callback=1`;
            return;
        }
    }
}

// End Transfer to Planet Script

// Internal Explore

var wantedPlanet;

function addInternalButton()
{
    if (document.URL.indexOf('callback=1') >= 0) return;
    let amIExplorer = document.getElementById('fleetClass').innerHTML;
    let planetsList = [];

    // Check if we have Explorer Fleet and that we are not flying
    if (amIExplorer != 'Explorer' && amIExplorer != 'Sentry') return;

    let objc = document.getElementById('objective');
    if (objc == undefined) return;
    objc.value='explore';

    // Get all Planets
    let optionsElements = document.getElementById('target1').getElementsByTagName('option');
    for (let index = 2; index < optionsElements.length; index++)
        planetsList.push(optionsElements[index].value.split(',')[1]);

    // Get My Location
    let myCords = document.getElementsByClassName('light tbborder padding5')[3].getElementsByTagName('a')[0].innerHTML;
    if (myCords == '100, 100, 100 local')
        wantedPlanet = planetsList[0];
    else
    {
        let baseLink = document.getElementsByClassName('tbborder highlight overauto')[0].getElementsByTagName('A')[0].href;
        if (baseLink.indexOf('colony') >= 0)
            baseLink = document.getElementsByClassName('tbborder highlight overauto')[0].getElementsByTagName('A')[1].href;
        let extractPlanet = baseLink.substring(baseLink.indexOf('planet=')+7, baseLink.indexOf('fleet=') -1);
        let tmpPlanet = planetsList.findIndex(x => x == extractPlanet);
        if (tmpPlanet == planetsList.length - 1)
            wantedPlanet = -1;
        else
            wantedPlanet = planetsList[tmpPlanet+1];
    }

    if (wantedPlanet == -1) return;

    let newButton = document.createElement('input');
    newButton.type = 'button'
    newButton.value = 'Planet';
    newButton.style = 'width: 80px;'
    newButton.className = 'darkbutton dangerbutton';
    newButton.addEventListener("click", exploreNextPlanet);
    document.getElementsByClassName('iBlock tbborder padding5 fullwidth light')[0].insertBefore(newButton, null);
}

function exploreNextPlanet() {
    let optionsElements = document.getElementById('target1')
    optionsElements.value='tworld,' + wantedPlanet;
    getMission("verify", "target1")
    setTimeout(getMission('launch'),100);
    if (settings.nextAuto == true)
        nextFleet();
}

// End Internal Explore

// Control Panel Functions

function buildMenu() {
    let lastEle = document.getElementsByClassName('margintop padding5 highlight bold centertext box')[5];
    let div = document.createElement('div');

    div.className = "light";
    div.innerHTML = addMenu('autoExplore', "Auto-Explore").outerHTML;
    div.innerHTML += addRow(addCheckBox('autoNext', 'Auto Choose Next Free Explorer', settings.nextAuto)).outerHTML;
    div.innerHTML += addRow(addCheckBox('fullAuto', 'Auto Send Probes to Exploration (Warning - Might not be allowed - Requires AutoNext)', settings.fullAuto)).outerHTML;
    div.innerHTML += addRow(addCheckBox('detectEnemies', 'Alert When Detect Enemies (Message Box)', settings.alertEnemies)).outerHTML;
    div.innerHTML += addRow(addTextBox('enemiesFactions', 'Add Enemies Factions (Fleets from this factions will be alerted (`;` between words))', settings.enemyFactions.join(';'), 100)).outerHTML;
    div.innerHTML += addRow(addTextBox('safeDistance', 'Safe Distance (km - Reduce Destination Range)', settings.safeDistance)).outerHTML;
    div.innerHTML += addRow(addCheckBox('whiteList', 'White List Fleets Name (Only Names Below Will Be Choosen as Next Explorer)', settings.whiteList)).outerHTML;
    div.innerHTML += addRow(addTextBox('fleetNames', 'Allowed Fleet Names (Fleet thats includes one of this words will be choosed (`;` between words))', settings.goodNames.join(';'), 100)).outerHTML;
    div.innerHTML += addRow(addTextBox('ignoreLetter', 'Ignore Symbol (Fleets with this symbol will be ignored)', settings.badLetter, 10)).outerHTML;
    div.innerHTML += addRow(addSubmit()).outerHTML;

    lastEle.parentElement.insertBefore(div, lastEle);
    document.getElementById('exploreSubmit').addEventListener('click', updateSettings);
}

function addMenu(id, text) {
    let div = document.createElement('div');
    div.className = "margintop padding5 highlight bold centertext box";
    div.id = id;
    div.innerHTML = text;
    return div;
}

function addCheckBox(id, header, checked) {
    let div = addItem(header);
    header = header.split(' ')[0];
    div.innerHTML += `<input type="checkbox" class="checkbox" id="${id}" ${checked == 1 ? "checked" : ""}>`;
    return div;
}

function addTextBox(id, header, data, big = 10) {
    let div = addItem(header);
    header = header.split(' ')[0];
    div.innerHTML += `<input type="text" class="text" id="${id}" value="${data}" size="${big}" maxlength="${big}">`;
    return div;
}

function addSubmit() {
    let div = document.createElement('input');
    div.type = "submit";
    div.className = "darkbutton greenbutton width75";
    div.value = "Modify";
    div.id = "exploreSubmit";
    return div;
}

function addRow(item) {
    let div = document.createElement('div');
    div.className = "tbborder padding5";
    div.innerHTML = item.outerHTML;
    return div;
}
function addItem(header) {
    let div = document.createElement('div');
    div.className = 'light padding5';
    div.innerHTML = `${header}: `;
    return div;
}

function loadSettings() {
    let data = GM_getValue('auto-explore-settings');
    if (!data)
        return getSettings(fullAuto, autoSwitchToNextFleet, showEnemies, safeDistance, whiteList, fleetsName, abortletter, enemiesFactions)

    var allData = data.split('&');

    return getSettings(
        allData[0] == 0 ? false : true,
        allData[1] == 0 ? false : true,
        allData[2] == 0 ? false : true,
        allData[3],
        allData[4] == 0 ? false : true,
        allData[5].split(';'),
        allData[6],
        allData[7].split(';')
    );
}

function updateSettings() {
    let autoNext = document.getElementById('autoNext').checked;
    let fullAuto = document.getElementById('fullAuto').checked;
    let detectEnemies = document.getElementById('detectEnemies').checked;
    let safeDistance = document.getElementById('safeDistance').value;
    let whiteList = document.getElementById('whiteList').checked;
    let fleetNames = document.getElementById('fleetNames').value;
    let ignoreLetter = document.getElementById('ignoreLetter').value;
    let enemiesFactions = document.getElementById('enemiesFactions').value;

    saveSettings(fullAuto, autoNext, detectEnemies, safeDistance, whiteList, fleetNames, ignoreLetter, enemiesFactions);
}

function saveSettings(full, next, alert, safe, white, gNames, bNames, eFactions) {
    let data = getSettings(
        full == false ? 0 : 1,
        next == false ? 0 : 1,
        alert == false ? 0 : 1,
        safe,
        white == false ? 0 : 1,
        gNames,
        bNames,
        eFactions
     );

    let makestring = `${data.fullAuto}&${data.nextAuto}&${data.alertEnemies}&${data.safeDistance}&${data.whiteList}&${data.goodNames}&${data.badLetter}&${data.enemyFactions}`;
    GM_setValue('auto-explore-settings', makestring);
    location.reload();
}

function getSettings(full, next, alert, safe, white, gNames, bNames, eFactions) {
    return { fullAuto: full, nextAuto: next, alertEnemies: alert, safeDistance:safe, whiteList:white, goodNames: gNames, badLetter: bNames, enemyFactions: eFactions };
}

// End Settings

// Utilities

function sendAjaxRequest(type, link, async, withResponse, params) {
    return new Promise(function (fulfill, reject){
        var xhttp = new XMLHttpRequest();
        xhttp.open(type, link , true);
        xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        xhttp.send(params);
        xhttp.onreadystatechange = function () {
          if(xhttp.readyState === 4 && xhttp.status === 200) {
              if (withResponse == true)
                  fulfill(xhttp.responseText);
              else
                  fulfill();
          }
        };
    });
}

function divAjaxRequest(type, link, async, withResponse, params) {
    return new Promise(function (fulfill, reject){
        sendAjaxRequest(type, link, async, withResponse, params).then(function(html){
            var div = document.createElement('div');
            div.innerHTML = html;
            return fulfill(div);
        });
    });
}