Greasy Fork is available in English.

HeroWarsHelper

Automation of actions for the game Hero Wars


Installer ce script?
  1. // ==UserScript==// @name HeroWarsHelper// @name:en HeroWarsHelper// @name:ru HeroWarsHelper// @namespace HeroWarsHelper// @version 2.333// @description Automation of actions for the game Hero Wars// @description:en Automation of actions for the game Hero Wars// @description:ru Автоматизация действий для игры Хроники Хаоса// @author ZingerY// @license Copyright ZingerY// @homepage https://zingery.ru/scripts/HeroWarsHelper.user.js// @icon https://zingery.ru/scripts/VaultBoyIco16.ico// @icon64 https://zingery.ru/scripts/VaultBoyIco64.png// @match https://www.hero-wars.com/*// @match https://apps-1701433570146040.apps.fbsbx.com/*// @run-at document-start// ==/UserScript==(function() {/*** Start script** Стартуем скрипт*/console.log('%cStart ' + GM_info.script.name + ', v' + GM_info.script.version + ' by ' + GM_info.script.author, 'color: red');/*** Script info** Информация о скрипте*/this.scriptInfo = (({name, version, author, homepage, lastModified}, updateUrl) =>({name, version, author, homepage, lastModified, updateUrl}))(GM_info.script, GM_info.scriptUpdateURL);this.GM_info = GM_info;/*** Information for completing daily quests** Информация для выполнения ежендевных квестов*/const questsInfo = {};/*** Is the game data loaded** Загружены ли данные игры*/let isLoadGame = false;/*** Headers of the last request** Заголовки последнего запроса*/let lastHeaders = {};/*** Information about sent gifts** Информация об отправленных подарках*/let freebieCheckInfo = null;/*** missionTimer** missionTimer*/let missionBattle = null;/*** User data** Данные пользователя*/let userInfo;this.isTimeBetweenNewDays = function () {if (userInfo.timeZone <= 3) {return false;}const nextDayTs = new Date(userInfo.nextDayTs * 1e3);const nextServerDayTs = new Date(userInfo.nextServerDayTs * 1e3);if (nextDayTs > nextServerDayTs) {nextDayTs.setDate(nextDayTs.getDate() - 1);}const now = Date.now();if (now > nextDayTs && now < nextServerDayTs) {return true;}return false;};function getUserInfo() {return userInfo;}/*** Original methods for working with AJAX** Оригинальные методы для работы с AJAX*/const original = {open: XMLHttpRequest.prototype.open,send: XMLHttpRequest.prototype.send,setRequestHeader: XMLHttpRequest.prototype.setRequestHeader,SendWebSocket: WebSocket.prototype.send,fetch: fetch,};// Sentry blocking// Блокировка наблюдателяthis.fetch = function (url, options) {/*** Checking URL for blocking* Проверяем URL на блокировку*/if (url.includes('sentry.io')) {console.log('%cFetch blocked', 'color: red');console.log(url, options);const body = {id: md5(Date.now()),};let info = {};try {info = JSON.parse(options.body);} catch (e) {}if (info.event_id) {body.id = info.event_id;}/*** Mock response for blocked URL** Мокаем ответ для заблокированного URL*/const mockResponse = new Response('Custom blocked response', {status: 200,headers: { 'Content-Type': 'application/json' },body,});return Promise.resolve(mockResponse);} else {/*** Call the original fetch function for all other URLs* Вызываем оригинальную функцию fetch для всех других URL*/return original.fetch.apply(this, arguments);}};/*** Decoder for converting byte data to JSON string** Декодер для перобразования байтовых данных в JSON строку*/const decoder = new TextDecoder("utf-8");/*** Stores a history of requests** Хранит историю запросов*/let requestHistory = {};/*** URL for API requests** URL для запросов к API*/let apiUrl = '';/*** Connecting to the game code** Подключение к коду игры*/this.cheats = new hackGame();/*** The function of calculating the r###lts of the battle** Функция расчета результатов боя*/this.BattleCalc = cheats.BattleCalc;/*** Sending a request available through the console** Отправка запроса доступная через консоль*/this.SendRequest = send;/*** Simple combat calculation available through the console** Простой расчет боя доступный через консоль*/this.Calc = function (data) {const type = getBattleType(data?.type);return new Promise((resolve, reject) => {try {BattleCalc(data, type, resolve);} catch (e) {reject(e);}})}/*** Short asynchronous request* Usage example (returns information about a character):* const userInfo = await Send('{"calls":[{"name":"userGetInfo","args":{},"ident":"body"}]}')** Короткий асинхронный запрос* Пример использования (возвращает информацию о персонаже):* const userInfo = await Send('{"calls":[{"name":"userGetInfo","args":{},"ident":"body"}]}')*/this.Send = function (json, pr) {return new Promise((resolve, reject) => {try {send(json, resolve, pr);} catch (e) {reject(e);}})}this.xyz = (({ name, version, author }) => ({ name, version, author }))(GM_info.script);const i18nLangData = {/* English translation by BaBa */en: {/* Checkboxes */SKIP_FIGHTS: 'Skip battle',SKIP_FIGHTS_TITLE: 'Skip battle in Outland and the arena of the titans, auto-pass in the tower and campaign',ENDLESS_CARDS: 'Infinite cards',ENDLESS_CARDS_TITLE: 'Disable Divination Cards wasting',AUTO_EXPEDITION: 'Auto Expedition',AUTO_EXPEDITION_TITLE: 'Auto-sending expeditions',CANCEL_FIGHT: 'Cancel battle',CANCEL_FIGHT_TITLE: 'Ability to cancel manual combat on GW, CoW and Asgard',GIFTS: 'Gifts',GIFTS_TITLE: 'Collect gifts automatically',BATTLE_RECALCULATION: 'Battle recalculation',BATTLE_RECALCULATION_TITLE: 'Preliminary calculation of the battle',QUANTITY_CONTROL: 'Quantity control',QUANTITY_CONTROL_TITLE: 'Ability to specify the number of opened "lootboxes"',REPEAT_CAMPAIGN: 'Repeat missions',REPEAT_CAMPAIGN_TITLE: 'Auto-repeat battles in the campaign',DISABLE_DONAT: 'Disable donation',DISABLE_DONAT_TITLE: 'Removes all donation offers',DAILY_QUESTS: 'Quests',DAILY_QUESTS_TITLE: 'Complete daily quests',AUTO_QUIZ: 'AutoQuiz',AUTO_QUIZ_TITLE: 'Automatically receive correct answers to quiz questions',SECRET_WEALTH_CHECKBOX: 'Automatic purchase in the store "Secret Wealth" when entering the game',HIDE_SERVERS: 'Collapse servers',HIDE_SERVERS_TITLE: 'Hide unused servers',/* Input fields */HOW_MUCH_TITANITE: 'How much titanite to farm',COMBAT_SPEED: 'Combat Speed Multiplier',NUMBER_OF_TEST: 'Number of test fights',NUMBER_OF_AUTO_BATTLE: 'Number of auto-battle attempts',/* Buttons */RUN_SCRIPT: 'Run the',TO_DO_EVERYTHING: 'Do All',TO_DO_EVERYTHING_TITLE: 'Perform multiple actions of your choice',OUTLAND: 'Outland',OUTLAND_TITLE: 'Collect Outland',TITAN_ARENA: 'ToE',TITAN_ARENA_TITLE: 'Complete the titan arena',DUNGEON: 'Dungeon',DUNGEON_TITLE: 'Go through the dungeon',SEER: 'Seer',SEER_TITLE: 'Roll the Seer',TOWER: 'Tower',TOWER_TITLE: 'Pass the tower',EXPEDITIONS: 'Expeditions',EXPEDITIONS_TITLE: 'Sending and collecting expeditions',SYNC: 'Sync',SYNC_TITLE: 'Partial synchronization of game data without reloading the page',ARCHDEMON: 'Archdemon',FURNACE_OF_SOULS: 'Furnace of souls',ARCHDEMON_TITLE: 'Hitting kills and collecting rewards',ESTER_EGGS: 'Easter eggs',ESTER_EGGS_TITLE: 'Collect all Easter eggs or rewards',REWARDS: 'Rewards',REWARDS_TITLE: 'Collect all quest rewards',MAIL: 'Mail',MAIL_TITLE: 'Collect all mail, except letters with energy and charges of the portal',MINIONS: 'Minions',MINIONS_TITLE: 'Attack minions with saved packs',ADVENTURE: 'Adv.',ADVENTURE_TITLE: 'Passes the adventure along the specified route',STORM: 'Storm',STORM_TITLE: 'Passes the Storm along the specified route',SANCTUARY: 'Sanctuary',SANCTUARY_TITLE: 'Fast travel to Sanctuary',GUILD_WAR: 'Guild War',GUILD_WAR_TITLE: 'Fast travel to Guild War',SECRET_WEALTH: 'Secret Wealth',SECRET_WEALTH_TITLE: 'Buy something in the store "Secret Wealth"',/* Misc */BOTTOM_URLS:'<a href="https://t.me/+0oMwICyV1aQ1MDAy" target="_blank" title="Telegram"><svg width="20" height="20" style="margin:2px" viewBox="0 0 1e3 1e3" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="a" x1="50%" x2="50%" y2="99.258%"><stop stop-color="#2AABEE" offset="0"/><stop stop-color="#229ED9" offset="1"/></linearGradient></defs><g fill-rule="evenodd"><circle cx="500" cy="500" r="500" fill="url(#a)"/><path d="m226.33 494.72c145.76-63.505 242.96-105.37 291.59-125.6 138.86-57.755 167.71-67.787 186.51-68.119 4.1362-0.072862 13.384 0.95221 19.375 5.8132 5.0584 4.1045 6.4501 9.6491 7.1161 13.541 0.666 3.8915 1.4953 12.756 0.83608 19.683-7.5246 79.062-40.084 270.92-56.648 359.47-7.0089 37.469-20.81 50.032-34.17 51.262-29.036 2.6719-51.085-19.189-79.207-37.624-44.007-28.847-68.867-46.804-111.58-74.953-49.366-32.531-17.364-50.411 10.769-79.631 7.3626-7.6471 135.3-124.01 137.77-134.57 0.30968-1.3202 0.59708-6.2414-2.3265-8.8399s-7.2385-1.7099-10.352-1.0032c-4.4137 1.0017-74.715 47.468-210.9 139.4-19.955 13.702-38.029 20.379-54.223 20.029-17.853-0.3857-52.194-10.094-77.723-18.393-31.313-10.178-56.199-15.56-54.032-32.846 1.1287-9.0037 13.528-18.212 37.197-27.624z" fill="#fff"/></g></svg></a><a href="https://www.patreon.com/HeroWarsUserScripts" target="_blank" title="Patreon"><svg width="20" height="20" viewBox="0 0 1080 1080" xmlns="http://www.w3.org/2000/svg"><g fill="#FFF" stroke="None"><path d="m1033 324.45c-0.19-137.9-107.59-250.92-233.6-291.7-156.48-50.64-362.86-43.3-512.28 27.2-181.1 85.46-237.99 272.66-240.11 459.36-1.74 153.5 13.58 557.79 241.62 560.67 169.44 2.15 194.67-216.18 273.07-321.33 55.78-74.81 127.6-95.94 216.01-117.82 151.95-37.61 255.51-157.53 255.29-316.38z"/></g></svg></a>',GIFTS_SENT: 'Gifts sent!',DO_YOU_WANT: 'Do you really want to do this?',BTN_RUN: 'Run',BTN_CANCEL: 'Cancel',BTN_ACCEPT: 'Accept',BTN_OK: 'OK',MSG_HAVE_BEEN_DEFEATED: 'You have been defeated!',BTN_AUTO: 'Auto',MSG_YOU_APPLIED: 'You applied',MSG_DAMAGE: 'damage',MSG_CANCEL_AND_STAT: 'Auto (F5) and show statistic',MSG_REPEAT_MISSION: 'Repeat the mission?',BTN_REPEAT: 'Repeat',BTN_NO: 'No',MSG_SPECIFY_QUANT: 'Specify Quantity:',BTN_OPEN: 'Open',QUESTION_COPY: 'Question copied to clipboard',ANSWER_KNOWN: 'The answer is known',ANSWER_NOT_KNOWN: 'ATTENTION THE ANSWER IS NOT KNOWN',BEING_RECALC: 'The battle is being recalculated',THIS_TIME: 'This time',VICTORY: '<span style="color:green;">VICTORY</span>',DEFEAT: '<span style="color:red;">DEFEAT</span>',CHANCE_TO_WIN: 'Chance to win <span style="color: red;">based on pre-calculation</span>',OPEN_DOLLS: 'nesting dolls recursively',SENT_QUESTION: 'Question sent',SETTINGS: 'Settings',MSG_BAN_ATTENTION: '<p style="color:red;">Using this feature may r###lt in a ban.</p> Continue?',BTN_YES_I_AGREE: 'Yes, I understand the risks!',BTN_NO_I_AM_AGAINST: 'No, I refuse it!',VALUES: 'Values',EXPEDITIONS_SENT: 'Expeditions:<br>Collected: {countGet}<br>Sent: {countSend}',EXPEDITIONS_NOTHING: 'Nothing to collect/send',EXPEDITIONS_NOTTIME: 'It is not time for expeditions',TITANIT: 'Titanit',COMPLETED: 'completed',FLOOR: 'Floor',LEVEL: 'Level',BATTLES: 'battles',EVENT: 'Event',NOT_AVAILABLE: 'not available',NO_HEROES: 'No heroes',DAMAGE_AMOUNT: 'Damage amount',NOTHING_TO_COLLECT: 'Nothing to collect',COLLECTED: 'Collected',REWARD: 'rewards',REMAINING_ATTEMPTS: 'Remaining attempts',BATTLES_CANCELED: 'Battles canceled',MINION_RAID: 'Minion Raid',STOPPED: 'Stopped',REPETITIONS: 'Repetitions',MISSIONS_PASSED: 'Missions passed',STOP: 'stop',TOTAL_OPEN: 'Total open',OPEN: 'Open',ROUND_STAT: 'Damage statistics for ',BATTLE: 'battles',MINIMUM: 'Minimum',MAXIMUM: 'Maximum',AVERAGE: 'Average',NOT_THIS_TIME: 'Not this time',RETRY_LIMIT_EXCEEDED: 'Retry limit exceeded',SUCCESS: 'Success',RECEIVED: 'Received',LETTERS: 'letters',PORTALS: 'portals',ATTEMPTS: 'attempts',/* Quests */QUEST_10001: 'Upgrade the skills of heroes 3 times',QUEST_10002: 'Complete 10 missions',QUEST_10003: 'Complete 3 heroic missions',QUEST_10004: 'Fight 3 times in the Arena or Grand Arena',QUEST_10006: 'Use the exchange of emeralds 1 time',QUEST_10007: 'Perform 1 summon in the Solu Atrium',QUEST_10016: 'Send gifts to guildmates',QUEST_10018: 'Use an experience potion',QUEST_10019: 'Open 1 chest in the Tower',QUEST_10020: 'Open 3 chests in Outland',QUEST_10021: 'Collect 75 Titanite in the Guild Dungeon',QUEST_10021: 'Collect 150 Titanite in the Guild Dungeon',QUEST_10023: 'Upgrade Gift of the Elements by 1 level',QUEST_10024: 'Level up any artifact once',QUEST_10025: 'Start Expedition 1',QUEST_10026: 'Start 4 Expeditions',QUEST_10027: 'Win 1 battle of the Tournament of Elements',QUEST_10028: 'Level up any titan artifact',QUEST_10029: 'Unlock the Orb of Titan Artifacts',QUEST_10030: 'Upgrade any Skin of any hero 1 time',QUEST_10031: 'Win 6 battles of the Tournament of Elements',QUEST_10043: 'Start or Join an Adventure',QUEST_10044: 'Use Summon Pets 1 time',QUEST_10046: 'Open 3 chests in Adventure',QUEST_10047: 'Get 150 Guild Activity Points',NOTHING_TO_DO: 'Nothing to do',YOU_CAN_COMPLETE: 'You can complete quests',BTN_DO_IT: 'Do it',NOT_QUEST_COMPLETED: 'Not a single quest completed',COMPLETED_QUESTS: 'Completed quests',/* everything button */ASSEMBLE_OUTLAND: 'Assemble Outland',PASS_THE_TOWER: 'Pass the tower',CHECK_EXPEDITIONS: 'Check Expeditions',COMPLETE_TOE: 'Complete ToE',COMPLETE_DUNGEON: 'Complete the dungeon',COLLECT_MAIL: 'Collect mail',COLLECT_MISC: 'Collect some bullshit',COLLECT_MISC_TITLE: 'Collect Easter Eggs, Skin Gems, Keys, Arena Coins and Soul Crystal',COLLECT_QUEST_REWARDS: 'Collect quest rewards',MAKE_A_SYNC: 'Make a sync',RUN_FUNCTION: 'Run the following functions?',BTN_GO: 'Go!',PERFORMED: 'Performed',DONE: 'Done',ERRORS_OCCURRES: 'Errors occurred while executing',COPY_ERROR: 'Copy error information to clipboard',BTN_YES: 'Yes',ALL_TASK_COMPLETED: 'All tasks completed',UNKNOWN: 'unknown',ENTER_THE_PATH: 'Enter the path of adventure using commas or dashes',START_ADVENTURE: 'Start your adventure along this path!',INCORRECT_WAY: 'Incorrect path in adventure: {from} -> {to}',BTN_CANCELED: 'Canceled',MUST_TWO_POINTS: 'The path must contain at least 2 points.',MUST_ONLY_NUMBERS: 'The path must contain only numbers and commas',NOT_ON_AN_ADVENTURE: 'You are not on an adventure',YOU_IN_NOT_ON_THE_WAY: 'Your location is not on the way',ATTEMPTS_NOT_ENOUGH: 'Your attempts are not enough to complete the path, continue?',YES_CONTINUE: 'Yes, continue!',NOT_ENOUGH_AP: 'Not enough action points',ATTEMPTS_ARE_OVER: 'The attempts are over',MOVES: 'Moves',BUFF_GET_ERROR: 'Buff getting error',BATTLE_END_ERROR: 'Battle end error',AUTOBOT: 'Autobot',FAILED_TO_WIN_AUTO: 'Failed to win the auto battle',ERROR_OF_THE_BATTLE_COPY: 'An error occurred during the passage of the battle<br>Copy the error to the clipboard?',ERROR_DURING_THE_BATTLE: 'Error during the battle',NO_CHANCE_WIN: 'No chance of winning this fight: 0/',LOST_HEROES: 'You have won, but you have lost one or several heroes',VICTORY_IMPOSSIBLE: 'Is victory impossible, should we focus on the r###lt?',FIND_COEFF: 'Find the coefficient greater than',BTN_PASS: 'PASS',BRAWLS: 'Brawls',BRAWLS_TITLE: 'Activates the ability to auto-brawl',START_AUTO_BRAWLS: 'Start Auto Brawls?',LOSSES: 'Losses',WINS: 'Wins',FIGHTS: 'Fights',STAGE: 'Stage',DONT_HAVE_LIVES: "You don't have lives",LIVES: 'Lives',SECRET_WEALTH_ALREADY: 'Item for Pet Potions already purchased',SECRET_WEALTH_NOT_ENOUGH: 'Not Enough Pet Potion, You Have {available}, Need {need}',SECRET_WEALTH_UPGRADE_NEW_PET: 'After purchasing the Pet Potion, it will not be enough to upgrade a new pet',SECRET_WEALTH_PURCHASED: 'Purchased {count} {name}',SECRET_WEALTH_CANCELED: 'Secret Wealth: Purchase Canceled',SECRET_WEALTH_BUY: 'You have {available} Pet Potion.<br>Do you want to buy {countBuy} {name} for {price} Pet Potion?',DAILY_BONUS: 'Daily bonus',DO_DAILY_QUESTS: 'Do daily quests',ACTIONS: 'Actions',ACTIONS_TITLE: 'Dialog box with various actions',OTHERS: 'Others',OTHERS_TITLE: 'Others',CHOOSE_ACTION: 'Choose an action',OPEN_LOOTBOX: 'You have {lootBox} boxes, should we open them?',STAMINA: 'Energy',BOXES_OVER: 'The boxes are over',NO_BOXES: 'No boxes',NO_MORE_ACTIVITY: 'No more activity for items today',EXCHANGE_ITEMS: 'Exchange items for activity points (max {maxActive})?',GET_ACTIVITY: 'Get Activity',NOT_ENOUGH_ITEMS: 'Not enough items',ACTIVITY_RECEIVED: 'Activity received',NO_PURCHASABLE_HERO_SOULS: 'No purchasable Hero Souls',PURCHASED_HERO_SOULS: 'Purchased {countHeroSouls} Hero Souls',NOT_ENOUGH_EMERALDS_540: 'Not enough emeralds, you need {imgEmerald}540 you have {imgEmerald}{currentStarMoney}',BUY_OUTLAND_BTN: 'Buy {count} chests {imgEmerald}{countEmerald}',CHESTS_NOT_AVAILABLE: 'Chests not available',OUTLAND_CHESTS_RECEIVED: 'Outland chests received',RAID_NOT_AVAILABLE: 'The raid is not available or there are no spheres',RAID_ADVENTURE: 'Raid {adventureId} adventure!',SOMETHING_WENT_WRONG: 'Something went wrong',ADVENTURE_COMPLETED: 'Adventure {adventureId} completed {times} times',CLAN_STAT_COPY: 'Clan statistics copied to clipboard',GET_ENERGY: 'Get Energy',GET_ENERGY_TITLE: 'Opens platinum boxes one at a time until you get 250 energy',ITEM_EXCHANGE: 'Item Exchange',ITEM_EXCHANGE_TITLE: 'Exchanges items for the specified amount of activity',BUY_SOULS: 'Buy souls',BUY_SOULS_TITLE: 'Buy hero souls from all available shops',BUY_OUTLAND: 'Buy Outland',BUY_OUTLAND_TITLE: 'Buy 9 chests in Outland for 540 emeralds',RAID: 'Raid',AUTO_RAID_ADVENTURE: 'Raid',AUTO_RAID_ADVENTURE_TITLE: 'Raid adventure set number of times',CLAN_STAT: 'Clan statistics',CLAN_STAT_TITLE: 'Copies clan statistics to the clipboard',BTN_AUTO_F5: 'Auto (F5)',BOSS_DAMAGE: 'Boss Damage: ',NOTHING_BUY: 'Nothing to buy',LOTS_BOUGHT: '{countBuy} lots bought for gold',BUY_FOR_GOLD: 'Buy for gold',BUY_FOR_GOLD_TITLE: 'Buy items for gold in the Town Shop and in the Pet Soul Stone Shop',REWARDS_AND_MAIL: 'Rewards and Mail',REWARDS_AND_MAIL_TITLE: 'Collects rewards and mail',COLLECT_REWARDS_AND_MAIL: 'Collected {countQuests} rewards and {countMail} letters',TIMER_ALREADY: 'Timer already started {time}',NO_ATTEMPTS_TIMER_START: 'No attempts, timer started {time}',EPIC_BRAWL_R###LT: 'Wins: {wins}/{attempts}, Coins: {coins}, Streak: {progress}/{nextStage} [Close]{end}',ATTEMPT_ENDED: '<br>Attempts ended, timer started {time}',EPIC_BRAWL: 'Cosmic Battle',EPIC_BRAWL_TITLE: 'Spends attempts in the Cosmic Battle',RELOAD_GAME: 'Reload game',TIMER: 'Timer:',SHOW_ERRORS: 'Show errors',SHOW_ERRORS_TITLE: 'Show server request errors',ERROR_MSG: 'Error: {name}<br>{description}',EVENT_AUTO_BOSS:'Maximum number of battles for calculation:</br>{length} ∗ {countTestBattle} = {maxCalcBattle}</br>If you have a weak computer, it may take a long time for this, click on the cross to cancel.</br>Should I search for the best pack from all or the first suitable one?',BEST_SLOW: 'Best (slower)',FIRST_FAST: 'First (faster)',FREEZE_INTERFACE: 'Calculating... <br>The interface may freeze.',ERROR_F12: 'Error, details in the console (F12)',FAILED_FIND_WIN_PACK: 'Failed to find a winning pack',BEST_PACK: 'Best pack:',BOSS_HAS_BEEN_DEF: 'Boss {bossLvl} has been defeated.',NOT_ENOUGH_ATTEMPTS_BOSS: 'Not enough attempts to defeat boss {bossLvl}, retry?',BOSS_VICTORY_IMPOSSIBLE:'Based on the recalculation of {battles} battles, victory has not been achieved. Would you like to continue the search for a winning battle in real battles?',BOSS_HAS_BEEN_DEF_TEXT:'Boss {bossLvl} defeated in<br>{countBattle}/{countMaxBattle} attempts{winTimer}<br>(Please synchronize or restart the game to update the data)',MAP: 'Map: ',PLAYER_POS: 'Player positions:',NY_GIFTS: 'Gifts',NY_GIFTS_TITLE: "Open all New Year's gifts",NY_NO_GIFTS: 'No gifts not received',NY_GIFTS_COLLECTED: '{count} gifts collected',CHANGE_MAP: 'Island map',CHANGE_MAP_TITLE: 'Change island map',SELECT_ISLAND_MAP: 'Select an island map:',MAP_NUM: 'Map {num}',SECRET_WEALTH_SHOP: 'Secret Wealth {name}: ',SHOPS: 'Shops',SHOPS_DEFAULT: 'Default',SHOPS_DEFAULT_TITLE: 'Default stores',SHOPS_LIST: 'Shops {number}',SHOPS_LIST_TITLE: 'List of shops {number}',SHOPS_WARNING:'Stores<br><span style="color:red">If you buy brawl store coins for emeralds, you must use them immediately, otherwise they will disappear after restarting the game!</span>',MINIONS_WARNING: 'The hero packs for attacking minions are incomplete, should I continue?',FAST_SEASON: 'Fast season',FAST_SEASON_TITLE: 'Skip the map selection screen in a season',SET_NUMBER_LEVELS: 'Specify the number of levels:',POSSIBLE_IMPROVE_LEVELS: 'It is possible to improve only {count} levels.<br>Improving?',NOT_ENOUGH_RESOURECES: 'Not enough resources',IMPROVED_LEVELS: 'Improved levels: {count}',ARTIFACTS_UPGRADE: 'Artifacts Upgrade',ARTIFACTS_UPGRADE_TITLE: 'Upgrades the specified amount of the cheapest hero artifacts',SKINS_UPGRADE: 'Skins Upgrade',SKINS_UPGRADE_TITLE: 'Upgrades the specified amount of the cheapest hero skins',HINT: '<br>Hint: ',PICTURE: '<br>Picture: ',ANSWER: '<br>Answer: ',NO_HEROES_PACK: 'Fight at least one battle to save the attacking team',BRAWL_AUTO_PACK: 'Automatic selection of packs',BRAWL_AUTO_PACK_NOT_CUR_HERO: 'Automatic pack selection is not suitable for the current hero',BRAWL_DAILY_TASK_COMPLETED: 'Daily task completed, continue attacking?',CALC_STAT: 'Calculate statistics',ELEMENT_TOURNAMENT_REWARD: 'Unclaimed bonus for Elemental Tournament',BTN_TRY_FIX_IT: 'Fix it',BTN_TRY_FIX_IT_TITLE: 'Enable auto attack combat correction',DAMAGE_FIXED: 'Damage fixed from {lastDamage} to {maxDamage}!',DAMAGE_NO_FIXED: 'Failed to fix damage: {lastDamage}',LETS_FIX: "Let's fix",COUNT_FIXED: 'For {count} attempts',DEFEAT_TURN_TIMER: 'Defeat! Turn on the timer to complete the mission?',SEASON_REWARD: 'Season Rewards',SEASON_REWARD_TITLE: 'Collects available free rewards from all current seasons',SEASON_REWARD_COLLECTED: 'Collected {count} season rewards',SELL_HERO_SOULS: 'Sell ​​souls',SELL_HERO_SOULS_TITLE: 'Exchanges all absolute star hero souls for gold',GOLD_RECEIVED: 'Gold received: {gold}',OPEN_ALL_EQUIP_BOXES: 'Open all Equipment Fragment Box?',SERVER_NOT_ACCEPT: 'The server did not accept the r###lt',INVASION_BOSS_BUFF: 'For {bossLvl} boss need buff {needBuff} you have {haveBuff}}',HERO_POWER: 'Hero Power',HERO_POWER_TITLE: 'Displays the current and maximum power of heroes',MAX_POWER_REACHED: 'Maximum power reached: {power}',CURRENT_POWER: 'Current power: {power}',POWER_TO_MAX: 'Power left to reach maximum: <span style="color:{color};">{power}</span><br>',BEST_R###LT: 'Best r###lt: {value}%',GUILD_ISLAND_TITLE: 'Fast travel to Guild Island',TITAN_VALLEY_TITLE: 'Fast travel to Titan Valley',},ru: {/* Чекбоксы */SKIP_FIGHTS: 'Пропуск боев',SKIP_FIGHTS_TITLE: 'Пропуск боев в запределье и арене титанов, автопропуск в башне и кампании',ENDLESS_CARDS: 'Бесконечные карты',ENDLESS_CARDS_TITLE: 'Отключить трату карт предсказаний',AUTO_EXPEDITION: 'АвтоЭкспедиции',AUTO_EXPEDITION_TITLE: 'Автоотправка экспедиций',CANCEL_FIGHT: 'Отмена боя',CANCEL_FIGHT_TITLE: 'Возможность отмены ручного боя на ВГ, СМ и в Асгарде',GIFTS: 'Подарки',GIFTS_TITLE: 'Собирать подарки автоматически',BATTLE_RECALCULATION: 'Прерасчет боя',BATTLE_RECALCULATION_TITLE: 'Предварительный расчет боя',QUANTITY_CONTROL: 'Контроль кол-ва',QUANTITY_CONTROL_TITLE: 'Возможность указывать количество открываемых "лутбоксов"',REPEAT_CAMPAIGN: 'Повтор в кампании',REPEAT_CAMPAIGN_TITLE: 'Автоповтор боев в кампании',DISABLE_DONAT: 'Отключить донат',DISABLE_DONAT_TITLE: 'Убирает все предложения доната',DAILY_QUESTS: 'Квесты',DAILY_QUESTS_TITLE: 'Выполнять ежедневные квесты',AUTO_QUIZ: 'АвтоВикторина',AUTO_QUIZ_TITLE: 'Автоматическое получение правильных ответов на вопросы викторины',SECRET_WEALTH_CHECKBOX: 'Автоматическая покупка в магазине "Тайное Богатство" при заходе в игру',HIDE_SERVERS: 'Свернуть сервера',HIDE_SERVERS_TITLE: 'Скрывать неиспользуемые сервера',/* Поля ввода */HOW_MUCH_TITANITE: 'Сколько фармим титанита',COMBAT_SPEED: 'Множитель ускорения боя',NUMBER_OF_TEST: 'Количество тестовых боев',NUMBER_OF_AUTO_BATTLE: 'Количество попыток автобоев',/* Кнопки */RUN_SCRIPT: 'Запустить скрипт',TO_DO_EVERYTHING: 'Сделать все',TO_DO_EVERYTHING_TITLE: 'Выполнить несколько действий',OUTLAND: 'Запределье',OUTLAND_TITLE: 'Собрать Запределье',TITAN_ARENA: 'Турн.Стихий',TITAN_ARENA_TITLE: 'Автопрохождение Турнира Стихий',DUNGEON: 'Подземелье',DUNGEON_TITLE: 'Автопрохождение подземелья',SEER: 'Провидец',SEER_TITLE: 'Покрутить Провидца',TOWER: 'Башня',TOWER_TITLE: 'Автопрохождение башни',EXPEDITIONS: 'Экспедиции',EXPEDITIONS_TITLE: 'Отправка и сбор экспедиций',SYNC: 'Синхронизация',SYNC_TITLE: 'Частичная синхронизация данных игры без перезагрузки сатраницы',ARCHDEMON: 'Архидемон',FURNACE_OF_SOULS: 'Горнило душ',ARCHDEMON_TITLE: 'Набивает килы и собирает награду',ESTER_EGGS: 'Пасхалки',ESTER_EGGS_TITLE: 'Собрать все пасхалки или награды',REWARDS: 'Награды',REWARDS_TITLE: 'Собрать все награды за задания',MAIL: 'Почта',MAIL_TITLE: 'Собрать всю почту, кроме писем с энергией и зарядами портала',MINIONS: 'Прислужники',MINIONS_TITLE: 'Атакует прислужников сохраннеными пачками',ADVENTURE: 'Прикл',ADVENTURE_TITLE: 'Проходит приключение по указанному маршруту',STORM: 'Буря',STORM_TITLE: 'Проходит бурю по указанному маршруту',SANCTUARY: 'Святилище',SANCTUARY_TITLE: 'Быстрый переход к Святилищу',GUILD_WAR: 'Война гильдий',GUILD_WAR_TITLE: 'Быстрый переход к Войне гильдий',SECRET_WEALTH: 'Тайное богатство',SECRET_WEALTH_TITLE: 'Купить что-то в магазине "Тайное богатство"',/* Разное */BOTTOM_URLS:'<a href="https://t.me/+q6gAGCRpwyFkNTYy" target="_blank" title="Telegram"><svg width="20" height="20" style="margin:2px" viewBox="0 0 1e3 1e3" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="a" x1="50%" x2="50%" y2="99.258%"><stop stop-color="#2AABEE" offset="0"/><stop stop-color="#229ED9" offset="1"/></linearGradient></defs><g fill-rule="evenodd"><circle cx="500" cy="500" r="500" fill="url(#a)"/><path d="m226.33 494.72c145.76-63.505 242.96-105.37 291.59-125.6 138.86-57.755 167.71-67.787 186.51-68.119 4.1362-0.072862 13.384 0.95221 19.375 5.8132 5.0584 4.1045 6.4501 9.6491 7.1161 13.541 0.666 3.8915 1.4953 12.756 0.83608 19.683-7.5246 79.062-40.084 270.92-56.648 359.47-7.0089 37.469-20.81 50.032-34.17 51.262-29.036 2.6719-51.085-19.189-79.207-37.624-44.007-28.847-68.867-46.804-111.58-74.953-49.366-32.531-17.364-50.411 10.769-79.631 7.3626-7.6471 135.3-124.01 137.77-134.57 0.30968-1.3202 0.59708-6.2414-2.3265-8.8399s-7.2385-1.7099-10.352-1.0032c-4.4137 1.0017-74.715 47.468-210.9 139.4-19.955 13.702-38.029 20.379-54.223 20.029-17.853-0.3857-52.194-10.094-77.723-18.393-31.313-10.178-56.199-15.56-54.032-32.846 1.1287-9.0037 13.528-18.212 37.197-27.624z" fill="#fff"/></g></svg></a><a href="https://vk.com/invite/YNPxKGX" target="_blank" title="Вконтакте"><svg width="20" height="20" style="margin:2px" viewBox="0 0 101 100" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)"><path d="M0.5 48C0.5 25.3726 0.5 14.0589 7.52944 7.02944C14.5589 0 25.8726 0 48.5 0H52.5C75.1274 0 86.4411 0 93.4706 7.02944C100.5 14.0589 100.5 25.3726 100.5 48V52C100.5 74.6274 100.5 85.9411 93.4706 92.9706C86.4411 100 75.1274 100 52.5 100H48.5C25.8726 100 14.5589 100 7.52944 92.9706C0.5 85.9411 0.5 74.6274 0.5 52V48Z" fill="#07f"/><path d="m53.708 72.042c-22.792 0-35.792-15.625-36.333-41.625h11.417c0.375 19.083 8.7915 27.167 15.458 28.833v-28.833h10.75v16.458c6.5833-0.7083 13.499-8.2082 15.832-16.458h10.75c-1.7917 10.167-9.2917 17.667-14.625 20.75 5.3333 2.5 13.875 9.0417 17.125 20.875h-11.834c-2.5417-7.9167-8.8745-14.042-17.25-14.875v14.875h-1.2919z" fill="#fff"/></g><defs><clipPath id="a"><rect transform="translate(.5)" width="100" height="100" fill="#fff"/></clipPath></defs></svg></a>',GIFTS_SENT: 'Подарки отправлены!',DO_YOU_WANT: 'Вы действительно хотите это сделать?',BTN_RUN: 'Запускай',BTN_CANCEL: 'Отмена',BTN_ACCEPT: 'Принять',BTN_OK: 'Ок',MSG_HAVE_BEEN_DEFEATED: 'Вы потерпели поражение!',BTN_AUTO: 'Авто',MSG_YOU_APPLIED: 'Вы нанесли',MSG_DAMAGE: 'урона',MSG_CANCEL_AND_STAT: 'Авто (F5) и показать Статистику',MSG_REPEAT_MISSION: 'Повторить миссию?',BTN_REPEAT: 'Повторить',BTN_NO: 'Нет',MSG_SPECIFY_QUANT: 'Указать количество:',BTN_OPEN: 'Открыть',QUESTION_COPY: 'Вопрос скопирован в буфер обмена',ANSWER_KNOWN: 'Ответ известен',ANSWER_NOT_KNOWN: 'ВНИМАНИЕ ОТВЕТ НЕ ИЗВЕСТЕН',BEING_RECALC: 'Идет прерасчет боя',THIS_TIME: 'На этот раз',VICTORY: '<span style="color:green;">ПОБЕДА</span>',DEFEAT: '<span style="color:red;">ПОРАЖЕНИЕ</span>',CHANCE_TO_WIN: 'Шансы на победу <span style="color:red;">на основе прерасчета</span>',OPEN_DOLLS: 'матрешек рекурсивно',SENT_QUESTION: 'Вопрос отправлен',SETTINGS: 'Настройки',MSG_BAN_ATTENTION: '<p style="color:red;">Использование этой функции может привести к бану.</p> Продолжить?',BTN_YES_I_AGREE: 'Да, я беру на себя все риски!',BTN_NO_I_AM_AGAINST: 'Нет, я отказываюсь от этого!',VALUES: 'Значения',EXPEDITIONS_SENT: 'Экспедиции:<br>Собрано: {countGet}<br>Отправлено: {countSend}',EXPEDITIONS_NOTHING: 'Нечего собирать/отправлять',EXPEDITIONS_NOTTIME: 'Не время для экспедиций',TITANIT: 'Титанит',COMPLETED: 'завершено',FLOOR: 'Этаж',LEVEL: 'Уровень',BATTLES: 'бои',EVENT: 'Эвент',NOT_AVAILABLE: 'недоступен',NO_HEROES: 'Нет героев',DAMAGE_AMOUNT: 'Количество урона',NOTHING_TO_COLLECT: 'Нечего собирать',COLLECTED: 'Собрано',REWARD: 'наград',REMAINING_ATTEMPTS: 'Осталось попыток',BATTLES_CANCELED: 'Битв отменено',MINION_RAID: 'Рейд прислужников',STOPPED: 'Остановлено',REPETITIONS: 'Повторений',MISSIONS_PASSED: 'Миссий пройдено',STOP: 'остановить',TOTAL_OPEN: 'Всего открыто',OPEN: 'Открыто',ROUND_STAT: 'Статистика урона за',BATTLE: 'боев',MINIMUM: 'Минимальный',MAXIMUM: 'Максимальный',AVERAGE: 'Средний',NOT_THIS_TIME: 'Не в этот раз',RETRY_LIMIT_EXCEEDED: 'Превышен лимит попыток',SUCCESS: 'Успех',RECEIVED: 'Получено',LETTERS: 'писем',PORTALS: 'порталов',ATTEMPTS: 'попыток',QUEST_10001: 'Улучши умения героев 3 раза',QUEST_10002: 'Пройди 10 миссий',QUEST_10003: 'Пройди 3 героические миссии',QUEST_10004: 'Сразись 3 раза на Арене или Гранд Арене',QUEST_10006: 'Используй обмен изумрудов 1 раз',QUEST_10007: 'Соверши 1 призыв в Атриуме Душ',QUEST_10016: 'Отправь подарки согильдийцам',QUEST_10018: 'Используй зелье опыта',QUEST_10019: 'Открой 1 сундук в Башне',QUEST_10020: 'Открой 3 сундука в Запределье',QUEST_10021: 'Собери 75 Титанита в Подземелье Гильдии',QUEST_10021: 'Собери 150 Титанита в Подземелье Гильдии',QUEST_10023: 'Прокачай Дар Стихий на 1 уровень',QUEST_10024: 'Повысь уровень любого артефакта один раз',QUEST_10025: 'Начни 1 Экспедицию',QUEST_10026: 'Начни 4 Экспедиции',QUEST_10027: 'Победи в 1 бою Турнира Стихий',QUEST_10028: 'Повысь уровень любого артефакта титанов',QUEST_10029: 'Открой сферу артефактов титанов',QUEST_10030: 'Улучши облик любого героя 1 раз',QUEST_10031: 'Победи в 6 боях Турнира Стихий',QUEST_10043: 'Начни или присоеденись к Приключению',QUEST_10044: 'Воспользуйся призывом питомцев 1 раз',QUEST_10046: 'Открой 3 сундука в Приключениях',QUEST_10047: 'Набери 150 очков активности в Гильдии',NOTHING_TO_DO: 'Нечего выполнять',YOU_CAN_COMPLETE: 'Можно выполнить квесты',BTN_DO_IT: 'Выполняй',NOT_QUEST_COMPLETED: 'Ни одного квеста не выполенно',COMPLETED_QUESTS: 'Выполнено квестов',/* everything button */ASSEMBLE_OUTLAND: 'Собрать Запределье',PASS_THE_TOWER: 'Пройти башню',CHECK_EXPEDITIONS: 'Проверить экспедиции',COMPLETE_TOE: 'Пройти Турнир Стихий',COMPLETE_DUNGEON: 'Пройти подземелье',COLLECT_MAIL: 'Собрать почту',COLLECT_MISC: 'Собрать всякую херню',COLLECT_MISC_TITLE: 'Собрать пасхалки, камни облика, ключи, монеты арены и Хрусталь души',COLLECT_QUEST_REWARDS: 'Собрать награды за квесты',MAKE_A_SYNC: 'Сделать синхронизацию',RUN_FUNCTION: 'Выполнить следующие функции?',BTN_GO: 'Погнали!',PERFORMED: 'Выполняется',DONE: 'Выполнено',ERRORS_OCCURRES: 'Призошли ошибки при выполнении',COPY_ERROR: 'Скопировать в буфер информацию об ошибке',BTN_YES: 'Да',ALL_TASK_COMPLETED: 'Все задачи выполнены',UNKNOWN: 'Неизвестно',ENTER_THE_PATH: 'Введите путь приключения через запятые или дефисы',START_ADVENTURE: 'Начать приключение по этому пути!',INCORRECT_WAY: 'Неверный путь в приключении: {from} -> {to}',BTN_CANCELED: 'Отменено',MUST_TWO_POINTS: 'Путь должен состоять минимум из 2х точек',MUST_ONLY_NUMBERS: 'Путь должен содержать только цифры и запятые',NOT_ON_AN_ADVENTURE: 'Вы не в приключении',YOU_IN_NOT_ON_THE_WAY: 'Указанный путь должен включать точку вашего положения',ATTEMPTS_NOT_ENOUGH: 'Ваших попыток не достаточно для завершения пути, продолжить?',YES_CONTINUE: 'Да, продолжай!',NOT_ENOUGH_AP: 'Попыток не достаточно',ATTEMPTS_ARE_OVER: 'Попытки закончились',MOVES: 'Ходы',BUFF_GET_ERROR: 'Ошибка при получении бафа',BATTLE_END_ERROR: 'Ошибка завершения боя',AUTOBOT: 'АвтоБой',FAILED_TO_WIN_AUTO: 'Не удалось победить в автобою',ERROR_OF_THE_BATTLE_COPY: 'Призошли ошибка в процессе прохождения боя<br>Скопировать ошибку в буфер обмена?',ERROR_DURING_THE_BATTLE: 'Ошибка в процессе прохождения боя',NO_CHANCE_WIN: 'Нет шансов победить в этом бою: 0/',LOST_HEROES: 'Вы победили, но потеряли одного или несколько героев!',VICTORY_IMPOSSIBLE: 'Победа не возможна, бъем на результат?',FIND_COEFF: 'Поиск коэффициента больше чем',BTN_PASS: 'ПРОПУСК',BRAWLS: 'Потасовки',BRAWLS_TITLE: 'Включает возможность автопотасовок',START_AUTO_BRAWLS: 'Запустить Автопотасовки?',LOSSES: 'Поражений',WINS: 'Побед',FIGHTS: 'Боев',STAGE: 'Стадия',DONT_HAVE_LIVES: 'У Вас нет жизней',LIVES: 'Жизни',SECRET_WEALTH_ALREADY: 'товар за Зелья питомцев уже куплен',SECRET_WEALTH_NOT_ENOUGH: 'Не достаточно Зелье Питомца, у Вас {available}, нужно {need}',SECRET_WEALTH_UPGRADE_NEW_PET: 'После покупки Зелье Питомца будет не достаточно для прокачки нового питомца',SECRET_WEALTH_PURCHASED: 'Куплено {count} {name}',SECRET_WEALTH_CANCELED: 'Тайное богатство: покупка отменена',SECRET_WEALTH_BUY: 'У вас {available} Зелье Питомца.<br>Вы хотите купить {countBuy} {name} за {price} Зелье Питомца?',DAILY_BONUS: 'Ежедневная награда',DO_DAILY_QUESTS: 'Сделать ежедневные квесты',ACTIONS: 'Действия',ACTIONS_TITLE: 'Диалоговое окно с различными действиями',OTHERS: 'Разное',OTHERS_TITLE: 'Диалоговое окно с дополнительными различными действиями',CHOOSE_ACTION: 'Выберите действие',OPEN_LOOTBOX: 'У Вас {lootBox} ящиков, откываем?',STAMINA: 'Энергия',BOXES_OVER: 'Ящики закончились',NO_BOXES: 'Нет ящиков',NO_MORE_ACTIVITY: 'Больше активности за предметы сегодня не получить',EXCHANGE_ITEMS: 'Обменять предметы на очки активности (не более {maxActive})?',GET_ACTIVITY: 'Получить активность',NOT_ENOUGH_ITEMS: 'Предметов недостаточно',ACTIVITY_RECEIVED: 'Получено активности',NO_PURCHASABLE_HERO_SOULS: 'Нет доступных для покупки душ героев',PURCHASED_HERO_SOULS: 'Куплено {countHeroSouls} душ героев',NOT_ENOUGH_EMERALDS_540: 'Недостаточно изюма, нужно {imgEmerald}540 у Вас {imgEmerald}{currentStarMoney}',BUY_OUTLAND_BTN: 'Купить {count} сундуков {imgEmerald}{countEmerald}',CHESTS_NOT_AVAILABLE: 'Сундуки не доступны',OUTLAND_CHESTS_RECEIVED: 'Получено сундуков Запределья',RAID_NOT_AVAILABLE: 'Рейд не доступен или сфер нет',RAID_ADVENTURE: 'Рейд {adventureId} приключения!',SOMETHING_WENT_WRONG: 'Что-то пошло не так',ADVENTURE_COMPLETED: 'Приключение {adventureId} пройдено {times} раз',CLAN_STAT_COPY: 'Клановая статистика скопирована в буфер обмена',GET_ENERGY: 'Получить энергию',GET_ENERGY_TITLE: 'Открывает платиновые шкатулки по одной до получения 250 энергии',ITEM_EXCHANGE: 'Обмен предметов',ITEM_EXCHANGE_TITLE: 'Обменивает предметы на указанное количество активности',BUY_SOULS: 'Купить души',BUY_SOULS_TITLE: 'Купить души героев из всех доступных магазинов',BUY_OUTLAND: 'Купить Запределье',BUY_OUTLAND_TITLE: 'Купить 9 сундуков в Запределье за 540 изумрудов',RAID: 'Рейд',AUTO_RAID_ADVENTURE: 'Рейд',AUTO_RAID_ADVENTURE_TITLE: 'Рейд приключения заданное количество раз',CLAN_STAT: 'Клановая статистика',CLAN_STAT_TITLE: 'Копирует клановую статистику в буфер обмена',BTN_AUTO_F5: 'Авто (F5)',BOSS_DAMAGE: 'Урон по боссу: ',NOTHING_BUY: 'Нечего покупать',LOTS_BOUGHT: 'За золото куплено {countBuy} лотов',BUY_FOR_GOLD: 'Скупить за золото',BUY_FOR_GOLD_TITLE: 'Скупить предметы за золото в Городской лавке и в магазине Камней Душ Питомцев',REWARDS_AND_MAIL: 'Награды и почта',REWARDS_AND_MAIL_TITLE: 'Собирает награды и почту',COLLECT_REWARDS_AND_MAIL: 'Собрано {countQuests} наград и {countMail} писем',TIMER_ALREADY: 'Таймер уже запущен {time}',NO_ATTEMPTS_TIMER_START: 'Попыток нет, запущен таймер {time}',EPIC_BRAWL_R###LT: '{i} Победы: {wins}/{attempts}, Монеты: {coins}, Серия: {progress}/{nextStage} [Закрыть]{end}',ATTEMPT_ENDED: '<br>Попытки закончились, запущен таймер {time}',EPIC_BRAWL: 'Вселенская битва',EPIC_BRAWL_TITLE: 'Тратит попытки во Вселенской битве',RELOAD_GAME: 'Перезагрузить игру',TIMER: 'Таймер:',SHOW_ERRORS: 'Отображать ошибки',SHOW_ERRORS_TITLE: 'Отображать ошибки запросов к серверу',ERROR_MSG: 'Ошибка: {name}<br>{description}',EVENT_AUTO_BOSS:'Максимальное количество боев для расчета:</br>{length} * {countTestBattle} = {maxCalcBattle}</br>Если у Вас слабый компьютер на это может потребоваться много времени, нажмите крестик для отмены.</br>Искать лучший пак из всех или первый подходящий?',BEST_SLOW: 'Лучший (медленее)',FIRST_FAST: 'Первый (быстрее)',FREEZE_INTERFACE: 'Идет расчет... <br> Интерфейс может зависнуть.',ERROR_F12: 'Ошибка, подробности в консоли (F12)',FAILED_FIND_WIN_PACK: 'Победный пак найти не удалось',BEST_PACK: 'Наилучший пак: ',BOSS_HAS_BEEN_DEF: 'Босс {bossLvl} побежден',NOT_ENOUGH_ATTEMPTS_BOSS: 'Для победы босса ${bossLvl} не хватило попыток, повторить?',BOSS_VICTORY_IMPOSSIBLE:'По результатам прерасчета {battles} боев победу получить не удалось. Вы хотите продолжить поиск победного боя на реальных боях?',BOSS_HAS_BEEN_DEF_TEXT:'Босс {bossLvl} побежден за<br>{countBattle}/{countMaxBattle} попыток{winTimer}<br>(Сделайте синхронизацию или перезагрузите игру для обновления данных)',MAP: 'Карта: ',PLAYER_POS: 'Позиции игроков:',NY_GIFTS: 'Подарки',NY_GIFTS_TITLE: 'Открыть все новогодние подарки',NY_NO_GIFTS: 'Нет не полученных подарков',NY_GIFTS_COLLECTED: 'Собрано {count} подарков',CHANGE_MAP: 'Карта острова',CHANGE_MAP_TITLE: 'Сменить карту острова',SELECT_ISLAND_MAP: 'Выберите карту острова:',MAP_NUM: 'Карта {num}',SECRET_WEALTH_SHOP: 'Тайное богатство {name}: ',SHOPS: 'Магазины',SHOPS_DEFAULT: 'Стандартные',SHOPS_DEFAULT_TITLE: 'Стандартные магазины',SHOPS_LIST: 'Магазины {number}',SHOPS_LIST_TITLE: 'Список магазинов {number}',SHOPS_WARNING:'Магазины<br><span style="color:red">Если Вы купите монеты магазинов потасовок за изумруды, то их надо использовать сразу, иначе после перезагрузки игры они пропадут!</span>',MINIONS_WARNING: 'Пачки героев для атаки приспешников неполные, продолжить?',FAST_SEASON: 'Быстрый сезон',FAST_SEASON_TITLE: 'Пропуск экрана с выбором карты в сезоне',SET_NUMBER_LEVELS: 'Указать колличество уровней:',POSSIBLE_IMPROVE_LEVELS: 'Возможно улучшить только {count} уровней.<br>Улучшаем?',NOT_ENOUGH_RESOURECES: 'Не хватает ресурсов',IMPROVED_LEVELS: 'Улучшено уровней: {count}',ARTIFACTS_UPGRADE: 'Улучшение артефактов',ARTIFACTS_UPGRADE_TITLE: 'Улучшает указанное количество самых дешевых артефактов героев',SKINS_UPGRADE: 'Улучшение обликов',SKINS_UPGRADE_TITLE: 'Улучшает указанное количество самых дешевых обликов героев',HINT: '<br>Подсказка: ',PICTURE: '<br>На картинке: ',ANSWER: '<br>Ответ: ',NO_HEROES_PACK: 'Проведите хотя бы один бой для сохранения атакующей команды',BRAWL_AUTO_PACK: 'Автоподбор пачки',BRAWL_AUTO_PACK_NOT_CUR_HERO: 'Автоматический подбор пачки не подходит для текущего героя',BRAWL_DAILY_TASK_COMPLETED: 'Ежедневное задание выполнено, продолжить атаку?',CALC_STAT: 'Посчитать статистику',ELEMENT_TOURNAMENT_REWARD: 'Несобранная награда за Турнир Стихий',BTN_TRY_FIX_IT: 'Исправить',BTN_TRY_FIX_IT_TITLE: 'Включить исправление боев при автоатаке',DAMAGE_FIXED: 'Урон исправлен с {lastDamage} до {maxDamage}!',DAMAGE_NO_FIXED: 'Не удалось исправить урон: {lastDamage}',LETS_FIX: 'Исправляем',COUNT_FIXED: 'За {count} попыток',DEFEAT_TURN_TIMER: 'Поражение! Включить таймер для завершения миссии?',SEASON_REWARD: 'Награды сезонов',SEASON_REWARD_TITLE: 'Собирает доступные бесплатные награды со всех текущих сезонов',SEASON_REWARD_COLLECTED: 'Собрано {count} наград сезонов',SELL_HERO_SOULS: 'Продать души',SELL_HERO_SOULS_TITLE: 'Обменивает все души героев с абсолютной звездой на золото',GOLD_RECEIVED: 'Получено золота: {gold}',OPEN_ALL_EQUIP_BOXES: 'Открыть все ящики фрагментов экипировки?',SERVER_NOT_ACCEPT: 'Сервер не принял результат',INVASION_BOSS_BUFF: 'Для {bossLvl} босса нужен баф {needBuff} у вас {haveBuff}',HERO_POWER: 'Сила героев',HERO_POWER_TITLE: 'Отображает текущую и максимальную силу героев',MAX_POWER_REACHED: 'Максимальная достигнутая мощь: {power}',CURRENT_POWER: 'Текущая мощь: {power}',POWER_TO_MAX: 'До максимума мощи осталось: <span style="color:{color};">{power}</span><br>',BEST_R###LT: 'Лучший результат: {value}%',GUILD_ISLAND_TITLE: 'Перейти к Острову гильдии',TITAN_VALLEY_TITLE: 'Перейти к Долине титанов',},};function getLang() {let lang = '';if (typeof NXFlashVars !== 'undefined') {lang = NXFlashVars.interface_lang}if (!lang) {lang = (navigator.language || navigator.userLanguage).substr(0, 2);}if (lang == 'ru') {return lang;}return 'en';}this.I18N = function (constant, replace) {const selectLang = getLang();if (constant && constant in i18nLangData[selectLang]) {const r###lt = i18nLangData[selectLang][constant];if (replace) {return r###lt.sprintf(replace);}return r###lt;}return `% ${constant} %`;};String.prototype.sprintf = String.prototype.sprintf ||function () {"use strict";var str = this.toString();if (arguments.length) {var t = typeof arguments[0];var key;var args = ("string" === t || "number" === t) ?Array.prototype.slice.call(arguments): arguments[0];for (key in args) {str = str.replace(new RegExp("\\{" + key + "\\}", "gi"), args[key]);}}return str;};/*** Checkboxes** Чекбоксы*/const checkboxes = {passBattle: {label: I18N('SKIP_FIGHTS'),cbox: null,title: I18N('SKIP_FIGHTS_TITLE'),default: false,},sendExpedition: {label: I18N('AUTO_EXPEDITION'),cbox: null,title: I18N('AUTO_EXPEDITION_TITLE'),default: false,},cancelBattle: {label: I18N('CANCEL_FIGHT'),cbox: null,title: I18N('CANCEL_FIGHT_TITLE'),default: false,},preCalcBattle: {label: I18N('BATTLE_RECALCULATION'),cbox: null,title: I18N('BATTLE_RECALCULATION_TITLE'),default: false,},countControl: {label: I18N('QUANTITY_CONTROL'),cbox: null,title: I18N('QUANTITY_CONTROL_TITLE'),default: true,},repeatMission: {label: I18N('REPEAT_CAMPAIGN'),cbox: null,title: I18N('REPEAT_CAMPAIGN_TITLE'),default: false,},noOfferDonat: {label: I18N('DISABLE_DONAT'),cbox: null,title: I18N('DISABLE_DONAT_TITLE'),/*** A crutch to get the field before getting the character id** Костыль чтоб получать поле до получения id персонажа*/default: (() => {$r###lt = false;try {$r###lt = JSON.parse(localStorage[GM_info.script.name + ':noOfferDonat']);} catch (e) {$r###lt = false;}return $r###lt || false;})(),},dailyQuests: {label: I18N('DAILY_QUESTS'),cbox: null,title: I18N('DAILY_QUESTS_TITLE'),default: false,},// ПотасовкиautoBrawls: {label: I18N('BRAWLS'),cbox: null,title: I18N('BRAWLS_TITLE'),default: (() => {$r###lt = false;try {$r###lt = JSON.parse(localStorage[GM_info.script.name + ':autoBrawls']);} catch (e) {$r###lt = false;}return $r###lt || false;})(),hide: false,},getAnswer: {label: I18N('AUTO_QUIZ'),cbox: null,title: I18N('AUTO_QUIZ_TITLE'),default: false,hide: false,},tryFixIt_v2: {label: I18N('BTN_TRY_FIX_IT'),cbox: null,title: I18N('BTN_TRY_FIX_IT_TITLE'),default: false,hide: false,},showErrors: {label: I18N('SHOW_ERRORS'),cbox: null,title: I18N('SHOW_ERRORS_TITLE'),default: true,},buyForGold: {label: I18N('BUY_FOR_GOLD'),cbox: null,title: I18N('BUY_FOR_GOLD_TITLE'),default: false,},hideServers: {label: I18N('HIDE_SERVERS'),cbox: null,title: I18N('HIDE_SERVERS_TITLE'),default: false,},fastSeason: {label: I18N('FAST_SEASON'),cbox: null,title: I18N('FAST_SEASON_TITLE'),default: false,},};/*** Get checkbox state** Получить состояние чекбокса*/function isChecked(checkBox) {if (!(checkBox in checkboxes)) {return false;}return checkboxes[checkBox].cbox?.checked;}/*** Input fields** Поля ввода*/const inputs = {countTitanit: {input: null,title: I18N('HOW_MUCH_TITANITE'),default: 150,},speedBattle: {input: null,title: I18N('COMBAT_SPEED'),default: 5,},countTestBattle: {input: null,title: I18N('NUMBER_OF_TEST'),default: 10,},countAutoBattle: {input: null,title: I18N('NUMBER_OF_AUTO_BATTLE'),default: 10,},FPS: {input: null,title: 'FPS',default: 60,}}/*** Checks the checkbox** Поплучить данные поля ввода*/function getInput(inputName) {return inputs[inputName]?.input?.value;}/*** Control FPS** Контроль FPS*/let nextAnimationFrame = Date.now();const oldRequestAnimationFrame = this.requestAnimationFrame;this.requestAnimationFrame = async function (e) {const FPS = Number(getInput('FPS')) || -1;const now = Date.now();const delay = nextAnimationFrame - now;nextAnimationFrame = Math.max(now, nextAnimationFrame) + Math.min(1e3 / FPS, 1e3);if (delay > 0) {await new Promise((e) => setTimeout(e, delay));}oldRequestAnimationFrame(e);};/*** Button List** Список кнопочек*/const buttons = {getOutland: {name: I18N('TO_DO_EVERYTHING'),title: I18N('TO_DO_EVERYTHING_TITLE'),onClick: testDoYourBest,},doActions: {name: I18N('ACTIONS'),title: I18N('ACTIONS_TITLE'),onClick: async function () {const popupButtons = [{msg: I18N('OUTLAND'),r###lt: function () {confShow(`${I18N('RUN_SCRIPT')} ${I18N('OUTLAND')}?`, getOutland);},title: I18N('OUTLAND_TITLE'),},{msg: I18N('TOWER'),r###lt: function () {confShow(`${I18N('RUN_SCRIPT')} ${I18N('TOWER')}?`, testTower);},title: I18N('TOWER_TITLE'),},{msg: I18N('EXPEDITIONS'),r###lt: function () {confShow(`${I18N('RUN_SCRIPT')} ${I18N('EXPEDITIONS')}?`, checkExpedition);},title: I18N('EXPEDITIONS_TITLE'),},{msg: I18N('MINIONS'),r###lt: function () {confShow(`${I18N('RUN_SCRIPT')} ${I18N('MINIONS')}?`, testRaidNodes);},title: I18N('MINIONS_TITLE'),},{msg: I18N('ESTER_EGGS'),r###lt: function () {confShow(`${I18N('RUN_SCRIPT')} ${I18N('ESTER_EGGS')}?`, offerFarmAllReward);},title: I18N('ESTER_EGGS_TITLE'),},{msg: I18N('STORM'),r###lt: function () {testAdventure('solo');},title: I18N('STORM_TITLE'),},{msg: I18N('REWARDS'),r###lt: function () {confShow(`${I18N('RUN_SCRIPT')} ${I18N('REWARDS')}?`, questAllFarm);},title: I18N('REWARDS_TITLE'),},{msg: I18N('MAIL'),r###lt: function () {confShow(`${I18N('RUN_SCRIPT')} ${I18N('MAIL')}?`, mailGetAll);},title: I18N('MAIL_TITLE'),},{msg: I18N('SEER'),r###lt: function () {confShow(`${I18N('RUN_SCRIPT')} ${I18N('SEER')}?`, rollAscension);},title: I18N('SEER_TITLE'),},/*{msg: I18N('NY_GIFTS'),r###lt: getGiftNewYear,title: I18N('NY_GIFTS_TITLE'),},*/];popupButtons.push({ r###lt: false, isClose: true });const answer = await popup.confirm(`${I18N('CHOOSE_ACTION')}:`, popupButtons);if (typeof answer === 'function') {answer();}},},doOthers: {name: I18N('OTHERS'),title: I18N('OTHERS_TITLE'),onClick: async function () {const popupButtons = [{msg: I18N('GET_ENERGY'),r###lt: farmStamina,title: I18N('GET_ENERGY_TITLE'),},{msg: I18N('ITEM_EXCHANGE'),r###lt: fillActive,title: I18N('ITEM_EXCHANGE_TITLE'),},{msg: I18N('BUY_SOULS'),r###lt: function () {confShow(`${I18N('RUN_SCRIPT')} ${I18N('BUY_SOULS')}?`, buyHeroFragments);},title: I18N('BUY_SOULS_TITLE'),},{msg: I18N('BUY_FOR_GOLD'),r###lt: function () {confShow(`${I18N('RUN_SCRIPT')} ${I18N('BUY_FOR_GOLD')}?`, buyInStoreForGold);},title: I18N('BUY_FOR_GOLD_TITLE'),},{msg: I18N('BUY_OUTLAND'),r###lt: bossOpenChestPay,title: I18N('BUY_OUTLAND_TITLE'),},{msg: I18N('CLAN_STAT'),r###lt: clanStatistic,title: I18N('CLAN_STAT_TITLE'),},{msg: I18N('EPIC_BRAWL'),r###lt: async function () {confShow(`${I18N('RUN_SCRIPT')} ${I18N('EPIC_BRAWL')}?`, () => {const brawl = new epicBrawl();brawl.start();});},title: I18N('EPIC_BRAWL_TITLE'),},{msg: I18N('ARTIFACTS_UPGRADE'),r###lt: updateArtifacts,title: I18N('ARTIFACTS_UPGRADE_TITLE'),},{msg: I18N('SKINS_UPGRADE'),r###lt: updateSkins,title: I18N('SKINS_UPGRADE_TITLE'),},{msg: I18N('SEASON_REWARD'),r###lt: farmBattlePass,title: I18N('SEASON_REWARD_TITLE'),},{msg: I18N('SELL_HERO_SOULS'),r###lt: sellHeroSoulsForGold,title: I18N('SELL_HERO_SOULS_TITLE'),},{msg: I18N('CHANGE_MAP'),r###lt: async function () {const maps = Object.values(lib.data.seasonAdventure.list).filter((e) => e.map.cells.length > 2).map((i) => ({msg: I18N('MAP_NUM', { num: i.id }),r###lt: i.id,}));const r###lt = await popup.confirm(I18N('SELECT_ISLAND_MAP'), [...maps, { r###lt: false, isClose: true }]);if (r###lt) {cheats.changeIslandMap(r###lt);}},title: I18N('CHANGE_MAP_TITLE'),},{msg: I18N('HERO_POWER'),r###lt: async () => {const calls = ['userGetInfo', 'heroGetAll'].map((name) => ({name,args: {},ident: name,}));const [maxHeroSumPower, heroSumPower] = await Send({ calls }).then((e) => [e.r###lts[0].r###lt.response.maxSumPower.heroes,Object.values(e.r###lts[1].r###lt.response).reduce((a, e) => a + e.power, 0),]);const power = maxHeroSumPower - heroSumPower;let msg =I18N('MAX_POWER_REACHED', { power: maxHeroSumPower.toLocaleString() }) +'<br>' +I18N('CURRENT_POWER', { power: heroSumPower.toLocaleString() }) +'<br>' +I18N('POWER_TO_MAX', { power: power.toLocaleString(), color: power >= 4000 ? 'green' : 'red' });await popup.confirm(msg, [{ msg: I18N('BTN_OK'), r###lt: 0 }]);},title: I18N('HERO_POWER_TITLE'),},];popupButtons.push({ r###lt: false, isClose: true });const answer = await popup.confirm(`${I18N('CHOOSE_ACTION')}:`, popupButtons);if (typeof answer === 'function') {answer();}},},testTitanArena: {isCombine: true,combineList: [{name: I18N('TITAN_ARENA'),title: I18N('TITAN_ARENA_TITLE'),onClick: function () {confShow(`${I18N('RUN_SCRIPT')} ${I18N('TITAN_ARENA')}?`, testTitanArena);},},{name: '>>',onClick: cheats.goTitanValley,title: I18N('TITAN_VALLEY_TITLE'),color: 'green',},],},testDungeon: {isCombine: true,combineList: [{name: I18N('DUNGEON'),onClick: function () {confShow(`${I18N('RUN_SCRIPT')} ${I18N('DUNGEON')}?`, testDungeon);},title: I18N('DUNGEON_TITLE'),},{name: '>>',onClick: cheats.goClanIsland,title: I18N('GUILD_ISLAND_TITLE'),color: 'green',},],},testAdventure: {isCombine: true,combineList: [{name: I18N('ADVENTURE'),onClick: () => {testAdventure();},title: I18N('ADVENTURE_TITLE'),},{name: I18N('AUTO_RAID_ADVENTURE'),onClick: autoRaidAdventure,title: I18N('AUTO_RAID_ADVENTURE_TITLE'),},{name: '>>',onClick: cheats.goSanctuary,title: I18N('SANCTUARY_TITLE'),color: 'green',},],},rewardsAndMailFarm: {name: I18N('REWARDS_AND_MAIL'),title: I18N('REWARDS_AND_MAIL_TITLE'),onClick: function () {confShow(`${I18N('RUN_SCRIPT')} ${I18N('REWARDS_AND_MAIL')}?`, rewardsAndMailFarm);},},goToClanWar: {name: I18N('GUILD_WAR'),title: I18N('GUILD_WAR_TITLE'),onClick: cheats.goClanWar,dot: true,},dailyQuests: {name: I18N('DAILY_QUESTS'),title: I18N('DAILY_QUESTS_TITLE'),onClick: async function () {const quests = new dailyQuests(() => {},() => {});await quests.autoInit();quests.start();},},newDay: {name: I18N('SYNC'),title: I18N('SYNC_TITLE'),onClick: function () {confShow(`${I18N('RUN_SCRIPT')} ${I18N('SYNC')}?`, cheats.refreshGame);},},// АрхидемонbossRatingEventDemon: {name: I18N('ARCHDEMON'),title: I18N('ARCHDEMON_TITLE'),onClick: function () {confShow(`${I18N('RUN_SCRIPT')} ${I18N('ARCHDEMON')}?`, bossRatingEvent);},hide: false,color: 'red',},// Горнило душbossRatingEventSouls: {name: I18N('FURNACE_OF_SOULS'),title: I18N('ARCHDEMON_TITLE'),onClick: function () {confShow(`${I18N('RUN_SCRIPT')} ${I18N('FURNACE_OF_SOULS')}?`, bossRatingEventSouls);},hide: true,color: 'red',},};/*** Display buttons** Вывести кнопочки*/function addControlButtons() {const { ScriptMenu } = HWHClasses;const scriptMenu = ScriptMenu.getInst();for (let name in buttons) {button = buttons[name];if (button.hide) {continue;}if (button.isCombine) {button['button'] = scriptMenu.addCombinedButton(button.combineList);continue;}button['button'] = scriptMenu.addButton(button);}}/*** Adds links** Добавляет ссылки*/function addBottomUrls() {const { ScriptMenu } = HWHClasses;const scriptMenu = ScriptMenu.getInst();scriptMenu.addHeader(I18N('BOTTOM_URLS'));}/*** Stop repetition of the mission** Остановить повтор миссии*/let isStopSendMission = false;/*** There is a repetition of the mission** Идет повтор миссии*/let isSendsMission = false;/*** Data on the past mission** Данные о прошедшей мисии*/let lastMissionStart = {}/*** Start time of the last battle in the company** Время начала последнего боя в кампании*/let lastMissionBattleStart = 0;/*** Data for calculating the last battle with the boss** Данные для расчете последнего боя с боссом*/let lastBossBattle = null;/*** Information about the last battle** Данные о прошедшей битве*/let lastBattleArg = {}let lastBossBattleStart = null;this.addBattleTimer = 4;this.invasionTimer = 2500;const invasionInfo = {id: 225,buff: 0,bossLvl: 130,};const invasionDataPacks = {130: { buff: 0, pet: 6005, heroes: [9, 62, 10, 1, 66], favor: { 9: 6006 } },140: { buff: 0, pet: 6005, heroes: [9, 62, 10, 1, 66], favor: {} },150: { buff: 0, pet: 6005, heroes: [9, 62, 10, 1, 66], favor: {} },160: { buff: 0, pet: 6005, heroes: [64, 66, 13, 9, 4], favor: { 4: 6006, 9: 6004, 13: 6003, 64: 6005, 66: 6002 } },170: { buff: 0, pet: 6005, heroes: [9, 62, 10, 1, 66], favor: { 1: 6006, 9: 6005, 10: 6008, 62: 6003, 66: 6002 } },180: { buff: 0, pet: 6006, heroes: [62, 10, 2, 4, 66], favor: { 2: 6005, 4: 6001, 10: 6006, 62: 6003 } },190: { buff: 40, pet: 6005, heroes: [9, 2, 43, 45, 66], favor: { 9: 6005, 45: 6002, 66: 6006 } },200: { buff: 20, pet: 6005, heroes: [9, 62, 1, 48, 66], favor: { 9: 6007, 62: 6003 } },210: { buff: 10, pet: 6008, heroes: [9, 10, 4, 32, 66], favor: { 9: 6005, 10: 6003, 32: 6007, 66: 6006 } },220: { buff: 20, pet: 6004, heroes: [9, 1, 48, 43, 66], favor: { 9: 6005, 43: 6006, 48: 6000, 66: 6002 } },230: { buff: 45, pet: 6001, heroes: [9, 7, 40, 43, 66], favor: { 7: 6006, 9: 6005, 40: 6004, 43: 6006, 66: 6006 } },240: { buff: 50, pet: 6009, heroes: [9, 40, 43, 51, 66], favor: { 9: 6005, 40: 6004, 43: 6002, 66: 6007 } },250: { buff: 70, pet: 6005, heroes: [9, 10, 13, 43, 66], favor: { 9: 6005, 10: 6002, 13: 6002, 43: 6006, 66: 6006 } },260: { buff: 80, pet: 6008, heroes: [9, 40, 43, 4, 66], favor: { 4: 6001, 9: 6006, 43: 6006 } },270: { buff: 115, pet: 6001, heroes: [9, 13, 43, 51, 66], favor: { 9: 6006, 43: 6006, 51: 6001 } },280: { buff: 80, pet: 6008, heroes: [9, 13, 43, 56, 66], favor: { 9: 6004, 13: 6006, 43: 6006, 66: 6006 } },290: { buff: 60, pet: 6005, heroes: [9, 10, 43, 56, 66], favor: { 9: 6005, 10: 6002, 43: 6006 } },300: { buff: 75, pet: 6006, heroes: [9, 62, 1, 45, 66], favor: { 1: 6006, 9: 6005, 45: 6002, 66: 6007 } },};/*** The name of the function of the beginning of the battle** Имя функции начала боя*/let nameFuncStartBattle = '';/*** The name of the function of the end of the battle** Имя функции конца боя*/let nameFuncEndBattle = '';/*** Data for calculating the last battle** Данные для расчета последнего боя*/let lastBattleInfo = null;/*** The ability to cancel the battle** Возможность отменить бой*/let isCancalBattle = true;function setIsCancalBattle(value) {isCancalBattle = value;}/*** Certificator of the last open nesting doll** Идетификатор последней открытой матрешки*/let lastRussianDollId = null;/*** Cancel the training guide** Отменить обучающее руководство*/this.isCanceledTutorial = false;/*** Data from the last question of the quiz** Данные последнего вопроса викторины*/let lastQuestion = null;/*** Answer to the last question of the quiz** Ответ на последний вопрос викторины*/let lastAnswer = null;/*** Flag for opening keys or titan artifact spheres** Флаг открытия ключей или сфер артефактов титанов*/let artifactChestOpen = false;/*** The name of the function to open keys or orbs of titan artifacts** Имя функции открытия ключей или сфер артефактов титанов*/let artifactChestOpenCallName = '';let correctShowOpenArtifact = 0;/*** Data for the last battle in the dungeon* (Fix endless cards)** Данные для последнего боя в подземке* (Исправление бесконечных карт)*/let lastDungeonBattleData = null;/*** Start time of the last battle in the dungeon** Время начала последнего боя в подземелье*/let lastDungeonBattleStart = 0;/*** Subscription end time** Время окончания подписки*/let subEndTime = 0;/*** Number of prediction cards** Количество карт предсказаний*/let countPredictionCard = 0;/*** Brawl pack** Пачка для потасовок*/let brawlsPack = null;/*** Autobrawl started** Автопотасовка запущена*/let isBrawlsAutoStart = false;let clanDominationGetInfo = null;/*** Copies the text to the clipboard** Копирует тест в буфер обмена* @param {*} text copied text // копируемый текст*/function copyText(text) {let copyTextarea = document.createElement("textarea");copyTextarea.style.opacity = "0";copyTextarea.textContent = text;document.body.appendChild(copyTextarea);copyTextarea.select();document.execCommand("copy");document.body.removeChild(copyTextarea);delete copyTextarea;}/*** Returns the history of requests** Возвращает историю запросов*/this.getRequestHistory = function() {return requestHistory;}/*** Generates a random integer from min to max** Гененирует случайное целое число от min до max*/const random = function (min, max) {return Math.floor(Math.random() * (max - min + 1) + min);}const randf = function (min, max) {return Math.random() * (max - min + 1) + min;};/*** Clearing the request history** Очистка истоии запросов*/setInterval(function () {let now = Date.now();for (let i in requestHistory) {const time = +i.split('_')[0];if (now - time > 300000) {delete requestHistory[i];}}}, 300000);/*** Displays the dialog box** Отображает диалоговое окно*/function confShow(message, yesCallback, noCallback) {let buts = [];message = message || I18N('DO_YOU_WANT');noCallback = noCallback || (() => {});if (yesCallback) {buts = [{ msg: I18N('BTN_RUN'), r###lt: true},{ msg: I18N('BTN_CANCEL'), r###lt: false, isCancel: true},]} else {yesCallback = () => {};buts = [{ msg: I18N('BTN_OK'), r###lt: true},];}popup.confirm(message, buts).then((e) => {// dialogPromice = null;if (e) {yesCallback();} else {noCallback();}});}/*** Override/proxy the method for creating a WS package send** Переопределяем/проксируем метод создания отправки WS пакета*/WebSocket.prototype.send = function (data) {if (!this.isSetOnMessage) {const oldOnmessage = this.onmessage;this.onmessage = function (event) {try {const data = JSON.parse(event.data);if (!this.isWebSocketLogin && data.r###lt.type == "iframeEvent.login") {this.isWebSocketLogin = true;} else if (data.r###lt.type == "iframeEvent.login") {return;}} catch (e) { }return oldOnmessage.apply(this, arguments);}this.isSetOnMessage = true;}original.SendWebSocket.call(this, data);}/*** Overriding/Proxying the Ajax Request Creation Method** Переопределяем/проксируем метод создания Ajax запроса*/XMLHttpRequest.prototype.open = function (method, url, async, user, password) {this.uniqid = Date.now() + '_' + random(1000000, 10000000);this.errorRequest = false;if (method == 'POST' && url.includes('.nextersglobal.com/api/') && /api\/$/.test(url)) {if (!apiUrl) {apiUrl = url;const socialInfo = /heroes-(.+?)\./.exec(apiUrl);console.log(socialInfo);}requestHistory[this.uniqid] = {method,url,error: [],headers: {},request: null,response: null,signature: [],calls: {},};} else if (method == 'POST' && url.includes('error.nextersglobal.com/client/')) {this.errorRequest = true;}return original.open.call(this, method, url, async, user, password);};/*** Overriding/Proxying the header setting method for the AJAX request** Переопределяем/проксируем метод установки заголовков для AJAX запроса*/XMLHttpRequest.prototype.setRequestHeader = function (name, value, check) {if (this.uniqid in requestHistory) {requestHistory[this.uniqid].headers[name] = value;} else {check = true;}if (name == 'X-Auth-Signature') {requestHistory[this.uniqid].signature.push(value);if (!check) {return;}}return original.setRequestHeader.call(this, name, value);};/*** Overriding/Proxying the AJAX Request Sending Method** Переопределяем/проксируем метод отправки AJAX запроса*/XMLHttpRequest.prototype.send = async function (sourceData) {if (this.uniqid in requestHistory) {let tempData = null;if (getClass(sourceData) == "ArrayBuffer") {tempData = decoder.decode(sourceData);} else {tempData = sourceData;}requestHistory[this.uniqid].request = tempData;let headers = requestHistory[this.uniqid].headers;lastHeaders = Object.assign({}, headers);/*** Game loading event** Событие загрузки игры*/if (headers["X-Request-Id"] > 2 && !isLoadGame) {isLoadGame = true;if (cheats.libGame) {lib.setData(cheats.libGame);} else {lib.setData(await cheats.LibLoad());}addControls();addControlButtons();addBottomUrls();if (isChecked('sendExpedition')) {const isTimeBetweenDays = isTimeBetweenNewDays();if (!isTimeBetweenDays) {checkExpedition();} else {setProgress(I18N('EXPEDITIONS_NOTTIME'), true);}}getAutoGifts();cheats.activateHacks();justInfo();if (isChecked('dailyQuests')) {testDailyQuests();}if (isChecked('buyForGold')) {buyInStoreForGold();}}/*** Outgoing request data processing** Обработка данных исходящего запроса*/sourceData = await checkChangeSend.call(this, sourceData, tempData);/*** Handling incoming request data** Обработка данных входящего запроса*/const oldReady = this.onreadystatechange;this.onreadystatechange = async function (e) {if (this.errorRequest) {return oldReady.apply(this, arguments);}if(this.readyState == 4 && this.status == 200) {isTextResponse = this.responseType === "text" || this.responseType === "";let response = isTextResponse ? this.responseText : this.response;requestHistory[this.uniqid].response = response;/*** Replacing incoming request data** Заменна данных входящего запроса*/if (isTextResponse) {await checkChangeResponse.call(this, response);}/*** A function to run after the request is executed** Функция запускаемая после выполения запроса*/if (typeof this.onReadySuccess == 'function') {setTimeout(this.onReadySuccess, 500);}/** Удаляем из истории запросов битвы с боссом */if ('invasion_bossStart' in requestHistory[this.uniqid].calls) delete requestHistory[this.uniqid];}if (oldReady) {try {return oldReady.apply(this, arguments);} catch(e) {console.log(oldReady);console.error('Error in oldReady:', e);}}}}if (this.errorRequest) {const oldReady = this.onreadystatechange;this.onreadystatechange = function () {Object.defineProperty(this, 'status', {writable: true});this.status = 200;Object.defineProperty(this, 'readyState', {writable: true});this.readyState = 4;Object.defineProperty(this, 'responseText', {writable: true});this.responseText = JSON.stringify({"r###lt": true});if (typeof this.onReadySuccess == 'function') {setTimeout(this.onReadySuccess, 200);}return oldReady.apply(this, arguments);}this.onreadystatechange();} else {try {return original.send.call(this, sourceData);} catch(e) {debugger;}}};/*** Processing and substitution of outgoing data** Обработка и подмена исходящих данных*/async function checkChangeSend(sourceData, tempData) {try {/*** A function that replaces battle data with incorrect ones to cancel combatя** Функция заменяющая данные боя на неверные для отмены боя*/const fixBattle = function (heroes) {for (const ids in heroes) {hero = heroes[ids];hero.energy = random(1, 999);if (hero.hp > 0) {hero.hp = random(1, hero.hp);}}}/*** Dialog window 2** Диалоговое окно 2*/const showMsg = async function (msg, ansF, ansS) {if (typeof popup == 'object') {return await popup.confirm(msg, [{msg: ansF, r###lt: false},{msg: ansS, r###lt: true},]);} else {return !confirm(`${msg}\n ${ansF} (${I18N('BTN_OK')})\n ${ansS} (${I18N('BTN_CANCEL')})`);}}/*** Dialog window 3** Диалоговое окно 3*/const showMsgs = async function (msg, ansF, ansS, ansT) {return await popup.confirm(msg, [{msg: ansF, r###lt: 0},{msg: ansS, r###lt: 1},{msg: ansT, r###lt: 2},]);}let changeRequest = false;testData = JSON.parse(tempData);for (const call of testData.calls) {if (!artifactChestOpen) {requestHistory[this.uniqid].calls[call.name] = call.ident;}/*** Cancellation of the battle in adventures, on VG and with minions of Asgard* Отмена боя в приключениях, на ВГ и с прислужниками Асгарда*/if ((call.name == 'adventure_endBattle' ||call.name == 'adventureSolo_endBattle' ||call.name == 'clanWarEndBattle' &&isChecked('cancelBattle') ||call.name == 'crossClanWar_endBattle' &&isChecked('cancelBattle') ||call.name == 'brawl_endBattle' ||call.name == 'towerEndBattle' ||call.name == 'invasion_bossEnd' ||call.name == 'titanArenaEndBattle' ||call.name == 'bossEndBattle' ||call.name == 'clanRaid_endNodeBattle') &&isCancalBattle) {nameFuncEndBattle = call.name;if (isChecked('tryFixIt_v2') &&!call.args.r###lt.win &&(call.name == 'brawl_endBattle' ||//call.name == 'crossClanWar_endBattle' ||call.name == 'epicBrawl_endBattle' ||//call.name == 'clanWarEndBattle' ||call.name == 'adventure_endBattle' ||call.name == 'titanArenaEndBattle' ||call.name == 'bossEndBattle' ||call.name == 'adventureSolo_endBattle') &&lastBattleInfo) {const noFixWin = call.name == 'clanWarEndBattle' || call.name == 'crossClanWar_endBattle';const cloneBattle = structuredClone(lastBattleInfo);lastBattleInfo = null;try {const { BestOrWinFixBattle } = HWHClasses;const bFix = new BestOrWinFixBattle(cloneBattle);bFix.setNoMakeWin(noFixWin);let endTime = Date.now() + 3e4;if (endTime < cloneBattle.endTime) {endTime = cloneBattle.endTime;}const r###lt = await bFix.start(cloneBattle.endTime, 150);if (r###lt.r###lt.win) {call.args.r###lt = r###lt.r###lt;call.args.progress = r###lt.progress;changeRequest = true;} else if (r###lt.value) {if (await popup.confirm(I18N('DEFEAT') + '<br>' + I18N('BEST_R###LT', { value: r###lt.value }), [{ msg: I18N('BTN_CANCEL'), r###lt: 0 },{ msg: I18N('BTN_ACCEPT'), r###lt: 1 },])) {call.args.r###lt = r###lt.r###lt;call.args.progress = r###lt.progress;changeRequest = true;}}} catch (error) {console.error(error);}}if (!call.args.r###lt.win) {let r###ltPopup = false;if (call.name == 'adventure_endBattle' ||//call.name == 'invasion_bossEnd' ||call.name == 'bossEndBattle' ||call.name == 'adventureSolo_endBattle') {r###ltPopup = await showMsgs(I18N('MSG_HAVE_BEEN_DEFEATED'), I18N('BTN_OK'), I18N('BTN_CANCEL'), I18N('BTN_AUTO'));} else if (call.name == 'clanWarEndBattle' ||call.name == 'crossClanWar_endBattle') {r###ltPopup = await showMsg(I18N('MSG_HAVE_BEEN_DEFEATED'), I18N('BTN_OK'), I18N('BTN_AUTO_F5'));} else if (call.name !== 'epicBrawl_endBattle' && call.name !== 'titanArenaEndBattle') {r###ltPopup = await showMsg(I18N('MSG_HAVE_BEEN_DEFEATED'), I18N('BTN_OK'), I18N('BTN_CANCEL'));}if (r###ltPopup) {if (call.name == 'invasion_bossEnd') {this.errorRequest = true;}fixBattle(call.args.progress[0].attackers.heroes);fixBattle(call.args.progress[0].defenders.heroes);changeRequest = true;if (r###ltPopup > 1) {this.onReadySuccess = testAutoBattle;// setTimeout(bossBattle, 1000);}}} else if (call.args.r###lt.stars < 3 && call.name == 'towerEndBattle') {r###ltPopup = await showMsg(I18N('LOST_HEROES'), I18N('BTN_OK'), I18N('BTN_CANCEL'), I18N('BTN_AUTO'));if (r###ltPopup) {fixBattle(call.args.progress[0].attackers.heroes);fixBattle(call.args.progress[0].defenders.heroes);changeRequest = true;if (r###ltPopup > 1) {this.onReadySuccess = testAutoBattle;}}}// Потасовкиif (isChecked('autoBrawls') && !isBrawlsAutoStart && call.name == 'brawl_endBattle') {}}/*** Save pack for Brawls** Сохраняем пачку для потасовок*/if (isChecked('autoBrawls') && !isBrawlsAutoStart && call.name == 'brawl_startBattle') {console.log(JSON.stringify(call.args));brawlsPack = call.args;if (await popup.confirm(I18N('START_AUTO_BRAWLS'),[{ msg: I18N('BTN_NO'), r###lt: false },{ msg: I18N('BTN_YES'), r###lt: true },],[{name: 'isAuto',label: I18N('BRAWL_AUTO_PACK'),checked: false,},])) {isBrawlsAutoStart = true;const isAuto = popup.getCheckBoxes().find((e) => e.name === 'isAuto');this.errorRequest = true;testBrawls(isAuto.checked);}}/*** Canceled fight in Asgard* Отмена боя в Асгарде*/if (call.name == 'clanRaid_endBossBattle' && isChecked('cancelBattle')) {const bossDamage = call.args.progress[0].defenders.heroes[1].extra;let maxDamage = bossDamage.damageTaken + bossDamage.damageTakenNextLevel;const lastDamage = maxDamage;const testFunc = [];if (testFuntions.masterFix) {testFunc.push({ msg: 'masterFix', isInput: true, default: 100 });}const r###ltPopup = await popup.confirm(`${I18N('MSG_YOU_APPLIED')} ${lastDamage.toLocaleString()} ${I18N('MSG_DAMAGE')}.`,[{ msg: I18N('BTN_OK'), r###lt: false },{ msg: I18N('BTN_AUTO_F5'), r###lt: 1 },{ msg: I18N('BTN_TRY_FIX_IT'), r###lt: 2 },...testFunc,],[{name: 'isStat',label: I18N('CALC_STAT'),checked: false,},]);if (r###ltPopup) {if (r###ltPopup == 2) {setProgress(I18N('LETS_FIX'), false);await new Promise((e) => setTimeout(e, 0));const cloneBattle = structuredClone(lastBossBattle);const endTime = cloneBattle.endTime - 1e4;console.log('fixBossBattleStart');const { BossFixBattle } = HWHClasses;const bFix = new BossFixBattle(cloneBattle);const r###lt = await bFix.start(endTime, 300);console.log(r###lt);let msgR###lt = I18N('DAMAGE_NO_FIXED', {lastDamage: lastDamage.toLocaleString()});if (r###lt.value > lastDamage) {call.args.r###lt = r###lt.r###lt;call.args.progress = r###lt.progress;msgR###lt = I18N('DAMAGE_FIXED', {lastDamage: lastDamage.toLocaleString(),maxDamage: r###lt.value.toLocaleString(),});}console.log(lastDamage, '>', r###lt.value);setProgress(msgR###lt +'<br/>' +I18N('COUNT_FIXED', {count: r###lt.maxCount,}),false,hideProgress);} else if (r###ltPopup > 3) {const cloneBattle = structuredClone(lastBossBattle);const { masterFixBattle } = HWHClasses;const mFix = new masterFixBattle(cloneBattle);const r###lt = await mFix.start(cloneBattle.endTime, r###ltPopup);console.log(r###lt);let msgR###lt = I18N('DAMAGE_NO_FIXED', {lastDamage: lastDamage.toLocaleString(),});if (r###lt.value > lastDamage) {maxDamage = r###lt.value;call.args.r###lt = r###lt.r###lt;call.args.progress = r###lt.progress;msgR###lt = I18N('DAMAGE_FIXED', {lastDamage: lastDamage.toLocaleString(),maxDamage: maxDamage.toLocaleString(),});}console.log('Урон:', lastDamage, maxDamage);setProgress(msgR###lt, false, hideProgress);} else {fixBattle(call.args.progress[0].attackers.heroes);fixBattle(call.args.progress[0].defenders.heroes);}changeRequest = true;}const isStat = popup.getCheckBoxes().find((e) => e.name === 'isStat');if (isStat.checked) {this.onReadySuccess = testBossBattle;}}/*** Save the Asgard Boss Attack Pack* Сохраняем пачку для атаки босса Асгарда*/if (call.name == 'clanRaid_startBossBattle') {console.log(JSON.stringify(call.args));}/*** Saving the request to start the last battle* Сохранение запроса начала последнего боя*/if (call.name == 'clanWarAttack' ||call.name == 'crossClanWar_startBattle' ||call.name == 'adventure_turnStartBattle' ||call.name == 'adventureSolo_turnStartBattle' ||call.name == 'bossAttack' ||call.name == 'invasion_bossStart' ||call.name == 'towerStartBattle') {nameFuncStartBattle = call.name;lastBattleArg = call.args;if (call.name == 'invasion_bossStart') {const timePassed = Date.now() - lastBossBattleStart;if (timePassed < invasionTimer) {await new Promise((e) => setTimeout(e, invasionTimer - timePassed));}invasionTimer -= 1;}lastBossBattleStart = Date.now();}if (call.name == 'invasion_bossEnd') {const lastBattle = lastBattleInfo;if (lastBattle && call.args.r###lt.win) {lastBattle.progress = call.args.progress;const r###lt = await Calc(lastBattle);let timer = getTimer(r###lt.battleTime, 1) + addBattleTimer;const period = Math.ceil((Date.now() - lastBossBattleStart) / 1000);console.log(timer, period);if (period < timer) {timer = timer - period;await countdownTimer(timer);}}}/*** Disable spending divination cards* Отключить трату карт предсказаний*/if (call.name == 'dungeonEndBattle') {if (call.args.isRaid) {if (countPredictionCard <= 0) {delete call.args.isRaid;changeRequest = true;} else if (countPredictionCard > 0) {countPredictionCard--;}}console.log(`Cards: ${countPredictionCard}`);/*** Fix endless cards* Исправление бесконечных карт*/const lastBattle = lastDungeonBattleData;if (lastBattle && !call.args.isRaid) {if (changeRequest) {lastBattle.progress = [{ attackers: { input: ["auto", 0, 0, "auto", 0, 0] } }];} else {lastBattle.progress = call.args.progress;}const r###lt = await Calc(lastBattle);if (changeRequest) {call.args.progress = r###lt.progress;call.args.r###lt = r###lt.r###lt;}let timer = r###lt.battleTimer + addBattleTimer;const period = Math.ceil((Date.now() - lastDungeonBattleStart) / 1000);console.log(timer, period);if (period < timer) {timer = timer - period;await countdownTimer(timer);}}}/*** Quiz Answer* Ответ на викторину*/if (call.name == 'quiz_answer') {/*** Automatically changes the answer to the correct one if there is one.* Автоматически меняет ответ на правильный если он есть*/if (lastAnswer && isChecked('getAnswer')) {call.args.answerId = lastAnswer;lastAnswer = null;changeRequest = true;}}/*** Present* Подарки*/if (call.name == 'freebieCheck') {freebieCheckInfo = call;}/** missionTimer */if (call.name == 'missionEnd' && missionBattle) {let startTimer = false;if (!call.args.r###lt.win) {startTimer = await popup.confirm(I18N('DEFEAT_TURN_TIMER'), [{ msg: I18N('BTN_NO'), r###lt: false },{ msg: I18N('BTN_YES'), r###lt: true },]);}if (call.args.r###lt.win || startTimer) {missionBattle.progress = call.args.progress;missionBattle.r###lt = call.args.r###lt;const r###lt = await Calc(missionBattle);let timer = r###lt.battleTimer + addBattleTimer;const period = Math.ceil((Date.now() - lastMissionBattleStart) / 1000);if (period < timer) {timer = timer - period;await countdownTimer(timer);}missionBattle = null;} else {this.errorRequest = true;}}/*** Getting mission data for auto-repeat* Получение данных миссии для автоповтора*/if (isChecked('repeatMission') &&call.name == 'missionEnd') {let missionInfo = {id: call.args.id,r###lt: call.args.r###lt,heroes: call.args.progress[0].attackers.heroes,count: 0,}setTimeout(async () => {if (!isSendsMission && await popup.confirm(I18N('MSG_REPEAT_MISSION'), [{ msg: I18N('BTN_REPEAT'), r###lt: true},{ msg: I18N('BTN_NO'), r###lt: false},])) {isStopSendMission = false;isSendsMission = true;sendsMission(missionInfo);}}, 0);}/*** Getting mission data* Получение данных миссии* missionTimer*/if (call.name == 'missionStart') {lastMissionStart = call.args;lastMissionBattleStart = Date.now();}/*** Specify the quantity for Titan Orbs and Pet Eggs* Указать количество для сфер титанов и яиц петов*/if (isChecked('countControl') &&(call.name == 'pet_chestOpen' ||call.name == 'titanUs###mmonCircle') &&call.args.amount > 1) {const startAmount = call.args.amount;const r###lt = await popup.confirm(I18N('MSG_SPECIFY_QUANT'), [{ msg: I18N('BTN_OPEN'), isInput: true, default: 1},]);if (r###lt) {const item = call.name == 'pet_chestOpen' ? { id: 90, type: 'consumable' } : { id: 13, type: 'coin' };cheats.updateInventory({[item.type]: {[item.id]: -(r###lt - startAmount),},});call.args.amount = r###lt;changeRequest = true;}}/*** Specify the amount for keys and spheres of titan artifacts* Указать колличество для ключей и сфер артефактов титанов*/if (isChecked('countControl') &&(call.name == 'artifactChestOpen' ||call.name == 'titanArtifactChestOpen') &&call.args.amount > 1 &&call.args.free &&!changeRequest) {artifactChestOpenCallName = call.name;const startAmount = call.args.amount;let r###lt = await popup.confirm(I18N('MSG_SPECIFY_QUANT'), [{ msg: I18N('BTN_OPEN'), isInput: true, default: 1 },]);if (r###lt) {const openChests = r###lt;let sphere = r###lt < 10 ? 1 : 10;call.args.amount = sphere;for (let count = openChests - sphere; count > 0; count -= sphere) {if (count < 10) sphere = 1;const ident = artifactChestOpenCallName + "_" + count;testData.calls.push({name: artifactChestOpenCallName,args: {amount: sphere,free: true,},ident: ident});if (!Array.isArray(requestHistory[this.uniqid].calls[call.name])) {requestHistory[this.uniqid].calls[call.name] = [requestHistory[this.uniqid].calls[call.name]];}requestHistory[this.uniqid].calls[call.name].push(ident);}const consumableId = call.name == 'artifactChestOpen' ? 45 : 55;cheats.updateInventory({consumable: {[consumableId]: -(openChests - startAmount),},});artifactChestOpen = true;changeRequest = true;}}if (call.name == 'consumableUseLootBox') {lastRussianDollId = call.args.libId;/*** Specify quantity for gold caskets* Указать количество для золотых шкатулок*/if (isChecked('countControl') &&call.args.libId == 148 &&call.args.amount > 1) {const r###lt = await popup.confirm(I18N('MSG_SPECIFY_QUANT'), [{ msg: I18N('BTN_OPEN'), isInput: true, default: call.args.amount},]);call.args.amount = r###lt;changeRequest = true;}if (isChecked('countControl') && call.args.libId >= 362 && call.args.libId <= 389) {this.massOpen = call.args.libId;}}if (call.name == 'invasion_bossStart' && isChecked('tryFixIt_v2') && call.args.id == invasionInfo.id) {const pack = invasionDataPacks[invasionInfo.bossLvl];if (pack) {if (pack.buff != invasionInfo.buff) {setProgress(I18N('INVASION_BOSS_BUFF', {bossLvl: invasionInfo.bossLvl,needBuff: pack.buff,haveBuff: invasionInfo.buff,}),false);} else {call.args.pet = pack.pet;call.args.heroes = pack.heroes;call.args.favor = pack.favor;changeRequest = true;}}}if (call.name == 'workshopBuff_create') {const pack = invasionDataPacks[invasionInfo.bossLvl];if (pack) {const addBuff = call.args.amount * 5;if (pack.buff < addBuff + invasionInfo.buff) {this.errorRequest = true;}setProgress(I18N('INVASION_BOSS_BUFF', {bossLvl: invasionInfo.bossLvl,needBuff: pack.buff,haveBuff: invasionInfo.buff,}),false);}}/*** Changing the maximum number of raids in the campaign* Изменение максимального количества рейдов в кампании*/// if (call.name == 'missionRaid') {// if (isChecked('countControl') && call.args.times > 1) {// const r###lt = +(await popup.confirm(I18N('MSG_SPECIFY_QUANT'), [// { msg: I18N('BTN_RUN'), isInput: true, default: call.args.times },// ]));// call.args.times = r###lt > call.args.times ? call.args.times : r###lt;// changeRequest = true;// }// }}let headers = requestHistory[this.uniqid].headers;if (changeRequest) {sourceData = JSON.stringify(testData);headers['X-Auth-Signature'] = getSignature(headers, sourceData);}let signature = headers['X-Auth-Signature'];if (signature) {original.setRequestHeader.call(this, 'X-Auth-Signature', signature);}} catch (err) {console.log("Request(send, " + this.uniqid + "):\n", sourceData, "Error:\n", err);}return sourceData;}/*** Processing and substitution of incoming data** Обработка и подмена входящих данных*/async function checkChangeResponse(response) {try {isChange = false;let nowTime = Math.round(Date.now() / 1000);callsIdent = requestHistory[this.uniqid].calls;respond = JSON.parse(response);/*** If the request returned an error removes the error (removes synchronization errors)* Если запрос вернул ошибку удаляет ошибку (убирает ошибки синхронизации)*/if (respond.error) {isChange = true;console.error(respond.error);if (isChecked('showErrors')) {popup.confirm(I18N('ERROR_MSG', {name: respond.error.name,description: respond.error.description,}));}if (respond.error.name != 'AccountBan') {delete respond.error;respond.r###lts = [];}}let mainReward = null;const allReward = {};let countTypeReward = 0;let readQuestInfo = false;for (const call of respond.r###lts) {/*** Obtaining initial data for completing quests* Получение исходных данных для выполнения квестов*/if (readQuestInfo) {questsInfo[call.ident] = call.r###lt.response;}/*** Getting a user ID* Получение идетификатора пользователя*/if (call.ident == callsIdent['registration']) {userId = call.r###lt.response.userId;if (localStorage['userId'] != userId) {localStorage['newGiftSendIds'] = '';localStorage['userId'] = userId;}await openOrMigrateDatabase(userId);readQuestInfo = true;}/*** Hiding donation offers 1* Скрываем предложения доната 1*/if (call.ident == callsIdent['billingGetAll'] && getSaveVal('noOfferDonat')) {const billings = call.r###lt.response?.billings;const bundle = call.r###lt.response?.bundle;if (billings && bundle) {call.r###lt.response.billings = call.r###lt.response.billings.filter((e) => ['repeatableOffer'].includes(e.type));call.r###lt.response.bundle = [];isChange = true;}}/*** Hiding donation offers 2* Скрываем предложения доната 2*/if (getSaveVal('noOfferDonat') &&(call.ident == callsIdent['offerGetAll'] ||call.ident == callsIdent['specialOffer_getAll'])) {let offers = call.r###lt.response;if (offers) {call.r###lt.response = offers.filter((e) => !['addBilling', 'bundleCarousel'].includes(e.type) || ['idleResource', 'stagesOffer'].includes(e.offerType));isChange = true;}}/*** Hiding donation offers 3* Скрываем предложения доната 3*/if (getSaveVal('noOfferDonat') && call.r###lt?.bundleUpdate) {delete call.r###lt.bundleUpdate;isChange = true;}/*** Hiding donation offers 4* Скрываем предложения доната 4*/if (call.r###lt?.specialOffers) {const offers = call.r###lt.specialOffers;call.r###lt.specialOffers = offers.filter((e) => !['addBilling', 'bundleCarousel'].includes(e.type) || ['idleResource', 'stagesOffer'].includes(e.offerType));isChange = true;}/*** Copies a quiz question to the clipboard* Копирует вопрос викторины в буфер обмена и получает на него ответ если есть*/if (call.ident == callsIdent['quiz_getNewQuestion']) {let quest = call.r###lt.response;console.log(quest.question);copyText(quest.question);setProgress(I18N('QUESTION_COPY'), true);quest.lang = null;if (typeof NXFlashVars !== 'undefined') {quest.lang = NXFlashVars.interface_lang;}lastQuestion = quest;if (isChecked('getAnswer')) {const answer = await getAnswer(lastQuestion);let showText = '';if (answer) {lastAnswer = answer;console.log(answer);showText = `${I18N('ANSWER_KNOWN')}: ${answer}`;} else {showText = I18N('ANSWER_NOT_KNOWN');}try {const hint = hintQuest(quest);if (hint) {showText += I18N('HINT') + hint;}} catch (e) {}setProgress(showText, true);}}/*** Submits a question with an answer to the database* Отправляет вопрос с ответом в базу данных*/if (call.ident == callsIdent['quiz_answer']) {const answer = call.r###lt.response;if (lastQuestion) {const answerInfo = {answer,question: lastQuestion,lang: null,};if (typeof NXFlashVars !== 'undefined') {answerInfo.lang = NXFlashVars.interface_lang;}lastQuestion = null;setTimeout(sendAnswerInfo, 0, answerInfo);}}/*** Get user data* Получить даныне пользователя*/if (call.ident == callsIdent['userGetInfo']) {let user = call.r###lt.response;document.title = user.name;userInfo = Object.assign({}, user);delete userInfo.refillable;if (!questsInfo['userGetInfo']) {questsInfo['userGetInfo'] = user;}}/*** Start of the battle for recalculation* Начало боя для прерасчета*/if (call.ident == callsIdent['clanWarAttack'] ||call.ident == callsIdent['crossClanWar_startBattle'] ||call.ident == callsIdent['bossAttack'] ||call.ident == callsIdent['battleGetReplay'] ||call.ident == callsIdent['brawl_startBattle'] ||call.ident == callsIdent['adventureSolo_turnStartBattle'] ||call.ident == callsIdent['invasion_bossStart'] ||call.ident == callsIdent['titanArenaStartBattle'] ||call.ident == callsIdent['towerStartBattle'] ||call.ident == callsIdent['epicBrawl_startBattle'] ||call.ident == callsIdent['adventure_turnStartBattle']) {let battle = call.r###lt.response.battle || call.r###lt.response.replay;if (call.ident == callsIdent['brawl_startBattle'] ||call.ident == callsIdent['bossAttack'] ||call.ident == callsIdent['towerStartBattle'] ||call.ident == callsIdent['invasion_bossStart']) {battle = call.r###lt.response;}lastBattleInfo = battle;if (call.ident == callsIdent['battleGetReplay'] && call.r###lt.response.replay.type === "clan_raid") {if (call?.r###lt?.response?.replay?.r###lt?.damage) {const damages = Object.values(call.r###lt.response.replay.r###lt.damage);const bossDamage = damages.reduce((a, v) => a + v, 0);setProgress(I18N('BOSS_DAMAGE') + bossDamage.toLocaleString(), false, hideProgress);continue;}}if (!isChecked('preCalcBattle')) {continue;}const preCalcBattle = structuredClone(battle);setProgress(I18N('BEING_RECALC'));let battleDuration = 120;try {const typeBattle = getBattleType(preCalcBattle.type);battleDuration = +lib.data.battleConfig[typeBattle.split('_')[1]].config.battleDuration;} catch (e) { }//console.log(battle.type);function getBattleInfo(battle, isRandSeed) {return new Promise(function (resolve) {if (isRandSeed) {battle.seed = Math.floor(Date.now() / 1000) + random(0, 1e3);}BattleCalc(battle, getBattleType(battle.type), e => resolve(e));});}let actions = [getBattleInfo(preCalcBattle, false)];let countTestBattle = getInput('countTestBattle');if (call.ident == callsIdent['invasion_bossStart'] ) {countTestBattle = 0;}if (call.ident == callsIdent['battleGetReplay']) {preCalcBattle.progress = [{ attackers: { input: ['auto', 0, 0, 'auto', 0, 0] } }];}for (let i = 0; i < countTestBattle; i++) {actions.push(getBattleInfo(preCalcBattle, true));}Promise.all(actions).then(e => {e = e.map(n => ({win: n.r###lt.win, time: n.battleTime}));let firstBattle = e.shift();const timer = Math.floor(battleDuration - firstBattle.time);const min = ('00' + Math.floor(timer / 60)).slice(-2);const sec = ('00' + Math.floor(timer - min * 60)).slice(-2);let msg = `${I18N('THIS_TIME')} ${firstBattle.win ? I18N('VICTORY') : I18N('DEFEAT')}`;if (e.length) {const countWin = e.reduce((w, s) => w + s.win, 0);msg += ` ${I18N('CHANCE_TO_WIN')}: ${Math.floor((countWin / e.length) * 100)}% (${e.length})`;}msg += `, ${min}:${sec}`setProgress(msg, false, hideProgress)});}/*** Start of the Asgard boss fight* Начало боя с боссом Асгарда*/if (call.ident == callsIdent['clanRaid_startBossBattle']) {lastBossBattle = call.r###lt.response.battle;lastBossBattle.endTime = Date.now() + 160 * 1000;if (isChecked('preCalcBattle')) {const r###lt = await Calc(lastBossBattle).then(e => e.progress[0].defenders.heroes[1].extra);const bossDamage = r###lt.damageTaken + r###lt.damageTakenNextLevel;setProgress(I18N('BOSS_DAMAGE') + bossDamage.toLocaleString(), false, hideProgress);}}/*** Cancel tutorial* Отмена туториала*/if (isCanceledTutorial && call.ident == callsIdent['tutorialGetInfo']) {let chains = call.r###lt.response.chains;for (let n in chains) {chains[n] = 9999;}isChange = true;}/*** Opening keys and spheres of titan artifacts* Открытие ключей и сфер артефактов титанов*/if (artifactChestOpen &&(call.ident == callsIdent[artifactChestOpenCallName] ||(callsIdent[artifactChestOpenCallName] && callsIdent[artifactChestOpenCallName].includes(call.ident)))) {let reward = call.r###lt.response[artifactChestOpenCallName == 'artifactChestOpen' ? 'chestReward' : 'reward'];reward.forEach(e => {for (let f in e) {if (!allReward[f]) {allReward[f] = {};}for (let o in e[f]) {if (!allReward[f][o]) {allReward[f][o] = e[f][o];countTypeReward++;} else {allReward[f][o] += e[f][o];}}}});if (!call.ident.includes(artifactChestOpenCallName)) {mainReward = call.r###lt.response;}}if (countTypeReward > 20) {correctShowOpenArtifact = 3;} else {correctShowOpenArtifact = 0;}/*** Sum the r###lt of opening Pet Eggs* Суммирование результата открытия яиц питомцев*/if (isChecked('countControl') && call.ident == callsIdent['pet_chestOpen']) {const rewards = call.r###lt.response.rewards;if (rewards.length > 10) {/*** Removing pet cards* Убираем карточки петов*/for (const reward of rewards) {if (reward.petCard) {delete reward.petCard;}}}rewards.forEach(e => {for (let f in e) {if (!allReward[f]) {allReward[f] = {};}for (let o in e[f]) {if (!allReward[f][o]) {allReward[f][o] = e[f][o];} else {allReward[f][o] += e[f][o];}}}});call.r###lt.response.rewards = [allReward];isChange = true;}/*** Removing titan cards* Убираем карточки титанов*/if (call.ident == callsIdent['titanUs###mmonCircle']) {if (call.r###lt.response.rewards.length > 10) {for (const reward of call.r###lt.response.rewards) {if (reward.titanCard) {delete reward.titanCard;}}isChange = true;}}/*** Auto-repeat opening matryoshkas* АвтоПовтор открытия матрешек*/if (isChecked('countControl') && call.ident == callsIdent['consumableUseLootBox']) {let [countLootBox, lootBox] = Object.entries(call.r###lt.response).pop();countLootBox = +countLootBox;let newCount = 0;if (lootBox?.consumable && lootBox.consumable[lastRussianDollId]) {newCount += lootBox.consumable[lastRussianDollId];delete lootBox.consumable[lastRussianDollId];}if (newCount &&(await popup.confirm(`${I18N('BTN_OPEN')} ${newCount} ${I18N('OPEN_DOLLS')}?`, [{ msg: I18N('BTN_OPEN'), r###lt: true },{ msg: I18N('BTN_NO'), r###lt: false, isClose: true },]))) {const [count, recursionR###lt] = await openRussianDolls(lastRussianDollId, newCount);countLootBox += +count;mergeItemsObj(lootBox, recursionR###lt);isChange = true;}if (this.massOpen) {if (await popup.confirm(I18N('OPEN_ALL_EQUIP_BOXES'), [{ msg: I18N('BTN_OPEN'), r###lt: true },{ msg: I18N('BTN_NO'), r###lt: false, isClose: true },])) {const consumable = await Send({ calls: [{ name: 'inventoryGet', args: {}, ident: 'inventoryGet' }] }).then((e) =>Object.entries(e.r###lts[0].r###lt.response.consumable));const calls = [];const deleteItems = {};for (const [libId, amount] of consumable) {if (libId != this.massOpen && libId >= 362 && libId <= 389) {calls.push({name: 'consumableUseLootBox',args: { libId, amount },ident: 'consumableUseLootBox_' + libId,});deleteItems[libId] = -amount;}}const responses = await Send({ calls }).then((e) => e.r###lts.map((r) => r.r###lt.response).flat());for (const loot of responses) {const [count, r###lt] = Object.entries(loot).pop();countLootBox += +count;mergeItemsObj(lootBox, r###lt);}isChange = true;this.onReadySuccess = () => {cheats.updateInventory({ consumable: deleteItems });cheats.refreshInventory();};}}if (isChange) {call.r###lt.response = {[countLootBox]: lootBox,};}}/*** Dungeon recalculation (fix endless cards)* Прерасчет подземки (исправление бесконечных карт)*/if (call.ident == callsIdent['dungeonStartBattle']) {lastDungeonBattleData = call.r###lt.response;lastDungeonBattleStart = Date.now();}/*** Getting the number of prediction cards* Получение количества карт предсказаний*/if (call.ident == callsIdent['inventoryGet']) {countPredictionCard = call.r###lt.response.consumable[81] || 0;}/*** Getting subscription status* Получение состояния подписки*/if (call.ident == callsIdent['subscriptionGetInfo']) {const subscription = call.r###lt.response.subscription;if (subscription) {subEndTime = subscription.endTime * 1000;}}/*** Getting prediction cards* Получение карт предсказаний*/if (call.ident == callsIdent['questFarm']) {const consumable = call.r###lt.response?.consumable;if (consumable && consumable[81]) {countPredictionCard += consumable[81];console.log(`Cards: ${countPredictionCard}`);}}/*** Hiding extra servers* Скрытие лишних серверов*/if (call.ident == callsIdent['serverGetAll'] && isChecked('hideServers')) {let servers = call.r###lt.response.users.map(s => s.serverId)call.r###lt.response.servers = call.r###lt.response.servers.filter(s => servers.includes(s.id));isChange = true;}/*** Displays player positions in the adventure* Отображает позиции игроков в приключении*/if (call.ident == callsIdent['adventure_getLobbyInfo']) {const users = Object.values(call.r###lt.response.users);const mapIdent = call.r###lt.response.mapIdent;const adventureId = call.r###lt.response.adventureId;const maps = {adv_strongford_3pl_hell: 9,adv_valley_3pl_hell: 10,adv_ghirwil_3pl_hell: 11,adv_angels_3pl_hell: 12,}let msg = I18N('MAP') + (mapIdent in maps ? maps[mapIdent] : adventureId);msg += '<br>' + I18N('PLAYER_POS');for (const user of users) {msg += `<br>${user.user.name} - ${user.currentNode}`;}setProgress(msg, false, hideProgress);}/*** Automatic launch of a raid at the end of the adventure* Автоматический запуск рейда при окончании приключения*/if (call.ident == callsIdent['adventure_end']) {autoRaidAdventure()}/** Удаление лавки редкостей */if (call.ident == callsIdent['missionRaid']) {if (call.r###lt?.heroesMerchant) {delete call.r###lt.heroesMerchant;isChange = true;}}/** missionTimer */if (call.ident == callsIdent['missionStart']) {missionBattle = call.r###lt.response;}/** Награды турнира стихий */if (call.ident == callsIdent['hallOfFameGetTrophies']) {const trophys = call.r###lt.response;const calls = [];for (const week in trophys) {const trophy = trophys[week];if (!trophy.championRewardFarmed) {calls.push({name: 'hallOfFameFarmTrophyReward',args: { trophyId: week, rewardType: 'champion' },ident: 'body_champion_' + week,});}if (Object.keys(trophy.clanReward).length && !trophy.clanRewardFarmed) {calls.push({name: 'hallOfFameFarmTrophyReward',args: { trophyId: week, rewardType: 'clan' },ident: 'body_clan_' + week,});}}if (calls.length) {Send({ calls }).then((e) => e.r###lts.map((e) => e.r###lt.response)).then(async r###lts => {let coin18 = 0,coin19 = 0,gold = 0,starmoney = 0;for (const r of r###lts) {coin18 += r?.coin ? +r.coin[18] : 0;coin19 += r?.coin ? +r.coin[19] : 0;gold += r?.gold ? +r.gold : 0;starmoney += r?.starmoney ? +r.starmoney : 0;}let msg = I18N('ELEMENT_TOURNAMENT_REWARD') + '<br>';if (coin18) {msg += cheats.translate('LIB_COIN_NAME_18') + `: ${coin18}<br>`;}if (coin19) {msg += cheats.translate('LIB_COIN_NAME_19') + `: ${coin19}<br>`;}if (gold) {msg += cheats.translate('LIB_PSEUDO_COIN') + `: ${gold}<br>`;}if (starmoney) {msg += cheats.translate('LIB_PSEUDO_STARMONEY') + `: ${starmoney}<br>`;}await popup.confirm(msg, [{ msg: I18N('BTN_OK'), r###lt: 0 }]);});}}if (call.ident == callsIdent['clanDomination_getInfo']) {clanDominationGetInfo = call.r###lt.response;}if (call.ident == callsIdent['clanRaid_endBossBattle']) {console.log(call.r###lt.response);const damage = Object.values(call.r###lt.response.damage).reduce((a, e) => a + e);if (call.r###lt.response.r###lt.afterInvalid) {addProgress('<br>' + I18N('SERVER_NOT_ACCEPT'));}addProgress('<br>Server > ' + I18N('BOSS_DAMAGE') + damage.toLocaleString());}if (call.ident == callsIdent['invasion_getInfo']) {const r = call.r###lt.response;if (r?.actions?.length) {const boss = r.actions.find((e) => e.payload.id === invasionInfo.id);if (boss) {invasionInfo.buff = r.buffAmount;invasionInfo.bossLvl = boss.payload.level;if (isChecked('tryFixIt_v2')) {const pack = invasionDataPacks[invasionInfo.bossLvl];if (pack) {setProgress(I18N('INVASION_BOSS_BUFF', {bossLvl: invasionInfo.bossLvl,needBuff: pack.buff,haveBuff: invasionInfo.buff,}),false);}}}}}if (call.ident == callsIdent['workshopBuff_create']) {const r = call.r###lt.response;if (r.id == 1) {invasionInfo.buff = r.amount;if (isChecked('tryFixIt_v2')) {const pack = invasionDataPacks[invasionInfo.bossLvl];if (pack) {setProgress(I18N('INVASION_BOSS_BUFF', {bossLvl: invasionInfo.bossLvl,needBuff: pack.buff,haveBuff: invasionInfo.buff,}),false);}}}}/*if (call.ident == callsIdent['chatGetAll'] && call.args.chatType == 'clanDomination' && !callsIdent['clanDomination_mapState']) {this.onReadySuccess = async function () {const r###lt = await Send({calls: [{name: 'clanDomination_mapState',args: {},ident: 'clanDomination_mapState',},],}).then((e) => e.r###lts[0].r###lt.response);let townPositions = r###lt.townPositions;let positions = {};for (let pos in townPositions) {let townPosition = townPositions[pos];positions[townPosition.position] = townPosition;}Object.assign(clanDominationGetInfo, {townPositions: positions,});let userPositions = r###lt.userPositions;for (let pos in clanDominationGetInfo.townPositions) {let townPosition = clanDominationGetInfo.townPositions[pos];if (townPosition.status) {userPositions[townPosition.userId] = +pos;}}cheats.updateMap(r###lt);};}if (call.ident == callsIdent['clanDomination_mapState']) {const townPositions = call.r###lt.response.townPositions;const userPositions = call.r###lt.response.userPositions;for (let pos in townPositions) {let townPos = townPositions[pos];if (townPos.status) {userPositions[townPos.userId] = townPos.position;}}isChange = true;}*/}if (mainReward && artifactChestOpen) {console.log(allReward);mainReward[artifactChestOpenCallName == 'artifactChestOpen' ? 'chestReward' : 'reward'] = [allReward];artifactChestOpen = false;artifactChestOpenCallName = '';isChange = true;}} catch(err) {console.log("Request(response, " + this.uniqid + "):\n", "Error:\n", response, err);}if (isChange) {Object.defineProperty(this, 'responseText', {writable: true});this.responseText = JSON.stringify(respond);}}/*** Request an answer to a question** Запрос ответа на вопрос*/async function getAnswer(question) {// c29tZSBzdHJhbmdlIHN5bWJvbHM=const quizAPI = new ZingerYWebsiteAPI('getAnswer.php', arguments, { question });return new Promise((resolve, reject) => {quizAPI.request().then((data) => {if (data.r###lt) {resolve(data.r###lt);} else {resolve(false);}}).catch((error) => {console.error(error);resolve(false);});})}/*** Submitting a question and answer to a database** Отправка вопроса и ответа в базу данных*/function sendAnswerInfo(answerInfo) {// c29tZSBub25zZW5zZQ==const quizAPI = new ZingerYWebsiteAPI('setAnswer.php', arguments, { answerInfo });quizAPI.request().then((data) => {if (data.r###lt) {console.log(I18N('SENT_QUESTION'));}});}/*** Returns the battle type by preset type** Возвращает тип боя по типу пресета*/function getBattleType(strBattleType) {if (!strBattleType) {return null;}switch (strBattleType) {case 'titan_pvp':return 'get_titanPvp';case 'titan_pvp_manual':case 'titan_clan_pvp':case 'clan_pvp_titan':case 'clan_global_pvp_titan':case 'brawl_titan':case 'challenge_titan':case 'titan_mission':return 'get_titanPvpManual';case 'clan_raid': // Asgard Boss // Босс асгардаcase 'adventure': // Adventures // Приключенияcase 'clan_global_pvp':case 'epic_brawl':case 'clan_pvp':return 'get_clanPvp';case 'dungeon_titan':case 'titan_tower':return 'get_titan';case 'tower':case 'clan_dungeon':return 'get_tower';case 'pve':case 'mission':return 'get_pve';case 'mission_boss':return 'get_missionBoss';case 'challenge':case 'pvp_manual':return 'get_pvpManual';case 'grand':case 'arena':case 'pvp':case 'clan_domination':return 'get_pvp';case 'core':return 'get_core';default: {if (strBattleType.includes('invasion')) {return 'get_invasion';}if (strBattleType.includes('boss')) {return 'get_boss';}if (strBattleType.includes('titan_arena')) {return 'get_titanPvpManual';}return 'get_clanPvp';}}}/*** Returns the class name of the passed object** Возвращает название класса переданного объекта*/function getClass(obj) {return {}.toString.call(obj).slice(8, -1);}/*** Calculates the request signature** Расчитывает сигнатуру запроса*/this.getSignature = function(headers, data) {const sign = {signature: '',length: 0,add: function (text) {this.signature += text;if (this.length < this.signature.length) {this.length = 3 * (this.signature.length + 1) >> 1;}},}sign.add(headers["X-Request-Id"]);sign.add(':');sign.add(headers["X-Auth-Token"]);sign.add(':');sign.add(headers["X-Auth-Session-Id"]);sign.add(':');sign.add(data);sign.add(':');sign.add('LIBRARY-VERSION=1');sign.add('UNIQUE-SESSION-ID=' + headers["X-Env-Unique-Session-Id"]);return md5(sign.signature);}class HotkeyManager {constructor() {if (HotkeyManager.instance) {return HotkeyManager.instance;}this.hotkeys = [];document.addEventListener('keydown', this.handleKeyDown.bind(this));HotkeyManager.instance = this;}handleKeyDown(event) {const key = event.key.toLowerCase();const mods = {ctrl: event.ctrlKey,alt: event.altKey,shift: event.shiftKey,};this.hotkeys.forEach((hotkey) => {if (hotkey.key === key && hotkey.ctrl === mods.ctrl && hotkey.alt === mods.alt && hotkey.shift === mods.shift) {hotkey.callback(hotkey);}});}add(key, opt = {}, callback) {this.hotkeys.push({key: key.toLowerCase(),callback,ctrl: opt.ctrl || false,alt: opt.alt || false,shift: opt.shift || false,});}remove(key, opt = {}) {this.hotkeys = this.hotkeys.filter((hotkey) => {return !(hotkey.key === key.toLowerCase() &&hotkey.ctrl === (opt.ctrl || false) &&hotkey.alt === (opt.alt || false) &&hotkey.shift === (opt.shift || false));});}static getInst() {if (!HotkeyManager.instance) {new HotkeyManager();}return HotkeyManager.instance;}}class MouseClicker {constructor(element) {if (MouseClicker.instance) {return MouseClicker.instance;}this.element = element;this.mouse = {bubbles: true,cancelable: true,clientX: 0,clientY: 0,};this.element.addEventListener('mousemove', this.handleMouseMove.bind(this));this.clickInfo = {};this.nextTimeoutId = 1;MouseClicker.instance = this;}handleMouseMove(event) {this.mouse.clientX = event.clientX;this.mouse.clientY = event.clientY;}click(options) {options = options || this.mouse;this.element.dispatchEvent(new MouseEvent('mousedown', options));this.element.dispatchEvent(new MouseEvent('mouseup', options));}start(interval = 1000, clickCount = Infinity) {const currentMouse = { ...this.mouse };const timeoutId = this.nextTimeoutId++;let count = 0;const clickTimeout = () => {this.click(currentMouse);count++;if (count < clickCount) {this.clickInfo[timeoutId].timeout = setTimeout(clickTimeout, interval);} else {delete this.clickInfo[timeoutId];}};this.clickInfo[timeoutId] = {timeout: setTimeout(clickTimeout, interval),count: clickCount,};return timeoutId;}stop(timeoutId) {if (this.clickInfo[timeoutId]) {clearTimeout(this.clickInfo[timeoutId].timeout);delete this.clickInfo[timeoutId];}}stopAll() {for (const timeoutId in this.clickInfo) {clearTimeout(this.clickInfo[timeoutId].timeout);}this.clickInfo = {};}static getInst(element) {if (!MouseClicker.instance) {new MouseClicker(element);}return MouseClicker.instance;}}let extintionsList = [];/*** Creates an interface** Создает интерфейс*/function createInterface() {popup.init();const { ScriptMenu } = HWHClasses;const scriptMenu = ScriptMenu.getInst();scriptMenu.init();scriptMenu.addHeader(GM_info.script.name, justInfo);const versionHeader = scriptMenu.addHeader('v' + GM_info.script.version);if (extintionsList.length) {versionHeader.title = '';versionHeader.style.color = 'red';for (const extintion of extintionsList) {const { name, ver, author } = extintion;versionHeader.title += name + ', v' + ver + ' by ' + author + '\n';}}// AutoClickerconst hkm = new HotkeyManager();const fc = document.getElementById('flash-content') || document.getElementById('game');const mc = new MouseClicker(fc);function toggleClicker(self, timeout) {if (self.onClick) {console.log('Останавливаем клики');mc.stop(self.onClick);self.onClick = false;} else {console.log('Стартуем клики');self.onClick = mc.start(timeout);}}hkm.add('C', { ctrl: true, alt: true }, (self) => {console.log('"Ctrl + Alt + C"');toggleClicker(self, 20);});hkm.add('V', { ctrl: true, alt: true }, (self) => {console.log('"Ctrl + Alt + V"');toggleClicker(self, 100);});}function addExtentionName(name, ver, author) {extintionsList.push({name,ver,author,});}function addControls() {createInterface();const { ScriptMenu } = HWHClasses;const scriptMenu = ScriptMenu.getInst();const checkboxDetails = scriptMenu.addDetails(I18N('SETTINGS'), 'settings');for (let name in checkboxes) {if (checkboxes[name].hide) {continue;}checkboxes[name].cbox = scriptMenu.addCheckbox(checkboxes[name].label, checkboxes[name].title, checkboxDetails);/*** Getting the state of checkboxes from storage* Получаем состояние чекбоксов из storage*/let val = storage.get(name, null);if (val != null) {checkboxes[name].cbox.checked = val;} else {storage.set(name, checkboxes[name].default);checkboxes[name].cbox.checked = checkboxes[name].default;}/*** Tracing the change event of the checkbox for writing to storage* Отсеживание события изменения чекбокса для записи в storage*/checkboxes[name].cbox.dataset['name'] = name;checkboxes[name].cbox.addEventListener('change', async function (event) {const nameCheckbox = this.dataset['name'];/*if (this.checked && nameCheckbox == 'cancelBattle') {this.checked = false;if (await popup.confirm(I18N('MSG_BAN_ATTENTION'), [{ msg: I18N('BTN_NO_I_AM_AGAINST'), r###lt: true },{ msg: I18N('BTN_YES_I_AGREE'), r###lt: false },])) {return;}this.checked = true;}*/storage.set(nameCheckbox, this.checked);})}const inputDetails = scriptMenu.addDetails(I18N('VALUES'), 'values');for (let name in inputs) {inputs[name].input = scriptMenu.addInputText(inputs[name].title, false, inputDetails);/*** Get inputText state from storage* Получаем состояние inputText из storage*/let val = storage.get(name, null);if (val != null) {inputs[name].input.value = val;} else {storage.set(name, inputs[name].default);inputs[name].input.value = inputs[name].default;}/*** Tracing a field change event for a record in storage* Отсеживание события изменения поля для записи в storage*/inputs[name].input.dataset['name'] = name;inputs[name].input.addEventListener('input', function () {const inputName = this.dataset['name'];let value = +this.value;if (!value || Number.isNaN(value)) {value = storage.get(inputName, inputs[inputName].default);inputs[name].input.value = value;}storage.set(inputName, value);})}}/*** Sending a request** Отправка запроса*/function send(json, callback, pr) {if (typeof json == 'string') {json = JSON.parse(json);}for (const call of json.calls) {if (!call?.context?.actionTs) {call.context = {actionTs: Math.floor(performance.now())}}}json = JSON.stringify(json);/*** We get the headlines of the previous intercepted request* Получаем заголовки предыдущего перехваченого запроса*/let headers = lastHeaders;/*** We increase the header of the query Certifier by 1* Увеличиваем заголовок идетификатора запроса на 1*/headers["X-Request-Id"]++;/*** We calculate the title with the signature* Расчитываем заголовок с сигнатурой*/headers["X-Auth-Signature"] = getSignature(headers, json);/*** Create a new ajax request* Создаем новый AJAX запрос*/let xhr = new XMLHttpRequest;/*** Indicate the previously saved URL for API queries* Указываем ранее сохраненный URL для API запросов*/xhr.open('POST', apiUrl, true);/*** Add the function to the event change event* Добавляем функцию к событию смены статуса запроса*/xhr.onreadystatechange = function() {/*** If the r###lt of the request is obtained, we call the flask function* Если результат запроса получен вызываем колбек функцию*/if(xhr.readyState == 4) {callback(xhr.response, pr);}};/*** Indicate the type of request* Указываем тип запроса*/xhr.responseType = 'json';/*** We set the request headers* Задаем заголовки запроса*/for(let nameHeader in headers) {let head = headers[nameHeader];xhr.setRequestHeader(nameHeader, head);}/*** Sending a request* Отправляем запрос*/xhr.send(json);}let hideTimeoutProgress = 0;/*** Hide progress** Скрыть прогресс*/function hideProgress(timeout) {const { ScriptMenu } = HWHClasses;const scriptMenu = ScriptMenu.getInst();timeout = timeout || 0;clearTimeout(hideTimeoutProgress);hideTimeoutProgress = setTimeout(function () {scriptMenu.setStatus('');}, timeout);}/*** Progress display** Отображение прогресса*/function setProgress(text, hide, onclick) {const { ScriptMenu } = HWHClasses;const scriptMenu = ScriptMenu.getInst();scriptMenu.setStatus(text, onclick);hide = hide || false;if (hide) {hideProgress(3000);}}/*** Progress added** Дополнение прогресса*/function addProgress(text) {const { ScriptMenu } = HWHClasses;const scriptMenu = ScriptMenu.getInst();scriptMenu.addStatus(text);}/*** Returns the timer value depending on the subscription** Возвращает значение таймера в зависимости от подписки*/function getTimer(time, div) {let speedDiv = 5;if (subEndTime < Date.now()) {speedDiv = div || 1.5;}return Math.max(Math.ceil(time / speedDiv + 1.5), 4);}function startSlave() {const { slaveFixBattle } = HWHClasses;const sFix = new slaveFixBattle();sFix.wsStart();}this.testFuntions = {hideProgress,setProgress,addProgress,masterFix: false,startSlave,};this.HWHFuncs = {send,I18N,isChecked,getInput,copyText,confShow,hideProgress,setProgress,addProgress,getTimer,addExtentionName,getUserInfo,setIsCancalBattle,random,};this.HWHClasses = {checkChangeSend,checkChangeResponse,};/*** Calculates HASH MD5 from string** Расчитывает HASH MD5 из строки** [js-md5]{@link https://github.com/emn178/js-md5}** @namespace md5* @version 0.7.3* @author Chen, Yi-Cyuan [emn178@gmail.com]* @copyright Chen, Yi-Cyuan 2014-2017* @license MIT*/!function(){"use strict";function t(t){if(t)d[0]=d[16]=d[1]=d[2]=d[3]=d[4]=d[5]=d[6]=d[7]=d[8]=d[9]=d[10]=d[11]=d[12]=d[13]=d[14]=d[15]=0,this.blocks=d,this.buffer8=l;else if(a){var r=new ArrayBuffer(68);this.buffer8=new Uint8Array(r),this.blocks=new Uint32Array(r)}else this.blocks=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];this.h0=this.h1=this.h2=this.h3=this.start=this.bytes=this.hBytes=0,this.finalized=this.hashed=!1,this.first=!0}var r="input is invalid type",e="object"==typeof window,i=e?window:{};i.JS_MD5_NO_WINDOW&&(e=!1);var s=!e&&"object"==typeof self,h=!i.JS_MD5_NO_NODE_JS&&"object"==typeof process&&process.versions&&process.versions.node;h?i=global:s&&(i=self);var f=!i.JS_MD5_NO_COMMON_JS&&"object"==typeof module&&module.exports,o="function"==typeof define&&define.amd,a=!i.JS_MD5_NO_ARRAY_BUFFER&&"undefined"!=typeof ArrayBuffer,n="0123456789abcdef".split(""),u=[128,32768,8388608,-2147483648],y=[0,8,16,24],c=["hex","array","digest","buffer","arrayBuffer","base64"],p="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(""),d=[],l;if(a){var A=new ArrayBuffer(68);l=new Uint8Array(A),d=new Uint32Array(A)}!i.JS_MD5_NO_NODE_JS&&Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),!a||!i.JS_MD5_NO_ARRAY_BUFFER_IS_VIEW&&ArrayBuffer.isView||(ArrayBuffer.isView=function(t){return"object"==typeof t&&t.buffer&&t.buffer.constructor===ArrayBuffer});var b=function(r){return function(e){return new t(!0).update(e)[r]()}},v=function(){var r=b("hex");h&&(r=w(r)),r.create=function(){return new t},r.update=function(t){return r.create().update(t)};for(var e=0;e<c.length;++e){var i=c[e];r[i]=b(i)}return r},w=function(t){var e=eval("require('crypto')"),i=eval("require('buffer').Buffer"),s=function(s){if("string"==typeof s)return e.createHash("md5").update(s,"utf8").digest("hex");if(null===s||void 0===s)throw r;return s.constructor===ArrayBuffer&&(s=new Uint8Array(s)),Array.isArray(s)||ArrayBuffer.isView(s)||s.constructor===i?e.createHash("md5").update(new i(s)).digest("hex"):t(s)};return s};t.prototype.update=function(t){if(!this.finalized){var e,i=typeof t;if("string"!==i){if("object"!==i)throw r;if(null===t)throw r;if(a&&t.constructor===ArrayBuffer)t=new Uint8Array(t);else if(!(Array.isArray(t)||a&&ArrayBuffer.isView(t)))throw r;e=!0}for(var s,h,f=0,o=t.length,n=this.blocks,u=this.buffer8;f<o;){if(this.hashed&&(this.hashed=!1,n[0]=n[16],n[16]=n[1]=n[2]=n[3]=n[4]=n[5]=n[6]=n[7]=n[8]=n[9]=n[10]=n[11]=n[12]=n[13]=n[14]=n[15]=0),e)if(a)for(h=this.start;f<o&&h<64;++f)u[h++]=t[f];else for(h=this.start;f<o&&h<64;++f)n[h>>2]|=t[f]<<y[3&h++];else if(a)for(h=this.start;f<o&&h<64;++f)(s=t.charCodeAt(f))<128?u[h++]=s:s<2048?(u[h++]=192|s>>6,u[h++]=128|63&s):s<55296||s>=57344?(u[h++]=224|s>>12,u[h++]=128|s>>6&63,u[h++]=128|63&s):(s=65536+((1023&s)<<10|1023&t.charCodeAt(++f)),u[h++]=240|s>>18,u[h++]=128|s>>12&63,u[h++]=128|s>>6&63,u[h++]=128|63&s);else for(h=this.start;f<o&&h<64;++f)(s=t.charCodeAt(f))<128?n[h>>2]|=s<<y[3&h++]:s<2048?(n[h>>2]|=(192|s>>6)<<y[3&h++],n[h>>2]|=(128|63&s)<<y[3&h++]):s<55296||s>=57344?(n[h>>2]|=(224|s>>12)<<y[3&h++],n[h>>2]|=(128|s>>6&63)<<y[3&h++],n[h>>2]|=(128|63&s)<<y[3&h++]):(s=65536+((1023&s)<<10|1023&t.charCodeAt(++f)),n[h>>2]|=(240|s>>18)<<y[3&h++],n[h>>2]|=(128|s>>12&63)<<y[3&h++],n[h>>2]|=(128|s>>6&63)<<y[3&h++],n[h>>2]|=(128|63&s)<<y[3&h++]);this.lastByteIndex=h,this.bytes+=h-this.start,h>=64?(this.start=h-64,this.hash(),this.hashed=!0):this.start=h}return this.bytes>4294967295&&(this.hBytes+=this.bytes/4294967296<<0,this.bytes=this.bytes%4294967296),this}},t.prototype.finalize=function(){if(!this.finalized){this.finalized=!0;var t=this.blocks,r=this.lastByteIndex;t[r>>2]|=u[3&r],r>=56&&(this.hashed||this.hash(),t[0]=t[16],t[16]=t[1]=t[2]=t[3]=t[4]=t[5]=t[6]=t[7]=t[8]=t[9]=t[10]=t[11]=t[12]=t[13]=t[14]=t[15]=0),t[14]=this.bytes<<3,t[15]=this.hBytes<<3|this.bytes>>>29,this.hash()}},t.prototype.hash=function(){var t,r,e,i,s,h,f=this.blocks;this.first?r=((r=((t=((t=f[0]-680876937)<<7|t>>>25)-271733879<<0)^(e=((e=(-271733879^(i=((i=(-1732584194^2004318071&t)+f[1]-117830708)<<12|i>>>20)+t<<0)&(-271733879^t))+f[2]-1126478375)<<17|e>>>15)+i<<0)&(i^t))+f[3]-1316259209)<<22|r>>>10)+e<<0:(t=this.h0,r=this.h1,e=this.h2,r=((r+=((t=((t+=((i=this.h3)^r&(e^i))+f[0]-680876936)<<7|t>>>25)+r<<0)^(e=((e+=(r^(i=((i+=(e^t&(r^e))+f[1]-389564586)<<12|i>>>20)+t<<0)&(t^r))+f[2]+606105819)<<17|e>>>15)+i<<0)&(i^t))+f[3]-1044525330)<<22|r>>>10)+e<<0),r=((r+=((t=((t+=(i^r&(e^i))+f[4]-176418897)<<7|t>>>25)+r<<0)^(e=((e+=(r^(i=((i+=(e^t&(r^e))+f[5]+1200080426)<<12|i>>>20)+t<<0)&(t^r))+f[6]-1473231341)<<17|e>>>15)+i<<0)&(i^t))+f[7]-45705983)<<22|r>>>10)+e<<0,r=((r+=((t=((t+=(i^r&(e^i))+f[8]+1770035416)<<7|t>>>25)+r<<0)^(e=((e+=(r^(i=((i+=(e^t&(r^e))+f[9]-1958414417)<<12|i>>>20)+t<<0)&(t^r))+f[10]-42063)<<17|e>>>15)+i<<0)&(i^t))+f[11]-1990404162)<<22|r>>>10)+e<<0,r=((r+=((t=((t+=(i^r&(e^i))+f[12]+1804603682)<<7|t>>>25)+r<<0)^(e=((e+=(r^(i=((i+=(e^t&(r^e))+f[13]-40341101)<<12|i>>>20)+t<<0)&(t^r))+f[14]-1502002290)<<17|e>>>15)+i<<0)&(i^t))+f[15]+1236535329)<<22|r>>>10)+e<<0,r=((r+=((i=((i+=(r^e&((t=((t+=(e^i&(r^e))+f[1]-165796510)<<5|t>>>27)+r<<0)^r))+f[6]-1069501632)<<9|i>>>23)+t<<0)^t&((e=((e+=(t^r&(i^t))+f[11]+643717713)<<14|e>>>18)+i<<0)^i))+f[0]-373897302)<<20|r>>>12)+e<<0,r=((r+=((i=((i+=(r^e&((t=((t+=(e^i&(r^e))+f[5]-701558691)<<5|t>>>27)+r<<0)^r))+f[10]+38016083)<<9|i>>>23)+t<<0)^t&((e=((e+=(t^r&(i^t))+f[15]-660478335)<<14|e>>>18)+i<<0)^i))+f[4]-405537848)<<20|r>>>12)+e<<0,r=((r+=((i=((i+=(r^e&((t=((t+=(e^i&(r^e))+f[9]+568446438)<<5|t>>>27)+r<<0)^r))+f[14]-1019803690)<<9|i>>>23)+t<<0)^t&((e=((e+=(t^r&(i^t))+f[3]-187363961)<<14|e>>>18)+i<<0)^i))+f[8]+1163531501)<<20|r>>>12)+e<<0,r=((r+=((i=((i+=(r^e&((t=((t+=(e^i&(r^e))+f[13]-1444681467)<<5|t>>>27)+r<<0)^r))+f[2]-51403784)<<9|i>>>23)+t<<0)^t&((e=((e+=(t^r&(i^t))+f[7]+1735328473)<<14|e>>>18)+i<<0)^i))+f[12]-1926607734)<<20|r>>>12)+e<<0,r=((r+=((h=(i=((i+=((s=r^e)^(t=((t+=(s^i)+f[5]-378558)<<4|t>>>28)+r<<0))+f[8]-2022574463)<<11|i>>>21)+t<<0)^t)^(e=((e+=(h^r)+f[11]+1839030562)<<16|e>>>16)+i<<0))+f[14]-35309556)<<23|r>>>9)+e<<0,r=((r+=((h=(i=((i+=((s=r^e)^(t=((t+=(s^i)+f[1]-1530992060)<<4|t>>>28)+r<<0))+f[4]+1272893353)<<11|i>>>21)+t<<0)^t)^(e=((e+=(h^r)+f[7]-155497632)<<16|e>>>16)+i<<0))+f[10]-1094730640)<<23|r>>>9)+e<<0,r=((r+=((h=(i=((i+=((s=r^e)^(t=((t+=(s^i)+f[13]+681279174)<<4|t>>>28)+r<<0))+f[0]-358537222)<<11|i>>>21)+t<<0)^t)^(e=((e+=(h^r)+f[3]-722521979)<<16|e>>>16)+i<<0))+f[6]+76029189)<<23|r>>>9)+e<<0,r=((r+=((h=(i=((i+=((s=r^e)^(t=((t+=(s^i)+f[9]-640364487)<<4|t>>>28)+r<<0))+f[12]-421815835)<<11|i>>>21)+t<<0)^t)^(e=((e+=(h^r)+f[15]+530742520)<<16|e>>>16)+i<<0))+f[2]-995338651)<<23|r>>>9)+e<<0,r=((r+=((i=((i+=(r^((t=((t+=(e^(r|~i))+f[0]-198630844)<<6|t>>>26)+r<<0)|~e))+f[7]+1126891415)<<10|i>>>22)+t<<0)^((e=((e+=(t^(i|~r))+f[14]-1416354905)<<15|e>>>17)+i<<0)|~t))+f[5]-57434055)<<21|r>>>11)+e<<0,r=((r+=((i=((i+=(r^((t=((t+=(e^(r|~i))+f[12]+1700485571)<<6|t>>>26)+r<<0)|~e))+f[3]-1894986606)<<10|i>>>22)+t<<0)^((e=((e+=(t^(i|~r))+f[10]-1051523)<<15|e>>>17)+i<<0)|~t))+f[1]-2054922799)<<21|r>>>11)+e<<0,r=((r+=((i=((i+=(r^((t=((t+=(e^(r|~i))+f[8]+1873313359)<<6|t>>>26)+r<<0)|~e))+f[15]-30611744)<<10|i>>>22)+t<<0)^((e=((e+=(t^(i|~r))+f[6]-1560198380)<<15|e>>>17)+i<<0)|~t))+f[13]+1309151649)<<21|r>>>11)+e<<0,r=((r+=((i=((i+=(r^((t=((t+=(e^(r|~i))+f[4]-145523070)<<6|t>>>26)+r<<0)|~e))+f[11]-1120210379)<<10|i>>>22)+t<<0)^((e=((e+=(t^(i|~r))+f[2]+718787259)<<15|e>>>17)+i<<0)|~t))+f[9]-343485551)<<21|r>>>11)+e<<0,this.first?(this.h0=t+1732584193<<0,this.h1=r-271733879<<0,this.h2=e-1732584194<<0,this.h3=i+271733878<<0,this.first=!1):(this.h0=this.h0+t<<0,this.h1=this.h1+r<<0,this.h2=this.h2+e<<0,this.h3=this.h3+i<<0)},t.prototype.hex=function(){this.finalize();var t=this.h0,r=this.h1,e=this.h2,i=this.h3;return n[t>>4&15]+n[15&t]+n[t>>12&15]+n[t>>8&15]+n[t>>20&15]+n[t>>16&15]+n[t>>28&15]+n[t>>24&15]+n[r>>4&15]+n[15&r]+n[r>>12&15]+n[r>>8&15]+n[r>>20&15]+n[r>>16&15]+n[r>>28&15]+n[r>>24&15]+n[e>>4&15]+n[15&e]+n[e>>12&15]+n[e>>8&15]+n[e>>20&15]+n[e>>16&15]+n[e>>28&15]+n[e>>24&15]+n[i>>4&15]+n[15&i]+n[i>>12&15]+n[i>>8&15]+n[i>>20&15]+n[i>>16&15]+n[i>>28&15]+n[i>>24&15]},t.prototype.toString=t.prototype.hex,t.prototype.digest=function(){this.finalize();var t=this.h0,r=this.h1,e=this.h2,i=this.h3;return[255&t,t>>8&255,t>>16&255,t>>24&255,255&r,r>>8&255,r>>16&255,r>>24&255,255&e,e>>8&255,e>>16&255,e>>24&255,255&i,i>>8&255,i>>16&255,i>>24&255]},t.prototype.array=t.prototype.digest,t.prototype.arrayBuffer=function(){this.finalize();var t=new ArrayBuffer(16),r=new Uint32Array(t);return r[0]=this.h0,r[1]=this.h1,r[2]=this.h2,r[3]=this.h3,t},t.prototype.buffer=t.prototype.arrayBuffer,t.prototype.base64=function(){for(var t,r,e,i="",s=this.array(),h=0;h<15;)t=s[h++],r=s[h++],e=s[h++],i+=p[t>>>2]+p[63&(t<<4|r>>>4)]+p[63&(r<<2|e>>>6)]+p[63&e];return t=s[h],i+=p[t>>>2]+p[t<<4&63]+"=="};var _=v();f?module.exports=_:(i.md5=_,o&&define(function(){return _}))}();class Caller {static globalHooks = {onError: null,};constructor(calls = null) {this.calls = [];this.r###lts = {};if (calls) {this.add(calls);}}static setGlobalHook(event, callback) {if (this.globalHooks[event] !== undefined) {this.globalHooks[event] = callback;} else {throw new Error(`Unknown event: ${event}`);}}addCall(call) {const { name = call, args = {} } = typeof call === 'object' ? call : { name: call };this.calls.push({ name, args });return this;}add(name) {if (Array.isArray(name)) {name.forEach((call) => this.addCall(call));} else {this.addCall(name);}return this;}handleError(error) {const errorName = error.name;const errorDescription = error.description;if (Caller.globalHooks.onError) {const shouldThrow = Caller.globalHooks.onError(error);if (shouldThrow === false) {return;}}if (error.call) {const callInfo = error.call;throw new Error(`${errorName} in ${callInfo.name}: ${errorDescription}\n` + `Args: ${JSON.stringify(callInfo.args)}\n`);} else if (errorName === 'common\\rpc\\exception\\InvalidRequest') {throw new Error(`Invalid request: ${errorDescription}`);} else {throw new Error(`Unknown error: ${errorName} - ${errorDescription}`);}}async send() {if (!this.calls.length) {throw new Error('No calls to send.');}const identToNameMap = {};const callsWithIdent = this.calls.map((call, index) => {const ident = this.calls.length === 1 ? 'body' : `group_${index}_body`;identToNameMap[ident] = call.name;return { ...call, ident };});try {const response = await Send({ calls: callsWithIdent });if (response.error) {this.handleError(response.error);}if (!response.r###lts) {throw new Error('Invalid response format: missing "r###lts" field');}response.r###lts.forEach((r###lt) => {const name = identToNameMap[r###lt.ident];if (!this.r###lts[name]) {this.r###lts[name] = [];}this.r###lts[name].push(r###lt.r###lt.response);});} catch (error) {throw error;}return this;}r###lt(name, forceArray = false) {const r###lts = name ? this.r###lts[name] || [] : Object.values(this.r###lts).flat();return forceArray || r###lts.length !== 1 ? r###lts : r###lts[0];}async execute(name) {try {await this.send();return this.r###lt(name);} catch (error) {throw error;}}clear() {this.calls = [];this.r###lts = {};return this;}isEmpty() {return this.calls.length === 0 && Object.keys(this.r###lts).length === 0;}static async send(calls) {return new Caller(calls).execute();}}this.Caller = Caller;/*// Примеры использования(async () => {// Короткий вызовawait new Caller('inventoryGet').execute();// Простой вызовlet r###lt = await new Caller().add('inventoryGet').execute();console.log('Inventory Get R###lt:', r###lt);// Сложный вызовlet caller = new Caller();await caller.add([{name: 'inventoryGet',args: {},},{name: 'heroGetAll',args: {},},]).send();console.log('Inventory Get R###lt:', caller.r###lt('inventoryGet'));console.log('Hero Get All R###lt:', caller.r###lt('heroGetAll'));// Очистка всех данныхcaller.clear();})();*//*** Script for beautiful dialog boxes** Скрипт для красивых диалоговых окошек*/const popup = new (function () {this.popUp,this.downer,this.middle,this.msgText,this.buttons = [];this.checkboxes = [];this.dialogPromice = null;this.isInit = false;this.init = function () {if (this.isInit) {return;}addStyle();addBlocks();addEventListeners();this.isInit = true;}const addEventListeners = () => {document.addEventListener('keyup', (e) => {if (e.key == 'Escape') {if (this.dialogPromice) {const { func, r###lt } = this.dialogPromice;this.dialogPromice = null;popup.hide();func(r###lt);}}});}const addStyle = () => {let style = document.createElement('style');style.innerText = `.PopUp_ {position: absolute;min-width: 300px;max-width: 500px;max-height: 600px;background-color: #190e08e6;z-index: 10001;top: 169px;left: 345px;border: 3px #ce9767 solid;border-radius: 10px;display: flex;flex-direction: column;justify-content: space-around;padding: 15px 9px;box-sizing: border-box;}.PopUp_back {position: absolute;background-color: #00000066;width: 100%;height: 100%;z-index: 10000;top: 0;left: 0;}.PopUp_close {width: 40px;height: 40px;position: absolute;right: -18px;top: -18px;border: 3px solid #c18550;border-radius: 20px;background: radial-gradient(circle, rgba(190,30,35,1) 0%, rgba(0,0,0,1) 100%);background-position-y: 3px;box-shadow: -1px 1px 3px black;cursor: pointer;box-sizing: border-box;}.PopUp_close:hover {filter: brightness(1.2);}.PopUp_crossClose {width: 100%;height: 100%;background-size: 65%;background-position: center;background-repeat: no-repeat;background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='%23f4cd73' d='M 0.826 12.559 C 0.431 12.963 3.346 15.374 3.74 14.97 C 4.215 15.173 8.167 10.457 7.804 10.302 C 7.893 10.376 11.454 14.64 11.525 14.372 C 12.134 15.042 15.118 12.086 14.638 11.689 C 14.416 11.21 10.263 7.477 10.402 7.832 C 10.358 7.815 11.731 7.101 14.872 3.114 C 14.698 2.145 13.024 1.074 12.093 1.019 C 11.438 0.861 8.014 5.259 8.035 5.531 C 7.86 5.082 3.61 1.186 3.522 1.59 C 2.973 1.027 0.916 4.611 1.17 4.873 C 0.728 4.914 5.088 7.961 5.61 7.995 C 5.225 7.532 0.622 12.315 0.826 12.559 Z'/%3e%3c/svg%3e")}.PopUp_blocks {width: 100%;height: 50%;display: flex;justify-content: space-evenly;align-items: center;flex-wrap: wrap;justify-content: center;}.PopUp_blocks:last-child {margin-top: 25px;}.PopUp_buttons {display: flex;margin: 7px 10px;flex-direction: column;}.PopUp_button {background-color: #52A81C;border-radius: 5px;box-shadow: inset 0px -4px 10px, inset 0px 3px 2px #99fe20, 0px 0px 4px, 0px -3px 1px #d7b275, 0px 0px 0px 3px #ce9767;cursor: pointer;padding: 4px 12px 6px;}.PopUp_input {text-align: center;font-size: 16px;height: 27px;border: 1px solid #cf9250;border-radius: 9px 9px 0px 0px;background: transparent;color: #fce1ac;padding: 1px 10px;box-sizing: border-box;box-shadow: 0px 0px 4px, 0px 0px 0px 3px #ce9767;}.PopUp_checkboxes {display: flex;flex-direction: column;margin: 15px 15px -5px 15px;align-items: flex-start;}.PopUp_ContCheckbox {margin: 2px 0px;}.PopUp_checkbox {position: absolute;z-index: -1;opacity: 0;}.PopUp_checkbox+label {display: inline-flex;align-items: center;user-select: none;font-size: 15px;font-family: sans-serif;font-weight: 600;font-stretch: condensed;letter-spacing: 1px;color: #fce1ac;text-shadow: 0px 0px 1px;}.PopUp_checkbox+label::before {content: '';display: inline-block;width: 20px;height: 20px;border: 1px solid #cf9250;border-radius: 7px;margin-right: 7px;}.PopUp_checkbox:checked+label::before {background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2388cb13' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e");}.PopUp_input::placeholder {color: #fce1ac75;}.PopUp_input:focus {outline: 0;}.PopUp_input + .PopUp_button {border-radius: 0px 0px 5px 5px;padding: 2px 18px 5px;}.PopUp_button:hover {filter: brightness(1.2);}.PopUp_button:active {box-shadow: inset 0px 5px 10px, inset 0px 1px 2px #99fe20, 0px 0px 4px, 0px -3px 1px #d7b275, 0px 0px 0px 3px #ce9767;}.PopUp_text {font-size: 22px;font-family: sans-serif;font-weight: 600;font-stretch: condensed;letter-spacing: 1px;text-align: center;}.PopUp_buttonText {color: #E4FF4C;text-shadow: 0px 1px 2px black;}.PopUp_msgText {color: #FDE5B6;text-shadow: 0px 0px 2px;}.PopUp_hideBlock {display: none;}`;document.head.appendChild(style);}const addBlocks = () => {this.back = document.createElement('div');this.back.classList.add('PopUp_back');this.back.classList.add('PopUp_hideBlock');document.body.append(this.back);this.popUp = document.createElement('div');this.popUp.classList.add('PopUp_');this.back.append(this.popUp);let upper = document.createElement('div')upper.classList.add('PopUp_blocks');this.popUp.append(upper);this.middle = document.createElement('div')this.middle.classList.add('PopUp_blocks');this.middle.classList.add('PopUp_checkboxes');this.popUp.append(this.middle);this.downer = document.createElement('div')this.downer.classList.add('PopUp_blocks');this.popUp.append(this.downer);this.msgText = document.createElement('div');this.msgText.classList.add('PopUp_text', 'PopUp_msgText');upper.append(this.msgText);}this.showBack = function () {this.back.classList.remove('PopUp_hideBlock');}this.hideBack = function () {this.back.classList.add('PopUp_hideBlock');}this.show = function () {if (this.checkboxes.length) {this.middle.classList.remove('PopUp_hideBlock');}this.showBack();this.popUp.classList.remove('PopUp_hideBlock');this.popUp.style.left = (window.innerWidth - this.popUp.offsetWidth) / 2 + 'px';this.popUp.style.top = (window.innerHeight - this.popUp.offsetHeight) / 3 + 'px';}this.hide = function () {this.hideBack();this.popUp.classList.add('PopUp_hideBlock');}this.addAnyButton = (option) => {const contButton = document.createElement('div');contButton.classList.add('PopUp_buttons');this.downer.append(contButton);let inputField = {value: option.r###lt || option.default}if (option.isInput) {inputField = document.createElement('input');inputField.type = 'text';if (option.placeholder) {inputField.placeholder = option.placeholder;}if (option.default) {inputField.value = option.default;}inputField.classList.add('PopUp_input');contButton.append(inputField);}const button = document.createElement('div');button.classList.add('PopUp_button');button.title = option.title || '';contButton.append(button);const buttonText = document.createElement('div');buttonText.classList.add('PopUp_text', 'PopUp_buttonText');buttonText.innerHTML = option.msg;button.append(buttonText);return { button, contButton, inputField };}this.addCloseButton = () => {let button = document.createElement('div')button.classList.add('PopUp_close');this.popUp.append(button);let crossClose = document.createElement('div')crossClose.classList.add('PopUp_crossClose');button.append(crossClose);return { button, contButton: button };}this.addButton = (option, buttonClick) => {const { button, contButton, inputField } = option.isClose ? this.addCloseButton() : this.addAnyButton(option);if (option.isClose) {this.dialogPromice = { func: buttonClick, r###lt: option.r###lt };}button.addEventListener('click', () => {let r###lt = '';if (option.isInput) {r###lt = inputField.value;}if (option.isClose || option.isCancel) {this.dialogPromice = null;}buttonClick(r###lt);});this.buttons.push(contButton);}this.clearButtons = () => {while (this.buttons.length) {this.buttons.pop().remove();}}this.addCheckBox = (checkBox) => {const contCheckbox = document.createElement('div');contCheckbox.classList.add('PopUp_ContCheckbox');this.middle.append(contCheckbox);const checkbox = document.createElement('input');checkbox.type = 'checkbox';checkbox.id = 'PopUpCheckbox' + this.checkboxes.length;checkbox.dataset.name = checkBox.name;checkbox.checked = checkBox.checked;checkbox.label = checkBox.label;checkbox.title = checkBox.title || '';checkbox.classList.add('PopUp_checkbox');contCheckbox.appendChild(checkbox)const checkboxLabel = document.createElement('label');checkboxLabel.innerText = checkBox.label;checkboxLabel.title = checkBox.title || '';checkboxLabel.setAttribute('for', checkbox.id);contCheckbox.appendChild(checkboxLabel);this.checkboxes.push(checkbox);}this.clearCheckBox = () => {this.middle.classList.add('PopUp_hideBlock');while (this.checkboxes.length) {this.checkboxes.pop().parentNode.remove();}}this.setMsgText = (text) => {this.msgText.innerHTML = text;}this.getCheckBoxes = () => {const checkBoxes = [];for (const checkBox of this.checkboxes) {checkBoxes.push({name: checkBox.dataset.name,label: checkBox.label,checked: checkBox.checked});}return checkBoxes;}this.confirm = async (msg, buttOpt, checkBoxes = []) => {if (!this.isInit) {this.init();}this.clearButtons();this.clearCheckBox();return new Promise((complete, failed) => {this.setMsgText(msg);if (!buttOpt) {buttOpt = [{ msg: 'Ok', r###lt: true, isInput: false }];}for (const checkBox of checkBoxes) {this.addCheckBox(checkBox);}for (let butt of buttOpt) {this.addButton(butt, (r###lt) => {r###lt = r###lt || butt.r###lt;complete(r###lt);popup.hide();});if (butt.isCancel) {this.dialogPromice = { func: complete, r###lt: butt.r###lt };}}this.show();});}});this.HWHFuncs.popup = popup;/*** Script control panel** Панель управления скриптом*/class ScriptMenu {constructor() {if (ScriptMenu.instance) {return ScriptMenu.instance;}this.mainMenu = null;this.buttons = [];this.checkboxes = [];this.option = {showMenu: true,showDetails: {},};ScriptMenu.instance = this;return this;}static getInst() {if (!ScriptMenu.instance) {new ScriptMenu();}return ScriptMenu.instance;}init(option = {}) {this.option = Object.assign(this.option, option);const saveOption = this.loadSaveOption();this.option = Object.assign(this.option, saveOption);this.addStyle();this.addBlocks();}addStyle() {const style = document.createElement('style');style.innerText = `.scriptMenu_status {position: absolute;z-index: 10001;top: -1px;left: 30%;cursor: pointer;border-radius: 0px 0px 10px 10px;background: #190e08e6;border: 1px #ce9767 solid;font-size: 18px;font-family: sans-serif;font-weight: 600;font-stretch: condensed;letter-spacing: 1px;color: #fce1ac;text-shadow: 0px 0px 1px;transition: 0.5s;padding: 2px 10px 3px;}.scriptMenu_statusHide {top: -35px;height: 30px;overflow: hidden;}.scriptMenu_label {position: absolute;top: 30%;left: -4px;z-index: 9999;cursor: pointer;width: 30px;height: 30px;background: radial-gradient(circle, #47a41b 0%, #1a2f04 100%);border: 1px solid #1a2f04;border-radius: 5px;box-shadow:inset 0px 2px 4px #83ce26,inset 0px -4px 6px #1a2f04,0px 0px 2px black,0px 0px 0px 2px #ce9767;}.scriptMenu_label:hover {filter: brightness(1.2);}.scriptMenu_arrowLabel {width: 100%;height: 100%;background-size: 75%;background-position: center;background-repeat: no-repeat;background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='%2388cb13' d='M7.596 7.304a.802.802 0 0 1 0 1.392l-6.363 3.692C.713 12.69 0 12.345 0 11.692V4.308c0-.653.713-.998 1.233-.696l6.363 3.692Z'/%3e%3cpath fill='%2388cb13' d='M15.596 7.304a.802.802 0 0 1 0 1.392l-6.363 3.692C8.713 12.69 8 12.345 8 11.692V4.308c0-.653.713-.998 1.233-.696l6.363 3.692Z'/%3e%3c/svg%3e");box-shadow: 0px 1px 2px #000;border-radius: 5px;filter: drop-shadow(0px 1px 2px #000D);}.scriptMenu_main {position: absolute;max-width: 285px;z-index: 9999;top: 50%;transform: translateY(-40%);background: #190e08e6;border: 1px #ce9767 solid;border-radius: 0px 10px 10px 0px;border-left: none;box-sizing: border-box;font-size: 15px;font-family: sans-serif;font-weight: 600;font-stretch: condensed;letter-spacing: 1px;color: #fce1ac;text-shadow: 0px 0px 1px;transition: 1s;}.scriptMenu_conteiner {max-height: 80vh;overflow: scroll;scrollbar-width: none; /* Для Firefox */-ms-overflow-style: none; /* Для Internet Explorer и Edge */display: flex;flex-direction: column;flex-wrap: nowrap;padding: 5px 10px 5px 5px;}.scriptMenu_conteiner::-webkit-scrollbar {display: none; /* Для Chrome, Safari и Opera */}.scriptMenu_showMenu {display: none;}.scriptMenu_showMenu:checked~.scriptMenu_main {left: 0px;}.scriptMenu_showMenu:not(:checked)~.scriptMenu_main {left: -300px;}.scriptMenu_divInput {margin: 2px;}.scriptMenu_divInputText {margin: 2px;align-self: center;display: flex;}.scriptMenu_checkbox {position: absolute;z-index: -1;opacity: 0;}.scriptMenu_checkbox+label {display: inline-flex;align-items: center;user-select: none;}.scriptMenu_checkbox+label::before {content: '';display: inline-block;width: 20px;height: 20px;border: 1px solid #cf9250;border-radius: 7px;margin-right: 7px;}.scriptMenu_checkbox:checked+label::before {background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2388cb13' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e");}.scriptMenu_close {width: 40px;height: 40px;position: absolute;right: -18px;top: -18px;border: 3px solid #c18550;border-radius: 20px;background: radial-gradient(circle, rgba(190,30,35,1) 0%, rgba(0,0,0,1) 100%);background-position-y: 3px;box-shadow: -1px 1px 3px black;cursor: pointer;box-sizing: border-box;}.scriptMenu_close:hover {filter: brightness(1.2);}.scriptMenu_crossClose {width: 100%;height: 100%;background-size: 65%;background-position: center;background-repeat: no-repeat;background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='%23f4cd73' d='M 0.826 12.559 C 0.431 12.963 3.346 15.374 3.74 14.97 C 4.215 15.173 8.167 10.457 7.804 10.302 C 7.893 10.376 11.454 14.64 11.525 14.372 C 12.134 15.042 15.118 12.086 14.638 11.689 C 14.416 11.21 10.263 7.477 10.402 7.832 C 10.358 7.815 11.731 7.101 14.872 3.114 C 14.698 2.145 13.024 1.074 12.093 1.019 C 11.438 0.861 8.014 5.259 8.035 5.531 C 7.86 5.082 3.61 1.186 3.522 1.59 C 2.973 1.027 0.916 4.611 1.17 4.873 C 0.728 4.914 5.088 7.961 5.61 7.995 C 5.225 7.532 0.622 12.315 0.826 12.559 Z'/%3e%3c/svg%3e")}.scriptMenu_button {user-select: none;cursor: pointer;padding: 5px 14px 8px;}.scriptMenu_button:hover {filter: brightness(1.2);}.scriptMenu_buttonText {color: #fce5b7;text-shadow: 0px 1px 2px black;text-align: center;}.scriptMenu_header {text-align: center;align-self: center;font-size: 15px;margin: 0px 15px;}.scriptMenu_header a {color: #fce5b7;text-decoration: none;}.scriptMenu_InputText {text-align: center;width: 130px;height: 24px;border: 1px solid #cf9250;border-radius: 9px;background: transparent;color: #fce1ac;padding: 0px 10px;box-sizing: border-box;}.scriptMenu_InputText:focus {filter: brightness(1.2);outline: 0;}.scriptMenu_InputText::placeholder {color: #fce1ac75;}.scriptMenu_Summary {cursor: pointer;margin-left: 7px;}.scriptMenu_Details {align-self: center;}.scriptMenu_buttonGroup {display: flex;justify-content: center;user-select: none;cursor: pointer;padding: 0;margin: 3px 0;}.scriptMenu_buttonGroup .scriptMenu_button {width: 100%;padding: 5px 8px 8px;}.scriptMenu_mainButton {border-radius: 5px;margin: 3px 0;}.scriptMenu_combineButtonLeft {border-top-left-radius: 5px;border-bottom-left-radius: 5px;margin-right: 2px;}.scriptMenu_combineButtonCenter {border-radius: 0px;margin-right: 2px;}.scriptMenu_combineButtonRight {border-top-right-radius: 5px;border-bottom-right-radius: 5px;}.scriptMenu_beigeButton {border: 1px solid #442901;background: radial-gradient(circle, rgba(165,120,56,1) 80%, rgba(0,0,0,1) 110%);box-shadow: inset 0px 2px 4px #e9b282, inset 0px -4px 6px #442901, inset 0px 1px 6px #442901, inset 0px 0px 6px, 0px 0px 2px black, 0px 0px 0px 1px #ce9767;}.scriptMenu_beigeButton:active {box-shadow: inset 0px 4px 6px #442901, inset 0px 4px 6px #442901, inset 0px 0px 6px, 0px 0px 4px, 0px 0px 0px 1px #ce9767;}.scriptMenu_greenButton {border: 1px solid #1a2f04;background: radial-gradient(circle, #47a41b 0%, #1a2f04 150%);box-shadow: inset 0px 2px 4px #83ce26, inset 0px -4px 6px #1a2f04, 0px 0px 2px black, 0px 0px 0px 1px #ce9767;}.scriptMenu_greenButton:active {box-shadow: inset 0px 4px 6px #1a2f04, inset 0px 4px 6px #1a2f04, inset 0px 0px 6px, 0px 0px 4px, 0px 0px 0px 1px #ce9767;}.scriptMenu_redButton {border: 1px solid #440101;background: radial-gradient(circle, rgb(198, 34, 34) 80%, rgb(0, 0, 0) 110%);box-shadow: inset 0px 2px 4px #e98282, inset 0px -4px 6px #440101, inset 0px 1px 6px #440101, inset 0px 0px 6px, 0px 0px 2px black, 0px 0px 0px 1px #ce9767;}.scriptMenu_redButton:active {box-shadow: inset 0px 4px 6px #440101, inset 0px 4px 6px #440101, inset 0px 0px 6px, 0px 0px 4px, 0px 0px 0px 1px #ce9767;}.scriptMenu_attention {position: relative;}.scriptMenu_attention .scriptMenu_dot {display: flex;justify-content: center;align-items: center;}.scriptMenu_dot {position: absolute;top: -7px;right: -7px;width: 20px;height: 20px;border-radius: 50%;border: 1px solid #c18550;background: radial-gradient(circle, #f000 25%, black 100%);box-shadow: 0px 0px 2px black;background-position: 0px -1px;font-size: 10px;text-align: center;color: white;text-shadow: 1px 1px 1px black;box-sizing: border-box;display: none;}`;document.head.appendChild(style);}addBlocks() {const main = document.createElement('div');document.body.appendChild(main);this.status = document.createElement('div');this.status.classList.add('scriptMenu_status');this.setStatus('');main.appendChild(this.status);const label = document.createElement('label');label.classList.add('scriptMenu_label');label.setAttribute('for', 'checkbox_showMenu');main.appendChild(label);const arrowLabel = document.createElement('div');arrowLabel.classList.add('scriptMenu_arrowLabel');label.appendChild(arrowLabel);const checkbox = document.createElement('input');checkbox.type = 'checkbox';checkbox.id = 'checkbox_showMenu';checkbox.checked = this.option.showMenu;checkbox.classList.add('scriptMenu_showMenu');checkbox.addEventListener('change', () => {this.option.showMenu = checkbox.checked;this.saveSaveOption();});main.appendChild(checkbox);const mainMenu = document.createElement('div');mainMenu.classList.add('scriptMenu_main');main.appendChild(mainMenu);this.mainMenu = document.createElement('div');this.mainMenu.classList.add('scriptMenu_conteiner');mainMenu.appendChild(this.mainMenu);const closeButton = document.createElement('label');closeButton.classList.add('scriptMenu_close');closeButton.setAttribute('for', 'checkbox_showMenu');this.mainMenu.appendChild(closeButton);const crossClose = document.createElement('div');crossClose.classList.add('scriptMenu_crossClose');closeButton.appendChild(crossClose);}getButtonColor(color) {const buttonColors = {green: 'scriptMenu_greenButton',red: 'scriptMenu_redButton',beige: 'scriptMenu_beigeButton',};return buttonColors[color] || buttonColors['beige'];}setStatus(text, onclick) {if (this._currentStatusClickHandler) {this.status.removeEventListener('click', this._currentStatusClickHandler);this._currentStatusClickHandler = null;}if (!text) {this.status.classList.add('scriptMenu_statusHide');this.status.innerHTML = '';} else {this.status.classList.remove('scriptMenu_statusHide');this.status.innerHTML = text;}if (typeof onclick === 'function') {this.status.addEventListener('click', onclick, { once: true });this._currentStatusClickHandler = onclick;}}addStatus(text) {if (!this.status.innerHTML) {this.status.classList.remove('scriptMenu_statusHide');}this.status.innerHTML += text;}addHeader(text, onClick, main = this.mainMenu) {const header = document.createElement('div');header.classList.add('scriptMenu_header');header.innerHTML = text;if (typeof onClick === 'function') {header.addEventListener('click', onClick);}main.appendChild(header);return header;}addButton(btn, main = this.mainMenu) {const { name, onClick, title, color, dot, classes = [], isCombine } = btn;const button = document.createElement('div');if (!isCombine) {classes.push('scriptMenu_mainButton');}button.classList.add('scriptMenu_button', this.getButtonColor(color), ...classes);button.title = title;button.addEventListener('click', onClick);main.appendChild(button);const buttonText = document.createElement('div');buttonText.classList.add('scriptMenu_buttonText');buttonText.innerText = name;button.appendChild(buttonText);if (dot) {const dotAtention = document.createElement('div');dotAtention.classList.add('scriptMenu_dot');dotAtention.title = dot;button.appendChild(dotAtention);}this.buttons.push(button);return button;}addCombinedButton(buttonList, main = this.mainMenu) {const buttonGroup = document.createElement('div');buttonGroup.classList.add('scriptMenu_buttonGroup');let count = 0;for (const btn of buttonList) {btn.isCombine = true;btn.classes ??= [];if (count === 0) {btn.classes.push('scriptMenu_combineButtonLeft');} else if (count === buttonList.length - 1) {btn.classes.push('scriptMenu_combineButtonRight');} else {btn.classes.push('scriptMenu_combineButtonCenter');}this.addButton(btn, buttonGroup);count++;}const dotAtention = document.createElement('div');dotAtention.classList.add('scriptMenu_dot');buttonGroup.appendChild(dotAtention);main.appendChild(buttonGroup);return buttonGroup;}addCheckbox(label, title, main = this.mainMenu) {const divCheckbox = document.createElement('div');divCheckbox.classList.add('scriptMenu_divInput');divCheckbox.title = title;main.appendChild(divCheckbox);const checkbox = document.createElement('input');checkbox.type = 'checkbox';checkbox.id = 'scriptMenuCheckbox' + this.checkboxes.length;checkbox.classList.add('scriptMenu_checkbox');divCheckbox.appendChild(checkbox);const checkboxLabel = document.createElement('label');checkboxLabel.innerText = label;checkboxLabel.setAttribute('for', checkbox.id);divCheckbox.appendChild(checkboxLabel);this.checkboxes.push(checkbox);return checkbox;}addInputText(title, placeholder, main = this.mainMenu) {const divInputText = document.createElement('div');divInputText.classList.add('scriptMenu_divInputText');divInputText.title = title;main.appendChild(divInputText);const newInputText = document.createElement('input');newInputText.type = 'text';if (placeholder) {newInputText.placeholder = placeholder;}newInputText.classList.add('scriptMenu_InputText');divInputText.appendChild(newInputText);return newInputText;}addDetails(summaryText, name = null) {const details = document.createElement('details');details.classList.add('scriptMenu_Details');this.mainMenu.appendChild(details);const summary = document.createElement('summary');summary.classList.add('scriptMenu_Summary');summary.innerText = summaryText;if (name) {details.open = this.option.showDetails[name] ?? false;details.dataset.name = name;details.addEventListener('toggle', () => {this.option.showDetails[details.dataset.name] = details.open;this.saveSaveOption();});}details.appendChild(summary);return details;}saveSaveOption() {try {localStorage.setItem('scriptMenu_saveOption', JSON.stringify(this.option));} catch (e) {console.log('¯\\_(ツ)_/¯');}}loadSaveOption() {let saveOption = null;try {saveOption = localStorage.getItem('scriptMenu_saveOption');} catch (e) {console.log('¯\\_(ツ)_/¯');}if (!saveOption) {return {};}try {saveOption = JSON.parse(saveOption);} catch (e) {return {};}return saveOption;}}this.HWHClasses.ScriptMenu = ScriptMenu;//const scriptMenu = ScriptMenu.getInst();/*** Пример использованияconst scriptMenu = ScriptMenu.getInst();scriptMenu.init();scriptMenu.addHeader('v1.508');scriptMenu.addCheckbox('testHack', 'Тестовый взлом игры!');scriptMenu.addButton({text: 'Запуск!',onClick: () => console.log('click'),title: 'подсказака',});scriptMenu.addInputText('input подсказака');*//*** Game Library** Игровая библиотека*/class Library {defaultLibUrl = 'https://heroesru-a.akamaihd.net/vk/v1101/lib/lib.json';constructor() {if (!Library.instance) {Library.instance = this;}return Library.instance;}async load() {try {await this.getUrlLib();console.log(this.defaultLibUrl);this.data = await fetch(this.defaultLibUrl).then(e => e.json())} catch (error) {console.error('Не удалось загрузить библиотеку', error)}}async getUrlLib() {try {const db = new Database('hw_cache', 'cache');await db.open();const cacheLibFullUrl = await db.get('lib/lib.json.gz', false);this.defaultLibUrl = cacheLibFullUrl.fullUrl.split('.gz').shift();} catch(e) {}}getData(id) {return this.data[id];}setData(data) {this.data = data;}}this.lib = new Library();/*** Database** База данных*/class Database {constructor(dbName, storeName) {this.dbName = dbName;this.storeName = storeName;this.db = null;}async open() {return new Promise((resolve, reject) => {const request = indexedDB.open(this.dbName);request.onerror = () => {reject(new Error(`Failed to open database ${this.dbName}`));};request.onsuccess = () => {this.db = request.r###lt;resolve();};request.onupgradeneeded = (event) => {const db = event.target.r###lt;if (!db.objectStoreNames.contains(this.storeName)) {db.createObjectStore(this.storeName);}};});}async set(key, value) {return new Promise((resolve, reject) => {const transaction = this.db.transaction([this.storeName], 'readwrite');const store = transaction.objectStore(this.storeName);const request = store.put(value, key);request.onerror = () => {reject(new Error(`Failed to save value with key ${key}`));};request.onsuccess = () => {resolve();};});}async get(key, def) {return new Promise((resolve, reject) => {const transaction = this.db.transaction([this.storeName], 'readonly');const store = transaction.objectStore(this.storeName);const request = store.get(key);request.onerror = () => {resolve(def);};request.onsuccess = () => {resolve(request.r###lt);};});}async delete(key) {return new Promise((resolve, reject) => {const transaction = this.db.transaction([this.storeName], 'readwrite');const store = transaction.objectStore(this.storeName);const request = store.delete(key);request.onerror = () => {reject(new Error(`Failed to delete value with key ${key}`));};request.onsuccess = () => {resolve();};});}}/*** Returns the stored value** Возвращает сохраненное значение*/function getSaveVal(saveName, def) {const r###lt = storage.get(saveName, def);return r###lt;}this.HWHFuncs.getSaveVal = getSaveVal;/*** Stores value** Сохраняет значение*/function setSaveVal(saveName, value) {storage.set(saveName, value);}this.HWHFuncs.setSaveVal = setSaveVal;/*** Database initialization** Инициализация базы данных*/const db = new Database(GM_info.script.name, 'settings');/*** Data store** Хранилище данных*/const storage = {userId: 0,/*** Default values** Значения по умолчанию*/values: [...Object.entries(checkboxes).map(e => ({ [e[0]]: e[1].default })),...Object.entries(inputs).map(e => ({ [e[0]]: e[1].default })),].reduce((acc, obj) => ({ ...acc, ...obj }), {}),name: GM_info.script.name,get: function (key, def) {if (key in this.values) {return this.values[key];}return def;},set: function (key, value) {this.values[key] = value;db.set(this.userId, this.values).catch(e => null);localStorage[this.name + ':' + key] = value;},delete: function (key) {delete this.values[key];db.set(this.userId, this.values);delete localStorage[this.name + ':' + key];}}/*** Returns all keys from localStorage that start with prefix (for migration)** Возвращает все ключи из localStorage которые начинаются с prefix (для миграции)*/function getAllValuesStartingWith(prefix) {const values = [];for (let i = 0; i < localStorage.length; i++) {const key = localStorage.key(i);if (key.startsWith(prefix)) {const val = localStorage.getItem(key);const keyValue = key.split(':')[1];values.push({ key: keyValue, val });}}return values;}/*** Opens or migrates to a database** Открывает или мигрирует в базу данных*/async function openOrMigrateDatabase(userId) {storage.userId = userId;try {await db.open();} catch(e) {return;}let settings = await db.get(userId, false);if (settings) {storage.values = settings;return;}const values = getAllValuesStartingWith(GM_info.script.name);for (const value of values) {let val = null;try {val = JSON.parse(value.val);} catch {break;}storage.values[value.key] = val;}await db.set(userId, storage.values);}class ZingerYWebsiteAPI {/*** Class for interaction with the API of the zingery.ru website* Intended only for use with the HeroWarsHelper script:* https://gfork.dahi.icu/ru/scripts/450693-herowarshelper* Copyright ZingerY*/url = 'https://zingery.ru/heroes/';// YWJzb2x1dGVseSB1c2VsZXNzIGxpbmU=constructor(urn, env, data = {}) {this.urn = urn;this.fd = {now: Date.now(),fp: this.constructor.toString().replaceAll(/\s/g, ''),env: env.callee.toString().replaceAll(/\s/g, ''),info: (({ name, version, author }) => [name, version, author])(GM_info.script),...data,};}sign() {return md5([...this.fd.info, ~(this.fd.now % 1e3), this.fd.fp].join('_'));}encode(data) {return btoa(encodeURIComponent(JSON.stringify(data)));}decode(data) {return JSON.parse(decodeURIComponent(atob(data)));}headers() {return {'X-Request-Signature': this.sign(),'X-Script-Name': GM_info.script.name,'X-Script-Version': GM_info.script.version,'X-Script-Author': GM_info.script.author,'X-Script-ZingerY': 42,};}async request() {try {const response = await fetch(this.url + this.urn, {method: 'POST',headers: this.headers(),body: this.encode(this.fd),});const text = await response.text();return this.decode(text);} catch (e) {console.error(e);return [];}}/*** Класс для взаимодействия с API сайта zingery.ru* Предназначен только для использования со скриптом HeroWarsHelper:* https://greasyfork.org/ru/scripts/450693-herowarshelper* Copyright ZingerY*/}/*** Sending expeditions** Отправка экспедиций*/function checkExpedition() {const { Expedition } = HWHClasses;return new Promise((resolve, reject) => {const expedition = new Expedition(resolve, reject);expedition.start();});}class Expedition {checkExpedInfo = {calls: [{name: 'expeditionGet',args: {},ident: 'expeditionGet',},{name: 'heroGetAll',args: {},ident: 'heroGetAll',},],};constructor(resolve, reject) {this.resolve = resolve;this.reject = reject;}async start() {const data = await Send(JSON.stringify(this.checkExpedInfo));const expedInfo = data.r###lts[0].r###lt.response;const dataHeroes = data.r###lts[1].r###lt.response;const dataExped = { useHeroes: [], exped: [] };const calls = [];/*** Adding expeditions to collect* Добавляем экспедиции для сбора*/let countGet = 0;for (var n in expedInfo) {const exped = expedInfo[n];const dateNow = Date.now() / 1000;if (exped.status == 2 && exped.endTime != 0 && dateNow > exped.endTime) {countGet++;calls.push({name: 'expeditionFarm',args: { expeditionId: exped.id },ident: 'expeditionFarm_' + exped.id,});} else {dataExped.useHeroes = dataExped.useHeroes.concat(exped.heroes);}if (exped.status == 1) {dataExped.exped.push({ id: exped.id, power: exped.power });}}dataExped.exped = dataExped.exped.sort((a, b) => b.power - a.power);/*** Putting together a list of heroes* Собираем список героев*/const heroesArr = [];for (let n in dataHeroes) {const hero = dataHeroes[n];if (hero.power > 0 && !dataExped.useHeroes.includes(hero.id)) {let heroPower = hero.power;// Лара Крофт * 3if (hero.id == 63 && hero.color >= 16) {heroPower *= 3;}heroesArr.push({ id: hero.id, power: heroPower });}}/*** Adding expeditions to send* Добавляем экспедиции для отправки*/let countSend = 0;heroesArr.sort((a, b) => a.power - b.power);for (const exped of dataExped.exped) {let heroesIds = this.selectionHeroes(heroesArr, exped.power);if (heroesIds && heroesIds.length > 4) {for (let q in heroesArr) {if (heroesIds.includes(heroesArr[q].id)) {delete heroesArr[q];}}countSend++;calls.push({name: 'expeditionSendHeroes',args: {expeditionId: exped.id,heroes: heroesIds,},ident: 'expeditionSendHeroes_' + exped.id,});}}if (calls.length) {await Send({ calls });this.end(I18N('EXPEDITIONS_SENT', {countGet, countSend}));return;}this.end(I18N('EXPEDITIONS_NOTHING'));}/*** Selection of heroes for expeditions** Подбор героев для экспедиций*/selectionHeroes(heroes, power) {const r###ltHeroers = [];const heroesIds = [];for (let q = 0; q < 5; q++) {for (let i in heroes) {let hero = heroes[i];if (heroesIds.includes(hero.id)) {continue;}const summ = r###ltHeroers.reduce((acc, hero) => acc + hero.power, 0);const need = Math.round((power - summ) / (5 - r###ltHeroers.length));if (hero.power > need) {r###ltHeroers.push(hero);heroesIds.push(hero.id);break;}}}const summ = r###ltHeroers.reduce((acc, hero) => acc + hero.power, 0);if (summ < power) {return false;}return heroesIds;}/*** Ends expedition script** Завершает скрипт экспедиции*/end(msg) {setProgress(msg, true);this.resolve();}}this.HWHClasses.Expedition = Expedition;/*** Walkthrough of the dungeon** Прохождение подземелья*/function testDungeon() {const { executeDungeon } = HWHClasses;return new Promise((resolve, reject) => {const dung = new executeDungeon(resolve, reject);const titanit = getInput('countTitanit');dung.start(titanit);});}/*** Walkthrough of the dungeon** Прохождение подземелья*/function executeDungeon(resolve, reject) {dungeonActivity = 0;maxDungeonActivity = 150;titanGetAll = [];teams = {heroes: [],earth: [],fire: [],neutral: [],water: [],}titanStats = [];titansStates = {};let talentMsg = '';let talentMsgReward = '';callsExecuteDungeon = {calls: [{name: "dungeonGetInfo",args: {},ident: "dungeonGetInfo"}, {name: "teamGetAll",args: {},ident: "teamGetAll"}, {name: "teamGetFavor",args: {},ident: "teamGetFavor"}, {name: "clanGetInfo",args: {},ident: "clanGetInfo"}, {name: "titanGetAll",args: {},ident: "titanGetAll"}, {name: "inventoryGet",args: {},ident: "inventoryGet"}]}this.start = function(titanit) {maxDungeonActivity = titanit || getInput('countTitanit');send(JSON.stringify(callsExecuteDungeon), startDungeon);}/*** Getting data on the dungeon** Получаем данные по подземелью*/function startDungeon(e) {res = e.r###lts;dungeonGetInfo = res[0].r###lt.response;if (!dungeonGetInfo) {endDungeon('noDungeon', res);return;}teamGetAll = res[1].r###lt.response;teamGetFavor = res[2].r###lt.response;dungeonActivity = res[3].r###lt.response.stat.todayDungeonActivity;titanGetAll = Object.values(res[4].r###lt.response);countPredictionCard = res[5].r###lt.response.consumable[81];teams.hero = {favor: teamGetFavor.dungeon_hero,heroes: teamGetAll.dungeon_hero.filter(id => id < 6000),teamNum: 0,}heroPet = teamGetAll.dungeon_hero.filter(id => id >= 6000).pop();if (heroPet) {teams.hero.pet = heroPet;}teams.neutral = {favor: {},heroes: getTitanTeam(titanGetAll, 'neutral'),teamNum: 0,};teams.water = {favor: {},heroes: getTitanTeam(titanGetAll, 'water'),teamNum: 0,};teams.fire = {favor: {},heroes: getTitanTeam(titanGetAll, 'fire'),teamNum: 0,};teams.earth = {favor: {},heroes: getTitanTeam(titanGetAll, 'earth'),teamNum: 0,};checkFloor(dungeonGetInfo);}function getTitanTeam(titans, type) {switch (type) {case 'neutral':return titans.sort((a, b) => b.power - a.power).slice(0, 5).map(e => e.id);case 'water':return titans.filter(e => e.id.toString().slice(2, 3) == '0').map(e => e.id);case 'fire':return titans.filter(e => e.id.toString().slice(2, 3) == '1').map(e => e.id);case 'earth':return titans.filter(e => e.id.toString().slice(2, 3) == '2').map(e => e.id);}}function getNeutralTeam() {const titans = titanGetAll.filter(e => !titansStates[e.id]?.isDead)return titans.sort((a, b) => b.power - a.power).slice(0, 5).map(e => e.id);}function fixTitanTeam(titans) {titans.heroes = titans.heroes.filter(e => !titansStates[e]?.isDead);return titans;}/*** Checking the floor** Проверяем этаж*/async function checkFloor(dungeonInfo) {if (!('floor' in dungeonInfo) || dungeonInfo.floor?.state == 2) {saveProgress();return;}checkTalent(dungeonInfo);// console.log(dungeonInfo, dungeonActivity);setProgress(`${I18N('DUNGEON')}: ${I18N('TITANIT')} ${dungeonActivity}/${maxDungeonActivity} ${talentMsg}`);if (dungeonActivity >= maxDungeonActivity) {endDungeon('endDungeon', 'maxActive ' + dungeonActivity + '/' + maxDungeonActivity);return;}titansStates = dungeonInfo.states.titans;titanStats = titanObjToArray(titansStates);const floorChoices = dungeonInfo.floor.userData;const floorType = dungeonInfo.floorType;//const primeElement = dungeonInfo.elements.prime;if (floorType == "battle") {const calls = [];for (let teamNum in floorChoices) {attackerType = floorChoices[teamNum].attackerType;const args = fixTitanTeam(teams[attackerType]);if (attackerType == 'neutral') {args.heroes = getNeutralTeam();}if (!args.heroes.length) {continue;}args.teamNum = teamNum;calls.push({name: "dungeonStartBattle",args,ident: "body_" + teamNum})}if (!calls.length) {endDungeon('endDungeon', 'All Dead');return;}const battleDatas = await Send(JSON.stringify({ calls })).then(e => e.r###lts.map(n => n.r###lt.response))const battleR###lts = [];for (n in battleDatas) {battleData = battleDatas[n]battleData.progress = [{ attackers: { input: ["auto", 0, 0, "auto", 0, 0] } }];battleR###lts.push(await Calc(battleData).then(r###lt => {r###lt.teamNum = n;r###lt.attackerType = floorChoices[n].attackerType;return r###lt;}));}processingPromises(battleR###lts)}}async function checkTalent(dungeonInfo) {const talent = dungeonInfo.talent;if (!talent) {return;}const dungeonFloor = +dungeonInfo.floorNumber;const talentFloor = +talent.floorRandValue;let doorsAmount = 3 - talent.conditions.doorsAmount;if (dungeonFloor === talentFloor && (!doorsAmount || !talent.conditions?.farmedDoors[dungeonFloor])) {const reward = await Send({calls: [{ name: 'heroTalent_getReward', args: { talentType: 'tmntDungeonTalent', reroll: false }, ident: 'group_0_body' },{ name: 'heroTalent_farmReward', args: { talentType: 'tmntDungeonTalent' }, ident: 'group_1_body' },],}).then((e) => e.r###lts[0].r###lt.response);const type = Object.keys(reward).pop();const itemId = Object.keys(reward[type]).pop();const count = reward[type][itemId];const itemName = cheats.translate(`LIB_${type.toUpperCase()}_NAME_${itemId}`);talentMsgReward += `<br> ${count} ${itemName}`;doorsAmount++;}talentMsg = `<br>TMNT Talent: ${doorsAmount}/3 ${talentMsgReward}<br>`;}function processingPromises(r###lts) {let selectBattle = r###lts[0];if (r###lts.length < 2) {// console.log(selectBattle);if (!selectBattle.r###lt.win) {endDungeon('dungeonEndBattle\n', selectBattle);return;}endBattle(selectBattle);return;}selectBattle = false;let bestState = -1000;for (const r###lt of r###lts) {const recovery = getState(r###lt);if (recovery > bestState) {bestState = recovery;selectBattle = r###lt}}// console.log(selectBattle.teamNum, r###lts);if (!selectBattle || bestState <= -1000) {endDungeon('dungeonEndBattle\n', r###lts);return;}startBattle(selectBattle.teamNum, selectBattle.attackerType).then(endBattle);}/*** Let's start the fight** Начинаем бой*/function startBattle(teamNum, attackerType) {return new Promise(function (resolve, reject) {args = fixTitanTeam(teams[attackerType]);args.teamNum = teamNum;if (attackerType == 'neutral') {const titans = titanGetAll.filter(e => !titansStates[e.id]?.isDead)args.heroes = titans.sort((a, b) => b.power - a.power).slice(0, 5).map(e => e.id);}startBattleCall = {calls: [{name: "dungeonStartBattle",args,ident: "body"}]}send(JSON.stringify(startBattleCall), r###ltBattle, {resolve,teamNum,attackerType});});}/*** Returns the r###lt of the battle in a promise** Возращает резульат боя в промис*/function r###ltBattle(r###ltBattles, args) {battleData = r###ltBattles.r###lts[0].r###lt.response;battleType = "get_tower";if (battleData.type == "dungeon_titan") {battleType = "get_titan";}battleData.progress = [{ attackers: { input: ["auto", 0, 0, "auto", 0, 0] } }];BattleCalc(battleData, battleType, function (r###lt) {r###lt.teamNum = args.teamNum;r###lt.attackerType = args.attackerType;args.resolve(r###lt);});}/*** Finishing the fight** Заканчиваем бой*/async function endBattle(battleInfo) {if (battleInfo.r###lt.win) {const args = {r###lt: battleInfo.r###lt,progress: battleInfo.progress,}if (countPredictionCard > 0) {args.isRaid = true;} else {const timer = getTimer(battleInfo.battleTime);console.log(timer);await countdownTimer(timer, `${I18N('DUNGEON')}: ${I18N('TITANIT')} ${dungeonActivity}/${maxDungeonActivity} ${talentMsg}`);}const calls = [{name: "dungeonEndBattle",args,ident: "body"}];lastDungeonBattleData = null;send(JSON.stringify({ calls }), r###ltEndBattle);} else {endDungeon('dungeonEndBattle win: false\n', battleInfo);}}/*** Getting and processing battle r###lts** Получаем и обрабатываем результаты боя*/function r###ltEndBattle(e) {if ('error' in e) {popup.confirm(I18N('ERROR_MSG', {name: e.error.name,description: e.error.description,}));endDungeon('errorRequest', e);return;}battleR###lt = e.r###lts[0].r###lt.response;if ('error' in battleR###lt) {endDungeon('errorBattleR###lt', battleR###lt);return;}dungeonGetInfo = battleR###lt.dungeon ?? battleR###lt;dungeonActivity += battleR###lt.reward.dungeonActivity ?? 0;checkFloor(dungeonGetInfo);}/*** Returns the coefficient of condition of the* difference in titanium before and after the battle** Возвращает коэффициент состояния титанов после боя*/function getState(r###lt) {if (!r###lt.r###lt.win) {return -1000;}let befor###mFactor = 0;const beforeTitans = r###lt.battleData.attackers;for (let titanId in beforeTitans) {const titan = beforeTitans[titanId];const state = titan.state;let factor = 1;if (state) {const hp = state.hp / titan.hp;const energy = state.energy / 1e3;factor = hp + energy / 20}befor###mFactor += factor;}let afterSumFactor = 0;const afterTitans = r###lt.progress[0].attackers.heroes;for (let titanId in afterTitans) {const titan = afterTitans[titanId];const hp = titan.hp / beforeTitans[titanId].hp;const energy = titan.energy / 1e3;const factor = hp + energy / 20;afterSumFactor += factor;}return afterSumFactor - befor###mFactor;}/*** Converts an object with IDs to an array with IDs** Преобразует объект с идетификаторами в массив с идетификаторами*/function titanObjToArray(obj) {let titans = [];for (let id in obj) {obj[id].id = id;titans.push(obj[id]);}return titans;}function saveProgress() {let saveProgressCall = {calls: [{name: "dungeonSaveProgress",args: {},ident: "body"}]}send(JSON.stringify(saveProgressCall), r###ltEndBattle);}function endDungeon(reason, info) {console.warn(reason, info);setProgress(`${I18N('DUNGEON')} ${I18N('COMPLETED')}`, true);resolve();}}this.HWHClasses.executeDungeon = executeDungeon;/*** Passing the tower** Прохождение башни*/function testTower() {const { executeTower } = HWHClasses;return new Promise((resolve, reject) => {tower = new executeTower(resolve, reject);tower.start();});}/*** Passing the tower** Прохождение башни*/function executeTower(resolve, reject) {lastTowerInfo = {};scullCoin = 0;heroGetAll = [];heroesStates = {};argsBattle = {heroes: [],favor: {},};callsExecuteTower = {calls: [{name: "towerGetInfo",args: {},ident: "towerGetInfo"}, {name: "teamGetAll",args: {},ident: "teamGetAll"}, {name: "teamGetFavor",args: {},ident: "teamGetFavor"}, {name: "inventoryGet",args: {},ident: "inventoryGet"}, {name: "heroGetAll",args: {},ident: "heroGetAll"}]}buffIds = [{id: 0, cost: 0, isBuy: false}, // plug // заглушка{id: 1, cost: 1, isBuy: true}, // 3% attack // 3% атака{id: 2, cost: 6, isBuy: true}, // 2% attack // 2% атака{id: 3, cost: 16, isBuy: true}, // 4% attack // 4% атака{id: 4, cost: 40, isBuy: true}, // 8% attack // 8% атака{id: 5, cost: 1, isBuy: true}, // 10% armor // 10% броня{id: 6, cost: 6, isBuy: true}, // 5% armor // 5% броня{id: 7, cost: 16, isBuy: true}, // 10% armor // 10% броня{id: 8, cost: 40, isBuy: true}, // 20% armor // 20% броня{ id: 9, cost: 1, isBuy: true }, // 10% protection from magic // 10% защита от магии{ id: 10, cost: 6, isBuy: true }, // 5% protection from magic // 5% защита от магии{ id: 11, cost: 16, isBuy: true }, // 10% protection from magic // 10% защита от магии{ id: 12, cost: 40, isBuy: true }, // 20% protection from magic // 20% защита от магии{ id: 13, cost: 1, isBuy: false }, // 40% health hero // 40% здоровья герою{ id: 14, cost: 6, isBuy: false }, // 40% health hero // 40% здоровья герою{ id: 15, cost: 16, isBuy: false }, // 80% health hero // 80% здоровья герою{ id: 16, cost: 40, isBuy: false }, // 40% health to all heroes // 40% здоровья всем героям{ id: 17, cost: 1, isBuy: false }, // 40% energy to the hero // 40% энергии герою{ id: 18, cost: 3, isBuy: false }, // 40% energy to the hero // 40% энергии герою{ id: 19, cost: 8, isBuy: false }, // 80% energy to the hero // 80% энергии герою{ id: 20, cost: 20, isBuy: false }, // 40% energy to all heroes // 40% энергии всем героям{ id: 21, cost: 40, isBuy: false }, // Hero R###rrection // Воскрешение героя]this.start = function () {send(JSON.stringify(callsExecuteTower), startTower);}/*** Getting data on the Tower** Получаем данные по башне*/function startTower(e) {res = e.r###lts;towerGetInfo = res[0].r###lt.response;if (!towerGetInfo) {endTower('noTower', res);return;}teamGetAll = res[1].r###lt.response;teamGetFavor = res[2].r###lt.response;inventoryGet = res[3].r###lt.response;heroGetAll = Object.values(res[4].r###lt.response);scullCoin = inventoryGet.coin[7] ?? 0;argsBattle.favor = teamGetFavor.tower;argsBattle.heroes = heroGetAll.sort((a, b) => b.power - a.power).slice(0, 5).map(e => e.id);pet = teamGetAll.tower.filter(id => id >= 6000).pop();if (pet) {argsBattle.pet = pet;}checkFloor(towerGetInfo);}function fixHeroesTeam(argsBattle) {let fixHeroes = argsBattle.heroes.filter(e => !heroesStates[e]?.isDead);if (fixHeroes.length < 5) {heroGetAll = heroGetAll.filter(e => !heroesStates[e.id]?.isDead);fixHeroes = heroGetAll.sort((a, b) => b.power - a.power).slice(0, 5).map(e => e.id);Object.keys(argsBattle.favor).forEach(e => {if (!fixHeroes.includes(+e)) {delete argsBattle.favor[e];}})}argsBattle.heroes = fixHeroes;return argsBattle;}/*** Check the floor** Проверяем этаж*/function checkFloor(towerInfo) {lastTowerInfo = towerInfo;maySkipFloor = +towerInfo.maySkipFloor;floorNumber = +towerInfo.floorNumber;heroesStates = towerInfo.states.heroes;floorInfo = towerInfo.floor;/*** Is there at least one chest open on the floor* Открыт ли на этаже хоть один сундук*/isOpenChest = false;if (towerInfo.floorType == "chest") {isOpenChest = towerInfo.floor.chests.reduce((n, e) => n + e.opened, 0);}setProgress(`${I18N('TOWER')}: ${I18N('FLOOR')} ${floorNumber}`);if (floorNumber > 49) {if (isOpenChest) {endTower('alreadyOpenChest 50 floor', floorNumber);return;}}/*** If the chest is open and you can skip floors, then move on* Если сундук открыт и можно скипать этажи, то переходим дальше*/if (towerInfo.mayFullSkip && +towerInfo.teamLevel == 130) {if (floorNumber == 1) {fullSkipTower();return;}if (isOpenChest) {nextOpenChest(floorNumber);} else {nextChestOpen(floorNumber);}return;}// console.log(towerInfo, scullCoin);switch (towerInfo.floorType) {case "battle":if (floorNumber <= maySkipFloor) {skipFloor();return;}if (floorInfo.state == 2) {nextFloor();return;}startBattle().then(endBattle);return;case "buff":checkBuff(towerInfo);return;case "chest":openChest(floorNumber);return;default:console.log('!', towerInfo.floorType, towerInfo);break;}}/*** Let's start the fight** Начинаем бой*/function startBattle() {return new Promise(function (resolve, reject) {towerStartBattle = {calls: [{name: "towerStartBattle",args: fixHeroesTeam(argsBattle),ident: "body"}]}send(JSON.stringify(towerStartBattle), r###ltBattle, resolve);});}/*** Returns the r###lt of the battle in a promise** Возращает резульат боя в промис*/function r###ltBattle(r###ltBattles, resolve) {battleData = r###ltBattles.r###lts[0].r###lt.response;battleType = "get_tower";BattleCalc(battleData, battleType, function (r###lt) {resolve(r###lt);});}/*** Finishing the fight** Заканчиваем бой*/function endBattle(battleInfo) {if (battleInfo.r###lt.stars >= 3) {endBattleCall = {calls: [{name: "towerEndBattle",args: {r###lt: battleInfo.r###lt,progress: battleInfo.progress,},ident: "body"}]}send(JSON.stringify(endBattleCall), r###ltEndBattle);} else {endTower('towerEndBattle win: false\n', battleInfo);}}/*** Getting and processing battle r###lts** Получаем и обрабатываем результаты боя*/function r###ltEndBattle(e) {battleR###lt = e.r###lts[0].r###lt.response;if ('error' in battleR###lt) {endTower('errorBattleR###lt', battleR###lt);return;}if ('reward' in battleR###lt) {scullCoin += battleR###lt.reward?.coin[7] ?? 0;}nextFloor();}function nextFloor() {nextFloorCall = {calls: [{name: "towerNextFloor",args: {},ident: "body"}]}send(JSON.stringify(nextFloorCall), checkDataFloor);}function openChest(floorNumber) {floorNumber = floorNumber || 0;openChestCall = {calls: [{name: "towerOpenChest",args: {num: 2},ident: "body"}]}send(JSON.stringify(openChestCall), floorNumber < 50 ? nextFloor : lastChest);}function lastChest() {endTower('openChest 50 floor', floorNumber);}function skipFloor() {skipFloorCall = {calls: [{name: "towerSkipFloor",args: {},ident: "body"}]}send(JSON.stringify(skipFloorCall), checkDataFloor);}function checkBuff(towerInfo) {buffArr = towerInfo.floor;promises = [];for (let buff of buffArr) {buffInfo = buffIds[buff.id];if (buffInfo.isBuy && buffInfo.cost <= scullCoin) {scullCoin -= buffInfo.cost;promises.push(buyBuff(buff.id));}}Promise.all(promises).then(nextFloor);}function buyBuff(buffId) {return new Promise(function (resolve, reject) {buyBuffCall = {calls: [{name: "towerBuyBuff",args: {buffId},ident: "body"}]}send(JSON.stringify(buyBuffCall), resolve);});}function checkDataFloor(r###lt) {towerInfo = r###lt.r###lts[0].r###lt.response;if ('reward' in towerInfo && towerInfo.reward?.coin) {scullCoin += towerInfo.reward?.coin[7] ?? 0;}if ('tower' in towerInfo) {towerInfo = towerInfo.tower;}if ('skullReward' in towerInfo) {scullCoin += towerInfo.skullReward?.coin[7] ?? 0;}checkFloor(towerInfo);}/*** Getting tower rewards** Получаем награды башни*/function farmTowerRewards(reason) {let { pointRewards, points } = lastTowerInfo;let pointsAll = Object.getOwnPropertyNames(pointRewards);let farmPoints = pointsAll.filter(e => +e <= +points && !pointRewards[e]);if (!farmPoints.length) {return;}let farmTowerRewardsCall = {calls: [{name: "tower_farmPointRewards",args: {points: farmPoints},ident: "tower_farmPointRewards"}]}if (scullCoin > 0) {farmTowerRewardsCall.calls.push({name: "tower_farmSkullReward",args: {},ident: "tower_farmSkullReward"});}send(JSON.stringify(farmTowerRewardsCall), () => { });}function fullSkipTower() {/*** Next chest** Следующий сундук*/function nextChest(n) {return {name: "towerNextChest",args: {},ident: "group_" + n + "_body"}}/*** Open chest** Открыть сундук*/function openChest(n) {return {name: "towerOpenChest",args: {"num": 2},ident: "group_" + n + "_body"}}const fullSkipTowerCall = {calls: []}let n = 0;for (let i = 0; i < 15; i++) {// 15 сундуковfullSkipTowerCall.calls.push(nextChest(++n));fullSkipTowerCall.calls.push(openChest(++n));// +5 сундуков, 250 изюма // towerOpenChest// if (i < 5) {// fullSkipTowerCall.calls.push(openChest(++n, 2));// }}fullSkipTowerCall.calls.push({name: 'towerGetInfo',args: {},ident: 'group_' + ++n + '_body',});send(JSON.stringify(fullSkipTowerCall), data => {for (const r of data.r###lts) {const towerInfo = r?.r###lt?.response;if (towerInfo && 'skullReward' in towerInfo) {scullCoin += towerInfo.skullReward?.coin[7] ?? 0;}}data.r###lts[0] = data.r###lts[data.r###lts.length - 1];checkDataFloor(data);});}function nextChestOpen(floorNumber) {const calls = [{name: "towerOpenChest",args: {num: 2},ident: "towerOpenChest"}];Send(JSON.stringify({ calls })).then(e => {nextOpenChest(floorNumber);});}function nextOpenChest(floorNumber) {if (floorNumber > 49) {endTower('openChest 50 floor', floorNumber);return;}let nextOpenChestCall = {calls: [{name: "towerNextChest",args: {},ident: "towerNextChest"}, {name: "towerOpenChest",args: {num: 2},ident: "towerOpenChest"}]}send(JSON.stringify(nextOpenChestCall), checkDataFloor);}function endTower(reason, info) {console.log(reason, info);if (reason != 'noTower') {farmTowerRewards(reason);}setProgress(`${I18N('TOWER')} ${I18N('COMPLETED')}!`, true);resolve();}}this.HWHClasses.executeTower = executeTower;/*** Passage of the arena of the titans** Прохождение арены титанов*/function testTitanArena() {const { executeTitanArena } = HWHClasses;return new Promise((resolve, reject) => {titAren = new executeTitanArena(resolve, reject);titAren.start();});}/*** Passage of the arena of the titans** Прохождение арены титанов*/function executeTitanArena(resolve, reject) {let titan_arena = [];let finishListBattle = [];/*** ID of the current batch** Идетификатор текущей пачки*/let currentRival = 0;/*** Number of attempts to finish off the pack** Количество попыток добития пачки*/let attempts = 0;/*** Was there an attempt to finish off the current shooting range** Была ли попытка добития текущего тира*/let isCheckCurrentTier = false;/*** Current shooting range** Текущий тир*/let currTier = 0;/*** Number of battles on the current dash** Количество битв на текущем тире*/let countRivalsTier = 0;let callsStart = {calls: [{name: "titanArenaGetStatus",args: {},ident: "titanArenaGetStatus"}, {name: "teamGetAll",args: {},ident: "teamGetAll"}]}this.start = function () {send(JSON.stringify(callsStart), startTitanArena);}function startTitanArena(data) {let titanArena = data.r###lts[0].r###lt.response;if (titanArena.status == 'disabled') {endTitanArena('disabled', titanArena);return;}let teamGetAll = data.r###lts[1].r###lt.response;titan_arena = teamGetAll.titan_arena;checkTier(titanArena)}function checkTier(titanArena) {if (titanArena.status == "peace_time") {endTitanArena('Peace_time', titanArena);return;}currTier = titanArena.tier;if (currTier) {setProgress(`${I18N('TITAN_ARENA')}: ${I18N('LEVEL')} ${currTier}`);}if (titanArena.status == "completed_tier") {titanArenaCompleteTier();return;}/*** Checking for the possibility of a raid* Проверка на возможность рейда*/if (titanArena.canRaid) {titanArenaStartRaid();return;}/*** Check was an attempt to achieve the current shooting range* Проверка была ли попытка добития текущего тира*/if (!isCheckCurrentTier) {checkRivals(titanArena.rivals);return;}endTitanArena('Done or not canRaid', titanArena);}/*** Submit dash information for verification** Отправка информации о тире на проверку*/function checkR###ltInfo(data) {let titanArena = data.r###lts[0].r###lt.response;checkTier(titanArena);}/*** Finish the current tier** Завершить текущий тир*/function titanArenaCompleteTier() {isCheckCurrentTier = false;let calls = [{name: "titanArenaCompleteTier",args: {},ident: "body"}];send(JSON.stringify({calls}), checkR###ltInfo);}/*** Gathering points to be completed** Собираем точки которые нужно добить*/function checkRivals(rivals) {finishListBattle = [];for (let n in rivals) {if (rivals[n].attackScore < 250) {finishListBattle.push(n);}}console.log('checkRivals', finishListBattle);countRivalsTier = finishListBattle.length;roundRivals();}/*** Selecting the next point to finish off** Выбор следующей точки для добития*/function roundRivals() {let countRivals = finishListBattle.length;if (!countRivals) {/*** Whole range checked** Весь тир проверен*/isCheckCurrentTier = true;titanArenaGetStatus();return;}// setProgress('TitanArena: Уровень ' + currTier + ' Бои: ' + (countRivalsTier - countRivals + 1) + '/' + countRivalsTier);currentRival = finishListBattle.pop();attempts = +currentRival;// console.log('roundRivals', currentRival);titanArenaStartBattle(currentRival);}/*** The start of a solo battle** Начало одиночной битвы*/function titanArenaStartBattle(rivalId) {let calls = [{name: "titanArenaStartBattle",args: {rivalId: rivalId,titans: titan_arena},ident: "body"}];send(JSON.stringify({calls}), calcR###lt);}/*** Calculation of the r###lts of the battle** Расчет результатов боя*/function calcR###lt(data) {let battlesInfo = data.r###lts[0].r###lt.response.battle;/*** If attempts are equal to the current battle number we make* Если попытки равны номеру текущего боя делаем прерасчет*/if (attempts == currentRival) {preCalcBattle(battlesInfo);return;}/*** If there are still attempts, we calculate a new battle* Если попытки еще есть делаем расчет нового боя*/if (attempts > 0) {attempts--;calcBattleR###lt(battlesInfo).then(r###ltCalcBattle);return;}/*** Otherwise, go to the next opponent* Иначе переходим к следующему сопернику*/roundRivals();}/*** Processing the r###lts of the battle calculation** Обработка результатов расчета битвы*/function r###ltCalcBattle(r###ltBattle) {// console.log('r###ltCalcBattle', currentRival, attempts, r###ltBattle.r###lt.win);/*** If the current calculation of victory is not a chance or the attempt ended with the finish the battle* Если текущий расчет победа или шансов нет или попытки кончились завершаем бой*/if (r###ltBattle.r###lt.win || !attempts) {titanArenaEndBattle({progress: r###ltBattle.progress,r###lt: r###ltBattle.r###lt,rivalId: r###ltBattle.battleData.typeId});return;}/*** If not victory and there are attempts we start a new battle* Если не победа и есть попытки начинаем новый бой*/titanArenaStartBattle(r###ltBattle.battleData.typeId);}/*** Returns the promise of calculating the r###lts of the battle** Возращает промис расчета результатов битвы*/function getBattleInfo(battle, isRandSeed) {return new Promise(function (resolve) {if (isRandSeed) {battle.seed = Math.floor(Date.now() / 1000) + random(0, 1e3);}// console.log(battle.seed);BattleCalc(battle, "get_titanClanPvp", e => resolve(e));});}/*** Recalculate battles** Прерасчтет битвы*/function preCalcBattle(battle) {let actions = [getBattleInfo(battle, false)];const countTestBattle = getInput('countTestBattle');for (let i = 0; i < countTestBattle; i++) {actions.push(getBattleInfo(battle, true));}Promise.all(actions).then(r###ltPreCalcBattle);}/*** Processing the r###lts of the battle recalculation** Обработка результатов прерасчета битвы*/function r###ltPreCalcBattle(e) {let wins = e.map(n => n.r###lt.win);let firstBattle = e.shift();let countWin = wins.reduce((w, s) => w + s);const countTestBattle = getInput('countTestBattle');console.log('r###ltPreCalcBattle', `${countWin}/${countTestBattle}`)if (countWin > 0) {attempts = getInput('countAutoBattle');} else {attempts = 0;}r###ltCalcBattle(firstBattle);}/*** Complete an arena battle** Завершить битву на арене*/function titanArenaEndBattle(args) {let calls = [{name: "titanArenaEndBattle",args,ident: "body"}];send(JSON.stringify({calls}), r###ltTitanArenaEndBattle);}function r###ltTitanArenaEndBattle(e) {let attackScore = e.r###lts[0].r###lt.response.attackScore;let numReval = countRivalsTier - finishListBattle.length;setProgress(`${I18N('TITAN_ARENA')}: ${I18N('LEVEL')} ${currTier} </br>${I18N('BATTLES')}: ${numReval}/${countRivalsTier} - ${attackScore}`);/*** TODO: Might need to improve the r###lts.* TODO: Возможно стоит сделать улучшение результатов*/// console.log('r###ltTitanArenaEndBattle', e)console.log('r###ltTitanArenaEndBattle', numReval + '/' + countRivalsTier, attempts)roundRivals();}/*** Arena State** Состояние арены*/function titanArenaGetStatus() {let calls = [{name: "titanArenaGetStatus",args: {},ident: "body"}];send(JSON.stringify({calls}), checkR###ltInfo);}/*** Arena Raid Request** Запрос рейда арены*/function titanArenaStartRaid() {let calls = [{name: "titanArenaStartRaid",args: {titans: titan_arena},ident: "body"}];send(JSON.stringify({calls}), calcR###lts);}function calcR###lts(data) {let battlesInfo = data.r###lts[0].r###lt.response;let {attackers, rivals} = battlesInfo;let promises = [];for (let n in rivals) {rival = rivals[n];promises.push(calcBattleR###lt({attackers: attackers,defenders: [rival.team],seed: rival.seed,typeId: n,}));}Promise.all(promises).then(r###lts => {const endR###lts = {};for (let info of r###lts) {let id = info.battleData.typeId;endR###lts[id] = {progress: info.progress,r###lt: info.r###lt,}}titanArenaEndRaid(endR###lts);});}function calcBattleR###lt(battleData) {return new Promise(function (resolve, reject) {BattleCalc(battleData, "get_titanClanPvp", resolve);});}/*** Sending Raid R###lts** Отправка результатов рейда*/function titanArenaEndRaid(r###lts) {titanArenaEndRaidCall = {calls: [{name: "titanArenaEndRaid",args: {r###lts},ident: "body"}]}send(JSON.stringify(titanArenaEndRaidCall), checkRaidR###lts);}function checkRaidR###lts(data) {r###lts = data.r###lts[0].r###lt.response.r###lts;isSucsesRaid = true;for (let i in r###lts) {isSucsesRaid &&= (r###lts[i].attackScore >= 250);}if (isSucsesRaid) {titanArenaCompleteTier();} else {titanArenaGetStatus();}}function titanArenaFarmDailyReward() {titanArenaFarmDailyRewardCall = {calls: [{name: "titanArenaFarmDailyReward",args: {},ident: "body"}]}send(JSON.stringify(titanArenaFarmDailyRewardCall), () => {console.log('Done farm daily reward')});}function endTitanArena(reason, info) {if (!['Peace_time', 'disabled'].includes(reason)) {titanArenaFarmDailyReward();}console.log(reason, info);setProgress(`${I18N('TITAN_ARENA')} ${I18N('COMPLETED')}!`, true);resolve();}}this.HWHClasses.executeTitanArena = executeTitanArena;function hackGame() {const self = this;selfGame = null;bindId = 1e9;this.libGame = null;this.doneLibLoad = () => {};/*** List of correspondence of used classes to their names** Список соответствия используемых классов их названиям*/ObjectsList = [{ name: 'BattlePresets', prop: 'game.battle.controller.thread.BattlePresets' },{ name: 'DataStorage', prop: 'game.data.storage.DataStorage' },{ name: 'BattleConfigStorage', prop: 'game.data.storage.battle.BattleConfigStorage' },{ name: 'BattleInstantPlay', prop: 'game.battle.controller.instant.BattleInstantPlay' },{ name: 'MultiBattleInstantReplay', prop: 'game.battle.controller.instant.MultiBattleInstantReplay' },{ name: 'MultiBattleR###lt', prop: 'game.battle.controller.MultiBattleR###lt' },{ name: 'PlayerMissionData', prop: 'game.model.user.mission.PlayerMissionData' },{ name: 'PlayerMissionBattle', prop: 'game.model.user.mission.PlayerMissionBattle' },{ name: 'GameModel', prop: 'game.model.GameModel' },{ name: 'CommandManager', prop: 'game.command.CommandManager' },{ name: 'MissionCommandList', prop: 'game.command.rpc.mission.MissionCommandList' },{ name: 'RPCCommandBase', prop: 'game.command.rpc.RPCCommandBase' },{ name: 'PlayerTowerData', prop: 'game.model.user.tower.PlayerTowerData' },{ name: 'TowerCommandList', prop: 'game.command.tower.TowerCommandList' },{ name: 'PlayerHeroTeamResolver', prop: 'game.model.user.hero.PlayerHeroTeamResolver' },{ name: 'BattlePausePopup', prop: 'game.view.popup.battle.BattlePausePopup' },{ name: 'BattlePopup', prop: 'game.view.popup.battle.BattlePopup' },{ name: 'DisplayObjectContainer', prop: 'starling.display.DisplayObjectContainer' },{ name: 'GuiClipContainer', prop: 'engine.core.clipgui.GuiClipContainer' },{ name: 'BattlePausePopupClip', prop: 'game.view.popup.battle.BattlePausePopupClip' },{ name: 'ClipLabel', prop: 'game.view.gui.components.ClipLabel' },{ name: 'ClipLabelBase', prop: 'game.view.gui.components.ClipLabelBase' },{ name: 'Translate', prop: 'com.progrestar.common.lang.Translate' },{ name: 'ClipButtonLabeledCentered', prop: 'game.view.gui.components.ClipButtonLabeledCentered' },{ name: 'BattlePausePopupMediator', prop: 'game.mediator.gui.popup.battle.BattlePausePopupMediator' },{ name: 'SettingToggleButton', prop: 'game.mechanics.settings.popup.view.SettingToggleButton' },{ name: 'PlayerDungeonData', prop: 'game.mechanics.dungeon.model.PlayerDungeonData' },{ name: 'NextDayUpdatedManager', prop: 'game.model.user.NextDayUpdatedManager' },{ name: 'BattleController', prop: 'game.battle.controller.BattleController' },{ name: 'BattleSettingsModel', prop: 'game.battle.controller.BattleSettingsModel' },{ name: 'BooleanProperty', prop: 'engine.core.utils.property.BooleanProperty' },{ name: 'RuleStorage', prop: 'game.data.storage.rule.RuleStorage' },{ name: 'BattleConfig', prop: 'battle.BattleConfig' },{ name: 'BattleGuiMediator', prop: 'game.battle.gui.BattleGuiMediator' },{ name: 'BooleanPropertyWriteable', prop: 'engine.core.utils.property.BooleanPropertyWriteable' },{ name: 'BattleLogEncoder', prop: 'battle.log.BattleLogEncoder' },{ name: 'BattleLogReader', prop: 'battle.log.BattleLogReader' },{ name: 'PlayerSubscriptionInfoValueObject', prop: 'game.model.user.subscription.PlayerSubscriptionInfoValueObject' },{ name: 'AdventureMapCamera', prop: 'game.mechanics.adventure.popup.map.AdventureMapCamera' },];/*** Contains the game classes needed to write and override game methods** Содержит классы игры необходимые для написания и подмены методов игры*/Game = {/*** Function 'e'* Функция 'e'*/bindFunc: function (a, b) {if (null == b) return null;null == b.__id__ && (b.__id__ = bindId++);var c;null == a.hx__closures__ ? (a.hx__closures__ = {}) : (c = a.hx__closures__[b.__id__]);null == c && ((c = b.bind(a)), (a.hx__closures__[b.__id__] = c));return c;},};/*** Connects to game objects via the object creation event** Подключается к объектам игры через событие создания объекта*/function connectGame() {for (let obj of ObjectsList) {/*** https: //stackoverflow.com/questions/42611719/how-to-intercept-and-modify-a-specific-property-for-any-object*/Object.defineProperty(Object.prototype, obj.prop, {set: function (value) {if (!selfGame) {selfGame = this;}if (!Game[obj.name]) {Game[obj.name] = value;}// console.log('set ' + obj.prop, this, value);this[obj.prop + '_'] = value;},get: function () {// console.log('get ' + obj.prop, this);return this[obj.prop + '_'];},});}}/*** Game.BattlePresets* @param {bool} a isReplay* @param {bool} b autoToggleable* @param {bool} c auto On Start* @param {object} d config* @param {bool} f showBothTeams*//*** Returns the r###lts of the battle to the callback function* Возвращает в функцию callback результаты боя* @param {*} battleData battle data данные боя* @param {*} battleConfig combat configuration type options:** тип конфигурации боя варианты:** "get_invasion", "get_titanPvpManual", "get_titanPvp",* "get_titanClanPvp","get_clanPvp","get_titan","get_boss",* "get_tower","get_pve","get_pvpManual","get_pvp","get_core"** You can specify the xYc function in the game.assets.storage.BattleAssetStorage class** Можно уточнить в классе game.assets.storage.BattleAssetStorage функция xYc* @param {*} callback функция в которую вернуться результаты боя*/this.BattleCalc = function (battleData, battleConfig, callback) {// battleConfig = battleConfig || getBattleType(battleData.type)if (!Game.BattlePresets) throw Error('Use connectGame');battlePresets = new Game.BattlePresets(battleData.progress,!1,!0,Game.DataStorage[getFn(Game.DataStorage, 24)][getF(Game.BattleConfigStorage, battleConfig)](),!1);let battleInstantPlay;if (battleData.progress?.length > 1) {battleInstantPlay = new Game.MultiBattleInstantReplay(battleData, battlePresets);} else {battleInstantPlay = new Game.BattleInstantPlay(battleData, battlePresets);}battleInstantPlay[getProtoFn(Game.BattleInstantPlay, 9)].add((battleInstant) => {const MBR_2 = getProtoFn(Game.MultiBattleR###lt, 2);const battleR###lts = battleInstant[getF(Game.BattleInstantPlay, 'get_r###lt')]();const battleData = battleInstant[getF(Game.BattleInstantPlay, 'get_rawBattleInfo')]();const battleLogs = [];const timeLimit = battlePresets[getF(Game.BattlePresets, 'get_timeLimit')]();let battleTime = 0;let battleTimer = 0;for (const battleR###lt of battleR###lts[MBR_2]) {const battleLog = Game.BattleLogEncoder.read(new Game.BattleLogReader(battleR###lt));battleLogs.push(battleLog);const maxTime = Math.max(...battleLog.map((e) => (e.time < timeLimit && e.time !== 168.8 ? e.time : 0)));battleTimer += getTimer(maxTime);battleTime += maxTime;}callback({battleLogs,battleTime,battleTimer,battleData,progress: battleR###lts[getF(Game.MultiBattleR###lt, 'get_progress')](),r###lt: battleR###lts[getF(Game.MultiBattleR###lt, 'get_r###lt')](),});});battleInstantPlay.start();};/*** Returns a function with the specified name from the class** Возвращает из класса функцию с указанным именем* @param {Object} classF Class // класс* @param {String} nameF function name // имя функции* @param {String} pos name and alias order // порядок имени и псевдонима* @returns*/function getF(classF, nameF, pos) {pos = pos || false;let prop = Object.entries(classF.prototype.__properties__);if (!pos) {return prop.filter((e) => e[1] == nameF).pop()[0];} else {return prop.filter((e) => e[0] == nameF).pop()[1];}}/*** Returns a function with the specified name from the class** Возвращает из класса функцию с указанным именем* @param {Object} classF Class // класс* @param {String} nameF function name // имя функции* @returns*/function getFnP(classF, nameF) {let prop = Object.entries(classF.__properties__);return prop.filter((e) => e[1] == nameF).pop()[0];}/*** Returns the function name with the specified ordinal from the class** Возвращает имя функции с указаным порядковым номером из класса* @param {Object} classF Class // класс* @param {Number} nF Order number of function // порядковый номер функции* @returns*/function getFn(classF, nF) {let prop = Object.keys(classF);return prop[nF];}/*** Returns the name of the function with the specified serial number from the prototype of the class** Возвращает имя функции с указаным порядковым номером из прототипа класса* @param {Object} classF Class // класс* @param {Number} nF Order number of function // порядковый номер функции* @returns*/function getProtoFn(classF, nF) {let prop = Object.keys(classF.prototype);return prop[nF];}function findInstanceOf(obj, targetClass) {const prototypeKeys = Object.keys(Object.getPrototypeOf(obj));const matchingKey = prototypeKeys.find((key) => obj[key] instanceof targetClass);return matchingKey ? obj[matchingKey] : null;}/*** Description of replaced functions** Описание подменяемых функций*/replaceFunction = {company: function () {let PMD_12 = getProtoFn(Game.PlayerMissionData, 12);let oldSkipMisson = Game.PlayerMissionData.prototype[PMD_12];Game.PlayerMissionData.prototype[PMD_12] = function (a, b, c) {if (!isChecked('passBattle')) {oldSkipMisson.call(this, a, b, c);return;}try {this[getProtoFn(Game.PlayerMissionData, 9)] = new Game.PlayerMissionBattle(a, b, c);var a = new Game.BattlePresets(!1,!1,!0,Game.DataStorage[getFn(Game.DataStorage, 24)][getProtoFn(Game.BattleConfigStorage, 20)](),!1);a = new Game.BattleInstantPlay(c, a);a[getProtoFn(Game.BattleInstantPlay, 9)].add(Game.bindFunc(this, this.P$h));a.start();} catch (error) {console.error('company', error);oldSkipMisson.call(this, a, b, c);}};Game.PlayerMissionData.prototype.P$h = function (a) {let GM_2 = getFn(Game.GameModel, 2);let GM_P2 = getProtoFn(Game.GameModel, 2);let CM_20 = getProtoFn(Game.CommandManager, 20);let MCL_2 = getProtoFn(Game.MissionCommandList, 2);let MBR_15 = getF(Game.MultiBattleR###lt, 'get_r###lt');let RPCCB_15 = getProtoFn(Game.RPCCommandBase, 16);let PMD_32 = getProtoFn(Game.PlayerMissionData, 32);Game.GameModel[GM_2]()[GM_P2][CM_20][MCL_2](a[MBR_15]())[RPCCB_15](Game.bindFunc(this, this[PMD_32]));};},/*tower: function () {let PTD_67 = getProtoFn(Game.PlayerTowerData, 67);let oldSkipTower = Game.PlayerTowerData.prototype[PTD_67];Game.PlayerTowerData.prototype[PTD_67] = function (a) {if (!isChecked('passBattle')) {oldSkipTower.call(this, a);return;}try {var p = new Game.BattlePresets(!1,!1,!0,Game.DataStorage[getFn(Game.DataStorage, 24)][getProtoFn(Game.BattleConfigStorage, 20)](),!1);a = new Game.BattleInstantPlay(a, p);a[getProtoFn(Game.BattleInstantPlay, 9)].add(Game.bindFunc(this, this.P$h));a.start();} catch (error) {console.error('tower', error);oldSkipMisson.call(this, a, b, c);}};Game.PlayerTowerData.prototype.P$h = function (a) {const GM_2 = getFnP(Game.GameModel, 'get_instance');const GM_P2 = getProtoFn(Game.GameModel, 2);const CM_29 = getProtoFn(Game.CommandManager, 29);const TCL_5 = getProtoFn(Game.TowerCommandList, 5);const MBR_15 = getF(Game.MultiBattleR###lt, 'get_r###lt');const RPCCB_15 = getProtoFn(Game.RPCCommandBase, 17);const PTD_78 = getProtoFn(Game.PlayerTowerData, 78);Game.GameModel[GM_2]()[GM_P2][CM_29][TCL_5](a[MBR_15]())[RPCCB_15](Game.bindFunc(this, this[PTD_78]));};},*/// skipSelectHero: function() {// if (!HOST) throw Error('Use connectGame');// Game.PlayerHeroTeamResolver.prototype[getProtoFn(Game.PlayerHeroTeamResolver, 3)] = () => false;// },passBattle: function () {let BPP_4 = getProtoFn(Game.BattlePausePopup, 4);let oldPassBattle = Game.BattlePausePopup.prototype[BPP_4];Game.BattlePausePopup.prototype[BPP_4] = function (a) {if (!isChecked('passBattle')) {oldPassBattle.call(this, a);return;}try {Game.BattlePopup.prototype[getProtoFn(Game.BattlePausePopup, 4)].call(this, a);this[getProtoFn(Game.BattlePausePopup, 3)]();this[getProtoFn(Game.DisplayObjectContainer, 3)](this.clip[getProtoFn(Game.GuiClipContainer, 2)]());this.clip[getProtoFn(Game.BattlePausePopupClip, 1)][getProtoFn(Game.ClipLabelBase, 9)](Game.Translate.translate('UI_POPUP_BATTLE_PAUSE'));this.clip[getProtoFn(Game.BattlePausePopupClip, 2)][getProtoFn(Game.ClipButtonLabeledCentered, 2)](Game.Translate.translate('UI_POPUP_BATTLE_RETREAT'),((q = this[getProtoFn(Game.BattlePausePopup, 1)]), Game.bindFunc(q, q[getProtoFn(Game.BattlePausePopupMediator, 17)])));this.clip[getProtoFn(Game.BattlePausePopupClip, 5)][getProtoFn(Game.ClipButtonLabeledCentered, 2)](this[getProtoFn(Game.BattlePausePopup, 1)][getProtoFn(Game.BattlePausePopupMediator, 14)](),this[getProtoFn(Game.BattlePausePopup, 1)][getProtoFn(Game.BattlePausePopupMediator, 13)]()? ((q = this[getProtoFn(Game.BattlePausePopup, 1)]), Game.bindFunc(q, q[getProtoFn(Game.BattlePausePopupMediator, 18)])): ((q = this[getProtoFn(Game.BattlePausePopup, 1)]), Game.bindFunc(q, q[getProtoFn(Game.BattlePausePopupMediator, 18)])));this.clip[getProtoFn(Game.BattlePausePopupClip, 5)][getProtoFn(Game.ClipButtonLabeledCentered, 0)][getProtoFn(Game.ClipLabelBase, 24)]();this.clip[getProtoFn(Game.BattlePausePopupClip, 3)][getProtoFn(Game.SettingToggleButton, 3)](this[getProtoFn(Game.BattlePausePopup, 1)][getProtoFn(Game.BattlePausePopupMediator, 9)]());this.clip[getProtoFn(Game.BattlePausePopupClip, 4)][getProtoFn(Game.SettingToggleButton, 3)](this[getProtoFn(Game.BattlePausePopup, 1)][getProtoFn(Game.BattlePausePopupMediator, 10)]());this.clip[getProtoFn(Game.BattlePausePopupClip, 6)][getProtoFn(Game.SettingToggleButton, 3)](this[getProtoFn(Game.BattlePausePopup, 1)][getProtoFn(Game.BattlePausePopupMediator, 11)]());} catch (error) {console.error('passBattle', error);oldPassBattle.call(this, a);}};let retreatButtonLabel = getF(Game.BattlePausePopupMediator, 'get_retreatButtonLabel');let oldFunc = Game.BattlePausePopupMediator.prototype[retreatButtonLabel];Game.BattlePausePopupMediator.prototype[retreatButtonLabel] = function () {if (isChecked('passBattle')) {return I18N('BTN_PASS');} else {return oldFunc.call(this);}};},endlessCards: function () {let PDD_21 = getProtoFn(Game.PlayerDungeonData, 21);let oldEndlessCards = Game.PlayerDungeonData.prototype[PDD_21];Game.PlayerDungeonData.prototype[PDD_21] = function () {if (countPredictionCard <= 0) {return true;} else {return oldEndlessCards.call(this);}};},speedBattle: function () {const get_timeScale = getF(Game.BattleController, 'get_timeScale');const oldSpeedBattle = Game.BattleController.prototype[get_timeScale];Game.BattleController.prototype[get_timeScale] = function () {const speedBattle = Number.parseFloat(getInput('speedBattle'));if (!speedBattle) {return oldSpeedBattle.call(this);}try {const BC_12 = getProtoFn(Game.BattleController, 12);const BSM_12 = getProtoFn(Game.BattleSettingsModel, 12);const BP_get_value = getF(Game.BooleanProperty, 'get_value');if (this[BC_12][BSM_12][BP_get_value]()) {return 0;}const BSM_2 = getProtoFn(Game.BattleSettingsModel, 2);const BC_49 = getProtoFn(Game.BattleController, 49);const BSM_1 = getProtoFn(Game.BattleSettingsModel, 1);const BC_14 = getProtoFn(Game.BattleController, 14);const BC_3 = getFn(Game.BattleController, 3);if (this[BC_12][BSM_2][BP_get_value]()) {var a = speedBattle * this[BC_49]();} else {a = this[BC_12][BSM_1][BP_get_value]();const maxSpeed = Math.max(...this[BC_14]);const multiple = a == this[BC_14].indexOf(maxSpeed) ? (maxSpeed >= 4 ? speedBattle : this[BC_14][a]) : this[BC_14][a];a = multiple * Game.BattleController[BC_3][BP_get_value]() * this[BC_49]();}const BSM_24 = getProtoFn(Game.BattleSettingsModel, 24);a > this[BC_12][BSM_24][BP_get_value]() && (a = this[BC_12][BSM_24][BP_get_value]());const DS_23 = getFn(Game.DataStorage, 23);const get_battleSpeedMultiplier = getF(Game.RuleStorage, 'get_battleSpeedMultiplier', true);var b = Game.DataStorage[DS_23][get_battleSpeedMultiplier]();const R_1 = getFn(selfGame.Reflect, 1);const BC_1 = getFn(Game.BattleController, 1);const get_config = getF(Game.BattlePresets, 'get_config');null != b &&(a = selfGame.Reflect[R_1](b, this[BC_1][get_config]().ident)? a * selfGame.Reflect[R_1](b, this[BC_1][get_config]().ident): a * selfGame.Reflect[R_1](b, 'default'));return a;} catch (error) {console.error('passBatspeedBattletle', error);return oldSpeedBattle.call(this);}};},/*** Acceleration button without Valkyries favor** Кнопка ускорения без Покровительства Валькирий*/battleFastKey: function () {const BGM_44 = getProtoFn(Game.BattleGuiMediator, 44);const oldBattleFastKey = Game.BattleGuiMediator.prototype[BGM_44];Game.BattleGuiMediator.prototype[BGM_44] = function () {let flag = true;//console.log(flag)if (!flag) {return oldBattleFastKey.call(this);}try {const BGM_9 = getProtoFn(Game.BattleGuiMediator, 9);const BGM_10 = getProtoFn(Game.BattleGuiMediator, 10);const BPW_0 = getProtoFn(Game.BooleanPropertyWriteable, 0);this[BGM_9][BPW_0](true);this[BGM_10][BPW_0](true);} catch (error) {console.error(error);return oldBattleFastKey.call(this);}};},fastSeason: function () {const GameNavigator = selfGame['game.screen.navigator.GameNavigator'];const oldFuncName = getProtoFn(GameNavigator, 18);const newFuncName = getProtoFn(GameNavigator, 16);const oldFastSeason = GameNavigator.prototype[oldFuncName];const newFastSeason = GameNavigator.prototype[newFuncName];GameNavigator.prototype[oldFuncName] = function (a, b) {if (isChecked('fastSeason')) {return newFastSeason.apply(this, [a]);} else {return oldFastSeason.apply(this, [a, b]);}};},ShowChestReward: function () {const TitanArtifactChest = selfGame['game.mechanics.titan_arena.mediator.chest.TitanArtifactChestRewardPopupMediator'];const getOpenAmountTitan = getF(TitanArtifactChest, 'get_openAmount');const oldGetOpenAmountTitan = TitanArtifactChest.prototype[getOpenAmountTitan];TitanArtifactChest.prototype[getOpenAmountTitan] = function () {if (correctShowOpenArtifact) {correctShowOpenArtifact--;return 100;}return oldGetOpenAmountTitan.call(this);};const ArtifactChest = selfGame['game.view.popup.artifactchest.rewardpopup.ArtifactChestRewardPopupMediator'];const getOpenAmount = getF(ArtifactChest, 'get_openAmount');const oldGetOpenAmount = ArtifactChest.prototype[getOpenAmount];ArtifactChest.prototype[getOpenAmount] = function () {if (correctShowOpenArtifact) {correctShowOpenArtifact--;return 100;}return oldGetOpenAmount.call(this);};},fixCompany: function () {const GameBattleView = selfGame['game.mediator.gui.popup.battle.GameBattleView'];const BattleThread = selfGame['game.battle.controller.thread.BattleThread'];const getOnViewDisposed = getF(BattleThread, 'get_onViewDisposed');const getThread = getF(GameBattleView, 'get_thread');const oldFunc = GameBattleView.prototype[getThread];GameBattleView.prototype[getThread] = function () {return (oldFunc.call(this) || {[getOnViewDisposed]: async () => {},});};},BuyTitanArtifact: function () {const BIP_4 = getProtoFn(selfGame['game.view.popup.shop.buy.BuyItemPopup'], 4);const BuyItemPopup = selfGame['game.view.popup.shop.buy.BuyItemPopup'];const oldFunc = BuyItemPopup.prototype[BIP_4];BuyItemPopup.prototype[BIP_4] = function () {if (isChecked('countControl')) {const BuyTitanArtifactItemPopup = selfGame['game.view.popup.shop.buy.BuyTitanArtifactItemPopup'];const BTAP_0 = getProtoFn(BuyTitanArtifactItemPopup, 0);if (this[BTAP_0]) {const BuyTitanArtifactPopupMediator = selfGame['game.mediator.gui.popup.shop.buy.BuyTitanArtifactItemPopupMediator'];const BTAM_1 = getProtoFn(BuyTitanArtifactPopupMediator, 1);const BuyItemPopupMediator = selfGame['game.mediator.gui.popup.shop.buy.BuyItemPopupMediator'];const BIPM_5 = getProtoFn(BuyItemPopupMediator, 5);const BIPM_7 = getProtoFn(BuyItemPopupMediator, 7);const BIPM_9 = getProtoFn(BuyItemPopupMediator, 9);let need = Math.min(this[BTAP_0][BTAM_1](), this[BTAP_0][BIPM_7]);need = need ? need : 60;this[BTAP_0][BIPM_9] = need;this[BTAP_0][BIPM_5] = 10;}}oldFunc.call(this);};},ClanQuestsFastFarm: function () {const VipRuleValueObject = selfGame['game.data.storage.rule.VipRuleValueObject'];const getClanQuestsFastFarm = getF(VipRuleValueObject, 'get_clanQuestsFastFarm', 1);VipRuleValueObject.prototype[getClanQuestsFastFarm] = function () {return 0;};},adventureCamera: function () {const AMC_40 = getProtoFn(Game.AdventureMapCamera, 40);const AMC_5 = getProtoFn(Game.AdventureMapCamera, 5);const oldFunc = Game.AdventureMapCamera.prototype[AMC_40];Game.AdventureMapCamera.prototype[AMC_40] = function (a) {this[AMC_5] = 0.4;oldFunc.bind(this)(a);};},unlockMission: function () {const WorldMapStoryDrommerHelper = selfGame['game.mediator.gui.worldmap.WorldMapStoryDrommerHelper'];const WMSDH_4 = getFn(WorldMapStoryDrommerHelper, 4);const WMSDH_7 = getFn(WorldMapStoryDrommerHelper, 7);WorldMapStoryDrommerHelper[WMSDH_4] = function () {return true;};WorldMapStoryDrommerHelper[WMSDH_7] = function () {return true;};},};/*** Starts replacing recorded functions** Запускает замену записанных функций*/this.activateHacks = function () {if (!selfGame) throw Error('Use connectGame');for (let func in replaceFunction) {try {replaceFunction[func]();} catch (error) {console.error(error);}}};/*** Returns the game object** Возвращает объект игры*/this.getSelfGame = function () {return selfGame;};/*** Updates game data** Обновляет данные игры*/this.refreshGame = function () {new Game.NextDayUpdatedManager()[getProtoFn(Game.NextDayUpdatedManager, 5)]();try {cheats.refreshInventory();} catch (e) {}};/*** Update inventory** Обновляет инвентарь*/this.refreshInventory = async function () {const GM_INST = getFnP(Game.GameModel, 'get_instance');const GM_0 = getProtoFn(Game.GameModel, 0);const P_24 = getProtoFn(selfGame['game.model.user.Player'], 24);const Player = Game.GameModel[GM_INST]()[GM_0];Player[P_24] = new selfGame['game.model.user.inventory.PlayerInventory']();Player[P_24].init(await Send({ calls: [{ name: 'inventoryGet', args: {}, ident: 'body' }] }).then((e) => e.r###lts[0].r###lt.response));};this.updateInventory = function (reward) {const GM_INST = getFnP(Game.GameModel, 'get_instance');const GM_0 = getProtoFn(Game.GameModel, 0);const P_24 = getProtoFn(selfGame['game.model.user.Player'], 24);const Player = Game.GameModel[GM_INST]()[GM_0];Player[P_24].init(reward);};this.updateMap = function (data) {const PCDD_21 = getProtoFn(selfGame['game.mechanics.clanDomination.model.PlayerClanDominationData'], 21);const P_60 = getProtoFn(selfGame['game.model.user.Player'], 60);const GM_0 = getProtoFn(Game.GameModel, 0);const getInstance = getFnP(selfGame['Game'], 'get_instance');const PlayerClanDominationData = Game.GameModel[getInstance]()[GM_0];PlayerClanDominationData[P_60][PCDD_21].update(data);};/*** Change the play screen on windowName** Сменить экран игры на windowName** Possible options:** Возможные варианты:** MISSION, ARENA, GRAND, CHEST, SKILLS, SOCIAL_GIFT, CLAN, ENCHANT, TOWER, RATING, CHALLENGE, BOSS, CHAT, CLAN_DUNGEON, CLAN_CHEST, TITAN_GIFT, CLAN_RAID, ASGARD, HERO_ASCENSION, ROLE_ASCENSION, ASCENSION_CHEST, TITAN_MISSION, TITAN_ARENA, TITAN_ARTIFACT, TITAN_ARTIFACT_CHEST, TITAN_VALLEY, TITAN_SPIRITS, TITAN_ARTIFACT_MERCHANT, TITAN_ARENA_HALL_OF_FAME, CLAN_PVP, CLAN_PVP_MERCHANT, CLAN_GLOBAL_PVP, CLAN_GLOBAL_PVP_TITAN, ARTIFACT, ZEPPELIN, ARTIFACT_CHEST, ARTIFACT_MERCHANT, EXPEDITIONS, SUBSCRIPTION, NY2018_GIFTS, NY2018_TREE, NY2018_WELCOME, ADVENTURE, ADVENTURESOLO, SANCTUARY, PET_MERCHANT, PET_LIST, PET_SUMMON, BOSS_RATING_EVENT, BRAWL*/this.goNavigtor = function (windowName) {let mechanicStorage = selfGame['game.data.storage.mechanic.MechanicStorage'];let window = mechanicStorage[windowName];let event = new selfGame['game.mediator.gui.popup.PopupStashEventParams']();let Game = selfGame['Game'];let navigator = getF(Game, 'get_navigator');let navigate = getProtoFn(selfGame['game.screen.navigator.GameNavigator'], 20);let instance = getFnP(Game, 'get_instance');Game[instance]()[navigator]()[navigate](window, event);};/*** Move to the sanctuary cheats.goSanctuary()** Переместиться в святилище cheats.goSanctuary()*/this.goSanctuary = () => {this.goNavigtor('SANCTUARY');};/** Перейти в Долину титанов */this.goTitanValley = () => {this.goNavigtor('TITAN_VALLEY');};/*** Go to Guild War** Перейти к Войне Гильдий*/this.goClanWar = function () {let instance = getFnP(Game.GameModel, 'get_instance');let player = Game.GameModel[instance]().A;let clanWarSelect = selfGame['game.mechanics.cross_clan_war.popup.selectMode.CrossClanWarSelectModeMediator'];new clanWarSelect(player).open();};/** Перейти к Острову гильдии */this.goClanIsland = function () {let instance = getFnP(Game.GameModel, 'get_instance');let player = Game.GameModel[instance]().A;let clanIslandSelect = selfGame['game.view.gui.ClanIslandPopupMediator'];new clanIslandSelect(player).open();};/*** Go to BrawlShop** Переместиться в BrawlShop*/this.goBrawlShop = () => {const instance = getFnP(Game.GameModel, 'get_instance');const P_36 = getProtoFn(selfGame['game.model.user.Player'], 36);const PSD_0 = getProtoFn(selfGame['game.model.user.shop.PlayerShopData'], 0);const IM_0 = getProtoFn(selfGame['haxe.ds.IntMap'], 0);const PSDE_4 = getProtoFn(selfGame['game.model.user.shop.PlayerShopDataEntry'], 4);const player = Game.GameModel[instance]().A;const shop = player[P_36][PSD_0][IM_0][1038][PSDE_4];const shopPopup = new selfGame['game.mechanics.brawl.mediator.BrawlShopPopupMediator'](player, shop);shopPopup.open(new selfGame['game.mediator.gui.popup.PopupStashEventParams']());};/*** Returns all stores from game data** Возвращает все магазины из данных игры*/this.getShops = () => {const instance = getFnP(Game.GameModel, 'get_instance');const P_36 = getProtoFn(selfGame['game.model.user.Player'], 36);const PSD_0 = getProtoFn(selfGame['game.model.user.shop.PlayerShopData'], 0);const IM_0 = getProtoFn(selfGame['haxe.ds.IntMap'], 0);const player = Game.GameModel[instance]().A;return player[P_36][PSD_0][IM_0];};/*** Returns the store from the game data by ID** Возвращает магазин из данных игры по идетификатору*/this.getShop = (id) => {const PSDE_4 = getProtoFn(selfGame['game.model.user.shop.PlayerShopDataEntry'], 4);const shops = this.getShops();const shop = shops[id]?.[PSDE_4];return shop;};/*** Change island map** Сменить карту острова*/this.changeIslandMap = (mapId = 2) => {const GameInst = getFnP(selfGame['Game'], 'get_instance');const GM_0 = getProtoFn(Game.GameModel, 0);const PSAD_31 = getProtoFn(selfGame['game.mechanics.season_adventure.model.PlayerSeasonAdventureData'], 31);const Player = Game.GameModel[GameInst]()[GM_0];const PlayerSeasonAdventureData = findInstanceOf(Player, selfGame['game.mechanics.season_adventure.model.PlayerSeasonAdventureData']);PlayerSeasonAdventureData[PSAD_31]({ id: mapId, seasonAdventure: { id: mapId, startDate: 1701914400, endDate: 1709690400, closed: false } });const GN_15 = getProtoFn(selfGame['game.screen.navigator.GameNavigator'], 17);const navigator = getF(selfGame['Game'], 'get_navigator');selfGame['Game'][GameInst]()[navigator]()[GN_15](new selfGame['game.mediator.gui.popup.PopupStashEventParams']());};/*** Game library availability tracker** Отслеживание доступности игровой библиотеки*/function checkLibLoad() {timeout = setTimeout(() => {if (Game.GameModel) {changeLib();} else {checkLibLoad();}}, 100);}/*** Game library data spoofing** Подмена данных игровой библиотеки*/function changeLib() {console.log('lib connect');const originalStartFunc = Game.GameModel.prototype.start;Game.GameModel.prototype.start = function (a, b, c) {self.libGame = b.raw;self.doneLibLoad(self.libGame);try {const levels = b.raw.seasonAdventure.level;for (const id in levels) {const level = levels[id];level.clientData.graphics.fogged = level.clientData.graphics.visible;}const adv = b.raw.seasonAdventure.list[1];adv.clientData.asset = 'dialog_season_adventure_tiles';} catch (e) {console.warn(e);}originalStartFunc.call(this, a, b, c);};}this.LibLoad = function () {return new Promise((e) => {this.doneLibLoad = e;});};/*** Returns the value of a language constant** Возвращает значение языковой константы* @param {*} langConst language constant // языковая константа* @returns*/this.translate = function (langConst) {return Game.Translate.translate(langConst);};connectGame();checkLibLoad();}/*** Auto collection of gifts** Автосбор подарков*/function getAutoGifts() {// c3ltYm9scyB0aGF0IG1lYW4gbm90aGluZw==let valName = 'giftSendIds_' + userInfo.id;if (!localStorage['clearGift' + userInfo.id]) {localStorage[valName] = '';localStorage['clearGift' + userInfo.id] = '+';}if (!localStorage[valName]) {localStorage[valName] = '';}const giftsAPI = new ZingerYWebsiteAPI('getGifts.php', arguments);/*** Submit a request to receive gift codes** Отправка запроса для получения кодов подарков*/giftsAPI.request().then((data) => {let freebieCheckCalls = {calls: [],};data.forEach((giftId, n) => {if (localStorage[valName].includes(giftId)) return;freebieCheckCalls.calls.push({name: 'registration',args: {user: { referrer: {} },giftId,},context: {actionTs: Math.floor(performance.now()),cookie: window?.NXAppInfo?.session_id || null,},ident: giftId,});});if (!freebieCheckCalls.calls.length) {return;}send(JSON.stringify(freebieCheckCalls), (e) => {let countGetGifts = 0;const gifts = [];for (check of e.r###lts) {gifts.push(check.ident);if (check.r###lt.response != null) {countGetGifts++;}}const saveGifts = localStorage[valName].split(';');localStorage[valName] = [...saveGifts, ...gifts].slice(-50).join(';');console.log(`${I18N('GIFTS')}: ${countGetGifts}`);});});}/*** To fill the kills in the Forge of Souls** Набить килов в горниле душ*/async function bossRatingEvent() {const topGet = await Send(JSON.stringify({ calls: [{ name: "topGet", args: { type: "bossRatingTop", extraId: 0 }, ident: "body" }] }));if (!topGet || !topGet.r###lts[0].r###lt.response[0]) {setProgress(`${I18N('EVENT')} ${I18N('NOT_AVAILABLE')}`, true);return;}const replayId = topGet.r###lts[0].r###lt.response[0].userData.replayId;const r###lt = await Send(JSON.stringify({calls: [{ name: "battleGetReplay", args: { id: replayId }, ident: "battleGetReplay" },{ name: "heroGetAll", args: {}, ident: "heroGetAll" },{ name: "pet_getAll", args: {}, ident: "pet_getAll" },{ name: "offerGetAll", args: {}, ident: "offerGetAll" }]}));const bossEventInfo = r###lt.r###lts[3].r###lt.response.find(e => e.offerType == "bossEvent");if (!bossEventInfo) {setProgress(`${I18N('EVENT')} ${I18N('NOT_AVAILABLE')}`, true);return;}const usedHeroes = bossEventInfo.progress.usedHeroes;const party = Object.values(r###lt.r###lts[0].r###lt.response.replay.attackers);const availableHeroes = Object.values(r###lt.r###lts[1].r###lt.response).map(e => e.id);const availablePets = Object.values(r###lt.r###lts[2].r###lt.response).map(e => e.id);const calls = [];/*** First pack** Первая пачка*/const args = {heroes: [],favor: {}}for (let hero of party) {if (hero.id >= 6000 && availablePets.includes(hero.id)) {args.pet = hero.id;continue;}if (!availableHeroes.includes(hero.id) || usedHeroes.includes(hero.id)) {continue;}args.heroes.push(hero.id);if (hero.favorPetId) {args.favor[hero.id] = hero.favorPetId;}}if (args.heroes.length) {calls.push({name: 'bossRating_startBattle',args,ident: 'body_0',});}/*** Other packs** Другие пачки*/let heroes = [];let count = 1;while (heroId = availableHeroes.pop()) {if (args.heroes.includes(heroId) || usedHeroes.includes(heroId)) {continue;}heroes.push(heroId);if (heroes.length == 5) {calls.push({name: 'bossRating_startBattle',args: {heroes: [...heroes],pet: availablePets[Math.floor(Math.random() * availablePets.length)],},ident: 'body_' + count,});heroes = [];count++;}}if (!calls.length) {setProgress(`${I18N('NO_HEROES')}`, true);return;}const r###ltBattles = await Send(JSON.stringify({ calls }));console.log(r###ltBattles);rewardBossRatingEvent();}/*** Collecting Rewards from the Forge of Souls** Сбор награды из Горнила Душ*/function rewardBossRatingEvent() {let rewardBossRatingCall = '{"calls":[{"name":"offerGetAll","args":{},"ident":"offerGetAll"}]}';send(rewardBossRatingCall, function (data) {let bossEventInfo = data.r###lts[0].r###lt.response.find(e => e.offerType == "bossEvent");if (!bossEventInfo) {setProgress(`${I18N('EVENT')} ${I18N('NOT_AVAILABLE')}`, true);return;}let farmedChests = bossEventInfo.progress.farmedChests;let score = bossEventInfo.progress.score;setProgress(`${I18N('DAMAGE_AMOUNT')}: ${score}`);let revard = bossEventInfo.reward;let getRewardCall = {calls: []}let count = 0;for (let i = 1; i < 10; i++) {if (farmedChests.includes(i)) {continue;}if (score < revard[i].score) {break;}getRewardCall.calls.push({name: 'bossRating_getReward',args: {rewardId: i,},ident: 'body_' + i,});count++;}if (!count) {setProgress(`${I18N('NOTHING_TO_COLLECT')}`, true);return;}send(JSON.stringify(getRewardCall), e => {console.log(e);setProgress(`${I18N('COLLECTED')} ${e?.r###lts?.length} ${I18N('REWARD')}`, true);});});}/*** Collect Easter eggs and event rewards** Собрать пасхалки и награды событий*/function offerFarmAllReward() {const offerGetAllCall = '{"calls":[{"name":"offerGetAll","args":{},"ident":"offerGetAll"}]}';return Send(offerGetAllCall).then((data) => {const offerGetAll = data.r###lts[0].r###lt.response.filter(e => e.type == "reward" && !e?.freeRewardObtained && e.reward);if (!offerGetAll.length) {setProgress(`${I18N('NOTHING_TO_COLLECT')}`, true);return;}const calls = [];for (let reward of offerGetAll) {calls.push({name: "offerFarmReward",args: {offerId: reward.id},ident: "offerFarmReward_" + reward.id});}return Send(JSON.stringify({ calls })).then(e => {console.log(e);setProgress(`${I18N('COLLECTED')} ${e?.r###lts?.length} ${I18N('REWARD')}`, true);});});}/*** Assemble Outland** Собрать запределье*/function getOutland() {return new Promise(function (resolve, reject) {send('{"calls":[{"name":"bossGetAll","args":{},"ident":"bossGetAll"}]}', e => {let bosses = e.r###lts[0].r###lt.response;let bossRaidOpenChestCall = {calls: []};for (let boss of bosses) {if (boss.mayRaid) {bossRaidOpenChestCall.calls.push({name: "bossRaid",args: {bossId: boss.id},ident: "bossRaid_" + boss.id});bossRaidOpenChestCall.calls.push({name: "bossOpenChest",args: {bossId: boss.id,amount: 1,starmoney: 0},ident: "bossOpenChest_" + boss.id});} else if (boss.chestId == 1) {bossRaidOpenChestCall.calls.push({name: "bossOpenChest",args: {bossId: boss.id,amount: 1,starmoney: 0},ident: "bossOpenChest_" + boss.id});}}if (!bossRaidOpenChestCall.calls.length) {setProgress(`${I18N('OUTLAND')} ${I18N('NOTHING_TO_COLLECT')}`, true);resolve();return;}send(JSON.stringify(bossRaidOpenChestCall), e => {setProgress(`${I18N('OUTLAND')} ${I18N('COLLECTED')}`, true);resolve();});});});}/*** Collect all rewards** Собрать все награды*/function questAllFarm() {return new Promise(function (resolve, reject) {let questGetAllCall = {calls: [{name: "questGetAll",args: {},ident: "body"}]}send(JSON.stringify(questGetAllCall), function (data) {let questGetAll = data.r###lts[0].r###lt.response;const questAllFarmCall = {calls: []}let number = 0;for (let quest of questGetAll) {if (quest.id < 1e6 && quest.state == 2) {questAllFarmCall.calls.push({name: "questFarm",args: {questId: quest.id},ident: `group_${number}_body`});number++;}}if (!questAllFarmCall.calls.length) {setProgress(`${I18N('COLLECTED')} ${number} ${I18N('REWARD')}`, true);resolve();return;}send(JSON.stringify(questAllFarmCall), function (res) {console.log(res);setProgress(`${I18N('COLLECTED')} ${number} ${I18N('REWARD')}`, true);resolve();});});})}/*** Mission auto repeat** Автоповтор миссии* isStopSendMission = false;* isSendsMission = true;**/this.sendsMission = async function (param) {if (isStopSendMission) {isSendsMission = false;console.log(I18N('STOPPED'));setProgress('');await popup.confirm(`${I18N('STOPPED')}<br>${I18N('REPETITIONS')}: ${param.count}`, [{msg: 'Ok',r###lt: true}, ])return;}lastMissionBattleStart = Date.now();let missionStartCall = {"calls": [{"name": "missionStart","args": lastMissionStart,"ident": "body"}]}/*** Mission Request** Запрос на выполнение мисии*/SendRequest(JSON.stringify(missionStartCall), async e => {if (e['error']) {isSendsMission = false;console.log(e['error']);setProgress('');let msg = e['error'].name + ' ' + e['error'].description + `<br>${I18N('REPETITIONS')}: ${param.count}`;await popup.confirm(msg, [{msg: 'Ok', r###lt: true},])return;}/*** Mission data calculation** Расчет данных мисии*/BattleCalc(e.r###lts[0].r###lt.response, 'get_tower', async r => {/** missionTimer */let timer = getTimer(r.battleTime) + 5;const period = Math.ceil((Date.now() - lastMissionBattleStart) / 1000);if (period < timer) {timer = timer - period;await countdownTimer(timer, `${I18N('MISSIONS_PASSED')}: ${param.count}`);}let missionEndCall = {"calls": [{"name": "missionEnd","args": {"id": param.id,"r###lt": r.r###lt,"progress": r.progress},"ident": "body"}]}/*** Mission Completion Request** Запрос на завершение миссии*/SendRequest(JSON.stringify(missionEndCall), async (e) => {if (e['error']) {isSendsMission = false;console.log(e['error']);setProgress('');let msg = e['error'].name + ' ' + e['error'].description + `<br>${I18N('REPETITIONS')}: ${param.count}`;await popup.confirm(msg, [{msg: 'Ok', r###lt: true},])return;}r = e.r###lts[0].r###lt.response;if (r['error']) {isSendsMission = false;console.log(r['error']);setProgress('');await popup.confirm(`<br>${I18N('REPETITIONS')}: ${param.count}` + ' 3 ' + r['error'], [{msg: 'Ok', r###lt: true},])return;}param.count++;setProgress(`${I18N('MISSIONS_PASSED')}: ${param.count} (${I18N('STOP')})`, false, () => {isStopSendMission = true;});setTimeout(sendsMission, 1, param);});})});}/*** Opening of russian dolls** Открытие матрешек*/async function openRussianDolls(libId, amount) {let sum = 0;const sumR###lt = {};let count = 0;while (amount) {sum += amount;setProgress(`${I18N('TOTAL_OPEN')} ${sum}`);const calls = [{name: 'consumableUseLootBox',args: { libId, amount },ident: 'body',},];const response = await Send(JSON.stringify({ calls })).then((e) => e.r###lts[0].r###lt.response);let [countLootBox, r###lt] = Object.entries(response).pop();count += +countLootBox;let newCount = 0;if (r###lt?.consumable && r###lt.consumable[libId]) {newCount = r###lt.consumable[libId];delete r###lt.consumable[libId];}mergeItemsObj(sumR###lt, r###lt);amount = newCount;}setProgress(`${I18N('TOTAL_OPEN')} ${sum}`, 5000);return [count, sumR###lt];}function mergeItemsObj(obj1, obj2) {for (const key in obj2) {if (obj1[key]) {if (typeof obj1[key] == 'object') {for (const innerKey in obj2[key]) {obj1[key][innerKey] = (obj1[key][innerKey] || 0) + obj2[key][innerKey];}} else {obj1[key] += obj2[key] || 0;}} else {obj1[key] = obj2[key];}}return obj1;}/*** Collect all mail, except letters with energy and charges of the portal** Собрать всю почту, кроме писем с энергией и зарядами портала*/function mailGetAll() {const getMailInfo = '{"calls":[{"name":"mailGetAll","args":{},"ident":"body"}]}';return Send(getMailInfo).then(dataMail => {const letters = dataMail.r###lts[0].r###lt.response.letters;const letterIds = lettersFilter(letters);if (!letterIds.length) {setProgress(I18N('NOTHING_TO_COLLECT'), true);return;}const calls = [{ name: "mailFarm", args: { letterIds }, ident: "body" }];return Send(JSON.stringify({ calls })).then(res => {const lettersIds = res.r###lts[0].r###lt.response;if (lettersIds) {const countLetters = Object.keys(lettersIds).length;setProgress(`${I18N('RECEIVED')} ${countLetters} ${I18N('LETTERS')}`, true);}});});}/*** Filters received emails** Фильтрует получаемые письма*/function lettersFilter(letters) {const lettersIds = [];for (let l in letters) {letter = letters[l];const reward = letter?.reward;if (!reward || !Object.keys(reward).length) {continue;}/*** Mail Collection Exceptions** Исключения на сбор писем*/const isFarmLetter = !(/** Portals // сферы портала */(reward?.refillable ? reward.refillable[45] : false) ||/** Energy // энергия */(reward?.stamina ? reward.stamina : false) ||/** accelerating energy gain // ускорение набора энергии */(reward?.buff ? true : false) ||/** VIP Points // вип очки */(reward?.vipPoints ? reward.vipPoints : false) ||/** souls of heroes // душы героев */(reward?.fragmentHero ? true : false) ||/** heroes // герои */(reward?.bundleHeroReward ? true : false));if (isFarmLetter) {lettersIds.push(~~letter.id);continue;}/*** Если до окончания годности письма менее 24 часов,* то оно собирается не смотря на исключения*/const availableUntil = +letter?.availableUntil;if (availableUntil) {const maxTimeLeft = 24 * 60 * 60 * 1000;const timeLeft = (new Date(availableUntil * 1000) - new Date())console.log('Time left:', timeLeft)if (timeLeft < maxTimeLeft) {lettersIds.push(~~letter.id);continue;}}}return lettersIds;}/*** Displaying information about the areas of the portal and attempts on the VG** Отображение информации о сферах портала и попытках на ВГ*/async function justInfo() {return new Promise(async (resolve, reject) => {const calls = [{name: 'userGetInfo',args: {},ident: 'userGetInfo',},{name: 'clanWarGetInfo',args: {},ident: 'clanWarGetInfo',},{name: 'titanArenaGetStatus',args: {},ident: 'titanArenaGetStatus',},{name: 'quest_completeEasterEggQuest',args: {},ident: 'quest_completeEasterEggQuest',},];const r###lt = await Send(JSON.stringify({ calls }));const infos = r###lt.r###lts;const portalSphere = infos[0].r###lt.response.refillable.find(n => n.id == 45);const clanWarMyTries = infos[1].r###lt.response?.myTries ?? 0;const arePointsMax = infos[1].r###lt.response?.arePointsMax;const titansLevel = +(infos[2].r###lt.response?.tier ?? 0);const titansStatus = infos[2].r###lt.response?.status; //peace_time || battleconst sanctuaryButton = buttons['testAdventure'].button;const sanctuaryDot = sanctuaryButton.querySelector('.scriptMenu_dot');const clanWarButton = buttons['goToClanWar'].button;const clanWarDot = clanWarButton.querySelector('.scriptMenu_dot');const titansArenaButton = buttons['testTitanArena'].button;const titansArenaDot = titansArenaButton.querySelector('.scriptMenu_dot');if (portalSphere.amount) {sanctuaryButton.classList.add('scriptMenu_attention');sanctuaryDot.title = `${portalSphere.amount} ${I18N('PORTALS')}`;sanctuaryDot.innerText = portalSphere.amount;sanctuaryDot.style.backgroundColor = 'red';} else {sanctuaryButton.classList.remove('scriptMenu_attention');}if (clanWarMyTries && !arePointsMax) {clanWarButton.classList.add('scriptMenu_attention');clanWarDot.title = `${clanWarMyTries} ${I18N('ATTEMPTS')}`;clanWarDot.innerText = clanWarMyTries;clanWarDot.style.backgroundColor = 'red';} else {clanWarButton.classList.remove('scriptMenu_attention');}if (titansLevel < 7 && titansStatus == 'battle') { ;titansArenaButton.classList.add('scriptMenu_attention');titansArenaDot.title = `${titansLevel} ${I18N('LEVEL')}`;titansArenaDot.innerText = titansLevel;titansArenaDot.style.backgroundColor = 'red';} else {titansArenaButton.classList.remove('scriptMenu_attention');}const imgPortal ='data:image/gif;base64,R0lGODlhLwAvAHAAACH5BAEAAP8ALAAAAAAvAC8AhwAAABkQWgjF3krO3ghSjAhSzinF3u+tGWvO3s5rGSmE5gha7+/OWghSrWvmnClShCmUlAiE5u+MGe/W3mvvWmspUmvvGSnOWinOnCnOGWsZjErvnAiUlErvWmsIUkrvGQjOWgjOnAjOGUoZjM6MGe/OIWvv5q1KGSnv5mulGe/vWs7v3ozv3kqEGYxKGWuEWmtSKUrv3mNaCEpKUs7OWiml5ggxWmMpEAgZpRlaCO/35q1rGRkxKWtarSkZrRljKSkZhAjv3msIGRk6CEparQhjWq3v3kql3ozOGe/vnM6tGYytWu9rGWuEGYzO3kqE3gil5s6MWq3vnGvFnM7vWoxrGc5KGYyMWs6tWq2MGYzOnO+tWmvFWkqlWoxrWgAZhEqEWq2tWoytnIyt3krFnGul3mulWmulnEIpUkqlGUqlnK3OnK2MWs7OnClSrSmUte+tnGvFGYytGYzvWs5rWowpGa3O3u/OnErFWoyMnGuE3muEnEqEnIyMGYzOWs7OGe9r3u9rWq3vWq1rWq1r3invWimlWu+t3q0pWq2t3u8pWu8p3q0p3invnCnvGe/vGa2tGa3vGa2tnK0pGe9rnK1rnCmlGe8pGe8pnK0pnGsZrSkp3msp3s7vGYzvnM7vnIzvGc6tnM5r3oxr3gilWs6t3owpWs4pWs4p3owp3s5rnIxrnAilGc4pGc4pnIwpnAgp3kop3s7O3u9KGe+MWoxKWoyM3kIIUgiUte+MnErFGc5KWowIGe9K3u9KWq3OWq1KWq1K3gjvWimEWu+M3q0IWq2M3u8IWu8I3q0I3gjvnAjvGa3OGa2MnK0IGe9KnK1KnCmEGe8IGe8InK0InEoZrSkI3msI3s6MnM5K3oxK3giEWs6M3owIWs4IWs4I3owI3s5KnIxKnAiEGc4IGc4InIwInAgI3koI3kJaCAgQKUIpEGtKUkJSKUIIECla7ylazmtahGta70pa70pahGtazkpazmtrWiExUkprUiljWikQKRkQCAAQCAAACAAAAAj/AP8JHEiwoMGDCBMqXMiwocODJlBIRBHDxMOLBmMEkSjAgICPE2Mw/OUH4z8TGz+agBIBCsuWUAQE0WLwzkAkKZZcnAilhk+fA1bUiEC0ZZABJOD8IyHhwJYDkpakafJQ4kooR5yw0LFihQ4WJhAMKCoARRYSTJgkUOInBZK2DiX2rGHEiI67eFcYATtAAVEoKEiQSFBFDs4UKbg0lGgAigIEeCNzrWvCxIChEcoy3dGiSoITTRQvnCLRrxOveI2McbKahevKJmooiKkFy4Gzg5tMMaMwitwIj/PqGPCugL0CT47ANhEjQg3Atg9IT5CiS4uEUcRIBH4EtREETuB9/xn/BUcBBbBXGGgpoPaBEid23EuXgvdBJhtQGFCwwA7eMgs0gEMDBJD3hR7KbRVbSwP8UcIWJNwjIRLXGZRAAhLVsIACR9y1whMNfNGAHgiUcUSBX8ADWwwKzCYADTSUcMA9ebwQmkFYMMFGhgu80x1XTxSAwxNdGWGCAiG6YQBzly3QkhYxlsDGP1cg4YBBaC0h1zsLPGHXCkfA00AZeu11hALl1VBZXwW0RAaMDGDxTxNdTGEQExJoiUINXCpwmhFOKJCcVmCdOR56MezXJhRvwFlCC2lcWVAUEjBxRobw9HhEXUYekWBlsoVoQEWyFbAAFPRIQQMDJcDQhRhYSv+QZ1kGcAnPYya4BhZYlb1TQ4iI+tVmBPpIQQWrMORxkKwSsEFrDaa+8xgCy1mmgLSHxtDXAhtGMIOxDKjgAkLM7iAAYD4VJ+0RAyAgVl++ikfAESxy62QB365awrjLyprAcxEY4FOmXEp7LbctjlfAAE1yGwEBYBirAgP8GtTUARIMM1QBPrVYQAHF9dgiml/Mexl/3DbAwxnHMqBExQVdLAEMjRXQgHOyydaibPCgqEDH3JrawDosUDExCTATZJuMJ0AAxRNXtLFFPD+P/DB58AC9wH4N4BMxDRPvkPRAbLx3AAlVMLBFCXeQgIaIKJKHQ9X8+forAetMsaoKB7j/MAhCL5j9VFNPJYBGiCGW18CtsvWIs5j7gLEGqyV81gxC6ZBQQgkSMEUCLQckMMLHNhcAD3B+8TdyA0PPACWrB8SH0BItyHAAAwdE4YILTSUww8cELwAyt7D4JSberkd5wA4neIFQE020sMPmJZBwAi0SJMBOA6WTXgAsDYDPOj7r3KNFy5WfkEBCKbTQBQzTM+By5wm4YAPr+LM+IIE27LPOFWswmgqqZ4UEXCEhLUjBGWbgAs3JD2OfWcc68GEDArCOAASwAfnWUYUwtIEKSVCBCiSgPuclpAlImMI9YNDAzeFuMEwQ2w3W4Q530PAGLthBFNqwghCKMAoF3MEB/xNihvr8Ix4sdCCrJja47CVAMFjAwid6eJcQWi8BO4jHQl6AGFjdwwUnOMF75CfCMpoxCTpAoxoZMBgs3qMh7ZODQFYYxgSMsQTh###K0BiZJNxBCZ7zwhsbYqO3wCoe7AjjCaxAggNUcY94mcDa3qMECWSBHYN0CBfj0IQliEFCMFjkIulAAisUkBZYyB4USxAFCZnkH1xsgltSYCMYyACMpizghS7kOTZIKJMmeYEZzCCH6iCmBS1IRzpkcEsXVMGZMMgHJvfwyoLsYQ9nmMIUuDAFPIAhH8pUZjLbcY89rKKaC9nDFeLxy3vkYwbJTMcL0InOeOSjBVShJz2pqQvPfvrznwANKEMCAgA7';setProgress('<img src="' + imgPortal + '" style="height: 25px;position: relative;top: 5px;"> ' + `${portalSphere.amount} </br> ${I18N('GUILD_WAR')}: ${clanWarMyTries}`, true);resolve();});}async function getDailyBonus() {const dailyBonusInfo = await Send(JSON.stringify({calls: [{name: "dailyBonusGetInfo",args: {},ident: "body"}]})).then(e => e.r###lts[0].r###lt.response);const { availableToday, availableVip, currentDay } = dailyBonusInfo;if (!availableToday) {console.log('Уже собрано');return;}const currentVipPoints = +userInfo.vipPoints;const dailyBonusStat = lib.getData('dailyBonusStatic');const vipInfo = lib.getData('level').vip;let currentVipLevel = 0;for (let i in vipInfo) {vipLvl = vipInfo[i];if (currentVipPoints >= vipLvl.vipPoints) {currentVipLevel = vipLvl.level;}}const vipLevelDouble = dailyBonusStat[`${currentDay}_0_0`].vipLevelDouble;const calls = [{name: "dailyBonusFarm",args: {vip: availableVip && currentVipLevel >= vipLevelDouble ? 1 : 0},ident: "body"}];const r###lt = await Send(JSON.stringify({ calls }));if (r###lt.error) {console.error(r###lt.error);return;}const reward = r###lt.r###lts[0].r###lt.response;const type = Object.keys(reward).pop();const itemId = Object.keys(reward[type]).pop();const count = reward[type][itemId];const itemName = cheats.translate(`LIB_${type.toUpperCase()}_NAME_${itemId}`);console.log(`Ежедневная награда: Получено ${count} ${itemName}`, reward);}async function farmStamina(lootBoxId = 148) {const lootBox = await Send('{"calls":[{"name":"inventoryGet","args":{},"ident":"inventoryGet"}]}').then(e => e.r###lts[0].r###lt.response.consumable[148]);/** Добавить другие ящики *//*** 144 - медная шкатулка* 145 - бронзовая шкатулка* 148 - платиновая шкатулка*/if (!lootBox) {setProgress(I18N('NO_BOXES'), true);return;}let maxFarmEnergy = getSaveVal('maxFarmEnergy', 100);const r###lt = await popup.confirm(I18N('OPEN_LOOTBOX', { lootBox }), [{ r###lt: false, isClose: true },{ msg: I18N('BTN_YES'), r###lt: true },{ msg: I18N('STAMINA'), isInput: true, default: maxFarmEnergy },]);if (!+r###lt) {return;}if ((typeof r###lt) !== 'boolean' && Number.parseInt(r###lt)) {maxFarmEnergy = +r###lt;setSaveVal('maxFarmEnergy', maxFarmEnergy);} else {maxFarmEnergy = 0;}let collectEnergy = 0;for (let count = lootBox; count > 0; count--) {const response = await Send('{"calls":[{"name":"consumableUseLootBox","args":{"libId":148,"amount":1},"ident":"body"}]}').then((e) => e.r###lts[0].r###lt.response);const r###lt = Object.values(response).pop();if ('stamina' in r###lt) {setProgress(`${I18N('OPEN')}: ${lootBox - count}/${lootBox} ${I18N('STAMINA')} +${r###lt.stamina}<br>${I18N('STAMINA')}: ${collectEnergy}`, false);console.log(`${ I18N('STAMINA') } + ${ r###lt.stamina }`);if (!maxFarmEnergy) {return;}collectEnergy += +r###lt.stamina;if (collectEnergy >= maxFarmEnergy) {console.log(`${I18N('STAMINA')} + ${ collectEnergy }`);setProgress(`${I18N('STAMINA')} + ${ collectEnergy }`, false);return;}} else {setProgress(`${I18N('OPEN')}: ${lootBox - count}/${lootBox}<br>${I18N('STAMINA')}: ${collectEnergy}`, false);console.log(r###lt);}}setProgress(I18N('BOXES_OVER'), true);}async function fillActive() {const data = await Send(JSON.stringify({calls: [{name: "questGetAll",args: {},ident: "questGetAll"}, {name: "inventoryGet",args: {},ident: "inventoryGet"}, {name: "clanGetInfo",args: {},ident: "clanGetInfo"}]})).then(e => e.r###lts.map(n => n.r###lt.response));const quests = data[0];const inv = data[1];const stat = data[2].stat;const maxActive = 2000 - stat.todayItemsActivity;if (maxActive <= 0) {setProgress(I18N('NO_MORE_ACTIVITY'), true);return;}let countGetActive = 0;const quest = quests.find(e => e.id > 10046 && e.id < 10051);if (quest) {countGetActive = 1750 - quest.progress;}if (countGetActive <= 0) {countGetActive = maxActive;}console.log(countGetActive);countGetActive = +(await popup.confirm(I18N('EXCHANGE_ITEMS', { maxActive }), [{ r###lt: false, isClose: true },{ msg: I18N('GET_ACTIVITY'), isInput: true, default: countGetActive.toString() },]));if (!countGetActive) {return;}if (countGetActive > maxActive) {countGetActive = maxActive;}const items = lib.getData('inventoryItem');let itemsInfo = [];for (let type of ['gear', 'scroll']) {for (let i in inv[type]) {const v = items[type][i]?.enchantValue || 0;itemsInfo.push({id: i,count: inv[type][i],v,type})}const invType = 'fragment' + type.toLowerCase().charAt(0).toUpperCase() + type.slice(1);for (let i in inv[invType]) {const v = items[type][i]?.fragmentEnchantValue || 0;itemsInfo.push({id: i,count: inv[invType][i],v,type: invType})}}itemsInfo = itemsInfo.filter(e => e.v < 4 && e.count > 200);itemsInfo = itemsInfo.sort((a, b) => b.count - a.count);console.log(itemsInfo);const activeItem = itemsInfo.shift();console.log(activeItem);const countItem = Math.ceil(countGetActive / activeItem.v);if (countItem > activeItem.count) {setProgress(I18N('NOT_ENOUGH_ITEMS'), true);console.log(activeItem);return;}await Send(JSON.stringify({calls: [{name: "clanItemsForActivity",args: {items: {[activeItem.type]: {[activeItem.id]: countItem}}},ident: "body"}]})).then(e => {/** TODO: Вывести потраченые предметы */console.log(e);setProgress(`${I18N('ACTIVITY_RECEIVED')}: ` + e.r###lts[0].r###lt.response, true);});}async function buyHeroFragments() {const r###lt = await Send('{"calls":[{"name":"inventoryGet","args":{},"ident":"inventoryGet"},{"name":"shopGetAll","args":{},"ident":"shopGetAll"}]}').then(e => e.r###lts.map(n => n.r###lt.response));const inv = r###lt[0];const shops = Object.values(r###lt[1]).filter(shop => [4, 5, 6, 8, 9, 10, 17].includes(shop.id));const calls = [];for (let shop of shops) {const slots = Object.values(shop.slots);for (const slot of slots) {/* Уже куплено */if (slot.bought) {continue;}/* Не душа героя */if (!('fragmentHero' in slot.reward)) {continue;}const coin = Object.keys(slot.cost).pop();const coinId = Object.keys(slot.cost[coin]).pop();const stock = inv[coin][coinId] || 0;/* Не хватает на покупку */if (slot.cost[coin][coinId] > stock) {continue;}inv[coin][coinId] -= slot.cost[coin][coinId];calls.push({name: "shopBuy",args: {shopId: shop.id,slot: slot.id,cost: slot.cost,reward: slot.reward,},ident: `shopBuy_${shop.id}_${slot.id}`,})}}if (!calls.length) {setProgress(I18N('NO_PURCHASABLE_HERO_SOULS'), true);return;}const bought = await Send(JSON.stringify({ calls })).then(e => e.r###lts.map(n => n.r###lt.response));if (!bought) {console.log('что-то пошло не так')return;}let countHeroSouls = 0;for (const buy of bought) {countHeroSouls += +Object.values(Object.values(buy).pop()).pop();}console.log(countHeroSouls, bought, calls);setProgress(I18N('PURCHASED_HERO_SOULS', { countHeroSouls }), true);}/** Открыть платные сундуки в Запределье за 90 */async function bossOpenChestPay() {const callsNames = ['userGetInfo', 'bossGetAll', 'specialOffer_getAll', 'getTime'];const info = await Send({ calls: callsNames.map((name) => ({ name, args: {}, ident: name })) }).then((e) =>e.r###lts.map((n) => n.r###lt.response));const user = info[0];const boses = info[1];const offers = info[2];const time = info[3];const discountOffer = offers.find((e) => e.offerType == 'costReplaceOutlandChest');let discount = 1;if (discountOffer && discountOffer.endTime > time) {discount = 1 - discountOffer.offerData.outlandChest.discountPercent / 100;}cost9chests = 540 * discount;cost18chests = 1740 * discount;costFirstChest = 90 * discount;costSecondChest = 200 * discount;const currentStarMoney = user.starMoney;if (currentStarMoney < cost9chests) {setProgress('Недостаточно изюма, нужно ' + cost9chests + ' у Вас ' + currentStarMoney, true);return;}const imgEmerald ="<img style='position: relative;top: 3px;' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAXCAYAAAD+4+QTAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAY8SURBVEhLpVV5bFVlFv/d7a19W3tfN1pKabGFAm3Rlg4toAWRiH+AioiaqAkaE42NycRR0ZnomJnJYHAJERGNyx/GJYoboo2igKVSMUUKreW1pRvUvr7XvvXe9+7qeW1nGJaJycwvObnny/fl/L7zO+c7l8EV0LAKzA+H83lAFAC/BeDJN2gnc5yd/WaQ8Q0NCCnAANkU+ZfjIpKqJWBOd4EDbHagueBPb1tWuesi9Rqn86zJZDbAMTp4xo###Maa4FVe6fra3bbzQbYN6A8Cmrz0qoBx8gzMmaj/QfKHWyxs+4e1DiC78M9v5TTn1RtbVH+kMWlJCCad100VOmQiUWFnNLg4HW42QeYEl3KnIiP5Bzu/dr27o0UistD48k2d8rF9Sib9GZKaejAnOmrs2/6e3VR3q7idF41GWVA41uQQ1RMY00ZJrChcrAYvx8HHaSjil8LLilCY98BORylBKlWQHhjzfvfFnuTfPn1O+xFolzM7s5nMI80rSl7qib8ykRNcWyaUosBWgnN6BL3pHuRwucjmnBTUCjfHwElkNiaNPHYr0mYCKnMeE/r3OC2NQiZZheHsfQ9Vu1uAM+eBIX2W5Nqsh/ewtxlrhl75NtUviDpwq+s+NOXWwWFhKKCd6iCQVByV2qSb0wEo5PvhY9YikGrH3uAdiBtBDIdVVAvlyfjBOffuesTcDxySqD3mUxaOPLZ6aktAOS/kqHaYigN7gnsxMGnDAuEuiPw6ymIt3MwaZFFQB7MeTmYjPLSWjTTCioQ5XCOMJIPeoInD/SNOviy6heLmALkckRTyf3xLbtQ8k6sdOodcxoocMoXU9JoFdF8VESMMiWRJmykyedqXTInaQJnOTtYDcJtZ+DXkRSrOou1cCoHx4LptL0nLgYU8kWhwlFgrNV2wFnEmVAr+w9gUzkwQic2DoNmLYe0QgkYXIuYg4uYYosYQJs1fMGkEpqWzUVucDh9E37gCIWFgvY9FcbniEipii6hbwZVilP0kXB/jysrrPLqU3yDG0JzXhA3OjWgsXo8UG6XbR6AxScqJjJHo/gmY0+9FIOn80I0UkukQFohJNFZmwV/uhosX2j59KPuF8JgS5CI3wHB90RUdKL12pMs7Z3VvfH6WyOajPt+Deb7FRDCBmNmNpNmPhHEWCW0IMXUQaTVEtVPhseYTZRCBeB86h8+hY0yDodsHfny+4NETB7JOLN74TXqmu1Yu4ixHuj3ii0/eaatx7RgY/NYKtR2tm+6B7lbwTGg3bDQ06MLTcsoJettR4DqaC8+u/gfe6HwZOzuGQU8JDR5f1B2+6uHWp8RPSjfsj5/dDyMzfIAj3bqSK8bGW579ECPWXRViHTijDK2BPoj###xkbXCZflh1H5ISkCCSWJxI8jcjmErhnaHh6fdzdbZTd0aKd7Q+5T/gqj6VyBBkwmfG0QySkkHDJq19dDrgvP3GQq/Pt6h/8mesLqqFz+6DRq0qWkR4uGzEYhrGJBktNdvQGfoJH490YwmNuwKt+LWvWubtAk6GlPHhfw/LCyQz0BXEZOaoLcDf1lAt2z1z5nIhlIsL0Csfo90sWDkHXDYXaq2VWFZShffOfoQc0qOIzT9wbGvpXxOYGgG6SdwLuJSE6mPT1ZNdUdM9fyi8YlnTEiHLc423GBPaFBSVQcrQqcMYrJrbjElVRUf8FIq57K4z/8x7rL9f7ymsb0vHz83GmsXlJJSlsXKhxn3w+YSyrC48vKB0zVbLYqHCUYEe5SekaRYznBuLvU1olwbBmvr4r/v4RzteN4761x+Wxg9dGPH/wkzhL8WRHkMvKo7j/sc/Swfir7ZT/WTYSapc6LwFhc4qSKwLEYHXoz/bnzv8dOw7+4ojyYkvLyfI4MokhNToSKZwYf+6u3e39P3y8XH6AeY5yxHiBcx11OA8rZO9qTdaNx9/n9KPyUdnOulKuFyui6GHAAkHpEDBptqauaKtcMySRBW3HH2Do1+9WbP9GXocVGj5okJfit8jATY06Dh+MBIyiwZrrylb4XXneO1BV9df7n/tMb0/0J17O9LJU7Nn/x+UrKvOyOq58dXtNz0Q2Luz+cUnrqe1q+qmyv8q9/+EypuXZrK2kdEwgW3R5pW/r8I0gN8AVk6uP7Y929oAAAAASUVORK5CYII='>";if (currentStarMoney < cost9chests) {setProgress(I18N('NOT_ENOUGH_EMERALDS_540', { currentStarMoney, imgEmerald }), true);return;}const buttons = [{ r###lt: false, isClose: true }];if (currentStarMoney >= cost9chests) {buttons.push({msg: I18N('BUY_OUTLAND_BTN', { count: 9, countEmerald: cost9chests, imgEmerald }),r###lt: [costFirstChest, costFirstChest, 0],});}if (currentStarMoney >= cost18chests) {buttons.push({msg: I18N('BUY_OUTLAND_BTN', { count: 18, countEmerald: cost18chests, imgEmerald }),r###lt: [costFirstChest, costFirstChest, 0, costSecondChest, costSecondChest, 0],});}const answer = await popup.confirm(`<div style="margin-bottom: 15px;">${I18N('BUY_OUTLAND')}</div>`, buttons);if (!answer) {return;}const callBoss = [];let n = 0;for (let boss of boses) {const bossId = boss.id;if (boss.chestNum != 2) {continue;}const calls = [];for (const starmoney of answer) {calls.push({name: 'bossOpenChest',args: {amount: 1,bossId,starmoney,},ident: 'bossOpenChest_' + ++n,});}callBoss.push(calls);}if (!callBoss.length) {setProgress(I18N('CHESTS_NOT_AVAILABLE'), true);return;}let count = 0;let errors = 0;for (const calls of callBoss) {const r###lt = await Send({ calls });console.log(r###lt);if (r###lt?.r###lts) {count += r###lt.r###lts.length;} else {errors++;}}setProgress(`${I18N('OUTLAND_CHESTS_RECEIVED')}: ${count}`, true);}async function autoRaidAdventure() {const calls = [{name: "userGetInfo",args: {},ident: "userGetInfo"},{name: "adventure_raidGetInfo",args: {},ident: "adventure_raidGetInfo"}];const r###lt = await Send(JSON.stringify({ calls })).then(e => e.r###lts.map(n => n.r###lt.response));const portalSphere = r###lt[0].refillable.find(n => n.id == 45);const adventureRaid = Object.entries(r###lt[1].raid).filter(e => e[1]).pop()const adventureId = adventureRaid ? adventureRaid[0] : 0;if (!portalSphere.amount || !adventureId) {setProgress(I18N('RAID_NOT_AVAILABLE'), true);return;}const countRaid = +(await popup.confirm(I18N('RAID_ADVENTURE', { adventureId }), [{ r###lt: false, isClose: true },{ msg: I18N('RAID'), isInput: true, default: portalSphere.amount },]));if (!countRaid) {return;}if (countRaid > portalSphere.amount) {countRaid = portalSphere.amount;}const r###ltRaid = await Send(JSON.stringify({calls: [...Array(countRaid)].map((e, i) => ({name: "adventure_raid",args: {adventureId},ident: `body_${i}`}))})).then(e => e.r###lts.map(n => n.r###lt.response));if (!r###ltRaid.length) {console.log(r###ltRaid);setProgress(I18N('SOMETHING_WENT_WRONG'), true);return;}console.log(r###ltRaid, adventureId, portalSphere.amount);setProgress(I18N('ADVENTURE_COMPLETED', { adventureId, times: r###ltRaid.length }), true);}/** Вывести всю клановую статистику в консоль браузера */async function clanStatistic() {const copy = function (text) {const copyTextarea = document.createElement("textarea");copyTextarea.style.opacity = "0";copyTextarea.textContent = text;document.body.appendChild(copyTextarea);copyTextarea.select();document.execCommand("copy");document.body.removeChild(copyTextarea);delete copyTextarea;}const calls = [{ name: "clanGetInfo", args: {}, ident: "clanGetInfo" },{ name: "clanGetWeeklyStat", args: {}, ident: "clanGetWeeklyStat" },{ name: "clanGetLog", args: {}, ident: "clanGetLog" },];const r###lt = await Send(JSON.stringify({ calls }));const dataClanInfo = r###lt.r###lts[0].r###lt.response;const dataClanStat = r###lt.r###lts[1].r###lt.response;const dataClanLog = r###lt.r###lts[2].r###lt.response;const membersStat = {};for (let i = 0; i < dataClanStat.stat.length; i++) {membersStat[dataClanStat.stat[i].id] = dataClanStat.stat[i];}const joinStat = {};historyLog = dataClanLog.history;for (let j in historyLog) {his = historyLog[j];if (his.event == 'join') {joinStat[his.userId] = his.ctime;}}const infoArr = [];const members = dataClanInfo.clan.members;for (let n in members) {var member = [n,members[n].name,members[n].level,dataClanInfo.clan.warriors.includes(+n) ? 1 : 0,(new Date(members[n].lastLoginTime * 1000)).toLocaleString().replace(',', ''),joinStat[n] ? (new Date(joinStat[n] * 1000)).toLocaleString().replace(',', '') : '',membersStat[n].activity.reverse().join('\t'),membersStat[n].adventureStat.reverse().join('\t'),membersStat[n].clanGifts.reverse().join('\t'),membersStat[n].clanWarStat.reverse().join('\t'),membersStat[n].dungeonActivity.reverse().join('\t'),];infoArr.push(member);}const info = infoArr.sort((a, b) => (b[2] - a[2])).map((e) => e.join('\t')).join('\n');console.log(info);copy(info);setProgress(I18N('CLAN_STAT_COPY'), true);}async function buyInStoreForGold() {const r###lt = await Send('{"calls":[{"name":"shopGetAll","args":{},"ident":"body"},{"name":"userGetInfo","args":{},"ident":"userGetInfo"}]}').then(e => e.r###lts.map(n => n.r###lt.response));const shops = r###lt[0];const user = r###lt[1];let gold = user.gold;const calls = [];if (shops[17]) {const slots = shops[17].slots;for (let i = 1; i <= 2; i++) {if (!slots[i].bought) {const costGold = slots[i].cost.gold;if ((gold - costGold) < 0) {continue;}gold -= costGold;calls.push({name: "shopBuy",args: {shopId: 17,slot: i,cost: slots[i].cost,reward: slots[i].reward,},ident: 'body_' + i,})}}}const slots = shops[1].slots;for (let i = 4; i <= 6; i++) {if (!slots[i].bought && slots[i]?.cost?.gold) {const costGold = slots[i].cost.gold;if ((gold - costGold) < 0) {continue;}gold -= costGold;calls.push({name: "shopBuy",args: {shopId: 1,slot: i,cost: slots[i].cost,reward: slots[i].reward,},ident: 'body_' + i,})}}if (!calls.length) {setProgress(I18N('NOTHING_BUY'), true);return;}const r###ltBuy = await Send(JSON.stringify({ calls })).then(e => e.r###lts.map(n => n.r###lt.response));console.log(r###ltBuy);const countBuy = r###ltBuy.length;setProgress(I18N('LOTS_BOUGHT', { countBuy }), true);}function rewardsAndMailFarm() {return new Promise(function (resolve, reject) {let questGetAllCall = {calls: [{name: "questGetAll",args: {},ident: "questGetAll"}, {name: "mailGetAll",args: {},ident: "mailGetAll"}]}send(JSON.stringify(questGetAllCall), function (data) {if (!data) return;const questGetAll = data.r###lts[0].r###lt.response.filter((e) => e.state == 2);const questBattlePass = lib.getData('quest').battlePass;const questChainBPass = lib.getData('battlePass').questChain;const listBattlePass = lib.getData('battlePass').list;const questAllFarmCall = {calls: [],};const questIds = [];for (let quest of questGetAll) {if (quest.id >= 2001e4) {continue;}if (quest.id > 1e6 && quest.id < 2e7) {const questInfo = questBattlePass[quest.id];const chain = questChainBPass[questInfo.chain];if (chain.requirement?.battlePassTicket) {continue;}const battlePass = listBattlePass[chain.battlePass];const startTime = battlePass.startCondition.time.value * 1e3const endTime = new Date(startTime + battlePass.duration * 1e3);if (startTime > Date.now() || endTime < Date.now()) {continue;}}if (quest.id >= 2e7) {questIds.push(quest.id);continue;}questAllFarmCall.calls.push({name: 'questFarm',args: {questId: quest.id,},ident: `questFarm_${quest.id}`,});}if (questIds.length) {questAllFarmCall.calls.push({name: 'quest_questsFarm',args: { questIds },ident: 'quest_questsFarm',});}let letters = data?.r###lts[1]?.r###lt?.response?.letters;letterIds = lettersFilter(letters);if (letterIds.length) {questAllFarmCall.calls.push({name: 'mailFarm',args: { letterIds },ident: 'mailFarm',});}if (!questAllFarmCall.calls.length) {setProgress(I18N('NOTHING_TO_COLLECT'), true);resolve();return;}send(JSON.stringify(questAllFarmCall), async function (res) {let countQuests = 0;let countMail = 0;let questsIds = [];for (let call of res.r###lts) {if (call.ident.includes('questFarm')) {countQuests++;} else if (call.ident.includes('questsFarm')) {countQuests += Object.keys(call.r###lt.response).length;} else if (call.ident.includes('mailFarm')) {countMail = Object.keys(call.r###lt.response).length;}const newQuests = call.r###lt.newQuests;if (newQuests) {for (let quest of newQuests) {if ((quest.id < 1e6 || (quest.id >= 2e7 && quest.id < 2001e4)) && quest.state == 2) {questsIds.push(quest.id);}}}}while (questsIds.length) {const questIds = [];const calls = [];for (let questId of questsIds) {if (questId < 1e6) {calls.push({name: 'questFarm',args: {questId,},ident: `questFarm_${questId}`,});countQuests++;} else if (questId >= 2e7 && questId < 2001e4) {questIds.push(questId);countQuests++;}}calls.push({name: 'quest_questsFarm',args: { questIds },ident: 'body',});const r###lts = await Send({ calls }).then((e) => e.r###lts.map((e) => e.r###lt));questsIds = [];for (const r###lt of r###lts) {const newQuests = r###lt.newQuests;if (newQuests) {for (let quest of newQuests) {if (quest.state == 2) {questsIds.push(quest.id);}}}}}setProgress(I18N('COLLECT_REWARDS_AND_MAIL', { countQuests, countMail }), true);resolve();});});})}class epicBrawl {timeout = null;time = null;constructor() {if (epicBrawl.inst) {return epicBrawl.inst;}epicBrawl.inst = this;return this;}runTimeout(func, timeDiff) {const worker = new Worker(URL.createObjectURL(new Blob([`self.onmessage = function(e) {const timeDiff = e.data;if (timeDiff > 0) {setTimeout(() => {self.postMessage(1);self.close();}, timeDiff);}};`])));worker.postMessage(timeDiff);worker.onmessage = () => {func();};return true;}timeDiff(date1, date2) {const date1Obj = new Date(date1);const date2Obj = new Date(date2);const timeDiff = Math.abs(date2Obj - date1Obj);const totalSeconds = timeDiff / 1000;const minutes = Math.floor(totalSeconds / 60);const seconds = Math.floor(totalSeconds % 60);const formattedMinutes = String(minutes).padStart(2, '0');const formattedSeconds = String(seconds).padStart(2, '0');return `${formattedMinutes}:${formattedSeconds}`;}check() {console.log(new Date(this.time))if (Date.now() > this.time) {this.timeout = null;this.start()return;}this.timeout = this.runTimeout(() => this.check(), 6e4);return this.timeDiff(this.time, Date.now())}async start() {if (this.timeout) {const time = this.timeDiff(this.time, Date.now());console.log(new Date(this.time))setProgress(I18N('TIMER_ALREADY', { time }), false, hideProgress);return;}setProgress(I18N('EPIC_BRAWL'), false, hideProgress);const teamInfo = await Send('{"calls":[{"name":"teamGetAll","args":{},"ident":"teamGetAll"},{"name":"teamGetFavor","args":{},"ident":"teamGetFavor"},{"name":"userGetInfo","args":{},"ident":"userGetInfo"}]}').then(e => e.r###lts.map(n => n.r###lt.response));const refill = teamInfo[2].refillable.find(n => n.id == 52)this.time = (refill.lastRefill + 3600) * 1000const attempts = refill.amount;if (!attempts) {console.log(new Date(this.time));const time = this.check();setProgress(I18N('NO_ATTEMPTS_TIMER_START', { time }), false, hideProgress);return;}if (!teamInfo[0].epic_brawl) {setProgress(I18N('NO_HEROES_PACK'), false, hideProgress);return;}const args = {heroes: teamInfo[0].epic_brawl.filter(e => e < 1000),pet: teamInfo[0].epic_brawl.filter(e => e > 6000).pop(),favor: teamInfo[1].epic_brawl,}let wins = 0;let coins = 0;let streak = { progress: 0, nextStage: 0 };for (let i = attempts; i > 0; i--) {const info = await Send(JSON.stringify({calls: [{ name: "epicBrawl_getEnemy", args: {}, ident: "epicBrawl_getEnemy" }, { name: "epicBrawl_startBattle", args, ident: "epicBrawl_startBattle" }]})).then(e => e.r###lts.map(n => n.r###lt.response));const { progress, r###lt } = await Calc(info[1].battle);const endR###lt = await Send(JSON.stringify({ calls: [{ name: "epicBrawl_endBattle", args: { progress, r###lt }, ident: "epicBrawl_endBattle" }, { name: "epicBrawl_getWinStreak", args: {}, ident: "epicBrawl_getWinStreak" }] })).then(e => e.r###lts.map(n => n.r###lt.response));const r###ltInfo = endR###lt[0].r###lt;streak = endR###lt[1];wins += r###ltInfo.win;coins += r###ltInfo.reward ? r###ltInfo.reward.coin[39] : 0;console.log(endR###lt[0].r###lt)if (endR###lt[1].progress == endR###lt[1].nextStage) {const farm = await Send('{"calls":[{"name":"epicBrawl_farmWinStreak","args":{},"ident":"body"}]}').then(e => e.r###lts[0].r###lt.response);coins += farm.coin[39];}setProgress(I18N('EPIC_BRAWL_R###LT', {i, wins, attempts, coins,progress: streak.progress,nextStage: streak.nextStage,end: '',}), false, hideProgress);}console.log(new Date(this.time));const time = this.check();setProgress(I18N('EPIC_BRAWL_R###LT', {wins, attempts, coins,i: '',progress: streak.progress,nextStage: streak.nextStage,end: I18N('ATTEMPT_ENDED', { time }),}), false, hideProgress);}}function countdownTimer(seconds, message, onClick = null) {message = message || I18N('TIMER');const stopTimer = Date.now() + seconds * 1e3;const isOnClick = typeof onClick === 'function';return new Promise((resolve) => {const interval = setInterval(async () => {const now = Date.now();const remaining = (stopTimer - now) / 1000;const clickHandler = isOnClick? () => {onClick();clearInterval(interval);setProgress('', true);resolve(false);}: undefined;setProgress(`${message} ${remaining.toFixed(2)}`, false, clickHandler);if (now > stopTimer) {clearInterval(interval);setProgress('', true);resolve(true);}}, 100);});}this.HWHFuncs.countdownTimer = countdownTimer;/** Набить килов в горниле душк */async function bossRatingEventSouls() {const data = await Send({calls: [{ name: "heroGetAll", args: {}, ident: "teamGetAll" },{ name: "offerGetAll", args: {}, ident: "offerGetAll" },{ name: "pet_getAll", args: {}, ident: "pet_getAll" },]});const bossEventInfo = data.r###lts[1].r###lt.response.find(e => e.offerType == "bossEvent");if (!bossEventInfo) {setProgress('Эвент завершен', true);return;}if (bossEventInfo.progress.score > 250) {setProgress('Уже убито больше 250 врагов');rewardBossRatingEventSouls();return;}const availablePets = Object.values(data.r###lts[2].r###lt.response).map(e => e.id);const heroGetAllList = data.r###lts[0].r###lt.response;const usedHeroes = bossEventInfo.progress.usedHeroes;const heroList = [];for (let heroId in heroGetAllList) {let hero = heroGetAllList[heroId];if (usedHeroes.includes(hero.id)) {continue;}heroList.push(hero.id);}if (!heroList.length) {setProgress('Нет героев', true);return;}const pet = availablePets.includes(6005) ? 6005 : availablePets[Math.floor(Math.random() * availablePets.length)];const petLib = lib.getData('pet');let count = 1;for (const heroId of heroList) {const args = {heroes: [heroId],pet}/** Поиск питомца для героя */for (const petId of availablePets) {if (petLib[petId].favorHeroes.includes(heroId)) {args.favor = {[heroId]: petId}break;}}const calls = [{name: "bossRatingEvent_startBattle",args,ident: "body"}, {name: "offerGetAll",args: {},ident: "offerGetAll"}];const res = await Send({ calls });count++;if ('error' in res) {console.error(res.error);setProgress('Перезагрузите игру и попробуйте позже', true);return;}const eventInfo = res.r###lts[1].r###lt.response.find(e => e.offerType == "bossEvent");if (eventInfo.progress.score > 250) {break;}setProgress('Количество убитых врагов: ' + eventInfo.progress.score + '<br>Использовано ' + count + ' героев');}rewardBossRatingEventSouls();}/** Сбор награды из Горнила Душ */async function rewardBossRatingEventSouls() {const data = await Send({calls: [{ name: "offerGetAll", args: {}, ident: "offerGetAll" }]});const bossEventInfo = data.r###lts[0].r###lt.response.find(e => e.offerType == "bossEvent");if (!bossEventInfo) {setProgress('Эвент завершен', true);return;}const farmedChests = bossEventInfo.progress.farmedChests;const score = bossEventInfo.progress.score;// setProgress('Количество убитых врагов: ' + score);const revard = bossEventInfo.reward;const calls = [];let count = 0;for (let i = 1; i < 10; i++) {if (farmedChests.includes(i)) {continue;}if (score < revard[i].score) {break;}calls.push({name: "bossRatingEvent_getReward",args: {rewardId: i},ident: "body_" + i});count++;}if (!count) {setProgress('Нечего собирать', true);return;}Send({ calls }).then(e => {console.log(e);setProgress('Собрано ' + e?.r###lts?.length + ' наград', true);})}/*** Spin the Seer** Покрутить провидца*/async function rollAscension() {const refillable = await Send({calls:[{name:"userGetInfo",args:{},ident:"userGetInfo"}]}).then(e => e.r###lts[0].r###lt.response.refillable);const i47 = refillable.find(i => i.id == 47);if (i47?.amount) {await Send({ calls: [{ name: "ascensionChest_open", args: { paid: false, amount: 1 }, ident: "body" }] });setProgress(I18N('DONE'), true);} else {setProgress(I18N('NOT_ENOUGH_AP'), true);}}/*** Collect gifts for the New Year** Собрать подарки на новый год*/function getGiftNewYear() {Send({ calls: [{ name: "newYearGiftGet", args: { type: 0 }, ident: "body" }] }).then(e => {const gifts = e.r###lts[0].r###lt.response.gifts;const calls = gifts.filter(e => e.opened == 0).map(e => ({name: "newYearGiftOpen",args: {giftId: e.id},ident: `body_${e.id}`}));if (!calls.length) {setProgress(I18N('NY_NO_GIFTS'), 5000);return;}Send({ calls }).then(e => {console.log(e.r###lts)const msg = I18N('NY_GIFTS_COLLECTED', { count: e.r###lts.length });console.log(msg);setProgress(msg, 5000);});})}async function updateArtifacts() {const count = +await popup.confirm(I18N('SET_NUMBER_LEVELS'), [{ msg: I18N('BTN_GO'), isInput: true, default: 10 },{ r###lt: false, isClose: true }]);if (!count) {return;}const quest = new questRun;await quest.autoInit();const heroes = Object.values(quest.questInfo['heroGetAll']);const inventory = quest.questInfo['inventoryGet'];const calls = [];for (let i = count; i > 0; i--) {const upArtifact = quest.getUpgradeArtifact();if (!upArtifact.heroId) {if (await popup.confirm(I18N('POSSIBLE_IMPROVE_LEVELS', { count: calls.length }), [{ msg: I18N('YES'), r###lt: true },{ r###lt: false, isClose: true }])) {break;} else {return;}}const hero = heroes.find(e => e.id == upArtifact.heroId);hero.artifacts[upArtifact.slotId].level++;inventory[upArtifact.costCurrency][upArtifact.costId] -= upArtifact.costValue;calls.push({name: "heroArtifactLevelUp",args: {heroId: upArtifact.heroId,slotId: upArtifact.slotId},ident: `heroArtifactLevelUp_${i}`});}if (!calls.length) {console.log(I18N('NOT_ENOUGH_RESOURECES'));setProgress(I18N('NOT_ENOUGH_RESOURECES'), false);return;}await Send(JSON.stringify({ calls })).then(e => {if ('error' in e) {console.log(I18N('NOT_ENOUGH_RESOURECES'));setProgress(I18N('NOT_ENOUGH_RESOURECES'), false);} else {console.log(I18N('IMPROVED_LEVELS', { count: e.r###lts.length }));setProgress(I18N('IMPROVED_LEVELS', { count: e.r###lts.length }), false);}});}window.sign = a => {const i = this['\x78\x79\x7a'];return md5([i['\x6e\x61\x6d\x65'], i['\x76\x65\x72\x73\x69\x6f\x6e'], i['\x61\x75\x74\x68\x6f\x72'], ~(a % 1e3)]['\x6a\x6f\x69\x6e']('\x5f'))}async function updateSkins() {const count = +await popup.confirm(I18N('SET_NUMBER_LEVELS'), [{ msg: I18N('BTN_GO'), isInput: true, default: 10 },{ r###lt: false, isClose: true }]);if (!count) {return;}const quest = new questRun;await quest.autoInit();const heroes = Object.values(quest.questInfo['heroGetAll']);const inventory = quest.questInfo['inventoryGet'];const calls = [];for (let i = count; i > 0; i--) {const upSkin = quest.getUpgradeSkin();if (!upSkin.heroId) {if (await popup.confirm(I18N('POSSIBLE_IMPROVE_LEVELS', { count: calls.length }), [{ msg: I18N('YES'), r###lt: true },{ r###lt: false, isClose: true }])) {break;} else {return;}}const hero = heroes.find(e => e.id == upSkin.heroId);hero.skins[upSkin.skinId]++;inventory[upSkin.costCurrency][upSkin.costCurrencyId] -= upSkin.cost;calls.push({name: "heroSkinUpgrade",args: {heroId: upSkin.heroId,skinId: upSkin.skinId},ident: `heroSkinUpgrade_${i}`})}if (!calls.length) {console.log(I18N('NOT_ENOUGH_RESOURECES'));setProgress(I18N('NOT_ENOUGH_RESOURECES'), false);return;}await Send(JSON.stringify({ calls })).then(e => {if ('error' in e) {console.log(I18N('NOT_ENOUGH_RESOURECES'));setProgress(I18N('NOT_ENOUGH_RESOURECES'), false);} else {console.log(I18N('IMPROVED_LEVELS', { count: e.r###lts.length }));setProgress(I18N('IMPROVED_LEVELS', { count: e.r###lts.length }), false);}});}function getQuestionInfo(img, nameOnly = false) {const libHeroes = Object.values(lib.data.hero);const parts = img.split(':');const id = parts[1];switch (parts[0]) {case 'titanArtifact_id':return cheats.translate("LIB_TITAN_ARTIFACT_NAME_" + id);case 'titan':return cheats.translate("LIB_HERO_NAME_" + id);case 'skill':return cheats.translate("LIB_SKILL_" + id);case 'inventoryItem_gear':return cheats.translate("LIB_GEAR_NAME_" + id);case 'inventoryItem_coin':return cheats.translate("LIB_COIN_NAME_" + id);case 'artifact':if (nameOnly) {return cheats.translate("LIB_ARTIFACT_NAME_" + id);}heroes = libHeroes.filter(h => h.id < 100 && h.artifacts.includes(+id));return {/** Как называется этот артефакт? */name: cheats.translate("LIB_ARTIFACT_NAME_" + id),/** Какому герою принадлежит этот артефакт? */heroes: heroes.map(h => cheats.translate("LIB_HERO_NAME_" + h.id))};case 'hero':if (nameOnly) {return cheats.translate("LIB_HERO_NAME_" + id);}artifacts = lib.data.hero[id].artifacts;return {/** Как зовут этого героя? */name: cheats.translate("LIB_HERO_NAME_" + id),/** Какой артефакт принадлежит этому герою? */artifact: artifacts.map(a => cheats.translate("LIB_ARTIFACT_NAME_" + a))};}}function hintQuest(quest) {const r###lt = {};if (quest?.questionIcon) {const info = getQuestionInfo(quest.questionIcon);if (info?.heroes) {/** Какому герою принадлежит этот артефакт? */r###lt.answer = quest.answers.filter(e => info.heroes.includes(e.answerText.slice(1)));}if (info?.artifact) {/** Какой артефакт принадлежит этому герою? */r###lt.answer = quest.answers.filter(e => info.artifact.includes(e.answerText.slice(1)));}if (typeof info == 'string') {r###lt.info = { name: info };} else {r###lt.info = info;}}if (quest.answers[0]?.answerIcon) {r###lt.answer = quest.answers.filter(e => quest.question.includes(getQuestionInfo(e.answerIcon, true)))}if ((!r###lt?.answer || !r###lt.answer.length) && !r###lt.info?.name) {return false;}let r###ltText = '';if (r###lt?.info) {r###ltText += I18N('PICTURE') + r###lt.info.name;}console.log(r###lt);if (r###lt?.answer && r###lt.answer.length) {r###ltText += I18N('ANSWER') + r###lt.answer[0].id + (!r###lt.answer[0].answerIcon ? ' - ' + r###lt.answer[0].answerText : '');}return r###ltText;}async function farmBattlePass() {const isFarmReward = (reward) => {return !(reward?.buff || reward?.fragmentHero || reward?.bundleHeroReward);};const battlePassProcess = (pass) => {if (!pass.id) {return []}const levels = Object.values(lib.data.battlePass.level).filter(x => x.battlePass == pass.id)const last_level = levels[levels.length - 1];let actual = Math.max(...levels.filter(p => pass.exp >= p.experience).map(p => p.level))if (pass.exp > last_level.experience) {actual = last_level.level + (pass.exp - last_level.experience) / last_level.experienceByLevel;}const calls = [];for(let i = 1; i <= actual; i++) {const level = i >= last_level.level ? last_level : levels.find(l => l.level === i);const reward = {free: level?.freeReward, paid:level?.paidReward};if (!pass.rewards[i]?.free && isFarmReward(reward.free)) {const args = {level: i, free:true};if (!pass.gold) { args.id = pass.id }calls.push({ name: 'battlePass_farmReward', args, ident: `${pass.gold ? 'body' : 'spesial'}_free_${args.id}_${i}` });}if (pass.ticket && !pass.rewards[i]?.paid && isFarmReward(reward.paid)) {const args = {level: i, free:false};if (!pass.gold) { args.id = pass.id}calls.push({ name: 'battlePass_farmReward', args, ident: `${pass.gold ? 'body' : 'spesial'}_paid_${args.id}_${i}` });}}return calls;}const passes = await Send({calls: [{ name: 'battlePass_getInfo', args: {}, ident: 'getInfo' },{ name: 'battlePass_getSpecial', args: {}, ident: 'getSpecial' },],}).then((e) => [{...e.r###lts[0].r###lt.response?.battlePass, gold: true}, ...Object.values(e.r###lts[1].r###lt.response)]);const calls = passes.map(p => battlePassProcess(p)).flat()if (!calls.length) {setProgress(I18N('NOTHING_TO_COLLECT'));return;}let r###lts = await Send({calls});if (r###lts.error) {console.log(r###lts.error);setProgress(I18N('SOMETHING_WENT_WRONG'));} else {setProgress(I18N('SEASON_REWARD_COLLECTED', {count: r###lts.r###lts.length}), true);}}async function sellHeroSoulsForGold() {let { fragmentHero, heroes } = await Send({calls: [{ name: 'inventoryGet', args: {}, ident: 'inventoryGet' },{ name: 'heroGetAll', args: {}, ident: 'heroGetAll' },],}).then((e) => e.r###lts.map((r) => r.r###lt.response)).then((e) => ({ fragmentHero: e[0].fragmentHero, heroes: e[1] }));const calls = [];for (let i in fragmentHero) {if (heroes[i] && heroes[i].star == 6) {calls.push({name: 'inventorySell',args: {type: 'hero',libId: i,amount: fragmentHero[i],fragment: true,},ident: 'inventorySell_' + i,});}}if (!calls.length) {console.log(0);return 0;}const rewards = await Send({ calls }).then((e) => e.r###lts.map((r) => r.r###lt?.response?.gold || 0));const gold = rewards.reduce((e, a) => e + a, 0);setProgress(I18N('GOLD_RECEIVED', { gold }), true);}/*** Attack of the minions of Asgard** Атака прислужников Асгарда*/function testRaidNodes() {const { executeRaidNodes } = HWHClasses;return new Promise((resolve, reject) => {const tower = new executeRaidNodes(resolve, reject);tower.start();});}/*** Attack of the minions of Asgard** Атака прислужников Асгарда*/function executeRaidNodes(resolve, reject) {let raidData = {teams: [],favor: {},nodes: [],attempts: 0,countExecuteBattles: 0,cancelBattle: 0,}callsExecuteRaidNodes = {calls: [{name: "clanRaid_getInfo",args: {},ident: "clanRaid_getInfo"}, {name: "teamGetAll",args: {},ident: "teamGetAll"}, {name: "teamGetFavor",args: {},ident: "teamGetFavor"}]}this.start = function () {send(JSON.stringify(callsExecuteRaidNodes), startRaidNodes);}async function startRaidNodes(data) {res = data.r###lts;clanRaidInfo = res[0].r###lt.response;teamGetAll = res[1].r###lt.response;teamGetFavor = res[2].r###lt.response;let index = 0;let isNotFullPack = false;for (let team of teamGetAll.clanRaid_nodes) {if (team.length < 6) {isNotFullPack = true;}raidData.teams.push({data: {},heroes: team.filter(id => id < 6000),pet: team.filter(id => id >= 6000).pop(),battleIndex: index++});}raidData.favor = teamGetFavor.clanRaid_nodes;if (isNotFullPack) {if (await popup.confirm(I18N('MINIONS_WARNING'), [{ msg: I18N('BTN_NO'), r###lt: true },{ msg: I18N('BTN_YES'), r###lt: false },])) {endRaidNodes('isNotFullPack');return;}}raidData.nodes = clanRaidInfo.nodes;raidData.attempts = clanRaidInfo.attempts;setIsCancalBattle(false);checkNodes();}function getAttackNode() {for (let nodeId in raidData.nodes) {let node = raidData.nodes[nodeId];let points = 0for (team of node.teams) {points += team.points;}let now = Date.now() / 1000;if (!points && now > node.timestamps.start && now < node.timestamps.end) {let countTeam = node.teams.length;delete raidData.nodes[nodeId];return {nodeId,countTeam};}}return null;}function checkNodes() {setProgress(`${I18N('REMAINING_ATTEMPTS')}: ${raidData.attempts}`);let nodeInfo = getAttackNode();if (nodeInfo && raidData.attempts) {startNodeBattles(nodeInfo);return;}endRaidNodes('EndRaidNodes');}function startNodeBattles(nodeInfo) {let {nodeId, countTeam} = nodeInfo;let teams = raidData.teams.slice(0, countTeam);let heroes = raidData.teams.map(e => e.heroes).flat();let favor = {...raidData.favor};for (let heroId in favor) {if (!heroes.includes(+heroId)) {delete favor[heroId];}}let calls = [{name: "clanRaid_startNodeBattles",args: {nodeId,teams,favor},ident: "body"}];send(JSON.stringify({calls}), r###ltNodeBattles);}function r###ltNodeBattles(e) {if (e['error']) {endRaidNodes('nodeBattlesError', e['error']);return;}console.log(e);let battles = e.r###lts[0].r###lt.response.battles;let promises = [];let battleIndex = 0;for (let battle of battles) {battle.battleIndex = battleIndex++;promises.push(calcBattleR###lt(battle));}Promise.all(promises).then(r###lts => {const endR###lts = {};let isAllWin = true;for (let r of r###lts) {isAllWin &&= r.r###lt.win;}if (!isAllWin) {cancelEndNodeBattle(r###lts[0]);return;}raidData.countExecuteBattles = r###lts.length;let timeout = 500;for (let r of r###lts) {setTimeout(endNodeBattle, timeout, r);timeout += 500;}});}/*** Returns the battle calculation promise** Возвращает промис расчета боя*/function calcBattleR###lt(battleData) {return new Promise(function (resolve, reject) {BattleCalc(battleData, "get_clanPvp", resolve);});}/*** Cancels the fight** Отменяет бой*/function cancelEndNodeBattle(r) {const fixBattle = function (heroes) {for (const ids in heroes) {hero = heroes[ids];hero.energy = random(1, 999);if (hero.hp > 0) {hero.hp = random(1, hero.hp);}}}fixBattle(r.progress[0].attackers.heroes);fixBattle(r.progress[0].defenders.heroes);endNodeBattle(r);}/*** Ends the fight** Завершает бой*/function endNodeBattle(r) {let nodeId = r.battleData.r###lt.nodeId;let battleIndex = r.battleData.battleIndex;let calls = [{name: "clanRaid_endNodeBattle",args: {nodeId,battleIndex,r###lt: r.r###lt,progress: r.progress},ident: "body"}]SendRequest(JSON.stringify({calls}), battleR###lt);}/*** Processing the r###lts of the battle** Обработка результатов боя*/function battleR###lt(e) {if (e['error']) {endRaidNodes('missionEndError', e['error']);return;}r = e.r###lts[0].r###lt.response;if (r['error']) {if (r.reason == "invalidBattle") {raidData.cancelBattle++;checkNodes();} else {endRaidNodes('missionEndError', e['error']);}return;}if (!(--raidData.countExecuteBattles)) {raidData.attempts--;checkNodes();}}/*** Completing a task** Завершение задачи*/function endRaidNodes(reason, info) {setIsCancalBattle(true);let textCancel = raidData.cancelBattle ? ` ${I18N('BATTLES_CANCELED')}: ${raidData.cancelBattle}` : '';setProgress(`${I18N('MINION_RAID')} ${I18N('COMPLETED')}! ${textCancel}`, true);console.log(reason, info);resolve();}}this.HWHClasses.executeRaidNodes = executeRaidNodes;/*** Asgard Boss Attack Replay** Повтор атаки босса Асгарда*/function testBossBattle() {const { executeBossBattle } = HWHClasses;return new Promise((resolve, reject) => {const bossBattle = new executeBossBattle(resolve, reject);bossBattle.start(lastBossBattle);});}/*** Asgard Boss Attack Replay** Повтор атаки босса Асгарда*/function executeBossBattle(resolve, reject) {this.start = function (battleInfo) {preCalcBattle(battleInfo);}function getBattleInfo(battle) {return new Promise(function (resolve) {battle.seed = Math.floor(Date.now() / 1000) + random(0, 1e3);BattleCalc(battle, getBattleType(battle.type), e => {let extra = e.progress[0].defenders.heroes[1].extra;resolve(extra.damageTaken + extra.damageTakenNextLevel);});});}function preCalcBattle(battle) {let actions = [];const countTestBattle = getInput('countTestBattle');for (let i = 0; i < countTestBattle; i++) {actions.push(getBattleInfo(battle, true));}Promise.all(actions).then(r###ltPreCalcBattle);}async function r###ltPreCalcBattle(damages) {let maxDamage = 0;let minDamage = 1e10;let avgDamage = 0;for (let damage of damages) {avgDamage += damageif (damage > maxDamage) {maxDamage = damage;}if (damage < minDamage) {minDamage = damage;}}avgDamage /= damages.length;console.log(damages.map(e => e.toLocaleString()).join('\n'), avgDamage, maxDamage);await popup.confirm(`${I18N('ROUND_STAT')} ${damages.length} ${I18N('BATTLE')}:` +`<br>${I18N('MINIMUM')}: ` + minDamage.toLocaleString() +`<br>${I18N('MAXIMUM')}: ` + maxDamage.toLocaleString() +`<br>${I18N('AVERAGE')}: ` + avgDamage.toLocaleString(), [{ msg: I18N('BTN_OK'), r###lt: 0},])endBossBattle(I18N('BTN_CANCEL'));}/*** Completing a task** Завершение задачи*/function endBossBattle(reason, info) {console.log(reason, info);resolve();}}this.HWHClasses.executeBossBattle = executeBossBattle;class FixBattle {minTimer = 1.3;maxTimer = 15.3;constructor(battle, isTimeout = true) {this.battle = structuredClone(battle);this.isTimeout = isTimeout;}timeout(callback, timeout) {if (this.isTimeout) {this.worker.postMessage(timeout);this.worker.onmessage = callback;} else {callback();}}randTimer() {return Math.random() * (this.maxTimer - this.minTimer + 1) + this.minTimer;}setAvgTime(startTime) {this.fixTime += Date.now() - startTime;this.avgTime = this.fixTime / this.count;}init() {this.fixTime = 0;this.lastTimer = 0;this.index = 0;this.lastBossDamage = 0;this.bestR###lt = {count: 0,timer: 0,value: 0,r###lt: null,progress: null,};this.lastBattleR###lt = {win: false,};this.worker = new Worker(URL.createObjectURL(new Blob([`self.onmessage = function(e) {const timeout = e.data;setTimeout(() => {self.postMessage(1);}, timeout);};`,])));}async start(endTime = Date.now() + 6e4, maxCount = 100) {this.endTime = endTime;this.maxCount = maxCount;this.init();return await new Promise((resolve) => {this.resolve = resolve;this.count = 0;this.loop();});}endFix() {this.bestR###lt.maxCount = this.count;this.worker.terminate();this.resolve(this.bestR###lt);}async loop() {const start = Date.now();if (this.isEndLoop()) {this.endFix();return;}this.count++;try {this.lastR###lt = await Calc(this.battle);} catch (e) {this.updateProgressTimer(this.index++);this.timeout(this.loop.bind(this), 0);return;}const { progress, r###lt } = this.lastR###lt;this.lastBattleR###lt = r###lt;this.lastBattleProgress = progress;this.setAvgTime(start);this.checkR###lt();this.showR###lt();this.updateProgressTimer();this.timeout(this.loop.bind(this), 0);}isEndLoop() {return this.count >= this.maxCount || this.endTime < Date.now();}updateProgressTimer(index = 0) {this.lastTimer = this.randTimer();this.battle.progress = [{ attackers: { input: ['auto', 0, 0, 'auto', index, this.lastTimer] } }];}showR###lt() {console.log(this.count,this.avgTime.toFixed(2),(this.endTime - Date.now()) / 1000,this.lastTimer.toFixed(2),this.lastBossDamage.toLocaleString(),this.bestR###lt.value.toLocaleString());}checkR###lt() {const { damageTaken, damageTakenNextLevel } = this.lastBattleProgress[0].defenders.heroes[1].extra;this.lastBossDamage = damageTaken + damageTakenNextLevel;if (this.lastBossDamage > this.bestR###lt.value) {this.bestR###lt = {count: this.count,timer: this.lastTimer,value: this.lastBossDamage,r###lt: structuredClone(this.lastBattleR###lt),progress: structuredClone(this.lastBattleProgress),};}}stopFix() {this.endTime = 0;}}this.HWHClasses.FixBattle = FixBattle;class WinFixBattle extends FixBattle {checkR###lt() {if (this.lastBattleR###lt.win) {this.bestR###lt = {count: this.count,timer: this.lastTimer,value: this.lastBattleR###lt.stars,r###lt: structuredClone(this.lastBattleR###lt),progress: structuredClone(this.lastBattleProgress),battleTimer: this.lastR###lt.battleTimer,};}}setWinTimer(value) {this.winTimer = value;}setMaxTimer(value) {this.maxTimer = value;}randTimer() {if (this.winTimer) {return this.winTimer;}return super.randTimer();}isEndLoop() {return super.isEndLoop() || this.bestR###lt.r###lt?.win;}showR###lt() {console.log(this.count,this.avgTime.toFixed(2),(this.endTime - Date.now()) / 1000,this.lastR###lt.battleTime,this.lastTimer,this.bestR###lt.value);const endTime = ((this.endTime - Date.now()) / 1000).toFixed(2);const avgTime = this.avgTime.toFixed(2);const msg = `${I18N('LETS_FIX')} ${this.count}/${this.maxCount}<br/>${endTime}s<br/>${avgTime}ms`;setProgress(msg, false, this.stopFix.bind(this));}}this.HWHClasses.WinFixBattle = WinFixBattle;class BestOrWinFixBattle extends WinFixBattle {isNoMakeWin = false;getState(r###lt) {let befor###mFactor = 0;const beforeHeroes = r###lt.battleData.defenders[0];for (let heroId in beforeHeroes) {const hero = beforeHeroes[heroId];const state = hero.state;let factor = 1;if (state) {const hp = state.hp / (hero?.hp || 1);const energy = state.energy / 1e3;factor = hp + energy / 20;}befor###mFactor += factor;}let afterSumFactor = 0;const afterHeroes = r###lt.progress[0].defenders.heroes;for (let heroId in afterHeroes) {const hero = afterHeroes[heroId];const hp = hero.hp / (beforeHeroes[heroId]?.hp || 1);const energy = hero.energy / 1e3;const factor = hp + energy / 20;afterSumFactor += factor;}return 100 - Math.floor((afterSumFactor / befor###mFactor) * 1e4) / 100;}setNoMakeWin(value) {this.isNoMakeWin = value;}checkR###lt() {const state = this.getState(this.lastR###lt);console.log(state);if (state > this.bestR###lt.value) {if (!(this.isNoMakeWin && this.lastBattleR###lt.win)) {this.bestR###lt = {count: this.count,timer: this.lastTimer,value: state,r###lt: structuredClone(this.lastBattleR###lt),progress: structuredClone(this.lastBattleProgress),battleTimer: this.lastR###lt.battleTimer,};}}}}this.HWHClasses.BestOrWinFixBattle = BestOrWinFixBattle;class BossFixBattle extends FixBattle {showR###lt() {super.showR###lt();//setTimeout(() => {const best = this.bestR###lt;const maxDmg = best.value.toLocaleString();const avgTime = this.avgTime.toLocaleString();const msg = `${I18N('LETS_FIX')} ${this.count}/${this.maxCount}<br/>${maxDmg}<br/>${avgTime}ms`;setProgress(msg, false, this.stopFix.bind(this));//}, 0);}}this.HWHClasses.BossFixBattle = BossFixBattle;class DungeonFixBattle extends FixBattle {init() {super.init();this.isTimeout = false;this.bestR###lt = {count: 0,timer: 0,value: {hp: -Infinity,energy: -Infinity,},r###lt: null,progress: null,};}setState() {const r###lt = this.lastR###lt;let beforeHP = 0;let beforeEnergy = 0;const beforeTitans = r###lt.battleData.attackers;for (let titanId in beforeTitans) {const titan = beforeTitans[titanId];const state = titan.state;if (state) {beforeHP += state.hp / titan.hp;beforeEnergy += state.energy / 1e3;}}let afterHP = 0;let afterEnergy = 0;const afterTitans = r###lt.progress[0].attackers.heroes;for (let titanId in afterTitans) {const titan = afterTitans[titanId];afterHP += titan.hp / beforeTitans[titanId].hp;afterEnergy += titan.energy / 1e3;}this.lastState = {hp: afterHP - beforeHP,energy: afterEnergy - beforeEnergy,};}checkR###lt() {this.setState();if (this.lastState.hp > this.bestR###lt.value.hp ||(this.lastState.hp === this.bestR###lt.value.hp && this.lastState.energy > this.bestR###lt.value.energy)) {this.bestR###lt = {count: this.count,timer: this.lastTimer,value: this.lastState,r###lt: this.lastR###lt.r###lt,progress: this.lastR###lt.progress,};}}showR###lt() {if (this.isShowR###lt) {console.log(this.count, this.lastTimer.toFixed(2), JSON.stringify(this.lastState), JSON.stringify(this.bestR###lt.value));}}}this.HWHClasses.DungeonFixBattle = DungeonFixBattle;const masterWsMixin = {wsStart() {const socket = new WebSocket(this.url);socket.onopen = () => {console.log('Connected to server');// Пример создания новой задачиconst newTask = {type: 'newTask',battle: this.battle,endTime: this.endTime - 1e4,maxCount: this.maxCount,};socket.send(JSON.stringify(newTask));};socket.onmessage = this.onmessage.bind(this);socket.onclose = () => {console.log('Disconnected from server');};this.ws = socket;},onmessage(event) {const data = JSON.parse(event.data);switch (data.type) {case 'newTask': {console.log('newTask:', data);this.id = data.id;this.countExecutor = data.count;break;}case 'getSolTask': {console.log('getSolTask:', data);this.endFix(data.solutions);break;}case 'resolveTask': {console.log('resolveTask:', data);if (data.id === this.id && data.solutions.length === this.countExecutor) {this.worker.terminate();this.endFix(data.solutions);}break;}default:console.log('Unknown message type:', data.type);}},getTask() {this.ws.send(JSON.stringify({type: 'getSolTask',id: this.id,}));},};/*mFix = new action.masterFixBattle(battle)await mFix.start(Date.now() + 6e4, 1);*/class masterFixBattle extends FixBattle {constructor(battle, url = 'wss://localho.st:3000') {super(battle, true);this.url = url;}async start(endTime, maxCount) {this.endTime = endTime;this.maxCount = maxCount;this.init();this.wsStart();return await new Promise((resolve) => {this.resolve = resolve;const timeout = this.endTime - Date.now();this.timeout(this.getTask.bind(this), timeout);});}async endFix(solutions) {this.ws.close();let maxCount = 0;for (const solution of solutions) {maxCount += solution.maxCount;if (solution.value > this.bestR###lt.value) {this.bestR###lt = solution;}}this.count = maxCount;super.endFix();}}Object.assign(masterFixBattle.prototype, masterWsMixin);this.HWHClasses.masterFixBattle = masterFixBattle;class masterWinFixBattle extends WinFixBattle {constructor(battle, url = 'wss://localho.st:3000') {super(battle, true);this.url = url;}async start(endTime, maxCount) {this.endTime = endTime;this.maxCount = maxCount;this.init();this.wsStart();return await new Promise((resolve) => {this.resolve = resolve;const timeout = this.endTime - Date.now();this.timeout(this.getTask.bind(this), timeout);});}async endFix(solutions) {this.ws.close();let maxCount = 0;for (const solution of solutions) {maxCount += solution.maxCount;if (solution.value > this.bestR###lt.value) {this.bestR###lt = solution;}}this.count = maxCount;super.endFix();}}Object.assign(masterWinFixBattle.prototype, masterWsMixin);this.HWHClasses.masterWinFixBattle = masterWinFixBattle;const slaveWsMixin = {wsStop() {this.ws.close();},wsStart() {const socket = new WebSocket(this.url);socket.onopen = () => {console.log('Connected to server');};socket.onmessage = this.onmessage.bind(this);socket.onclose = () => {console.log('Disconnected from server');};this.ws = socket;},async onmessage(event) {const data = JSON.parse(event.data);switch (data.type) {case 'newTask': {console.log('newTask:', data.task);const { battle, endTime, maxCount } = data.task;this.battle = battle;const id = data.task.id;const solution = await this.start(endTime, maxCount);this.ws.send(JSON.stringify({type: 'resolveTask',id,solution,}));break;}default:console.log('Unknown message type:', data.type);}},};/*sFix = new action.slaveFixBattle();sFix.wsStart()*/class slaveFixBattle extends FixBattle {constructor(url = 'wss://localho.st:3000') {super(null, false);this.isTimeout = false;this.url = url;}}Object.assign(slaveFixBattle.prototype, slaveWsMixin);this.HWHClasses.slaveFixBattle = slaveFixBattle;class slaveWinFixBattle extends WinFixBattle {constructor(url = 'wss://localho.st:3000') {super(null, false);this.isTimeout = false;this.url = url;}}Object.assign(slaveWinFixBattle.prototype, slaveWsMixin);this.HWHClasses.slaveWinFixBattle = slaveWinFixBattle;/*** Auto-repeat attack** Автоповтор атаки*/function testAutoBattle() {const { executeAutoBattle } = HWHClasses;return new Promise((resolve, reject) => {const bossBattle = new executeAutoBattle(resolve, reject);bossBattle.start(lastBattleArg, lastBattleInfo);});}/*** Auto-repeat attack** Автоповтор атаки*/function executeAutoBattle(resolve, reject) {let battleArg = {};let countBattle = 0;let countError = 0;let findCoeff = 0;let dataNotEeceived = 0;let stopAutoBattle = false;let isSetWinTimer = false;const svgJustice = '<svg width="20" height="20" viewBox="0 0 124 125" xmlns="http://www.w3.org/2000/svg" style="fill: #fff;"><g><path d="m54 0h-1c-7.25 6.05-17.17 6.97-25.78 10.22-8.6 3.25-23.68 1.07-23.22 12.78s-0.47 24.08 1 35 2.36 18.36 7 28c4.43-8.31-3.26-18.88-3-30 0.26-11.11-2.26-25.29-1-37 11.88-4.16 26.27-0.42 36.77-9.23s20.53 6.05 29.23-0.77c-6.65-2.98-14.08-4.96-20-9z"/></g><g><path d="m108 5c-11.05 2.96-27.82 2.2-35.08 11.92s-14.91 14.71-22.67 23.33c-7.77 8.62-14.61 15.22-22.25 23.75 7.05 11.93 14.33 2.58 20.75-4.25 6.42-6.82 12.98-13.03 19.5-19.5s12.34-13.58 19.75-18.25c2.92 7.29-8.32 12.65-13.25 18.75-4.93 6.11-12.19 11.48-17.5 17.5s-12.31 11.38-17.25 17.75c10.34 14.49 17.06-3.04 26.77-10.23s15.98-16.89 26.48-24.52c10.5-7.64 12.09-24.46 14.75-36.25z"/></g><g><path d="m60 25c-11.52-6.74-24.53 8.28-38 6 0.84 9.61-1.96 20.2 2 29 5.53-4.04-4.15-23.2 4.33-26.67 8.48-3.48 18.14-1.1 24.67-8.33 2.73 0.3 4.81 2.98 7 0z"/></g><g><path d="m100 75c3.84-11.28 5.62-25.85 3-38-4.2 5.12-3.5 13.58-4 20s-3.52 13.18 1 18z"/></g><g><path d="m55 94c15.66-5.61 33.71-20.85 29-39-3.07 8.05-4.3 16.83-10.75 23.25s-14.76 8.35-18.25 15.75z"/></g><g><path d="m0 94v7c6.05 3.66 9.48 13.3 18 11-3.54-11.78 8.07-17.05 14-25 6.66 1.52 13.43 16.26 19 5-11.12-9.62-20.84-21.33-32-31-9.35 6.63 4.76 11.99 6 19-7.88 5.84-13.24 17.59-25 14z"/></g><g><path d="m82 125h26v-19h16v-1c-11.21-8.32-18.38-21.74-30-29-8.59 10.26-19.05 19.27-27 30h15v19z"/></g><g><path d="m68 110c-7.68-1.45-15.22 4.83-21.92-1.08s-11.94-5.72-18.08-11.92c-3.03 8.84 10.66 9.88 16.92 16.08s17.09 3.47 23.08-3.08z"/></g></svg>';const svgBoss = '<svg width="20" height="20" viewBox="0 0 40 41" xmlns="http://www.w3.org/2000/svg" style="fill: #fff;"><g><path d="m21 12c-2.19-3.23 5.54-10.95-0.97-10.97-6.52-0.02 1.07 7.75-1.03 10.97-2.81 0.28-5.49-0.2-8-1-0.68 3.53 0.55 6.06 4 4 0.65 7.03 1.11 10.95 1.67 18.33 0.57 7.38 6.13 7.2 6.55-0.11 0.42-7.3 1.35-11.22 1.78-18.22 3.53 1.9 4.73-0.42 4-4-2.61 0.73-5.14 1.35-8 1m-1 17c-1.59-3.6-1.71-10.47 0-14 1.59 3.6 1.71 10.47 0 14z"/></g><g><path d="m6 19c-1.24-4.15 2.69-8.87 1-12-3.67 4.93-6.52 10.57-6 17 5.64-0.15 8.82 4.98 13 8 1.3-6.54-0.67-12.84-8-13z"/></g><g><path d="m33 7c0.38 5.57 2.86 14.79-7 15v10c4.13-2.88 7.55-7.97 13-8 0.48-6.46-2.29-12.06-6-17z"/></g></svg>';const svgAttempt = '<svg width="20" height="20" viewBox="0 0 645 645" xmlns="http://www.w3.org/2000/svg" style="fill: #fff;"><g><path d="m442 26c-8.8 5.43-6.6 21.6-12.01 30.99-2.5 11.49-5.75 22.74-8.99 34.01-40.61-17.87-92.26-15.55-133.32-0.32-72.48 27.31-121.88 100.19-142.68 171.32 10.95-4.49 19.28-14.97 29.3-21.7 50.76-37.03 121.21-79.04 183.47-44.07 16.68 5.8 2.57 21.22-0.84 31.7-4.14 12.19-11.44 23.41-13.93 36.07 56.01-17.98 110.53-41.23 166-61-20.49-59.54-46.13-117.58-67-177z"/></g><g><path d="m563 547c23.89-16.34 36.1-45.65 47.68-71.32 23.57-62.18 7.55-133.48-28.38-186.98-15.1-22.67-31.75-47.63-54.3-63.7 1.15 14.03 6.71 26.8 8.22 40.78 12.08 61.99 15.82 148.76-48.15 183.29-10.46-0.54-15.99-16.1-24.32-22.82-8.2-7.58-14.24-19.47-23.75-24.25-4.88 59.04-11.18 117.71-15 177 62.9 5.42 126.11 9.6 189 15-4.84-9.83-17.31-15.4-24.77-24.23-9.02-7.06-17.8-15.13-26.23-22.77z"/></g><g><path d="m276 412c-10.69-15.84-30.13-25.9-43.77-40.23-15.39-12.46-30.17-25.94-45.48-38.52-15.82-11.86-29.44-28.88-46.75-37.25-19.07 24.63-39.96 48.68-60.25 72.75-18.71 24.89-42.41 47.33-58.75 73.25 22.4-2.87 44.99-13.6 66.67-13.67 0.06 22.8 10.69 42.82 20.41 62.59 49.09 93.66 166.6 114.55 261.92 96.08-6.07-9.2-22.11-9.75-31.92-16.08-59.45-26.79-138.88-75.54-127.08-151.92 21.66-2.39 43.42-4.37 65-7z"/></g></svg>';this.start = function (battleArgs, battleInfo) {battleArg = battleArgs;if (nameFuncStartBattle == 'invasion_bossStart') {startBattle();return;}preCalcBattle(battleInfo);}/*** Returns a promise for combat recalculation** Возвращает промис для прерасчета боя*/function getBattleInfo(battle) {return new Promise(function (resolve) {battle.seed = Math.floor(Date.now() / 1000) + random(0, 1e3);Calc(battle).then(e => {e.coeff = calcCoeff(e, 'defenders');resolve(e);});});}/*** Battle recalculation** Прерасчет боя*/function preCalcBattle(battle) {let actions = [];const countTestBattle = getInput('countTestBattle');for (let i = 0; i < countTestBattle; i++) {actions.push(getBattleInfo(battle));}Promise.all(actions).then(r###ltPreCalcBattle);}/*** Processing the r###lts of the battle recalculation** Обработка результатов прерасчета боя*/async function r###ltPreCalcBattle(r###lts) {let countWin = r###lts.reduce((s, w) => w.r###lt.win + s, 0);setProgress(`${I18N('CHANCE_TO_WIN')} ${Math.floor(countWin / r###lts.length * 100)}% (${r###lts.length})`, false, hideProgress);if (countWin > 0) {setIsCancalBattle(false);startBattle();return;}let minCoeff = 100;let maxCoeff = -100;let avgCoeff = 0;r###lts.forEach(e => {if (e.coeff < minCoeff) minCoeff = e.coeff;if (e.coeff > maxCoeff) maxCoeff = e.coeff;avgCoeff += e.coeff;});avgCoeff /= r###lts.length;if (nameFuncStartBattle == 'invasion_bossStart' ||nameFuncStartBattle == 'bossAttack') {const r###lt = await popup.confirm(I18N('BOSS_VICTORY_IMPOSSIBLE', { battles: r###lts.length }), [{ msg: I18N('BTN_CANCEL'), r###lt: false, isCancel: true },{ msg: I18N('BTN_DO_IT'), r###lt: true },])if (r###lt) {setIsCancalBattle(false);startBattle();return;}setProgress(I18N('NOT_THIS_TIME'), true);endAutoBattle('invasion_bossStart');return;}const r###lt = await popup.confirm(I18N('VICTORY_IMPOSSIBLE') +`<br>${I18N('ROUND_STAT')} ${r###lts.length} ${I18N('BATTLE')}:` +`<br>${I18N('MINIMUM')}: ` + minCoeff.toLocaleString() +`<br>${I18N('MAXIMUM')}: ` + maxCoeff.toLocaleString() +`<br>${I18N('AVERAGE')}: ` + avgCoeff.toLocaleString() +`<br>${I18N('FIND_COEFF')} ` + avgCoeff.toLocaleString(), [{ msg: I18N('BTN_CANCEL'), r###lt: 0, isCancel: true },{ msg: I18N('BTN_GO'), isInput: true, default: Math.round(avgCoeff * 1000) / 1000 },])if (r###lt) {findCoeff = r###lt;setIsCancalBattle(false);startBattle();return;}setProgress(I18N('NOT_THIS_TIME'), true);endAutoBattle(I18N('NOT_THIS_TIME'));}/*** Calculation of the combat r###lt coefficient** Расчет коэфициента результата боя*/function calcCoeff(r###lt, packType) {let befor###mFactor = 0;const beforePack = r###lt.battleData[packType][0];for (let heroId in beforePack) {const hero = beforePack[heroId];const state = hero.state;let factor = 1;if (state) {const hp = state.hp / state.maxHp;const energy = state.energy / 1e3;factor = hp + energy / 20;}befor###mFactor += factor;}let afterSumFactor = 0;const afterPack = r###lt.progress[0][packType].heroes;for (let heroId in afterPack) {const hero = afterPack[heroId];const stateHp = beforePack[heroId]?.state?.hp || beforePack[heroId]?.stats?.hp;const hp = hero.hp / stateHp;const energy = hero.energy / 1e3;const factor = hp + energy / 20;afterSumFactor += factor;}const r###ltCoeff = -(afterSumFactor - befor###mFactor);return Math.round(r###ltCoeff * 1000) / 1000;}/*** Start battle** Начало боя*/function startBattle() {countBattle++;const countMaxBattle = getInput('countAutoBattle');// setProgress(countBattle + '/' + countMaxBattle);if (countBattle > countMaxBattle) {setProgress(`${I18N('RETRY_LIMIT_EXCEEDED')}: ${countMaxBattle}`, true);endAutoBattle(`${I18N('RETRY_LIMIT_EXCEEDED')}: ${countMaxBattle}`)return;}if (stopAutoBattle) {setProgress(I18N('STOPPED'), true);endAutoBattle('STOPPED');return;}send({calls: [{name: nameFuncStartBattle,args: battleArg,ident: "body"}]}, calcR###ltBattle);}/*** Battle calculation** Расчет боя*/async function calcR###ltBattle(e) {if (!e) {console.log('данные не были получены');if (dataNotEeceived < 10) {dataNotEeceived++;startBattle();return;}endAutoBattle('Error', 'данные не были получены ' + dataNotEeceived + ' раз');return;}if ('error' in e) {if (e.error.description === 'too many tries') {invasionTimer += 100;countBattle--;countError++;console.log(`Errors: ${countError}`, e.error);startBattle();return;}const r###lt = await popup.confirm(I18N('ERROR_DURING_THE_BATTLE') + '<br>' + e.error.description, [{ msg: I18N('BTN_OK'), r###lt: false },{ msg: I18N('RELOAD_GAME'), r###lt: true },]);endAutoBattle('Error', e.error);if (r###lt) {location.reload();}return;}let battle = e.r###lts[0].r###lt.response.battleif (nameFuncStartBattle == 'towerStartBattle' ||nameFuncStartBattle == 'bossAttack' ||nameFuncStartBattle == 'invasion_bossStart') {battle = e.r###lts[0].r###lt.response;}lastBattleInfo = battle;BattleCalc(battle, getBattleType(battle.type), r###ltBattle);}/*** Processing the r###lts of the battle** Обработка результатов боя*/async function r###ltBattle(e) {const isWin = e.r###lt.win;if (isWin) {endBattle(e, false);return;} else if (isChecked('tryFixIt_v2')) {const { WinFixBattle } = HWHClasses;const cloneBattle = structuredClone(e.battleData);const bFix = new WinFixBattle(cloneBattle);let attempts = Infinity;if (nameFuncStartBattle == 'invasion_bossStart' && !isSetWinTimer) {let winTimer = await popup.confirm(`Secret number:`, [{ r###lt: false, isClose: true },{ msg: 'Go', isInput: true, default: '0' },]);winTimer = Number.parseFloat(winTimer);if (winTimer) {attempts = 5;bFix.setWinTimer(winTimer);}isSetWinTimer = true;}let endTime = Date.now() + 6e4;if (nameFuncStartBattle == 'invasion_bossStart') {endTime = Date.now() + 6e4 * 4;bFix.setMaxTimer(120.3);}const r###lt = await bFix.start(endTime, attempts);console.log(r###lt);if (r###lt.value) {endBattle(r###lt, false);return;}}const countMaxBattle = getInput('countAutoBattle');if (findCoeff) {const coeff = calcCoeff(e, 'defenders');setProgress(`${countBattle}/${countMaxBattle}, ${coeff}`);if (coeff > findCoeff) {endBattle(e, false);return;}} else {if (nameFuncStartBattle == 'invasion_bossStart') {const bossLvl = lastBattleInfo.typeId >= 130 ? lastBattleInfo.typeId : '';const justice = lastBattleInfo?.effects?.attackers?.percentInOutDamageModAndEnergyIncrease_any_99_100_300_99_1000_300 || 0;setProgress(`${svgBoss} ${bossLvl} ${svgJustice} ${justice} <br>${svgAttempt} ${countBattle}/${countMaxBattle}`, false, () => {stopAutoBattle = true;});await new Promise((resolve) => setTimeout(resolve, 5000));} else {setProgress(`${countBattle}/${countMaxBattle}`);}}if (nameFuncStartBattle == 'towerStartBattle' ||nameFuncStartBattle == 'bossAttack' ||nameFuncStartBattle == 'invasion_bossStart') {startBattle();return;}cancelEndBattle(e);}/*** Cancel fight** Отмена боя*/function cancelEndBattle(r) {const fixBattle = function (heroes) {for (const ids in heroes) {hero = heroes[ids];hero.energy = random(1, 999);if (hero.hp > 0) {hero.hp = random(1, hero.hp);}}}fixBattle(r.progress[0].attackers.heroes);fixBattle(r.progress[0].defenders.heroes);endBattle(r, true);}/*** End of the fight** Завершение боя */function endBattle(battleR###lt, isCancal) {let calls = [{name: nameFuncEndBattle,args: {r###lt: battleR###lt.r###lt,progress: battleR###lt.progress},ident: "body"}];if (nameFuncStartBattle == 'invasion_bossStart') {calls[0].args.id = lastBattleArg.id;}send(JSON.stringify({calls}), async e => {console.log(e);if (isCancal) {startBattle();return;}setProgress(`${I18N('SUCCESS')}!`, 5000)if (nameFuncStartBattle == 'invasion_bossStart' ||nameFuncStartBattle == 'bossAttack') {const countMaxBattle = getInput('countAutoBattle');const bossLvl = lastBattleInfo.typeId >= 130 ? lastBattleInfo.typeId : '';const justice = lastBattleInfo?.effects?.attackers?.percentInOutDamageModAndEnergyIncrease_any_99_100_300_99_1000_300 || 0;let winTimer = '';if (nameFuncStartBattle == 'invasion_bossStart') {winTimer = '<br>Secret number: ' + battleR###lt.progress[0].attackers.input[5];}const r###lt = await popup.confirm(I18N('BOSS_HAS_BEEN_DEF_TEXT', {bossLvl: `${svgBoss} ${bossLvl} ${svgJustice} ${justice}`,countBattle: svgAttempt + ' ' + countBattle,countMaxBattle,winTimer,}),[{ msg: I18N('BTN_OK'), r###lt: 0 },{ msg: I18N('MAKE_A_SYNC'), r###lt: 1 },{ msg: I18N('RELOAD_GAME'), r###lt: 2 },]);if (r###lt) {if (r###lt == 1) {cheats.refreshGame();}if (r###lt == 2) {location.reload();}}}endAutoBattle(`${I18N('SUCCESS')}!`)});}/*** Completing a task** Завершение задачи*/function endAutoBattle(reason, info) {setIsCancalBattle(true);console.log(reason, info);resolve();}}this.HWHClasses.executeAutoBattle = executeAutoBattle;function testDailyQuests() {const { dailyQuests } = HWHClasses;return new Promise((resolve, reject) => {const quests = new dailyQuests(resolve, reject);quests.init(questsInfo);quests.start();});}/*** Automatic completion of daily quests** Автоматическое выполнение ежедневных квестов*/class dailyQuests {/*** Send(' {"calls":[{"name":"userGetInfo","args":{},"ident":"body"}]}').then(e => console.log(e))* Send(' {"calls":[{"name":"heroGetAll","args":{},"ident":"body"}]}').then(e => console.log(e))* Send(' {"calls":[{"name":"titanGetAll","args":{},"ident":"body"}]}').then(e => console.log(e))* Send(' {"calls":[{"name":"inventoryGet","args":{},"ident":"body"}]}').then(e => console.log(e))* Send(' {"calls":[{"name":"questGetAll","args":{},"ident":"body"}]}').then(e => console.log(e))* Send(' {"calls":[{"name":"bossGetAll","args":{},"ident":"body"}]}').then(e => console.log(e))*/callsList = ['userGetInfo', 'heroGetAll', 'titanGetAll', 'inventoryGet', 'questGetAll', 'bossGetAll', 'missionGetAll'];dataQuests = {10001: {description: 'Улучши умения героев 3 раза', // ++++++++++++++++doItCall: () => {const upgradeSkills = this.getUpgradeSkills();return upgradeSkills.map(({ heroId, skill }, index) => ({name: 'heroUpgradeSkill',args: { heroId, skill },ident: `heroUpgradeSkill_${index}`,}));},isWeCanDo: () => {const upgradeSkills = this.getUpgradeSkills();let sumGold = 0;for (const skill of upgradeSkills) {sumGold += this.skillCost(skill.value);if (!skill.heroId) {return false;}}return this.questInfo['userGetInfo'].gold > sumGold;},},10002: {description: 'Пройди 10 миссий', // --------------isWeCanDo: () => false,},10003: {description: 'Пройди 3 героические миссии', // ++++++++++++++++isWeCanDo: () => {const vipPoints = +this.questInfo.userGetInfo.vipPoints;const goldTicket = !!this.questInfo.inventoryGet.consumable[151];return (vipPoints > 100 || goldTicket) && this.getHeroicMissionId();},doItCall: () => {const selectedMissionId = this.getHeroicMissionId();const goldTicket = !!this.questInfo.inventoryGet.consumable[151];const vipLevel = Math.max(...lib.data.level.vip.filter(l => l.vipPoints <= +this.questInfo.userGetInfo.vipPoints).map(l => l.level));// Возвращаем массив команд для рейдаif (vipLevel >= 5 || goldTicket) {return [{ name: 'missionRaid', args: { id: selectedMissionId, times: 3 }, ident: 'missionRaid_1' }];} else {return [{ name: 'missionRaid', args: { id: selectedMissionId, times: 1 }, ident: 'missionRaid_1' },{ name: 'missionRaid', args: { id: selectedMissionId, times: 1 }, ident: 'missionRaid_2' },{ name: 'missionRaid', args: { id: selectedMissionId, times: 1 }, ident: 'missionRaid_3' },];}},},10004: {description: 'Сразись 3 раза на Арене или Гранд Арене', // --------------isWeCanDo: () => false,},10006: {description: 'Используй обмен изумрудов 1 раз', // ++++++++++++++++doItCall: () => [{name: 'refillableAlchemyUse',args: { multi: false },ident: 'refillableAlchemyUse',},],isWeCanDo: () => {const starMoney = this.questInfo['userGetInfo'].starMoney;return starMoney >= 20;},},10007: {description: 'Соверши 1 призыв в Атриуме Душ', // ++++++++++++++++doItCall: () => [{ name: 'gacha_open', args: { ident: 'heroGacha', free: true, pack: false }, ident: 'gacha_open' }],isWeCanDo: () => {const soulCrystal = this.questInfo['inventoryGet'].coin[38];return soulCrystal > 0;},},10016: {description: 'Отправь подарки согильдийцам', // ++++++++++++++++doItCall: () => [{ name: 'clanSendDailyGifts', args: {}, ident: 'clanSendDailyGifts' }],isWeCanDo: () => true,},10018: {description: 'Используй зелье опыта', // ++++++++++++++++doItCall: () => {const expHero = this.getExpHero();return [{name: 'consumableUseHeroXp',args: {heroId: expHero.heroId,libId: expHero.libId,amount: 1,},ident: 'consumableUseHeroXp',},];},isWeCanDo: () => {const expHero = this.getExpHero();return expHero.heroId && expHero.libId;},},10019: {description: 'Открой 1 сундук в Башне',doItFunc: testTower,isWeCanDo: () => false,},10020: {description: 'Открой 3 сундука в Запределье', // ГотовоdoItCall: () => {return this.getOutlandChest();},isWeCanDo: () => {const outlandChest = this.getOutlandChest();return outlandChest.length > 0;},},10021: {description: 'Собери 75 Титанита в Подземелье Гильдии',isWeCanDo: () => false,},10022: {description: 'Собери 150 Титанита в Подземелье Гильдии',doItFunc: testDungeon,isWeCanDo: () => false,},10023: {description: 'Прокачай Дар Стихий на 1 уровень', // ГотовоdoItCall: () => {const heroId = this.getHeroIdTitanGift();return [{ name: 'heroTitanGiftLevelUp', args: { heroId }, ident: 'heroTitanGiftLevelUp' },{ name: 'heroTitanGiftDrop', args: { heroId }, ident: 'heroTitanGiftDrop' },];},isWeCanDo: () => {const heroId = this.getHeroIdTitanGift();return heroId;},},10024: {description: 'Повысь уровень любого артефакта один раз', // ГотовоdoItCall: () => {const upArtifact = this.getUpgradeArtifact();return [{name: 'heroArtifactLevelUp',args: {heroId: upArtifact.heroId,slotId: upArtifact.slotId,},ident: `heroArtifactLevelUp`,},];},isWeCanDo: () => {const upgradeArtifact = this.getUpgradeArtifact();return upgradeArtifact.heroId;},},10025: {description: 'Начни 1 Экспедицию',doItFunc: checkExpedition,isWeCanDo: () => false,},10026: {description: 'Начни 4 Экспедиции', // --------------doItFunc: checkExpedition,isWeCanDo: () => false,},10027: {description: 'Победи в 1 бою Турнира Стихий',doItFunc: testTitanArena,isWeCanDo: () => false,},10028: {description: 'Повысь уровень любого артефакта титанов', // ГотовоdoItCall: () => {const upTitanArtifact = this.getUpgradeTitanArtifact();return [{name: 'titanArtifactLevelUp',args: {titanId: upTitanArtifact.titanId,slotId: upTitanArtifact.slotId,},ident: `titanArtifactLevelUp`,},];},isWeCanDo: () => {const upgradeTitanArtifact = this.getUpgradeTitanArtifact();return upgradeTitanArtifact.titanId;},},10029: {description: 'Открой сферу артефактов титанов', // ++++++++++++++++doItCall: () => [{ name: 'titanArtifactChestOpen', args: { amount: 1, free: true }, ident: 'titanArtifactChestOpen' }],isWeCanDo: () => {return this.questInfo['inventoryGet']?.consumable[55] > 0;},},10030: {description: 'Улучши облик любого героя 1 раз', // ГотовоdoItCall: () => {const upSkin = this.getUpgradeSkin();return [{name: 'heroSkinUpgrade',args: {heroId: upSkin.heroId,skinId: upSkin.skinId,},ident: `heroSkinUpgrade`,},];},isWeCanDo: () => {const upgradeSkin = this.getUpgradeSkin();return upgradeSkin.heroId;},},10031: {description: 'Победи в 6 боях Турнира Стихий', // --------------doItFunc: testTitanArena,isWeCanDo: () => false,},10043: {description: 'Начни или присоеденись к Приключению', // --------------isWeCanDo: () => false,},10044: {description: 'Воспользуйся призывом питомцев 1 раз', // ++++++++++++++++doItCall: () => [{ name: 'pet_chestOpen', args: { amount: 1, paid: false }, ident: 'pet_chestOpen' }],isWeCanDo: () => {return this.questInfo['inventoryGet']?.consumable[90] > 0;},},10046: {/*** TODO: Watch Adventure* TODO: Смотреть приключение*/description: 'Открой 3 сундука в Приключениях',isWeCanDo: () => false,},10047: {description: 'Набери 150 очков активности в Гильдии', // ГотовоdoItCall: () => {const enchantRune = this.getEnchantRune();return [{name: 'heroEnchantRune',args: {heroId: enchantRune.heroId,tier: enchantRune.tier,items: {consumable: { [enchantRune.itemId]: 1 },},},ident: `heroEnchantRune`,},];},isWeCanDo: () => {const userInfo = this.questInfo['userGetInfo'];const enchantRune = this.getEnchantRune();return enchantRune.heroId && userInfo.gold > 1e3;},},};constructor(resolve, reject, questInfo) {this.resolve = resolve;this.reject = reject;}init(questInfo) {this.questInfo = questInfo;this.isAuto = false;}async autoInit(isAuto) {this.isAuto = isAuto || false;const quests = {};const calls = this.callsList.map((name) => ({name,args: {},ident: name,}));const r###lt = await Send(JSON.stringify({ calls })).then((e) => e.r###lts);for (const call of r###lt) {quests[call.ident] = call.r###lt.response;}this.questInfo = quests;}async start() {const weCanDo = [];const selectedActions = getSaveVal('selectedActions', {});for (let quest of this.questInfo['questGetAll']) {if (quest.id in this.dataQuests && quest.state == 1) {if (!selectedActions[quest.id]) {selectedActions[quest.id] = {checked: false,};}const isWeCanDo = this.dataQuests[quest.id].isWeCanDo;if (!isWeCanDo.call(this)) {continue;}weCanDo.push({name: quest.id,label: I18N(`QUEST_${quest.id}`),checked: selectedActions[quest.id].checked,});}}if (!weCanDo.length) {this.end(I18N('NOTHING_TO_DO'));return;}console.log(weCanDo);let taskList = [];if (this.isAuto) {taskList = weCanDo;} else {const answer = await popup.confirm(`${I18N('YOU_CAN_COMPLETE')}:`,[{ msg: I18N('BTN_DO_IT'), r###lt: true },{ msg: I18N('BTN_CANCEL'), r###lt: false, isCancel: true },],weCanDo);if (!answer) {this.end('');return;}taskList = popup.getCheckBoxes();taskList.forEach((e) => {selectedActions[e.name].checked = e.checked;});setSaveVal('selectedActions', selectedActions);}const calls = [];let countChecked = 0;for (const task of taskList) {if (task.checked) {countChecked++;const quest = this.dataQuests[task.name];console.log(quest.description);if (quest.doItCall) {const doItCall = quest.doItCall.call(this);calls.push(...doItCall);}}}if (!countChecked) {this.end(I18N('NOT_QUEST_COMPLETED'));return;}const r###lt = await Send(JSON.stringify({ calls }));if (r###lt.error) {console.error(r###lt.error, r###lt.error.call);}this.end(`${I18N('COMPLETED_QUESTS')}: ${countChecked}`);}errorHandling(error) {//console.error(error);let errorInfo = error.toString() + '\n';try {const errorStack = error.stack.split('\n');const endStack = errorStack.map((e) => e.split('@')[0]).indexOf('testDoYourBest');errorInfo += errorStack.slice(0, endStack).join('\n');} catch (e) {errorInfo += error.stack;}copyText(errorInfo);}skillCost(lvl) {return 573 * lvl ** 0.9 + lvl ** 2.379;}getUpgradeSkills() {const heroes = Object.values(this.questInfo['heroGetAll']);const upgradeSkills = [{ heroId: 0, slotId: 0, value: 130 },{ heroId: 0, slotId: 0, value: 130 },{ heroId: 0, slotId: 0, value: 130 },];const skillLib = lib.getData('skill');/*** color - 1 (белый) открывает 1 навык* color - 2 (зеленый) открывает 2 навык* color - 4 (синий) открывает 3 навык* color - 7 (фиолетовый) открывает 4 навык*/const colors = [1, 2, 4, 7];for (const hero of heroes) {const level = hero.level;const color = hero.color;for (let skillId in hero.skills) {const tier = skillLib[skillId].tier;const sVal = hero.skills[skillId];if (color < colors[tier] || tier < 1 || tier > 4) {continue;}for (let upSkill of upgradeSkills) {if (sVal < upSkill.value && sVal < level) {upSkill.value = sVal;upSkill.heroId = hero.id;upSkill.skill = tier;break;}}}}return upgradeSkills;}getUpgradeArtifact() {const heroes = Object.values(this.questInfo['heroGetAll']);const inventory = this.questInfo['inventoryGet'];const upArt = { heroId: 0, slotId: 0, level: 100 };const heroLib = lib.getData('hero');const artifactLib = lib.getData('artifact');for (const hero of heroes) {const heroInfo = heroLib[hero.id];const level = hero.level;if (level < 20) {continue;}for (let slotId in hero.artifacts) {const art = hero.artifacts[slotId];/* Текущая звезданость арта */const star = art.star;if (!star) {continue;}/* Текущий уровень арта */const level = art.level;if (level >= 100) {continue;}/* Идентификатор арта в библиотеке */const artifactId = heroInfo.artifacts[slotId];const artInfo = artifactLib.id[artifactId];const costNextLevel = artifactLib.type[artInfo.type].levels[level + 1].cost;const costCurrency = Object.keys(costNextLevel).pop();const costValues = Object.entries(costNextLevel[costCurrency]).pop();const costId = costValues[0];const costValue = +costValues[1];/** TODO: Возможно стоит искать самый высокий уровень который можно качнуть? */if (level < upArt.level && inventory[costCurrency][costId] >= costValue) {upArt.level = level;upArt.heroId = hero.id;upArt.slotId = slotId;upArt.costCurrency = costCurrency;upArt.costId = costId;upArt.costValue = costValue;}}}return upArt;}getUpgradeSkin() {const heroes = Object.values(this.questInfo['heroGetAll']);const inventory = this.questInfo['inventoryGet'];const upSkin = { heroId: 0, skinId: 0, level: 60, cost: 1500 };const skinLib = lib.getData('skin');for (const hero of heroes) {const level = hero.level;if (level < 20) {continue;}for (let skinId in hero.skins) {/* Текущий уровень скина */const level = hero.skins[skinId];if (level >= 60) {continue;}/* Идентификатор скина в библиотеке */const skinInfo = skinLib[skinId];if (!skinInfo.statData.levels?.[level + 1]) {continue;}const costNextLevel = skinInfo.statData.levels[level + 1].cost;const costCurrency = Object.keys(costNextLevel).pop();const costCurrencyId = Object.keys(costNextLevel[costCurrency]).pop();const costValue = +costNextLevel[costCurrency][costCurrencyId];/** TODO: Возможно стоит искать самый высокий уровень который можно качнуть? */if (level < upSkin.level && costValue < upSkin.cost && inventory[costCurrency][costCurrencyId] >= costValue) {upSkin.cost = costValue;upSkin.level = level;upSkin.heroId = hero.id;upSkin.skinId = skinId;upSkin.costCurrency = costCurrency;upSkin.costCurrencyId = costCurrencyId;}}}return upSkin;}getUpgradeTitanArtifact() {const titans = Object.values(this.questInfo['titanGetAll']);const inventory = this.questInfo['inventoryGet'];const userInfo = this.questInfo['userGetInfo'];const upArt = { titanId: 0, slotId: 0, level: 120 };const titanLib = lib.getData('titan');const artTitanLib = lib.getData('titanArtifact');for (const titan of titans) {const titanInfo = titanLib[titan.id];// const level = titan.level// if (level < 20) {// continue;// }for (let slotId in titan.artifacts) {const art = titan.artifacts[slotId];/* Текущая звезданость арта */const star = art.star;if (!star) {continue;}/* Текущий уровень арта */const level = art.level;if (level >= 120) {continue;}/* Идентификатор арта в библиотеке */const artifactId = titanInfo.artifacts[slotId];const artInfo = artTitanLib.id[artifactId];const costNextLevel = artTitanLib.type[artInfo.type].levels[level + 1].cost;const costCurrency = Object.keys(costNextLevel).pop();let costValue = 0;let currentValue = 0;if (costCurrency == 'gold') {costValue = costNextLevel[costCurrency];currentValue = userInfo.gold;} else {const costValues = Object.entries(costNextLevel[costCurrency]).pop();const costId = costValues[0];costValue = +costValues[1];currentValue = inventory[costCurrency][costId];}/** TODO: Возможно стоит искать самый высокий уровень который можно качнуть? */if (level < upArt.level && currentValue >= costValue) {upArt.level = level;upArt.titanId = titan.id;upArt.slotId = slotId;break;}}}return upArt;}getEnchantRune() {const heroes = Object.values(this.questInfo['heroGetAll']);const inventory = this.questInfo['inventoryGet'];const enchRune = { heroId: 0, tier: 0, exp: 43750, itemId: 0 };for (let i = 1; i <= 4; i++) {if (inventory.consumable[i] > 0) {enchRune.itemId = i;break;}return enchRune;}const runeLib = lib.getData('rune');const runeLvls = Object.values(runeLib.level);/*** color - 4 (синий) открывает 1 и 2 символ* color - 7 (фиолетовый) открывает 3 символ* color - 8 (фиолетовый +1) открывает 4 символ* color - 9 (фиолетовый +2) открывает 5 символ*/// TODO: кажется надо учесть уровень командыconst colors = [4, 4, 7, 8, 9];for (const hero of heroes) {const color = hero.color;for (let runeTier in hero.runes) {/* Проверка на доступность руны */if (color < colors[runeTier]) {continue;}/* Текущий опыт руны */const exp = hero.runes[runeTier];if (exp >= 43750) {continue;}let level = 0;if (exp) {for (let lvl of runeLvls) {if (exp >= lvl.enchantValue) {level = lvl.level;} else {break;}}}/** Уровень героя необходимый для уровня руны */const heroLevel = runeLib.level[level].heroLevel;if (hero.level < heroLevel) {continue;}/** TODO: Возможно стоит искать самый высокий уровень который можно качнуть? */if (exp < enchRune.exp) {enchRune.exp = exp;enchRune.heroId = hero.id;enchRune.tier = runeTier;break;}}}return enchRune;}getOutlandChest() {const bosses = this.questInfo['bossGetAll'];const calls = [];for (let boss of bosses) {if (boss.mayRaid) {calls.push({name: 'bossRaid',args: {bossId: boss.id,},ident: 'bossRaid_' + boss.id,});calls.push({name: 'bossOpenChest',args: {bossId: boss.id,amount: 1,starmoney: 0,},ident: 'bossOpenChest_' + boss.id,});} else if (boss.chestId == 1) {calls.push({name: 'bossOpenChest',args: {bossId: boss.id,amount: 1,starmoney: 0,},ident: 'bossOpenChest_' + boss.id,});}}return calls;}getExpHero() {const heroes = Object.values(this.questInfo['heroGetAll']);const inventory = this.questInfo['inventoryGet'];const expHero = { heroId: 0, exp: 3625195, libId: 0 };/** зелья опыта (consumable 9, 10, 11, 12) */for (let i = 9; i <= 12; i++) {if (inventory.consumable[i]) {expHero.libId = i;break;}}for (const hero of heroes) {const exp = hero.xp;if (exp < expHero.exp) {expHero.heroId = hero.id;}}return expHero;}getHeroIdTitanGift() {const heroes = Object.values(this.questInfo['heroGetAll']);const inventory = this.questInfo['inventoryGet'];const user = this.questInfo['userGetInfo'];const titanGiftLib = lib.getData('titanGift');/** Искры */const titanGift = inventory.consumable[24];let heroId = 0;let minLevel = 30;if (titanGift < 250 || user.gold < 7000) {return 0;}for (const hero of heroes) {if (hero.titanGiftLevel >= 30) {continue;}if (!hero.titanGiftLevel) {return hero.id;}const cost = titanGiftLib[hero.titanGiftLevel].cost;if (minLevel > hero.titanGiftLevel && titanGift >= cost.consumable[24] && user.gold >= cost.gold) {minLevel = hero.titanGiftLevel;heroId = hero.id;}}return heroId;}getHeroicMissionId() {// Получаем доступные миссии с 3 звездамиconst availableMissionsToRaid = Object.values(this.questInfo.missionGetAll).filter((mission) => mission.stars === 3).map((mission) => mission.id);// Получаем героев для улучшения, у которых меньше 6 звездconst heroesToUpgrade = Object.values(this.questInfo.heroGetAll).filter((hero) => hero.star < 6).sort((a, b) => b.power - a.power).map((hero) => hero.id);// Получаем героические миссии, которые доступны для рейдовconst heroicMissions = Object.values(lib.data.mission).filter((mission) => mission.isHeroic && availableMissionsToRaid.includes(mission.id));// Собираем дропы из героических миссийconst drops = heroicMissions.map((mission) => {const lastWave = mission.normalMode.waves[mission.normalMode.waves.length - 1];const allRewards = lastWave.enemies[lastWave.enemies.length - 1].drop.map((drop) => drop.reward);const heroId = +Object.keys(allRewards.find((reward) => reward.fragmentHero).fragmentHero).pop();return { id: mission.id, heroId };});// Определяем, какие дропы подходят для героев, которых нужно улучшитьconst heroDrops = heroesToUpgrade.map((heroId) => drops.find((drop) => drop.heroId == heroId)).filter((drop) => drop);const firstMission = heroDrops[0];// Выбираем миссию для рейдаconst selectedMissionId = firstMission ? firstMission.id : 1;const stamina = this.questInfo.userGetInfo.refillable.find((x) => x.id == 1).amount;const costMissions = 3 * lib.data.mission[selectedMissionId].normalMode.teamExp;if (stamina < costMissions) {console.log('Энергии не достаточно');return 0;}return selectedMissionId;}end(status) {setProgress(status, true);this.resolve();}}this.questRun = dailyQuests;this.HWHClasses.dailyQuests = dailyQuests;function testDoYourBest() {const { doYourBest } = HWHClasses;return new Promise((resolve, reject) => {const doIt = new doYourBest(resolve, reject);doIt.start();});}/*** Do everything button** Кнопка сделать все*/class doYourBest {funcList = [{name: 'getOutland',label: I18N('ASSEMBLE_OUTLAND'),checked: false},{name: 'testTower',label: I18N('PASS_THE_TOWER'),checked: false},{name: 'checkExpedition',label: I18N('CHECK_EXPEDITIONS'),checked: false},{name: 'testTitanArena',label: I18N('COMPLETE_TOE'),checked: false},{name: 'mailGetAll',label: I18N('COLLECT_MAIL'),checked: false},{name: 'collectAllStuff',label: I18N('COLLECT_MISC'),title: I18N('COLLECT_MISC_TITLE'),checked: false},{name: 'getDailyBonus',label: I18N('DAILY_BONUS'),checked: false},{name: 'dailyQuests',label: I18N('DO_DAILY_QUESTS'),checked: false},{name: 'rollAscension',label: I18N('SEER_TITLE'),checked: false},{name: 'questAllFarm',label: I18N('COLLECT_QUEST_REWARDS'),checked: false},{name: 'testDungeon',label: I18N('COMPLETE_DUNGEON'),checked: false},{name: 'synchronization',label: I18N('MAKE_A_SYNC'),checked: false},{name: 'reloadGame',label: I18N('RELOAD_GAME'),checked: false},];functions = {getOutland,testTower,checkExpedition,testTitanArena,mailGetAll,collectAllStuff: async () => {await offerFarmAllReward();await Send('{"calls":[{"name":"subscriptionFarm","args":{},"ident":"body"},{"name":"zeppelinGiftFarm","args":{},"ident":"zeppelinGiftFarm"},{"name":"grandFarmCoins","args":{},"ident":"grandFarmCoins"},{"name":"gacha_refill","args":{"ident":"heroGacha"},"ident":"gacha_refill"}]}');},dailyQuests: async function () {const quests = new dailyQuests(() => { }, () => { });await quests.autoInit(true);await quests.start();},rollAscension,getDailyBonus,questAllFarm,testDungeon,synchronization: async () => {cheats.refreshGame();},reloadGame: async () => {location.reload();},}constructor(resolve, reject, questInfo) {this.resolve = resolve;this.reject = reject;this.questInfo = questInfo}async start() {const selectedDoIt = getSaveVal('selectedDoIt', {});this.funcList.forEach(task => {if (!selectedDoIt[task.name]) {selectedDoIt[task.name] = {checked: task.checked}} else {task.checked = selectedDoIt[task.name].checked}});const answer = await popup.confirm(I18N('RUN_FUNCTION'), [{ msg: I18N('BTN_CANCEL'), r###lt: false, isCancel: true },{ msg: I18N('BTN_GO'), r###lt: true },], this.funcList);if (!answer) {this.end('');return;}const taskList = popup.getCheckBoxes();taskList.forEach(task => {selectedDoIt[task.name].checked = task.checked;});setSaveVal('selectedDoIt', selectedDoIt);for (const task of popup.getCheckBoxes()) {if (task.checked) {try {setProgress(`${task.label} <br>${I18N('PERFORMED')}!`);await this.functions[task.name]();setProgress(`${task.label} <br>${I18N('DONE')}!`);} catch (error) {if (await popup.confirm(`${I18N('ERRORS_OCCURRES')}:<br> ${task.label} <br>${I18N('COPY_ERROR')}?`, [{ msg: I18N('BTN_NO'), r###lt: false },{ msg: I18N('BTN_YES'), r###lt: true },])) {this.errorHandling(error);}}}}setTimeout((msg) => {this.end(msg);}, 2000, I18N('ALL_TASK_COMPLETED'));return;}errorHandling(error) {//console.error(error);let errorInfo = error.toString() + '\n';try {const errorStack = error.stack.split('\n');const endStack = errorStack.map(e => e.split('@')[0]).indexOf("testDoYourBest");errorInfo += errorStack.slice(0, endStack).join('\n');} catch (e) {errorInfo += error.stack;}copyText(errorInfo);}end(status) {setProgress(status, true);this.resolve();}}this.HWHClasses.doYourBest = doYourBest;/*** Passing the adventure along the specified route** Прохождение приключения по указанному маршруту*/function testAdventure(type) {const { executeAdventure } = HWHClasses;return new Promise((resolve, reject) => {const bossBattle = new executeAdventure(resolve, reject);bossBattle.start(type);});}/*** Passing the adventure along the specified route** Прохождение приключения по указанному маршруту*/class executeAdventure {type = 'default';actions = {default: {getInfo: "adventure_getInfo",startBattle: 'adventure_turnStartBattle',endBattle: 'adventure_endBattle',collectBuff: 'adventure_turnCollectBuff'},solo: {getInfo: "adventureSolo_getInfo",startBattle: 'adventureSolo_turnStartBattle',endBattle: 'adventureSolo_endBattle',collectBuff: 'adventureSolo_turnCollectBuff'}}terminatеReason = I18N('UNKNOWN');callAdventureInfo = {name: "adventure_getInfo",args: {},ident: "adventure_getInfo"}callTeamGetAll = {name: "teamGetAll",args: {},ident: "teamGetAll"}callTeamGetFavor = {name: "teamGetFavor",args: {},ident: "teamGetFavor"}callStartBattle = {name: "adventure_turnStartBattle",args: {},ident: "body"}callEndBattle = {name: "adventure_endBattle",args: {r###lt: {},progress: {},},ident: "body"}callCollectBuff = {name: "adventure_turnCollectBuff",args: {},ident: "body"}constructor(resolve, reject) {this.resolve = resolve;this.reject = reject;}async start(type) {this.type = type || this.type;this.callAdventureInfo.name = this.actions[this.type].getInfo;const data = await Send(JSON.stringify({calls: [this.callAdventureInfo,this.callTeamGetAll,this.callTeamGetFavor]}));return this.checkAdventureInfo(data.r###lts);}async getPath() {const oldVal = getSaveVal('adventurePath', '');const keyPath = `adventurePath:${this.mapIdent}`;const answer = await popup.confirm(I18N('ENTER_THE_PATH'), [{msg: I18N('START_ADVENTURE'),placeholder: '1,2,3,4,5,6',isInput: true,default: getSaveVal(keyPath, oldVal)},{msg: I18N('BTN_CANCEL'),r###lt: false,isCancel: true},]);if (!answer) {this.terminatеReason = I18N('BTN_CANCELED');return false;}let path = answer.split(',');if (path.length < 2) {path = answer.split('-');}if (path.length < 2) {this.terminatеReason = I18N('MUST_TWO_POINTS');return false;}for (let p in path) {path[p] = +path[p].trim()if (Number.isNaN(path[p])) {this.terminatеReason = I18N('MUST_ONLY_NUMBERS');return false;}}if (!this.checkPath(path)) {return false;}setSaveVal(keyPath, answer);return path;}checkPath(path) {for (let i = 0; i < path.length - 1; i++) {const currentPoint = path[i];const nextPoint = path[i + 1];const isValidPath = this.paths.some(p =>(p.from_id === currentPoint && p.to_id === nextPoint) ||(p.from_id === nextPoint && p.to_id === currentPoint));if (!isValidPath) {this.terminatеReason = I18N('INCORRECT_WAY', {from: currentPoint,to: nextPoint,});return false;}}return true;}async checkAdventureInfo(data) {this.advInfo = data[0].r###lt.response;if (!this.advInfo) {this.terminatеReason = I18N('NOT_ON_AN_ADVENTURE') ;return this.end();}const heroesTeam = data[1].r###lt.response.adventure_hero;const favor = data[2]?.r###lt.response.adventure_hero;const heroes = heroesTeam.slice(0, 5);const pet = heroesTeam[5];this.args = {pet,heroes,favor,path: [],broadcast: false}const advUserInfo = this.advInfo.users[userInfo.id];this.turnsLeft = advUserInfo.turnsLeft;this.currentNode = advUserInfo.currentNode;this.nodes = this.advInfo.nodes;this.paths = this.advInfo.paths;this.mapIdent = this.advInfo.mapIdent;this.path = await this.getPath();if (!this.path) {return this.end();}if (this.currentNode == 1 && this.path[0] != 1) {this.path.unshift(1);}return this.loop();}async loop() {const position = this.path.indexOf(+this.currentNode);if (!(~position)) {this.terminatеReason = I18N('YOU_IN_NOT_ON_THE_WAY');return this.end();}this.path = this.path.slice(position);if ((this.path.length - 1) > this.turnsLeft &&await popup.confirm(I18N('ATTEMPTS_NOT_ENOUGH'), [{ msg: I18N('YES_CONTINUE'), r###lt: false },{ msg: I18N('BTN_NO'), r###lt: true },])) {this.terminatеReason = I18N('NOT_ENOUGH_AP');return this.end();}const toPath = [];for (const nodeId of this.path) {if (!this.turnsLeft) {this.terminatеReason = I18N('ATTEMPTS_ARE_OVER');return this.end();}toPath.push(nodeId);console.log(toPath);if (toPath.length > 1) {setProgress(toPath.join(' > ') + ` ${I18N('MOVES')}: ` + this.turnsLeft);}if (nodeId == this.currentNode) {continue;}const nodeInfo = this.getNodeInfo(nodeId);if (nodeInfo.type == 'TYPE_COMBAT') {if (nodeInfo.state == 'empty') {this.turnsLeft--;continue;}/*** Disable regular battle cancellation** Отключаем штатную отменую боя*/setIsCancalBattle(false);if (await this.battle(toPath)) {this.turnsLeft--;toPath.splice(0, toPath.indexOf(nodeId));nodeInfo.state = 'empty';setIsCancalBattle(true);continue;}setIsCancalBattle(true);return this.end()}if (nodeInfo.type == 'TYPE_PLAYERBUFF') {const buff = this.checkBuff(nodeInfo);if (buff == null) {continue;}if (await this.collectBuff(buff, toPath)) {this.turnsLeft--;toPath.splice(0, toPath.indexOf(nodeId));continue;}this.terminatеReason = I18N('BUFF_GET_ERROR');return this.end();}}this.terminatеReason = I18N('SUCCESS');return this.end();}/*** Carrying out a fight** Проведение боя*/async battle(path, preCalc = true) {const data = await this.startBattle(path);try {const battle = data.r###lts[0].r###lt.response.battle;const r###lt = await Calc(battle);if (r###lt.r###lt.win) {const info = await this.endBattle(r###lt);if (info.r###lts[0].r###lt.response?.error) {this.terminatеReason = I18N('BATTLE_END_ERROR');return false;}} else {await this.cancelBattle(r###lt);if (preCalc && await this.preCalcBattle(battle)) {path = path.slice(-2);for (let i = 1; i <= getInput('countAutoBattle'); i++) {setProgress(`${I18N('AUTOBOT')}: ${i}/${getInput('countAutoBattle')}`);const r###lt = await this.battle(path, false);if (r###lt) {setProgress(I18N('VICTORY'));return true;}}this.terminatеReason = I18N('FAILED_TO_WIN_AUTO');return false;}return false;}} catch (error) {console.error(error);if (await popup.confirm(I18N('ERROR_OF_THE_BATTLE_COPY'), [{ msg: I18N('BTN_NO'), r###lt: false },{ msg: I18N('BTN_YES'), r###lt: true },])) {this.errorHandling(error, data);}this.terminatеReason = I18N('ERROR_DURING_THE_BATTLE');return false;}return true;}/*** Recalculate battles** Прерасчтет битвы*/async preCalcBattle(battle) {const countTestBattle = getInput('countTestBattle');for (let i = 0; i < countTestBattle; i++) {battle.seed = Math.floor(Date.now() / 1000) + random(0, 1e3);const r###lt = await Calc(battle);if (r###lt.r###lt.win) {console.log(i, countTestBattle);return true;}}this.terminatеReason = I18N('NO_CHANCE_WIN') + countTestBattle;return false;}/*** Starts a fight** Начинает бой*/startBattle(path) {this.args.path = path;this.callStartBattle.name = this.actions[this.type].startBattle;this.callStartBattle.args = this.argsconst calls = [this.callStartBattle];return Send(JSON.stringify({ calls }));}cancelBattle(battle) {const fixBattle = function (heroes) {for (const ids in heroes) {const hero = heroes[ids];hero.energy = random(1, 999);if (hero.hp > 0) {hero.hp = random(1, hero.hp);}}}fixBattle(battle.progress[0].attackers.heroes);fixBattle(battle.progress[0].defenders.heroes);return this.endBattle(battle);}/*** Ends the fight** Заканчивает бой*/endBattle(battle) {this.callEndBattle.name = this.actions[this.type].endBattle;this.callEndBattle.args.r###lt = battle.r###ltthis.callEndBattle.args.progress = battle.progressconst calls = [this.callEndBattle];return Send(JSON.stringify({ calls }));}/*** Checks if you can get a buff** Проверяет можно ли получить баф*/checkBuff(nodeInfo) {let id = null;let value = 0;for (const buffId in nodeInfo.buffs) {const buff = nodeInfo.buffs[buffId];if (buff.owner == null && buff.value > value) {id = buffId;value = buff.value;}}nodeInfo.buffs[id].owner = 'Я';return id;}/*** Collects a buff** Собирает баф*/async collectBuff(buff, path) {this.callCollectBuff.name = this.actions[this.type].collectBuff;this.callCollectBuff.args = { buff, path };const calls = [this.callCollectBuff];return Send(JSON.stringify({ calls }));}getNodeInfo(nodeId) {return this.nodes.find(node => node.id == nodeId);}errorHandling(error, data) {//console.error(error);let errorInfo = error.toString() + '\n';try {const errorStack = error.stack.split('\n');const endStack = errorStack.map(e => e.split('@')[0]).indexOf("testAdventure");errorInfo += errorStack.slice(0, endStack).join('\n');} catch (e) {errorInfo += error.stack;}if (data) {errorInfo += '\nData: ' + JSON.stringify(data);}copyText(errorInfo);}end() {setIsCancalBattle(true);setProgress(this.terminatеReason, true);console.log(this.terminatеReason);this.resolve();}}this.HWHClasses.executeAdventure = executeAdventure;/*** Passage of brawls** Прохождение потасовок*/function testBrawls(isAuto) {const { executeBrawls } = HWHClasses;return new Promise((resolve, reject) => {const brawls = new executeBrawls(resolve, reject);brawls.start(brawlsPack, isAuto);});}/*** Passage of brawls** Прохождение потасовок*/class executeBrawls {callBrawlQuestGetInfo = {name: "brawl_questGetInfo",args: {},ident: "brawl_questGetInfo"}callBrawlFindEnemies = {name: "brawl_findEnemies",args: {},ident: "brawl_findEnemies"}callBrawlQuestFarm = {name: "brawl_questFarm",args: {},ident: "brawl_questFarm"}callUserGetInfo = {name: "userGetInfo",args: {},ident: "userGetInfo"}callTeamGetMaxUpgrade = {name: "teamGetMaxUpgrade",args: {},ident: "teamGetMaxUpgrade"}callBrawlGetInfo = {name: "brawl_getInfo",args: {},ident: "brawl_getInfo"}stats = {win: 0,loss: 0,count: 0,}stage = {'3': 1,'7': 2,'12': 3,}attempts = 0;constructor(resolve, reject) {this.resolve = resolve;this.reject = reject;const allHeroIds = Object.keys(lib.getData('hero'));this.callTeamGetMaxUpgrade.args.units = {hero: allHeroIds.filter((id) => +id < 1000),titan: allHeroIds.filter((id) => +id >= 4000 && +id < 4100),pet: allHeroIds.filter((id) => +id >= 6000 && +id < 6100),};}async start(args, isAuto) {this.isAuto = isAuto;this.args = args;setIsCancalBattle(false);this.brawlInfo = await this.getBrawlInfo();this.attempts = this.brawlInfo.attempts;if (!this.attempts && !this.info.boughtEndlessLivesToday) {this.end(I18N('DONT_HAVE_LIVES'));return;}while (1) {if (!isBrawlsAutoStart) {this.end(I18N('BTN_CANCELED'));return;}const maxStage = this.brawlInfo.questInfo.stage;const stage = this.stage[maxStage];const progress = this.brawlInfo.questInfo.progress;setProgress(`${I18N('STAGE')} ${stage}: ${progress}/${maxStage}<br>${I18N('FIGHTS')}: ${this.stats.count}<br>${I18N('WINS')}: ${this.stats.win}<br>${I18N('LOSSES')}: ${this.stats.loss}<br>${I18N('LIVES')}: ${this.attempts}<br>${I18N('STOP')}`,false,function () {isBrawlsAutoStart = false;});if (this.brawlInfo.questInfo.canFarm) {const r###lt = await this.questFarm();console.log(r###lt);}if (!this.continueAttack && this.brawlInfo.questInfo.stage == 12 && this.brawlInfo.questInfo.progress == 12) {if (await popup.confirm(I18N('BRAWL_DAILY_TASK_COMPLETED'), [{ msg: I18N('BTN_NO'), r###lt: true },{ msg: I18N('BTN_YES'), r###lt: false },])) {this.end(I18N('SUCCESS'));return;} else {this.continueAttack = true;}}if (!this.attempts && !this.info.boughtEndlessLivesToday) {this.end(I18N('DONT_HAVE_LIVES'));return;}const enemie = Object.values(this.brawlInfo.findEnemies).shift();// Автоматический подбор пачкиif (this.isAuto) {if (this.mandatoryId <= 4000 && this.mandatoryId != 13) {this.end(I18N('BRAWL_AUTO_PACK_NOT_CUR_HERO'));return;}if (this.mandatoryId >= 4000 && this.mandatoryId < 4100) {this.args = await this.updateTitanPack(enemie.heroes);} else if (this.mandatoryId < 4000 && this.mandatoryId == 13) {this.args = await this.updateHeroesPack(enemie.heroes);}}const r###lt = await this.battle(enemie.userId);this.brawlInfo = {questInfo: r###lt[1].r###lt.response,findEnemies: r###lt[2].r###lt.response,};}}async updateTitanPack(enemieHeroes) {const packs = [[4033, 4040, 4041, 4042, 4043],[4032, 4040, 4041, 4042, 4043],[4031, 4040, 4041, 4042, 4043],[4030, 4040, 4041, 4042, 4043],[4032, 4033, 4040, 4042, 4043],[4030, 4033, 4041, 4042, 4043],[4031, 4033, 4040, 4042, 4043],[4032, 4033, 4040, 4041, 4043],[4023, 4040, 4041, 4042, 4043],[4030, 4033, 4040, 4042, 4043],[4031, 4033, 4040, 4041, 4043],[4022, 4040, 4041, 4042, 4043],[4030, 4033, 4040, 4041, 4043],[4021, 4040, 4041, 4042, 4043],[4020, 4040, 4041, 4042, 4043],[4023, 4033, 4040, 4042, 4043],[4030, 4032, 4033, 4042, 4043],[4023, 4033, 4040, 4041, 4043],[4031, 4032, 4033, 4040, 4043],[4030, 4032, 4033, 4041, 4043],[4030, 4031, 4033, 4042, 4043],[4013, 4040, 4041, 4042, 4043],[4030, 4032, 4033, 4040, 4043],[4030, 4031, 4033, 4041, 4043],[4012, 4040, 4041, 4042, 4043],[4030, 4031, 4033, 4040, 4043],[4011, 4040, 4041, 4042, 4043],[4010, 4040, 4041, 4042, 4043],[4023, 4032, 4033, 4042, 4043],[4022, 4032, 4033, 4042, 4043],[4023, 4032, 4033, 4041, 4043],[4021, 4032, 4033, 4042, 4043],[4022, 4032, 4033, 4041, 4043],[4023, 4030, 4033, 4042, 4043],[4023, 4032, 4033, 4040, 4043],[4013, 4033, 4040, 4042, 4043],[4020, 4032, 4033, 4042, 4043],[4021, 4032, 4033, 4041, 4043],[4022, 4030, 4033, 4042, 4043],[4022, 4032, 4033, 4040, 4043],[4023, 4030, 4033, 4041, 4043],[4023, 4031, 4033, 4040, 4043],[4013, 4033, 4040, 4041, 4043],[4020, 4031, 4033, 4042, 4043],[4020, 4032, 4033, 4041, 4043],[4021, 4030, 4033, 4042, 4043],[4021, 4032, 4033, 4040, 4043],[4022, 4030, 4033, 4041, 4043],[4022, 4031, 4033, 4040, 4043],[4023, 4030, 4033, 4040, 4043],[4030, 4031, 4032, 4033, 4043],[4003, 4040, 4041, 4042, 4043],[4020, 4030, 4033, 4042, 4043],[4020, 4031, 4033, 4041, 4043],[4020, 4032, 4033, 4040, 4043],[4021, 4030, 4033, 4041, 4043],[4021, 4031, 4033, 4040, 4043],[4022, 4030, 4033, 4040, 4043],[4030, 4031, 4032, 4033, 4042],[4002, 4040, 4041, 4042, 4043],[4020, 4030, 4033, 4041, 4043],[4020, 4031, 4033, 4040, 4043],[4021, 4030, 4033, 4040, 4043],[4030, 4031, 4032, 4033, 4041],[4001, 4040, 4041, 4042, 4043],[4030, 4031, 4032, 4033, 4040],[4000, 4040, 4041, 4042, 4043],[4013, 4032, 4033, 4042, 4043],[4012, 4032, 4033, 4042, 4043],[4013, 4032, 4033, 4041, 4043],[4023, 4031, 4032, 4033, 4043],[4011, 4032, 4033, 4042, 4043],[4012, 4032, 4033, 4041, 4043],[4013, 4030, 4033, 4042, 4043],[4013, 4032, 4033, 4040, 4043],[4023, 4030, 4032, 4033, 4043],[4003, 4033, 4040, 4042, 4043],[4013, 4023, 4040, 4042, 4043],[4010, 4032, 4033, 4042, 4043],[4011, 4032, 4033, 4041, 4043],[4012, 4030, 4033, 4042, 4043],[4012, 4032, 4033, 4040, 4043],[4013, 4030, 4033, 4041, 4043],[4013, 4031, 4033, 4040, 4043],[4023, 4030, 4031, 4033, 4043],[4003, 4033, 4040, 4041, 4043],[4013, 4023, 4040, 4041, 4043],[4010, 4031, 4033, 4042, 4043],[4010, 4032, 4033, 4041, 4043],[4011, 4030, 4033, 4042, 4043],[4011, 4032, 4033, 4040, 4043],[4012, 4030, 4033, 4041, 4043],[4012, 4031, 4033, 4040, 4043],[4013, 4030, 4033, 4040, 4043],[4010, 4030, 4033, 4042, 4043],[4010, 4031, 4033, 4041, 4043],[4010, 4032, 4033, 4040, 4043],[4011, 4030, 4033, 4041, 4043],[4011, 4031, 4033, 4040, 4043],[4012, 4030, 4033, 4040, 4043],[4010, 4030, 4033, 4041, 4043],[4010, 4031, 4033, 4040, 4043],[4011, 4030, 4033, 4040, 4043],[4003, 4032, 4033, 4042, 4043],[4002, 4032, 4033, 4042, 4043],[4003, 4032, 4033, 4041, 4043],[4013, 4031, 4032, 4033, 4043],[4001, 4032, 4033, 4042, 4043],[4002, 4032, 4033, 4041, 4043],[4003, 4030, 4033, 4042, 4043],[4003, 4032, 4033, 4040, 4043],[4013, 4030, 4032, 4033, 4043],[4003, 4023, 4040, 4042, 4043],[4000, 4032, 4033, 4042, 4043],[4001, 4032, 4033, 4041, 4043],[4002, 4030, 4033, 4042, 4043],[4002, 4032, 4033, 4040, 4043],[4003, 4030, 4033, 4041, 4043],[4003, 4031, 4033, 4040, 4043],[4020, 4022, 4023, 4042, 4043],[4013, 4030, 4031, 4033, 4043],[4003, 4023, 4040, 4041, 4043],[4000, 4031, 4033, 4042, 4043],[4000, 4032, 4033, 4041, 4043],[4001, 4030, 4033, 4042, 4043],[4001, 4032, 4033, 4040, 4043],[4002, 4030, 4033, 4041, 4043],[4002, 4031, 4033, 4040, 4043],[4003, 4030, 4033, 4040, 4043],[4021, 4022, 4023, 4040, 4043],[4020, 4022, 4023, 4041, 4043],[4020, 4021, 4023, 4042, 4043],[4023, 4030, 4031, 4032, 4033],[4000, 4030, 4033, 4042, 4043],[4000, 4031, 4033, 4041, 4043],[4000, 4032, 4033, 4040, 4043],[4001, 4030, 4033, 4041, 4043],[4001, 4031, 4033, 4040, 4043],[4002, 4030, 4033, 4040, 4043],[4020, 4022, 4023, 4040, 4043],[4020, 4021, 4023, 4041, 4043],[4022, 4030, 4031, 4032, 4033],[4000, 4030, 4033, 4041, 4043],[4000, 4031, 4033, 4040, 4043],[4001, 4030, 4033, 4040, 4043],[4020, 4021, 4023, 4040, 4043],[4021, 4030, 4031, 4032, 4033],[4020, 4030, 4031, 4032, 4033],[4003, 4031, 4032, 4033, 4043],[4020, 4022, 4023, 4033, 4043],[4003, 4030, 4032, 4033, 4043],[4003, 4013, 4040, 4042, 4043],[4020, 4021, 4023, 4033, 4043],[4003, 4030, 4031, 4033, 4043],[4003, 4013, 4040, 4041, 4043],[4013, 4030, 4031, 4032, 4033],[4012, 4030, 4031, 4032, 4033],[4011, 4030, 4031, 4032, 4033],[4010, 4030, 4031, 4032, 4033],[4013, 4023, 4031, 4032, 4033],[4013, 4023, 4030, 4032, 4033],[4020, 4022, 4023, 4032, 4033],[4013, 4023, 4030, 4031, 4033],[4021, 4022, 4023, 4030, 4033],[4020, 4022, 4023, 4031, 4033],[4020, 4021, 4023, 4032, 4033],[4020, 4021, 4022, 4023, 4043],[4003, 4030, 4031, 4032, 4033],[4020, 4022, 4023, 4030, 4033],[4020, 4021, 4023, 4031, 4033],[4020, 4021, 4022, 4023, 4042],[4002, 4030, 4031, 4032, 4033],[4020, 4021, 4023, 4030, 4033],[4020, 4021, 4022, 4023, 4041],[4001, 4030, 4031, 4032, 4033],[4020, 4021, 4022, 4023, 4040],[4000, 4030, 4031, 4032, 4033],[4003, 4023, 4031, 4032, 4033],[4013, 4020, 4022, 4023, 4043],[4003, 4023, 4030, 4032, 4033],[4010, 4012, 4013, 4042, 4043],[4013, 4020, 4021, 4023, 4043],[4003, 4023, 4030, 4031, 4033],[4011, 4012, 4013, 4040, 4043],[4010, 4012, 4013, 4041, 4043],[4010, 4011, 4013, 4042, 4043],[4020, 4021, 4022, 4023, 4033],[4010, 4012, 4013, 4040, 4043],[4010, 4011, 4013, 4041, 4043],[4020, 4021, 4022, 4023, 4032],[4010, 4011, 4013, 4040, 4043],[4020, 4021, 4022, 4023, 4031],[4020, 4021, 4022, 4023, 4030],[4003, 4013, 4031, 4032, 4033],[4010, 4012, 4013, 4033, 4043],[4003, 4020, 4022, 4023, 4043],[4013, 4020, 4022, 4023, 4033],[4003, 4013, 4030, 4032, 4033],[4010, 4011, 4013, 4033, 4043],[4003, 4020, 4021, 4023, 4043],[4013, 4020, 4021, 4023, 4033],[4003, 4013, 4030, 4031, 4033],[4010, 4012, 4013, 4023, 4043],[4003, 4020, 4022, 4023, 4033],[4010, 4012, 4013, 4032, 4033],[4010, 4011, 4013, 4023, 4043],[4003, 4020, 4021, 4023, 4033],[4011, 4012, 4013, 4030, 4033],[4010, 4012, 4013, 4031, 4033],[4010, 4011, 4013, 4032, 4033],[4013, 4020, 4021, 4022, 4023],[4010, 4012, 4013, 4030, 4033],[4010, 4011, 4013, 4031, 4033],[4012, 4020, 4021, 4022, 4023],[4010, 4011, 4013, 4030, 4033],[4011, 4020, 4021, 4022, 4023],[4010, 4020, 4021, 4022, 4023],[4010, 4012, 4013, 4023, 4033],[4000, 4002, 4003, 4042, 4043],[4010, 4011, 4013, 4023, 4033],[4001, 4002, 4003, 4040, 4043],[4000, 4002, 4003, 4041, 4043],[4000, 4001, 4003, 4042, 4043],[4010, 4011, 4012, 4013, 4043],[4003, 4020, 4021, 4022, 4023],[4000, 4002, 4003, 4040, 4043],[4000, 4001, 4003, 4041, 4043],[4010, 4011, 4012, 4013, 4042],[4002, 4020, 4021, 4022, 4023],[4000, 4001, 4003, 4040, 4043],[4010, 4011, 4012, 4013, 4041],[4001, 4020, 4021, 4022, 4023],[4010, 4011, 4012, 4013, 4040],[4000, 4020, 4021, 4022, 4023],[4001, 4002, 4003, 4033, 4043],[4000, 4002, 4003, 4033, 4043],[4003, 4010, 4012, 4013, 4043],[4003, 4013, 4020, 4022, 4023],[4000, 4001, 4003, 4033, 4043],[4003, 4010, 4011, 4013, 4043],[4003, 4013, 4020, 4021, 4023],[4010, 4011, 4012, 4013, 4033],[4010, 4011, 4012, 4013, 4032],[4010, 4011, 4012, 4013, 4031],[4010, 4011, 4012, 4013, 4030],[4001, 4002, 4003, 4023, 4043],[4000, 4002, 4003, 4023, 4043],[4003, 4010, 4012, 4013, 4033],[4000, 4002, 4003, 4032, 4033],[4000, 4001, 4003, 4023, 4043],[4003, 4010, 4011, 4013, 4033],[4001, 4002, 4003, 4030, 4033],[4000, 4002, 4003, 4031, 4033],[4000, 4001, 4003, 4032, 4033],[4010, 4011, 4012, 4013, 4023],[4000, 4002, 4003, 4030, 4033],[4000, 4001, 4003, 4031, 4033],[4010, 4011, 4012, 4013, 4022],[4000, 4001, 4003, 4030, 4033],[4010, 4011, 4012, 4013, 4021],[4010, 4011, 4012, 4013, 4020],[4001, 4002, 4003, 4013, 4043],[4001, 4002, 4003, 4023, 4033],[4000, 4002, 4003, 4013, 4043],[4000, 4002, 4003, 4023, 4033],[4003, 4010, 4012, 4013, 4023],[4000, 4001, 4003, 4013, 4043],[4000, 4001, 4003, 4023, 4033],[4003, 4010, 4011, 4013, 4023],[4001, 4002, 4003, 4013, 4033],[4000, 4002, 4003, 4013, 4033],[4000, 4001, 4003, 4013, 4033],[4000, 4001, 4002, 4003, 4043],[4003, 4010, 4011, 4012, 4013],[4000, 4001, 4002, 4003, 4042],[4002, 4010, 4011, 4012, 4013],[4000, 4001, 4002, 4003, 4041],[4001, 4010, 4011, 4012, 4013],[4000, 4001, 4002, 4003, 4040],[4000, 4010, 4011, 4012, 4013],[4001, 4002, 4003, 4013, 4023],[4000, 4002, 4003, 4013, 4023],[4000, 4001, 4003, 4013, 4023],[4000, 4001, 4002, 4003, 4033],[4000, 4001, 4002, 4003, 4032],[4000, 4001, 4002, 4003, 4031],[4000, 4001, 4002, 4003, 4030],[4000, 4001, 4002, 4003, 4023],[4000, 4001, 4002, 4003, 4022],[4000, 4001, 4002, 4003, 4021],[4000, 4001, 4002, 4003, 4020],[4000, 4001, 4002, 4003, 4013],[4000, 4001, 4002, 4003, 4012],[4000, 4001, 4002, 4003, 4011],[4000, 4001, 4002, 4003, 4010],].filter((p) => p.includes(this.mandatoryId));const bestPack = {pack: packs[0],winRate: 0,countBattle: 0,id: 0,};for (const id in packs) {const pack = packs[id];const attackers = this.maxUpgrade.filter((e) => pack.includes(e.id)).reduce((obj, e) => ({ ...obj, [e.id]: e }), {});const battle = {attackers,defenders: [enemieHeroes],type: 'brawl_titan',};const isRandom = this.isRandomBattle(battle);const stat = {count: 0,win: 0,winRate: 0,};for (let i = 1; i <= 20; i++) {battle.seed = Math.floor(Date.now() / 1000) + Math.random() * 1000;const r###lt = await Calc(battle);stat.win += r###lt.r###lt.win;stat.count += 1;stat.winRate = stat.win / stat.count;if (!isRandom || (i >= 2 && stat.winRate < 0.65) || (i >= 10 && stat.winRate == 1)) {break;}}if (!isRandom && stat.win) {return {favor: {},heroes: pack,};}if (stat.winRate > 0.85) {return {favor: {},heroes: pack,};}if (stat.winRate > bestPack.winRate) {bestPack.countBattle = stat.count;bestPack.winRate = stat.winRate;bestPack.pack = pack;bestPack.id = id;}}//console.log(bestPack.id, bestPack.pack, bestPack.winRate, bestPack.countBattle);return {favor: {},heroes: bestPack.pack,};}isRandomPack(pack) {const ids = Object.keys(pack);return ids.includes('4023') || ids.includes('4021');}isRandomBattle(battle) {return this.isRandomPack(battle.attackers) || this.isRandomPack(battle.defenders[0]);}async updateHeroesPack(enemieHeroes) {const packs = [{id:1,args:{userId:-830021,heroes:[63,13,9,48,1],pet:6006,favor:{1:6004,9:6005,13:6002,48:6e3,63:6009}},attackers:{1:{id:1,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{2:130,3:130,4:130,5:130,6022:130,8268:1,8269:1},power:198058,star:6,runes:[43750,43750,43750,43750,43750],skins:{1:60,54:60,95:60,154:60,250:60,325:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6004,type:"hero",perks:[4,1],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,9,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,9,10]},agility:3093,hp:419649,intelligence:3644,physicalAttack:11481.6,strength:17049,armor:12720,dodge:17232.28,magicPenetration:22780,magicPower:55816,magicResist:1580,modifiedSkillTier:5,skin:0,favorPetId:6004,favorPower:11064},9:{id:9,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{335:130,336:130,337:130,338:130,6027:130,8270:1,8271:1},power:195886,star:6,runes:[43750,43750,43750,43750,43750],skins:{9:60,41:60,163:60,189:60,311:60,338:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6005,type:"hero",perks:[7,2,20],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,9,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,9,10]},agility:3068,hp:227134,intelligence:19003,physicalAttack:7020.32,strength:3068,armor:19995,dodge:14644,magicPower:64780.6,magicResist:31597,modifiedSkillTier:5,skin:0,favorPetId:6005,favorPower:11064},13:{id:"13",xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{452:130,453:130,454:130,455:130,6012:130,8274:1,8275:1},power:194833,star:6,runes:[43750,43750,43750,43750,43750],skins:{13:60,38:60,148:60,199:60,240:60,335:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6002,type:"hero",perks:[7,2,21],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,9,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,9,10]},agility:2885,hp:344763,intelligence:17625,physicalAttack:50,strength:3020,armor:19060,magicPenetration:58138.6,magicPower:70100.6,magicResist:27227,modifiedSkillTier:4,skin:0,favorPetId:6002,favorPower:11064},48:{id:48,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{240:130,241:130,242:130,243:130,6002:130},power:190584,star:6,runes:[43750,43750,43750,43750,43750],skins:{103:60,165:60,217:60,296:60,326:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6e3,type:"hero",perks:[5,2],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,10]},agility:17308,hp:397737,intelligence:2888,physicalAttack:40298.32,physicalCritChance:12280,strength:3169,armor:12185,armorPenetration:20137.6,magicResist:24816,skin:0,favorPetId:6e3,favorPower:11064},63:{id:63,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{442:130,443:130,444:130,445:130,6041:130,8272:1,8273:1},power:193520,star:6,runes:[43750,43750,43750,43750,43750],skins:{341:60,350:60,351:60,352:1},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6009,type:"hero",perks:[6,1,21],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,9,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,9,10]},agility:17931,hp:488832,intelligence:2737,physicalAttack:54213.6,strength:2877,armor:800,armorPenetration:32477.6,magicResist:8526,physicalCritChance:9545,modifiedSkillTier:3,skin:0,favorPetId:6009,favorPower:11064},6006:{id:6006,color:10,star:6,xp:450551,level:130,slots:[25,50,50,25,50,50],skills:{6030:130,6031:130},power:181943,type:"pet",perks:[5,9],name:null,intelligence:11064,magicPenetration:47911,strength:12360}}},{id:2,args:{userId:-830049,heroes:[46,13,52,49,4],pet:6006,favor:{4:6001,13:6002,46:6006,49:6004,52:6003}},attackers:{4:{id:4,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{255:130,256:130,257:130,258:130,6007:130},power:189782,star:6,runes:[43750,43750,43750,43750,43750],skins:{4:60,35:60,92:60,161:60,236:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6001,type:"hero",perks:[4,5,2,22],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,10]},agility:3065,hp:482631,intelligence:3402,physicalAttack:2800,strength:17488,armor:56262.6,magicPower:51021,magicResist:36971,skin:0,favorPetId:6001,favorPower:11064},13:{id:"13",xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{452:130,453:130,454:130,455:130,6012:130,8274:1,8275:1},power:194833,star:6,runes:[43750,43750,43750,43750,43750],skins:{13:60,38:60,148:60,199:60,240:60,335:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6002,type:"hero",perks:[7,2,21],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,9,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,9,10]},agility:2885,hp:344763,intelligence:17625,physicalAttack:50,strength:3020,armor:19060,magicPenetration:58138.6,magicPower:70100.6,magicResist:27227,modifiedSkillTier:4,skin:0,favorPetId:6002,favorPower:11064},46:{id:46,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{230:130,231:130,232:130,233:130,6032:130},power:189653,star:6,runes:[43750,43750,43750,43750,43750],skins:{101:60,159:60,178:60,262:60,315:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6006,type:"hero",perks:[9,5,1,22],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,10]},agility:2122,hp:637517,intelligence:16208,physicalAttack:50,strength:5151,armor:38507.6,magicPower:74495.6,magicResist:22237,skin:0,favorPetId:6006,favorPower:11064},49:{id:49,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{245:130,246:130,247:130,248:130,6022:130},power:193163,star:6,runes:[43750,43750,43750,43750,43750],skins:{104:60,191:60,252:60,305:60,329:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6004,type:"hero",perks:[10,1,22],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,10]},agility:17935,hp:250405,intelligence:2790,physicalAttack:40413.6,strength:2987,armor:11655,dodge:14844.28,magicResist:3175,physicalCritChance:14135,skin:0,favorPetId:6004,favorPower:11064},52:{id:52,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{310:130,311:130,312:130,313:130,6017:130},power:185075,star:6,runes:[43750,43750,43750,43750,43750],skins:{188:60,213:60,248:60,297:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6003,type:"hero",perks:[5,8,2,13,15,22],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,10]},agility:18270,hp:226207,intelligence:2620,physicalAttack:44206,strength:3260,armor:13150,armorPenetration:40301,magicPower:9957.6,magicResist:33892.6,skin:0,favorPetId:6003,favorPower:11064},6006:{id:6006,color:10,star:6,xp:450551,level:130,slots:[25,50,50,25,50,50],skills:{6030:130,6031:130},power:181943,type:"pet",perks:[5,9],name:null,intelligence:11064,magicPenetration:47911,strength:12360}}},{id:3,args:{userId:8263225,heroes:[29,63,13,48,1],pet:6006,favor:{1:6004,13:6002,29:6006,48:6e3,63:6003}},attackers:{1:{id:1,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{2:130,3:130,4:130,5:130,6022:130,8268:1,8269:1},power:198058,star:6,runes:[43750,43750,43750,43750,43750],skins:{1:60,54:60,95:60,154:60,250:60,325:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6004,type:"hero",perks:[4,1],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,9,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,9,10]},agility:3093,hp:419649,intelligence:3644,physicalAttack:11481.6,strength:17049,armor:12720,dodge:17232.28,magicPenetration:22780,magicPower:55816,magicResist:1580,modifiedSkillTier:5,skin:0,favorPetId:6004,favorPower:11064},13:{id:"13",xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{452:130,453:130,454:130,455:130,6012:130,8274:1,8275:1},power:194833,star:6,runes:[43750,43750,43750,43750,43750],skins:{13:60,38:60,148:60,199:60,240:60,335:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6002,type:"hero",perks:[7,2,21],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,9,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,9,10]},agility:2885,hp:344763,intelligence:17625,physicalAttack:50,strength:3020,armor:19060,magicPenetration:58138.6,magicPower:70100.6,magicResist:27227,modifiedSkillTier:4,skin:0,favorPetId:6002,favorPower:11064},29:{id:29,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{145:130,146:130,147:130,148:130,6032:130},power:189790,star:6,runes:[43750,43750,43750,43750,43750],skins:{29:60,72:60,88:60,147:60,242:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6006,type:"hero",perks:[9,5,2,22],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,10]},agility:2885,hp:491431,intelligence:18331,physicalAttack:106,strength:3020,armor:37716.6,magicPower:76792.6,magicResist:31377,skin:0,favorPetId:6006,favorPower:11064},48:{id:48,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{240:130,241:130,242:130,243:130,6002:130},power:190584,star:6,runes:[43750,43750,43750,43750,43750],skins:{103:60,165:60,217:60,296:60,326:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6e3,type:"hero",perks:[5,2],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,10]},agility:17308,hp:397737,intelligence:2888,physicalAttack:40298.32,physicalCritChance:12280,strength:3169,armor:12185,armorPenetration:20137.6,magicResist:24816,skin:0,favorPetId:6e3,favorPower:11064},63:{id:63,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{442:130,443:130,444:130,445:130,6017:130,8272:1,8273:1},power:191031,star:6,runes:[43750,43750,43750,43750,43750],skins:{341:60,350:60,351:60,352:1},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6003,type:"hero",perks:[6,1,21],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,9,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,9,10]},agility:17931,hp:488832,intelligence:2737,physicalAttack:44256,strength:2877,armor:800,armorPenetration:22520,magicPower:9957.6,magicResist:18483.6,physicalCritChance:9545,modifiedSkillTier:3,skin:0,favorPetId:6003,favorPower:11064},6006:{id:6006,color:10,star:6,xp:450551,level:130,slots:[25,50,50,25,50,50],skills:{6030:130,6031:130},power:181943,type:"pet",perks:[5,9],name:null,intelligence:11064,magicPenetration:47911,strength:12360}}},{id:4,args:{userId:8263247,heroes:[55,13,40,51,1],pet:6006,favor:{1:6007,13:6002,40:6004,51:6006,55:6001}},attackers:{1:{id:1,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{2:130,3:130,4:130,5:130,6035:130,8268:1,8269:1},power:195170,star:6,runes:[43750,43750,43750,43750,43750],skins:{1:60,54:60,95:60,154:60,250:60,325:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6007,type:"hero",perks:[4,1],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,9,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,9,10]},agility:3093,hp:419649,intelligence:3644,physicalAttack:1524,strength:17049,armor:22677.6,dodge:14245,magicPenetration:22780,magicPower:65773.6,magicResist:1580,modifiedSkillTier:5,skin:0,favorPetId:6007,favorPower:11064},13:{id:"13",xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{452:130,453:130,454:130,455:130,6012:130,8274:1,8275:1},power:194833,star:6,runes:[43750,43750,43750,43750,43750],skins:{13:60,38:60,148:60,199:60,240:60,335:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6002,type:"hero",perks:[7,2,21],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,9,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,9,10]},agility:2885,hp:344763,intelligence:17625,physicalAttack:50,strength:3020,armor:19060,magicPenetration:58138.6,magicPower:70100.6,magicResist:27227,modifiedSkillTier:4,skin:0,favorPetId:6002,favorPower:11064},40:{id:40,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{200:130,201:130,202:130,203:130,6022:130,8244:1,8245:1},power:192541,star:6,runes:[43750,43750,43750,43750,43750],skins:{53:60,89:60,129:60,168:60,314:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6004,type:"hero",perks:[5,9,1],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,9,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,9,10]},agility:17540,hp:343191,intelligence:2805,physicalAttack:48430.6,strength:2976,armor:24410,dodge:15732.28,magicResist:17633,modifiedSkillTier:3,skin:0,favorPetId:6004,favorPower:11064},51:{id:51,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{305:130,306:130,307:130,308:130,6032:130},power:190005,star:6,runes:[43750,43750,43750,43750,43750],skins:{181:60,219:60,260:60,290:60,334:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6006,type:"hero",perks:[5,9,1,12],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,10]},agility:2526,hp:438205,intelligence:18851,physicalAttack:50,strength:2921,armor:39442.6,magicPower:88978.6,magicResist:22960,skin:0,favorPetId:6006,favorPower:11064},55:{id:55,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{325:130,326:130,327:130,328:130,6007:130},power:190529,star:6,runes:[43750,43750,43750,43750,43750],skins:{239:60,278:60,309:60,327:60,346:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6001,type:"hero",perks:[7,1],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,10]},agility:2631,hp:499591,intelligence:19438,physicalAttack:50,strength:3286,armor:32892.6,armorPenetration:36870,magicPower:60704,magicResist:10010,skin:0,favorPetId:6001,favorPower:11064},6006:{id:6006,color:10,star:6,xp:450551,level:130,slots:[25,50,50,25,50,50],skills:{6030:130,6031:130},power:181943,type:"pet",perks:[5,9],name:null,intelligence:11064,magicPenetration:47911,strength:12360}}},{id:5,args:{userId:8263303,heroes:[31,29,13,40,1],pet:6004,favor:{1:6001,13:6007,29:6002,31:6006,40:6004}},attackers:{1:{id:1,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{2:130,3:130,4:130,5:130,6007:130,8268:1,8269:1},power:195170,star:6,runes:[43750,43750,43750,43750,43750],skins:{1:60,54:60,95:60,154:60,250:60,325:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6001,type:"hero",perks:[4,1],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,9,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,9,10]},agility:3093,hp:519225,intelligence:3644,physicalAttack:1524,strength:17049,armor:22677.6,dodge:14245,magicPenetration:22780,magicPower:55816,magicResist:1580,modifiedSkillTier:5,skin:0,favorPetId:6001,favorPower:11064},13:{id:"13",xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{452:130,453:130,454:130,455:130,6035:130,8274:1,8275:1},power:194833,star:6,runes:[43750,43750,43750,43750,43750],skins:{13:60,38:60,148:60,199:60,240:60,335:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6007,type:"hero",perks:[7,2,21],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,9,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,9,10]},agility:2885,hp:344763,intelligence:17625,physicalAttack:50,strength:3020,armor:29017.6,magicPenetration:48181,magicPower:70100.6,magicResist:27227,modifiedSkillTier:4,skin:0,favorPetId:6007,favorPower:11064},29:{id:29,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{145:130,146:130,147:130,148:130,6012:130},power:189790,star:6,runes:[43750,43750,43750,43750,43750],skins:{29:60,72:60,88:60,147:60,242:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6002,type:"hero",perks:[9,5,2,22],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,10]},agility:2885,hp:491431,intelligence:18331,physicalAttack:106,strength:3020,armor:27759,magicPenetration:9957.6,magicPower:76792.6,magicResist:31377,skin:0,favorPetId:6002,favorPower:11064},31:{id:31,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{155:130,156:130,157:130,158:130,6032:130},power:190305,star:6,runes:[43750,43750,43750,43750,43750],skins:{44:60,94:60,133:60,200:60,295:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6006,type:"hero",perks:[9,5,2,20],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,10]},agility:2781,dodge:12620,hp:374484,intelligence:18945,physicalAttack:78,strength:2916,armor:28049.6,magicPower:67686.6,magicResist:15252,skin:0,favorPetId:6006,favorPower:11064},40:{id:40,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{200:130,201:130,202:130,203:130,6022:130,8244:1,8245:1},power:192541,star:6,runes:[43750,43750,43750,43750,43750],skins:{53:60,89:60,129:60,168:60,314:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6004,type:"hero",perks:[5,9,1],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,9,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,9,10]},agility:17540,hp:343191,intelligence:2805,physicalAttack:48430.6,strength:2976,armor:24410,dodge:15732.28,magicResist:17633,modifiedSkillTier:3,skin:0,favorPetId:6004,favorPower:11064},6004:{id:6004,color:10,star:6,xp:450551,level:130,slots:[25,50,50,25,50,50],skills:{6020:130,6021:130},power:181943,type:"pet",perks:[5],name:null,armorPenetration:47911,intelligence:11064,strength:12360}}},{id:6,args:{userId:8263317,heroes:[62,13,9,56,61],pet:6003,favor:{9:6004,13:6002,56:6006,61:6001,62:6003}},attackers:{9:{id:9,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{335:130,336:130,337:130,338:130,6022:130,8270:1,8271:1},power:198525,star:6,runes:[43750,43750,43750,43750,43750],skins:{9:60,41:60,163:60,189:60,311:60,338:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6004,type:"hero",perks:[7,2,20],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,9,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,9,10]},agility:3068,hp:227134,intelligence:19003,physicalAttack:10007.6,strength:3068,armor:19995,dodge:17631.28,magicPower:54823,magicResist:31597,modifiedSkillTier:5,skin:0,favorPetId:6004,favorPower:11064},13:{id:"13",xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{452:130,453:130,454:130,455:130,6012:130,8274:1,8275:1},power:194833,star:6,runes:[43750,43750,43750,43750,43750],skins:{13:60,38:60,148:60,199:60,240:60,335:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6002,type:"hero",perks:[7,2,21],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,9,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,9,10]},agility:2885,hp:344763,intelligence:17625,physicalAttack:50,strength:3020,armor:19060,magicPenetration:58138.6,magicPower:70100.6,magicResist:27227,modifiedSkillTier:4,skin:0,favorPetId:6002,favorPower:11064},56:{id:56,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{376:130,377:130,378:130,379:130,6032:130},power:184420,star:6,runes:[43750,43750,43750,43750,43750],skins:{264:60,279:60,294:60,321:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6006,type:"hero",perks:[5,7,1,21],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,10]},agility:2791,hp:235111,intelligence:18813,physicalAttack:50,strength:2656,armor:22982.6,magicPenetration:48159,magicPower:75598.6,magicResist:13990,skin:0,favorPetId:6006,favorPower:11064},61:{id:61,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{411:130,412:130,413:130,414:130,6007:130},power:184868,star:6,runes:[43750,43750,43750,43750,43750],skins:{302:60,306:60,323:60,340:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6001,type:"hero",perks:[4,2,22],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,10]},agility:2545,hp:466176,intelligence:3320,physicalAttack:34305,strength:18309,armor:31077.6,magicResist:24101,physicalCritChance:9009,skin:0,favorPetId:6001,favorPower:11064},62:{id:62,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{437:130,438:130,439:130,440:130,6017:130},power:173991,star:6,runes:[43750,43750,43750,43750,43750],skins:{320:60,343:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6003,type:"hero",perks:[8,7,2,22],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,10]},agility:2530,hp:276010,intelligence:19245,physicalAttack:50,strength:3543,armor:12890,magicPenetration:23658,magicPower:80966.6,magicResist:12447.6,skin:0,favorPetId:6003,favorPower:11064},6003:{id:6003,color:10,star:6,xp:450551,level:130,slots:[25,50,50,25,50,50],skills:{6015:130,6016:130},power:181943,type:"pet",perks:[8],name:null,intelligence:11064,magicPenetration:47911,strength:12360}}},{id:7,args:{userId:8263335,heroes:[32,29,13,43,1],pet:6006,favor:{1:6004,13:6008,29:6006,32:6002,43:6007}},attackers:{1:{id:1,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{2:130,3:130,4:130,5:130,6022:130,8268:1,8269:1},power:198058,star:6,runes:[43750,43750,43750,43750,43750],skins:{1:60,54:60,95:60,154:60,250:60,325:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6004,type:"hero",perks:[4,1],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,9,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,9,10]},agility:3093,hp:419649,intelligence:3644,physicalAttack:11481.6,strength:17049,armor:12720,dodge:17232.28,magicPenetration:22780,magicPower:55816,magicResist:1580,modifiedSkillTier:5,skin:0,favorPetId:6004,favorPower:11064},13:{id:"13",xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{452:130,453:130,454:130,455:130,6038:130,8274:1,8275:1},power:194833,star:6,runes:[43750,43750,43750,43750,43750],skins:{13:60,38:60,148:60,199:60,240:60,335:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6008,type:"hero",perks:[7,2,21],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,9,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,9,10]},agility:2885,hp:344763,intelligence:17625,physicalAttack:50,strength:3020,armor:29017.6,magicPenetration:48181,magicPower:70100.6,magicResist:27227,modifiedSkillTier:4,skin:0,favorPetId:6008,favorPower:11064},29:{id:29,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{145:130,146:130,147:130,148:130,6032:130},power:189790,star:6,runes:[43750,43750,43750,43750,43750],skins:{29:60,72:60,88:60,147:60,242:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6006,type:"hero",perks:[9,5,2,22],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,10]},agility:2885,hp:491431,intelligence:18331,physicalAttack:106,strength:3020,armor:37716.6,magicPower:76792.6,magicResist:31377,skin:0,favorPetId:6006,favorPower:11064},32:{id:32,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{160:130,161:130,162:130,163:130,6012:130},power:189956,star:6,runes:[43750,43750,43750,43750,43750],skins:{45:60,73:60,81:60,135:60,212:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6002,type:"hero",perks:[7,5,2,22],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,10]},agility:2815,hp:551066,intelligence:18800,physicalAttack:50,strength:2810,armor:19040,magicPenetration:9957.6,magicPower:89495.6,magicResist:20805,skin:0,favorPetId:6002,favorPower:11064},43:{id:43,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{215:130,216:130,217:130,218:130,6035:130},power:189593,star:6,runes:[43750,43750,43750,43750,43750],skins:{98:60,130:60,169:60,201:60,304:60},currentSkin:0,titanGiftLevel:30,titanCoinsSpent:null,artifacts:[{level:130,star:6},{level:130,star:6},{level:130,star:6}],scale:1,petId:6007,type:"hero",perks:[7,9,1,21],ascensions:{1:[0,1,2,3,4,5,6,7,8,9],2:[0,1,2,3,4,5,6,7,8,10],3:[0,1,2,3,4,5,6,7,8,9],4:[0,1,2,3,4,5,6,7,8,9],5:[0,1,2,3,4,5,6,7,8,10]},agility:2447,hp:265217,intelligence:18758,physicalAttack:50,strength:2842,armor:18637.6,magicPenetration:52439,magicPower:75465.6,magicResist:22695,skin:0,favorPetId:6007,favorPower:11064},6006:{id:6006,color:10,star:6,xp:450551,level:130,slots:[25,50,50,25,50,50],skills:{6030:130,6031:130},power:181943,type:"pet",perks:[5,9],name:null,intelligence:11064,magicPenetration:47911,strength:12360}}}];const bestPack = {pack: packs[0],countWin: 0,}for (const pack of packs) {const attackers = pack.attackers;const battle = {attackers,defenders: [enemieHeroes],type: 'brawl',};let countWinBattles = 0;let countTestBattle = 10;for (let i = 0; i < countTestBattle; i++) {battle.seed = Math.floor(Date.now() / 1000) + Math.random() * 1000;const r###lt = await Calc(battle);if (r###lt.r###lt.win) {countWinBattles++;}if (countWinBattles > 7) {console.log(pack)return pack.args;}}if (countWinBattles > bestPack.countWin) {bestPack.countWin = countWinBattles;bestPack.pack = pack.args;}}console.log(bestPack);return bestPack.pack;}async questFarm() {const calls = [this.callBrawlQuestFarm];const r###lt = await Send(JSON.stringify({ calls }));return r###lt.r###lts[0].r###lt.response;}async getBrawlInfo() {const data = await Send(JSON.stringify({calls: [this.callUserGetInfo,this.callBrawlQuestGetInfo,this.callBrawlFindEnemies,this.callTeamGetMaxUpgrade,this.callBrawlGetInfo,]}));let attempts = data.r###lts[0].r###lt.response.refillable.find(n => n.id == 48);const maxUpgrade = data.r###lts[3].r###lt.response;const maxHero = Object.values(maxUpgrade.hero);const maxTitan = Object.values(maxUpgrade.titan);const maxPet = Object.values(maxUpgrade.pet);this.maxUpgrade = [...maxHero, ...maxPet, ...maxTitan];this.info = data.r###lts[4].r###lt.response;this.mandatoryId = lib.data.brawl.promoHero[this.info.id].promoHero;return {attempts: attempts.amount,questInfo: data.r###lts[1].r###lt.response,findEnemies: data.r###lts[2].r###lt.response,}}/*** Carrying out a fight** Проведение боя*/async battle(userId) {this.stats.count++;const battle = await this.startBattle(userId, this.args);const r###lt = await Calc(battle);console.log(r###lt.r###lt);if (r###lt.r###lt.win) {this.stats.win++;} else {this.stats.loss++;if (!this.info.boughtEndlessLivesToday) {this.attempts--;}}return await this.endBattle(r###lt);// return await this.cancelBattle(r###lt);}/*** Starts a fight** Начинает бой*/async startBattle(userId, args) {const call = {name: "brawl_startBattle",args,ident: "brawl_startBattle"}call.args.userId = userId;const calls = [call];const r###lt = await Send(JSON.stringify({ calls }));return r###lt.r###lts[0].r###lt.response;}cancelBattle(battle) {const fixBattle = function (heroes) {for (const ids in heroes) {const hero = heroes[ids];hero.energy = random(1, 999);if (hero.hp > 0) {hero.hp = random(1, hero.hp);}}}fixBattle(battle.progress[0].attackers.heroes);fixBattle(battle.progress[0].defenders.heroes);return this.endBattle(battle);}/*** Ends the fight** Заканчивает бой*/async endBattle(battle) {battle.progress[0].attackers.input = ['auto', 0, 0, 'auto', 0, 0];const calls = [{name: "brawl_endBattle",args: {r###lt: battle.r###lt,progress: battle.progress},ident: "brawl_endBattle"},this.callBrawlQuestGetInfo,this.callBrawlFindEnemies,];const r###lt = await Send(JSON.stringify({ calls }));return r###lt.r###lts;}end(endReason) {setIsCancalBattle(true);isBrawlsAutoStart = false;setProgress(endReason, true);console.log(endReason);this.resolve();}}this.HWHClasses.executeBrawls = executeBrawls;/*** Runs missions from the company on a specified list* Выполняет миссии из компании по списку* @param {Array} missions [{id: 25, times: 3}, {id: 45, times: 30}]* @param {Boolean} isRaids выполнять миссии рейдом* @returns*/function testCompany(missions, isRaids = false) {const { ExecuteCompany } = HWHClasses;return new Promise((resolve, reject) => {const tower = new ExecuteCompany(resolve, reject);tower.start(missions, isRaids);});}/*** Fulfilling company missions* Выполнение миссий компании*/class ExecuteCompany {constructor(resolve, reject) {this.resolve = resolve;this.reject = reject;this.missionsIds = [];this.currentNum = 0;this.isRaid = false;this.currentTimes = 0;this.argsMission = {id: 0,heroes: [],favor: {},};}async start(missionIds, isRaids) {this.missionsIds = missionIds;this.isRaid = isRaids;const data = await Caller.send(['teamGetAll', 'teamGetFavor']);this.startCompany(data);}startCompany(data) {const [teamGetAll, teamGetFavor] = data;this.argsMission.heroes = teamGetAll.mission.filter((id) => id < 6000);this.argsMission.favor = teamGetFavor.mission;const pet = teamGetAll.mission.filter((id) => id >= 6000).pop();if (pet) {this.argsMission.pet = pet;}this.checkStat();}checkStat() {if (!this.missionsIds[this.currentNum].times) {this.currentNum++;}if (this.currentNum === this.missionsIds.length) {this.endCompany('EndCompany');return;}this.argsMission.id = this.missionsIds[this.currentNum].id;this.currentTimes = this.missionsIds[this.currentNum].times;setProgress('Сompany: ' + this.argsMission.id + ' - ' + this.currentTimes, false);if (this.isRaid) {this.missionRaid();} else {this.missionStart();}}async missionRaid() {try {await Caller.send({name: 'missionRaid',args: {id: this.argsMission.id,times: this.currentTimes,},});} catch (error) {console.warn(error);}this.missionsIds[this.currentNum].times = 0;this.checkStat();}async missionStart() {this.lastMissionBattleStart = Date.now();let r###lt = null;try {r###lt = await Caller.send({name: 'missionStart',args: this.argsMission,});} catch (error) {console.warn(error);this.endCompany('missionStartError', error['error']);return;}this.missionEnd(await Calc(r###lt));}async missionEnd(r) {const timer = r.battleTimer;await countdownTimer(timer, 'Сompany: ' + this.argsMission.id + ' - ' + this.currentTimes);try {await Caller.send({name: 'missionEnd',args: {id: this.argsMission.id,r###lt: r.r###lt,progress: r.progress,},});} catch (error) {this.endCompany('missionEndError', error);return;}this.missionsIds[this.currentNum].times--;this.checkStat();}endCompany(reason, info) {setProgress('Сompany completed!', true);console.log(reason, info);this.resolve();}}this.HWHClasses.ExecuteCompany = ExecuteCompany;})();/*** TODO:* Получение всех уровней при сборе всех наград (квест на титанит и на энку) +-* Добивание на арене титанов* Закрытие окошек по Esc +-* Починить работу скрипта на уровне команды ниже 10 +-* Написать номальную синхронизацию* Запрет сбора квестов и отправки экспеиций в промежуток между локальным обновлением и глобальным обновлением дня* Улучшение боев*/