HeroWarsDungeon

Automation of actions for the game Hero Wars

当前为 2024-06-01 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name HeroWarsDungeon
  3. // @name:en HeroWarsDungeon
  4. // @name:ru HeroWarsDungeon
  5. // @namespace HeroWarsDungeon
  6. // @version 2.254.1
  7. // @description Automation of actions for the game Hero Wars
  8. // @description:en Automation of actions for the game Hero Wars
  9. // @description:ru Автоматизация действий для игры Хроники Хаоса
  10. // @author ZingerY, ApuoH, Gudwin
  11. // @license Copyright ZingerY
  12. // @homepage https://zingery.ru/scripts/HeroWarsHelper.user.js
  13. // @icon http://ilovemycomp.narod.ru/VaultBoyIco16.ico
  14. // @icon64 http://ilovemycomp.narod.ru/VaultBoyIco64.png
  15. // @match https://www.hero-wars.com/*
  16. // @match https://apps-1701433570146040.apps.fbsbx.com/*
  17. // @run-at document-start
  18. // ==/UserScript==
  19.  
  20. // сделал ApuoH
  21. (function() {
  22. /**
  23. * Start script
  24. *
  25. * Стартуем скрипт
  26. */
  27. console.log('%cStart ' + GM_info.script.name + ', v' + GM_info.script.version, 'color: red');
  28. /**
  29. * Script info
  30. *
  31. * Информация о скрипте
  32. */
  33. const scriptInfo = (({name, version, author, homepage, lastModified}, updateUrl, source) =>
  34. ({name, version, author, homepage, lastModified, updateUrl, source}))
  35. (GM_info.script, GM_info.scriptUpdateURL, arguments.callee.toString());
  36. /**
  37. * Information for completing daily quests
  38. *
  39. * Информация для выполнения ежендевных квестов
  40. */
  41. const questsInfo = {};
  42. /**
  43. * Is the game data loaded
  44. *
  45. * Загружены ли данные игры
  46. */
  47. let isLoadGame = false;
  48. /**
  49. * Headers of the last request
  50. *
  51. * Заголовки последнего запроса
  52. */
  53. let lastHeaders = {};
  54. /**
  55. * Information about sent gifts
  56. *
  57. * Информация об отправленных подарках
  58. */
  59. let freebieCheckInfo = null;
  60. /**
  61. * missionTimer
  62. *
  63. * missionTimer
  64. */
  65. let missionBattle = null;
  66. /** Пачки для тестов в чате*/ //тест сохранка
  67. let repleyBattle = {
  68. defenders: {},
  69. attackers: {},
  70. effects: {},
  71. state: {},
  72. seed: undefined
  73. }
  74. /**
  75. * User data
  76. *
  77. * Данные пользователя
  78. */
  79. let userInfo;
  80. /**
  81. * Original methods for working with AJAX
  82. *
  83. * Оригинальные методы для работы с AJAX
  84. */
  85. const original = {
  86. open: XMLHttpRequest.prototype.open,
  87. send: XMLHttpRequest.prototype.send,
  88. setRequestHeader: XMLHttpRequest.prototype.setRequestHeader,
  89. SendWebSocket: WebSocket.prototype.send,
  90. };
  91. /**
  92. * Decoder for converting byte data to JSON string
  93. *
  94. * Декодер для перобразования байтовых данных в JSON строку
  95. */
  96. const decoder = new TextDecoder("utf-8");
  97. /**
  98. * Stores a history of requests
  99. *
  100. * Хранит историю запросов
  101. */
  102. let requestHistory = {};
  103. /**
  104. * URL for API requests
  105. *
  106. * URL для запросов к API
  107. */
  108. let apiUrl = '';
  109.  
  110. /**
  111. * Connecting to the game code
  112. *
  113. * Подключение к коду игры
  114. */
  115. this.cheats = new hackGame();
  116. /**
  117. * The function of calculating the results of the battle
  118. *
  119. * Функция расчета результатов боя
  120. */
  121. this.BattleCalc = cheats.BattleCalc;
  122. /**
  123. * Sending a request available through the console
  124. *
  125. * Отправка запроса доступная через консоль
  126. */
  127. this.SendRequest = send;
  128. /**
  129. * Simple combat calculation available through the console
  130. *
  131. * Простой расчет боя доступный через консоль
  132. */
  133. this.Calc = function (data) {
  134. const type = getBattleType(data?.type);
  135. return new Promise((resolve, reject) => {
  136. try {
  137. BattleCalc(data, type, resolve);
  138. } catch (e) {
  139. reject(e);
  140. }
  141. })
  142. }
  143. //тест остановка подземки
  144. let stopDung = false;
  145. /**
  146. * Short asynchronous request
  147. * Usage example (returns information about a character):
  148. * const userInfo = await Send('{"calls":[{"name":"userGetInfo","args":{},"ident":"body"}]}')
  149. *
  150. * Короткий асинхронный запрос
  151. * Пример использования (возвращает информацию о персонаже):
  152. * const userInfo = await Send('{"calls":[{"name":"userGetInfo","args":{},"ident":"body"}]}')
  153. */
  154. this.Send = function (json, pr) {
  155. return new Promise((resolve, reject) => {
  156. try {
  157. send(json, resolve, pr);
  158. } catch (e) {
  159. reject(e);
  160. }
  161. })
  162. }
  163.  
  164. this.xyz = (({ name, version, author }) => ({ name, version, author }))(GM_info.script);
  165. const i18nLangData = {
  166. /* English translation by BaBa */
  167. en: {
  168. /* Checkboxes */
  169. SKIP_FIGHTS: 'Skip battle',
  170. SKIP_FIGHTS_TITLE: 'Skip battle in Outland and the arena of the titans, auto-pass in the tower and campaign',
  171. ENDLESS_CARDS: 'Infinite cards',
  172. ENDLESS_CARDS_TITLE: 'Disable Divination Cards wasting',
  173. AUTO_EXPEDITION: 'Auto Expedition',
  174. AUTO_EXPEDITION_TITLE: 'Auto-sending expeditions',
  175. CANCEL_FIGHT: 'Cancel battle',
  176. CANCEL_FIGHT_TITLE: 'Ability to cancel manual combat on GW, CoW and Asgard',
  177. GIFTS: 'Gifts',
  178. GIFTS_TITLE: 'Collect gifts automatically',
  179. BATTLE_RECALCULATION: 'Battle recalculation',
  180. BATTLE_RECALCULATION_TITLE: 'Preliminary calculation of the battle',
  181. BATTLE_FISHING: 'Finishing',
  182. BATTLE_FISHING_TITLE: 'Finishing off the team from the last replay in the chat',
  183. BATTLE_TRENING: 'Workout',
  184. BATTLE_TRENING_TITLE: 'A training battle in the chat against the team from the last replay',
  185. QUANTITY_CONTROL: 'Quantity control',
  186. QUANTITY_CONTROL_TITLE: 'Ability to specify the number of opened "lootboxes"',
  187. REPEAT_CAMPAIGN: 'Repeat missions',
  188. REPEAT_CAMPAIGN_TITLE: 'Auto-repeat battles in the campaign',
  189. DISABLE_DONAT: 'Disable donation',
  190. DISABLE_DONAT_TITLE: 'Removes all donation offers',
  191. DAILY_QUESTS: 'Quests',
  192. DAILY_QUESTS_TITLE: 'Complete daily quests',
  193. AUTO_QUIZ: 'AutoQuiz',
  194. AUTO_QUIZ_TITLE: 'Automatically receive correct answers to quiz questions',
  195. SECRET_WEALTH_CHECKBOX: 'Automatic purchase in the store "Secret Wealth" when entering the game',
  196. HIDE_SERVERS: 'Collapse servers',
  197. HIDE_SERVERS_TITLE: 'Hide unused servers',
  198. /* Input fields */
  199. HOW_MUCH_TITANITE: 'How much titanite to farm',
  200. COMBAT_SPEED: 'Combat Speed Multiplier',
  201. HOW_REPEAT_CAMPAIGN: 'how many mission replays', //тест добавил
  202. NUMBER_OF_TEST: 'Number of test fights',
  203. NUMBER_OF_AUTO_BATTLE: 'Number of auto-battle attempts',
  204. USER_ID_TITLE: 'Enter the player ID',
  205. AMOUNT: 'Gift number, 1 - hero development, 2 - pets, 3 - light, 4 - darkness, 5 - ascension, 6 - appearance',
  206. GIFT_NUM: 'Number of gifts to be sent',
  207. /* Buttons */
  208. RUN_SCRIPT: 'Run the',
  209. STOP_SCRIPT: 'Stop the',
  210. TO_DO_EVERYTHING: 'Do All',
  211. TO_DO_EVERYTHING_TITLE: 'Perform multiple actions of your choice',
  212. OUTLAND: 'Outland',
  213. OUTLAND_TITLE: 'Collect Outland',
  214. TITAN_ARENA: 'ToE',
  215. TITAN_ARENA_TITLE: 'Complete the titan arena',
  216. DUNGEON: 'Dungeon',
  217. DUNGEON_TITLE: 'Go through the dungeon',
  218. DUNGEON2: 'Dungeon full',
  219. DUNGEON_FULL_TITLE: 'Dungeon for Full Titans',
  220. STOP_DUNGEON: 'Stop Dungeon',
  221. STOP_DUNGEON_TITLE: 'Stop digging the dungeon',
  222. SEER: 'Seer',
  223. SEER_TITLE: 'Roll the Seer',
  224. TOWER: 'Tower',
  225. TOWER_TITLE: 'Pass the tower',
  226. EXPEDITIONS: 'Expeditions',
  227. EXPEDITIONS_TITLE: 'Sending and collecting expeditions',
  228. SYNC: 'Sync',
  229. SYNC_TITLE: 'Partial synchronization of game data without reloading the page',
  230. ARCHDEMON: 'Archdemon',
  231. ARCHDEMON_TITLE: 'Hitting kills and collecting rewards',
  232. CRUCIBLE_SOULS: 'Crucible',
  233. CRUCIBLE_SOULS_TITLE: 'Fill the kilos in the crucible of souls',
  234. ESTER_EGGS: 'Easter eggs',
  235. ESTER_EGGS_TITLE: 'Collect all Easter eggs or rewards',
  236. REWARDS: 'Rewards',
  237. REWARDS_TITLE: 'Collect all quest rewards',
  238. MAIL: 'Mail',
  239. MAIL_TITLE: 'Collect all mail, except letters with energy and charges of the portal',
  240. MINIONS: 'Minions',
  241. MINIONS_TITLE: 'Attack minions with saved packs',
  242. ADVENTURE: 'Adventure',
  243. ADVENTURE_TITLE: 'Passes the adventure along the specified route',
  244. STORM: 'Storm',
  245. STORM_TITLE: 'Passes the Storm along the specified route',
  246. SANCTUARY: 'Sanctuary',
  247. SANCTUARY_TITLE: 'Fast travel to Sanctuary',
  248. GUILD_WAR: 'Guild War',
  249. GUILD_WAR_TITLE: 'Fast travel to Guild War',
  250. SECRET_WEALTH: 'Secret Wealth',
  251. SECRET_WEALTH_TITLE: 'Buy something in the store "Secret Wealth"',
  252. /* Misc */
  253. 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>',
  254. GIFTS_SENT: 'Gifts sent!',
  255. DO_YOU_WANT: 'Do you really want to do this?',
  256. BTN_RUN: 'Run',
  257. BTN_CANCEL: 'Cancel',
  258. BTN_OK: 'OK',
  259. MSG_HAVE_BEEN_DEFEATED: 'You have been defeated!',
  260. BTN_AUTO: 'Auto',
  261. MSG_YOU_APPLIED: 'You applied',
  262. MSG_DAMAGE: 'damage',
  263. MSG_CANCEL_AND_STAT: 'Auto (F5) and show statistic',
  264. MSG_REPEAT_MISSION: 'Repeat the mission?',
  265. BTN_REPEAT: 'Repeat',
  266. BTN_NO: 'No',
  267. MSG_SPECIFY_QUANT: 'Specify Quantity:',
  268. BTN_OPEN: 'Open',
  269. QUESTION_COPY: 'Question copied to clipboard',
  270. ANSWER_KNOWN: 'The answer is known',
  271. ANSWER_NOT_KNOWN: 'ATTENTION THE ANSWER IS NOT KNOWN',
  272. BEING_RECALC: 'The battle is being recalculated',
  273. THIS_TIME: 'This time',
  274. VICTORY: '<span style="color:green;">VICTORY</span>',
  275. DEFEAT: '<span style="color:red;">DEFEAT</span>',
  276. CHANCE_TO_WIN: 'Chance to win <span style="color: red;">based on pre-calculation</span>',
  277. OPEN_DOLLS: 'nesting dolls recursively',
  278. SENT_QUESTION: 'Question sent',
  279. SETTINGS: 'Settings',
  280. MSG_BAN_ATTENTION: '<p style="color:red;">Using this feature may result in a ban.</p> Continue?',
  281. BTN_YES_I_AGREE: 'Yes, I understand the risks!',
  282. BTN_NO_I_AM_AGAINST: 'No, I refuse it!',
  283. VALUES: 'Values',
  284. SAVING: 'Saving',
  285. USER_ID: 'User Id',
  286. SEND_GIFT: 'The gift has been sent',
  287. EXPEDITIONS_SENT: 'Expeditions:<br>Collected: {countGet}<br>Sent: {countSend}',
  288. EXPEDITIONS_NOTHING: 'Nothing to collect/send',
  289. TITANIT: 'Titanit',
  290. COMPLETED: 'completed',
  291. FLOOR: 'Floor',
  292. LEVEL: 'Level',
  293. BATTLES: 'battles',
  294. EVENT: 'Event',
  295. NOT_AVAILABLE: 'not available',
  296. NO_HEROES: 'No heroes',
  297. DAMAGE_AMOUNT: 'Damage amount',
  298. NOTHING_TO_COLLECT: 'Nothing to collect',
  299. COLLECTED: 'Collected',
  300. REWARD: 'rewards',
  301. REMAINING_ATTEMPTS: 'Remaining attempts',
  302. BATTLES_CANCELED: 'Battles canceled',
  303. MINION_RAID: 'Minion Raid',
  304. STOPPED: 'Stopped',
  305. REPETITIONS: 'Repetitions',
  306. MISSIONS_PASSED: 'Missions passed',
  307. STOP: 'stop',
  308. TOTAL_OPEN: 'Total open',
  309. OPEN: 'Open',
  310. ROUND_STAT: 'Damage statistics for ',
  311. BATTLE: 'battles',
  312. MINIMUM: 'Minimum',
  313. MAXIMUM: 'Maximum',
  314. AVERAGE: 'Average',
  315. NOT_THIS_TIME: 'Not this time',
  316. RETRY_LIMIT_EXCEEDED: 'Retry limit exceeded',
  317. SUCCESS: 'Success',
  318. RECEIVED: 'Received',
  319. LETTERS: 'letters',
  320. PORTALS: 'portals',
  321. ATTEMPTS: 'attempts',
  322. /* Quests */
  323. QUEST_10001: 'Upgrade the skills of heroes 3 times',
  324. QUEST_10002: 'Complete 10 missions',
  325. QUEST_10003: 'Complete 3 heroic missions',
  326. QUEST_10004: 'Fight 3 times in the Arena or Grand Arena',
  327. QUEST_10006: 'Use the exchange of emeralds 1 time',
  328. QUEST_10007: 'Perform 1 summon in the Solu Atrium',
  329. QUEST_10016: 'Send gifts to guildmates',
  330. QUEST_10018: 'Use an experience potion',
  331. QUEST_10019: 'Open 1 chest in the Tower',
  332. QUEST_10020: 'Open 3 chests in Outland',
  333. QUEST_10021: 'Collect 75 Titanite in the Guild Dungeon',
  334. QUEST_10021: 'Collect 150 Titanite in the Guild Dungeon',
  335. QUEST_10023: 'Upgrade Gift of the Elements by 1 level',
  336. QUEST_10024: 'Level up any artifact once',
  337. QUEST_10025: 'Start Expedition 1',
  338. QUEST_10026: 'Start 4 Expeditions',
  339. QUEST_10027: 'Win 1 battle of the Tournament of Elements',
  340. QUEST_10028: 'Level up any titan artifact',
  341. QUEST_10029: 'Unlock the Orb of Titan Artifacts',
  342. QUEST_10030: 'Upgrade any Skin of any hero 1 time',
  343. QUEST_10031: 'Win 6 battles of the Tournament of Elements',
  344. QUEST_10043: 'Start or Join an Adventure',
  345. QUEST_10044: 'Use Summon Pets 1 time',
  346. QUEST_10046: 'Open 3 chests in Adventure',
  347. QUEST_10047: 'Get 150 Guild Activity Points',
  348. NOTHING_TO_DO: 'Nothing to do',
  349. YOU_CAN_COMPLETE: 'You can complete quests',
  350. BTN_DO_IT: 'Do it',
  351. NOT_QUEST_COMPLETED: 'Not a single quest completed',
  352. COMPLETED_QUESTS: 'Completed quests',
  353. /* everything button */
  354. ASSEMBLE_OUTLAND: 'Assemble Outland',
  355. PASS_THE_TOWER: 'Pass the tower',
  356. CHECK_EXPEDITIONS: 'Check Expeditions',
  357. COMPLETE_TOE: 'Complete ToE',
  358. COMPLETE_DUNGEON: 'Complete the dungeon',
  359. COMPLETE_DUNGEON_FULL: 'Complete the dungeon for Full Titans',
  360. COLLECT_MAIL: 'Collect mail',
  361. COLLECT_MISC: 'Collect some bullshit',
  362. COLLECT_MISC_TITLE: 'Collect Easter Eggs, Skin Gems, Keys, Arena Coins and Soul Crystal',
  363. COLLECT_QUEST_REWARDS: 'Collect quest rewards',
  364. MAKE_A_SYNC: 'Make a sync',
  365.  
  366. RUN_FUNCTION: 'Run the following functions?',
  367. BTN_GO: 'Go!',
  368. PERFORMED: 'Performed',
  369. DONE: 'Done',
  370. ERRORS_OCCURRES: 'Errors occurred while executing',
  371. COPY_ERROR: 'Copy error information to clipboard',
  372. BTN_YES: 'Yes',
  373. ALL_TASK_COMPLETED: 'All tasks completed',
  374.  
  375. UNKNOWN: 'unknown',
  376. ENTER_THE_PATH: 'Enter the path of adventure using commas or dashes',
  377. START_ADVENTURE: 'Start your adventure along this path!',
  378. INCORRECT_WAY: 'Incorrect path in adventure: {from} -> {to}',
  379. BTN_CANCELED: 'Canceled',
  380. MUST_TWO_POINTS: 'The path must contain at least 2 points.',
  381. MUST_ONLY_NUMBERS: 'The path must contain only numbers and commas',
  382. NOT_ON_AN_ADVENTURE: 'You are not on an adventure',
  383. YOU_IN_NOT_ON_THE_WAY: 'Your location is not on the way',
  384. ATTEMPTS_NOT_ENOUGH: 'Your attempts are not enough to complete the path, continue?',
  385. YES_CONTINUE: 'Yes, continue!',
  386. NOT_ENOUGH_AP: 'Not enough action points',
  387. ATTEMPTS_ARE_OVER: 'The attempts are over',
  388. MOVES: 'Moves',
  389. BUFF_GET_ERROR: 'Buff getting error',
  390. BATTLE_END_ERROR: 'Battle end error',
  391. AUTOBOT: 'Autobot',
  392. FAILED_TO_WIN_AUTO: 'Failed to win the auto battle',
  393. ERROR_OF_THE_BATTLE_COPY: 'An error occurred during the passage of the battle<br>Copy the error to the clipboard?',
  394. ERROR_DURING_THE_BATTLE: 'Error during the battle',
  395. NO_CHANCE_WIN: 'No chance of winning this fight: 0/',
  396. LOST_HEROES: 'You have won, but you have lost one or several heroes',
  397. VICTORY_IMPOSSIBLE: 'Is victory impossible, should we focus on the result?',
  398. FIND_COEFF: 'Find the coefficient greater than',
  399. BTN_PASS: 'PASS',
  400. BRAWLS: 'Brawls',
  401. BRAWLS_TITLE: 'Activates the ability to auto-brawl',
  402. START_AUTO_BRAWLS: 'Start Auto Brawls?',
  403. LOSSES: 'Losses',
  404. WINS: 'Wins',
  405. FIGHTS: 'Fights',
  406. STAGE: 'Stage',
  407. DONT_HAVE_LIVES: "You don't have lives",
  408. LIVES: 'Lives',
  409. SECRET_WEALTH_ALREADY: 'Item for Pet Potions already purchased',
  410. SECRET_WEALTH_NOT_ENOUGH: 'Not Enough Pet Potion, You Have {available}, Need {need}',
  411. SECRET_WEALTH_UPGRADE_NEW_PET: 'After purchasing the Pet Potion, it will not be enough to upgrade a new pet',
  412. SECRET_WEALTH_PURCHASED: 'Purchased {count} {name}',
  413. SECRET_WEALTH_CANCELED: 'Secret Wealth: Purchase Canceled',
  414. SECRET_WEALTH_BUY: 'You have {available} Pet Potion.<br>Do you want to buy {countBuy} {name} for {price} Pet Potion?',
  415. DAILY_BONUS: 'Daily bonus',
  416. DO_DAILY_QUESTS: 'Do daily quests',
  417. ACTIONS: 'Actions',
  418. ACTIONS_TITLE: 'Dialog box with various actions',
  419. OTHERS: 'Others',
  420. OTHERS_TITLE: 'Others',
  421. CHOOSE_ACTION: 'Choose an action',
  422. OPEN_LOOTBOX: 'You have {lootBox} boxes, should we open them?',
  423. STAMINA: 'Energy',
  424. BOXES_OVER: 'The boxes are over',
  425. NO_BOXES: 'No boxes',
  426. NO_MORE_ACTIVITY: 'No more activity for items today',
  427. EXCHANGE_ITEMS: 'Exchange items for activity points (max {maxActive})?',
  428. GET_ACTIVITY: 'Get Activity',
  429. NOT_ENOUGH_ITEMS: 'Not enough items',
  430. ACTIVITY_RECEIVED: 'Activity received',
  431. NO_PURCHASABLE_HERO_SOULS: 'No purchasable Hero Souls',
  432. PURCHASED_HERO_SOULS: 'Purchased {countHeroSouls} Hero Souls',
  433. NOT_ENOUGH_EMERALDS_540: 'Not enough emeralds, you need 540 you have {currentStarMoney}',
  434. CHESTS_NOT_AVAILABLE: 'Chests not available',
  435. OUTLAND_CHESTS_RECEIVED: 'Outland chests received',
  436. RAID_NOT_AVAILABLE: 'The raid is not available or there are no spheres',
  437. RAID_ADVENTURE: 'Raid {adventureId} adventure!',
  438. SOMETHING_WENT_WRONG: 'Something went wrong',
  439. ADVENTURE_COMPLETED: 'Adventure {adventureId} completed {times} times',
  440. CLAN_STAT_COPY: 'Clan statistics copied to clipboard',
  441. GET_ENERGY: 'Get Energy',
  442. GET_ENERGY_TITLE: 'Opens platinum boxes one at a time until you get 250 energy',
  443. ITEM_EXCHANGE: 'Item Exchange',
  444. ITEM_EXCHANGE_TITLE: 'Exchanges items for the specified amount of activity',
  445. BUY_SOULS: 'Buy souls',
  446. BUY_SOULS_TITLE: 'Buy hero souls from all available shops',
  447. BUY_OUTLAND: 'Buy Outland',
  448. BUY_OUTLAND_TITLE: 'Buy 9 chests in Outland for 540 emeralds',
  449. RAID: 'Raid',
  450. AUTO_RAID_ADVENTURE: 'Raid adventure',
  451. AUTO_RAID_ADVENTURE_TITLE: 'Raid adventure set number of times',
  452. CLAN_STAT: 'Clan statistics',
  453. CLAN_STAT_TITLE: 'Copies clan statistics to the clipboard',
  454. BTN_AUTO_F5: 'Auto (F5)',
  455. BOSS_DAMAGE: 'Boss Damage: ',
  456. NOTHING_BUY: 'Nothing to buy',
  457. LOTS_BOUGHT: '{countBuy} lots bought for gold',
  458. BUY_FOR_GOLD: 'Buy for gold',
  459. BUY_FOR_GOLD_TITLE: 'Buy items for gold in the Town Shop and in the Pet Soul Stone Shop',
  460. REWARDS_AND_MAIL: 'Rewars and Mail',
  461. REWARDS_AND_MAIL_TITLE: 'Collects rewards and mail',
  462. New_Year_Clan: 'a gift for a friend',
  463. New_Year_Clan_TITLE: 'New Year gifts to friends',
  464. COLLECT_REWARDS_AND_MAIL: 'Collected {countQuests} rewards and {countMail} letters',
  465. TIMER_ALREADY: 'Timer already started {time}',
  466. NO_ATTEMPTS_TIMER_START: 'No attempts, timer started {time}',
  467. EPIC_BRAWL_RESULT: 'Wins: {wins}/{attempts}, Coins: {coins}, Streak: {progress}/{nextStage} [Close]{end}',
  468. ATTEMPT_ENDED: '<br>Attempts ended, timer started {time}',
  469. EPIC_BRAWL: 'Cosmic Battle',
  470. EPIC_BRAWL_TITLE: 'Spends attempts in the Cosmic Battle',
  471. RELOAD_GAME: 'Reload game',
  472. TIMER: 'Timer:',
  473. SHOW_ERRORS: 'Show errors',
  474. SHOW_ERRORS_TITLE: 'Show server request errors',
  475. ERROR_MSG: 'Error: {name}<br>{description}',
  476. 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?',
  477. BEST_SLOW: 'Best (slower)',
  478. FIRST_FAST: 'First (faster)',
  479. FREEZE_INTERFACE: 'Calculating... <br>The interface may freeze.',
  480. ERROR_F12: 'Error, details in the console (F12)',
  481. FAILED_FIND_WIN_PACK: 'Failed to find a winning pack',
  482. BEST_PACK: 'Best pack:',
  483. BOSS_HAS_BEEN_DEF: 'Boss {bossLvl} has been defeated.',
  484. NOT_ENOUGH_ATTEMPTS_BOSS: 'Not enough attempts to defeat boss {bossLvl}, retry?',
  485. 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?',
  486. BOSS_HAS_BEEN_DEF_TEXT: 'Boss {bossLvl} defeated in<br>{countBattle}/{countMaxBattle} attempts<br>(Please synchronize or restart the game to update the data)',
  487. MAP: 'Map: ',
  488. PLAYER_POS: 'Player positions:',
  489. NY_GIFTS: 'Gifts',
  490. NY_GIFTS_TITLE: "Open all New Year's gifts",
  491. NY_NO_GIFTS: 'No gifts not received',
  492. NY_GIFTS_COLLECTED: '{count} gifts collected',
  493. CHANGE_MAP: 'Island map',
  494. CHANGE_MAP_TITLE: 'Change island map',
  495. SELECT_ISLAND_MAP: 'Select an island map:',
  496. MAP_NUM: 'Map {num}',
  497. SECRET_WEALTH_SHOP: 'Secret Wealth {name}: ',
  498. SHOPS: 'Shops',
  499. SHOPS_DEFAULT: 'Default',
  500. SHOPS_DEFAULT_TITLE: 'Default stores',
  501. SHOPS_LIST: 'Shops {number}',
  502. SHOPS_LIST_TITLE: 'List of shops {number}',
  503. 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>',
  504. MINIONS_WARNING: 'The hero packs for attacking minions are incomplete, should I continue?',
  505. FAST_SEASON: 'Fast season',
  506. FAST_SEASON_TITLE: 'Skip the map selection screen in a season',
  507. SET_NUMBER_LEVELS: 'Specify the number of levels:',
  508. POSSIBLE_IMPROVE_LEVELS: 'It is possible to improve only {count} levels.<br>Improving?',
  509. NOT_ENOUGH_RESOURECES: 'Not enough resources',
  510. IMPROVED_LEVELS: 'Improved levels: {count}',
  511. ARTIFACTS_UPGRADE: 'Artifacts Upgrade',
  512. ARTIFACTS_UPGRADE_TITLE: 'Upgrades the specified amount of the cheapest hero artifacts',
  513. SKINS_UPGRADE: 'Skins Upgrade',
  514. SKINS_UPGRADE_TITLE: 'Upgrades the specified amount of the cheapest hero skins',
  515. HINT: '<br>Hint: ',
  516. PICTURE: '<br>Picture: ',
  517. ANSWER: '<br>Answer: ',
  518. NO_HEROES_PACK: 'Fight at least one battle to save the attacking team',
  519. BRAWL_AUTO_PACK: 'Automatic selection of packs',
  520. BRAWL_AUTO_PACK_NOT_CUR_HERO: 'Automatic pack selection is not suitable for the current hero',
  521. BRAWL_DAILY_TASK_COMPLETED: 'Daily task completed, continue attacking?',
  522. },
  523. ru: {
  524. /* Чекбоксы */
  525. SKIP_FIGHTS: 'Пропуск боев',
  526. SKIP_FIGHTS_TITLE: 'Пропуск боев в запределье и арене титанов, автопропуск в башне и кампании',
  527. ENDLESS_CARDS: 'Бесконечные карты',
  528. ENDLESS_CARDS_TITLE: 'Отключить трату карт предсказаний',
  529. AUTO_EXPEDITION: 'АвтоЭкспедиции',
  530. AUTO_EXPEDITION_TITLE: 'Автоотправка экспедиций',
  531. CANCEL_FIGHT: 'Отмена боя',
  532. CANCEL_FIGHT_TITLE: 'Возможность отмены ручного боя на ВГ, СМ и в Асгарде',
  533. GIFTS: 'Подарки',
  534. GIFTS_TITLE: 'Собирать подарки автоматически',
  535. BATTLE_RECALCULATION: 'Прерасчет боя',
  536. BATTLE_RECALCULATION_TITLE: 'Предварительный расчет боя',
  537. BATTLE_FISHING: 'Добивание',
  538. BATTLE_FISHING_TITLE: 'Добивание в чате команды из последнего реплея',
  539. BATTLE_TRENING: 'Тренировка',
  540. BATTLE_TRENING_TITLE: 'Тренировочный бой в чате против команды из последнего реплея',
  541. QUANTITY_CONTROL: 'Контроль кол-ва',
  542. QUANTITY_CONTROL_TITLE: 'Возможность указывать количество открываемых "лутбоксов"',
  543. REPEAT_CAMPAIGN: 'Повтор в компании',
  544. REPEAT_CAMPAIGN_TITLE: 'Автоповтор боев в кампании',
  545. DISABLE_DONAT: 'Отключить донат',
  546. DISABLE_DONAT_TITLE: 'Убирает все предложения доната',
  547. DAILY_QUESTS: 'Квесты',
  548. DAILY_QUESTS_TITLE: 'Выполнять ежедневные квесты',
  549. AUTO_QUIZ: 'АвтоВикторина',
  550. AUTO_QUIZ_TITLE: 'Автоматическое получение правильных ответов на вопросы викторины',
  551. SECRET_WEALTH_CHECKBOX: 'Автоматическая покупка в магазине "Тайное Богатство" при заходе в игру',
  552. HIDE_SERVERS: 'Свернуть сервера',
  553. HIDE_SERVERS_TITLE: 'Скрывать неиспользуемые сервера',
  554. /* Поля ввода */
  555. HOW_MUCH_TITANITE: 'Сколько фармим титанита',
  556. COMBAT_SPEED: 'Множитель ускорения боя',
  557. HOW_REPEAT_CAMPAIGN: 'Сколько повторов миссий', //тест добавил
  558. NUMBER_OF_TEST: 'Количество тестовых боев',
  559. NUMBER_OF_AUTO_BATTLE: 'Количество попыток автобоев',
  560. USER_ID_TITLE: 'Введите айди игрока',
  561. AMOUNT: 'Количество отправляемых подарков',
  562. GIFT_NUM: 'Номер подарка, 1 - развитие героев, 2 - питомцы, 3 - света, 4 - тьмы, 5 - вознесения, 6 - облик',
  563. /* Кнопки */
  564. RUN_SCRIPT: 'Запустить скрипт',
  565. STOP_SCRIPT: 'Остановить скрипт',
  566. TO_DO_EVERYTHING: 'Сделать все',
  567. TO_DO_EVERYTHING_TITLE: 'Выполнить несколько действий',
  568. OUTLAND: 'Запределье',
  569. OUTLAND_TITLE: 'Собрать Запределье',
  570. TITAN_ARENA: 'Турнир Стихий',
  571. TITAN_ARENA_TITLE: 'Автопрохождение Турнира Стихий',
  572. DUNGEON: 'Подземелье',
  573. DUNGEON_TITLE: 'Автопрохождение подземелья',
  574. DUNGEON2: 'Подземелье фулл',
  575. DUNGEON_FULL_TITLE: 'Подземелье для фуловых титанов',
  576. STOP_DUNGEON: 'Стоп подземка',
  577. STOP_DUNGEON_TITLE: 'Остановить копание подземелья',
  578. SEER: 'Провидец',
  579. SEER_TITLE: 'Покрутить Провидца',
  580. TOWER: 'Башня',
  581. TOWER_TITLE: 'Автопрохождение башни',
  582. EXPEDITIONS: 'Экспедиции',
  583. EXPEDITIONS_TITLE: 'Отправка и сбор экспедиций',
  584. SYNC: 'Синхронизация',
  585. SYNC_TITLE: 'Частичная синхронизация данных игры без перезагрузки сатраницы',
  586. ARCHDEMON: 'Архидемон',
  587. ARCHDEMON_TITLE: 'Набивает килы и собирает награду',
  588. CRUCIBLE_SOULS: 'Горнило душ',
  589. CRUCIBLE_SOULS_TITLE:'Набить килов в горниле душ',
  590. ESTER_EGGS: 'Пасхалки',
  591. ESTER_EGGS_TITLE: 'Собрать все пасхалки или награды',
  592. REWARDS: 'Награды',
  593. REWARDS_TITLE: 'Собрать все награды за задания',
  594. MAIL: 'Почта',
  595. MAIL_TITLE: 'Собрать всю почту, кроме писем с энергией и зарядами портала',
  596. MINIONS: 'Прислужники',
  597. MINIONS_TITLE: 'Атакует прислужников сохраннеными пачками',
  598. ADVENTURE: 'Приключение',
  599. ADVENTURE_TITLE: 'Проходит приключение по указанному маршруту',
  600. STORM: 'Буря',
  601. STORM_TITLE: 'Проходит бурю по указанному маршруту',
  602. SANCTUARY: 'Святилище',
  603. SANCTUARY_TITLE: 'Быстрый переход к Святилищу',
  604. GUILD_WAR: 'Война гильдий',
  605. GUILD_WAR_TITLE: 'Быстрый переход к Войне гильдий',
  606. SECRET_WEALTH: 'Тайное богатство',
  607. SECRET_WEALTH_TITLE: 'Купить что-то в магазине "Тайное богатство"',
  608. /* Разное */
  609. 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>',
  610. GIFTS_SENT: 'Подарки отправлены!',
  611. DO_YOU_WANT: 'Вы действительно хотите это сделать?',
  612. BTN_RUN: 'Запускай',
  613. BTN_CANCEL: 'Отмена',
  614. BTN_OK: 'Ок',
  615. MSG_HAVE_BEEN_DEFEATED: 'Вы потерпели поражение!',
  616. BTN_AUTO: 'Авто',
  617. MSG_YOU_APPLIED: 'Вы нанесли',
  618. MSG_DAMAGE: 'урона',
  619. MSG_CANCEL_AND_STAT: 'Авто (F5) и показать Статистику',
  620. MSG_REPEAT_MISSION: 'Повторить миссию?',
  621. BTN_REPEAT: 'Повторить',
  622. BTN_NO: 'Нет',
  623. MSG_SPECIFY_QUANT: 'Указать количество:',
  624. BTN_OPEN: 'Открыть',
  625. QUESTION_COPY: 'Вопрос скопирован в буфер обмена',
  626. ANSWER_KNOWN: 'Ответ известен',
  627. ANSWER_NOT_KNOWN: 'ВНИМАНИЕ ОТВЕТ НЕ ИЗВЕСТЕН',
  628. BEING_RECALC: 'Идет прерасчет боя',
  629. THIS_TIME: 'На этот раз',
  630. VICTORY: '<span style="color:green;">ПОБЕДА</span>',
  631. DEFEAT: '<span style="color:red;">ПОРАЖЕНИЕ</span>',
  632. CHANCE_TO_WIN: 'Шансы на победу <span style="color:red;">на основе прерасчета</span>',
  633. OPEN_DOLLS: 'матрешек рекурсивно',
  634. SENT_QUESTION: 'Вопрос отправлен',
  635. SETTINGS: 'Настройки',
  636. MSG_BAN_ATTENTION: '<p style="color:red;">Использование этой функции может привести к бану.</p> Продолжить?',
  637. BTN_YES_I_AGREE: 'Да, я беру на себя все риски!',
  638. BTN_NO_I_AM_AGAINST: 'Нет, я отказываюсь от этого!',
  639. VALUES: 'Значения',
  640. SAVING: 'Сохранка',
  641. USER_ID: 'айди пользователя',
  642. SEND_GIFT: 'Подарок отправлен',
  643. EXPEDITIONS_SENT: 'Экспедиции:<br>Собрано: {countGet}<br>Отправлено: {countSend}',
  644. EXPEDITIONS_NOTHING: 'Нечего собирать/отправлять',
  645. TITANIT: 'Титанит',
  646. COMPLETED: 'завершено',
  647. FLOOR: 'Этаж',
  648. LEVEL: 'Уровень',
  649. BATTLES: 'бои',
  650. EVENT: 'Эвент',
  651. NOT_AVAILABLE: 'недоступен',
  652. NO_HEROES: 'Нет героев',
  653. DAMAGE_AMOUNT: 'Количество урона',
  654. NOTHING_TO_COLLECT: 'Нечего собирать',
  655. COLLECTED: 'Собрано',
  656. REWARD: 'наград',
  657. REMAINING_ATTEMPTS: 'Осталось попыток',
  658. BATTLES_CANCELED: 'Битв отменено',
  659. MINION_RAID: 'Рейд прислужников',
  660. STOPPED: 'Остановлено',
  661. REPETITIONS: 'Повторений',
  662. MISSIONS_PASSED: 'Миссий пройдено',
  663. STOP: 'остановить',
  664. TOTAL_OPEN: 'Всего открыто',
  665. OPEN: 'Открыто',
  666. ROUND_STAT: 'Статистика урона за',
  667. BATTLE: 'боев',
  668. MINIMUM: 'Минимальный',
  669. MAXIMUM: 'Максимальный',
  670. AVERAGE: 'Средний',
  671. NOT_THIS_TIME: 'Не в этот раз',
  672. RETRY_LIMIT_EXCEEDED: 'Превышен лимит попыток',
  673. SUCCESS: 'Успех',
  674. RECEIVED: 'Получено',
  675. LETTERS: 'писем',
  676. PORTALS: 'порталов',
  677. ATTEMPTS: 'попыток',
  678. QUEST_10001: 'Улучши умения героев 3 раза',
  679. QUEST_10002: 'Пройди 10 миссий',
  680. QUEST_10003: 'Пройди 3 героические миссии',
  681. QUEST_10004: 'Сразись 3 раза на Арене или Гранд Арене',
  682. QUEST_10006: 'Используй обмен изумрудов 1 раз',
  683. QUEST_10007: 'Соверши 1 призыв в Атриуме Душ',
  684. QUEST_10016: 'Отправь подарки согильдийцам',
  685. QUEST_10018: 'Используй зелье опыта',
  686. QUEST_10019: 'Открой 1 сундук в Башне',
  687. QUEST_10020: 'Открой 3 сундука в Запределье',
  688. QUEST_10021: 'Собери 75 Титанита в Подземелье Гильдии',
  689. QUEST_10021: 'Собери 150 Титанита в Подземелье Гильдии',
  690. QUEST_10023: 'Прокачай Дар Стихий на 1 уровень',
  691. QUEST_10024: 'Повысь уровень любого артефакта один раз',
  692. QUEST_10025: 'Начни 1 Экспедицию',
  693. QUEST_10026: 'Начни 4 Экспедиции',
  694. QUEST_10027: 'Победи в 1 бою Турнира Стихий',
  695. QUEST_10028: 'Повысь уровень любого артефакта титанов',
  696. QUEST_10029: 'Открой сферу артефактов титанов',
  697. QUEST_10030: 'Улучши облик любого героя 1 раз',
  698. QUEST_10031: 'Победи в 6 боях Турнира Стихий',
  699. QUEST_10043: 'Начни или присоеденись к Приключению',
  700. QUEST_10044: 'Воспользуйся призывом питомцев 1 раз',
  701. QUEST_10046: 'Открой 3 сундука в Приключениях',
  702. QUEST_10047: 'Набери 150 очков активности в Гильдии',
  703. NOTHING_TO_DO: 'Нечего выполнять',
  704. YOU_CAN_COMPLETE: 'Можно выполнить квесты',
  705. BTN_DO_IT: 'Выполняй',
  706. NOT_QUEST_COMPLETED: 'Ни одного квеста не выполенно',
  707. COMPLETED_QUESTS: 'Выполнено квестов',
  708. /* everything button */
  709. ASSEMBLE_OUTLAND: 'Собрать Запределье',
  710. PASS_THE_TOWER: 'Пройти башню',
  711. CHECK_EXPEDITIONS: 'Проверить экспедиции',
  712. COMPLETE_TOE: 'Пройти Турнир Стихий',
  713. COMPLETE_DUNGEON: 'Пройти подземелье',
  714. COMPLETE_DUNGEON_FULL: 'Пройти подземелье фулл',
  715. COLLECT_MAIL: 'Собрать почту',
  716. COLLECT_MISC: 'Собрать всякую херню',
  717. COLLECT_MISC_TITLE: 'Собрать пасхалки, камни облика, ключи, монеты арены и Хрусталь души',
  718. COLLECT_QUEST_REWARDS: 'Собрать награды за квесты',
  719. MAKE_A_SYNC: 'Сделать синхронизацию',
  720.  
  721. RUN_FUNCTION: 'Выполнить следующие функции?',
  722. BTN_GO: 'Погнали!',
  723. PERFORMED: 'Выполняется',
  724. DONE: 'Выполнено',
  725. ERRORS_OCCURRES: 'Призошли ошибки при выполнении',
  726. COPY_ERROR: 'Скопировать в буфер информацию об ошибке',
  727. BTN_YES: 'Да',
  728. ALL_TASK_COMPLETED: 'Все задачи выполнены',
  729.  
  730. UNKNOWN: 'Неизвестно',
  731. ENTER_THE_PATH: 'Введите путь приключения через запятые или дефисы',
  732. START_ADVENTURE: 'Начать приключение по этому пути!',
  733. INCORRECT_WAY: 'Неверный путь в приключении: {from} -> {to}',
  734. BTN_CANCELED: 'Отменено',
  735. MUST_TWO_POINTS: 'Путь должен состоять минимум из 2х точек',
  736. MUST_ONLY_NUMBERS: 'Путь должен содержать только цифры и запятые',
  737. NOT_ON_AN_ADVENTURE: 'Вы не в приключении',
  738. YOU_IN_NOT_ON_THE_WAY: 'Указанный путь должен включать точку вашего положения',
  739. ATTEMPTS_NOT_ENOUGH: 'Ваших попыток не достаточно для завершения пути, продолжить?',
  740. YES_CONTINUE: 'Да, продолжай!',
  741. NOT_ENOUGH_AP: 'Попыток не достаточно',
  742. ATTEMPTS_ARE_OVER: 'Попытки закончились',
  743. MOVES: 'Ходы',
  744. BUFF_GET_ERROR: 'Ошибка при получении бафа',
  745. BATTLE_END_ERROR: 'Ошибка завершения боя',
  746. AUTOBOT: 'АвтоБой',
  747. FAILED_TO_WIN_AUTO: 'Не удалось победить в автобою',
  748. ERROR_OF_THE_BATTLE_COPY: 'Призошли ошибка в процессе прохождения боя<br>Скопировать ошибку в буфер обмена?',
  749. ERROR_DURING_THE_BATTLE: 'Ошибка в процессе прохождения боя',
  750. NO_CHANCE_WIN: 'Нет шансов победить в этом бою: 0/',
  751. LOST_HEROES: 'Вы победили, но потеряли одного или несколько героев!',
  752. VICTORY_IMPOSSIBLE: 'Победа не возможна, бъем на результат?',
  753. FIND_COEFF: 'Поиск коэффициента больше чем',
  754. BTN_PASS: 'ПРОПУСК',
  755. BRAWLS: 'Потасовки',
  756. BRAWLS_TITLE: 'Включает возможность автопотасовок',
  757. START_AUTO_BRAWLS: 'Запустить Автопотасовки?',
  758. LOSSES: 'Поражений',
  759. WINS: 'Побед',
  760. FIGHTS: 'Боев',
  761. STAGE: 'Стадия',
  762. DONT_HAVE_LIVES: 'У Вас нет жизней',
  763. LIVES: 'Жизни',
  764. SECRET_WEALTH_ALREADY: 'товар за Зелья питомцев уже куплен',
  765. SECRET_WEALTH_NOT_ENOUGH: 'Не достаточно Зелье Питомца, у Вас {available}, нужно {need}',
  766. SECRET_WEALTH_UPGRADE_NEW_PET: 'После покупки Зелье Питомца будет не достаточно для прокачки нового питомца',
  767. SECRET_WEALTH_PURCHASED: 'Куплено {count} {name}',
  768. SECRET_WEALTH_CANCELED: 'Тайное богатство: покупка отменена',
  769. SECRET_WEALTH_BUY: 'У вас {available} Зелье Питомца.<br>Вы хотите купить {countBuy} {name} за {price} Зелье Питомца?',
  770. DAILY_BONUS: 'Ежедневная награда',
  771. DO_DAILY_QUESTS: 'Сделать ежедневные квесты',
  772. ACTIONS: 'Действия',
  773. ACTIONS_TITLE: 'Диалоговое окно с различными действиями',
  774. OTHERS: 'Разное',
  775. OTHERS_TITLE: 'Диалоговое окно с дополнительными различными действиями',
  776. CHOOSE_ACTION: 'Выберите действие',
  777. OPEN_LOOTBOX: 'У Вас {lootBox} ящиков, откываем?',
  778. STAMINA: 'Энергия',
  779. BOXES_OVER: 'Ящики закончились',
  780. NO_BOXES: 'Нет ящиков',
  781. NO_MORE_ACTIVITY: 'Больше активности за предметы сегодня не получить',
  782. EXCHANGE_ITEMS: 'Обменять предметы на очки активности (не более {maxActive})?',
  783. GET_ACTIVITY: 'Получить активность',
  784. NOT_ENOUGH_ITEMS: 'Предметов недостаточно',
  785. ACTIVITY_RECEIVED: 'Получено активности',
  786. NO_PURCHASABLE_HERO_SOULS: 'Нет доступных для покупки душ героев',
  787. PURCHASED_HERO_SOULS: 'Куплено {countHeroSouls} душ героев',
  788. NOT_ENOUGH_EMERALDS_540: 'Недостаточно изюма, нужно 540 у Вас {currentStarMoney}',
  789. CHESTS_NOT_AVAILABLE: 'Сундуки не доступны',
  790. OUTLAND_CHESTS_RECEIVED: 'Получено сундуков Запределья',
  791. RAID_NOT_AVAILABLE: 'Рейд не доступен или сфер нет',
  792. RAID_ADVENTURE: 'Рейд {adventureId} приключения!',
  793. SOMETHING_WENT_WRONG: 'Что-то пошло не так',
  794. ADVENTURE_COMPLETED: 'Приключение {adventureId} пройдено {times} раз',
  795. CLAN_STAT_COPY: 'Клановая статистика скопирована в буфер обмена',
  796. GET_ENERGY: 'Получить энергию',
  797. GET_ENERGY_TITLE: 'Открывает платиновые шкатулки по одной до получения 250 энергии',
  798. ITEM_EXCHANGE: 'Обмен предметов',
  799. ITEM_EXCHANGE_TITLE: 'Обменивает предметы на указанное количество активности',
  800. BUY_SOULS: 'Купить души',
  801. BUY_SOULS_TITLE: 'Купить души героев из всех доступных магазинов',
  802. BUY_OUTLAND: 'Купить Запределье',
  803. BUY_OUTLAND_TITLE: 'Купить 9 сундуков в Запределье за 540 изумрудов',
  804. RAID: 'Рейд',
  805. AUTO_RAID_ADVENTURE: 'Рейд приключения',
  806. AUTO_RAID_ADVENTURE_TITLE: 'Рейд приключения заданное количество раз',
  807. CLAN_STAT: 'Клановая статистика',
  808. CLAN_STAT_TITLE: 'Копирует клановую статистику в буфер обмена',
  809. BTN_AUTO_F5: 'Авто (F5)',
  810. BOSS_DAMAGE: 'Урон по боссу: ',
  811. NOTHING_BUY: 'Нечего покупать',
  812. LOTS_BOUGHT: 'За золото куплено {countBuy} лотов',
  813. BUY_FOR_GOLD: 'Скупить за золото',
  814. BUY_FOR_GOLD_TITLE: 'Скупить предметы за золото в Городской лавке и в магазине Камней Душ Питомцев',
  815. REWARDS_AND_MAIL: 'Награды и почта',
  816. REWARDS_AND_MAIL_TITLE: 'Собирает награды и почту',
  817. New_Year_Clan: 'подарок другу',
  818. New_Year_Clan_TITLE: 'Новогодние подарки друзьям',
  819. COLLECT_REWARDS_AND_MAIL: 'Собрано {countQuests} наград и {countMail} писем',
  820. TIMER_ALREADY: 'Таймер уже запущен {time}',
  821. NO_ATTEMPTS_TIMER_START: 'Попыток нет, запущен таймер {time}',
  822. EPIC_BRAWL_RESULT: '{i} Победы: {wins}/{attempts}, Монеты: {coins}, Серия: {progress}/{nextStage} [Закрыть]{end}',
  823. ATTEMPT_ENDED: '<br>Попытки закончились, запущен таймер {time}',
  824. EPIC_BRAWL: 'Вселенская битва',
  825. EPIC_BRAWL_TITLE: 'Тратит попытки во Вселенской битве',
  826. RELOAD_GAME: 'Перезагрузить игру',
  827. TIMER: 'Таймер:',
  828. SHOW_ERRORS: 'Отображать ошибки',
  829. SHOW_ERRORS_TITLE: 'Отображать ошибки запросов к серверу',
  830. ERROR_MSG: 'Ошибка: {name}<br>{description}',
  831. EVENT_AUTO_BOSS: 'Максимальное количество боев для расчета:</br>{length} * {countTestBattle} = {maxCalcBattle}</br>Если у Вас слабый компьютер на это может потребоваться много времени, нажмите крестик для отмены.</br>Искать лучший пак из всех или первый подходящий?',
  832. BEST_SLOW: 'Лучший (медленее)',
  833. FIRST_FAST: 'Первый (быстрее)',
  834. FREEZE_INTERFACE: 'Идет расчет... <br> Интерфейс может зависнуть.',
  835. ERROR_F12: 'Ошибка, подробности в консоли (F12)',
  836. FAILED_FIND_WIN_PACK: 'Победный пак найти не удалось',
  837. BEST_PACK: 'Наилучший пак: ',
  838. BOSS_HAS_BEEN_DEF: 'Босс {bossLvl} побежден',
  839. NOT_ENOUGH_ATTEMPTS_BOSS: 'Для победы босса ${bossLvl} не хватило попыток, повторить?',
  840. BOSS_VICTORY_IMPOSSIBLE: 'По результатам прерасчета {battles} боев победу получить не удалось. Вы хотите продолжить поиск победного боя на реальных боях?',
  841. BOSS_HAS_BEEN_DEF_TEXT: 'Босс {bossLvl} побежден за<br>{countBattle}/{countMaxBattle} попыток<br>(Сделайте синхронизацию или перезагрузите игру для обновления данных)',
  842. MAP: 'Карта: ',
  843. PLAYER_POS: 'Позиции игроков:',
  844. NY_GIFTS: 'Подарки',
  845. NY_GIFTS_TITLE: 'Открыть все новогодние подарки',
  846. NY_NO_GIFTS: 'Нет не полученных подарков',
  847. NY_GIFTS_COLLECTED: 'Собрано {count} подарков',
  848. CHANGE_MAP: 'Карта острова',
  849. CHANGE_MAP_TITLE: 'Сменить карту острова',
  850. SELECT_ISLAND_MAP: 'Выберите карту острова:',
  851. MAP_NUM: 'Карта {num}',
  852. SECRET_WEALTH_SHOP: 'Тайное богатство {name}: ',
  853. SHOPS: 'Магазины',
  854. SHOPS_DEFAULT: 'Стандартные',
  855. SHOPS_DEFAULT_TITLE: 'Стандартные магазины',
  856. SHOPS_LIST: 'Магазины {number}',
  857. SHOPS_LIST_TITLE: 'Список магазинов {number}',
  858. SHOPS_WARNING: 'Магазины<br><span style="color:red">Если Вы купите монеты магазинов потасовок за изумруды, то их надо использовать сразу, иначе после перезагрузки игры они пропадут!</span>',
  859. MINIONS_WARNING: 'Пачки героев для атаки приспешников неполные, продолжить?',
  860. FAST_SEASON: 'Быстрый сезон',
  861. FAST_SEASON_TITLE: 'Пропуск экрана с выбором карты в сезоне',
  862. SET_NUMBER_LEVELS: 'Указать колличество уровней:',
  863. POSSIBLE_IMPROVE_LEVELS: 'Возможно улучшить только {count} уровней.<br>Улучшаем?',
  864. NOT_ENOUGH_RESOURECES: 'Не хватает ресурсов',
  865. IMPROVED_LEVELS: 'Улучшено уровней: {count}',
  866. ARTIFACTS_UPGRADE: 'Улучшение артефактов',
  867. ARTIFACTS_UPGRADE_TITLE: 'Улучшает указанное количество самых дешевых артефактов героев',
  868. SKINS_UPGRADE: 'Улучшение обликов',
  869. SKINS_UPGRADE_TITLE: 'Улучшает указанное количество самых дешевых обликов героев',
  870. HINT: '<br>Подсказка: ',
  871. PICTURE: '<br>На картинке: ',
  872. ANSWER: '<br>Ответ: ',
  873. NO_HEROES_PACK: 'Проведите хотя бы один бой для сохранения атакующей команды',
  874. BRAWL_AUTO_PACK: 'Автоподбор пачки',
  875. BRAWL_AUTO_PACK_NOT_CUR_HERO: 'Автоматический подбор пачки не подходит для текущего героя',
  876. BRAWL_DAILY_TASK_COMPLETED: 'Ежедневное задание выполнено, продолжить атаку?',
  877. },
  878. };
  879.  
  880. function getLang() {
  881. let lang = '';
  882. if (typeof NXFlashVars !== 'undefined') {
  883. lang = NXFlashVars.interface_lang
  884. }
  885. if (!lang) {
  886. lang = (navigator.language || navigator.userLanguage).substr(0, 2);
  887. }
  888. if (lang == 'ru') {
  889. return lang;
  890. }
  891. return 'en';
  892. }
  893.  
  894. this.I18N = function (constant, replace) {
  895. const selectLang = getLang();
  896. if (constant && constant in i18nLangData[selectLang]) {
  897. const result = i18nLangData[selectLang][constant];
  898. if (replace) {
  899. return result.sprintf(replace);
  900. }
  901. return result;
  902. }
  903. return `% ${constant} %`;
  904. };
  905.  
  906. String.prototype.sprintf = String.prototype.sprintf ||
  907. function () {
  908. "use strict";
  909. var str = this.toString();
  910. if (arguments.length) {
  911. var t = typeof arguments[0];
  912. var key;
  913. var args = ("string" === t || "number" === t) ?
  914. Array.prototype.slice.call(arguments)
  915. : arguments[0];
  916.  
  917. for (key in args) {
  918. str = str.replace(new RegExp("\\{" + key + "\\}", "gi"), args[key]);
  919. }
  920. }
  921.  
  922. return str;
  923. };
  924.  
  925. /**
  926. * Checkboxes
  927. *
  928. * Чекбоксы
  929. */
  930. const checkboxes = {
  931. passBattle: {
  932. label: I18N('SKIP_FIGHTS'),
  933. cbox: null,
  934. title: I18N('SKIP_FIGHTS_TITLE'),
  935. default: false
  936. },
  937. /*sendExpedition: {
  938. label: I18N('AUTO_EXPEDITION'),
  939. cbox: null,
  940. title: I18N('AUTO_EXPEDITION_TITLE'),
  941. default: false
  942. },*/ //тест сдедал экспедиции на авто в сделать все
  943. cancelBattle: {
  944. label: I18N('CANCEL_FIGHT'),
  945. cbox: null,
  946. title: I18N('CANCEL_FIGHT_TITLE'),
  947. default: false,
  948. },
  949. preCalcBattle: {
  950. label: I18N('BATTLE_RECALCULATION'),
  951. cbox: null,
  952. title: I18N('BATTLE_RECALCULATION_TITLE'),
  953. default: false
  954. },
  955. finishingBattle: {
  956. label: I18N('BATTLE_FISHING'),
  957. cbox: null,
  958. title: I18N('BATTLE_FISHING_TITLE'),
  959. default: false
  960. },
  961. treningBattle: {
  962. label: I18N('BATTLE_TRENING'),
  963. cbox: null,
  964. title: I18N('BATTLE_TRENING_TITLE'),
  965. default: false
  966. },
  967. countControl: {
  968. label: I18N('QUANTITY_CONTROL'),
  969. cbox: null,
  970. title: I18N('QUANTITY_CONTROL_TITLE'),
  971. default: true
  972. },
  973. repeatMission: {
  974. label: I18N('REPEAT_CAMPAIGN'),
  975. cbox: null,
  976. title: I18N('REPEAT_CAMPAIGN_TITLE'),
  977. default: false
  978. },
  979. noOfferDonat: {
  980. label: I18N('DISABLE_DONAT'),
  981. cbox: null,
  982. title: I18N('DISABLE_DONAT_TITLE'),
  983. /**
  984. * A crutch to get the field before getting the character id
  985. *
  986. * Костыль чтоб получать поле до получения id персонажа
  987. */
  988. default: (() => {
  989. $result = false;
  990. try {
  991. $result = JSON.parse(localStorage[GM_info.script.name + ':noOfferDonat'])
  992. } catch(e) {
  993. $result = false;
  994. }
  995. return $result || false;
  996. })(),
  997. },
  998. dailyQuests: {
  999. label: I18N('DAILY_QUESTS'),
  1000. cbox: null,
  1001. title: I18N('DAILY_QUESTS_TITLE'),
  1002. default: false
  1003. },
  1004. // Потасовки
  1005. /*autoBrawls: {
  1006. label: I18N('BRAWLS'),
  1007. cbox: null,
  1008. title: I18N('BRAWLS_TITLE'),
  1009. default: (() => {
  1010. $result = false;
  1011. try {
  1012. $result = JSON.parse(localStorage[GM_info.script.name + ':autoBrawls'])
  1013. } catch (e) {
  1014. $result = false;
  1015. }
  1016. return $result || false;
  1017. })(),
  1018. hide: false,
  1019. },
  1020. getAnswer: {
  1021. label: I18N('AUTO_QUIZ'),
  1022. cbox: null,
  1023. title: I18N('AUTO_QUIZ_TITLE'),
  1024. default: false,
  1025. hide: true,
  1026. },
  1027. showErrors: {
  1028. label: I18N('SHOW_ERRORS'),
  1029. cbox: null,
  1030. title: I18N('SHOW_ERRORS_TITLE'),
  1031. default: true
  1032. },*/
  1033. buyForGold: {
  1034. label: I18N('BUY_FOR_GOLD'),
  1035. cbox: null,
  1036. title: I18N('BUY_FOR_GOLD_TITLE'),
  1037. default: false
  1038. },
  1039. hideServers: {
  1040. label: I18N('HIDE_SERVERS'),
  1041. cbox: null,
  1042. title: I18N('HIDE_SERVERS_TITLE'),
  1043. default: false
  1044. },
  1045. fastSeason: {
  1046. label: I18N('FAST_SEASON'),
  1047. cbox: null,
  1048. title: I18N('FAST_SEASON_TITLE'),
  1049. default: false
  1050. },
  1051. };
  1052. /**
  1053. * Get checkbox state
  1054. *
  1055. * Получить состояние чекбокса
  1056. */
  1057. function isChecked(checkBox) {
  1058. if (!(checkBox in checkboxes)) {
  1059. return false;
  1060. }
  1061. return checkboxes[checkBox].cbox?.checked;
  1062. }
  1063. /**
  1064. * Input fields
  1065. *
  1066. * Поля ввода
  1067. */
  1068. const inputs = {
  1069. countTitanit: {
  1070. input: null,
  1071. title: I18N('HOW_MUCH_TITANITE'),
  1072. default: 150,
  1073. },
  1074. speedBattle: {
  1075. input: null,
  1076. title: I18N('COMBAT_SPEED'),
  1077. default: 5,
  1078. },
  1079. //тест повтор компании
  1080. countRaid: {
  1081. input: null,
  1082. title: I18N('HOW_REPEAT_CAMPAIGN'),
  1083. default: 5,
  1084. },
  1085. countTestBattle: {
  1086. input: null,
  1087. title: I18N('NUMBER_OF_TEST'),
  1088. default: 10,
  1089. },
  1090. countAutoBattle: {
  1091. input: null,
  1092. title: I18N('NUMBER_OF_AUTO_BATTLE'),
  1093. default: 10,
  1094. },
  1095. /*FPS: {
  1096. input: null,
  1097. title: 'FPS',
  1098. default: 60,
  1099. }*/
  1100. }
  1101. //сохранка тест
  1102. const inputs2 = {
  1103. countBattle: {
  1104. input: null,
  1105. title: '-1 сохраняет защиту, -2 атаку противника с Replay',
  1106. default: 1,
  1107. },
  1108. needResource: {
  1109. input: null,
  1110. title: 'Мощь противника мин.(тыс.)/урона(млн.)',
  1111. default: 300,
  1112. },
  1113. needResource2: {
  1114. input: null,
  1115. title: 'Мощь противника макс./тип бафа',
  1116. default: 1500,
  1117. },
  1118. }
  1119. //новогодние подарки игрокам других гильдий
  1120. const inputs3 = {
  1121. userID: { // айди игрока посмотреть открыв его инфо
  1122. input: null,
  1123. title: I18N('USER_ID_TITLE'),
  1124. default: 111111,
  1125. },
  1126. GiftNum: { // номер подарка считаем слева направо от 1 до 6, под 1 это за 750 новогодних игрушек
  1127. input: null,
  1128. title: I18N('GIFT_NUM'),
  1129. default: 10,
  1130. },
  1131. AmontID: { // количество ресурсов от 1 до бесконечности
  1132. input: null,
  1133. title: I18N('AMOUNT'),
  1134. default: 1,
  1135. },
  1136. }
  1137. /**
  1138. * Checks the checkbox
  1139. *
  1140. * Поплучить данные поля ввода
  1141. */
  1142. /*function getInput(inputName) {
  1143. return inputs[inputName]?.input?.value;
  1144. }*/
  1145. function getInput(inputName) {
  1146. if (inputName in inputs){return inputs[inputName]?.input?.value;}
  1147. else if (inputName in inputs2){return inputs2[inputName]?.input?.value;}
  1148. //else if (inputName in inputs3){return inputs3[inputName]?.input?.value;}
  1149. else return null
  1150. }
  1151.  
  1152. //тест рейд
  1153. /** Автоповтор миссии */
  1154. let isRepeatMission = false;
  1155. /** Вкл/Выкл автоповтор миссии */
  1156. this.switchRepeatMission = function() {
  1157. isRepeatMission = !isRepeatMission;
  1158. console.log(isRepeatMission);
  1159. }
  1160.  
  1161. /**
  1162. * Control FPS
  1163. *
  1164. * Контроль FPS
  1165. */
  1166. let nextAnimationFrame = Date.now();
  1167. const oldRequestAnimationFrame = this.requestAnimationFrame;
  1168. this.requestAnimationFrame = async function (e) {
  1169. const FPS = Number(getInput('FPS')) || -1;
  1170. const now = Date.now();
  1171. const delay = nextAnimationFrame - now;
  1172. nextAnimationFrame = Math.max(now, nextAnimationFrame) + Math.min(1e3 / FPS, 1e3);
  1173. if (delay > 0) {
  1174. await new Promise((e) => setTimeout(e, delay));
  1175. }
  1176. oldRequestAnimationFrame(e);
  1177. };
  1178.  
  1179. /**
  1180. * Button List
  1181. *
  1182. * Список кнопочек
  1183. */
  1184. const buttons = {
  1185. getOutland: {
  1186. name: I18N('TO_DO_EVERYTHING'),
  1187. title: I18N('TO_DO_EVERYTHING_TITLE'),
  1188. func: testDoYourBest,
  1189. },
  1190. /*
  1191. doActions: {
  1192. name: I18N('ACTIONS'),
  1193. title: I18N('ACTIONS_TITLE'),
  1194. func: async function () {
  1195. const popupButtons = [
  1196. {
  1197. msg: I18N('OUTLAND'),
  1198. result: function () {
  1199. confShow(`${I18N('RUN_SCRIPT')} ${I18N('OUTLAND')}?`, getOutland);
  1200. },
  1201. title: I18N('OUTLAND_TITLE'),
  1202. },
  1203. {
  1204. msg: I18N('TOWER'),
  1205. result: function () {
  1206. confShow(`${I18N('RUN_SCRIPT')} ${I18N('TOWER')}?`, testTower);
  1207. },
  1208. title: I18N('TOWER_TITLE'),
  1209. },
  1210. {
  1211. msg: I18N('EXPEDITIONS'),
  1212. result: function () {
  1213. confShow(`${I18N('RUN_SCRIPT')} ${I18N('EXPEDITIONS')}?`, checkExpedition);
  1214. },
  1215. title: I18N('EXPEDITIONS_TITLE'),
  1216. },
  1217. {
  1218. msg: I18N('MINIONS'),
  1219. result: function () {
  1220. confShow(`${I18N('RUN_SCRIPT')} ${I18N('MINIONS')}?`, testRaidNodes);
  1221. },
  1222. title: I18N('MINIONS_TITLE'),
  1223. },
  1224. {
  1225. msg: I18N('ESTER_EGGS'),
  1226. result: function () {
  1227. confShow(`${I18N('RUN_SCRIPT')} ${I18N('ESTER_EGGS')}?`, offerFarmAllReward);
  1228. },
  1229. title: I18N('ESTER_EGGS_TITLE'),
  1230. },
  1231. {
  1232. msg: I18N('STORM'),
  1233. result: function () {
  1234. testAdventure('solo');
  1235. },
  1236. title: I18N('STORM_TITLE'),
  1237. },
  1238. {
  1239. msg: I18N('REWARDS'),
  1240. result: function () {
  1241. confShow(`${I18N('RUN_SCRIPT')} ${I18N('REWARDS')}?`, questAllFarm);
  1242. },
  1243. title: I18N('REWARDS_TITLE'),
  1244. },
  1245. {
  1246. msg: I18N('MAIL'),
  1247. result: function () {
  1248. confShow(`${I18N('RUN_SCRIPT')} ${I18N('MAIL')}?`, mailGetAll);
  1249. },
  1250. title: I18N('MAIL_TITLE'),
  1251. },
  1252. {
  1253. msg: I18N('SEER'),
  1254. result: function () {
  1255. confShow(`${I18N('RUN_SCRIPT')} ${I18N('SEER')}?`, rollAscension);
  1256. },
  1257. title: I18N('SEER_TITLE'),
  1258. },
  1259. {
  1260. msg: I18N('NY_GIFTS'),
  1261. result: getGiftNewYear,
  1262. title: I18N('NY_GIFTS_TITLE'),
  1263. },
  1264. ];
  1265. popupButtons.push({ result: false, isClose: true })
  1266. const answer = await popup.confirm(`${I18N('CHOOSE_ACTION')}:`, popupButtons);
  1267. if (typeof answer === 'function') {
  1268. answer();
  1269. }
  1270. }
  1271. },*/
  1272. doOthers: {
  1273. name: I18N('OTHERS'),
  1274. title: I18N('OTHERS_TITLE'),
  1275. func: async function () {
  1276. const popupButtons = [
  1277. /*
  1278. {
  1279. msg: I18N('GET_ENERGY'),
  1280. result: farmStamina,
  1281. title: I18N('GET_ENERGY_TITLE'),
  1282. },
  1283. {
  1284. msg: I18N('ITEM_EXCHANGE'),
  1285. result: fillActive,
  1286. title: I18N('ITEM_EXCHANGE_TITLE'),
  1287. },
  1288. {
  1289. msg: I18N('BUY_SOULS'),
  1290. result: function () {
  1291. confShow(`${I18N('RUN_SCRIPT')} ${I18N('BUY_SOULS')}?`, buyHeroFragments);
  1292. },
  1293. title: I18N('BUY_SOULS_TITLE'),
  1294. },
  1295. {
  1296. msg: I18N('BUY_FOR_GOLD'),
  1297. result: function () {
  1298. confShow(`${I18N('RUN_SCRIPT')} ${I18N('BUY_FOR_GOLD')}?`, buyInStoreForGold);
  1299. },
  1300. title: I18N('BUY_FOR_GOLD_TITLE'),
  1301. },
  1302. {
  1303. msg: I18N('BUY_OUTLAND'),
  1304. result: function () {
  1305. confShow(I18N('BUY_OUTLAND_TITLE') + '?', bossOpenChestPay);
  1306. },
  1307. title: I18N('BUY_OUTLAND_TITLE'),
  1308. },
  1309. {
  1310. msg: I18N('AUTO_RAID_ADVENTURE'),
  1311. result: autoRaidAdventure,
  1312. title: I18N('AUTO_RAID_ADVENTURE_TITLE'),
  1313. },
  1314. {
  1315. msg: I18N('CLAN_STAT'),
  1316. result: clanStatistic,
  1317. title: I18N('CLAN_STAT_TITLE'),
  1318. },
  1319. {
  1320. msg: I18N('EPIC_BRAWL'),
  1321. result: async function () {
  1322. confShow(`${I18N('RUN_SCRIPT')} ${I18N('EPIC_BRAWL')}?`, () => {
  1323. const brawl = new epicBrawl;
  1324. brawl.start();
  1325. });
  1326. },
  1327. title: I18N('EPIC_BRAWL_TITLE'),
  1328. },*/
  1329. {
  1330. msg: I18N('ARTIFACTS_UPGRADE'),
  1331. result: updateArtifacts,
  1332. title: I18N('ARTIFACTS_UPGRADE_TITLE'),
  1333. },
  1334. {
  1335. msg: I18N('SKINS_UPGRADE'),
  1336. result: updateSkins,
  1337. title: I18N('SKINS_UPGRADE_TITLE'),
  1338. },
  1339. {
  1340. msg: I18N('CHANGE_MAP'),
  1341. result: async function () {
  1342. const maps = [];
  1343. for (let num = 1; num < 5; num++) {
  1344. maps.push({
  1345. msg: I18N('MAP_NUM', { num }),
  1346. result: num,
  1347. });
  1348. }
  1349.  
  1350. const result = await popup.confirm(I18N('SELECT_ISLAND_MAP'), [
  1351. ...maps,
  1352. { result: false, isClose: true },
  1353. ]);
  1354. if (result) {
  1355. cheats.changeIslandMap(result);
  1356. }
  1357. },
  1358. title: I18N('CHANGE_MAP_TITLE'),
  1359. },
  1360. {
  1361. msg: I18N('SHOPS'),
  1362. result: async function () {
  1363. const shopButtons = [{
  1364. msg: I18N('SHOPS_DEFAULT'),
  1365. result: function () {
  1366. cheats.goDefaultShops();
  1367. },
  1368. title: I18N('SHOPS_DEFAULT_TITLE'),
  1369. }, {
  1370. msg: I18N('SECRET_WEALTH'),
  1371. result: function () {
  1372. cheats.goSecretWealthShops();
  1373. },
  1374. title: I18N('SECRET_WEALTH'),
  1375. }];
  1376. for (let i = 0; i < 4; i++) {
  1377. const number = i + 1;
  1378. shopButtons.push({
  1379. msg: I18N('SHOPS_LIST', { number }),
  1380. result: function () {
  1381. cheats.goCustomShops(i);
  1382. },
  1383. title: I18N('SHOPS_LIST_TITLE', { number }),
  1384. })
  1385. }
  1386. shopButtons.push({ result: false, isClose: true })
  1387. const answer = await popup.confirm(I18N('SHOPS_WARNING'), shopButtons);
  1388. if (typeof answer === 'function') {
  1389. answer();
  1390. }
  1391. },
  1392. title: I18N('SHOPS'),
  1393. },
  1394. ];
  1395.  
  1396. popupButtons.push({ result: false, isClose: true })
  1397. const answer = await popup.confirm(`${I18N('CHOOSE_ACTION')}:`, popupButtons);
  1398. if (typeof answer === 'function') {
  1399. answer();
  1400. }
  1401. }
  1402. },
  1403. testTitanArena: {
  1404. name: I18N('TITAN_ARENA'),
  1405. title: I18N('TITAN_ARENA_TITLE'),
  1406. func: function () {
  1407. confShow(`${I18N('RUN_SCRIPT')} ${I18N('TITAN_ARENA')}?`, testTitanArena);
  1408. },
  1409. },
  1410. /* тест подземка есть в сделать все
  1411. testDungeon: {
  1412. name: I18N('DUNGEON'),
  1413. title: I18N('DUNGEON_TITLE'),
  1414. func: function () {
  1415. confShow(`${I18N('RUN_SCRIPT')} ${I18N('DUNGEON')}?`, testDungeon);
  1416. },
  1417. hide: true,
  1418. },*/
  1419. //тест подземка 2
  1420. DungeonFull: {
  1421. name: I18N('DUNGEON2'),
  1422. title: I18N('DUNGEON_FULL_TITLE'),
  1423. func: function () {
  1424. confShow(`${I18N('RUN_SCRIPT')} ${I18N('DUNGEON_FULL_TITLE')}?`, DungeonFull);
  1425. },
  1426. },
  1427. //остановить подземелье
  1428. stopDungeon: {
  1429. name: I18N('STOP_DUNGEON'),
  1430. title: I18N('STOP_DUNGEON_TITLE'),
  1431. func: function () {
  1432. confShow(`${I18N('STOP_SCRIPT')} ${I18N('STOP_DUNGEON_TITLE')}?`, stopDungeon);
  1433. },
  1434. },
  1435. // Архидемон
  1436. bossRatingEvent: {
  1437. name: I18N('ARCHDEMON'),
  1438. title: I18N('ARCHDEMON_TITLE'),
  1439. func: function () {
  1440. confShow(`${I18N('RUN_SCRIPT')} ${I18N('ARCHDEMON')}?`, bossRatingEvent);
  1441. },
  1442. hide: true,
  1443. },
  1444. /*
  1445. // Горнило душ
  1446. bossRatingEvent: {
  1447. name: I18N('CRUCIBLE_SOULS'),
  1448. title: I18N('CRUCIBLE_SOULS_TITLE'),
  1449. func: function () {
  1450. confShow(`${I18N('RUN_SCRIPT')} ${I18N('CRUCIBLE_SOULS')}?`, bossRatingEventSouls);
  1451. },
  1452. },*/
  1453. // Буря
  1454. /*testAdventure2: {
  1455. name: I18N('STORM'),
  1456. title: I18N('STORM_TITLE'),
  1457. func: () => {
  1458. testAdventure2('solo');
  1459. },
  1460. },*/
  1461. rewardsAndMailFarm: {
  1462. name: I18N('REWARDS_AND_MAIL'),
  1463. title: I18N('REWARDS_AND_MAIL_TITLE'),
  1464. func: function () {
  1465. confShow(`${I18N('RUN_SCRIPT')} ${I18N('REWARDS_AND_MAIL')}?`, rewardsAndMailFarm);
  1466. },
  1467. },
  1468. //тест прислужники
  1469. testRaidNodes: {
  1470. name: I18N('MINIONS'),
  1471. title: I18N('MINIONS_TITLE'),
  1472. func: function () {
  1473. confShow(`${I18N('RUN_SCRIPT')} ${I18N('MINIONS')}?`, testRaidNodes);
  1474. },
  1475. },
  1476. testAdventure: {
  1477. name: I18N('ADVENTURE'),
  1478. title: I18N('ADVENTURE_TITLE'),
  1479. func: () => {
  1480. testAdventure();
  1481. },
  1482. },
  1483. goToSanctuary: {
  1484. name: I18N('SANCTUARY'),
  1485. title: I18N('SANCTUARY_TITLE'),
  1486. func: cheats.goSanctuary,
  1487. },
  1488. goToClanWar: {
  1489. name: I18N('GUILD_WAR'),
  1490. title: I18N('GUILD_WAR_TITLE'),
  1491. func: cheats.goClanWar,
  1492. },
  1493. dailyQuests: {
  1494. name: I18N('DAILY_QUESTS'),
  1495. title: I18N('DAILY_QUESTS_TITLE'),
  1496. func: async function () {
  1497. const quests = new dailyQuests(() => { }, () => { });
  1498. await quests.autoInit();
  1499. quests.start();
  1500. },
  1501. },
  1502. //подарок др
  1503. /*NewYearGift_Clan: {
  1504. name: I18N('New_Year_Clan'),
  1505. title: I18N('New_Year_Clan_TITLE'),
  1506. func: function () {
  1507. confShow(`${I18N('RUN_SCRIPT')} ${I18N('New_Year_Clan_TITLE')}?`, NewYearGift_Clan);
  1508. },
  1509. },*/
  1510. newDay: {
  1511. name: I18N('SYNC'),
  1512. title: I18N('SYNC_TITLE'),
  1513. func: function () {
  1514. confShow(`${I18N('RUN_SCRIPT')} ${I18N('SYNC')}?`, cheats.refreshGame);
  1515. },
  1516. },
  1517. }
  1518. /**
  1519. * Display buttons
  1520. *
  1521. * Вывести кнопочки
  1522. */
  1523. function addControlButtons() {
  1524. for (let name in buttons) {
  1525. button = buttons[name];
  1526. if (button.hide) {
  1527. continue;
  1528. }
  1529. button['button'] = scriptMenu.addButton(button.name, button.func, button.title);
  1530. }
  1531. }
  1532. /**
  1533. * Adds links
  1534. *
  1535. * Добавляет ссылки
  1536. */
  1537. function addBottomUrls() {
  1538. scriptMenu.addHeader(I18N('BOTTOM_URLS'));
  1539. }
  1540. /**
  1541. * Stop repetition of the mission
  1542. *
  1543. * Остановить повтор миссии
  1544. */
  1545. let isStopSendMission = false;
  1546. /**
  1547. * There is a repetition of the mission
  1548. *
  1549. * Идет повтор миссии
  1550. */
  1551. let isSendsMission = false;
  1552. /**
  1553. * Data on the past mission
  1554. *
  1555. * Данные о прошедшей мисии
  1556. */
  1557. let lastMissionStart = {}
  1558. /**
  1559. * Start time of the last battle in the company
  1560. *
  1561. * Время начала последнего боя в кампании
  1562. */
  1563. let lastMissionBattleStart = 0;
  1564. /**
  1565. * Data on the past attack on the boss
  1566. *
  1567. * Данные о прошедшей атаке на босса
  1568. */
  1569. let lastBossBattle = {}
  1570. /**
  1571. * Data for calculating the last battle with the boss
  1572. *
  1573. * Данные для расчете последнего боя с боссом
  1574. */
  1575. let lastBossBattleInfo = null;
  1576. /**
  1577. * Ability to cancel the battle in Asgard
  1578. *
  1579. * Возможность отменить бой в Астгарде
  1580. */
  1581. let isCancalBossBattle = true;
  1582. /**
  1583. * Information about the last battle
  1584. *
  1585. * Данные о прошедшей битве
  1586. */
  1587. let lastBattleArg = {}
  1588. let lastBossBattleStart = null;
  1589. this.addBattleTimer = 4;
  1590. this.invasionTimer = 2500;
  1591. /**
  1592. * The name of the function of the beginning of the battle
  1593. *
  1594. * Имя функции начала боя
  1595. */
  1596. let nameFuncStartBattle = '';
  1597. /**
  1598. * The name of the function of the end of the battle
  1599. *
  1600. * Имя функции конца боя
  1601. */
  1602. let nameFuncEndBattle = '';
  1603. /**
  1604. * Data for calculating the last battle
  1605. *
  1606. * Данные для расчета последнего боя
  1607. */
  1608. let lastBattleInfo = null;
  1609. /**
  1610. * The ability to cancel the battle
  1611. *
  1612. * Возможность отменить бой
  1613. */
  1614. let isCancalBattle = true;
  1615.  
  1616. /**
  1617. * Certificator of the last open nesting doll
  1618. *
  1619. * Идетификатор последней открытой матрешки
  1620. */
  1621. let lastRussianDollId = null;
  1622. /**
  1623. * Cancel the training guide
  1624. *
  1625. * Отменить обучающее руководство
  1626. */
  1627. this.isCanceledTutorial = false;
  1628.  
  1629. /**
  1630. * Data from the last question of the quiz
  1631. *
  1632. * Данные последнего вопроса викторины
  1633. */
  1634. let lastQuestion = null;
  1635. /**
  1636. * Answer to the last question of the quiz
  1637. *
  1638. * Ответ на последний вопрос викторины
  1639. */
  1640. let lastAnswer = null;
  1641. /**
  1642. * Flag for opening keys or titan artifact spheres
  1643. *
  1644. * Флаг открытия ключей или сфер артефактов титанов
  1645. */
  1646. let artifactChestOpen = false;
  1647. /**
  1648. * The name of the function to open keys or orbs of titan artifacts
  1649. *
  1650. * Имя функции открытия ключей или сфер артефактов титанов
  1651. */
  1652. let artifactChestOpenCallName = '';
  1653. let correctShowOpenArtifact = 0;
  1654. /**
  1655. * Data for the last battle in the dungeon
  1656. * (Fix endless cards)
  1657. *
  1658. * Данные для последнего боя в подземке
  1659. * (Исправление бесконечных карт)
  1660. */
  1661. let lastDungeonBattleData = null;
  1662. /**
  1663. * Start time of the last battle in the dungeon
  1664. *
  1665. * Время начала последнего боя в подземелье
  1666. */
  1667. let lastDungeonBattleStart = 0;
  1668. /**
  1669. * Subscription end time
  1670. *
  1671. * Время окончания подписки
  1672. */
  1673. let subEndTime = 0;
  1674. /**
  1675. * Number of prediction cards
  1676. *
  1677. * Количество карт предсказаний
  1678. */
  1679. let countPredictionCard = 0;
  1680.  
  1681. /**
  1682. * Brawl pack
  1683. *
  1684. * Пачка для потасовок
  1685. */
  1686. let brawlsPack = null;
  1687. /**
  1688. * Autobrawl started
  1689. *
  1690. * Автопотасовка запущена
  1691. */
  1692. let isBrawlsAutoStart = false;
  1693. /**
  1694. * Copies the text to the clipboard
  1695. *
  1696. * Копирует тест в буфер обмена
  1697. * @param {*} text copied text // копируемый текст
  1698. */
  1699. function copyText(text) {
  1700. let copyTextarea = document.createElement("textarea");
  1701. copyTextarea.style.opacity = "0";
  1702. copyTextarea.textContent = text;
  1703. document.body.appendChild(copyTextarea);
  1704. copyTextarea.select();
  1705. document.execCommand("copy");
  1706. document.body.removeChild(copyTextarea);
  1707. delete copyTextarea;
  1708. }
  1709. /**
  1710. * Returns the history of requests
  1711. *
  1712. * Возвращает историю запросов
  1713. */
  1714. this.getRequestHistory = function() {
  1715. return requestHistory;
  1716. }
  1717. /**
  1718. * Generates a random integer from min to max
  1719. *
  1720. * Гененирует случайное целое число от min до max
  1721. */
  1722. const random = function (min, max) {
  1723. return Math.floor(Math.random() * (max - min + 1) + min);
  1724. }
  1725. /**
  1726. * Clearing the request history
  1727. *
  1728. * Очистка истоии запросов
  1729. */
  1730. setInterval(function () {
  1731. let now = Date.now();
  1732. for (let i in requestHistory) {
  1733. const time = +i.split('_')[0];
  1734. if (now - time > 300000) {
  1735. delete requestHistory[i];
  1736. }
  1737. }
  1738. }, 300000);
  1739. /**
  1740. * Displays the dialog box
  1741. *
  1742. * Отображает диалоговое окно
  1743. */
  1744. function confShow(message, yesCallback, noCallback) {
  1745. let buts = [];
  1746. message = message || I18N('DO_YOU_WANT');
  1747. noCallback = noCallback || (() => {});
  1748. if (yesCallback) {
  1749. buts = [
  1750. { msg: I18N('BTN_RUN'), result: true},
  1751. { msg: I18N('BTN_CANCEL'), result: false, isCancel: true},
  1752. ]
  1753. } else {
  1754. yesCallback = () => {};
  1755. buts = [
  1756. { msg: I18N('BTN_OK'), result: true},
  1757. ];
  1758. }
  1759. popup.confirm(message, buts).then((e) => {
  1760. // dialogPromice = null;
  1761. if (e) {
  1762. yesCallback();
  1763. } else {
  1764. noCallback();
  1765. }
  1766. });
  1767. }
  1768. /**
  1769. * Override/proxy the method for creating a WS package send
  1770. *
  1771. * Переопределяем/проксируем метод создания отправки WS пакета
  1772. */
  1773. WebSocket.prototype.send = function (data) {
  1774. if (!this.isSetOnMessage) {
  1775. const oldOnmessage = this.onmessage;
  1776. this.onmessage = function (event) {
  1777. try {
  1778. const data = JSON.parse(event.data);
  1779. if (!this.isWebSocketLogin && data.result.type == "iframeEvent.login") {
  1780. this.isWebSocketLogin = true;
  1781. } else if (data.result.type == "iframeEvent.login") {
  1782. return;
  1783. }
  1784. } catch (e) { }
  1785. return oldOnmessage.apply(this, arguments);
  1786. }
  1787. this.isSetOnMessage = true;
  1788. }
  1789. original.SendWebSocket.call(this, data);
  1790. }
  1791. /**
  1792. * Overriding/Proxying the Ajax Request Creation Method
  1793. *
  1794. * Переопределяем/проксируем метод создания Ajax запроса
  1795. */
  1796. XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
  1797. this.uniqid = Date.now() + '_' + random(1000000, 10000000);
  1798. this.errorRequest = false;
  1799. if (method == 'POST' && url.includes('.nextersglobal.com/api/') && /api\/$/.test(url)) {
  1800. if (!apiUrl) {
  1801. apiUrl = url;
  1802. const socialInfo = /heroes-(.+?)\./.exec(apiUrl);
  1803. console.log(socialInfo);
  1804. }
  1805. requestHistory[this.uniqid] = {
  1806. method,
  1807. url,
  1808. error: [],
  1809. headers: {},
  1810. request: null,
  1811. response: null,
  1812. signature: [],
  1813. calls: {},
  1814. };
  1815. } else if (method == 'POST' && url.includes('error.nextersglobal.com/client/')) {
  1816. this.errorRequest = true;
  1817. }
  1818. return original.open.call(this, method, url, async, user, password);
  1819. };
  1820. /**
  1821. * Overriding/Proxying the header setting method for the AJAX request
  1822. *
  1823. * Переопределяем/проксируем метод установки заголовков для AJAX запроса
  1824. */
  1825. XMLHttpRequest.prototype.setRequestHeader = function (name, value, check) {
  1826. if (this.uniqid in requestHistory) {
  1827. requestHistory[this.uniqid].headers[name] = value;
  1828. } else {
  1829. check = true;
  1830. }
  1831.  
  1832. if (name == 'X-Auth-Signature') {
  1833. requestHistory[this.uniqid].signature.push(value);
  1834. if (!check) {
  1835. return;
  1836. }
  1837. }
  1838.  
  1839. return original.setRequestHeader.call(this, name, value);
  1840. };
  1841. /**
  1842. * Overriding/Proxying the AJAX Request Sending Method
  1843. *
  1844. * Переопределяем/проксируем метод отправки AJAX запроса
  1845. */
  1846. XMLHttpRequest.prototype.send = async function (sourceData) {
  1847. if (this.uniqid in requestHistory) {
  1848. let tempData = null;
  1849. if (getClass(sourceData) == "ArrayBuffer") {
  1850. tempData = decoder.decode(sourceData);
  1851. } else {
  1852. tempData = sourceData;
  1853. }
  1854. requestHistory[this.uniqid].request = tempData;
  1855. let headers = requestHistory[this.uniqid].headers;
  1856. lastHeaders = Object.assign({}, headers);
  1857. /**
  1858. * Game loading event
  1859. *
  1860. * Событие загрузки игры
  1861. */
  1862. if (headers["X-Request-Id"] > 2 && !isLoadGame) {
  1863. isLoadGame = true;
  1864. await lib.load();
  1865. addControls();
  1866. addControlButtons();
  1867. addBottomUrls();
  1868.  
  1869. //if (isChecked('sendExpedition')) {
  1870. checkExpedition(); //экспедиции на авто при входе в игру
  1871. //}
  1872.  
  1873. getAutoGifts();
  1874.  
  1875. cheats.activateHacks();
  1876.  
  1877. justInfo();
  1878. if (isChecked('dailyQuests')) {
  1879. testDailyQuests();
  1880. }
  1881.  
  1882. if (isChecked('buyForGold')) {
  1883. buyInStoreForGold();
  1884. }
  1885. }
  1886. /**
  1887. * Outgoing request data processing
  1888. *
  1889. * Обработка данных исходящего запроса
  1890. */
  1891. sourceData = await checkChangeSend.call(this, sourceData, tempData);
  1892. /**
  1893. * Handling incoming request data
  1894. *
  1895. * Обработка данных входящего запроса
  1896. */
  1897. const oldReady = this.onreadystatechange;
  1898. this.onreadystatechange = async function (e) {
  1899. if (this.errorRequest) {
  1900. return oldReady.apply(this, arguments);
  1901. }
  1902. if(this.readyState == 4 && this.status == 200) {
  1903. isTextResponse = this.responseType === "text" || this.responseType === "";
  1904. let response = isTextResponse ? this.responseText : this.response;
  1905. requestHistory[this.uniqid].response = response;
  1906. /**
  1907. * Replacing incoming request data
  1908. *
  1909. * Заменна данных входящего запроса
  1910. */
  1911. if (isTextResponse) {
  1912. await checkChangeResponse.call(this, response);
  1913. }
  1914. /**
  1915. * A function to run after the request is executed
  1916. *
  1917. * Функция запускаемая после выполения запроса
  1918. */
  1919. if (typeof this.onReadySuccess == 'function') {
  1920. setTimeout(this.onReadySuccess, 500);
  1921. }
  1922. /** Удаляем из истории запросов битвы с боссом */
  1923. if ('invasion_bossStart' in requestHistory[this.uniqid].calls) delete requestHistory[this.uniqid];
  1924. }
  1925. if (oldReady) {
  1926. return oldReady.apply(this, arguments);
  1927. }
  1928. }
  1929. }
  1930. if (this.errorRequest) {
  1931. const oldReady = this.onreadystatechange;
  1932. this.onreadystatechange = function () {
  1933. Object.defineProperty(this, 'status', {
  1934. writable: true
  1935. });
  1936. this.status = 200;
  1937. Object.defineProperty(this, 'readyState', {
  1938. writable: true
  1939. });
  1940. this.readyState = 4;
  1941. Object.defineProperty(this, 'responseText', {
  1942. writable: true
  1943. });
  1944. this.responseText = JSON.stringify({
  1945. "result": true
  1946. });
  1947. if (typeof this.onReadySuccess == 'function') {
  1948. setTimeout(this.onReadySuccess, 500);
  1949. }
  1950. return oldReady.apply(this, arguments);
  1951. }
  1952. this.onreadystatechange();
  1953. } else {
  1954. try {
  1955. return original.send.call(this, sourceData);
  1956. } catch(e) {
  1957. debugger;
  1958. }
  1959.  
  1960. }
  1961. };
  1962. /**
  1963. * Processing and substitution of outgoing data
  1964. *
  1965. * Обработка и подмена исходящих данных
  1966. */
  1967. async function checkChangeSend(sourceData, tempData) {
  1968. try {
  1969. /**
  1970. * A function that replaces battle data with incorrect ones to cancel combatя
  1971. *
  1972. * Функция заменяющая данные боя на неверные для отмены боя
  1973. */
  1974. const fixBattle = function (heroes) {
  1975. for (const ids in heroes) {
  1976. hero = heroes[ids];
  1977. hero.energy = random(1, 999);
  1978. if (hero.hp > 0) {
  1979. hero.hp = random(1, hero.hp);
  1980. }
  1981. }
  1982. }
  1983. /**
  1984. * Dialog window 2
  1985. *
  1986. * Диалоговое окно 2
  1987. */
  1988. const showMsg = async function (msg, ansF, ansS) {
  1989. if (typeof popup == 'object') {
  1990. return await popup.confirm(msg, [
  1991. {msg: ansF, result: false},
  1992. {msg: ansS, result: true},
  1993. ]);
  1994. } else {
  1995. return !confirm(`${msg}\n ${ansF} (${I18N('BTN_OK')})\n ${ansS} (${I18N('BTN_CANCEL')})`);
  1996. }
  1997. }
  1998. /**
  1999. * Dialog window 3
  2000. *
  2001. * Диалоговое окно 3
  2002. */
  2003. const showMsgs = async function (msg, ansF, ansS, ansT) {
  2004. return await popup.confirm(msg, [
  2005. {msg: ansF, result: 0},
  2006. {msg: ansS, result: 1},
  2007. {msg: ansT, result: 2},
  2008. ]);
  2009. }
  2010.  
  2011. let changeRequest = false;
  2012. testData = JSON.parse(tempData);
  2013. for (const call of testData.calls) {
  2014. if (!artifactChestOpen) {
  2015. requestHistory[this.uniqid].calls[call.name] = call.ident;
  2016. }
  2017. /**
  2018. * Cancellation of the battle in adventures, on VG and with minions of Asgard
  2019. * Отмена боя в приключениях, на ВГ и с прислужниками Асгарда
  2020. */
  2021. if ((call.name == 'adventure_endBattle' ||
  2022. call.name == 'adventureSolo_endBattle' ||
  2023. call.name == 'clanWarEndBattle' &&
  2024. isChecked('cancelBattle') ||
  2025. call.name == 'crossClanWar_endBattle' &&
  2026. isChecked('cancelBattle') ||
  2027. call.name == 'brawl_endBattle' ||
  2028. call.name == 'towerEndBattle' ||
  2029. call.name == 'invasion_bossEnd' ||
  2030. call.name == 'bossEndBattle' ||
  2031. call.name == 'clanRaid_endNodeBattle') &&
  2032. isCancalBattle) {
  2033. nameFuncEndBattle = call.name;
  2034. if (!call.args.result.win) {
  2035. let resultPopup = false;
  2036. if (call.name == 'adventure_endBattle' ||
  2037. call.name == 'invasion_bossEnd' ||
  2038. call.name == 'bossEndBattle' ||
  2039. call.name == 'adventureSolo_endBattle') {
  2040. resultPopup = await showMsgs(I18N('MSG_HAVE_BEEN_DEFEATED'), I18N('BTN_OK'), I18N('BTN_CANCEL'), I18N('BTN_AUTO'));
  2041. } else if (call.name == 'clanWarEndBattle' ||
  2042. call.name == 'crossClanWar_endBattle') {
  2043. resultPopup = await showMsg(I18N('MSG_HAVE_BEEN_DEFEATED'), I18N('BTN_OK'), I18N('BTN_AUTO_F5'));
  2044. } else {
  2045. resultPopup = await showMsg(I18N('MSG_HAVE_BEEN_DEFEATED'), I18N('BTN_OK'), I18N('BTN_CANCEL'));
  2046. }
  2047. if (resultPopup) {
  2048. if (call.name == 'invasion_bossEnd') {
  2049. this.errorRequest = true;
  2050. }
  2051. fixBattle(call.args.progress[0].attackers.heroes);
  2052. fixBattle(call.args.progress[0].defenders.heroes);
  2053. changeRequest = true;
  2054. if (resultPopup > 1) {
  2055. this.onReadySuccess = testAutoBattle;
  2056. // setTimeout(bossBattle, 1000);
  2057. }
  2058. }
  2059. } else if (call.args.result.stars < 3 && call.name == 'towerEndBattle') {
  2060. resultPopup = await showMsg(I18N('LOST_HEROES'), I18N('BTN_OK'), I18N('BTN_CANCEL'), I18N('BTN_AUTO'));
  2061. if (resultPopup) {
  2062. fixBattle(call.args.progress[0].attackers.heroes);
  2063. fixBattle(call.args.progress[0].defenders.heroes);
  2064. changeRequest = true;
  2065. if (resultPopup > 1) {
  2066. this.onReadySuccess = testAutoBattle;
  2067. }
  2068. }
  2069. }
  2070. // Потасовки
  2071. if (isChecked('autoBrawls') && !isBrawlsAutoStart && call.name == 'brawl_endBattle') {}
  2072. }
  2073. /**
  2074. * Save pack for Brawls
  2075. *
  2076. * Сохраняем пачку для потасовок
  2077. */
  2078. if (isChecked('autoBrawls') && !isBrawlsAutoStart && call.name == 'brawl_startBattle') {
  2079. console.log(JSON.stringify(call.args));
  2080. brawlsPack = call.args;
  2081. if (
  2082. await popup.confirm(
  2083. I18N('START_AUTO_BRAWLS'),
  2084. [
  2085. { msg: I18N('BTN_NO'), result: false },
  2086. { msg: I18N('BTN_YES'), result: true },
  2087. ],
  2088. [
  2089. {
  2090. name: 'isAuto',
  2091. label: I18N('BRAWL_AUTO_PACK'),
  2092. checked: false,
  2093. },
  2094. ]
  2095. )
  2096. ) {
  2097. isBrawlsAutoStart = true;
  2098. const isAuto = popup.getCheckBoxes().find((e) => e.name === 'isAuto');
  2099. this.errorRequest = true;
  2100. testBrawls(isAuto.checked);
  2101. }
  2102. }
  2103. /**
  2104. * Canceled fight in Asgard
  2105. * Отмена боя в Асгарде
  2106. */
  2107. if (call.name == 'clanRaid_endBossBattle' &&
  2108. isCancalBossBattle &&
  2109. isChecked('cancelBattle')) {
  2110. bossDamage = call.args.progress[0].defenders.heroes[1].extra;
  2111. sumDamage = bossDamage.damageTaken + bossDamage.damageTakenNextLevel;
  2112. let resultPopup = await showMsgs(
  2113. `${I18N('MSG_YOU_APPLIED')} ${sumDamage.toLocaleString()} ${I18N('MSG_DAMAGE')}.`,
  2114. I18N('BTN_OK'), I18N('BTN_AUTO_F5'), I18N('MSG_CANCEL_AND_STAT'))
  2115. if (resultPopup) {
  2116. fixBattle(call.args.progress[0].attackers.heroes);
  2117. fixBattle(call.args.progress[0].defenders.heroes);
  2118. changeRequest = true;
  2119. if (resultPopup > 1) {
  2120. this.onReadySuccess = testBossBattle;
  2121. // setTimeout(bossBattle, 1000);
  2122. }
  2123. }
  2124. }
  2125. /**
  2126. * Save the Asgard Boss Attack Pack
  2127. * Сохраняем пачку для атаки босса Асгарда
  2128. */
  2129. if (call.name == 'clanRaid_startBossBattle') {
  2130. lastBossBattle = call.args;
  2131. }
  2132. /**
  2133. * Saving the request to start the last battle
  2134. * Сохранение запроса начала последнего боя
  2135. */
  2136. if (call.name == 'clanWarAttack' ||
  2137. call.name == 'crossClanWar_startBattle' ||
  2138. call.name == 'adventure_turnStartBattle' ||
  2139. call.name == 'bossAttack' ||
  2140. call.name == 'invasion_bossStart' ||
  2141. call.name == 'towerStartBattle') {
  2142. nameFuncStartBattle = call.name;
  2143. lastBattleArg = call.args;
  2144.  
  2145. if (call.name == 'invasion_bossStart') {
  2146. const timePassed = Date.now() - lastBossBattleStart;
  2147. if (timePassed < invasionTimer) {
  2148. await new Promise((e) => setTimeout(e, invasionTimer - timePassed));
  2149. }
  2150. invasionTimer -= 1;
  2151. }
  2152. lastBossBattleStart = Date.now();
  2153. }
  2154. if (call.name == 'invasion_bossEnd') {
  2155. const lastBattle = lastBattleInfo;
  2156. if (lastBattle && call.args.result.win) {
  2157. lastBattle.progress = call.args.progress;
  2158. const result = await Calc(lastBattle);
  2159. let timer = getTimer(result.battleTime, 1) + addBattleTimer;
  2160. const period = Math.ceil((Date.now() - lastBossBattleStart) / 1000);
  2161. console.log(timer, period);
  2162. if (period < timer) {
  2163. timer = timer - period;
  2164. await countdownTimer(timer);
  2165. }
  2166. }
  2167. }
  2168. /**
  2169. * Disable spending divination cards
  2170. * Отключить трату карт предсказаний
  2171. */
  2172. if (call.name == 'dungeonEndBattle') {
  2173. if (call.args.isRaid) {
  2174. if (countPredictionCard <= 0) {
  2175. delete call.args.isRaid;
  2176. changeRequest = true;
  2177. } else if (countPredictionCard > 0) {
  2178. countPredictionCard--;
  2179. }
  2180. }
  2181. console.log(`Cards: ${countPredictionCard}`);
  2182. /**
  2183. * Fix endless cards
  2184. * Исправление бесконечных карт
  2185. */
  2186. const lastBattle = lastDungeonBattleData;
  2187. if (lastBattle && !call.args.isRaid) {
  2188. if (changeRequest) {
  2189. lastBattle.progress = [{ attackers: { input: ["auto", 0, 0, "auto", 0, 0] } }];
  2190. } else {
  2191. lastBattle.progress = call.args.progress;
  2192. }
  2193. const result = await Calc(lastBattle);
  2194.  
  2195. if (changeRequest) {
  2196. call.args.progress = result.progress;
  2197. call.args.result = result.result;
  2198. }
  2199.  
  2200. let timer = getTimer(result.battleTime) + addBattleTimer;
  2201. const period = Math.ceil((Date.now() - lastDungeonBattleStart) / 1000);
  2202. console.log(timer, period);
  2203. if (period < timer) {
  2204. timer = timer - period;
  2205. await countdownTimer(timer);
  2206. }
  2207. }
  2208. }
  2209. /**
  2210. * Quiz Answer
  2211. * Ответ на викторину
  2212. */
  2213. if (call.name == 'quizAnswer') {
  2214. /**
  2215. * Automatically changes the answer to the correct one if there is one.
  2216. * Автоматически меняет ответ на правильный если он есть
  2217. */
  2218. if (lastAnswer && isChecked('getAnswer')) {
  2219. call.args.answerId = lastAnswer;
  2220. lastAnswer = null;
  2221. changeRequest = true;
  2222. }
  2223. }
  2224. /**
  2225. * Present
  2226. * Подарки
  2227. */
  2228. if (call.name == 'freebieCheck') {
  2229. freebieCheckInfo = call;
  2230. }
  2231. /** missionTimer */
  2232. if (call.name == 'missionEnd' && missionBattle) {
  2233. missionBattle.progress = call.args.progress;
  2234. missionBattle.result = call.args.result;
  2235. const result = await Calc(missionBattle);
  2236.  
  2237. let timer = getTimer(result.battleTime) + addBattleTimer;
  2238. const period = Math.ceil((Date.now() - lastMissionBattleStart) / 1000);
  2239. if (period < timer) {
  2240. timer = timer - period;
  2241. await countdownTimer(timer);
  2242. }
  2243. missionBattle = null;
  2244. }
  2245. /**
  2246. * Getting mission data for auto-repeat
  2247. * Получение данных миссии для автоповтора
  2248. */
  2249. if (isChecked('repeatMission') &&
  2250. call.name == 'missionEnd') {
  2251. let missionInfo = {
  2252. id: call.args.id,
  2253. result: call.args.result,
  2254. heroes: call.args.progress[0].attackers.heroes,
  2255. count: 0,
  2256. }
  2257. setTimeout(async () => {
  2258. if (!isSendsMission && await popup.confirm(I18N('MSG_REPEAT_MISSION'), [
  2259. { msg: I18N('BTN_REPEAT'), result: true},
  2260. { msg: I18N('BTN_NO'), result: false},
  2261. ])) {
  2262. isStopSendMission = false;
  2263. isSendsMission = true;
  2264. sendsMission(missionInfo);
  2265. }
  2266. }, 0);
  2267. }
  2268. /**
  2269. * Getting mission data
  2270. * Получение данных миссии
  2271. * missionTimer
  2272. */
  2273. if (call.name == 'missionStart') {
  2274. lastMissionStart = call.args;
  2275. lastMissionBattleStart = Date.now();
  2276. }
  2277.  
  2278. /**
  2279. * Specify the quantity for Titan Orbs and Pet Eggs
  2280. * Указать количество для сфер титанов и яиц петов
  2281. */
  2282. if (isChecked('countControl') &&
  2283. (call.name == 'pet_chestOpen' ||
  2284. call.name == 'titanUseSummonCircle') &&
  2285. call.args.amount > 1) {
  2286. call.args.amount = 1;
  2287. const result = await popup.confirm(I18N('MSG_SPECIFY_QUANT'), [
  2288. { msg: I18N('BTN_OPEN'), isInput: true, default: call.args.amount},
  2289. ]);
  2290. if (result) {
  2291. call.args.amount = result;
  2292. changeRequest = true;
  2293. }
  2294. }
  2295. /**
  2296. * Specify the amount for keys and spheres of titan artifacts
  2297. * Указать колличество для ключей и сфер артефактов титанов
  2298. */
  2299. if (isChecked('countControl') &&
  2300. (call.name == 'artifactChestOpen' ||
  2301. call.name == 'titanArtifactChestOpen') &&
  2302. call.args.amount > 1 &&
  2303. call.args.free &&
  2304. !changeRequest) {
  2305. artifactChestOpenCallName = call.name;
  2306. let result = await popup.confirm(I18N('MSG_SPECIFY_QUANT'), [
  2307. { msg: I18N('BTN_OPEN'), isInput: true, default: call.args.amount },
  2308. ]);
  2309. if (result) {
  2310. let sphere = result < 10 ? 1 : 10;
  2311.  
  2312. call.args.amount = sphere;
  2313. result -= sphere;
  2314.  
  2315. for (let count = result; count > 0; count -= sphere) {
  2316. if (count < 10) sphere = 1;
  2317. const ident = artifactChestOpenCallName + "_" + count;
  2318. testData.calls.push({
  2319. name: artifactChestOpenCallName,
  2320. args: {
  2321. amount: sphere,
  2322. free: true,
  2323. },
  2324. ident: ident
  2325. });
  2326. if (!Array.isArray(requestHistory[this.uniqid].calls[call.name])) {
  2327. requestHistory[this.uniqid].calls[call.name] = [requestHistory[this.uniqid].calls[call.name]];
  2328. }
  2329. requestHistory[this.uniqid].calls[call.name].push(ident);
  2330. }
  2331.  
  2332. artifactChestOpen = true;
  2333. changeRequest = true;
  2334. }
  2335. }
  2336. if (call.name == 'consumableUseLootBox') {
  2337. lastRussianDollId = call.args.libId;
  2338. /**
  2339. * Specify quantity for gold caskets
  2340. * Указать количество для золотых шкатулок
  2341. */
  2342. if (isChecked('countControl') &&
  2343. call.args.libId == 148 &&
  2344. call.args.amount > 1) {
  2345. const result = await popup.confirm(I18N('MSG_SPECIFY_QUANT'), [
  2346. { msg: I18N('BTN_OPEN'), isInput: true, default: call.args.amount},
  2347. ]);
  2348. call.args.amount = result;
  2349. changeRequest = true;
  2350. }
  2351. }
  2352. /**
  2353. * Changing the maximum number of raids in the campaign
  2354. * Изменение максимального количества рейдов в кампании
  2355. */
  2356. // if (call.name == 'missionRaid') {
  2357. // if (isChecked('countControl') && call.args.times > 1) {
  2358. // const result = +(await popup.confirm(I18N('MSG_SPECIFY_QUANT'), [
  2359. // { msg: I18N('BTN_RUN'), isInput: true, default: call.args.times },
  2360. // ]));
  2361. // call.args.times = result > call.args.times ? call.args.times : result;
  2362. // changeRequest = true;
  2363. // }
  2364. // }
  2365. }
  2366.  
  2367. let headers = requestHistory[this.uniqid].headers;
  2368. if (changeRequest) {
  2369. sourceData = JSON.stringify(testData);
  2370. headers['X-Auth-Signature'] = getSignature(headers, sourceData);
  2371. }
  2372.  
  2373. let signature = headers['X-Auth-Signature'];
  2374. if (signature) {
  2375. original.setRequestHeader.call(this, 'X-Auth-Signature', signature);
  2376. }
  2377. } catch (err) {
  2378. console.log("Request(send, " + this.uniqid + "):\n", sourceData, "Error:\n", err);
  2379. }
  2380. return sourceData;
  2381. }
  2382. /**
  2383. * Processing and substitution of incoming data
  2384. *
  2385. * Обработка и подмена входящих данных
  2386. */
  2387. async function checkChangeResponse(response) {
  2388. try {
  2389. isChange = false;
  2390. let nowTime = Math.round(Date.now() / 1000);
  2391. callsIdent = requestHistory[this.uniqid].calls;
  2392. respond = JSON.parse(response);
  2393. /**
  2394. * If the request returned an error removes the error (removes synchronization errors)
  2395. * Если запрос вернул ошибку удаляет ошибку (убирает ошибки синхронизации)
  2396. */
  2397. if (respond.error) {
  2398. isChange = true;
  2399. console.error(respond.error);
  2400. if (isChecked('showErrors')) {
  2401. popup.confirm(I18N('ERROR_MSG', {
  2402. name: respond.error.name,
  2403. description: respond.error.description,
  2404. }));
  2405. }
  2406. delete respond.error;
  2407. respond.results = [];
  2408. }
  2409. let mainReward = null;
  2410. const allReward = {};
  2411. let countTypeReward = 0;
  2412. let readQuestInfo = false;
  2413. for (const call of respond.results) {
  2414. /**
  2415. * Obtaining initial data for completing quests
  2416. * Получение исходных данных для выполнения квестов
  2417. */
  2418. if (readQuestInfo) {
  2419. questsInfo[call.ident] = call.result.response;
  2420. }
  2421. /**
  2422. * Getting a user ID
  2423. * Получение идетификатора пользователя
  2424. */
  2425. if (call.ident == callsIdent['registration']) {
  2426. userId = call.result.response.userId;
  2427. if (localStorage['userId'] != userId) {
  2428. localStorage['newGiftSendIds'] = '';
  2429. localStorage['userId'] = userId;
  2430. }
  2431. await openOrMigrateDatabase(userId);
  2432. readQuestInfo = true;
  2433. }
  2434. /**
  2435. * Hiding donation offers 1
  2436. * Скрываем предложения доната 1
  2437. */
  2438. if (call.ident == callsIdent['billingGetAll'] && getSaveVal('noOfferDonat')) {
  2439. const billings = call.result.response?.billings;
  2440. const bundle = call.result.response?.bundle;
  2441. if (billings && bundle) {
  2442. call.result.response.billings = [];
  2443. call.result.response.bundle = [];
  2444. isChange = true;
  2445. }
  2446. }
  2447. /**
  2448. * Hiding donation offers 2
  2449. * Скрываем предложения доната 2
  2450. */
  2451. if (getSaveVal('noOfferDonat') &&
  2452. (call.ident == callsIdent['offerGetAll'] ||
  2453. call.ident == callsIdent['specialOffer_getAll'])) {
  2454. let offers = call.result.response;
  2455. if (offers) {
  2456. call.result.response = offers.filter(e => !['addBilling', 'bundleCarousel'].includes(e.type) || ['idleResource'].includes(e.offerType));
  2457. isChange = true;
  2458. }
  2459. }
  2460. /**
  2461. * Hiding donation offers 3
  2462. * Скрываем предложения доната 3
  2463. */
  2464. if (getSaveVal('noOfferDonat') && call.result?.bundleUpdate) {
  2465. delete call.result.bundleUpdate;
  2466. isChange = true;
  2467. }
  2468. /**
  2469. * Copies a quiz question to the clipboard
  2470. * Копирует вопрос викторины в буфер обмена и получает на него ответ если есть
  2471. */
  2472. if (call.ident == callsIdent['quizGetNewQuestion']) {
  2473. let quest = call.result.response;
  2474. console.log(quest.question);
  2475. copyText(quest.question);
  2476. setProgress(I18N('QUESTION_COPY'), true);
  2477. quest.lang = null;
  2478. if (typeof NXFlashVars !== 'undefined') {
  2479. quest.lang = NXFlashVars.interface_lang;
  2480. }
  2481. lastQuestion = quest;
  2482. if (isChecked('getAnswer')) {
  2483. const answer = await getAnswer(lastQuestion);
  2484. let showText = '';
  2485. if (answer) {
  2486. lastAnswer = answer;
  2487. console.log(answer);
  2488. showText = `${I18N('ANSWER_KNOWN')}: ${answer}`;
  2489. } else {
  2490. showText = I18N('ANSWER_NOT_KNOWN');
  2491. }
  2492.  
  2493. try {
  2494. const hint = hintQuest(quest);
  2495. if (hint) {
  2496. showText += I18N('HINT') + hint;
  2497. }
  2498. } catch(e) {}
  2499.  
  2500. setProgress(showText, true);
  2501. }
  2502. }
  2503. /**
  2504. * Submits a question with an answer to the database
  2505. * Отправляет вопрос с ответом в базу данных
  2506. */
  2507. if (call.ident == callsIdent['quizAnswer']) {
  2508. const answer = call.result.response;
  2509. if (lastQuestion) {
  2510. const answerInfo = {
  2511. answer,
  2512. question: lastQuestion,
  2513. lang: null,
  2514. }
  2515. if (typeof NXFlashVars !== 'undefined') {
  2516. answerInfo.lang = NXFlashVars.interface_lang;
  2517. }
  2518. lastQuestion = null;
  2519. setTimeout(sendAnswerInfo, 0, answerInfo);
  2520. }
  2521. }
  2522. /**
  2523. * Get user data
  2524. * Получить даныне пользователя
  2525. */
  2526. if (call.ident == callsIdent['userGetInfo']) {
  2527. let user = call.result.response;
  2528. userInfo = Object.assign({}, user);
  2529. delete userInfo.refillable;
  2530. if (!questsInfo['userGetInfo']) {
  2531. questsInfo['userGetInfo'] = user;
  2532. }
  2533. }
  2534. /**
  2535. * Start of the battle for recalculation
  2536. * Начало боя для прерасчета
  2537. */
  2538. if (call.ident == callsIdent['clanWarAttack'] ||
  2539. call.ident == callsIdent['crossClanWar_startBattle'] ||
  2540. call.ident == callsIdent['bossAttack'] ||
  2541. call.ident == callsIdent['battleGetReplay'] ||
  2542. call.ident == callsIdent['brawl_startBattle'] ||
  2543. call.ident == callsIdent['adventureSolo_turnStartBattle'] ||
  2544. call.ident == callsIdent['invasion_bossStart'] ||
  2545. call.ident == callsIdent['towerStartBattle'] ||
  2546. call.ident == callsIdent['adventure_turnStartBattle']) {
  2547. let battle = call.result.response.battle || call.result.response.replay;
  2548. if (call.ident == callsIdent['brawl_startBattle'] ||
  2549. call.ident == callsIdent['bossAttack'] ||
  2550. call.ident == callsIdent['towerStartBattle'] ||
  2551. call.ident == callsIdent['invasion_bossStart']) {
  2552. battle = call.result.response;
  2553. }
  2554. lastBattleInfo = battle;
  2555. if (!isChecked('preCalcBattle')) {
  2556. continue;
  2557. }
  2558. setProgress(I18N('BEING_RECALC'));
  2559. let battleDuration = 120;
  2560. try {
  2561. const typeBattle = getBattleType(battle.type);
  2562. battleDuration = +lib.data.battleConfig[typeBattle.split('_')[1]].config.battleDuration;
  2563. } catch (e) { }
  2564. //console.log(battle.type);
  2565. function getBattleInfo(battle, isRandSeed) {
  2566. return new Promise(function (resolve) {
  2567. if (isRandSeed) {
  2568. battle.seed = Math.floor(Date.now() / 1000) + random(0, 1e3);
  2569. }
  2570. BattleCalc(battle, getBattleType(battle.type), e => resolve(e));
  2571. });
  2572. }
  2573. let actions = [getBattleInfo(battle, false)]
  2574. const countTestBattle = getInput('countTestBattle');
  2575. if (call.ident == callsIdent['battleGetReplay']) {
  2576. battle.progress = [{ attackers: { input: ["auto", 0, 0, "auto", 0, 0] } }];
  2577. }
  2578. for (let i = 0; i < countTestBattle; i++) {
  2579. actions.push(getBattleInfo(battle, true));
  2580. }
  2581. Promise.all(actions)
  2582. .then(e => {
  2583. e = e.map(n => ({win: n.result.win, time: n.battleTime}));
  2584. let firstBattle = e.shift();
  2585. const timer = Math.floor(battleDuration - firstBattle.time);
  2586. const min = ('00' + Math.floor(timer / 60)).slice(-2);
  2587. const sec = ('00' + Math.floor(timer - min * 60)).slice(-2);
  2588. const countWin = e.reduce((w, s) => w + s.win, 0);
  2589. setProgress(`${I18N('THIS_TIME')} ${(firstBattle.win ? I18N('VICTORY') : I18N('DEFEAT'))} ${I18N('CHANCE_TO_WIN')}: ${Math.floor(countWin / e.length * 100)}% (${e.length}), ${min}:${sec}`, false, hideProgress)
  2590. });
  2591. }
  2592. //тест сохранки
  2593. /** Запоминаем команды в реплее*/
  2594. if (call.ident == callsIdent['battleGetReplay']) {
  2595. let battle = call.result.response.replay;
  2596. repleyBattle.attackers = battle.attackers;
  2597. repleyBattle.defenders = battle.defenders[0];
  2598. repleyBattle.effects = battle.effects.defenders;
  2599. repleyBattle.state = battle.progress[0].defenders.heroes;
  2600. repleyBattle.seed = battle.seed;
  2601. }
  2602. /** Нападение в турнире*/
  2603. if (call.ident == callsIdent['titanArenaStartBattle']) {
  2604. let bestBattle = getInput('countBattle');
  2605. let unrandom = getInput('needResource');
  2606. let maxPower = getInput('needResource2');
  2607. if (bestBattle * unrandom * maxPower == 0) {
  2608. let battle = call.result.response.battle;
  2609. if (bestBattle == 0) {
  2610. battle.progress = bestLordBattle[battle.typeId]?.progress;
  2611. }
  2612. if (unrandom == 0 && !!repleyBattle.seed) {
  2613. battle.seed = repleyBattle.seed;
  2614. }
  2615. if (maxPower == 0) {
  2616. battle.attackers = getTitansPack(Object.keys(battle.attackers));
  2617. }
  2618. isChange = true;
  2619. }
  2620. }
  2621. /** Тест боев с усилениями команд защиты*/
  2622. if (call.ident == callsIdent['chatAcceptChallenge']) {
  2623. let battle = call.result.response.battle;
  2624. addBuff(battle);
  2625. let testType = getInput('countBattle');
  2626. if (testType.slice(0, 1) == "-") {
  2627. testType = parseInt(testType.slice(1), 10);
  2628. switch (testType) {
  2629. case 1:
  2630. battle.defenders[0] = repleyBattle.defenders;
  2631. break; //наша атака против защиты из реплея
  2632. case 2:
  2633. battle.defenders[0] = repleyBattle.attackers;
  2634. break; //наша атака против атаки из реплея
  2635. case 3:
  2636. battle.attackers = repleyBattle.attackers;
  2637. break; //атака из реплея против защиты в чате
  2638. case 4:
  2639. battle.attackers = repleyBattle.defenders;
  2640. break; //защита из реплея против защиты в чате
  2641. case 5:
  2642. battle.attackers = repleyBattle.attackers;
  2643. battle.defenders[0] = repleyBattle.defenders;
  2644. break; //атака из реплея против защиты из реплея
  2645. case 6:
  2646. battle.attackers = repleyBattle.defenders;
  2647. battle.defenders[0] = repleyBattle.attackers;
  2648. break; //защита из реплея против атаки из реплея
  2649. case 7:
  2650. battle.attackers = repleyBattle.attackers;
  2651. battle.defenders[0] = repleyBattle.attackers;
  2652. break; //атака из реплея против атаки из реплея
  2653. case 8:
  2654. battle.attackers = repleyBattle.defenders;
  2655. battle.defenders[0] = repleyBattle.defenders;
  2656. break; //защита из реплея против защиты из реплея
  2657. }
  2658. }
  2659.  
  2660. isChange = true;
  2661. }
  2662. /** Тест боев с усилениями команд защиты тренировках*/
  2663. if (call.ident == callsIdent['demoBattles_startBattle']) {
  2664. let battle = call.result.response.battle;
  2665. addBuff(battle);
  2666. let testType = getInput('countBattle');
  2667. if (testType.slice(0, 1) == "-") {
  2668. testType = parseInt(testType.slice(1), 10);
  2669. switch (testType) {
  2670. case 1:
  2671. battle.defenders[0] = repleyBattle.defenders;
  2672. break; //наша атака против защиты из реплея
  2673. case 2:
  2674. battle.defenders[0] = repleyBattle.attackers;
  2675. break; //наша атака против атаки из реплея
  2676. case 3:
  2677. battle.attackers = repleyBattle.attackers;
  2678. break; //атака из реплея против защиты в чате
  2679. case 4:
  2680. battle.attackers = repleyBattle.defenders;
  2681. break; //защита из реплея против защиты в чате
  2682. case 5:
  2683. battle.attackers = repleyBattle.attackers;
  2684. battle.defenders[0] = repleyBattle.defenders;
  2685. break; //атака из реплея против защиты из реплея
  2686. case 6:
  2687. battle.attackers = repleyBattle.defenders;
  2688. battle.defenders[0] = repleyBattle.attackers;
  2689. break; //защита из реплея против атаки из реплея
  2690. case 7:
  2691. battle.attackers = repleyBattle.attackers;
  2692. battle.defenders[0] = repleyBattle.attackers;
  2693. break; //атака из реплея против атаки из реплея
  2694. case 8:
  2695. battle.attackers = repleyBattle.defenders;
  2696. battle.defenders[0] = repleyBattle.defenders;
  2697. break; //защита из реплея против защиты из реплея
  2698. }
  2699. }
  2700.  
  2701. isChange = true;
  2702. }
  2703. //тест сохранки
  2704. /**
  2705. * Start of the Asgard boss fight
  2706. * Начало боя с боссом Асгарда
  2707. */
  2708. if (call.ident == callsIdent['clanRaid_startBossBattle']) {
  2709. lastBossBattleInfo = call.result.response.battle;
  2710. if (isChecked('preCalcBattle')) {
  2711. const result = await Calc(lastBossBattleInfo).then(e => e.progress[0].defenders.heroes[1].extra);
  2712. const bossDamage = result.damageTaken + result.damageTakenNextLevel;
  2713. setProgress(I18N('BOSS_DAMAGE') + bossDamage.toLocaleString(), false, hideProgress);
  2714. }
  2715. }
  2716. /**
  2717. * Cancel tutorial
  2718. * Отмена туториала
  2719. */
  2720. if (isCanceledTutorial && call.ident == callsIdent['tutorialGetInfo']) {
  2721. let chains = call.result.response.chains;
  2722. for (let n in chains) {
  2723. chains[n] = 9999;
  2724. }
  2725. isChange = true;
  2726. }
  2727. /**
  2728. * Opening keys and spheres of titan artifacts
  2729. * Открытие ключей и сфер артефактов титанов
  2730. */
  2731. if (artifactChestOpen &&
  2732. (call.ident == callsIdent[artifactChestOpenCallName] ||
  2733. (callsIdent[artifactChestOpenCallName] && callsIdent[artifactChestOpenCallName].includes(call.ident)))) {
  2734. let reward = call.result.response[artifactChestOpenCallName == 'artifactChestOpen' ? 'chestReward' : 'reward'];
  2735.  
  2736. reward.forEach(e => {
  2737. for (let f in e) {
  2738. if (!allReward[f]) {
  2739. allReward[f] = {};
  2740. }
  2741. for (let o in e[f]) {
  2742. if (!allReward[f][o]) {
  2743. allReward[f][o] = e[f][o];
  2744. countTypeReward++;
  2745. } else {
  2746. allReward[f][o] += e[f][o];
  2747. }
  2748. }
  2749. }
  2750. });
  2751.  
  2752. if (!call.ident.includes(artifactChestOpenCallName)) {
  2753. mainReward = call.result.response;
  2754. }
  2755. }
  2756.  
  2757. if (countTypeReward > 20) {
  2758. correctShowOpenArtifact = 3;
  2759. } else {
  2760. correctShowOpenArtifact = 0;
  2761. }
  2762.  
  2763. /**
  2764. * Sum the result of opening Pet Eggs
  2765. * Суммирование результата открытия яиц питомцев
  2766. */
  2767. if (isChecked('countControl') && call.ident == callsIdent['pet_chestOpen']) {
  2768. const rewards = call.result.response.rewards;
  2769. if (rewards.length > 10) {
  2770. /**
  2771. * Removing pet cards
  2772. * Убираем карточки петов
  2773. */
  2774. for (const reward of rewards) {
  2775. if (reward.petCard) {
  2776. delete reward.petCard;
  2777. }
  2778. }
  2779. }
  2780. rewards.forEach(e => {
  2781. for (let f in e) {
  2782. if (!allReward[f]) {
  2783. allReward[f] = {};
  2784. }
  2785. for (let o in e[f]) {
  2786. if (!allReward[f][o]) {
  2787. allReward[f][o] = e[f][o];
  2788. } else {
  2789. allReward[f][o] += e[f][o];
  2790. }
  2791. }
  2792. }
  2793. });
  2794. call.result.response.rewards = [allReward];
  2795. isChange = true;
  2796. }
  2797. /**
  2798. * Removing titan cards
  2799. * Убираем карточки титанов
  2800. */
  2801. if (call.ident == callsIdent['titanUseSummonCircle']) {
  2802. if (call.result.response.rewards.length > 10) {
  2803. for (const reward of call.result.response.rewards) {
  2804. if (reward.titanCard) {
  2805. delete reward.titanCard;
  2806. }
  2807. }
  2808. isChange = true;
  2809. }
  2810. }
  2811. /**
  2812. * Auto-repeat opening matryoshkas
  2813. * АвтоПовтор открытия матрешек
  2814. */
  2815. if (isChecked('countControl') && call.ident == callsIdent['consumableUseLootBox']) {
  2816. let lootBox = call.result.response;
  2817. let newCount = 0;
  2818. for (let n of lootBox) {
  2819. if (n?.consumable && n.consumable[lastRussianDollId]) {
  2820. newCount += n.consumable[lastRussianDollId]
  2821. }
  2822. }
  2823. if (newCount && await popup.confirm(`${I18N('BTN_OPEN')} ${newCount} ${I18N('OPEN_DOLLS')}?`, [
  2824. { msg: I18N('BTN_OPEN'), result: true},
  2825. { msg: I18N('BTN_NO'), result: false},
  2826. ])) {
  2827. const recursionResult = await openRussianDolls(lastRussianDollId, newCount);
  2828. lootBox = [...lootBox, ...recursionResult];
  2829. }
  2830.  
  2831. /** Объединение результата лутбоксов */
  2832. const allLootBox = {};
  2833. lootBox.forEach(e => {
  2834. for (let f in e) {
  2835. if (!allLootBox[f]) {
  2836. if (typeof e[f] == 'object') {
  2837. allLootBox[f] = {};
  2838. } else {
  2839. allLootBox[f] = 0;
  2840. }
  2841. }
  2842. if (typeof e[f] == 'object') {
  2843. for (let o in e[f]) {
  2844. if (newCount && o == lastRussianDollId) {
  2845. continue;
  2846. }
  2847. if (!allLootBox[f][o]) {
  2848. allLootBox[f][o] = e[f][o];
  2849. } else {
  2850. allLootBox[f][o] += e[f][o];
  2851. }
  2852. }
  2853. } else {
  2854. allLootBox[f] += e[f];
  2855. }
  2856. }
  2857. });
  2858. /** Разбитие результата */
  2859. const output = [];
  2860. const maxCount = 5;
  2861. let currentObj = {};
  2862. let count = 0;
  2863. for (let f in allLootBox) {
  2864. if (!currentObj[f]) {
  2865. if (typeof allLootBox[f] == 'object') {
  2866. for (let o in allLootBox[f]) {
  2867. currentObj[f] ||= {}
  2868. if (!currentObj[f][o]) {
  2869. currentObj[f][o] = allLootBox[f][o];
  2870. count++;
  2871. if (count === maxCount) {
  2872. output.push(currentObj);
  2873. currentObj = {};
  2874. count = 0;
  2875. }
  2876. }
  2877. }
  2878. } else {
  2879. currentObj[f] = allLootBox[f];
  2880. count++;
  2881. if (count === maxCount) {
  2882. output.push(currentObj);
  2883. currentObj = {};
  2884. count = 0;
  2885. }
  2886. }
  2887. }
  2888. }
  2889. if (count > 0) {
  2890. output.push(currentObj);
  2891. }
  2892.  
  2893. console.log(output);
  2894. call.result.response = output;
  2895. isChange = true;
  2896. }
  2897. /**
  2898. * Dungeon recalculation (fix endless cards)
  2899. * Прерасчет подземки (исправление бесконечных карт)
  2900. */
  2901. if (call.ident == callsIdent['dungeonStartBattle']) {
  2902. lastDungeonBattleData = call.result.response;
  2903. lastDungeonBattleStart = Date.now();
  2904. }
  2905. /**
  2906. * Getting the number of prediction cards
  2907. * Получение количества карт предсказаний
  2908. */
  2909. if (call.ident == callsIdent['inventoryGet']) {
  2910. countPredictionCard = call.result.response.consumable[81] || 0;
  2911. }
  2912. /**
  2913. * Getting subscription status
  2914. * Получение состояния подписки
  2915. */
  2916. if (call.ident == callsIdent['subscriptionGetInfo']) {
  2917. const subscription = call.result.response.subscription;
  2918. if (subscription) {
  2919. subEndTime = subscription.endTime * 1000;
  2920. }
  2921. }
  2922. /**
  2923. * Getting prediction cards
  2924. * Получение карт предсказаний
  2925. */
  2926. if (call.ident == callsIdent['questFarm']) {
  2927. const consumable = call.result.response?.consumable;
  2928. if (consumable && consumable[81]) {
  2929. countPredictionCard += consumable[81];
  2930. console.log(`Cards: ${countPredictionCard}`);
  2931. }
  2932. }
  2933. /**
  2934. * Hiding extra servers
  2935. * Скрытие лишних серверов
  2936. */
  2937. if (call.ident == callsIdent['serverGetAll'] && isChecked('hideServers')) {
  2938. let servers = call.result.response.users.map(s => s.serverId)
  2939. call.result.response.servers = call.result.response.servers.filter(s => servers.includes(s.id));
  2940. isChange = true;
  2941. }
  2942. /**
  2943. * Displays player positions in the adventure
  2944. * Отображает позиции игроков в приключении
  2945. */
  2946. if (call.ident == callsIdent['adventure_getLobbyInfo']) {
  2947. const users = Object.values(call.result.response.users);
  2948. const mapIdent = call.result.response.mapIdent;
  2949. const adventureId = call.result.response.adventureId;
  2950. const maps = {
  2951. adv_strongford_3pl_hell: 9,
  2952. adv_valley_3pl_hell: 10,
  2953. adv_ghirwil_3pl_hell: 11,
  2954. adv_angels_3pl_hell: 12,
  2955. }
  2956. let msg = I18N('MAP') + (mapIdent in maps ? maps[mapIdent] : adventureId);
  2957. msg += '<br>' + I18N('PLAYER_POS');
  2958. for (const user of users) {
  2959. msg += `<br>${user.user.name} - ${user.currentNode}`;
  2960. }
  2961. setProgress(msg, false, hideProgress);
  2962. }
  2963. /**
  2964. * Automatic launch of a raid at the end of the adventure
  2965. * Автоматический запуск рейда при окончании приключения
  2966. */
  2967. if (call.ident == callsIdent['adventure_end']) {
  2968. autoRaidAdventure()
  2969. }
  2970. /** Удаление лавки редкостей */
  2971. if (call.ident == callsIdent['missionRaid']) {
  2972. if (call.result?.heroesMerchant) {
  2973. delete call.result.heroesMerchant;
  2974. isChange = true;
  2975. }
  2976. }
  2977. /** missionTimer */
  2978. if (call.ident == callsIdent['missionStart']) {
  2979. missionBattle = call.result.response;
  2980. }
  2981. }
  2982.  
  2983. if (mainReward && artifactChestOpen) {
  2984. console.log(allReward);
  2985. mainReward[artifactChestOpenCallName == 'artifactChestOpen' ? 'chestReward' : 'reward'] = [allReward];
  2986. artifactChestOpen = false;
  2987. artifactChestOpenCallName = '';
  2988. isChange = true;
  2989. }
  2990. } catch(err) {
  2991. console.log("Request(response, " + this.uniqid + "):\n", "Error:\n", response, err);
  2992. }
  2993.  
  2994. if (isChange) {
  2995. Object.defineProperty(this, 'responseText', {
  2996. writable: true
  2997. });
  2998. this.responseText = JSON.stringify(respond);
  2999. }
  3000. }
  3001.  
  3002. /** Добавляет в бой эффекты усиления*/
  3003. function addBuff(battle) {
  3004. let effects = battle.effects;
  3005. let buffType = getInput('needResource2');
  3006. if (-1 < buffType && buffType < 7) {
  3007. let percentBuff = getInput('needResource');
  3008. effects.defenders = {};
  3009. effects.defenders[buffs[buffType]] = percentBuff;
  3010. } else if (buffType.slice(0, 1) == "-" || isChecked('treningBattle')) {
  3011. buffType = parseInt(buffType.slice(1), 10);
  3012. effects.defenders = repleyBattle.effects;
  3013. battle.defenders[0] = repleyBattle.defenders;
  3014. let def = battle.defenders[0];
  3015. if (buffType == 1) {
  3016. for (let i in def) {
  3017. let state = def[i].state;
  3018. state.hp = state.maxHp;
  3019. state.energy = 0;
  3020. state.isDead = false;
  3021. }
  3022. } else if (buffType == 2 || isChecked('finishingBattle')) {
  3023. for (let i in def) {
  3024. let state = def[i].state;
  3025. let rState = repleyBattle.state[i];
  3026. if (!!rState) {
  3027. state.hp = rState.hp;
  3028. state.energy = rState.energy;
  3029. state.isDead = rState.isDead;
  3030. } else {
  3031. state.hp = 0;
  3032. state.energy = 0;
  3033. state.isDead = true;
  3034. }
  3035. }
  3036. }
  3037. }
  3038. }
  3039. 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'];
  3040.  
  3041. /**
  3042. * Request an answer to a question
  3043. *
  3044. * Запрос ответа на вопрос
  3045. */
  3046. async function getAnswer(question) {
  3047. const now = Date.now();
  3048. const body = JSON.stringify({ ...question, now });
  3049. const signature = window['\x73\x69\x67\x6e'](now);
  3050. return new Promise(resolve => {
  3051. fetch('https://zingery.ru/heroes/getAnswer.php', {
  3052. method: 'POST',
  3053. headers: {
  3054. 'X-Request-Signature': signature,
  3055. 'X-Script-Name': GM_info.script.name,
  3056. 'X-Script-Version': GM_info.script.version,
  3057. 'X-Script-Author': GM_info.script.author,
  3058. },
  3059. body,
  3060. }).then(
  3061. response => response.json()
  3062. ).then(
  3063. data => {
  3064. if (data.result) {
  3065. resolve(data.result);
  3066. } else {
  3067. resolve(false);
  3068. }
  3069. }
  3070. ).catch((error) => {
  3071. console.error(error);
  3072. resolve(false);
  3073. });
  3074. })
  3075. }
  3076.  
  3077. /**
  3078. * Submitting a question and answer to a database
  3079. *
  3080. * Отправка вопроса и ответа в базу данных
  3081. */
  3082. function sendAnswerInfo(answerInfo) {
  3083. fetch('https://zingery.ru/heroes/setAnswer.php', {
  3084. method: 'POST',
  3085. body: JSON.stringify(answerInfo)
  3086. }).then(
  3087. response => response.json()
  3088. ).then(
  3089. data => {
  3090. if (data.result) {
  3091. console.log(I18N('SENT_QUESTION'));
  3092. }
  3093. }
  3094. )
  3095. }
  3096.  
  3097. /**
  3098. * Returns the battle type by preset type
  3099. *
  3100. * Возвращает тип боя по типу пресета
  3101. */
  3102. function getBattleType(strBattleType) {
  3103. if (strBattleType.includes("invasion")) {
  3104. return "get_invasion";
  3105. }
  3106. if (strBattleType.includes("boss")) {
  3107. return "get_boss";
  3108. }
  3109. switch (strBattleType) {
  3110. case "invasion":
  3111. return "get_invasion";
  3112. case "titan_pvp_manual":
  3113. return "get_titanPvpManual";
  3114. case "titan_pvp":
  3115. return "get_titanPvp";
  3116. case "titan_clan_pvp":
  3117. case "clan_pvp_titan":
  3118. case "clan_global_pvp_titan":
  3119. case "brawl_titan":
  3120. case "challenge_titan":
  3121. return "get_titanClanPvp";
  3122. case "clan_raid": // Asgard Boss // Босс асгарда
  3123. case "adventure": // Adventures // Приключения
  3124. case "clan_global_pvp":
  3125. case "clan_pvp":
  3126. return "get_clanPvp";
  3127. case "dungeon_titan":
  3128. case "titan_tower":
  3129. return "get_titan";
  3130. case "tower":
  3131. case "clan_dungeon":
  3132. return "get_tower";
  3133. case "pve":
  3134. return "get_pve";
  3135. case "pvp_manual":
  3136. return "get_pvpManual";
  3137. case "grand":
  3138. case "arena":
  3139. case "pvp":
  3140. case "challenge":
  3141. return "get_pvp";
  3142. case "core":
  3143. return "get_core";
  3144. case "boss_10":
  3145. case "boss_11":
  3146. case "boss_12":
  3147. return "get_boss";
  3148. default:
  3149. return "get_clanPvp";
  3150. }
  3151. }
  3152. /**
  3153. * Returns the class name of the passed object
  3154. *
  3155. * Возвращает название класса переданного объекта
  3156. */
  3157. function getClass(obj) {
  3158. return {}.toString.call(obj).slice(8, -1);
  3159. }
  3160. /**
  3161. * Calculates the request signature
  3162. *
  3163. * Расчитывает сигнатуру запроса
  3164. */
  3165. this.getSignature = function(headers, data) {
  3166. const sign = {
  3167. signature: '',
  3168. length: 0,
  3169. add: function (text) {
  3170. this.signature += text;
  3171. if (this.length < this.signature.length) {
  3172. this.length = 3 * (this.signature.length + 1) >> 1;
  3173. }
  3174. },
  3175. }
  3176. sign.add(headers["X-Request-Id"]);
  3177. sign.add(':');
  3178. sign.add(headers["X-Auth-Token"]);
  3179. sign.add(':');
  3180. sign.add(headers["X-Auth-Session-Id"]);
  3181. sign.add(':');
  3182. sign.add(data);
  3183. sign.add(':');
  3184. sign.add('LIBRARY-VERSION=1');
  3185. sign.add('UNIQUE-SESSION-ID=' + headers["X-Env-Unique-Session-Id"]);
  3186.  
  3187. return md5(sign.signature);
  3188. }
  3189. /**
  3190. * Creates an interface
  3191. *
  3192. * Создает интерфейс
  3193. */
  3194. function createInterface() {
  3195. scriptMenu.init({
  3196. showMenu: true
  3197. });
  3198. scriptMenu.addHeader(GM_info.script.name, justInfo);
  3199. scriptMenu.addHeader('v' + GM_info.script.version);
  3200. }
  3201.  
  3202. function addControls() {
  3203. createInterface();
  3204. const checkboxDetails = scriptMenu.addDetails(I18N('SETTINGS'));
  3205. for (let name in checkboxes) {
  3206. if (checkboxes[name].hide) {
  3207. continue;
  3208. }
  3209. checkboxes[name].cbox = scriptMenu.addCheckbox(checkboxes[name].label, checkboxes[name].title, checkboxDetails);
  3210. /**
  3211. * Getting the state of checkboxes from storage
  3212. * Получаем состояние чекбоксов из storage
  3213. */
  3214. let val = storage.get(name, null);
  3215. if (val != null) {
  3216. checkboxes[name].cbox.checked = val;
  3217. } else {
  3218. storage.set(name, checkboxes[name].default);
  3219. checkboxes[name].cbox.checked = checkboxes[name].default;
  3220. }
  3221. /**
  3222. * Tracing the change event of the checkbox for writing to storage
  3223. * Отсеживание события изменения чекбокса для записи в storage
  3224. */
  3225. checkboxes[name].cbox.dataset['name'] = name;
  3226. checkboxes[name].cbox.addEventListener('change', async function (event) {
  3227. const nameCheckbox = this.dataset['name'];
  3228. /*
  3229. if (this.checked && nameCheckbox == 'cancelBattle') {
  3230. this.checked = false;
  3231. if (await popup.confirm(I18N('MSG_BAN_ATTENTION'), [
  3232. { msg: I18N('BTN_NO_I_AM_AGAINST'), result: true },
  3233. { msg: I18N('BTN_YES_I_AGREE'), result: false },
  3234. ])) {
  3235. return;
  3236. }
  3237. this.checked = true;
  3238. }
  3239. */
  3240. storage.set(nameCheckbox, this.checked);
  3241. })
  3242. }
  3243.  
  3244. const inputDetails = scriptMenu.addDetails(I18N('VALUES'));
  3245. for (let name in inputs) {
  3246. inputs[name].input = scriptMenu.addInputText(inputs[name].title, false, inputDetails);
  3247. /**
  3248. * Get inputText state from storage
  3249. * Получаем состояние inputText из storage
  3250. */
  3251. let val = storage.get(name, null);
  3252. if (val != null) {
  3253. inputs[name].input.value = val;
  3254. } else {
  3255. storage.set(name, inputs[name].default);
  3256. inputs[name].input.value = inputs[name].default;
  3257. }
  3258. /**
  3259. * Tracing a field change event for a record in storage
  3260. * Отсеживание события изменения поля для записи в storage
  3261. */
  3262. inputs[name].input.dataset['name'] = name;
  3263. inputs[name].input.addEventListener('input', function () {
  3264. const inputName = this.dataset['name'];
  3265. let value = +this.value;
  3266. if (!value || Number.isNaN(value)) {
  3267. value = storage.get(inputName, inputs[inputName].default);
  3268. inputs[name].input.value = value;
  3269. }
  3270. storage.set(inputName, value);
  3271. })
  3272. }
  3273. const inputDetails2 = scriptMenu.addDetails(I18N('SAVING'));
  3274. for (let name in inputs2) {
  3275. inputs2[name].input = scriptMenu.addInputText(inputs2[name].title, false, inputDetails2);
  3276. /**
  3277. * Get inputText state from storage
  3278. * Получаем состояние inputText из storage
  3279. */
  3280. let val = storage.get(name, null);
  3281. if (val != null) {
  3282. inputs2[name].input.value = val;
  3283. } else {
  3284. storage.set(name, inputs2[name].default);
  3285. inputs2[name].input.value = inputs2[name].default;
  3286. }
  3287. /**
  3288. * Tracing a field change event for a record in storage
  3289. * Отсеживание события изменения поля для записи в storage
  3290. */
  3291. inputs2[name].input.dataset['name'] = name;
  3292. inputs2[name].input.addEventListener('input', function () {
  3293. const inputName = this.dataset['name'];
  3294. let value = +this.value;
  3295. if (!value || Number.isNaN(value)) {
  3296. value = storage.get(inputName, inputs2[inputName].default);
  3297. inputs2[name].input.value = value;
  3298. }
  3299. storage.set(inputName, value);
  3300. })
  3301. }
  3302. /* const inputDetails3 = scriptMenu.addDetails(I18N('USER_ID'));
  3303. for (let name in inputs3) {
  3304. inputs3[name].input = scriptMenu.addInputText(inputs3[name].title, false, inputDetails3);
  3305. /**
  3306. * Get inputText state from storage
  3307. * Получаем состояние inputText из storage
  3308. *
  3309. let val = storage.get(name, null);
  3310. if (val != null) {
  3311. inputs3[name].input.value = val;
  3312. } else {
  3313. storage.set(name, inputs3[name].default);
  3314. inputs3[name].input.value = inputs3[name].default;
  3315. }
  3316. /**
  3317. * Tracing a field change event for a record in storage
  3318. * Отсеживание события изменения поля для записи в storage
  3319. *
  3320. inputs3[name].input.dataset['name'] = name;
  3321. inputs3[name].input.addEventListener('input', function () {
  3322. const inputName = this.dataset['name'];
  3323. let value = +this.value;
  3324. if (!value || Number.isNaN(value)) {
  3325. value = storage.get(inputName, inputs3[inputName].default);
  3326. inputs3[name].input.value = value;
  3327. }
  3328. storage.set(inputName, value);
  3329. })
  3330. }*/
  3331. }
  3332.  
  3333. /**
  3334. * Sending a request
  3335. *
  3336. * Отправка запроса
  3337. */
  3338. function send(json, callback, pr) {
  3339. if (typeof json == 'string') {
  3340. json = JSON.parse(json);
  3341. }
  3342. for (const call of json.calls) {
  3343. if (!call?.context?.actionTs) {
  3344. call.context = {
  3345. actionTs: Math.floor(performance.now())
  3346. }
  3347. }
  3348. }
  3349. json = JSON.stringify(json);
  3350. /**
  3351. * We get the headlines of the previous intercepted request
  3352. * Получаем заголовки предыдущего перехваченого запроса
  3353. */
  3354. let headers = lastHeaders;
  3355. /**
  3356. * We increase the header of the query Certifier by 1
  3357. * Увеличиваем заголовок идетификатора запроса на 1
  3358. */
  3359. headers["X-Request-Id"]++;
  3360. /**
  3361. * We calculate the title with the signature
  3362. * Расчитываем заголовок с сигнатурой
  3363. */
  3364. headers["X-Auth-Signature"] = getSignature(headers, json);
  3365. /**
  3366. * Create a new ajax request
  3367. * Создаем новый AJAX запрос
  3368. */
  3369. let xhr = new XMLHttpRequest;
  3370. /**
  3371. * Indicate the previously saved URL for API queries
  3372. * Указываем ранее сохраненный URL для API запросов
  3373. */
  3374. xhr.open('POST', apiUrl, true);
  3375. /**
  3376. * Add the function to the event change event
  3377. * Добавляем функцию к событию смены статуса запроса
  3378. */
  3379. xhr.onreadystatechange = function() {
  3380. /**
  3381. * If the result of the request is obtained, we call the flask function
  3382. * Если результат запроса получен вызываем колбек функцию
  3383. */
  3384. if(xhr.readyState == 4) {
  3385. callback(xhr.response, pr);
  3386. }
  3387. };
  3388. /**
  3389. * Indicate the type of request
  3390. * Указываем тип запроса
  3391. */
  3392. xhr.responseType = 'json';
  3393. /**
  3394. * We set the request headers
  3395. * Задаем заголовки запроса
  3396. */
  3397. for(let nameHeader in headers) {
  3398. let head = headers[nameHeader];
  3399. xhr.setRequestHeader(nameHeader, head);
  3400. }
  3401. /**
  3402. * Sending a request
  3403. * Отправляем запрос
  3404. */
  3405. xhr.send(json);
  3406. }
  3407.  
  3408. let hideTimeoutProgress = 0;
  3409. /**
  3410. * Hide progress
  3411. *
  3412. * Скрыть прогресс
  3413. */
  3414. function hideProgress(timeout) {
  3415. timeout = timeout || 0;
  3416. clearTimeout(hideTimeoutProgress);
  3417. hideTimeoutProgress = setTimeout(function () {
  3418. scriptMenu.setStatus('');
  3419. }, timeout);
  3420. }
  3421. /**
  3422. * Progress display
  3423. *
  3424. * Отображение прогресса
  3425. */
  3426. function setProgress(text, hide, onclick) {
  3427. scriptMenu.setStatus(text, onclick);
  3428. hide = hide || false;
  3429. if (hide) {
  3430. hideProgress(3000);
  3431. }
  3432. }
  3433.  
  3434. /**
  3435. * Returns the timer value depending on the subscription
  3436. *
  3437. * Возвращает значение таймера в зависимости от подписки
  3438. */
  3439. function getTimer(time, div) {
  3440. let speedDiv = 5;
  3441. if (subEndTime < Date.now()) {
  3442. speedDiv = div || 1.5;
  3443. }
  3444. return Math.max(Math.ceil(time / speedDiv + 1.5), 4);
  3445. }
  3446.  
  3447. /**
  3448. * Calculates HASH MD5 from string
  3449. *
  3450. * Расчитывает HASH MD5 из строки
  3451. *
  3452. * [js-md5]{@link https://github.com/emn178/js-md5}
  3453. *
  3454. * @namespace md5
  3455. * @version 0.7.3
  3456. * @author Chen, Yi-Cyuan [emn178@gmail.com]
  3457. * @copyright Chen, Yi-Cyuan 2014-2017
  3458. * @license MIT
  3459. */
  3460. !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 _}))}();
  3461.  
  3462. /**
  3463. * Script for beautiful dialog boxes
  3464. *
  3465. * Скрипт для красивых диалоговых окошек
  3466. */
  3467. const popup = new (function () {
  3468. this.popUp,
  3469. this.downer,
  3470. this.middle,
  3471. this.msgText,
  3472. this.buttons = [];
  3473. this.checkboxes = [];
  3474. this.dialogPromice = null;
  3475.  
  3476. function init() {
  3477. addStyle();
  3478. addBlocks();
  3479. addEventListeners();
  3480. }
  3481.  
  3482. const addEventListeners = () => {
  3483. document.addEventListener('keyup', (e) => {
  3484. if (e.key == 'Escape') {
  3485. if (this.dialogPromice) {
  3486. const { func, result } = this.dialogPromice;
  3487. this.dialogPromice = null;
  3488. popup.hide();
  3489. func(result);
  3490. }
  3491. }
  3492. });
  3493. }
  3494.  
  3495. const addStyle = () => {
  3496. let style = document.createElement('style');
  3497. style.innerText = `
  3498. .PopUp_ {
  3499. position: absolute;
  3500. min-width: 300px;
  3501. max-width: 500px;
  3502. max-height: 600px;
  3503. background-color: #190e08e6;
  3504. z-index: 10001;
  3505. top: 169px;
  3506. left: 345px;
  3507. border: 3px #ce9767 solid;
  3508. border-radius: 10px;
  3509. display: flex;
  3510. flex-direction: column;
  3511. justify-content: space-around;
  3512. padding: 15px 9px;
  3513. box-sizing: border-box;
  3514. }
  3515.  
  3516. .PopUp_back {
  3517. position: absolute;
  3518. background-color: #00000066;
  3519. width: 100%;
  3520. height: 100%;
  3521. z-index: 10000;
  3522. top: 0;
  3523. left: 0;
  3524. }
  3525.  
  3526. .PopUp_close {
  3527. width: 40px;
  3528. height: 40px;
  3529. position: absolute;
  3530. right: -18px;
  3531. top: -18px;
  3532. border: 3px solid #c18550;
  3533. border-radius: 20px;
  3534. background: radial-gradient(circle, rgba(190,30,35,1) 0%, rgba(0,0,0,1) 100%);
  3535. background-position-y: 3px;
  3536. box-shadow: -1px 1px 3px black;
  3537. cursor: pointer;
  3538. box-sizing: border-box;
  3539. }
  3540.  
  3541. .PopUp_close:hover {
  3542. filter: brightness(1.2);
  3543. }
  3544.  
  3545. .PopUp_crossClose {
  3546. width: 100%;
  3547. height: 100%;
  3548. background-size: 65%;
  3549. background-position: center;
  3550. background-repeat: no-repeat;
  3551. 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")
  3552. }
  3553.  
  3554. .PopUp_blocks {
  3555. width: 100%;
  3556. height: 50%;
  3557. display: flex;
  3558. justify-content: space-evenly;
  3559. align-items: center;
  3560. flex-wrap: wrap;
  3561. justify-content: center;
  3562. }
  3563.  
  3564. .PopUp_blocks:last-child {
  3565. margin-top: 25px;
  3566. }
  3567.  
  3568. .PopUp_buttons {
  3569. display: flex;
  3570. margin: 7px 10px;
  3571. flex-direction: column;
  3572. }
  3573.  
  3574. .PopUp_button {
  3575. background-color: #52A81C;
  3576. border-radius: 5px;
  3577. box-shadow: inset 0px -4px 10px, inset 0px 3px 2px #99fe20, 0px 0px 4px, 0px -3px 1px #d7b275, 0px 0px 0px 3px #ce9767;
  3578. cursor: pointer;
  3579. padding: 4px 12px 6px;
  3580. }
  3581.  
  3582. .PopUp_input {
  3583. text-align: center;
  3584. font-size: 16px;
  3585. height: 27px;
  3586. border: 1px solid #cf9250;
  3587. border-radius: 9px 9px 0px 0px;
  3588. background: transparent;
  3589. color: #fce1ac;
  3590. padding: 1px 10px;
  3591. box-sizing: border-box;
  3592. box-shadow: 0px 0px 4px, 0px 0px 0px 3px #ce9767;
  3593. }
  3594.  
  3595. .PopUp_checkboxes {
  3596. display: flex;
  3597. flex-direction: column;
  3598. margin: 15px 15px -5px 15px;
  3599. align-items: flex-start;
  3600. }
  3601.  
  3602. .PopUp_ContCheckbox {
  3603. margin: 2px 0px;
  3604. }
  3605.  
  3606. .PopUp_checkbox {
  3607. position: absolute;
  3608. z-index: -1;
  3609. opacity: 0;
  3610. }
  3611. .PopUp_checkbox+label {
  3612. display: inline-flex;
  3613. align-items: center;
  3614. user-select: none;
  3615.  
  3616. font-size: 15px;
  3617. font-family: sans-serif;
  3618. font-weight: 600;
  3619. font-stretch: condensed;
  3620. letter-spacing: 1px;
  3621. color: #fce1ac;
  3622. text-shadow: 0px 0px 1px;
  3623. }
  3624. .PopUp_checkbox+label::before {
  3625. content: '';
  3626. display: inline-block;
  3627. width: 20px;
  3628. height: 20px;
  3629. border: 1px solid #cf9250;
  3630. border-radius: 7px;
  3631. margin-right: 7px;
  3632. }
  3633. .PopUp_checkbox:checked+label::before {
  3634. 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");
  3635. }
  3636.  
  3637. .PopUp_input::placeholder {
  3638. color: #fce1ac75;
  3639. }
  3640.  
  3641. .PopUp_input:focus {
  3642. outline: 0;
  3643. }
  3644.  
  3645. .PopUp_input + .PopUp_button {
  3646. border-radius: 0px 0px 5px 5px;
  3647. padding: 2px 18px 5px;
  3648. }
  3649.  
  3650. .PopUp_button:hover {
  3651. filter: brightness(1.2);
  3652. }
  3653.  
  3654. .PopUp_button:active {
  3655. box-shadow: inset 0px 5px 10px, inset 0px 1px 2px #99fe20, 0px 0px 4px, 0px -3px 1px #d7b275, 0px 0px 0px 3px #ce9767;
  3656. }
  3657.  
  3658. .PopUp_text {
  3659. font-size: 22px;
  3660. font-family: sans-serif;
  3661. font-weight: 600;
  3662. font-stretch: condensed;
  3663. white-space: pre-wrap;
  3664. letter-spacing: 1px;
  3665. text-align: center;
  3666. }
  3667.  
  3668. .PopUp_buttonText {
  3669. color: #E4FF4C;
  3670. text-shadow: 0px 1px 2px black;
  3671. }
  3672.  
  3673. .PopUp_msgText {
  3674. color: #FDE5B6;
  3675. text-shadow: 0px 0px 2px;
  3676. }
  3677.  
  3678. .PopUp_hideBlock {
  3679. display: none;
  3680. }
  3681. `;
  3682. document.head.appendChild(style);
  3683. }
  3684.  
  3685. const addBlocks = () => {
  3686. this.back = document.createElement('div');
  3687. this.back.classList.add('PopUp_back');
  3688. this.back.classList.add('PopUp_hideBlock');
  3689. document.body.append(this.back);
  3690.  
  3691. this.popUp = document.createElement('div');
  3692. this.popUp.classList.add('PopUp_');
  3693. this.back.append(this.popUp);
  3694.  
  3695. let upper = document.createElement('div')
  3696. upper.classList.add('PopUp_blocks');
  3697. this.popUp.append(upper);
  3698.  
  3699. this.middle = document.createElement('div')
  3700. this.middle.classList.add('PopUp_blocks');
  3701. this.middle.classList.add('PopUp_checkboxes');
  3702. this.popUp.append(this.middle);
  3703.  
  3704. this.downer = document.createElement('div')
  3705. this.downer.classList.add('PopUp_blocks');
  3706. this.popUp.append(this.downer);
  3707.  
  3708. this.msgText = document.createElement('div');
  3709. this.msgText.classList.add('PopUp_text', 'PopUp_msgText');
  3710. upper.append(this.msgText);
  3711. }
  3712.  
  3713. this.showBack = function () {
  3714. this.back.classList.remove('PopUp_hideBlock');
  3715. }
  3716.  
  3717. this.hideBack = function () {
  3718. this.back.classList.add('PopUp_hideBlock');
  3719. }
  3720.  
  3721. this.show = function () {
  3722. if (this.checkboxes.length) {
  3723. this.middle.classList.remove('PopUp_hideBlock');
  3724. }
  3725. this.showBack();
  3726. this.popUp.classList.remove('PopUp_hideBlock');
  3727. this.popUp.style.left = (window.innerWidth - this.popUp.offsetWidth) / 2 + 'px';
  3728. this.popUp.style.top = (window.innerHeight - this.popUp.offsetHeight) / 3 + 'px';
  3729. }
  3730.  
  3731. this.hide = function () {
  3732. this.hideBack();
  3733. this.popUp.classList.add('PopUp_hideBlock');
  3734. }
  3735.  
  3736. this.addAnyButton = (option) => {
  3737. const contButton = document.createElement('div');
  3738. contButton.classList.add('PopUp_buttons');
  3739. this.downer.append(contButton);
  3740.  
  3741. let inputField = {
  3742. value: option.result || option.default
  3743. }
  3744. if (option.isInput) {
  3745. inputField = document.createElement('input');
  3746. inputField.type = 'text';
  3747. if (option.placeholder) {
  3748. inputField.placeholder = option.placeholder;
  3749. }
  3750. if (option.default) {
  3751. inputField.value = option.default;
  3752. }
  3753. inputField.classList.add('PopUp_input');
  3754. contButton.append(inputField);
  3755. }
  3756.  
  3757. const button = document.createElement('div');
  3758. button.classList.add('PopUp_button');
  3759. button.title = option.title || '';
  3760. contButton.append(button);
  3761.  
  3762. const buttonText = document.createElement('div');
  3763. buttonText.classList.add('PopUp_text', 'PopUp_buttonText');
  3764. buttonText.innerText = option.msg;
  3765. button.append(buttonText);
  3766.  
  3767. return { button, contButton, inputField };
  3768. }
  3769.  
  3770. this.addCloseButton = () => {
  3771. let button = document.createElement('div')
  3772. button.classList.add('PopUp_close');
  3773. this.popUp.append(button);
  3774.  
  3775. let crossClose = document.createElement('div')
  3776. crossClose.classList.add('PopUp_crossClose');
  3777. button.append(crossClose);
  3778.  
  3779. return { button, contButton: button };
  3780. }
  3781.  
  3782. this.addButton = (option, buttonClick) => {
  3783.  
  3784. const { button, contButton, inputField } = option.isClose ? this.addCloseButton() : this.addAnyButton(option);
  3785. if (option.isClose) {
  3786. this.dialogPromice = {func: buttonClick, result: option.result};
  3787. }
  3788. button.addEventListener('click', () => {
  3789. let result = '';
  3790. if (option.isInput) {
  3791. result = inputField.value;
  3792. }
  3793. if (option.isClose || option.isCancel) {
  3794. this.dialogPromice = null;
  3795. }
  3796. buttonClick(result);
  3797. });
  3798.  
  3799. this.buttons.push(contButton);
  3800. }
  3801.  
  3802. this.clearButtons = () => {
  3803. while (this.buttons.length) {
  3804. this.buttons.pop().remove();
  3805. }
  3806. }
  3807.  
  3808. this.addCheckBox = (checkBox) => {
  3809. const contCheckbox = document.createElement('div');
  3810. contCheckbox.classList.add('PopUp_ContCheckbox');
  3811. this.middle.append(contCheckbox);
  3812.  
  3813. const checkbox = document.createElement('input');
  3814. checkbox.type = 'checkbox';
  3815. checkbox.id = 'PopUpCheckbox' + this.checkboxes.length;
  3816. checkbox.dataset.name = checkBox.name;
  3817. checkbox.checked = checkBox.checked;
  3818. checkbox.label = checkBox.label;
  3819. checkbox.title = checkBox.title || '';
  3820. checkbox.classList.add('PopUp_checkbox');
  3821. contCheckbox.appendChild(checkbox)
  3822.  
  3823. const checkboxLabel = document.createElement('label');
  3824. checkboxLabel.innerText = checkBox.label;
  3825. checkboxLabel.title = checkBox.title || '';
  3826. checkboxLabel.setAttribute('for', checkbox.id);
  3827. contCheckbox.appendChild(checkboxLabel);
  3828.  
  3829. this.checkboxes.push(checkbox);
  3830. }
  3831.  
  3832. this.clearCheckBox = () => {
  3833. this.middle.classList.add('PopUp_hideBlock');
  3834. while (this.checkboxes.length) {
  3835. this.checkboxes.pop().parentNode.remove();
  3836. }
  3837. }
  3838.  
  3839. this.setMsgText = (text) => {
  3840. this.msgText.innerHTML = text;
  3841. }
  3842.  
  3843. this.getCheckBoxes = () => {
  3844. const checkBoxes = [];
  3845.  
  3846. for (const checkBox of this.checkboxes) {
  3847. checkBoxes.push({
  3848. name: checkBox.dataset.name,
  3849. label: checkBox.label,
  3850. checked: checkBox.checked
  3851. });
  3852. }
  3853.  
  3854. return checkBoxes;
  3855. }
  3856.  
  3857. this.confirm = async (msg, buttOpt, checkBoxes = []) => {
  3858. this.clearButtons();
  3859. this.clearCheckBox();
  3860. return new Promise((complete, failed) => {
  3861. this.setMsgText(msg);
  3862. if (!buttOpt) {
  3863. buttOpt = [{ msg: 'Ok', result: true, isInput: false }];
  3864. }
  3865. for (const checkBox of checkBoxes) {
  3866. this.addCheckBox(checkBox);
  3867. }
  3868. for (let butt of buttOpt) {
  3869. this.addButton(butt, (result) => {
  3870. result = result || butt.result;
  3871. complete(result);
  3872. popup.hide();
  3873. });
  3874. if (butt.isCancel) {
  3875. this.dialogPromice = {func: complete, result: butt.result};
  3876. }
  3877. }
  3878. this.show();
  3879. });
  3880. }
  3881.  
  3882. document.addEventListener('DOMContentLoaded', init);
  3883. });
  3884.  
  3885. /**
  3886. * Script control panel
  3887. *
  3888. * Панель управления скриптом
  3889. */
  3890. const scriptMenu = new (function () {
  3891.  
  3892. this.mainMenu,
  3893. this.buttons = [],
  3894. this.checkboxes = [];
  3895. this.option = {
  3896. showMenu: false,
  3897. showDetails: {}
  3898. };
  3899.  
  3900. this.init = function (option = {}) {
  3901. this.option = Object.assign(this.option, option);
  3902. this.option.showDetails = this.loadShowDetails();
  3903. addStyle();
  3904. addBlocks();
  3905. }
  3906.  
  3907. const addStyle = () => {
  3908. style = document.createElement('style');
  3909. style.innerText = `
  3910. .scriptMenu_status {
  3911. position: absolute;
  3912. z-index: 10001;
  3913. white-space: pre-wrap; //тест для выравнивания кнопок
  3914. /* max-height: 30px; */
  3915. top: -1px;
  3916. left: 30%;
  3917. cursor: pointer;
  3918. border-radius: 0px 0px 10px 10px;
  3919. background: #190e08e6;
  3920. border: 1px #ce9767 solid;
  3921. font-size: 18px;
  3922. font-family: sans-serif;
  3923. font-weight: 600;
  3924. font-stretch: condensed;
  3925. letter-spacing: 1px;
  3926. color: #fce1ac;
  3927. text-shadow: 0px 0px 1px;
  3928. transition: 0.5s;
  3929. padding: 2px 10px 3px;
  3930. }
  3931. .scriptMenu_statusHide {
  3932. top: -35px;
  3933. height: 30px;
  3934. overflow: hidden;
  3935. }
  3936. .scriptMenu_label {
  3937. position: absolute;
  3938. top: 30%;
  3939. left: -4px;
  3940. z-index: 9999;
  3941. cursor: pointer;
  3942. width: 30px;
  3943. height: 30px;
  3944. background: radial-gradient(circle, #47a41b 0%, #1a2f04 100%);
  3945. border: 1px solid #1a2f04;
  3946. border-radius: 5px;
  3947. box-shadow:
  3948. inset 0px 2px 4px #83ce26,
  3949. inset 0px -4px 6px #1a2f04,
  3950. 0px 0px 2px black,
  3951. 0px 0px 0px 2px #ce9767;
  3952. }
  3953. .scriptMenu_label:hover {
  3954. filter: brightness(1.2);
  3955. }
  3956. .scriptMenu_arrowLabel {
  3957. width: 100%;
  3958. height: 100%;
  3959. background-size: 75%;
  3960. background-position: center;
  3961. background-repeat: no-repeat;
  3962. 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");
  3963. box-shadow: 0px 1px 2px #000;
  3964. border-radius: 5px;
  3965. filter: drop-shadow(0px 1px 2px #000D);
  3966. }
  3967. .scriptMenu_main {
  3968. position: absolute;
  3969. max-width: 285px;
  3970. z-index: 9999;
  3971. top: 50%;
  3972. transform: translateY(-40%);
  3973. background: #190e08e6;
  3974. border: 1px #ce9767 solid;
  3975. border-radius: 0px 10px 10px 0px;
  3976. border-left: none;
  3977. padding: 5px 10px 5px 5px;
  3978. box-sizing: border-box;
  3979. font-size: 15px;
  3980. font-family: sans-serif;
  3981. font-weight: 600;
  3982. font-stretch: condensed;
  3983. letter-spacing: 1px;
  3984. color: #fce1ac;
  3985. text-shadow: 0px 0px 1px;
  3986. transition: 1s;
  3987. display: flex;
  3988. flex-direction: column;
  3989. flex-wrap: nowrap;
  3990. }
  3991. .scriptMenu_showMenu {
  3992. display: none;
  3993. }
  3994. .scriptMenu_showMenu:checked~.scriptMenu_main {
  3995. left: 0px;
  3996. }
  3997. .scriptMenu_showMenu:not(:checked)~.scriptMenu_main {
  3998. left: -300px;
  3999. }
  4000. .scriptMenu_divInput {
  4001. margin: 2px;
  4002. }
  4003. .scriptMenu_divInputText {
  4004. margin: 2px;
  4005. align-self: center;
  4006. display: flex;
  4007. }
  4008. .scriptMenu_checkbox {
  4009. position: absolute;
  4010. z-index: -1;
  4011. opacity: 0;
  4012. }
  4013. .scriptMenu_checkbox+label {
  4014. display: inline-flex;
  4015. align-items: center;
  4016. user-select: none;
  4017. }
  4018. .scriptMenu_checkbox+label::before {
  4019. content: '';
  4020. display: inline-block;
  4021. width: 20px;
  4022. height: 20px;
  4023. border: 1px solid #cf9250;
  4024. border-radius: 7px;
  4025. margin-right: 7px;
  4026. }
  4027. .scriptMenu_checkbox:checked+label::before {
  4028. 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");
  4029. }
  4030. .scriptMenu_close {
  4031. width: 40px;
  4032. height: 40px;
  4033. position: absolute;
  4034. right: -18px;
  4035. top: -18px;
  4036. border: 3px solid #c18550;
  4037. border-radius: 20px;
  4038. background: radial-gradient(circle, rgba(190,30,35,1) 0%, rgba(0,0,0,1) 100%);
  4039. background-position-y: 3px;
  4040. box-shadow: -1px 1px 3px black;
  4041. cursor: pointer;
  4042. box-sizing: border-box;
  4043. }
  4044. .scriptMenu_close:hover {
  4045. filter: brightness(1.2);
  4046. }
  4047. .scriptMenu_crossClose {
  4048. width: 100%;
  4049. height: 100%;
  4050. background-size: 65%;
  4051. background-position: center;
  4052. background-repeat: no-repeat;
  4053. 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")
  4054. }
  4055. .scriptMenu_button {
  4056. user-select: none;
  4057. border-radius: 5px;
  4058. cursor: pointer;
  4059. padding: 5px 14px 8px;
  4060. margin: 4px;
  4061. background: radial-gradient(circle, rgba(165,120,56,1) 80%, rgba(0,0,0,1) 110%);
  4062. box-shadow: inset 0px -4px 6px #442901, inset 0px 1px 6px #442901, inset 0px 0px 6px, 0px 0px 4px, 0px 0px 0px 2px #ce9767;
  4063. }
  4064. .scriptMenu_button:hover {
  4065. filter: brightness(1.2);
  4066. }
  4067. .scriptMenu_button:active {
  4068. box-shadow: inset 0px 4px 6px #442901, inset 0px 4px 6px #442901, inset 0px 0px 6px, 0px 0px 4px, 0px 0px 0px 2px #ce9767;
  4069. }
  4070. .scriptMenu_buttonText {
  4071. color: #fce5b7;
  4072. text-shadow: 0px 1px 2px black;
  4073. text-align: center;
  4074. }
  4075. .scriptMenu_header {
  4076. text-align: center;
  4077. align-self: center;
  4078. font-size: 15px;
  4079. margin: 0px 15px;
  4080. }
  4081. .scriptMenu_header a {
  4082. color: #fce5b7;
  4083. text-decoration: none;
  4084. }
  4085. .scriptMenu_InputText {
  4086. text-align: center;
  4087. width: 130px;
  4088. height: 24px;
  4089. border: 1px solid #cf9250;
  4090. border-radius: 9px;
  4091. background: transparent;
  4092. color: #fce1ac;
  4093. padding: 0px 10px;
  4094. box-sizing: border-box;
  4095. }
  4096. .scriptMenu_InputText:focus {
  4097. filter: brightness(1.2);
  4098. outline: 0;
  4099. }
  4100. .scriptMenu_InputText::placeholder {
  4101. color: #fce1ac75;
  4102. }
  4103. .scriptMenu_Summary {
  4104. cursor: pointer;
  4105. margin-left: 7px;
  4106. }
  4107. .scriptMenu_Details {
  4108. align-self: center;
  4109. }
  4110. `;
  4111. document.head.appendChild(style);
  4112. }
  4113.  
  4114. const addBlocks = () => {
  4115. const main = document.createElement('div');
  4116. document.body.appendChild(main);
  4117.  
  4118. this.status = document.createElement('div');
  4119. this.status.classList.add('scriptMenu_status');
  4120. this.setStatus('');
  4121. main.appendChild(this.status);
  4122.  
  4123. const label = document.createElement('label');
  4124. label.classList.add('scriptMenu_label');
  4125. label.setAttribute('for', 'checkbox_showMenu');
  4126. main.appendChild(label);
  4127.  
  4128. const arrowLabel = document.createElement('div');
  4129. arrowLabel.classList.add('scriptMenu_arrowLabel');
  4130. label.appendChild(arrowLabel);
  4131.  
  4132. const checkbox = document.createElement('input');
  4133. checkbox.type = 'checkbox';
  4134. checkbox.id = 'checkbox_showMenu';
  4135. checkbox.checked = this.option.showMenu;
  4136. checkbox.classList.add('scriptMenu_showMenu');
  4137. main.appendChild(checkbox);
  4138.  
  4139. this.mainMenu = document.createElement('div');
  4140. this.mainMenu.classList.add('scriptMenu_main');
  4141. main.appendChild(this.mainMenu);
  4142.  
  4143. const closeButton = document.createElement('label');
  4144. closeButton.classList.add('scriptMenu_close');
  4145. closeButton.setAttribute('for', 'checkbox_showMenu');
  4146. this.mainMenu.appendChild(closeButton);
  4147.  
  4148. const crossClose = document.createElement('div');
  4149. crossClose.classList.add('scriptMenu_crossClose');
  4150. closeButton.appendChild(crossClose);
  4151. }
  4152.  
  4153. this.setStatus = (text, onclick) => {
  4154. if (!text) {
  4155. this.status.classList.add('scriptMenu_statusHide');
  4156. } else {
  4157. this.status.classList.remove('scriptMenu_statusHide');
  4158. this.status.innerHTML = text;
  4159. }
  4160.  
  4161. if (typeof onclick == 'function') {
  4162. this.status.addEventListener("click", onclick, {
  4163. once: true
  4164. });
  4165. }
  4166. }
  4167.  
  4168. /**
  4169. * Adding a text element
  4170. *
  4171. * Добавление текстового элемента
  4172. * @param {String} text text // текст
  4173. * @param {Function} func Click function // функция по клику
  4174. * @param {HTMLDivElement} main parent // родитель
  4175. */
  4176. this.addHeader = (text, func, main) => {
  4177. main = main || this.mainMenu;
  4178. const header = document.createElement('div');
  4179. header.classList.add('scriptMenu_header');
  4180. header.innerHTML = text;
  4181. if (typeof func == 'function') {
  4182. header.addEventListener('click', func);
  4183. }
  4184. main.appendChild(header);
  4185. }
  4186.  
  4187. /**
  4188. * Adding a button
  4189. *
  4190. * Добавление кнопки
  4191. * @param {String} text
  4192. * @param {Function} func
  4193. * @param {String} title
  4194. * @param {HTMLDivElement} main parent // родитель
  4195. */
  4196. this.addButton = (text, func, title, main) => {
  4197. main = main || this.mainMenu;
  4198. const button = document.createElement('div');
  4199. button.classList.add('scriptMenu_button');
  4200. button.title = title;
  4201. button.addEventListener('click', func);
  4202. main.appendChild(button);
  4203.  
  4204. const buttonText = document.createElement('div');
  4205. buttonText.classList.add('scriptMenu_buttonText');
  4206. buttonText.innerText = text;
  4207. button.appendChild(buttonText);
  4208. this.buttons.push(button);
  4209.  
  4210. return button;
  4211. }
  4212.  
  4213. /**
  4214. * Adding checkbox
  4215. *
  4216. * Добавление чекбокса
  4217. * @param {String} label
  4218. * @param {String} title
  4219. * @param {HTMLDivElement} main parent // родитель
  4220. * @returns
  4221. */
  4222. this.addCheckbox = (label, title, main) => {
  4223. main = main || this.mainMenu;
  4224. const divCheckbox = document.createElement('div');
  4225. divCheckbox.classList.add('scriptMenu_divInput');
  4226. divCheckbox.title = title;
  4227. main.appendChild(divCheckbox);
  4228.  
  4229. const checkbox = document.createElement('input');
  4230. checkbox.type = 'checkbox';
  4231. checkbox.id = 'scriptMenuCheckbox' + this.checkboxes.length;
  4232. checkbox.classList.add('scriptMenu_checkbox');
  4233. divCheckbox.appendChild(checkbox)
  4234.  
  4235. const checkboxLabel = document.createElement('label');
  4236. checkboxLabel.innerText = label;
  4237. checkboxLabel.setAttribute('for', checkbox.id);
  4238. divCheckbox.appendChild(checkboxLabel);
  4239.  
  4240. this.checkboxes.push(checkbox);
  4241. return checkbox;
  4242. }
  4243.  
  4244. /**
  4245. * Adding input field
  4246. *
  4247. * Добавление поля ввода
  4248. * @param {String} title
  4249. * @param {String} placeholder
  4250. * @param {HTMLDivElement} main parent // родитель
  4251. * @returns
  4252. */
  4253. this.addInputText = (title, placeholder, main) => {
  4254. main = main || this.mainMenu;
  4255. const divInputText = document.createElement('div');
  4256. divInputText.classList.add('scriptMenu_divInputText');
  4257. divInputText.title = title;
  4258. main.appendChild(divInputText);
  4259.  
  4260. const newInputText = document.createElement('input');
  4261. newInputText.type = 'text';
  4262. if (placeholder) {
  4263. newInputText.placeholder = placeholder;
  4264. }
  4265. newInputText.classList.add('scriptMenu_InputText');
  4266. divInputText.appendChild(newInputText)
  4267. return newInputText;
  4268. }
  4269.  
  4270. /**
  4271. * Adds a dropdown block
  4272. *
  4273. * Добавляет раскрывающийся блок
  4274. * @param {String} summary
  4275. * @param {String} name
  4276. * @returns
  4277. */
  4278. this.addDetails = (summaryText, name = null) => {
  4279. const details = document.createElement('details');
  4280. details.classList.add('scriptMenu_Details');
  4281. this.mainMenu.appendChild(details);
  4282.  
  4283. const summary = document.createElement('summary');
  4284. summary.classList.add('scriptMenu_Summary');
  4285. summary.innerText = summaryText;
  4286. if (name) {
  4287. const self = this;
  4288. details.open = this.option.showDetails[name];
  4289. details.dataset.name = name;
  4290. summary.addEventListener('click', () => {
  4291. self.option.showDetails[details.dataset.name] = !details.open;
  4292. self.saveShowDetails(self.option.showDetails);
  4293. });
  4294. }
  4295. details.appendChild(summary);
  4296.  
  4297. return details;
  4298. }
  4299.  
  4300. /**
  4301. * Saving the expanded state of the details blocks
  4302. *
  4303. * Сохранение состояния развенутости блоков details
  4304. * @param {*} value
  4305. */
  4306. this.saveShowDetails = (value) => {
  4307. localStorage.setItem('scriptMenu_showDetails', JSON.stringify(value));
  4308. }
  4309.  
  4310. /**
  4311. * Loading the state of expanded blocks details
  4312. *
  4313. * Загрузка состояния развенутости блоков details
  4314. * @returns
  4315. */
  4316. this.loadShowDetails = () => {
  4317. let showDetails = localStorage.getItem('scriptMenu_showDetails');
  4318.  
  4319. if (!showDetails) {
  4320. return {};
  4321. }
  4322.  
  4323. try {
  4324. showDetails = JSON.parse(showDetails);
  4325. } catch (e) {
  4326. return {};
  4327. }
  4328.  
  4329. return showDetails;
  4330. }
  4331. });
  4332.  
  4333. /**
  4334. * Пример использования
  4335. scriptMenu.init();
  4336. scriptMenu.addHeader('v1.508');
  4337. scriptMenu.addCheckbox('testHack', 'Тестовый взлом игры!');
  4338. scriptMenu.addButton('Запуск!', () => console.log('click'), 'подсказака');
  4339. scriptMenu.addInputText('input подсказака');
  4340. */
  4341. /**
  4342. * Game Library
  4343. *
  4344. * Игровая библиотека
  4345. */
  4346. class Library {
  4347. defaultLibUrl = 'https://heroesru-a.akamaihd.net/vk/v1101/lib/lib.json';
  4348.  
  4349. constructor() {
  4350. if (!Library.instance) {
  4351. Library.instance = this;
  4352. }
  4353.  
  4354. return Library.instance;
  4355. }
  4356.  
  4357. async load() {
  4358. try {
  4359. await this.getUrlLib();
  4360. console.log(this.defaultLibUrl);
  4361. this.data = await fetch(this.defaultLibUrl).then(e => e.json())
  4362. } catch (error) {
  4363. console.error('Не удалось загрузить библиотеку', error)
  4364. }
  4365. }
  4366.  
  4367. async getUrlLib() {
  4368. try {
  4369. const db = new Database('hw_cache', 'cache');
  4370. await db.open();
  4371. const cacheLibFullUrl = await db.get('lib/lib.json.gz', false);
  4372. this.defaultLibUrl = cacheLibFullUrl.fullUrl.split('.gz').shift();
  4373. } catch(e) {}
  4374. }
  4375.  
  4376. getData(id) {
  4377. return this.data[id];
  4378. }
  4379. }
  4380.  
  4381. this.lib = new Library();
  4382. /**
  4383. * Database
  4384. *
  4385. * База данных
  4386. */
  4387. class Database {
  4388. constructor(dbName, storeName) {
  4389. this.dbName = dbName;
  4390. this.storeName = storeName;
  4391. this.db = null;
  4392. }
  4393.  
  4394. async open() {
  4395. return new Promise((resolve, reject) => {
  4396. const request = indexedDB.open(this.dbName);
  4397.  
  4398. request.onerror = () => {
  4399. reject(new Error(`Failed to open database ${this.dbName}`));
  4400. };
  4401.  
  4402. request.onsuccess = () => {
  4403. this.db = request.result;
  4404. resolve();
  4405. };
  4406.  
  4407. request.onupgradeneeded = (event) => {
  4408. const db = event.target.result;
  4409. if (!db.objectStoreNames.contains(this.storeName)) {
  4410. db.createObjectStore(this.storeName);
  4411. }
  4412. };
  4413. });
  4414. }
  4415.  
  4416. async set(key, value) {
  4417. return new Promise((resolve, reject) => {
  4418. const transaction = this.db.transaction([this.storeName], 'readwrite');
  4419. const store = transaction.objectStore(this.storeName);
  4420. const request = store.put(value, key);
  4421.  
  4422. request.onerror = () => {
  4423. reject(new Error(`Failed to save value with key ${key}`));
  4424. };
  4425.  
  4426. request.onsuccess = () => {
  4427. resolve();
  4428. };
  4429. });
  4430. }
  4431.  
  4432. async get(key, def) {
  4433. return new Promise((resolve, reject) => {
  4434. const transaction = this.db.transaction([this.storeName], 'readonly');
  4435. const store = transaction.objectStore(this.storeName);
  4436. const request = store.get(key);
  4437.  
  4438. request.onerror = () => {
  4439. resolve(def);
  4440. };
  4441.  
  4442. request.onsuccess = () => {
  4443. resolve(request.result);
  4444. };
  4445. });
  4446. }
  4447.  
  4448. async delete(key) {
  4449. return new Promise((resolve, reject) => {
  4450. const transaction = this.db.transaction([this.storeName], 'readwrite');
  4451. const store = transaction.objectStore(this.storeName);
  4452. const request = store.delete(key);
  4453.  
  4454. request.onerror = () => {
  4455. reject(new Error(`Failed to delete value with key ${key}`));
  4456. };
  4457.  
  4458. request.onsuccess = () => {
  4459. resolve();
  4460. };
  4461. });
  4462. }
  4463. }
  4464.  
  4465. /**
  4466. * Returns the stored value
  4467. *
  4468. * Возвращает сохраненное значение
  4469. */
  4470. function getSaveVal(saveName, def) {
  4471. const result = storage.get(saveName, def);
  4472. return result;
  4473. }
  4474.  
  4475. /**
  4476. * Stores value
  4477. *
  4478. * Сохраняет значение
  4479. */
  4480. function setSaveVal(saveName, value) {
  4481. storage.set(saveName, value);
  4482. }
  4483.  
  4484. /**
  4485. * Database initialization
  4486. *
  4487. * Инициализация базы данных
  4488. */
  4489. const db = new Database(GM_info.script.name, 'settings');
  4490.  
  4491. /**
  4492. * Data store
  4493. *
  4494. * Хранилище данных
  4495. */
  4496. const storage = {
  4497. userId: 0,
  4498. /**
  4499. * Default values
  4500. *
  4501. * Значения по умолчанию
  4502. */
  4503. values: [
  4504. ...Object.entries(checkboxes).map(e => ({ [e[0]]: e[1].default })),
  4505. ...Object.entries(inputs).map(e => ({ [e[0]]: e[1].default })),
  4506. ...Object.entries(inputs2).map(e => ({ [e[0]]: e[1].default })),
  4507. //...Object.entries(inputs3).map(e => ({ [e[0]]: e[1].default })),
  4508. ].reduce((acc, obj) => ({ ...acc, ...obj }), {}),
  4509. name: GM_info.script.name,
  4510. get: function (key, def) {
  4511. if (key in this.values) {
  4512. return this.values[key];
  4513. }
  4514. return def;
  4515. },
  4516. set: function (key, value) {
  4517. this.values[key] = value;
  4518. db.set(this.userId, this.values).catch(
  4519. e => null
  4520. );
  4521. localStorage[this.name + ':' + key] = value;
  4522. },
  4523. delete: function (key) {
  4524. delete this.values[key];
  4525. db.set(this.userId, this.values);
  4526. delete localStorage[this.name + ':' + key];
  4527. }
  4528. }
  4529.  
  4530. /**
  4531. * Returns all keys from localStorage that start with prefix (for migration)
  4532. *
  4533. * Возвращает все ключи из localStorage которые начинаются с prefix (для миграции)
  4534. */
  4535. function getAllValuesStartingWith(prefix) {
  4536. const values = [];
  4537. for (let i = 0; i < localStorage.length; i++) {
  4538. const key = localStorage.key(i);
  4539. if (key.startsWith(prefix)) {
  4540. const val = localStorage.getItem(key);
  4541. const keyValue = key.split(':')[1];
  4542. values.push({ key: keyValue, val });
  4543. }
  4544. }
  4545. return values;
  4546. }
  4547.  
  4548. /**
  4549. * Opens or migrates to a database
  4550. *
  4551. * Открывает или мигрирует в базу данных
  4552. */
  4553. async function openOrMigrateDatabase(userId) {
  4554. storage.userId = userId;
  4555. try {
  4556. await db.open();
  4557. } catch(e) {
  4558. return;
  4559. }
  4560. let settings = await db.get(userId, false);
  4561.  
  4562. if (settings) {
  4563. storage.values = settings;
  4564. return;
  4565. }
  4566.  
  4567. const values = getAllValuesStartingWith(GM_info.script.name);
  4568. for (const value of values) {
  4569. let val = null;
  4570. try {
  4571. val = JSON.parse(value.val);
  4572. } catch {
  4573. break;
  4574. }
  4575. storage.values[value.key] = val;
  4576. }
  4577. await db.set(userId, storage.values);
  4578. }
  4579.  
  4580. /**
  4581. * Sending expeditions
  4582. *
  4583. * Отправка экспедиций
  4584. */
  4585. function checkExpedition() {
  4586. return new Promise((resolve, reject) => {
  4587. const expedition = new Expedition(resolve, reject);
  4588. expedition.start();
  4589. });
  4590. }
  4591.  
  4592. class Expedition {
  4593. checkExpedInfo = {
  4594. calls: [
  4595. {
  4596. name: 'expeditionGet',
  4597. args: {},
  4598. ident: 'expeditionGet',
  4599. },
  4600. {
  4601. name: 'heroGetAll',
  4602. args: {},
  4603. ident: 'heroGetAll',
  4604. },
  4605. ],
  4606. };
  4607.  
  4608. constructor(resolve, reject) {
  4609. this.resolve = resolve;
  4610. this.reject = reject;
  4611. }
  4612.  
  4613. async start() {
  4614. const data = await Send(JSON.stringify(this.checkExpedInfo));
  4615.  
  4616. const expedInfo = data.results[0].result.response;
  4617. const dataHeroes = data.results[1].result.response;
  4618. const dataExped = { useHeroes: [], exped: [] };
  4619. const calls = [];
  4620.  
  4621. /**
  4622. * Adding expeditions to collect
  4623. * Добавляем экспедиции для сбора
  4624. */
  4625. let countGet = 0;
  4626. for (var n in expedInfo) {
  4627. const exped = expedInfo[n];
  4628. const dateNow = Date.now() / 1000;
  4629. if (exped.status == 2 && exped.endTime != 0 && dateNow > exped.endTime) {
  4630. countGet++;
  4631. calls.push({
  4632. name: 'expeditionFarm',
  4633. args: { expeditionId: exped.id },
  4634. ident: 'expeditionFarm_' + exped.id,
  4635. });
  4636. } else {
  4637. dataExped.useHeroes = dataExped.useHeroes.concat(exped.heroes);
  4638. }
  4639. if (exped.status == 1) {
  4640. dataExped.exped.push({ id: exped.id, power: exped.power });
  4641. }
  4642. }
  4643. dataExped.exped = dataExped.exped.sort((a, b) => b.power - a.power);
  4644.  
  4645. /**
  4646. * Putting together a list of heroes
  4647. * Собираем список героев
  4648. */
  4649. const heroesArr = [];
  4650. for (let n in dataHeroes) {
  4651. const hero = dataHeroes[n];
  4652. if (hero.xp > 0 && !dataExped.useHeroes.includes(hero.id)) {
  4653. let heroPower = hero.power;
  4654. // Лара Крофт * 3
  4655. if (hero.id == 63 && hero.color >= 16) {
  4656. heroPower *= 3;
  4657. }
  4658. heroesArr.push({ id: hero.id, power: heroPower });
  4659. }
  4660. }
  4661.  
  4662. /**
  4663. * Adding expeditions to send
  4664. * Добавляем экспедиции для отправки
  4665. */
  4666. let countSend = 0;
  4667. heroesArr.sort((a, b) => a.power - b.power);
  4668. for (const exped of dataExped.exped) {
  4669. let heroesIds = this.selectionHeroes(heroesArr, exped.power);
  4670. if (heroesIds && heroesIds.length > 4) {
  4671. for (let q in heroesArr) {
  4672. if (heroesIds.includes(heroesArr[q].id)) {
  4673. delete heroesArr[q];
  4674. }
  4675. }
  4676. countSend++;
  4677. calls.push({
  4678. name: 'expeditionSendHeroes',
  4679. args: {
  4680. expeditionId: exped.id,
  4681. heroes: heroesIds,
  4682. },
  4683. ident: 'expeditionSendHeroes_' + exped.id,
  4684. });
  4685. }
  4686. }
  4687.  
  4688. if (calls.length) {
  4689. await Send({ calls });
  4690. this.end(I18N('EXPEDITIONS_SENT', {countGet, countSend}));
  4691. return;
  4692. }
  4693. this.end(I18N('EXPEDITIONS_NOTHING'));
  4694. }
  4695.  
  4696. /**
  4697. * Selection of heroes for expeditions
  4698. *
  4699. * Подбор героев для экспедиций
  4700. */
  4701. selectionHeroes(heroes, power) {
  4702. const resultHeroers = [];
  4703. const heroesIds = [];
  4704. for (let q = 0; q < 5; q++) {
  4705. for (let i in heroes) {
  4706. let hero = heroes[i];
  4707. if (heroesIds.includes(hero.id)) {
  4708. continue;
  4709. }
  4710.  
  4711. const summ = resultHeroers.reduce((acc, hero) => acc + hero.power, 0);
  4712. const need = Math.round((power - summ) / (5 - resultHeroers.length));
  4713. if (hero.power > need) {
  4714. resultHeroers.push(hero);
  4715. heroesIds.push(hero.id);
  4716. break;
  4717. }
  4718. }
  4719. }
  4720.  
  4721. const summ = resultHeroers.reduce((acc, hero) => acc + hero.power, 0);
  4722. if (summ < power) {
  4723. return false;
  4724. }
  4725. return heroesIds;
  4726. }
  4727.  
  4728. /**
  4729. * Ends expedition script
  4730. *
  4731. * Завершает скрипт экспедиции
  4732. */
  4733. end(msg) {
  4734. setProgress(msg, true);
  4735. this.resolve();
  4736. }
  4737. }
  4738.  
  4739. /**
  4740. * Walkthrough of the dungeon
  4741. *
  4742. * Прохождение подземелья
  4743. */
  4744. function testDungeon() {
  4745. return new Promise((resolve, reject) => {
  4746. const dung = new executeDungeon(resolve, reject);
  4747. const titanit = getInput('countTitanit');
  4748. dung.start(titanit);
  4749. });
  4750. }
  4751.  
  4752. /**
  4753. * Walkthrough of the dungeon
  4754. *
  4755. * Прохождение подземелья
  4756. */
  4757. function executeDungeon(resolve, reject) {
  4758. dungeonActivity = 0;
  4759. maxDungeonActivity = 150;
  4760.  
  4761. titanGetAll = [];
  4762.  
  4763. teams = {
  4764. heroes: [],
  4765. earth: [],
  4766. fire: [],
  4767. neutral: [],
  4768. water: [],
  4769. }
  4770.  
  4771. titanStats = [];
  4772.  
  4773. titansStates = {};
  4774.  
  4775. callsExecuteDungeon = {
  4776. calls: [{
  4777. name: "dungeonGetInfo",
  4778. args: {},
  4779. ident: "dungeonGetInfo"
  4780. }, {
  4781. name: "teamGetAll",
  4782. args: {},
  4783. ident: "teamGetAll"
  4784. }, {
  4785. name: "teamGetFavor",
  4786. args: {},
  4787. ident: "teamGetFavor"
  4788. }, {
  4789. name: "clanGetInfo",
  4790. args: {},
  4791. ident: "clanGetInfo"
  4792. }, {
  4793. name: "titanGetAll",
  4794. args: {},
  4795. ident: "titanGetAll"
  4796. }, {
  4797. name: "inventoryGet",
  4798. args: {},
  4799. ident: "inventoryGet"
  4800. }]
  4801. }
  4802.  
  4803. this.start = function(titanit) {
  4804. maxDungeonActivity = titanit || getInput('countTitanit');
  4805. send(JSON.stringify(callsExecuteDungeon), startDungeon);
  4806. }
  4807.  
  4808. /**
  4809. * Getting data on the dungeon
  4810. *
  4811. * Получаем данные по подземелью
  4812. */
  4813. function startDungeon(e) {
  4814. stopDung = false; // стоп подземка
  4815. res = e.results;
  4816. dungeonGetInfo = res[0].result.response;
  4817. if (!dungeonGetInfo) {
  4818. endDungeon('noDungeon', res);
  4819. return;
  4820. }
  4821. teamGetAll = res[1].result.response;
  4822. teamGetFavor = res[2].result.response;
  4823. dungeonActivity = res[3].result.response.stat.todayDungeonActivity;
  4824. titanGetAll = Object.values(res[4].result.response);
  4825. countPredictionCard = res[5].result.response.consumable[81];
  4826.  
  4827. teams.hero = {
  4828. favor: teamGetFavor.dungeon_hero,
  4829. heroes: teamGetAll.dungeon_hero.filter(id => id < 6000),
  4830. teamNum: 0,
  4831. }
  4832. heroPet = teamGetAll.dungeon_hero.filter(id => id >= 6000).pop();
  4833. if (heroPet) {
  4834. teams.hero.pet = heroPet;
  4835. }
  4836.  
  4837. teams.neutral = {
  4838. favor: {},
  4839. heroes: getTitanTeam(titanGetAll, 'neutral'),
  4840. teamNum: 0,
  4841. };
  4842. teams.water = {
  4843. favor: {},
  4844. heroes: getTitanTeam(titanGetAll, 'water'),
  4845. teamNum: 0,
  4846. };
  4847. teams.fire = {
  4848. favor: {},
  4849. heroes: getTitanTeam(titanGetAll, 'fire'),
  4850. teamNum: 0,
  4851. };
  4852. teams.earth = {
  4853. favor: {},
  4854. heroes: getTitanTeam(titanGetAll, 'earth'),
  4855. teamNum: 0,
  4856. };
  4857.  
  4858.  
  4859. checkFloor(dungeonGetInfo);
  4860. }
  4861.  
  4862. function getTitanTeam(titans, type) {
  4863. switch (type) {
  4864. case 'neutral':
  4865. return titans.sort((a, b) => b.power - a.power).slice(0, 5).map(e => e.id);
  4866. case 'water':
  4867. return titans.filter(e => e.id.toString().slice(2, 3) == '0').map(e => e.id);
  4868. case 'fire':
  4869. return titans.filter(e => e.id.toString().slice(2, 3) == '1').map(e => e.id);
  4870. case 'earth':
  4871. return titans.filter(e => e.id.toString().slice(2, 3) == '2').map(e => e.id);
  4872. }
  4873. }
  4874.  
  4875. function getNeutralTeam() {
  4876. const titans = titanGetAll.filter(e => !titansStates[e.id]?.isDead)
  4877. return titans.sort((a, b) => b.power - a.power).slice(0, 5).map(e => e.id);
  4878. }
  4879.  
  4880. function fixTitanTeam(titans) {
  4881. titans.heroes = titans.heroes.filter(e => !titansStates[e]?.isDead);
  4882. return titans;
  4883. }
  4884.  
  4885. /**
  4886. * Checking the floor
  4887. *
  4888. * Проверяем этаж
  4889. */
  4890. async function checkFloor(dungeonInfo) {
  4891. if (!('floor' in dungeonInfo) || dungeonInfo.floor?.state == 2) {
  4892. saveProgress();
  4893. return;
  4894. }
  4895. // console.log(dungeonInfo, dungeonActivity);
  4896. setProgress(`${I18N('DUNGEON')}: ${I18N('TITANIT')} ${dungeonActivity}/${maxDungeonActivity}`);
  4897. if (dungeonActivity >= maxDungeonActivity) {
  4898. endDungeon('endDungeon', 'maxActive ' + dungeonActivity + '/' + maxDungeonActivity);
  4899. return;
  4900. }
  4901. titansStates = dungeonInfo.states.titans;
  4902. titanStats = titanObjToArray(titansStates);
  4903. if (stopDung){
  4904. endDungeon('Стоп подземка,', 'набрано титанита: ' + dungeonActivity + '/' + maxDungeonActivity);
  4905. return;
  4906. }
  4907. const floorChoices = dungeonInfo.floor.userData;
  4908. const floorType = dungeonInfo.floorType;
  4909. //const primeElement = dungeonInfo.elements.prime;
  4910. if (floorType == "battle") {
  4911. const calls = [];
  4912. for (let teamNum in floorChoices) {
  4913. attackerType = floorChoices[teamNum].attackerType;
  4914. const args = fixTitanTeam(teams[attackerType]);
  4915. if (attackerType == 'neutral') {
  4916. args.heroes = getNeutralTeam();
  4917. }
  4918. if (!args.heroes.length) {
  4919. continue;
  4920. }
  4921. args.teamNum = teamNum;
  4922. calls.push({
  4923. name: "dungeonStartBattle",
  4924. args,
  4925. ident: "body_" + teamNum
  4926. })
  4927. }
  4928. if (!calls.length) {
  4929. endDungeon('endDungeon', 'All Dead');
  4930. return;
  4931. }
  4932. const battleDatas = await Send(JSON.stringify({ calls }))
  4933. .then(e => e.results.map(n => n.result.response))
  4934. const battleResults = [];
  4935. for (n in battleDatas) {
  4936. battleData = battleDatas[n]
  4937. battleData.progress = [{ attackers: { input: ["auto", 0, 0, "auto", 0, 0] } }];
  4938. battleResults.push(await Calc(battleData).then(result => {
  4939. result.teamNum = n;
  4940. result.attackerType = floorChoices[n].attackerType;
  4941. return result;
  4942. }));
  4943. }
  4944. processingPromises(battleResults)
  4945. }
  4946. }
  4947.  
  4948. function processingPromises(results) {
  4949. let selectBattle = results[0];
  4950. if (results.length < 2) {
  4951. // console.log(selectBattle);
  4952. if (!selectBattle.result.win) {
  4953. endDungeon('dungeonEndBattle\n', selectBattle);
  4954. return;
  4955. }
  4956. endBattle(selectBattle);
  4957. return;
  4958. }
  4959.  
  4960. selectBattle = false;
  4961. let bestState = -1000;
  4962. for (const result of results) {
  4963. const recovery = getState(result);
  4964. if (recovery > bestState) {
  4965. bestState = recovery;
  4966. selectBattle = result
  4967. }
  4968. }
  4969. // console.log(selectBattle.teamNum, results);
  4970. if (!selectBattle || bestState <= -1000) {
  4971. endDungeon('dungeonEndBattle\n', results);
  4972. return;
  4973. }
  4974.  
  4975. startBattle(selectBattle.teamNum, selectBattle.attackerType)
  4976. .then(endBattle);
  4977. }
  4978.  
  4979. /**
  4980. * Let's start the fight
  4981. *
  4982. * Начинаем бой
  4983. */
  4984. function startBattle(teamNum, attackerType) {
  4985. return new Promise(function (resolve, reject) {
  4986. args = fixTitanTeam(teams[attackerType]);
  4987. args.teamNum = teamNum;
  4988. if (attackerType == 'neutral') {
  4989. const titans = titanGetAll.filter(e => !titansStates[e.id]?.isDead)
  4990. args.heroes = titans.sort((a, b) => b.power - a.power).slice(0, 5).map(e => e.id);
  4991. }
  4992. startBattleCall = {
  4993. calls: [{
  4994. name: "dungeonStartBattle",
  4995. args,
  4996. ident: "body"
  4997. }]
  4998. }
  4999. send(JSON.stringify(startBattleCall), resultBattle, {
  5000. resolve,
  5001. teamNum,
  5002. attackerType
  5003. });
  5004. });
  5005. }
  5006. /**
  5007. * Returns the result of the battle in a promise
  5008. *
  5009. * Возращает резульат боя в промис
  5010. */
  5011. function resultBattle(resultBattles, args) {
  5012. battleData = resultBattles.results[0].result.response;
  5013. battleType = "get_tower";
  5014. if (battleData.type == "dungeon_titan") {
  5015. battleType = "get_titan";
  5016. }
  5017. battleData.progress = [{ attackers: { input: ["auto", 0, 0, "auto", 0, 0] } }];
  5018. BattleCalc(battleData, battleType, function (result) {
  5019. result.teamNum = args.teamNum;
  5020. result.attackerType = args.attackerType;
  5021. args.resolve(result);
  5022. });
  5023. }
  5024. /**
  5025. * Finishing the fight
  5026. *
  5027. * Заканчиваем бой
  5028. */
  5029. async function endBattle(battleInfo) {
  5030. if (battleInfo.result.win) {
  5031. const args = {
  5032. result: battleInfo.result,
  5033. progress: battleInfo.progress,
  5034. }
  5035. if (countPredictionCard > 0) {
  5036. args.isRaid = true;
  5037. } else {
  5038. const timer = getTimer(battleInfo.battleTime);
  5039. console.log(timer);
  5040. await countdownTimer(timer, `${I18N('DUNGEON')}: ${I18N('TITANIT')} ${dungeonActivity}/${maxDungeonActivity}`);
  5041. }
  5042. const calls = [{
  5043. name: "dungeonEndBattle",
  5044. args,
  5045. ident: "body"
  5046. }];
  5047. lastDungeonBattleData = null;
  5048. send(JSON.stringify({ calls }), resultEndBattle);
  5049. } else {
  5050. endDungeon('dungeonEndBattle win: false\n', battleInfo);
  5051. }
  5052. }
  5053.  
  5054. /**
  5055. * Getting and processing battle results
  5056. *
  5057. * Получаем и обрабатываем результаты боя
  5058. */
  5059. function resultEndBattle(e) {
  5060. if ('error' in e) {
  5061. popup.confirm(I18N('ERROR_MSG', {
  5062. name: e.error.name,
  5063. description: e.error.description,
  5064. }));
  5065. endDungeon('errorRequest', e);
  5066. return;
  5067. }
  5068. battleResult = e.results[0].result.response;
  5069. if ('error' in battleResult) {
  5070. endDungeon('errorBattleResult', battleResult);
  5071. return;
  5072. }
  5073. dungeonGetInfo = battleResult.dungeon ?? battleResult;
  5074. dungeonActivity += battleResult.reward.dungeonActivity ?? 0;
  5075. checkFloor(dungeonGetInfo);
  5076. }
  5077.  
  5078. /**
  5079. * Returns the coefficient of condition of the
  5080. * difference in titanium before and after the battle
  5081. *
  5082. * Возвращает коэффициент состояния титанов после боя
  5083. */
  5084. function getState(result) {
  5085. if (!result.result.win) {
  5086. return -1000;
  5087. }
  5088.  
  5089. let beforeSumFactor = 0;
  5090. const beforeTitans = result.battleData.attackers;
  5091. for (let titanId in beforeTitans) {
  5092. const titan = beforeTitans[titanId];
  5093. const state = titan.state;
  5094. let factor = 1;
  5095. if (state) {
  5096. const hp = state.hp / titan.hp;
  5097. const energy = state.energy / 1e3;
  5098. factor = hp + energy / 20
  5099. }
  5100. beforeSumFactor += factor;
  5101. }
  5102.  
  5103. let afterSumFactor = 0;
  5104. const afterTitans = result.progress[0].attackers.heroes;
  5105. for (let titanId in afterTitans) {
  5106. const titan = afterTitans[titanId];
  5107. const hp = titan.hp / beforeTitans[titanId].hp;
  5108. const energy = titan.energy / 1e3;
  5109. const factor = hp + energy / 20;
  5110. afterSumFactor += factor;
  5111. }
  5112. return afterSumFactor - beforeSumFactor;
  5113. }
  5114.  
  5115. /**
  5116. * Converts an object with IDs to an array with IDs
  5117. *
  5118. * Преобразует объект с идетификаторами в массив с идетификаторами
  5119. */
  5120. function titanObjToArray(obj) {
  5121. let titans = [];
  5122. for (let id in obj) {
  5123. obj[id].id = id;
  5124. titans.push(obj[id]);
  5125. }
  5126. return titans;
  5127. }
  5128.  
  5129. function saveProgress() {
  5130. let saveProgressCall = {
  5131. calls: [{
  5132. name: "dungeonSaveProgress",
  5133. args: {},
  5134. ident: "body"
  5135. }]
  5136. }
  5137. send(JSON.stringify(saveProgressCall), resultEndBattle);
  5138. }
  5139.  
  5140. function endDungeon(reason, info) {
  5141. console.warn(reason, info);
  5142. setProgress(`${I18N('DUNGEON')} ${I18N('COMPLETED')}`, true);
  5143. resolve();
  5144. }
  5145. }
  5146.  
  5147. /**
  5148. * Passing the tower
  5149. *
  5150. * Прохождение башни
  5151. */
  5152. function testTower() {
  5153. return new Promise((resolve, reject) => {
  5154. tower = new executeTower(resolve, reject);
  5155. tower.start();
  5156. });
  5157. }
  5158.  
  5159. /**
  5160. * Passing the tower
  5161. *
  5162. * Прохождение башни
  5163. */
  5164. function executeTower(resolve, reject) {
  5165. lastTowerInfo = {};
  5166.  
  5167. scullCoin = 0;
  5168.  
  5169. heroGetAll = [];
  5170.  
  5171. heroesStates = {};
  5172.  
  5173. argsBattle = {
  5174. heroes: [],
  5175. favor: {},
  5176. };
  5177.  
  5178. callsExecuteTower = {
  5179. calls: [{
  5180. name: "towerGetInfo",
  5181. args: {},
  5182. ident: "towerGetInfo"
  5183. }, {
  5184. name: "teamGetAll",
  5185. args: {},
  5186. ident: "teamGetAll"
  5187. }, {
  5188. name: "teamGetFavor",
  5189. args: {},
  5190. ident: "teamGetFavor"
  5191. }, {
  5192. name: "inventoryGet",
  5193. args: {},
  5194. ident: "inventoryGet"
  5195. }, {
  5196. name: "heroGetAll",
  5197. args: {},
  5198. ident: "heroGetAll"
  5199. }]
  5200. }
  5201.  
  5202. buffIds = [
  5203. {id: 0, cost: 0, isBuy: false}, // plug // заглушка
  5204. {id: 1, cost: 1, isBuy: true}, // 3% attack // 3% атака
  5205. {id: 2, cost: 6, isBuy: true}, // 2% attack // 2% атака
  5206. {id: 3, cost: 16, isBuy: true}, // 4% attack // 4% атака
  5207. {id: 4, cost: 40, isBuy: true}, // 8% attack // 8% атака
  5208. {id: 5, cost: 1, isBuy: true}, // 10% armor // 10% броня
  5209. {id: 6, cost: 6, isBuy: true}, // 5% armor // 5% броня
  5210. {id: 7, cost: 16, isBuy: true}, // 10% armor // 10% броня
  5211. {id: 8, cost: 40, isBuy: true}, // 20% armor // 20% броня
  5212. { id: 9, cost: 1, isBuy: true }, // 10% protection from magic // 10% защита от магии
  5213. { id: 10, cost: 6, isBuy: true }, // 5% protection from magic // 5% защита от магии
  5214. { id: 11, cost: 16, isBuy: true }, // 10% protection from magic // 10% защита от магии
  5215. { id: 12, cost: 40, isBuy: true }, // 20% protection from magic // 20% защита от магии
  5216. { id: 13, cost: 1, isBuy: false }, // 40% health hero // 40% здоровья герою
  5217. { id: 14, cost: 6, isBuy: false }, // 40% health hero // 40% здоровья герою
  5218. { id: 15, cost: 16, isBuy: false }, // 80% health hero // 80% здоровья герою
  5219. { id: 16, cost: 40, isBuy: false }, // 40% health to all heroes // 40% здоровья всем героям
  5220. { id: 17, cost: 1, isBuy: false }, // 40% energy to the hero // 40% энергии герою
  5221. { id: 18, cost: 3, isBuy: false }, // 40% energy to the hero // 40% энергии герою
  5222. { id: 19, cost: 8, isBuy: false }, // 80% energy to the hero // 80% энергии герою
  5223. { id: 20, cost: 20, isBuy: false }, // 40% energy to all heroes // 40% энергии всем героям
  5224. { id: 21, cost: 40, isBuy: false }, // Hero Resurrection // Воскрешение героя
  5225. ]
  5226.  
  5227. this.start = function () {
  5228. send(JSON.stringify(callsExecuteTower), startTower);
  5229. }
  5230.  
  5231. /**
  5232. * Getting data on the Tower
  5233. *
  5234. * Получаем данные по башне
  5235. */
  5236. function startTower(e) {
  5237. res = e.results;
  5238. towerGetInfo = res[0].result.response;
  5239. if (!towerGetInfo) {
  5240. endTower('noTower', res);
  5241. return;
  5242. }
  5243. teamGetAll = res[1].result.response;
  5244. teamGetFavor = res[2].result.response;
  5245. inventoryGet = res[3].result.response;
  5246. heroGetAll = Object.values(res[4].result.response);
  5247.  
  5248. scullCoin = inventoryGet.coin[7] ?? 0;
  5249.  
  5250. argsBattle.favor = teamGetFavor.tower;
  5251. argsBattle.heroes = heroGetAll.sort((a, b) => b.power - a.power).slice(0, 5).map(e => e.id);
  5252. pet = teamGetAll.tower.filter(id => id >= 6000).pop();
  5253. if (pet) {
  5254. argsBattle.pet = pet;
  5255. }
  5256.  
  5257. checkFloor(towerGetInfo);
  5258. }
  5259.  
  5260. function fixHeroesTeam(argsBattle) {
  5261. let fixHeroes = argsBattle.heroes.filter(e => !heroesStates[e]?.isDead);
  5262. if (fixHeroes.length < 5) {
  5263. heroGetAll = heroGetAll.filter(e => !heroesStates[e.id]?.isDead);
  5264. fixHeroes = heroGetAll.sort((a, b) => b.power - a.power).slice(0, 5).map(e => e.id);
  5265. Object.keys(argsBattle.favor).forEach(e => {
  5266. if (!fixHeroes.includes(+e)) {
  5267. delete argsBattle.favor[e];
  5268. }
  5269. })
  5270. }
  5271. argsBattle.heroes = fixHeroes;
  5272. return argsBattle;
  5273. }
  5274.  
  5275. /**
  5276. * Check the floor
  5277. *
  5278. * Проверяем этаж
  5279. */
  5280. function checkFloor(towerInfo) {
  5281. lastTowerInfo = towerInfo;
  5282. maySkipFloor = +towerInfo.maySkipFloor;
  5283. floorNumber = +towerInfo.floorNumber;
  5284. heroesStates = towerInfo.states.heroes;
  5285. floorInfo = towerInfo.floor;
  5286.  
  5287. /**
  5288. * Is there at least one chest open on the floor
  5289. * Открыт ли на этаже хоть один сундук
  5290. */
  5291. isOpenChest = false;
  5292. if (towerInfo.floorType == "chest") {
  5293. isOpenChest = towerInfo.floor.chests.reduce((n, e) => n + e.opened, 0);
  5294. }
  5295.  
  5296. setProgress(`${I18N('TOWER')}: ${I18N('FLOOR')} ${floorNumber}`);
  5297. if (floorNumber > 49) {
  5298. if (isOpenChest) {
  5299. endTower('alreadyOpenChest 50 floor', floorNumber);
  5300. return;
  5301. }
  5302. }
  5303. /**
  5304. * If the chest is open and you can skip floors, then move on
  5305. * Если сундук открыт и можно скипать этажи, то переходим дальше
  5306. */
  5307. if (towerInfo.mayFullSkip && +towerInfo.teamLevel == 130) {
  5308. if (isOpenChest) {
  5309. nextOpenChest(floorNumber);
  5310. } else {
  5311. nextChestOpen(floorNumber);
  5312. }
  5313. return;
  5314. }
  5315.  
  5316. // console.log(towerInfo, scullCoin);
  5317. switch (towerInfo.floorType) {
  5318. case "battle":
  5319. if (floorNumber <= maySkipFloor) {
  5320. skipFloor();
  5321. return;
  5322. }
  5323. if (floorInfo.state == 2) {
  5324. nextFloor();
  5325. return;
  5326. }
  5327. startBattle().then(endBattle);
  5328. return;
  5329. case "buff":
  5330. checkBuff(towerInfo);
  5331. return;
  5332. case "chest":
  5333. openChest(floorNumber);
  5334. return;
  5335. default:
  5336. console.log('!', towerInfo.floorType, towerInfo);
  5337. break;
  5338. }
  5339. }
  5340.  
  5341. /**
  5342. * Let's start the fight
  5343. *
  5344. * Начинаем бой
  5345. */
  5346. function startBattle() {
  5347. return new Promise(function (resolve, reject) {
  5348. towerStartBattle = {
  5349. calls: [{
  5350. name: "towerStartBattle",
  5351. args: fixHeroesTeam(argsBattle),
  5352. ident: "body"
  5353. }]
  5354. }
  5355. send(JSON.stringify(towerStartBattle), resultBattle, resolve);
  5356. });
  5357. }
  5358. /**
  5359. * Returns the result of the battle in a promise
  5360. *
  5361. * Возращает резульат боя в промис
  5362. */
  5363. function resultBattle(resultBattles, resolve) {
  5364. battleData = resultBattles.results[0].result.response;
  5365. battleType = "get_tower";
  5366. BattleCalc(battleData, battleType, function (result) {
  5367. resolve(result);
  5368. });
  5369. }
  5370. /**
  5371. * Finishing the fight
  5372. *
  5373. * Заканчиваем бой
  5374. */
  5375. function endBattle(battleInfo) {
  5376. if (battleInfo.result.stars >= 3) {
  5377. endBattleCall = {
  5378. calls: [{
  5379. name: "towerEndBattle",
  5380. args: {
  5381. result: battleInfo.result,
  5382. progress: battleInfo.progress,
  5383. },
  5384. ident: "body"
  5385. }]
  5386. }
  5387. send(JSON.stringify(endBattleCall), resultEndBattle);
  5388. } else {
  5389. endTower('towerEndBattle win: false\n', battleInfo);
  5390. }
  5391. }
  5392.  
  5393. /**
  5394. * Getting and processing battle results
  5395. *
  5396. * Получаем и обрабатываем результаты боя
  5397. */
  5398. function resultEndBattle(e) {
  5399. battleResult = e.results[0].result.response;
  5400. if ('error' in battleResult) {
  5401. endTower('errorBattleResult', battleResult);
  5402. return;
  5403. }
  5404. if ('reward' in battleResult) {
  5405. scullCoin += battleResult.reward?.coin[7] ?? 0;
  5406. }
  5407. nextFloor();
  5408. }
  5409.  
  5410. function nextFloor() {
  5411. nextFloorCall = {
  5412. calls: [{
  5413. name: "towerNextFloor",
  5414. args: {},
  5415. ident: "body"
  5416. }]
  5417. }
  5418. send(JSON.stringify(nextFloorCall), checkDataFloor);
  5419. }
  5420.  
  5421. function openChest(floorNumber) {
  5422. floorNumber = floorNumber || 0;
  5423. openChestCall = {
  5424. calls: [{
  5425. name: "towerOpenChest",
  5426. args: {
  5427. num: 2
  5428. },
  5429. ident: "body"
  5430. }]
  5431. }
  5432. send(JSON.stringify(openChestCall), floorNumber < 50 ? nextFloor : lastChest);
  5433. }
  5434.  
  5435. function lastChest() {
  5436. endTower('openChest 50 floor', floorNumber);
  5437. }
  5438.  
  5439. function skipFloor() {
  5440. skipFloorCall = {
  5441. calls: [{
  5442. name: "towerSkipFloor",
  5443. args: {},
  5444. ident: "body"
  5445. }]
  5446. }
  5447. send(JSON.stringify(skipFloorCall), checkDataFloor);
  5448. }
  5449.  
  5450. function checkBuff(towerInfo) {
  5451. buffArr = towerInfo.floor;
  5452. promises = [];
  5453. for (let buff of buffArr) {
  5454. buffInfo = buffIds[buff.id];
  5455. if (buffInfo.isBuy && buffInfo.cost <= scullCoin) {
  5456. scullCoin -= buffInfo.cost;
  5457. promises.push(buyBuff(buff.id));
  5458. }
  5459. }
  5460. Promise.all(promises).then(nextFloor);
  5461. }
  5462.  
  5463. function buyBuff(buffId) {
  5464. return new Promise(function (resolve, reject) {
  5465. buyBuffCall = {
  5466. calls: [{
  5467. name: "towerBuyBuff",
  5468. args: {
  5469. buffId
  5470. },
  5471. ident: "body"
  5472. }]
  5473. }
  5474. send(JSON.stringify(buyBuffCall), resolve);
  5475. });
  5476. }
  5477.  
  5478. function checkDataFloor(result) {
  5479. towerInfo = result.results[0].result.response;
  5480. if ('reward' in towerInfo && towerInfo.reward?.coin) {
  5481. scullCoin += towerInfo.reward?.coin[7] ?? 0;
  5482. }
  5483. if ('tower' in towerInfo) {
  5484. towerInfo = towerInfo.tower;
  5485. }
  5486. if ('skullReward' in towerInfo) {
  5487. scullCoin += towerInfo.skullReward?.coin[7] ?? 0;
  5488. }
  5489. checkFloor(towerInfo);
  5490. }
  5491. /**
  5492. * Getting tower rewards
  5493. *
  5494. * Получаем награды башни
  5495. */
  5496. function farmTowerRewards(reason) {
  5497. let { pointRewards, points } = lastTowerInfo;
  5498. let pointsAll = Object.getOwnPropertyNames(pointRewards);
  5499. let farmPoints = pointsAll.filter(e => +e <= +points && !pointRewards[e]);
  5500. if (!farmPoints.length) {
  5501. return;
  5502. }
  5503. let farmTowerRewardsCall = {
  5504. calls: [{
  5505. name: "tower_farmPointRewards",
  5506. args: {
  5507. points: farmPoints
  5508. },
  5509. ident: "tower_farmPointRewards"
  5510. }]
  5511. }
  5512.  
  5513. if (scullCoin > 0 && reason == 'openChest 50 floor') {
  5514. farmTowerRewardsCall.calls.push({
  5515. name: "tower_farmSkullReward",
  5516. args: {},
  5517. ident: "tower_farmSkullReward"
  5518. });
  5519. }
  5520.  
  5521. send(JSON.stringify(farmTowerRewardsCall), () => { });
  5522. }
  5523.  
  5524. function fullSkipTower() {
  5525. /**
  5526. * Next chest
  5527. *
  5528. * Следующий сундук
  5529. */
  5530. function nextChest(n) {
  5531. return {
  5532. name: "towerNextChest",
  5533. args: {},
  5534. ident: "group_" + n + "_body"
  5535. }
  5536. }
  5537. /**
  5538. * Open chest
  5539. *
  5540. * Открыть сундук
  5541. */
  5542. function openChest(n) {
  5543. return {
  5544. name: "towerOpenChest",
  5545. args: {
  5546. "num": 2
  5547. },
  5548. ident: "group_" + n + "_body"
  5549. }
  5550. }
  5551.  
  5552. const fullSkipTowerCall = {
  5553. calls: []
  5554. }
  5555.  
  5556. let n = 0;
  5557. for (let i = 0; i < 15; i++) {
  5558. fullSkipTowerCall.calls.push(nextChest(++n));
  5559. fullSkipTowerCall.calls.push(openChest(++n));
  5560. }
  5561.  
  5562. send(JSON.stringify(fullSkipTowerCall), data => {
  5563. data.results[0] = data.results[28];
  5564. checkDataFloor(data);
  5565. });
  5566. }
  5567.  
  5568. function nextChestOpen(floorNumber) {
  5569. const calls = [{
  5570. name: "towerOpenChest",
  5571. args: {
  5572. num: 2
  5573. },
  5574. ident: "towerOpenChest"
  5575. }];
  5576.  
  5577. Send(JSON.stringify({ calls })).then(e => {
  5578. nextOpenChest(floorNumber);
  5579. });
  5580. }
  5581.  
  5582. function nextOpenChest(floorNumber) {
  5583. if (floorNumber > 49) {
  5584. endTower('openChest 50 floor', floorNumber);
  5585. return;
  5586. }
  5587. if (floorNumber == 1) {
  5588. fullSkipTower();
  5589. return;
  5590. }
  5591.  
  5592. let nextOpenChestCall = {
  5593. calls: [{
  5594. name: "towerNextChest",
  5595. args: {},
  5596. ident: "towerNextChest"
  5597. }, {
  5598. name: "towerOpenChest",
  5599. args: {
  5600. num: 2
  5601. },
  5602. ident: "towerOpenChest"
  5603. }]
  5604. }
  5605. send(JSON.stringify(nextOpenChestCall), checkDataFloor);
  5606. }
  5607.  
  5608. function endTower(reason, info) {
  5609. console.log(reason, info);
  5610. if (reason != 'noTower') {
  5611. farmTowerRewards(reason);
  5612. }
  5613. setProgress(`${I18N('TOWER')} ${I18N('COMPLETED')}!`, true);
  5614. resolve();
  5615. }
  5616. }
  5617.  
  5618. /**
  5619. * Passage of the arena of the titans
  5620. *
  5621. * Прохождение арены титанов
  5622. */
  5623. function testTitanArena() {
  5624. return new Promise((resolve, reject) => {
  5625. titAren = new executeTitanArena(resolve, reject);
  5626. titAren.start();
  5627. });
  5628. }
  5629.  
  5630. /**
  5631. * Passage of the arena of the titans
  5632. *
  5633. * Прохождение арены титанов
  5634. */
  5635. function executeTitanArena(resolve, reject) {
  5636. let titan_arena = [];
  5637. let finishListBattle = [];
  5638. /**
  5639. * ID of the current batch
  5640. *
  5641. * Идетификатор текущей пачки
  5642. */
  5643. let currentRival = 0;
  5644. /**
  5645. * Number of attempts to finish off the pack
  5646. *
  5647. * Количество попыток добития пачки
  5648. */
  5649. let attempts = 0;
  5650. /**
  5651. * Was there an attempt to finish off the current shooting range
  5652. *
  5653. * Была ли попытка добития текущего тира
  5654. */
  5655. let isCheckCurrentTier = false;
  5656. /**
  5657. * Current shooting range
  5658. *
  5659. * Текущий тир
  5660. */
  5661. let currTier = 0;
  5662. /**
  5663. * Number of battles on the current dash
  5664. *
  5665. * Количество битв на текущем тире
  5666. */
  5667. let countRivalsTier = 0;
  5668.  
  5669. let callsStart = {
  5670. calls: [{
  5671. name: "titanArenaGetStatus",
  5672. args: {},
  5673. ident: "titanArenaGetStatus"
  5674. }, {
  5675. name: "teamGetAll",
  5676. args: {},
  5677. ident: "teamGetAll"
  5678. }]
  5679. }
  5680.  
  5681. this.start = function () {
  5682. send(JSON.stringify(callsStart), startTitanArena);
  5683. }
  5684.  
  5685. function startTitanArena(data) {
  5686. let titanArena = data.results[0].result.response;
  5687. if (titanArena.status == 'disabled') {
  5688. endTitanArena('disabled', titanArena);
  5689. return;
  5690. }
  5691.  
  5692. let teamGetAll = data.results[1].result.response;
  5693. titan_arena = teamGetAll.titan_arena;
  5694.  
  5695. checkTier(titanArena)
  5696. }
  5697.  
  5698. function checkTier(titanArena) {
  5699. if (titanArena.status == "peace_time") {
  5700. endTitanArena('Peace_time', titanArena);
  5701. return;
  5702. }
  5703. currTier = titanArena.tier;
  5704. if (currTier) {
  5705. setProgress(`${I18N('TITAN_ARENA')}: ${I18N('LEVEL')} ${currTier}`);
  5706. }
  5707.  
  5708. if (titanArena.status == "completed_tier") {
  5709. titanArenaCompleteTier();
  5710. return;
  5711. }
  5712. /**
  5713. * Checking for the possibility of a raid
  5714. * Проверка на возможность рейда
  5715. */
  5716. if (titanArena.canRaid) {
  5717. titanArenaStartRaid();
  5718. return;
  5719. }
  5720. /**
  5721. * Check was an attempt to achieve the current shooting range
  5722. * Проверка была ли попытка добития текущего тира
  5723. */
  5724. if (!isCheckCurrentTier) {
  5725. checkRivals(titanArena.rivals);
  5726. return;
  5727. }
  5728.  
  5729. endTitanArena('Done or not canRaid', titanArena);
  5730. }
  5731. /**
  5732. * Submit dash information for verification
  5733. *
  5734. * Отправка информации о тире на проверку
  5735. */
  5736. function checkResultInfo(data) {
  5737. let titanArena = data.results[0].result.response;
  5738. checkTier(titanArena);
  5739. }
  5740. /**
  5741. * Finish the current tier
  5742. *
  5743. * Завершить текущий тир
  5744. */
  5745. function titanArenaCompleteTier() {
  5746. isCheckCurrentTier = false;
  5747. let calls = [{
  5748. name: "titanArenaCompleteTier",
  5749. args: {},
  5750. ident: "body"
  5751. }];
  5752. send(JSON.stringify({calls}), checkResultInfo);
  5753. }
  5754. /**
  5755. * Gathering points to be completed
  5756. *
  5757. * Собираем точки которые нужно добить
  5758. */
  5759. function checkRivals(rivals) {
  5760. finishListBattle = [];
  5761. for (let n in rivals) {
  5762. if (rivals[n].attackScore < 250) {
  5763. finishListBattle.push(n);
  5764. }
  5765. }
  5766. console.log('checkRivals', finishListBattle);
  5767. countRivalsTier = finishListBattle.length;
  5768. roundRivals();
  5769. }
  5770. /**
  5771. * Selecting the next point to finish off
  5772. *
  5773. * Выбор следующей точки для добития
  5774. */
  5775. function roundRivals() {
  5776. let countRivals = finishListBattle.length;
  5777. if (!countRivals) {
  5778. /**
  5779. * Whole range checked
  5780. *
  5781. * Весь тир проверен
  5782. */
  5783. isCheckCurrentTier = true;
  5784. titanArenaGetStatus();
  5785. return;
  5786. }
  5787. // setProgress('TitanArena: Уровень ' + currTier + ' Бои: ' + (countRivalsTier - countRivals + 1) + '/' + countRivalsTier);
  5788. currentRival = finishListBattle.pop();
  5789. attempts = +currentRival;
  5790. // console.log('roundRivals', currentRival);
  5791. titanArenaStartBattle(currentRival);
  5792. }
  5793. /**
  5794. * The start of a solo battle
  5795. *
  5796. * Начало одиночной битвы
  5797. */
  5798. function titanArenaStartBattle(rivalId) {
  5799. let calls = [{
  5800. name: "titanArenaStartBattle",
  5801. args: {
  5802. rivalId: rivalId,
  5803. titans: titan_arena
  5804. },
  5805. ident: "body"
  5806. }];
  5807. send(JSON.stringify({calls}), calcResult);
  5808. }
  5809. /**
  5810. * Calculation of the results of the battle
  5811. *
  5812. * Расчет результатов боя
  5813. */
  5814. function calcResult(data) {
  5815. let battlesInfo = data.results[0].result.response.battle;
  5816. /**
  5817. * If attempts are equal to the current battle number we make
  5818. * Если попытки равны номеру текущего боя делаем прерасчет
  5819. */
  5820. if (attempts == currentRival) {
  5821. preCalcBattle(battlesInfo);
  5822. return;
  5823. }
  5824. /**
  5825. * If there are still attempts, we calculate a new battle
  5826. * Если попытки еще есть делаем расчет нового боя
  5827. */
  5828. if (attempts > 0) {
  5829. attempts--;
  5830. calcBattleResult(battlesInfo)
  5831. .then(resultCalcBattle);
  5832. return;
  5833. }
  5834. /**
  5835. * Otherwise, go to the next opponent
  5836. * Иначе переходим к следующему сопернику
  5837. */
  5838. roundRivals();
  5839. }
  5840. /**
  5841. * Processing the results of the battle calculation
  5842. *
  5843. * Обработка результатов расчета битвы
  5844. */
  5845. function resultCalcBattle(resultBattle) {
  5846. // console.log('resultCalcBattle', currentRival, attempts, resultBattle.result.win);
  5847. /**
  5848. * If the current calculation of victory is not a chance or the attempt ended with the finish the battle
  5849. * Если текущий расчет победа или шансов нет или попытки кончились завершаем бой
  5850. */
  5851. if (resultBattle.result.win || !attempts) {
  5852. titanArenaEndBattle({
  5853. progress: resultBattle.progress,
  5854. result: resultBattle.result,
  5855. rivalId: resultBattle.battleData.typeId
  5856. });
  5857. return;
  5858. }
  5859. /**
  5860. * If not victory and there are attempts we start a new battle
  5861. * Если не победа и есть попытки начинаем новый бой
  5862. */
  5863. titanArenaStartBattle(resultBattle.battleData.typeId);
  5864. }
  5865. /**
  5866. * Returns the promise of calculating the results of the battle
  5867. *
  5868. * Возращает промис расчета результатов битвы
  5869. */
  5870. function getBattleInfo(battle, isRandSeed) {
  5871. return new Promise(function (resolve) {
  5872. if (isRandSeed) {
  5873. battle.seed = Math.floor(Date.now() / 1000) + random(0, 1e3);
  5874. }
  5875. // console.log(battle.seed);
  5876. BattleCalc(battle, "get_titanClanPvp", e => resolve(e));
  5877. });
  5878. }
  5879. /**
  5880. * Recalculate battles
  5881. *
  5882. * Прерасчтет битвы
  5883. */
  5884. function preCalcBattle(battle) {
  5885. let actions = [getBattleInfo(battle, false)];
  5886. const countTestBattle = getInput('countTestBattle');
  5887. for (let i = 0; i < countTestBattle; i++) {
  5888. actions.push(getBattleInfo(battle, true));
  5889. }
  5890. Promise.all(actions)
  5891. .then(resultPreCalcBattle);
  5892. }
  5893. /**
  5894. * Processing the results of the battle recalculation
  5895. *
  5896. * Обработка результатов прерасчета битвы
  5897. */
  5898. function resultPreCalcBattle(e) {
  5899. let wins = e.map(n => n.result.win);
  5900. let firstBattle = e.shift();
  5901. let countWin = wins.reduce((w, s) => w + s);
  5902. const countTestBattle = getInput('countTestBattle');
  5903. console.log('resultPreCalcBattle', `${countWin}/${countTestBattle}`)
  5904. if (countWin > 0) {
  5905. attempts = getInput('countAutoBattle');
  5906. } else {
  5907. attempts = 0;
  5908. }
  5909. resultCalcBattle(firstBattle);
  5910. }
  5911.  
  5912. /**
  5913. * Complete an arena battle
  5914. *
  5915. * Завершить битву на арене
  5916. */
  5917. function titanArenaEndBattle(args) {
  5918. let calls = [{
  5919. name: "titanArenaEndBattle",
  5920. args,
  5921. ident: "body"
  5922. }];
  5923. send(JSON.stringify({calls}), resultTitanArenaEndBattle);
  5924. }
  5925.  
  5926. function resultTitanArenaEndBattle(e) {
  5927. let attackScore = e.results[0].result.response.attackScore;
  5928. let numReval = countRivalsTier - finishListBattle.length;
  5929. setProgress(`${I18N('TITAN_ARENA')}: ${I18N('LEVEL')} ${currTier} </br>${I18N('BATTLES')}: ${numReval}/${countRivalsTier} - ${attackScore}`);
  5930. /**
  5931. * TODO: Might need to improve the results.
  5932. * TODO: Возможно стоит сделать улучшение результатов
  5933. */
  5934. // console.log('resultTitanArenaEndBattle', e)
  5935. console.log('resultTitanArenaEndBattle', numReval + '/' + countRivalsTier, attempts)
  5936. roundRivals();
  5937. }
  5938. /**
  5939. * Arena State
  5940. *
  5941. * Состояние арены
  5942. */
  5943. function titanArenaGetStatus() {
  5944. let calls = [{
  5945. name: "titanArenaGetStatus",
  5946. args: {},
  5947. ident: "body"
  5948. }];
  5949. send(JSON.stringify({calls}), checkResultInfo);
  5950. }
  5951. /**
  5952. * Arena Raid Request
  5953. *
  5954. * Запрос рейда арены
  5955. */
  5956. function titanArenaStartRaid() {
  5957. let calls = [{
  5958. name: "titanArenaStartRaid",
  5959. args: {
  5960. titans: titan_arena
  5961. },
  5962. ident: "body"
  5963. }];
  5964. send(JSON.stringify({calls}), calcResults);
  5965. }
  5966.  
  5967. function calcResults(data) {
  5968. let battlesInfo = data.results[0].result.response;
  5969. let {attackers, rivals} = battlesInfo;
  5970.  
  5971. let promises = [];
  5972. for (let n in rivals) {
  5973. rival = rivals[n];
  5974. promises.push(calcBattleResult({
  5975. attackers: attackers,
  5976. defenders: [rival.team],
  5977. seed: rival.seed,
  5978. typeId: n,
  5979. }));
  5980. }
  5981.  
  5982. Promise.all(promises)
  5983. .then(results => {
  5984. const endResults = {};
  5985. for (let info of results) {
  5986. let id = info.battleData.typeId;
  5987. endResults[id] = {
  5988. progress: info.progress,
  5989. result: info.result,
  5990. }
  5991. }
  5992. titanArenaEndRaid(endResults);
  5993. });
  5994. }
  5995.  
  5996. function calcBattleResult(battleData) {
  5997. return new Promise(function (resolve, reject) {
  5998. BattleCalc(battleData, "get_titanClanPvp", resolve);
  5999. });
  6000. }
  6001.  
  6002. /**
  6003. * Sending Raid Results
  6004. *
  6005. * Отправка результатов рейда
  6006. */
  6007. function titanArenaEndRaid(results) {
  6008. titanArenaEndRaidCall = {
  6009. calls: [{
  6010. name: "titanArenaEndRaid",
  6011. args: {
  6012. results
  6013. },
  6014. ident: "body"
  6015. }]
  6016. }
  6017. send(JSON.stringify(titanArenaEndRaidCall), checkRaidResults);
  6018. }
  6019.  
  6020. function checkRaidResults(data) {
  6021. results = data.results[0].result.response.results;
  6022. isSucsesRaid = true;
  6023. for (let i in results) {
  6024. isSucsesRaid &&= (results[i].attackScore >= 250);
  6025. }
  6026.  
  6027. if (isSucsesRaid) {
  6028. titanArenaCompleteTier();
  6029. } else {
  6030. titanArenaGetStatus();
  6031. }
  6032. }
  6033.  
  6034. function titanArenaFarmDailyReward() {
  6035. titanArenaFarmDailyRewardCall = {
  6036. calls: [{
  6037. name: "titanArenaFarmDailyReward",
  6038. args: {},
  6039. ident: "body"
  6040. }]
  6041. }
  6042. send(JSON.stringify(titanArenaFarmDailyRewardCall), () => {console.log('Done farm daily reward')});
  6043. }
  6044.  
  6045. function endTitanArena(reason, info) {
  6046. if (!['Peace_time', 'disabled'].includes(reason)) {
  6047. titanArenaFarmDailyReward();
  6048. }
  6049. console.log(reason, info);
  6050. setProgress(`${I18N('TITAN_ARENA')} ${I18N('COMPLETED')}!`, true);
  6051. resolve();
  6052. }
  6053. }
  6054.  
  6055. function hackGame() {
  6056. self = this;
  6057. selfGame = null;
  6058. bindId = 1e9;
  6059. this.libGame = null;
  6060.  
  6061. /**
  6062. * List of correspondence of used classes to their names
  6063. *
  6064. * Список соответствия используемых классов их названиям
  6065. */
  6066. ObjectsList = [
  6067. {name:"BattlePresets", prop:"game.battle.controller.thread.BattlePresets"},
  6068. {name:"DataStorage", prop:"game.data.storage.DataStorage"},
  6069. {name:"BattleConfigStorage", prop:"game.data.storage.battle.BattleConfigStorage"},
  6070. {name:"BattleInstantPlay", prop:"game.battle.controller.instant.BattleInstantPlay"},
  6071. {name:"MultiBattleResult", prop:"game.battle.controller.MultiBattleResult"},
  6072.  
  6073. {name:"PlayerMissionData", prop:"game.model.user.mission.PlayerMissionData"},
  6074. {name:"PlayerMissionBattle", prop:"game.model.user.mission.PlayerMissionBattle"},
  6075. {name:"GameModel", prop:"game.model.GameModel"},
  6076. {name:"CommandManager", prop:"game.command.CommandManager"},
  6077. {name:"MissionCommandList", prop:"game.command.rpc.mission.MissionCommandList"},
  6078. {name:"RPCCommandBase", prop:"game.command.rpc.RPCCommandBase"},
  6079. {name:"PlayerTowerData", prop:"game.model.user.tower.PlayerTowerData"},
  6080. {name:"TowerCommandList", prop:"game.command.tower.TowerCommandList"},
  6081. {name:"PlayerHeroTeamResolver", prop:"game.model.user.hero.PlayerHeroTeamResolver"},
  6082. {name:"BattlePausePopup", prop:"game.view.popup.battle.BattlePausePopup"},
  6083. {name:"BattlePopup", prop:"game.view.popup.battle.BattlePopup"},
  6084. {name:"DisplayObjectContainer", prop:"starling.display.DisplayObjectContainer"},
  6085. {name:"GuiClipContainer", prop:"engine.core.clipgui.GuiClipContainer"},
  6086. {name:"BattlePausePopupClip", prop:"game.view.popup.battle.BattlePausePopupClip"},
  6087. {name:"ClipLabel", prop:"game.view.gui.components.ClipLabel"},
  6088. {name:"ClipLabelBase", prop:"game.view.gui.components.ClipLabelBase"},
  6089. {name:"Translate", prop:"com.progrestar.common.lang.Translate"},
  6090. {name:"ClipButtonLabeledCentered", prop:"game.view.gui.components.ClipButtonLabeledCentered"},
  6091. {name:"BattlePausePopupMediator", prop:"game.mediator.gui.popup.battle.BattlePausePopupMediator"},
  6092. {name:"SettingToggleButton", prop:"game.mechanics.settings.popup.view.SettingToggleButton"},
  6093. {name:"PlayerDungeonData", prop:"game.mechanics.dungeon.model.PlayerDungeonData"},
  6094. {name:"NextDayUpdatedManager", prop:"game.model.user.NextDayUpdatedManager"},
  6095. {name:"BattleController", prop:"game.battle.controller.BattleController"},
  6096. {name:"BattleSettingsModel", prop:"game.battle.controller.BattleSettingsModel"},
  6097. {name:"BooleanProperty", prop:"engine.core.utils.property.BooleanProperty"},
  6098. {name:"RuleStorage", prop:"game.data.storage.rule.RuleStorage"},
  6099. {name:"BattleConfig", prop:"battle.BattleConfig"},
  6100. {name:"BattleGuiMediator", prop:"game.battle.gui.BattleGuiMediator"},
  6101. {name:"BooleanPropertyWriteable", prop:"engine.core.utils.property.BooleanPropertyWriteable"},
  6102. { name: "BattleLogEncoder", prop: "battle.log.BattleLogEncoder" },
  6103. { name: "BattleLogReader", prop: "battle.log.BattleLogReader" },
  6104. { name: "PlayerSubscriptionInfoValueObject", prop: "game.model.user.subscription.PlayerSubscriptionInfoValueObject" },
  6105. ];
  6106.  
  6107. /**
  6108. * Contains the game classes needed to write and override game methods
  6109. *
  6110. * Содержит классы игры необходимые для написания и подмены методов игры
  6111. */
  6112. Game = {
  6113. /**
  6114. * Function 'e'
  6115. * Функция 'e'
  6116. */
  6117. bindFunc: function (a, b) {
  6118. if (null == b)
  6119. return null;
  6120. null == b.__id__ && (b.__id__ = bindId++);
  6121. var c;
  6122. null == a.hx__closures__ ? a.hx__closures__ = {} :
  6123. c = a.hx__closures__[b.__id__];
  6124. null == c && (c = b.bind(a), a.hx__closures__[b.__id__] = c);
  6125. return c
  6126. },
  6127. };
  6128.  
  6129. /**
  6130. * Connects to game objects via the object creation event
  6131. *
  6132. * Подключается к объектам игры через событие создания объекта
  6133. */
  6134. function connectGame() {
  6135. for (let obj of ObjectsList) {
  6136. /**
  6137. * https: //stackoverflow.com/questions/42611719/how-to-intercept-and-modify-a-specific-property-for-any-object
  6138. */
  6139. Object.defineProperty(Object.prototype, obj.prop, {
  6140. set: function (value) {
  6141. if (!selfGame) {
  6142. selfGame = this;
  6143. }
  6144. if (!Game[obj.name]) {
  6145. Game[obj.name] = value;
  6146. }
  6147. // console.log('set ' + obj.prop, this, value);
  6148. this[obj.prop + '_'] = value;
  6149. },
  6150. get: function () {
  6151. // console.log('get ' + obj.prop, this);
  6152. return this[obj.prop + '_'];
  6153. }
  6154. });
  6155. }
  6156. }
  6157.  
  6158. /**
  6159. * Game.BattlePresets
  6160. * @param {bool} a isReplay
  6161. * @param {bool} b autoToggleable
  6162. * @param {bool} c auto On Start
  6163. * @param {object} d config
  6164. * @param {bool} f showBothTeams
  6165. */
  6166. /**
  6167. * Returns the results of the battle to the callback function
  6168. * Возвращает в функцию callback результаты боя
  6169. * @param {*} battleData battle data данные боя
  6170. * @param {*} battleConfig combat configuration type options:
  6171. *
  6172. * тип конфигурации боя варианты:
  6173. *
  6174. * "get_invasion", "get_titanPvpManual", "get_titanPvp",
  6175. * "get_titanClanPvp","get_clanPvp","get_titan","get_boss",
  6176. * "get_tower","get_pve","get_pvpManual","get_pvp","get_core"
  6177. *
  6178. * You can specify the xYc function in the game.assets.storage.BattleAssetStorage class
  6179. *
  6180. * Можно уточнить в классе game.assets.storage.BattleAssetStorage функция xYc
  6181. * @param {*} callback функция в которую вернуться результаты боя
  6182. */
  6183. this.BattleCalc = function (battleData, battleConfig, callback) {
  6184. // battleConfig = battleConfig || getBattleType(battleData.type)
  6185. if (!Game.BattlePresets) throw Error('Use connectGame');
  6186. battlePresets = new Game.BattlePresets(!!battleData.progress, !1, !0, Game.DataStorage[getFn(Game.DataStorage, 24)][getF(Game.BattleConfigStorage, battleConfig)](), !1);
  6187. battleInstantPlay = new Game.BattleInstantPlay(battleData, battlePresets);
  6188. battleInstantPlay[getProtoFn(Game.BattleInstantPlay, 9)].add((battleInstant) => {
  6189. const battleResult = battleInstant[getF(Game.BattleInstantPlay, 'get_result')]();
  6190. const battleData = battleInstant[getF(Game.BattleInstantPlay, 'get_rawBattleInfo')]();
  6191. const battleLog = Game.BattleLogEncoder.read(new Game.BattleLogReader(battleResult[getProtoFn(Game.MultiBattleResult, 2)][0]));
  6192. const timeLimit = battlePresets[getF(Game.BattlePresets, 'get_timeLimit')]();
  6193. const battleTime = Math.max(...battleLog.map((e) => (e.time < timeLimit && e.time !== 168.8 ? e.time : 0)));
  6194. callback({
  6195. battleTime,
  6196. battleData,
  6197. progress: battleResult[getF(Game.MultiBattleResult, 'get_progress')](),
  6198. result: battleResult[getF(Game.MultiBattleResult, 'get_result')]()
  6199. })
  6200. });
  6201. battleInstantPlay.start();
  6202. }
  6203.  
  6204. /**
  6205. * Returns a function with the specified name from the class
  6206. *
  6207. * Возвращает из класса функцию с указанным именем
  6208. * @param {Object} classF Class // класс
  6209. * @param {String} nameF function name // имя функции
  6210. * @param {String} pos name and alias order // порядок имени и псевдонима
  6211. * @returns
  6212. */
  6213. function getF(classF, nameF, pos) {
  6214. pos = pos || false;
  6215. let prop = Object.entries(classF.prototype.__properties__)
  6216. if (!pos) {
  6217. return prop.filter((e) => e[1] == nameF).pop()[0];
  6218. } else {
  6219. return prop.filter((e) => e[0] == nameF).pop()[1];
  6220. }
  6221. }
  6222.  
  6223. /**
  6224. * Returns a function with the specified name from the class
  6225. *
  6226. * Возвращает из класса функцию с указанным именем
  6227. * @param {Object} classF Class // класс
  6228. * @param {String} nameF function name // имя функции
  6229. * @returns
  6230. */
  6231. function getFnP(classF, nameF) {
  6232. let prop = Object.entries(classF.__properties__)
  6233. return prop.filter((e) => e[1] == nameF).pop()[0];
  6234. }
  6235.  
  6236. /**
  6237. * Returns the function name with the specified ordinal from the class
  6238. *
  6239. * Возвращает имя функции с указаным порядковым номером из класса
  6240. * @param {Object} classF Class // класс
  6241. * @param {Number} nF Order number of function // порядковый номер функции
  6242. * @returns
  6243. */
  6244. function getFn(classF, nF) {
  6245. let prop = Object.keys(classF);
  6246. return prop[nF];
  6247. }
  6248.  
  6249. /**
  6250. * Returns the name of the function with the specified serial number from the prototype of the class
  6251. *
  6252. * Возвращает имя функции с указаным порядковым номером из прототипа класса
  6253. * @param {Object} classF Class // класс
  6254. * @param {Number} nF Order number of function // порядковый номер функции
  6255. * @returns
  6256. */
  6257. function getProtoFn(classF, nF) {
  6258. let prop = Object.keys(classF.prototype);
  6259. return prop[nF];
  6260. }
  6261. /**
  6262. * Description of replaced functions
  6263. *
  6264. * Описание подменяемых функций
  6265. */
  6266. replaceFunction = {
  6267. company: function() {
  6268. let PMD_12 = getProtoFn(Game.PlayerMissionData, 12);
  6269. let oldSkipMisson = Game.PlayerMissionData.prototype[PMD_12];
  6270. Game.PlayerMissionData.prototype[PMD_12] = function (a, b, c) {
  6271. if (!isChecked('passBattle')) {
  6272. oldSkipMisson.call(this, a, b, c);
  6273. return;
  6274. }
  6275.  
  6276. try {
  6277. this[getProtoFn(Game.PlayerMissionData, 9)] = new Game.PlayerMissionBattle(a, b, c);
  6278.  
  6279. var a = new Game.BattlePresets(!1, !1, !0, Game.DataStorage[getFn(Game.DataStorage, 24)][getProtoFn(Game.BattleConfigStorage, 20)](), !1);
  6280. a = new Game.BattleInstantPlay(c, a);
  6281. a[getProtoFn(Game.BattleInstantPlay, 9)].add(Game.bindFunc(this, this.P$h));
  6282. a.start()
  6283. } catch (error) {
  6284. console.error('company', error)
  6285. oldSkipMisson.call(this, a, b, c);
  6286. }
  6287. }
  6288.  
  6289. Game.PlayerMissionData.prototype.P$h = function (a) {
  6290. let GM_2 = getFn(Game.GameModel, 2);
  6291. let GM_P2 = getProtoFn(Game.GameModel, 2);
  6292. let CM_20 = getProtoFn(Game.CommandManager, 20);
  6293. let MCL_2 = getProtoFn(Game.MissionCommandList, 2);
  6294. let MBR_15 = getF(Game.MultiBattleResult, "get_result");
  6295. let RPCCB_15 = getProtoFn(Game.RPCCommandBase, 16);
  6296. let PMD_32 = getProtoFn(Game.PlayerMissionData, 32);
  6297. Game.GameModel[GM_2]()[GM_P2][CM_20][MCL_2](a[MBR_15]())[RPCCB_15](Game.bindFunc(this, this[PMD_32]))
  6298. }
  6299. },
  6300. tower: function() {
  6301. let PTD_67 = getProtoFn(Game.PlayerTowerData, 67);
  6302. let oldSkipTower = Game.PlayerTowerData.prototype[PTD_67];
  6303. Game.PlayerTowerData.prototype[PTD_67] = function (a) {
  6304. if (!isChecked('passBattle')) {
  6305. oldSkipTower.call(this, a);
  6306. return;
  6307. }
  6308. try {
  6309. var p = new Game.BattlePresets(!1, !1, !0, Game.DataStorage[getFn(Game.DataStorage, 24)][getProtoFn(Game.BattleConfigStorage,20)](), !1);
  6310. a = new Game.BattleInstantPlay(a, p);
  6311. a[getProtoFn(Game.BattleInstantPlay, 9)].add(Game.bindFunc(this, this.P$h));
  6312. a.start()
  6313. } catch (error) {
  6314. console.error('tower', error)
  6315. oldSkipMisson.call(this, a, b, c);
  6316. }
  6317. }
  6318.  
  6319. Game.PlayerTowerData.prototype.P$h = function (a) {
  6320. const GM_2 = getFnP(Game.GameModel, "get_instance");
  6321. const GM_P2 = getProtoFn(Game.GameModel, 2);
  6322. const CM_29 = getProtoFn(Game.CommandManager, 29);
  6323. const TCL_5 = getProtoFn(Game.TowerCommandList, 5);
  6324. const MBR_15 = getF(Game.MultiBattleResult, "get_result");
  6325. const RPCCB_15 = getProtoFn(Game.RPCCommandBase, 17);
  6326. const PTD_78 = getProtoFn(Game.PlayerTowerData, 78);
  6327. Game.GameModel[GM_2]()[GM_P2][CM_29][TCL_5](a[MBR_15]())[RPCCB_15](Game.bindFunc(this, this[PTD_78]));
  6328. }
  6329. },
  6330. // skipSelectHero: function() {
  6331. // if (!HOST) throw Error('Use connectGame');
  6332. // Game.PlayerHeroTeamResolver.prototype[getProtoFn(Game.PlayerHeroTeamResolver, 3)] = () => false;
  6333. // },
  6334. passBattle: function() {
  6335. let BPP_4 = getProtoFn(Game.BattlePausePopup, 4);
  6336. let oldPassBattle = Game.BattlePausePopup.prototype[BPP_4];
  6337. Game.BattlePausePopup.prototype[BPP_4] = function (a) {
  6338. if (!isChecked('passBattle')) {
  6339. oldPassBattle.call(this, a);
  6340. return;
  6341. }
  6342. try {
  6343. Game.BattlePopup.prototype[getProtoFn(Game.BattlePausePopup, 4)].call(this, a);
  6344. this[getProtoFn(Game.BattlePausePopup, 3)]();
  6345. this[getProtoFn(Game.DisplayObjectContainer, 3)](this.clip[getProtoFn(Game.GuiClipContainer, 2)]());
  6346. this.clip[getProtoFn(Game.BattlePausePopupClip, 1)][getProtoFn(Game.ClipLabelBase, 9)](Game.Translate.translate("UI_POPUP_BATTLE_PAUSE"));
  6347.  
  6348. 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)])));
  6349. this.clip[getProtoFn(Game.BattlePausePopupClip, 5)][getProtoFn(Game.ClipButtonLabeledCentered, 2)](
  6350. this[getProtoFn(Game.BattlePausePopup, 1)][getProtoFn(Game.BattlePausePopupMediator, 14)](),
  6351. this[getProtoFn(Game.BattlePausePopup, 1)][getProtoFn(Game.BattlePausePopupMediator, 13)]() ?
  6352. (q = this[getProtoFn(Game.BattlePausePopup, 1)], Game.bindFunc(q, q[getProtoFn(Game.BattlePausePopupMediator, 18)])) :
  6353. (q = this[getProtoFn(Game.BattlePausePopup, 1)], Game.bindFunc(q, q[getProtoFn(Game.BattlePausePopupMediator, 18)]))
  6354. );
  6355.  
  6356. this.clip[getProtoFn(Game.BattlePausePopupClip, 5)][getProtoFn(Game.ClipButtonLabeledCentered, 0)][getProtoFn(Game.ClipLabelBase, 24)]();
  6357. this.clip[getProtoFn(Game.BattlePausePopupClip, 3)][getProtoFn(Game.SettingToggleButton, 3)](this[getProtoFn(Game.BattlePausePopup, 1)][getProtoFn(Game.BattlePausePopupMediator, 9)]());
  6358. this.clip[getProtoFn(Game.BattlePausePopupClip, 4)][getProtoFn(Game.SettingToggleButton, 3)](this[getProtoFn(Game.BattlePausePopup, 1)][getProtoFn(Game.BattlePausePopupMediator, 10)]());
  6359. this.clip[getProtoFn(Game.BattlePausePopupClip, 6)][getProtoFn(Game.SettingToggleButton, 3)](this[getProtoFn(Game.BattlePausePopup, 1)][getProtoFn(Game.BattlePausePopupMediator, 11)]());
  6360. } catch(error) {
  6361. console.error('passBattle', error)
  6362. oldPassBattle.call(this, a);
  6363. }
  6364. }
  6365.  
  6366. let retreatButtonLabel = getF(Game.BattlePausePopupMediator, "get_retreatButtonLabel");
  6367. let oldFunc = Game.BattlePausePopupMediator.prototype[retreatButtonLabel];
  6368. Game.BattlePausePopupMediator.prototype[retreatButtonLabel] = function () {
  6369. if (isChecked('passBattle')) {
  6370. return I18N('BTN_PASS');
  6371. } else {
  6372. return oldFunc.call(this);
  6373. }
  6374. }
  6375. },
  6376. /*
  6377. endlessCards: function() {
  6378. let PDD_20 = getProtoFn(Game.PlayerDungeonData, 20);
  6379. let oldEndlessCards = Game.PlayerDungeonData.prototype[PDD_20];
  6380. Game.PlayerDungeonData.prototype[PDD_20] = function () {
  6381. if (countPredictionCard <= 0) {
  6382. return true;
  6383. } else {
  6384. return oldEndlessCards.call(this);
  6385. }
  6386. }
  6387. },*/
  6388. speedBattle: function () {
  6389. const get_timeScale = getF(Game.BattleController, "get_timeScale");
  6390. const oldSpeedBattle = Game.BattleController.prototype[get_timeScale];
  6391. Game.BattleController.prototype[get_timeScale] = function () {
  6392. const speedBattle = Number.parseFloat(getInput('speedBattle'));
  6393. if (!speedBattle) {
  6394. return oldSpeedBattle.call(this);
  6395. }
  6396. try {
  6397. const BC_12 = getProtoFn(Game.BattleController, 12);
  6398. const BSM_12 = getProtoFn(Game.BattleSettingsModel, 12);
  6399. const BP_get_value = getF(Game.BooleanProperty, "get_value");
  6400. if (this[BC_12][BSM_12][BP_get_value]()) {
  6401. return 0;
  6402. }
  6403. const BSM_2 = getProtoFn(Game.BattleSettingsModel, 2);
  6404. const BC_49 = getProtoFn(Game.BattleController, 49);
  6405. const BSM_1 = getProtoFn(Game.BattleSettingsModel, 1);
  6406. const BC_14 = getProtoFn(Game.BattleController, 14);
  6407. const BC_3 = getFn(Game.BattleController, 3);
  6408. if (this[BC_12][BSM_2][BP_get_value]()) {
  6409. var a = speedBattle * this[BC_49]();
  6410. } else {
  6411. a = this[BC_12][BSM_1][BP_get_value]();
  6412. const maxSpeed = Math.max(...this[BC_14]);
  6413. const multiple = a == this[BC_14].indexOf(maxSpeed) ? (maxSpeed >= 4 ? speedBattle : this[BC_14][a]) : this[BC_14][a];
  6414. a = multiple * Game.BattleController[BC_3][BP_get_value]() * this[BC_49]();
  6415. }
  6416. const BSM_24 = getProtoFn(Game.BattleSettingsModel, 24);
  6417. a > this[BC_12][BSM_24][BP_get_value]() && (a = this[BC_12][BSM_24][BP_get_value]());
  6418. const DS_23 = getFn(Game.DataStorage, 23);
  6419. const get_battleSpeedMultiplier = getF(Game.RuleStorage, "get_battleSpeedMultiplier", true);
  6420. var b = Game.DataStorage[DS_23][get_battleSpeedMultiplier]();
  6421. const R_1 = getFn(selfGame.Reflect, 1);
  6422. const BC_1 = getFn(Game.BattleController, 1);
  6423. const get_config = getF(Game.BattlePresets, "get_config");
  6424. 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"));
  6425. return a
  6426. } catch(error) {
  6427. console.error('passBatspeedBattletle', error)
  6428. return oldSpeedBattle.call(this);
  6429. }
  6430. }
  6431. },
  6432.  
  6433. /**
  6434. * Acceleration button without Valkyries favor
  6435. *
  6436. * Кнопка ускорения без Покровительства Валькирий
  6437. */
  6438. battleFastKey: function () {
  6439. const PSIVO_9 = getProtoFn(Game.PlayerSubscriptionInfoValueObject, 9);
  6440. const oldBattleFastKey = Game.PlayerSubscriptionInfoValueObject.prototype[PSIVO_9];
  6441. Game.PlayerSubscriptionInfoValueObject.prototype[PSIVO_9] = function () {
  6442. //const BGM_42 = getProtoFn(Game.BattleGuiMediator, 42);
  6443. //const oldBattleFastKey = Game.BattleGuiMediator.prototype[BGM_42];
  6444. //Game.BattleGuiMediator.prototype[BGM_42] = function () {
  6445. let flag = true;
  6446. //console.log(flag)
  6447. if (flag) {
  6448. return true;
  6449. } else {
  6450. return oldBattleFastKey.call(this);
  6451. }
  6452. /*
  6453. if (!flag) {
  6454. return oldBattleFastKey.call(this);
  6455. }
  6456. try {
  6457. const BGM_9 = getProtoFn(Game.BattleGuiMediator, 9);
  6458. const BGM_10 = getProtoFn(Game.BattleGuiMediator, 10);
  6459. const BPW_0 = getProtoFn(Game.BooleanPropertyWriteable, 0);
  6460. this[BGM_9][BPW_0](true);
  6461. this[BGM_10][BPW_0](true);
  6462. } catch (error) {
  6463. console.error(error);
  6464. return oldBattleFastKey.call(this);
  6465. }*/
  6466. }
  6467. },
  6468. /* ТЕСТ 2.240
  6469. battleFastKey: function () {
  6470. const BGM_43 = getProtoFn(Game.BattleGuiMediator, 43);
  6471. const oldBattleFastKey = Game.BattleGuiMediator.prototype[BGM_43];
  6472. Game.BattleGuiMediator.prototype[BGM_43] = function () {
  6473. let flag = true;
  6474. //console.log(flag)
  6475. if (!flag) {
  6476. return oldBattleFastKey.call(this);
  6477. }
  6478. try {
  6479. const BGM_9 = getProtoFn(Game.BattleGuiMediator, 9);
  6480. const BGM_10 = getProtoFn(Game.BattleGuiMediator, 10);
  6481. const BPW_0 = getProtoFn(Game.BooleanPropertyWriteable, 0);
  6482. this[BGM_9][BPW_0](true);
  6483. this[BGM_10][BPW_0](true);
  6484. } catch (error) {
  6485. console.error(error);
  6486. return oldBattleFastKey.call(this);
  6487. }
  6488. }
  6489. },*/
  6490. fastSeason: function () {
  6491. const GameNavigator = selfGame["game.screen.navigator.GameNavigator"];
  6492. const oldFuncName = getProtoFn(GameNavigator, 16);
  6493. const newFuncName = getProtoFn(GameNavigator, 14);
  6494. const oldFastSeason = GameNavigator.prototype[oldFuncName];
  6495. const newFastSeason = GameNavigator.prototype[newFuncName];
  6496. GameNavigator.prototype[oldFuncName] = function (a, b) {
  6497. if (isChecked('fastSeason')) {
  6498. return newFastSeason.apply(this, [a]);
  6499. } else {
  6500. return oldFastSeason.apply(this, [a, b]);
  6501. }
  6502. }
  6503. },
  6504. ShowChestReward: function () {
  6505. const TitanArtifactChest = selfGame["game.mechanics.titan_arena.mediator.chest.TitanArtifactChestRewardPopupMediator"];
  6506. const getOpenAmountTitan = getF(TitanArtifactChest, "get_openAmount");
  6507. const oldGetOpenAmountTitan = TitanArtifactChest.prototype[getOpenAmountTitan];
  6508. TitanArtifactChest.prototype[getOpenAmountTitan] = function () {
  6509. if (correctShowOpenArtifact) {
  6510. correctShowOpenArtifact--;
  6511. return 100;
  6512. }
  6513. return oldGetOpenAmountTitan.call(this);
  6514. }
  6515.  
  6516. const ArtifactChest = selfGame["game.view.popup.artifactchest.rewardpopup.ArtifactChestRewardPopupMediator"];
  6517. const getOpenAmount = getF(ArtifactChest, "get_openAmount");
  6518. const oldGetOpenAmount = ArtifactChest.prototype[getOpenAmount];
  6519. ArtifactChest.prototype[getOpenAmount] = function () {
  6520. if (correctShowOpenArtifact) {
  6521. correctShowOpenArtifact--;
  6522. return 100;
  6523. }
  6524. return oldGetOpenAmount.call(this);
  6525. }
  6526.  
  6527. },
  6528. fixCompany: function () {
  6529. const GameBattleView = selfGame["game.mediator.gui.popup.battle.GameBattleView"];
  6530. const BattleThread = selfGame["game.battle.controller.thread.BattleThread"];
  6531. const getOnViewDisposed = getF(BattleThread, 'get_onViewDisposed');
  6532. const getThread = getF(GameBattleView, 'get_thread');
  6533. const oldFunc = GameBattleView.prototype[getThread];
  6534. GameBattleView.prototype[getThread] = function () {
  6535. return oldFunc.call(this) || {
  6536. [getOnViewDisposed]: async () => { }
  6537. }
  6538. }
  6539. }
  6540. }
  6541.  
  6542. /**
  6543. * Starts replacing recorded functions
  6544. *
  6545. * Запускает замену записанных функций
  6546. */
  6547. this.activateHacks = function () {
  6548. if (!selfGame) throw Error('Use connectGame');
  6549. for (let func in replaceFunction) {
  6550. replaceFunction[func]();
  6551. }
  6552. }
  6553.  
  6554. /**
  6555. * Returns the game object
  6556. *
  6557. * Возвращает объект игры
  6558. */
  6559. this.getSelfGame = function () {
  6560. return selfGame;
  6561. }
  6562.  
  6563. /**
  6564. * Updates game data
  6565. *
  6566. * Обновляет данные игры
  6567. */
  6568. this.refreshGame = function () {
  6569. (new Game.NextDayUpdatedManager)[getProtoFn(Game.NextDayUpdatedManager, 5)]();
  6570. try {
  6571. cheats.refreshInventory();
  6572. } catch (e) { }
  6573. }
  6574.  
  6575. /**
  6576. * Update inventory
  6577. *
  6578. * Обновляет инвентарь
  6579. */
  6580. this.refreshInventory = async function () {
  6581. const GM_INST = getFnP(Game.GameModel, "get_instance");
  6582. const GM_0 = getProtoFn(Game.GameModel, 0);
  6583. const P_24 = getProtoFn(selfGame["game.model.user.Player"], 24);
  6584. const Player = Game.GameModel[GM_INST]()[GM_0];
  6585. Player[P_24] = new selfGame["game.model.user.inventory.PlayerInventory"]
  6586. Player[P_24].init(await Send('{"calls":[{"name":"inventoryGet","args":{},"ident":"inventoryGet"}]}').then(e => e.results[0].result.response))
  6587. }
  6588.  
  6589. /**
  6590. * Change the play screen on windowName
  6591. *
  6592. * Сменить экран игры на windowName
  6593. *
  6594. * Possible options:
  6595. *
  6596. * Возможные варианты:
  6597. *
  6598. * 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
  6599. */
  6600. this.goNavigtor = function (windowName) {
  6601. let mechanicStorage = selfGame["game.data.storage.mechanic.MechanicStorage"];
  6602. let window = mechanicStorage[windowName];
  6603. let event = new selfGame["game.mediator.gui.popup.PopupStashEventParams"];
  6604. let Game = selfGame['Game'];
  6605. let navigator = getF(Game, "get_navigator")
  6606. let navigate = getProtoFn(selfGame["game.screen.navigator.GameNavigator"], 18)
  6607. let instance = getFnP(Game, 'get_instance');
  6608. Game[instance]()[navigator]()[navigate](window, event);
  6609. }
  6610.  
  6611. /**
  6612. * Move to the sanctuary cheats.goSanctuary()
  6613. *
  6614. * Переместиться в святилище cheats.goSanctuary()
  6615. */
  6616. this.goSanctuary = () => {
  6617. this.goNavigtor("SANCTUARY");
  6618. }
  6619.  
  6620. /**
  6621. * Go to Guild War
  6622. *
  6623. * Перейти к Войне Гильдий
  6624. */
  6625. this.goClanWar = function() {
  6626. let instance = getFnP(Game.GameModel, 'get_instance')
  6627. let player = Game.GameModel[instance]().A;
  6628. let clanWarSelect = selfGame["game.mechanics.cross_clan_war.popup.selectMode.CrossClanWarSelectModeMediator"];
  6629. new clanWarSelect(player).open();
  6630. }
  6631.  
  6632. /**
  6633. * Go to BrawlShop
  6634. *
  6635. * Переместиться в BrawlShop
  6636. */
  6637. this.goBrawlShop = () => {
  6638. const instance = getFnP(Game.GameModel, 'get_instance')
  6639. const P_36 = getProtoFn(selfGame["game.model.user.Player"], 36);
  6640. const PSD_0 = getProtoFn(selfGame["game.model.user.shop.PlayerShopData"], 0);
  6641. const IM_0 = getProtoFn(selfGame["haxe.ds.IntMap"], 0);
  6642. const PSDE_4 = getProtoFn(selfGame["game.model.user.shop.PlayerShopDataEntry"], 4);
  6643.  
  6644. const player = Game.GameModel[instance]().A;
  6645. const shop = player[P_36][PSD_0][IM_0][1038][PSDE_4];
  6646. const shopPopup = new selfGame["game.mechanics.brawl.mediator.BrawlShopPopupMediator"](player, shop)
  6647. shopPopup.open(new selfGame["game.mediator.gui.popup.PopupStashEventParams"])
  6648. }
  6649.  
  6650. /**
  6651. * Returns all stores from game data
  6652. *
  6653. * Возвращает все магазины из данных игры
  6654. */
  6655. this.getShops = () => {
  6656. const instance = getFnP(Game.GameModel, 'get_instance')
  6657. const P_36 = getProtoFn(selfGame["game.model.user.Player"], 36);
  6658. const PSD_0 = getProtoFn(selfGame["game.model.user.shop.PlayerShopData"], 0);
  6659. const IM_0 = getProtoFn(selfGame["haxe.ds.IntMap"], 0);
  6660.  
  6661. const player = Game.GameModel[instance]().A;
  6662. return player[P_36][PSD_0][IM_0];
  6663. }
  6664.  
  6665. /**
  6666. * Returns the store from the game data by ID
  6667. *
  6668. * Возвращает магазин из данных игры по идетификатору
  6669. */
  6670. this.getShop = (id) => {
  6671. const PSDE_4 = getProtoFn(selfGame["game.model.user.shop.PlayerShopDataEntry"], 4);
  6672. const shops = this.getShops();
  6673. const shop = shops[id]?.[PSDE_4];
  6674. return shop;
  6675. }
  6676. /**
  6677. * Moves to the store with the specified ID
  6678. *
  6679. * Перемещает к магазину с указанным идетификатором
  6680. */
  6681. this.goShopId = function (id) {
  6682. const shop = this.getShop(id);
  6683. if (!shop) {
  6684. return;
  6685. }
  6686. let event = new selfGame["game.mediator.gui.popup.PopupStashEventParams"];
  6687. let Game = selfGame['Game'];
  6688. let navigator = getF(Game, "get_navigator");
  6689. let navigate = getProtoFn(selfGame["game.screen.navigator.GameNavigator"], 21);
  6690. let instance = getFnP(Game, 'get_instance');
  6691. Game[instance]()[navigator]()[navigate](shop, event);
  6692. }
  6693. /**
  6694. * Opens a list of non-standard stores
  6695. *
  6696. * Открывает список не стандартных магазинов
  6697. */
  6698. this.goCustomShops = async (p = 0) => {
  6699. /** Запрос данных нужных магазинов */
  6700. const calls = [{ name: "shopGetAll", args: {}, ident: "shopGetAll" }];
  6701. const shops = lib.getData('shop');
  6702. for (const id in shops) {
  6703. const check = !shops[id].ident.includes('merchantPromo') &&
  6704. ![1, 4, 5, 6, 7, 8, 9, 10, 11, 1023, 1024].includes(+id);
  6705. if (check) {
  6706. calls.push({
  6707. name: "shopGet", args: { shopId: id }, ident: `shopGet_${id}`
  6708. })
  6709. }
  6710. }
  6711. const result = await Send({ calls }).then(e => e.results.map(n => n.result.response));
  6712. const shopAll = result.shift();
  6713. const DS_32 = getFn(Game.DataStorage, 32)
  6714. const SDS_5 = getProtoFn(selfGame["game.data.storage.shop.ShopDescriptionStorage"], 5)
  6715. const SD_21 = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 21);
  6716. const SD_1 = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 1);
  6717. const SD_9 = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 9);
  6718. const ident = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 11);
  6719. for (let shop of result) {
  6720. shopAll[shop.id] = shop;
  6721. // Снимаем все ограничения с магазинов
  6722. const shopLibData = Game.DataStorage[DS_32][SDS_5](shop.id)
  6723. shopLibData[SD_21] = 1;
  6724. shopLibData[SD_1] = new selfGame["game.model.user.requirement.Requirement"]
  6725. shopLibData[SD_9] = new selfGame["game.data.storage.level.LevelRequirement"]({
  6726. teamLevel: 10
  6727. });
  6728. }
  6729. /** Скрываем все остальные магазины */
  6730. for (let id in shops) {
  6731. const shopLibData = Game.DataStorage[DS_32][SDS_5](id)
  6732. if (shopLibData[ident].includes('merchantPromo')) {
  6733. shopLibData[SD_21] = 0;
  6734. shopLibData[SD_9] = new selfGame["game.data.storage.level.LevelRequirement"]({
  6735. teamLevel: 999
  6736. });
  6737. }
  6738. }
  6739. const instance = getFnP(Game.GameModel, 'get_instance')
  6740. const GM_0 = getProtoFn(Game.GameModel, 0);
  6741. const P_36 = getProtoFn(selfGame["game.model.user.Player"], 36);
  6742. const player = Game.GameModel[instance]()[GM_0];
  6743. /** Пересоздаем объект с магазинами */
  6744. player[P_36] = new selfGame["game.model.user.shop.PlayerShopData"](player);
  6745. player[P_36].init(shopAll);
  6746. /** Даем магазинам новые названия */
  6747. const PSDE_4 = getProtoFn(selfGame["game.model.user.shop.PlayerShopDataEntry"], 4);
  6748. const shopName = getFn(cheats.getShop(1), 14);
  6749. const currentShops = this.getShops();
  6750. let count = 0;
  6751. const start = 9 * p + 1;
  6752. const end = start + 8;
  6753. for (let id in currentShops) {
  6754. const shop = currentShops[id][PSDE_4];
  6755. if ([1, 4, 5, 6, 8, 9, 10, 11].includes(+id)) {
  6756. /** Скрываем стандартные магазины */
  6757. shop[SD_21] = 0;
  6758. } else {
  6759. count++;
  6760. if (count < start || count > end) {
  6761. shop[SD_21] = 0;
  6762. continue;
  6763. }
  6764. shop[SD_21] = 1;
  6765. shop[shopName] = cheats.translate("LIB_SHOP_NAME_" + id) + ' ' + id;
  6766. shop[SD_1] = new selfGame["game.model.user.requirement.Requirement"]
  6767. shop[SD_9] = new selfGame["game.data.storage.level.LevelRequirement"]({
  6768. teamLevel: 10
  6769. });
  6770. }
  6771. }
  6772. console.log(count, start, end)
  6773. /** Отправляемся в городскую лавку */
  6774. this.goShopId(1);
  6775. }
  6776. /**
  6777. * Opens a list of standard stores
  6778. *
  6779. * Открывает список стандартных магазинов
  6780. */
  6781. this.goDefaultShops = async () => {
  6782. const result = await Send({ calls: [{ name: "shopGetAll", args: {}, ident: "shopGetAll" }] })
  6783. .then(e => e.results.map(n => n.result.response));
  6784. const shopAll = result.shift();
  6785. const shops = lib.getData('shop');
  6786. const DS_8 = getFn(Game.DataStorage, 8)
  6787. const DSB_4 = getProtoFn(selfGame["game.data.storage.DescriptionStorageBase"], 4)
  6788. /** Получаем объект валюты магазина для оторажения */
  6789. const coins = Game.DataStorage[DS_8][DSB_4](85);
  6790. coins.__proto__ = selfGame["game.data.storage.resource.ConsumableDescription"].prototype;
  6791. const DS_32 = getFn(Game.DataStorage, 32)
  6792. const SDS_5 = getProtoFn(selfGame["game.data.storage.shop.ShopDescriptionStorage"], 5)
  6793. const SD_21 = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 21);
  6794. for (const id in shops) {
  6795. const shopLibData = Game.DataStorage[DS_32][SDS_5](id)
  6796. if ([1, 4, 5, 6, 8, 9, 10, 11].includes(+id)) {
  6797. shopLibData[SD_21] = 1;
  6798. } else {
  6799. shopLibData[SD_21] = 0;
  6800. }
  6801. }
  6802. const instance = getFnP(Game.GameModel, 'get_instance')
  6803. const GM_0 = getProtoFn(Game.GameModel, 0);
  6804. const P_36 = getProtoFn(selfGame["game.model.user.Player"], 36);
  6805. const player = Game.GameModel[instance]()[GM_0];
  6806. /** Пересоздаем объект с магазинами */
  6807. player[P_36] = new selfGame["game.model.user.shop.PlayerShopData"](player);
  6808. player[P_36].init(shopAll);
  6809. const PSDE_4 = getProtoFn(selfGame["game.model.user.shop.PlayerShopDataEntry"], 4);
  6810. const currentShops = this.getShops();
  6811. for (let id in currentShops) {
  6812. const shop = currentShops[id][PSDE_4];
  6813. if ([1, 4, 5, 6, 8, 9, 10, 11].includes(+id)) {
  6814. shop[SD_21] = 1;
  6815. } else {
  6816. shop[SD_21] = 0;
  6817. }
  6818. }
  6819. this.goShopId(1);
  6820. }
  6821. /**
  6822. * Opens a list of Secret Wealth stores
  6823. *
  6824. * Открывает список магазинов Тайное богатство
  6825. */
  6826. this.goSecretWealthShops = async () => {
  6827. /** Запрос данных нужных магазинов */
  6828. const calls = [{ name: "shopGetAll", args: {}, ident: "shopGetAll" }];
  6829. const shops = lib.getData('shop');
  6830. for (const id in shops) {
  6831. if (shops[id].ident.includes('merchantPromo') && shops[id].teamLevelToUnlock <= 130) {
  6832. calls.push({
  6833. name: "shopGet", args: { shopId: id }, ident: `shopGet_${id}`
  6834. })
  6835. }
  6836. }
  6837. const result = await Send({ calls }).then(e => e.results.map(n => n.result.response));
  6838. const shopAll = result.shift();
  6839. const DS_32 = getFn(Game.DataStorage, 32)
  6840. const SDS_5 = getProtoFn(selfGame["game.data.storage.shop.ShopDescriptionStorage"], 5)
  6841. const SD_21 = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 21);
  6842. const SD_1 = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 1);
  6843. const SD_9 = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 9);
  6844. const ident = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 11);
  6845. const specialCurrency = getProtoFn(selfGame["game.data.storage.shop.ShopDescription"], 15);
  6846. const DS_8 = getFn(Game.DataStorage, 8)
  6847. const DSB_4 = getProtoFn(selfGame["game.data.storage.DescriptionStorageBase"], 4)
  6848. /** Получаем объект валюты магазина для оторажения */
  6849. const coins = Game.DataStorage[DS_8][DSB_4](85);
  6850. coins.__proto__ = selfGame["game.data.storage.resource.CoinDescription"].prototype;
  6851. for (let shop of result) {
  6852. shopAll[shop.id] = shop;
  6853. /** Снимаем все ограничения с магазинов */
  6854. const shopLibData = Game.DataStorage[DS_32][SDS_5](shop.id)
  6855. if (shopLibData[ident].includes('merchantPromo')) {
  6856. shopLibData[SD_21] = 1;
  6857. shopLibData[SD_1] = new selfGame["game.model.user.requirement.Requirement"]
  6858. shopLibData[SD_9] = new selfGame["game.data.storage.level.LevelRequirement"]({
  6859. teamLevel: 10
  6860. });
  6861. }
  6862. }
  6863. /** Скрываем все остальные магазины */
  6864. for (let id in shops) {
  6865. const shopLibData = Game.DataStorage[DS_32][SDS_5](id)
  6866. if (!shopLibData[ident].includes('merchantPromo')) {
  6867. shopLibData[SD_21] = 0;
  6868. }
  6869. }
  6870. const instance = getFnP(Game.GameModel, 'get_instance')
  6871. const GM_0 = getProtoFn(Game.GameModel, 0);
  6872. const P_36 = getProtoFn(selfGame["game.model.user.Player"], 36);
  6873. const player = Game.GameModel[instance]()[GM_0];
  6874. /** Пересоздаем объект с магазинами */
  6875. player[P_36] = new selfGame["game.model.user.shop.PlayerShopData"](player);
  6876. player[P_36].init(shopAll);
  6877. /** Даем магазинам новые названия */
  6878. const PSDE_4 = getProtoFn(selfGame["game.model.user.shop.PlayerShopDataEntry"], 4);
  6879. const shopName = getFn(cheats.getShop(1), 14);
  6880. const currentShops = this.getShops();
  6881. for (let id in currentShops) {
  6882. const shop = currentShops[id][PSDE_4];
  6883. if (shop[ident].includes('merchantPromo')) {
  6884. shop[SD_21] = 1;
  6885. shop[specialCurrency] = coins;
  6886. shop[shopName] = cheats.translate("LIB_SHOP_NAME_" + id) + ' ' + id;
  6887. } else if ([1, 4, 5, 6, 8, 9, 10, 11].includes(+id)) {
  6888. /** Скрываем стандартные магазины */
  6889. shop[SD_21] = 0;
  6890. }
  6891. }
  6892. /** Отправляемся в городскую лавку */
  6893. this.goShopId(1);
  6894. }
  6895. /**
  6896. * Change island map
  6897. *
  6898. * Сменить карту острова
  6899. */
  6900. this.changeIslandMap = (mapId = 2) => {
  6901. const GameInst = getFnP(selfGame['Game'], 'get_instance');
  6902. const GM_0 = getProtoFn(Game.GameModel, 0);
  6903. const P_59 = getProtoFn(selfGame["game.model.user.Player"], 59);
  6904. const Player = Game.GameModel[GameInst]()[GM_0];
  6905. Player[P_59].$({ id: mapId, seasonAdventure: { id: mapId, startDate: 1701914400, endDate: 1709690400, closed: false } });
  6906.  
  6907. const GN_15 = getProtoFn(selfGame["game.screen.navigator.GameNavigator"], 15)
  6908. const navigator = getF(selfGame['Game'], "get_navigator");
  6909. selfGame['Game'][GameInst]()[navigator]()[GN_15](new selfGame["game.mediator.gui.popup.PopupStashEventParams"]);
  6910. }
  6911.  
  6912. /**
  6913. * Game library availability tracker
  6914. *
  6915. * Отслеживание доступности игровой библиотеки
  6916. */
  6917. function checkLibLoad() {
  6918. timeout = setTimeout(() => {
  6919. if (Game.GameModel) {
  6920. changeLib();
  6921. } else {
  6922. checkLibLoad();
  6923. }
  6924. }, 100)
  6925. }
  6926.  
  6927. /**
  6928. * Game library data spoofing
  6929. *
  6930. * Подмена данных игровой библиотеки
  6931. */
  6932. function changeLib() {
  6933. console.log('lib connect');
  6934. const originalStartFunc = Game.GameModel.prototype.start;
  6935. Game.GameModel.prototype.start = function (a, b, c) {
  6936. self.libGame = b.raw;
  6937. try {
  6938. const levels = b.raw.seasonAdventure.level;
  6939. for (const id in levels) {
  6940. const level = levels[id];
  6941. level.clientData.graphics.fogged = level.clientData.graphics.visible
  6942. }
  6943. } catch (e) {
  6944. console.warn(e);
  6945. }
  6946. originalStartFunc.call(this, a, b, c);
  6947. }
  6948. }
  6949.  
  6950. /**
  6951. * Returns the value of a language constant
  6952. *
  6953. * Возвращает значение языковой константы
  6954. * @param {*} langConst language constant // языковая константа
  6955. * @returns
  6956. */
  6957. this.translate = function (langConst) {
  6958. return Game.Translate.translate(langConst);
  6959. }
  6960.  
  6961. connectGame();
  6962. checkLibLoad();
  6963. }
  6964.  
  6965. /**
  6966. * Auto collection of gifts
  6967. *
  6968. * Автосбор подарков
  6969. */
  6970. function getAutoGifts() {
  6971. let valName = 'giftSendIds_' + userInfo.id;
  6972.  
  6973. if (!localStorage['clearGift' + userInfo.id]) {
  6974. localStorage[valName] = '';
  6975. localStorage['clearGift' + userInfo.id] = '+';
  6976. }
  6977.  
  6978. if (!localStorage[valName]) {
  6979. localStorage[valName] = '';
  6980. }
  6981.  
  6982. const now = Date.now();
  6983. const body = JSON.stringify({ now });
  6984. const signature = window['\x73\x69\x67\x6e'](now);
  6985. /**
  6986. * Submit a request to receive gift codes
  6987. *
  6988. * Отправка запроса для получения кодов подарков
  6989. */
  6990. fetch('https://zingery.ru/heroes/getGifts.php', {
  6991. method: 'POST',
  6992. headers: {
  6993. 'X-Request-Signature': signature,
  6994. 'X-Script-Name': GM_info.script.name,
  6995. 'X-Script-Version': GM_info.script.version,
  6996. 'X-Script-Author': GM_info.script.author,
  6997. },
  6998. body
  6999. }).then(
  7000. response => response.json()
  7001. ).then(
  7002. data => {
  7003. let freebieCheckCalls = {
  7004. calls: []
  7005. }
  7006. data.forEach((giftId, n) => {
  7007. if (localStorage[valName].includes(giftId)) return;
  7008. freebieCheckCalls.calls.push({
  7009. name: "registration",
  7010. args: {
  7011. user: { referrer: {} },
  7012. giftId
  7013. },
  7014. context: {
  7015. actionTs: Math.floor(performance.now()),
  7016. cookie: window?.NXAppInfo?.session_id || null
  7017. },
  7018. ident: giftId
  7019. });
  7020. });
  7021.  
  7022. if (!freebieCheckCalls.calls.length) {
  7023. return;
  7024. }
  7025.  
  7026. send(JSON.stringify(freebieCheckCalls), e => {
  7027. let countGetGifts = 0;
  7028. const gifts = [];
  7029. for (check of e.results) {
  7030. gifts.push(check.ident);
  7031. if (check.result.response != null) {
  7032. countGetGifts++;
  7033. }
  7034. }
  7035. const saveGifts = localStorage[valName].split(';');
  7036. localStorage[valName] = [...saveGifts, ...gifts].slice(-50).join(';');
  7037. console.log(`${I18N('GIFTS')}: ${countGetGifts}`);
  7038. });
  7039. }
  7040. )
  7041. }
  7042.  
  7043. /**
  7044. * To fill the kills in the Forge of Souls
  7045. *
  7046. * Набить килов в горниле душ
  7047. */
  7048. async function bossRatingEvent() {
  7049. const topGet = await Send(JSON.stringify({ calls: [{ name: "topGet", args: { type: "bossRatingTop", extraId: 0 }, ident: "body" }] }));
  7050. if (!topGet || !topGet.results[0].result.response[0]) {
  7051. setProgress(`${I18N('EVENT')} ${I18N('NOT_AVAILABLE')}`, true);
  7052. return;
  7053. }
  7054. const replayId = topGet.results[0].result.response[0].userData.replayId;
  7055. const result = await Send(JSON.stringify({
  7056. calls: [
  7057. { name: "battleGetReplay", args: { id: replayId }, ident: "battleGetReplay" },
  7058. { name: "heroGetAll", args: {}, ident: "heroGetAll" },
  7059. { name: "pet_getAll", args: {}, ident: "pet_getAll" },
  7060. { name: "offerGetAll", args: {}, ident: "offerGetAll" }
  7061. ]
  7062. }));
  7063. const bossEventInfo = result.results[3].result.response.find(e => e.offerType == "bossEvent");
  7064. if (!bossEventInfo) {
  7065. setProgress(`${I18N('EVENT')} ${I18N('NOT_AVAILABLE')}`, true);
  7066. return;
  7067. }
  7068. const usedHeroes = bossEventInfo.progress.usedHeroes;
  7069. const party = Object.values(result.results[0].result.response.replay.attackers);
  7070. const availableHeroes = Object.values(result.results[1].result.response).map(e => e.id);
  7071. const availablePets = Object.values(result.results[2].result.response).map(e => e.id);
  7072. const calls = [];
  7073. /**
  7074. * First pack
  7075. *
  7076. * Первая пачка
  7077. */
  7078. const args = {
  7079. heroes: [],
  7080. favor: {}
  7081. }
  7082. for (let hero of party) {
  7083. if (hero.id >= 6000 && availablePets.includes(hero.id)) {
  7084. args.pet = hero.id;
  7085. continue;
  7086. }
  7087. if (!availableHeroes.includes(hero.id) || usedHeroes.includes(hero.id)) {
  7088. continue;
  7089. }
  7090. args.heroes.push(hero.id);
  7091. if (hero.favorPetId) {
  7092. args.favor[hero.id] = hero.favorPetId;
  7093. }
  7094. }
  7095. if (args.heroes.length) {
  7096. calls.push({
  7097. name: "bossRatingEvent_startBattle",
  7098. args,
  7099. ident: "body_0"
  7100. });
  7101. }
  7102. /**
  7103. * Other packs
  7104. *
  7105. * Другие пачки
  7106. */
  7107. let heroes = [];
  7108. let count = 1;
  7109. while (heroId = availableHeroes.pop()) {
  7110. if (args.heroes.includes(heroId) || usedHeroes.includes(heroId)) {
  7111. continue;
  7112. }
  7113. heroes.push(heroId);
  7114. if (heroes.length == 5) {
  7115. calls.push({
  7116. name: "bossRatingEvent_startBattle",
  7117. args: {
  7118. heroes: [...heroes],
  7119. pet: availablePets[Math.floor(Math.random() * availablePets.length)]
  7120. },
  7121. ident: "body_" + count
  7122. });
  7123. heroes = [];
  7124. count++;
  7125. }
  7126. }
  7127.  
  7128. if (!calls.length) {
  7129. setProgress(`${I18N('NO_HEROES')}`, true);
  7130. return;
  7131. }
  7132.  
  7133. const resultBattles = await Send(JSON.stringify({ calls }));
  7134. console.log(resultBattles);
  7135. rewardBossRatingEvent();
  7136. }
  7137.  
  7138. /**
  7139. * Collecting Rewards from the Forge of Souls
  7140. *
  7141. * Сбор награды из Горнила Душ
  7142. */
  7143. function rewardBossRatingEvent() {
  7144. let rewardBossRatingCall = '{"calls":[{"name":"offerGetAll","args":{},"ident":"offerGetAll"}]}';
  7145. send(rewardBossRatingCall, function (data) {
  7146. let bossEventInfo = data.results[0].result.response.find(e => e.offerType == "bossEvent");
  7147. if (!bossEventInfo) {
  7148. setProgress(`${I18N('EVENT')} ${I18N('NOT_AVAILABLE')}`, true);
  7149. return;
  7150. }
  7151.  
  7152. let farmedChests = bossEventInfo.progress.farmedChests;
  7153. let score = bossEventInfo.progress.score;
  7154. setProgress(`${I18N('DAMAGE_AMOUNT')}: ${score}`);
  7155. let revard = bossEventInfo.reward;
  7156.  
  7157. let getRewardCall = {
  7158. calls: []
  7159. }
  7160.  
  7161. let count = 0;
  7162. for (let i = 1; i < 10; i++) {
  7163. if (farmedChests.includes(i)) {
  7164. continue;
  7165. }
  7166. if (score < revard[i].score) {
  7167. break;
  7168. }
  7169. getRewardCall.calls.push({
  7170. name: "bossRatingEvent_getReward",
  7171. args: {
  7172. rewardId: i
  7173. },
  7174. ident: "body_" + i
  7175. });
  7176. count++;
  7177. }
  7178. if (!count) {
  7179. setProgress(`${I18N('NOTHING_TO_COLLECT')}`, true);
  7180. return;
  7181. }
  7182.  
  7183. send(JSON.stringify(getRewardCall), e => {
  7184. console.log(e);
  7185. setProgress(`${I18N('COLLECTED')} ${e?.results?.length} ${I18N('REWARD')}`, true);
  7186. });
  7187. });
  7188. }
  7189.  
  7190. /**
  7191. * Collect Easter eggs and event rewards
  7192. *
  7193. * Собрать пасхалки и награды событий
  7194. */
  7195. function offerFarmAllReward() {
  7196. const offerGetAllCall = '{"calls":[{"name":"offerGetAll","args":{},"ident":"offerGetAll"}]}';
  7197. return Send(offerGetAllCall).then((data) => {
  7198. const offerGetAll = data.results[0].result.response.filter(e => e.type == "reward" && !e?.freeRewardObtained && e.reward);
  7199. if (!offerGetAll.length) {
  7200. setProgress(`${I18N('NOTHING_TO_COLLECT')}`, true);
  7201. return;
  7202. }
  7203.  
  7204. const calls = [];
  7205. for (let reward of offerGetAll) {
  7206. calls.push({
  7207. name: "offerFarmReward",
  7208. args: {
  7209. offerId: reward.id
  7210. },
  7211. ident: "offerFarmReward_" + reward.id
  7212. });
  7213. }
  7214.  
  7215. return Send(JSON.stringify({ calls })).then(e => {
  7216. console.log(e);
  7217. setProgress(`${I18N('COLLECTED')} ${e?.results?.length} ${I18N('REWARD')}`, true);
  7218. });
  7219. });
  7220. }
  7221.  
  7222. /**
  7223. * Assemble Outland
  7224. *
  7225. * Собрать запределье
  7226. */
  7227. function getOutland() {
  7228. return new Promise(function (resolve, reject) {
  7229. send('{"calls":[{"name":"bossGetAll","args":{},"ident":"bossGetAll"}]}', e => {
  7230. let bosses = e.results[0].result.response;
  7231.  
  7232. let bossRaidOpenChestCall = {
  7233. calls: []
  7234. };
  7235.  
  7236. for (let boss of bosses) {
  7237. if (boss.mayRaid) {
  7238. bossRaidOpenChestCall.calls.push({
  7239. name: "bossRaid",
  7240. args: {
  7241. bossId: boss.id
  7242. },
  7243. ident: "bossRaid_" + boss.id
  7244. });
  7245. bossRaidOpenChestCall.calls.push({
  7246. name: "bossOpenChest",
  7247. args: {
  7248. bossId: boss.id,
  7249. amount: 1,
  7250. starmoney: 0
  7251. },
  7252. ident: "bossOpenChest_" + boss.id
  7253. });
  7254. } else if (boss.chestId == 1) {
  7255. bossRaidOpenChestCall.calls.push({
  7256. name: "bossOpenChest",
  7257. args: {
  7258. bossId: boss.id,
  7259. amount: 1,
  7260. starmoney: 0
  7261. },
  7262. ident: "bossOpenChest_" + boss.id
  7263. });
  7264. }
  7265. }
  7266.  
  7267. if (!bossRaidOpenChestCall.calls.length) {
  7268. setProgress(`${I18N('OUTLAND')} ${I18N('NOTHING_TO_COLLECT')}`, true);
  7269. resolve();
  7270. return;
  7271. }
  7272.  
  7273. send(JSON.stringify(bossRaidOpenChestCall), e => {
  7274. setProgress(`${I18N('OUTLAND')} ${I18N('COLLECTED')}`, true);
  7275. resolve();
  7276. });
  7277. });
  7278. });
  7279. }
  7280.  
  7281. /**
  7282. * Collect all rewards
  7283. *
  7284. * Собрать все награды
  7285. */
  7286. function questAllFarm() {
  7287. return new Promise(function (resolve, reject) {
  7288. let questGetAllCall = {
  7289. calls: [{
  7290. name: "questGetAll",
  7291. args: {},
  7292. ident: "body"
  7293. }]
  7294. }
  7295. send(JSON.stringify(questGetAllCall), function (data) {
  7296. let questGetAll = data.results[0].result.response;
  7297. const questAllFarmCall = {
  7298. calls: []
  7299. }
  7300. let number = 0;
  7301. for (let quest of questGetAll) {
  7302. if (quest.id < 1e6 && quest.state == 2) {
  7303. questAllFarmCall.calls.push({
  7304. name: "questFarm",
  7305. args: {
  7306. questId: quest.id
  7307. },
  7308. ident: `group_${number}_body`
  7309. });
  7310. number++;
  7311. }
  7312. }
  7313.  
  7314. if (!questAllFarmCall.calls.length) {
  7315. setProgress(`${I18N('COLLECTED')} ${number} ${I18N('REWARD')}`, true);
  7316. resolve();
  7317. return;
  7318. }
  7319.  
  7320. send(JSON.stringify(questAllFarmCall), function (res) {
  7321. console.log(res);
  7322. setProgress(`${I18N('COLLECTED')} ${number} ${I18N('REWARD')}`, true);
  7323. resolve();
  7324. });
  7325. });
  7326. })
  7327. }
  7328.  
  7329. /**
  7330. * Mission auto repeat
  7331. *
  7332. * Автоповтор миссии
  7333. * isStopSendMission = false;
  7334. * isSendsMission = true;
  7335. **/
  7336. this.sendsMission = async function (param) {
  7337. if (isStopSendMission) {
  7338. isSendsMission = false;
  7339. console.log(I18N('STOPPED'));
  7340. setProgress('');
  7341. await popup.confirm(`${I18N('STOPPED')}<br>${I18N('REPETITIONS')}: ${param.count}`, [{
  7342. msg: 'Ok',
  7343. result: true
  7344. }, ])
  7345. return;
  7346. }
  7347. lastMissionBattleStart = Date.now();
  7348. let missionStartCall = {
  7349. "calls": [{
  7350. "name": "missionStart",
  7351. "args": lastMissionStart,
  7352. "ident": "body"
  7353. }]
  7354. }
  7355. /**
  7356. * Mission Request
  7357. *
  7358. * Запрос на выполнение мисcии
  7359. */
  7360. SendRequest(JSON.stringify(missionStartCall), async e => {
  7361. if (e['error']) {
  7362. isSendsMission = false;
  7363. console.log(e['error']);
  7364. setProgress('');
  7365. let msg = e['error'].name + ' ' + e['error'].description + `<br>${I18N('REPETITIONS')}: ${param.count}`;
  7366. await popup.confirm(msg, [
  7367. {msg: 'Ok', result: true},
  7368. ])
  7369. return;
  7370. }
  7371. /**
  7372. * Mission data calculation
  7373. *
  7374. * Расчет данных мисcии
  7375. */
  7376. BattleCalc(e.results[0].result.response, 'get_tower', async r => {
  7377. /** missionTimer */
  7378. let timer = getTimer(r.battleTime) + 5;
  7379. const period = Math.ceil((Date.now() - lastMissionBattleStart) / 1000);
  7380. if (period < timer) {
  7381. timer = timer - period;
  7382. await countdownTimer(timer, `${I18N('MISSIONS_PASSED')}: ${param.count}`);
  7383. }
  7384.  
  7385. let missionEndCall = {
  7386. "calls": [{
  7387. "name": "missionEnd",
  7388. "args": {
  7389. "id": param.id,
  7390. "result": r.result,
  7391. "progress": r.progress
  7392. },
  7393. "ident": "body"
  7394. }]
  7395. }
  7396. /**
  7397. * Mission Completion Request
  7398. *
  7399. * Запрос на завершение миссии
  7400. */
  7401. SendRequest(JSON.stringify(missionEndCall), async (e) => {
  7402. if (e['error']) {
  7403. isSendsMission = false;
  7404. console.log(e['error']);
  7405. setProgress('');
  7406. let msg = e['error'].name + ' ' + e['error'].description + `<br>${I18N('REPETITIONS')}: ${param.count}`;
  7407. await popup.confirm(msg, [
  7408. {msg: 'Ok', result: true},
  7409. ])
  7410. return;
  7411. }
  7412. r = e.results[0].result.response;
  7413. if (r['error']) {
  7414. isSendsMission = false;
  7415. console.log(r['error']);
  7416. setProgress('');
  7417. await popup.confirm(`<br>${I18N('REPETITIONS')}: ${param.count}` + ' 3 ' + r['error'], [
  7418. {msg: 'Ok', result: true},
  7419. ])
  7420. return;
  7421. }
  7422.  
  7423. param.count++;
  7424. let RaidMission = getInput('countRaid');
  7425.  
  7426. if (RaidMission==param.count){
  7427. isStopSendMission = true;
  7428. console.log(RaidMission);
  7429. }
  7430. setProgress(`${I18N('MISSIONS_PASSED')}: ${param.count} (${I18N('STOP')})`, false, () => {
  7431. isStopSendMission = true;
  7432. });
  7433. setTimeout(sendsMission, 1, param);
  7434. });
  7435. })
  7436. });
  7437. }
  7438.  
  7439. /**
  7440. * Opening of russian dolls
  7441. *
  7442. * Открытие матрешек
  7443. */
  7444. async function openRussianDolls(libId, amount) {
  7445. let sum = 0;
  7446. let sumResult = [];
  7447.  
  7448. while (amount) {
  7449. sum += amount;
  7450. setProgress(`${I18N('TOTAL_OPEN')} ${sum}`);
  7451. const calls = [{
  7452. name: "consumableUseLootBox",
  7453. args: { libId, amount },
  7454. ident: "body"
  7455. }];
  7456. const result = await Send(JSON.stringify({ calls })).then(e => e.results[0].result.response);
  7457. let newCount = 0;
  7458. for (let n of result) {
  7459. if (n?.consumable && n.consumable[libId]) {
  7460. newCount += n.consumable[libId]
  7461. }
  7462. }
  7463. sumResult = [...sumResult, ...result];
  7464. amount = newCount;
  7465. }
  7466.  
  7467. setProgress(`${I18N('TOTAL_OPEN')} ${sum}`, 5000);
  7468. return sumResult;
  7469. }
  7470.  
  7471. /**
  7472. * Collect all mail, except letters with energy and charges of the portal
  7473. *
  7474. * Собрать всю почту, кроме писем с энергией и зарядами портала
  7475. */
  7476. function mailGetAll() {
  7477. const getMailInfo = '{"calls":[{"name":"mailGetAll","args":{},"ident":"body"}]}';
  7478.  
  7479. return Send(getMailInfo).then(dataMail => {
  7480. const letters = dataMail.results[0].result.response.letters;
  7481. const letterIds = lettersFilter(letters);
  7482. if (!letterIds.length) {
  7483. setProgress(I18N('NOTHING_TO_COLLECT'), true);
  7484. return;
  7485. }
  7486.  
  7487. const calls = [
  7488. { name: "mailFarm", args: { letterIds }, ident: "body" }
  7489. ];
  7490.  
  7491. return Send(JSON.stringify({ calls })).then(res => {
  7492. const lettersIds = res.results[0].result.response;
  7493. if (lettersIds) {
  7494. const countLetters = Object.keys(lettersIds).length;
  7495. setProgress(`${I18N('RECEIVED')} ${countLetters} ${I18N('LETTERS')}`, true);
  7496. }
  7497. });
  7498. });
  7499. }
  7500.  
  7501. /**
  7502. * Filters received emails
  7503. *
  7504. * Фильтрует получаемые письма
  7505. */
  7506. function lettersFilter(letters) {
  7507. const lettersIds = [];
  7508. for (let l in letters) {
  7509. letter = letters[l];
  7510. const reward = letter.reward;
  7511. if (!reward) {
  7512. continue;
  7513. }
  7514. /**
  7515. * Mail Collection Exceptions
  7516. *
  7517. * Исключения на сбор писем
  7518. */
  7519. const isFarmLetter = !(
  7520. /** Portals // сферы портала */
  7521. (reward?.refillable ? reward.refillable[45] : false) ||
  7522. /** Energy // энергия */
  7523. (reward?.stamina ? reward.stamina : false) ||
  7524. /** accelerating energy gain // ускорение набора энергии */
  7525. (reward?.buff ? true : false) ||
  7526. /** VIP Points // вип очки */
  7527. (reward?.vipPoints ? reward.vipPoints : false) ||
  7528. /** souls of heroes // душы героев */
  7529. (reward?.fragmentHero ? true : false) ||
  7530. /** heroes // герои */
  7531. (reward?.bundleHeroReward ? true : false)
  7532. );
  7533. if (isFarmLetter) {
  7534. lettersIds.push(~~letter.id);
  7535. continue;
  7536. }
  7537. /**
  7538. * Если до окончания годности письма менее 24 часов,
  7539. * то оно собирается не смотря на исключения
  7540. */
  7541. const availableUntil = +letter?.availableUntil;
  7542. if (availableUntil) {
  7543. const maxTimeLeft = 24 * 60 * 60 * 1000;
  7544. const timeLeft = (new Date(availableUntil * 1000) - new Date())
  7545. console.log('Time left:', timeLeft)
  7546. if (timeLeft < maxTimeLeft) {
  7547. lettersIds.push(~~letter.id);
  7548. continue;
  7549. }
  7550. }
  7551. }
  7552. return lettersIds;
  7553. }
  7554.  
  7555. /**
  7556. * Displaying information about the areas of the portal and attempts on the VG
  7557. *
  7558. * Отображение информации о сферах портала и попытках на ВГ
  7559. */
  7560. async function justInfo() {
  7561. return new Promise(async (resolve, reject) => {
  7562. const calls = [{
  7563. name: "userGetInfo",
  7564. args: {},
  7565. ident: "userGetInfo"
  7566. },
  7567. {
  7568. name: "clanWarGetInfo",
  7569. args: {},
  7570. ident: "clanWarGetInfo"
  7571. },
  7572. {
  7573. name: "titanArenaGetStatus",
  7574. args: {},
  7575. ident: "titanArenaGetStatus"
  7576. }];
  7577. const result = await Send(JSON.stringify({ calls }));
  7578. const infos = result.results;
  7579. const portalSphere = infos[0].result.response.refillable.find(n => n.id == 45);
  7580. const clanWarMyTries = infos[1].result.response?.myTries ?? 0;
  7581. const arePointsMax = infos[1].result.response?.arePointsMax;
  7582. const titansLevel = +(infos[2].result.response?.tier ?? 0);
  7583. const titansStatus = infos[2].result.response?.status; //peace_time || battle
  7584.  
  7585. const sanctuaryButton = buttons['goToSanctuary'].button;
  7586. const clanWarButton = buttons['goToClanWar'].button;
  7587. const titansArenaButton = buttons['testTitanArena'].button;
  7588.  
  7589. /*if (portalSphere.amount) {
  7590. sanctuaryButton.style.color = portalSphere.amount >= 3 ? 'red' : 'brown';
  7591. sanctuaryButton.title = `${I18N('SANCTUARY_TITLE')}\n${portalSphere.amount} ${I18N('PORTALS')}`;
  7592. } else {*/
  7593. sanctuaryButton.style.color = '';
  7594. sanctuaryButton.title = I18N('SANCTUARY_TITLE');
  7595. //}
  7596. /*if (clanWarMyTries && !arePointsMax) {
  7597. clanWarButton.style.color = 'red';
  7598. clanWarButton.title = `${I18N('GUILD_WAR_TITLE')}\n${clanWarMyTries}${I18N('ATTEMPTS')}`;
  7599. } else {*/
  7600. clanWarButton.style.color = '';
  7601. clanWarButton.title = I18N('GUILD_WAR_TITLE');
  7602. //}
  7603.  
  7604. /*if (titansLevel < 7 && titansStatus == 'battle') {
  7605. const partColor = Math.floor(125 * titansLevel / 7);
  7606. titansArenaButton.style.color = `rgb(255,${partColor},${partColor})`;
  7607. titansArenaButton.title = `${I18N('TITAN_ARENA_TITLE')}\n${titansLevel} ${I18N('LEVEL')}`;
  7608. } else {*/
  7609. titansArenaButton.style.color = '';
  7610. titansArenaButton.title = I18N('TITAN_ARENA_TITLE');
  7611. //}
  7612. //тест убрал подсветку красным в меню
  7613. setProgress('<img src="https://zingery.ru/heroes/portal.png" style="height: 25px;position: relative;top: 5px;"> ' + `${portalSphere.amount} </br> ${I18N('GUILD_WAR')}: ${clanWarMyTries}`, true);
  7614. resolve();
  7615. });
  7616. }
  7617. // тест сделать все
  7618. /** Отправить подарки мое*/
  7619. function testclanSendDailyGifts() {
  7620.  
  7621. send('{"calls":[{"name":"clanSendDailyGifts","args":{},"ident":"clanSendDailyGifts"}]}', e => {
  7622. setProgress('Награды собраны', true);});
  7623. }
  7624. /** Открой сферу артефактов титанов*/
  7625. function testtitanArtifactChestOpen() {
  7626. send('{"calls":[{"name":"titanArtifactChestOpen","args":{"amount":1,"free":true},"ident":"body"}]}',
  7627. isWeCanDo => {
  7628. return info['inventoryGet']?.consumable[55] > 0
  7629. //setProgress('Награды собраны', true);
  7630. });
  7631. }
  7632. /** Воспользуйся призывом питомцев 1 раз*/
  7633. function testpet_chestOpen() {
  7634. send('{"calls":[{"name":"pet_chestOpen","args":{"amount":1,"paid":false},"ident":"pet_chestOpen"}]}',
  7635. isWeCanDo => {
  7636. return info['inventoryGet']?.consumable[90] > 0
  7637. //setProgress('Награды собраны', true);
  7638. });
  7639. }
  7640.  
  7641. async function getDailyBonus() {
  7642. const dailyBonusInfo = await Send(JSON.stringify({
  7643. calls: [{
  7644. name: "dailyBonusGetInfo",
  7645. args: {},
  7646. ident: "body"
  7647. }]
  7648. })).then(e => e.results[0].result.response);
  7649. const { availableToday, availableVip, currentDay } = dailyBonusInfo;
  7650.  
  7651. if (!availableToday) {
  7652. console.log('Уже собрано');
  7653. return;
  7654. }
  7655.  
  7656. const currentVipPoints = +userInfo.vipPoints;
  7657. const dailyBonusStat = lib.getData('dailyBonusStatic');
  7658. const vipInfo = lib.getData('level').vip;
  7659. let currentVipLevel = 0;
  7660. for (let i in vipInfo) {
  7661. vipLvl = vipInfo[i];
  7662. if (currentVipPoints >= vipLvl.vipPoints) {
  7663. currentVipLevel = vipLvl.level;
  7664. }
  7665. }
  7666. const vipLevelDouble = dailyBonusStat[`${currentDay}_0_0`].vipLevelDouble;
  7667.  
  7668. const calls = [{
  7669. name: "dailyBonusFarm",
  7670. args: {
  7671. vip: availableVip && currentVipLevel >= vipLevelDouble ? 1 : 0
  7672. },
  7673. ident: "body"
  7674. }];
  7675.  
  7676. const result = await Send(JSON.stringify({ calls }));
  7677. if (result.error) {
  7678. console.error(result.error);
  7679. return;
  7680. }
  7681.  
  7682. const reward = result.results[0].result.response;
  7683. const type = Object.keys(reward).pop();
  7684. const itemId = Object.keys(reward[type]).pop();
  7685. const count = reward[type][itemId];
  7686. const itemName = cheats.translate(`LIB_${type.toUpperCase()}_NAME_${itemId}`);
  7687.  
  7688. console.log(`Ежедневная награда: Получено ${count} ${itemName}`, reward);
  7689. }
  7690.  
  7691. async function farmStamina(lootBoxId = 148) {
  7692. const lootBox = await Send('{"calls":[{"name":"inventoryGet","args":{},"ident":"inventoryGet"}]}')
  7693. .then(e => e.results[0].result.response.consumable[148]);
  7694.  
  7695. /** Добавить другие ящики */
  7696. /**
  7697. * 144 - медная шкатулка
  7698. * 145 - бронзовая шкатулка
  7699. * 148 - платиновая шкатулка
  7700. */
  7701. if (!lootBox) {
  7702. setProgress(I18N('NO_BOXES'), true);
  7703. return;
  7704. }
  7705.  
  7706. let maxFarmEnergy = getSaveVal('maxFarmEnergy', 100);
  7707. const result = await popup.confirm(I18N('OPEN_LOOTBOX', { lootBox }), [
  7708. { result: false, isClose: true },
  7709. { msg: I18N('BTN_YES'), result: true },
  7710. { msg: I18N('STAMINA'), isInput: true, default: maxFarmEnergy },
  7711. ]);
  7712.  
  7713. if (!+result) {
  7714. return;
  7715. }
  7716.  
  7717. if ((typeof result) !== 'boolean' && Number.parseInt(result)) {
  7718. maxFarmEnergy = +result;
  7719. setSaveVal('maxFarmEnergy', maxFarmEnergy);
  7720. } else {
  7721. maxFarmEnergy = 0;
  7722. }
  7723.  
  7724. let collectEnergy = 0;
  7725. for (let count = lootBox; count > 0; count--) {
  7726. const result = await Send('{"calls":[{"name":"consumableUseLootBox","args":{"libId":148,"amount":1},"ident":"body"}]}')
  7727. .then(e => e.results[0].result.response[0]);
  7728. if ('stamina' in result) {
  7729. setProgress(`${I18N('OPEN')}: ${lootBox - count}/${lootBox} ${I18N('STAMINA')} +${result.stamina}<br>${I18N('STAMINA')}: ${collectEnergy}`, false);
  7730. console.log(`${ I18N('STAMINA') } + ${ result.stamina }`);
  7731. if (!maxFarmEnergy) {
  7732. return;
  7733. }
  7734. collectEnergy += +result.stamina;
  7735. if (collectEnergy >= maxFarmEnergy) {
  7736. console.log(`${I18N('STAMINA')} + ${ collectEnergy }`);
  7737. setProgress(`${I18N('STAMINA')} + ${ collectEnergy }`, false);
  7738. return;
  7739. }
  7740. } else {
  7741. setProgress(`${I18N('OPEN')}: ${lootBox - count}/${lootBox}<br>${I18N('STAMINA')}: ${collectEnergy}`, false);
  7742. console.log(result);
  7743. }
  7744. }
  7745.  
  7746. setProgress(I18N('BOXES_OVER'), true);
  7747. }
  7748.  
  7749. async function fillActive() {
  7750. const data = await Send(JSON.stringify({
  7751. calls: [{
  7752. name: "questGetAll",
  7753. args: {},
  7754. ident: "questGetAll"
  7755. }, {
  7756. name: "inventoryGet",
  7757. args: {},
  7758. ident: "inventoryGet"
  7759. }, {
  7760. name: "clanGetInfo",
  7761. args: {},
  7762. ident: "clanGetInfo"
  7763. }
  7764. ]
  7765. })).then(e => e.results.map(n => n.result.response));
  7766.  
  7767. const quests = data[0];
  7768. const inv = data[1];
  7769. const stat = data[2].stat;
  7770. const maxActive = 2000 - stat.todayItemsActivity;
  7771. if (maxActive <= 0) {
  7772. setProgress(I18N('NO_MORE_ACTIVITY'), true);
  7773. return;
  7774. }
  7775.  
  7776. let countGetActive = 0;
  7777. const quest = quests.find(e => e.id > 10046 && e.id < 10051);
  7778. if (quest) {
  7779. countGetActive = 1750 - quest.progress;
  7780. }
  7781.  
  7782. if (countGetActive <= 0) {
  7783. countGetActive = maxActive;
  7784. }
  7785. console.log(countGetActive);
  7786.  
  7787. countGetActive = +(await popup.confirm(I18N('EXCHANGE_ITEMS', { maxActive }), [
  7788. { result: false, isClose: true },
  7789. { msg: I18N('GET_ACTIVITY'), isInput: true, default: countGetActive.toString() },
  7790. ]));
  7791.  
  7792. if (!countGetActive) {
  7793. return;
  7794. }
  7795.  
  7796. if (countGetActive > maxActive) {
  7797. countGetActive = maxActive;
  7798. }
  7799.  
  7800. const items = lib.getData('inventoryItem');
  7801.  
  7802. let itemsInfo = [];
  7803. for (let type of ['gear', 'scroll']) {
  7804. for (let i in inv[type]) {
  7805. const v = items[type][i]?.enchantValue || 0;
  7806. itemsInfo.push({
  7807. id: i,
  7808. count: inv[type][i],
  7809. v,
  7810. type
  7811. })
  7812. }
  7813. const invType = 'fragment' + type.toLowerCase().charAt(0).toUpperCase() + type.slice(1);
  7814. for (let i in inv[invType]) {
  7815. const v = items[type][i]?.fragmentEnchantValue || 0;
  7816. itemsInfo.push({
  7817. id: i,
  7818. count: inv[invType][i],
  7819. v,
  7820. type: invType
  7821. })
  7822. }
  7823. }
  7824. itemsInfo = itemsInfo.filter(e => e.v < 4 && e.count > 200);
  7825. itemsInfo = itemsInfo.sort((a, b) => b.count - a.count);
  7826. console.log(itemsInfo);
  7827. const activeItem = itemsInfo.shift();
  7828. console.log(activeItem);
  7829. const countItem = Math.ceil(countGetActive / activeItem.v);
  7830. if (countItem > activeItem.count) {
  7831. setProgress(I18N('NOT_ENOUGH_ITEMS'), true);
  7832. console.log(activeItem);
  7833. return;
  7834. }
  7835.  
  7836. await Send(JSON.stringify({
  7837. calls: [{
  7838. name: "clanItemsForActivity",
  7839. args: {
  7840. items: {
  7841. [activeItem.type]: {
  7842. [activeItem.id]: countItem
  7843. }
  7844. }
  7845. },
  7846. ident: "body"
  7847. }]
  7848. })).then(e => {
  7849. /** TODO: Вывести потраченые предметы */
  7850. console.log(e);
  7851. setProgress(`${I18N('ACTIVITY_RECEIVED')}: ` + e.results[0].result.response, true);
  7852. });
  7853. }
  7854.  
  7855. async function buyHeroFragments() {
  7856. const result = await Send('{"calls":[{"name":"inventoryGet","args":{},"ident":"inventoryGet"},{"name":"shopGetAll","args":{},"ident":"shopGetAll"}]}')
  7857. .then(e => e.results.map(n => n.result.response));
  7858. const inv = result[0];
  7859. const shops = Object.values(result[1]).filter(shop => [4, 5, 6, 8, 9, 10, 17].includes(shop.id));
  7860. const calls = [];
  7861.  
  7862. for (let shop of shops) {
  7863. const slots = Object.values(shop.slots);
  7864. for (const slot of slots) {
  7865. /* Уже куплено */
  7866. if (slot.bought) {
  7867. continue;
  7868. }
  7869. /* Не душа героя */
  7870. if (!('fragmentHero' in slot.reward)) {
  7871. continue;
  7872. }
  7873. const coin = Object.keys(slot.cost).pop();
  7874. const coinId = Object.keys(slot.cost[coin]).pop();
  7875. const stock = inv[coin][coinId] || 0;
  7876. /* Не хватает на покупку */
  7877. if (slot.cost[coin][coinId] > stock) {
  7878. continue;
  7879. }
  7880. inv[coin][coinId] -= slot.cost[coin][coinId];
  7881. calls.push({
  7882. name: "shopBuy",
  7883. args: {
  7884. shopId: shop.id,
  7885. slot: slot.id,
  7886. cost: slot.cost,
  7887. reward: slot.reward,
  7888. },
  7889. ident: `shopBuy_${shop.id}_${slot.id}`,
  7890. })
  7891. }
  7892. }
  7893.  
  7894. if (!calls.length) {
  7895. setProgress(I18N('NO_PURCHASABLE_HERO_SOULS'), true);
  7896. return;
  7897. }
  7898.  
  7899. const bought = await Send(JSON.stringify({ calls })).then(e => e.results.map(n => n.result.response));
  7900. if (!bought) {
  7901. console.log('что-то пошло не так')
  7902. return;
  7903. }
  7904.  
  7905. let countHeroSouls = 0;
  7906. for (const buy of bought) {
  7907. countHeroSouls += +Object.values(Object.values(buy).pop()).pop();
  7908. }
  7909. console.log(countHeroSouls, bought, calls);
  7910. setProgress(I18N('PURCHASED_HERO_SOULS', { countHeroSouls }), true);
  7911. }
  7912.  
  7913. /** Открыть платные сундуки в Запределье за 90 */
  7914. async function bossOpenChestPay() {
  7915. const info = await Send('{"calls":[{"name":"userGetInfo","args":{},"ident":"userGetInfo"},{"name":"bossGetAll","args":{},"ident":"bossGetAll"}]}')
  7916. .then(e => e.results.map(n => n.result.response));
  7917.  
  7918. const user = info[0];
  7919. const boses = info[1];
  7920.  
  7921. const currentStarMoney = user.starMoney;
  7922. if (currentStarMoney < 540) {
  7923. setProgress(I18N('NOT_ENOUGH_EMERALDS_540', { currentStarMoney }), true);
  7924. return;
  7925. }
  7926.  
  7927. const calls = [];
  7928.  
  7929. let n = 0;
  7930. const amount = 1;
  7931. for (let boss of boses) {
  7932. const bossId = boss.id;
  7933. if (boss.chestNum != 2) {
  7934. continue;
  7935. }
  7936. for (const starmoney of [90, 90, 0]) {
  7937. calls.push({
  7938. name: "bossOpenChest",
  7939. args: {
  7940. bossId,
  7941. amount,
  7942. starmoney
  7943. },
  7944. ident: "bossOpenChest_" + (++n)
  7945. });
  7946. }
  7947. }
  7948.  
  7949. if (!calls.length) {
  7950. setProgress(I18N('CHESTS_NOT_AVAILABLE'), true);
  7951. return;
  7952. }
  7953.  
  7954. const result = await Send(JSON.stringify({ calls }));
  7955. console.log(result);
  7956. if (result?.results) {
  7957. setProgress(`${I18N('OUTLAND_CHESTS_RECEIVED')}: ` + result.results.length, true);
  7958. } else {
  7959. setProgress(I18N('CHESTS_NOT_AVAILABLE'), true);
  7960. }
  7961. }
  7962.  
  7963. async function autoRaidAdventure() {
  7964. const calls = [
  7965. {
  7966. name: "userGetInfo",
  7967. args: {},
  7968. ident: "userGetInfo"
  7969. },
  7970. {
  7971. name: "adventure_raidGetInfo",
  7972. args: {},
  7973. ident: "adventure_raidGetInfo"
  7974. }
  7975. ];
  7976. const result = await Send(JSON.stringify({ calls }))
  7977. .then(e => e.results.map(n => n.result.response));
  7978.  
  7979. const portalSphere = result[0].refillable.find(n => n.id == 45);
  7980. const adventureRaid = Object.entries(result[1].raid).filter(e => e[1]).pop()
  7981. const adventureId = adventureRaid ? adventureRaid[0] : 0;
  7982.  
  7983. if (!portalSphere.amount || !adventureId) {
  7984. setProgress(I18N('RAID_NOT_AVAILABLE'), true);
  7985. return;
  7986. }
  7987.  
  7988. const countRaid = +(await popup.confirm(I18N('RAID_ADVENTURE', { adventureId }), [
  7989. { result: false, isClose: true },
  7990. { msg: I18N('RAID'), isInput: true, default: portalSphere.amount },
  7991. ]));
  7992.  
  7993. if (!countRaid) {
  7994. return;
  7995. }
  7996.  
  7997. if (countRaid > portalSphere.amount) {
  7998. countRaid = portalSphere.amount;
  7999. }
  8000.  
  8001. const resultRaid = await Send(JSON.stringify({
  8002. calls: [...Array(countRaid)].map((e, i) => ({
  8003. name: "adventure_raid",
  8004. args: {
  8005. adventureId
  8006. },
  8007. ident: `body_${i}`
  8008. }))
  8009. })).then(e => e.results.map(n => n.result.response));
  8010.  
  8011. if (!resultRaid.length) {
  8012. console.log(resultRaid);
  8013. setProgress(I18N('SOMETHING_WENT_WRONG'), true);
  8014. return;
  8015. }
  8016.  
  8017. console.log(resultRaid, adventureId, portalSphere.amount);
  8018. setProgress(I18N('ADVENTURE_COMPLETED', { adventureId, times: resultRaid.length }), true);
  8019. }
  8020.  
  8021. /** Вывести всю клановую статистику в консоль браузера */
  8022. async function clanStatistic() {
  8023. const copy = function (text) {
  8024. const copyTextarea = document.createElement("textarea");
  8025. copyTextarea.style.opacity = "0";
  8026. copyTextarea.textContent = text;
  8027. document.body.appendChild(copyTextarea);
  8028. copyTextarea.select();
  8029. document.execCommand("copy");
  8030. document.body.removeChild(copyTextarea);
  8031. delete copyTextarea;
  8032. }
  8033. const calls = [
  8034. { name: "clanGetInfo", args: {}, ident: "clanGetInfo" },
  8035. { name: "clanGetWeeklyStat", args: {}, ident: "clanGetWeeklyStat" },
  8036. { name: "clanGetLog", args: {}, ident: "clanGetLog" },
  8037. ];
  8038.  
  8039. const result = await Send(JSON.stringify({ calls }));
  8040.  
  8041. const dataClanInfo = result.results[0].result.response;
  8042. const dataClanStat = result.results[1].result.response;
  8043. const dataClanLog = result.results[2].result.response;
  8044.  
  8045. const membersStat = {};
  8046. for (let i = 0; i < dataClanStat.stat.length; i++) {
  8047. membersStat[dataClanStat.stat[i].id] = dataClanStat.stat[i];
  8048. }
  8049.  
  8050. const joinStat = {};
  8051. historyLog = dataClanLog.history;
  8052. for (let j in historyLog) {
  8053. his = historyLog[j];
  8054. if (his.event == 'join') {
  8055. joinStat[his.userId] = his.ctime;
  8056. }
  8057. }
  8058.  
  8059. const infoArr = [];
  8060. const members = dataClanInfo.clan.members;
  8061. for (let n in members) {
  8062. var member = [
  8063. n,
  8064. members[n].name,
  8065. members[n].level,
  8066. dataClanInfo.clan.warriors.includes(+n) ? 1 : 0,
  8067. (new Date(members[n].lastLoginTime * 1000)).toLocaleString().replace(',', ''),
  8068. joinStat[n] ? (new Date(joinStat[n] * 1000)).toLocaleString().replace(',', '') : '',
  8069. membersStat[n].activity.reverse().join('\t'),
  8070. membersStat[n].adventureStat.reverse().join('\t'),
  8071. membersStat[n].clanGifts.reverse().join('\t'),
  8072. membersStat[n].clanWarStat.reverse().join('\t'),
  8073. membersStat[n].dungeonActivity.reverse().join('\t'),
  8074. ];
  8075. infoArr.push(member);
  8076. }
  8077. const info = infoArr.sort((a, b) => (b[2] - a[2])).map((e) => e.join('\t')).join('\n');
  8078. console.log(info);
  8079. copy(info);
  8080. setProgress(I18N('CLAN_STAT_COPY'), true);
  8081. }
  8082.  
  8083. async function buyInStoreForGold() {
  8084. const result = await Send('{"calls":[{"name":"shopGetAll","args":{},"ident":"body"},{"name":"userGetInfo","args":{},"ident":"userGetInfo"}]}').then(e => e.results.map(n => n.result.response));
  8085. const shops = result[0];
  8086. const user = result[1];
  8087. let gold = user.gold;
  8088. const calls = [];
  8089. if (shops[17]) {
  8090. const slots = shops[17].slots;
  8091. for (let i = 1; i <= 2; i++) {
  8092. if (!slots[i].bought) {
  8093. const costGold = slots[i].cost.gold;
  8094. if ((gold - costGold) < 0) {
  8095. continue;
  8096. }
  8097. gold -= costGold;
  8098. calls.push({
  8099. name: "shopBuy",
  8100. args: {
  8101. shopId: 17,
  8102. slot: i,
  8103. cost: slots[i].cost,
  8104. reward: slots[i].reward,
  8105. },
  8106. ident: 'body_' + i,
  8107. })
  8108. }
  8109. }
  8110. }
  8111. const slots = shops[1].slots;
  8112. for (let i = 4; i <= 6; i++) {
  8113. if (!slots[i].bought && slots[i]?.cost?.gold) {
  8114. const costGold = slots[i].cost.gold;
  8115. if ((gold - costGold) < 0) {
  8116. continue;
  8117. }
  8118. gold -= costGold;
  8119. calls.push({
  8120. name: "shopBuy",
  8121. args: {
  8122. shopId: 1,
  8123. slot: i,
  8124. cost: slots[i].cost,
  8125. reward: slots[i].reward,
  8126. },
  8127. ident: 'body_' + i,
  8128. })
  8129. }
  8130. }
  8131.  
  8132. if (!calls.length) {
  8133. setProgress(I18N('NOTHING_BUY'), true);
  8134. return;
  8135. }
  8136.  
  8137. const resultBuy = await Send(JSON.stringify({ calls })).then(e => e.results.map(n => n.result.response));
  8138. console.log(resultBuy);
  8139. const countBuy = resultBuy.length;
  8140. setProgress(I18N('LOTS_BOUGHT', { countBuy }), true);
  8141. }
  8142.  
  8143. function rewardsAndMailFarm() {
  8144. return new Promise(function (resolve, reject) {
  8145. let questGetAllCall = {
  8146. calls: [{
  8147. name: "questGetAll",
  8148. args: {},
  8149. ident: "questGetAll"
  8150. }, {
  8151. name: "mailGetAll",
  8152. args: {},
  8153. ident: "mailGetAll"
  8154. }]
  8155. }
  8156. send(JSON.stringify(questGetAllCall), function (data) {
  8157. if (!data) return;
  8158. let questGetAll = data.results[0].result.response.filter(e => e.state == 2);
  8159. const questBattlePass = lib.getData('quest').battlePass;
  8160. const questChainBPass = lib.getData('battlePass').questChain;
  8161.  
  8162. const questAllFarmCall = {
  8163. calls: []
  8164. }
  8165. let number = 0;
  8166. for (let quest of questGetAll) {
  8167. if (quest.id > 1e6) {
  8168. const questInfo = questBattlePass[quest.id];
  8169. const chain = questChainBPass[questInfo.chain];
  8170. if (chain.requirement?.battlePassTicket) {
  8171. continue;
  8172. }
  8173. }
  8174. questAllFarmCall.calls.push({
  8175. name: "questFarm",
  8176. args: {
  8177. questId: quest.id
  8178. },
  8179. ident: `questFarm_${number}`
  8180. });
  8181. number++;
  8182. }
  8183.  
  8184. let letters = data?.results[1]?.result?.response?.letters;
  8185. letterIds = lettersFilter(letters);
  8186.  
  8187. if (letterIds.length) {
  8188. questAllFarmCall.calls.push({
  8189. name: "mailFarm",
  8190. args: { letterIds },
  8191. ident: "mailFarm"
  8192. })
  8193. }
  8194.  
  8195. if (!questAllFarmCall.calls.length) {
  8196. setProgress(I18N('NOTHING_TO_COLLECT'), true);
  8197. resolve();
  8198. return;
  8199. }
  8200.  
  8201. send(JSON.stringify(questAllFarmCall), function (res) {
  8202. let reSend = false;
  8203. let countQuests = 0;
  8204. let countMail = 0;
  8205. for (let call of res.results) {
  8206. if (call.ident.includes('questFarm')) {
  8207. countQuests++;
  8208. } else {
  8209. countMail = Object.keys(call.result.response).length;
  8210. }
  8211.  
  8212. /** TODO: Переписать чтоб не вызывать функцию дважды */
  8213. const newQuests = call.result.newQuests;
  8214. if (newQuests) {
  8215. for (let quest of newQuests) {
  8216. if (quest.id < 1e6 && quest.state == 2) {
  8217. reSend = true;
  8218. }
  8219. }
  8220. }
  8221. }
  8222. setProgress(I18N('COLLECT_REWARDS_AND_MAIL', { countQuests, countMail }), true);
  8223. if (reSend) {
  8224. rewardsAndMailFarm()
  8225. }
  8226. resolve();
  8227. });
  8228. });
  8229. })
  8230. }
  8231.  
  8232. class epicBrawl {
  8233. timeout = null;
  8234. time = null;
  8235.  
  8236. constructor() {
  8237. if (epicBrawl.inst) {
  8238. return epicBrawl.inst;
  8239. }
  8240. epicBrawl.inst = this;
  8241. return this;
  8242. }
  8243.  
  8244. runTimeout(func, timeDiff) {
  8245. const worker = new Worker(URL.createObjectURL(new Blob([`
  8246. self.onmessage = function(e) {
  8247. const timeDiff = e.data;
  8248.  
  8249. if (timeDiff > 0) {
  8250. setTimeout(() => {
  8251. self.postMessage(1);
  8252. self.close();
  8253. }, timeDiff);
  8254. }
  8255. };
  8256. `])));
  8257. worker.postMessage(timeDiff);
  8258. worker.onmessage = () => {
  8259. func();
  8260. };
  8261. return true;
  8262. }
  8263.  
  8264. timeDiff(date1, date2) {
  8265. const date1Obj = new Date(date1);
  8266. const date2Obj = new Date(date2);
  8267.  
  8268. const timeDiff = Math.abs(date2Obj - date1Obj);
  8269.  
  8270. const totalSeconds = timeDiff / 1000;
  8271. const minutes = Math.floor(totalSeconds / 60);
  8272. const seconds = Math.floor(totalSeconds % 60);
  8273.  
  8274. const formattedMinutes = String(minutes).padStart(2, '0');
  8275. const formattedSeconds = String(seconds).padStart(2, '0');
  8276.  
  8277. return `${formattedMinutes}:${formattedSeconds}`;
  8278. }
  8279.  
  8280. check() {
  8281. console.log(new Date(this.time))
  8282. if (Date.now() > this.time) {
  8283. this.timeout = null;
  8284. this.start()
  8285. return;
  8286. }
  8287. this.timeout = this.runTimeout(() => this.check(), 6e4);
  8288. return this.timeDiff(this.time, Date.now())
  8289. }
  8290.  
  8291. async start() {
  8292. if (this.timeout) {
  8293. const time = this.timeDiff(this.time, Date.now());
  8294. console.log(new Date(this.time))
  8295. setProgress(I18N('TIMER_ALREADY', { time }), false, hideProgress);
  8296. return;
  8297. }
  8298. setProgress(I18N('EPIC_BRAWL'), false, hideProgress);
  8299. 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));
  8300. const refill = teamInfo[2].refillable.find(n => n.id == 52)
  8301. this.time = (refill.lastRefill + 3600) * 1000
  8302. const attempts = refill.amount;
  8303. if (!attempts) {
  8304. console.log(new Date(this.time));
  8305. const time = this.check();
  8306. setProgress(I18N('NO_ATTEMPTS_TIMER_START', { time }), false, hideProgress);
  8307. return;
  8308. }
  8309.  
  8310. if (!teamInfo[0].epic_brawl) {
  8311. setProgress(I18N('NO_HEROES_PACK'), false, hideProgress);
  8312. return;
  8313. }
  8314.  
  8315. const args = {
  8316. heroes: teamInfo[0].epic_brawl.filter(e => e < 1000),
  8317. pet: teamInfo[0].epic_brawl.filter(e => e > 6000).pop(),
  8318. favor: teamInfo[1].epic_brawl,
  8319. }
  8320.  
  8321. let wins = 0;
  8322. let coins = 0;
  8323. let streak = { progress: 0, nextStage: 0 };
  8324. for (let i = attempts; i > 0; i--) {
  8325. const info = await Send(JSON.stringify({
  8326. calls: [
  8327. { name: "epicBrawl_getEnemy", args: {}, ident: "epicBrawl_getEnemy" }, { name: "epicBrawl_startBattle", args, ident: "epicBrawl_startBattle" }
  8328. ]
  8329. })).then(e => e.results.map(n => n.result.response));
  8330.  
  8331. const { progress, result } = await Calc(info[1].battle);
  8332. 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));
  8333.  
  8334. const resultInfo = endResult[0].result;
  8335. streak = endResult[1];
  8336.  
  8337. wins += resultInfo.win;
  8338. coins += resultInfo.reward ? resultInfo.reward.coin[39] : 0;
  8339.  
  8340. console.log(endResult[0].result)
  8341. if (endResult[1].progress == endResult[1].nextStage) {
  8342. const farm = await Send('{"calls":[{"name":"epicBrawl_farmWinStreak","args":{},"ident":"body"}]}').then(e => e.results[0].result.response);
  8343. coins += farm.coin[39];
  8344. }
  8345.  
  8346. setProgress(I18N('EPIC_BRAWL_RESULT', {
  8347. i, wins, attempts, coins,
  8348. progress: streak.progress,
  8349. nextStage: streak.nextStage,
  8350. end: '',
  8351. }), false, hideProgress);
  8352. }
  8353.  
  8354. console.log(new Date(this.time));
  8355. const time = this.check();
  8356. setProgress(I18N('EPIC_BRAWL_RESULT', {
  8357. wins, attempts, coins,
  8358. i: '',
  8359. progress: streak.progress,
  8360. nextStage: streak.nextStage,
  8361. end: I18N('ATTEMPT_ENDED', { time }),
  8362. }), false, hideProgress);
  8363. }
  8364. }
  8365. /* тест остановка подземки*/
  8366. function stopDungeon(e) {
  8367. stopDung = true;
  8368. }
  8369.  
  8370. function countdownTimer(seconds, message) {
  8371. message = message || I18N('TIMER');
  8372. const stopTimer = Date.now() + seconds * 1e3
  8373. return new Promise(resolve => {
  8374. const interval = setInterval(async () => {
  8375. const now = Date.now();
  8376. setProgress(`${message} ${((stopTimer - now) / 1000).toFixed(2)}`, false);
  8377. if (now > stopTimer) {
  8378. clearInterval(interval);
  8379. setProgress('', 1);
  8380. resolve();
  8381. }
  8382. }, 100);
  8383. });
  8384. }
  8385.  
  8386. /** Набить килов в горниле душк */
  8387. async function bossRatingEventSouls() {
  8388. const data = await Send({
  8389. calls: [
  8390. { name: "heroGetAll", args: {}, ident: "teamGetAll" },
  8391. { name: "offerGetAll", args: {}, ident: "offerGetAll" },
  8392. { name: "pet_getAll", args: {}, ident: "pet_getAll" },
  8393. ]
  8394. });
  8395. const bossEventInfo = data.results[1].result.response.find(e => e.offerType == "bossEvent");
  8396. if (!bossEventInfo) {
  8397. setProgress('Эвент завершен', true);
  8398. return;
  8399. }
  8400.  
  8401. if (bossEventInfo.progress.score > 250) {
  8402. setProgress('Уже убито больше 250 врагов');
  8403. rewardBossRatingEventSouls();
  8404. return;
  8405. }
  8406. const availablePets = Object.values(data.results[2].result.response).map(e => e.id);
  8407. const heroGetAllList = data.results[0].result.response;
  8408. const usedHeroes = bossEventInfo.progress.usedHeroes;
  8409. const heroList = [];
  8410.  
  8411. for (let heroId in heroGetAllList) {
  8412. let hero = heroGetAllList[heroId];
  8413. if (usedHeroes.includes(hero.id)) {
  8414. continue;
  8415. }
  8416. heroList.push(hero.id);
  8417. }
  8418.  
  8419. if (!heroList.length) {
  8420. setProgress('Нет героев', true);
  8421. return;
  8422. }
  8423.  
  8424. const pet = availablePets.includes(6005) ? 6005 : availablePets[Math.floor(Math.random() * availablePets.length)];
  8425. const petLib = lib.getData('pet');
  8426. let count = 1;
  8427.  
  8428. for (const heroId of heroList) {
  8429. const args = {
  8430. heroes: [heroId],
  8431. pet
  8432. }
  8433. /** Поиск питомца для героя */
  8434. for (const petId of availablePets) {
  8435. if (petLib[petId].favorHeroes.includes(heroId)) {
  8436. args.favor = {
  8437. [heroId]: petId
  8438. }
  8439. break;
  8440. }
  8441. }
  8442.  
  8443. const calls = [{
  8444. name: "bossRatingEvent_startBattle",
  8445. args,
  8446. ident: "body"
  8447. }, {
  8448. name: "offerGetAll",
  8449. args: {},
  8450. ident: "offerGetAll"
  8451. }];
  8452.  
  8453. const res = await Send({ calls });
  8454. count++;
  8455.  
  8456. if ('error' in res) {
  8457. console.error(res.error);
  8458. setProgress('Перезагрузите игру и попробуйте позже', true);
  8459. return;
  8460. }
  8461.  
  8462. const eventInfo = res.results[1].result.response.find(e => e.offerType == "bossEvent");
  8463. if (eventInfo.progress.score > 250) {
  8464. break;
  8465. }
  8466. setProgress('Количество убитых врагов: ' + eventInfo.progress.score + '<br>Использовано ' + count + ' героев');
  8467. }
  8468.  
  8469. rewardBossRatingEventSouls();
  8470. }
  8471. /** Сбор награды из Горнила Душ */
  8472. async function rewardBossRatingEventSouls() {
  8473. const data = await Send({
  8474. calls: [
  8475. { name: "offerGetAll", args: {}, ident: "offerGetAll" }
  8476. ]
  8477. });
  8478.  
  8479. const bossEventInfo = data.results[0].result.response.find(e => e.offerType == "bossEvent");
  8480. if (!bossEventInfo) {
  8481. setProgress('Эвент завершен', true);
  8482. return;
  8483. }
  8484.  
  8485. const farmedChests = bossEventInfo.progress.farmedChests;
  8486. const score = bossEventInfo.progress.score;
  8487. // setProgress('Количество убитых врагов: ' + score);
  8488. const revard = bossEventInfo.reward;
  8489. const calls = [];
  8490.  
  8491. let count = 0;
  8492. for (let i = 1; i < 10; i++) {
  8493. if (farmedChests.includes(i)) {
  8494. continue;
  8495. }
  8496. if (score < revard[i].score) {
  8497. break;
  8498. }
  8499. calls.push({
  8500. name: "bossRatingEvent_getReward",
  8501. args: {
  8502. rewardId: i
  8503. },
  8504. ident: "body_" + i
  8505. });
  8506. count++;
  8507. }
  8508. if (!count) {
  8509. setProgress('Нечего собирать', true);
  8510. return;
  8511. }
  8512.  
  8513. Send({ calls }).then(e => {
  8514. console.log(e);
  8515. setProgress('Собрано ' + e?.results?.length + ' наград', true);
  8516. })
  8517. }
  8518. /**
  8519. * Spin the Seer
  8520. *
  8521. * Покрутить провидца
  8522. */
  8523. async function rollAscension() {
  8524. const refillable = await Send({calls:[
  8525. {
  8526. name:"userGetInfo",
  8527. args:{},
  8528. ident:"userGetInfo"
  8529. }
  8530. ]}).then(e => e.results[0].result.response.refillable);
  8531. const i47 = refillable.find(i => i.id == 47);
  8532. if (i47?.amount) {
  8533. await Send({ calls: [{ name: "ascensionChest_open", args: { paid: false, amount: 1 }, ident: "body" }] });
  8534. setProgress(I18N('DONE'), true);
  8535. } else {
  8536. setProgress(I18N('NOT_ENOUGH_AP'), true);
  8537. }
  8538. }
  8539.  
  8540. /**
  8541. * Collect gifts for the New Year
  8542. *
  8543. * Собрать подарки на новый год
  8544. */
  8545. function getGiftNewYear() {
  8546. Send({ calls: [{ name: "newYearGiftGet", args: { type: 0 }, ident: "body" }] }).then(e => {
  8547. const gifts = e.results[0].result.response.gifts;
  8548. const calls = gifts.filter(e => e.opened == 0).map(e => ({
  8549. name: "newYearGiftOpen",
  8550. args: {
  8551. giftId: e.id
  8552. },
  8553. ident: `body_${e.id}`
  8554. }));
  8555. if (!calls.length) {
  8556. setProgress(I18N('NY_NO_GIFTS'), 5000);
  8557. return;
  8558. }
  8559. Send({ calls }).then(e => {
  8560. console.log(e.results)
  8561. const msg = I18N('NY_GIFTS_COLLECTED', { count: e.results.length });
  8562. console.log(msg);
  8563. setProgress(msg, 5000);
  8564. });
  8565. })
  8566. }
  8567.  
  8568. async function updateArtifacts() {
  8569. const count = +await popup.confirm(I18N('SET_NUMBER_LEVELS'), [
  8570. { msg: I18N('BTN_GO'), isInput: true, default: 10 },
  8571. { result: false, isClose: true }
  8572. ]);
  8573. if (!count) {
  8574. return;
  8575. }
  8576. const quest = new questRun;
  8577. await quest.autoInit();
  8578. const heroes = Object.values(quest.questInfo['heroGetAll']);
  8579. const inventory = quest.questInfo['inventoryGet'];
  8580. const calls = [];
  8581. for (let i = count; i > 0; i--) {
  8582. const upArtifact = quest.getUpgradeArtifact();
  8583. if (!upArtifact.heroId) {
  8584. if (await popup.confirm(I18N('POSSIBLE_IMPROVE_LEVELS', { count: calls.length }), [
  8585. { msg: I18N('YES'), result: true },
  8586. { result: false, isClose: true }
  8587. ])) {
  8588. break;
  8589. } else {
  8590. return;
  8591. }
  8592. }
  8593. const hero = heroes.find(e => e.id == upArtifact.heroId);
  8594. hero.artifacts[upArtifact.slotId].level++;
  8595. inventory[upArtifact.costСurrency][upArtifact.costId] -= upArtifact.costValue;
  8596. calls.push({
  8597. name: "heroArtifactLevelUp",
  8598. args: {
  8599. heroId: upArtifact.heroId,
  8600. slotId: upArtifact.slotId
  8601. },
  8602. ident: `heroArtifactLevelUp_${i}`
  8603. });
  8604. }
  8605.  
  8606. if (!calls.length) {
  8607. console.log(I18N('NOT_ENOUGH_RESOURECES'));
  8608. setProgress(I18N('NOT_ENOUGH_RESOURECES'), false);
  8609. return;
  8610. }
  8611.  
  8612. await Send(JSON.stringify({ calls })).then(e => {
  8613. if ('error' in e) {
  8614. console.log(I18N('NOT_ENOUGH_RESOURECES'));
  8615. setProgress(I18N('NOT_ENOUGH_RESOURECES'), false);
  8616. } else {
  8617. console.log(I18N('IMPROVED_LEVELS', { count: e.results.length }));
  8618. setProgress(I18N('IMPROVED_LEVELS', { count: e.results.length }), false);
  8619. }
  8620. });
  8621. }
  8622.  
  8623. window.sign = a => {
  8624. const i = this['\x78\x79\x7a'];
  8625. 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'))
  8626. }
  8627.  
  8628. async function updateSkins() {
  8629. const count = +await popup.confirm(I18N('SET_NUMBER_LEVELS'), [
  8630. { msg: I18N('BTN_GO'), isInput: true, default: 10 },
  8631. { result: false, isClose: true }
  8632. ]);
  8633. if (!count) {
  8634. return;
  8635. }
  8636.  
  8637. const quest = new questRun;
  8638. await quest.autoInit();
  8639. const heroes = Object.values(quest.questInfo['heroGetAll']);
  8640. const inventory = quest.questInfo['inventoryGet'];
  8641. const calls = [];
  8642. for (let i = count; i > 0; i--) {
  8643. const upSkin = quest.getUpgradeSkin();
  8644. if (!upSkin.heroId) {
  8645. if (await popup.confirm(I18N('POSSIBLE_IMPROVE_LEVELS', { count: calls.length }), [
  8646. { msg: I18N('YES'), result: true },
  8647. { result: false, isClose: true }
  8648. ])) {
  8649. break;
  8650. } else {
  8651. return;
  8652. }
  8653. }
  8654. const hero = heroes.find(e => e.id == upSkin.heroId);
  8655. hero.skins[upSkin.skinId]++;
  8656. inventory[upSkin.costСurrency][upSkin.costСurrencyId] -= upSkin.cost;
  8657. calls.push({
  8658. name: "heroSkinUpgrade",
  8659. args: {
  8660. heroId: upSkin.heroId,
  8661. skinId: upSkin.skinId
  8662. },
  8663. ident: `heroSkinUpgrade_${i}`
  8664. })
  8665. }
  8666.  
  8667. if (!calls.length) {
  8668. console.log(I18N('NOT_ENOUGH_RESOURECES'));
  8669. setProgress(I18N('NOT_ENOUGH_RESOURECES'), false);
  8670. return;
  8671. }
  8672.  
  8673. await Send(JSON.stringify({ calls })).then(e => {
  8674. if ('error' in e) {
  8675. console.log(I18N('NOT_ENOUGH_RESOURECES'));
  8676. setProgress(I18N('NOT_ENOUGH_RESOURECES'), false);
  8677. } else {
  8678. console.log(I18N('IMPROVED_LEVELS', { count: e.results.length }));
  8679. setProgress(I18N('IMPROVED_LEVELS', { count: e.results.length }), false);
  8680. }
  8681. });
  8682. }
  8683.  
  8684. function getQuestionInfo(img, nameOnly = false) {
  8685. const libHeroes = Object.values(lib.data.hero);
  8686. const parts = img.split(':');
  8687. const id = parts[1];
  8688. switch (parts[0]) {
  8689. case 'titanArtifact_id':
  8690. return cheats.translate("LIB_TITAN_ARTIFACT_NAME_" + id);
  8691. case 'titan':
  8692. return cheats.translate("LIB_HERO_NAME_" + id);
  8693. case 'skill':
  8694. return cheats.translate("LIB_SKILL_" + id);
  8695. case 'inventoryItem_gear':
  8696. return cheats.translate("LIB_GEAR_NAME_" + id);
  8697. case 'inventoryItem_coin':
  8698. return cheats.translate("LIB_COIN_NAME_" + id);
  8699. case 'artifact':
  8700. if (nameOnly) {
  8701. return cheats.translate("LIB_ARTIFACT_NAME_" + id);
  8702. }
  8703. heroes = libHeroes.filter(h => h.id < 100 && h.artifacts.includes(+id));
  8704. return {
  8705. /** Как называется этот артефакт? */
  8706. name: cheats.translate("LIB_ARTIFACT_NAME_" + id),
  8707. /** Какому герою принадлежит этот артефакт? */
  8708. heroes: heroes.map(h => cheats.translate("LIB_HERO_NAME_" + h.id))
  8709. };
  8710. case 'hero':
  8711. if (nameOnly) {
  8712. return cheats.translate("LIB_HERO_NAME_" + id);
  8713. }
  8714. artifacts = lib.data.hero[id].artifacts;
  8715. return {
  8716. /** Как зовут этого героя? */
  8717. name: cheats.translate("LIB_HERO_NAME_" + id),
  8718. /** Какой артефакт принадлежит этому герою? */
  8719. artifact: artifacts.map(a => cheats.translate("LIB_ARTIFACT_NAME_" + a))
  8720. };
  8721. }
  8722. }
  8723.  
  8724. function hintQuest(quest) {
  8725. const result = {};
  8726. if (quest?.questionIcon) {
  8727. const info = getQuestionInfo(quest.questionIcon);
  8728. if (info?.heroes) {
  8729. /** Какому герою принадлежит этот артефакт? */
  8730. result.answer = quest.answers.filter(e => info.heroes.includes(e.answerText.slice(1)));
  8731. }
  8732. if (info?.artifact) {
  8733. /** Какой артефакт принадлежит этому герою? */
  8734. result.answer = quest.answers.filter(e => info.artifact.includes(e.answerText.slice(1)));
  8735. }
  8736. if (typeof info == 'string') {
  8737. result.info = { name: info };
  8738. } else {
  8739. result.info = info;
  8740. }
  8741. }
  8742.  
  8743. if (quest.answers[0]?.answerIcon) {
  8744. result.answer = quest.answers.filter(e => quest.question.includes(getQuestionInfo(e.answerIcon, true)))
  8745. }
  8746.  
  8747. if ((!result?.answer || !result.answer.length) && !result.info?.name) {
  8748. return false;
  8749. }
  8750.  
  8751. let resultText = '';
  8752. if (result?.info) {
  8753. resultText += I18N('PICTURE') + result.info.name;
  8754. }
  8755. console.log(result);
  8756. if (result?.answer && result.answer.length) {
  8757. resultText += I18N('ANSWER') + result.answer[0].id + (!result.answer[0].answerIcon ? ' - ' + result.answer[0].answerText : '');
  8758. }
  8759.  
  8760. return resultText;
  8761. }
  8762.  
  8763. /**
  8764. * Attack of the minions of Asgard
  8765. *
  8766. * Атака прислужников Асгарда
  8767. */
  8768. function testRaidNodes() {
  8769. return new Promise((resolve, reject) => {
  8770. const tower = new executeRaidNodes(resolve, reject);
  8771. tower.start();
  8772. });
  8773. }
  8774.  
  8775. /**
  8776. * Attack of the minions of Asgard
  8777. *
  8778. * Атака прислужников Асгарда
  8779. */
  8780. function executeRaidNodes(resolve, reject) {
  8781. let raidData = {
  8782. teams: [],
  8783. favor: {},
  8784. nodes: [],
  8785. attempts: 0,
  8786. countExecuteBattles: 0,
  8787. cancelBattle: 0,
  8788. }
  8789.  
  8790. callsExecuteRaidNodes = {
  8791. calls: [{
  8792. name: "clanRaid_getInfo",
  8793. args: {},
  8794. ident: "clanRaid_getInfo"
  8795. }, {
  8796. name: "teamGetAll",
  8797. args: {},
  8798. ident: "teamGetAll"
  8799. }, {
  8800. name: "teamGetFavor",
  8801. args: {},
  8802. ident: "teamGetFavor"
  8803. }]
  8804. }
  8805.  
  8806. this.start = function () {
  8807. send(JSON.stringify(callsExecuteRaidNodes), startRaidNodes);
  8808. }
  8809.  
  8810. async function startRaidNodes(data) {
  8811. res = data.results;
  8812. clanRaidInfo = res[0].result.response;
  8813. teamGetAll = res[1].result.response;
  8814. teamGetFavor = res[2].result.response;
  8815.  
  8816. let index = 0;
  8817. let isNotFullPack = false;
  8818. for (let team of teamGetAll.clanRaid_nodes) {
  8819. if (team.length < 6) {
  8820. isNotFullPack = true;
  8821. }
  8822. raidData.teams.push({
  8823. data: {},
  8824. heroes: team.filter(id => id < 6000),
  8825. pet: team.filter(id => id >= 6000).pop(),
  8826. battleIndex: index++
  8827. });
  8828. }
  8829. raidData.favor = teamGetFavor.clanRaid_nodes;
  8830.  
  8831. if (isNotFullPack) {
  8832. if (await popup.confirm(I18N('MINIONS_WARNING'), [
  8833. { msg: I18N('BTN_NO'), result: true },
  8834. { msg: I18N('BTN_YES'), result: false },
  8835. ])) {
  8836. endRaidNodes('isNotFullPack');
  8837. return;
  8838. }
  8839. }
  8840.  
  8841. raidData.nodes = clanRaidInfo.nodes;
  8842. raidData.attempts = clanRaidInfo.attempts;
  8843. isCancalBattle = false;
  8844.  
  8845. checkNodes();
  8846. }
  8847.  
  8848. function getAttackNode() {
  8849. for (let nodeId in raidData.nodes) {
  8850. let node = raidData.nodes[nodeId];
  8851. let points = 0
  8852. for (team of node.teams) {
  8853. points += team.points;
  8854. }
  8855. let now = Date.now() / 1000;
  8856. if (!points && now > node.timestamps.start && now < node.timestamps.end) {
  8857. let countTeam = node.teams.length;
  8858. delete raidData.nodes[nodeId];
  8859. return {
  8860. nodeId,
  8861. countTeam
  8862. };
  8863. }
  8864. }
  8865. return null;
  8866. }
  8867.  
  8868. function checkNodes() {
  8869. setProgress(`${I18N('REMAINING_ATTEMPTS')}: ${raidData.attempts}`);
  8870. let nodeInfo = getAttackNode();
  8871. if (nodeInfo && raidData.attempts) {
  8872. startNodeBattles(nodeInfo);
  8873. return;
  8874. }
  8875.  
  8876. endRaidNodes('EndRaidNodes');
  8877. }
  8878.  
  8879. function startNodeBattles(nodeInfo) {
  8880. let {nodeId, countTeam} = nodeInfo;
  8881. let teams = raidData.teams.slice(0, countTeam);
  8882. let heroes = raidData.teams.map(e => e.heroes).flat();
  8883. let favor = {...raidData.favor};
  8884. for (let heroId in favor) {
  8885. if (!heroes.includes(+heroId)) {
  8886. delete favor[heroId];
  8887. }
  8888. }
  8889.  
  8890. let calls = [{
  8891. name: "clanRaid_startNodeBattles",
  8892. args: {
  8893. nodeId,
  8894. teams,
  8895. favor
  8896. },
  8897. ident: "body"
  8898. }];
  8899.  
  8900. send(JSON.stringify({calls}), resultNodeBattles);
  8901. }
  8902.  
  8903. function resultNodeBattles(e) {
  8904. if (e['error']) {
  8905. endRaidNodes('nodeBattlesError', e['error']);
  8906. return;
  8907. }
  8908.  
  8909. console.log(e);
  8910. let battles = e.results[0].result.response.battles;
  8911. let promises = [];
  8912. let battleIndex = 0;
  8913. for (let battle of battles) {
  8914. battle.battleIndex = battleIndex++;
  8915. promises.push(calcBattleResult(battle));
  8916. }
  8917.  
  8918. Promise.all(promises)
  8919. .then(results => {
  8920. const endResults = {};
  8921. let isAllWin = true;
  8922. for (let r of results) {
  8923. isAllWin &&= r.result.win;
  8924. }
  8925. if (!isAllWin) {
  8926. cancelEndNodeBattle(results[0]);
  8927. return;
  8928. }
  8929. raidData.countExecuteBattles = results.length;
  8930. let timeout = 500;
  8931. for (let r of results) {
  8932. setTimeout(endNodeBattle, timeout, r);
  8933. timeout += 500;
  8934. }
  8935. });
  8936. }
  8937. /**
  8938. * Returns the battle calculation promise
  8939. *
  8940. * Возвращает промис расчета боя
  8941. */
  8942. function calcBattleResult(battleData) {
  8943. return new Promise(function (resolve, reject) {
  8944. BattleCalc(battleData, "get_clanPvp", resolve);
  8945. });
  8946. }
  8947. /**
  8948. * Cancels the fight
  8949. *
  8950. * Отменяет бой
  8951. */
  8952. function cancelEndNodeBattle(r) {
  8953. const fixBattle = function (heroes) {
  8954. for (const ids in heroes) {
  8955. hero = heroes[ids];
  8956. hero.energy = random(1, 999);
  8957. if (hero.hp > 0) {
  8958. hero.hp = random(1, hero.hp);
  8959. }
  8960. }
  8961. }
  8962. fixBattle(r.progress[0].attackers.heroes);
  8963. fixBattle(r.progress[0].defenders.heroes);
  8964. endNodeBattle(r);
  8965. }
  8966. /**
  8967. * Ends the fight
  8968. *
  8969. * Завершает бой
  8970. */
  8971. function endNodeBattle(r) {
  8972. let nodeId = r.battleData.result.nodeId;
  8973. let battleIndex = r.battleData.battleIndex;
  8974. let calls = [{
  8975. name: "clanRaid_endNodeBattle",
  8976. args: {
  8977. nodeId,
  8978. battleIndex,
  8979. result: r.result,
  8980. progress: r.progress
  8981. },
  8982. ident: "body"
  8983. }]
  8984.  
  8985. SendRequest(JSON.stringify({calls}), battleResult);
  8986. }
  8987. /**
  8988. * Processing the results of the battle
  8989. *
  8990. * Обработка результатов боя
  8991. */
  8992. function battleResult(e) {
  8993. if (e['error']) {
  8994. endRaidNodes('missionEndError', e['error']);
  8995. return;
  8996. }
  8997. r = e.results[0].result.response;
  8998. if (r['error']) {
  8999. if (r.reason == "invalidBattle") {
  9000. raidData.cancelBattle++;
  9001. checkNodes();
  9002. } else {
  9003. endRaidNodes('missionEndError', e['error']);
  9004. }
  9005. return;
  9006. }
  9007.  
  9008. if (!(--raidData.countExecuteBattles)) {
  9009. raidData.attempts--;
  9010. checkNodes();
  9011. }
  9012. }
  9013. /**
  9014. * Completing a task
  9015. *
  9016. * Завершение задачи
  9017. */
  9018. function endRaidNodes(reason, info) {
  9019. isCancalBattle = true;
  9020. let textCancel = raidData.cancelBattle ? ` ${I18N('BATTLES_CANCELED')}: ${raidData.cancelBattle}` : '';
  9021. setProgress(`${I18N('MINION_RAID')} ${I18N('COMPLETED')}! ${textCancel}`, true);
  9022. console.log(reason, info);
  9023. resolve();
  9024. }
  9025. }
  9026.  
  9027. /**
  9028. * Asgard Boss Attack Replay
  9029. *
  9030. * Повтор атаки босса Асгарда
  9031. */
  9032. function testBossBattle() {
  9033. return new Promise((resolve, reject) => {
  9034. const bossBattle = new executeBossBattle(resolve, reject);
  9035. bossBattle.start(lastBossBattle, lastBossBattleInfo);
  9036. });
  9037. }
  9038.  
  9039. /**
  9040. * Asgard Boss Attack Replay
  9041. *
  9042. * Повтор атаки босса Асгарда
  9043. */
  9044. function executeBossBattle(resolve, reject) {
  9045. let lastBossBattleArgs = {};
  9046. let reachDamage = 0;
  9047. let countBattle = 0;
  9048. let countMaxBattle = 10;
  9049. let lastDamage = 0;
  9050.  
  9051. this.start = function (battleArg, battleInfo) {
  9052. lastBossBattleArgs = battleArg;
  9053. preCalcBattle(battleInfo);
  9054. }
  9055.  
  9056. function getBattleInfo(battle) {
  9057. return new Promise(function (resolve) {
  9058. battle.seed = Math.floor(Date.now() / 1000) + random(0, 1e3);
  9059. BattleCalc(battle, getBattleType(battle.type), e => {
  9060. let extra = e.progress[0].defenders.heroes[1].extra;
  9061. resolve(extra.damageTaken + extra.damageTakenNextLevel);
  9062. });
  9063. });
  9064. }
  9065.  
  9066. function preCalcBattle(battle) {
  9067. let actions = [];
  9068. const countTestBattle = getInput('countTestBattle');
  9069. for (let i = 0; i < countTestBattle; i++) {
  9070. actions.push(getBattleInfo(battle, true));
  9071. }
  9072. Promise.all(actions)
  9073. .then(resultPreCalcBattle);
  9074. }
  9075.  
  9076. function fixDamage(damage) {
  9077. for (let i = 1e6; i > 1; i /= 10) {
  9078. if (damage > i) {
  9079. let n = i / 10;
  9080. damage = Math.ceil(damage / n) * n;
  9081. break;
  9082. }
  9083. }
  9084. return damage;
  9085. }
  9086.  
  9087. async function resultPreCalcBattle(damages) {
  9088. let maxDamage = 0;
  9089. let minDamage = 1e10;
  9090. let avgDamage = 0;
  9091. for (let damage of damages) {
  9092. avgDamage += damage
  9093. if (damage > maxDamage) {
  9094. maxDamage = damage;
  9095. }
  9096. if (damage < minDamage) {
  9097. minDamage = damage;
  9098. }
  9099. }
  9100. avgDamage /= damages.length;
  9101. console.log(damages.map(e => e.toLocaleString()).join('\n'), avgDamage, maxDamage);
  9102.  
  9103. reachDamage = fixDamage(avgDamage);
  9104. const result = await popup.confirm(
  9105. `${I18N('ROUND_STAT')} ${damages.length} ${I18N('BATTLE')}:` +
  9106. `<br>${I18N('MINIMUM')}: ` + minDamage.toLocaleString() +
  9107. `<br>${I18N('MAXIMUM')}: ` + maxDamage.toLocaleString() +
  9108. `<br>${I18N('AVERAGE')}: ` + avgDamage.toLocaleString()
  9109. /*+ '<br>Поиск урона больше чем ' + reachDamage.toLocaleString()*/
  9110. , [
  9111. { msg: I18N('BTN_OK'), result: 0},
  9112. /* {msg: 'Погнали', isInput: true, default: reachDamage}, */
  9113. ])
  9114. if (result) {
  9115. reachDamage = result;
  9116. isCancalBossBattle = false;
  9117. startBossBattle();
  9118. return;
  9119. }
  9120. endBossBattle(I18N('BTN_CANCEL'));
  9121. }
  9122.  
  9123. function startBossBattle() {
  9124. countBattle++;
  9125. countMaxBattle = getInput('countAutoBattle');
  9126. if (countBattle > countMaxBattle) {
  9127. setProgress('Превышен лимит попыток: ' + countMaxBattle, true);
  9128. endBossBattle('Превышен лимит попыток: ' + countMaxBattle);
  9129. return;
  9130. }
  9131. let calls = [{
  9132. name: "clanRaid_startBossBattle",
  9133. args: lastBossBattleArgs,
  9134. ident: "body"
  9135. }];
  9136. send(JSON.stringify({calls}), calcResultBattle);
  9137. }
  9138.  
  9139. function calcResultBattle(e) {
  9140. BattleCalc(e.results[0].result.response.battle, "get_clanPvp", resultBattle);
  9141. }
  9142.  
  9143. async function resultBattle(e) {
  9144. let extra = e.progress[0].defenders.heroes[1].extra
  9145. resultDamage = extra.damageTaken + extra.damageTakenNextLevel
  9146. console.log(resultDamage);
  9147. scriptMenu.setStatus(countBattle + ') ' + resultDamage.toLocaleString());
  9148. lastDamage = resultDamage;
  9149. if (resultDamage > reachDamage && await popup.confirm(countBattle + ') Урон ' + resultDamage.toLocaleString(), [
  9150. {msg: 'Ок', result: true},
  9151. {msg: 'Не пойдет', result: false},
  9152. ])) {
  9153. endBattle(e, false);
  9154. return;
  9155. }
  9156. cancelEndBattle(e);
  9157. }
  9158.  
  9159. function cancelEndBattle (r) {
  9160. const fixBattle = function (heroes) {
  9161. for (const ids in heroes) {
  9162. hero = heroes[ids];
  9163. hero.energy = random(1, 999);
  9164. if (hero.hp > 0) {
  9165. hero.hp = random(1, hero.hp);
  9166. }
  9167. }
  9168. }
  9169. fixBattle(r.progress[0].attackers.heroes);
  9170. fixBattle(r.progress[0].defenders.heroes);
  9171. endBattle(r, true);
  9172. }
  9173.  
  9174. function endBattle(battleResult, isCancal) {
  9175. let calls = [{
  9176. name: "clanRaid_endBossBattle",
  9177. args: {
  9178. result: battleResult.result,
  9179. progress: battleResult.progress
  9180. },
  9181. ident: "body"
  9182. }];
  9183.  
  9184. send(JSON.stringify({calls}), e => {
  9185. console.log(e);
  9186. if (isCancal) {
  9187. startBossBattle();
  9188. return;
  9189. }
  9190. scriptMenu.setStatus('Босс пробит нанесен урон: ' + lastDamage);
  9191. setTimeout(() => {
  9192. scriptMenu.setStatus('');
  9193. }, 5000);
  9194. endBossBattle('Узпех!');
  9195. });
  9196. }
  9197.  
  9198. /**
  9199. * Completing a task
  9200. *
  9201. * Завершение задачи
  9202. */
  9203. function endBossBattle(reason, info) {
  9204. isCancalBossBattle = true;
  9205. console.log(reason, info);
  9206. resolve();
  9207. }
  9208. }
  9209.  
  9210. /**
  9211. * Auto-repeat attack
  9212. *
  9213. * Автоповтор атаки
  9214. */
  9215. function testAutoBattle() {
  9216. return new Promise((resolve, reject) => {
  9217. const bossBattle = new executeAutoBattle(resolve, reject);
  9218. bossBattle.start(lastBattleArg, lastBattleInfo);
  9219. });
  9220. }
  9221.  
  9222. /**
  9223. * Auto-repeat attack
  9224. *
  9225. * Автоповтор атаки
  9226. */
  9227. function executeAutoBattle(resolve, reject) {
  9228. let battleArg = {};
  9229. let countBattle = 0;
  9230. let countError = 0;
  9231. let findCoeff = 0;
  9232. 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>';
  9233. 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>';
  9234. 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>';
  9235.  
  9236. this.start = function (battleArgs, battleInfo) {
  9237. battleArg = battleArgs;
  9238. preCalcBattle(battleInfo);
  9239. }
  9240. /**
  9241. * Returns a promise for combat recalculation
  9242. *
  9243. * Возвращает промис для прерасчета боя
  9244. */
  9245. function getBattleInfo(battle) {
  9246. return new Promise(function (resolve) {
  9247. battle.seed = Math.floor(Date.now() / 1000) + random(0, 1e3);
  9248. Calc(battle).then(e => {
  9249. e.coeff = calcCoeff(e, 'defenders');
  9250. resolve(e);
  9251. });
  9252. });
  9253. }
  9254. /**
  9255. * Battle recalculation
  9256. *
  9257. * Прерасчет боя
  9258. */
  9259. function preCalcBattle(battle) {
  9260. let actions = [];
  9261. const countTestBattle = getInput('countTestBattle');
  9262. for (let i = 0; i < countTestBattle; i++) {
  9263. actions.push(getBattleInfo(battle));
  9264. }
  9265. Promise.all(actions)
  9266. .then(resultPreCalcBattle);
  9267. }
  9268. /**
  9269. * Processing the results of the battle recalculation
  9270. *
  9271. * Обработка результатов прерасчета боя
  9272. */
  9273. async function resultPreCalcBattle(results) {
  9274. let countWin = results.reduce((s, w) => w.result.win + s, 0);
  9275. setProgress(`${I18N('CHANCE_TO_WIN')} ${Math.floor(countWin / results.length * 100)}% (${results.length})`, false, hideProgress);
  9276. if (countWin > 0) {
  9277. isCancalBattle = false;
  9278. startBattle();
  9279. return;
  9280. }
  9281.  
  9282. let minCoeff = 100;
  9283. let maxCoeff = -100;
  9284. let avgCoeff = 0;
  9285. results.forEach(e => {
  9286. if (e.coeff < minCoeff) minCoeff = e.coeff;
  9287. if (e.coeff > maxCoeff) maxCoeff = e.coeff;
  9288. avgCoeff += e.coeff;
  9289. });
  9290. avgCoeff /= results.length;
  9291.  
  9292. if (nameFuncStartBattle == 'invasion_bossStart' ||
  9293. nameFuncStartBattle == 'bossAttack') {
  9294. const result = await popup.confirm(
  9295. I18N('BOSS_VICTORY_IMPOSSIBLE', { battles: results.length }), [
  9296. { msg: I18N('BTN_CANCEL'), result: false, isCancel: true },
  9297. { msg: I18N('BTN_DO_IT'), result: true },
  9298. ])
  9299. if (result) {
  9300. isCancalBattle = false;
  9301. startBattle();
  9302. return;
  9303. }
  9304. setProgress(I18N('NOT_THIS_TIME'), true);
  9305. endAutoBattle('invasion_bossStart');
  9306. return;
  9307. }
  9308.  
  9309. const result = await popup.confirm(
  9310. I18N('VICTORY_IMPOSSIBLE') +
  9311. `<br>${I18N('ROUND_STAT')} ${results.length} ${I18N('BATTLE')}:` +
  9312. `<br>${I18N('MINIMUM')}: ` + minCoeff.toLocaleString() +
  9313. `<br>${I18N('MAXIMUM')}: ` + maxCoeff.toLocaleString() +
  9314. `<br>${I18N('AVERAGE')}: ` + avgCoeff.toLocaleString() +
  9315. `<br>${I18N('FIND_COEFF')} ` + avgCoeff.toLocaleString(), [
  9316. { msg: I18N('BTN_CANCEL'), result: 0, isCancel: true },
  9317. { msg: I18N('BTN_GO'), isInput: true, default: Math.round(avgCoeff * 1000) / 1000 },
  9318. ])
  9319. if (result) {
  9320. findCoeff = result;
  9321. isCancalBattle = false;
  9322. startBattle();
  9323. return;
  9324. }
  9325. setProgress(I18N('NOT_THIS_TIME'), true);
  9326. endAutoBattle(I18N('NOT_THIS_TIME'));
  9327. }
  9328.  
  9329. /**
  9330. * Calculation of the combat result coefficient
  9331. *
  9332. * Расчет коэфициента результата боя
  9333. */
  9334. function calcCoeff(result, packType) {
  9335. let beforeSumFactor = 0;
  9336. const beforePack = result.battleData[packType][0];
  9337. for (let heroId in beforePack) {
  9338. const hero = beforePack[heroId];
  9339. const state = hero.state;
  9340. let factor = 1;
  9341. if (state) {
  9342. const hp = state.hp / state.maxHp;
  9343. const energy = state.energy / 1e3;
  9344. factor = hp + energy / 20;
  9345. }
  9346. beforeSumFactor += factor;
  9347. }
  9348.  
  9349. let afterSumFactor = 0;
  9350. const afterPack = result.progress[0][packType].heroes;
  9351. for (let heroId in afterPack) {
  9352. const hero = afterPack[heroId];
  9353. const stateHp = beforePack[heroId]?.state?.hp || beforePack[heroId]?.stats?.hp;
  9354. const hp = hero.hp / stateHp;
  9355. const energy = hero.energy / 1e3;
  9356. const factor = hp + energy / 20;
  9357. afterSumFactor += factor;
  9358. }
  9359. const resultCoeff = -(afterSumFactor - beforeSumFactor);
  9360. return Math.round(resultCoeff * 1000) / 1000;
  9361. }
  9362. /**
  9363. * Start battle
  9364. *
  9365. * Начало боя
  9366. */
  9367. function startBattle() {
  9368. countBattle++;
  9369. const countMaxBattle = getInput('countAutoBattle');
  9370. // setProgress(countBattle + '/' + countMaxBattle);
  9371. if (countBattle > countMaxBattle) {
  9372. setProgress(`${I18N('RETRY_LIMIT_EXCEEDED')}: ${countMaxBattle}`, true);
  9373. endAutoBattle(`${I18N('RETRY_LIMIT_EXCEEDED')}: ${countMaxBattle}`)
  9374. return;
  9375. }
  9376. send({calls: [{
  9377. name: nameFuncStartBattle,
  9378. args: battleArg,
  9379. ident: "body"
  9380. }]}, calcResultBattle);
  9381. }
  9382. /**
  9383. * Battle calculation
  9384. *
  9385. * Расчет боя
  9386. */
  9387. async function calcResultBattle(e) {
  9388. if ('error' in e) {
  9389. if (e.error.description === 'too many tries') {
  9390. invasionTimer += 100;
  9391. countBattle--;
  9392. countError++;
  9393. console.log(`Errors: ${countError}`, e.error);
  9394. startBattle();
  9395. return;
  9396. }
  9397. const result = await popup.confirm(I18N('ERROR_DURING_THE_BATTLE') + '<br>' + e.error.description, [
  9398. { msg: I18N('BTN_OK'), result: false },
  9399. { msg: I18N('RELOAD_GAME'), result: true },
  9400. ]);
  9401. endAutoBattle('Error', e.error);
  9402. if (result) {
  9403. location.reload();
  9404. }
  9405. return;
  9406. }
  9407. let battle = e.results[0].result.response.battle
  9408. if (nameFuncStartBattle == 'towerStartBattle' ||
  9409. nameFuncStartBattle == 'bossAttack' ||
  9410. nameFuncStartBattle == 'invasion_bossStart') {
  9411. battle = e.results[0].result.response;
  9412. }
  9413. lastBattleInfo = battle;
  9414. BattleCalc(battle, getBattleType(battle.type), resultBattle);
  9415. }
  9416. /**
  9417. * Processing the results of the battle
  9418. *
  9419. * Обработка результатов боя
  9420. */
  9421. function resultBattle(e) {
  9422. const isWin = e.result.win;
  9423. if (isWin) {
  9424. endBattle(e, false);
  9425. return;
  9426. }
  9427. const countMaxBattle = getInput('countAutoBattle');
  9428. if (findCoeff) {
  9429. const coeff = calcCoeff(e, 'defenders');
  9430. setProgress(`${countBattle}/${countMaxBattle}, ${coeff}`);
  9431. if (coeff > findCoeff) {
  9432. endBattle(e, false);
  9433. return;
  9434. }
  9435. } else {
  9436. if (nameFuncStartBattle == 'invasion_bossStart') {
  9437. const bossLvl = lastBattleInfo.typeId >= 130 ? lastBattleInfo.typeId : '';
  9438. const justice = lastBattleInfo?.effects?.attackers?.percentInOutDamageMod_any_99_100_300_99_1000 || 0;
  9439. setProgress(`${svgBoss} ${bossLvl} ${svgJustice} ${justice} <br>${svgAttempt} ${countBattle}/${countMaxBattle}`);
  9440. } else {
  9441. setProgress(`${countBattle}/${countMaxBattle}`);
  9442. }
  9443. }
  9444. if (nameFuncStartBattle == 'towerStartBattle' ||
  9445. nameFuncStartBattle == 'bossAttack' ||
  9446. nameFuncStartBattle == 'invasion_bossStart') {
  9447. startBattle();
  9448. return;
  9449. }
  9450. cancelEndBattle(e);
  9451. }
  9452. /**
  9453. * Cancel fight
  9454. *
  9455. * Отмена боя
  9456. */
  9457. function cancelEndBattle(r) {
  9458. const fixBattle = function (heroes) {
  9459. for (const ids in heroes) {
  9460. hero = heroes[ids];
  9461. hero.energy = random(1, 999);
  9462. if (hero.hp > 0) {
  9463. hero.hp = random(1, hero.hp);
  9464. }
  9465. }
  9466. }
  9467. fixBattle(r.progress[0].attackers.heroes);
  9468. fixBattle(r.progress[0].defenders.heroes);
  9469. endBattle(r, true);
  9470. }
  9471. /**
  9472. * End of the fight
  9473. *
  9474. * Завершение боя */
  9475. function endBattle(battleResult, isCancal) {
  9476. let calls = [{
  9477. name: nameFuncEndBattle,
  9478. args: {
  9479. result: battleResult.result,
  9480. progress: battleResult.progress
  9481. },
  9482. ident: "body"
  9483. }];
  9484.  
  9485. if (nameFuncStartBattle == 'invasion_bossStart') {
  9486. calls[0].args.id = lastBattleArg.id;
  9487. }
  9488.  
  9489. send(JSON.stringify({
  9490. calls
  9491. }), async e => {
  9492. console.log(e);
  9493. if (isCancal) {
  9494. startBattle();
  9495. return;
  9496. }
  9497.  
  9498. setProgress(`${I18N('SUCCESS')}!`, 5000)
  9499. if (nameFuncStartBattle == 'invasion_bossStart' ||
  9500. nameFuncStartBattle == 'bossAttack') {
  9501. const countMaxBattle = getInput('countAutoBattle');
  9502. const bossLvl = lastBattleInfo.typeId >= 130 ? lastBattleInfo.typeId : '';
  9503. const justice = lastBattleInfo?.effects?.attackers?.percentInOutDamageMod_any_99_100_300_99_1000 || 0;
  9504. const result = await popup.confirm(
  9505. I18N('BOSS_HAS_BEEN_DEF_TEXT', {
  9506. bossLvl: `${svgBoss} ${bossLvl} ${svgJustice} ${justice}`,
  9507. countBattle: svgAttempt + ' ' + countBattle,
  9508. countMaxBattle,}),
  9509. [
  9510. { msg: I18N('BTN_OK'), result: 0 },
  9511. { msg: I18N('MAKE_A_SYNC'), result: 1 },
  9512. { msg: I18N('RELOAD_GAME'), result: 2 },
  9513. ]);
  9514. if (result) {
  9515. if (result == 1) {
  9516. cheats.refreshGame();
  9517. }
  9518. if (result == 2) {
  9519. location.reload();
  9520. }
  9521. }
  9522.  
  9523. }
  9524. endAutoBattle(`${I18N('SUCCESS')}!`)
  9525. });
  9526. }
  9527. /**
  9528. * Completing a task
  9529. *
  9530. * Завершение задачи
  9531. */
  9532. function endAutoBattle(reason, info) {
  9533. isCancalBattle = true;
  9534. console.log(reason, info);
  9535. resolve();
  9536. }
  9537. }
  9538.  
  9539. function testDailyQuests() {
  9540. return new Promise((resolve, reject) => {
  9541. const quests = new dailyQuests(resolve, reject);
  9542. quests.init(questsInfo);
  9543. quests.start();
  9544. });
  9545. }
  9546.  
  9547. /**
  9548. * Automatic completion of daily quests
  9549. *
  9550. * Автоматическое выполнение ежедневных квестов
  9551. */
  9552. class dailyQuests {
  9553. /**
  9554. * Send(' {"calls":[{"name":"userGetInfo","args":{},"ident":"body"}]}').then(e => console.log(e))
  9555. * Send(' {"calls":[{"name":"heroGetAll","args":{},"ident":"body"}]}').then(e => console.log(e))
  9556. * Send(' {"calls":[{"name":"titanGetAll","args":{},"ident":"body"}]}').then(e => console.log(e))
  9557. * Send(' {"calls":[{"name":"inventoryGet","args":{},"ident":"body"}]}').then(e => console.log(e))
  9558. * Send(' {"calls":[{"name":"questGetAll","args":{},"ident":"body"}]}').then(e => console.log(e))
  9559. * Send(' {"calls":[{"name":"bossGetAll","args":{},"ident":"body"}]}').then(e => console.log(e))
  9560. */
  9561. callsList = [
  9562. "userGetInfo",
  9563. "heroGetAll",
  9564. "titanGetAll",
  9565. "inventoryGet",
  9566. "questGetAll",
  9567. "bossGetAll",
  9568. ]
  9569.  
  9570. dataQuests = {
  9571. 10001: {
  9572. description: 'Улучши умения героев 3 раза', // ++++++++++++++++
  9573. doItCall: () => {
  9574. const upgradeSkills = this.getUpgradeSkills();
  9575. return upgradeSkills.map(({ heroId, skill }, index) => ({ name: "heroUpgradeSkill", args: { heroId, skill }, "ident": `heroUpgradeSkill_${index}` }));
  9576. },
  9577. isWeCanDo: () => {
  9578. const upgradeSkills = this.getUpgradeSkills();
  9579. let sumGold = 0;
  9580. for (const skill of upgradeSkills) {
  9581. sumGold += this.skillCost(skill.value);
  9582. if (!skill.heroId) {
  9583. return false;
  9584. }
  9585. }
  9586. return this.questInfo['userGetInfo'].gold > sumGold;
  9587. },
  9588. },
  9589. 10002: {
  9590. description: 'Пройди 10 миссий', // --------------
  9591. isWeCanDo: () => false,
  9592. },
  9593. 10003: {
  9594. description: 'Пройди 3 героические миссии', // --------------
  9595. isWeCanDo: () => false,
  9596. },
  9597. 10004: {
  9598. description: 'Сразись 3 раза на Арене или Гранд Арене', // --------------
  9599. isWeCanDo: () => false,
  9600. },
  9601. 10006: {
  9602. description: 'Используй обмен изумрудов 1 раз', // ++++++++++++++++
  9603. doItCall: () => [{
  9604. name: "refillableAlchemyUse",
  9605. args: { multi: false },
  9606. ident: "refillableAlchemyUse"
  9607. }],
  9608. isWeCanDo: () => {
  9609. const starMoney = this.questInfo['userGetInfo'].starMoney;
  9610. return starMoney >= 20;
  9611. },
  9612. },
  9613. 10007: {
  9614. description: 'Соверши 1 призыв в Атриуме Душ', // ++++++++++++++++
  9615. doItCall: () => [{ name: "gacha_open", args: { ident: "heroGacha", free: true, pack: false }, ident: "gacha_open" }],
  9616. isWeCanDo: () => {
  9617. const soulCrystal = this.questInfo['inventoryGet'].coin[38];
  9618. return soulCrystal > 0;
  9619. },
  9620. },
  9621. /*10016: {
  9622. description: 'Отправь подарки согильдийцам', // ++++++++++++++++
  9623. doItCall: () => [{ name: "clanSendDailyGifts", args: {}, ident: "clanSendDailyGifts" }],
  9624. isWeCanDo: () => true,
  9625. },*/
  9626. 10018: {
  9627. description: 'Используй зелье опыта', // ++++++++++++++++
  9628. doItCall: () => {
  9629. const expHero = this.getExpHero();
  9630. return [{
  9631. name: "consumableUseHeroXp",
  9632. args: {
  9633. heroId: expHero.heroId,
  9634. libId: expHero.libId,
  9635. amount: 1
  9636. },
  9637. ident: "consumableUseHeroXp"
  9638. }];
  9639. },
  9640. isWeCanDo: () => {
  9641. const expHero = this.getExpHero();
  9642. return expHero.heroId && expHero.libId;
  9643. },
  9644. },
  9645. 10019: {
  9646. description: 'Открой 1 сундук в Башне',
  9647. doItFunc: testTower,
  9648. isWeCanDo: () => false,
  9649. },
  9650. 10020: {
  9651. description: 'Открой 3 сундука в Запределье', // Готово
  9652. doItCall: () => {
  9653. return this.getOutlandChest();
  9654. },
  9655. isWeCanDo: () => {
  9656. const outlandChest = this.getOutlandChest();
  9657. return outlandChest.length > 0;
  9658. },
  9659. },
  9660. 10021: {
  9661. description: 'Собери 75 Титанита в Подземелье Гильдии',
  9662. isWeCanDo: () => false,
  9663. },
  9664. 10022: {
  9665. description: 'Собери 150 Титанита в Подземелье Гильдии',
  9666. doItFunc: testDungeon,
  9667. isWeCanDo: () => false,
  9668. },
  9669. 10023: {
  9670. description: 'Прокачай Дар Стихий на 1 уровень', // Готово
  9671. doItCall: () => {
  9672. const heroId = this.getHeroIdTitanGift();
  9673. return [
  9674. { name: "heroTitanGiftLevelUp", args: { heroId }, ident: "heroTitanGiftLevelUp" },
  9675. { name: "heroTitanGiftDrop", args: { heroId }, ident: "heroTitanGiftDrop" }
  9676. ]
  9677. },
  9678. isWeCanDo: () => {
  9679. const heroId = this.getHeroIdTitanGift();
  9680. return heroId;
  9681. },
  9682. },
  9683. 10024: {
  9684. description: 'Повысь уровень любого артефакта один раз', // Готово
  9685. doItCall: () => {
  9686. const upArtifact = this.getUpgradeArtifact();
  9687. return [
  9688. {
  9689. name: "heroArtifactLevelUp",
  9690. args: {
  9691. heroId: upArtifact.heroId,
  9692. slotId: upArtifact.slotId
  9693. },
  9694. ident: `heroArtifactLevelUp`
  9695. }
  9696. ];
  9697. },
  9698. isWeCanDo: () => {
  9699. const upgradeArtifact = this.getUpgradeArtifact();
  9700. return upgradeArtifact.heroId;
  9701. },
  9702. },
  9703. 10025: {
  9704. description: 'Начни 1 Экспедицию',
  9705. doItFunc: checkExpedition,
  9706. isWeCanDo: () => false,
  9707. },
  9708. 10026: {
  9709. description: 'Начни 4 Экспедиции', // --------------
  9710. doItFunc: checkExpedition,
  9711. isWeCanDo: () => false,
  9712. },
  9713. 10027: {
  9714. description: 'Победи в 1 бою Турнира Стихий',
  9715. doItFunc: testTitanArena,
  9716. isWeCanDo: () => false,
  9717. },
  9718. 10028: {
  9719. description: 'Повысь уровень любого артефакта титанов', // Готово
  9720. doItCall: () => {
  9721. const upTitanArtifact = this.getUpgradeTitanArtifact();
  9722. return [
  9723. {
  9724. name: "titanArtifactLevelUp",
  9725. args: {
  9726. titanId: upTitanArtifact.titanId,
  9727. slotId: upTitanArtifact.slotId
  9728. },
  9729. ident: `titanArtifactLevelUp`
  9730. }
  9731. ];
  9732. },
  9733. isWeCanDo: () => {
  9734. const upgradeTitanArtifact = this.getUpgradeTitanArtifact();
  9735. return upgradeTitanArtifact.titanId;
  9736. },
  9737. },
  9738. 10029: {
  9739. description: 'Открой сферу артефактов титанов', // ++++++++++++++++
  9740. doItCall: () => [{ name: "titanArtifactChestOpen", args: { amount: 1, free: true }, ident: "titanArtifactChestOpen" }],
  9741. isWeCanDo: () => {
  9742. return this.questInfo['inventoryGet']?.consumable[55] > 0
  9743. },
  9744. },
  9745. 10030: {
  9746. description: 'Улучши облик любого героя 1 раз', // Готово
  9747. doItCall: () => {
  9748. const upSkin = this.getUpgradeSkin();
  9749. return [
  9750. {
  9751. name: "heroSkinUpgrade",
  9752. args: {
  9753. heroId: upSkin.heroId,
  9754. skinId: upSkin.skinId
  9755. },
  9756. ident: `heroSkinUpgrade`
  9757. }
  9758. ];
  9759. },
  9760. isWeCanDo: () => {
  9761. const upgradeSkin = this.getUpgradeSkin();
  9762. return upgradeSkin.heroId;
  9763. },
  9764. },
  9765. 10031: {
  9766. description: 'Победи в 6 боях Турнира Стихий', // --------------
  9767. doItFunc: testTitanArena,
  9768. isWeCanDo: () => false,
  9769. },
  9770. 10043: {
  9771. description: 'Начни или присоеденись к Приключению', // --------------
  9772. isWeCanDo: () => false,
  9773. },
  9774. 10044: {
  9775. description: 'Воспользуйся призывом питомцев 1 раз', // ++++++++++++++++
  9776. doItCall: () => [{ name: "pet_chestOpen", args: { amount: 1, paid: false }, ident: "pet_chestOpen" }],
  9777. isWeCanDo: () => {
  9778. return this.questInfo['inventoryGet']?.consumable[90] > 0
  9779. },
  9780. },
  9781. 10046: {
  9782. /**
  9783. * TODO: Watch Adventure
  9784. * TODO: Смотреть приключение
  9785. */
  9786. description: 'Открой 3 сундука в Приключениях',
  9787. isWeCanDo: () => false,
  9788. },
  9789. 10047: {
  9790. description: 'Набери 150 очков активности в Гильдии', // Готово
  9791. doItCall: () => {
  9792. const enchantRune = this.getEnchantRune();
  9793. return [
  9794. {
  9795. name: "heroEnchantRune",
  9796. args: {
  9797. heroId: enchantRune.heroId,
  9798. tier: enchantRune.tier,
  9799. items: {
  9800. consumable: { [enchantRune.itemId]: 1 }
  9801. }
  9802. },
  9803. ident: `heroEnchantRune`
  9804. }
  9805. ];
  9806. },
  9807. isWeCanDo: () => {
  9808. const userInfo = this.questInfo['userGetInfo'];
  9809. const enchantRune = this.getEnchantRune();
  9810. return enchantRune.heroId && userInfo.gold > 1e3;
  9811. },
  9812. },
  9813. };
  9814.  
  9815. constructor(resolve, reject, questInfo) {
  9816. this.resolve = resolve;
  9817. this.reject = reject;
  9818. }
  9819.  
  9820. init(questInfo) {
  9821. this.questInfo = questInfo;
  9822. this.isAuto = false;
  9823. }
  9824.  
  9825. async autoInit(isAuto) {
  9826. this.isAuto = isAuto || false;
  9827. const quests = {};
  9828. const calls = this.callsList.map(name => ({
  9829. name, args: {}, ident: name
  9830. }))
  9831. const result = await Send(JSON.stringify({ calls })).then(e => e.results);
  9832. for (const call of result) {
  9833. quests[call.ident] = call.result.response;
  9834. }
  9835. this.questInfo = quests;
  9836. }
  9837.  
  9838. async start() {
  9839. const weCanDo = [];
  9840. const selectedActions = getSaveVal('selectedActions', {});
  9841. for (let quest of this.questInfo['questGetAll']) {
  9842. if (quest.id in this.dataQuests && quest.state == 1) {
  9843. if (!selectedActions[quest.id]) {
  9844. selectedActions[quest.id] = {
  9845. checked: false
  9846. }
  9847. }
  9848.  
  9849. const isWeCanDo = this.dataQuests[quest.id].isWeCanDo;
  9850. if (!isWeCanDo.call(this)) {
  9851. continue;
  9852. }
  9853.  
  9854. weCanDo.push({
  9855. name: quest.id,
  9856. label: I18N(`QUEST_${quest.id}`),
  9857. checked: selectedActions[quest.id].checked
  9858. });
  9859. }
  9860. }
  9861.  
  9862. if (!weCanDo.length) {
  9863. this.end(I18N('NOTHING_TO_DO'));
  9864. return;
  9865. }
  9866.  
  9867. console.log(weCanDo);
  9868. let taskList = [];
  9869. if (this.isAuto) {
  9870. taskList = weCanDo;
  9871. } else {
  9872. const answer = await popup.confirm(`${I18N('YOU_CAN_COMPLETE') }:`, [
  9873. { msg: I18N('BTN_DO_IT'), result: true },
  9874. { msg: I18N('BTN_CANCEL'), result: false, isCancel: true },
  9875. ], weCanDo);
  9876. if (!answer) {
  9877. this.end('');
  9878. return;
  9879. }
  9880. taskList = popup.getCheckBoxes();
  9881. taskList.forEach(e => {
  9882. selectedActions[e.name].checked = e.checked;
  9883. });
  9884. setSaveVal('selectedActions', selectedActions);
  9885. }
  9886.  
  9887. const calls = [];
  9888. let countChecked = 0;
  9889. for (const task of taskList) {
  9890. if (task.checked) {
  9891. countChecked++;
  9892. const quest = this.dataQuests[task.name]
  9893. console.log(quest.description);
  9894.  
  9895. if (quest.doItCall) {
  9896. const doItCall = quest.doItCall.call(this);
  9897. calls.push(...doItCall);
  9898. }
  9899. }
  9900. }
  9901.  
  9902. if (!countChecked) {
  9903. this.end(I18N('NOT_QUEST_COMPLETED'));
  9904. return;
  9905. }
  9906.  
  9907. const result = await Send(JSON.stringify({ calls }));
  9908. if (result.error) {
  9909. console.error(result.error, result.error.call)
  9910. }
  9911. this.end(`${I18N('COMPLETED_QUESTS')}: ${countChecked}`);
  9912. }
  9913.  
  9914. errorHandling(error) {
  9915. //console.error(error);
  9916. let errorInfo = error.toString() + '\n';
  9917. try {
  9918. const errorStack = error.stack.split('\n');
  9919. const endStack = errorStack.map(e => e.split('@')[0]).indexOf("testDoYourBest");
  9920. errorInfo += errorStack.slice(0, endStack).join('\n');
  9921. } catch (e) {
  9922. errorInfo += error.stack;
  9923. }
  9924. copyText(errorInfo);
  9925. }
  9926.  
  9927. skillCost(lvl) {
  9928. return 573 * lvl ** 0.9 + lvl ** 2.379;
  9929. }
  9930.  
  9931. getUpgradeSkills() {
  9932. const heroes = Object.values(this.questInfo['heroGetAll']);
  9933. const upgradeSkills = [
  9934. { heroId: 0, slotId: 0, value: 130 },
  9935. { heroId: 0, slotId: 0, value: 130 },
  9936. { heroId: 0, slotId: 0, value: 130 },
  9937. ];
  9938. const skillLib = lib.getData('skill');
  9939. /**
  9940. * color - 1 (белый) открывает 1 навык
  9941. * color - 2 (зеленый) открывает 2 навык
  9942. * color - 4 (синий) открывает 3 навык
  9943. * color - 7 (фиолетовый) открывает 4 навык
  9944. */
  9945. const colors = [1, 2, 4, 7];
  9946. for (const hero of heroes) {
  9947. const level = hero.level;
  9948. const color = hero.color;
  9949. for (let skillId in hero.skills) {
  9950. const tier = skillLib[skillId].tier;
  9951. const sVal = hero.skills[skillId];
  9952. if (color < colors[tier] || tier < 1 || tier > 4) {
  9953. continue;
  9954. }
  9955. for (let upSkill of upgradeSkills) {
  9956. if (sVal < upSkill.value && sVal < level) {
  9957. upSkill.value = sVal;
  9958. upSkill.heroId = hero.id;
  9959. upSkill.skill = tier;
  9960. break;
  9961. }
  9962. }
  9963. }
  9964. }
  9965. return upgradeSkills;
  9966. }
  9967.  
  9968. getUpgradeArtifact() {
  9969. const heroes = Object.values(this.questInfo['heroGetAll']);
  9970. const inventory = this.questInfo['inventoryGet'];
  9971. const upArt = { heroId: 0, slotId: 0, level: 100 };
  9972.  
  9973. const heroLib = lib.getData('hero');
  9974. const artifactLib = lib.getData('artifact');
  9975.  
  9976. for (const hero of heroes) {
  9977. const heroInfo = heroLib[hero.id];
  9978. const level = hero.level
  9979. if (level < 20) {
  9980. continue;
  9981. }
  9982.  
  9983. for (let slotId in hero.artifacts) {
  9984. const art = hero.artifacts[slotId];
  9985. /* Текущая звезданость арта */
  9986. const star = art.star;
  9987. if (!star) {
  9988. continue;
  9989. }
  9990. /* Текущий уровень арта */
  9991. const level = art.level;
  9992. if (level >= 100) {
  9993. continue;
  9994. }
  9995. /* Идентификатор арта в библиотеке */
  9996. const artifactId = heroInfo.artifacts[slotId];
  9997. const artInfo = artifactLib.id[artifactId];
  9998. const costNextLevel = artifactLib.type[artInfo.type].levels[level + 1].cost;
  9999.  
  10000. const costСurrency = Object.keys(costNextLevel).pop();
  10001. const costValues = Object.entries(costNextLevel[costСurrency]).pop();
  10002. const costId = costValues[0];
  10003. const costValue = +costValues[1];
  10004.  
  10005. /** TODO: Возможно стоит искать самый высокий уровень который можно качнуть? */
  10006. if (level < upArt.level && inventory[costСurrency][costId] >= costValue) {
  10007. upArt.level = level;
  10008. upArt.heroId = hero.id;
  10009. upArt.slotId = slotId;
  10010. upArt.costСurrency = costСurrency;
  10011. upArt.costId = costId;
  10012. upArt.costValue = costValue;
  10013. }
  10014. }
  10015. }
  10016. return upArt;
  10017. }
  10018.  
  10019. getUpgradeSkin() {
  10020. const heroes = Object.values(this.questInfo['heroGetAll']);
  10021. const inventory = this.questInfo['inventoryGet'];
  10022. const upSkin = { heroId: 0, skinId: 0, level: 60, cost: 1500 };
  10023.  
  10024. const skinLib = lib.getData('skin');
  10025.  
  10026. for (const hero of heroes) {
  10027. const level = hero.level
  10028. if (level < 20) {
  10029. continue;
  10030. }
  10031.  
  10032. for (let skinId in hero.skins) {
  10033. /* Текущий уровень скина */
  10034. const level = hero.skins[skinId];
  10035. if (level >= 60) {
  10036. continue;
  10037. }
  10038. /* Идентификатор скина в библиотеке */
  10039. const skinInfo = skinLib[skinId];
  10040. if (!skinInfo.statData.levels?.[level + 1]) {
  10041. continue;
  10042. }
  10043. const costNextLevel = skinInfo.statData.levels[level + 1].cost;
  10044.  
  10045. const costСurrency = Object.keys(costNextLevel).pop();
  10046. const costСurrencyId = Object.keys(costNextLevel[costСurrency]).pop();
  10047. const costValue = +costNextLevel[costСurrency][costСurrencyId];
  10048.  
  10049. /** TODO: Возможно стоит искать самый высокий уровень который можно качнуть? */
  10050. if (level < upSkin.level &&
  10051. costValue < upSkin.cost &&
  10052. inventory[costСurrency][costСurrencyId] >= costValue) {
  10053. upSkin.cost = costValue;
  10054. upSkin.level = level;
  10055. upSkin.heroId = hero.id;
  10056. upSkin.skinId = skinId;
  10057. upSkin.costСurrency = costСurrency;
  10058. upSkin.costСurrencyId = costСurrencyId;
  10059. }
  10060. }
  10061. }
  10062. return upSkin;
  10063. }
  10064.  
  10065. getUpgradeTitanArtifact() {
  10066. const titans = Object.values(this.questInfo['titanGetAll']);
  10067. const inventory = this.questInfo['inventoryGet'];
  10068. const userInfo = this.questInfo['userGetInfo'];
  10069. const upArt = { titanId: 0, slotId: 0, level: 120 };
  10070.  
  10071. const titanLib = lib.getData('titan');
  10072. const artTitanLib = lib.getData('titanArtifact');
  10073.  
  10074. for (const titan of titans) {
  10075. const titanInfo = titanLib[titan.id];
  10076. // const level = titan.level
  10077. // if (level < 20) {
  10078. // continue;
  10079. // }
  10080.  
  10081. for (let slotId in titan.artifacts) {
  10082. const art = titan.artifacts[slotId];
  10083. /* Текущая звезданость арта */
  10084. const star = art.star;
  10085. if (!star) {
  10086. continue;
  10087. }
  10088. /* Текущий уровень арта */
  10089. const level = art.level;
  10090. if (level >= 120) {
  10091. continue;
  10092. }
  10093. /* Идентификатор арта в библиотеке */
  10094. const artifactId = titanInfo.artifacts[slotId];
  10095. const artInfo = artTitanLib.id[artifactId];
  10096. const costNextLevel = artTitanLib.type[artInfo.type].levels[level + 1].cost;
  10097.  
  10098. const costСurrency = Object.keys(costNextLevel).pop();
  10099. let costValue = 0;
  10100. let currentValue = 0;
  10101. if (costСurrency == 'gold') {
  10102. costValue = costNextLevel[costСurrency];
  10103. currentValue = userInfo.gold;
  10104. } else {
  10105. const costValues = Object.entries(costNextLevel[costСurrency]).pop();
  10106. const costId = costValues[0];
  10107. costValue = +costValues[1];
  10108. currentValue = inventory[costСurrency][costId];
  10109. }
  10110.  
  10111. /** TODO: Возможно стоит искать самый высокий уровень который можно качнуть? */
  10112. if (level < upArt.level && currentValue >= costValue) {
  10113. upArt.level = level;
  10114. upArt.titanId = titan.id;
  10115. upArt.slotId = slotId;
  10116. break;
  10117. }
  10118. }
  10119. }
  10120. return upArt;
  10121. }
  10122.  
  10123. getEnchantRune() {
  10124. const heroes = Object.values(this.questInfo['heroGetAll']);
  10125. const inventory = this.questInfo['inventoryGet'];
  10126. const enchRune = { heroId: 0, tier: 0, exp: 43750, itemId: 0 };
  10127. for (let i = 1; i <= 4; i++) {
  10128. if (inventory.consumable[i] > 0) {
  10129. enchRune.itemId = i;
  10130. break;
  10131. }
  10132. return enchRune;
  10133. }
  10134.  
  10135. const runeLib = lib.getData('rune');
  10136. const runeLvls = Object.values(runeLib.level);
  10137. /**
  10138. * color - 4 (синий) открывает 1 и 2 символ
  10139. * color - 7 (фиолетовый) открывает 3 символ
  10140. * color - 8 (фиолетовый +1) открывает 4 символ
  10141. * color - 9 (фиолетовый +2) открывает 5 символ
  10142. */
  10143. // TODO: кажется надо учесть уровень команды
  10144. const colors = [4, 4, 7, 8, 9];
  10145. for (const hero of heroes) {
  10146. const color = hero.color;
  10147.  
  10148.  
  10149. for (let runeTier in hero.runes) {
  10150. /* Проверка на доступность руны */
  10151. if (color < colors[runeTier]) {
  10152. continue;
  10153. }
  10154. /* Текущий опыт руны */
  10155. const exp = hero.runes[runeTier];
  10156. if (exp >= 43750) {
  10157. continue;
  10158. }
  10159.  
  10160. let level = 0;
  10161. if (exp) {
  10162. for (let lvl of runeLvls) {
  10163. if (exp >= lvl.enchantValue) {
  10164. level = lvl.level;
  10165. } else {
  10166. break;
  10167. }
  10168. }
  10169. }
  10170. /** Уровень героя необходимый для уровня руны */
  10171. const heroLevel = runeLib.level[level].heroLevel;
  10172. if (hero.level < heroLevel) {
  10173. continue;
  10174. }
  10175.  
  10176. /** TODO: Возможно стоит искать самый высокий уровень который можно качнуть? */
  10177. if (exp < enchRune.exp) {
  10178. enchRune.exp = exp;
  10179. enchRune.heroId = hero.id;
  10180. enchRune.tier = runeTier;
  10181. break;
  10182. }
  10183. }
  10184. }
  10185. return enchRune;
  10186. }
  10187.  
  10188. getOutlandChest() {
  10189. const bosses = this.questInfo['bossGetAll'];
  10190.  
  10191. const calls = [];
  10192.  
  10193. for (let boss of bosses) {
  10194. if (boss.mayRaid) {
  10195. calls.push({
  10196. name: "bossRaid",
  10197. args: {
  10198. bossId: boss.id
  10199. },
  10200. ident: "bossRaid_" + boss.id
  10201. });
  10202. calls.push({
  10203. name: "bossOpenChest",
  10204. args: {
  10205. bossId: boss.id,
  10206. amount: 1,
  10207. starmoney: 0
  10208. },
  10209. ident: "bossOpenChest_" + boss.id
  10210. });
  10211. } else if (boss.chestId == 1) {
  10212. calls.push({
  10213. name: "bossOpenChest",
  10214. args: {
  10215. bossId: boss.id,
  10216. amount: 1,
  10217. starmoney: 0
  10218. },
  10219. ident: "bossOpenChest_" + boss.id
  10220. });
  10221. }
  10222. }
  10223.  
  10224. return calls;
  10225. }
  10226.  
  10227. getExpHero() {
  10228. const heroes = Object.values(this.questInfo['heroGetAll']);
  10229. const inventory = this.questInfo['inventoryGet'];
  10230. const expHero = { heroId: 0, exp: 3625195, libId: 0 };
  10231. /** зелья опыта (consumable 9, 10, 11, 12) */
  10232. for (let i = 9; i <= 12; i++) {
  10233. if (inventory.consumable[i]) {
  10234. expHero.libId = i;
  10235. break;
  10236. }
  10237. }
  10238.  
  10239. for (const hero of heroes) {
  10240. const exp = hero.xp;
  10241. if (exp < expHero.exp) {
  10242. expHero.heroId = hero.id;
  10243. }
  10244. }
  10245. return expHero;
  10246. }
  10247.  
  10248. getHeroIdTitanGift() {
  10249. const heroes = Object.values(this.questInfo['heroGetAll']);
  10250. const inventory = this.questInfo['inventoryGet'];
  10251. const user = this.questInfo['userGetInfo'];
  10252. const titanGiftLib = lib.getData('titanGift');
  10253. /** Искры */
  10254. const titanGift = inventory.consumable[24];
  10255. let heroId = 0;
  10256. let minLevel = 30;
  10257.  
  10258. if (titanGift < 250 || user.gold < 7000) {
  10259. return 0;
  10260. }
  10261.  
  10262. for (const hero of heroes) {
  10263. if (hero.titanGiftLevel >= 30) {
  10264. continue;
  10265. }
  10266.  
  10267. if (!hero.titanGiftLevel) {
  10268. return hero.id;
  10269. }
  10270.  
  10271. const cost = titanGiftLib[hero.titanGiftLevel].cost;
  10272. if (minLevel > hero.titanGiftLevel &&
  10273. titanGift >= cost.consumable[24] &&
  10274. user.gold >= cost.gold
  10275. ) {
  10276. minLevel = hero.titanGiftLevel;
  10277. heroId = hero.id;
  10278. }
  10279. }
  10280.  
  10281. return heroId;
  10282. }
  10283.  
  10284. end(status) {
  10285. setProgress(status, true);
  10286. this.resolve();
  10287. }
  10288. }
  10289.  
  10290. this.questRun = dailyQuests;
  10291.  
  10292. function testDoYourBest() {
  10293. return new Promise((resolve, reject) => {
  10294. const doIt = new doYourBest(resolve, reject);
  10295. doIt.start();
  10296. });
  10297. }
  10298.  
  10299. /**
  10300. * Do everything button
  10301. *
  10302. * Кнопка сделать все
  10303. */
  10304. class doYourBest {
  10305.  
  10306. funcList = [
  10307. //собрать запределье
  10308. {
  10309. name: 'getOutland',
  10310. label: I18N('ASSEMBLE_OUTLAND'),
  10311. checked: false
  10312. },
  10313. //пройти башню
  10314. {
  10315. name: 'testTower',
  10316. label: I18N('PASS_THE_TOWER'),
  10317. checked: false
  10318. },
  10319. //экспедиции
  10320. {
  10321. name: 'checkExpedition',
  10322. label: I18N('CHECK_EXPEDITIONS'),
  10323. checked: false
  10324. },
  10325. //турнир стихий
  10326. {
  10327. name: 'testTitanArena',
  10328. label: I18N('COMPLETE_TOE'),
  10329. checked: false
  10330. },
  10331. //собрать почту
  10332. {
  10333. name: 'mailGetAll',
  10334. label: I18N('COLLECT_MAIL'),
  10335. checked: false
  10336. },
  10337. //Собрать всякую херню
  10338. {
  10339. name: 'collectAllStuff',
  10340. label: I18N('COLLECT_MISC'),
  10341. title: I18N('COLLECT_MISC_TITLE'),
  10342. checked: false
  10343. },
  10344. //ежедневная награда
  10345. {
  10346. name: 'getDailyBonus',
  10347. label: I18N('DAILY_BONUS'),
  10348. checked: false
  10349. },
  10350. //ежедневные квесты удалить наверно есть в настройках
  10351. {
  10352. name: 'dailyQuests',
  10353. label: I18N('DO_DAILY_QUESTS'),
  10354. checked: false
  10355. },
  10356. //Провидец
  10357. {
  10358. name: 'rollAscension',
  10359. label: I18N('SEER_TITLE'),
  10360. checked: false
  10361. },
  10362. //собрать награды за квесты
  10363. {
  10364. name: 'questAllFarm',
  10365. label: I18N('COLLECT_QUEST_REWARDS'),
  10366. checked: false
  10367. },
  10368. // тест отправь подарки согильдийцам
  10369. {
  10370. name: 'testclanSendDailyGifts',
  10371. label: I18N('QUEST_10016'),
  10372. checked: false
  10373. },
  10374. //собрать новогодние подарки
  10375. /*{
  10376. name: 'getGiftNewYear',
  10377. label: I18N('NY_GIFTS'),
  10378. checked: false
  10379. },*/
  10380. // тест сферу титанов
  10381. /*{
  10382. name: 'testtitanArtifactChestOpen',
  10383. label: I18N('QUEST_10029'),
  10384. checked: false
  10385. },
  10386. // тест призыв петов
  10387. {
  10388. name: 'testpet_chestOpen',
  10389. label: I18N('QUEST_10044'),
  10390. checked: false
  10391. },*/
  10392. //пройти подземелье обычное
  10393. {
  10394. name: 'testDungeon',
  10395. label: I18N('COMPLETE_DUNGEON'),
  10396. checked: false
  10397. },
  10398. //пройти подземелье для фуловых титанов
  10399. {
  10400. name: 'DungeonFull',
  10401. label: I18N('COMPLETE_DUNGEON_FULL'),
  10402. checked: false
  10403. },
  10404. //синхронизация
  10405. {
  10406. name: 'synchronization',
  10407. label: I18N('MAKE_A_SYNC'),
  10408. checked: false
  10409. },
  10410. //перезагрузка
  10411. {
  10412. name: 'reloadGame',
  10413. label: I18N('RELOAD_GAME'),
  10414. checked: false
  10415. },
  10416. ];
  10417.  
  10418. functions = {
  10419. getOutland,//собрать запределье
  10420. testTower,//прохождение башни
  10421. checkExpedition,//автоэкспедиции
  10422. testTitanArena,//Автопрохождение Турнира Стихий
  10423. mailGetAll,//Собрать всю почту, кроме писем с энергией и зарядами портала
  10424. //Собрать пасхалки, камни облика, ключи, монеты арены и Хрусталь души
  10425. collectAllStuff: async () => {
  10426. await offerFarmAllReward();
  10427. 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"}]}');
  10428. },
  10429. //Выполнять ежедневные квесты
  10430. dailyQuests: async function () {
  10431. const quests = new dailyQuests(() => { }, () => { });
  10432. await quests.autoInit(true);
  10433. await quests.start();
  10434. },
  10435. rollAscension,//провидец
  10436. getDailyBonus,//ежедневная награда
  10437. questAllFarm,//Собрать все награды за задания
  10438. testclanSendDailyGifts, //отправить подарки
  10439. getGiftNewYear,//собрать новогодние подарки
  10440. testtitanArtifactChestOpen, //открой сферу титанов
  10441. testpet_chestOpen, //Воспользуйся призывом питомцев 1 раз
  10442. testDungeon,//подземка обычная
  10443. DungeonFull,//подземка для фуловых титанов
  10444. synchronization: async () => {
  10445. cheats.refreshGame();
  10446. },
  10447. reloadGame: async () => {
  10448. location.reload();
  10449. },
  10450. }
  10451.  
  10452. constructor(resolve, reject, questInfo) {
  10453. this.resolve = resolve;
  10454. this.reject = reject;
  10455. this.questInfo = questInfo
  10456. }
  10457.  
  10458. async start() {
  10459. const selectedDoIt = getSaveVal('selectedDoIt', {});
  10460.  
  10461. this.funcList.forEach(task => {
  10462. if (!selectedDoIt[task.name]) {
  10463. selectedDoIt[task.name] = {
  10464. checked: task.checked
  10465. }
  10466. } else {
  10467. task.checked = selectedDoIt[task.name].checked
  10468. }
  10469. });
  10470.  
  10471. const answer = await popup.confirm(I18N('RUN_FUNCTION'), [
  10472. { msg: I18N('BTN_CANCEL'), result: false, isCancel: true },
  10473. { msg: I18N('BTN_GO'), result: true },
  10474. ], this.funcList);
  10475.  
  10476. if (!answer) {
  10477. this.end('');
  10478. return;
  10479. }
  10480.  
  10481. const taskList = popup.getCheckBoxes();
  10482. taskList.forEach(task => {
  10483. selectedDoIt[task.name].checked = task.checked;
  10484. });
  10485. setSaveVal('selectedDoIt', selectedDoIt);
  10486. for (const task of popup.getCheckBoxes()) {
  10487. if (task.checked) {
  10488. try {
  10489. setProgress(`${task.label} <br>${I18N('PERFORMED')}!`);
  10490. await this.functions[task.name]();
  10491. setProgress(`${task.label} <br>${I18N('DONE')}!`);
  10492. } catch (error) {
  10493. if (await popup.confirm(`${I18N('ERRORS_OCCURRES')}:<br> ${task.label} <br>${I18N('COPY_ERROR')}?`, [
  10494. { msg: I18N('BTN_NO'), result: false },
  10495. { msg: I18N('BTN_YES'), result: true },
  10496. ])) {
  10497. this.errorHandling(error);
  10498. }
  10499. }
  10500. }
  10501. }
  10502. setTimeout((msg) => {
  10503. this.end(msg);
  10504. }, 2000, I18N('ALL_TASK_COMPLETED'));
  10505. return;
  10506. }
  10507.  
  10508. errorHandling(error) {
  10509. //console.error(error);
  10510. let errorInfo = error.toString() + '\n';
  10511. try {
  10512. const errorStack = error.stack.split('\n');
  10513. const endStack = errorStack.map(e => e.split('@')[0]).indexOf("testDoYourBest");
  10514. errorInfo += errorStack.slice(0, endStack).join('\n');
  10515. } catch (e) {
  10516. errorInfo += error.stack;
  10517. }
  10518. copyText(errorInfo);
  10519. }
  10520.  
  10521. end(status) {
  10522. setProgress(status, true);
  10523. this.resolve();
  10524. }
  10525. }
  10526.  
  10527. /**
  10528. * Passing the adventure along the specified route
  10529. *
  10530. * Прохождение приключения по указанному маршруту
  10531. */
  10532. function testAdventure(type) {
  10533. return new Promise((resolve, reject) => {
  10534. const bossBattle = new executeAdventure(resolve, reject);
  10535. bossBattle.start(type);
  10536. });
  10537. }
  10538.  
  10539. //Буря
  10540. function testAdventure2(solo) {
  10541. return new Promise((resolve, reject) => {
  10542. const bossBattle = new executeAdventure2(resolve, reject);
  10543. bossBattle.start(solo);
  10544. });
  10545. }
  10546.  
  10547. /**
  10548. * Passing the adventure along the specified route
  10549. *
  10550. * Прохождение приключения по указанному маршруту
  10551. */
  10552. class executeAdventure {
  10553.  
  10554. type = 'default';
  10555.  
  10556. actions = {
  10557. default: {
  10558. getInfo: "adventure_getInfo",
  10559. startBattle: 'adventure_turnStartBattle',
  10560. endBattle: 'adventure_endBattle',
  10561. collectBuff: 'adventure_turnCollectBuff'
  10562. },
  10563. solo: {
  10564. getInfo: "adventureSolo_getInfo",
  10565. startBattle: 'adventureSolo_turnStartBattle',
  10566. endBattle: 'adventureSolo_endBattle',
  10567. collectBuff: 'adventureSolo_turnCollectBuff'
  10568. }
  10569. }
  10570.  
  10571. terminatеReason = I18N('UNKNOWN');
  10572. callAdventureInfo = {
  10573. name: "adventure_getInfo",
  10574. args: {},
  10575. ident: "adventure_getInfo"
  10576. }
  10577. callTeamGetAll = {
  10578. name: "teamGetAll",
  10579. args: {},
  10580. ident: "teamGetAll"
  10581. }
  10582. callTeamGetFavor = {
  10583. name: "teamGetFavor",
  10584. args: {},
  10585. ident: "teamGetFavor"
  10586. }
  10587. //тест прикла
  10588. defaultWays = {
  10589. //Галахад, 1-я
  10590. "adv_strongford_2pl_easy": {
  10591. first: '1,2,3,5,6',
  10592. second: '1,2,4,7,6',
  10593. third: '1,2,3,5,6'
  10594. },
  10595. //Джинджер, 2-я
  10596. "adv_valley_3pl_easy": {
  10597. first: '1,2,5,8,9,11',
  10598. second: '1,3,6,9,11',
  10599. third: '1,4,7,10,9,11'
  10600. },
  10601. //Орион, 3-я
  10602. "adv_ghirwil_3pl_easy": {
  10603. first: '1,5,6,9,11',
  10604. second: '1,4,12,13,11',
  10605. third: '1,2,3,7,10,11'
  10606. },
  10607. //Тесак, 4-я
  10608. "adv_angels_3pl_easy_fire": {
  10609. first: '1,2,4,7,18,8,12,19,22,23',
  10610. second: '1,3,6,11,17,10,16,21,22,23',
  10611. third: '1,5,24,25,9,14,15,20,22,23'
  10612. },
  10613. //Галахад, 5-я
  10614. "adv_strongford_3pl_normal_2": {
  10615. first: '1,2,7,8,12,16,23,26,25,21,24',
  10616. second: '1,4,6,10,11,15,22,15,19,18,24',
  10617. third: '1,5,9,10,14,17,20,27,25,21,24'
  10618. },
  10619. //Джинджер, 6-я
  10620. "adv_valley_3pl_normal": {
  10621. first: '1,2,4,7,10,13,16,19,24,22,25',
  10622. second: '1,3,6,9,12,15,18,21,26,23,25',
  10623. third: '1,5,7,8,11,14,17,20,22,25'
  10624. },
  10625. //Орион, 7-я
  10626. "adv_ghirwil_3pl_normal_2": {
  10627. first: '1,11,10,11,12,15,12,11,21,25,27',
  10628. second: '1,7,3,4,3,6,13,19,20,24,27',
  10629. third: '1,8,5,9,16,23,22,26,27'
  10630. },
  10631. //Тесак, 8-я
  10632. "adv_angels_3pl_normal": {
  10633. first: '1,3,4,8,7,9,10,13,17,16,20,22,23,31,32',
  10634. second: '1,3,5,7,8,11,14,18,20,22,24,27,30,26,32',
  10635. third: '1,3,2,6,7,9,11,15,19,20,22,21,28,29,25'
  10636. },
  10637. //Галахад, 9-я
  10638. "adv_strongford_3pl_hard_2": {
  10639. first: '1,2,6,10,15,7,16,17,23,22,27,32,35,37,40,45',
  10640. second: '1,3,8,12,11,18,19,28,34,33,38,41,43,46,45',
  10641. third: '1,2,5,9,14,20,26,21,30,36,39,42,44,45'
  10642. },
  10643. //Джинджер, 10-я
  10644. "adv_valley_3pl_hard": {
  10645. first: '1,3,2,6,11,17,25,30,35,34,29,24,21,17,12,7',
  10646. second: '1,4,8,13,18,22,26,31,36,40,45,44,43,38,33,28',
  10647. third: '1,5,9,14,19,23,27,32,37,42,48,51,50,49,46,52'
  10648. },
  10649. //Орион, 11-я
  10650. "adv_ghirwil_3pl_hard": {
  10651. first: '1,2,3,6,8,12,11,15,21,27,36,34,33,35,37',
  10652. second: '1,2,4,6,9,13,18,17,16,22,28,29,30,31,25,19',
  10653. third: '1,2,5,6,10,13,14,20,26,32,38,41,40,39,37'
  10654. },
  10655. //Тесак, 12-я
  10656. "adv_angels_3pl_hard": {
  10657. first: '1,2,8,11,7,4,7,16,23,32,33,25,34,29,35,36',
  10658. second: '1,3,9,13,10,6,10,22,31,30,21,30,15,28,20,27',
  10659. third: '1,5,12,14,24,17,24,25,26,18,19,20,27'
  10660. },
  10661. //Тесак, 13-я
  10662. "adv_angels_3pl_hell": {
  10663. first: '1,2,4,6,16,23,33,34,25,32,29,28,20,27',
  10664. second: '1,7,11,17,24,14,26,18,19,20,27,20,12,8',
  10665. third: '1,9,3,5,10,22,31,36,31,30,15,28,29,30,21,13'
  10666. },
  10667. //Галахад, 13-я
  10668. "adv_strongford_3pl_hell": {
  10669. first: '1,2,5,11,14,20,26,21,30,35,38,41,43,44',
  10670. second: '1,2,6,12,15,7,16,17,23,22,27,42,34,36,39,44',
  10671. third: '1,3,8,9,13,18,19,28,0,33,37,40,32,45,44'
  10672. },
  10673. //Орион, 13-я
  10674. "adv_ghirwil_3pl_hell": {
  10675. first: '1,2,3,6,8,12,11,15,21,27,36,34,33,35,37',
  10676. second: '1,2,4,6,9,13,18,17,16,22,28,29,30,31,25,19',
  10677. third: '1,2,5,6,10,13,14,20,26,32,38,41,40,39,37'
  10678. },
  10679. //Джинджер, 13-я
  10680. "adv_valley_3pl_hell": {
  10681. first: '1,3,2,6,11,17,25,30,35,34,29,24,21,17,12,7',
  10682. second: '1,4,8,13,18,22,26,31,36,40,45,44,43,38,33,28',
  10683. third: '1,5,9,14,19,23,27,32,37,42,48,51,50,49,46,52'
  10684. }
  10685. }
  10686. callStartBattle = {
  10687. name: "adventure_turnStartBattle",
  10688. args: {},
  10689. ident: "body"
  10690. }
  10691. callEndBattle = {
  10692. name: "adventure_endBattle",
  10693. args: {
  10694. result: {},
  10695. progress: {},
  10696. },
  10697. ident: "body"
  10698. }
  10699. callCollectBuff = {
  10700. name: "adventure_turnCollectBuff",
  10701. args: {},
  10702. ident: "body"
  10703. }
  10704.  
  10705. constructor(resolve, reject) {
  10706. this.resolve = resolve;
  10707. this.reject = reject;
  10708. }
  10709.  
  10710. async start(type) {
  10711. //this.type = type || this.type;
  10712. //this.callAdventureInfo.name = this.actions[this.type].getInfo;
  10713. const data = await Send(JSON.stringify({
  10714. calls: [
  10715. this.callAdventureInfo,
  10716. this.callTeamGetAll,
  10717. this.callTeamGetFavor
  10718. ]
  10719. }));
  10720. //тест прикла1
  10721. this.path = await this.getPath(data.results[0].result.response.mapIdent);
  10722. if (!this.path) {
  10723. this.end();
  10724. return;
  10725. }
  10726. return this.checkAdventureInfo(data.results);
  10727. }
  10728.  
  10729. async getPath(mapId) {
  10730. //const oldVal = getSaveVal('adventurePath', '');
  10731. //const keyPath = `adventurePath:${this.mapIdent}`;
  10732. const answer = await popup.confirm(I18N('ENTER_THE_PATH'), [
  10733. {
  10734. msg: I18N('START_ADVENTURE'),
  10735. placeholder: '1,2,3,4,5,6',
  10736. isInput: true,
  10737. //default: getSaveVal(keyPath, oldVal)
  10738. default: getSaveVal('adventurePath', '')
  10739. },
  10740. {
  10741. msg: ' Начать по пути №1! ',
  10742. placeholder: '1,2,3',
  10743. isInput: true,
  10744. default: this.defaultWays[mapId]?.first
  10745. },
  10746. {
  10747. msg: ' Начать по пути №2! ',
  10748. placeholder: '1,2,3',
  10749. isInput: true,
  10750. default: this.defaultWays[mapId]?.second
  10751. },
  10752. {
  10753. msg: ' Начать по пути №3! ',
  10754. placeholder: '1,2,3',
  10755. isInput: true,
  10756. default: this.defaultWays[mapId]?.third
  10757. },
  10758. {
  10759. msg: I18N('BTN_CANCEL'),
  10760. result: false,
  10761. isCancel: true
  10762. },
  10763. ]);
  10764. if (!answer) {
  10765. this.terminatеReason = I18N('BTN_CANCELED');
  10766. return false;
  10767. }
  10768.  
  10769. let path = answer.split(',');
  10770. if (path.length < 2) {
  10771. path = answer.split('-');
  10772. }
  10773. if (path.length < 2) {
  10774. this.terminatеReason = I18N('MUST_TWO_POINTS');
  10775. return false;
  10776. }
  10777.  
  10778. for (let p in path) {
  10779. path[p] = +path[p].trim()
  10780. if (Number.isNaN(path[p])) {
  10781. this.terminatеReason = I18N('MUST_ONLY_NUMBERS');
  10782. return false;
  10783. }
  10784. }
  10785.  
  10786. /*if (!this.checkPath(path)) {
  10787. return false;
  10788. }*/
  10789. //setSaveVal(keyPath, answer);
  10790. setSaveVal('adventurePath', answer);
  10791. return path;
  10792. }
  10793. /*
  10794. checkPath(path) {
  10795. for (let i = 0; i < path.length - 1; i++) {
  10796. const currentPoint = path[i];
  10797. const nextPoint = path[i + 1];
  10798.  
  10799. const isValidPath = this.paths.some(p =>
  10800. (p.from_id === currentPoint && p.to_id === nextPoint) ||
  10801. (p.from_id === nextPoint && p.to_id === currentPoint)
  10802. );
  10803.  
  10804. if (!isValidPath) {
  10805. this.terminatеReason = I18N('INCORRECT_WAY', {
  10806. from: currentPoint,
  10807. to: nextPoint,
  10808. });
  10809. return false;
  10810. }
  10811. }
  10812.  
  10813. return true;
  10814. }
  10815. */
  10816. async checkAdventureInfo(data) {
  10817. this.advInfo = data[0].result.response;
  10818. if (!this.advInfo) {
  10819. this.terminatеReason = I18N('NOT_ON_AN_ADVENTURE') ;
  10820. return this.end();
  10821. }
  10822. const heroesTeam = data[1].result.response.adventure_hero;
  10823. const favor = data[2]?.result.response.adventure_hero;
  10824. const heroes = heroesTeam.slice(0, 5);
  10825. const pet = heroesTeam[5];
  10826. this.args = {
  10827. pet,
  10828. heroes,
  10829. favor,
  10830. path: [],
  10831. broadcast: false
  10832. }
  10833. const advUserInfo = this.advInfo.users[userInfo.id];
  10834. this.turnsLeft = advUserInfo.turnsLeft;
  10835. this.currentNode = advUserInfo.currentNode;
  10836. this.nodes = this.advInfo.nodes;
  10837. //this.paths = this.advInfo.paths;
  10838. //this.mapIdent = this.advInfo.mapIdent;
  10839.  
  10840. /*this.path = await this.getPath();
  10841. if (!this.path) {
  10842. return this.end();
  10843. }*/
  10844.  
  10845. if (this.currentNode == 1 && this.path[0] != 1) {
  10846. this.path.unshift(1);
  10847. }
  10848.  
  10849. return this.loop();
  10850. }
  10851.  
  10852. async loop() {
  10853. const position = this.path.indexOf(+this.currentNode);
  10854. if (!(~position)) {
  10855. this.terminatеReason = I18N('YOU_IN_NOT_ON_THE_WAY');
  10856. return this.end();
  10857. }
  10858. this.path = this.path.slice(position);
  10859. if ((this.path.length - 1) > this.turnsLeft &&
  10860. await popup.confirm(I18N('ATTEMPTS_NOT_ENOUGH'), [
  10861. { msg: I18N('YES_CONTINUE'), result: false },
  10862. { msg: I18N('BTN_NO'), result: true },
  10863. ])) {
  10864. this.terminatеReason = I18N('NOT_ENOUGH_AP');
  10865. return this.end();
  10866. }
  10867. const toPath = [];
  10868. for (const nodeId of this.path) {
  10869. if (!this.turnsLeft) {
  10870. this.terminatеReason = I18N('ATTEMPTS_ARE_OVER');
  10871. return this.end();
  10872. }
  10873. toPath.push(nodeId);
  10874. console.log(toPath);
  10875. if (toPath.length > 1) {
  10876. setProgress(toPath.join(' > ') + ` ${I18N('MOVES')}: ` + this.turnsLeft);
  10877. }
  10878. if (nodeId == this.currentNode) {
  10879. continue;
  10880. }
  10881.  
  10882. const nodeInfo = this.getNodeInfo(nodeId);
  10883. if (nodeInfo.type == 'TYPE_COMBAT') {
  10884. if (nodeInfo.state == 'empty') {
  10885. this.turnsLeft--;
  10886. continue;
  10887. }
  10888.  
  10889. /**
  10890. * Disable regular battle cancellation
  10891. *
  10892. * Отключаем штатную отменую боя
  10893. */
  10894. isCancalBattle = false;
  10895. if (await this.battle(toPath)) {
  10896. this.turnsLeft--;
  10897. toPath.splice(0, toPath.indexOf(nodeId));
  10898. nodeInfo.state = 'empty';
  10899. isCancalBattle = true;
  10900. continue;
  10901. }
  10902. isCancalBattle = true;
  10903. return this.end()
  10904. }
  10905.  
  10906. if (nodeInfo.type == 'TYPE_PLAYERBUFF') {
  10907. const buff = this.checkBuff(nodeInfo);
  10908. if (buff == null) {
  10909. continue;
  10910. }
  10911.  
  10912. if (await this.collectBuff(buff, toPath)) {
  10913. this.turnsLeft--;
  10914. toPath.splice(0, toPath.indexOf(nodeId));
  10915. continue;
  10916. }
  10917. this.terminatеReason = I18N('BUFF_GET_ERROR');
  10918. return this.end();
  10919. }
  10920. }
  10921. this.terminatеReason = I18N('SUCCESS');
  10922. return this.end();
  10923. }
  10924.  
  10925. /**
  10926. * Carrying out a fight
  10927. *
  10928. * Проведение боя
  10929. */
  10930. async battle(path, preCalc = true) {
  10931. const data = await this.startBattle(path);
  10932. try {
  10933. const battle = data.results[0].result.response.battle;
  10934. const result = await Calc(battle);
  10935. if (result.result.win) {
  10936. const info = await this.endBattle(result);
  10937. if (info.results[0].result.response?.error) {
  10938. this.terminatеReason = I18N('BATTLE_END_ERROR');
  10939. return false;
  10940. }
  10941. } else {
  10942. await this.cancelBattle(result);
  10943.  
  10944. if (preCalc && await this.preCalcBattle(battle)) {
  10945. path = path.slice(-2);
  10946. for (let i = 1; i <= getInput('countAutoBattle'); i++) {
  10947. setProgress(`${I18N('AUTOBOT')}: ${i}/${getInput('countAutoBattle')}`);
  10948. const result = await this.battle(path, false);
  10949. if (result) {
  10950. setProgress(I18N('VICTORY'));
  10951. return true;
  10952. }
  10953. }
  10954. this.terminatеReason = I18N('FAILED_TO_WIN_AUTO');
  10955. return false;
  10956. }
  10957. return false;
  10958. }
  10959. } catch (error) {
  10960. console.error(error);
  10961. if (await popup.confirm(I18N('ERROR_OF_THE_BATTLE_COPY'), [
  10962. { msg: I18N('BTN_NO'), result: false },
  10963. { msg: I18N('BTN_YES'), result: true },
  10964. ])) {
  10965. this.errorHandling(error, data);
  10966. }
  10967. this.terminatеReason = I18N('ERROR_DURING_THE_BATTLE');
  10968. return false;
  10969. }
  10970. return true;
  10971. }
  10972.  
  10973. /**
  10974. * Recalculate battles
  10975. *
  10976. * Прерасчтет битвы
  10977. */
  10978. async preCalcBattle(battle) {
  10979. const countTestBattle = getInput('countTestBattle');
  10980. for (let i = 0; i < countTestBattle; i++) {
  10981. battle.seed = Math.floor(Date.now() / 1000) + random(0, 1e3);
  10982. const result = await Calc(battle);
  10983. if (result.result.win) {
  10984. console.log(i, countTestBattle);
  10985. return true;
  10986. }
  10987. }
  10988. this.terminatеReason = I18N('NO_CHANCE_WIN') + countTestBattle;
  10989. return false;
  10990. }
  10991.  
  10992. /**
  10993. * Starts a fight
  10994. *
  10995. * Начинает бой
  10996. */
  10997. startBattle(path) {
  10998. this.args.path = path;
  10999. this.callStartBattle.name = this.actions[this.type].startBattle;
  11000. this.callStartBattle.args = this.args
  11001. const calls = [this.callStartBattle];
  11002. return Send(JSON.stringify({ calls }));
  11003. }
  11004.  
  11005. cancelBattle(battle) {
  11006. const fixBattle = function (heroes) {
  11007. for (const ids in heroes) {
  11008. const hero = heroes[ids];
  11009. hero.energy = random(1, 999);
  11010. if (hero.hp > 0) {
  11011. hero.hp = random(1, hero.hp);
  11012. }
  11013. }
  11014. }
  11015. fixBattle(battle.progress[0].attackers.heroes);
  11016. fixBattle(battle.progress[0].defenders.heroes);
  11017. return this.endBattle(battle);
  11018. }
  11019.  
  11020. /**
  11021. * Ends the fight
  11022. *
  11023. * Заканчивает бой
  11024. */
  11025. endBattle(battle) {
  11026. this.callEndBattle.name = this.actions[this.type].endBattle;
  11027. this.callEndBattle.args.result = battle.result
  11028. this.callEndBattle.args.progress = battle.progress
  11029. const calls = [this.callEndBattle];
  11030. return Send(JSON.stringify({ calls }));
  11031. }
  11032.  
  11033. /**
  11034. * Checks if you can get a buff
  11035. *
  11036. * Проверяет можно ли получить баф
  11037. */
  11038. checkBuff(nodeInfo) {
  11039. let id = null;
  11040. let value = 0;
  11041. for (const buffId in nodeInfo.buffs) {
  11042. const buff = nodeInfo.buffs[buffId];
  11043. if (buff.owner == null && buff.value > value) {
  11044. id = buffId;
  11045. value = buff.value;
  11046. }
  11047. }
  11048. nodeInfo.buffs[id].owner = 'Я';
  11049. return id;
  11050. }
  11051.  
  11052. /**
  11053. * Collects a buff
  11054. *
  11055. * Собирает баф
  11056. */
  11057. async collectBuff(buff, path) {
  11058. this.callCollectBuff.name = this.actions[this.type].collectBuff;
  11059. this.callCollectBuff.args = { buff, path };
  11060. const calls = [this.callCollectBuff];
  11061. return Send(JSON.stringify({ calls }));
  11062. }
  11063.  
  11064. getNodeInfo(nodeId) {
  11065. return this.nodes.find(node => node.id == nodeId);
  11066. }
  11067.  
  11068. errorHandling(error, data) {
  11069. //console.error(error);
  11070. let errorInfo = error.toString() + '\n';
  11071. try {
  11072. const errorStack = error.stack.split('\n');
  11073. const endStack = errorStack.map(e => e.split('@')[0]).indexOf("testAdventure");
  11074. errorInfo += errorStack.slice(0, endStack).join('\n');
  11075. } catch (e) {
  11076. errorInfo += error.stack;
  11077. }
  11078. if (data) {
  11079. errorInfo += '\nData: ' + JSON.stringify(data);
  11080. }
  11081. copyText(errorInfo);
  11082. }
  11083.  
  11084. end() {
  11085. isCancalBattle = true;
  11086. setProgress(this.terminatеReason, true);
  11087. console.log(this.terminatеReason);
  11088. this.resolve();
  11089. }
  11090. }
  11091. class executeAdventure2 {
  11092.  
  11093. type = 'default';
  11094.  
  11095. actions = {
  11096. default: {
  11097. getInfo: "adventure_getInfo",
  11098. startBattle: 'adventure_turnStartBattle',
  11099. endBattle: 'adventure_endBattle',
  11100. collectBuff: 'adventure_turnCollectBuff'
  11101. },
  11102. solo: {
  11103. getInfo: "adventureSolo_getInfo",
  11104. startBattle: 'adventureSolo_turnStartBattle',
  11105. endBattle: 'adventureSolo_endBattle',
  11106. collectBuff: 'adventureSolo_turnCollectBuff'
  11107. }
  11108. }
  11109.  
  11110. terminatеReason = I18N('UNKNOWN');
  11111. callAdventureInfo = {
  11112. name: "adventure_getInfo",
  11113. args: {},
  11114. ident: "adventure_getInfo"
  11115. }
  11116. callTeamGetAll = {
  11117. name: "teamGetAll",
  11118. args: {},
  11119. ident: "teamGetAll"
  11120. }
  11121. callTeamGetFavor = {
  11122. name: "teamGetFavor",
  11123. args: {},
  11124. ident: "teamGetFavor"
  11125. }
  11126. callStartBattle = {
  11127. name: "adventure_turnStartBattle",
  11128. args: {},
  11129. ident: "body"
  11130. }
  11131. callEndBattle = {
  11132. name: "adventure_endBattle",
  11133. args: {
  11134. result: {},
  11135. progress: {},
  11136. },
  11137. ident: "body"
  11138. }
  11139. callCollectBuff = {
  11140. name: "adventure_turnCollectBuff",
  11141. args: {},
  11142. ident: "body"
  11143. }
  11144.  
  11145. constructor(resolve, reject) {
  11146. this.resolve = resolve;
  11147. this.reject = reject;
  11148. }
  11149.  
  11150. async start(type) {
  11151. this.type = type || this.type;
  11152. this.callAdventureInfo.name = this.actions[this.type].getInfo;
  11153. const data = await Send(JSON.stringify({
  11154. calls: [
  11155. this.callAdventureInfo,
  11156. this.callTeamGetAll,
  11157. this.callTeamGetFavor
  11158. ]
  11159. }));
  11160. return this.checkAdventureInfo(data.results);
  11161. }
  11162.  
  11163. async getPath() {
  11164. const oldVal = getSaveVal('adventurePath', '');
  11165. const keyPath = `adventurePath:${this.mapIdent}`;
  11166. const answer = await popup.confirm(I18N('ENTER_THE_PATH'), [
  11167. {
  11168. msg: I18N('START_ADVENTURE'),
  11169. placeholder: '1,2,3,4,5,6',
  11170. isInput: true,
  11171. default: getSaveVal(keyPath, oldVal)
  11172. },
  11173. {
  11174. msg: I18N('BTN_CANCEL'),
  11175. result: false,
  11176. isCancel: true
  11177. },
  11178. ]);
  11179. if (!answer) {
  11180. this.terminatеReason = I18N('BTN_CANCELED');
  11181. return false;
  11182. }
  11183.  
  11184. let path = answer.split(',');
  11185. if (path.length < 2) {
  11186. path = answer.split('-');
  11187. }
  11188. if (path.length < 2) {
  11189. this.terminatеReason = I18N('MUST_TWO_POINTS');
  11190. return false;
  11191. }
  11192.  
  11193. for (let p in path) {
  11194. path[p] = +path[p].trim()
  11195. if (Number.isNaN(path[p])) {
  11196. this.terminatеReason = I18N('MUST_ONLY_NUMBERS');
  11197. return false;
  11198. }
  11199. }
  11200. if (!this.checkPath(path)) {
  11201. return false;
  11202. }
  11203. setSaveVal(keyPath, answer);
  11204. return path;
  11205. }
  11206.  
  11207. checkPath(path) {
  11208. for (let i = 0; i < path.length - 1; i++) {
  11209. const currentPoint = path[i];
  11210. const nextPoint = path[i + 1];
  11211.  
  11212. const isValidPath = this.paths.some(p =>
  11213. (p.from_id === currentPoint && p.to_id === nextPoint) ||
  11214. (p.from_id === nextPoint && p.to_id === currentPoint)
  11215. );
  11216.  
  11217. if (!isValidPath) {
  11218. this.terminatеReason = I18N('INCORRECT_WAY', {
  11219. from: currentPoint,
  11220. to: nextPoint,
  11221. });
  11222. return false;
  11223. }
  11224. }
  11225.  
  11226. return true;
  11227. }
  11228.  
  11229. async checkAdventureInfo(data) {
  11230. this.advInfo = data[0].result.response;
  11231. if (!this.advInfo) {
  11232. this.terminatеReason = I18N('NOT_ON_AN_ADVENTURE') ;
  11233. return this.end();
  11234. }
  11235. const heroesTeam = data[1].result.response.adventure_hero;
  11236. const favor = data[2]?.result.response.adventure_hero;
  11237. const heroes = heroesTeam.slice(0, 5);
  11238. const pet = heroesTeam[5];
  11239. this.args = {
  11240. pet,
  11241. heroes,
  11242. favor,
  11243. path: [],
  11244. broadcast: false
  11245. }
  11246. const advUserInfo = this.advInfo.users[userInfo.id];
  11247. this.turnsLeft = advUserInfo.turnsLeft;
  11248. this.currentNode = advUserInfo.currentNode;
  11249. this.nodes = this.advInfo.nodes;
  11250. this.paths = this.advInfo.paths;
  11251. this.mapIdent = this.advInfo.mapIdent;
  11252.  
  11253. this.path = await this.getPath();
  11254. if (!this.path) {
  11255. return this.end();
  11256. }
  11257.  
  11258. if (this.currentNode == 1 && this.path[0] != 1) {
  11259. this.path.unshift(1);
  11260. }
  11261.  
  11262. return this.loop();
  11263. }
  11264.  
  11265. async loop() {
  11266. const position = this.path.indexOf(+this.currentNode);
  11267. if (!(~position)) {
  11268. this.terminatеReason = I18N('YOU_IN_NOT_ON_THE_WAY');
  11269. return this.end();
  11270. }
  11271. this.path = this.path.slice(position);
  11272. if ((this.path.length - 1) > this.turnsLeft &&
  11273. await popup.confirm(I18N('ATTEMPTS_NOT_ENOUGH'), [
  11274. { msg: I18N('YES_CONTINUE'), result: false },
  11275. { msg: I18N('BTN_NO'), result: true },
  11276. ])) {
  11277. this.terminatеReason = I18N('NOT_ENOUGH_AP');
  11278. return this.end();
  11279. }
  11280. const toPath = [];
  11281. for (const nodeId of this.path) {
  11282. if (!this.turnsLeft) {
  11283. this.terminatеReason = I18N('ATTEMPTS_ARE_OVER');
  11284. return this.end();
  11285. }
  11286. toPath.push(nodeId);
  11287. console.log(toPath);
  11288. if (toPath.length > 1) {
  11289. setProgress(toPath.join(' > ') + ` ${I18N('MOVES')}: ` + this.turnsLeft);
  11290. }
  11291. if (nodeId == this.currentNode) {
  11292. continue;
  11293. }
  11294.  
  11295. const nodeInfo = this.getNodeInfo(nodeId);
  11296. if (nodeInfo.type == 'TYPE_COMBAT') {
  11297. if (nodeInfo.state == 'empty') {
  11298. this.turnsLeft--;
  11299. continue;
  11300. }
  11301.  
  11302. /**
  11303. * Disable regular battle cancellation
  11304. *
  11305. * Отключаем штатную отменую боя
  11306. */
  11307. isCancalBattle = false;
  11308. if (await this.battle(toPath)) {
  11309. this.turnsLeft--;
  11310. toPath.splice(0, toPath.indexOf(nodeId));
  11311. nodeInfo.state = 'empty';
  11312. isCancalBattle = true;
  11313. continue;
  11314. }
  11315. isCancalBattle = true;
  11316. return this.end()
  11317. }
  11318.  
  11319. if (nodeInfo.type == 'TYPE_PLAYERBUFF') {
  11320. const buff = this.checkBuff(nodeInfo);
  11321. if (buff == null) {
  11322. continue;
  11323. }
  11324.  
  11325. if (await this.collectBuff(buff, toPath)) {
  11326. this.turnsLeft--;
  11327. toPath.splice(0, toPath.indexOf(nodeId));
  11328. continue;
  11329. }
  11330. this.terminatеReason = I18N('BUFF_GET_ERROR');
  11331. return this.end();
  11332. }
  11333. }
  11334. this.terminatеReason = I18N('SUCCESS');
  11335. return this.end();
  11336. }
  11337.  
  11338. /**
  11339. * Carrying out a fight
  11340. *
  11341. * Проведение боя
  11342. */
  11343. async battle(path, preCalc = true) {
  11344. const data = await this.startBattle(path);
  11345. try {
  11346. const battle = data.results[0].result.response.battle;
  11347. const result = await Calc(battle);
  11348. if (result.result.win) {
  11349. const info = await this.endBattle(result);
  11350. if (info.results[0].result.response?.error) {
  11351. this.terminatеReason = I18N('BATTLE_END_ERROR');
  11352. return false;
  11353. }
  11354. } else {
  11355. await this.cancelBattle(result);
  11356.  
  11357. if (preCalc && await this.preCalcBattle(battle)) {
  11358. path = path.slice(-2);
  11359. for (let i = 1; i <= getInput('countAutoBattle'); i++) {
  11360. setProgress(`${I18N('AUTOBOT')}: ${i}/${getInput('countAutoBattle')}`);
  11361. const result = await this.battle(path, false);
  11362. if (result) {
  11363. setProgress(I18N('VICTORY'));
  11364. return true;
  11365. }
  11366. }
  11367. this.terminatеReason = I18N('FAILED_TO_WIN_AUTO');
  11368. return false;
  11369. }
  11370. return false;
  11371. }
  11372. } catch (error) {
  11373. console.error(error);
  11374. if (await popup.confirm(I18N('ERROR_OF_THE_BATTLE_COPY'), [
  11375. { msg: I18N('BTN_NO'), result: false },
  11376. { msg: I18N('BTN_YES'), result: true },
  11377. ])) {
  11378. this.errorHandling(error, data);
  11379. }
  11380. this.terminatеReason = I18N('ERROR_DURING_THE_BATTLE');
  11381. return false;
  11382. }
  11383. return true;
  11384. }
  11385.  
  11386. /**
  11387. * Recalculate battles
  11388. *
  11389. * Прерасчтет битвы
  11390. */
  11391. async preCalcBattle(battle) {
  11392. const countTestBattle = getInput('countTestBattle');
  11393. for (let i = 0; i < countTestBattle; i++) {
  11394. battle.seed = Math.floor(Date.now() / 1000) + random(0, 1e3);
  11395. const result = await Calc(battle);
  11396. if (result.result.win) {
  11397. console.log(i, countTestBattle);
  11398. return true;
  11399. }
  11400. }
  11401. this.terminatеReason = I18N('NO_CHANCE_WIN') + countTestBattle;
  11402. return false;
  11403. }
  11404.  
  11405. /**
  11406. * Starts a fight
  11407. *
  11408. * Начинает бой
  11409. */
  11410. startBattle(path) {
  11411. this.args.path = path;
  11412. this.callStartBattle.name = this.actions[this.type].startBattle;
  11413. this.callStartBattle.args = this.args
  11414. const calls = [this.callStartBattle];
  11415. return Send(JSON.stringify({ calls }));
  11416. }
  11417.  
  11418. cancelBattle(battle) {
  11419. const fixBattle = function (heroes) {
  11420. for (const ids in heroes) {
  11421. const hero = heroes[ids];
  11422. hero.energy = random(1, 999);
  11423. if (hero.hp > 0) {
  11424. hero.hp = random(1, hero.hp);
  11425. }
  11426. }
  11427. }
  11428. fixBattle(battle.progress[0].attackers.heroes);
  11429. fixBattle(battle.progress[0].defenders.heroes);
  11430. return this.endBattle(battle);
  11431. }
  11432.  
  11433. /**
  11434. * Ends the fight
  11435. *
  11436. * Заканчивает бой
  11437. */
  11438. endBattle(battle) {
  11439. this.callEndBattle.name = this.actions[this.type].endBattle;
  11440. this.callEndBattle.args.result = battle.result
  11441. this.callEndBattle.args.progress = battle.progress
  11442. const calls = [this.callEndBattle];
  11443. return Send(JSON.stringify({ calls }));
  11444. }
  11445.  
  11446. /**
  11447. * Checks if you can get a buff
  11448. *
  11449. * Проверяет можно ли получить баф
  11450. */
  11451. checkBuff(nodeInfo) {
  11452. let id = null;
  11453. let value = 0;
  11454. for (const buffId in nodeInfo.buffs) {
  11455. const buff = nodeInfo.buffs[buffId];
  11456. if (buff.owner == null && buff.value > value) {
  11457. id = buffId;
  11458. value = buff.value;
  11459. }
  11460. }
  11461. nodeInfo.buffs[id].owner = 'Я';
  11462. return id;
  11463. }
  11464.  
  11465. /**
  11466. * Collects a buff
  11467. *
  11468. * Собирает баф
  11469. */
  11470. async collectBuff(buff, path) {
  11471. this.callCollectBuff.name = this.actions[this.type].collectBuff;
  11472. this.callCollectBuff.args = { buff, path };
  11473. const calls = [this.callCollectBuff];
  11474. return Send(JSON.stringify({ calls }));
  11475. }
  11476.  
  11477. getNodeInfo(nodeId) {
  11478. return this.nodes.find(node => node.id == nodeId);
  11479. }
  11480.  
  11481. errorHandling(error, data) {
  11482. //console.error(error);
  11483. let errorInfo = error.toString() + '\n';
  11484. try {
  11485. const errorStack = error.stack.split('\n');
  11486. const endStack = errorStack.map(e => e.split('@')[0]).indexOf("testAdventure");
  11487. errorInfo += errorStack.slice(0, endStack).join('\n');
  11488. } catch (e) {
  11489. errorInfo += error.stack;
  11490. }
  11491. if (data) {
  11492. errorInfo += '\nData: ' + JSON.stringify(data);
  11493. }
  11494. copyText(errorInfo);
  11495. }
  11496.  
  11497. end() {
  11498. isCancalBattle = true;
  11499. setProgress(this.terminatеReason, true);
  11500. console.log(this.terminatеReason);
  11501. this.resolve();
  11502. }
  11503. }
  11504. /**
  11505. * Passage of brawls
  11506. *
  11507. * Прохождение потасовок
  11508. */
  11509. function testBrawls(isAuto) {
  11510. return new Promise((resolve, reject) => {
  11511. const brawls = new executeBrawls(resolve, reject);
  11512. brawls.start(brawlsPack, isAuto);
  11513. });
  11514. }
  11515. /**
  11516. * Passage of brawls
  11517. *
  11518. * Прохождение потасовок
  11519. */
  11520. class executeBrawls {
  11521. callBrawlQuestGetInfo = {
  11522. name: "brawl_questGetInfo",
  11523. args: {},
  11524. ident: "brawl_questGetInfo"
  11525. }
  11526. callBrawlFindEnemies = {
  11527. name: "brawl_findEnemies",
  11528. args: {},
  11529. ident: "brawl_findEnemies"
  11530. }
  11531. callBrawlQuestFarm = {
  11532. name: "brawl_questFarm",
  11533. args: {},
  11534. ident: "brawl_questFarm"
  11535. }
  11536. callUserGetInfo = {
  11537. name: "userGetInfo",
  11538. args: {},
  11539. ident: "userGetInfo"
  11540. }
  11541. callTeamGetMaxUpgrade = {
  11542. name: "teamGetMaxUpgrade",
  11543. args: {},
  11544. ident: "teamGetMaxUpgrade"
  11545. }
  11546. callBrawlGetInfo = {
  11547. name: "brawl_getInfo",
  11548. args: {},
  11549. ident: "brawl_getInfo"
  11550. }
  11551.  
  11552. stats = {
  11553. win: 0,
  11554. loss: 0,
  11555. count: 0,
  11556. }
  11557.  
  11558. stage = {
  11559. '3': 1,
  11560. '7': 2,
  11561. '12': 3,
  11562. }
  11563.  
  11564. attempts = 0;
  11565.  
  11566. constructor(resolve, reject) {
  11567. this.resolve = resolve;
  11568. this.reject = reject;
  11569. }
  11570.  
  11571. async start(args, isAuto) {
  11572. this.isAuto = isAuto;
  11573. this.args = args;
  11574. isCancalBattle = false;
  11575. this.brawlInfo = await this.getBrawlInfo();
  11576. this.attempts = this.brawlInfo.attempts;
  11577.  
  11578. if (!this.attempts && !this.info.boughtEndlessLivesToday) {
  11579. this.end(I18N('DONT_HAVE_LIVES'));
  11580. return;
  11581. }
  11582.  
  11583. while (1) {
  11584. if (!isBrawlsAutoStart) {
  11585. this.end(I18N('BTN_CANCELED'));
  11586. return;
  11587. }
  11588.  
  11589. const maxStage = this.brawlInfo.questInfo.stage;
  11590. const stage = this.stage[maxStage];
  11591. const progress = this.brawlInfo.questInfo.progress;
  11592.  
  11593. setProgress(
  11594. `${I18N('STAGE')} ${stage}: ${progress}/${maxStage}<br>${I18N('FIGHTS')}: ${this.stats.count}<br>${I18N('WINS')}: ${
  11595. this.stats.win
  11596. }<br>${I18N('LOSSES')}: ${this.stats.loss}<br>${I18N('LIVES')}: ${this.attempts}<br>${I18N('STOP')}`,
  11597. false,
  11598. function () {
  11599. isBrawlsAutoStart = false;
  11600. }
  11601. );
  11602.  
  11603. if (this.brawlInfo.questInfo.canFarm) {
  11604. const result = await this.questFarm();
  11605. console.log(result);
  11606. }
  11607.  
  11608. if (!this.continueAttack &&
  11609. this.brawlInfo.questInfo.stage == 12 &&
  11610. this.brawlInfo.questInfo.progress == 12) {
  11611. if (
  11612. await popup.confirm(I18N('BRAWL_DAILY_TASK_COMPLETED'), [
  11613. { msg: I18N('BTN_NO'), result: true },
  11614. { msg: I18N('BTN_YES'), result: false },
  11615. ])
  11616. ) {
  11617. this.end(I18N('SUCCESS'));
  11618. return;
  11619. } else {
  11620. this.continueAttack = true;
  11621. }
  11622. }
  11623.  
  11624. if (!this.attempts && !this.info.boughtEndlessLivesToday) {
  11625. this.end(I18N('DONT_HAVE_LIVES'))
  11626. return;
  11627. }
  11628.  
  11629. const enemie = Object.values(this.brawlInfo.findEnemies).shift();
  11630.  
  11631. // Автоматический подбор пачки
  11632. if (this.isAuto) {
  11633. if (this.mandatoryId !== 42) {
  11634. this.end(I18N('BRAWL_AUTO_PACK_NOT_CUR_HERO'));
  11635. return;
  11636. }
  11637. this.args = await this.updatePack(enemie.heroes);
  11638. }
  11639.  
  11640. const result = await this.battle(enemie.userId);
  11641. this.brawlInfo = {
  11642. questInfo: result[1].result.response,
  11643. findEnemies: result[2].result.response,
  11644. };
  11645. }
  11646. }
  11647.  
  11648. async updatePack(enemieHeroes) {
  11649. const packs=[
  11650. {id:7,args:{userId:8263523,heroes:[62,9,40,51,42],pet:6008,favor:{9:6005,40:6004,42:6007,51:6006,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,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},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},42:{id:"42",xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{210:130,211:130,212:130,213:130,6035:130},power:189864,star:6,runes:[43750,43750,43750,43750,43750],skins:{91:60,115:60,121:60,195:60,307:60},currentSkin:195,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,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:2442,hp:518209,intelligence:3476,physicalAttack:50,strength:18155,armor:37797.6,magicPower:76563.6,magicResist:29975,skin:195,favorPetId:6007,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},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},6008:{id:6008,color:10,star:6,xp:450551,level:130,slots:[25,50,50,25,50,50],skills:{6036:130,6037:130},power:181943,type:"pet",perks:[5],name:null,armorPenetration:47911,intelligence:11064,strength:12360}}},{id:5,args:{userId:8263470,heroes:[29,55,9,51,42],pet:6006,favor:{9:6004,29:6002,42:6001,51:6006,55:6005}},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},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},42:{id:"42",xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{210:130,211:130,212:130,213:130,6007:130},power:189864,star:6,runes:[43750,43750,43750,43750,43750],skins:{91:60,115:60,121:60,195:60,307:60},currentSkin:195,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:2442,hp:617785,intelligence:3476,physicalAttack:50,strength:18155,armor:37797.6,magicPower:66606,magicResist:29975,skin:195,favorPetId:6001,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,6027:130},power:190778,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:6005,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:400015,intelligence:19438,physicalAttack:7020.32,strength:3286,armor:22935,armorPenetration:36870,magicPower:70661.6,magicResist:10010,skin:0,favorPetId:6005,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:8263410,heroes:[9,40,56,51,42],pet:6008,favor:{9:6005,40:6004,42:6007,51:6001,56:6006}},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,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},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},42:{id:"42",xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{210:130,211:130,212:130,213:130,6035:130},power:189864,star:6,runes:[43750,43750,43750,43750,43750],skins:{91:60,115:60,121:60,195:60,307:60},currentSkin:195,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,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:2442,hp:518209,intelligence:3476,physicalAttack:50,strength:18155,armor:37797.6,magicPower:76563.6,magicResist:29975,skin:195,favorPetId:6007,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,6007: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:6001,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:537781,intelligence:18851,physicalAttack:50,strength:2921,armor:39442.6,magicPower:79021,magicResist:22960,skin:0,favorPetId:6001,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},6008:{id:6008,color:10,star:6,xp:450551,level:130,slots:[25,50,50,25,50,50],skills:{6036:130,6037:130},power:181943,type:"pet",perks:[5],name:null,armorPenetration:47911,intelligence:11064,strength:12360}}},{id:2,args:{userId:8263340,heroes:[29,9,56,51,42],pet:6006,favor:{9:6005,29:6002,42:6001,51:6006,56:6007}},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,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},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},42:{id:"42",xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{210:130,211:130,212:130,213:130,6007:130},power:189864,star:6,runes:[43750,43750,43750,43750,43750],skins:{91:60,115:60,121:60,195:60,307:60},currentSkin:195,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:2442,hp:617785,intelligence:3476,physicalAttack:50,strength:18155,armor:37797.6,magicPower:66606,magicResist:29975,skin:195,favorPetId:6001,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},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,6035: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:6007,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: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}}},{id:1,args:{userId:8263376,heroes:[31,9,48,16,42],pet:6006,favor:{9:6005,16:6004,31:6001,42:6007,48:6e3}},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,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},16:{id:16,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{301:130,302:130,303:130,350:130,6022:130},power:193730,star:6,runes:[43750,43750,43750,43750,43750],skins:{16:60,58:60,177:60,192:60,258: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:[6,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:17007,hp:286172,intelligence:3196,physicalAttack:40354.6,strength:3207,armor:16985,armorPenetration:33360,dodge:17014.28,magicResist:6866,skin:0,favorPetId:6004,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,6007: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:6001,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:474060,intelligence:18945,physicalAttack:78,strength:2916,armor:28049.6,magicPower:57729,magicResist:15252,skin:0,favorPetId:6001,favorPower:11064},42:{id:"42",xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{210:130,211:130,212:130,213:130,6035:130},power:189864,star:6,runes:[43750,43750,43750,43750,43750],skins:{91:60,115:60,121:60,195:60,307:60},currentSkin:195,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,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:2442,hp:518209,intelligence:3476,physicalAttack:50,strength:18155,armor:37797.6,magicPower:76563.6,magicResist:29975,skin:195,favorPetId:6007,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},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:8263465,heroes:[46,9,56,51,42],pet:6006,favor:{9:6005,42:6001,51:6006,56:6007}},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,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},42:{id:"42",xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{210:130,211:130,212:130,213:130,6007:130},power:189864,star:6,runes:[43750,43750,43750,43750,43750],skins:{91:60,115:60,121:60,195:60,307:60},currentSkin:195,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:2442,hp:617785,intelligence:3476,physicalAttack:50,strength:18155,armor:37797.6,magicPower:66606,magicResist:29975,skin:195,favorPetId:6001,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},power:177096,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:0,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:28550,magicPower:64538,magicResist:22237,skin:0,favorPetId:0,favorPower:0},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},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,6035: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:6007,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: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}}},{id:6,args:{userId:8263484,heroes:[62,9,40,16,42],pet:6008,favor:{9:6005,16:6e3,40:6004,42:6007,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,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},16:{id:16,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{301:130,302:130,303:130,350:130,6002:130},power:191091,star:6,runes:[43750,43750,43750,43750,43750],skins:{16:60,58:60,177:60,192:60,258: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:[6,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:17007,hp:286172,intelligence:3196,physicalAttack:37367.32,strength:3207,armor:16985,armorPenetration:43317.6,dodge:14027,magicResist:6866,skin:0,favorPetId:6e3,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},42:{id:"42",xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{210:130,211:130,212:130,213:130,6035:130},power:189864,star:6,runes:[43750,43750,43750,43750,43750],skins:{91:60,115:60,121:60,195:60,307:60},currentSkin:195,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,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:2442,hp:518209,intelligence:3476,physicalAttack:50,strength:18155,armor:37797.6,magicPower:76563.6,magicResist:29975,skin:195,favorPetId:6007,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},6008:{id:6008,color:10,star:6,xp:450551,level:130,slots:[25,50,50,25,50,50],skills:{6036:130,6037:130},power:181943,type:"pet",perks:[5],name:null,armorPenetration:47911,intelligence:11064,strength:12360}}},{id:8,args:{userId:8263225,heroes:[35,9,48,16,42],pet:6006,favor:{9:6005,16:6e3,35:6006,42:6007,48:6001}},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,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},16:{id:16,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{301:130,302:130,303:130,350:130,6002:130},power:191091,star:6,runes:[43750,43750,43750,43750,43750],skins:{16:60,58:60,177:60,192:60,258: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:[6,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:17007,hp:286172,intelligence:3196,physicalAttack:37367.32,strength:3207,armor:16985,armorPenetration:43317.6,dodge:14027,magicResist:6866,skin:0,favorPetId:6e3,favorPower:11064},35:{id:35,xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{175:130,176:130,177:130,178:130,6032:130},power:189498,star:6,runes:[43750,43750,43750,43750,43750],skins:{48:60,74:60,79:60,194:60,293: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:[8,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:2647,hp:424763,intelligence:3554,physicalAttack:50,strength:17676,armor:41168.6,magicPower:69799.6,magicResist:43058,skin:0,favorPetId:6006,favorPower:11064},42:{id:"42",xp:3625195,level:130,color:18,slots:[0,0,0,0,0,0],skills:{210:130,211:130,212:130,213:130,6035:130},power:189864,star:6,runes:[43750,43750,43750,43750,43750],skins:{91:60,115:60,121:60,195:60,307:60},currentSkin:195,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,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:2442,hp:518209,intelligence:3476,physicalAttack:50,strength:18155,armor:37797.6,magicPower:76563.6,magicResist:29975,skin:195,favorPetId:6007,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,6007:130},power:190335,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:6001,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:497313,intelligence:2888,physicalAttack:33328,physicalCritChance:12280,strength:3169,armor:22142.6,armorPenetration:10180,magicResist:24816,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}}}
  11651. ];
  11652.  
  11653. const bestPack = {
  11654. pack: packs[0],
  11655. countWin: 0,
  11656. }
  11657.  
  11658. for (const pack of packs) {
  11659. const attackers = pack.attackers;
  11660. const battle = {
  11661. attackers,
  11662. defenders: [enemieHeroes],
  11663. type: 'brawl',
  11664. };
  11665.  
  11666. let countWinBattles = 0;
  11667. let countTestBattle = 10;
  11668. for (let i = 0; i < countTestBattle; i++) {
  11669. battle.seed = Math.floor(Date.now() / 1000) + Math.random() * 1000;
  11670. const result = await Calc(battle);
  11671. if (result.result.win) {
  11672. countWinBattles++;
  11673. }
  11674. if (countWinBattles > 7) {
  11675. console.log(pack)
  11676. bestPack.pack = pack.args;
  11677. }
  11678. }
  11679. if (countWinBattles > bestPack.countWin) {
  11680. bestPack.countWin = countWinBattles;
  11681. bestPack.pack = pack;
  11682. }
  11683. }
  11684.  
  11685. console.log(bestPack);
  11686. return bestPack.pack;
  11687. }
  11688.  
  11689. async questFarm() {
  11690. const calls = [this.callBrawlQuestFarm];
  11691. const result = await Send(JSON.stringify({ calls }));
  11692. return result.results[0].result.response;
  11693. }
  11694.  
  11695. async getBrawlInfo() {
  11696. const data = await Send(JSON.stringify({
  11697. calls: [
  11698. this.callUserGetInfo,
  11699. this.callBrawlQuestGetInfo,
  11700. this.callBrawlFindEnemies,
  11701. this.callTeamGetMaxUpgrade,
  11702. this.callBrawlGetInfo,
  11703. ]
  11704. }));
  11705.  
  11706. let attempts = data.results[0].result.response.refillable.find(n => n.id == 48);
  11707. const maxUpgrade = data.results[3].result.response;
  11708. const maxHero = Object.values(maxUpgrade.hero);
  11709. const maxTitan = Object.values(maxUpgrade.titan);
  11710. const maxPet = Object.values(maxUpgrade.pet);
  11711. this.maxUpgrade = [...maxHero, ...maxPet];
  11712. this.info = data.results[4].result.response;
  11713. this.mandatoryId = lib.data.brawl.promoHero[this.info.id].promoHero;
  11714. return {
  11715. attempts: attempts.amount,
  11716. questInfo: data.results[1].result.response,
  11717. findEnemies: data.results[2].result.response,
  11718. }
  11719. }
  11720.  
  11721. /**
  11722. * Carrying out a fight
  11723. *
  11724. * Проведение боя
  11725. */
  11726. async battle(userId) {
  11727. this.stats.count++;
  11728. const battle = await this.startBattle(userId, this.args);
  11729. const result = await Calc(battle);
  11730. console.log(result.result);
  11731. if (result.result.win) {
  11732. this.stats.win++;
  11733. } else {
  11734. this.stats.loss++;
  11735. if (!this.info.boughtEndlessLivesToday) {
  11736. this.attempts--;
  11737. }
  11738. }
  11739. return await this.endBattle(result);
  11740. // return await this.cancelBattle(result);
  11741. }
  11742.  
  11743. /**
  11744. * Starts a fight
  11745. *
  11746. * Начинает бой
  11747. */
  11748. async startBattle(userId, args) {
  11749. const call = {
  11750. name: "brawl_startBattle",
  11751. args,
  11752. ident: "brawl_startBattle"
  11753. }
  11754. call.args.userId = userId;
  11755. const calls = [call];
  11756. const result = await Send(JSON.stringify({ calls }));
  11757. return result.results[0].result.response;
  11758. }
  11759.  
  11760. cancelBattle(battle) {
  11761. const fixBattle = function (heroes) {
  11762. for (const ids in heroes) {
  11763. const hero = heroes[ids];
  11764. hero.energy = random(1, 999);
  11765. if (hero.hp > 0) {
  11766. hero.hp = random(1, hero.hp);
  11767. }
  11768. }
  11769. }
  11770. fixBattle(battle.progress[0].attackers.heroes);
  11771. fixBattle(battle.progress[0].defenders.heroes);
  11772. return this.endBattle(battle);
  11773. }
  11774.  
  11775. /**
  11776. * Ends the fight
  11777. *
  11778. * Заканчивает бой
  11779. */
  11780. async endBattle(battle) {
  11781. battle.progress[0].attackers.input = ['auto', 0, 0, 'auto', 0, 0];
  11782. const calls = [{
  11783. name: "brawl_endBattle",
  11784. args: {
  11785. result: battle.result,
  11786. progress: battle.progress
  11787. },
  11788. ident: "brawl_endBattle"
  11789. },
  11790. this.callBrawlQuestGetInfo,
  11791. this.callBrawlFindEnemies,
  11792. ];
  11793. const result = await Send(JSON.stringify({ calls }));
  11794. return result.results;
  11795. }
  11796.  
  11797. end(endReason) {
  11798. isCancalBattle = true;
  11799. isBrawlsAutoStart = false;
  11800. setProgress(endReason, true);
  11801. console.log(endReason);
  11802. this.resolve();
  11803. }
  11804. }
  11805.  
  11806. // подземку вконце впихнул
  11807. function DungeonFull() {
  11808. return new Promise((resolve, reject) => {
  11809. const dung = new executeDungeon2(resolve, reject);
  11810. const titanit = getInput('countTitanit');
  11811. dung.start(titanit);
  11812. });
  11813. }
  11814. /** Прохождение подземелья */
  11815. function executeDungeon2(resolve, reject) {
  11816. let dungeonActivity = 0;
  11817. let startDungeonActivity = 0;
  11818. let maxDungeonActivity = 150;
  11819. let limitDungeonActivity = 30180;
  11820. let countShowStats = 1;
  11821. //let fastMode = isChecked('fastMode');
  11822. let end = false;
  11823.  
  11824. let countTeam = [];
  11825. let timeDungeon = {
  11826. all: new Date().getTime(),
  11827. findAttack: 0,
  11828. attackNeutral: 0,
  11829. attackEarthOrFire: 0
  11830. }
  11831.  
  11832. let titansStates = {};
  11833. let bestBattle = {};
  11834.  
  11835. let teams = {
  11836. neutral: [],
  11837. water: [],
  11838. earth: [],
  11839. fire: [],
  11840. hero: []
  11841. }
  11842.  
  11843. let callsExecuteDungeon = {
  11844. calls: [{
  11845. name: "dungeonGetInfo",
  11846. args: {},
  11847. ident: "dungeonGetInfo"
  11848. }, {
  11849. name: "teamGetAll",
  11850. args: {},
  11851. ident: "teamGetAll"
  11852. }, {
  11853. name: "teamGetFavor",
  11854. args: {},
  11855. ident: "teamGetFavor"
  11856. }, {
  11857. name: "clanGetInfo",
  11858. args: {},
  11859. ident: "clanGetInfo"
  11860. }]
  11861. }
  11862.  
  11863. this.start = async function(titanit) {
  11864. //maxDungeonActivity = titanit > limitDungeonActivity ? limitDungeonActivity : titanit;
  11865. maxDungeonActivity = titanit || getInput('countTitanit');
  11866. send(JSON.stringify(callsExecuteDungeon), startDungeon);
  11867. }
  11868.  
  11869. /** Получаем данные по подземелью */
  11870. function startDungeon(e) {
  11871. stopDung = false; // стоп подземка
  11872. let res = e.results;
  11873. let dungeonGetInfo = res[0].result.response;
  11874. if (!dungeonGetInfo) {
  11875. endDungeon('noDungeon', res);
  11876. return;
  11877. }
  11878. console.log("Начинаем копать на фулл: ", new Date());
  11879. let teamGetAll = res[1].result.response;
  11880. let teamGetFavor = res[2].result.response;
  11881. dungeonActivity = res[3].result.response.stat.todayDungeonActivity;
  11882. startDungeonActivity = res[3].result.response.stat.todayDungeonActivity;
  11883. titansStates = dungeonGetInfo.states.titans;
  11884.  
  11885. teams.hero = {
  11886. favor: teamGetFavor.dungeon_hero,
  11887. heroes: teamGetAll.dungeon_hero.filter(id => id < 6000),
  11888. teamNum: 0,
  11889. }
  11890. let heroPet = teamGetAll.dungeon_hero.filter(id => id >= 6000).pop();
  11891. if (heroPet) {
  11892. teams.hero.pet = heroPet;
  11893. }
  11894. teams.neutral = getTitanTeam('neutral');
  11895. teams.water = {
  11896. favor: {},
  11897. heroes: getTitanTeam('water'),
  11898. teamNum: 0,
  11899. };
  11900. teams.earth = {
  11901. favor: {},
  11902. heroes: getTitanTeam('earth'),
  11903. teamNum: 0,
  11904. };
  11905. teams.fire = {
  11906. favor: {},
  11907. heroes: getTitanTeam('fire'),
  11908. teamNum: 0,
  11909. };
  11910.  
  11911. checkFloor(dungeonGetInfo);
  11912. }
  11913.  
  11914. function getTitanTeam(type) {
  11915. switch (type) {
  11916. case 'neutral':
  11917. return [4023, 4022, 4012, 4021, 4011, 4010, 4020];
  11918. case 'water':
  11919. return [4000, 4001, 4002, 4003]
  11920. .filter(e => !titansStates[e]?.isDead);
  11921. case 'earth':
  11922. return [4020, 4022, 4021, 4023]
  11923. .filter(e => !titansStates[e]?.isDead);
  11924. case 'fire':
  11925. return [4010, 4011, 4012, 4013]
  11926. .filter(e => !titansStates[e]?.isDead);
  11927. }
  11928. }
  11929.  
  11930. /** Создать копию объекта */
  11931. function clone(a) {
  11932. return JSON.parse(JSON.stringify(a));
  11933. }
  11934.  
  11935. /** Находит стихию на этаже */
  11936. function findElement(floor, element) {
  11937. for (let i in floor) {
  11938. if (floor[i].attackerType === element) {
  11939. return i;
  11940. }
  11941. }
  11942. return undefined;
  11943. }
  11944.  
  11945. /** Проверяем этаж */
  11946. async function checkFloor(dungeonInfo) {
  11947. if (!('floor' in dungeonInfo) || dungeonInfo.floor?.state == 2) {
  11948. saveProgress();
  11949. return;
  11950. }
  11951. // console.log(dungeonInfo, dungeonActivity);
  11952. setProgress(`${I18N('DUNGEON2')}: ${I18N('TITANIT')} ${dungeonActivity}/${maxDungeonActivity}`);
  11953. //setProgress('Dungeon: Титанит ' + dungeonActivity + '/' + maxDungeonActivity);
  11954. if (dungeonActivity >= maxDungeonActivity) {
  11955. endDungeon('Стоп подземка,', 'набрано титанита: ' + dungeonActivity + '/' + maxDungeonActivity);
  11956. return;
  11957. }
  11958. let activity = dungeonActivity - startDungeonActivity;
  11959. titansStates = dungeonInfo.states.titans;
  11960. if (stopDung){
  11961. endDungeon('Стоп подземка,', 'набрано титанита: ' + dungeonActivity + '/' + maxDungeonActivity);
  11962. return;
  11963. }
  11964. /*if (activity / 1000 > countShowStats) {
  11965. countShowStats++;
  11966. showStats();
  11967. }*/
  11968. bestBattle = {};
  11969. let floorChoices = dungeonInfo.floor.userData;
  11970. if (floorChoices.length > 1) {
  11971. for (let element in teams) {
  11972. let teamNum = findElement(floorChoices, element);
  11973. if (!!teamNum) {
  11974. if (element == 'earth') {
  11975. teamNum = await chooseEarthOrFire(floorChoices);
  11976. if (teamNum < 0) {
  11977. endDungeon('Невозможно победить без потери Титана!', dungeonInfo);
  11978. return;
  11979. }
  11980. }
  11981. chooseElement(floorChoices[teamNum].attackerType, teamNum);
  11982. return;
  11983. }
  11984. }
  11985. } else {
  11986. chooseElement(floorChoices[0].attackerType, 0);
  11987. }
  11988. }
  11989.  
  11990. /** Выбираем огнем или землей атаковать */
  11991. async function chooseEarthOrFire(floorChoices) {
  11992. bestBattle.recovery = -11;
  11993. let selectedTeamNum = -1;
  11994. for (let attempt = 0; selectedTeamNum < 0 && attempt < 4; attempt++) {
  11995. for (let teamNum in floorChoices) {
  11996. let attackerType = floorChoices[teamNum].attackerType;
  11997. selectedTeamNum = await attemptAttackEarthOrFire(teamNum, attackerType, attempt);
  11998. }
  11999. }
  12000. console.log("Выбор команды огня или земли: ", selectedTeamNum < 0 ? "не сделан" : floorChoices[selectedTeamNum].attackerType);
  12001. return selectedTeamNum;
  12002. }
  12003.  
  12004. /** Попытка атаки землей и огнем */
  12005. async function attemptAttackEarthOrFire(teamNum, attackerType, attempt) {
  12006. let start = new Date();
  12007. let team = clone(teams[attackerType]);
  12008. let startIndex = team.heroes.length + attempt - 4;
  12009. if (startIndex >= 0) {
  12010. team.heroes = team.heroes.slice(startIndex);
  12011. let recovery = await getBestRecovery(teamNum, attackerType, team, 25);
  12012. if (recovery > bestBattle.recovery) {
  12013. bestBattle.recovery = recovery;
  12014. bestBattle.selectedTeamNum = teamNum;
  12015. bestBattle.team = team;
  12016. }
  12017. }
  12018. let workTime = new Date().getTime() - start.getTime();
  12019. timeDungeon.attackEarthOrFire += workTime;
  12020. if (bestBattle.recovery < -10) {
  12021. return -1;
  12022. }
  12023. return bestBattle.selectedTeamNum;
  12024. }
  12025.  
  12026. /** Выбираем стихию для атаки */
  12027. async function chooseElement(attackerType, teamNum) {
  12028. let result;
  12029. switch (attackerType) {
  12030. case 'hero':
  12031. case 'water':
  12032. result = await startBattle(teamNum, attackerType, teams[attackerType]);
  12033. break;
  12034. case 'earth':
  12035. case 'fire':
  12036. result = await attackEarthOrFire(teamNum, attackerType);
  12037. break;
  12038. case 'neutral':
  12039. result = await attackNeutral(teamNum, attackerType);
  12040. }
  12041. if (!!result && attackerType != 'hero') {
  12042. let recovery = (!!!bestBattle.recovery ? 10 * getRecovery(result) : bestBattle.recovery) * 100;
  12043. let titans = result.progress[0].attackers.heroes;
  12044. console.log("Проведен бой: " + attackerType +
  12045. ", recovery = " + (recovery > 0 ? "+" : "") + Math.round(recovery) + "% \r\n", titans);
  12046. }
  12047. endBattle(result);
  12048. }
  12049.  
  12050. /** Атакуем Землей или Огнем */
  12051. async function attackEarthOrFire(teamNum, attackerType) {
  12052. if (!!!bestBattle.recovery) {
  12053. bestBattle.recovery = -11;
  12054. let selectedTeamNum = -1;
  12055. for (let attempt = 0; selectedTeamNum < 0 && attempt < 4; attempt++) {
  12056. selectedTeamNum = await attemptAttackEarthOrFire(teamNum, attackerType, attempt);
  12057. }
  12058. if (selectedTeamNum < 0) {
  12059. endDungeon('Невозможно победить без потери Титана!', attackerType);
  12060. return;
  12061. }
  12062. }
  12063. return findAttack(teamNum, attackerType, bestBattle.team);
  12064. }
  12065.  
  12066. /** Находим подходящий результат для атаки */
  12067. async function findAttack(teamNum, attackerType, team) {
  12068. let start = new Date();
  12069. let recovery = -1000;
  12070. let iterations = 0;
  12071. let result;
  12072. let correction = 0.01;
  12073. for (let needRecovery = bestBattle.recovery; recovery < needRecovery; needRecovery -= correction, iterations++) {
  12074. result = await startBattle(teamNum, attackerType, team);
  12075. recovery = getRecovery(result);
  12076. }
  12077. bestBattle.recovery = recovery;
  12078. let workTime = new Date().getTime() - start.getTime();
  12079. timeDungeon.findAttack += workTime;
  12080. return result;
  12081. }
  12082.  
  12083. /** Атакуем Нейтральной командой */
  12084. async function attackNeutral(teamNum, attackerType) {
  12085. let start = new Date();
  12086. let factors = calcFactor();
  12087. bestBattle.recovery = -0.2;
  12088. await findBestBattleNeutral(teamNum, attackerType, factors, true)
  12089. if (bestBattle.recovery < 0 || (bestBattle.recovery < 0.2 && factors[0].value < 0.5)) {
  12090. let recovery = 100 * bestBattle.recovery;
  12091. console.log("Не удалось найти удачный бой в быстром режиме: " + attackerType +
  12092. ", recovery = " + (recovery > 0 ? "+" : "") + Math.round(recovery) + "% \r\n", bestBattle.attackers);
  12093. await findBestBattleNeutral(teamNum, attackerType, factors, false)
  12094. }
  12095. let workTime = new Date().getTime() - start.getTime();
  12096. timeDungeon.attackNeutral += workTime;
  12097. if (!!bestBattle.attackers) {
  12098. let team = getTeam(bestBattle.attackers);
  12099. return findAttack(teamNum, attackerType, team);
  12100. }
  12101. endDungeon('Не удалось найти удачный бой!', attackerType);
  12102. return undefined;
  12103. }
  12104.  
  12105. /** Находит лучшую нейтральную команду */
  12106. async function findBestBattleNeutral(teamNum, attackerType, factors, mode) {
  12107. let countFactors = factors.length < 4 ? factors.length : 4;
  12108. let aradgi = !titansStates['4013']?.isDead;
  12109. let edem = !titansStates['4023']?.isDead;
  12110. let dark = [4032, 4033].filter(e => !titansStates[e]?.isDead);
  12111. let light = [4042].filter(e => !titansStates[e]?.isDead);
  12112. let actions = [];
  12113. if (mode) {
  12114. for (let i = 0; i < countFactors; i++) {
  12115. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(factors[i].id)));
  12116. }
  12117. if (countFactors > 1) {
  12118. let firstId = factors[0].id;
  12119. let secondId = factors[1].id;
  12120. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4001, secondId)));
  12121. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4002, secondId)));
  12122. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4003, secondId)));
  12123. }
  12124. if (aradgi) {
  12125. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(4013)));
  12126. if (countFactors > 0) {
  12127. let firstId = factors[0].id;
  12128. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4000, 4013)));
  12129. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4001, 4013)));
  12130. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4002, 4013)));
  12131. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4003, 4013)));
  12132. }
  12133. if (edem) {
  12134. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(4023, 4000, 4013)));
  12135. }
  12136. }
  12137. } else {
  12138. if (mode) {
  12139. for (let i = 0; i < factors.length; i++) {
  12140. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(factors[i].id)));
  12141. }
  12142. } else {
  12143. countFactors = factors.length < 2 ? factors.length : 2;
  12144. }
  12145. for (let i = 0; i < countFactors; i++) {
  12146. let mainId = factors[i].id;
  12147. if (aradgi && (mode || i > 0)) {
  12148. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4000, 4013)));
  12149. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4001, 4013)));
  12150. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4002, 4013)));
  12151. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4003, 4013)));
  12152. }
  12153. for (let i = 0; i < dark.length; i++) {
  12154. let darkId = dark[i];
  12155. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4001, darkId)));
  12156. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4002, darkId)));
  12157. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4003, darkId)));
  12158. }
  12159. for (let i = 0; i < light.length; i++) {
  12160. let lightId = light[i];
  12161. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4001, lightId)));
  12162. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4002, lightId)));
  12163. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4003, lightId)));
  12164. }
  12165. let isFull = mode || i > 0;
  12166. for (let j = isFull ? i + 1 : 2; j < factors.length; j++) {
  12167. let extraId = factors[j].id;
  12168. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4000, extraId)));
  12169. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4001, extraId)));
  12170. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(mainId, 4002, extraId)));
  12171. }
  12172. }
  12173. if (aradgi) {
  12174. if (mode) {
  12175. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(4013)));
  12176. }
  12177. for (let i = 0; i < dark.length; i++) {
  12178. let darkId = dark[i];
  12179. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(darkId, 4001, 4013)));
  12180. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(darkId, 4002, 4013)));
  12181. }
  12182. for (let i = 0; i < light.length; i++) {
  12183. let lightId = light[i];
  12184. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(lightId, 4001, 4013)));
  12185. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(lightId, 4002, 4013)));
  12186. }
  12187. }
  12188. for (let i = 0; i < dark.length; i++) {
  12189. let firstId = dark[i];
  12190. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId)));
  12191. for (let j = i + 1; j < dark.length; j++) {
  12192. let secondId = dark[j];
  12193. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4001, secondId)));
  12194. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4002, secondId)));
  12195. }
  12196. }
  12197. for (let i = 0; i < light.length; i++) {
  12198. let firstId = light[i];
  12199. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId)));
  12200. for (let j = i + 1; j < light.length; j++) {
  12201. let secondId = light[j];
  12202. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4001, secondId)));
  12203. actions.push(startBattle(teamNum, attackerType, getNeutralTeam(firstId, 4002, secondId)));
  12204. }
  12205. }
  12206. }
  12207. for (let result of await Promise.all(actions)) {
  12208. let recovery = getRecovery(result);
  12209. if (recovery > bestBattle.recovery) {
  12210. bestBattle.recovery = recovery;
  12211. bestBattle.attackers = result.progress[0].attackers.heroes;
  12212. }
  12213. }
  12214. }
  12215.  
  12216. /** Получаем нейтральную команду */
  12217. function getNeutralTeam(id, swapId, addId) {
  12218. let neutralTeam = clone(teams.water);
  12219. let neutral = neutralTeam.heroes;
  12220. if (neutral.length == 4) {
  12221. if (!!swapId) {
  12222. for (let i in neutral) {
  12223. if (neutral[i] == swapId) {
  12224. neutral[i] = addId;
  12225. }
  12226. }
  12227. }
  12228. } else if (!!addId) {
  12229. neutral.push(addId);
  12230. }
  12231. neutral.push(id);
  12232. return neutralTeam;
  12233. }
  12234.  
  12235. /** Получить команду титанов */
  12236. function getTeam(titans) {
  12237. return {
  12238. favor: {},
  12239. heroes: Object.keys(titans).map(id => parseInt(id)),
  12240. teamNum: 0,
  12241. };
  12242. }
  12243.  
  12244. /** Вычисляем фактор боеготовности титанов */
  12245. function calcFactor() {
  12246. let neutral = teams.neutral;
  12247. let factors = [];
  12248. for (let i in neutral) {
  12249. let titanId = neutral[i];
  12250. let titan = titansStates[titanId];
  12251. let factor = !!titan ? titan.hp / titan.maxHp + titan.energy / 10000.0 : 1;
  12252. if (factor > 0) {
  12253. factors.push({id: titanId, value: factor});
  12254. }
  12255. }
  12256. factors.sort(function(a, b) {
  12257. return a.value - b.value;
  12258. });
  12259. return factors;
  12260. }
  12261.  
  12262. /** Возвращает наилучший результат из нескольких боев */
  12263. async function getBestRecovery(teamNum, attackerType, team, countBattle) {
  12264. let bestRecovery = -1000;
  12265. let actions = [];
  12266. for (let i = 0; i < countBattle; i++) {
  12267. actions.push(startBattle(teamNum, attackerType, team));
  12268. }
  12269. for (let result of await Promise.all(actions)) {
  12270. let recovery = getRecovery(result);
  12271. if (recovery > bestRecovery) {
  12272. bestRecovery = recovery;
  12273. }
  12274. }
  12275. return bestRecovery;
  12276. }
  12277.  
  12278. /** Возвращает разницу в здоровье атакующей команды после и до битвы и проверяет здоровье титанов на необходимый минимум*/
  12279. function getRecovery(result) {
  12280. if (result.result.stars < 3) {
  12281. return -100;
  12282. }
  12283. let beforeSumFactor = 0;
  12284. let afterSumFactor = 0;
  12285. let beforeTitans = result.battleData.attackers;
  12286. let afterTitans = result.progress[0].attackers.heroes;
  12287. for (let i in afterTitans) {
  12288. let titan = afterTitans[i];
  12289. let percentHP = titan.hp / beforeTitans[i].hp;
  12290. let energy = titan.energy;
  12291. let factor = checkTitan(i, energy, percentHP) ? getFactor(i, energy, percentHP) : -100;
  12292. afterSumFactor += factor;
  12293. }
  12294. for (let i in beforeTitans) {
  12295. let titan = beforeTitans[i];
  12296. let state = titan.state;
  12297. beforeSumFactor += !!state ? getFactor(i, state.energy, state.hp / titan.hp) : 1;
  12298. }
  12299. return afterSumFactor - beforeSumFactor;
  12300. }
  12301.  
  12302. /** Возвращает состояние титана*/
  12303. function getFactor(id, energy, percentHP) {
  12304. let elemantId = id.slice(2, 3);
  12305. let isEarthOrFire = elemantId == '1' || elemantId == '2';
  12306. let energyBonus = id == '4020' && energy == 1000 ? 0.1 : energy / 20000.0;
  12307. let factor = percentHP + energyBonus;
  12308. return isEarthOrFire ? factor : factor / 10;
  12309. }
  12310.  
  12311. /** Проверяет состояние титана*/
  12312. function checkTitan(id, energy, percentHP) {
  12313. switch (id) {
  12314. case '4020':
  12315. return percentHP > 0.25 || (energy == 1000 && percentHP > 0.05);
  12316. break;
  12317. case '4010':
  12318. return percentHP + energy / 2000.0 > 0.63;
  12319. break;
  12320. case '4000':
  12321. return percentHP > 0.62 || (energy < 1000 && (
  12322. (percentHP > 0.45 && energy >= 400) ||
  12323. (percentHP > 0.3 && energy >= 670)));
  12324. }
  12325. return true;
  12326. }
  12327.  
  12328.  
  12329. /** Начинаем бой */
  12330. function startBattle(teamNum, attackerType, args) {
  12331. return new Promise(function (resolve, reject) {
  12332. args.teamNum = teamNum;
  12333. let startBattleCall = {
  12334. calls: [{
  12335. name: "dungeonStartBattle",
  12336. args,
  12337. ident: "body"
  12338. }]
  12339. }
  12340. send(JSON.stringify(startBattleCall), resultBattle, {
  12341. resolve,
  12342. teamNum,
  12343. attackerType
  12344. });
  12345. });
  12346. }
  12347.  
  12348. /** Возращает результат боя в промис */
  12349. /*function resultBattle(resultBattles, args) {
  12350. if (!!resultBattles && !!resultBattles.results) {
  12351. let battleData = resultBattles.results[0].result.response;
  12352. let battleType = "get_tower";
  12353. if (battleData.type == "dungeon_titan") {
  12354. battleType = "get_titan";
  12355. }
  12356. battleData.progress = [{ attackers: { input: ["auto", 0, 0, "auto", 0, 0] } }];//тест подземка правки
  12357. BattleCalc(battleData, battleType, function (result) {
  12358. result.teamNum = args.teamNum;
  12359. result.attackerType = args.attackerType;
  12360. args.resolve(result);
  12361. });
  12362. } else {
  12363. endDungeon('Потеряна связь с сервером игры!', 'break');
  12364. }
  12365. }*/
  12366. function resultBattle(resultBattles, args) {
  12367. battleData = resultBattles.results[0].result.response;
  12368. battleType = "get_tower";
  12369. if (battleData.type == "dungeon_titan") {
  12370. battleType = "get_titan";
  12371. }
  12372. battleData.progress = [{ attackers: { input: ["auto", 0, 0, "auto", 0, 0] } }];
  12373. BattleCalc(battleData, battleType, function (result) {
  12374. result.teamNum = args.teamNum;
  12375. result.attackerType = args.attackerType;
  12376. args.resolve(result);
  12377. });
  12378. }
  12379.  
  12380. /** Заканчиваем бой */
  12381.  
  12382. ////
  12383. async function endBattle(battleInfo) {
  12384. if (!!battleInfo) {
  12385. const args = {
  12386. result: battleInfo.result,
  12387. progress: battleInfo.progress,
  12388. }
  12389. if (battleInfo.result.stars < 3) {
  12390. endDungeon('Герой или Титан мог погибнуть в бою!', battleInfo);
  12391. return;
  12392. }
  12393. if (countPredictionCard > 0) {
  12394. args.isRaid = true;
  12395. } else {
  12396. const timer = getTimer(battleInfo.battleTime);
  12397. console.log(timer);
  12398. await countdownTimer(timer, `${I18N('DUNGEON2')}: ${I18N('TITANIT')} ${dungeonActivity}/${maxDungeonActivity}`);
  12399. }
  12400. const calls = [{
  12401. name: "dungeonEndBattle",
  12402. args,
  12403. ident: "body"
  12404. }];
  12405. lastDungeonBattleData = null;
  12406. send(JSON.stringify({ calls }), resultEndBattle);
  12407. } else {
  12408. endDungeon('dungeonEndBattle win: false\n', battleInfo);
  12409. }
  12410. }
  12411. /** Получаем и обрабатываем результаты боя */
  12412. function resultEndBattle(e) {
  12413. if (!!e && !!e.results) {
  12414. let battleResult = e.results[0].result.response;
  12415. if ('error' in battleResult) {
  12416. endDungeon('errorBattleResult', battleResult);
  12417. return;
  12418. }
  12419. let dungeonGetInfo = battleResult.dungeon ?? battleResult;
  12420. dungeonActivity += battleResult.reward.dungeonActivity ?? 0;
  12421. checkFloor(dungeonGetInfo);
  12422. } else {
  12423. endDungeon('Потеряна связь с сервером игры!', 'break');
  12424. }
  12425. }
  12426.  
  12427. /** Добавить команду титанов в общий список команд */
  12428. function addTeam(team) {
  12429. for (let i in countTeam) {
  12430. if (equalsTeam(countTeam[i].team, team)) {
  12431. countTeam[i].count++;
  12432. return;
  12433. }
  12434. }
  12435. countTeam.push({team: team, count: 1});
  12436. }
  12437.  
  12438. /** Сравнить команды на равенство */
  12439. function equalsTeam(team1, team2) {
  12440. if (team1.length == team2.length) {
  12441. for (let i in team1) {
  12442. if (team1[i] != team2[i]) {
  12443. return false;
  12444. }
  12445. }
  12446. return true;
  12447. }
  12448. return false;
  12449. }
  12450.  
  12451. function saveProgress() {
  12452. let saveProgressCall = {
  12453. calls: [{
  12454. name: "dungeonSaveProgress",
  12455. args: {},
  12456. ident: "body"
  12457. }]
  12458. }
  12459. send(JSON.stringify(saveProgressCall), resultEndBattle);
  12460. }
  12461.  
  12462.  
  12463. /** Выводит статистику прохождения подземелья */
  12464. function showStats() {
  12465. let activity = dungeonActivity - startDungeonActivity;
  12466. let workTime = clone(timeDungeon);
  12467. workTime.all = new Date().getTime() - workTime.all;
  12468. for (let i in workTime) {
  12469. workTime[i] = (workTime[i] / 1000).round(0);
  12470. }
  12471. countTeam.sort(function(a, b) {
  12472. return b.count - a.count;
  12473. });
  12474. console.log(titansStates);
  12475. console.log("Собрано титанита: ", activity);
  12476. console.log("Скорость сбора: " + (3600 * activity / workTime.all).round(0) + " титанита/час");
  12477. console.log("Время раскопок: ");
  12478. for (let i in workTime) {
  12479. let timeNow = workTime[i];
  12480. console.log(i + ": ", (timeNow / 3600).round(0) + " ч. " + (timeNow % 3600 / 60).round(0) + " мин. " + timeNow % 60 + " сек.");
  12481. }
  12482. console.log("Частота использования команд: ");
  12483. for (let i in countTeam) {
  12484. let teams = countTeam[i];
  12485. console.log(teams.team + ": ", teams.count);
  12486. }
  12487. }
  12488.  
  12489. /** Заканчиваем копать подземелье */
  12490. function endDungeon(reason, info) {
  12491. if (!end) {
  12492. end = true;
  12493. console.log(reason, info);
  12494. showStats();
  12495. if (info == 'break') {
  12496. setProgress('Dungeon stoped: Титанит ' + dungeonActivity + '/' + maxDungeonActivity +
  12497. "\r\nПотеряна связь с сервером игры!", false, hideProgress);
  12498. } else {
  12499. setProgress('Dungeon completed: Титанит ' + dungeonActivity + '/' + maxDungeonActivity, false, hideProgress);
  12500. }
  12501. setTimeout(cheats.refreshGame, 1000);
  12502. resolve();
  12503. }
  12504. }
  12505. }
  12506.  
  12507. //дарим подарки участникам других гильдий не выходя из своей гильдии
  12508. function NewYearGift_Clan() {
  12509. console.log('NewYearGift_Clan called...');
  12510. const userID = getInput('userID');
  12511. const AmontID = getInput('AmontID');
  12512. const GiftNum = getInput('GiftNum');
  12513.  
  12514. const data = {
  12515. "calls": [{
  12516. "name": "newYearGiftSend",
  12517. "args": {
  12518. "userId": userID,
  12519. "amount": AmontID,
  12520. "giftNum": GiftNum,
  12521. "users": {
  12522. [userID]: AmontID
  12523. }
  12524. },
  12525. "ident": "body"
  12526. }
  12527. ]
  12528. }
  12529.  
  12530. const dataJson = JSON.stringify(data);
  12531.  
  12532. SendRequest(dataJson, e => {
  12533. let userInfo = e.results[0].result.response;
  12534. console.log(userInfo);
  12535. });
  12536. setProgress(I18N('SEND_GIFT'), true);
  12537. }
  12538. })();
  12539.  
  12540. /**
  12541. * TODO:
  12542. * Получение всех уровней при сборе всех наград (квест на титанит и на энку) +-
  12543. * Добивание на арене титанов
  12544. * Закрытие окошек по Esc +-
  12545. * Починить работу скрипта на уровне команды ниже 10 +-
  12546. * Написать номальную синхронизацию
  12547. * Добавить дополнительные настройки автопокупки в "Тайном богатстве"
  12548. */