- // ==UserScript==
- // @name HeroWarsDungeon
- // @name:en HeroWarsDungeon
- // @name:ru HeroWarsDungeon
- // @namespace HeroWarsDungeon
- // @version 2.312
- // @description Automation of actions for the game Hero Wars
- // @description:en Automation of actions for the game Hero Wars
- // @description:ru Автоматизация действий для игры Хроники Хаоса
- // @author ZingerY, ApuoH, Gudwin
- // @license Copyright ZingerY
- // @icon http://ilovemycomp.narod.ru/VaultBoyIco16.ico
- // @icon64 http://ilovemycomp.narod.ru/VaultBoyIco64.png
- // @match https://www.hero-wars.com/*
- // @match https://apps-1701433570146040.apps.fbsbx.com/*
- // @run-at document-start
- // ==/UserScript==
-
- // сделал ApuoH
- (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;
- /** Пачки для тестов в чате*/ //тест сохранка
- let repleyBattle = {
- defenders: {},
- attackers: {},
- effects: {},
- state: {},
- seed: undefined
- }
- /**
- * 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;
- };
- /**
- * 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 results 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);
- }
- })
- }
- //тест остановка подземки
- let stopDung = false;
- /**
- * 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',
- BATTLE_FISHING: 'Finishing',
- BATTLE_FISHING_TITLE: 'Finishing off the team from the last replay in the chat',
- BATTLE_TRENING: 'Workout',
- BATTLE_TRENING_TITLE: 'A training battle in the chat against the team from the last replay',
- 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',
- HOW_REPEAT_CAMPAIGN: 'how many mission replays', //тест добавил
- NUMBER_OF_TEST: 'Number of test fights',
- NUMBER_OF_AUTO_BATTLE: 'Number of auto-battle attempts',
- USER_ID_TITLE: 'Enter the player ID',
- AMOUNT: 'Gift number, 1 - hero development, 2 - pets, 3 - light, 4 - darkness, 5 - ascension, 6 - appearance',
- GIFT_NUM: 'Number of gifts to be sent',
- /* Buttons */
- RUN_SCRIPT: 'Run the',
- STOP_SCRIPT: 'Stop 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',
- DUNGEON2: 'Dungeon full',
- DUNGEON_FULL_TITLE: 'Dungeon for Full Titans',
- STOP_DUNGEON: 'Stop Dungeon',
- STOP_DUNGEON_TITLE: 'Stop digging 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: 'Adventure',
- 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_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 result 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',
- SAVING: 'Saving',
- USER_ID: 'User Id',
- SEND_GIFT: 'The gift has been sent',
- EXPEDITIONS_SENT: 'Expeditions:<br>Collected: {countGet}<br>Sent: {countSend}',
- EXPEDITIONS_NOTHING: 'Nothing to collect/send',
- 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',
- COMPLETE_DUNGEON_FULL: 'Complete the dungeon for Full Titans',
- 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 result?',
- 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 adventure',
- 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',
- New_Year_Clan: 'a gift for a friend',
- New_Year_Clan_TITLE: 'New Year gifts to friends',
- 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_RESULT: '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 result',
- INVASION_BOSS_BUFF: 'For {bossLvl} boss need buff {needBuff} you have {haveBuff}}',
- },
- 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: 'Предварительный расчет боя',
- BATTLE_FISHING: 'Добивание',
- BATTLE_FISHING_TITLE: 'Добивание в чате команды из последнего реплея',
- BATTLE_TRENING: 'Тренировка',
- BATTLE_TRENING_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: 'Множитель ускорения боя',
- HOW_REPEAT_CAMPAIGN: 'Сколько повторов миссий', //тест добавил
- NUMBER_OF_TEST: 'Количество тестовых боев',
- NUMBER_OF_AUTO_BATTLE: 'Количество попыток автобоев',
- USER_ID_TITLE: 'Введите айди игрока',
- AMOUNT: 'Количество отправляемых подарков',
- GIFT_NUM: 'Номер подарка, 1 - развитие героев, 2 - питомцы, 3 - света, 4 - тьмы, 5 - вознесения, 6 - облик',
- /* Кнопки */
- RUN_SCRIPT: 'Запустить скрипт',
- STOP_SCRIPT: 'Остановить скрипт',
- TO_DO_EVERYTHING: 'Сделать все',
- TO_DO_EVERYTHING_TITLE: 'Выполнить несколько действий',
- OUTLAND: 'Запределье',
- OUTLAND_TITLE: 'Собрать Запределье',
- TITAN_ARENA: 'Турнир Стихий',
- TITAN_ARENA_TITLE: 'Автопрохождение Турнира Стихий',
- DUNGEON: 'Подземелье',
- DUNGEON_TITLE: 'Автопрохождение подземелья',
- DUNGEON2: 'Подземелье фулл',
- DUNGEON_FULL_TITLE: 'Подземелье для фуловых титанов',
- STOP_DUNGEON: 'Стоп подземка',
- STOP_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_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: 'Значения',
- SAVING: 'Сохранка',
- USER_ID: 'айди пользователя',
- SEND_GIFT: 'Подарок отправлен',
- EXPEDITIONS_SENT: 'Экспедиции:<br>Собрано: {countGet}<br>Отправлено: {countSend}',
- EXPEDITIONS_NOTHING: 'Нечего собирать/отправлять',
- 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: 'Пройти подземелье',
- COMPLETE_DUNGEON_FULL: 'Пройти подземелье фулл',
- 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: 'Собирает награды и почту',
- New_Year_Clan: 'подарок другу',
- New_Year_Clan_TITLE: 'Новогодние подарки друзьям',
- COLLECT_REWARDS_AND_MAIL: 'Собрано {countQuests} наград и {countMail} писем',
- TIMER_ALREADY: 'Таймер уже запущен {time}',
- NO_ATTEMPTS_TIMER_START: 'Попыток нет, запущен таймер {time}',
- EPIC_BRAWL_RESULT: '{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}',
- },
- };
-
- 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 result = i18nLangData[selectLang][constant];
- if (replace) {
- return result.sprintf(replace);
- }
- return result;
- }
- 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,
- },
- finishingBattle: {
- label: I18N('BATTLE_FISHING'),
- cbox: null,
- title: I18N('BATTLE_FISHING_TITLE'),
- default: false,
- },
- treningBattle: {
- label: I18N('BATTLE_TRENING'),
- cbox: null,
- title: I18N('BATTLE_TRENING_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: (() => {
- $result = false;
- try {
- $result = JSON.parse(localStorage[GM_info.script.name + ':noOfferDonat']);
- } catch (e) {
- $result = false;
- }
- return $result || 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: (() => {
- $result = false;
- try {
- $result = JSON.parse(localStorage[GM_info.script.name + ':autoBrawls']);
- } catch (e) {
- $result = false;
- }
- return $result || false;
- })(),
- hide: false,
- },
- getAnswer: {
- label: I18N('AUTO_QUIZ'),
- cbox: null,
- title: I18N('AUTO_QUIZ_TITLE'),
- default: false,
- hide: true,
- },*/
- 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,
- },
- //тест повтор компании
- countRaid: {
- input: null,
- title: I18N('HOW_REPEAT_CAMPAIGN'),
- 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,
- }*/
- }
- //сохранка тест
- const inputs2 = {
- countBattle: {
- input: null,
- title: '-1 сохраняет защиту, -2 атаку противника с Replay',
- default: 1,
- },
- needResource: {
- input: null,
- title: 'Мощь противника мин.(тыс.)/урона(млн.)',
- default: 300,
- },
- needResource2: {
- input: null,
- title: 'Мощь противника макс./тип бафа',
- default: 1500,
- },
- }
- //новогодние подарки игрокам других гильдий
- const inputs3 = {
- userID: { // айди игрока посмотреть открыв его инфо
- input: null,
- title: I18N('USER_ID_TITLE'),
- default: 111111,
- },
- GiftNum: { // номер подарка считаем слева направо от 1 до 6, под 1 это за 750 новогодних игрушек
- input: null,
- title: I18N('GIFT_NUM'),
- default: 10,
- },
- AmontID: { // количество ресурсов от 1 до бесконечности
- input: null,
- title: I18N('AMOUNT'),
- default: 1,
- },
- }
- /**
- * Checks the checkbox
- *
- * Поплучить данные поля ввода
- */
- /*function getInput(inputName) {
- return inputs[inputName]?.input?.value;
- }*/
- function getInput(inputName) {
- if (inputName in inputs){return inputs[inputName]?.input?.value;}
- else if (inputName in inputs2){return inputs2[inputName]?.input?.value;}
- //else if (inputName in inputs3){return inputs3[inputName]?.input?.value;}
- else return null
- }
-
- //тест рейд
- /** Автоповтор миссии */
- let isRepeatMission = false;
- /** Вкл/Выкл автоповтор миссии */
- this.switchRepeatMission = function() {
- isRepeatMission = !isRepeatMission;
- console.log(isRepeatMission);
- }
-
- /**
- * 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'),
- func: testDoYourBest,
- },
- /*
- doActions: {
- name: I18N('ACTIONS'),
- title: I18N('ACTIONS_TITLE'),
- func: async function () {
- const popupButtons = [
- {
- msg: I18N('OUTLAND'),
- result: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('OUTLAND')}?`, getOutland);
- },
- title: I18N('OUTLAND_TITLE'),
- },
- {
- msg: I18N('TOWER'),
- result: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('TOWER')}?`, testTower);
- },
- title: I18N('TOWER_TITLE'),
- },
- {
- msg: I18N('EXPEDITIONS'),
- result: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('EXPEDITIONS')}?`, checkExpedition);
- },
- title: I18N('EXPEDITIONS_TITLE'),
- },
- {
- msg: I18N('MINIONS'),
- result: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('MINIONS')}?`, testRaidNodes);
- },
- title: I18N('MINIONS_TITLE'),
- },
- {
- msg: I18N('ESTER_EGGS'),
- result: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('ESTER_EGGS')}?`, offerFarmAllReward);
- },
- title: I18N('ESTER_EGGS_TITLE'),
- },
- {
- msg: I18N('STORM'),
- result: function () {
- testAdventure('solo');
- },
- title: I18N('STORM_TITLE'),
- },
- {
- msg: I18N('REWARDS'),
- result: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('REWARDS')}?`, questAllFarm);
- },
- title: I18N('REWARDS_TITLE'),
- },
- {
- msg: I18N('MAIL'),
- result: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('MAIL')}?`, mailGetAll);
- },
- title: I18N('MAIL_TITLE'),
- },
- {
- msg: I18N('SEER'),
- result: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('SEER')}?`, rollAscension);
- },
- title: I18N('SEER_TITLE'),
- },
- {
- msg: I18N('NY_GIFTS'),
- result: getGiftNewYear,
- title: I18N('NY_GIFTS_TITLE'),
- },
- ];
- popupButtons.push({ result: 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'),
- func: async function () {
- const popupButtons = [
- /*
- {
- msg: I18N('GET_ENERGY'),
- result: farmStamina,
- title: I18N('GET_ENERGY_TITLE'),
- },
- {
- msg: I18N('ITEM_EXCHANGE'),
- result: fillActive,
- title: I18N('ITEM_EXCHANGE_TITLE'),
- },
- {
- msg: I18N('BUY_SOULS'),
- result: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('BUY_SOULS')}?`, buyHeroFragments);
- },
- title: I18N('BUY_SOULS_TITLE'),
- },
- {
- msg: I18N('BUY_FOR_GOLD'),
- result: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('BUY_FOR_GOLD')}?`, buyInStoreForGold);
- },
- title: I18N('BUY_FOR_GOLD_TITLE'),
- },
- {
- msg: I18N('BUY_OUTLAND'),
- result: bossOpenChestPay,
- title: I18N('BUY_OUTLAND_TITLE'),
- },
- {
- msg: I18N('AUTO_RAID_ADVENTURE'),
- result: autoRaidAdventure,
- title: I18N('AUTO_RAID_ADVENTURE_TITLE'),
- },
- {
- msg: I18N('CLAN_STAT'),
- result: clanStatistic,
- title: I18N('CLAN_STAT_TITLE'),
- },
- {
- msg: I18N('EPIC_BRAWL'),
- result: async function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('EPIC_BRAWL')}?`, () => {
- const brawl = new epicBrawl();
- brawl.start();
- });
- },
- title: I18N('EPIC_BRAWL_TITLE'),
- },*/
- {
- msg: I18N('ARTIFACTS_UPGRADE'),
- result: updateArtifacts,
- title: I18N('ARTIFACTS_UPGRADE_TITLE'),
- },
- {
- msg: I18N('SKINS_UPGRADE'),
- result: updateSkins,
- title: I18N('SKINS_UPGRADE_TITLE'),
- },
- {
- msg: I18N('SEASON_REWARD'),
- result: farmBattlePass,
- title: I18N('SEASON_REWARD_TITLE'),
- },
- {
- msg: I18N('SELL_HERO_SOULS'),
- result: sellHeroSoulsForGold,
- title: I18N('SELL_HERO_SOULS_TITLE'),
- },
- {
- msg: I18N('CHANGE_MAP'),
- result: 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 }),
- result: i.id,
- }));
-
- /*const result = await popup.confirm(I18N('SELECT_ISLAND_MAP'), [
- ...maps,
- { result: false, isClose: true },
- ]);*/
- //тест карта острова
- const result = await popup.confirm(I18N('SELECT_ISLAND_MAP'), [...maps, { result: false, isClose: true }]);
- if (result) {
- cheats.changeIslandMap(result);
- }
- },
- title: I18N('CHANGE_MAP_TITLE'),
- },
- {
- msg: I18N('SHOPS'),
- result: async function () {
- const shopButtons = [{
- msg: I18N('SHOPS_DEFAULT'),
- result: function () {
- cheats.goDefaultShops();
- },
- title: I18N('SHOPS_DEFAULT_TITLE'),
- }, {
- msg: I18N('SECRET_WEALTH'),
- result: function () {
- cheats.goSecretWealthShops();
- },
- title: I18N('SECRET_WEALTH'),
- }];
- for (let i = 0; i < 4; i++) {
- const number = i + 1;
- shopButtons.push({
- msg: I18N('SHOPS_LIST', { number }),
- result: function () {
- cheats.goCustomShops(i);
- },
- title: I18N('SHOPS_LIST_TITLE', { number }),
- })
- }
- shopButtons.push({ result: false, isClose: true })
- const answer = await popup.confirm(I18N('SHOPS_WARNING'), shopButtons);
- if (typeof answer === 'function') {
- answer();
- }
- },
- title: I18N('SHOPS'),
- },
- ];
-
- popupButtons.push({ result: false, isClose: true });
- const answer = await popup.confirm(`${I18N('CHOOSE_ACTION')}:`, popupButtons);
- if (typeof answer === 'function') {
- answer();
- }
- },
- },
- testTitanArena: {
- name: I18N('TITAN_ARENA'),
- title: I18N('TITAN_ARENA_TITLE'),
- func: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('TITAN_ARENA')}?`, testTitanArena);
- },
- },
- /* тест подземка есть в сделать все
- testDungeon: {
- name: I18N('DUNGEON'),
- title: I18N('DUNGEON_TITLE'),
- func: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('DUNGEON')}?`, testDungeon);
- },
- hide: true,
- },*/
- //тест подземка 2
- DungeonFull: {
- name: I18N('DUNGEON2'),
- title: I18N('DUNGEON_FULL_TITLE'),
- func: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('DUNGEON_FULL_TITLE')}?`, DungeonFull);
- },
- },
- //остановить подземелье
- stopDungeon: {
- name: I18N('STOP_DUNGEON'),
- title: I18N('STOP_DUNGEON_TITLE'),
- func: function () {
- confShow(`${I18N('STOP_SCRIPT')} ${I18N('STOP_DUNGEON_TITLE')}?`, stopDungeon);
- },
- },
- // Архидемон
- bossRatingEvent: {
- name: I18N('ARCHDEMON'),
- title: I18N('ARCHDEMON_TITLE'),
- func: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('ARCHDEMON')}?`, bossRatingEvent);
- },
- hide: true,
- },
- // Горнило душ
- bossRatingEvent: {
- name: I18N('FURNACE_OF_SOULS'),
- title: I18N('ARCHDEMON_TITLE'),
- func: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('FURNACE_OF_SOULS')}?`, bossRatingEventSouls);
- },
- hide: true,
- },
- // Буря
- /*testAdventure2: {
- name: I18N('STORM'),
- title: I18N('STORM_TITLE'),
- func: () => {
- testAdventure2('solo');
- },
- },*/
- rewardsAndMailFarm: {
- name: I18N('REWARDS_AND_MAIL'),
- title: I18N('REWARDS_AND_MAIL_TITLE'),
- func: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('REWARDS_AND_MAIL')}?`, rewardsAndMailFarm);
- },
- },
- //тест прислужники
- testRaidNodes: {
- name: I18N('MINIONS'),
- title: I18N('MINIONS_TITLE'),
- func: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('MINIONS')}?`, testRaidNodes);
- },
- },
- testAdventure: {
- name: I18N('ADVENTURE'),
- title: I18N('ADVENTURE_TITLE'),
- func: () => {
- testAdventure();
- },
- },
- goToSanctuary: {
- name: I18N('SANCTUARY'),
- title: I18N('SANCTUARY_TITLE'),
- func: cheats.goSanctuary,
- },
- goToClanWar: {
- name: I18N('GUILD_WAR'),
- title: I18N('GUILD_WAR_TITLE'),
- func: cheats.goClanWar,
- },
- dailyQuests: {
- name: I18N('DAILY_QUESTS'),
- title: I18N('DAILY_QUESTS_TITLE'),
- func: async function () {
- const quests = new dailyQuests(
- () => {},
- () => {}
- );
- await quests.autoInit();
- quests.start();
- },
- },
- //подарок др
- /*NewYearGift_Clan: {
- name: I18N('New_Year_Clan'),
- title: I18N('New_Year_Clan_TITLE'),
- func: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('New_Year_Clan_TITLE')}?`, NewYearGift_Clan);
- },
- },*/
- newDay: {
- name: I18N('SYNC'),
- title: I18N('SYNC_TITLE'),
- func: function () {
- confShow(`${I18N('RUN_SCRIPT')} ${I18N('SYNC')}?`, cheats.refreshGame);
- },
- },
- };
- /**
- * Display buttons
- *
- * Вывести кнопочки
- */
- function addControlButtons() {
- for (let name in buttons) {
- button = buttons[name];
- if (button.hide) {
- continue;
- }
- button['button'] = scriptMenu.addButton(button.name, button.func, button.title);
- }
- }
- /**
- * Adds links
- *
- * Добавляет ссылки
- */
- function addBottomUrls() {
- 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 = {
- buff: 0,
- bossLvl: 130,
- };
- const invasionDataPacks = {
- 130: { buff: 0, pet: 6004, heroes: [58, 48, 16, 65, 59], favor: { 16: 6004, 48: 6001, 58: 6002, 59: 6005, 65: 6000 } },
- 140: { buff: 0, pet: 6006, heroes: [1, 4, 13, 58, 65], favor: { 1: 6001, 4: 6006, 13: 6002, 58: 6005, 65: 6000 } },
- 150: { buff: 0, pet: 6006, heroes: [1, 12, 17, 21, 65], favor: { 1: 6001, 12: 6003, 17: 6006, 21: 6002, 65: 6000 } },
- 160: { buff: 0, pet: 6008, heroes: [12, 21, 34, 58, 65], favor: { 12: 6003, 21: 6006, 34: 6008, 58: 6002, 65: 6001 } },
- 170: { buff: 0, pet: 6005, heroes: [33, 12, 65, 21, 4], favor: { 4: 6001, 12: 6003, 21: 6006, 33: 6008, 65: 6000 } },
- 180: { buff: 20, pet: 6009, heroes: [58, 13, 5, 17, 65], favor: { 5: 6006, 13: 6003, 58: 6005 } },
- 190: { buff: 0, pet: 6006, heroes: [1, 12, 21, 36, 65], favor: { 1: 6004, 12: 6003, 21: 6006, 36: 6005, 65: 6000 } },
- 200: { buff: 0, pet: 6006, heroes: [12, 1, 13, 2, 65], favor: { 2: 6001, 12: 6003, 13: 6006, 65: 6000 } },
- 210: { buff: 15, pet: 6005, heroes: [12, 21, 33, 58, 65], favor: { 12: 6003, 21: 6006, 33: 6008, 58: 6005, 65: 6001 } },
- 220: { buff: 5, pet: 6006, heroes: [58, 13, 7, 34, 65], favor: { 7: 6002, 13: 6008, 34: 6006, 58: 6005, 65: 6001 } },
- 230: { buff: 35, pet: 6005, heroes: [5, 7, 13, 58, 65], favor: { 5: 6006, 7: 6003, 13: 6002, 58: 6005, 65: 6000 } },
- 240: { buff: 0, pet: 6005, heroes: [12, 58, 1, 36, 65], favor: { 1: 6006, 12: 6003, 36: 6005, 65: 6001 } },
- 250: { buff: 15, pet: 6005, heroes: [12, 36, 4, 16, 65], favor: { 12: 6003, 16: 6004, 36: 6005, 65: 6001 } },
- 260: { buff: 15, pet: 6005, heroes: [48, 12, 36, 65, 4], favor: { 4: 6006, 12: 6003, 36: 6005, 48: 6000, 65: 6007 } },
- 270: { buff: 35, pet: 6005, heroes: [12, 58, 36, 4, 65], favor: { 4: 6006, 12: 6003, 36: 6005 } },
- 280: { buff: 80, pet: 6005, heroes: [21, 36, 48, 7, 65], favor: { 7: 6003, 21: 6006, 36: 6005, 48: 6001, 65: 6000 } },
- 290: { buff: 95, pet: 6008, heroes: [12, 21, 36, 35, 65], favor: { 12: 6003, 21: 6006, 36: 6005, 65: 6007 } },
- 300: { buff: 25, pet: 6005, heroes: [12, 13, 4, 34, 65], favor: { 4: 6006, 12: 6003, 13: 6007, 34: 6002 } },
- 310: { buff: 45, pet: 6005, heroes: [12, 21, 58, 33, 65], favor: { 12: 6003, 21: 6006, 33: 6002, 58: 6005, 65: 6007 } },
- 320: { buff: 70, pet: 6005, heroes: [12, 48, 2, 6, 65], favor: { 6: 6005, 12: 6003 } },
- 330: { buff: 70, pet: 6005, heroes: [12, 21, 36, 5, 65], favor: { 5: 6002, 12: 6003, 21: 6006, 36: 6005, 65: 6000 } },
- 340: { buff: 55, pet: 6009, heroes: [12, 36, 13, 6, 65], favor: { 6: 6005, 12: 6003, 13: 6002, 36: 6006, 65: 6000 } },
- 350: { buff: 100, pet: 6005, heroes: [12, 21, 58, 34, 65], favor: { 12: 6003, 21: 6006, 58: 6005 } },
- 360: { buff: 85, pet: 6007, heroes: [12, 21, 36, 4, 65], favor: { 4: 6006, 12: 6003, 21: 6002, 36: 6005 } },
- 370: { buff: 90, pet: 6008, heroes: [12, 21, 36, 13, 65], favor: { 12: 6003, 13: 6007, 21: 6006, 36: 6005, 65: 6001 } },
- 380: { buff: 165, pet: 6005, heroes: [12, 33, 36, 4, 65], favor: { 4: 6001, 12: 6003, 33: 6006 } },
- 390: { buff: 235, pet: 6005, heroes: [21, 58, 48, 2, 65], favor: { 2: 6005, 21: 6002 } },
- 400: { buff: 125, pet: 6006, heroes: [12, 21, 36, 48, 65], favor: { 12: 6003, 21: 6006, 36: 6005, 48: 6001, 65: 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;
-
- /**
- * 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'), result: true},
- { msg: I18N('BTN_CANCEL'), result: false, isCancel: true},
- ]
- } else {
- yesCallback = () => {};
- buts = [
- { msg: I18N('BTN_OK'), result: 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.result.type == "iframeEvent.login") {
- this.isWebSocketLogin = true;
- } else if (data.result.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')) {
- // checkExpedition(); //экспедиции на авто при входе в игру
- //}
-
- //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) {
- return oldReady.apply(this, arguments);
- }
- }
- }
- 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({
- "result": 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, result: false},
- {msg: ansS, result: 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, result: 0},
- {msg: ansS, result: 1},
- {msg: ansT, result: 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.result.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 bFix = new BestOrWinFixBattle(cloneBattle);
- bFix.setNoMakeWin(noFixWin);
- let endTime = Date.now() + 3e4;
- if (endTime < cloneBattle.endTime) {
- endTime = cloneBattle.endTime;
- }
- const result = await bFix.start(cloneBattle.endTime, 150);
-
- if (result.result.win) {
- call.args.result = result.result;
- call.args.progress = result.progress;
- changeRequest = true;
- } else if (result.value) {
- if (
- await popup.confirm('Поражение<br>Лучший результат: ' + result.value + '%', [
- { msg: 'Отмена', result: 0 },
- { msg: 'Принять', result: 1 },
- ])
- ) {
- call.args.result = result.result;
- call.args.progress = result.progress;
- changeRequest = true;
- }
- }
- } catch (error) {
- console.error(error);
- }
- }
-
- if (!call.args.result.win) {
- let resultPopup = false;
- if (call.name == 'adventure_endBattle' ||
- //call.name == 'invasion_bossEnd' ||
- call.name == 'bossEndBattle' ||
- call.name == 'adventureSolo_endBattle') {
- resultPopup = 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') {
- resultPopup = await showMsg(I18N('MSG_HAVE_BEEN_DEFEATED'), I18N('BTN_OK'), I18N('BTN_AUTO_F5'));
- } else if (call.name !== 'epicBrawl_endBattle' && call.name !== 'titanArenaEndBattle') {
- resultPopup = await showMsg(I18N('MSG_HAVE_BEEN_DEFEATED'), I18N('BTN_OK'), I18N('BTN_CANCEL'));
- }
- if (resultPopup) {
- 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 (resultPopup > 1) {
- this.onReadySuccess = testAutoBattle;
- // setTimeout(bossBattle, 1000);
- }
- }
- } else if (call.args.result.stars < 3 && call.name == 'towerEndBattle') {
- resultPopup = await showMsg(I18N('LOST_HEROES'), I18N('BTN_OK'), I18N('BTN_CANCEL'), I18N('BTN_AUTO'));
- if (resultPopup) {
- fixBattle(call.args.progress[0].attackers.heroes);
- fixBattle(call.args.progress[0].defenders.heroes);
- changeRequest = true;
- if (resultPopup > 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'), result: false },
- { msg: I18N('BTN_YES'), result: 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 resultPopup = await popup.confirm(
- `${I18N('MSG_YOU_APPLIED')} ${lastDamage.toLocaleString()} ${I18N('MSG_DAMAGE')}.`,
- [
- { msg: I18N('BTN_OK'), result: false },
- { msg: I18N('BTN_AUTO_F5'), result: 1 },
- { msg: I18N('BTN_TRY_FIX_IT'), result: 2 },
- ...testFunc,
- ],
- [
- {
- name: 'isStat',
- label: I18N('CALC_STAT'),
- checked: false,
- },
- ]
- );
- if (resultPopup) {
- if (resultPopup == 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 bFix = new BossFixBattle(cloneBattle);
- const result = await bFix.start(endTime, 300);
- console.log(result);
-
- let msgResult = I18N('DAMAGE_NO_FIXED', {
- lastDamage: lastDamage.toLocaleString()
- });
- if (result.value > lastDamage) {
- call.args.result = result.result;
- call.args.progress = result.progress;
- msgResult = I18N('DAMAGE_FIXED', {
- lastDamage: lastDamage.toLocaleString(),
- maxDamage: result.value.toLocaleString(),
- });
- }
- console.log(lastDamage, '>', result.value);
- setProgress(
- msgResult +
- '<br/>' +
- I18N('COUNT_FIXED', {
- count: result.maxCount,
- }),
- false,
- hideProgress
- );
- } else if (resultPopup > 3) {
- const cloneBattle = structuredClone(lastBossBattle);
- const mFix = new masterFixBattle(cloneBattle);
- const result = await mFix.start(cloneBattle.endTime, resultPopup);
- console.log(result);
- let msgResult = I18N('DAMAGE_NO_FIXED', {
- lastDamage: lastDamage.toLocaleString(),
- });
- if (result.value > lastDamage) {
- maxDamage = result.value;
- call.args.result = result.result;
- call.args.progress = result.progress;
- msgResult = I18N('DAMAGE_FIXED', {
- lastDamage: lastDamage.toLocaleString(),
- maxDamage: maxDamage.toLocaleString(),
- });
- }
- console.log('Урон:', lastDamage, maxDamage);
- setProgress(msgResult, 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.result.win) {
- lastBattle.progress = call.args.progress;
- const result = await Calc(lastBattle);
- let timer = getTimer(result.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 result = await Calc(lastBattle);
-
- if (changeRequest) {
- call.args.progress = result.progress;
- call.args.result = result.result;
- }
-
- let timer = result.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 == 'quizAnswer') {
- /**
- * 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.result.win) {
- startTimer = await popup.confirm(I18N('DEFEAT_TURN_TIMER'), [
- { msg: I18N('BTN_NO'), result: false },
- { msg: I18N('BTN_YES'), result: true },
- ]);
- }
-
- if (call.args.result.win || startTimer) {
- missionBattle.progress = call.args.progress;
- missionBattle.result = call.args.result;
- const result = await Calc(missionBattle);
-
- let timer = result.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,
- result: call.args.result,
- heroes: call.args.progress[0].attackers.heroes,
- count: 0,
- }
- setTimeout(async () => {
- if (!isSendsMission && await popup.confirm(I18N('MSG_REPEAT_MISSION'), [
- { msg: I18N('BTN_REPEAT'), result: true},
- { msg: I18N('BTN_NO'), result: 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 == 'titanUseSummonCircle') &&
- call.args.amount > 1) {
- const startAmount = call.args.amount;
- const result = await popup.confirm(I18N('MSG_SPECIFY_QUANT'), [
- { msg: I18N('BTN_OPEN'), isInput: true, default: 1},
- ]);
- if (result) {
- const item = call.name == 'pet_chestOpen' ? { id: 90, type: 'consumable' } : { id: 13, type: 'coin' };
- cheats.updateInventory({
- [item.type]: {
- [item.id]: -(result - startAmount),
- },
- });
- call.args.amount = result;
- 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 result = await popup.confirm(I18N('MSG_SPECIFY_QUANT'), [
- { msg: I18N('BTN_OPEN'), isInput: true, default: 1 },
- ]);
- if (result) {
- const openChests = result;
- let sphere = result < 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 result = await popup.confirm(I18N('MSG_SPECIFY_QUANT'), [
- { msg: I18N('BTN_OPEN'), isInput: true, default: call.args.amount},
- ]);
- call.args.amount = result;
- 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 == 217) {
- const pack = invasionDataPacks[invasionInfo.bossLvl];
- 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;
- }
- }
- /**
- * Changing the maximum number of raids in the campaign
- * Изменение максимального количества рейдов в кампании
- */
- // if (call.name == 'missionRaid') {
- // if (isChecked('countControl') && call.args.times > 1) {
- // const result = +(await popup.confirm(I18N('MSG_SPECIFY_QUANT'), [
- // { msg: I18N('BTN_RUN'), isInput: true, default: call.args.times },
- // ]));
- // call.args.times = result > call.args.times ? call.args.times : result;
- // 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.results = [];
- }
- }
- let mainReward = null;
- const allReward = {};
- let countTypeReward = 0;
- let readQuestInfo = false;
- for (const call of respond.results) {
- /**
- * Obtaining initial data for completing quests
- * Получение исходных данных для выполнения квестов
- */
- if (readQuestInfo) {
- questsInfo[call.ident] = call.result.response;
- }
- /**
- * Getting a user ID
- * Получение идетификатора пользователя
- */
- if (call.ident == callsIdent['registration']) {
- userId = call.result.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.result.response?.billings;
- const bundle = call.result.response?.bundle;
- if (billings && bundle) {
- call.result.response.billings = call.result.response.billings.filter((e) => ['repeatableOffer'].includes(e.type));
- call.result.response.bundle = [];
- isChange = true;
- }
- }
- /**
- * Hiding donation offers 2
- * Скрываем предложения доната 2
- */
- if (getSaveVal('noOfferDonat') &&
- (call.ident == callsIdent['offerGetAll'] ||
- call.ident == callsIdent['specialOffer_getAll'])) {
- let offers = call.result.response;
- if (offers) {
- call.result.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.result?.bundleUpdate) {
- delete call.result.bundleUpdate;
- isChange = true;
- }
- /**
- * Hiding donation offers 4
- * Скрываем предложения доната 4
- */
- if (call.result?.specialOffers) {
- const offers = call.result.specialOffers;
- call.result.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['quizGetNewQuestion']) {
- let quest = call.result.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['quizAnswer']) {
- const answer = call.result.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.result.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['adventure_turnStartBattle']) {
- let battle = call.result.response.battle || call.result.response.replay;
- if (call.ident == callsIdent['brawl_startBattle'] ||
- call.ident == callsIdent['bossAttack'] ||
- call.ident == callsIdent['towerStartBattle'] ||
- call.ident == callsIdent['invasion_bossStart']) {
- battle = call.result.response;
- }
- lastBattleInfo = battle;
- if (call.ident == callsIdent['battleGetReplay'] && call.result.response.replay.type === "clan_raid") {
- if (call?.result?.response?.replay?.result?.damage) {
- const damages = Object.values(call.result.response.replay.result.damage);
- const bossDamage = damages.reduce((a, v) => a + v, 0);
- setProgress(I18N('BOSS_DAMAGE') + bossDamage.toLocaleString(), false, hideProgress);
- continue;
- }
- }
- if (!isChecked('preCalcBattle')) {
- continue;
- }
- setProgress(I18N('BEING_RECALC'));
- let battleDuration = 120;
- try {
- const typeBattle = getBattleType(battle.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(battle, false)]
- let countTestBattle = getInput('countTestBattle');
- if (call.ident == callsIdent['invasion_bossStart'] ) {
- countTestBattle = 0;
- }
- if (call.ident == callsIdent['battleGetReplay']) {
- battle.progress = [{ attackers: { input: ['auto', 0, 0, 'auto', 0, 0] } }];
- }
- for (let i = 0; i < countTestBattle; i++) {
- actions.push(getBattleInfo(battle, true));
- }
- Promise.all(actions)
- .then(e => {
- e = e.map(n => ({win: n.result.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)
- });
- }
- //тест сохранки
- /** Запоминаем команды в реплее*/
- if (call.ident == callsIdent['battleGetReplay']) {
- let battle = call.result.response.replay;
- repleyBattle.attackers = battle.attackers;
- repleyBattle.defenders = battle.defenders[0];
- repleyBattle.effects = battle.effects.defenders;
- repleyBattle.state = battle.progress[0].defenders.heroes;
- repleyBattle.seed = battle.seed;
- }
- /** Нападение в турнире*/
- if (call.ident == callsIdent['titanArenaStartBattle']) {
- let bestBattle = getInput('countBattle');
- let unrandom = getInput('needResource');
- let maxPower = getInput('needResource2');
- if (bestBattle * unrandom * maxPower == 0) {
- let battle = call.result.response.battle;
- if (bestBattle == 0) {
- battle.progress = bestLordBattle[battle.typeId]?.progress;
- }
- if (unrandom == 0 && !!repleyBattle.seed) {
- battle.seed = repleyBattle.seed;
- }
- if (maxPower == 0) {
- battle.attackers = getTitansPack(Object.keys(battle.attackers));
- }
- isChange = true;
- }
- }
- /** Тест боев с усилениями команд защиты*/
- if (call.ident == callsIdent['chatAcceptChallenge']) {
- let battle = call.result.response.battle;
- addBuff(battle);
- let testType = getInput('countBattle');
- if (testType.slice(0, 1) == "-") {
- testType = parseInt(testType.slice(1), 10);
- switch (testType) {
- case 1:
- battle.defenders[0] = repleyBattle.defenders;
- break; //наша атака против защиты из реплея
- case 2:
- battle.defenders[0] = repleyBattle.attackers;
- break; //наша атака против атаки из реплея
- case 3:
- battle.attackers = repleyBattle.attackers;
- break; //атака из реплея против защиты в чате
- case 4:
- battle.attackers = repleyBattle.defenders;
- break; //защита из реплея против защиты в чате
- case 5:
- battle.attackers = repleyBattle.attackers;
- battle.defenders[0] = repleyBattle.defenders;
- break; //атака из реплея против защиты из реплея
- case 6:
- battle.attackers = repleyBattle.defenders;
- battle.defenders[0] = repleyBattle.attackers;
- break; //защита из реплея против атаки из реплея
- case 7:
- battle.attackers = repleyBattle.attackers;
- battle.defenders[0] = repleyBattle.attackers;
- break; //атака из реплея против атаки из реплея
- case 8:
- battle.attackers = repleyBattle.defenders;
- battle.defenders[0] = repleyBattle.defenders;
- break; //защита из реплея против защиты из реплея
- case 15:
- battle.attackers = repleyBattle.defenders;
- battle.defenders[0] = repleyBattle.defenders;
- break; //защита из реплея против защиты из реплея
- }
- }
-
- isChange = true;
- }
- /** Тест боев с усилениями команд защиты тренировках*/
- if (call.ident == callsIdent['demoBattles_startBattle']) {
- let battle = call.result.response.battle;
- addBuff(battle);
- let testType = getInput('countBattle');
- if (testType.slice(0, 1) == "-") {
- testType = parseInt(testType.slice(1), 10);
- switch (testType) {
- case 1:
- battle.defenders[0] = repleyBattle.defenders;
- break; //наша атака против защиты из реплея
- case 2:
- battle.defenders[0] = repleyBattle.attackers;
- break; //наша атака против атаки из реплея
- case 3:
- battle.attackers = repleyBattle.attackers;
- break; //атака из реплея против защиты в чате
- case 4:
- battle.attackers = repleyBattle.defenders;
- break; //защита из реплея против защиты в чате
- case 5:
- battle.attackers = repleyBattle.attackers;
- battle.defenders[0] = repleyBattle.defenders;
- break; //атака из реплея против защиты из реплея
- case 6:
- battle.attackers = repleyBattle.defenders;
- battle.defenders[0] = repleyBattle.attackers;
- break; //защита из реплея против атаки из реплея
- case 7:
- battle.attackers = repleyBattle.attackers;
- battle.defenders[0] = repleyBattle.attackers;
- break; //атака из реплея против атаки из реплея
- case 8:
- battle.attackers = repleyBattle.defenders;
- battle.defenders[0] = repleyBattle.defenders;
- break; //защита из реплея против защиты из реплея
- }
- }
-
- isChange = true;
- }
- //тест сохранки
- /**
- * Start of the Asgard boss fight
- * Начало боя с боссом Асгарда
- */
- if (call.ident == callsIdent['clanRaid_startBossBattle']) {
- lastBossBattle = call.result.response.battle;
- lastBossBattle.endTime = Date.now() + 160 * 1000;
- if (isChecked('preCalcBattle')) {
- const result = await Calc(lastBossBattle).then(e => e.progress[0].defenders.heroes[1].extra);
- const bossDamage = result.damageTaken + result.damageTakenNextLevel;
- setProgress(I18N('BOSS_DAMAGE') + bossDamage.toLocaleString(), false, hideProgress);
- }
- }
- /**
- * Cancel tutorial
- * Отмена туториала
- */
- if (isCanceledTutorial && call.ident == callsIdent['tutorialGetInfo']) {
- let chains = call.result.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.result.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.result.response;
- }
- }
-
- if (countTypeReward > 20) {
- correctShowOpenArtifact = 3;
- } else {
- correctShowOpenArtifact = 0;
- }
-
- /**
- * Sum the result of opening Pet Eggs
- * Суммирование результата открытия яиц питомцев
- */
- if (isChecked('countControl') && call.ident == callsIdent['pet_chestOpen']) {
- const rewards = call.result.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.result.response.rewards = [allReward];
- isChange = true;
- }
- /**
- * Removing titan cards
- * Убираем карточки титанов
- */
- if (call.ident == callsIdent['titanUseSummonCircle']) {
- if (call.result.response.rewards.length > 10) {
- for (const reward of call.result.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.result.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'), result: true },
- { msg: I18N('BTN_NO'), result: false, isClose: true },
- ]))
- ) {
- const [count, recursionResult] = await openRussianDolls(lastRussianDollId, newCount);
- countLootBox += +count;
- mergeItemsObj(lootBox, recursionResult);
- isChange = true;
- }
-
- if (this.massOpen) {
- if (
- await popup.confirm(I18N('OPEN_ALL_EQUIP_BOXES'), [
- { msg: I18N('BTN_OPEN'), result: true },
- { msg: I18N('BTN_NO'), result: false, isClose: true },
- ])
- ) {
- const consumable = await Send({ calls: [{ name: 'inventoryGet', args: {}, ident: 'inventoryGet' }] }).then((e) =>
- Object.entries(e.results[0].result.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.results.map((r) => r.result.response).flat());
-
- for (const loot of responses) {
- const [count, result] = Object.entries(loot).pop();
- countLootBox += +count;
-
- mergeItemsObj(lootBox, result);
- }
- isChange = true;
-
- this.onReadySuccess = () => {
- cheats.updateInventory({ consumable: deleteItems });
- cheats.refreshInventory();
- };
- }
- }
-
- if (isChange) {
- call.result.response = {
- [countLootBox]: lootBox,
- };
- }
-
- }
- /**
- * Dungeon recalculation (fix endless cards)
- * Прерасчет подземки (исправление бесконечных карт)
- */
- if (call.ident == callsIdent['dungeonStartBattle']) {
- lastDungeonBattleData = call.result.response;
- lastDungeonBattleStart = Date.now();
- }
- /**
- * Getting the number of prediction cards
- * Получение количества карт предсказаний
- */
- if (call.ident == callsIdent['inventoryGet']) {
- countPredictionCard = call.result.response.consumable[81] || 0;
- }
- /**
- * Getting subscription status
- * Получение состояния подписки
- */
- if (call.ident == callsIdent['subscriptionGetInfo']) {
- const subscription = call.result.response.subscription;
- if (subscription) {
- subEndTime = subscription.endTime * 1000;
- }
- }
- /**
- * Getting prediction cards
- * Получение карт предсказаний
- */
- if (call.ident == callsIdent['questFarm']) {
- const consumable = call.result.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.result.response.users.map(s => s.serverId)
- call.result.response.servers = call.result.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.result.response.users);
- const mapIdent = call.result.response.mapIdent;
- const adventureId = call.result.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.result?.heroesMerchant) {
- delete call.result.heroesMerchant;
- isChange = true;
- }
- }
- /** missionTimer */
- if (call.ident == callsIdent['missionStart']) {
- missionBattle = call.result.response;
- }
- /** Награды турнира стихий */
- if (call.ident == callsIdent['hallOfFameGetTrophies']) {
- const trophys = call.result.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.results.map((e) => e.result.response))
- .then(async results => {
- let coin18 = 0,
- coin19 = 0,
- gold = 0,
- starmoney = 0;
- for (const r of results) {
- 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'), result: 0 }]);
- });
- }
- }
- if (call.ident == callsIdent['clanDomination_getInfo']) {
- clanDominationGetInfo = call.result.response;
- }
- if (call.ident == callsIdent['clanRaid_endBossBattle']) {
- console.log(call.result.response);
- const damage = Object.values(call.result.response.damage).reduce((a, e) => a + e);
- if (call.result.response.result.afterInvalid) {
- addProgress('<br>' + I18N('SERVER_NOT_ACCEPT'));
- }
- addProgress('<br>Server > ' + I18N('BOSS_DAMAGE') + damage.toLocaleString());
- }
- if (call.ident == callsIdent['invasion_getInfo']) {
- const r = call.result.response;
- if (r?.actions?.length) {
- const boss = r.actions.find((e) => e.payload.id === 217);
- invasionInfo.buff = r.buffAmount;
- invasionInfo.bossLvl = boss.payload.level;
- if (isChecked('tryFixIt_v2')) {
- const pack = invasionDataPacks[invasionInfo.bossLvl];
- setProgress(
- I18N('INVASION_BOSS_BUFF', {
- bossLvl: invasionInfo.bossLvl,
- needBuff: pack.buff,
- haveBuff: invasionInfo.buff
- }),
- false
- );
- }
- }
- }
- if (call.ident == callsIdent['workshopBuff_create']) {
- const r = call.result.response;
- if (r.id == 1) {
- invasionInfo.buff = r.amount;
- if (isChecked('tryFixIt_v2')) {
- const pack = invasionDataPacks[invasionInfo.bossLvl];
- 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 result = await Send({
- calls: [
- {
- name: 'clanDomination_mapState',
- args: {},
- ident: 'clanDomination_mapState',
- },
- ],
- }).then((e) => e.results[0].result.response);
- let townPositions = result.townPositions;
- let positions = {};
- for (let pos in townPositions) {
- let townPosition = townPositions[pos];
- positions[townPosition.position] = townPosition;
- }
- Object.assign(clanDominationGetInfo, {
- townPositions: positions,
- });
- let userPositions = result.userPositions;
- for (let pos in clanDominationGetInfo.townPositions) {
- let townPosition = clanDominationGetInfo.townPositions[pos];
- if (townPosition.status) {
- userPositions[townPosition.userId] = +pos;
- }
- }
- cheats.updateMap(result);
- };
- }
- if (call.ident == callsIdent['clanDomination_mapState']) {
- const townPositions = call.result.response.townPositions;
- const userPositions = call.result.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);
- }
- }
-
- /** Добавляет в бой эффекты усиления*/
- function addBuff(battle) {
- let effects = battle.effects;
- let buffType = getInput('needResource2');
- if (-1 < buffType && buffType < 7) {
- let percentBuff = getInput('needResource');
- effects.defenders = {};
- effects.defenders[buffs[buffType]] = percentBuff;
- } else if (buffType.slice(0, 1) == "-" || isChecked('treningBattle')) {
- buffType = parseInt(buffType.slice(1), 10);
- effects.defenders = repleyBattle.effects;
- battle.defenders[0] = repleyBattle.defenders;
- let def = battle.defenders[0];
- if (buffType == 1) {
- for (let i in def) {
- let state = def[i].state;
- state.hp = state.maxHp;
- state.energy = 0;
- state.isDead = false;
- }
- } else if (buffType == 2 || isChecked('finishingBattle')) {
- for (let i in def) {
- let state2 = def[i].state;
- let rState = repleyBattle.state[i];
- if (!!rState) {
- state2.hp = rState.hp;
- state2.energy = rState.energy;
- state2.isDead = rState.isDead;
- } else {
- state2.hp = 0;
- state2.energy = 0;
- state2.isDead = true;
- }
- }
- }
- }
- }
- const buffs = ['percentBuffAll_allAttacks', 'percentBuffAll_armor', 'percentBuffAll_magicResist', 'percentBuffAll_physicalAttack', 'percentBuffAll_magicPower', 'percentDamageBuff_dot', 'percentBuffAll_healing', 'percentBuffAllForFallenAllies', 'percentBuffAll_energyIncrease', 'percentIncomeDamageReduce_any', 'percentIncomeDamageReduce_physical', 'percentIncomeDamageReduce_magic', 'percentIncomeDamageReduce_dot', 'percentBuffHp', 'percentBuffByPerk_energyIncrease_8', 'percentBuffByPerk_energyIncrease_5', 'percentBuffByPerk_energyIncrease_4', 'percentBuffByPerk_allAttacks_5', 'percentBuffByPerk_allAttacks_4', 'percentBuffByPerk_allAttacks_9', 'percentBuffByPerk_castSpeed_7', 'percentBuffByPerk_castSpeed_6', 'percentBuffByPerk_castSpeed_10', 'percentBuffByPerk_armorPenetration_6', 'percentBuffByPerk_physicalAttack_6', 'percentBuffByPerk_armorPenetration_10', 'percentBuffByPerk_physicalAttack_10', 'percentBuffByPerk_magicPower_7', 'percentDamageBuff_any','percentDamageBuff_physical','percentDamageBuff_magic','corruptedBoss_25_80_1_100_10','tutorialPetUlt_1.2','tutorialBossPercentDamage_1','corruptedBoss_50_80_1_100_10','corruptedBoss_75_80_1_100_10','corruptedBoss_80_80_1_100_10','percentBuffByPerk_castSpeed_4','percentBuffByPerk_energyIncrease_7','percentBuffByPerk_castSpeed_9','percentBuffByPerk_castSpeed_8','bossStageBuff_1000000_20000','bossStageBuff_1500000_30000','bossStageBuff_2000000_40000','bossStageBuff_3000000_50000','bossStageBuff_4000000_60000','bossStageBuff_5000000_70000','bossStageBuff_7500000_80000','bossStageBuff_11000000_90000','bossStageBuff_15000000_100000','bossStageBuff_20000000_120000','bossStageBuff_30000000_150000','bossStageBuff_40000000_200000','bossStageBuff_50000000_250000','percentBuffPet_strength','percentBuffPet_castSpeed','percentBuffPet_petEnergyIncrease','stormPowerBuff_100_1000','stormPowerBuff_100','changeStarSphereIncomingDamage_any','changeBlackHoleDamage','buffSpeedWhenStarfall','changeTeamStartEnergy','decreaseStarSphereDamage','avoidAllBlackholeDamageOnce','groveKeeperAvoidBlackholeDamageChance_3','undeadPreventsNightmares_3','engeneerIncreaseStarMachineIncomingDamage_3','overloadHealDamageStarSphere','nightmareDeathGiveLifesteal_100','starfallIncreaseAllyHeal_9_100','decreaseStarSphereDamage_4','increaseNightmaresIncomingDamageByCount','debuffNightmareOnSpawnFrom_7_hp','damageNightmareGiveEnergy','ultEnergyCompensationOnPlanetParade_6','bestDamagerBeforeParadeGetsImprovedBuff_any','starSphereDeathGiveEnergy','bestDamagerOnParadeBecomesImmortal_any','preventNightmare','buffStatWithHealing_physicalAttack_magic_100','buffStatWithHealing_magicPower_physical_100','buffStatWithHealing_hp_dot_100','replaceHealingWithDamage_magic','critWithRetaliation_10_dot','posessionWithBuffStat_25_20_5_10','energyBurnDamageWithEffect_magic_Silence_5_5','percentBuffHp','percentBuffAll_energyIncrease','percentBuffAll_magicResist','percentBuffAll_armor','percentIncomeDamageReduce_any','percentBuffAll_healing','percentIncomeDamageReduce_any','percentBuffHp','percentBuffAll_energyIncrease','percentIncomeDamageReduce_any','percentBuffHp','percentBuffByPerk_castSpeed_All','percentBuffAll_castSpeed'];
-
- /**
- * 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.result) {
- resolve(data.result);
- } 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.result) {
- 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);
- }
- /**
- * Creates an interface
- *
- * Создает интерфейс
- */
- function createInterface() {
- popup.init();
- scriptMenu.init({
- showMenu: true
- });
- scriptMenu.addHeader(GM_info.script.name, justInfo);
- scriptMenu.addHeader('v' + GM_info.script.version);
- }
-
- function addControls() {
- createInterface();
- const checkboxDetails = scriptMenu.addDetails(I18N('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'), result: true },
- { msg: I18N('BTN_YES_I_AGREE'), result: false },
- ])) {
- return;
- }
- this.checked = true;
- }
- */
- storage.set(nameCheckbox, this.checked);
- })
- }
-
- const inputDetails = scriptMenu.addDetails(I18N('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);
- })
- }
- const inputDetails2 = scriptMenu.addDetails(I18N('SAVING'));
- for (let name in inputs2) {
- inputs2[name].input = scriptMenu.addInputText(inputs2[name].title, false, inputDetails2);
- /**
- * Get inputText state from storage
- * Получаем состояние inputText из storage
- */
- let val = storage.get(name, null);
- if (val != null) {
- inputs2[name].input.value = val;
- } else {
- storage.set(name, inputs2[name].default);
- inputs2[name].input.value = inputs2[name].default;
- }
- /**
- * Tracing a field change event for a record in storage
- * Отсеживание события изменения поля для записи в storage
- */
- inputs2[name].input.dataset['name'] = name;
- inputs2[name].input.addEventListener('input', function () {
- const inputName = this.dataset['name'];
- let value = +this.value;
- if (!value || Number.isNaN(value)) {
- value = storage.get(inputName, inputs2[inputName].default);
- inputs2[name].input.value = value;
- }
- storage.set(inputName, value);
- })
- }
- /* const inputDetails3 = scriptMenu.addDetails(I18N('USER_ID'));
- for (let name in inputs3) {
- inputs3[name].input = scriptMenu.addInputText(inputs3[name].title, false, inputDetails3);
- /**
- * Get inputText state from storage
- * Получаем состояние inputText из storage
- *
- let val = storage.get(name, null);
- if (val != null) {
- inputs3[name].input.value = val;
- } else {
- storage.set(name, inputs3[name].default);
- inputs3[name].input.value = inputs3[name].default;
- }
- /**
- * Tracing a field change event for a record in storage
- * Отсеживание события изменения поля для записи в storage
- *
- inputs3[name].input.dataset['name'] = name;
- inputs3[name].input.addEventListener('input', function () {
- const inputName = this.dataset['name'];
- let value = +this.value;
- if (!value || Number.isNaN(value)) {
- value = storage.get(inputName, inputs3[inputName].default);
- inputs3[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 result 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) {
- timeout = timeout || 0;
- clearTimeout(hideTimeoutProgress);
- hideTimeoutProgress = setTimeout(function () {
- scriptMenu.setStatus('');
- }, timeout);
- }
- /**
- * Progress display
- *
- * Отображение прогресса
- */
- function setProgress(text, hide, onclick) {
- scriptMenu.setStatus(text, onclick);
- hide = hide || false;
- if (hide) {
- hideProgress(3000);
- }
- }
-
- /**
- * Progress added
- *
- * Дополнение прогресса
- */
- function addProgress(text) {
- 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 sFix = new slaveFixBattle();
- sFix.wsStart();
- }
-
- this.testFuntions = {
- hideProgress,
- setProgress,
- addProgress,
- masterFix: false,
- startSlave,
- };
-
- /**
- * 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 _}))}();
-
- /**
- * 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, result } = this.dialogPromice;
- this.dialogPromice = null;
- popup.hide();
- func(result);
- }
- }
- });
- }
-
- 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;
- white-space: pre-wrap;
- 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.result || 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, result: option.result };
- }
- button.addEventListener('click', () => {
- let result = '';
- if (option.isInput) {
- result = inputField.value;
- }
- if (option.isClose || option.isCancel) {
- this.dialogPromice = null;
- }
- buttonClick(result);
- });
-
- 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', result: true, isInput: false }];
- }
- for (const checkBox of checkBoxes) {
- this.addCheckBox(checkBox);
- }
- for (let butt of buttOpt) {
- this.addButton(butt, (result) => {
- result = result || butt.result;
- complete(result);
- popup.hide();
- });
- if (butt.isCancel) {
- this.dialogPromice = { func: complete, result: butt.result };
- }
- }
- this.show();
- });
- }
-
- });
-
- /**
- * Script control panel
- *
- * Панель управления скриптом
- */
- const scriptMenu = new (function () {
-
- this.mainMenu,
- this.buttons = [],
- this.checkboxes = [];
- this.option = {
- showMenu: false,
- showDetails: {}
- };
-
- this.init = function (option = {}) {
- this.option = Object.assign(this.option, option);
- this.option.showDetails = this.loadShowDetails();
- addStyle();
- addBlocks();
- }
-
- const addStyle = () => {
- style = document.createElement('style');
- style.innerText = `
- .scriptMenu_status {
- position: absolute;
- z-index: 10001;
- white-space: pre-wrap; //тест для выравнивания кнопок
- /* max-height: 30px; */
- 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;
- padding: 5px 10px 5px 5px;
- 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;
- display: flex;
- flex-direction: column;
- flex-wrap: nowrap;
- }
- .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;
- border-radius: 5px;
- cursor: pointer;
- padding: 5px 14px 8px;
- margin: 4px;
- background: radial-gradient(circle, rgba(165,120,56,1) 80%, rgba(0,0,0,1) 110%);
- box-shadow: inset 0px -4px 6px #442901, inset 0px 1px 6px #442901, inset 0px 0px 6px, 0px 0px 4px, 0px 0px 0px 2px #ce9767;
- }
- .scriptMenu_button:hover {
- filter: brightness(1.2);
- }
- .scriptMenu_button:active {
- box-shadow: inset 0px 4px 6px #442901, inset 0px 4px 6px #442901, inset 0px 0px 6px, 0px 0px 4px, 0px 0px 0px 2px #ce9767;
- }
- .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;
- }
- `;
- document.head.appendChild(style);
- }
-
- const 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');
- main.appendChild(checkbox);
-
- this.mainMenu = document.createElement('div');
- this.mainMenu.classList.add('scriptMenu_main');
- main.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);
- }
-
- this.setStatus = (text, onclick) => {
- 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.addStatus = (text) => {
- if (!this.status.innerHTML) {
- this.status.classList.remove('scriptMenu_statusHide');
- }
- this.status.innerHTML += text;
- }
-
- /**
- * Adding a text element
- *
- * Добавление текстового элемента
- * @param {String} text text // текст
- * @param {Function} func Click function // функция по клику
- * @param {HTMLDivElement} main parent // родитель
- */
- this.addHeader = (text, func, main) => {
- main = main || this.mainMenu;
- const header = document.createElement('div');
- header.classList.add('scriptMenu_header');
- header.innerHTML = text;
- if (typeof func == 'function') {
- header.addEventListener('click', func);
- }
- main.appendChild(header);
- }
-
- /**
- * Adding a button
- *
- * Добавление кнопки
- * @param {String} text
- * @param {Function} func
- * @param {String} title
- * @param {HTMLDivElement} main parent // родитель
- */
- this.addButton = (text, func, title, main) => {
- main = main || this.mainMenu;
- const button = document.createElement('div');
- button.classList.add('scriptMenu_button');
- button.title = title;
- button.addEventListener('click', func);
- main.appendChild(button);
-
- const buttonText = document.createElement('div');
- buttonText.classList.add('scriptMenu_buttonText');
- buttonText.innerText = text;
- button.appendChild(buttonText);
- this.buttons.push(button);
-
- return button;
- }
-
- /**
- * Adding checkbox
- *
- * Добавление чекбокса
- * @param {String} label
- * @param {String} title
- * @param {HTMLDivElement} main parent // родитель
- * @returns
- */
- this.addCheckbox = (label, title, main) => {
- main = 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;
- }
-
- /**
- * Adding input field
- *
- * Добавление поля ввода
- * @param {String} title
- * @param {String} placeholder
- * @param {HTMLDivElement} main parent // родитель
- * @returns
- */
- this.addInputText = (title, placeholder, main) => {
- main = 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;
- }
-
- /**
- * Adds a dropdown block
- *
- * Добавляет раскрывающийся блок
- * @param {String} summary
- * @param {String} name
- * @returns
- */
- this.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) {
- const self = this;
- details.open = this.option.showDetails[name];
- details.dataset.name = name;
- summary.addEventListener('click', () => {
- self.option.showDetails[details.dataset.name] = !details.open;
- self.saveShowDetails(self.option.showDetails);
- });
- }
- details.appendChild(summary);
-
- return details;
- }
-
- /**
- * Saving the expanded state of the details blocks
- *
- * Сохранение состояния развенутости блоков details
- * @param {*} value
- */
- this.saveShowDetails = (value) => {
- localStorage.setItem('scriptMenu_showDetails', JSON.stringify(value));
- }
-
- /**
- * Loading the state of expanded blocks details
- *
- * Загрузка состояния развенутости блоков details
- * @returns
- */
- this.loadShowDetails = () => {
- let showDetails = localStorage.getItem('scriptMenu_showDetails');
-
- if (!showDetails) {
- return {};
- }
-
- try {
- showDetails = JSON.parse(showDetails);
- } catch (e) {
- return {};
- }
-
- return showDetails;
- }
- });
-
- /**
- * Пример использования
- scriptMenu.init();
- scriptMenu.addHeader('v1.508');
- scriptMenu.addCheckbox('testHack', 'Тестовый взлом игры!');
- scriptMenu.addButton('Запуск!', () => console.log('click'), 'подсказака');
- 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.result;
- resolve();
- };
-
- request.onupgradeneeded = (event) => {
- const db = event.target.result;
- 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.result);
- };
- });
- }
-
- 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 result = storage.get(saveName, def);
- return result;
- }
-
- /**
- * Stores value
- *
- * Сохраняет значение
- */
- function setSaveVal(saveName, value) {
- storage.set(saveName, value);
- }
-
- /**
- * 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 })),
- ...Object.entries(inputs2).map(e => ({ [e[0]]: e[1].default })),
- //...Object.entries(inputs3).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 GiftCodeCollector {
- constructor(filterCodes = []) {
- /** Массив кодов которые возвращать не нужно */
- this.collectedGiftCodes = filterCodes;
- this.codes = [];
- }
-
- async fetchData() {
- const response = await fetch('https://community-api.hero-wars.com/api/posts/limit/10');
- const data = await response.json();
- return data.data;
- }
-
- async getGiftCodes() {
- const data = await this.fetchData();
- data.forEach((post) => {
- let code = '';
- post.attributes.body.forEach((body) => {
- if (body.type !== 'paragraph') {
- return;
- }
-
- const bodyText = body.data.text;
- const giftUrl = this.getGiftUrl(bodyText);
- const urlText = giftUrl || bodyText;
-
- const findCode = this.getCodeFromText(urlText);
- if (findCode) {
- code = findCode;
- }
- });
- if (!code || this.collectedGiftCodes.includes(code)) {
- return;
- }
- this.codes.push(code);
- });
- return this.codes;
- }
-
- getGiftUrl(text) {
- const regex = /href=([\"\'])(.*?bit\.ly.*?)\1/;
- const matches = text.match(regex);
- return matches ? matches[2] : null;
- }
-
- getCodeFromText(text) {
- const regex = /gift_id=(\w{10,32})/;
- const matches = text.match(regex);
- return matches ? matches[1] : null;
- }
- }
-
- /**
- * Sending expeditions
- *
- * Отправка экспедиций
- */
- function checkExpedition() {
- 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.results[0].result.response;
- const dataHeroes = data.results[1].result.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.xp > 0 && !dataExped.useHeroes.includes(hero.id)) {
- let heroPower = hero.power;
- // Лара Крофт * 3
- if (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 resultHeroers = [];
- 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 = resultHeroers.reduce((acc, hero) => acc + hero.power, 0);
- const need = Math.round((power - summ) / (5 - resultHeroers.length));
- if (hero.power > need) {
- resultHeroers.push(hero);
- heroesIds.push(hero.id);
- break;
- }
- }
- }
-
- const summ = resultHeroers.reduce((acc, hero) => acc + hero.power, 0);
- if (summ < power) {
- return false;
- }
- return heroesIds;
- }
-
- /**
- * Ends expedition script
- *
- * Завершает скрипт экспедиции
- */
- end(msg) {
- setProgress(msg, true);
- this.resolve();
- }
- }
-
- /**
- * Walkthrough of the dungeon
- *
- * Прохождение подземелья
- */
- function testDungeon() {
- 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) {
- stopDung = false; // стоп подземка
- res = e.results;
- dungeonGetInfo = res[0].result.response;
- if (!dungeonGetInfo) {
- endDungeon('noDungeon', res);
- return;
- }
- teamGetAll = res[1].result.response;
- teamGetFavor = res[2].result.response;
- dungeonActivity = res[3].result.response.stat.todayDungeonActivity;
- titanGetAll = Object.values(res[4].result.response);
- countPredictionCard = res[5].result.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);
- if (stopDung){
- endDungeon('Стоп подземка,', 'набрано титанита: ' + dungeonActivity + '/' + maxDungeonActivity);
- return;
- }
- 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.results.map(n => n.result.response))
- const battleResults = [];
- for (n in battleDatas) {
- battleData = battleDatas[n]
- battleData.progress = [{ attackers: { input: ["auto", 0, 0, "auto", 0, 0] } }];
- battleResults.push(await Calc(battleData).then(result => {
- result.teamNum = n;
- result.attackerType = floorChoices[n].attackerType;
- return result;
- }));
- }
- processingPromises(battleResults)
- }
- }
-
- 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.results[0].result.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(results) {
- let selectBattle = results[0];
- if (results.length < 2) {
- // console.log(selectBattle);
- if (!selectBattle.result.win) {
- endDungeon('dungeonEndBattle\n', selectBattle);
- return;
- }
- endBattle(selectBattle);
- return;
- }
-
- selectBattle = false;
- let bestState = -1000;
- for (const result of results) {
- const recovery = getState(result);
- if (recovery > bestState) {
- bestState = recovery;
- selectBattle = result
- }
- }
- // console.log(selectBattle.teamNum, results);
- if (!selectBattle || bestState <= -1000) {
- endDungeon('dungeonEndBattle\n', results);
- 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), resultBattle, {
- resolve,
- teamNum,
- attackerType
- });
- });
- }
- /**
- * Returns the result of the battle in a promise
- *
- * Возращает резульат боя в промис
- */
- function resultBattle(resultBattles, args) {
- battleData = resultBattles.results[0].result.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 (result) {
- result.teamNum = args.teamNum;
- result.attackerType = args.attackerType;
- args.resolve(result);
- });
- }
- /**
- * Finishing the fight
- *
- * Заканчиваем бой
- */
- async function endBattle(battleInfo) {
- if (battleInfo.result.win) {
- const args = {
- result: battleInfo.result,
- 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 }), resultEndBattle);
- } else {
- endDungeon('dungeonEndBattle win: false\n', battleInfo);
- }
- }
-
- /**
- * Getting and processing battle results
- *
- * Получаем и обрабатываем результаты боя
- */
- function resultEndBattle(e) {
- if ('error' in e) {
- popup.confirm(I18N('ERROR_MSG', {
- name: e.error.name,
- description: e.error.description,
- }));
- endDungeon('errorRequest', e);
- return;
- }
- battleResult = e.results[0].result.response;
- if ('error' in battleResult) {
- endDungeon('errorBattleResult', battleResult);
- return;
- }
- dungeonGetInfo = battleResult.dungeon ?? battleResult;
- dungeonActivity += battleResult.reward.dungeonActivity ?? 0;
- checkFloor(dungeonGetInfo);
- }
-
- /**
- * Returns the coefficient of condition of the
- * difference in titanium before and after the battle
- *
- * Возвращает коэффициент состояния титанов после боя
- */
- function getState(result) {
- if (!result.result.win) {
- return -1000;
- }
-
- let beforeSumFactor = 0;
- const beforeTitans = result.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
- }
- beforeSumFactor += factor;
- }
-
- let afterSumFactor = 0;
- const afterTitans = result.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 - beforeSumFactor;
- }
-
- /**
- * 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), resultEndBattle);
- }
-
- function endDungeon(reason, info) {
- console.warn(reason, info);
- setProgress(`${I18N('DUNGEON')} ${I18N('COMPLETED')}`, true);
- resolve();
- }
- }
-
- /**
- * Passing the tower
- *
- * Прохождение башни
- */
- function testTower() {
- 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 Resurrection // Воскрешение героя
- ]
-
- this.start = function () {
- send(JSON.stringify(callsExecuteTower), startTower);
- }
-
- /**
- * Getting data on the Tower
- *
- * Получаем данные по башне
- */
- function startTower(e) {
- res = e.results;
- towerGetInfo = res[0].result.response;
- if (!towerGetInfo) {
- endTower('noTower', res);
- return;
- }
- teamGetAll = res[1].result.response;
- teamGetFavor = res[2].result.response;
- inventoryGet = res[3].result.response;
- heroGetAll = Object.values(res[4].result.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), resultBattle, resolve);
- });
- }
- /**
- * Returns the result of the battle in a promise
- *
- * Возращает резульат боя в промис
- */
- function resultBattle(resultBattles, resolve) {
- battleData = resultBattles.results[0].result.response;
- battleType = "get_tower";
- BattleCalc(battleData, battleType, function (result) {
- resolve(result);
- });
- }
- /**
- * Finishing the fight
- *
- * Заканчиваем бой
- */
- function endBattle(battleInfo) {
- if (battleInfo.result.stars >= 3) {
- endBattleCall = {
- calls: [{
- name: "towerEndBattle",
- args: {
- result: battleInfo.result,
- progress: battleInfo.progress,
- },
- ident: "body"
- }]
- }
- send(JSON.stringify(endBattleCall), resultEndBattle);
- } else {
- endTower('towerEndBattle win: false\n', battleInfo);
- }
- }
-
- /**
- * Getting and processing battle results
- *
- * Получаем и обрабатываем результаты боя
- */
- function resultEndBattle(e) {
- battleResult = e.results[0].result.response;
- if ('error' in battleResult) {
- endTower('errorBattleResult', battleResult);
- return;
- }
- if ('reward' in battleResult) {
- scullCoin += battleResult.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(result) {
- towerInfo = result.results[0].result.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.results) {
- const towerInfo = r?.result?.response;
- if (towerInfo && 'skullReward' in towerInfo) {
- scullCoin += towerInfo.skullReward?.coin[7] ?? 0;
- }
- }
- data.results[0] = data.results[data.results.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();
- }
- }
-
- /**
- * Passage of the arena of the titans
- *
- * Прохождение арены титанов
- */
- function testTitanArena() {
- 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.results[0].result.response;
- if (titanArena.status == 'disabled') {
- endTitanArena('disabled', titanArena);
- return;
- }
-
- let teamGetAll = data.results[1].result.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 checkResultInfo(data) {
- let titanArena = data.results[0].result.response;
- checkTier(titanArena);
- }
- /**
- * Finish the current tier
- *
- * Завершить текущий тир
- */
- function titanArenaCompleteTier() {
- isCheckCurrentTier = false;
- let calls = [{
- name: "titanArenaCompleteTier",
- args: {},
- ident: "body"
- }];
- send(JSON.stringify({calls}), checkResultInfo);
- }
- /**
- * 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}), calcResult);
- }
- /**
- * Calculation of the results of the battle
- *
- * Расчет результатов боя
- */
- function calcResult(data) {
- let battlesInfo = data.results[0].result.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--;
- calcBattleResult(battlesInfo)
- .then(resultCalcBattle);
- return;
- }
- /**
- * Otherwise, go to the next opponent
- * Иначе переходим к следующему сопернику
- */
- roundRivals();
- }
- /**
- * Processing the results of the battle calculation
- *
- * Обработка результатов расчета битвы
- */
- function resultCalcBattle(resultBattle) {
- // console.log('resultCalcBattle', currentRival, attempts, resultBattle.result.win);
- /**
- * If the current calculation of victory is not a chance or the attempt ended with the finish the battle
- * Если текущий расчет победа или шансов нет или попытки кончились завершаем бой
- */
- if (resultBattle.result.win || !attempts) {
- titanArenaEndBattle({
- progress: resultBattle.progress,
- result: resultBattle.result,
- rivalId: resultBattle.battleData.typeId
- });
- return;
- }
- /**
- * If not victory and there are attempts we start a new battle
- * Если не победа и есть попытки начинаем новый бой
- */
- titanArenaStartBattle(resultBattle.battleData.typeId);
- }
- /**
- * Returns the promise of calculating the results 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(resultPreCalcBattle);
- }
- /**
- * Processing the results of the battle recalculation
- *
- * Обработка результатов прерасчета битвы
- */
- function resultPreCalcBattle(e) {
- let wins = e.map(n => n.result.win);
- let firstBattle = e.shift();
- let countWin = wins.reduce((w, s) => w + s);
- const countTestBattle = getInput('countTestBattle');
- console.log('resultPreCalcBattle', `${countWin}/${countTestBattle}`)
- if (countWin > 0) {
- attempts = getInput('countAutoBattle');
- } else {
- attempts = 0;
- }
- resultCalcBattle(firstBattle);
- }
-
- /**
- * Complete an arena battle
- *
- * Завершить битву на арене
- */
- function titanArenaEndBattle(args) {
- let calls = [{
- name: "titanArenaEndBattle",
- args,
- ident: "body"
- }];
- send(JSON.stringify({calls}), resultTitanArenaEndBattle);
- }
-
- function resultTitanArenaEndBattle(e) {
- let attackScore = e.results[0].result.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 results.
- * TODO: Возможно стоит сделать улучшение результатов
- */
- // console.log('resultTitanArenaEndBattle', e)
- console.log('resultTitanArenaEndBattle', numReval + '/' + countRivalsTier, attempts)
- roundRivals();
- }
- /**
- * Arena State
- *
- * Состояние арены
- */
- function titanArenaGetStatus() {
- let calls = [{
- name: "titanArenaGetStatus",
- args: {},
- ident: "body"
- }];
- send(JSON.stringify({calls}), checkResultInfo);
- }
- /**
- * Arena Raid Request
- *
- * Запрос рейда арены
- */
- function titanArenaStartRaid() {
- let calls = [{
- name: "titanArenaStartRaid",
- args: {
- titans: titan_arena
- },
- ident: "body"
- }];
- send(JSON.stringify({calls}), calcResults);
- }
-
- function calcResults(data) {
- let battlesInfo = data.results[0].result.response;
- let {attackers, rivals} = battlesInfo;
-
- let promises = [];
- for (let n in rivals) {
- rival = rivals[n];
- promises.push(calcBattleResult({
- attackers: attackers,
- defenders: [rival.team],
- seed: rival.seed,
- typeId: n,
- }));
- }
-
- Promise.all(promises)
- .then(results => {
- const endResults = {};
- for (let info of results) {
- let id = info.battleData.typeId;
- endResults[id] = {
- progress: info.progress,
- result: info.result,
- }
- }
- titanArenaEndRaid(endResults);
- });
- }
-
- function calcBattleResult(battleData) {
- return new Promise(function (resolve, reject) {
- BattleCalc(battleData, "get_titanClanPvp", resolve);
- });
- }
-
- /**
- * Sending Raid Results
- *
- * Отправка результатов рейда
- */
- function titanArenaEndRaid(results) {
- titanArenaEndRaidCall = {
- calls: [{
- name: "titanArenaEndRaid",
- args: {
- results
- },
- ident: "body"
- }]
- }
- send(JSON.stringify(titanArenaEndRaidCall), checkRaidResults);
- }
-
- function checkRaidResults(data) {
- results = data.results[0].result.response.results;
- isSucsesRaid = true;
- for (let i in results) {
- isSucsesRaid &&= (results[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();
- }
- }
-
- 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: 'MultiBattleResult', prop: 'game.battle.controller.MultiBattleResult' },
-
- { 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' },
- { name: 'SendReplayPopUp', prop: 'game.mediator.gui.popup.chat.sendreplay.SendReplayPopUp' }, //полное окно реплей на вг
- ];
-
- /**
- * 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 results 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.MultiBattleResult, 2);
- const battleResults = battleInstant[getF(Game.BattleInstantPlay, 'get_result')]();
- 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 battleResult of battleResults[MBR_2]) {
- const battleLog = Game.BattleLogEncoder.read(new Game.BattleLogReader(battleResult));
- 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: battleResults[getF(Game.MultiBattleResult, 'get_progress')](),
- result: battleResults[getF(Game.MultiBattleResult, 'get_result')](),
- });
- });
- 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];
- }
- /**
- * 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.MultiBattleResult, 'get_result');
- 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.MultiBattleResult, 'get_result');
- 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 PSIVO_9 = getProtoFn(Game.PlayerSubscriptionInfoValueObject, 9);
- const oldBattleFastKey = Game.PlayerSubscriptionInfoValueObject.prototype[PSIVO_9];
- Game.PlayerSubscriptionInfoValueObject.prototype[PSIVO_9] = 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 true;
- } else {
- 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;
- };
- },
- SendReplayPopUp: function() {
- game_view_popup_ClipBasedPopup.prototype.SendReplayPopUp.call(this);
- //if(this.mediator.get_canShareChat()) {
- var clipFull = new game_mediator_gui_popup_chat_sendreplay_SendReplayPopUpClip();
- game_assets_storage_AssetStorage.rsx.popup_theme.get_factory().create(clipFull,game_assets_storage_AssetStorage.rsx.popup_theme.data.getClipByName("send_replay_popup"));
- this.addChild(clipFull.get_graphics());
- clipFull.tf_title.set_text(com_progrestar_common_lang_Translate.translate("UI_DIALOG_CHAT_SEND_REPLAY_TEXT"));
- clipFull.replay_info.tf_label.set_text(com_progrestar_common_lang_Translate.translate("UI_DIALOG_CHAT_REPLAY_TEXT"));
- clipFull.action_btn.set_label(com_progrestar_common_lang_Translate.translate("UI_POPUP_CHAT_SEND"));
- clipFull.tf_message_input.set_prompt(com_progrestar_common_lang_Translate.translate("UI_DIALOG_CHAT_INPUT_MESSAGE_PROMPT"));
- clipFull.tf_message_input.set_text(this.mediator.get_defauiltText());
- clipFull.action_btn.get_signal_click().add($bind(this,this.handler_sendClick));
- clipFull.replay_info.btn_option.get_signal_click().add($bind(this,this.handler_replayClick));
- this.clip = clipFull;
- /*} else {
- var clipShort = new game_mediator_gui_popup_chat_sendreplay_SendReplayPopUpClipShort();
- game_assets_storage_AssetStorage.rsx.popup_theme.get_factory().create(clipShort,game_assets_storage_AssetStorage.rsx.popup_theme.data.getClipByName("send_replay_popup_short"));
- this.addChild(clipShort.get_graphics());
- this.clip = clipShort;
- }*/
- this.clip.button_close.get_signal_click().add(($_=this.mediator,$bind($_,$_.close)));
- this.clip.tf_replay.set_text(com_progrestar_common_lang_Translate.translate("UI_DIALOG_ARENA_REPLAY_URL"));
- this.clip.replay_url_input.set_text(this.mediator.get_replayURL());
- this.clip.replay_url_input.addEventListener("change",$bind(this,this.handler_replayUrlInputChange));
- this.clip.copy_btn.set_label(com_progrestar_common_lang_Translate.translate("UI_DIALOG_BUTTON_COPY"));
- },
-
- };
-
- /**
- * 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.results[0].result.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");
- }
-
- /**
- * 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();
- }
-
- /**
- * 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;
- }
-
- /**
- * Moves to the store with the specified ID
- *
- * Перемещает к магазину с указанным идетификатором
- */
- this.goShopId = function (id) {
- const shop = this.getShop(id);
- if (!shop) {
- return;
- }
- 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"], 21);
- let instance = getFnP(Game, 'get_instance');
- Game[instance]()[navigator]()[navigate](shop, event);
- }
-
- /**
- * Opens a list of non-standard stores
- *
- * Открывает список не стандартных магазинов
- */
- this.goCustomShops = async (p = 0) => {
- /** Запрос данных нужных магазинов */
- const calls = [{ name: "shopGetAll", args: {}, ident: "shopGetAll" }];
- const shops = lib.getData('shop');
- for (const id in shops) {
- const check = !shops[id].ident.includes('merchantPromo') &&
- ![1, 4, 5, 6, 7, 8, 9, 10, 11, 1023, 1024].includes(+id);
- if (check) {
- calls.push({
- name: "shopGet", args: { shopId: id }, ident: `shopGet_${id}`
- })
- }
- }
- const result = await Send({ calls }).then(e => e.results.map(n => n.result.response));
- const shopAll = result.shift();
- const DS_32 = getFn(Game.DataStorage, 32)
-
- const SDS_5 = getProtoFn(selfGame["game.data.storage.shop.ShopDescriptionStorage"], 5)
-
- const SD_21 = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 21);
- const SD_1 = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 1);
- const SD_9 = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 9);
- const ident = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 11);
-
- for (let shop of result) {
- shopAll[shop.id] = shop;
- // Снимаем все ограничения с магазинов
- const shopLibData = Game.DataStorage[DS_32][SDS_5](shop.id)
- shopLibData[SD_21] = 1;
- shopLibData[SD_1] = new selfGame["game.model.user.requirement.Requirement"]
- shopLibData[SD_9] = new selfGame["game.data.storage.level.LevelRequirement"]({
- teamLevel: 10
- });
- }
- /** Скрываем все остальные магазины */
- for (let id in shops) {
- const shopLibData = Game.DataStorage[DS_32][SDS_5](id)
- if (shopLibData[ident].includes('merchantPromo')) {
- shopLibData[SD_21] = 0;
- shopLibData[SD_9] = new selfGame["game.data.storage.level.LevelRequirement"]({
- teamLevel: 999
- });
- }
- }
-
- const instance = getFnP(Game.GameModel, 'get_instance')
- const GM_0 = getProtoFn(Game.GameModel, 0);
- const P_36 = getProtoFn(selfGame["game.model.user.Player"], 36);
- const player = Game.GameModel[instance]()[GM_0];
- /** Пересоздаем объект с магазинами */
- player[P_36] = new selfGame["game.model.user.shop.PlayerShopData"](player);
- player[P_36].init(shopAll);
- /** Даем магазинам новые названия */
- const PSDE_4 = getProtoFn(selfGame["game.model.user.shop.PlayerShopDataEntry"], 4);
-
- const shopName = getFn(cheats.getShop(1), 14);
- const currentShops = this.getShops();
- let count = 0;
- const start = 9 * p + 1;
- const end = start + 8;
- for (let id in currentShops) {
- const shop = currentShops[id][PSDE_4];
- if ([1, 4, 5, 6, 8, 9, 10, 11].includes(+id)) {
- /** Скрываем стандартные магазины */
- shop[SD_21] = 0;
- } else {
- count++;
- if (count < start || count > end) {
- shop[SD_21] = 0;
- continue;
- }
- shop[SD_21] = 1;
- shop[shopName] = cheats.translate("LIB_SHOP_NAME_" + id) + ' ' + id;
- shop[SD_1] = new selfGame["game.model.user.requirement.Requirement"]
- shop[SD_9] = new selfGame["game.data.storage.level.LevelRequirement"]({
- teamLevel: 10
- });
- }
- }
- console.log(count, start, end)
- /** Отправляемся в городскую лавку */
- this.goShopId(1);
- }
-
- /**
- * Opens a list of standard stores
- *
- * Открывает список стандартных магазинов
- */
- this.goDefaultShops = async () => {
- const result = await Send({ calls: [{ name: "shopGetAll", args: {}, ident: "shopGetAll" }] })
- .then(e => e.results.map(n => n.result.response));
- const shopAll = result.shift();
- const shops = lib.getData('shop');
-
- const DS_8 = getFn(Game.DataStorage, 8)
- const DSB_4 = getProtoFn(selfGame["game.data.storage.DescriptionStorageBase"], 4)
-
- /** Получаем объект валюты магазина для оторажения */
- const coins = Game.DataStorage[DS_8][DSB_4](85);
- coins.__proto__ = selfGame["game.data.storage.resource.ConsumableDescription"].prototype;
-
- const DS_32 = getFn(Game.DataStorage, 32)
- const SDS_5 = getProtoFn(selfGame["game.data.storage.shop.ShopDescriptionStorage"], 5)
-
- const SD_21 = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 21);
- for (const id in shops) {
- const shopLibData = Game.DataStorage[DS_32][SDS_5](id)
- if ([1, 4, 5, 6, 8, 9, 10, 11].includes(+id)) {
- shopLibData[SD_21] = 1;
- } else {
- shopLibData[SD_21] = 0;
- }
- }
-
- const instance = getFnP(Game.GameModel, 'get_instance')
- const GM_0 = getProtoFn(Game.GameModel, 0);
- const P_36 = getProtoFn(selfGame["game.model.user.Player"], 36);
- const player = Game.GameModel[instance]()[GM_0];
- /** Пересоздаем объект с магазинами */
- player[P_36] = new selfGame["game.model.user.shop.PlayerShopData"](player);
- player[P_36].init(shopAll);
-
- const PSDE_4 = getProtoFn(selfGame["game.model.user.shop.PlayerShopDataEntry"], 4);
- const currentShops = this.getShops();
- for (let id in currentShops) {
- const shop = currentShops[id][PSDE_4];
- if ([1, 4, 5, 6, 8, 9, 10, 11].includes(+id)) {
- shop[SD_21] = 1;
- } else {
- shop[SD_21] = 0;
- }
- }
- this.goShopId(1);
- }
-
- /**
- * Opens a list of Secret Wealth stores
- *
- * Открывает список магазинов Тайное богатство
- */
- this.goSecretWealthShops = async () => {
- /** Запрос данных нужных магазинов */
- const calls = [{ name: "shopGetAll", args: {}, ident: "shopGetAll" }];
- const shops = lib.getData('shop');
- for (const id in shops) {
- if (shops[id].ident.includes('merchantPromo') && shops[id].teamLevelToUnlock <= 130) {
- calls.push({
- name: "shopGet", args: { shopId: id }, ident: `shopGet_${id}`
- })
- }
- }
- const result = await Send({ calls }).then(e => e.results.map(n => n.result.response));
- const shopAll = result.shift();
- const DS_32 = getFn(Game.DataStorage, 32)
-
- const SDS_5 = getProtoFn(selfGame["game.data.storage.shop.ShopDescriptionStorage"], 5)
-
- const SD_21 = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 21);
- const SD_1 = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 1);
- const SD_9 = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 9);
- const ident = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 11);
- const specialCurrency = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 15);
-
- const DS_8 = getFn(Game.DataStorage, 8)
- const DSB_4 = getProtoFn(selfGame["game.data.storage.DescriptionStorageBase"], 4)
-
- /** Получаем объект валюты магазина для оторажения */
- const coins = Game.DataStorage[DS_8][DSB_4](85);
- coins.__proto__ = selfGame["game.data.storage.resource.CoinDescription"].prototype;
-
- for (let shop of result) {
- shopAll[shop.id] = shop;
- /** Снимаем все ограничения с магазинов */
- const shopLibData = Game.DataStorage[DS_32][SDS_5](shop.id)
- if (shopLibData[ident].includes('merchantPromo')) {
- shopLibData[SD_21] = 1;
- shopLibData[SD_1] = new selfGame["game.model.user.requirement.Requirement"]
- shopLibData[SD_9] = new selfGame["game.data.storage.level.LevelRequirement"]({
- teamLevel: 10
- });
- }
- }
-
- /** Скрываем все остальные магазины */
- for (let id in shops) {
- const shopLibData = Game.DataStorage[DS_32][SDS_5](id)
- if (!shopLibData[ident].includes('merchantPromo')) {
- shopLibData[SD_21] = 0;
- }
- }
-
- const instance = getFnP(Game.GameModel, 'get_instance')
- const GM_0 = getProtoFn(Game.GameModel, 0);
- const P_36 = getProtoFn(selfGame["game.model.user.Player"], 36);
- const player = Game.GameModel[instance]()[GM_0];
- /** Пересоздаем объект с магазинами */
- player[P_36] = new selfGame["game.model.user.shop.PlayerShopData"](player);
- player[P_36].init(shopAll);
- /** Даем магазинам новые названия */
- const PSDE_4 = getProtoFn(selfGame["game.model.user.shop.PlayerShopDataEntry"], 4);
-
- const shopName = getFn(cheats.getShop(1), 14);
- const currentShops = this.getShops();
- for (let id in currentShops) {
- const shop = currentShops[id][PSDE_4];
- if (shop[ident].includes('merchantPromo')) {
- shop[SD_21] = 1;
- shop[specialCurrency] = coins;
- shop[shopName] = cheats.translate("LIB_SHOP_NAME_" + id) + ' ' + id;
- } else if ([1, 4, 5, 6, 8, 9, 10, 11].includes(+id)) {
- /** Скрываем стандартные магазины */
- shop[SD_21] = 0;
- }
- }
- /** Отправляемся в городскую лавку */
- this.goShopId(1);
- }
-
- /**
- * Change island map
- *
- * Сменить карту острова
- */
- this.changeIslandMap = (mapId = 2) => {
- const GameInst = getFnP(selfGame['Game'], 'get_instance');
- const GM_0 = getProtoFn(Game.GameModel, 0);
- const P_59 = getProtoFn(selfGame["game.model.user.Player"], 60);
- const PSAD_31 = getProtoFn(selfGame['game.mechanics.season_adventure.model.PlayerSeasonAdventureData'], 31);
- const Player = Game.GameModel[GameInst]()[GM_0];
- Player[P_59][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
- *
- * Автосбор подарков
- */
- async function getAutoGifts() {
- const collector = new GiftCodeCollector();
- const giftCodes = await collector.getGiftCodes();
- console.log(giftCodes);
-
- for (const key of giftCodes)
- send({ calls: [{ name: "registration", args: { giftId:key, user: { referrer: {} } },
- context: { actionTs: Math.floor(performance.now()), cookie: window?.NXAppInfo?.session_id || null }, ident: "body" }] });
- }
-
- /**
- * 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.results[0].result.response[0]) {
- setProgress(`${I18N('EVENT')} ${I18N('NOT_AVAILABLE')}`, true);
- return;
- }
- const replayId = topGet.results[0].result.response[0].userData.replayId;
- const result = 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 = result.results[3].result.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(result.results[0].result.response.replay.attackers);
- const availableHeroes = Object.values(result.results[1].result.response).map(e => e.id);
- const availablePets = Object.values(result.results[2].result.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: "bossRatingEvent_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: "bossRatingEvent_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 resultBattles = await Send(JSON.stringify({ calls }));
- console.log(resultBattles);
- 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.results[0].result.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: "bossRatingEvent_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?.results?.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.results[0].result.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?.results?.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.results[0].result.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.results[0].result.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',
- result: true
- }, ])
- return;
- }
- lastMissionBattleStart = Date.now();
- let missionStartCall = {
- "calls": [{
- "name": "missionStart",
- "args": lastMissionStart,
- "ident": "body"
- }]
- }
- /**
- * Mission Request
- *
- * Запрос на выполнение мисcии
- */
- 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', result: true},
- ])
- return;
- }
- /**
- * Mission data calculation
- *
- * Расчет данных мисcии
- */
- BattleCalc(e.results[0].result.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,
- "result": r.result,
- "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', result: true},
- ])
- return;
- }
- r = e.results[0].result.response;
- if (r['error']) {
- isSendsMission = false;
- console.log(r['error']);
- setProgress('');
- await popup.confirm(`<br>${I18N('REPETITIONS')}: ${param.count}` + ' 3 ' + r['error'], [
- {msg: 'Ok', result: true},
- ])
- return;
- }
-
- param.count++;
- let RaidMission = getInput('countRaid');
-
- if (RaidMission==param.count){
- isStopSendMission = true;
- console.log(RaidMission);
- }
- 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 sumResult = {};
- 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.results[0].result.response);
- let [countLootBox, result] = Object.entries(response).pop();
- count += +countLootBox;
- let newCount = 0;
-
- if (result?.consumable && result.consumable[libId]) {
- newCount = result.consumable[libId];
- delete result.consumable[libId];
- }
-
- mergeItemsObj(sumResult, result);
- amount = newCount;
- }
-
- setProgress(`${I18N('TOTAL_OPEN')} ${sum}`, 5000);
- return [count, sumResult];
- }
-
- 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.results[0].result.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.results[0].result.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"
- }];
- const result = await Send(JSON.stringify({ calls }));
- const infos = result.results;
- const portalSphere = infos[0].result.response.refillable.find(n => n.id == 45);
- const clanWarMyTries = infos[1].result.response?.myTries ?? 0;
- const arePointsMax = infos[1].result.response?.arePointsMax;
- const titansLevel = +(infos[2].result.response?.tier ?? 0);
- const titansStatus = infos[2].result.response?.status; //peace_time || battle
-
- const sanctuaryButton = buttons['goToSanctuary'].button;
- const clanWarButton = buttons['goToClanWar'].button;
- const titansArenaButton = buttons['testTitanArena'].button;
-
- /*if (portalSphere.amount) {
- sanctuaryButton.style.color = portalSphere.amount >= 3 ? 'red' : 'brown';
- sanctuaryButton.title = `${I18N('SANCTUARY_TITLE')}\n${portalSphere.amount} ${I18N('PORTALS')}`;
- } else {*/
- sanctuaryButton.style.color = '';
- sanctuaryButton.title = I18N('SANCTUARY_TITLE');
- //}
- /*if (clanWarMyTries && !arePointsMax) {
- clanWarButton.style.color = 'red';
- clanWarButton.title = `${I18N('GUILD_WAR_TITLE')}\n${clanWarMyTries}${I18N('ATTEMPTS')}`;
- } else {*/
- clanWarButton.style.color = '';
- clanWarButton.title = I18N('GUILD_WAR_TITLE');
- //}
-
- /*if (titansLevel < 7 && titansStatus == 'battle') {
- const partColor = Math.floor(125 * titansLevel / 7);
- titansArenaButton.style.color = `rgb(255,${partColor},${partColor})`;
- titansArenaButton.title = `${I18N('TITAN_ARENA_TITLE')}\n${titansLevel} ${I18N('LEVEL')}`;
- } else {*/
- titansArenaButton.style.color = '';
- titansArenaButton.title = I18N('TITAN_ARENA_TITLE');
- //}
- //тест убрал подсветку красным в меню
- 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/xNihvr8Ix4sdCCrJja47CVAMFjAwid6eJcQWi8BO4jHQl6AGFjdwwUnOMF75CfCMpoxCTpAoxoZMBgs3qMh7ZODQFYYxgSMsQThCpcK0BiZJNxBCZ7zwhsbYqO3wCoe7AjjCaxAggNUcY94mcDa3qMECWSBHYN0CBfj0IQliEFCMFjkIulAAisUkBZYyB4USxAFCZnkH1xsgltSYCMYyACMpizghS7kOTZIKJMmeYEZzCCH6iCmBS1IRzpkcEsXVMGZMMgHJvfwyoLsYQ9nmMIUuDAFPIAhH8pUZjLbcY89rKKaC9nDFeLxy3vkYwbJTMcL0InOeOSjBVShJz2pqQvPfvrznwANKEMCAgA7';
-
- setProgress('<img src="' + imgPortal + '" style="height: 25px;position: relative;top: 5px;"> ' + `${portalSphere.amount} </br> ${I18N('GUILD_WAR')}: ${clanWarMyTries}`, true);
- resolve();
- });
- }
- // тест сделать все
- /** Отправить подарки мое*/
- function testclanSendDailyGifts() {
-
- send('{"calls":[{"name":"clanSendDailyGifts","args":{},"ident":"clanSendDailyGifts"}]}', e => {
- setProgress('Награды собраны', true);});
- }
- /** Открой сферу артефактов титанов*/
- function testtitanArtifactChestOpen() {
- send('{"calls":[{"name":"titanArtifactChestOpen","args":{"amount":1,"free":true},"ident":"body"}]}',
- isWeCanDo => {
- return info['inventoryGet']?.consumable[55] > 0
- //setProgress('Награды собраны', true);
- });
- }
- /** Воспользуйся призывом питомцев 1 раз*/
- function testpet_chestOpen() {
- send('{"calls":[{"name":"pet_chestOpen","args":{"amount":1,"paid":false},"ident":"pet_chestOpen"}]}',
- isWeCanDo => {
- return info['inventoryGet']?.consumable[90] > 0
- //setProgress('Награды собраны', true);
- });
- }
-
- async function getDailyBonus() {
- const dailyBonusInfo = await Send(JSON.stringify({
- calls: [{
- name: "dailyBonusGetInfo",
- args: {},
- ident: "body"
- }]
- })).then(e => e.results[0].result.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 result = await Send(JSON.stringify({ calls }));
- if (result.error) {
- console.error(result.error);
- return;
- }
-
- const reward = result.results[0].result.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.results[0].result.response.consumable[148]);
-
- /** Добавить другие ящики */
- /**
- * 144 - медная шкатулка
- * 145 - бронзовая шкатулка
- * 148 - платиновая шкатулка
- */
- if (!lootBox) {
- setProgress(I18N('NO_BOXES'), true);
- return;
- }
-
- let maxFarmEnergy = getSaveVal('maxFarmEnergy', 100);
- const result = await popup.confirm(I18N('OPEN_LOOTBOX', { lootBox }), [
- { result: false, isClose: true },
- { msg: I18N('BTN_YES'), result: true },
- { msg: I18N('STAMINA'), isInput: true, default: maxFarmEnergy },
- ]);
-
- if (!+result) {
- return;
- }
-
- if ((typeof result) !== 'boolean' && Number.parseInt(result)) {
- maxFarmEnergy = +result;
- 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.results[0].result.response
- );
- const result = Object.values(response).pop();
- if ('stamina' in result) {
- setProgress(`${I18N('OPEN')}: ${lootBox - count}/${lootBox} ${I18N('STAMINA')} +${result.stamina}<br>${I18N('STAMINA')}: ${collectEnergy}`, false);
- console.log(`${ I18N('STAMINA') } + ${ result.stamina }`);
- if (!maxFarmEnergy) {
- return;
- }
- collectEnergy += +result.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(result);
- }
- }
-
- 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.results.map(n => n.result.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 }), [
- { result: 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.results[0].result.response, true);
- });
- }
-
- async function buyHeroFragments() {
- const result = await Send('{"calls":[{"name":"inventoryGet","args":{},"ident":"inventoryGet"},{"name":"shopGetAll","args":{},"ident":"shopGetAll"}]}')
- .then(e => e.results.map(n => n.result.response));
- const inv = result[0];
- const shops = Object.values(result[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.results.map(n => n.result.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.results.map((n) => n.result.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+ZfjIpKqJWBOd4EDbHagueBPb1tWuesi9Rqn86zJZDbAMTp4xoSFzMaa4FVe6fra3bbzQbYN6A8Cmrz0qoBx8gzMmaj/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/dDyMzfIAj3bqSK8bGW579ECPWXRViHTijDK2BPojcPCxkbXCZflh1H5ISkCCSWJxI8jcjmErhnaHh6fdzdbZTd0aKd7Q+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 = [{ result: false, isClose: true }];
-
- if (currentStarMoney >= cost9chests) {
- buttons.push({
- msg: I18N('BUY_OUTLAND_BTN', { count: 9, countEmerald: cost9chests, imgEmerald }),
- result: [costFirstChest, costFirstChest, 0],
- });
- }
-
- if (currentStarMoney >= cost18chests) {
- buttons.push({
- msg: I18N('BUY_OUTLAND_BTN', { count: 18, countEmerald: cost18chests, imgEmerald }),
- result: [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 result = await Send({ calls });
- console.log(result);
- if (result?.results) {
- count += result.results.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 result = await Send(JSON.stringify({ calls }))
- .then(e => e.results.map(n => n.result.response));
-
- const portalSphere = result[0].refillable.find(n => n.id == 45);
- const adventureRaid = Object.entries(result[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 }), [
- { result: false, isClose: true },
- { msg: I18N('RAID'), isInput: true, default: portalSphere.amount },
- ]));
-
- if (!countRaid) {
- return;
- }
-
- if (countRaid > portalSphere.amount) {
- countRaid = portalSphere.amount;
- }
-
- const resultRaid = await Send(JSON.stringify({
- calls: [...Array(countRaid)].map((e, i) => ({
- name: "adventure_raid",
- args: {
- adventureId
- },
- ident: `body_${i}`
- }))
- })).then(e => e.results.map(n => n.result.response));
-
- if (!resultRaid.length) {
- console.log(resultRaid);
- setProgress(I18N('SOMETHING_WENT_WRONG'), true);
- return;
- }
-
- console.log(resultRaid, adventureId, portalSphere.amount);
- setProgress(I18N('ADVENTURE_COMPLETED', { adventureId, times: resultRaid.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 result = await Send(JSON.stringify({ calls }));
-
- const dataClanInfo = result.results[0].result.response;
- const dataClanStat = result.results[1].result.response;
- const dataClanLog = result.results[2].result.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 result = await Send('{"calls":[{"name":"shopGetAll","args":{},"ident":"body"},{"name":"userGetInfo","args":{},"ident":"userGetInfo"}]}').then(e => e.results.map(n => n.result.response));
- const shops = result[0];
- const user = result[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 resultBuy = await Send(JSON.stringify({ calls })).then(e => e.results.map(n => n.result.response));
- console.log(resultBuy);
- const countBuy = resultBuy.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.results[0].result.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 * 1e3
- const 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?.results[1]?.result?.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.results) {
- if (call.ident.includes('questFarm')) {
- countQuests++;
- } else if (call.ident.includes('questsFarm')) {
- countQuests += Object.keys(call.result.response).length;
- } else if (call.ident.includes('mailFarm')) {
- countMail = Object.keys(call.result.response).length;
- }
-
- const newQuests = call.result.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 results = await Send({ calls }).then((e) => e.results.map((e) => e.result));
- questsIds = [];
- for (const result of results) {
- const newQuests = result.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.results.map(n => n.result.response));
- const refill = teamInfo[2].refillable.find(n => n.id == 52)
- this.time = (refill.lastRefill + 3600) * 1000
- const 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.results.map(n => n.result.response));
-
- const { progress, result } = await Calc(info[1].battle);
- const endResult = await Send(JSON.stringify({ calls: [{ name: "epicBrawl_endBattle", args: { progress, result }, ident: "epicBrawl_endBattle" }, { name: "epicBrawl_getWinStreak", args: {}, ident: "epicBrawl_getWinStreak" }] })).then(e => e.results.map(n => n.result.response));
-
- const resultInfo = endResult[0].result;
- streak = endResult[1];
-
- wins += resultInfo.win;
- coins += resultInfo.reward ? resultInfo.reward.coin[39] : 0;
-
- console.log(endResult[0].result)
- if (endResult[1].progress == endResult[1].nextStage) {
- const farm = await Send('{"calls":[{"name":"epicBrawl_farmWinStreak","args":{},"ident":"body"}]}').then(e => e.results[0].result.response);
- coins += farm.coin[39];
- }
-
- setProgress(I18N('EPIC_BRAWL_RESULT', {
- 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_RESULT', {
- wins, attempts, coins,
- i: '',
- progress: streak.progress,
- nextStage: streak.nextStage,
- end: I18N('ATTEMPT_ENDED', { time }),
- }), false, hideProgress);
- }
- }
- /* тест остановка подземки*/
- function stopDungeon(e) {
- stopDung = true;
- }
-
- function countdownTimer(seconds, message) {
- message = message || I18N('TIMER');
- const stopTimer = Date.now() + seconds * 1e3
- return new Promise(resolve => {
- const interval = setInterval(async () => {
- const now = Date.now();
- setProgress(`${message} ${((stopTimer - now) / 1000).toFixed(2)}`, false);
- if (now > stopTimer) {
- clearInterval(interval);
- setProgress('', 1);
- resolve();
- }
- }, 100);
- });
- }
-
- /** Набить килов в горниле душк */
- 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.results[1].result.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.results[2].result.response).map(e => e.id);
- const heroGetAllList = data.results[0].result.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.results[1].result.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.results[0].result.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?.results?.length + ' наград', true);
- })
- }
- /**
- * Spin the Seer
- *
- * Покрутить провидца
- */
- async function rollAscension() {
- const refillable = await Send({calls:[
- {
- name:"userGetInfo",
- args:{},
- ident:"userGetInfo"
- }
- ]}).then(e => e.results[0].result.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.results[0].result.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.results)
- const msg = I18N('NY_GIFTS_COLLECTED', { count: e.results.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 },
- { result: 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'), result: true },
- { result: 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.results.length }));
- setProgress(I18N('IMPROVED_LEVELS', { count: e.results.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 },
- { result: 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'), result: true },
- { result: 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.results.length }));
- setProgress(I18N('IMPROVED_LEVELS', { count: e.results.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 result = {};
- if (quest?.questionIcon) {
- const info = getQuestionInfo(quest.questionIcon);
- if (info?.heroes) {
- /** Какому герою принадлежит этот артефакт? */
- result.answer = quest.answers.filter(e => info.heroes.includes(e.answerText.slice(1)));
- }
- if (info?.artifact) {
- /** Какой артефакт принадлежит этому герою? */
- result.answer = quest.answers.filter(e => info.artifact.includes(e.answerText.slice(1)));
- }
- if (typeof info == 'string') {
- result.info = { name: info };
- } else {
- result.info = info;
- }
- }
-
- if (quest.answers[0]?.answerIcon) {
- result.answer = quest.answers.filter(e => quest.question.includes(getQuestionInfo(e.answerIcon, true)))
- }
-
- if ((!result?.answer || !result.answer.length) && !result.info?.name) {
- return false;
- }
-
- let resultText = '';
- if (result?.info) {
- resultText += I18N('PICTURE') + result.info.name;
- }
- console.log(result);
- if (result?.answer && result.answer.length) {
- resultText += I18N('ANSWER') + result.answer[0].id + (!result.answer[0].answerIcon ? ' - ' + result.answer[0].answerText : '');
- }
-
- return resultText;
- }
-
- 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.results[0].result.response?.battlePass, gold: true}, ...Object.values(e.results[1].result.response)]);
-
- const calls = passes.map(p => battlePassProcess(p)).flat()
-
- if (!calls.length) {
- setProgress(I18N('NOTHING_TO_COLLECT'));
- return;
- }
-
- let results = await Send({calls});
- if (results.error) {
- console.log(results.error);
- setProgress(I18N('SOMETHING_WENT_WRONG'));
- } else {
- setProgress(I18N('SEASON_REWARD_COLLECTED', {count: results.results.length}), true);
- }
- }
-
- async function sellHeroSoulsForGold() {
- let { fragmentHero, heroes } = await Send({
- calls: [
- { name: 'inventoryGet', args: {}, ident: 'inventoryGet' },
- { name: 'heroGetAll', args: {}, ident: 'heroGetAll' },
- ],
- })
- .then((e) => e.results.map((r) => r.result.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.results.map((r) => r.result?.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() {
- 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.results;
- clanRaidInfo = res[0].result.response;
- teamGetAll = res[1].result.response;
- teamGetFavor = res[2].result.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'), result: true },
- { msg: I18N('BTN_YES'), result: false },
- ])) {
- endRaidNodes('isNotFullPack');
- return;
- }
- }
-
- raidData.nodes = clanRaidInfo.nodes;
- raidData.attempts = clanRaidInfo.attempts;
- isCancalBattle = false;
-
- checkNodes();
- }
-
- function getAttackNode() {
- for (let nodeId in raidData.nodes) {
- let node = raidData.nodes[nodeId];
- let points = 0
- for (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}), resultNodeBattles);
- }
-
- function resultNodeBattles(e) {
- if (e['error']) {
- endRaidNodes('nodeBattlesError', e['error']);
- return;
- }
-
- console.log(e);
- let battles = e.results[0].result.response.battles;
- let promises = [];
- let battleIndex = 0;
- for (let battle of battles) {
- battle.battleIndex = battleIndex++;
- promises.push(calcBattleResult(battle));
- }
-
- Promise.all(promises)
- .then(results => {
- const endResults = {};
- let isAllWin = true;
- for (let r of results) {
- isAllWin &&= r.result.win;
- }
- if (!isAllWin) {
- cancelEndNodeBattle(results[0]);
- return;
- }
- raidData.countExecuteBattles = results.length;
- let timeout = 500;
- for (let r of results) {
- setTimeout(endNodeBattle, timeout, r);
- timeout += 500;
- }
- });
- }
- /**
- * Returns the battle calculation promise
- *
- * Возвращает промис расчета боя
- */
- function calcBattleResult(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.result.nodeId;
- let battleIndex = r.battleData.battleIndex;
- let calls = [{
- name: "clanRaid_endNodeBattle",
- args: {
- nodeId,
- battleIndex,
- result: r.result,
- progress: r.progress
- },
- ident: "body"
- }]
-
- SendRequest(JSON.stringify({calls}), battleResult);
- }
- /**
- * Processing the results of the battle
- *
- * Обработка результатов боя
- */
- function battleResult(e) {
- if (e['error']) {
- endRaidNodes('missionEndError', e['error']);
- return;
- }
- r = e.results[0].result.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) {
- isCancalBattle = true;
- let textCancel = raidData.cancelBattle ? ` ${I18N('BATTLES_CANCELED')}: ${raidData.cancelBattle}` : '';
- setProgress(`${I18N('MINION_RAID')} ${I18N('COMPLETED')}! ${textCancel}`, true);
- console.log(reason, info);
- resolve();
- }
- }
-
- /**
- * Asgard Boss Attack Replay
- *
- * Повтор атаки босса Асгарда
- */
- function testBossBattle() {
- 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(resultPreCalcBattle);
- }
-
- async function resultPreCalcBattle(damages) {
- let maxDamage = 0;
- let minDamage = 1e10;
- let avgDamage = 0;
- for (let damage of damages) {
- avgDamage += damage
- if (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'), result: 0},
- ])
- endBossBattle(I18N('BTN_CANCEL'));
- }
-
- /**
- * Completing a task
- *
- * Завершение задачи
- */
- function endBossBattle(reason, info) {
- console.log(reason, info);
- resolve();
- }
- }
-
- 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.bestResult = {
- count: 0,
- timer: 0,
- value: 0,
- result: null,
- progress: null,
- };
- this.lastBattleResult = {
- 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.bestResult.maxCount = this.count;
- this.worker.terminate();
- this.resolve(this.bestResult);
- }
-
- async loop() {
- const start = Date.now();
- if (this.isEndLoop()) {
- this.endFix();
- return;
- }
- this.count++;
- try {
- this.lastResult = await Calc(this.battle);
- } catch (e) {
- this.updateProgressTimer(this.index++);
- this.timeout(this.loop.bind(this), 0);
- return;
- }
- const { progress, result } = this.lastResult;
- this.lastBattleResult = result;
- this.lastBattleProgress = progress;
- this.setAvgTime(start);
- this.checkResult();
- this.showResult();
- 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] } }];
- }
-
- showResult() {
- console.log(
- this.count,
- this.avgTime.toFixed(2),
- (this.endTime - Date.now()) / 1000,
- this.lastTimer.toFixed(2),
- this.lastBossDamage.toLocaleString(),
- this.bestResult.value.toLocaleString()
- );
- }
-
- checkResult() {
- const { damageTaken, damageTakenNextLevel } = this.lastBattleProgress[0].defenders.heroes[1].extra;
- this.lastBossDamage = damageTaken + damageTakenNextLevel;
- if (this.lastBossDamage > this.bestResult.value) {
- this.bestResult = {
- count: this.count,
- timer: this.lastTimer,
- value: this.lastBossDamage,
- result: structuredClone(this.lastBattleResult),
- progress: structuredClone(this.lastBattleProgress),
- };
- }
- }
-
- stopFix() {
- this.endTime = 0;
- }
- }
-
- class WinFixBattle extends FixBattle {
- checkResult() {
- if (this.lastBattleResult.win) {
- this.bestResult = {
- count: this.count,
- timer: this.lastTimer,
- value: this.lastBattleResult.stars,
- result: structuredClone(this.lastBattleResult),
- progress: structuredClone(this.lastBattleProgress),
- battleTimer: this.lastResult.battleTimer,
- };
- }
- }
-
- setWinTimer(value) {
- this.winTimer = value;
- }
-
- setMaxTimer(value) {
- this.maxTimer = value;
- }
-
- randTimer() {
- const min = 1.3;
- const max = 30.3;
- return Math.random() * (max - min + 1) + min;
- }
-
- isEndLoop() {
- return super.isEndLoop() || this.bestResult.result?.win;
- }
-
- showResult() {
- console.log(
- this.count,
- this.avgTime.toFixed(2),
- (this.endTime - Date.now()) / 1000,
- this.lastResult.battleTime,
- this.lastTimer,
- this.bestResult.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));
- }
- }
-
- class BestOrWinFixBattle extends WinFixBattle {
- isNoMakeWin = false;
-
- getState(result) {
- let beforeSumFactor = 0;
- const beforeHeroes = result.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;
- }
- beforeSumFactor += factor;
- }
-
- let afterSumFactor = 0;
- const afterHeroes = result.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 / beforeSumFactor) * 1e4) / 100;
- }
-
- setNoMakeWin(value) {
- this.isNoMakeWin = value;
- }
-
- checkResult() {
- const state = this.getState(this.lastResult);
- console.log(state);
-
- if (state > this.bestResult.value) {
- if (!(this.isNoMakeWin && this.lastBattleResult.win)) {
- this.bestResult = {
- count: this.count,
- timer: this.lastTimer,
- value: state,
- result: structuredClone(this.lastBattleResult),
- progress: structuredClone(this.lastBattleProgress),
- battleTimer: this.lastResult.battleTimer,
- };
- }
- }
- }
- }
-
- class BossFixBattle extends FixBattle {
- showResult() {
- super.showResult();
- //setTimeout(() => {
- const best = this.bestResult;
- 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);
- }
- }
-
- class DungeonFixBattle extends FixBattle {
- init() {
- super.init();
- this.isTimeout = false;
- }
-
- setState() {
- const result = this.lastResult;
- let beforeSumFactor = 0;
- const beforeHeroes = result.battleData.attackers;
- 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;
- }
- beforeSumFactor += factor;
- }
-
- let afterSumFactor = 0;
- const afterHeroes = result.progress[0].attackers.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;
- }
- this.lastState = Math.floor((afterSumFactor / beforeSumFactor) * 1e4) / 100;
- }
-
- checkResult() {
- this.setState();
- if (this.lastResult.result.win && this.lastState > this.bestResult.value) {
- this.bestResult = {
- count: this.count,
- timer: this.lastTimer,
- value: this.lastState,
- result: this.lastResult.result,
- progress: this.lastResult.progress,
- };
- }
- }
-
- showResult() {
- console.log(
- this.count,
- this.avgTime.toFixed(2),
- (this.endTime - Date.now()) / 1000,
- this.lastTimer.toFixed(2),
- this.lastState.toLocaleString(),
- this.bestResult.value.toLocaleString()
- );
- }
- }
-
- 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.bestResult.value) {
- this.bestResult = solution;
- }
- }
- this.count = maxCount;
- super.endFix();
- }
- }
-
- Object.assign(masterFixBattle.prototype, masterWsMixin);
- 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.bestResult.value) {
- this.bestResult = solution;
- }
- }
- this.count = maxCount;
- super.endFix();
- }
- }
-
- Object.assign(masterWinFixBattle.prototype, masterWsMixin);
-
- 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);
-
- class slaveWinFixBattle extends WinFixBattle {
- constructor(url = 'wss://localho.st:3000') {
- super(null, false);
- this.isTimeout = false;
- this.url = url;
- }
- }
-
- Object.assign(slaveWinFixBattle.prototype, slaveWsMixin);
- /**
- * Auto-repeat attack
- *
- * Автоповтор атаки
- */
- function testAutoBattle() {
- 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(resultPreCalcBattle);
- }
- /**
- * Processing the results of the battle recalculation
- *
- * Обработка результатов прерасчета боя
- */
- async function resultPreCalcBattle(results) {
- let countWin = results.reduce((s, w) => w.result.win + s, 0);
- setProgress(`${I18N('CHANCE_TO_WIN')} ${Math.floor(countWin / results.length * 100)}% (${results.length})`, false, hideProgress);
- if (countWin > 0) {
- isCancalBattle = false;
- startBattle();
- return;
- }
-
- let minCoeff = 100;
- let maxCoeff = -100;
- let avgCoeff = 0;
- results.forEach(e => {
- if (e.coeff < minCoeff) minCoeff = e.coeff;
- if (e.coeff > maxCoeff) maxCoeff = e.coeff;
- avgCoeff += e.coeff;
- });
- avgCoeff /= results.length;
-
- if (nameFuncStartBattle == 'invasion_bossStart' ||
- nameFuncStartBattle == 'bossAttack') {
- const result = await popup.confirm(
- I18N('BOSS_VICTORY_IMPOSSIBLE', { battles: results.length }), [
- { msg: I18N('BTN_CANCEL'), result: false, isCancel: true },
- { msg: I18N('BTN_DO_IT'), result: true },
- ])
- if (result) {
- isCancalBattle = false;
- startBattle();
- return;
- }
- setProgress(I18N('NOT_THIS_TIME'), true);
- endAutoBattle('invasion_bossStart');
- return;
- }
-
- const result = await popup.confirm(
- I18N('VICTORY_IMPOSSIBLE') +
- `<br>${I18N('ROUND_STAT')} ${results.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'), result: 0, isCancel: true },
- { msg: I18N('BTN_GO'), isInput: true, default: Math.round(avgCoeff * 1000) / 1000 },
- ])
- if (result) {
- findCoeff = result;
- isCancalBattle = false;
- startBattle();
- return;
- }
- setProgress(I18N('NOT_THIS_TIME'), true);
- endAutoBattle(I18N('NOT_THIS_TIME'));
- }
-
- /**
- * Calculation of the combat result coefficient
- *
- * Расчет коэфициента результата боя
- */
- function calcCoeff(result, packType) {
- let beforeSumFactor = 0;
- const beforePack = result.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;
- }
- beforeSumFactor += factor;
- }
-
- let afterSumFactor = 0;
- const afterPack = result.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 resultCoeff = -(afterSumFactor - beforeSumFactor);
- return Math.round(resultCoeff * 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"
- }]}, calcResultBattle);
- }
- /**
- * Battle calculation
- *
- * Расчет боя
- */
- async function calcResultBattle(e) {
- if ('error' in e) {
- if (e.error.description === 'too many tries') {
- invasionTimer += 100;
- countBattle--;
- countError++;
- console.log(`Errors: ${countError}`, e.error);
- startBattle();
- return;
- }
- const result = await popup.confirm(I18N('ERROR_DURING_THE_BATTLE') + '<br>' + e.error.description, [
- { msg: I18N('BTN_OK'), result: false },
- { msg: I18N('RELOAD_GAME'), result: true },
- ]);
- endAutoBattle('Error', e.error);
- if (result) {
- location.reload();
- }
- return;
- }
- let battle = e.results[0].result.response.battle
- if (nameFuncStartBattle == 'towerStartBattle' ||
- nameFuncStartBattle == 'bossAttack' ||
- nameFuncStartBattle == 'invasion_bossStart') {
- battle = e.results[0].result.response;
- }
- lastBattleInfo = battle;
- BattleCalc(battle, getBattleType(battle.type), resultBattle);
- }
- /**
- * Processing the results of the battle
- *
- * Обработка результатов боя
- */
- async function resultBattle(e) {
- const isWin = e.result.win;
- if (isWin) {
- endBattle(e, false);
- return;
- } else if (isChecked('tryFixIt_v2')) {
- 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:`, [
- { result: 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 result = await bFix.start(endTime, attempts);
- console.log(result);
- if (result.value) {
- endBattle(result, 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(battleResult, isCancal) {
- let calls = [{
- name: nameFuncEndBattle,
- args: {
- result: battleResult.result,
- progress: battleResult.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: ' + battleResult.progress[0].attackers.input[5];
- }
-
- const result = await popup.confirm(
- I18N('BOSS_HAS_BEEN_DEF_TEXT', {
- bossLvl: `${svgBoss} ${bossLvl} ${svgJustice} ${justice}`,
- countBattle: svgAttempt + ' ' + countBattle,
- countMaxBattle,}),
- winTimer,
- [
- { msg: I18N('BTN_OK'), result: 0 },
- { msg: I18N('MAKE_A_SYNC'), result: 1 },
- { msg: I18N('RELOAD_GAME'), result: 2 },
- ]);
- if (result) {
- if (result == 1) {
- cheats.refreshGame();
- }
- if (result == 2) {
- location.reload();
- }
- }
-
- }
- endAutoBattle(`${I18N('SUCCESS')}!`)
- });
- }
- /**
- * Completing a task
- *
- * Завершение задачи
- */
- function endAutoBattle(reason, info) {
- isCancalBattle = true;
- console.log(reason, info);
- resolve();
- }
- }
-
- function testDailyQuests() {
- 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 result = await Send(JSON.stringify({ calls })).then((e) => e.results);
- for (const call of result) {
- quests[call.ident] = call.result.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'), result: true },
- { msg: I18N('BTN_CANCEL'), result: 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 result = await Send(JSON.stringify({ calls }));
- if (result.error) {
- console.error(result.error, result.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;
-
- function testDoYourBest() {
- 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: 'testclanSendDailyGifts',
- label: I18N('QUEST_10016'),
- checked: false
- },
- //получить подарки
- /*{
- name: 'getGift',
- label: I18N('NY_GIFTS'),
- checked: false
- },*/
- //собрать новогодние подарки
- /*{
- name: 'getGiftNewYear',
- label: I18N('NY_GIFTS'),
- checked: false
- },*/
- // тест сферу титанов
- /*{
- name: 'testtitanArtifactChestOpen',
- label: I18N('QUEST_10029'),
- checked: false
- },
- // тест призыв петов
- {
- name: 'testpet_chestOpen',
- label: I18N('QUEST_10044'),
- checked: false
- },*/
- //пройти подземелье обычное
- {
- name: 'testDungeon',
- label: I18N('COMPLETE_DUNGEON'),
- checked: false
- },
- //пройти подземелье для фуловых титанов
- {
- name: 'DungeonFull',
- label: I18N('COMPLETE_DUNGEON_FULL'),
- 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,//Собрать все награды за задания
- testclanSendDailyGifts, //отправить подарки
- /*getGift: async () => {
- const collector = new GiftCodeCollector();
- const giftCodes = await collector.getGiftCodes();
- console.log(giftCodes);
-
- for (const key of giftCodes)
- send({ calls: [{ name: "registration", args: { giftId:key, user: { referrer: {} } },
- context: { actionTs: Math.floor(performance.now()), cookie: window?.NXAppInfo?.session_id || null }, ident: "body" }] });
- },*/
- getGiftNewYear,//собрать новогодние подарки
- testtitanArtifactChestOpen, //открой сферу титанов
- testpet_chestOpen, //Воспользуйся призывом питомцев 1 раз
- testDungeon,//подземка обычная
- DungeonFull,//подземка для фуловых титанов
- 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'), result: false, isCancel: true },
- { msg: I18N('BTN_GO'), result: 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'), result: false },
- { msg: I18N('BTN_YES'), result: 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();
- }
- }
-
- /**
- * Passing the adventure along the specified route
- *
- * Прохождение приключения по указанному маршруту
- */
- function testAdventure(type) {
- return new Promise((resolve, reject) => {
- const bossBattle = new executeAdventure(resolve, reject);
- bossBattle.start(type);
- });
- }
-
- //Буря
- function testAdventure2(solo) {
- return new Promise((resolve, reject) => {
- const bossBattle = new executeAdventure2(resolve, reject);
- bossBattle.start(solo);
- });
- }
-
- /**
- * 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"
- }
- //тест прикла
- defaultWays = {
- //Галахад, 1-я
- "adv_strongford_2pl_easy": {
- first: '1,2,3,5,6',
- second: '1,2,4,7,6',
- third: '1,2,3,5,6'
- },
- //Джинджер, 2-я
- "adv_valley_3pl_easy": {
- first: '1,2,5,8,9,11',
- second: '1,3,6,9,11',
- third: '1,4,7,10,9,11'
- },
- //Орион, 3-я
- "adv_ghirwil_3pl_easy": {
- first: '1,5,6,9,11',
- second: '1,4,12,13,11',
- third: '1,2,3,7,10,11'
- },
- //Тесак, 4-я
- "adv_angels_3pl_easy_fire": {
- first: '1,2,4,7,18,8,12,19,22,23',
- second: '1,3,6,11,17,10,16,21,22,23',
- third: '1,5,24,25,9,14,15,20,22,23'
- },
- //Галахад, 5-я
- "adv_strongford_3pl_normal_2": {
- first: '1,2,7,8,12,16,23,26,25,21,24',
- second: '1,4,6,10,11,15,22,15,19,18,24',
- third: '1,5,9,10,14,17,20,27,25,21,24'
- },
- //Джинджер, 6-я
- "adv_valley_3pl_normal": {
- first: '1,2,4,7,10,13,16,19,24,22,25',
- second: '1,3,6,9,12,15,18,21,26,23,25',
- third: '1,5,7,8,11,14,17,20,22,25'
- },
- //Орион, 7-я
- "adv_ghirwil_3pl_normal_2": {
- first: '1,11,10,11,12,15,12,11,21,25,27',
- second: '1,7,3,4,3,6,13,19,20,24,27',
- third: '1,8,5,9,16,23,22,26,27'
- },
- //Тесак, 8-я
- "adv_angels_3pl_normal": {
- first: '1,3,4,8,7,9,10,13,17,16,20,22,23,31,32',
- second: '1,3,5,7,8,11,14,18,20,22,24,27,30,26,32',
- third: '1,3,2,6,7,9,11,15,19,20,22,21,28,29,25'
- },
- //Галахад, 9-я
- "adv_strongford_3pl_hard_2": {
- first: '1,2,6,10,15,7,16,17,23,22,27,32,35,37,40,45',
- second: '1,3,8,12,11,18,19,28,34,33,38,41,43,46,45',
- third: '1,2,5,9,14,20,26,21,30,36,39,42,44,45'
- },
- //Джинджер, 10-я
- "adv_valley_3pl_hard": {
- first: '1,3,2,6,11,17,25,30,35,34,29,24,21,17,12,7',
- second: '1,4,8,13,18,22,26,31,36,40,45,44,43,38,33,28',
- third: '1,5,9,14,19,23,27,32,37,42,48,51,50,49,46,52'
- },
- //Орион, 11-я
- "adv_ghirwil_3pl_hard": {
- first: '1,2,3,6,8,12,11,15,21,27,36,34,33,35,37',
- second: '1,2,4,6,9,13,18,17,16,22,28,29,30,31,25,19',
- third: '1,2,5,6,10,13,14,20,26,32,38,41,40,39,37'
- },
- //Тесак, 12-я
- "adv_angels_3pl_hard": {
- first: '1,2,8,11,7,4,7,16,23,32,33,25,34,29,35,36',
- second: '1,3,9,13,10,6,10,22,31,30,21,30,15,28,20,27',
- third: '1,5,12,14,24,17,24,25,26,18,19,20,27'
- },
- //Тесак, 13-я
- "adv_angels_3pl_hell": {
- first: '1,2,4,6,16,23,33,34,25,32,29,28,20,27',
- second: '1,7,11,17,24,14,26,18,19,20,27,20,12,8',
- third: '1,9,3,5,10,22,31,36,31,30,15,28,29,30,21,13'
- },
- //Галахад, 13-я
- "adv_strongford_3pl_hell": {
- first: '1,2,5,11,14,20,26,21,30,35,38,41,43,44',
- second: '1,2,6,12,15,7,16,17,23,22,27,42,34,36,39,44',
- third: '1,3,8,9,13,18,19,28,0,33,37,40,32,45,44'
- },
- //Орион, 13-я
- "adv_ghirwil_3pl_hell": {
- first: '1,2,3,6,8,12,11,15,21,27,36,34,33,35,37',
- second: '1,2,4,6,9,13,18,17,16,22,28,29,30,31,25,19',
- third: '1,2,5,6,10,13,14,20,26,32,38,41,40,39,37'
- },
- //Джинджер, 13-я
- "adv_valley_3pl_hell": {
- first: '1,3,2,6,11,17,25,30,35,34,29,24,21,17,12,7',
- second: '1,4,8,13,18,22,26,31,36,40,45,44,43,38,33,28',
- third: '1,5,9,14,19,23,27,32,37,42,48,51,50,49,46,52'
- }
- }
- callStartBattle = {
- name: "adventure_turnStartBattle",
- args: {},
- ident: "body"
- }
- callEndBattle = {
- name: "adventure_endBattle",
- args: {
- result: {},
- 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
- ]
- }));
- //тест прикла1
- this.path = await this.getPath(data.results[0].result.response.mapIdent);
- if (!this.path) {
- this.end();
- return;
- }
- return this.checkAdventureInfo(data.results);
- }
-
- async getPath(mapId) {
- //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)
- default: getSaveVal('adventurePath', '')
- },
- {
- msg: ' Начать по пути №1! ',
- placeholder: '1,2,3',
- isInput: true,
- default: this.defaultWays[mapId]?.first
- },
- {
- msg: ' Начать по пути №2! ',
- placeholder: '1,2,3',
- isInput: true,
- default: this.defaultWays[mapId]?.second
- },
- {
- msg: ' Начать по пути №3! ',
- placeholder: '1,2,3',
- isInput: true,
- default: this.defaultWays[mapId]?.third
- },
- {
- msg: I18N('BTN_CANCEL'),
- result: 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);
- setSaveVal('adventurePath', 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].result.response;
- if (!this.advInfo) {
- this.terminatеReason = I18N('NOT_ON_AN_ADVENTURE') ;
- return this.end();
- }
- const heroesTeam = data[1].result.response.adventure_hero;
- const favor = data[2]?.result.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'), result: false },
- { msg: I18N('BTN_NO'), result: 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
- *
- * Отключаем штатную отменую боя
- */
- isCancalBattle = false;
- if (await this.battle(toPath)) {
- this.turnsLeft--;
- toPath.splice(0, toPath.indexOf(nodeId));
- nodeInfo.state = 'empty';
- isCancalBattle = true;
- continue;
- }
- isCancalBattle = 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.results[0].result.response.battle;
- const result = await Calc(battle);
- if (result.result.win) {
- const info = await this.endBattle(result);
- if (info.results[0].result.response?.error) {
- this.terminatеReason = I18N('BATTLE_END_ERROR');
- return false;
- }
- } else {
- await this.cancelBattle(result);
-
- 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 result = await this.battle(path, false);
- if (result) {
- 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'), result: false },
- { msg: I18N('BTN_YES'), result: 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 result = await Calc(battle);
- if (result.result.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.args
- const 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.result = battle.result
- this.callEndBattle.args.progress = battle.progress
- const 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() {
- isCancalBattle = true;
- setProgress(this.terminatеReason, true);
- console.log(this.terminatеReason);
- this.resolve();
- }
- }
- class executeAdventure2 {
-
- 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: {
- result: {},
- 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.results);
- }
-
- 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'),
- result: 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].result.response;
- if (!this.advInfo) {
- this.terminatеReason = I18N('NOT_ON_AN_ADVENTURE') ;
- return this.end();
- }
- const heroesTeam = data[1].result.response.adventure_hero;
- const favor = data[2]?.result.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'), result: false },
- { msg: I18N('BTN_NO'), result: 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
- *
- * Отключаем штатную отменую боя
- */
- isCancalBattle = false;
- if (await this.battle(toPath)) {
- this.turnsLeft--;
- toPath.splice(0, toPath.indexOf(nodeId));
- nodeInfo.state = 'empty';
- isCancalBattle = true;
- continue;
- }
- isCancalBattle = 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.results[0].result.response.battle;
- const result = await Calc(battle);
- if (result.result.win) {
- const info = await this.endBattle(result);
- if (info.results[0].result.response?.error) {
- this.terminatеReason = I18N('BATTLE_END_ERROR');
- return false;
- }
- } else {
- await this.cancelBattle(result);
-
- 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 result = await this.battle(path, false);
- if (result) {
- 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'), result: false },
- { msg: I18N('BTN_YES'), result: 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 result = await Calc(battle);
- if (result.result.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.args
- const 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.result = battle.result
- this.callEndBattle.args.progress = battle.progress
- const 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() {
- isCancalBattle = true;
- setProgress(this.terminatеReason, true);
- console.log(this.terminatеReason);
- this.resolve();
- }
- }
- /**
- * Passage of brawls
- *
- * Прохождение потасовок
- */
- function testBrawls(isAuto) {
- 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;
- isCancalBattle = 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 result = await this.questFarm();
- console.log(result);
- }
-
- 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'), result: true },
- { msg: I18N('BTN_YES'), result: 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 result = await this.battle(enemie.userId);
- this.brawlInfo = {
- questInfo: result[1].result.response,
- findEnemies: result[2].result.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 result = await Calc(battle);
- stat.win += result.result.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 result = await Calc(battle);
- if (result.result.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 result = await Send(JSON.stringify({ calls }));
- return result.results[0].result.response;
- }
-
- async getBrawlInfo() {
- const data = await Send(JSON.stringify({
- calls: [
- this.callUserGetInfo,
- this.callBrawlQuestGetInfo,
- this.callBrawlFindEnemies,
- this.callTeamGetMaxUpgrade,
- this.callBrawlGetInfo,
- ]
- }));
-
- let attempts = data.results[0].result.response.refillable.find(n => n.id == 48);
-
- const maxUpgrade = data.results[3].result.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.results[4].result.response;
- this.mandatoryId = lib.data.brawl.promoHero[this.info.id].promoHero;
- return {
- attempts: attempts.amount,
- questInfo: data.results[1].result.response,
- findEnemies: data.results[2].result.response,
- }
- }
-
- /**
- * Carrying out a fight
- *
- * Проведение боя
- */
- async battle(userId) {
- this.stats.count++;
- const battle = await this.startBattle(userId, this.args);
- const result = await Calc(battle);
- console.log(result.result);
- if (result.result.win) {
- this.stats.win++;
- } else {
- this.stats.loss++;
- if (!this.info.boughtEndlessLivesToday) {
- this.attempts--;
- }
- }
- return await this.endBattle(result);
- // return await this.cancelBattle(result);
- }
-
- /**
- * Starts a fight
- *
- * Начинает бой
- */
- async startBattle(userId, args) {
- const call = {
- name: "brawl_startBattle",
- args,
- ident: "brawl_startBattle"
- }
- call.args.userId = userId;
- const calls = [call];
- const result = await Send(JSON.stringify({ calls }));
- return result.results[0].result.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: {
- result: battle.result,
- progress: battle.progress
- },
- ident: "brawl_endBattle"
- },
- this.callBrawlQuestGetInfo,
- this.callBrawlFindEnemies,
- ];
- const result = await Send(JSON.stringify({ calls }));
- return result.results;
- }
-
- end(endReason) {
- isCancalBattle = true;
- isBrawlsAutoStart = false;
- setProgress(endReason, true);
- console.log(endReason);
- this.resolve();
- }
- }
-
- // подземку вконце впихнул
- function DungeonFull() {
- return new Promise((resolve, reject) => {
- const dung = new executeDungeon2(resolve, reject);
- const titanit = getInput('countTitanit');
- dung.start(titanit);
- });
- }
- /** Прохождение подземелья */
- function executeDungeon2(resolve, reject) {
- let dungeonActivity = 0;
- let startDungeonActivity = 0;
- let maxDungeonActivity = 150;
- let limitDungeonActivity = 30180;
- let countShowStats = 1;
- //let fastMode = isChecked('fastMode');
- let end = false;
-
- let countTeam = [];
- let timeDungeon = {
- all: new Date().getTime(),
- findAttack: 0,
- attackNeutral: 0,
- attackEarthOrFire: 0
- }
-
- let titansStates = {};
- let bestBattle = {};
-
- let teams = {
- neutral: [],
- water: [],
- earth: [],
- fire: [],
- hero: []
- }
-
- //тест
- let talentMsg = '';
- let talentMsgReward = ''
-
- let callsExecuteDungeon = {
- calls: [{
- name: "dungeonGetInfo",
- args: {},
- ident: "dungeonGetInfo"
- }, {
- name: "teamGetAll",
- args: {},
- ident: "teamGetAll"
- }, {
- name: "teamGetFavor",
- args: {},
- ident: "teamGetFavor"
- }, {
- name: "clanGetInfo",
- args: {},
- ident: "clanGetInfo"
- }]
- }
-
- this.start = async function(titanit) {
- //maxDungeonActivity = titanit > limitDungeonActivity ? limitDungeonActivity : titanit;
- maxDungeonActivity = titanit || getInput('countTitanit');
- send(JSON.stringify(callsExecuteDungeon), startDungeon);
- }
-
- /** Получаем данные по подземелью */
- function startDungeon(e) {
- stopDung = false; // стоп подземка
- let res = e.results;
- let dungeonGetInfo = res[0].result.response;
- if (!dungeonGetInfo) {
- endDungeon('noDungeon', res);
- return;
- }
- console.log("Начинаем копать на фулл: ", new Date());
- let teamGetAll = res[1].result.response;
- let teamGetFavor = res[2].result.response;
- dungeonActivity = res[3].result.response.stat.todayDungeonActivity;
- startDungeonActivity = res[3].result.response.stat.todayDungeonActivity;
- titansStates = dungeonGetInfo.states.titans;
-
- teams.hero = {
- favor: teamGetFavor.dungeon_hero,
- heroes: teamGetAll.dungeon_hero.filter(id => id < 6000),
- teamNum: 0,
- }
- let heroPet = teamGetAll.dungeon_hero.filter(id => id >= 6000).pop();
- if (heroPet) {
- teams.hero.pet = heroPet;
- }
- teams.neutral = getTitanTeam('neutral');
- teams.water = {
- favor: {},
- heroes: getTitanTeam('water'),
- teamNum: 0,
- };
- teams.earth = {
- favor: {},
- heroes: getTitanTeam('earth'),
- teamNum: 0,
- };
- teams.fire = {
- favor: {},
- heroes: getTitanTeam('fire'),
- teamNum: 0,
- };
-
- checkFloor(dungeonGetInfo);
- }
-
- function getTitanTeam(type) {
- switch (type) {
- case 'neutral':
- return [4023, 4022, 4012, 4021, 4011, 4010, 4020];
- case 'water':
- return [4000, 4001, 4002, 4003]
- .filter(e => !titansStates[e]?.isDead);
- case 'earth':
- return [4020, 4022, 4021, 4023]
- .filter(e => !titansStates[e]?.isDead);
- case 'fire':
- return [4010, 4011, 4012, 4013]
- .filter(e => !titansStates[e]?.isDead);
- }
- }
-
- /** Создать копию объекта */
- function clone(a) {
- return JSON.parse(JSON.stringify(a));
- }
-
- /** Находит стихию на этаже */
- function findElement(floor, element) {
- for (let i in floor) {
- if (floor[i].attackerType === element) {
- return i;
- }
- }
- return undefined;
- }
-
- /** Проверяем этаж */
- async function checkFloor(dungeonInfo) {
- if (!('floor' in dungeonInfo) || dungeonInfo.floor?.state == 2) {
- saveProgress();
- return;
- }
- checkTalent(dungeonInfo);
- // console.log(dungeonInfo, dungeonActivity);
- setProgress(`${I18N('DUNGEON2')}: ${I18N('TITANIT')} ${dungeonActivity}/${maxDungeonActivity} ${talentMsg}`);
- //setProgress('Dungeon: Титанит ' + dungeonActivity + '/' + maxDungeonActivity);
- if (dungeonActivity >= maxDungeonActivity) {
- endDungeon('Стоп подземка,', 'набрано титанита: ' + dungeonActivity + '/' + maxDungeonActivity);
- return;
- }
- let activity = dungeonActivity - startDungeonActivity;
- titansStates = dungeonInfo.states.titans;
- if (stopDung){
- endDungeon('Стоп подземка,', 'набрано титанита: ' + dungeonActivity + '/' + maxDungeonActivity);
- return;
- }
- /*if (activity / 1000 > countShowStats) {
- countShowStats++;
- showStats();
- }*/
- bestBattle = {};
- let floorChoices = dungeonInfo.floor.userData;
- if (floorChoices.length > 1) {
- for (let element in teams) {
- let teamNum = findElement(floorChoices, element);
- if (!!teamNum) {
- if (element == 'earth') {
- teamNum = await chooseEarthOrFire(floorChoices);
- if (teamNum < 0) {
- endDungeon('Невозможно победить без потери Титана!', dungeonInfo);
- return;
- }
- }
- chooseElement(floorChoices[teamNum].attackerType, teamNum);
- return;
- }
- }
- } else {
- chooseElement(floorChoices[0].attackerType, 0);
- }
- }
- //тест черепахи
- 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.results[0].result.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>`;
- }
-
- /** Выбираем огнем или землей атаковать */
- async function chooseEarthOrFire(floorChoices) {
- bestBattle.recovery = -11;
- let selectedTeamNum = -1;
- for (let attempt = 0; selectedTeamNum < 0 && attempt < 4; attempt++) {
- for (let teamNum in floorChoices) {
- let attackerType = floorChoices[teamNum].attackerType;
- selectedTeamNum = await attemptAttackEarthOrFire(teamNum, attackerType, attempt);
- }
- }
- console.log("Выбор команды огня или земли: ", selectedTeamNum < 0 ? "не сделан" : floorChoices[selectedTeamNum].attackerType);
- return selectedTeamNum;
- }
-
- /** Попытка атаки землей и огнем */
- async function attemptAttackEarthOrFire(teamNum, attackerType, attempt) {
- let start = new Date();
- let team = clone(teams[attackerType]);
- let startIndex = team.heroes.length + attempt - 4;
- if (startIndex >= 0) {
- team.heroes = team.heroes.slice(startIndex);
- let recovery = await getBestRecovery(teamNum, attackerType, team, 25);
- if (recovery > bestBattle.recovery) {
- bestBattle.recovery = recovery;
- bestBattle.selectedTeamNum = teamNum;
- bestBattle.team = team;
- }
- }
- let workTime = new Date().getTime() - start.getTime();
- timeDungeon.attackEarthOrFire += workTime;
- if (bestBattle.recovery < -10) {
- return -1;
- }
- return bestBattle.selectedTeamNum;
- }
-
- /** Выбираем стихию для атаки */
- async function chooseElement(attackerType, teamNum) {
- let result;
- switch (attackerType) {
- case 'hero':
- case 'water':
- result = await startBattle(teamNum, attackerType, teams[attackerType]);
- break;
- case 'earth':
- case 'fire':
- result = await attackEarthOrFire(teamNum, attackerType);
- break;
- case 'neutral':
- result = await attackNeutral(teamNum, attackerType);
- }
- if (!!result && attackerType != 'hero') {
- let recovery = (!!!bestBattle.recovery ? 10 * getRecovery(result) : bestBattle.recovery) * 100;
- let titans = result.progress[0].attackers.heroes;
- console.log("Проведен бой: " + attackerType +
- ", recovery = " + (recovery > 0 ? "+" : "") + Math.round(recovery) + "% \r\n", titans);
- }
- endBattle(result);
- }
-
- /** Атакуем Землей или Огнем */
- async function attackEarthOrFire(teamNum, attackerType) {
- if (!!!bestBattle.recovery) {
- bestBattle.recovery = -11;
- let selectedTeamNum = -1;
- for (let attempt = 0; selectedTeamNum < 0 && attempt < 4; attempt++) {
- selectedTeamNum = await attemptAttackEarthOrFire(teamNum, attackerType, attempt);
- }
- if (selectedTeamNum < 0) {
- endDungeon('Невозможно победить без потери Титана!', attackerType);
- return;
- }
- }
- return findAttack(teamNum, attackerType, bestBattle.team);
- }
-
- /** Находим подходящий результат для атаки */
- async function findAttack(teamNum, attackerType, team) {
- let start = new Date();
- let recovery = -1000;
- let iterations = 0;
- let result;
- let correction = 0.01;
- for (let needRecovery = bestBattle.recovery; recovery < needRecovery; needRecovery -= correction, iterations++) {
- result = await startBattle(teamNum, attackerType, team);
- recovery = getRecovery(result);
- }
- bestBattle.recovery = recovery;
- let workTime = new Date().getTime() - start.getTime();
- timeDungeon.findAttack += workTime;
- return result;
- }
-
- /** Атакуем Нейтральной командой */
- async function attackNeutral(teamNum, attackerType) {
- let start = new Date();
- let factors = calcFactor();
- bestBattle.recovery = -0.2;
- await findBestBattleNeutral(teamNum, attackerType, factors, true)
- if (bestBattle.recovery < 0 || (bestBattle.recovery < 0.2 && factors[0].value < 0.5)) {
- let recovery = 100 * bestBattle.recovery;
- console.log("Не удалось найти удачный бой в быстром режиме: " + attackerType +
- ", recovery = " + (recovery > 0 ? "+" : "") + Math.round(recovery) + "% \r\n", bestBattle.attackers);
- await findBestBattleNeutral(teamNum, attackerType, factors, false)
- }
- let workTime = new Date().getTime() - start.getTime();
- timeDungeon.attackNeutral += workTime;
- if (!!bestBattle.attackers) {
- let team = getTeam(bestBattle.attackers);
- return findAttack(teamNum, attackerType, team);
- }
- endDungeon('Не удалось найти удачный бой!', attackerType);
- return undefined;
- }
-
- /** Находит лучшую нейтральную команду */
- async function findBestBattleNeutral(teamNum, attackerType, factors, mode) {
- let countFactors = factors.length < 4 ? factors.length : 4;
- let aradgi = !titansStates['4013']?.isDead;
- let edem = !titansStates['4023']?.isDead;
- let dark = [4032, 4033].filter(e => !titansStates[e]?.isDead);
- let light = [4042].filter(e => !titansStates[e]?.isDead);
- let actions = [];
- if (mode) {
- for (let i = 0; i < countFactors; i++) {
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(factors[i].id)));
- }
- if (countFactors > 1) {
- let firstId = factors[0].id;
- let secondId = factors[1].id;
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4001, secondId)));
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4002, secondId)));
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4003, secondId)));
- }
- if (aradgi) {
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(4013)));
- if (countFactors > 0) {
- let firstId = factors[0].id;
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4000, 4013)));
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4001, 4013)));
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4002, 4013)));
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4003, 4013)));
- }
- if (edem) {
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(4023, 4000, 4013)));
- }
- }
- } else {
- if (mode) {
- for (let i = 0; i < factors.length; i++) {
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(factors[i].id)));
- }
- } else {
- countFactors = factors.length < 2 ? factors.length : 2;
- }
- for (let i = 0; i < countFactors; i++) {
- let mainId = factors[i].id;
- if (aradgi && (mode || i > 0)) {
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4000, 4013)));
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4001, 4013)));
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4002, 4013)));
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4003, 4013)));
- }
- for (let i = 0; i < dark.length; i++) {
- let darkId = dark[i];
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4001, darkId)));
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4002, darkId)));
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4003, darkId)));
- }
- for (let i = 0; i < light.length; i++) {
- let lightId = light[i];
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4001, lightId)));
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4002, lightId)));
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4003, lightId)));
- }
- let isFull = mode || i > 0;
- for (let j = isFull ? i + 1 : 2; j < factors.length; j++) {
- let extraId = factors[j].id;
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4000, extraId)));
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4001, extraId)));
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4002, extraId)));
- }
- }
- if (aradgi) {
- if (mode) {
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(4013)));
- }
- for (let i = 0; i < dark.length; i++) {
- let darkId = dark[i];
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(darkId, 4001, 4013)));
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(darkId, 4002, 4013)));
- }
- for (let i = 0; i < light.length; i++) {
- let lightId = light[i];
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(lightId, 4001, 4013)));
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(lightId, 4002, 4013)));
- }
- }
- for (let i = 0; i < dark.length; i++) {
- let firstId = dark[i];
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId)));
- for (let j = i + 1; j < dark.length; j++) {
- let secondId = dark[j];
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4001, secondId)));
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4002, secondId)));
- }
- }
- for (let i = 0; i < light.length; i++) {
- let firstId = light[i];
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId)));
- for (let j = i + 1; j < light.length; j++) {
- let secondId = light[j];
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4001, secondId)));
- actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4002, secondId)));
- }
- }
- }
- for (let result of await Promise.all(actions)) {
- let recovery = getRecovery(result);
- if (recovery > bestBattle.recovery) {
- bestBattle.recovery = recovery;
- bestBattle.attackers = result.progress[0].attackers.heroes;
- }
- }
- }
-
- /** Получаем нейтральную команду */
- function getNeutralTeam(id, swapId, addId) {
- let neutralTeam = clone(teams.water);
- let neutral = neutralTeam.heroes;
- if (neutral.length == 4) {
- if (!!swapId) {
- for (let i in neutral) {
- if (neutral[i] == swapId) {
- neutral[i] = addId;
- }
- }
- }
- } else if (!!addId) {
- neutral.push(addId);
- }
- neutral.push(id);
- return neutralTeam;
- }
-
- /** Получить команду титанов */
- function getTeam(titans) {
- return {
- favor: {},
- heroes: Object.keys(titans).map(id => parseInt(id)),
- teamNum: 0,
- };
- }
-
- /** Вычисляем фактор боеготовности титанов */
- function calcFactor() {
- let neutral = teams.neutral;
- let factors = [];
- for (let i in neutral) {
- let titanId = neutral[i];
- let titan = titansStates[titanId];
- let factor = !!titan ? titan.hp / titan.maxHp + titan.energy / 10000.0 : 1;
- if (factor > 0) {
- factors.push({id: titanId, value: factor});
- }
- }
- factors.sort(function(a, b) {
- return a.value - b.value;
- });
- return factors;
- }
-
- /** Возвращает наилучший результат из нескольких боев */
- async function getBestRecovery(teamNum, attackerType, team, countBattle) {
- let bestRecovery = -1000;
- let actions = [];
- for (let i = 0; i < countBattle; i++) {
- actions.push(startBattle(teamNum, attackerType, team));
- }
- for (let result of await Promise.all(actions)) {
- let recovery = getRecovery(result);
- if (recovery > bestRecovery) {
- bestRecovery = recovery;
- }
- }
- return bestRecovery;
- }
-
- /** Возвращает разницу в здоровье атакующей команды после и до битвы и проверяет здоровье титанов на необходимый минимум*/
- function getRecovery(result) {
- if (result.result.stars < 3) {
- return -100;
- }
- let beforeSumFactor = 0;
- let afterSumFactor = 0;
- let beforeTitans = result.battleData.attackers;
- let afterTitans = result.progress[0].attackers.heroes;
- for (let i in afterTitans) {
- let titan = afterTitans[i];
- let percentHP = titan.hp / beforeTitans[i].hp;
- let energy = titan.energy;
- let factor = checkTitan(i, energy, percentHP) ? getFactor(i, energy, percentHP) : -100;
- afterSumFactor += factor;
- }
- for (let i in beforeTitans) {
- let titan = beforeTitans[i];
- let state = titan.state;
- beforeSumFactor += !!state ? getFactor(i, state.energy, state.hp / titan.hp) : 1;
- }
- return afterSumFactor - beforeSumFactor;
- }
-
- /** Возвращает состояние титана*/
- function getFactor(id, energy, percentHP) {
- let elemantId = id.slice(2, 3);
- let isEarthOrFire = elemantId == '1' || elemantId == '2';
- let energyBonus = id == '4020' && energy == 1000 ? 0.1 : energy / 20000.0;
- let factor = percentHP + energyBonus;
- return isEarthOrFire ? factor : factor / 10;
- }
-
- /** Проверяет состояние титана*/
- function checkTitan(id, energy, percentHP) {
- switch (id) {
- case '4020':
- return percentHP > 0.25 || (energy == 1000 && percentHP > 0.05);
- break;
- case '4010':
- return percentHP + energy / 2000.0 > 0.63;
- break;
- case '4000':
- return percentHP > 0.62 || (energy < 1000 && (
- (percentHP > 0.45 && energy >= 400) ||
- (percentHP > 0.3 && energy >= 670)));
- }
- return true;
- }
-
-
- /** Начинаем бой */
- function startBattle(teamNum, attackerType, args) {
- return new Promise(function (resolve, reject) {
- args.teamNum = teamNum;
- let startBattleCall = {
- calls: [{
- name: "dungeonStartBattle",
- args,
- ident: "body"
- }]
- }
- send(JSON.stringify(startBattleCall), resultBattle, {
- resolve,
- teamNum,
- attackerType
- });
- });
- }
-
- /** Возращает результат боя в промис */
- /*function resultBattle(resultBattles, args) {
- if (!!resultBattles && !!resultBattles.results) {
- let battleData = resultBattles.results[0].result.response;
- let 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 (result) {
- result.teamNum = args.teamNum;
- result.attackerType = args.attackerType;
- args.resolve(result);
- });
- } else {
- endDungeon('Потеряна связь с сервером игры!', 'break');
- }
- }*/
- function resultBattle(resultBattles, args) {
- battleData = resultBattles.results[0].result.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 (result) {
- result.teamNum = args.teamNum;
- result.attackerType = args.attackerType;
- args.resolve(result);
- });
- }
-
- /** Заканчиваем бой */
-
- ////
- async function endBattle(battleInfo) {
- if (!!battleInfo) {
- const args = {
- result: battleInfo.result,
- progress: battleInfo.progress,
- }
- if (battleInfo.result.stars < 3) {
- endDungeon('Герой или Титан мог погибнуть в бою!', battleInfo);
- return;
- }
- if (countPredictionCard > 0) {
- args.isRaid = true;
- } else {
- const timer = getTimer(battleInfo.battleTime);
- console.log(timer);
- await countdownTimer(timer, `${I18N('DUNGEON2')}: ${I18N('TITANIT')} ${dungeonActivity}/${maxDungeonActivity} ${talentMsg}`);
- }
- const calls = [{
- name: "dungeonEndBattle",
- args,
- ident: "body"
- }];
- lastDungeonBattleData = null;
- send(JSON.stringify({ calls }), resultEndBattle);
- } else {
- endDungeon('dungeonEndBattle win: false\n', battleInfo);
- }
- }
- /** Получаем и обрабатываем результаты боя */
- function resultEndBattle(e) {
- if (!!e && !!e.results) {
- let battleResult = e.results[0].result.response;
- if ('error' in battleResult) {
- endDungeon('errorBattleResult', battleResult);
- return;
- }
- let dungeonGetInfo = battleResult.dungeon ?? battleResult;
- dungeonActivity += battleResult.reward.dungeonActivity ?? 0;
- checkFloor(dungeonGetInfo);
- } else {
- endDungeon('Потеряна связь с сервером игры!', 'break');
- }
- }
-
- /** Добавить команду титанов в общий список команд */
- function addTeam(team) {
- for (let i in countTeam) {
- if (equalsTeam(countTeam[i].team, team)) {
- countTeam[i].count++;
- return;
- }
- }
- countTeam.push({team: team, count: 1});
- }
-
- /** Сравнить команды на равенство */
- function equalsTeam(team1, team2) {
- if (team1.length == team2.length) {
- for (let i in team1) {
- if (team1[i] != team2[i]) {
- return false;
- }
- }
- return true;
- }
- return false;
- }
-
- function saveProgress() {
- let saveProgressCall = {
- calls: [{
- name: "dungeonSaveProgress",
- args: {},
- ident: "body"
- }]
- }
- send(JSON.stringify(saveProgressCall), resultEndBattle);
- }
-
-
- /** Выводит статистику прохождения подземелья */
- function showStats() {
- let activity = dungeonActivity - startDungeonActivity;
- let workTime = clone(timeDungeon);
- workTime.all = new Date().getTime() - workTime.all;
- for (let i in workTime) {
- workTime[i] = (workTime[i] / 1000).round(0);
- }
- countTeam.sort(function(a, b) {
- return b.count - a.count;
- });
- console.log(titansStates);
- console.log("Собрано титанита: ", activity);
- console.log("Скорость сбора: " + (3600 * activity / workTime.all).round(0) + " титанита/час");
- console.log("Время раскопок: ");
- for (let i in workTime) {
- let timeNow = workTime[i];
- console.log(i + ": ", (timeNow / 3600).round(0) + " ч. " + (timeNow % 3600 / 60).round(0) + " мин. " + timeNow % 60 + " сек.");
- }
- console.log("Частота использования команд: ");
- for (let i in countTeam) {
- let teams = countTeam[i];
- console.log(teams.team + ": ", teams.count);
- }
- }
-
- /** Заканчиваем копать подземелье */
- function endDungeon(reason, info) {
- if (!end) {
- end = true;
- console.log(reason, info);
- showStats();
- if (info == 'break') {
- setProgress('Dungeon stoped: Титанит ' + dungeonActivity + '/' + maxDungeonActivity +
- "\r\nПотеряна связь с сервером игры!", false, hideProgress);
- } else {
- setProgress('Dungeon completed: Титанит ' + dungeonActivity + '/' + maxDungeonActivity, false, hideProgress);
- }
- setTimeout(cheats.refreshGame, 1000);
- resolve();
- }
- }
- }
-
- //дарим подарки участникам других гильдий не выходя из своей гильдии
- function NewYearGift_Clan() {
- console.log('NewYearGift_Clan called...');
- const userID = getInput('userID');
- const AmontID = getInput('AmontID');
- const GiftNum = getInput('GiftNum');
-
- const data = {
- "calls": [{
- "name": "newYearGiftSend",
- "args": {
- "userId": userID,
- "amount": AmontID,
- "giftNum": GiftNum,
- "users": {
- [userID]: AmontID
- }
- },
- "ident": "body"
- }
- ]
- }
-
- const dataJson = JSON.stringify(data);
-
- SendRequest(dataJson, e => {
- let userInfo = e.results[0].result.response;
- console.log(userInfo);
- });
- setProgress(I18N('SEND_GIFT'), true);
- }
- })();
-
- /**
- * TODO:
- * Получение всех уровней при сборе всех наград (квест на титанит и на энку) +-
- * Добивание на арене титанов
- * Закрытие окошек по Esc +-
- * Починить работу скрипта на уровне команды ниже 10 +-
- * Написать нормальную синхронизацию
- * Запрет сбора квестов и отправки экспеиций в промежуток между локальным обновлением и глобальным обновлением дня
- * Улучшение боев
- */