NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name InfoCompte // @namespace https://openuserjs.org/users/The_Stubbs // @version 11.1.4 // @description InfoCompte script for OGame // @author Vulca, benneb & now The Stubbs // @license MIT // @match https://*.ogame.gameforge.com/game/* // @updateURL https://openuserjs.org/meta/The_Stubbs/InfoCompte.meta.js // @downloadURL https://openuserjs.org/install/The_Stubbs/InfoCompte.user.js // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @run-at document-idle // @mood https://www.youtube.com/watch?v=FsfrsLxt0l8 // ==/UserScript== const playerId = document.querySelector('[name=ogame-player-id]').content; const version = 8; const key = `${ playerId }.${ version }`; function get$a() { return GM_getValue(key, {}); } function set$6(data) { GM_setValue(key, data); } function clear() { GM_setValue(key, {}); } var Storage = { get: get$a, set: set$6, clear }; const translations = { en: { 1: 'Metal mine', 2: 'Crystal mine', 3: 'Deuterium synthetizer', 4: 'Solar plant', 12: 'Fusion plant', 14: 'Robotics factory', 15: 'Nanite factory', 21: 'Shipyard', 22: 'Metal storage', 23: 'Crystal storage', 24: 'Deuterium storage', 31: 'Research laboratory', 33: 'Terraformer', 34: 'Alliance depot', 36: 'Repair dock', 41: 'Moonbase', 42: 'Sensor phalanx', 43: 'Jump gate', 44: 'Missile silo', 106: 'Espionage', 108: 'Computer', 109: 'Weapons', 110: 'Shielding', 111: 'Armour', 113: 'Energy', 114: 'Hyperspace', 115: 'Combustion drive', 117: 'Impulse drive', 118: 'Hyperspace drive', 120: 'Laser', 121: 'Ion', 122: 'Plasma', 123: 'Intergalacticresearch network', 124: 'Astrophysics', 199: 'Graviton', 202: 'Small cargo', 203: 'Large cargo', 204: 'Light fighter', 205: 'Heavy fighter', 206: 'Cruiser', 207: 'Battleship', 208: 'Colony ship', 209: 'Recycler', 210: 'Espionage probe', 211: 'Bomber', 212: 'Solar satellite', 213: 'Destroyer', 214: 'Deathstar', 215: 'Battlecruiser', 217: 'Crawlers', 218: 'Reaper', 219: 'Pathfinder', 401: 'Rocket launcher', 402: 'Light laser', 403: 'Heavy laser', 404: 'Gauss cannon', 405: 'Ion cannon', 406: 'Plasma turret', 407: 'Small shield dome', 408: 'Large shield dome', 502: 'Anti-ballistic missiles', 503: 'Interplanetary missile', 11_101: 'Residential Sector', 11_102: 'Biosphere Farm', 11_103: 'Research Centre', 11_104: 'Academy of Sciences', 11_105: 'Neuro-Calibration Centre', 11_106: 'High Energy Smelting', 11_107: 'Food Silo', 11_108: 'Fusion-Powered Production', 11_109: 'Skyscraper', 11_110: 'Biotech Lab', 11_111: 'Metropolis', 11_112: 'Planetary Shield', 11_201: 'Intergalactic Envoys', 11_202: 'High-Performance Extractors', 11_203: 'Fusion Drives', 11_204: 'Stealth Field Generator', 11_205: 'Orbital Den', 11_206: 'Research AI', 11_207: 'High-Performance Terraformer', 11_208: 'Enhanced Production Technologies', 11_209: 'Light Fighter Mk II', 11_210: 'Cruiser Mk II', 11_211: 'Improved Lab Technology', 11_212: 'Plasma Terraformer', 11_213: 'Low-Temperature Drives', 11_214: 'Bomber Mk II', 11_215: 'Destructeur Mk II', 11_216: 'Battlecruiser Mk II', 11_217: 'Robot Assistants', 11_218: 'Supercomputer', 12_101: 'Meditation Enclave', 12_102: 'Crystal Farm', 12_103: 'Rune Technologium', 12_104: 'Rune Forge', 12_105: 'Oriktorium', 12_106: 'Magma Forge', 12_107: 'Disruption Chamber', 12_108: 'Megalith', 12_109: 'Crystal Refinery', 12_110: 'Deuterium Synthesiser', 12_111: 'Mineral Research Centre', 12_112: 'Advanced Recycling Plant', 12_201: 'Magma Refinement', 12_202: 'Acoustic Scanning', 12_203: 'High Energy Pump Systems', 12_204: 'Cargo Hold Expansion', 12_205: 'Magma-Powered Production', 12_206: 'Geothermal Power Plants', 12_207: 'Depth Sounding', 12_208: 'Ion Crystal Enhancement (Heavy Fighter)', 12_209: 'Improved Stellarator', 12_210: 'Hardened Diamond Drill Heads', 12_211: 'Seismic Mining Technology', 12_212: 'Magma-Powered Pump Systems', 12_213: 'Ion Crystal Modules', 12_214: 'Optimised Silo Construction Method', 12_215: 'Diamond Energy Transmitter', 12_216: 'Obsidian Shield Reinforcement', 12_217: 'Rune Shields', 12_218: 'Rock’tal Collector Enhancement', 13_101: 'Assembly Line', 13_102: 'Fusion Cell Factory', 13_103: 'Robotics Research Centre', 13_104: 'Update Network', 13_105: 'Quantum Computer Centre', 13_106: 'Automatised Assembly Centre', 13_107: 'High-Performance Transformer', 13_108: 'Microchip Assembly Line', 13_109: 'Production Assembly Hall', 13_110: 'High-Performance Synthesiser', 13_111: 'Chip Mass Production', 13_112: 'Nano Repair Bots', 13_201: 'Catalyser Technology', 13_202: 'Plasma Drive', 13_203: 'Efficiency Module', 13_204: 'Depot AI', 13_205: 'General Overhaul (Light Fighter)', 13_206: 'Automated Transport Lines', 13_207: 'Improved Drone AI', 13_208: 'Experimental Recycling Technology', 13_209: 'General Overhaul (Cruiser)', 13_210: 'Slingshot Autopilot', 13_211: 'High-Temperature Superconductors', 13_212: 'General Overhaul (Battleship)', 13_213: 'Artificial Swarm Intelligence', 13_214: 'General Overhaul (Battlecruiser)', 13_215: 'General Overhaul (Bomber)', 13_216: 'General Overhaul (Destroyer)', 13_217: 'Experimental Weapons Technology', 13_218: 'Mechan General Enhancement', 14_101: 'Sanctuary', 14_102: 'Antimatter Condenser', 14_103: 'Vortex Chamber', 14_104: 'Halls of Realisation', 14_105: 'Forum of Transcendence', 14_106: 'Antimatter Convector', 14_107: 'Cloning Laboratory', 14_108: 'Chrysalis Accelerator', 14_109: 'Bio Modifier', 14_110: 'Psionic Modulator', 14_111: 'Ship Manufacturing Hall', 14_112: 'Supra Refractor', 14_201: 'Heat Recovery', 14_202: 'Sulphide Process', 14_203: 'Psionic Network', 14_204: 'Telekinetic Tractor Beam', 14_205: 'Enhanced Sensor Technology', 14_206: 'Neuromodal Compressor', 14_207: 'Neuro-Interface', 14_208: 'Interplanetary Analysis Network', 14_209: 'Overclocking (Heavy Fighter)', 14_210: 'Telekinetic Drive', 14_211: 'Sixth Sense', 14_212: 'Psychoharmoniser', 14_213: 'Efficient Swarm Intelligence', 14_214: 'Overclocking (Large Cargo)', 14_215: 'Gravitation Sensors', 14_216: 'Overclocking (Battleship)', 14_217: 'Psionic Shield Matrix', 14_218: 'Kaelesh Discoverer Enhancement', accountOverview: "Account overview", alliance: 'Alliance', amortizations: 'Amortizations', amortizationsSettings: 'Amortizations settings', amortizationsWarning: 'Takes time to complete', at: 'at', basicIncome: 'Basic income', buildings: 'Buildings', classes: 'Classes', clearAllData: "Clear all data", colors: 'Colors', costs: 'Costs', crystal: 'Crystal', dailyProductions: 'Daily productions', days: 'jours', defences: 'Defences', deuterium: 'Deuterium', deuteriumEquivalent: 'Deuterium equivalent', empire: 'Empire', empireOf: "Empire of", explorerPlayerClass: 'Discoverer', exports: 'Exports', exportNotification: 'Export placed in clipboard', gameforgeAffiliateLink: 'Gameforge affiliate link', generatedOn: 'Generated on', highscore: 'Highscore', hours: 'hours', humans: 'Humans', ifDestroyed: 'place(s) if destroyed', image: 'Image', indestructibles: 'Indestructibles', inProduction: 'In production', kaelesh: 'Kaelesh', kofi: 'Buy me a coffee', level: 'Level', levels: 'Levels', lifeform: 'Lifeform', lifeformBuildings: 'Lifeform buildings', lifeformLevels: 'Lifeform levels', lifeformResearches: 'Lifeform researches', lifeformSettings: "Lifefom settings", lifeforms: 'Lifeforms', maximum: 'maximum', maximumTemperatures: 'Maxmimum temperatures', mechas: 'Mechas', menuTitle: 'Script settings', metal: 'Metal', minerPlayerClass: 'Collector', mines: 'Mines', miscellaneous: 'Miscellaneous', months: 'months', moon: 'Moon', moons: 'Moons', moonBuildings: 'Moon buildings', moonDefences: 'Moon defences', neededData: 'Needed data', on: 'on', placeAccountOverviewOnTop: 'Place account overview on top', plainText: 'Plain text', planet: 'Planet', planetBuildings: 'Planet buildings', planetDefences: 'Planet defences', planetFields: 'Planet fields', planets: 'Planets', planetsPointsRepartition: 'Planets points repartition', planetsToIgnore: 'Planets to ignore', points: 'Points', pointsRepartition: 'Points repartition', premium: 'Objects & officers', production: 'Production', productionOf: "Production of", productions: 'Productions', rates: 'Trade rates', researcherAllicanceClass: 'Researcher', researches: 'Researches', resources: 'Resources', resourceSettings: 'Resource settings', rocktal: 'Rock’tal', settings: 'Settings', ships: 'Ships', shipyards: 'Shipyards', standardUnit: 'Standard unit', supportLink: 'https://forum.origin.ogame.gameforge.com/forum/thread/151-infocompte/', technologies: 'Technologies', textWithBBCode: 'Text with BBCode', total: 'Total', traderAllicanceClass: 'Trader', update: 'Update', used: 'used', useCompactNumbers: 'Use compact numbers', useMaximumCrawlers: 'Use the max. crawlers', useResourceBoosters: 'Use resource boosters', warriorAllicanceClass: 'Warrior', warriorPlayerClass: 'General', weeks: 'weeks', whenUpgraded: 'place(s) when upgraded', with: 'with', years: 'years' }, fr: { 1: "Mine de métal", 2: "Mine de cristal", 3: "Synthétiseur de deutérium", 4: "Centrale électrique solaire", 12: "Centrale électrique de fusion", 14: "Usine de robots", 15: "Usine de nanites", 21: "Chantier spatial", 22: "Hangar de métal", 23: "Hangar de cristal", 24: "Réservoir de deutérium", 31: "Laboratoire de recherche", 33: "Terraformeur", 34: "Dépôt de ravitaillement", 36: "Dock spatial", 41: "Base lunaire", 42: "Phalange de capteur", 43: "Porte de saut spatial", 44: "Silo de missiles", 106: "Espionnage", 108: "Ordinateur", 109: "Armes", 110: "Bouclier", 111: "Protection", 113: "Énergie", 114: "Hyperespace", 115: "Réacteur à combustion", 117: "Réacteur à impulsion", 118: "Propulsion hyperespace", 120: "Laser", 121: "Ions", 122: "Plasma", 123: "Réseau de recherche", 124: "Astrophysique", 199: "Graviton", 202: "Petit transporteur", 203: "Grand transporteur", 204: "Chasseur léger", 205: "Chasseur lourd", 206: "Croiseur", 207: "Vaisseau de bataille", 208: "Vaisseau de colonisation", 209: "Recycleur", 210: "Sonde d'espionnage", 211: "Bombardier", 212: "Satellite solaire", 213: "Destructeur", 214: "Étoile de la mort", 215: "Traqueur", 217: "Foreuses", 218: "Faucheur", 219: "Éclaireur", 401: "Lanceur de missiles", 402: "Artillerie laser légère", 403: "Artillerie laser lourde", 404: "Canon de Gauss", 405: "Artillerie à ions", 406: "Lanceur de plasma", 407: "Petit bouclier", 408: "Grand bouclier", 502: "Missile d'interception", 503: "Missile interplanétaire", 11_101: "Secteur résidentiel", 11_102: "Ferme biosphérique", 11_103: "Centre de recherche", 11_104: "Académie des sciences", 11_105: "Centre de neurocalibrage", 11_106: "Fusion à haute énergie", 11_107: "Réserve alimentaire", 11_108: "Extraction par fusion", 11_109: "Tour d’habitation", 11_110: "Laboratoire de biotechnologie", 11_111: "Metropolis", 11_112: "Bouclier planétaire", 11_201: "Intergalactic Envoys", 11_202: "Extracteurs à haute performance", 11_203: "Moteur à fusion", 11_204: "Générateur de champ de camouflage", 11_205: "Planque orbitale", 11_206: "IA de recherche", 11_207: "Terraformeur à haute performance", 11_208: "Technologies d'extraction améliorées", 11_209: "Chasseur léger Mk II", 11_210: "Croiseur Mk II", 11_211: "Technologie de laboratoire améliorée", 11_212: "Terraformeur à plasma", 11_213: "Propulseurs à faible température", 11_214: "Bombardier Mk II", 11_215: "Destroyer Mk II", 11_216: "Traqueur Mk II", 11_217: "Assistants robotiques", 11_218: "Superordinateur", 12_101: "Enclave stoïque", 12_102: "Culture du cristal", 12_103: "Centre technologique runique", 12_104: "Forge runique", 12_105: "Orictorium", 12_106: "Fusion magmatique", 12_107: "Chambre de disruption", 12_108: "Monument rocheux", 12_109: "Raffinerie de cristal", 12_110: "Syntoniseur de deutérium", 12_111: "Centre de recherche sur les minéraux", 12_112: "Usine de traitement à haut rendement", 12_201: "Batteries volcaniques", 12_202: "Sondage acoustique", 12_203: "Système de pompage à haute énergie", 12_204: "Extension d'espace fret", 12_205: "Extraction magmatique", 12_206: "Centrales géothermiques", 12_207: "Sondage en profondeur", 12_208: "Renforcement à cristaux ioniques", 12_209: "Stellarator amélioré", 12_210: "Tête de forage en diamant renforcées", 12_211: "Technologie d'extraction sismique", 12_212: "Pompes au magma", 12_213: "Module à cristaux ioniques", 12_214: "Construction optimisée de silos", 12_215: "Émetteur d'énergie à diamants", 12_216: "Intensification du bouclier à l'obsidienne", 12_217: "Boucliers runiques", 12_218: "Renfort du collecteur Rocta", 13_101: "Chaîne de production", 13_102: "Usine de fusion de cellules", 13_103: "Centre de recherche en robotique", 13_104: "Réseau d’actualisation", 13_105: "Centre d’informatique quantique", 13_106: "Centre d’assemblage automatisé", 13_107: "Transformateur hyperpuissant", 13_108: "Chaîne de production de micropuces", 13_109: "Atelier de montage", 13_110: "Synthétiseur à haut rendement", 13_111: "Production de masse de puces", 13_112: "Nanorobots réparateurs", 13_201: "Technique de catalyse", 13_202: "Moteur à plasma", 13_203: "Module d'optimisation", 13_204: "IA du dépôt", 13_205: "Révision général (chasseur léger)", 13_206: "Chaîne de production automatisée", 13_207: "IA de drone améliorée", 13_208: "Technique de recyclage expérimental", 13_209: "Révision général (croiseur)", 13_210: "Pilote automatique Slingshot", 13_211: "Supraconducteur à haute température", 13_212: "Révision général (vaisseau de bataille)", 13_213: "Intelligence artificielle collective", 13_214: "Révision général (traqueur)", 13_215: "Révision général (bombardier)", 13_216: "Révision général (destructeur)", 13_217: "Technique d'armement expérimental", 13_218: "Renforcement du général des Mechas", 14_101: "Refugium", 14_102: "Condensateur d’antimatière", 14_103: "Salle à vortex", 14_104: "Maison du savoir", 14_105: "Forum de la transcendance", 14_106: "Convecteur d’antimatière", 14_107: "Laboratoire de clonage", 14_108: "Accélérateur par chrysalide", 14_109: "Biomodificateur", 14_110: "Modulateur psionique", 14_111: "Hangar de construction de vaisseau", 14_112: "Supraréfracteur", 14_201: "Récupération de chaleur", 14_202: "Traitement au sulfure", 14_203: "Réseau psionique", 14_204: "Faisceau de traction télékinésique ", 14_205: "Technologie de détection améliorée", 14_206: "Compresseur neuromodal", 14_207: "Neuro-interface", 14_208: "Réseau d'analyse superglobal", 14_209: "Surcadençage (chasseur lourd)", 14_210: "Système de propulsion télékinétique", 14_211: "Sixième sens", 14_212: "Harmonisateur psychique", 14_213: "Efficient Swarm Intelligence", 14_214: "Surcadençage (grand transporteur)", 14_215: "Capteurs gravitationnels", 14_216: "Surcadençage (vaisseau de bataille)", 14_217: "Matrice de protection psionique", 14_218: "Renforcement d'explorateur Kaelesh", accountOverview: "Résumé du compte", alliance: "Alliance", amortizations: "Amortissements", amortizationsSettings: "Options d'amortissement", amortizationsWarning: "Prend un certain temps", at: "à", basicIncome: "Revenu de base", buildings: "Bâtiments", classes: "Classes", clearAllData: "Supprimer toutes les données", colors: "Couleurs", costs: "Coûts", crystal: "Cristal", dailyProductions: "Productions journalières", days: "jours", defences: "Défenses", deuterium: "Deutérium", deuteriumEquivalent: "Équivalent deutérium", empire: "Empire", empireOf: "Empire du joueur", explorerPlayerClass: "Explorateur", exports: "Exports", exportNotification: "Export placé dans le presse-papier", gameforgeAffiliateLink: "Lien d'affiliation Gameforge", generatedOn: "Généré le", highscore: "Classement", hours: "heures", humans: "Humains", ifDestroyed: "place(s) si détruit", image: "Image", indestructibles: "Indestructibles", inProduction: "En production", kaelesh: "Kaeleshs", kofi: "Buy me a coffee", level: "Niveau", levels: "Niveaux", lifeform: "Forme de vie", lifeformBuildings: "Bâtiments FDV", lifeformLevels: "Niveaux des FDV", lifeformResearches: "Recherches FDV", lifeformSettings: "Gestionnaire de forme de vie", lifeforms: "Formes de vie", maximum: "maximum", maximumTemperatures: "Températures maximales", mechas: "Mécas", menuTitle: "Options du script", metal: "Métal", minerPlayerClass: "Collecteur", mines: "Mines", miscellaneous: "Divers", months: "mois", moon: "Lune", moons: "Lunes", moonBuildings: "Bâtiments lunaires", moonDefences: "Défenses lunaires", neededData: "Données manquantes", on: "sur", placeAccountOverviewOnTop: 'Résumé du compte au-dessus', plainText: "Texte brut", planet: "Planète", planetBuildings: "Bâtiments planétaires", planetDefences: "Défenses planétaires", planetFields: "Cases planétaires", planets: "Planètes", planetsPointsRepartition: "Répartition des points par planète", planetsToIgnore: "Planètes à ignorer", points: "Points", pointsRepartition: "Répartition des points", premium: 'Objets & officiers', production: "Production", productionOf: "Production du joueur", productions: "Productions", rates: "Taux de change", researcherAllicanceClass: "Chercheur", researches: "Recherches", resources: "Ressources", resourceSettings: "Paramétrage des productions", rocktal: "Roctas", settings: "Options", ships: "Vaisseaux", shipyards: "Chantiers spatiaux", standardUnit: "Unité standard", supportLink: "https://board.fr.ogame.gameforge.com/index.php?thread/746302-infocompte/", technologies: "Technologies", textWithBBCode: "Texte avec BBCode", total: "Total", traderAllicanceClass: "Marchand", update: "Mettre à jour", used: "utilisées", useCompactNumbers: "Utiliser les nombres abrégés", useMaximumCrawlers: "Utiliser le max. de foreuses", useResourceBoosters: "Utiliser les boosters de ressources", warriorAllicanceClass: "Guerrier", warriorPlayerClass: "Général", weeks: "semaines", whenUpgraded: "place(s) quand terminé", with: "avec", years: "années" } }; var Translation = translations[document.documentElement.lang] || translations.en; const locale = LocalizationStrings.decimalPoint === '.' ? 'en-US' : 'de-DE'; const options$1 = { compact: { notation: 'compact' , compactDisplay: 'short', maximumFractionDigits: 2 }, decimal: { style: 'decimal', maximumFractionDigits: 2 }, percent: { style: 'percent', minimumFractionDigits: 2 } }; function getNumber(value) { value = value.replaceAll(LocalizationStrings.thousandSeperator, ''); value = value.replaceAll(LocalizationStrings.decimalPoint, '.'); return parseFloat(value); } function getFullNumberString$2(value) { return value.toLocaleString(locale, options$1.decimal); } function getTruncatedNumberString$2(value) { value = Math.trunc(value); return getFullNumberString$2(value); } function getCompactNumberString(value) { value = Math.floor(value).toLocaleString('en', options$1.compact); return value.replaceAll('.', LocalizationStrings.decimalPoint); } function getDurationString(value) { let unit; if (value === Infinity) { return Infinity; } else if (value > 8_760) { unit = Translation.years; value /= 8_760; } else if (value > 732) { unit = Translation.months; value /= 732; } else if (value > 168) { unit = Translation.weeks; value /= 168; } else if (value > 24) { unit = Translation.days; value /= 24; } else { unit = Translation.hours; } return `${ getFullNumberString$2(value) } ${ unit }`; } function getPercentString$1(value) { value ||= 0; return value.toLocaleString(locale, options$1.percent); } function getReducedObjects(...objects) { const result = {}; for (const object of objects) { for (const key in object) { if (areObjects(result[key], object[key])) { const value = getReducedObjects(result[key], object[key]); result[key] = value; } else if (object[key] !== undefined) { const value = object[key]; result[key] = value; } } } return result; } function toArray(value) { return value ? Array.isArray(value) ? value : [value] : []; } function areObjects(...values) { for(const value of values) { if (!isObject(value)) { return false; } } return true; } function isObject(value) { return value != null && value.constructor.name === 'Object'; } var Types = { getNumber, getFullNumberString: getFullNumberString$2, getTruncatedNumberString: getTruncatedNumberString$2, getCompactNumberString, getDurationString, getPercentString: getPercentString$1, getReducedObjects, toArray, areObjects, isObject }; const upgradables = { }; const mines = { all: [1, 2, 3] }; const buildings = { all: [4, 12, 14, 15, 21, 22, 23, 24, 31, 33, 34, 36, 41, 42, 43, 44], planet: [4, 12, 14, 15, 21, 22, 23, 24, 31, 33, 34, 36, 44], moon: [14, 21, 22, 23, 24, 41, 42, 43] }; const lifeforms$1 = { buildings: { humans: [11_101, 11_102, 11_103, 11_104, 11_105, 11_106, 11_107, 11_108, 11_109, 11_110, 11_111, 11_112], rocktal: [12_101, 12_102, 12_103, 12_104, 12_105, 12_106, 12_107, 12_108, 12_109, 12_110, 12_111, 12_112], mechas: [13_101, 13_102, 13_103, 13_104, 13_105, 13_106, 13_107, 13_108, 13_109, 13_110, 13_111, 13_112], kaelesh: [14_101, 14_102, 14_103, 14_104, 14_105, 14_106, 14_107, 14_108, 14_109, 14_110, 14_111, 14_112], null: [] }, researches: { humans: [11_201, 11_202, 11_203, 11_204, 11_205, 11_206, 11_207, 11_208, 11_209, 11_210, 11_211, 11_212, 11_213, 11_214, 11_215, 11_216, 11_217, 11_218], rocktal: [12_201, 12_202, 12_203, 12_204, 12_205, 12_206, 12_207, 12_208, 12_209, 12_210, 12_211, 12_212, 12_213, 12_214, 12_215, 12_216, 12_217, 12_218], mechas: [13_201, 13_202, 13_203, 13_204, 13_205, 13_206, 13_207, 13_208, 13_209, 13_210, 13_211, 13_212, 13_213, 13_214, 13_215, 13_216, 13_217, 13_218], kaelesh: [14_201, 14_202, 14_203, 14_204, 14_205, 14_206, 14_207, 14_208, 14_209, 14_210, 14_211, 14_212, 14_213, 14_214, 14_215, 14_216, 14_217, 14_218], null: [] } }; const researches = { all: [106, 108, 109, 110, 111, 113, 114, 115, 117, 118, 120, 121, 122, 123, 124, 199] }; const units = { defences: { all: [ 401, 402, 403, 404, 405, 406, 407, 408, 502, 503 ] }, ships: { all: [202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 217, 218, 219], statics: [212, 217] } }; const resources = { producers: [ 1, 2, 3, 4, 12, 11_101, 11_102, 12_101, 12_102, 13_101, 13_102, 14_101, 14_102 ], increasers: [ 11_106, 11_108, 11_202, 11_208, 12_106, 12_109, 12_110, 12_202, 12_203, 12_205, 12_207, 12_210, 12_211, 12_212, 13_110, 13_201, 13_206, 13_213, 14_202, 14_212 ], enhancers: [ 11_111, 12_213, 12_218, 13_107, 13_111 ] }; const planet = { }; const moon = { }; lifeforms$1.buildings.all = [...lifeforms$1.buildings.humans, ...lifeforms$1.buildings.rocktal, ...lifeforms$1.buildings.mechas, ...lifeforms$1.buildings.kaelesh]; lifeforms$1.researches.all = [...lifeforms$1.researches.humans, ...lifeforms$1.researches.rocktal, ...lifeforms$1.researches.mechas, ...lifeforms$1.researches.kaelesh]; lifeforms$1.all = [...lifeforms$1.buildings.all, ...lifeforms$1.researches.all]; upgradables.planet = [...mines.all, ...buildings.planet, ...lifeforms$1.all]; upgradables.moon = [...buildings.moon]; units.all = [...units.ships.all, ...units.defences.all]; units.ships.planet = units.ships.all; units.ships.moon = units.ships.planet.filter(id => id !== 217); units.planet = [...units.ships.planet, ...units.defences.all]; units.moon = [...units.ships.moon, ...units.defences.all]; units.statics = [...units.defences.all, ...units.ships.statics]; planet.all = [...upgradables.planet, ...units.planet]; moon.all = [...upgradables.moon, ...units.moon]; var IDs = { planet, moon, upgradables, mines, buildings, lifeforms: lifeforms$1, researches, units, resources }; const boosters = { 'b29918a7d1f313fd91d788c9c444dfbe996640ee': ['metal', .4], 'ce3bb161706f1788c893b3196834d67102318866': ['metal', .4], 'e17ff7930eb79c7207502348180a2b4a437474d4': ['metal', .4], '780aa9d6619ae572a318dacc29e7bb77ad980380': ['metal', .3], '9132f52e224e6ba87677e5ccc5cd1391320cf7d2': ['metal', .3], 'a0cba1aa5de23e877b10b196f40855bafc91256c': ['metal', .3], '1ab70d0954b4ebbb91e020c60afbaacb28707e5d': ['metal', .2], '5e62926be58e94ebb28a231ecad87f8e852d0f6d': ['metal', .2], '2e4d16cdaec1ea8ba2af28c914bb80f4d0939ce3': ['metal', .2], 'cea22d098a0b48c8960101e05c0bd2a7fadc72c5': ['metal', .1], '5650071c78c9fcf9681fc2c780694de96de29c1b': ['crystal', .4], 'd3f3321fcd999f657e9dc4ccf9cb34731524123f': ['crystal', .4], '5e33a2cfb73e9054540c5172f66b770b28765475': ['crystal', .4], '206bc65589c10c31b645c34991c12fc8556165b2': ['crystal', .3], '627957046e2d5315bf13104e258ca0ea37ca7489': ['crystal', .3], '11d508fc74f136dde21fe9506cad6db3d43149d5': ['crystal', .3], 'a703be5a40a8fe8128466721f5f925ae1e86d13a': ['crystal', .2], '2746f4d2372da032f4daa294606ee88e5ca7a46a': ['crystal', .2], '60a0fee6f82b2b4cec6928c1b052ac586f0b2a0d': ['crystal', .2], '286f3eaf6072f55d8858514b159d1df5f16a5654': ['crystal', .1], '7a10926f00a92b563713ade10f89777a98efd96c': ['deuterium', .4], 'd9b86d155a459c658cb7bfca594ce4b48e24546b': ['deuterium', .4], '55966a0911221acfc9b7a88791a2846f659a1e29': ['deuterium', .4], 'db408084e3b2b7b0e1fe13d9f234d2ebd76f11c5': ['deuterium', .3], '9f8eab23fd888c7d3c5a07e0d250a66f017ecec7': ['deuterium', .3], '4c7de7803df3ccb01d546ebce9e71379b1c49719': ['deuterium', .3], 'd5c2ed6852d80e61359aef62171ec7c932fc3bd7': ['deuterium', .2], '14a51990fe394912463be7a591b8c3fd41a47aad': ['deuterium', .2], 'b4c6a0e05891b6bfd9509bd92b6653d61fdae8e5': ['deuterium', .2], 'f0e514af79d0808e334e9b6b695bf864b861bdfa': ['deuterium', .1] }; function getBodyBoostersBonuses(ids) { const result = { metal: 0, crystal: 0, deuterium: 0 }; for (const id of ids) { const booster = boosters[id]; if (booster) { const [key, value] = booster; result[key] = value; } } return result; } function getCoordinates(string) { return string.slice(1, -1); } var Shared$1 = { getBodyBoostersBonuses, getCoordinates }; function getPositions$1() { const type = planetType && 'moon' || 'planet'; const result = {}; for (const element of document.querySelectorAll('.planet:not(.summary)')) { const coordinates = Shared$1.getCoordinates(element.querySelector('.planetData .coords').textContent); result[coordinates] = { [type]: getBody(element, type) }; } return result; } function getBody(element, type) { const result = { type, id: getBodyID$1(element), name: getBodyName$1(element), fields: getBodyFields$1(element), technologies: getTechnologies$1(element.querySelectorAll('.values:not(.items, .resources, .storage, .research) > div')) }; if (type === 'planet') { result.position = parseInt(element.querySelector('.coords').textContent.split(':').pop()); result.temperature = getBodyTemperature$1(element); result.resources = getBodyResources$1(element); result.boosters = getBodyBoosters$1(element); } return result; } function getBodyID$1(element) { return parseInt(element.id.match(/\d+/g)[0]); } function getBodyName$1(element) { return element.querySelector('.planetname').textContent; } function getBodyFields$1(element) { const [used, maximum] = element.querySelector('.fields').textContent.match(/\d+/g); return { used: parseInt(used), maximum: parseInt(maximum) }; } function getBodyTemperature$1(element) { const { textContent } = element.querySelector('.planetDataBottom'); const [minimum, maximum] = textContent.match(/-?\d+/g); return parseInt(maximum); } function getBodyResources$1(element) { const result = {}; if (!planetType) { result.energy = getBodyEnergy(element); } return result; } function getBodyEnergy(element) { const { textContent } = element.querySelector('.planetData :is(.neutral, .undermark, .overmark)'); return Types.getNumber(textContent); } function getBodyBoosters$1(element) { const ids = []; for (const item of element.querySelectorAll('.item_img')) { ids.push(item.style.background.substring(26, 66)); } return Shared$1.getBodyBoostersBonuses(ids); } function getTechnologies$1(elements) { const result = {}; for (const element of elements) { const id = parseInt(element.classList[0]); const value = Types.getNumber(element.firstChild.textContent); const upgrade = getTechnologyUpgrade$1(element, id, value); const upgraded = value + upgrade; result[id] = { value, upgrade, upgraded }; } return result; } function getTechnologyUpgrade$1(element, id, currentLevel) { if (IDs.units.all.includes(id)) { return getUnitUpgrade$1(element); } else { return getUpgradeableUpgrade$1(element, currentLevel); } } function getUnitUpgrade$1(element) { let result = 0; for (const { textContent } of element.querySelectorAll('.active, .loop')) { result += parseInt(textContent); } return result; } function getUpgradeableUpgrade$1(element, currentLevel) { const targetLevel = parseInt(element.querySelector('.active')?.textContent) || 0; return Math.max(0, targetLevel - currentLevel); } var Empire$1 = { getPositions: getPositions$1, getTechnologies: getTechnologies$1 }; const classes = { player: { miner: 'miner', warrior: 'warrior', explorer: 'explorer' }, alliance: { trader: 'trader', warrior: 'warrior', explorer: 'researcher' } }; const lifeforms = [ 'humans', 'rocktal', 'mechas', 'kaelesh' ]; const miniatures = { '60555c3c87b9eb3b5ddf76780b5712': 202, '9e24203ce8e9723008272d51786780': 202, 'fdbcc505474e3e108d10a3ed4a19f4': 203, 'f38c9fcab7e958698a7f8013b3cc3e': 203, '9ed5c1b6aea28fa51f84cdb8cb1e7e': 204, '9091972f8d216eb9ab0b01b31065ff': 204, '8266a2cbae5ad630c5fedbdf270f3e': 205, 'a5931e3e4a1609da1bfe4ea7984758': 205, 'b7ee4f9d556a0f39dae8d2133e05b7': 206, '26d5b34d33384155d541f8e3a56bd0': 206, '3f4a081f4d15662bed33473db53d5b': 207, '04ae451ca1bbf437b04dcb1689e7ac': 207, '41a21e4253d2231f8937ddef1ba43e': 208, '875d71d6af78f83966b16fc806f398': 208, '6246eb3d7fa67414f6b818fa79dd9b': 209, '6bf35a0f61e69a466a0a4691a8e089': 209, '347821e80cafc52aec04f27c3a2a4d': 210, '4b46516da39af486f25103faacaeae': 210, '4d55a520aed09d0c43e7b962f33e27': 211, 'da0705b3be831864ffa2b5a91d630d': 211, '665c65072887153d44a6684ec276e9': 212, '5f3ca7e91fc0a9b1ee014c3c01ea41': 212, 'c2b9fedc9c93ef22f2739c49fbac52': 213, '6ba84c9dfcfff57452dcaf77d8f722': 213, '155e9e24fc1d34ed4660de8d428f45': 214, '6be8cd7c88e3c5510e8a9d8ca64daa': 214, '24f511ec14a71e2d83fd750aa0dee2': 215, '07f6bd1320f406d474639b7f1f499c': 215, '28e8d79a5b489dc795cc47f3adf165': 217, 'a31e24320e2814bc93a4ebef8f55b4': 217, '12d016c8bb0d71e053b901560c17cc': 218, '1febaddff40e056ce9bf0c1ac930f8': 218, 'b8d8d18f2baf674acedb7504c7cc83': 219, '56a8934f9a63b45d1294eea63767e5': 219, '4c4fbd313bc449e16f5212f23d6311': 401, 'b5d139528cdf1233e61bd58184e1c5': 401, '68e11c389f7f62134def76575b27e5': 402, '34b3f95bf2d4e3355fed09a3e1877e': 402, '3adede7d38b3ecfc7457375a4cd2a5': 403, '9d88c2d9b8e5872bef32a7f8659695': 403, '2e7227f88e3601612093ee2e9101e0': 404, '0fc6c29d06858b5b9ca0b0a4d1532e': 404, '2add2bd4bf0cbcf07f779bf85d43cc': 405, '4dd51eeb4ab03af617828169bffd5b': 405, 'ceed170b2583498228e9ab6b087af1': 406, 'ea3e0adf01fb3cf64e1938a7c55dfb': 406, '58390eb6945e04861c99eb311366cc': 407, '4d20894a828929ff5a61f62c757149': 407, '1c77121b235b5a9e9591c7c78883d3': 408, '533c32ff26f4db6857e3e41c09d443': 408, 'fb4e438cabd12ef1b0500a0f41abc1': 502, '40a392214240328e42014108815526': 502, '36221e9493458b9fcc776bf350983e': 503, '2cf0473c0bb2e5cf3135358ccc4edf': 503 }; async function get$9() { for (let i = 0; i < 5; i++) { try { const result = { player: getPlayer(), universe: getUniverse() }; console.log('InfoCompte: Data has been scraped with success', result); return result; } catch(error) { console.warn('InfoCompte: An error occurred while scraping data (see below). The script will retry in an instant'); console.error(error); await new Promise(resolve => setTimeout(resolve, 1_000)); } } console.warn('InfoCompte: Data scraping failed'); } function getPlayer() { return { name: document.querySelector('[name=ogame-player-name]').content, class: getClass$1(), officers: getOfficers(), lifeforms: getLifeforms(), researches: getResearches(), positions: getPositions(), alliance: { class: getAllianceClass() }, points: { total: getTotalPoints() } }; } function getClass$1() { if (currentPage !== 'empire') { let result = null; for (const key in classes.player) { if (document.querySelector(`#characterclass .${ key }`)) { result = classes.player[key]; break; } } return result; } } function getOfficers() { if (currentPage !== 'empire') { const result = { commander: true, admiral: true, engineer: true, geologist: true, technocrat: true }; for (const key in result) { if (!document.querySelector(`#officers .on.${ key }`)) { result[key] = false; result.all = false; } result.all ??= true; } return result; } } function getLifeforms() { if (currentPage === 'lfsettings') { const result = {}; for (const element of document.querySelectorAll('.lifeform-item')) { const icon = element.querySelector('.lifeform-item-icon'); const p = element.querySelector('.lifeform-item-wrapper p:nth-last-of-type(2)'); const key = getLifeformKey(icon.classList[1]); const values = p.textContent.match(/\d+/g); result[key] = { level: parseInt(values[0]), xp: { current: parseInt(values[1]), maximum: parseInt(values[2]) } }; } return result; } } function getResearches() { if (currentPage === 'empire') { const planet = document.querySelector('.planet:not(.summary)'); const researches = planet.querySelectorAll('.research > div'); return Empire$1.getTechnologies(researches); } else if (currentPage === 'research') { return getTechnologies(); } } function getPositions() { if (currentPage === 'empire') { return Empire$1.getPositions(); } else { const result = getPlanetListPositions(); setBody$1(result); return result; } } function getPlanetListPositions() { const result = {}; for (const element of document.querySelectorAll('#planetList .smallplanet')) { const coordinates = Shared$1.getCoordinates(element.querySelector('.planet-koords').textContent); const moon = element.querySelector('.moonlink'); result[coordinates] = { planet: { type: 'planet', id: getBodyID(element.querySelector('.planetlink')), name: getBodyName(element.querySelector('.planetPic')), position: getBodyPosition(coordinates) }, moon: moon && { type: 'moon', id: getBodyID(element.querySelector('.moonlink')), name: getBodyName(moon.querySelector('.icon-moon')) } || null }; } return result; } function setBody$1(positions) { const coordinates = document.querySelector('[name=ogame-planet-coordinates]').content; const type = document.querySelector('[name=ogame-planet-type]').content; const body = positions[coordinates][type]; body.fields = getBodyFields(); body.technologies = getBodyTechnologies(); if (body.type === 'planet') { body.lifeform = getBodyLifeform(); body.temperature = getBodyTemperature(); body.boosters = getBodyBoosters(); body.productions = getBodyProductions(); body.resources = getBodyResources(); body.technologies = getBodyTechnologies(); } } function getBodyID(element) { return parseInt(new URL(element.href).searchParams.get('cp')); } function getBodyName(element) { return element.alt; } function getBodyPosition(coordinates) { return parseInt(coordinates.split(':').pop()); } function getBodyLifeform() { return { species: getBodyLifeformSpecies(), researches: getBodyLifeformResearches() }; } function getBodyLifeformSpecies() { if (document.querySelector('#lifeform')) { let result = null; for (const key of ['lifeform1', 'lifeform2', 'lifeform3', 'lifeform4']) { if (document.querySelector(`#lifeform .${ key }`)) { result = key; break; } } if (result) { result = getLifeformKey(result); } return result; } } function getBodyLifeformResearches() { if (currentPage === 'lfresearch') { const result = []; for (const element of document.querySelectorAll('#technologies .hasDetails')) { const id = parseInt(element.dataset.technology); result.push(id); } return result; } } function getLifeformKey(string) { const index = parseInt(string.slice(-1)) - 1; return lifeforms[index]; } function getBodyFields() { if (currentPage === 'overview') { const [used, maximum] = textContent[1].match(/\d+(?=\D+?\/)|(?<=\/\D+?)\d+/g); return { used: parseInt(used), maximum: parseInt(maximum) }; } } function getBodyTemperature() { if (currentPage === 'overview') { const [minimum, maximum] = textContent[3].match(/-?\d+/g); return parseInt(maximum); } } function getBodyBoosters() { const elements = document.querySelectorAll('#buffBar img'); if (elements) { const ids = []; for (const { src } of elements) { ids.push(src.substring(56, 96)); } return Shared$1.getBodyBoostersBonuses(ids); } } function getBodyProductions() { const element = document.querySelector('.listOfResourceSettingsPerPlanet'); if (element) { const result = { basic: getBodyProductionValues(element.querySelector('.alt')), mines: { metal: getBodyProductionValues(element.querySelector('.\\31')), crystal: getBodyProductionValues(element.querySelector('.\\32')), deuterium: getBodyProductionValues(element.querySelector('.\\33')) }, fusion: getBodyProductionValues(element.querySelector('.\\31 2')), lifeforms: getBodyLifeformProductions(element.querySelectorAll('.\\31 2 ~ tr')), crawlers: getBodyProductionValues(element.querySelector('.\\32 17')), plasma: getBodyProductionValues(element.querySelector('.\\31 22')), objects: getBodyProductionValues(element.querySelector('.\\31 000')), geologist: getBodyProductionValues(element.querySelector('.\\31 001')), officers: getBodyProductionValues(element.querySelector('.\\31 003')), classes: { player: getBodyProductionValues(element.querySelector('.\\31 004')), alliance: getBodyProductionValues(element.querySelector('.\\31 005')), }, total: getBodyProductionValues(element.querySelector('.summary')) }; result.mines.total = { metal: result.mines.metal.metal, crystal: result.mines.crystal.crystal, deuterium: result.mines.deuterium.deuterium, factor: null }; result.premium = { metal: result.objects.metal + result.geologist.metal + result.officers.metal, crystal: result.objects.crystal + result.geologist.crystal + result.officers.crystal, deuterium: result.objects.deuterium + result.geologist.deuterium + result.officers.deuterium, factor: null }; result.classes.total = { metal: result.classes.player.metal + result.classes.alliance.metal, crystal: result.classes.player.crystal + result.classes.alliance.crystal, deuterium: result.classes.player.deuterium + result.classes.alliance.deuterium, factor: null }; return result; } } function getBodyLifeformProductions(elements) { const result = { metal: 0, crystal: 0, deuterium: 0, factor: null }; for (const element of elements) { const id = parseInt(element.classList[element.classList.length - 1]); if (id > 1_005) { const { metal, crystal, deuterium } = getBodyProductionValues(element); result.metal += metal; result.crystal += crystal; result.deuterium += deuterium; } } return result; } function getBodyProductionValues(element) { const elements = element.querySelectorAll('td:nth-last-child(-n+5)'); return { metal: getBodyProductionValue(elements[0]), crystal: getBodyProductionValue(elements[1]), deuterium: getBodyProductionValue(elements[2]), factor: getBodyProductionFactor(elements[4]) }; } function getBodyProductionValue(element) { // after update 11.15: const value = element.querySelector('span').dataset.tooltipTitle; const span = element.querySelector('span'); const value = span.title || span.dataset.tooltipTitle || span.dataset.title; return Types.getNumber(value); } function getBodyProductionFactor(element) { let result = null; if (element.childElementCount) { // management of alternative drop downs const value = element.querySelector('a')?.dataset.value || element.querySelector('option:checked').value; result = parseInt(value) * .01; } return result; } function getBodyResources() { return { energy: resourcesBar.resources.energy.amount }; } function getBodyTechnologies() { const hasTechnologies = document.querySelector('#technologies'); const isResearch = currentPage === 'research'; if (hasTechnologies && !isResearch) { return getTechnologies(); } } function getTechnologies() { const result = {}; for (const element of document.querySelectorAll('#technologies .hasDetails')) { const id = parseInt(element.dataset.technology); const value = parseInt(element.querySelector('.level, .amount').dataset.value); const upgrade = getTechnologyUpgrade(element, id, value); const upgraded = value + upgrade; result[id] = { value, upgrade, upgraded }; } return result; } function getTechnologyUpgrade(element, id, currentLevel) { if (IDs.units.all.includes(id)) { return getUnitUpgrade(element, id); } else { return getUpgradeableUpgrade(element, currentLevel); } } function getUnitUpgrade(element, id) { let result = 0; for (const element of document.querySelectorAll(':is(#productionboxshipyardcomponent, #productionboxextendedshipyardcomponent) :is(.first, .queue td)')) { const key = element.querySelector('img').src.substring(32, 62); if (miniatures[key] === id) { result += parseInt(element.textContent); } } return result; } function getUpgradeableUpgrade(element, currentLevel) { const targetLevel = parseInt(element.querySelector('.targetlevel')?.dataset.value) || 0; return Math.max(0, targetLevel - currentLevel); } function getAllianceClass() { if (currentPage === 'alliance' && alliance.tab !== 'createNewAlliance') { const element = document.querySelector('.alliance_class'); let result = null; for (const key in classes.alliance) { if (element.classList.contains(key)) { result = classes.alliance[key]; break; } } return result; } } function getTotalPoints() { if (currentPage === 'overview') { const [value] = textContent[7].match(/(?<=\>).*?(?=\s)/); return Types.getNumber(value); } } function getUniverse() { return { language: document.querySelector('[name=ogame-language]').content, name: document.querySelector('[name=ogame-universe-name]').content, speed: parseInt(document.querySelector('[name=ogame-universe-speed]').content), highscores: getUniverseHighscores() }; } function getUniverseHighscores() { if (currentPage === 'highscore') { return { [currentCategory]: { [currentType]: { players: getPlayersHighscore(), player: getPlayerScore() } } }; } } function getPlayersHighscore() { // firstChild property of score element is used for compatibility reason with OGLight const result = {}; for (const element of document.querySelectorAll('#ranks tbody tr')) { const position = element.querySelector('.position'); const score = element.querySelector('.score'); const key = parseInt(position.textContent); const value = Types.getNumber(score.firstChild.textContent); result[key] = value; } return result; } function getPlayerScore() { // firstChild property of score element is used for compatibility reason with OGLight const element = document.querySelector('#ranks .myrank'); if (element) { const position = element.querySelector('.position'); const score = element.querySelector('.score'); return { position: parseInt(position.textContent), points: Types.getNumber(score.firstChild.textContent) }; } } function elementHasChanged(selector) { return new Promise(function(resolve) { const observer = new MutationObserver(function() { observer.disconnect(); resolve(); }); observer.observe(document.querySelector(selector), { childList: true, subtree: true }); }); } var Scraper = { get: get$9, elementHasChanged }; var Colors = { main: '#6f9fc8', mines: '#eb782d', planetBuildings: '#9c3d00', moonBuildings: '#83919c', lifeformBuildings: '#6c56a3', lifeformResearches: '#95559f', researches: '#0077b6', defences: '#16bd05', ships: '#e30613', crawlers: '#eb782d', upgrade: '#ffd700', metal: '#a9a9a9', crystal: '#8dceec', deuterium: '#6cc6a3' }; function set$5(data) { setScript(data); setClass(data); setOfficers(data); setLifeforms(data); setResearches(data); setPositions(data); setAllianceClass(data); setTotalPoints(data); setUniverseHighscores(data); } function setScript(data) { if (data.script === undefined) { data.script = { amortizations: { form: { mines: true, lifeformBuildings: true, lifeformResearches: true, plasma: true, useMaximumCrawlers: true } }, collapsibles: { }, colors: { }, needed: { empire: { }, lifeforms: { researches: [] }, productions: [] }, rates: { metal: 2, crystal: 1.5, deuterium: 1, unit: 'metal' }, useCompactNumbers: true }; setScriptColors(data.script); } } function setScriptColors(data) { for (const key in Colors) { data.colors[key] = Colors[key]; } delete data.colors.main; delete data.colors.crawlers; delete data.colors.upgrade; } function setClass(data) { const { player } = data; if (player.class === undefined) { player.class = null; } } function setOfficers(data) { const { player } = data; if (player.officers === undefined) { player.officers = { commander: false, admiral: false, engineer: false, geologist: false, technocrat: false }; } } function setLifeforms(data) { const { player, script } = data; if (player.lifeforms === undefined) { const lifeforms = player.lifeforms = {}; for (const id of ['humans', 'rocktal', 'mechas', 'kaelesh', null]) { lifeforms[id] = { level: 0, xp: { current: 0, maximum: 0 } }; } script.needed.lifeforms.settings = true; } } function setResearches(data) { const { player, script } = data; if (player.researches === undefined) { const researches = player.researches = {}; for(const id of IDs.researches.all) { researches[id] ||= { value: 0, upgrade: 0, upgraded: 0 }; } script.needed.empire.planet = true; } } function setPositions(data) { const { player, script } = data; const { positions } = player; for (const coordinates in positions) { const { planet, moon } = positions[coordinates]; setBody(planet, script); if (moon) { setBody(moon, script); } } } function setBody(body, script) { setBodyFields(body, script); setBodyTechnologies(body, script); if (body.type === 'planet') { setBodyLifeform(body, script); setBodyTemperature(body, script); setBodyResources(body, script); setBodyBoosters(body, script); setBodyProductions(body, script); } } function setBodyLifeform(body, script) { body.lifeform ||= {}; if (body.lifeform.species === undefined) { body.lifeform.species = null; } if (body.lifeform.researches === undefined) { body.lifeform.researches = []; script.needed.lifeforms.researches.push([body.id, body.name]); } } function setBodyFields(body, script) { if (body.fields === undefined) { body.fields = { used: 0, maximum: 0 }; script.needed.empire[body.type] = true; } } function setBodyTemperature(body, script) { if (body.temperature === undefined) { body.temperature = 50; script.needed.empire[body.type] = true; } } function setBodyResources(body, script) { if (body.resources === undefined) { body.resources = { energy: 0 }; script.needed.empire[body.type] = true; } } function setBodyBoosters(body, script) { if (body.boosters === undefined) { body.boosters = { metal: 0, crystal: 0, deuterium: 0 }; script.needed.empire[body.type] = true; } } function setBodyProductions(body, script) { if (body.productions === undefined) { body.productions = { basic: { metal: 0, crystal: 0, deuterium: 0 }, mines: { metal: { metal: 0, crystal: 0, deuterium: 0 }, crystal: { metal: 0, crystal: 0, deuterium: 0 }, deuterium: { metal: 0, crystal: 0, deuterium: 0 }, total: { metal: 0, crystal: 0, deuterium: 0 } }, fusion: { metal: 0, crystal: 0, deuterium: 0, factor: 1 }, lifeforms: { metal: 0, crystal: 0, deuterium: 0 }, crawlers: { metal: 0, crystal: 0, deuterium: 0, factor: 1 }, plasma: { metal: 0, crystal: 0, deuterium: 0 }, objects: { metal: 0, crystal: 0, deuterium: 0 }, geologist: { metal: 0, crystal: 0, deuterium: 0 }, officers: { metal: 0, crystal: 0, deuterium: 0 }, classes: { player: { metal: 0, crystal: 0, deuterium: 0 }, alliance: { metal: 0, crystal: 0, deuterium: 0 }, total: { metal: 0, crystal: 0, deuterium: 0 } }, premium: { metal: 0, crystal: 0, deuterium: 0 }, total: { metal: 0, crystal: 0, deuterium: 0 } }; script.needed.productions.push([body.id, body.name]); } } function setBodyTechnologies(body, script) { body.technologies ||= {}; for(const id of IDs[body.type].all) { if (body.technologies[id] === undefined) { body.technologies[id] ||= { value: 0, upgrade: 0, upgraded: 0 }; script.needed.empire[body.type] = true; } } } function setAllianceClass(data) { const { player, script } = data; if (player.alliance.class === undefined) { player.alliance.class = null; script.needed.alliance = true; } } function setTotalPoints(data) { const { player } = data; if (player.points.total === undefined) { player.points.total = 0; } } function setUniverseHighscores(data) { const { universe, script } = data; if (universe.highscores === undefined) { script.needed.highscores = true; } } var Defaults = { set: set$5 }; function set$4(data) { if (currentPage === 'highscore') { const highscore = data.universe.highscores[1][0]; if (highscore.player) { const indestructibles = data.player.points.values.indestructibles; const upgrades = data.player.points.values.upgrades; const upgraded = highscore.player.points + upgrades; const movements = highscore.player.movements = { ifDestroyed: 0, whenUpgraded: 0 }; for (const key in highscore.players) { const value = highscore.players[key]; if (value < highscore.player.points) { if (value > indestructibles) { movements.ifDestroyed = parseInt(key) - highscore.player.position; } else break; } } for (const key in highscore.players) { const value = highscore.players[key]; if (value > highscore.player.points) { if (value < upgraded) { movements.whenUpgraded = highscore.player.position - parseInt(key); break; } } else break; } } } } var Highscore = { set: set$4 }; function clean$1(data) { const { positions } = data.player; const { needed } = data.script; const id = parseInt(document.querySelector('[name=ogame-planet-id]').content); cleanObsoleteData(needed, positions); cleanEmpire(needed); cleanLifeforms(needed, id); cleanProductions(needed, id); cleanAllianceClass(needed); cleanHighscores(needed); } function cleanObsoleteData(data, positions) { cleanObsoleteIDs(data.lifeforms.researches, positions); cleanObsoleteIDs(data.productions, positions); } function cleanObsoleteIDs(array, positions) { const result = []; for (const [id] of array) { const element = Object.values(positions).find(({ planet, moon }) => planet.id === id || moon?.id === id); if (!element) { result.push(id); } } for (const id of result) { removeFromArray(array, id); } } function cleanEmpire(data) { if (currentPage === 'empire') { if (planetType) { data.empire.moon = false; } else { data.empire.planet = false; } } } function cleanLifeforms(data, id) { cleanLifeformResearches(data, id); cleanLifeformSettings(data); } function cleanLifeformResearches(data, id) { if (currentPage === 'lfresearch' || (currentPage === 'lfsettings' && !document.querySelector('#lifeform .lifeform-item-icon'))) { removeFromArray(data.lifeforms.researches, id); } } function cleanLifeformSettings(data) { if (currentPage === 'lfsettings' && document.querySelector('#lifeform .lifeform-item-icon')) { data.lifeforms.settings = false; } } function cleanProductions(data, id) { if (currentPage === 'resourcesettings') { removeFromArray(data.productions, id); } } function cleanAllianceClass(data) { if (currentPage === 'alliance') { data.alliance = false; } } function cleanHighscores(data) { if (currentPage === 'highscore') { data.highscores = false; } } function removeFromArray(array, id) { const index = array.findIndex(element => element[0] === id); array.splice(index, 1); } var Needed$1 = { clean: clean$1 }; class Resources { static getPoints(resources) { return (resources.metal + resources.crystal + resources.deuterium) * .001; } static getSU(resources, rates) { return (resources.metal / rates.metal + resources.crystal / rates.crystal + resources.deuterium) * rates[rates.unit]; } static getTotal(resources, rates) { if (rates.unit === 'points') { return this.getPoints(resources); } else { return this.getSU(resources, rates); } } constructor(...args) { if (args.length === 3) { this.metal = args[0]; this.crystal = args[1]; this.deuterium = args[2]; } else if (args.length === 1) { this.metal = args[0].metal; this.crystal = args[0].crystal; this.deuterium = args[0].deuterium; } else { this.metal = 0; this.crystal = 0; this.deuterium = 0; } } add(...costs) { for (const cost of costs) { this.metal += cost.metal; this.crystal += cost.crystal; this.deuterium += cost.deuterium; } return this; } subtract(...costs) { for (const cost of costs) { this.metal -= cost.metal; this.crystal -= cost.crystal; this.deuterium -= cost.deuterium; } return this; } divide(value) { this.metal /= value; this.crystal /= value; this.deuterium /= value; return this; } multiply(value) { this.metal *= value; this.crystal *= value; this.deuterium *= value; return this; } trunc() { this.metal = Math.trunc(this.metal); this.crystal = Math.trunc(this.crystal); this.deuterium = Math.trunc(this.deuterium); return this; } toPoints() { return (this.metal + this.crystal + this.deuterium) * .001; } toSU(rates) { return (this.metal / rates.metal + this.crystal / rates.crystal + this.deuterium) * rates[rates.unit]; } toTotal(rates) { if (rates.unit === 'points') { return this.toPoints(); } else { return this.toSU(rates); } } } const Units = { 202: { metal: 2_000, crystal: 2_000, deuterium: 0 }, 203: { metal: 6_000, crystal: 6_000, deuterium: 0 }, 204: { metal: 3_000, crystal: 1_000, deuterium: 0 }, 205: { metal: 6_000, crystal: 4_000, deuterium: 0 }, 206: { metal: 20_000, crystal: 7_000, deuterium: 2_000 }, 207: { metal: 45_000, crystal: 15_000, deuterium: 0 }, 208: { metal: 10_000, crystal: 20_000, deuterium: 10_000 }, 209: { metal: 10_000, crystal: 6_000, deuterium: 2_000 }, 210: { metal: 0, crystal: 1_000, deuterium: 0 }, 211: { metal: 50_000, crystal: 25_000, deuterium: 15_000 }, 212: { metal: 0, crystal: 2_000, deuterium: 500 }, 213: { metal: 60_000, crystal: 50_000, deuterium: 15_000 }, 214: { metal: 5_000_000, crystal: 4_000_000, deuterium: 1_000_000 }, 215: { metal: 30_000, crystal: 40_000, deuterium: 15_000 }, 217: { metal: 2_000, crystal: 2_000, deuterium: 1_000 }, 218: { metal: 85_000, crystal: 55_000, deuterium: 20_000 }, 219: { metal: 8_000, crystal: 15_000, deuterium: 8_000 }, 401: { metal: 2_000, crystal: 0, deuterium: 0 }, 402: { metal: 1_500, crystal: 500, deuterium: 0 }, 403: { metal: 6_000, crystal: 2_000, deuterium: 0 }, 404: { metal: 20_000, crystal: 15_000, deuterium: 2_000 }, 405: { metal: 5_000, crystal: 3_000, deuterium: 0 }, 406: { metal: 50_000, crystal: 50_000, deuterium: 30_000 }, 407: { metal: 10_000, crystal: 10_000, deuterium: 0 }, 408: { metal: 50_000, crystal: 50_000, deuterium: 0 }, 502: { metal: 8_000, crystal: 0, deuterium: 2_000 }, 503: { metal: 12_500, crystal: 2_500, deuterium: 10_000 }, getValues(technologies, id) { const { value } = technologies[id]; return Units.get(id, value); }, getUpgrades(technologies, id) { const { upgrade } = technologies[id]; return Units.get(id, upgrade); }, getUpgraded(technologies, id) { const { upgraded } = technologies[id]; return Units.get(id, upgraded); }, get(id, count) { const result = new Resources(Units[id]); return result.multiply(count); } }; const Upgradables = { 1: { metal: 60, crystal: 15, deuterium: 0, factor: 1.5 }, 2: { metal: 48, crystal: 24, deuterium: 0, factor: 1.6 }, 3: { metal: 225, crystal: 75, deuterium: 0, factor: 1.5 }, 4: { metal: 75, crystal: 30, deuterium: 0, factor: 1.5 }, 12: { metal: 900, crystal: 360, deuterium: 180, factor: 1.8 }, 14: { metal: 400, crystal: 120, deuterium: 200, factor: 2 }, 15: { metal: 1_000_000, crystal: 500_000, deuterium: 100_000, factor: 2 }, 21: { metal: 400, crystal: 200, deuterium: 100, factor: 2 }, 22: { metal: 1_000, crystal: 0, deuterium: 0, factor: 2 }, 23: { metal: 1_000, crystal: 500, deuterium: 0, factor: 2 }, 24: { metal: 1_000, crystal: 1_000, deuterium: 0, factor: 2 }, 31: { metal: 200, crystal: 400, deuterium: 200, factor: 2 }, 33: { metal: 0, crystal: 50_000, deuterium: 100_000, factor: 2 }, 34: { metal: 20_000, crystal: 40_000, deuterium: 0, factor: 2 }, 36: { metal: 200, crystal: 0, deuterium: 50, factor: 5 }, 41: { metal: 20_000, crystal: 40_000, deuterium: 20_000, factor: 2 }, 42: { metal: 20_000, crystal: 40_000, deuterium: 20_000, factor: 2 }, 43: { metal: 2_000_000, crystal: 4_000_000, deuterium: 2_000_000, factor: 2 }, 44: { metal: 20_000, crystal: 20_000, deuterium: 1_000, factor: 2 }, 106: { metal: 200, crystal: 1_000, deuterium: 200, factor: 2 }, 108: { metal: 0, crystal: 400, deuterium: 600, factor: 2 }, 109: { metal: 800, crystal: 200, deuterium: 0, factor: 2 }, 110: { metal: 200, crystal: 600, deuterium: 0, factor: 2 }, 111: { metal: 1_000, crystal: 0, deuterium: 0, factor: 2 }, 113: { metal: 0, crystal: 800, deuterium: 400, factor: 2 }, 114: { metal: 0, crystal: 4_000, deuterium: 2_000, factor: 2 }, 115: { metal: 400, crystal: 0, deuterium: 600, factor: 2 }, 117: { metal: 2_000, crystal: 4_000, deuterium: 600, factor: 2 }, 118: { metal: 10_000, crystal: 20_000, deuterium: 6_000, factor: 2 }, 120: { metal: 200, crystal: 100, deuterium: 0, factor: 2 }, 121: { metal: 1_000, crystal: 300, deuterium: 100, factor: 2 }, 122: { metal: 2_000, crystal: 4_000, deuterium: 1_000, factor: 2 }, 123: { metal: 240_000, crystal: 400_000, deuterium: 160_000, factor: 2 }, 124: { metal: 4_000, crystal: 8_000, deuterium: 4_000, factor: 1.75 }, 199: { metal: 0, crystal: 0, deuterium: 0, factor: 3 }, 11_101: { metal: 7, crystal: 2, deuterium: 0, factor: 1.2 }, 11_102: { metal: 5, crystal: 2, deuterium: 0, factor: 1.23 }, 11_103: { metal: 20_000, crystal: 25_000, deuterium: 10_000, factor: 1.3 }, 11_104: { metal: 5_000, crystal: 3_200, deuterium: 1_500, factor: 1.7 }, 11_105: { metal: 50_000, crystal: 40_000, deuterium: 50_000, factor: 1.7 }, 11_106: { metal: 9_000, crystal: 6_000, deuterium: 3_000, factor: 1.5 }, 11_107: { metal: 25_000, crystal: 13_000, deuterium: 7_000, factor: 1.09 }, 11_108: { metal: 50_000, crystal: 25_000, deuterium: 15_000, factor: 1.5 }, 11_109: { metal: 75_000, crystal: 20_000, deuterium: 25_000, factor: 1.09 }, 11_110: { metal: 150_000, crystal: 30_000, deuterium: 15_000, factor: 1.12 }, 11_111: { metal: 80_000, crystal: 35_000, deuterium: 60_000, factor: 1.5 }, 11_112: { metal: 250_000, crystal: 125_000, deuterium: 125_000, factor: 1.2 }, 11_201: { metal: 5_000, crystal: 2_500, deuterium: 500, factor: 1.3 }, 11_202: { metal: 7_000, crystal: 10_000, deuterium: 5_000, factor: 1.5 }, 11_203: { metal: 15_000, crystal: 10_000, deuterium: 5_000, factor: 1.3 }, 11_204: { metal: 20_000, crystal: 15_000, deuterium: 7_500, factor: 1.3 }, 11_205: { metal: 25_000, crystal: 20_000, deuterium: 10_000, factor: 1.2 }, 11_206: { metal: 35_000, crystal: 25_000, deuterium: 15_000, factor: 1.5 }, 11_207: { metal: 70_000, crystal: 40_000, deuterium: 20_000, factor: 1.3 }, 11_208: { metal: 80_000, crystal: 50_000, deuterium: 20_000, factor: 1.5 }, 11_209: { metal: 320_000, crystal: 240_000, deuterium: 100_000, factor: 1.5 }, 11_210: { metal: 320_000, crystal: 240_000, deuterium: 100_000, factor: 1.5 }, 11_211: { metal: 120_000, crystal: 30_000, deuterium: 25_000, factor: 1.5 }, 11_212: { metal: 100_000, crystal: 40_000, deuterium: 30_000, factor: 1.3 }, 11_213: { metal: 200_000, crystal: 100_000, deuterium: 100_000, factor: 1.3 }, 11_214: { metal: 160_000, crystal: 120_000, deuterium: 50_000, factor: 1.5 }, 11_215: { metal: 160_000, crystal: 120_000, deuterium: 50_000, factor: 1.5 }, 11_216: { metal: 320_000, crystal: 240_000, deuterium: 100_000, factor: 1.5 }, 11_217: { metal: 300_000, crystal: 180_000, deuterium: 120_000, factor: 1.5 }, 11_218: { metal: 500_000, crystal: 300_000, deuterium: 200_000, factor: 1.3 }, 12_101: { metal: 9, crystal: 3, deuterium: 0, factor: 1.2 }, 12_102: { metal: 7, crystal: 2, deuterium: 0, factor: 1.2 }, 12_103: { metal: 40_000, crystal: 10_000, deuterium: 15_000, factor: 1.3 }, 12_104: { metal: 5_000, crystal: 3_800, deuterium: 1_000, factor: 1.7 }, 12_105: { metal: 50_000, crystal: 40_000, deuterium: 50_000, factor: 1.65 }, 12_106: { metal: 10_000, crystal: 8_000, deuterium: 1_000, factor: 1.4 }, 12_107: { metal: 20_000, crystal: 15_000, deuterium: 10_000, factor: 1.2 }, 12_108: { metal: 50_000, crystal: 35_000, deuterium: 15_000, factor: 1.5 }, 12_109: { metal: 85_000, crystal: 44_000, deuterium: 25_000, factor: 1.4 }, 12_110: { metal: 120_000, crystal: 50_000, deuterium: 20_000, factor: 1.4 }, 12_111: { metal: 250_000, crystal: 150_000, deuterium: 100_000, factor: 1.8 }, 12_112: { metal: 250_000, crystal: 125_000, deuterium: 125_000, factor: 1.5 }, 12_201: { metal: 10_000, crystal: 6_000, deuterium: 1_000, factor: 1.5 }, 12_202: { metal: 7_500, crystal: 12_500, deuterium: 5_000, factor: 1.5 }, 12_203: { metal: 15_000, crystal: 10_000, deuterium: 5_000, factor: 1.5 }, 12_204: { metal: 20_000, crystal: 15_000, deuterium: 7_500, factor: 1.3 }, 12_205: { metal: 25_000, crystal: 20_000, deuterium: 10_000, factor: 1.5 }, 12_206: { metal: 50_000, crystal: 50_000, deuterium: 20_000, factor: 1.5 }, 12_207: { metal: 70_000, crystal: 40_000, deuterium: 20_000, factor: 1.5 }, 12_208: { metal: 160_000, crystal: 120_000, deuterium: 50_000, factor: 1.5 }, 12_209: { metal: 75_000, crystal: 55_000, deuterium: 25_000, factor: 1.5 }, 12_210: { metal: 85_000, crystal: 40_000, deuterium: 35_000, factor: 1.5 }, 12_211: { metal: 120_000, crystal: 30_000, deuterium: 25_000, factor: 1.5 }, 12_212: { metal: 100_000, crystal: 40_000, deuterium: 30_000, factor: 1.5 }, 12_213: { metal: 200_000, crystal: 100_000, deuterium: 100_000, factor: 1.2 }, 12_214: { metal: 220_000, crystal: 110_000, deuterium: 110_000, factor: 1.3 }, 12_215: { metal: 240_000, crystal: 120_000, deuterium: 120_000, factor: 1.3 }, 12_216: { metal: 250_000, crystal: 250_000, deuterium: 250_000, factor: 1.4 }, 12_217: { metal: 500_000, crystal: 300_000, deuterium: 200_000, factor: 1.5 }, 12_218: { metal: 300_000, crystal: 180_000, deuterium: 120_000, factor: 1.7 }, 13_101: { metal: 6, crystal: 2, deuterium: 0, factor: 1.21 }, 13_102: { metal: 5, crystal: 2, deuterium: 0, factor: 1.18 }, 13_103: { metal: 30_000, crystal: 20_000, deuterium: 10_000, factor: 1.3 }, 13_104: { metal: 5_000, crystal: 3_800, deuterium: 1_000, factor: 1.8 }, 13_105: { metal: 50_000, crystal: 40_000, deuterium: 50_000, factor: 1.8 }, 13_106: { metal: 7_500, crystal: 7_000, deuterium: 1_000, factor: 1.3 }, 13_107: { metal: 35_000, crystal: 15_000, deuterium: 10_000, factor: 1.5 }, 13_108: { metal: 50_000, crystal: 20_000, deuterium: 30_000, factor: 1.07 }, 13_109: { metal: 100_000, crystal: 10_000, deuterium: 3_000, factor: 1.14 }, 13_110: { metal: 100_000, crystal: 40_000, deuterium: 20_000, factor: 1.5 }, 13_111: { metal: 55_000, crystal: 50_000, deuterium: 30_000, factor: 1.5 }, 13_112: { metal: 250_000, crystal: 125_000, deuterium: 125_000, factor: 1.4 }, 13_201: { metal: 10_000, crystal: 6_000, deuterium: 1_000, factor: 1.5 }, 13_202: { metal: 7_500, crystal: 12_500, deuterium: 5_000, factor: 1.3 }, 13_203: { metal: 15_000, crystal: 10_000, deuterium: 5_000, factor: 1.5 }, 13_204: { metal: 20_000, crystal: 15_000, deuterium: 7_500, factor: 1.3 }, 13_205: { metal: 160_000, crystal: 120_000, deuterium: 50_000, factor: 1.5 }, 13_206: { metal: 50_000, crystal: 50_000, deuterium: 20_000, factor: 1.5 }, 13_207: { metal: 70_000, crystal: 40_000, deuterium: 20_000, factor: 1.3 }, 13_208: { metal: 160_000, crystal: 120_000, deuterium: 50_000, factor: 1.5 }, 13_209: { metal: 160_000, crystal: 120_000, deuterium: 50_000, factor: 1.5 }, 13_210: { metal: 85_000, crystal: 40_000, deuterium: 35_000, factor: 1.2 }, 13_211: { metal: 120_000, crystal: 30_000, deuterium: 25_000, factor: 1.3 }, 13_212: { metal: 160_000, crystal: 120_000, deuterium: 50_000, factor: 1.5 }, 13_213: { metal: 200_000, crystal: 100_000, deuterium: 100_000, factor: 1.5 }, 13_214: { metal: 160_000, crystal: 120_000, deuterium: 50_000, factor: 1.5 }, 13_215: { metal: 320_000, crystal: 240_000, deuterium: 100_000, factor: 1.5 }, 13_216: { metal: 320_000, crystal: 240_000, deuterium: 100_000, factor: 1.5 }, 13_217: { metal: 500_000, crystal: 300_000, deuterium: 200_000, factor: 1.5 }, 13_218: { metal: 300_000, crystal: 180_000, deuterium: 120_000, factor: 1.7 }, 14_101: { metal: 4, crystal: 3, deuterium: 0, factor: 1.21 }, 14_102: { metal: 6, crystal: 3, deuterium: 0, factor: 1.21 }, 14_103: { metal: 20_000, crystal: 15_000, deuterium: 15_000, factor: 1.3 }, 14_104: { metal: 7_500, crystal: 5_000, deuterium: 800, factor: 1.8 }, 14_105: { metal: 60_000, crystal: 30_000, deuterium: 50_000, factor: 1.8 }, 14_106: { metal: 8_500, crystal: 5_000, deuterium: 3_000, factor: 1.25 }, 14_107: { metal: 15_000, crystal: 15_000, deuterium: 5_000, factor: 1.2 }, 14_108: { metal: 75_000, crystal: 25_000, deuterium: 30_000, factor: 1.05 }, 14_109: { metal: 87_500, crystal: 25_000, deuterium: 30_000, factor: 1.2 }, 14_110: { metal: 150_000, crystal: 30_000, deuterium: 30_000, factor: 1.5 }, 14_111: { metal: 75_000, crystal: 50_000, deuterium: 55_000, factor: 1.2 }, 14_112: { metal: 500_000, crystal: 250_000, deuterium: 250_000, factor: 1.4 }, 14_201: { metal: 10_000, crystal: 6_000, deuterium: 1_000, factor: 1.5 }, 14_202: { metal: 7_500, crystal: 12_500, deuterium: 5_000, factor: 1.5 }, 14_203: { metal: 15_000, crystal: 10_000, deuterium: 5_000, factor: 1.5 }, 14_204: { metal: 20_000, crystal: 15_000, deuterium: 7_500, factor: 1.5 }, 14_205: { metal: 25_000, crystal: 20_000, deuterium: 10_000, factor: 1.5 }, 14_206: { metal: 50_000, crystal: 50_000, deuterium: 20_000, factor: 1.3 }, 14_207: { metal: 70_000, crystal: 40_000, deuterium: 20_000, factor: 1.5 }, 14_208: { metal: 80_000, crystal: 50_000, deuterium: 20_000, factor: 1.2 }, 14_209: { metal: 320_000, crystal: 240_000, deuterium: 100_000, factor: 1.5 }, 14_210: { metal: 85_000, crystal: 40_000, deuterium: 35_000, factor: 1.2 }, 14_211: { metal: 120_000, crystal: 30_000, deuterium: 25_000, factor: 1.5 }, 14_212: { metal: 100_000, crystal: 40_000, deuterium: 30_000, factor: 1.5 }, 14_213: { metal: 200_000, crystal: 100_000, deuterium: 100_000, factor: 1.5 }, 14_214: { metal: 160_000, crystal: 120_000, deuterium: 50_000, factor: 1.5 }, 14_215: { metal: 240_000, crystal: 120_000, deuterium: 120_000, factor: 1.5 }, 14_216: { metal: 320_000, crystal: 240_000, deuterium: 100_000, factor: 1.5 }, 14_217: { metal: 500_000, crystal: 300_000, deuterium: 200_000, factor: 1.5 }, 14_218: { metal: 300_000, crystal: 180_000, deuterium: 120_000, factor: 1.7 }, getValues(technologies, id, reductions) { const { value } = technologies[id]; const from = 1; const to = value; return Upgradables.get(id, from, to, reductions); }, getUpgrades(technologies, id, reductions) { const { value, upgraded } = technologies[id]; const from = value + 1; const to = upgraded; return Upgradables.get(id, from, to, reductions); }, getUpgraded(technologies, id, reductions) { const { upgraded } = technologies[id]; const from = 1; const to = upgraded; return Upgradables.get(id, from, to, reductions); }, get(id, from, to, reductions) { const { metal, crystal, deuterium, factor } = Upgradables[id]; const rate = 1 - reductions?.[id] || 1; const isLifeform = id > 10_000; const result = new Resources(); for (let level = from; level <= to; level++) { const cost = new Resources(metal, crystal, deuterium); const multiplier = factor ** (level - 1) * (isLifeform * level || 1) * rate; result.add(cost.multiply(multiplier).trunc()); } return result; } }; const Values = { get(technologies, ids, reductions) { const result = new Resources(); if (technologies) { for (const id of Types.toArray(ids)) { if (technologies[id]) { const cost = getClass(id).getValues(technologies, id, reductions); result.add(cost); } } } return result; } }; const Upgrades = { get(technologies, ids, reductions) { const result = new Resources(); if (technologies) { for (const id of Types.toArray(ids)) { if (technologies[id]) { const cost = getClass(id).getUpgrades(technologies, id, reductions); result.add(cost); } } } return result; } }; const Upgraded = { get(technologies, ids, reductions) { const result = new Resources(); if (technologies) { for (const id of Types.toArray(ids)) { if (technologies[id]) { const cost = getClass(id).getUpgraded(technologies, id, reductions); result.add(cost); } } } return result; } }; function getClass(id) { if (id < 200 || id > 600) { return Upgradables; } else { return Units; } } var Costs = { Values, Upgrades, Upgraded }; function set$3(data) { setValues(data); setPercents(data); } function setValues(data) { setPositionsValues(data); setAccountValues(data); setResearchesValues(data); setShipsValues(data); setIndestructiblesValues(data); setUpgradesValues(data); } function setPositionsValues(data) { const { positions } = data.player; for (const coordinates in positions) { const { planet, moon } = positions[coordinates]; setPlanetValues(planet); if (moon) { setMoonValues(moon); } } } function setPlanetValues(body) { body.points = {}; body.points.values = {}; setMinesValues(body); setBuildingsValues(body); setLifeformsValues(body); setUnitsValues(body); setStaticsValues(body); } function setMoonValues(body) { body.points = {}; body.points.values = {}; setBuildingsValues(body); setUnitsValues(body); setStaticsValues(body); } function setMinesValues(body) { const { technologies, points } = body; const metal = Costs.Values.get(technologies, 1).toPoints(); const crystal = Costs.Values.get(technologies, 2).toPoints(); const deuterium = Costs.Values.get(technologies, 3).toPoints(); const all = metal + crystal + deuterium; points.values.mines = { all, metal, crystal, deuterium }; } function setBuildingsValues(body) { const { technologies, points } = body; points.values.buildings = { all: Costs.Values.get(technologies, IDs.buildings.all).toPoints() }; } function setLifeformsValues(body) { const { technologies, points } = body; const buildings = Costs.Values.get(technologies, IDs.lifeforms.buildings.all).toPoints(); const researches = Costs.Values.get(technologies, IDs.lifeforms.researches.all).toPoints(); const all = buildings + researches; points.values.lifeforms = { all, buildings, researches }; } function setUnitsValues(body) { const { technologies, points } = body; points.values.units = { ships: { statics: Costs.Values.get(technologies, IDs.units.ships.statics).toPoints() }, defences: { all: Costs.Values.get(technologies, IDs.units.defences.all).toPoints() } }; } function setStaticsValues(body) { const { mines, buildings, lifeforms, units } = body.points.values; body.points.values.statics = (mines?.all || 0) + buildings.all + (lifeforms?.all || 0) + units.ships.statics + units.defences.all; } function setAccountValues(data) { const { positions, points } = data.player; const values = points.values = { mines: { all: 0, metal: 0, crystal: 0, deuterium: 0 }, buildings: { all: 0, planet: 0, moon: 0 }, lifeforms: { all: 0, buildings: 0, researches: 0 }, units: { defences: { all: 0 } } }; for (const coordinates in positions) { const { planet, moon } = positions[coordinates]; values.mines.all += planet.points.values.mines.all; values.mines.metal += planet.points.values.mines.metal; values.mines.crystal += planet.points.values.mines.crystal; values.mines.deuterium += planet.points.values.mines.deuterium; values.buildings.all += planet.points.values.buildings.all; values.buildings.planet += planet.points.values.buildings.all; values.lifeforms.all += planet.points.values.lifeforms.all; values.lifeforms.buildings += planet.points.values.lifeforms.buildings; values.lifeforms.researches += planet.points.values.lifeforms.researches; values.units.defences.all += planet.points.values.units.defences.all; if (moon) { values.buildings.all += moon.points.values.buildings.all; values.buildings.moon += moon.points.values.buildings.all; values.units.defences.all += moon.points.values.units.defences.all; } } } function setResearchesValues(data) { const { researches, points } = data.player; points.values.researches = { all: Costs.Values.get(researches, IDs.researches.all).toPoints() }; } function setShipsValues(data) { const { values, total } = data.player.points; values.units.ships = { all: Math.max(0, total - values.mines.all - values.buildings.all - values.lifeforms.all - values.units.defences.all - values.researches.all) }; } function setIndestructiblesValues(data) { const { values, total } = data.player.points; values.indestructibles = total - values.buildings.moon - values.units.ships.all - values.units.defences.all; } function setUpgradesValues(data) { const { positions, researches, points } = data.player; const result = new Resources(); for (const coordinates in positions) { const { planet, moon } = positions[coordinates]; result.add(Costs.Upgrades.get(planet.technologies, IDs.planet.all)); if (moon) { result.add(Costs.Upgrades.get(moon.technologies, IDs.moon.all)); } } result.add(Costs.Upgrades.get(researches, IDs.researches.all)); points.values.upgrades = result.toPoints(); } function setPercents(data) { setPositionsPercents(data); setAccountPercents(data); } function setPositionsPercents(data) { const { positions, points } = data.player; const { total } = points; for (const coordinates in positions) { const { planet, moon } = positions[coordinates]; planet.points.percents = getPercents(planet.points.values, total); if (moon) { moon.points.percents = getPercents(moon.points.values, total); } } } function setAccountPercents(data) { const { points } = data.player; points.percents = getPercents(points.values, points.total); } function getPercents(values, total) { const result = {}; for (const key in values) { const value = values[key]; if (Types.isObject(value)) { result[key] = getPercents(value, total); } else { result[key] = Math.trunc(value) / total; if (result[key] === Infinity) { result[key] = 0; } } } return result; } var Points = { set: set$3 }; function set$2(reduced, scraped) { clean(reduced, scraped); sort(reduced, scraped); } function clean(reduced, scraped) { if (currentPage === 'empire') { cleanFromEmpire(reduced.player.positions, scraped.player.positions); } else { cleanFromPlanetList(scraped.player.positions, scraped.player.positions); } } function cleanFromEmpire(reduced, scraped) { for (const coordinates in reduced) { if (!scraped[coordinates]) { if (planetType) { delete reduced[coordinates].moon; } else { delete reduced[coordinates]; } } } } function cleanFromPlanetList(reduced, scraped) { for (const coordinates in reduced) { if (!scraped[coordinates]) { delete reduced[coordinates]; } else if (!scraped[coordinates].moon) { delete reduced[coordinates].moon; } } } function sort(reduced, scraped) { if (currentPage !== 'empire') { const result = {}; for (const coordinates in scraped.player.positions) { result[coordinates] = reduced.player.positions[coordinates]; } reduced.player.positions = result; } } var Positions$1 = { set: set$2 }; function filter(data) { const { positions } = data.player; const result = []; for (const coordinates in positions) { const { productions } = positions[coordinates].planet; if (productions) { result.push(productions); } } return result; } function get$8(...productions) { const result = {}; for (const production of productions) { for (const key in production) { const value = production[key]; if (Types.isObject(value)) { result[key] = get$8(result[key], value); } else if (key !== 'factor') { result[key] ||= 0; result[key] += value; } } } return result; } function set$1(data) { const productions = filter(data); data.player.productions = get$8(...productions); } var Productions$2 = { set: set$1 }; function set(reduced, scraped) { Positions$1.set(reduced, scraped); Defaults.set(reduced); Productions$2.set(reduced); Points.set(reduced); Highscore.set(reduced); Needed$1.clean(reduced); } var Transforms = { set }; async function get$7() { const stored = Storage.get(); const scraped = await Scraper.get(); const reduced = Types.getReducedObjects(stored, scraped); Transforms.set(reduced, scraped); return reduced; } var Data = { get: get$7 }; function init$8(data) { if (currentPage !== 'empire') { setEnergyIconWarning(); setPlanetsIconsWarnings(data); } } function setEnergyIconWarning() { const element = document.body.querySelector('#energy_box'); if (element.querySelector('#resources_energy').dataset.raw < 0) { element.querySelector('.resourceIcon.energy').classList.add('ic_energy-warning'); } } function setPlanetsIconsWarnings(data) { const list = document.querySelectorAll('#planetList .planetPic'); if (list) { const { positions } = data.player; let i = 0; for (const coordinates in positions) { if (positions[coordinates].planet.resources.energy < 0) { list[i].classList.add('ic_energy-warning'); } i++; } } } var EnergyWarnings = { init: init$8 }; function init$7(data) { if (currentPage === 'highscore') { setGapPoints(data); setEvents$7(); } } function setGapPoints(data) { // the existence of player values needs to be tested before due to a game's bug that redirects to the wrong highscore pages when there is to much players with the same rank const { player } = data.universe.highscores[currentCategory][currentType]; if (player) { for (const element of document.querySelectorAll('#ranks tbody tr:not(.myrank) .score')) { // firstChild property of score element is used for compatibility reason with OGLight const value = Types.getNumber(element.firstChild.textContent); const difference = value - player.points; const prefix = difference > 0 && '+' || ''; element.title = prefix + Types.getFullNumberString(difference); element.classList.add('tooltipRight'); } } } async function setEvents$7() { await Scraper.elementHasChanged('#stat_list_content'); await Scraper.elementHasChanged('#stat_list_content'); const scraped = await Scraper.get(); const stored = Storage.get(); const reduced = Types.getReducedObjects(stored, scraped); Storage.set(reduced); init$7(reduced); } var Highscores = { init: init$7 }; function init$6() { if (currentPage !== 'empire') { const template = document.createElement('template'); template.innerHTML = getHTML$a(); document.querySelector('#menuTable').appendChild(template.content); setEvents$6(); } } function getHTML$a() { return `<li> <span id="ic_menu_icon-button" class="menu_icon"> <div id="ic_menu_icon-wrapper" class="tooltipRight" title="${ Translation.menuTitle }"> <svg viewBox="0 0 1000 1000" height="18" fill="currentColor"> <path d="M378 158 195 842H0l183-684h195zm603 0L880 354H733a200 200 0 0 0-185 146c-11 40-6 75 15 104 21 28 51 42 92 42h195l-52 196H603c-95 0-166-34-215-100-49-67-61-148-35-242 25-94 79-175 164-242 85-66 174-100 269-100h195z"/> </svg> </div> </span> <a class="menubutton" href="${ Translation.supportLink }" target="_blank"> <span id="ic_menu_text" class="textlabel">InfoCompte ${ GM_info.script.version }</span> </a> </li>`; } function setEvents$6() { document.body.querySelector('#ic_menu_icon-button').addEventListener('click', function() { document.body.querySelector('#ic_settings').showModal(); }); } var MenuButton = { init: init$6 }; function getHTML$9(data) { return `<svg viewBox="0 0 100 100" transform="rotate(-90)"> ${(function() { const offset = 25 * Math.PI * 2; // radius * TAU let rotation = 0; let result = ''; for (const key in data) { const { percent, color } = data[key]; if (percent) { const circle = `<circle cx="50" cy="50" r="25" fill="transparent" stroke="${ color }" stroke-width="50" stroke-dasharray="${ percent * offset } ${ offset }" transform="rotate(${ rotation * 360 } 50 50)"/>`; rotation += percent; result += circle; } } return result; })()} </svg>`; } var PieChart = { getHTML: getHTML$9 }; let useCompactNumbers; function setCollapseStates(data) { const { collapsibles } = data.script; for (const element of document.body.querySelectorAll('.ic_panel')) { const { id, dataset } = element; const state = collapsibles[id] || dataset.state; dataset.state = state; } } function setCompactNumbers(value) { useCompactNumbers = value; } function setEvents$5() { for (const element of document.body.querySelectorAll('.ic_panel')) { element.querySelector('.ic_panel_title').addEventListener( 'click', function() { const data = Storage.get(); const { collapsibles } = data.script; const { id, dataset } = element; if (dataset.state === 'collapsed') { dataset.state = 'expanded'; collapsibles[id] = 'expanded'; } else { dataset.state = 'collapsed'; collapsibles[id] = 'collapsed'; } Storage.set(data); }); } } function getNumberHTML(value) { const truncated = Types.getTruncatedNumberString(value); if (useCompactNumbers) { const compact = Types.getCompactNumberString(value); return `<span class="tooltipRight" title="${ truncated }">${ compact }</span>`; } else { return `<span>${ truncated }</span>`; } } var Shared = { setCollapseStates, setCompactNumbers, setEvents: setEvents$5, getNumberHTML }; function getHTML$8(data) { const { points, movements } = getData(data); const { values, percents } = points; return `<div id="ic_account-points-panel" class="ic_panel" data-state="expanded"> <h3 class="ic_panel_title"><span></span>${ Translation.pointsRepartition }</h3> <div class="ic_panel_main"> <table class="ic_table"> <tr> <th>${ Translation.mines }</th> <td>${ values.mines.all } — <span class="ic_percent">${ percents.mines.all }</span></td> </tr> <tr> <th>${ Translation.planetBuildings }</th> <td>${ values.buildings.planet } — <span class="ic_percent">${ percents.buildings.planet }</span></td> </tr> <tr> <th>${ Translation.moonBuildings }</th> <td>${ values.buildings.moon } — <span class="ic_percent">${ percents.buildings.moon }</span></td> </tr> <tr> <th>${ Translation.lifeformBuildings }</th> <td>${ values.lifeforms.buildings } — <span class="ic_percent">${ percents.lifeforms.buildings }</span></td> </tr> <tr> <th>${ Translation.lifeformResearches }</th> <td>${ values.lifeforms.researches } — <span class="ic_percent">${ percents.lifeforms.researches }</span></td> </tr> <tr> <th>${ Translation.researches }</th> <td>${ values.researches.all } — <span class="ic_percent">${ percents.researches.all }</span></td> </tr> <tr> <th>${ Translation.ships }</th> <td>${ values.units.ships.all } — <span class="ic_percent">${ percents.units.ships.all }</span></td> </tr> <tr> <th>${ Translation.defences }</th> <td>${ values.units.defences.all } — <span class="ic_percent">${ percents.units.defences.all }</span></td> </tr> <tr> <th>${ Translation.indestructibles }</th> <td> <div>${ values.indestructibles } — <span class="ic_percent">${ percents.indestructibles }</span></div> <div>- ${ movements.ifDestroyed } ${ Translation.ifDestroyed }</div> </td> </tr> <tr> <th>${ Translation.inProduction }</th> <td> <div>${ values.upgrades } — <span class="ic_percent">${ percents.upgrades }</span></div> <div>+ ${ movements.whenUpgraded } ${ Translation.whenUpgraded }</div> </td> </tr> </table> ${ PieChart.getHTML(getPieChartData(data)) } </div> </div>`; } function getData(data) { const { player, universe, script } = data; const { points } = player; const values = getValuesData(points.values); const percents = getPercentsData(points.percents); const movements = universe.highscores?.[1][0].player?.movements || { ifDestroyed: 0, whenUpgraded: 0 }; return { movements, points: { values, percents } }; } function getValuesData(values) { const result = {}; for (const key in values) { if (Types.isObject(values[key])) { result[key] = getValuesData(values[key]); } else { result[key] = Shared.getNumberHTML(values[key]); } } return result; } function getPercentsData(percents) { const result = {}; for (const key in percents) { if (Types.isObject(percents[key])) { result[key] = getPercentsData(percents[key]); } else { result[key] = Types.getPercentString(percents[key]); } } return result; } function getPieChartData(data) { const { percents } = data.player.points; const { colors } = data.script; return { mines: { percent: percents.mines.all, color: colors.mines }, planetBuildings: { percent: percents.buildings.planet, color: colors.planetBuildings }, moonBuildings: { percent: percents.buildings.moon, color: colors.moonBuildings }, lifeformBuildings: { percent: percents.lifeforms.buildings, color: colors.lifeformBuildings }, lifeformResearches: { percent: percents.lifeforms.researches, color: colors.lifeformResearches }, researches: { percent: percents.researches.all, color: colors.researches }, ships: { percent: percents.units.ships.all, color: colors.ships }, defences: { percent: percents.units.defences.all, color: colors.defences } }; } var Account = { getHTML: getHTML$8 }; const Bonuses$1 = { Buildings: { 11_103: [.0025, 0, 0, .25, 0, 0], 11_106: [.015, 0, 0, 0, 0, 0], 11_108: [0, .015, .01, 0, 0, 0], 11_111: [.005, 0, 0, 1, 0, 0], 12_103: [.0025, 0, 0, .25, 0, 0], 12_106: [.02, 0, 0, 0, 0, 0], 12_108: [.01, 0, 0, .5, 0, 0], 12_109: [0, .02, 0, 0, 0, 0], 12_110: [0, 0, .02, 0, 0, 0], 12_111: [.005, 0, 0, .5, 0, 0], 13_103: [.0025, 0, 0, .25, 0, 0], 13_107: [0, .003, 0, 0, 0, 0], 13_110: [0, 0, .02, 0, 0, 0], 13_111: [.004, 0, 0, 1, 0, 0], 14_103: [.0025, 0, 0, .25, 0, 0], 14_107: [.0025, 0, 0, 0, 0, 0], get(position) { const { lifeform, technologies } = position.planet; const { species } = lifeform; const result = {}; for (const id of IDs.lifeforms.buildings[species]) { const bonuses = Bonuses$1.Buildings[id]; if (bonuses) { result[id] = [ bonuses[0] * technologies[id].upgraded, bonuses[1] * technologies[id].upgraded, bonuses[2] * technologies[id].upgraded ]; } } Bonuses$1.clamp(result, Bonuses$1.Buildings); return result; } }, Researches: { 11_202: [.0006, .0006, .0006, 0, 0, 0], 11_208: [.0006, .0006, .0006, 0, 0, 0], 12_202: [0, .0008, 0, 0, 0, 0], 12_203: [0, 0, .0008, 0, 0, 0], 12_205: [.0008, .0008, .0008, 0, 0, 0], 12_207: [.0008, 0, 0, 0, 0, 0], 12_210: [.0008, 0, 0, 0, 0, 0], 12_209: [.0015, 0, 0, .5, 0, 0], 12_211: [0, .0008, 0, 0, 0, 0], 12_212: [0, 0, .0008, 0, 0, 0], 12_213: [.001, 0, 0, .5, 0, 0], 12_218: [.002, 0, 0, 0, 0, 0], 13_201: [0, 0, .0008, 0, 0, 0], 13_206: [.0006, .0006, .0006, 0, 0, 0], 13_213: [.0006, .0006, .0006, 0, 0, 0], 14_202: [0, 0, .0008, 0, 0, 0], 14_212: [.0006, .0006, .0006, 0, 0, 0], get(data, positions) { const result = {}; for (const coordinates in data.player.positions) { const { lifeform, technologies } = data.player.positions[coordinates].planet; const { species, researches } = lifeform; const lifeformLevelMultiplier = 1 + .001 * data.player.lifeforms[species].level; const buildings = positions[coordinates]; const buildingsMultiplier = 1 + (buildings[11_111]?.[0] || 0) + (buildings[13_107]?.[1] || 0) + (buildings[13_111]?.[0] || 0); for (const id of researches) { const bonuses = Bonuses$1.Researches[id]; if (bonuses) { const kaeleshBuildingMultiplier = 1 + (IDs.lifeforms.researches.kaelesh.includes(id) && buildings[14_107]?.[0] || 0); const multiplier = buildingsMultiplier * kaeleshBuildingMultiplier * lifeformLevelMultiplier * technologies[id].upgraded; result[id] ||= [0, 0, 0]; result[id][0] += bonuses[0] * multiplier; result[id][1] += bonuses[1] * multiplier; result[id][2] += bonuses[2] * multiplier; } } } Bonuses$1.clamp(result, Bonuses$1.Researches); return result; } }, get(data) { const { positions } = data.player; const buildings = {}; for (const coordinates in positions) { buildings[coordinates] = Bonuses$1.Buildings.get(positions[coordinates]); } return { buildings, researches: Bonuses$1.Researches.get(data, buildings) }; }, clamp(result, bonuses) { for (const key in result) { if (bonuses[key][3]) { result[key][0] = Math.min(result[key][0], bonuses[key][3]); } if (bonuses[key][4]) { result[key][1] = Math.min(result[key][1], bonuses[key][4]); } if (bonuses[key][5]) { result[key][2] = Math.min(result[key][2], bonuses[key][5]); } } } }; const Reductions = { 11_103: IDs.lifeforms.researches.all, 12_103: IDs.lifeforms.researches.all, 12_108: IDs.lifeforms.buildings.rocktal, 12_111: IDs.resources.producers, 12_209: 122, 13_103: IDs.lifeforms.researches.all, 14_103: IDs.lifeforms.researches.all, reduce(bonuses) { const result = {}; for (const key in bonuses) { const ids = Reductions[key]; if (ids) { for (const id of Types.toArray(ids)) { result[id] ||= 0; result[id] += bonuses[key][0]; } } } return result; }, get(bonuses) { const buildings = {}; for (const coordinates in bonuses.buildings) { buildings[coordinates] = Reductions.reduce(bonuses.buildings[coordinates]); } return { buildings, researches: Reductions.reduce(bonuses.researches) }; } }; var Lifeforms$2 = { Bonuses: Bonuses$1, Reductions }; const Bonuses = { Buildings: Lifeforms$2.Bonuses.Buildings, Researches: { get(data, buildings) { const { positions, researches } = data.player; const { planetsToIgnoreCount } = data.script.amortizations.form; const multiplier = (Math.round(researches[124].upgraded * .5) + 1 - planetsToIgnoreCount) / Object.keys(positions).length; const result = Lifeforms$2.Bonuses.Researches.get(data, buildings); for (const key in result) { result[key][0] *= multiplier; result[key][1] *= multiplier; result[key][2] *= multiplier; } Lifeforms$2.Bonuses.clamp(result, Lifeforms$2.Bonuses.Researches); return result; } }, get(data) { const { positions } = data.player; const buildings = {}; for (const coordinates in positions) { buildings[coordinates] = Lifeforms$2.Bonuses.Buildings.get(positions[coordinates]); } const researches = Bonuses.Researches.get(data, buildings); return { buildings, researches }; } }; var Lifeforms$1 = { Bonuses, Reductions: Lifeforms$2.Reductions }; const Basic = { get(data) { const { speed } = data.universe; return new Resources(30 * speed, 15 * speed, 0); } }; const Mines$1 = { metal: { bonuses: [1.35, 1.23, 1.17, 1], get(data, planet) { const { position, technologies } = planet; const { upgraded } = technologies[1]; const { speed } = data.universe; const index = Math.min(3, Math.abs(position - 8)); const bonus = Mines$1.metal.bonuses[index]; const result = new Resources(); result.metal = Math.trunc(30 * upgraded * 1.1 ** upgraded * bonus * speed); return result; } }, crystal: { bonuses: [1.4, 1.3, 1.2, 1], get(data, planet) { const { position, technologies } = planet; const { upgraded } = technologies[2]; const { speed } = data.universe; const index = Math.min(3, position - 1); const bonus = Mines$1.crystal.bonuses[index]; const result = new Resources(); result.crystal = Math.trunc(20 * upgraded * 1.1 ** upgraded * bonus * speed); return result; } }, deuterium: { get(data, planet) { const { temperature, technologies } = planet; const { upgraded } = technologies[3]; const { speed } = data.universe; const bonus = 1.44 - .004 * temperature; const result = new Resources(); result.deuterium = Math.trunc(10 * upgraded * 1.1 ** upgraded * bonus * speed); return result; } }, get(data, planet) { const result = new Resources(); result.add( Mines$1.metal.get(data, planet), Mines$1.crystal.get(data, planet), Mines$1.deuterium.get(data, planet) ); return result; } }; const Crawlers = { get(data, planet, productions, bonuses, count) { const result = new Resources(productions); return result.multiply(Crawlers.getMultiplier(data, planet, bonuses, count)); }, getCurrentCount(data, planet, bonuses) { const current = planet.technologies[217].upgraded; const maximum = Crawlers.getMaximumCount(data, planet, bonuses); return Math.min(current, maximum); }, getMaximumCount(data, planet, bonuses) { const { player } = data; const { technologies } = planet; const levels = technologies[1].upgraded + technologies[2].upgraded + technologies[3].upgraded; const multiplier = 1 + (player.class === 'miner' && player.officers.geologist && .1 * (1 + bonuses[12_218]?.[0] || 1) || 0); return Math.floor(8 * levels * multiplier); }, getMultiplier(data, planet, bonuses, count) { const bb = .0002 * (1 + bonuses[12_213]?.[0] || 1); const cb = data.player.class === 'miner' ? .0002 * (.5 * (1 + bonuses[12_218]?.[0] || 1)) : 0; const multiplier = (bb + cb) * planet.productions.crawlers.factor; return Math.min(count * multiplier, .5); } }; const Lifeforms = { get(productions, bonuses, ids) { const result = new Resources(); for (const id of Types.toArray(ids)) { if (bonuses[id] && IDs.resources.increasers.includes(id)) { result.add(new Resources( productions.metal * bonuses[id][0], productions.crystal * bonuses[id][1], productions.deuterium * bonuses[id][2] )); } } return result; } }; const Plasma$1 = { get(data, productions) { const { upgraded } = data.player.researches[122]; return new Resources( productions.metal * .01 * upgraded, productions.crystal * .0066 * upgraded, productions.deuterium * .0033 * upgraded ); } }; const Officers = { get(data, productions) { const { all, geologist } = data.player.officers; const result = new Resources(productions); return result.multiply((geologist && .1 || 0) + (all && .02 || 0)); } }; const Classes = { get(data, productions, bonuses) { const result = new Resources(productions); return result.multiply(Classes.getMultiplier(data, bonuses)); }, getMultiplier(data, bonuses) { const { player } = data; let result = 0; result += player.class === 'miner' && .25 * (1 + bonuses[12_218]?.[0] || 1) || 0; result += player.alliance.class === 'trader' && .05 || 0; return result; } }; const Boosters = { get(productions, bonuses) { return new Resources( productions.metal * bonuses.metal, productions.crystal * bonuses.crystal, productions.deuterium * bonuses.deuterium ); } }; var Productions$1 = { Basic, Mines: Mines$1, Crawlers, Lifeforms, Plasma: Plasma$1, Officers, Classes, Boosters }; function getCost$2(data, coordinates, reductions, id) { const { technologies } = data.player.positions[coordinates].planet; return Costs.Upgrades.get(technologies, id, reductions.buildings[coordinates]); } function getProduction$3(data, coordinates, bonuses) { const { player, script } = data; const position = player.positions[coordinates]; const { planet } = position; const { lifeform, boosters } = planet; const { species } = lifeform; const { useMaximumCrawlers, useResourceBoosters } = script.amortizations.form; const crawlersGetCount = useMaximumCrawlers && Productions$1.Crawlers.getMaximumCount || Productions$1.Crawlers.getCurrentCount; const productions = Productions$1.Mines.get(data, planet); const result = new Resources(); result.add( productions, Productions$1.Lifeforms.get(productions, bonuses.buildings[coordinates], IDs.lifeforms.buildings[species]), Productions$1.Lifeforms.get(productions, bonuses.researches, IDs.resources.increasers), Productions$1.Crawlers.get(data, planet, productions, bonuses.researches, crawlersGetCount(data, planet, bonuses.researches)), Productions$1.Plasma.get(data, productions), Productions$1.Officers.get(data, productions), Productions$1.Classes.get(data, productions, bonuses.researches) ); if (boosters && useResourceBoosters) { result.add(Productions$1.Boosters.get(productions, boosters)); } return result; } function get$6(data, coordinates, bonuses, reductions, id) { const technology = data.player.positions[coordinates].planet.technologies[id]; const { rates } = data.script; // save inital values before upgrade const initialValue = technology.value; const initialUpgrade = technology.upgrade; const initialUpgraded = technology.upgraded; const initialProduction = getProduction$3(data, coordinates, bonuses); // set upgrade technology.value = technology.upgraded; technology.upgraded += 1; technology.upgrade = 1; // get result const level = technology.upgraded; const cost = getCost$2(data, coordinates, reductions, id); const production = getProduction$3(data, coordinates, bonuses).subtract(initialProduction); const amortization = cost.toTotal(rates) / production.toTotal(rates); // restore initial values & result return technology.value = initialValue; technology.upgrade = initialUpgrade; technology.upgraded = initialUpgraded; return { coordinates, id, level, cost, production, amortization }; } var Mines = { get: get$6 }; const Buildings$1 = { getCost(data, coordinates, reductions, id) { const { technologies } = data.player.positions[coordinates].planet; return Costs.Upgrades.get(technologies, id, reductions.buildings[coordinates]); }, getProduction(data, coordinates, bonuses, id) { const { planet } = data.player.positions[coordinates]; const productions = Productions$1.Mines.get(data, planet); return Productions$1.Lifeforms.get(productions, bonuses.buildings[coordinates], id); }, get(data, coordinates, bonuses, reductions, id) { const position = data.player.positions[coordinates]; const { technologies } = position.planet; const { rates } = data.script; const technology = technologies[id]; // save inital values before upgrade const initialValue = technology.value; const initialUpgrade = technology.upgrade; const initialUpgraded = technology.upgraded; const initialProduction = Buildings$1.getProduction(data, coordinates, bonuses, id); // set upgrade technology.value = technology.upgraded; technology.upgraded += 1; technology.upgrade = 1; bonuses.buildings[coordinates] = Lifeforms$1.Bonuses.Buildings.get(position); // compute needed values const level = technology.upgraded; const cost = Buildings$1.getCost(data, coordinates, reductions, id); const production = Buildings$1.getProduction(data, coordinates, bonuses, id).subtract(initialProduction); const amortization = cost.toTotal(rates) / production.toTotal(rates); // restore initial values & result return technology.value = initialValue; technology.upgrade = initialUpgrade; technology.upgraded = initialUpgraded; bonuses.buildings[coordinates] = Lifeforms$1.Bonuses.Buildings.get(position); return { coordinates, id, level, cost, production, amortization }; } }; const Researches$1 = { getCost(data, coordinates, reductions, id) { const { technologies } = data.player.positions[coordinates].planet; return Costs.Upgrades.get(technologies, id, reductions.buildings[coordinates]); }, getProduction(data, coordinates, bonuses, id) { const { positions } = data.player; const result = new Resources(); for (const coordinates in positions) { const { planet } = positions[coordinates]; const productions = Productions$1.Mines.get(data, planet); result.add(Productions$1.Lifeforms.get(productions, bonuses.researches, id)); } return result; }, get(data, coordinates, bonuses, reductions, id) { const position = data.player.positions[coordinates]; const { technologies } = position.planet; const { rates } = data.script; const technology = technologies[id]; // save inital values before upgrade const initialValue = technology.value; const initialUpgrade = technology.upgrade; const initialUpgraded = technology.upgraded; const initialProduction = Researches$1.getProduction(data, coordinates, bonuses, id); // set upgrade technology.value = technology.upgraded; technology.upgraded += 1; technology.upgrade = 1; bonuses.researches = Lifeforms$1.Bonuses.Researches.get(data, bonuses.buildings); // compute needed values const level = technology.upgraded; const cost = Researches$1.getCost(data, coordinates, reductions, id); const production = Researches$1.getProduction(data, coordinates, bonuses, id).subtract(initialProduction); const amortization = cost.toTotal(rates) / production.toTotal(rates); // restore initial values & result return technology.value = initialValue; technology.upgrade = initialUpgrade; technology.upgraded = initialUpgraded; bonuses.researches = Lifeforms$1.Bonuses.Researches.get(data, bonuses.buildings); return { coordinates, id, level, cost, production, amortization }; } }; var Increasers = { Buildings: Buildings$1, Researches: Researches$1 }; function getProduction$2(data, bonuses) { const { player, script } = data; const { positions, researches } = player; const { useMaximumCrawlers, useResourceBoosters, planetsToIgnoreCount } = script.amortizations.form; const crawlersGetCount = useMaximumCrawlers && Productions$1.Crawlers.getMaximumCount || Productions$1.Crawlers.getCurrentCount; const result = new Resources(); for (const coordinates in positions) { const position = positions[coordinates]; const { planet } = position; const { boosters } = planet; const productions = Productions$1.Mines.get(data, planet); result.add( Productions$1.Lifeforms.get(productions, bonuses.researches, IDs.resources.increasers), Productions$1.Crawlers.get(data, planet, productions, bonuses.researches, crawlersGetCount(data, planet, bonuses.researches)), Productions$1.Classes.get(data, productions, bonuses.researches) ); if (boosters && useResourceBoosters) { result.add(Productions$1.Boosters.get(productions, boosters)); } } return result.multiply((Math.round(researches[124].upgraded * .5) + 1 - planetsToIgnoreCount) / Object.keys(positions).length); } const Buildings = { getCost(data, coordinates, reductions, id) { const { technologies } = data.player.positions[coordinates].planet; return Costs.Upgrades.get(technologies, id, reductions.buildings[coordinates]); }, get(data, coordinates, bonuses, reductions, id) { const position = data.player.positions[coordinates]; const { technologies } = position.planet; const { rates } = data.script; const technology = technologies[id]; // save inital values before upgrade const initialValue = technology.value; const initialUpgrade = technology.upgrade; const initialUpgraded = technology.upgraded; const initialProduction = getProduction$2(data, bonuses); // set upgrade technology.value = technology.upgraded; technology.upgraded += 1; technology.upgrade = 1; bonuses.buildings[coordinates] = Lifeforms$1.Bonuses.Buildings.get(position); bonuses.researches = Lifeforms$1.Bonuses.Researches.get(data, bonuses.buildings); // compute needed values const level = technology.upgraded; const cost = Buildings.getCost(data, coordinates, reductions, id); const production = getProduction$2(data, bonuses).subtract(initialProduction); const amortization = cost.toTotal(rates) / production.toTotal(rates); // restore initial values & result return technology.value = initialValue; technology.upgrade = initialUpgrade; technology.upgraded = initialUpgraded; bonuses.buildings[coordinates] = Lifeforms$1.Bonuses.Buildings.get(position); bonuses.researches = Lifeforms$1.Bonuses.Researches.get(data, bonuses.buildings); return { coordinates, id, level, cost, production, amortization }; } }; const Researches = { getCost(data, coordinates, reductions, id) { const { technologies } = data.player.positions[coordinates].planet; return Costs.Upgrades.get(technologies, id, reductions.buildings[coordinates]); }, get(data, coordinates, bonuses, reductions, id) { const position = data.player.positions[coordinates]; const { technologies } = position.planet; const { rates } = data.script; const technology = technologies[id]; // save inital values before upgrade const initialValue = technology.value; const initialUpgrade = technology.upgrade; const initialUpgraded = technology.upgraded; const initialProduction = getProduction$2(data, bonuses); // set upgrade technology.value = technology.upgraded; technology.upgraded += 1; technology.upgrade = 1; bonuses.researches = Lifeforms$1.Bonuses.Researches.get(data, bonuses.buildings); // compute needed values const level = technology.upgraded; const cost = Researches.getCost(data, coordinates, reductions, id); const production = getProduction$2(data, bonuses).subtract(initialProduction); const amortization = cost.toTotal(rates) / production.toTotal(rates); // restore initial values & result return technology.value = initialValue; technology.upgrade = initialUpgrade; technology.upgraded = initialUpgraded; bonuses.researches = Lifeforms$1.Bonuses.Researches.get(data, bonuses.buildings); return { coordinates, id, level, cost, production, amortization }; } }; var Enhancers = { Buildings, Researches }; function getCost$1(data, reductions) { return Costs.Upgrades.get(data.player.researches, 122, reductions.researches); } function getProduction$1(data) { const { positions, researches } = data.player; const { planetsToIgnoreCount } = data.script.amortizations.form; const result = new Resources(); for (const coordinates in positions) { const { planet } = positions[coordinates]; const productions = Productions$1.Mines.get(data, planet); result.add(Productions$1.Plasma.get(data, productions)); } return result.multiply((Math.round(researches[124].upgraded * .5) + 1 - planetsToIgnoreCount) / Object.keys(positions).length); } function get$5(data, reductions) { const id = 122; const { researches } = data.player; const technology = researches[id]; const { rates } = data.script; // save inital values before upgrade const initialValue = technology.value; const initialUpgrade = technology.upgrade; const initialUpgraded = technology.upgraded; const initialProduction = getProduction$1(data); // set upgrade technology.value = technology.upgraded; technology.upgraded += 1; technology.upgrade = 1; // compute needed values const level = technology.upgraded; const cost = getCost$1(data, reductions); const production = getProduction$1(data).subtract(initialProduction); const amortization = cost.toTotal(rates) / production.toTotal(rates); // restore initial values & result return technology.value = initialValue; technology.upgrade = initialUpgrade; technology.upgraded = initialUpgraded; return { id, level, cost, production, amortization }; } var Plasma = { get: get$5 }; function getCost(data, reductions) { const { positions, researches } = data.player; const result = new Resources(); for (const coordinates in positions) { const { planet, moon } = positions[coordinates]; result.add( Costs.Upgraded.get(planet.technologies, IDs.upgradables.planet, reductions.buildings[coordinates]), Costs.Upgraded.get(planet.technologies, IDs.units.statics) ); if (moon) { result.add( Costs.Upgraded.get(moon.technologies, IDs.upgradables.moon), Costs.Upgraded.get(moon.technologies, IDs.units.statics) ); } } result.divide(Object.keys(positions).length); result.add(Costs.Upgrades.get(researches, 124)); return result; } function getProduction(data, bonuses) { const { player, script } = data; const { positions, researches } = player; const { useMaximumCrawlers, useResourceBoosters, planetsToIgnoreCount } = script.amortizations.form; const crawlersGetCount = useMaximumCrawlers && Productions$1.Crawlers.getMaximumCount || Productions$1.Crawlers.getCurrentCount; const result = new Resources(); for (const coordinates in positions) { const position = positions[coordinates]; const { planet } = position; const { lifeform, boosters } = planet; const { species } = lifeform; const productions = Productions$1.Mines.get(data, planet); result.add( productions, Productions$1.Basic.get(data), Productions$1.Lifeforms.get(productions, bonuses.buildings[coordinates], IDs.lifeforms.buildings[species]), Productions$1.Lifeforms.get(productions, bonuses.researches, IDs.resources.increasers), Productions$1.Crawlers.get(data, planet, productions, bonuses.researches, crawlersGetCount(data, planet, bonuses.researches)), Productions$1.Plasma.get(data, productions), Productions$1.Officers.get(data, productions), Productions$1.Classes.get(data, productions, bonuses.researches) ); if (boosters && useResourceBoosters) { result.add(Productions$1.Boosters.get(productions, boosters)); } } return result.multiply((Math.round(researches[124].upgraded * .5) + 1 - planetsToIgnoreCount) / Object.keys(positions).length); } function get$4(data, bonuses, reductions) { const id = 124; const technology = data.player.researches[id]; const { rates } = data.script; // save inital values before upgrade const initialValue = technology.value; const initialUpgrade = technology.upgrade; const initialUpgraded = technology.upgraded; const initialProduction = getProduction(data, bonuses); // set upgrade technology.upgraded = Math.round(technology.upgraded * .5) * 2 + 1; technology.value = Math.max(0, technology.upgraded - 2); technology.upgrade = technology.upgraded - technology.value; bonuses.researches = Lifeforms$1.Bonuses.Researches.get(data, bonuses.buildings); // get result const level = `${ technology.upgraded - 1 }/${ technology.upgraded }`; const cost = getCost(data, reductions); const production = getProduction(data, bonuses).subtract(initialProduction); const amortization = cost.toTotal(rates) / production.toTotal(rates); // restore initial values & result return technology.value = initialValue; technology.upgrade = initialUpgrade; technology.upgraded = initialUpgraded; bonuses.researches = Lifeforms$1.Bonuses.Researches.get(data, bonuses.buildings); return { id, level, cost, production, amortization }; } var Astrophysics = { get: get$4 }; var Technologies = { Mines, Increasers, Enhancers, Plasma, Astrophysics }; function removePlanetsToIgnore(data) { const { positions } = data.player; const { form } = data.script.amortizations; const result = []; for (const coordinates in positions) { if (form[coordinates]) { result.push(coordinates); } } for (coordinates of result) { delete positions[coordinates]; } form.planetsToIgnoreCount = result.length; } function getAll(data) { const { positions } = data.player; const { form } = data.script.amortizations; const bonuses = Lifeforms$1.Bonuses.get(data); const reductions = Lifeforms$1.Reductions.get(bonuses); const result = []; for (const coordinates in positions) { const position = positions[coordinates]; const { lifeform } = position.planet; const { species, researches } = lifeform; if (form.mines) { for (const id of IDs.mines.all) { result.push(Technologies.Mines.get(data, coordinates, bonuses, reductions, id)); } } if (form.lifeformBuildings) { for (const id of IDs.lifeforms.buildings[species]) { if (IDs.resources.increasers.includes(id)) { result.push(Technologies.Increasers.Buildings.get(data, coordinates, bonuses, reductions, id)); } else if (IDs.resources.enhancers.includes(id)) { result.push(Technologies.Enhancers.Buildings.get(data, coordinates, bonuses, reductions, id)); } } } if (form.lifeformResearches) { for (const id of researches) { if (IDs.resources.increasers.includes(id)) { result.push(Technologies.Increasers.Researches.get(data, coordinates, bonuses, reductions, id)); } else if (IDs.resources.enhancers.includes(id)) { result.push(Technologies.Enhancers.Researches.get(data, coordinates, bonuses, reductions, id)); } } } } if (form.plasma) { result.push(Technologies.Plasma.get(data, reductions)); } if (form.astrophysics) { result.push(Technologies.Astrophysics.get(data, bonuses, reductions)); } return result; } function getNext(technologies) { let amortization = Infinity; let result; for (const technology of technologies) { if (technology.amortization < amortization) { amortization = technology.amortization; result = technology; } } return result; } function get$3() { const data = Storage.get(); const { player, script } = data; const { positions, researches } = player; const result = []; removePlanetsToIgnore(data); for (let i = 0; i < 50; i++) { const next = getNext(getAll(data)); const technologies = next.coordinates && positions[next.coordinates].planet.technologies || researches; const technology = technologies[next.id]; technology.upgraded = next.id === 124 && Math.round(technology.upgraded * .5) * 2 + 1 || technology.upgraded + 1; result.push(next); } return result; } var Amortizations$2 = { get: get$3 }; function getHTML$7(data) { return `<div id="ic_amortizations-panel" class="ic_panel" data-state="collapsed"> <h3 class="ic_panel_title"><span></span>${ Translation.amortizations }</h3> <div class="ic_panel_main"> <form class="ic_form"> <fieldset> <button type="button" id="ic_amortizations-panel_settings-button" class="btn_blue ic_button" >${ Translation.settings }</button> <button type="button" id="ic_amortizations-panel_update-button" class="btn_blue ic_button tooltipRight" title="⚠ ${ Translation.amortizationsWarning }">${ Translation.update }</button> </fieldset> </form> <table class="ic_table"><tbody>${ getTableHTML(data) }</tbody></table> </div> </div>`; } function getTableHTML(data) { const { positions } = data.player; const { amortizations, numbers, rates } = data.script; const { table } = amortizations; let result = ''; if (table) { let i = 0; for (const { coordinates, id, level, cost, production, amortization } of table) { const isObsolete = coordinates && !positions[coordinates]; // for decolonized/destroyed cases if (!isObsolete) { result += `<tr> <td>${ ++i }.</td> <td> ${(function() { if (coordinates) { return `<div>${ positions[coordinates].planet.name }</div> <div>${ coordinates }</div>`; } else { return `<div>${ Translation.researches }</div>`; } })()} </td> <td><div>${ getTechnologyName(id) }</div><div>${ getTechnologyLevel(level) }</div></td> <td> <div>${ Shared.getNumberHTML(cost.metal, numbers) }</div> <div>${ Shared.getNumberHTML(cost.crystal, numbers) }</div> <div>${ Shared.getNumberHTML(cost.deuterium, numbers) }</div> <div>${ Shared.getNumberHTML(Resources.getTotal(cost, rates)) }</div> </td> <td> <div>${ Shared.getNumberHTML(production.metal, numbers) }</div> <div>${ Shared.getNumberHTML(production.crystal, numbers) }</div> <div>${ Shared.getNumberHTML(production.deuterium, numbers) }</div> <div>${ Shared.getNumberHTML(Resources.getTotal(production, rates)) }</div> </td> <td>${ Types.getDurationString(amortization) }</td> </tr>`; } } } if (result) { result = `<tr><th></th><th></th><th></th><th>${ Translation.costs }</th><th>${ Translation.productions }</th><th>${ Translation.amortizations }</th></tr> ${ result }`; } return result; } function getTechnologyName(id) { let result = Translation[id]; if(IDs.lifeforms.researches.all.includes(id)) { result += ` ${ getLifeformResearchAbbreviation(id) }`; } return result; } function getLifeformResearchAbbreviation(id) { const root = id % 1_000 - 200; const tier = Math.ceil(root / 6); const slot = root % 6 || 6; return `(${ tier }-${ slot })`; } function getTechnologyLevel(value) { const prefix = typeof value === 'number' && Translation.level || Translation.levels; return `${ prefix } ${ value }`; } function setEvents$4() { setUpdateEvent(); setSettingsEvent(); } function setUpdateEvent() { document.body.querySelector('#ic_amortizations-panel_update-button').addEventListener('click', function() { const data = Storage.get(); data.script.amortizations.table = Amortizations$2.get(); document.querySelector('#ic_amortizations-panel tbody').innerHTML = getTableHTML(data); Storage.set(data); }); } function setSettingsEvent() { document.body.querySelector('#ic_amortizations-panel_settings-button').addEventListener('click', function() { document.body.querySelector('#ic_amortizations-panel_settings').showModal(); }); } var Amortizations$1 = { getHTML: getHTML$7, setEvents: setEvents$4 }; function getTitleSection$2(value) { const date = new Date(); const url = `[url=https://board.fr.ogame.gameforge.com/index.php?thread/746302-infocompte/]InfoCompte ${ GM_info.script.version }[/url]`; const title = getSized(getColored$2(value, Colors.main), 24); const stamp = `${ Translation.generatedOn } ${ date.toLocaleDateString('fr-FR') } ${ Translation.at } ${ date.toLocaleTimeString('de-DE', { timeStyle: 'short' }) } ${ Translation.with } ${ url }`; return `${ title }\n${ stamp }\n\n`; } function getClassesSection(data) { let result = ''; if (data.player.class) { const value = Translation[`${ data.player.class }PlayerClass`]; result += getColored$2(value, Colors.main); } if (data.player.alliance.class) { const value = Translation[`${ data.player.alliance.class }AllicanceClass`]; const colored = getColored$2(value, Colors.main); result += result ? ` & ${ colored }` : colored; } if (result) { result = getSized(result, 14) + '\n\n'; } return result; } function getLifeformLevelsSection(data) { const { lifeforms } = data.player; let result = ''; for(const key in lifeforms) { const lifeform = lifeforms[key]; const level = getColored$2(lifeform.level, Colors.main); const current = Types.getFullNumberString(lifeform.xp.current); const maximum = Types.getFullNumberString(lifeform.xp.maximum); result += `${ Translation[key] } : ${ level } · ${ current }/${ maximum } xp\n`; } if (result) { const subtitle = getSectionTitle$1(Translation.lifeformLevels); result = `${ subtitle + result }\n`; } return result; } function getSectionTitle$1(value) { return getSized(getColored$2(value, Colors.main), 18) + '\n'; } function getPadding$2(value, length) { const count = Math.max(0, length - value.toString().length); return '_'.repeat(count); } function getColored$2(value, color) { return `[color=${ color }]${ value }[/color]`; } function getSized(value, size) { return `[size=${ size }]${ value }[/size]`; } function getAverage$1(array) { return Math.round(getSum$1(array) / array.length) + ' Ø'; } function getSum$1(array) { return array.reduce(function(previous, current) { return previous + current; }, 0); } var Exports$2 = { getTitleSection: getTitleSection$2, getClassesSection, getLifeformLevelsSection, getSectionTitle: getSectionTitle$1, getPadding: getPadding$2, getColored: getColored$2, getAverage: getAverage$1, getSum: getSum$1 }; const { getFullNumberString: getFullNumberString$1, getTruncatedNumberString: getTruncatedNumberString$1, getPercentString } = Types; const { getPadding: getPadding$1, getColored: getColored$1, getAverage, getSum } = Exports$2; function get$2(data) { return getTitleSection$1(data) + Exports$2.getClassesSection(data) + Exports$2.getLifeformLevelsSection(data) + getPointsSection$1(data) + getProductionsSection$1(data) + getTemperaturesSection(data) + getPlanetFieldsSection(data) + getPlanetBuildingsSection(data) + getMoonBuildingsSection(data) + getLifeformBuildingsSection(data) + getLifeformResearches(data) + getResearchesSection$1(data) + getShipsSection(data) + getPlanetDefencesSection(data) + getMoonDefencesSection(data); } function getTitleSection$1(data) { const { player, universe } = data; return Exports$2.getTitleSection(`${ Translation.empireOf } ${ player.name } ${ Translation.on } ${ universe.name }.${ universe.language }`); } function getPointsSection$1(data) { const { values, percents, total } = data.player.points; return getBlockSection(Translation.pointsRepartition, [ [Translation.mines, getTruncatedNumberString$1(values.mines.all), getPercentString(percents.mines.all)], [Translation.planetBuildings, getTruncatedNumberString$1(values.buildings.planet), getPercentString(percents.buildings.planet)], [Translation.moonBuildings, getTruncatedNumberString$1(values.buildings.moon), getPercentString(percents.buildings.moon)], [Translation.lifeformBuildings, getTruncatedNumberString$1(values.lifeforms.buildings), getPercentString(percents.lifeforms.buildings)], [Translation.lifeformResearches, getTruncatedNumberString$1(values.lifeforms.researches), getPercentString(percents.lifeforms.researches)], [Translation.researches, getTruncatedNumberString$1(values.researches.all), getPercentString(percents.researches.all)], [Translation.ships, getTruncatedNumberString$1(values.units.ships.all), getPercentString(percents.units.ships.all)], [Translation.defences, getTruncatedNumberString$1(values.units.defences.all), getPercentString(percents.units.defences.all)], [Translation.total, getTruncatedNumberString$1(total), `${ getPercentString(percents.indestructibles) } ${ Translation.indestructibles.toLowerCase() }`] ]); } function getProductionsSection$1(data) { const { metal, crystal, deuterium } = data.player.productions.total; return getBlockSection(Translation.dailyProductions, [ [Translation.metal, getTruncatedNumberString$1(metal * 24)], [Translation.crystal, getTruncatedNumberString$1(crystal * 24)], [Translation.deuterium, getTruncatedNumberString$1(deuterium * 24)] ]); } function getTemperaturesSection(data) { const { positions } = data.player; const values = []; for(const coordinates in positions) { const { temperature } = positions[coordinates].planet; values.push(temperature); } const rows = { '': { values } }; return getInlineSection(Translation.maximumTemperatures, rows, getAverage, 0); } function getPlanetFieldsSection(data) { const { positions } = data.player; const maximum = []; const used = []; for(const coordinates in positions) { const { fields } = positions[coordinates].planet; maximum.push(fields.maximum); used.push(fields.used); } const rows = { [Translation.maximum]: { values: maximum }, [Translation.used]: { values: used } }; return getInlineSection(Translation.planetFields, rows, getAverage, 3); } function getPlanetBuildingsSection(data) { const ids = [...IDs.mines.all, ...IDs.buildings.planet]; const rows = getInlineSectionRows(data, 'planet', ids); return getInlineSection(Translation.planetBuildings, rows, getSum, 2); } function getLifeformBuildingsSection(data) { const rows = getInlineSectionRows(data, 'planet', IDs.lifeforms.buildings.all); return getInlineSection(Translation.lifeformBuildings, rows, getSum, 2); } function getLifeformResearches(data) { const rows = getInlineSectionRows(data, 'planet', IDs.lifeforms.researches.all); return getInlineSection(Translation.lifeformResearches, rows, getSum, 2); } function getPlanetDefencesSection(data) { const rows = getInlineSectionRows(data, 'planet', IDs.units.defences.all); return getInlineSection(Translation.planetDefences, rows, getSum, 8); } function getMoonBuildingsSection(data) { const rows = getInlineSectionRows(data, 'moon', IDs.buildings.moon); return getInlineSection(Translation.moonBuildings, rows, getSum, 2); } function getMoonDefencesSection(data) { const rows = getInlineSectionRows(data, 'moon', IDs.units.defences.all); return getInlineSection(Translation.planetDefences, rows, getSum, 8); } function getResearchesSection$1(data) { // add test if there is no researches before return result const { researches } = data.player; const rows = []; for(const key in researches) { const research = researches[key]; const row = [Translation[key]]; if (research.upgrade) { row.push(research.upgraded, '', Colors.upgrade); } else { row.push(research.value); } rows.push(row); } return getBlockSection(Translation.researches, rows); } function getShipsSection(data) { const { positions } = data.player; const ids = IDs.units.ships.all; const values = {}; const upgraded = {}; const rows = []; for(const coordinates in positions) { const { planet, moon } = positions[coordinates]; for(const key of ids) { const technology = planet.technologies[key]; if (technology) { values[key] = values[key] + technology.upgraded || 0; upgraded[key] += technology.upgrade ? true : false; } } if (moon) { for(const key of ids) { const technology = moon.technologies[key]; if (technology) { values[key] = values[key] + technology.upgraded || 0; upgraded[key] += technology.upgrade ? true : false; } } } } for(const key in values) { let value = values[key]; if (value) { const row = []; row[0] = Translation[key]; row[1] = Types.getFullNumberString(value); if (upgraded[key]) { row[2] = Colors.upgrade; } rows.push(row); } } return getBlockSection(Translation.ships, rows); } function getBlockSection(title, rows) { let result = ''; for(const [key, value, suffix, color] of rows) { result += `${ key } : `; result += getColored$1(value, color || Colors.main); if (suffix) { result += ` · ${ suffix }`; } result += `\n`; } if (result) { result = Exports$2.getSectionTitle(title) + result + '\n'; } return result; } function getInlineSection(title, rows, fn, digits) { let result = ''; for(const key in rows) { const { values, upgrades } = rows[key]; let total = fn(values); if (total) { let hasUpgrade = false; for(let i = 0; i < values.length; i++) { let value = values[i]; const padding = getPadding$1(value, digits); if (upgrades?.[i]) { hasUpgrade = true; value = getColored$1(value, Colors.upgrade); } result += `${ padding + value }, `; } total = getFullNumberString$1(total); total = getColored$1(total, hasUpgrade ? Colors.upgrade : Colors.main); result = result.slice(0, -2); result += ` · ${ total } ${ key }\n`; } } if (result) { result = Exports$2.getSectionTitle(title) + result + '\n'; } return result; } function getInlineSectionRows(data, type, ids) { const { positions } = data.player; const result = {}; for(const coordinates in positions) { const body = positions[coordinates][type]; if (body) { for(const id of ids) { const technology = body.technologies[id]; if (technology) { const key = Translation[id]; result[key] ||= { values: [], upgrades: [] }; if (technology.upgrade) { result[key].values.push(technology.upgraded); result[key].upgrades.push(true); } else { result[key].values.push(technology.value); result[key].upgrades.push(false); } } } } } return result; } var Empire = { get: get$2 }; const { getFullNumberString, getTruncatedNumberString } = Types; const { getSectionTitle, getPadding, getColored } = Exports$2; function get$1(data) { return getTitleSection(data) + Exports$2.getClassesSection(data) + Exports$2.getLifeformLevelsSection(data) + getPointsSection(data) + getPlanetsSection(data) + getResearchesSection(data) + getProductionsSection(data) } function getTitleSection(data) { const { player, universe } = data; return Exports$2.getTitleSection(`${ Translation.productionOf } ${ player.name } ${ Translation.on } ${ universe.name }.${ universe.language }`); } function getPlanetsSection(data) { const { positions } = data.player; let content = ''; let i = 1; for (const coordinates in positions) { const { position, temperature, technologies } = positions[coordinates].planet; content += getPlanetNumber(i++); content += getPlanetPosition(position); content += getPlanetTechnology(technologies[1], Colors.metal, 2); content += getPlanetTechnology(technologies[2], Colors.crystal, 2); content += getPlanetTechnology(technologies[3], Colors.deuterium, 2); content += getPlanetTechnology(technologies[217], Colors.crawlers, 0); content += getPlanetTemperature(temperature); } return getSectionTitle(Translation.planets) + content + '\n'; } function getPointsSection(data) { const { mines } = data.player.points.values; const metal = getColored(getTruncatedNumberString(mines.metal), Colors.metal); const crystal = getColored(getTruncatedNumberString(mines.crystal), Colors.crystal); const deuterium = getColored(getTruncatedNumberString(mines.deuterium), Colors.deuterium); const total = getTruncatedNumberString(mines.all); return getSectionTitle(Translation.pointsRepartition) + `${ Translation[1] } : ${ metal }\n` + `${ Translation[2] } : ${ crystal }\n` + `${ Translation[3] } : ${ deuterium }\n` + `${ Translation.total } : ${ total }\n\n`; } function getProductionsSection(data) { const { mines, lifeforms, premium, total } = data.player.productions; const mineMetal = getDailyProductionString(mines.metal.metal, Colors.metal); const mineCrystal = getDailyProductionString(mines.crystal.crystal, Colors.crystal); const mineDeuterium = getDailyProductionString(mines.deuterium.deuterium, Colors.deuterium); const lifeformsMetal = getDailyProductionString(lifeforms.metal, Colors.metal); const lifeformsrystal = getDailyProductionString(lifeforms.crystal, Colors.crystal); const lifeformsDeuterium = getDailyProductionString(lifeforms.deuterium, Colors.deuterium); const premiumMetal = getDailyProductionString(premium.metal, Colors.metal); const premiumCrystal = getDailyProductionString(premium.crystal, Colors.crystal); const premiumDeuterium = getDailyProductionString(premium.deuterium, Colors.deuterium); const totalMetal = getDailyProductionString(total.metal, Colors.metal); const totalCrystal = getDailyProductionString(total.crystal, Colors.crystal); const totalDeuterium = getDailyProductionString(total.deuterium, Colors.deuterium); return getSectionTitle(Translation.dailyProductions) + `${ Translation.mines } : ${ mineMetal }, ${ mineCrystal }, ${ mineDeuterium }\n` + `${ Translation.lifeforms } : ${ lifeformsMetal }, ${ lifeformsrystal }, ${ lifeformsDeuterium }\n` + `${ Translation.premium } : ${ premiumMetal }, ${ premiumCrystal }, ${ premiumDeuterium }\n` + `${ Translation.total } : ${ totalMetal }, ${ totalCrystal }, ${ totalDeuterium }\n\n`; } function getResearchesSection(data) { const { researches } = data.player; const research = researches[122]; let result = ''; if (research) { let value; let color; if (research.upgrade) { value = research.upgraded; color = Colors.upgrade; } else { value = research.value; color = Colors.main; } value = getColored(value, color); result += `${ Translation[122] } : ${ value }\n`; } if (result) { result = getSectionTitle(Translation.researches) + result + '\n'; } return result; } function getPlanetNumber(value) { return `${ value.toString().padStart(2, '0') }. `; } function getPlanetPosition(value) { return `P${ value.toString().padStart(2, '0') }, `; } function getPlanetTechnology(technology, color, padding) { let value; if (technology.upgrade) { value = technology.upgraded; color = Colors.upgrade; } else { value = technology.value; } return getPadding(value, padding) + getColored(Types.getFullNumberString(value), color) + ', '; } function getPlanetTemperature(value) { return getColored(value + ' °C', '#f5bbb4') + '\n'; } function getDailyProductionString(value, color) { return getColored(getTruncatedNumberString(value * 24), color); } var Production = { get: get$1 }; var Exports$1 = { Empire, Production }; const keyframes = { fadeIn: { opacity: [0, 1] }, fadeOut: { opacity: [1, 0] } }; const options = { slow: { delay: 1_000, duration: 750 } }; function getHTML$6(data) { return `<div id="ic_exports-panel" class="ic_panel" data-state="collapsed"> <h3 class="ic_panel_title"><span></span>${ Translation.exports }</h3> <div class="ic_panel_main"> <form class="ic_form"> <fieldset> <label><input type="radio" name="format" value="bbcode" checked>${ Translation.textWithBBCode }</label> <label><input type="radio" name="format" value="text">${ Translation.plainText }</label> </fieldset> <fieldset> <button type="button" id="ic_empire-export-button" class="btn_blue ic_button">${ Translation.empire }</button> <button type="button" id="ic_production-export-button" class="btn_blue ic_button">${ Translation.production }</button> </fieldset> </form> <div id="ic_exports-notification">${ Translation.exportNotification }</div> </div> </div>`; } function setEvents$3() { document.body.querySelector('#ic_exports-panel form').addEventListener('click', function(event) { const { id } = event.target; if (id === 'ic_empire-export-button') { const result = Exports$1.Empire.get(Storage.get()); setExportToClipboard(result); } else if (id === 'ic_production-export-button') { const result = Exports$1.Production.get(Storage.get()); setExportToClipboard(result); } }); } function setExportToClipboard(text) { const { value } = document.querySelector('#ic_exports-panel [name=format]:checked'); if (value === 'text') { text = text.replace(/\[\/?[^\]]*\]/g, ''); } navigator.clipboard.writeText(text); animateNotification(); } async function animateNotification() { const form = document.querySelector('#ic_exports-panel form'); const notification = document.querySelector('#ic_exports-notification'); const { fadeIn, fadeOut } = keyframes; await form.animate(fadeOut, 250).finished; form.style.display = 'none'; notification.style.display = 'inline-flex'; await notification.animate(fadeIn, 500).finished; await notification.animate(fadeOut, options.slow).finished; notification.style.display = 'none'; form.style.display = 'flex'; form.animate(fadeIn, 250); } var Exports = { getHTML: getHTML$6, setEvents: setEvents$3 }; const root = `https://${ window.location.host }/game/index.php?`; function getHTML$5(data) { const { positions } = data.player; const { needed } = data.script; let result = ''; result += getLifeformResearchesHTML$1(needed); result += getProductionsHTML$1(needed); result += getMiscellaneousHTML(needed, positions); if (result) { result = `<div id="ic_needed-panel" class="ic_panel" data-state="expanded"> <h3 class="ic_panel_title"><span></span>${ Translation.neededData }</h3> <div class="ic_panel_main">${ result }</div> </div>`; } return result; } function getLifeformResearchesHTML$1(data) { let result = ''; if (data.lifeforms.researches.length) { const links = []; for (const [id, name] of data.lifeforms.researches) { links.push(`<a href="${ root }page=ingame&component=lfresearch&cp=${ id }">${ name }</a>`); } result = `<section><h4>${ Translation.lifeformResearches }</h4><p>${ links.join(', ') }.</p></section>`; } return result; } function getProductionsHTML$1(data) { let result = ''; if (data.productions.length) { const links = []; for (const [id, name] of data.productions) { links.push(`<a href="${ root }page=ingame&component=resourcesettings&cp=${ id }">${ name }</a>`); } result = `<section><h4>${ Translation.resourceSettings }</h4><p>${ links.join(', ') }.</p></section>`; } return result; } function getMiscellaneousHTML(data, positions) { const links = []; let result = ''; if (data.empire.planet) { links.push(`<a href="${ root }page=standalone&component=empire" target="_blank">${ Translation.empire } (${ Translation.planets })</a>`); } if (data.empire.moon) { links.push(`<a href="${ root }page=standalone&component=empire&planetType=1" target="_blank">${ Translation.empire } (${ Translation.moons })</a>`); } if (data.lifeforms.settings) { const id = getPlanetID(positions); links.push(`<a href="${ root }page=ingame&component=lfsettings&cp=${ id }">${ Translation.lifeformSettings }</a>`); // an planet id is needed because there is no lfsettings if player is on a moon } if (data.alliance) { links.push(`<a href="${ root }page=ingame&component=alliance">${ Translation.alliance }</a>`); } if (data.highscores) { links.push(`<a href="${ root }page=highscore&category=1">${ Translation.highscore }</a>`); } if (links.length) { result = `<section><h4>${ Translation.miscellaneous }</h4><p>${ links.join(', ') }.</p></section>`; } return result; } function getPlanetID(positions) { const type = document.querySelector('[name=ogame-planet-type]').content; if (type === 'moon') { const coordinates = document.querySelector('[name=ogame-planet-coordinates]').content; return positions[coordinates].planet.id; } else { return parseInt(document.querySelector('[name=ogame-planet-id]').content); } } var Needed = { getHTML: getHTML$5 }; function getHTML$4(data) { return `<div id="ic_positions-points-panel" class="ic_panel" data-state="collapsed"> <h3 class="ic_panel_title"><span></span>${ Translation.planetsPointsRepartition }</h3> <div class="ic_panel_main"> <table class="ic_table"> ${(function() { const { positions } = data.player; let result = ''; for (const coordinates in positions) { const position = positions[coordinates]; result += `<tr> <th>${ coordinates }</th> <td>${ getNamesHTML(position) }</td> <td>${ getMinesHTML(position) }</td> <td>${ getBuildingsHTML(position) }</td> <td>${ getLifeformBuildingsHTML(position) }</td> <td>${ getLifeformResearchesHTML(position) }</td> <td>${ getDefencesHTML(position) }</td> <td>${ getTotalHTML(position) }</td> </tr>`; } return result; })()} </table> </div> </div>`; } function getNamesHTML(position) { const { planet, moon } = position; let result = `<div>${ planet.name }</div>`; if (moon) { result += `<div>${ moon.name }</div>`; } return result; } function getMinesHTML(position) { const points = Shared.getNumberHTML(position.planet.points.values.mines.all); return `<div>${ points }</div>`; } function getBuildingsHTML(position) { const { planet, moon } = position; const points = Shared.getNumberHTML(planet.points.values.buildings.all); let result = `<div>${ points }</div>`; if (moon) { const points = Shared.getNumberHTML(moon.points.values.buildings.all); result += `<div>${ points }</div>`; } return result; } function getLifeformBuildingsHTML(position) { const points = Shared.getNumberHTML(position.planet.points.values.lifeforms.buildings); return `<div>${ points }</div>`; } function getLifeformResearchesHTML(position) { const points = Shared.getNumberHTML(position.planet.points.values.lifeforms.researches); return `<div>${ points }</div>`; } function getDefencesHTML(position) { const { planet, moon } = position; const points = Shared.getNumberHTML(planet.points.values.units.defences.all); let result = `<div>${ points }</div>`; if (moon) { const points = Shared.getNumberHTML(moon.points.values.units.defences.all); result += `<div>${ points }</div>`; } return result; } function getTotalHTML(position) { const { planet, moon } = position; const points = Shared.getNumberHTML(planet.points.values.statics); const percent = Types.getPercentString(planet.points.percents.statics); let result = `<div>${ points } — <span class="ic_percent">${ percent }</span></div>`; if (moon) { const points = Shared.getNumberHTML(moon.points.values.statics); const percent = Types.getPercentString(moon.points.percents.statics); result +=`<div>${ points } — <span class="ic_percent">${ percent }</span></div>`; } return result; } var Positions = { getHTML: getHTML$4 }; function getHTML$3(data) { return `<div id="ic_productions-panel" class="ic_panel" data-state="collapsed"> <h3 class="ic_panel_title"><span></span>${ Translation.dailyProductions }</h3> <div class="ic_panel_main"><table class="ic_table">${ getRowsHTML(data) }</table></div> </div>`; } function getRowsHTML(data) { const { basic, mines, fusion, lifeforms, crawlers, plasma, classes, premium, total } = data.player.productions; const { rates } = data.script; return `<tr><th>${ Translation.basicIncome }</th>${ getProductionsHTML(basic, total, rates) }</tr> <tr><th>${ Translation.mines }</th>${ getProductionsHTML(mines.total, total, rates) }</tr> <tr><th>${ Translation[12] }</th>${ getProductionsHTML(fusion, total, rates) }</tr> <tr><th>${ Translation.lifeforms }</th>${ getProductionsHTML(lifeforms, total, rates) }</tr> <tr><th>${ Translation[217] }</th>${ getProductionsHTML(crawlers, total, rates) }</tr> <tr><th>${ Translation[122] }</th>${ getProductionsHTML(plasma, total, rates) }</tr> <tr><th>${ Translation.classes }</th>${ getProductionsHTML(classes.total, total, rates) }</tr> <tr><th>${ Translation.premium }</th>${ getProductionsHTML(premium, total, rates) }</tr> <tr><th>${ Translation.total }</th>${ getProductionsHTML(total, total, rates) }</tr>`; } function getProductionsHTML(production, total, rates) { const dmp = production.metal * 24; const dmt = total.metal * 24; const dcp = production.crystal * 24; const dct = total.crystal * 24; const ddp = production.deuterium * 24; const ddt = total.deuterium * 24; const dtp = Resources.getTotal(production, rates) * 24; const dtt = Resources.getTotal(total, rates) * 24; return `<td><div>${ Shared.getNumberHTML(dmp) }</div><div>${ Types.getPercentString(dmp / dmt) }</div></td> <td><div>${ Shared.getNumberHTML(dcp) }</div><div>${ Types.getPercentString(dcp / dct) }</div></td> <td><div>${ Shared.getNumberHTML(ddp) }</div><div>${ Types.getPercentString(ddp / ddt) }</div></td> <td><div>${ Shared.getNumberHTML(dtp) }</div><div>${ Types.getPercentString(dtp / dtt) }</div></td>`; } var Productions = { getHTML: getHTML$3 }; var Panels = { Account, Amortizations: Amortizations$1, Exports, Needed, Positions, Productions, Shared }; function init$5(data) { if (currentPage === 'overview') { const { useCompactNumbers, placeAccountOverviewOnTop } = data.script; Panels.Shared.setCompactNumbers(useCompactNumbers); const template = document.createElement('template'); template.innerHTML = getHTML$2(data); if (placeAccountOverviewOnTop) { document.querySelector('#overviewcomponent').prepend(template.content); } else { document.querySelector('#middle').appendChild(template.content); } Panels.Shared.setCollapseStates(data); setEvents$2(); } } function getHTML$2(data) { const { placeAccountOverviewOnTop } = data.script; const positionClass = placeAccountOverviewOnTop && 'ic_top-box' || 'ic_bottom-box'; return `<div class="ic_box ${ positionClass }"> <h3 class="ic_box_title">${ Translation.accountOverview }</h3> ${ Panels.Needed.getHTML(data) } ${ Panels.Account.getHTML(data) } ${ Panels.Positions.getHTML(data) } ${ Panels.Productions.getHTML(data) } ${ Panels.Amortizations.getHTML(data) } ${ Panels.Exports.getHTML(data) } </div>`; } function setEvents$2() { Panels.Shared.setEvents(); Panels.Amortizations.setEvents(); Panels.Exports.setEvents(); } var OverviewBox = { init: init$5 }; function init$4(data) { const template = document.createElement('template'); template.innerHTML = getHTML$1(data); document.body.appendChild(template.content); setEvents$1(); } function getHTML$1(data) { const { form } = data.script.amortizations; return `<dialog id="ic_amortizations-panel_settings" class="ic_dialog"> <h1>${ Translation.amortizationsSettings }<span id="ic_amortizations-panel_close-button" class="ui-icon ui-icon-closethick"></span></h1> <form class="ic_form"> <fieldset> <legend>${ Translation.technologies }</legend> <label> <input type="checkbox" value="mines" ${ form.mines && 'checked' || '' }> ${ Translation.mines } </label> <label> <input type="checkbox" value="lifeformBuildings" ${ form.lifeformBuildings && 'checked' || '' }> ${ Translation.lifeformBuildings } </label> <label> <input type="checkbox" value="lifeformResearches" ${ form.lifeformResearches && 'checked' || '' }> ${ Translation.lifeformResearches } </label> <label> <input type="checkbox" value="plasma" ${ form.plasma && 'checked' || '' }> ${ Translation[122] } </label> <label> <input type="checkbox" value="astrophysics" ${ form.astrophysics && 'checked' || '' }> ${ Translation[124] } </label> </fieldset> <fieldset> <legend>${ Translation.planetsToIgnore }</legend> ${(function() { const { positions } = data.player; let result = ''; for (const coordinates in positions) { const { name } = positions[coordinates].planet; result += `<label><input type="checkbox" value="${ coordinates }" ${ form[coordinates] && 'checked' || '' }>${ name } [${ coordinates }]</label>`; } return result; })()} </fieldset> <fieldset> <legend>${ Translation.miscellaneous }</legend> <label> <input type="checkbox" value="useMaximumCrawlers" ${ form.useMaximumCrawlers && 'checked' || '' }> ${ Translation.useMaximumCrawlers } </label> <label> <input type="checkbox" value="useResourceBoosters" ${ form.useResourceBoosters && 'checked' || '' }> ${ Translation.useResourceBoosters } </label> </fieldset> </form> </dialog>`; } function setEvents$1() { setFormEvent$1(); setCloseEvent$1(); } function setFormEvent$1() { const dialog = document.body.querySelector('#ic_amortizations-panel_settings'); const form = dialog.querySelector('form'); dialog.addEventListener('close', function() { const data = Storage.get(); const { amortizations } = data.script; for (const { value, checked } of form.querySelectorAll('input')) { amortizations.form[value] = checked; } Storage.set(data); }); } function setCloseEvent$1() { document.body.addEventListener('click', function(event) { const { target } = event; const dialog = document.body.querySelector('#ic_amortizations-panel_settings'); if (target.id === 'ic_amortizations-panel_close-button' || target.contains(dialog)) { dialog.close(); } }); } var Amortizations = { init: init$4 }; function init$3(data) { const template = document.createElement('template'); template.innerHTML = getHTML(data); document.body.appendChild(template.content); setEvents(); } function getHTML(data) { const { colors, rates, useCompactNumbers, placeAccountOverviewOnTop } = data.script; return `<dialog id="ic_settings" class="ic_dialog"> <h1>${ Translation.settings }<span id="ic_settings_close-button" class="ui-icon ui-icon-closethick"></span></h1> <form class="ic_form"> <fieldset id="ic_settings_colors"> <legend>${ Translation.colors }</legend> ${(function() { let result = ''; for (const key in colors) { result += `<label>${ Translation[key] }<input type="color" value="${ colors[key] }" data-key="${ key }"></label>`; } return result; })()} </fieldset> <fieldset id="ic_settings_rates"> <legend>${ Translation.rates }</legend> <label>${ Translation.metal }<input type="number" value="${ rates.metal }" data-key="metal"></label> <label>${ Translation.crystal }<input type="number"value="${ rates.crystal }" data-key="crystal"></label> <label>${ Translation.deuterium }<input type="number" value="1" disabled></label> </fieldset> <fieldset id="ic_settings_standardUnit"> <legend>${ Translation.standardUnit }</legend> <label><input type="radio" name="standardUnit" value="metal" ${ rates.unit === 'metal' && 'checked' || '' }>${ Translation.metal }</label> <label><input type="radio" name="standardUnit" value="crystal" ${ rates.unit === 'crystal' && 'checked' || '' }>${ Translation.crystal }</label> <label><input type="radio" name="standardUnit" value="deuterium" ${ rates.unit === 'deuterium' && 'checked' || '' }>${ Translation.deuterium }</label> <label><input type="radio" name="standardUnit" value="points" ${ rates.unit === 'points' && 'checked' || '' }>${ Translation.points }</label> </fieldset> <fieldset> <legend>${ Translation.miscellaneous }</legend> <label><input type="checkbox" id="ic_settings_use-compact-numbers" ${ useCompactNumbers && 'checked' || '' }>${ Translation.useCompactNumbers }</label> <label><input type="checkbox" id="ic_settings_place-account-overview-on-top" ${ placeAccountOverviewOnTop && 'checked' || '' }>${ Translation.placeAccountOverviewOnTop }</label> </fieldset> </form> <button type="button" id="ic_settings_clear-button" class="btn_blue">${ Translation.clearAllData }</button> <div id="ic_support-links"> <div><a href="https://hero.li/OGame-The-Stubbs" target="_blank">${ Translation.gameforgeAffiliateLink}</a> 🔥</div> <div><a href="https://ko-fi.com/A0A4DEZRA" target="_blank">${ Translation.kofi }</a> ❤️</div> </div> </dialog>`; } function setEvents() { setFormEvent(); setResetEvent(); setCloseEvent(); } function setFormEvent() { const dialog = document.body.querySelector('#ic_settings'); const form = dialog.querySelector('form'); dialog.addEventListener('close', function() { const data = Storage.get(); const { script } = data; for (const { dataset, value } of form.querySelectorAll('#ic_settings_colors [type=color]')) { script.colors[dataset.key] = value; } for (const { dataset, value } of form.querySelectorAll('#ic_settings_rates [type=number]:not(:disabled)')) { script.rates[dataset.key] = parseFloat(value); } script.rates.unit = form.querySelector('#ic_settings_standardUnit [type=radio]:checked').value; script.useCompactNumbers = form.querySelector('#ic_settings_use-compact-numbers').checked; script.placeAccountOverviewOnTop = form.querySelector('#ic_settings_place-account-overview-on-top').checked; Storage.set(data); }); } function setResetEvent() { document.body.querySelector('#ic_settings_clear-button').addEventListener('click', function() { Storage.clear(); location.reload(); }); } function setCloseEvent() { document.body.addEventListener('click', function(event) { const { target } = event; const dialog = document.body.querySelector('#ic_settings'); if (target.id === 'ic_settings_close-button' || target.contains(dialog)) { dialog.close(); } }); } var Global = { init: init$3 }; function init$2(data) { if (currentPage !== 'empire') { Amortizations.init(data); Global.init(data); } } var Settings = { init: init$2 }; function init$1(data) { const result = get(data); GM_addStyle(result); } function get(data) { const { colors } = data.script; return `.ic_energy-warning { animation: pulse .5s ease-in-out infinite alternate; filter: sepia(100%) saturate(500%) brightness(75%) hue-rotate(270deg); } .ic_button { min-width: unset; } .ic_percent { display: inline-block; width: 48px; } .ic_table:first-child tr:nth-child(even) { background: #141e26; } .ic_table:not(:first-child) tr:nth-child(odd) { background: #141e26; } .ic_table :is(th, td) { padding: 6px; white-space: nowrap; } .ic_table :is(th, td) > div:not(:last-child) { margin-bottom: 6px; } .ic_form { display: flex; } .ic_form fieldset { display: flex; } .ic_form legend { color: #6f9fc8; font-weight: bold; margin-bottom: 8px; } .ic_form label { align-items: center; display: flex; } .ic_form label:has([type=checkbox], [type=radio]) { gap: 4px; } .ic_form input { margin: 0; } .ic_form [type=color] { background: none; border: none; padding: 0; width: 34px; height: 20px; } .ic_form [type=color]::-webkit-color-swatch-wrapper { padding: 0; } .ic_form [type=color]::-webkit-color-swatch { border: none; border-radius: 3px; } .ic_form [type=number] { -moz-appearance: textfield; background: #b3c3cb; border: 0; border-radius: 3px; padding: 2px 4px; text-align: center; width: 26px; } .ic_form [type=number]::-webkit-outer-spin-button, .ic_form [type=number]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; } .ic_form [type=number]:disabled { background: none; color: lightgrey; } .ic_form :is(label, input) { cursor: pointer; } .ic_dialog { background: url(//gf1.geo.gfsrv.net/cdnc8/a70be772b78f27691516fa29654cef.jpg) -100px -100px; border: 1px solid #1f2833; color: lightgrey; padding: 16px; } .ic_dialog::backdrop { background: rgb(0, 0, 0, .5); } .ic_dialog h1 { align-items: center; background: linear-gradient(to top, #3d4b5b 0%, #2b343f 49%, #1f262d 50%, #1f2934 100%); color: #6f9fc8; display: flex; font-weight: bold; justify-content: space-between; margin: -16px -16px 16px; padding: 8px 16px; } .ic_dialog form { flex-direction: column; gap: 16px; } .ic_dialog fieldset { flex-direction: column; gap: 4px; } .ic_dialog label:has([type=color], [type=number]) { gap: 8px; justify-content: space-between; } .ic_dialog .ui-icon { cursor: pointer; margin-left: 8px; } .ic_box { background: #0d1014; border: 2px solid black; box-sizing: border-box; color: lightgrey; line-height: 1; padding: 8px; position: relative; width: 654px; } .ic_box::before, .ic_box::after { content: ''; position: absolute; width: 668px; } .ic_box::before { background: url(//gf3.geo.gfsrv.net/cdn53/f333e15eb738b8ec692340f507e1ae.png) bottom left no-repeat, url(//gf2.geo.gfsrv.net/cdnd5/66551209db14e23b3001901b996cc6.png) bottom right no-repeat; height: 28px; left: -9px; top: -3px; } .ic_box::after { background: url(//gf3.geo.gfsrv.net/cdnea/0330abcdca0d125d35a0ebace4b584.png) bottom left no-repeat, url(//gf1.geo.gfsrv.net/cdn9b/8003a40825bc96919c5fec01b018b8.png) bottom right no-repeat; height: 50px; bottom: -4px; left: -9px; z-index: -1; } .ic_top-box { margin: 5px auto 5px auto; } .ic_bottom-box { margin-bottom: 24px; } .ic_box_title { background: url(//gf1.geo.gfsrv.net/cdnfb/a4e7913209228ebaf2297429aeb87b.png); color: #6f9fc8; font: bold 12px/27px Verdana,Arial,Helvetica,sans-serif; margin: -9px -8px 4px; text-align: center; position: relative; } .ic_box_title::before, .ic_box_title::after { content: ''; display: block; position: absolute; top: 0; width: 26px; height: 27px; } .ic_box_title::before { background: url(//gf2.geo.gfsrv.net/cdn4a/127bd495b9325216af08a588ecc540.png); left: 0; } .ic_box_title::after { background: url(//gf2.geo.gfsrv.net/cdn1d/80db96934a5b82ce002f839cd85a44.png); right: 0; } .ic_panel { padding: 1px 0; } .ic_panel_title { background-image: url(//gf3.geo.gfsrv.net/cdne1/d03835718066a5a592a6426736e019.png); color: #576472; cursor: pointer; font-weight: bold; line-height: 28px; overflow: hidden; padding-left: 35px; position: relative; } .ic_panel_title::after { background-image: url(//gf3.geo.gfsrv.net/cdne1/d03835718066a5a592a6426736e019.png); background-position: -21px -169px; content: ''; display: block; position: absolute; right: -2px; top: 1px; width: 10px; height: 26px; } .ic_panel_title:hover::after { background-position: -21px -196px; } .ic_panel_title:hover { background-position: 0 -28px; color: #6f9fc8; } .ic_panel_title > span { background-image: url(//gf3.geo.gfsrv.net/cdne1/d03835718066a5a592a6426736e019.png); left: -4px; position: absolute; width: 31px; height: 27px; } .ic_panel[data-state=collapsed] .ic_panel_main { display: none; } .ic_panel[data-state=expanded] .ic_panel_title > span { background-position: 0 -113px; } .ic_panel[data-state=expanded] .ic_panel_title:hover > span { background-position: 0 -141px; } .ic_panel[data-state=collapsed] .ic_panel_title > span { background-position: 0 -57px; } .ic_panel[data-state=collapsed] .ic_panel_title:hover > span { background-position: 0 -85px; } .ic_panel_main { background: #12171c; border: 1px solid black; display: flex; font-size: 11px; margin: 0 1px; } .ic_panel_main form { padding: 8px; } #overviewcomponent { margin-bottom: 0; } #ic_needed-panel .ic_panel_main { flex-direction: column; gap: 12px; padding: 8px; } #ic_needed-panel h4 { font-weight: bold; margin-bottom: 8px; } #ic_needed-panel p { line-height: 1.5; } #ic_account-points-panel th { text-align: left; } #ic_account-points-panel td:last-child { text-align: right; } #ic_account-points-panel tr:nth-child(8) > * { padding-bottom: 8px; } #ic_account-points-panel tr:nth-child(9) > * { border-top: 1px dotted rgb(128, 128, 128, .2); padding-top: 8px; } #ic_account-points-panel th::before { color: transparent; content: '\u2b24'; margin-right: 8px; } #ic_account-points-panel tr:nth-child(1) th::before { color: ${ colors.mines }; } #ic_account-points-panel tr:nth-child(2) th::before { color: ${ colors.planetBuildings }; } #ic_account-points-panel tr:nth-child(3) th::before { color: ${ colors.moonBuildings }; } #ic_account-points-panel tr:nth-child(4) th::before { color: ${ colors.lifeformBuildings }; } #ic_account-points-panel tr:nth-child(5) th::before { color: ${ colors.lifeformResearches }; } #ic_account-points-panel tr:nth-child(6) th::before { color: ${ colors.researches }; } #ic_account-points-panel tr:nth-child(7) th::before { color: ${ colors.ships }; } #ic_account-points-panel tr:nth-child(8) th::before { color: ${ colors.defences }; } #ic_account-points-panel svg { padding: 36px; } #ic_positions-points-panel table { width: 100%; } #ic_positions-points-panel tr { text-align: center; } #ic_positions-points-panel td { vertical-align: top; } #ic_positions-points-panel :is(th, td):nth-child(-n + 2) { text-align: left; width: 0; } #ic_positions-points-panel td:nth-child(3) { color: ${ colors.mines }; } #ic_positions-points-panel td:nth-child(4) { color: ${ colors.planetBuildings }; } #ic_positions-points-panel td:nth-child(4) div:nth-child(2) { color: ${ colors.moonBuildings }; } #ic_positions-points-panel td:nth-child(5) { color: ${ colors.lifeformBuildings }; } #ic_positions-points-panel td:nth-child(6) { color: ${ colors.lifeformResearches }; } #ic_positions-points-panel td:nth-child(7) { color: ${ colors.defences }; } #ic_positions-points-panel td:last-child { text-align: right; width: 0; } #ic_productions-panel table { width: 100%; } #ic_productions-panel tr > :first-child { text-align: left; } #ic_productions-panel td { text-align: right; } #ic_productions-panel td:nth-child(2) { color: ${ colors.metal }; } #ic_productions-panel td:nth-child(3) { color: ${ colors.crystal }; } #ic_productions-panel td:nth-child(4) { color: ${ colors.deuterium }; } #ic_amortizations-panel form { flex-direction: column; gap: 8px; } #ic_amortizations-panel fieldset { gap: 8px; justify-content: end; } #ic_amortizations-panel label:not(:last-child) { margin-bottom: 2px; } #ic_amortizations-panel table { text-align: center; } #ic_amortizations-panel td:nth-child(n + 4) div:first-child { color: ${ colors.metal }; } #ic_amortizations-panel td:nth-child(n + 4) div:nth-child(2) { color: ${ colors.crystal }; } #ic_amortizations-panel td:nth-child(n + 4) div:nth-child(3) { color: ${ colors.deuterium }; } #ic_amortizations-panel .ic_panel_main { flex-direction: column; } #ic_exports-panel .ic_panel_main { flex-direction: column; } #ic_exports-panel form { justify-content: space-between; } #ic_exports-panel fieldset { gap: 8px; } #ic_exports-notification { align-items: center; display: none; justify-content: center; padding: 8px; height: 27.6px; } #ic_menu_text { font-size: 10px; } #ic_menu_icon-wrapper { align-items: center; background: linear-gradient(to bottom, #1b2024 50%, #000 50%); border-radius: 4px; color: #353a3c; cursor: pointer; display: flex; justify-content: center; width: 27px; height: 27px; } #ic_menu_icon-wrapper:hover { color: #d39343; } #ic_settings button { display: block; margin: 24px auto 16px auto; } #ic_support-links { align-items: center; animation: 4s linear infinite alternate slide; background: linear-gradient(-45deg, #ee775242, #e73c7e42, #23a6d542, #23d5ab42); background-size: 300% 100%; display: flex; flex-direction: column; gap: 8px; margin: auto -16px -16px; padding: 12px; } #ic_support-links a { color: lightgrey; text-decoration-color: #d3d3d380; } @keyframes slide { to { background-position-x: 100%; } } @keyframes pulse { to { opacity: .2; } }`; } var Styles = { init: init$1 }; function init(data) { Settings.init(data); EnergyWarnings.init(data); MenuButton.init(data); Highscores.init(data); OverviewBox.init(data); Styles.init(data); } var Interface = { init }; const data = await Data.get(); Interface.init(data); Storage.set(data);