// ==UserScript== // @author Audrey // @description Helper script for Fallenlondon // @downloadURL https://forge.chapril.org/audrey/fallen_london_scripts/raw/branch/master/FL_enhancer.user.js // @grant none // @icon https://images.fallenlondon.com/favicons/favicon.ico // @match https://www.fallenlondon.com/* // @name FallenLondon Enhancer // @namespace https://forge.chapril.org/audrey/ // @require https://forge.chapril.org/audrey/fallen_london_scripts/raw/branch/master/jquery/jquery-3.6.0.min.js // @version 0.1-rc1 // ==/UserScript== "use strict"; $(document).ready(fl_enhancer); /////////// // STORY // /////////// function update_airs_bar() { if (!localStorage.FLE_airs) { return; } let quirks = JSON.parse(localStorage.FLE_airs); let html = '
'; $.each(quirks, function( key, value ) { html += '
' + value.num + '
'; }); $('div#FLE-airs').remove(); $(html + '
').insertAfter('button.travel-button--infobar'); } function get_airs_value() { let updated = false; let airs = {} if (localStorage.FLE_airs) { airs = JSON.parse(localStorage.FLE_airs); } // Airs from a Location (storylet requirement) let airs_unlock = $('[alt^="You unlocked this with The Airs"]').first(); if (airs_unlock.length) { console.log('airs detected'); let [_, txt, num] = airs_unlock.attr('alt').match(/You unlocked this with (The Airs.*?)(\d+)/); if (!airs[txt]) { airs[txt] = { 'num': num, 'img': airs_unlock.attr('src') }; } updated = true; } if (updated) { localStorage.setItem('FLE_airs', JSON.stringify(airs)); } } //////////// // BAZAAR // //////////// let items_total_value_displayed = false; function display_items_total_value() { // Prevents multiple display if spamming the "bazaar" link if (items_total_value_displayed) { return; } // Only computing the sum if all items are displayed let shop = $('button.menu-item--active') if (shop.length && shop.text() != "Sell my things") { return; } let total_price = 0; $('li.shop__item').each( function( index, element ){ total_price = ( $( this ).find('span.js-item-value').text() * // Number of items $( this ).find('div.item__price').text() // Price ); }); $('.input--item-search').after('
  • Total value:
    ' + total_price + '
  • '); items_total_value_displayed = true; } //////////// // MYSELF // //////////// function update_quirks_bar() { if (!localStorage.FLE_quirks) { return; } let quirks = JSON.parse(localStorage.FLE_quirks); let html = '
    '; $.each(quirks, function( key, value ) { html += '
    ' + value.num + '
    '; }); $('div#FLE-quirks').remove(); $(html + '
    ').insertAfter('button.travel-button--infobar'); } function update_contacts_bar() { if (!localStorage.FLE_contacts) { return; } let icon_value_color = { '0': '', '1': '', '2': '', '3': '', '4': '', '5': 'background-color: rgb(180, 140, 0);', '6': 'background-color: rgb(190, 110, 23);', '7': 'background-color: rgb(183, 70, 5);', }; let contacts = JSON.parse(localStorage.FLE_contacts); let html = '
    '; let z_index = 0; $.each(contacts, function( key, value ) { html += '
    ' + value.Renown + '+' + value.Favours + '
    '; }); $('div#FLE-contacts').remove(); $(html + '
    ').insertAfter('button.travel-button--infobar'); } function get_quirks() { let quirks = {} $("[data-group-name=Quirks] li.quality-item").each( function( index, element ){ let found = $( this ).find('span').prop('textContent').match(/(\w+)\s+(\d+)/); if (found){ let [_, quirk, num] = found; quirks[quirk] = {'num': num, 'img': $( this).find('img').prop('src')}; } }); localStorage.setItem('FLE_quirks', JSON.stringify(quirks)); } function get_contacts() { let contacts = {} $("[data-group-name=Contacts] li.quality-item").each( function( index, element ){ let found = $( this ).find('span').prop('textContent').match(/(:?Favours|Renown): (.*) (\d+)\/\d+/); if (found) { let [_, type, faction, num] = found; if (!contacts[faction]) { contacts[faction] = {'Renown': 0, 'Favours': 0, 'img': $( this).find('img').prop('src')}; } contacts[faction][type] = num; } }); localStorage.setItem('FLE_contacts', JSON.stringify(contacts)); } function myself() { get_quirks(); update_quirks_bar(); get_contacts(); update_contacts_bar(); } ///////////////// // POSSESSIONS // ///////////////// function update_advantage_bar() { if (!localStorage.FLE_advantage) { return; } let advantage = JSON.parse(localStorage.FLE_advantage); let html = '
    '; $.each(advantage, function( key, value ) { html += '
    ' + value + '
    '; }); $('div#FLE-advantage').remove(); $(html + '
    ').insertAfter('button.travel-button--infobar'); } function get_advantage() { let advantage = {}; $("[data-group-name=Advantage] li.item img").each( function( index, element ){ let found = $( this ).prop('alt').match(/× (\d+);/); if (found) { advantage[$( this ).prop('src')] = found[1]; } }); localStorage.setItem('FLE_advantage', JSON.stringify(advantage)); } function possessions() { get_advantage(); update_bar(); } function monitor_url_change() { // https://dirask.com/posts/JavaScript-on-location-changed-event-on-url-changed-event-DKeyZj // If the url is updated ... ;(function() { let pushState = history.pushState; let replaceState = history.replaceState; history.pushState = function() { pushState.apply(history, arguments); window.dispatchEvent(new Event('pushstate')); window.dispatchEvent(new Event('locationchange')); }; history.replaceState = function() { replaceState.apply(history, arguments); window.dispatchEvent(new Event('replacestate')); window.dispatchEvent(new Event('locationchange')); }; window.addEventListener('popstate', function() { window.dispatchEvent(new Event('locationchange')); }); })(); } //////////// // GLOBAL // //////////// function update_bar() { update_airs_bar(); update_advantage_bar(); update_quirks_bar(); update_contacts_bar(); } function cleanup() { // Remove the banner $('div.banner').remove(); // Remove the candles $('div.candle-container').remove(); } function display_stats_progress() { $('ul.items--list li.sidebar-quality').each( function( index, element ){ bar = $( this ).find('div.progress-bar'); percent = bar.find('span').prop('style').width.slice(0, -1); lvl = Number($( this ).find('span.item__value').text()); target = lvl + 1; lvl_pts = Math.round(lvl * target / 2); CP = Math.round(target * percent / 100); points = Math.round(lvl_pts + CP); bar.html( bar.html() + '' + points + ' (' + lvl_pts + '+' + CP + '/' + target + ')' ); }); } function common() { // Remove the FL banner to avoid useless scrolling cleanup(); // Display CP and number of points required for the next level near the progress bar display_stats_progress(); // Display contacts, quirks, possessions & airs in the sidebar update_bar(); } function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } function go() { // Always done regardless of the location common(); // Actions specific to some locations url = window.location.toString(); if (url != 'https://www.fallenlondon.com/bazaar') { items_total_value_displayed = false; } switch (url) { case 'https://www.fallenlondon.com/': get_airs_value(); update_bar(); break; case 'https://www.fallenlondon.com/bazaar': display_items_total_value(); break; case 'https://www.fallenlondon.com/possessions': possessions(); break; case 'https://www.fallenlondon.com/myself': myself(); break; default: console.log(''); } } async function fl_enhancer() { // On page load (by the browser) await sleep(3600); go(); // When the url is updated by js monitor_url_change(); window.addEventListener('locationchange', async function(){ await sleep(2); go(); }); }