Sleazy Fork is available in English.

HaremHeroes Automatic++

Open the menu in HaremHeroes(topright) to toggle AutoControlls. Supports AutoSalary, AutoContest, AutoMission, AutoQuest, AutoTrollBattle, AutoArenaBattle and AutoPachinko(Free), AutoLeagues, AutoChampions and AutoStatUpgrades. Messages are printed in local console.

Від 29.11.2019. Дивіться остання версія.

// ==UserScript==
// @name         HaremHeroes Automatic++
// @namespace    JDscripts
// @version      4.301
// @description  Open the menu in HaremHeroes(topright) to toggle AutoControlls. Supports AutoSalary, AutoContest, AutoMission, AutoQuest, AutoTrollBattle, AutoArenaBattle and AutoPachinko(Free), AutoLeagues, AutoChampions and AutoStatUpgrades. Messages are printed in local console.
// @author       JD and Dorten(a bit)
// @match        http*://nutaku.haremheroes.com/*
// @match        http*://*.hentaiheroes.com/*
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

GM_addStyle('/* The switch - the box around the slider */ .switch { position: relative; display: inline-block; width: 40px; height: 24px; } /* Hide default HTML checkbox */ .switch input {display:none;} /* The slider */ .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; -webkit-transition: .4s; transition: .4s; } .slider.round:before { position: absolute; content: ""; height: 16px; width: 16px; left: 4px; bottom: 4px; background-color: white; -webkit-transition: .4s; transition: .4s; } input:checked + .slider { background-color: #2196F3; } input:focus + .slider { box-shadow: 0 0 1px #2196F3; } input:checked + .slider:before { -webkit-transform: translateX(16px); -ms-transform: translateX(16px); transform: translateX(16px); } /* Rounded sliders */ .slider.round { border-radius: 24px; } .slider.round:before { border-radius: 50%; }');

// var d="@require      https://cdn.jsdelivr.net/js-cookie/2.2.0/js.cookie.js"

function Storage()
{
    return localStorage.settPerTab=="true"?sessionStorage:localStorage;
}

function getHero()
{
    if(unsafeWindow.Hero === undefined)
    {
        setTimeout(autoLoop, Number(Storage().autoLoopTimeMili))
        //console.log(window.wrappedJSObject)
    }
    //console.log(unsafeWindow.Hero);
    return unsafeWindow.Hero;
}

function getGirlsMap()
{
    return unsafeWindow.GirlSalaryManager.girlsMap;
}

function getPage()
{
    try{
        var ob = document.getElementById("hh_nutaku");
        if(ob===undefined || ob === null)
        {
            ob = document.getElementById("hh_hentai");
        }
        var p=ob.className.match(/.*page-(.*) .*/i)[1];
        if (p=="missions" && $('h4.contests.selected').size()>0)
        {
            return "activities"
        }
        else
        {
            return p;
        }
    }
    catch(err)
    {
        return ""
    }
}

function url_add_param(url, param) {
	if (url.indexOf('?') === -1) url += '?';
	else url += '&';
	return url+param;
}

// Retruns true if on correct page.
function gotoPage(page)
{
    var cp=getPage();
    console.log('going '+cp+'->'+page);
    if(getPage() === page)
    {
        if (page=='missions')
        {
            $('h4.missions').each(function(){this.click();});
        }
        if (page=='activities')
        {
            $('h4.contests').each(function(){this.click();});
        }

        return true;
    }
    else
    {
        console.log("Navigating to page: "+page);
        var togoto = undefined;
        // get page path
        switch(page)
        {
            case "missions":
            case "activities":
                togoto = $("nav div[rel='content'] a:has(.activities)").attr("href");
                break;
            case "harem":
                togoto = $("nav div[rel='content'] a:has(.harem)").attr("href");
                break;
            case "map":
                togoto = $("nav div[rel='content'] a:has(.map)").attr("href");
                break;
            case "arena":
                togoto = $("nav div[rel='content'] a:has(.battle)").attr("href");
                break;
            case "pachinko":
                togoto = $("nav div[rel='content'] a:has(.pachinko)").attr("href");
                break;
            case "leaderboard":
                togoto = $("nav div[rel='content'] a:has(.leaderboard)").attr("href");
                break;
            case "shop":
                togoto = $("nav div[rel='content'] a:has(.shop)").attr("href");
                break;
            case "quest":
                togoto = getHero().infos.questing.current_url;
                if (togoto.includes("world"))
                {
                    console.log("All quests finished, turning off AutoQuest!");
                    Storage().autoQuest = false;
                    location.reload();
                    return false;
                }
                console.log("Current quest page: "+togoto);
                break;
            case "champions_map":
                togoto = $("nav div[rel='content'] a:has(.champions)").attr("href");
                break;
            default:
                console.log("Unknown goto page request. No page \'"+page+"\' defined.");
        }
        if(togoto != undefined)
        {
            if (page=="missions")
            {
                togoto = url_add_param(togoto, "tab=" + "missions");
            }
            if (page=="activities")
            {
                togoto = url_add_param(togoto, "tab=" + "contests");
            }
            sessionStorage.autoLoop = "false";
            window.location = window.location.origin + togoto;
        }
        else console.log("Couldn't find page path. Page was undefined...");
        return false;
    }
}

var proceedQuest = function () {
    //console.log("Starting auto quest.");
    // Check if at correct page.
    if (!gotoPage("quest")) {
        // Click on current quest to naviagte to it.
        console.log("Navigating to current quest.");
        return;
    }
    $("#popup_message close").click();
    // Get the proceed button type
    var proceedButtonMatch = $("#controls button:not([style='display: none;'])");
    if (proceedButtonMatch.length === 0){proceedButtonMatch = $("#controls button[act='free']");}
    var proceedCostEnergy = Number($("#controls .cost span[cur='*']").text());
    var units = [" ", "K", "M", "G", "T", "P", "E", "Z", "Y"]
    var proceedCostMoney = $("#controls .cost span[cur='$']").text();
    var Unit=proceedCostMoney.substr(-1);
    if (units.includes(Unit))
    {
        proceedCostMoney=Number(proceedCostMoney.split(Unit)[0].replace(",","").trim())*(1000**units.indexOf(Unit))
    }
    else
    {
        proceedCostMoney=Number(proceedCostMoney.replace(",","").trim());
    }

    var proceedType = proceedButtonMatch.attr("act");

    if (proceedButtonMatch.length === 0) console.log("Could not find resume button.");
    else if (proceedType === "free") {
        console.log("Proceeding for free.");
        proceedButtonMatch.click();
    }
    else if (proceedType === "pay") {
        var energyCurrent = getHero().infos.energy_quest;
        var moneyCurrent = getHero().infos.soft_currency;
        if(proceedCostEnergy <= energyCurrent)
        {
            // We have energy.
            console.log("Spending "+proceedCostEnergy+" Energy to proceed.");
        }
        else
        {
            console.log("Quest requires "+proceedCostEnergy+" Energy to proceed.");
            sessionStorage.questRequirement = "*"+proceedCostEnergy;
            return;
        }
        if(proceedCostMoney <= moneyCurrent)
        {
            // We have money.
            console.log("Spending "+proceedCostMoney+" Money to proceed.");
        }
        else
        {
            console.log("Spending "+proceedCostEnergy+" Energy to proceed.");
            sessionStorage.questRequirement = "$"+proceedCostMoney;
            return;
        }
        proceedButtonMatch.click();
        sessionStorage.autoLoop = "false";
        location.reload();
    }
    else if (proceedType === "use_item") {
        console.log("Proceeding by using X" + Number($("#controls .item span").text()) + " of the required item.");
        proceedButtonMatch.click();
    }
    else if (proceedType === "battle") {
        console.log("Proceeding to battle troll...");
        sessionStorage.questRequirement = "battle";
        // Proceed to battle troll.
        proceedButtonMatch.click();
        sessionStorage.autoLoop = "false";
        location.reload();
    }
    else if (proceedType === "end_archive") {
        console.log("Reached end of current archive. Proceeding to next archive.");
        sessionStorage.autoLoop = "false";
        proceedButtonMatch.click();
    }
    else if (proceedType === "end_play") {
        console.log("Reached end of current play. Proceeding to next play.");
        sessionStorage.autoLoop = "false";
        proceedButtonMatch.click();
    }
    else {
        console.log("Could not identify given resume button.");
        sessionStorage.questRequirement = "unknownQuestButton";
    }
};

/**
* Recieves a list of mission objects and returns the mission object to use.
* A mission object looks similar to this :-
* Eg 1:   {"id_member_mission":"256160093","id_mission":"23","duration":"53","cost":"1","remaining_time":"-83057","rewards":[{"classList":{"0":"slot","1":"slot_xp"},"type":"xp","data":28},{"classList":{"0":"slot","1":"slot_SC"},"type":"money","data":277}]}
* Eg 2:   {"id_member_mission":"256160095","id_mission":"10","duration":"53","cost":"1","remaining_time":"-81330","rewards":[{"classList":{"0":"slot","1":"slot_xp"},"type":"xp","data":28},{"classList":{"0":"slot","1":"rare"},"type":"item","data":{"id_item":"23","type":"gift","subtype":"0","identifier":"K3","rarity":"rare","value":"80","carac1":0,"carac2":0,"carac3":0,"endurance":0,"chance":0,"ego":0,"damage":0,"duration":0,"level_mini":"1","name":"Bracelet","Name":"Bracelet","ico":"https://content.haremheroes.com/pictures/items/K3.png","price_sell":5561,"count":1,"id_m_i":[]}}]}
* Eg 3:   {"id_member_mission":"256822795","id_mission":"337","duration":"17172","cost":"144","remaining_time":null,"remaining_cost":"144","rewards":[{"classList":{"0":"slot","1":"slot_HC"},"type":"koban","data":11}]}
* Eg 1 has mission rewards of xp and money.
* Eg 2 has mission rewards of xp and item.
* Eg 3 has mission rewards of koban/hard_currency.
* cost is the koban price for instant complete.
*/
function getSuitableMission(missionsList)
{
    var msn = missionsList[0];
    for(var m in missionsList)
    {
        if(Number(msn.duration) > Number(missionsList[m].duration))
        {
            msn = missionsList[m];
        }
    }
    return msn;
}

// returns boolean to set busy
function doMissionStuff()
{
    if(!gotoPage("missions"))
    {
        console.log("Navigating to activities page.");
        // return busy
        return true;
    }
    else
    {
        console.log("On activities page.");
        console.log("Collecting finished mission's reward.");
        $(".mission_button button:visible[rel='claim']").click();
        // TODO: select new missions and parse reward data from HTML, it's there in data attributes of tags
        var missions = [];
        var allGood = true;
        // parse missions
        $(".mission_object").each(function(idx,missionObject){
            var data = $.data(missionObject).d;
            // Do not list completed missions
            if(data.remaining_time !== null){
                // This is not a fresh mission
                if(data.remaining_time > 0)
                {
                    console.log("Unfinished mission detected...("+data.remaining_time+"sec. remaining)");
                    setTimer('nextMissionTime',Number(data.remaining_time)+1);
                }
                else{
                    console.log("Unclaimed mission detected...");
                }
                allGood = false;
                return;
            }
            data.missionObject = missionObject;
            var rewards = [];
            // set rewards
            {
                // get Reward slots
                var slots = missionObject.querySelectorAll(".slot");
                // traverse slots
                $.each(slots,function(idx,slotDiv){
                    var reward = {};
                    // get slot class list
                    reward.classList = slotDiv.classList;
                    // set reward type
                    if(reward.classList.contains("slot_xp"))reward.type = "xp";
                    else if(reward.classList.contains("slot_SC"))reward.type = "money";
                    else if(reward.classList.contains("slot_HC"))reward.type = "koban";
                    else reward.type = "item";
                    // set value if xp
                    if(reward.type === "xp" || reward.type === "money" || reward.type === "koban")
                    {
                        // remove all non numbers and HTML tags
                        try{
                            reward.data = Number(slotDiv.innerHTML.replace(/<.*?>/g,'').replace(/\D/g,''));
                        }
                        catch(e){
                            console.log("Couldn't parse xp/money data.");
                            console.log(slotDiv);
                        }
                    }
                    // set item details if item
                    else if(reward.type === "item")
                    {
                        try{
                            reward.data = $.data(slotDiv).d;
                        }
                        catch(e){
                            console.log("Couldn't parse item reward slot details.");
                            console.log(slotDiv);
                            reward.type = "unknown";
                        }
                    }
                    rewards.push(reward);
                });
            }
            data.rewards = rewards;
            missions.push(data);
        });
        if(!allGood){
            console.log("Something went wrong, need to retry later...");
            // busy
            return true;
        }
        console.log("Missions parsed, mission list is:-");
        console.log(missions);
        if(missions.length > 0)
        {
            console.log("Selecting mission from list.");
            var mission = getSuitableMission(missions);
            console.log("Selected mission:-");
            console.log(mission);
            console.log("Selected mission duration: "+mission.duration+"sec.");
            var missionButton = $(mission.missionObject).find("button:visible").first();
            console.log("Mission button of type: "+missionButton.attr("rel"));
            console.log("Clicking mission button.");
            missionButton.click();
            setTimer('nextMissionTime',Number(mission.duration)+1);
        }
        else{
            console.log("No missions detected...!");
            // get gift
            var ck = sessionStorage['giftleft'];
            var isAfterGift = document.querySelector("#missions .after_gift").style.display === 'block';
            if(!isAfterGift){
                if(ck === undefined || ck === 'giftleft')
                {
                    console.log("Collecting gift.");
                    delete sessionStorage['giftleft'];
                    document.querySelector(".end_gift button").click();
                }
                else{
                    console.log("Refreshing to collect gift...");
                    sessionStorage['giftleft']='giftleft';
                    window.reload();
                    // is busy
                    return true;
                }
            }
            var time = 0;
            for(var e in unsafeWindow.HHTimers.timers){
                try{if(unsafeWindow.HHTimers.timers[e].$elm.selector.includes("#missions_counter"))
                    time=unsafeWindow.HHTimers.timers[e];
                   }
                catch(e){}
            }
            if (time !== undefined)
            {
                time = time.remainingTime;
            }
            if(time === undefined)
            {
                //try again with different selector
                for(e in unsafeWindow.HHTimers.timers){
                    try{if(unsafeWindow.HHTimers.timers[e].$elm.selector.includes(".after_gift"))
                        time=unsafeWindow.HHTimers.timers[e];
                       }
                    catch(e){}
                }
                if (time !== undefined)
                {
                    time = time.remainingTime;
                }
            }
            if(time === undefined){
                console.log("New mission time was undefined... Setting it manually to 10min.");
                time = 10*60;
            }
            setTimer('nextMissionTime',Number(time)+1);
        }
        // not busy
        return false;
    }
}

// returns boolean to set busy
function doContestStuff()
{
    if(!gotoPage("activities"))
    {
        console.log("Navigating to activities page.");
        // return busy
        return true;
    }
    else
    {
        console.log("On activities page.");
        console.log("Collecting finished contests's reward.");
        $(".contest .ended button[rel='claim']").click();
        // need to get next contest timer data
        var time = 0;
        for(var e in unsafeWindow.HHTimers.timers){
            try{if(unsafeWindow.HHTimers.timers[e].$barElm/*.selector.includes(".contest_timer")*/)
                time=unsafeWindow.HHTimers.timers[e];
               }
            catch(e){}
        }
        time = time.remainingTime;
        try{if(time === undefined)
        {
            //try again with different selector
            time = undefined;
            for(e in unsafeWindow.HHTimers.timers){
                if(unsafeWindow.HHTimers.timers[e].$elm && unsafeWindow.HHTimers.timers[e].$elm[0].className.includes("contest_timer"))
                    // get closest time
                    if(!(unsafeWindow.HHTimers.timers[e].remainingTime>time))
                        time=unsafeWindow.HHTimers.timers[e].remainingTime;
            }
        }}catch(e){}
        if(time === undefined){
            console.log("New contest time was undefined... Setting it manually to 10min.");
            time = 10*60;
        }
        setTimer('nextContestTime',Number(time)+1);
        // Not busy
        return false;
    }
}

function randomInterval(min,max) // min and max included
{
    return Math.floor(Math.random()*(max-min+1)+min);
}

var CollectMoney = function()
{
    var Clicked=[];
    var ToClick=[];

    function ClickThem()
    {
        //console.log('Need to click: ',ToClick.length);
        if (ToClick.length>0)
        {
            //console.log('clicking N ',ToClick[0].formAction.split('/').last())
            $(ToClick[0]).click();
            ToClick.shift();
            //console.log('will click again');
            setTimeout(ClickThem,randomInterval(300,900));

            window.top.postMessage({ImAlive:true},'*');
        }
        else
        {
            //console.log('nothing to click, checking data');
            CollectData();
        }
    }

    function CollectData()
    {
        var btns=$("#harem_whole #harem_left .salary:not('.loads') button");
        //console.log('buttons: ',btns.size())
        btns.each(function (index, element) {
            //console.log(index,element.formAction);
            var gid=Number(element.parentElement.parentElement.parentElement.getAttribute('girl'));
            //console.log('checking '+gid);
            if (!Clicked.includes(gid))
            {
                Clicked.push(gid);
                ToClick.push(element);
                //console.log('added! ',Clicked,ToClick);
            }
        });

        console.log('Collected Data: ',Clicked,ToClick);

        if (ToClick.length>0)
        {
            //console.log('clicking!');
            setTimeout(ClickThem,randomInterval(150,500));
        }
        else//nothing to collect
        {
            var closestTime = undefined;
            var closestGirl = 0;
            var gMap = getGirlsMap();
            if(gMap === undefined)
            {
                // error
                console.log("Girls Map was undefined...! Error, manually setting salary time to 2 min.");
                closestTime = 2*60;
            }
            else
            {
                try{
                    // Calc. closest time
                    for(var key in gMap)
                    {
                        // undefined comparision is always false so first iteration is false, hence the not(!)
                        if(!(closestTime<gMap[key].gData.pay_in) && !Clicked.includes(key) && gMap[key].gData.pay_in!=0)
                        {
                            closestTime = gMap[key].gData.pay_in;
                            closestGirl = key;
                        }
                    }
                }
                catch(exp){
                    // error
                    console.log("Girls Map had undefined property...! Error, manually setting salary time to 2 min.");
                    closestTime = 2*60;
                }
            }
            if(closestTime === undefined)
            {
                console.log("closestTime was undefined...! Error, manually setting salary time to 2 min.");
                closestTime = 2*60;
            }
            if(closestTime <= 2*60 )
            {
                console.log("closestTime is "+closestTime+" ("+closestGirl+") less than/equal to 15 sec. Fuck it. It's buggy. NOT staying on this page");
                closestTime = 2*60;
            }
            setTimer('nextSalaryTime',Number(closestTime)+1);
            sessionStorage.autoLoop = "true";
            setTimeout(autoLoop, Number(Storage().autoLoopTimeMili));
        }
    }

    CollectData();
}

var getSalary = function () {
    try {
        if(!gotoPage("harem"))
        {
            // Not at Harem screen then goto the Harem screen.
            console.log("Navigating to Harem window.");
            // return busy
            return true;
        }
        else {
            console.log("Detected Harem Screen. Fetching Salary");
            is_cheat_click=function(e) {
                return false;
            };
            sessionStorage.autoLoop = "false";
            CollectMoney();
            // return busy
            return true;
        }
    }
    catch (ex) {
        console.log("Could not collect salary... " + ex);
        // return not busy
        return false;
    }
};

var doStatUpgrades=function()
{
    //Stats?
    //console.log('stats');
    var Hero=getHero();
    var level=Hero.infos.level;
    var stats=[Hero.infos.carac1,Hero.infos.carac2,Hero.infos.carac3];
    var money=Hero.infos.soft_currency;
    var count=0;
    var M=Storage().autoStats?Number(Storage().autoStats):500000000;
    var MainStat=stats[Hero.infos.class-1];
    var Limit=Hero.infos.level*30;//Hero.infos.level*19+Math.min(Hero.infos.level,25)*21;
    var carac=Hero.infos.class;
    var mp=0;
    for (var car=0; car<3; car++)
    {
        //console.log('stat '+carac);
        var s=stats[carac-1];
        var price = 5+s*2+(Math.max(0,s-2000)*2)+(Math.max(0,s-4000)*2)+(Math.max(0,s-6000)*2)+(Math.max(0,s-8000)*2);
        if (carac==Hero.infos.class)
        {
            mp=price;
        }
        //console.log('money: '+money+' stat'+carac+': '+stats[carac-1]+' price: '+price);
        if (stats[carac-1]<Limit && (money-price)>M && (carac==Hero.infos.class || price<mp/2 || MainStat==Limit))
        {
            count++;
            console.log('money: '+money+' stat'+carac+': '+stats[carac-1]+' price: '+price);
            money-=price;
            var params = {
                class: "Hero",
                carac: carac,
                action: "update_stats"
            };
            hh_ajax(params, function(data) {

            });
        }
        carac=(carac+1)%3+1;
    }
}

var doShopping=function()
{
    try
    {
        var Hero=getHero();
        var MS='carac'+Hero.infos.class;
        var SS1='carac'+(Hero.infos.class%3+1);
        var SS2='carac'+((Hero.infos.class+1)%3+1);
        var money=Hero.infos.soft_currency;

        try
        {
            var shop=JSON.parse(sessionStorage.storeContents);
        }
        catch(wtf)
        {
            sessionStorage.charLevel=0;
            return;
        }

		if (!sessionStorage.haveAff)
		{
			sessionStorage.charLevel=0;
            return;
		}

		var LGM=Number(Storage().autoLGM);
		var EGM=Number(Storage().autoEGM);
		var LGR=Number(Storage().autoLGR);
		var Exp=Number(Storage().autoExp);
		var Aff=Number(Storage().autoAff);
		var MaxAff=Number(Storage().MaxAff);
		var MaxExp=Number(Storage().MaxExp);
		var HaveAff=Number(sessionStorage.haveAff);
		var HaveExp=Number(sessionStorage.haveExp);

		console.log(HaveAff,HaveExp);

        if (Storage().autoLGMW==="true" || Storage().autoLGRW==="true" || Storage().autoEGMW==="true")
        {
            //console.log('items');
            var Was=shop[0].length;
            for (var n=shop[0].length-1;n>=0;n--)
            {

                if (Storage().autoLGMW==="true" && money>=LGM+Number(shop[0][n].price) && shop[0][n][MS]>0 && shop[0][n][SS1]==0 && shop[0][n][SS2]==0 && shop[0][n].chance==0 && shop[0][n].endurance==0 && shop[0][n].rarity=='legendary'||
                   Storage().autoEGMW==="true" && money>=EGM+Number(shop[0][n].price) && shop[0][n][MS]>0 && shop[0][n][SS1]==0 && shop[0][n][SS2]==0 && shop[0][n].chance==0 && shop[0][n].endurance==0 && shop[0][n].rarity=='epic'||
                   Storage().autoLGRW==="true" && money>=LGR+Number(shop[0][n].price) && shop[0][n][MS]>0 && shop[0][n][SS1]>0 && shop[0][n][SS2]>0 && shop[0][n].rarity=='legendary')
                {
                    console.log('wanna buy ',shop[0][n]);
                    if (money>=shop[0][n].price)
                    {
                        console.log("yay?");
                        money-=shop[0][n].price;
                        var params = {
                            class: "Item",
                            action: "buy",
                            id_item: shop[0][n].id_item,
                            type: "armor",
                            who: 1,
                            id_skin: shop[0][n].id_skin,
                            id_equip: shop[0][n].id_equip,
                        };
                        hh_ajax(params, function(data) {

                        });
                        shop[0].splice(n,1);
                    }
                    else
                    {
                        console.log("but can't");
                    }
                }
            }
            if (shop[0].length==0 && Was>0)
            {
                sessionStorage.charLevel=0;
            }
        }

        if (Storage().autoAffW==="true" && HaveAff<MaxAff)
        {
            //console.log('gifts');
            Was=shop[1].length;
            for (var nn=shop[1].length-1;nn>=0;nn--)
            {
                console.log('wanna buy ',shop[1][nn]);
                    if (money>=Aff+Number(shop[1][nn].price) && money>=shop[1][nn].price)
                    {
                        console.log("yay?");
                        money-=shop[1][nn].price;
                        var params2 = {
                            class: "Item",
                            action: "buy",
                            id_item: shop[1][nn].id_item,
                            type: "gift",
                            who: 1
                        };
                        hh_ajax(params2, function(data) {

                        });
                        shop[1].splice(nn,1);
                    }
                    else
                    {
                        console.log("but can't");
                    }
            }
            if (shop[1].length==0 && Was>0)
            {
                sessionStorage.charLevel=0;
            }
        }

        if (Storage().autoExpW==="true" && HaveExp<MaxExp)
        {
            //console.log('books');
            Was=shop[2].length;
            for (var nnn=shop[2].length-1;nnn>=0;nnn--)
            {
                console.log('wanna buy ',shop[2][nnn]);
                    if (money>=Exp+Number(shop[2][nnn].price) && money>=shop[2][nnn].price)
                    {
                        console.log("yay?");
                        money-=shop[2][nnn].price;
                        var params3 = {
                            class: "Item",
                            action: "buy",
                            id_item: shop[2][nnn].id_item,
                            type: "potion",
                            who: 1
                        };
                        hh_ajax(params3, function(data) {

                        });
                        shop[2].splice(nnn,1);
                    }
                    else
                    {
                        console.log("but can't");
                    }
            }
            if (shop[2].length==0 && Was>0)
            {
                sessionStorage.charLevel=0;
            }
        }
        sessionStorage.storeContents=JSON.stringify(shop);
        unsafeWindow.Hero.infos.soft_currency=money;
    }
    catch (ex)
    {
        console.log(ex);
        sessionStorage.charLevel=0;
    }
}

var doBossBattle = function()
{
    var currentPower = getHero().infos.energy_fight;
    if(currentPower < 1)
    {
        //console.log("No power for battle.");
        return;
    }

    var TTF;
    if (Storage().plusEvent=="true" && !checkTimer("eventGoing") && sessionStorage.eventTroll)
    {
        TTF=sessionStorage.eventTroll;
        console.log("Event troll fight");
    }
    else if(Storage().trollToFight !== undefined && !isNaN(Storage().trollToFight) && Storage().trollToFight !== "0")
    {
        TTF=Storage().trollToFight;
        console.log("Custom troll fight.");
    }
    else
    {
        TTF=getHero().infos.questing.id_world-1;
        console.log("Last troll fight");
    }

    console.log("Fighting troll N "+TTF);
    console.log("Going to crush: "+Trollz[Number(TTF)]);

    // Battles the latest boss.
    // Navigate to latest boss.
    //console.log('!!!!!',window.location.href,window.location.href=="/battle.html?id_troll=" + TTF);
    if(window.location.pathname=="/battle.html" && window.location.search=="?id_troll=" + TTF)
    {
        // On the battle screen.
        CrushThem();
    }
    else
    {
        console.log("Navigating to chosen Troll.");
        sessionStorage.autoLoop = "false";
        location.href = "/battle.html?id_troll=" + TTF;
        return true;
    }
};

var doChampionStuff=function()
{
    var page=getPage();
    if (page=='champions')
    {
        console.log('on champion page');
        if ($('button[rel=perform].green_button_L').length==0)
        {
            console.log('Something is wrong!');
            location.href = "/home.html";
            return true;
        }
        else
        {
            var TCount=$('span[cur=ticket]')[0].innerText.split(' ')[1];
            var ECount= getHero().infos.energy_quest;
            console.log("T:"+TCount+" E:"+ECount+" "+(Storage().autoChampsUseEne==="true"))
            if ((ECount<60 || Storage().autoChampsUseEne!=="true") && TCount=="0")
            {
                console.log("No tickets/energy!");
                setTimer('nextChampionTime',15*60);
                return false;
            }
            else
            {
                if (ECount>=60 && Storage().autoChampsUseEne==="true")
                {
                    console.log("Using energy");
                    $('button[rel=perform].green_button_L').click();
                }
                else if (TCount!="0")
                {
                    console.log("Using ticket");
                    $('button[rel=perform].blue_button_L').click();
                }
                setTimeout(function(){gotoPage('champions_map');},500);
                return true;
            }
        }
    }
    else if (page=='champions_map')
    {
        console.log('on champion map');
        for (let i=0;i<$('span.stage-bar-tier').length;i++)
        {
            let Impression=$('span.stage-bar-tier')[i].getAttribute("hh_title");
            let Started=Impression.split('/')[0]!="0";
            let OnTimer=$($('a.champion-lair div.champion-lair-name')[i+1]).find('div[rel=timer]').length>0;
            console.log("Champion "+(i+1)+" ["+Impression+"]"+(Started?" Started":" Not started")+(OnTimer?" on timer":" not on timer"));

            if (Started && !OnTimer)
            {
                console.log("Let's do him!");
                window.location = window.location.origin + '/champions/'+(i+1);
                return true;
            }
        }
        console.log("No good candidate");
        setTimer('nextChampionTime',15*60);
        return false;
    }
    else
    {
        gotoPage('champions_map');
        return true;
    }
}

var doBattle = function () {
    //console.log("Performing auto battle.");
    // Confirm if on correct screen.
    var page = getPage();
    if(page === "arena")
    {
        if ($("#arena[class='canvas']").length === 1) {
            // Oponent choose screen
            console.log("On opponent choose screen.");
            if(document.getElementById("popups").style.display === "block")
            {
                console.log("Popup detetcted. Refresh page.");
                unsafeWindow.reload();
                return;
            }
            else{
                console.log("No popups.");
            }

            var fought = sessionStorage.fought?sessionStorage.fought:0;
            console.log('already fought: '+fought);
            if(fought>=3)
            {
                console.log("No arena opponents found, storing nextArenaTime...")
                var arenatime = 0;
                for(var e in unsafeWindow.HHTimers.timers){
                    try{
                        if(unsafeWindow.HHTimers.timers[e].$elm.selector.startsWith(".arena_refresh_counter"))
                        arenatime=unsafeWindow.HHTimers.timers[e];
                       }
                    catch(e){}
                }
                arenatime = arenatime.remainingTime;
                setTimer('nextArenaTime',Number(arenatime)+1);
                sessionStorage.fought=0;
                return;
            }
            //selbutton[0].click();
            sessionStorage.autoLoop = "false";
            sessionStorage.fought=Number(fought)+1;
            window.location = window.location.origin + '/battle.html?id_arena='+fought;
        }
    }
    else if (page==="battle")
    {
        CrushThem();
    }
    else
    {
        // Switch to the correct screen
        console.log("Switching to battle screen.");
        gotoPage("arena");
        return;
    }
};

var doLeagueBattle = function () {
    //console.log("Performing auto leagues.");
    // Confirm if on correct screen.
    var currentPower = getHero().infos.energy_challenge;
    var ltime;

    var page = getPage();
    if(page==='battle')
    {
        // On the battle screen.
        CrushThem();
    }
    else if(page === "leaderboard")
    {
       // console.log('ls! '+$('h4.leagues').size());
        $('h4.leagues').each(function(){this.click();});

        if(currentPower < 1)
        {
            console.log("No power for leagues.");
            for(var e in unsafeWindow.HHTimers.timers){
               try{
                   if(unsafeWindow.HHTimers.timers[e].type=="energy_challenge")
                       ltime=unsafeWindow.HHTimers.timers[e];
                   }
               catch(e){}
               }
            ltime = Number(ltime.remainingTime)+15;
            setTimer('nextLeaguesTime',ltime);
            return;
        }

        while ($("span[sort_by='level'][select='asc']").size()==0)
        {
            console.log('resorting');
            $("span[sort_by='level']").each(function(){this.click()});
        }
        console.log('parsing enemies');
        var Data=[];
        $(".leadTable[sorting_table] tr").each(function(){if (this.cells[3].innerHTML==='0/3' || this.cells[3].innerHTML==='1/3' || this.cells[3].innerHTML==='2/3'){Data.push(this);}});
        if (Data.length==0)
        {
            ltime=35*60;
            console.log('No valid targets!');
            setTimer('nextLeaguesTime',ltime);
        }
        else
        {
            console.log(Data.length+' valid targets!');
            sessionStorage.autoLoop = "false";
            console.log("Hit?");
            location.href = "/battle.html?league_battle=1&id_member=" + $(Data[0]).attr("sorting_id")
        }
    }
    else if (page==="battle")
    {
        CrushThem();
    }
    else
    {
        // Switch to the correct screen
        console.log("Switching to leagues screen.");
        gotoPage("leaderboard");
        return;
    }
};

var  CrushThem = function()
{
    if (getPage() === "battle") {
        // On battle page.
        if ($("#rewards_popup .blue_text_button").size()>0)
        {
            $("#rewards_popup .blue_text_button").click();
        }
        if ($("#rewards_popup .blue_button_L").size()>0)
        {
            $("#rewards_popup .blue_button_L").click();
        }

        //console.log("On Battle Page.");
        if ($("#battle[class='canvas']").length === 1) {
            // Battle screen
            console.log("On battle screen.");
            // get button with no autofight, i.e. no koban
            var battleButton = $('#battle button[rel="launch"]:not(.autofight)');
            //console.log(battleButton.get());
            //console.log(battleButton);
            var currentPower = getHero().infos.energy_fight;
            if(battleButton === undefined){
                console.log("Battle Button was undefined. Disabling all auto-battle.");
                document.getElementById("autoBattleCheckbox").checked = false;
                document.getElementById("autoArenaCheckbox").checked = false;
                if (sessionStorage.questRequirement === "battle")
                {
                    document.getElementById("autoQuestCheckbox").checked = false;
                    console.log("Auto-quest disabled since it requires battle and auto-battle has errors.");
                }
                return;
            }
            var battle_price = battleButton.find('span').size()>0?battleButton.attr("price_fe"):0;

            if (location.search.split("league_battle=")[1])
            {
                currentPower=getHero().infos.energy_challenge;
            }
            if(battle_price === undefined){
                console.log("Could not detect battle button price. Error.");
                console.log("Disabling all auto-battle.");
                document.getElementById("autoBattleCheckbox").checked = false;
                document.getElementById("autoArenaCheckbox").checked = false;
                if (sessionStorage.questRequirement === "battle")
                {
                    document.getElementById("autoQuestCheckbox").checked = false;
                    console.log("Auto-quest disabled since it requires battle and auto-battle has errors.");
                }
                return;
            }
            console.log("battle price: "+battle_price+"P")
            if(currentPower >= battle_price)
            {
                // We have the power.
                is_cheat_click=function(e) {
                    return false;
                };
                battleButton.click();
                // Skip
                setTimeout(function(){$("#battle_middle button[rel='skip']").click();},2000);
                setTimeout(function(){$("#rewards_popup .blue_text_button").click();$("#rewards_popup .blue_button_L").click();},3500);

                if (sessionStorage.questRequirement === "battle") {
                    // Battle Done.
                    sessionStorage.questRequirement = "none";
                }

                location.href = "/home.html";
                return true;
            }
            else
            {
                // We need more power.
                console.log("Battle requires "+battle_price+" power.");
                sessionStorage.battlePowerRequired = battle_price;
                if(sessionStorage.questRequirement === "battle")sessionStorage.questRequirement = "P"+battle_price;
            }
        }
        else {
            console.log("Could not identify battle screen.");
            if (sessionStorage.questRequirement === "battle") sessionStorage.questRequirement = "errorInAutoBattle";
            return;
        }
    }
}

var setTimer=function(name, seconds)
{
    var ND=new Date().getTime() + seconds * 1000;
    Timers[name]=ND;
    sessionStorage.Timers=JSON.stringify(Timers);
    console.log(name+" set to "+toHHMMSS(ND/1000-new Date().getTimezoneOffset()*60)+' ('+ toHHMMSS(seconds)+')');
}

var clearTimer=function(name)
{
    delete Timers[name];
    sessionStorage.Timers=JSON.stringify(Timers);
}

var checkTimer=function(name)
{
    if (!Timers[name])
    {
        return true;
    }
    if (Timers[name]<new Date())
    {
        return true;
    }
    return false;
}

var getSecondsLeft=function(name)
{
    if (!Timers[name])
    {
        return 0;
    }
    return Math.ceil(Timers[name]/1000)-Math.ceil(new Date().getTime()/1000);
}

var getTimeLeft=function(name)
{
    if (!Timers[name])
    {
        return "No timer";
    }
    var diff=getSecondsLeft(name);
    if (diff<=0)
    {
        return "Time's up!";
    }
    return toHHMMSS(diff);
}



var updateData = function () {
    //console.log("updating UI");

    var trollOptions = document.getElementById("autoTrollSelector");
    Storage().autoTrollSelectedIndex = trollOptions.selectedIndex;
    Storage().trollToFight = trollOptions.value;
    Storage().plusEvent = document.getElementById("plusEvent").checked;
    Storage().autoSalary = document.getElementById("autoSalaryCheckbox").checked;
    Storage().autoContest = document.getElementById("autoContestCheckbox").checked;
    Storage().autoMission = document.getElementById("autoMissionCheckbox").checked;
    Storage().autoQuest = document.getElementById("autoQuestCheckbox").checked;
    Storage().autoTrollBattle = document.getElementById("autoBattleCheckbox").checked;
    Storage().eventTrollOrder = document.getElementById("eventTrollOrder").value;
    Storage().buyCombTimer = document.getElementById("buyCombTimer").value;
    Storage().autoArenaBattle = document.getElementById("autoArenaCheckbox").checked;
    Storage().autoLeagues = document.getElementById("autoLeagues").checked;
    Storage().autoStats = document.getElementById("autoStats").value;
    Storage().paranoia = document.getElementById("paranoia").checked;
    Storage().autoFreePachinko = document.getElementById("autoFreePachinko").checked;
    Storage().autoExp = document.getElementById("autoExp").value;
    Storage().autoExpW = document.getElementById("autoExpW").checked;
	Storage().MaxExp = document.getElementById("maxExp").value;
    Storage().autoAff = document.getElementById("autoAff").value;
    Storage().autoAffW = document.getElementById("autoAffW").checked;
	Storage().MaxAff = document.getElementById("maxAff").value;
    Storage().autoLGM = document.getElementById("autoLGM").value;
    Storage().autoLGMW = document.getElementById("autoLGMW").checked;
    Storage().autoLGR = document.getElementById("autoLGR").value;
    Storage().autoLGRW = document.getElementById("autoLGRW").checked;
    Storage().autoEGM = document.getElementById("autoEGM").value;
    Storage().autoEGMW = document.getElementById("autoEGMW").checked;
    Storage().showInfo = document.getElementById("showInfo").checked;
    Storage().autoChamps = document.getElementById("autoChamps").checked;
    Storage().autoChampsUseEne = document.getElementById("autoChampsUseEne").checked;

    Storage().spendKobans0 = document.getElementById("spendKobans0").checked;
    Storage().spendKobans1 = document.getElementById("spendKobans1").checked && Storage().spendKobans0=="true";
    document.getElementById("spendKobans1").checked=Storage().spendKobans1=="true";
    Storage().spendKobans2 = document.getElementById("spendKobans2").checked && Storage().spendKobans1=="true" && Storage().spendKobans0=="true"
    document.getElementById("spendKobans2").checked=Storage().spendKobans2=="true";

    Storage().buyCombat=document.getElementById("buyCombat").checked && Storage().spendKobans2=="true" && Storage().spendKobans1=="true" && Storage().spendKobans0=="true"
    document.getElementById("buyCombat").checked=Storage().buyCombat=="true";
    Storage().kobanBank=document.getElementById("kobanBank").value;

    localStorage.settPerTab = document.getElementById("settPerTab").checked;

    Storage().master=document.getElementById("master").checked;

    if (Storage().showInfo=="true")
    {
        var Tegzd='';
        Tegzd+='Master: '+(Storage().master==="true"?"ON":"OFF");
        if (Storage().paranoia=="true")
        {
            Tegzd+=(Tegzd.length>0?'\r\n':'')+sessionStorage.pinfo+': '+getTimeLeft('paranoiaSwitch');
        }
        if (Storage().autoSalary=="true")
        {
            Tegzd+=(Tegzd.length>0?'\r\n':'')+'Salary check: '+getTimeLeft('nextSalaryTime');
        }
        if (Storage().autoArenaBattle=="true")
        {
            Tegzd+=(Tegzd.length>0?'\r\n':'')+'Arena fight: '+getTimeLeft('nextArenaTime');
        }
        if (Storage().autoLeagues=="true")
        {
            Tegzd+=(Tegzd.length>0?'\r\n':'')+'League fight: '+getTimeLeft('nextLeaguesTime');
        }
        if (Storage().autoChamps=="true")
        {
            Tegzd+=(Tegzd.length>0?'\r\n':'')+'Champions check: '+getTimeLeft('nextChampionTime');
        }
       // if (autoBuy())
        {
            Tegzd+=(Tegzd.length>0?'\r\n':'')+'Shop update: '+getTimeLeft('nextShopTime');
        }
        if (Storage().autoMission=="true")
        {
            Tegzd+=(Tegzd.length>0?'\r\n':'')+'Mission: '+getTimeLeft('nextMissionTime');
        }
        if (Storage().autoContest=="true")
        {
            Tegzd+=(Tegzd.length>0?'\r\n':'')+'Contest: '+getTimeLeft('nextContestTime');
        }
        if (Storage().autoFreePachinko=="true")
        {
            Tegzd+=(Tegzd.length>0?'\r\n':'')+'Great Pachinko: '+getTimeLeft('nextPachinkoTime');
            Tegzd+=(Tegzd.length>0?'\r\n':'')+'Mythic Pachinko: '+getTimeLeft('nextPachinko2Time');
        }
        if (Tegzd.length>0)
        {
            document.getElementById('pInfo').style.display='block';
            document.getElementById('pInfo').textContent=Tegzd;
        }
    }
    else
    {
        document.getElementById('pInfo').style.display='none';
    }
};

var getPachinko = function(){
    try {
        if(!gotoPage("pachinko"))
        {
            // Not at Pachinko screen then goto the Pachinko screen.
            console.log("Navigating to Pachinko window.");
            return;
        }
        else {
            console.log("Detected Pachinko Screen. Fetching Pachinko");
            while ($('#playzone-replace-info button[free=1]')[0]===undefined)
            {
                $('.game-simple-block[type-pachinko=great]')[0].click();
            }
            if ($('#playzone-replace-info button[free=1]')[0].style.display=="none")
            {
                console.log('Not ready yet');
            }
            else
            {
                $('#playzone-replace-info button[free=1]')[0].click();
            }
            var npach;
            for(var e in unsafeWindow.HHTimers.timers){
                if(unsafeWindow.HHTimers.timers[e].$elm && unsafeWindow.HHTimers.timers[e].$elm.selector.startsWith(".pachinko_change"))
                    npach=unsafeWindow.HHTimers.timers[e].remainingTime;
            }
            if(npach !== undefined || npach !== 0)
            {
                setTimer('nextPachinkoTime',Number(npach)+1);
            }
            else
            {
                clearTimer('nextPachinkoTime');
            }
        }
    }
    catch (ex) {
        console.log("Could not collect Great Pachinko... " + ex);
    }
};

var getPachinko2 = function(){
    try {
        if(!gotoPage("pachinko"))
        {
            // Not at Pachinko screen then goto the Pachinko screen.
            console.log("Navigating to Pachinko window.");
            return;
        }
        else {
            console.log("Detected Pachinko Screen. Fetching Pachinko");
            var butt;
            if (hh_nutaku)
            {
                butt=$('#playzone-replace-info button[play="pachinko5|25|hard_currency"]')[0];
            }
            else
            {
                butt=$('#playzone-replace-info button[play="pachinko5|150|hard_currency"]')[0];
            }
            var counter=0;
            while (butt===undefined && (counter++)<250)
            {
                console.log('to mythic');
                $('.game-simple-block[type-pachinko=mythic]')[0].click();
            }
            if (butt===undefined)
            {
                console.log("Fuck my life!");
                setTimer('nextPachinko2Time',600);
                return false;
            }
            if (butt.className!="blue_button_L")
            {
                console.log('Not ready yet');
            }
            else
            {
                console.log('click');
                butt.click();
            }
            var npach;
            for(var e in unsafeWindow.HHTimers.timers){
                if(unsafeWindow.HHTimers.timers[e].$elm && unsafeWindow.HHTimers.timers[e].$elm.selector.startsWith('.game-simple-block[type-pachinko="mythic"]'))
                    npach=unsafeWindow.HHTimers.timers[e].remainingTime;
            }
            if(npach !== undefined || npach !== 0)
            {
                setTimer('nextPachinko2Time',Number(npach)+1);
            }
            else
            {
                clearTimer('nextPachinko2Time');
            }
        }
    }
    catch (ex) {
        console.log("Could not collect Mythic Pachinko... " + ex);
    }
};

var updateShop=function()
{
        if(!gotoPage("shop"))
        {
            console.log("Navigating to Market window.");
            return true;
        }
        else {
            console.log("Detected Market Screen. Fetching Assortment");

            var assA=[];
            var assG=[];
            var assP=[];
            $('#shop div.armor .slot').each(function(){if (this.dataset.d)assA.push(JSON.parse(this.dataset.d));});
            $('#shop div.gift .slot').each(function(){if (this.dataset.d)assG.push(JSON.parse(this.dataset.d));});
            $('#shop div.potion .slot').each(function(){if (this.dataset.d)assP.push(JSON.parse(this.dataset.d));});

			var HaveAff=0;
			var HaveExp=0;
			$('#inventory div.gift .slot').each(function(){if (this.dataset.d) { var d=JSON.parse(this.dataset.d); HaveAff+=d.count*d.value;}});
			$('#inventory div.potion .slot').each(function(){if (this.dataset.d) { var d=JSON.parse(this.dataset.d); HaveExp+=d.count*d.value;}});

			sessionStorage.haveAff=HaveAff;
			sessionStorage.haveExp=HaveExp;

			console.log('counted',sessionStorage.haveAff,sessionStorage.haveExp);

            sessionStorage.storeContents = JSON.stringify([assA,assG,assP]);
            sessionStorage.charLevel=getHero().infos.level;

            var nshop;
            for(var e in unsafeWindow.HHTimers.timers){
                if(unsafeWindow.HHTimers.timers[e].$elm && unsafeWindow.HHTimers.timers[e].$elm.selector.startsWith(".shop_count"))
                    nshop=unsafeWindow.HHTimers.timers[e].remainingTime;
            }
            if(nshop !== undefined && nshop !== 0)
            {
                console.log(nshop);
                setTimer('nextShopTime',Number(nshop)+1);
            }
            else
            {
                setTimer('nextShopTime',60);
            }
        }
    return false;
}

var toHHMMSS = function (secs)  {
    var sec_num = parseInt(secs, 10);
    var days   = Math.floor(sec_num / 86400);
    var hours   = Math.floor(sec_num / 3600) % 24;
    var minutes = Math.floor(sec_num / 60) % 60;
    var seconds = sec_num % 60;
    var n=0;
    return [days,hours,minutes,seconds]
        .map(v => v < 10 ? "0" + v : v)
        .filter((v,i) => {if (v !== "00"){n++; return true;} return n > 0})
        .join(":");
}

var flipParanoia=function()
{
    var burst=getBurst();

    var Setting=Storage().paranoiaSettings;

    var S1=Setting.split('/').map(s=>s.split('|').map(s=>s.split(':')));

    var toNextSwitch;
    var period;
    var n = new Date().getHours();
    S1[2].some(x => {if (n<x[0]) {period=x[1]; return true;}});

    if (burst && getHero().infos.energy_fight!=0 && Storage().autoTrollBattle=='true') //double(or more) burst if we want to fight
    {
        burst=false;
    }

    if (burst)
    {
        if (getPage()!='home') return;
        //going into hiding
        sessionStorage.burst="false";

        var periods=Object.assign(...S1[1].map(d => ({[d[0]]: d[1].split('-')})));

        toNextSwitch=randomInterval(Number(periods[period][0]),Number(periods[period][1]));
        if (toNextSwitch<=1800 && Storage().autoArenaBattle == "true")
        {
            var sl=getSecondsLeft("nextArenaTime");
            toNextSwitch=toNextSwitch<sl?toNextSwitch:sl;
        }
    }
    else
    {
        //going to work
        sessionStorage.autoLoop = "false";
        sessionStorage.burst="true";
        var b=S1[0][0][0].split('-');
        toNextSwitch=randomInterval(Number(b[0]),Number(b[1]));
    }
    var ND=new Date().getTime() + toNextSwitch * 1000;
    var offs=new Date().getTimezoneOffset();
    var message=period+(burst?" rest":" burst");
    console.log("PARANOIA: "+message);
    sessionStorage.pinfo=message;

    setTimer('paranoiaSwitch',toNextSwitch);
    if (sessionStorage.burst=="true")
    {
        if (hh_nutaku)
        {
            window.top.postMessage({reloadMe:true},'*');
        }
        else
        {
            window.top.location.reload();
        }
    }
}

var autoLoop = function () {
    updateData();
    if (!sessionStorage.questRequirement)
    {
        sessionStorage.questRequirement="none";
    }
    if (!sessionStorage.userLink)
    {
        sessionStorage.userLink="none"
    }
    if (!sessionStorage.battlePowerRequired)
    {
        sessionStorage.battlePowerRequired="0";
    }

    var busy = false;
    var page = window.location.href;
    var currentPower = getHero().infos.energy_fight;

    var burst=getBurst();

    if (burst /*|| checkTimer('nextMissionTime')*/)
    {
        if(Storage().autoFreePachinko === "true" && busy === false){
        // Navigate to pachinko

            if (checkTimer("nextPachinkoTime")) {
                console.log("Time to fetch Great Pachinko.");
                getPachinko();
                busy = true;
            }
            if (checkTimer("nextPachinko2Time")) {
                console.log("Time to fetch Mythic Pachinko.");
                getPachinko2();
                busy = true;
            }
        }
        if(Storage().autoLeagues === "true" && getHero().infos.level>=20 && busy === false ){
            // Navigate to leagues
            if (checkTimer('nextLeaguesTime')) {
                console.log("Time to fight in Leagues.");
                doLeagueBattle();
                busy = true;
            }
        }
        if(Storage().autoContest === "true" && busy === false){
            if (checkTimer('nextContestTime') || unsafeWindow.has_contests_datas ||$(".contest .ended button[rel='claim']").size()>0){
                console.log("Time to get contest rewards.");
                busy = doContestStuff();
            }
        }
        if(Storage().autoMission === "true" && busy === false){
            if (checkTimer('nextMissionTime')){
                console.log("Time to do missions.");
                busy = doMissionStuff();
            }
        }

        if (Storage().autoQuest === "true" && busy === false) {
            if (sessionStorage.questRequirement === "battle") {
                console.log("Quest requires battle.");
                doBossBattle();
                busy = true;
            }
            else if (sessionStorage.questRequirement[0] === '$') {
                if (Number(sessionStorage.questRequirement.substr(1)) < getHero().infos.soft_currency) {
                    // We have enough money... requirement fulfilled.
                    console.log("Continuing quest, required money obtained.");
                    sessionStorage.questRequirement = "none";
                    proceedQuest();
                    busy = true;
                }
                else {
                    if(isNaN(sessionStorage.questRequirement.substr(1)))
                    {
                        console.log(sessionStorage.questRequirement);
                        sessionStorage.questRequirement = "none";
                        console.log("Invalid money in session storage quest requirement !");
                    }
                    else{
                        // Else we need more money.
                        //console.log("Need money for quest, cannot continue. Turning ON AutoSalary.");
                        Storage().autoQuest = "true";
                    }
                    busy = false;
                }
            }
            else if (sessionStorage.questRequirement[0] === '*') {
                var energyNeeded = Number(sessionStorage.questRequirement.substr(1));
                var energyCurrent = getHero().infos.energy_quest;
                if (energyNeeded <= energyCurrent) {
                    // We have enough energy... requirement fulfilled.
                    console.log("Continuing quest, required energy obtained.");
                    sessionStorage.questRequirement = "none";
                    proceedQuest();
                    busy = true;
                }
                // Else we need energy, just wait.
                else {
                    busy = false;
                    //console.log("Replenishing energy for quest.(" + energyNeeded + " needed)");
                }
            }
            else if (sessionStorage.questRequirement[0] === 'P')
            {
                // Battle power required.
                var neededPower = Number(sessionStorage.questRequirement.substr(1));
                if(currentPower < neededPower)
                {
                    console.log("Quest requires "+neededPower+" Battle Power for advancement. Waiting...");
                    busy = false;
                }
                else
                {
                    console.log("Battle Power obtained, resuming quest...");
                    sessionStorage.questRequirement = "none";
                    proceedQuest();
                    busy = true;
                }
            }
            else if (sessionStorage.questRequirement === "unknownQuestButton") {
                console.log("AutoQuest disabled.AutoQuest cannot be performed due to unknown quest button. Please manually proceed the current quest screen.");
                document.getElementById("autoQuestCheckbox").checked = false;
                Storage().autoQuest = "false";
                sessionStorage.questRequirement = "none";
                busy = false;
            }
            else if (sessionStorage.questRequirement === "errorInAutoBattle") {
                console.log("AutoQuest disabled.AutoQuest cannot be performed due errors in AutoBattle. Please manually proceed the current quest screen.");
                document.getElementById("autoQuestCheckbox").checked = false;
                Storage().autoQuest = "false";
                sessionStorage.questRequirement = "none";
                busy = false;
            }
            else if(sessionStorage.questRequirement === "none")
            {
                //console.log("NONE req.");
                busy = true;
                proceedQuest();
            }
            else
            {
                console.log("Invalid quest requirement : "+sessionStorage.questRequirement);
                busy=false;
            }
        }
        else if(Storage().autoQuest === "false"){sessionStorage.questRequirement = "none";}

        if(Storage().autoArenaBattle === "true" && busy === false)
        {
            if (/*unsafeWindow.arena_data && unsafeWindow.arena_data.active_opponent*/$('a[rel=arena] span.button-notification-icon').size()>0)
            {
                console.log('Missed one in arena!');
                setTimer('nextArenaTime',0);
            }
            if(checkTimer("nextArenaTime"))
            {
                console.log("Time to fight in arena.");
                doBattle();
                busy = true;
            }
        }


        if(Storage().autoTrollBattle === "true" && getHero().infos.questing.id_world>0)
        {
            if(busy === false && currentPower >= Number(sessionStorage.battlePowerRequired) && currentPower > 0)
            {
                sessionStorage.battlePowerRequired = "0";
                busy = true;
                if(Storage().autoQuest === "true")
                {
                    if(sessionStorage.questRequirement[0] === 'P')
                    {
                        console.log("AutoBattle disabled for power collection for AutoQuest.");
                        document.getElementById("autoBattleCheckbox").checked = false;
                        Storage().autoTrollBattle = "false";
                        busy = false;
                    }
                    else
                    {
                        doBossBattle();
                    }
                }
                else
                {
                    doBossBattle();
                }
            }
        }
        else{sessionStorage.battlePowerRequired = "0";}

        if (busy==false && Storage().autoChamps==="true" && checkTimer('nextChampionTime'))
        {
            console.log("Time to check on champions!");
            busy=doChampionStuff();
        }

        if (/*autoBuy() &&*/ busy===false)
        {
            if (sessionStorage.charLevel===undefined)
            {
                sessionStorage.charLevel=0;
            }
            if (checkTimer('nextShopTime') || sessionStorage.charLevel<getHero().infos.level) {
                console.log("Time to check shop.");
                busy = updateShop();
            }
        }

        if (Storage().autoSalary === "true" && busy === false) {
            if (checkTimer("nextSalaryTime")) {
                console.log("Time to fetch salary.");
                busy = getSalary();
            }
        }

        if(busy === true && sessionStorage.userLink==="none" && !window.location.pathname.startsWith("/quest"))
        {
            sessionStorage.userLink = page;
        }
        else if(sessionStorage.userLink !=="none" && busy === false)
        {
            console.log("Restoring page "+sessionStorage.userLink);
            window.location = sessionStorage.userLink;
            sessionStorage.userLink = "none";
        }
    }

    if(Storage().paranoia === "true" && Storage().master==="true"){
         if (checkTimer("paranoiaSwitch")) {
             flipParanoia();
         }
    }

    if(isNaN(Storage().autoLoopTimeMili)){
        console.log("AutoLoopTimeMili is not a number.");
        setDefaults();
    }
    else{
        if (sessionStorage.autoLoop === "true") setTimeout(autoLoop, Number(localStorage.autoLoopTimeMili));
        else console.log("autoLoop Disabled");
    }
};

var setDefaults = function () {
    console.log("Setting Defaults.");
    Storage().autoSalary = "true";
    Storage().autoContest = "true";
    Storage().autoMission = "true";
    Storage().autoLeagues = "true";
    Storage().autoStats = "500000000";
    sessionStorage.autoLoop = "true";
    sessionStorage.userLink = "none";
    Storage().autoLoopTimeMili = "500";
    Storage().autoQuest = "true";
    Storage().autoTrollBattle = "true";
    Storage().eventTrollOrder="";
    Storage().buyCombTimer="16";
    Storage().autoArenaBattle = "true";
    sessionStorage.battlePowerRequired = "0";
    sessionStorage.questRequirement = "none";
    Storage().freshStart = "no";
    Storage().autoChamps="true";
    Storage().autoChampsUseEne="true";
    Storage().autoFreePachinko = "true";
    Storage().autoExp = "500000000";
    Storage().autoExpW = "true";
	Storage().MaxExp = "10000";
    Storage().autoAff = "500000000";
    Storage().autoAffW = "true";
	Storage().MaxAff = "50000";
    Storage().autoLGM = "500000000";
    Storage().autoLGMW = "true";
    Storage().autoLGR = "500000000";
    Storage().autoLGRW = "true";
    Storage().autoEGM = "500000000";
    Storage().autoEGMW = "true";
    Storage().paranoia="false";
    Storage().showInfo="true";
    Storage().spendKobans0="true";
    Storage().paranoiaSettings="120-300/Sleep:28800-29400|Active:300-420|Casual:1800-2100/6:Sleep|18:Active|22:Casual|24:Sleep";
    Storage().master="true";
};

var CollectEventData=function()
{
    if (unsafeWindow.event_object_data)
    {
        var timeLeft=event_object_data.seconds_until_event_end;
        setTimer('eventGoing',timeLeft);
        var Trollz=[];
        for (var i=0;i<event_object_data.girls.length;i++)
        {
            if (!event_object_data.girls[i].owned_girl && event_object_data.girls[i].troll)
            {
                if (Number(event_object_data.girls[i].troll.id_troll)<getHero().infos.questing.id_world)
                {
                    Trollz.push(Number(event_object_data.girls[i].troll.id_troll));
                }
            }
        }

        var Priority=(Storage().eventTrollOrder?Storage().eventTrollOrder:"").split(";");
        //console.log(Priority);
        //console.log(Trollz);
        if (Trollz.length>0)
        {
            if (Priority[0]!='')
            {
                var found=false;
                for (var n=0;n<Priority.length;n++)
                {
                    if (Trollz.includes(Number(Priority[n])))
                    {
                        //console.log(Priority[n]);
                        sessionStorage.eventTroll=Number(Priority[n]);
                        found=true;
                        break;
                    }
                }
                if (!found)
                {
                    delete sessionStorage.eventTroll;
                    //sessionStorage.eventTroll=Trollz.sort((a,b)=>{return a-b;})[0];
                }
            }
            else
            {
                sessionStorage.eventTroll=Trollz.sort((a,b)=>{return a-b;})[0];
            }
        }
        else
        {
            delete sessionStorage.eventTroll;
        }
        //console.log('WTF?');
        if (Storage().buyCombat=="true" && Storage().plusEvent=="true")
        {
            //console.log('WTF!');
            var diff=Math.ceil(Timers["eventGoing"]/1000)-Math.ceil(new Date().getTime()/1000);
            //console.log(diff);
            var hero=getHero();
            if (diff<Storage().buyCombTimer*3600 && sessionStorage.eventTroll && hero.infos.energy_fight==0)//Less than 16 hours remains and we still haven't get all troll girls
            {
                var price=hero.get_recharge_cost("fight");
                //console.log('PRC: '+price);
                if (hero.infos.hard_currency>=price+Number(Storage().kobanBank))
                {
                    console.log('Buying comb');
                    RechargeCombat(price);
                }
            }
        }
    }
}

var RechargeCombat=function(price) {
    hh_ajax(
        {
            class: "Hero",
            action: "recharge",
            type: "fight"
        }, function(data) {
                Hero.update("energy_fight", Hero.infos["energy_fight_max"]);
                Hero.update("hard_currency", 0 - price, true);
            });

}

/*var autoBuy=function()
{
    return true ;
}*/

var getBurst=function()
{
    if (document.getElementById('sMenu'))
    {
        if (document.getElementById('sMenu').parentElement.style.display=='block')
        {
            return false;
        }
    }
    return Storage().master==="true"&&(!(Storage().paranoia==="true") || sessionStorage.burst==="true");
}

var Trollz=["Latest","Dark Lord","Ninja Spy","Gruntt","Edwarda","Donatien","Silvanus","Bremen","Finalmecia","Roko Senseï","Karole","Jackson\'s Crew","Pandora witch"];
var Timers={};

var start = function () {

    if (unsafeWindow.Hero===undefined)
    {
        console.log('???no Hero???');
        $('.hh_logo').click();
        return;
    }
    $('.redirect.gayharem').hide();

    $('#starter_offer').hide();
    $('#starter_offer_background').hide();
    if (sessionStorage.Timers)
    {
        Timers=JSON.parse(sessionStorage.Timers);
    }
    // Add UI buttons.
    var UIcontainer = $("#contains_all nav div[rel='content']");
    UIcontainer.html( '<div style="font-size:x-small;position: absolute;right: 22%;width: inherit;text-align: center;display:flex;flex-direction:column;z-index:1000" id="sMenu">'
                     + '<div style="display:flex;flex-direction:row;">'
                     +  '<div style="padding:10px; display:flex;flex-direction:column;">'
                     +   '<span>Master switch</span><div><label class=\"switch\" title=\"Turn off to pause script\"><input id=\"master\" type=\"checkbox\"><span class=\"slider round\"></span></label></div>'
                     +   '<span>Questionable Shit</span><div><label class=\"switch\"><input id=\"spendKobans0\" type=\"checkbox\"><span class=\"slider round\"></span></label></div>'
                     +   '<span>Are you sure?</span><div><label class=\"switch\"><input id=\"spendKobans1\" type=\"checkbox\"><span class=\"slider round\"></span></label></div>'
                     +   '<span>You\'ve been warned</span><div><label class=\"switch\"><input id=\"spendKobans2\" type=\"checkbox\"><span class=\"slider round\"></span></label></div>'
                     +   '<span>Buy comb. in events</span><div><label class=\"switch\"><input id=\"buyCombat\" type=\"checkbox\"><span class=\"slider round\"></span></label><input id="kobanBank" type="text"></div>'
                     +   '<span>Hours to buy Comb</span><div><input id="buyCombTimer" style="width:80%" type="text"></div>'
                     +   '<span>Event Troll Order</span><div><input id="eventTrollOrder" style="width:80%" type="text"></div>'
                     +  '</div>'
                     +  '<div style="padding:10px; display:flex;flex-direction:column;">'
                     +   '<span>Settings per tab</span><div><label class=\"switch\"><input id=\"settPerTab\" type=\"checkbox\"><span class=\"slider round\"></span></label></div>'
                     +   '<span>AutoSal.</span><div><label class=\"switch\"><input id=\"autoSalaryCheckbox\" type=\"checkbox\"><span class=\"slider round\"></span></label></div>'
                     +   '<span>AutoContest</span><div><label class=\"switch\"><input id=\"autoContestCheckbox\" type=\"checkbox\"><span class=\"slider round\"></span></label></div>'
                     +   '<span>AutoMission</span><div><label class=\"switch\"><input id=\"autoMissionCheckbox\" type=\"checkbox\"><span class=\"slider round\"></span></label></div>'
                     +   '<span>AutoQuest</span><div><label class=\"switch\"><input id=\"autoQuestCheckbox\" type=\"checkbox\"><span class=\"slider round\"></span></label></div>'
                     +   '<div style="display:flex;flex-direction:row;">'
                     +    '<div style="padding:10px; display:flex;flex-direction:column;">'
                     +     '<span>AutoTrollBattle</span><div><label class=\"switch\"><input id=\"autoBattleCheckbox\" type=\"checkbox\"><span class=\"slider round\"></span></label><select id=\"autoTrollSelector\"></select></div>'
                     +    '</div>'
                     +    '<div style="padding:10px; display:flex;flex-direction:column;">'
                     +     '<span>+Event</span><div><label class=\"switch\"><input id=\"plusEvent\" type=\"checkbox\"><span class=\"slider round\"></span></label></div>'
                     +    '</div>'
                     +   '</div>'
                     +   '<span>AutoArenaBattle</span><div><label class=\"switch\"><input id=\"autoArenaCheckbox\" type=\"checkbox\"><span class=\"slider round\"></span></label></div>'
                     +   '<span>AutoPachinko(Free)</span><div><label class=\"switch\"><input id=\"autoFreePachinko\" type=\"checkbox\"><span class=\"slider round\"></span></label></div>'
                     +   '<span>Paranoia mode</span><div><label class=\"switch\"><input id=\"paranoia\" type=\"checkbox\"><span class=\"slider round\"></span></label></div>'
                     +  '</div>'
                     +  '<div style="padding:10px; display:flex;flex-direction:column;">'
                     +   '<span>AutoLeagues</span><div><label class=\"switch\"><input id=\"autoLeagues\" type=\"checkbox\"><span class=\"slider round\"></span></label></div>'
                     +   '<div style="display:flex;flex-direction:row;">'
                     +    '<div style="padding:10px; display:flex;flex-direction:column;">'
                     +     '<span>AutoChampions</span><div><label class=\"switch\"><input id=\"autoChamps\" type=\"checkbox\"><span class=\"slider round\"></span></label></div>'
                     +    '</div>'
                     +    '<div style="padding:10px; display:flex;flex-direction:column;">'
                     +     '<span>UseEne</span><div><label class=\"switch\"><input id=\"autoChampsUseEne\" type=\"checkbox\"><span class=\"slider round\"></span></label></div>'
                     +    '</div>'
                     +   '</div>'
                     +   '<span>AutoStats</span><div><input id="autoStats" type="text"></div>'
                     +   '<span>Buy Exp</span><div style="width:200px"><label class=\"switch\"><input id=\"autoExpW\" type=\"checkbox\"><span class=\"slider round\"></span></label><input id="autoExp" style="width:50%" type="text"><input id="maxExp" style="width:30%" type="text"></div>'
                     +   '<span>Buy Aff</span><div style="width:200px"><label class=\"switch\"><input id=\"autoAffW\" type=\"checkbox\"><span class=\"slider round\"></span></label><input id="autoAff" style="width:50%" type="text"><input id="maxAff" style="width:30%" type="text"></div>'
                     +   '<span>Buy Leg Gear Mono</span><div><label class=\"switch\"><input id=\"autoLGMW\" type=\"checkbox\"><span class=\"slider round\"></span></label><input id="autoLGM" type="text"></div>'
                     +   '<span>Buy Leg Gear Rainbow</span><div><label class=\"switch\"><input id=\"autoLGRW\" type=\"checkbox\"><span class=\"slider round\"></span></label><input id="autoLGR" type="text"></div>'
                     +   '<span>Buy Epi Gear Mono</span><div><label class=\"switch\"><input id=\"autoEGMW\" type=\"checkbox\"><span class=\"slider round\"></span></label><input id="autoEGM" type="text"></div>'
                     +   '<span>Show info</span><div><label class=\"switch\"><input id=\"showInfo\" type=\"checkbox\"><span class=\"slider round\"></span></label></div>'
                     +  '</div>'
                     + '</div>'
                     +'</div>'+UIcontainer.html());

    var div = document.createElement('div');
    div.innerHTML = '<div id="pInfo" style="padding-left:3px;z-index:-1;white-space: pre;position: absolute;right: 5%; left:70%; top:8%;border: 1px solid #ffa23e;background-color: rgba(0,0,0,.5);border-radius: 5px;"></div>'.trim();
    document.getElementById('contains_all').appendChild(div.firstChild);

    // Add auto troll options
    var trollOptions = document.getElementById("autoTrollSelector");

    for (var i=0;i<unsafeWindow.Hero.infos.questing.id_world;i++)
    {
        var option = document.createElement("option");
        option.value=i;
        option.text = Trollz[i];
        trollOptions.add(option);
    };

    document.getElementById("settPerTab").checked = localStorage.settPerTab === "true";
    trollOptions.selectedIndex = Storage().autoTrollSelectedIndex;
    document.getElementById("autoSalaryCheckbox").checked = Storage().autoSalary === "true";
    document.getElementById("autoContestCheckbox").checked = Storage().autoContest === "true";
    document.getElementById("autoMissionCheckbox").checked = Storage().autoMission === "true";
    document.getElementById("autoQuestCheckbox").checked = Storage().autoQuest === "true";
    document.getElementById("autoBattleCheckbox").checked = Storage().autoTrollBattle === "true";
    document.getElementById("eventTrollOrder").value = Storage().eventTrollOrder?Storage().eventTrollOrder:"1;2;3;4;5;6;7;8;9;10;11";
    document.getElementById("buyCombTimer").value = Storage().buyCombTimer?Storage().buyCombTimer:"16";
    document.getElementById("autoArenaCheckbox").checked = Storage().autoArenaBattle === "true";
    document.getElementById("autoFreePachinko").checked = Storage().autoFreePachinko === "true";
    document.getElementById("autoLeagues").checked = Storage().autoLeagues === "true";
    document.getElementById("autoStats").value = Storage().autoStats?Storage().autoStats:"500000000";
    document.getElementById("paranoia").checked = Storage().paranoia==="true";
    document.getElementById("autoExp").value = Storage().autoExp?Storage().autoExp:"500000000";
    document.getElementById("autoExpW").checked = Storage().autoExpW === "true";
    document.getElementById("autoAff").value = Storage().autoAff?Storage().autoAff:"500000000";
    document.getElementById("autoAffW").checked = Storage().autoAffW === "true";
	document.getElementById("maxExp").value = Storage().MaxExp?Storage().MaxExp:"10000";
    document.getElementById("maxAff").value = Storage().MaxAff?Storage().MaxAff:"50000";
    document.getElementById("autoLGM").value = Storage().autoLGM?Storage().autoLGM:"500000000";
    document.getElementById("autoLGMW").checked = Storage().autoLGMW === "true";
    document.getElementById("autoLGR").value = Storage().autoLGR?Storage().autoLGR:"500000000";
    document.getElementById("autoLGRW").checked = Storage().autoLGRW === "true";
    document.getElementById("autoEGM").value = Storage().autoEGM?Storage().autoEGM:"500000000";
    document.getElementById("autoEGMW").checked = Storage().autoEGMW === "true";
    document.getElementById("showInfo").checked = Storage().showInfo === "true";
    document.getElementById("plusEvent").checked = Storage().trollToFight=="-1" || Storage().plusEvent === "true";

    document.getElementById("autoChamps").checked = Storage().autoChamps === "true";
    document.getElementById("autoChampsUseEne").checked = Storage().autoChampsUseEne === "true";

    document.getElementById("spendKobans0").checked = Storage().spendKobans0 === "true";
    document.getElementById("spendKobans1").checked = Storage().spendKobans1 === "true";
    document.getElementById("spendKobans2").checked = Storage().spendKobans2 === "true";
    document.getElementById("buyCombat").checked = Storage().buyCombat === "true";
    document.getElementById("kobanBank").value = Storage().kobanBank?Storage().kobanBank:"1000000";

    document.getElementById("master").checked = Storage().master!=="false";

    sessionStorage.autoLoop = "true";
    if (typeof Storage().freshStart == "undefined" || isNaN(Number(Storage().autoLoopTimeMili))) {
        setDefaults();
    }

    if(getPage()=="shop")
    {
        updateShop();
    }

    if (/*autoBuy() &&*/ getBurst())
    {
        doShopping();
    /*}
    if (Storage().autoStats === "true" && getBurst())
    {*/
        doStatUpgrades();
    }

    CollectEventData();

    if (hh_nutaku)
    {
        function Alive()
        {
            window.top.postMessage({ImAlive:true},'*');
            if (sessionStorage.autoLoop=="true")
            {
                setTimeout(Alive,2000);
            }
        }
        Alive();
    }

    autoLoop();
};

var started=false;
var hardened_start=function()
{
    if (!started)
    {
        started=true;
        start();
    }
}

$("document").ready(function()
{
    setTimeout(hardened_start,1000);

});

setTimeout(hardened_start,5000);