QQOL

Quality of Quality of Life!

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

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

Tendrás que instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Tendrás que instalar una extensión como Tampermonkey antes de poder instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         QQOL
// @namespace    http://tampermonkey.net/
// @version      0.64
// @description  Quality of Quality of Life!
// @include *queslar.com/*
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js
// @grant        unsafeWindow
// ==/UserScript==

//mat-tab-label-0-1
//TODO HOOK INTO document.querySelector('app-gamecontent') observer


////
//var rootElement = getAllAngularRootElements()[0].children[1]["__ngContext__"][30];
//      storage = rootElement.playerGeneralService;
////


//0.64
// rootElement.playerCurrencyService.gem_fragments
//

//QQOL.gameData.marketService.serviceOrders
//

class FTGMod {
 constructor() {
   this.ver = '0.64';
   //OBSERVERS
   var modbody = this;
   this.serviceOrders = {};
   this.newActionObserver = new MutationObserver(function(mutations) {
     mutations.forEach(function(mutation) {
          modbody.OnNewAction();
     });
    });
    this.newActionObserver.observe(
      document.querySelector('head > title'),
      {subtree: true, characterData: true, childList: true }
    );
    this.onactionhooks = [];



    this.newTabObserver = new MutationObserver(function(mutations) {
      //APP-INVENTORY
      mutations.forEach(function(mutation) {
        if (mutation.target.nodeName.toLowerCase().includes('app-')) {
          if (mutation.addedNodes.length>0) {
            if (mutation.target.nodeName.toLowerCase().split('-').length==2) {
              if (mutation.target.nodeName.toLowerCase().split('-')[1]!='gamecontent') {
                let tab = mutation.target.nodeName.toLowerCase().split('-')[1];
                //crafting
                if (tab=='actions') {
                  let subtab = mutation.target.childNodes[2].nodeName.toLowerCase().split('-')[1];
                  if (subtab=='actions') {
                    subtab=='pets'; //Blah pls
                  }
                  modbody.currentTab = subtab;
                  modbody.OnNewTab(subtab);
                } else if (tab=='market') {
                  let subtab = mutation.target.childNodes[2].nodeName.toLowerCase().split('-')[2];
                  modbody.currentTab = subtab;
                  modbody.OnNewTab(subtab);
                } else {
                  modbody.currentTab = mutation.target.nodeName.toLowerCase().split('-')[1];
                  modbody.OnNewTab(mutation.target.nodeName.toLowerCase().split('-')[1]);
                }

            }
            }

          }
        }
      });
    });

   this.newTabObserver.observe(
     document.querySelector('app-gamecontent'),
     {subtree: true, childList: true }
   );
   this.ontabhooks = [];
   //I SUCK AT JS
   //document.onclick = function(){modbody.Update()} //im retarded, look up hooks later
                                                   //.clickable onclick?

   //NEW DOM
   var csselem = document.createElement("link");
   csselem.setAttribute("rel", "stylesheet");
   csselem.setAttribute("type", "text/css");
   csselem.setAttribute("href", "https://countto25.github.io/QueslarQQOL/cssfix.css");
   document.getElementsByTagName("head")[0].appendChild(csselem);

   let QQOLholder = document.createElement('div');
   QQOLholder.id = 'QQOL_holder';
   document.getElementById('profile-next-level').parentNode.insertBefore(QQOLholder,document.getElementById('profile-next-level').nextSibling);
   //document.getElementById('mat-tab-content-0-1').children[0].appendChild(QQOLholder);

   let QQOLinfo = document.createElement('div');
   QQOLinfo.style.marginTop = '10px';
   QQOLinfo.id='QQOL_info';
   QQOLinfo.innerHTML = '<mat-icon class="mat-icon material-icons" style="vertical-align: bottom: height: 16px; width: 16px; font-size: 16px">settings</mat-icon><span id="toSettings" class="QQOL-link-action">QQOL v'+this.ver+'</span>';

   let QQOLquests = document.createElement('div');
   QQOLquests.id='QQOL_quests';
   QQOLquests.innerHTML = 'Loading...';

   let QQOLkdexp = document.createElement('div');
   QQOLkdexp.id='QQOL_kingdomexploration';
   QQOLkdexp.innerHTML = '';


   let QQOLTimeToTargetLevel = document.createElement('div');
   QQOLTimeToTargetLevel.id='QQOL_TTTL';
   if (!localStorage.targetLevel || parseInt(localStorage.QQOL_tttl_show)!=1)
    QQOLTimeToTargetLevel.style.display = 'none';
   QQOLTimeToTargetLevel.innerHTML = '';

   let timetoleveluptooltip = document.createElement('div');
   timetoleveluptooltip.id = 'QQOL_time_to_levelup';
   let idletimeremainingtooltip = document.createElement('div');
   idletimeremainingtooltip.id='QQOL_remaining_time';
   document.getElementById('QQOL_holder').appendChild(QQOLinfo);
   document.getElementById('QQOL_holder').appendChild(idletimeremainingtooltip);
   document.getElementById('QQOL_holder').appendChild(timetoleveluptooltip);
   document.getElementById('QQOL_holder').appendChild(QQOLquests);
   document.getElementById('QQOL_holder').appendChild(QQOLTimeToTargetLevel);
   document.getElementById('QQOL_holder').appendChild(QQOLkdexp);


   //DECLARE SHIT
   this.rememberquest = null;
   this.activetab = null;
   this.updateInterval = null;

   //FINISH
   this.HookOnAction(() => {modbody.Update()});
   this.HookOnAction(() => {if (modbody.rememberquest!=null && document.title.split(' - ')[1]!='Party') modbody.rememberquest--;});
   this.HookOnAction(() => {if (modbody.updateInterval == null) {modbody.updateInterval = setInterval(() => {modbody.Update()}, 100)}});
   this.HookOnAction(() => this.IncomePerHour());

   this.HookOnTab((x) => {console.log(x)});
   this.HookOnTab((x) => {modbody.activetab = x});
   this.HookOnTab((x) => {if (x==='battle') this.BlockActionsOnOvercap()});

   setInterval(() => {modbody.CheckLatestVersion()}, 1000000);

   this.CheckLatestVersion();
   this.DoUI();
   this.SetupSettings();
   this.ReflectSettings();



   console.log('loaded Quality of Quality of Life mod v'+this.ver+'. Have a nice day!');
 }

 HookOnAction(func, exec=false) {
   if (exec) func();
   this.onactionhooks.push(func);
 }
 HookOnTab(func, exec=false) {
   if (exec) func();
   this.ontabhooks.push(func);
 }

 get gameData() {
   let rootElement = getAllAngularRootElements()[0].children[1]["__ngContext__"][30];
   return rootElement.playerGeneralService;

 }

 Update() {
   this.TimeRemaining();
   this.TimeToLevelUp();
   this.TimeToQuestComplete();
   this.ReflectTimeToTargetLevel();
   this.explorationTimer();
 }

 GetRemainingActions() {
   return this.gameData.playerActionService.actions.remaining;
 }

 OnNewAction() {
   for (let i=0; i<this.onactionhooks.length; i++) {
     this.onactionhooks[i]();
   }
 }

 OnNewTab(tname) {
   for (let i=0; i<this.ontabhooks.length; i++) {
     this.ontabhooks[i](tname);
   }
 }

 CreateTimerWindow() {
   if (document.querySelector('.h5.mt-1')) {
     let timerelement = document.createElement('span');
    timerelement.id = 'FTG_idle_timer';
    timerelement.classList.add('h5');
    timerelement.setAttribute('style','margin-top: .25rem !important;');
    document.querySelector('.h5.mt-1').parentNode.insertBefore(timerelement,document.querySelector('.h5.mt-1'))
  }
 }

 BlockActionsOnOvercap() {
   return '';
   //find smth to do with issue
   if (this.gameData.playerActionService.actions.remaining > this.gameData.playerActionService.actions.total &&
       this.gameData.playerActionService.currentSkill == "battling" &&
       !this.gameData.partyService.isFighting) {
     document.querySelector('[joyridestep="startingTutorialSix"]').style.pointerEvents = 'none';
     document.querySelector('[joyridestep="startingTutorialSix"]').innerHTML = 'Refreshing will reset action cap';
   } else {
     document.querySelector('[joyridestep="startingTutorialSix"]').style.pointerEvents = 'unset';
     document.querySelector('[joyridestep="startingTutorialSix"]').innerHTML = 'Fight';
   }
 }

 TimeRemaining() {
   let actionsRemaining = this.GetRemainingActions();
   let txt ='Idle time remaining: '+this.ActionsToTime(actionsRemaining);
   let playerId = this.gameData.gameService.playerData.id;
   if (this.gameData.partyService.hasParty) {
    let partyActionsRemaining = this.gameData.partyService.partyOverview.partyInformation[playerId].actions.daily_actions_remaining;
    actionsRemaining += partyActionsRemaining;
    //<span class="QQOL-tooltip">
    txt ='<span class="QQOL-tooltip"><span class="QQOL-tooltiptext">'
      +this.GetRemainingActions()+
      ' solo actions and '+partyActionsRemaining+' party actions</span>Idle time remaining</span>: '
      +this.ActionsToTime(actionsRemaining);
   }
   if (this.GetRemainingActions()<0) {
     txt ="<span style='color: red'>Restart your actions!</span>";
   }
   if (document.getElementById('QQOL_remaining_time'))
    document.getElementById('QQOL_remaining_time').innerHTML=txt;
 }

 explorationTimer()
 {
     //rootElement.playerGeneralService.playerKingdomService.kingdomData.selectedExploration

     if (!this.gameData.playerKingdomService.isInKingdom) {
         return;
     }

     if (!this.gameData.playerKingdomService.kingdomData) {
         return;
     }

     if (!this.gameData.playerKingdomService.kingdomData.selectedExploration) {
         return;
     }

     let exploration = this.gameData.playerKingdomService.kingdomData.selectedExploration;
     let timetoend = new Date(exploration.exploration_timer);
     timetoend = Math.floor(timetoend.getTime() / 1000);
     let now = new Date();
     now = Math.floor(now.getTime() / 1000);

     let diff = timetoend - now;
     let time = this.SecondsToString(diff);
     document.querySelector('#QQOL_kingdomexploration').innerHTML = 'KD exploration: '+time;
 }

 GetSeconds(actions) {
   return '';
 }

 IncomePerHour() {
  let infospan;
  let subname = (this.currentTab == 'party')?'p':'s'
  if (!document.querySelector('#QQOL_GEPH_'+subname)) {
    let appendTo = document.querySelector('.action-result-value-container');
    infospan = document.createElement('div');
    infospan.style.marginTop = '10px';
    infospan.id='QQOL_GEPH_'+subname;
    if (appendTo)
      appendTo.appendChild(infospan);
  } else {
    infospan = document.querySelector('#QQOL_GEPH_'+subname);
  }
  if (this.currentTab == 'party') {
    if (Object.keys(this.gameData.partyService.actionResult).length!=0) {
      let exp = this.gameData.partyService.actionResult.income.experience.amount;
      let gold = this.gameData.partyService.actionResult.income.gold.amount;
      infospan.innerHTML = `(<span class='QQOL-tooltip'>${(gold*600).toLocaleString()} gold and ${(exp*600).toLocaleString()} experience per hour<span class='QQOL-tooltiptext'>Unless you die</span></span>)`;
    }
  } else {
    if (Object.keys(this.gameData.playerActionService.actionResult).length!=0) {
      let exp = this.gameData.playerActionService.actionResult.income.experience.amount;
      let gold = this.gameData.playerActionService.actionResult.income.gold.amount;
      infospan.innerHTML = `(<span class='QQOL-tooltip'>${(gold*600).toLocaleString()} gold and ${(exp*600).toLocaleString()} experience per hour<span class='QQOL-tooltiptext'>Unless you die</span></span>)`;
    }
  }
 }


 TimeToQuestComplete() {
   let txt;
   let cQuest = this.gameData.playerQuestService.currentQuest[0];
   if (this.gameData.playerQuestService.currentQuestId!=0) {
     if (cQuest.objectiveType=='actions') {
       let remaining = cQuest.objectiveAmount - cQuest.currentProgress;
       txt = 'Time to quest completion: '+this.ActionsToTime(remaining);
    } else if (cQuest.objectiveType=='kills') {
      if (this.gameData.playerActionService.currentSkill=='battling') {
        txt = '<span class="QQOL-tooltip">Time to quest completion<span class="QQOL-tooltiptext">If you keep on fighting solo and avoiding death</span></span>: '
          +this.ActionsToTime(cQuest.objectiveAmount - cQuest.currentProgress)
      } else {
        txt = 'Kills quest active, not in battle';
      }
    } else if (cQuest.objectiveType=='gold') {
        if (this.gameData.playerActionService.currentSkill=='battling') {
          let gpt = 0;
          if (!this.gameData.partyService.isFighting) {
            gpt = this.gameData.playerActionService.actionResult.income.gold.amount;
            if (this.gameData.playerActionService.actionResult.income.gold.tax)
              gpt+=this.gameData.playerActionService.actionResult.income.gold.tax;
          } else {
              txt = 'Doing party actions';
              if (document.querySelector('#QQOL_quests'))
               document.querySelector('#QQOL_quests').innerHTML=txt;
              return false;
          }
          let actionsToCompletion = Math.ceil((cQuest.objectiveAmount - cQuest.currentProgress)/gpt);
          txt =
            '<span class="QQOL-tooltip">Time to quest completion<span class="QQOL-tooltiptext">At '
            +gpt+' gold per turn</span></span>: '+this.ActionsToTime(actionsToCompletion);
      } else {
        txt = 'Gold quest active, not in battle';
      }
    }
   } else {
     txt = '<span style="color:red">Grab a new quest!</span>';
   }
   if (document.querySelector('#QQOL_quests'))
    document.querySelector('#QQOL_quests').innerHTML=txt;
  }

 TimeToLevelUp() {
   if (document.getElementById('profile-next-level')) {
   let txt = document.getElementById('profile-next-level').innerHTML;
   let actionVal = parseInt(txt.replace(/\D/g,''));
   txt='Time to next level: '+this.ActionsToTime(actionVal);
   if (document.getElementById('QQOL_time_to_levelup'))
    document.getElementById('QQOL_time_to_levelup').innerHTML = txt;
    }

 }

 ExpToLevel() {
   let expBank = 0;
   let currentLevel = this.gameData.playerLevelsService.battling.level;
   if (!localStorage.getItem('targetLevel')) return false;
   let targetLevel = parseInt(localStorage.getItem('targetLevel'));
   let currentExp = this.gameData.playerLevelsService.battling.exp.have;
   if (targetLevel == 0) return false;
   for (let i=currentLevel; i<targetLevel; i++) {
     let expToLevel = Math.round(25000 * Math.pow(i, 0.5));
     let levelTemp = i;
     while (levelTemp > 1500) {
       expToLevel +=  250 * Math.pow((levelTemp - 1500), 1.25)
       levelTemp -= 1500;
     }
     expBank+=expToLevel;
   }
   return expBank-currentExp;
 }

 TimeToTargetLevel() {
   if (!localStorage.getItem('targetLevel')) {
     return 'Time to target level: check settings';
   }
   let actionVal;
   if (this.gameData.playerActionService.actionResult.income && this.gameData.playerActionService.actionResult.income.experience.amount) {
      actionVal = this.gameData.playerActionService.actionResult.income.experience.amount;
   } else {return '';}
   let totalExpReq = this.ExpToLevel();
   let actionsReq = Math.ceil(totalExpReq/actionVal);
   let tLevel = localStorage.targetLevel;
   return 'Time to level '+tLevel+': '+this.ActionsToTime(actionsReq);
 }

 ReflectTimeToTargetLevel() {
   let div = document.getElementById('QQOL_TTTL');
   if (!div) return;
   div.innerHTML = this.TimeToTargetLevel();
 }

 FindProvider() {
   let sTerm = document.getElementById('QQOL_service_search').value.toLowerCase();
   let users = document.querySelectorAll('td.cdk-column-username.mat-column-username > div');
   for (let i=0; i<users.length; i++) {
     if (users[i].innerHTML.toLowerCase().includes(sTerm)) {
       users[i].parentNode.parentNode.removeAttribute('style');
     } else {
       users[i].parentNode.parentNode.style.display='none'
     }
   }
 }
 ActionsToTime(actions) {
   if (actions<0) return '00:00';
   let minval = Math.floor(actions/10);
   let hourval = Math.floor(minval/60);
   let remMinutes = minval%60;
   let remSeconds = actions/10
   let subSeconds =  this.gameData.partyService.isFighting?this.gameData.partyService.countDown:this.gameData.playerActionService.countDown;
   if ((actions*6%60) - (6-subSeconds)  < 0)
    remMinutes--;

    let remSec = actions*6%60;
    let a = 6-subSeconds;
    if (remSec-a<0) {remSec=remSec+60-a} else {remSec = remSec-a;}
    if (remSec<10) remSec='.0'+remSec;
    else remSec='.'+remSec;

   let dayVal = Math.floor(hourval/24);
   return ((dayVal>0)?(dayVal+'d '):(''))+hourval%24+':'+(remMinutes<10?('0'+remMinutes):(remMinutes))+remSec;
 }



 SecondsToString(seconds)
{
  var numyears = Math.floor(seconds / 31536000);
  var numdays = Math.floor((seconds % 31536000) / 86400);
  var numhours = Math.floor(((seconds % 31536000) % 86400) / 3600);
  var numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60);
  var numseconds = Math.floor((((seconds % 31536000) % 86400) % 3600) % 60);
  return numhours.toString().padStart(2, '0') + ":" + numminutes.toString().padStart(2, '0') + "." + numseconds.toString().padStart(2, '0');
}




 get myEquipmentData() {
   let myID = this.gameData.gameService.playerData.id;
   return this.gameData.partyService.partyOverview.partyInformation[myID].equipment;
 }

  IsPlayerRelated(name) {
    if (this.playerRelatives.includes(name))
      return true;
    else
      return false;
 }



  CheckLatestVersion() {
    let modbody = this;
    var request = new XMLHttpRequest();
    request.open('GET', 'https://api.github.com/repos/countto25/queslarqqol/tags', true);
    request.onload = function() {
      if (request.status >= 200 && request.status < 400) {
        var data = JSON.parse(request.responseText);
        console.log(data);
        let latestVersion = data[1].name;
        console.log(parseFloat(latestVersion) + ' vs ' +parseFloat(modbody.ver));
        console.log(modbody.ver);
        console.log(parseFloat(latestVersion) > parseFloat(modbody.ver));
        if ((parseFloat(latestVersion) > parseFloat(modbody.ver))) {
          let txt = 'QQOL v'+modbody.ver+'. <a target="_blank" href="https://countto25.github.io/QueslarQQOL?update=true" class="QQOL-link-action" style="color:red; text-decoration: none">Please update</a>';
          document.querySelector('#toSettings').innerHTML=txt;
        } else if (parseFloat(latestVersion) < parseFloat(modbody.ver)) {
          let txt = 'QQOL v'+modbody.ver+'. <span style="color:green; text-decoration: none">Maybe do your actual job?</span>';
          document.querySelector('#toSettings').innerHTML=txt;
        }
      } else {console.log('error getting new version :')}
    }
    request.send();
  }

  fetchHTML(url) {
    if( 'undefined' == typeof(url) ) return false;
    let p;
    if( document.all ){
      p = new ActiveXObject("Microsoft.XMLHTTP");
    } else {
    p = new XMLHttpRequest();
    }
    let rnd = Math.random().toString().substring(3);
    if( url.indexOf('?') > -1 )
    {
      url+='&rnd='+rnd;
    }
    else
    {
      url+='?rnd='+rnd;
    }
    p.open("GET",url,false);
    p.send(null);
    return p.responseText;
}

  DoUI() {
    let div = document.createElement("div");
    let settingsmenu = this.fetchHTML('https://countto25.github.io/QueslarQQOL/menu.html');
    div.classList.add("QQOLsettings");
    div.style.display = 'none';
    div.innerHTML = settingsmenu;
    let modbody = this;
    document.body.appendChild(div);
    document.querySelector('#exitSettings').onclick = function() {
      document.querySelector('.QQOLsettings').style.display='none';
      modbody.ReflectSettings();
    }
    document.querySelector('#contactme').onclick = function() {
      document.querySelector('.chat-input ').value='/w FiammaTheGreat';
      document.querySelector('.QQOLsettings').style.display='none';
      modbody.ReflectSettings();
    }
    document.querySelector('#toSettings').onclick = function() {
      document.querySelector('.QQOLsettings').style.display='block';
    }
    let checks = document.querySelectorAll('input[type=checkbox].QQOLCheck');
    checks.forEach(check => {
      check.oninput = function() {
        localStorage.setItem('QQOL_'+this.getAttribute('for'), this.checked?1:0);
        console.log(this.checked?1:0);
      }
    });
    document.querySelector('input[for=tttl_value]').oninput = function() {
      localStorage.setItem('targetLevel', this.value);
    }
  }
  SetupSettings() {
    if (localStorage.getItem('QQOL_itr_show')===null) {
      localStorage.setItem('QQOL_itr_show', 1);
    }
    if (localStorage.getItem('QQOL_nl_show')===null) {
      localStorage.setItem('QQOL_nl_show', 1);
    }
    if (localStorage.getItem('QQOL_ttqc_show')===null) {
      localStorage.setItem('QQOL_ttqc_show', 1);
    }

    if (localStorage.getItem('QQOL_tttl_show')===null) {
      localStorage.setItem('QQOL_tttl_show', 0);
    }
    if (localStorage.getItem('QQOL_ttke_show')===null) {
        localStorage.setItem('QQOL_ttke_show', 0);
    }

    if (localStorage.getItem('QQOL_itr_show') === '0') {
      document.querySelector('input[for=itr_show]').checked = false;
    } else {
      document.querySelector('input[for=itr_show]').checked = true;
    }
    if (localStorage.getItem('QQOL_nl_show') === '0') {
      document.querySelector('input[for=nl_show]').checked = false;
    } else {
      document.querySelector('input[for=nl_show]').checked = true;
    }

    if (localStorage.getItem('QQOL_ttqc_show') === '0') {
      document.querySelector('input[for=ttqc_show]').checked = false;
    } else {
      document.querySelector('input[for=ttqc_show]').checked = true;
    }

    if (localStorage.getItem('QQOL_tttl_show') === '0') {
      document.querySelector('input[for=tttl_show]').checked = false;
    } else {
      document.querySelector('input[for=tttl_show]').checked = true;
    }

    if (localStorage.getItem('QQOL_ttke_show') === '0') {
      document.querySelector('input[for=ttke_show]').checked = false;
    } else {
      document.querySelector('input[for=ttke_show]').checked = true;
    }

    let tl = (localStorage.getItem('targetLevel') || -1);
    if (tl != -1) {
      document.querySelector('input[for=tttl_value]').value = parseInt(tl);
    }
  }

  ReflectSettings() {
    if (localStorage.getItem('QQOL_itr_show') === '0') {
      document.querySelector('#QQOL_remaining_time').style.display = 'none';
    } else {
      document.querySelector('#QQOL_remaining_time').style.display = 'block';
    }

    if (localStorage.getItem('QQOL_nl_show') === '0') {
      document.querySelector('#QQOL_time_to_levelup').style.display = 'none';
    } else {
      document.querySelector('#QQOL_time_to_levelup').style.display = 'block';
    }

    if (localStorage.getItem('QQOL_ttqc_show') === '0') {
      document.querySelector('#QQOL_quests').style.display = 'none';
    } else {
      document.querySelector('#QQOL_quests').style.display = 'block';
    }

    if (localStorage.getItem('QQOL_ttke_show') === '0') {
      document.querySelector('#QQOL_kingdomexploration').style.display = 'none';
    } else {
      document.querySelector('#QQOL_kingdomexploration').style.display = 'block';
    }

    if (localStorage.getItem('QQOL_tttl_show') === '0') {
      document.querySelector('#QQOL_TTTL').style.display = 'none';
    } else {
      document.querySelector('#QQOL_TTTL').style.display = 'block';
    }

  }

  AdvanceFromCurrent(exp) {
    let projectedLevel = this.gameData.playerLevelsService.battling.level;
    while (exp > 0) {
      let expToLevel = Math.round(25000 * Math.pow(projectedLevel, 0.5));
      let levelTemp = projectedLevel;
      while (levelTemp > 1500) {
        expToLevel +=  250 * Math.pow((levelTemp - 1500), 1.25)
        levelTemp -= 1500;
      }
      projectedLevel++;
      exp-=expToLevel;
    }
    return projectedLevel;
  }
 }


//TY GREASEMONKEY
var QQOL = null;
console.log('init load');
var QQOLSetupInterval = setInterval(QQOLGMSetup, 1000);
function QQOLGMSetup() {
  if (document.getElementById('profile-next-level')&&QQOL===null) {
    console.log('load OK');
    clearInterval(QQOLSetupInterval);
    console.log(QQOLSetupInterval+'');
    QQOL = new FTGMod();

  } else {
    console.log('retry init...');
    console.log('next level?'+document.getElementById('profile-next-level'));
    console.log((document.getElementById('profile-next-level')&&QQOL===null));
  }
}