Greasy Fork

Greasy Fork is available in English.

HWHNewCharacterExt

Extension for HeroWarsHelper script

当前为 2025-10-31 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name             HWHNewCharacterExt
// @name:en          HWHNewCharacterExt
// @name:ru          HWHNewCharacterExt
// @namespace        HWHNewCharacterExt
// @version          1.54
// @description      Extension for HeroWarsHelper script
// @description:en   Extension for HeroWarsHelper script
// @description:ru   Расширение для скрипта HeroWarsHelper
// @author           ZingerY, Green
// @license          Copyright Green
// @match            https://www.hero-wars.com/*
// @match            https://apps-1701433570146040.apps.fbsbx.com/*
// @run-at           document-start
// ==/UserScript==

(function () {
    if (!this.HWHClasses) {
        console.log('%cObject for extension not found', 'color: red');
        return;
    }

    console.log('%cStart Extension ' + GM_info.script.name + ', v' + GM_info.script.version + ' by ' + GM_info.script.author, 'color: red');
    const { addExtentionName } = HWHFuncs;
    addExtentionName(GM_info.script.name, GM_info.script.version, GM_info.script.author);

    const { popup, confShow, setProgress, I18N, countdownTimer } = HWHFuncs;

    const { i18nLangData } = HWHData;

    const { WinFixBattle } = HWHClasses;

    const i18nLangDataEn = {
        NEWCHARACTER: 'New Character',
        NEWCHARACTER_TITLE: 'Complete quests for a new hero or titan',
        NEWCHARACTER_NOEVENT: 'The event is not active',
        NEWHERO: '<span style="color: green;"> New Hero Event </span> <br>',
        NEWTITAN: '<span style="color: green;"> New Titan Event </span> <br>',
        NEWHERO_COMPLETETASKS: 'Complete the tasks',
        NEWHERO_COMPLETETASKS_TITLE: 'Complete the event tasks',
        NEWHERO_COMPLETECAPTERS: 'Complete chapters',
        NEWHERO_COMPLETECAPTERS_TITLE: 'Complete chapters',
        NEWHERO_SELECTACTION: 'Select an action',
        NEWTITAN_GETTITANS: 'Сollect the Titans',
        NEWTITAN_GETTITANS_TITLE: 'Сollecting the Titans of the maximum rank by purchasing fragments in the store',
        NEWTITAN_GETHEROES: 'Сollect the Heroes',
        NEWTITAN_GETHEROES_TITLE: 'Сollecting the Heroes of the maximum rank by purchasing fragments in the store',
        NEWTITAN_GETINFLUENCESKILL: 'Сollect totem skills',
        NEWTITAN_GETINFLUENCESKILL_TITLE: 'Get the influence skill of the maximum rank by purchasing fragments in the store',
        NEWTITAN_GETTITANSPROGRESS: '<span style="color: green;"> {counter} </span> titans left to collect',
        NEWTITAN_GETTITANSCOLLECTED: 'All titans have been collected',
        NEWTITAN_GETINFLUENCESKILLCOLLECTED: 'All influence skills have been collected',
        NEWTITAN_GETINFLUENCESKILLPROGRESS: '<span style="color: green;"> {counter} </span> influence skills left to collect <br> Collecting...',
        NEWTITAN_CHAPTERNOTAVAILABLE: 'Chapter unavailable. Complete Chapter 1',
        NEWTITAN_GETHEROCOLLECTED: 'All heroes have been collected',
        NEWTITAN_GETHEROCOLLECTEDPROGRESS: '<span style="color: green;"> {counter} </span> heroes left to collect <br> Collecting...',
        NEWCHARACTER_SOMETHINGWENTWRONG: '<span style="color: red;"> Something went wrong </span> <br> Please try again',
        NEWTITAN_COLLECTEVERYTHING: 'Collect everything',
        NEWTITAN_COLLECTEVERYTHING_TITLE: 'Collect heroes, titans, totems, pets',
        NEWTITAN_BOSSWASKILLED: '<span style="color: green;"> The boss was killed </span>',
        NEWTITAN_BOSSWASNOTKILLED: '<span style="color: green;"> The boss was not killed </span> <br> Restart the game and kill the boss',
        NEWTITAN_COMPLETECHAPTER: 'Complete the chapter',
        NEWTITAN_COMPLETECHAPTER_TITLE: 'Complete an available chapter',
        NEWTITAN_COMPLETECHAPTERAllCOMPLETED: 'All chapters completed',
        NEWTITAN_NOTENOUGHBUFF: 'Not enough power to complete Chapter <span style="color: green;"> {chapterNumber} </span>'+
        'You have: <span style="color: red;"> {buffAmount} </span> <br>' +
        'You need: <span style="color: green;"> {invasionBuff} </span>',
        NEWTITAN_ENTERTITANIDS: 'Chapter <span style="color: green;"> {chapterNumber} </span> is available for completion <br> Enter <span style="color: red;"> 5 </span> titan IDs separated by commas or dashes',
        NEWTITAN_ENTERHEROIDS: 'Chapter <span style="color: green;"> {chapterNumber} </span> is available for completion <br> Enter <span style="color: red;"> 5 </span> hero IDs separated by commas or dashes',
        NEWTITAN_MUSTFIVETITANS:'There must be <span style="color: red;"> 5 </span> titans',
        NEWTITAN_MUSTFIVEHEROES:'There must be <span style="color: red;"> 5 </span> heroes',
        NEWTITAN_MUST_ONLY_NUMBERS: 'The list must contain only numbers and commas',
        NEWTITAN_LETSBEGIN: 'Let\'s start...',
        NEWTITAN_OUTDATEDVERSION: '<span style="color: red;"> Outdated version of HeroWarsHelper </span> <br> Please update the script',
        NEWTITAN_MISSION_PROGRESS: 'Attack <span style="color: green;"> {missionNumber} </span> enemy team',
        NEWHERO_NOTHING_HERE: 'There\'s nothing here yet. Please wait.'
    };

    i18nLangData['en'] = Object.assign(i18nLangData['en'], i18nLangDataEn);

    const i18nLangDataRu = {
        NEWCHARACTER: 'Новый персонаж',
        NEWCHARACTER_TITLE: 'Выполнять задания для нового героя или титана',
        NEWCHARACTER_NOEVENT: 'Ивент не активен',
        NEWHERO: '<span style="color: green;"> Событие Нового Героя </span> <br>',
        NEWTITAN: '<span style="color: green;"> Событие Нового Титана </span> <br>',
        NEWHERO_COMPLETETASKS: 'Выполнить задания',
        NEWHERO_COMPLETETASKS_TITLE: 'Выполнить заданий ивента',
        NEWHERO_COMPLETECAPTERS: 'Проходить главы',
        NEWHERO_COMPLETECAPTERS_TITLE: 'Проходить главы',
        NEWHERO_SELECTACTION: 'Выберите действие',
        NEWTITAN_GETTITANS: 'Собрать титанов',
        NEWTITAN_GETTITANS_TITLE: 'Собрать титанов максимального ранга, покупая фрагменты в магазине',
        NEWTITAN_GETHEROES: 'Собрать героев',
        NEWTITAN_GETHEROES_TITLE: 'Собрать героев максимального ранга, покупая фрагменты в магазине',
        NEWTITAN_GETINFLUENCESKILL: 'Собрать тотемы',
        NEWTITAN_GETINFLUENCESKILL_TITLE: 'Собрать навыки тотемов максимального ранга, покупая фрагменты в магазине',
        NEWTITAN_GETTITANSPROGRESS: 'Осталось собрать титанов: <span style="color: green;"> {counter} </span> шт.',
        NEWTITAN_GETTITANSCOLLECTED: 'Все титаны собраны',
        NEWTITAN_GETINFLUENCESKILLCOLLECTED: 'Все навыки влияния собраны',
        NEWTITAN_GETINFLUENCESKILLPROGRESS: 'Осталось собрать навыков тотемов: <span style="color: green;"> {counter} </span> шт. <br> Собираем...',
        NEWTITAN_CHAPTERNOTAVAILABLE: 'Глава не доступна. Завершите первую главу',
        NEWTITAN_GETHEROCOLLECTED: 'Все герои собраны',
        NEWTITAN_GETHEROCOLLECTEDPROGRESS: 'Осталось собрать героев: <span style="color: green;"> {counter} </span> шт. <br> Собираем...',
        NEWCHARACTER_SOMETHINGWENTWRONG: '<span style="color: red;"> Что-то пошло не так </span> <br> Попробуйте заново',
        NEWTITAN_COLLECTEVERYTHING: 'Собрать все',
        NEWTITAN_COLLECTEVERYTHING_TITLE: 'Собрать героев, титанов, тотемы, питомцев',
        NEWTITAN_BOSSWASKILLED: '<span style="color: green;"> Убили босса </span>',
        NEWTITAN_BOSSWASNOTKILLED: '<span style="color: green;"> Босса не убили </span> <br> Перезагрузите игру, и убейте босса',
        NEWTITAN_COMPLETECHAPTER: 'Пройти главу',
        NEWTITAN_COMPLETECHAPTER_TITLE: 'Пройти доступную главу',
        NEWTITAN_COMPLETECHAPTERAllCOMPLETED: 'Все главы пройдены',
        NEWTITAN_NOTENOUGHBUFF: 'Недостаточно усиления для прохождения <span style="color: green;"> {chapterNumber} </span> главы <br> ' +
        'У вас: <span style="color: red;"> {buffAmount} </span> <br>' +
        'Необходимо: <span style="color: green;"> {invasionBuff} </span>',
        NEWTITAN_ENTERTITANIDS: 'Для прохождения доступна <span style="color: green;"> {chapterNumber} </span> глава <br> Введите <span style="color: red;"> 5 </span> id <span style="color: green;"> титанов </span> через запятые или дефисы',
        NEWTITAN_ENTERHEROIDS: 'Для прохождения доступна <span style="color: green;"> {chapterNumber} </span> глава <br> Введите <span style="color: red;"> 5 </span> id <span style="color: green;"> героев </span> через запятые или дефисы',
        NEWTITAN_MUSTFIVETITANS:'Должно быть <span style="color: red;"> 5 </span> титанов',
        NEWTITAN_MUSTFIVEHEROES:'Должно быть <span style="color: red;"> 5 </span> героев',
        NEWTITAN_MUST_ONLY_NUMBERS: 'Список должен содержать только цифры и запятые',
        NEWTITAN_LETSBEGIN: 'Начинаем начинать...',
        NEWTITAN_OUTDATEDVERSION: '<span style="color: red;"> Устаревшая версия HeroWarsHelper </span> <br> Пожалуйста, обновите скрипт',
        NEWTITAN_MISSION_PROGRESS: 'Атакуем <span style="color: green;"> {missionNumber} </span> комнаду противника',
        NEWHERO_NOTHING_HERE: 'Здесь пока ничего нет. Ожидайте'
    };

    i18nLangData['ru'] = Object.assign(i18nLangData['ru'], i18nLangDataRu);

    ///////////////////////////////////////////////////////////////////////////////////////////////

    // Добавление кнопоки в окно Разное
    const { othersPopupButtons } = HWHData;
    othersPopupButtons.push({
        get msg() {
            return I18N('NEWCHARACTER');
        },
        get title() {
            return I18N('NEWCHARACTER_TITLE');
        },
        result: async function () {
            if (scriptInfo.version < 2.390){
                confShow(`${I18N('NEWTITAN_OUTDATEDVERSION')}`);
                return;
            }
            console.log(scriptInfo.version);
            let invasionInfo = await Caller.send('invasion_getInfo');
            if (invasionInfo) {
                let invasionInfoId = invasionInfo.id;
                let chapters = Object.values(lib.data.invasion.chapter).filter((e) => e.invasionId === invasionInfoId);
                let titanShopId = await getShopId(chapters, 'titan');
                try {
                    if (titanShopId) {
                        await onClickNewTitanButton();
                    } else {
                        await onClickNewHeroButton();
                    }
                } catch (e) {
                    confShow(`${I18N('NEWCHARACTER_SOMETHINGWENTWRONG')}`);
                }
            } else {
                confShow(`${I18N('NEWCHARACTER_NOEVENT')}`);
            }
        },
        color: 'pink',
    });

    async function onClickNewHeroButton() {
        const popupButtons = [
            {
                get msg() {
                    return I18N('NEWHERO_COMPLETETASKS');
                },
                get title() {
                    return I18N('NEWHERO_COMPLETETASKS_TITLE');
                },
                result: async function () {
                    confShow(I18N('NEWHERO_NOTHING_HERE'));
                },
                color: 'green',
            },
            {
                get msg() {
                    return I18N('NEWHERO_COMPLETECAPTERS');
                },
                get title() {
                    return I18N('NEWHERO_COMPLETECAPTERS_TITLE');
                },
                result: () => {
                    confShow(I18N('NEWHERO_NOTHING_HERE'));
                },
                color: 'blue',
            },
        ];
        popupButtons.push({ result: false, isClose: true });
        const answer = await popup.confirm(`${I18N('NEWHERO')} ${I18N('NEWHERO_SELECTACTION')}`, popupButtons);
        if (typeof answer === 'function') {
            answer();
        }
    }

    async function onClickNewTitanButton() {
        const popupButtons = [
            {
                get msg() {
                    return I18N('NEWTITAN_GETTITANS');
                },
                get title() {
                    return I18N('NEWTITAN_GETTITANS_TITLE');
                },
                result: async function () {
                    await newTitanGetTitans();
                },
                color: 'green',
            },
            {
                get msg() {
                    return I18N('NEWTITAN_GETINFLUENCESKILL');
                },
                get title() {
                    return I18N('NEWTITAN_GETINFLUENCESKILL_TITLE');
                },
                result: async function () {
                    await newTitanGetInvasionFragmentSkill();
                },
                color: 'green',
            },
            {
                get msg() {
                    return I18N('NEWTITAN_GETHEROES');
                },
                get title() {
                    return I18N('NEWTITAN_GETHEROES_TITLE');
                },
                result: async function () {
                    let farmedChapters = await Caller.send('invasion_getInfo').then((e) => e.farmedChapters);
                    if (farmedChapters.length >= 1) {
                        await newTitanGetHeroes();
                    } else {
                        confShow(`${I18N('NEWTITAN_CHAPTERNOTAVAILABLE')}`);
                    }
                },
                color: 'green',
            },
            {
                get msg() {
                    return I18N('NEWTITAN_COLLECTEVERYTHING');
                },
                get title() {
                    return I18N('NEWTITAN_COLLECTEVERYTHING_TITLE');
                },
                result: async function () {
                    await newTitanGetTitans();
                    await newTitanGetInvasionFragmentSkill();
                    let farmedChapters = await Caller.send('invasion_getInfo').then((e) => e.farmedChapters);
                    if (farmedChapters.length >= 1) {
                        await newTitanGetHeroes();
                    } else {
                        confShow(`${I18N('NEWTITAN_CHAPTERNOTAVAILABLE')}`);
                    }
                },
                color: 'pink',
            },
            {
                get msg() {
                    return I18N('NEWTITAN_COMPLETECHAPTER');
                },
                get title() {
                    return I18N('NEWTITAN_COMPLETECHAPTER_TITLE');
                },
                result: async function () {
                    await newTitanCompleteChapter();
                },
                color: 'blue',
            },
        ];
        popupButtons.push({ result: false, isClose: true });
        const answer = await popup.confirm(`${I18N('NEWTITAN')} ${I18N('NEWHERO_SELECTACTION')}`, popupButtons);
        if (typeof answer === 'function') {
            answer();
        }
    }
    //****************************************************************************************************
    //****************************************************************************************************
    //****************************************************************************************************
    //****************************************************************************************************
    async function newTitanCompleteChapter() {
        //Получить состояние на карте
        let invasionInfo = await Caller.send('invasion_getInfo');
        let invasionInfoId = invasionInfo.id;
        let farmedChapters = invasionInfo.farmedChapters;
        let buffAmount = invasionInfo.buffAmount;
        console.log('invasionInfoId ' + invasionInfoId);
        console.log('farmedChapters ', JSON.stringify(farmedChapters));
        console.log('buffAmount ' + buffAmount);

        //Получить id главы для атаки
        let chapters = Object.values(lib.data.invasion.chapter).filter((e) => e.invasionId === invasionInfoId);
        if (chapters.length == farmedChapters.length) {
            confShow(I18N('NEWTITAN_GETTITANSCOLLECTED'));
        }
        console.log( chapters);
        let chapterId = 0;
        let invasionBuff = 0;
        let titanOrHero = '';
        let chapterNumber = 0;
        for (let chapter of chapters) {
            if (!farmedChapters.includes(chapter.id)) {
                chapterId = chapter.id;
                if (chapter.requirements?.invasionBuff) {
                    invasionBuff = chapter.requirements.invasionBuff;
                }
                titanOrHero = chapter.settings.unitType;
                chapterNumber = chapters.indexOf(chapter)+1;
                break;
            }
        }
        console.log('chapterId ' + chapterId);
        console.log('invasionBuff ' + invasionBuff);
        console.log('titanOrHero ' + titanOrHero);
        console.log('chapterNumber ' + chapterNumber);

        if (buffAmount < invasionBuff) {
            confShow(I18N('NEWTITAN_NOTENOUGHBUFF', { chapterNumber, buffAmount, invasionBuff}));
            return;
        }

        //Получить id магазина
        let shopId = getShopId(chapters, titanOrHero); //1073; // Магазин титанов
        console.log('Id магазина ' + shopId);
        if (titanOrHero === 'hero' ) {
            await сompleteHeroesChapter(shopId, chapterId, chapterNumber);
        }
        if (titanOrHero === 'titan' ) {
            await сompleteTitansChapter(shopId, chapterId, chapterNumber);
        }


    }
    async function сompleteHeroesChapter(shopId, chapterId, chapterNumber) {
        //Атакующие герои: Галахад, Тристан, Лирия, Кира, Себастьян.
        /*Питомцы
        6000 - Фенрис   //6005 - Альбрус
        6001 - Оливер	//6006 - Аксель
        6002 - Мерлин   //6007 - Бисквит
        6003 - Мара	    //6008 - Хорус
        6004 - Каин	    //6009 - Векс*/
        let heroAttackingTeams = {heroes: [2, 54, 67, 3, 48], pets: [6005,6000,6001,6006,6008]};
        let titanOrHero = 'hero';

        //Id героев, что необходимо собрать
        let heroIds = await getTeamButton(heroAttackingTeams.heroes, chapterNumber, titanOrHero);
        console.log('heroIds ', JSON.stringify(heroIds));
        if (!heroIds) {
            return;
        }
        setProgress(I18N('NEWTITAN_LETSBEGIN'), false);

        //Активировать главу
        let chapterInfo = await Caller.send({ name: 'invasion_setActiveChapter', args: { chapterId: chapterId } });
        let haveHeroFragments = chapterInfo.invasion.fragments;
        console.log('haveHeroFragments ', JSON.stringify(haveHeroFragments));

        //Id миссии
        let firstMissionId = chapterInfo.invasion.actions[0].payload.id;
        let missionId = firstMissionId;

        //Жизни
        let lives = chapterInfo.invasion.lives;
        console.log('firstMissionId ' + firstMissionId);
        console.log('missionId ' + missionId);
        console.log('lives ' + lives);

        //Фрагменты героев
        let heroFragments = [0, 0, 0, 0, 0];
        for (let i = 0; i < 5; i++) {
            if (haveHeroFragments[heroIds[i]]) {
                heroFragments[i] = haveHeroFragments[heroIds[i]];
            }
        }
        console.log('shopId ' + shopId);
        console.log(heroIds);
        console.log('heroFragments ', JSON.stringify(heroFragments));

        //Питомцы, что необходимо купить
        let pets = heroAttackingTeams.pets;

        while (lives > 0 && missionId <= firstMissionId + 7) {
            //Купить героев
            let result = await buyHeroesAndPets(shopId, heroIds, heroFragments, pets);

            //Текущая миссия босс или нет
            let boss = false;

            //Произвести атаку босса
            if (missionId == firstMissionId + 7) {
                boss = true;
                console.log('%cАтакуем босса ', 'color: green; font-weight: bold;');
            }

            //Получить атакующую команду
            let heroes = [];
            let havePets = [];
            let pet;
            await getAttackingTeam(heroes, havePets);
            console.log('heroes ', JSON.stringify(heroes));
            if (havePets.length > 0) {
                //Основной питомец 6005 - Альбрус
                let mainPet = 6005;
                if (havePets.includes(mainPet)) {
                    pet = mainPet;
                } else {
                    pet = havePets[0];
                }
            }

            //Проходим миссию
            setProgress(I18N('NEWTITAN_MISSION_PROGRESS', {missionNumber: 1 + missionId - firstMissionId}), false);
            await attackHeroMission(missionId, chapterId, heroes, pet, boss);

            //Результат атаки
            let invasionInfo = await Caller.send('invasion_getInfo');
            let missions = Object.values(invasionInfo.actions);
            for (let mission of missions) {
                if (mission.payload.wins == 0) {
                    missionId = mission.payload.id;
                    break;
                }
            }

            //Результат атаки босса
            if (boss) {
                if (invasionInfo.farmedChapters.includes(chapterId)) {
                    confShow(I18N('NEWTITAN_BOSSWASKILLED'));
                } else {
                    confShow(I18N('NEWTITAN_BOSSWASNOTKILLED'));
                }
                return;
            }
            lives = invasionInfo.lives;
            console.log('missionId ' + missionId);
            console.log('lives ' + lives);
        }
    }



    async function сompleteTitansChapter(shopId, chapterId, chapterNumber) {
        //Атакующие титаны: Ияри, Солярис, Молох, Игнис, Араджи
        /*Навыки тотемов:
        elemental                  primal
        4500 - Последний Всполох   4506 - Пульс Древних
        4502 - Ледниковый Период   4507 - Первородное Рвение
        4503 - Гнев Недр           4508 - Эгида Эха
        4509 - Танец Пламени       4514 - Тройной Круговорот
        4510 - Шепот Глубин        4515 - Зов Стихий
        4511 - Гул Скал */

        const elementalSkils = [4500,4502,4503,4509,4510,4511];
        const primalSkils = [4506,4507,4508,4514,4515]
        let titanAttackingTeams = {heroes: [4042, 4043, 4010, 4012, 4013], titanSkilsIds: [4500, 4507]};
        let titanOrHero = 'titan';

        //Id титанов, что необходимо собрать
        let titanIds = await getTeamButton(titanAttackingTeams.heroes, chapterNumber, titanOrHero);
        console.log('titanIds ', JSON.stringify(titanIds));
        if (!titanIds) {
            return;
        }
        setProgress(I18N('NEWTITAN_LETSBEGIN'), false);

        //Активировать главу
        let chapterInfo = await Caller.send({ name: 'invasion_setActiveChapter', args: { chapterId: chapterId } });
        let haveTitanFragments = chapterInfo.invasion.fragments;
        console.log('haveTitanFragments ', JSON.stringify(haveTitanFragments));

        //Id миссии
        let firstMissionId = chapterInfo.invasion.actions[0].payload.id;
        let missionId = firstMissionId;

        //Жизни
        let lives = chapterInfo.invasion.lives;
        console.log('firstMissionId ' + firstMissionId);
        console.log('missionId ' + missionId);
        console.log('lives ' + lives);

        //Фрагменты титанов
        let titanFragments = [0, 0, 0, 0, 0];
        for (let i = 0; i < 5; i++) {
            if (haveTitanFragments[titanIds[i]]) {
                titanFragments[i] = haveTitanFragments[titanIds[i]];
            }
        }
        console.log('shopId ' + shopId);
        console.log(titanIds);
        console.log('titanFragments ', JSON.stringify(titanFragments));

        //Навыки тотемов, что необходимо собрать
        let titanSkilsIds = titanAttackingTeams.titanSkilsIds;

        //Фрагменты навыков тотемов
        let titanSkilFragments = [];
        for (let t of titanSkilsIds){
            titanSkilFragments.push(0);
        }


        while (lives > 0 && missionId <= firstMissionId + 7) {
            //Купить титанов
            let result = await buyTitansAndTotemSkils(shopId, titanIds, titanFragments, titanSkilsIds, titanSkilFragments);

            //Текущая миссия босс или нет
            let boss = false;

            //Произвести атаку босса
            if (missionId == firstMissionId + 7) {
                boss = true;
                console.log('%cАтакуем босса ', 'color: green; font-weight: bold;');
            }

            //Получить атакующую команду
            let heroes = [];
            let titanSkil = [];
            await getAttackingTeam(heroes, titanSkil);
            console.log('heroes ', JSON.stringify(heroes));
            let spiritSkills = new Array();
            if (titanSkil.length > 0) {
                for (let ts of titanSkil) {
                    if (elementalSkils.includes(ts)) {
                        spiritSkills.push(['elemental', ts]);
                    }
                    if (primalSkils.includes(ts)) {
                        spiritSkills.push(['primalSkils', ts]);
                    }
                }
            }
            let firstSpiritSkills = Object.fromEntries(spiritSkills);

            //Проходим миссию
            setProgress(I18N('NEWTITAN_MISSION_PROGRESS', {missionNumber: 1 + missionId - firstMissionId}), false);
            await attackTitanMission(missionId, chapterId, heroes, firstSpiritSkills, boss);

            //Результат атаки
            let invasionInfo = await Caller.send('invasion_getInfo');
            let missions = Object.values(invasionInfo.actions);
            for (let mission of missions) {
                if (mission.payload.wins == 0) {
                    missionId = mission.payload.id;
                    break;
                }
            }

            //Результат атаки босса
            if (boss) {
                if (invasionInfo.farmedChapters.includes(chapterId)) {
                    confShow(I18N('NEWTITAN_BOSSWASKILLED'));
                } else {
                    confShow(I18N('NEWTITAN_BOSSWASNOTKILLED'));
                }
                return;
            }
            lives = invasionInfo.lives;
            console.log('missionId ' + missionId);
            console.log('lives ' + lives);
        }
    }

    async function newTitanGetTitans() {
        //Получить состояние на карте
        let invasionInfo = await Caller.send('invasion_getInfo');
        let invasionInfoId = invasionInfo.id;
        let farmedChapters = invasionInfo.farmedChapters;
        console.log('invasionInfoId ' + invasionInfoId);
        console.log('farmedChapters ', JSON.stringify(farmedChapters));

        //Получить id первой главый
        let chapters = Object.values(lib.data.invasion.chapter).filter((e) => e.invasionId === invasionInfoId);
        let chapterId = getChapterId(chapters, 'titan');
        console.log('chapterId ' + chapterId);

        //Получить id магазина
        let titanShopId = getShopId(chapters, 'titan'); //1073; // Магазин титанов
        console.log('Id магазина титанов ' + titanShopId);

        let cycle = true;
        while (cycle) {
            //Получить титанов, которых нужно собрать
            let allTitanIdsToBuy = await getTitanIdsToBuy();
            if (allTitanIdsToBuy.length == 0) {
                setProgress('', true);
                //await new Promise((e) => setTimeout(e, 4000));
                confShow(I18N('NEWTITAN_GETTITANSCOLLECTED'));
                cycle = false;
                return;
            }

            //Активировать главу
            let chapterInfo = await Caller.send({ name: 'invasion_setActiveChapter', args: { chapterId: chapterId } });
            let haveTitanFragments = chapterInfo.invasion.fragments;

            //Id миссии
            let firstMissionId = chapterInfo.invasion.actions[0].payload.id;
            let missionId = firstMissionId;

            //Жизни
            let lives = chapterInfo.invasion.lives;
            console.log('firstMissionId ' + firstMissionId);
            console.log('missionId ' + missionId);
            console.log('lives ' + lives);

            //Id титанов, что необходимо собрать
            let titanIds = [0, 0];
            if (allTitanIdsToBuy.length >= 2) {
                titanIds = [allTitanIdsToBuy[0], allTitanIdsToBuy[1]];
            } else {
                titanIds[0] = allTitanIdsToBuy[0];
                if (titanIds[0] != Number(Object.keys(haveTitanFragments)[0])) {
                    titanIds[1] = Number(Object.keys(haveTitanFragments)[0]);
                } else {
                    titanIds[1] = Number(Object.keys(haveTitanFragments)[1]);
                }
            }
            //Фрагменты титанов
            let titanFragments = [0, 0];
            if (haveTitanFragments[titanIds[0]]) {
                titanFragments[0] = haveTitanFragments[titanIds[0]];
            }
            if (haveTitanFragments[titanIds[1]]) {
                titanFragments[1] = haveTitanFragments[titanIds[1]];
            }

            console.log('titanShopId ' + titanShopId);
            console.log(titanIds);
            console.log(titanFragments);

            //Навыки тотемов, что необходимо собрать
            let titanSkilsIds = await getTitanSkillIdsToBuy();

            //Фрагменты навыков тотемов
            let titanSkilFragments = [0, 0];
            if (titanSkilsIds.length <= 1) {
                titanSkilFragments = [0];
            }

            setProgress(
                I18N('NEWTITAN_GETTITANSPROGRESS', { counter: allTitanIdsToBuy.length }) +
                    '<br>' +
                    I18N('NEWTITAN_GETINFLUENCESKILLPROGRESS', { counter: titanSkilsIds.length }),
                false
            );

            while (lives > 0 && missionId <= firstMissionId + 7) {
                //Купить титанов
                let result = await buyTitanInTheStore(titanShopId, titanIds, titanFragments, titanSkilsIds, titanSkilFragments);
                //Выйти, если босс побежден и полностью собрали двух титанов.
                if (result && farmedChapters.includes(chapterId)) {
                    break;
                }
                //Текущая миссия босс или нет
                let boss = false;

                //Произвести атаку босса, если его ни разу не убили
                if (!farmedChapters.includes(chapterId)) {
                    if (missionId == firstMissionId + 7) {
                        boss = true;
                        console.log('%cАтакуем босса ', 'color: green; font-weight: bold;');
                    }
                } else {
                    //Не атаковать босса, если его уже убили
                    if (missionId == firstMissionId + 7) {
                        break;
                    }
                }
                //Получить атакующую команду
                let heroes = [];
                let titanSkil = [];
                await getAttackingTeam(heroes, titanSkil);
                let firstSpiritSkills = {};

                //Проходим миссию
                setProgress(I18N('NEWTITAN_MISSION_PROGRESS', {missionNumber: 1 + missionId - firstMissionId}), false);
                await attackTitanMission(missionId, chapterId, heroes, firstSpiritSkills, boss);

                //Результат атаки
                let invasionInfo = await Caller.send('invasion_getInfo');
                farmedChapters = invasionInfo.farmedChapters;
                let missions = Object.values(invasionInfo.actions);
                for (let mission of missions) {
                    if (mission.payload.wins == 0) {
                        missionId = mission.payload.id;
                        break;
                    }
                }
                lives = invasionInfo.lives;
                console.log('missionId ' + missionId);
                console.log('lives ' + lives);
            }
        }
    }
    async function newTitanGetInvasionFragmentSkill() {
        //Получить состояние на карте
        let invasionInfo = await Caller.send('invasion_getInfo');
        let invasionInfoId = invasionInfo.id;
        let farmedChapters = invasionInfo.farmedChapters;
        console.log('invasionInfoId ' + invasionInfoId);
        console.log('farmedChapters ', JSON.stringify(farmedChapters));

        //Получить id первой главый
        let chapters = Object.values(lib.data.invasion.chapter).filter((e) => e.invasionId === invasionInfoId);
        let chapterId = getChapterId(chapters, 'titan');
        console.log('chapterId ' + chapterId);

        //Получить id магазина
        let titanShopId = getShopId(chapters, 'titan'); //1073; // Магазин титанов
        console.log('Id магазина титанов ' + titanShopId);

        let cycle = true;
        while (cycle) {
            //Получить навыки тотемов, которые нужно собрать
            let titanSkilsIds = await getTitanSkillIdsToBuy();
            if (titanSkilsIds.length == 0) {
                setProgress('', true);
                confShow(I18N('NEWTITAN_GETINFLUENCESKILLCOLLECTED'));
                cycle = false;
                return;
            }
            console.log(titanSkilsIds);
            setProgress(I18N('NEWTITAN_GETINFLUENCESKILLPROGRESS', { counter: titanSkilsIds.length }), false);

            //Фрагменты навыков тотемов
            let titanSkilFragments = [0, 0];
            if (titanSkilsIds.length == 1) {
                titanSkilFragments = [0];
            }

            //Активировать главу
            let chapterInfo = await Caller.send({ name: 'invasion_setActiveChapter', args: { chapterId: chapterId } });
            let haveTitanFragments = chapterInfo.invasion.fragments;

            //Id миссии
            let firstMissionId = chapterInfo.invasion.actions[0].payload.id;
            let missionId = firstMissionId;

            //Жизни
            let lives = chapterInfo.invasion.lives;
            console.log('firstMissionId ' + firstMissionId);
            console.log('missionId ' + missionId);
            console.log('lives ' + lives);

            //Id титанов, что необходимо купить
            //Ияри и Солярис
            let titanIds = [4042, 4043];

            //Фрагменты титанов
            let titanFragments = [0, 0];
            if (haveTitanFragments[titanIds[0]]) {
                titanFragments[0] = haveTitanFragments[titanIds[0]];
            }
            if (haveTitanFragments[titanIds[1]]) {
                titanFragments[1] = haveTitanFragments[titanIds[1]];
            }

            console.log('titanShopId ' + titanShopId);
            console.log(titanIds);
            console.log(titanFragments);

            while (lives > 0 && missionId <= firstMissionId + 7) {
                //Купить титанов и навыки тотемов
                let result = await buyTotemSkilsInTheStore(titanShopId, titanIds, titanFragments, titanSkilsIds, titanSkilFragments);
                //Выйти, если босс побежден и полностью собрали два навыка тотема
                if (result && farmedChapters.includes(chapterId)) {
                    break;
                }

                //Произвести атаку босса, если его ни разу не убили
                if (!farmedChapters.includes(chapterId)) {
                    if (missionId == firstMissionId + 7) {
                        console.log('%cАтакуем босса ', 'color: green; font-weight: bold;');
                    }
                } else {
                    //Не атаковать босса, если его уже убили
                    if (missionId == firstMissionId + 7) {
                        break;
                    }
                }

                //Получить атакующую команду
                let heroes = [];
                let titanSkil = [];
                await getAttackingTeam(heroes, titanSkil);
                console.log(heroes);

                let firstSpiritSkills = {};

                //Проходим миссию
                setProgress(I18N('NEWTITAN_MISSION_PROGRESS', {missionNumber: 1 + missionId - firstMissionId}), false);
                await attackTitanMission(missionId, chapterId, heroes, firstSpiritSkills);

                //Результат атаки
                let invasionInfo = await Caller.send('invasion_getInfo');
                farmedChapters = invasionInfo.farmedChapters;
                let missions = Object.values(invasionInfo.actions);
                for (let mission of missions) {
                    if (mission.payload.wins == 0) {
                        missionId = mission.payload.id;
                        break;
                    }
                }
                lives = invasionInfo.lives;
                console.log('missionId ' + missionId);
                console.log('lives ' + lives);
            }
        }
    }

    async function newTitanGetHeroes() {
        //Получить состояние на карте
        let invasionInfo = await Caller.send('invasion_getInfo');

        let invasionInfoId = invasionInfo.id;
        let farmedChapters = invasionInfo.farmedChapters;
        console.log('invasionInfoId ' + invasionInfoId);
        console.log('farmedChapters ', JSON.stringify(farmedChapters));

        //Получить id главый
        let chapters = Object.values(lib.data.invasion.chapter).filter((e) => e.invasionId === invasionInfoId);
        let chapterId = getChapterId(chapters, 'hero');
        console.log('chapterId ' + chapterId);

        //Получить id магазина
        let heroShopId = getShopId(chapters, 'hero'); //1074; // Магазин героев
        console.log('Id магазина героев ' + heroShopId);

        //Счетчик купленных питомцев
        let petCounter = [0];

        let cycle = true;
        while (cycle) {
            //Получить героев, которых нужно собрать
            let heroIdsToBuy = await getHeroIdsToBuy();
            if (heroIdsToBuy.length == 0) {
                setProgress('', true);
                confShow(I18N('NEWTITAN_GETHEROCOLLECTED'));
                cycle = false;
                return;
            }
            console.log(heroIdsToBuy);
            setProgress(I18N('NEWTITAN_GETHEROCOLLECTEDPROGRESS', { counter: heroIdsToBuy.length }), false);

            //Активировать главу
            let chapterInfo = await Caller.send({ name: 'invasion_setActiveChapter', args: { chapterId: chapterId } });
            let haveHeroFragments = chapterInfo.invasion.fragments;

            //Id миссии
            let firstMissionId = chapterInfo.invasion.actions[0].payload.id;
            let missionId = firstMissionId;

            //Жизни
            let lives = chapterInfo.invasion.lives;
            console.log('firstMissionId ' + firstMissionId);
            console.log('missionId ' + missionId);
            console.log('lives ' + lives);

            //Id героев, что необходимо купить
            let heroIds = [0, 0, 0];

            if (heroIdsToBuy.length >= 3) {
                heroIds = [heroIdsToBuy[0], heroIdsToBuy[1], heroIdsToBuy[2]];
            }
            //Резервные герои, для добавления в покупки: Галахад, Тристан, Лирия
            let reserveHeroes = [2, 54, 67];
            if (heroIdsToBuy.length == 2) {
                heroIds[0] = heroIdsToBuy[0];
                heroIds[1] = heroIdsToBuy[1];
                for (let r of reserveHeroes) {
                    if (r != heroIds[0] && r != heroIds[1]) {
                        heroIds[2] = r;
                        break;
                    }
                }
            }

            if (heroIdsToBuy.length == 1) {
                if (farmedChapters.includes(heroIds[0])) {
                    heroIds = reserveHeroes;
                } else {
                    heroIds[0] = heroIdsToBuy[0];
                    heroIds[1] = reserveHeroes[0];
                    heroIds[2] = reserveHeroes[1];
                }
            }

            //Фрагменты героев
            let heroFragments = [0, 0, 0];
            if (haveHeroFragments[heroIds[0]]) {
                heroFragments[0] = haveHeroFragments[heroIds[0]];
            }
            if (haveHeroFragments[heroIds[1]]) {
                heroFragments[1] = haveHeroFragments[heroIds[1]];
            }
            if (haveHeroFragments[heroIds[2]]) {
                heroFragments[2] = haveHeroFragments[heroIds[2]];
            }
            console.log(heroIds);
            console.log(heroFragments);

            while (lives > 0 && missionId <= firstMissionId + 7) {
                //Купить героев и питомцев
                let result = await buyHeroInTheStore(heroShopId, heroIds, heroFragments, petCounter);

                //Выйти, если босс побежден и полностью собрали три героя
                if (result && farmedChapters.includes(chapterId)) {
                    break;
                }

                //Текущая миссия босс или нет
                let boss = false;

                //Произвести атаку босса, если его ни разу не убили
                if (!farmedChapters.includes(chapterId)) {
                    if (missionId == firstMissionId + 7) {
                        boss = true;
                        console.log('%cАтакуем босса ', 'color: green; font-weight: bold;');
                    }
                } else {
                    //Не атаковать босса, если его уже убили
                    if (missionId == firstMissionId + 7) {
                        break;
                    }
                }
                //Получить атакующую команду
                let heroes = [];
                let havePets = [];
                let pet;
                await getAttackingTeam(heroes, havePets);
                console.log('heroes ', JSON.stringify(heroes));
                if (havePets.length > 0) {
                    //Основной питомец 6005 - Альбрус
                    let mainPet = 6005;
                    if (havePets.includes(mainPet)) {
                        pet = mainPet;
                    } else {
                        pet = havePets[0];
                    }
                }
                console.log('Атакующие герои ' + heroes);

                //Проходим миссию
                setProgress(I18N('NEWTITAN_MISSION_PROGRESS', {missionNumber: 1 + missionId - firstMissionId}), false);
                await attackHeroMission(missionId, chapterId, heroes, pet, boss);

                //Результат атаки
                let invasionInfo = await Caller.send('invasion_getInfo');
                farmedChapters = invasionInfo.farmedChapters;
                let missions = Object.values(invasionInfo.actions);
                for (let mission of missions) {
                    if (mission.payload.wins == 0) {
                        missionId = mission.payload.id;
                        break;
                    }
                }
                lives = invasionInfo.lives;
                console.log('missionId ' + missionId);
                console.log('lives ' + lives);
            }
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    async function getHeroIdsToBuy() {
        const quest = await Caller.send('questGetAll');
        const heroIds = quest
            .filter((e) => e.state == 1 && lib.data.quest.special[e.id]?.translationMethod === 'invasionStallHeroFragments')
            .map((e) => lib.data.quest.special[e.id].farmCondition.eventFunc.args.fragmentId);
        return heroIds;
    }

    async function getTitanIdsToBuy() {
        const quest = await Caller.send('questGetAll');
        const titanIds = quest
            .filter((e) => e.state == 1 && lib.data.quest.special[e.id]?.translationMethod === 'invasionStallFragmentsTitans')
            .map((e) => lib.data.quest.special[e.id].farmCondition.eventFunc.args.fragmentId);
        return titanIds;
    }

    async function getTitanSkillIdsToBuy() {
        const quest = await Caller.send('questGetAll');
        const titanSkillIds = quest
            .filter((e) => e.state == 1 && lib.data.quest.special[e.id]?.translationMethod === 'invasionStallFragmentsTitanSkills')
            .map((e) => lib.data.quest.special[e.id].farmCondition.eventFunc.args.fragmentId);
        return titanSkillIds;
    }

    function getShopId(chapters, titanOrHero) {
        for (let chapter of chapters) {
            if (chapter.settings.unitType === titanOrHero) {
                return chapter.settings.stallShopId;
            }
        }
        return false;
    }
    function getChapterId(chapters, titanOrHero) {
        for (let chapter of chapters) {
            if (chapter.settings.unitType === titanOrHero) {
                return chapter.id;
            }
        }
        return false;
    }

    async function getAttackingTeam (heroes, other = []) {
        let haveFragments = Object.entries(await Caller.send('invasion_getInfo').then((e) => e.fragments)).map(e => ({id:e[0],count:e[1]})).sort((a, b) => b.count - a.count);
        console.log(haveFragments);
        for (let m of haveFragments) {
            //Отделяем питомцев и фрагменты тотемов
            if (Number(m.id) < 4400 && heroes.length < 5) {
                heroes.push(Number(m.id));
            }
            if (Number(m.id) > 4400) {
                other.push(Number(m.id));
            }
        }
    }

    async function getTeamButton (titanAttackingTeams, chapterNumber, titanOrHero) {
        let message = '';
        if (titanOrHero === 'titan' ) {
            message = I18N('NEWTITAN_ENTERTITANIDS', {chapterNumber:chapterNumber});
        }
        if (titanOrHero === 'hero' ) {
            message = I18N('NEWTITAN_ENTERHEROIDS', {chapterNumber:chapterNumber});
        }
        const answer = await popup.confirm(message, [
            {
                msg: I18N('NEWTITAN_COMPLETECHAPTER'),
                placeholder: '1,2,3,4,5,6',
                isInput: true,
                default: titanAttackingTeams,
                color: 'green',
            },
            {
                msg: I18N('BTN_CANCEL'),
                result: false,
                isCancel: true,
                color: 'red',
            },
        ]);
        if (!answer) {
            return false;
        }

        let team = answer.split(',');
        if (team.length != 5) {
            team = answer.split('-');
        }

        if (team.length != 5) {
            if (titanOrHero === 'hero' ) {
                confShow(I18N('NEWTITAN_MUSTFIVEHEROES'));
            }
            if (titanOrHero === 'titan' ) {
                confShow(I18N('NEWTITAN_MUSTFIVETITANS'));
            }
            return false;
        }

        for (let p in team) {
            team[p] = +team[p].trim()
            if (Number.isNaN(team[p])) {
                confShow(I18N('NEWTITAN_MUST_ONLY_NUMBERS'));
                return false;
            }
        }
        return team;
    }

    async function buyTitanInTheStore(titanShopId, titanIds, titanFragments, titanSkilsIds, titanSkilFragments) {
        console.log('Зашли в магазин');
        console.log('titanIds ', JSON.stringify(titanIds));
        console.log('titanFragments ', JSON.stringify(titanFragments));
        console.log('titanSkilsIds ', JSON.stringify(titanSkilsIds));
        console.log('titanSkilFragments ', JSON.stringify(titanSkilFragments));

        let coins = await Caller.send('inventoryGet').then((e) => e.coin[1080]);
        console.log('Монеты: ' + coins);

        let shopSlots = null;

        while (coins >= 9) {
            //Получить состояние магазина
            if (!shopSlots) {
                shopSlots = await Caller.send([{ name: 'shopGet', args: { shopId: titanShopId } }]).then((e) => Object.values(e.slots));
            }
            for (let slot of shopSlots) {
                //Пропустить скрытые лоты
                if (slot.reward.invasionFragmentTitanRand || slot.reward.invasionFragmentSkillRand) {
                    continue;
                }
                //Купить первого титана
                if (slot.reward.invasionFragmentTitan?.[titanIds[0]] && titanFragments[0] < 7) {
                    if (coins >= slot.cost.coin[1080]) {
                        let shopBuy = await Caller.send({ name: 'shopBuy', args: { cost: {}, reward: {}, shopId: titanShopId, slot: slot.id } });
                        if (shopBuy.error) {
                            await Caller.send({ name: 'shop_pinSlot', args: { shopId: titanShopId, slotId: slot.id } });
                            coins = 0;
                            continue;
                        }
                        console.log('%cКуплен титан ', 'color: green; font-weight: bold;');
                        coins -= slot.cost.coin[1080];
                        titanFragments[0] += slot.reward.invasionFragmentTitan?.[titanIds[0]];

                        //Если c первым титаном есть второй
                        if (slot.reward.invasionFragmentTitan?.[titanIds[1]]) {
                            console.log('%cВторой титан в комплекте ', 'color: green; font-weight: bold;');
                            titanFragments[1] += slot.reward.invasionFragmentTitan?.[titanIds[1]];
                        }
                    } else {
                        await Caller.send({ name: 'shop_pinSlot', args: { shopId: titanShopId, slotId: slot.id } });
                    }
                    continue;
                }

                //Купить второго титана
                if (slot.reward.invasionFragmentTitan?.[titanIds[1]] && titanFragments[1] < 7) {
                    if (coins >= slot.cost.coin[1080]) {
                        let shopBuy = await Caller.send({ name: 'shopBuy', args: { cost: {}, reward: {}, shopId: titanShopId, slot: slot.id } });
                        if (shopBuy.error) {
                            await Caller.send({ name: 'shop_pinSlot', args: { shopId: titanShopId, slotId: slot.id } });
                            coins = 0;
                            continue;
                        }
                        console.log('%cКуплен титан ', 'color: green; font-weight: bold;');
                        coins -= slot.cost.coin[1080];
                        titanFragments[1] += slot.reward.invasionFragmentTitan?.[titanIds[1]];
                    } else {
                        await Caller.send({ name: 'shop_pinSlot', args: { shopId: titanShopId, slotId: slot.id } });
                    }
                    continue;
                }

                //Купить первый навык тотема
                if (slot.reward.invasionFragmentSkill?.[titanSkilsIds[0]] && titanSkilFragments[0] < 7) {
                    if (coins >= slot.cost.coin[1080]) {
                        let shopBuy = await Caller.send({ name: 'shopBuy', args: { cost: {}, reward: {}, shopId: titanShopId, slot: slot.id } });
                        if (shopBuy.error) {
                            await Caller.send({ name: 'shop_pinSlot', args: { shopId: titanShopId, slotId: slot.id } });
                            coins = 0;
                            continue;
                        }
                        console.log('%cКуплена часть навыка тотема ', 'color: green; font-weight: bold;');
                        coins -= slot.cost.coin[1080];
                        titanSkilFragments[0] += slot.reward.invasionFragmentSkill?.[titanSkilsIds[0]];
                    } else {
                        await Caller.send({ name: 'shop_pinSlot', args: { shopId: titanShopId, slotId: slot.id } });
                    }
                    continue;
                }

                //Купить второй навык тотема
                if (titanSkilsIds.length >= 2 && slot.reward.invasionFragmentSkill?.[titanSkilsIds[1]] && titanSkilFragments[1] < 7) {
                    if (coins >= slot.cost.coin[1080]) {
                        let shopBuy = await Caller.send({ name: 'shopBuy', args: { cost: {}, reward: {}, shopId: titanShopId, slot: slot.id } });
                        if (shopBuy.error) {
                            await Caller.send({ name: 'shop_pinSlot', args: { shopId: titanShopId, slotId: slot.id } });
                            coins = 0;
                            continue;
                        }
                        console.log('%cКуплена часть навыка тотема ', 'color: green; font-weight: bold;');
                        coins -= slot.cost.coin[1080];
                        titanSkilFragments[1] += slot.reward.invasionFragmentSkill?.[titanSkilsIds[1]];
                    } else {
                        await Caller.send({ name: 'shop_pinSlot', args: { shopId: titanShopId, slotId: slot.id } });
                    }
                    continue;
                }
                //Если ТИТАНЫ собраны
                if (titanFragments[0] >= 7 && titanFragments[1] >= 7) {
                    //Обновляем навыки
                    if (titanSkilsIds.length >= 2 && titanSkilFragments[0] >= 7 && titanSkilFragments[1] >= 7) {
                        console.log('%cМеняем навыки навыки тотемов', 'color: green; font-weight: bold;');
                        titanSkilsIds = await getTitanSkillIdsToBuy();
                        titanSkilFragments = [0, 0];
                        if (titanSkilsIds.length == 1) {
                            titanSkilFragments = [0];
                        }
                    }
                    if ((titanSkilsIds.length == 1 && titanSkilFragments[0] >= 7) || titanSkilsIds.length == 0) {
                        console.log('%cВсе навыки тотемов куплены, переходим к покупке следующих титанов', 'color: green; font-weight: bold;');
                        return true;
                    }
                }
            }
            //Обновить магазин
            if (coins >= 12) {
                shopSlots = await Caller.send([{ name: 'shopRefresh', args: { shopId: titanShopId } }]).then((e) => Object.values(e.slots));
                coins -= 3;
                console.log('Обновили магазин. Осталось монет: ' + coins);
                if (shopSlots.error) {
                    coins = 0;
                }
            } else {
                break;
            }
        }
        return false;
    }

    async function buyTotemSkilsInTheStore(titanShopId, titanIds, titanFragments, titanSkilsIds, titanSkilFragments) {
        console.log('Зашли в магазин');
        console.log('titanIds ', JSON.stringify(titanIds));
        console.log('titanFragments ', JSON.stringify(titanFragments));
        console.log('titanSkilsIds ', JSON.stringify(titanSkilsIds));
        console.log('titanSkilFragments ', JSON.stringify(titanSkilFragments));

        let coins = await Caller.send('inventoryGet').then((e) => e.coin[1080]);
        console.log('Монеты: ' + coins);

        let shopSlots = null;
        while (coins >= 9) {
            //Получить состояние магазина
            if (!shopSlots) {
                shopSlots = await Caller.send([{ name: 'shopGet', args: { shopId: titanShopId } }]).then((e) => Object.values(e.slots));
            }
            for (let slot of shopSlots) {
                //Пропустить скрытые лоты
                if (slot.reward.invasionFragmentTitanRand || slot.reward.invasionFragmentSkillRand) {
                    continue;
                }
                //Купить первый навык тотема
                if (slot.reward.invasionFragmentSkill?.[titanSkilsIds[0]] && titanSkilFragments[0] < 7) {
                    if (coins >= slot.cost.coin[1080]) {
                        let shopBuy = await Caller.send({ name: 'shopBuy', args: { cost: {}, reward: {}, shopId: titanShopId, slot: slot.id } });
                        if (shopBuy.error) {
                            await Caller.send({ name: 'shop_pinSlot', args: { shopId: titanShopId, slotId: slot.id } });
                            coins = 0;
                            continue;
                        }
                        console.log('%cКуплена часть навыка тотема ', 'color: green; font-weight: bold;');
                        coins -= slot.cost.coin[1080];
                        titanSkilFragments[0] += slot.reward.invasionFragmentSkill?.[titanSkilsIds[0]];
                    } else {
                        await Caller.send({ name: 'shop_pinSlot', args: { shopId: titanShopId, slotId: slot.id } });
                    }
                    continue;
                }

                //Купить второй навык тотема
                if (titanSkilsIds.length >= 2 && slot.reward.invasionFragmentSkill?.[titanSkilsIds[1]] && titanSkilFragments[1] < 7) {
                    if (coins >= slot.cost.coin[1080]) {
                        let shopBuy = await Caller.send({ name: 'shopBuy', args: { cost: {}, reward: {}, shopId: titanShopId, slot: slot.id } });
                        if (shopBuy.error) {
                            await Caller.send({ name: 'shop_pinSlot', args: { shopId: titanShopId, slotId: slot.id } });
                            coins = 0;
                            continue;
                        }
                        console.log('%cКуплена часть навыка тотема ', 'color: green; font-weight: bold;');
                        coins -= slot.cost.coin[1080];
                        titanSkilFragments[1] += slot.reward.invasionFragmentSkill?.[titanSkilsIds[1]];
                    } else {
                        await Caller.send({ name: 'shop_pinSlot', args: { shopId: titanShopId, slotId: slot.id } });
                    }
                    continue;
                }
                //Если навыки собраны, обновляем навыки
                if (titanSkilsIds.length >= 2 && titanSkilFragments[0] >= 7 && titanSkilFragments[1] >= 7) {
                    titanSkilsIds = await getTitanSkillIdsToBuy();
                    titanSkilFragments = [0, 0];
                    if (titanSkilsIds.length == 1) {
                        titanSkilFragments = [0];
                    }
                }

                if ((titanSkilsIds.length == 1 && titanSkilFragments[0] >= 7) || titanSkilsIds.length == 0) {
                    //Тратим оставшиеся монеты (пусть будет, вдруг пригодиццо)
                    /*if (coins >= slot.cost.coin[1080]){
                        let shopBuy = await Caller.send({name: 'shopBuy', args: {cost: {}, reward: {}, shopId: titanShopId, slot: slot.id}});
                        coins -= slot.cost.coin[1080];
                        if(shopBuy.error){
                            coins = 0;
                            continue;
                        }
                    }*/
                    //Купили все навыки, идем на выход
                    return true;
                }

                //Купить первого титана
                if (slot.reward.invasionFragmentTitan?.[titanIds[0]] && titanFragments[0] < 7) {
                    if (coins >= slot.cost.coin[1080]) {
                        let shopBuy = await Caller.send({ name: 'shopBuy', args: { cost: {}, reward: {}, shopId: titanShopId, slot: slot.id } });
                        if (shopBuy.error) {
                            await Caller.send({ name: 'shop_pinSlot', args: { shopId: titanShopId, slotId: slot.id } });
                            coins = 0;
                            continue;
                        }
                        console.log('%cКуплен титан ', 'color: green; font-weight: bold;');
                        coins -= slot.cost.coin[1080];
                        titanFragments[0] += slot.reward.invasionFragmentTitan?.[titanIds[0]];

                        //Если c первым титаном есть второй
                        if (slot.reward.invasionFragmentTitan?.[titanIds[1]]) {
                            console.log('%cВторой титан в комплекте ', 'color: green; font-weight: bold;');
                            titanFragments[1] += slot.reward.invasionFragmentTitan?.[titanIds[1]];
                        }
                    } else {
                        await Caller.send({ name: 'shop_pinSlot', args: { shopId: titanShopId, slotId: slot.id } });
                    }
                    continue;
                }

                //Купить второго титана
                if (slot.reward.invasionFragmentTitan?.[titanIds[1]] && titanFragments[1] < 7) {
                    if (coins >= slot.cost.coin[1080]) {
                        let shopBuy = await Caller.send({ name: 'shopBuy', args: { cost: {}, reward: {}, shopId: titanShopId, slot: slot.id } });
                        if (shopBuy.error) {
                            await Caller.send({ name: 'shop_pinSlot', args: { shopId: titanShopId, slotId: slot.id } });
                            coins = 0;
                            continue;
                        }
                        console.log('%cКуплен титан ', 'color: green; font-weight: bold;');
                        coins -= slot.cost.coin[1080];
                        titanFragments[1] += slot.reward.invasionFragmentTitan?.[titanIds[1]];
                    } else {
                        await Caller.send({ name: 'shop_pinSlot', args: { shopId: titanShopId, slotId: slot.id } });
                    }
                    continue;
                }
            }
            //Обновить магазин
            if (coins >= 12) {
                shopSlots = await Caller.send({ name: 'shopRefresh', args: { shopId: titanShopId } }).then((e) => Object.values(e.slots));
                coins -= 3;
                console.log('Обновили магазин. Осталось монет ' + coins);
                if (shopSlots.error) {
                    coins = 0;
                }
            } else {
                break;
            }
        }
        return false;
    }

    async function buyHeroInTheStore(heroShopId, heroIds, heroFragments, petCounter) {
        console.log('Зашли в магазин');
        console.log('heroShopId ' + heroShopId);
        console.log('petCounter ' + petCounter[0]);
        console.log('heroIds ', JSON.stringify(heroIds));
        console.log('heroFragments ', JSON.stringify(heroFragments));

        let coins = await Caller.send('inventoryGet').then((e) => e.coin[1080]);
        console.log('Монеты: ' + coins);

        let shopSlots = null;

        while (coins >= 9) {
            //Получить состояние магазина
            if (!shopSlots) {
                shopSlots = await Caller.send([{ name: 'shopGet', args: { shopId: heroShopId } }]).then((e) => Object.values(e.slots));
            }
            for (let slot of shopSlots) {
                //Пропустить скрытые лоты
                if (slot.reward.invasionFragmentHeroRand) {
                    continue;
                }
                //console.log(slot);
                //Купить первого героя
                if (slot.reward.invasionFragmentHero?.[heroIds[0]] && heroFragments[0] < 7) {
                    if (coins >= slot.cost.coin[1080]) {
                        let shopBuy = await Caller.send({ name: 'shopBuy', args: { cost: {}, reward: {}, shopId: heroShopId, slot: slot.id } });
                        if (shopBuy.error) {
                            await Caller.send({ name: 'shop_pinSlot', args: { shopId: heroShopId, slotId: slot.id } });
                            coins = 0;
                            continue;
                        }
                        console.log('%cКуплен герой ', 'color: green; font-weight: bold;');
                        coins -= slot.cost.coin[1080];
                        heroFragments[0] += slot.reward.invasionFragmentHero?.[heroIds[0]];

                        //Если c первым титаном есть второй
                        if (slot.reward.invasionFragmentHero?.[heroIds[1]]) {
                            console.log('%cВторой герой в комплекте ', 'color: green; font-weight: bold;');
                            heroFragments[1] += slot.reward.invasionFragmentHero?.[heroIds[1]];
                        }
                        //Если c первым титаном есть третий
                        if (slot.reward.invasionFragmentHero?.[heroIds[2]]) {
                            console.log('%cТретий герой в комплекте ', 'color: green; font-weight: bold;');
                            heroFragments[2] += slot.reward.invasionFragmentHero?.[heroIds[2]];
                        }
                    } else {
                        await Caller.send({ name: 'shop_pinSlot', args: { shopId: heroShopId, slotId: slot.id } });
                    }
                    continue;
                }

                //Купить второго героя
                if (slot.reward.invasionFragmentHero?.[heroIds[1]] && heroFragments[1] < 7) {
                    if (coins >= slot.cost.coin[1080]) {
                        let shopBuy = await Caller.send({ name: 'shopBuy', args: { cost: {}, reward: {}, shopId: heroShopId, slot: slot.id } });
                        if (shopBuy.error) {
                            await Caller.send({ name: 'shop_pinSlot', args: { shopId: heroShopId, slotId: slot.id } });
                            coins = 0;
                            continue;
                        }
                        console.log('%cКуплен герой ', 'color: green; font-weight: bold;');
                        coins -= slot.cost.coin[1080];
                        heroFragments[1] += slot.reward.invasionFragmentHero?.[heroIds[1]];
                        //Если cо вторым титаном есть третий
                        if (slot.reward.invasionFragmentHero?.[heroIds[2]]) {
                            console.log('%cТретий герой в комплекте ', 'color: green; font-weight: bold;');
                            heroFragments[2] += slot.reward.invasionFragmentHero?.[heroIds[2]];
                        }
                    } else {
                        await Caller.send({ name: 'shop_pinSlot', args: { shopId: heroShopId, slotId: slot.id } });
                    }
                    continue;
                }
                //Купить третьего героя
                if (slot.reward.invasionFragmentHero?.[heroIds[2]] && heroFragments[2] < 7) {
                    if (coins >= slot.cost.coin[1080]) {
                        let shopBuy = await Caller.send({ name: 'shopBuy', args: { cost: {}, reward: {}, shopId: heroShopId, slot: slot.id } });
                        if (shopBuy.error) {
                            await Caller.send({ name: 'shop_pinSlot', args: { shopId: heroShopId, slotId: slot.id } });
                            coins = 0;
                            continue;
                        }
                        console.log('%cКуплен герой ', 'color: green; font-weight: bold;');
                        coins -= slot.cost.coin[1080];
                        heroFragments[2] += slot.reward.invasionFragmentHero?.[heroIds[2]];
                    } else {
                        await Caller.send({ name: 'shop_pinSlot', args: { shopId: heroShopId, slotId: slot.id } });
                    }
                    continue;
                }
                //Потратить оставшиеся монеты, если герои уже куплены
                if (heroFragments[0] >= 7 && heroFragments[1] >= 7 && heroFragments[2] >= 7) {
                    console.log('Тратим монеты');
                    if (slot.reward.invasionFragmentPet && petCounter[0] < 10) {
                        if (coins >= slot.cost.coin[1080]) {
                            await Caller.send({ name: 'shopBuy', args: { cost: {}, reward: {}, shopId: heroShopId, slot: slot.id } });
                            coins -= slot.cost.coin[1080];
                            petCounter[0]++;
                            console.log('%cКуплен питомец ', 'color: green; font-weight: bold;');
                        } else {
                            await Caller.send({ name: 'shop_pinSlot', args: { shopId: heroShopId, slotId: slot.id } });
                        }
                    }
                    if (petCounter[0] >= 10) {
                        console.log('%cВсе питомцы куплены, переходим к покупке следующих героев', 'color: green; font-weight: bold;');
                        return true;
                    }
                }
            }
            //Обновить магазин
            if (coins >= 15) {
                shopSlots = await Caller.send({ name: 'shopRefresh', args: { shopId: heroShopId } }).then((e) => Object.values(e.slots));
                coins -= 3;
                console.log('Обновили магазин. Осталось монет ' + coins);
                if (shopSlots.error) {
                    coins = 0;
                }
            } else {
                break;
            }
        }
        return false;
    }

    async function buyTitansAndTotemSkils (shopId, titanIds, titanFragments, titanSkilsIds, titanSkilFragments) {
        console.log('Зашли в магазин');
        console.log('titanIds ', JSON.stringify(titanIds));
        console.log('titanFragments ', JSON.stringify(titanFragments));
        console.log('titanSkilsIds ', JSON.stringify(titanSkilsIds));
        console.log('titanSkilFragments ', JSON.stringify(titanSkilFragments));

        let coins = await Caller.send('inventoryGet').then((e) => e.coin[1080]);
        console.log('Монеты: ' + coins);

        let shopSlots = null;

        while (coins >= 9) {
            //Получить состояние магазина
            if (!shopSlots) {
                shopSlots = await Caller.send([{ name: 'shopGet', args: { shopId: shopId } }]).then((e) => Object.values(e.slots));
            }
            for (let slot of shopSlots) {
                //Пропустить скрытые лоты
                if (slot.reward.invasionFragmentTitanRand || slot.reward.invasionFragmentSkillRand) {
                    continue;
                }
                let boughtTitan = false;
                //Купить титанов
                for (let t = 0; t < titanIds.length; t++) {
                    if (slot.reward.invasionFragmentTitan?.[titanIds[t]] && titanFragments[t] < 7) {
                        if (coins >= slot.cost.coin[1080]) {
                            let shopBuy = await Caller.send({ name: 'shopBuy', args: { cost: {}, reward: {}, shopId: shopId, slot: slot.id } });
                            console.log('%cКуплен титан ', 'color: green; font-weight: bold;');
                            coins -= slot.cost.coin[1080];
                            titanFragments[t] += slot.reward.invasionFragmentTitan?.[titanIds[t]];

                            //Если c первым титаном есть другой
                            for (let i = t+1; i < titanIds.length; i++) {
                                if (slot.reward.invasionFragmentTitan?.[titanIds[i]]) {
                                    console.log('%cВторой титан в комплекте ', 'color: green; font-weight: bold;');
                                    titanFragments[i] += slot.reward.invasionFragmentTitan?.[titanIds[i]];
                                    break;
                                }
                            }
                        } else {
                            await Caller.send({ name: 'shop_pinSlot', args: { shopId: shopId, slotId: slot.id } });
                        }
                        boughtTitan = true;
                        break;
                    }
                }

                //Купить навыки тотема
                if (!boughtTitan) {
                    for (let s = 0; s < titanSkilsIds.length; s++) {
                        if (slot.reward.invasionFragmentSkill?.[titanSkilsIds[s]] && titanSkilFragments[s] < 7) {
                            if (coins >= slot.cost.coin[1080]) {
                                let shopBuy = await Caller.send({ name: 'shopBuy', args: { cost: {}, reward: {}, shopId: shopId, slot: slot.id } });
                                console.log('%cКуплена часть навыка тотема ', 'color: green; font-weight: bold;');
                                coins -= slot.cost.coin[1080];
                                titanSkilFragments[s] += slot.reward.invasionFragmentSkill?.[titanSkilsIds[s]];
                            } else {
                                await Caller.send({ name: 'shop_pinSlot', args: { shopId: shopId, slotId: slot.id } });
                            }
                            break;
                        }
                    }
                }

                //Если ТИТАНЫ и тотемы собраны
                let titanF = false;
                let titanS = false;
                for (let tf of titanFragments) {
                    if (tf < 7) {
                        titanF = false;
                        break;
                    }
                    titanF = true;
                }
                for (let ts of titanSkilFragments) {
                    if (ts < 7) {
                        titanS = false;
                        break;
                    }
                    titanS = true;
                }
                if ( titanF && titanS) {
                    return;
                }
            }
            //Обновить магазин
            if (coins >= 12) {
                shopSlots = await Caller.send([{ name: 'shopRefresh', args: { shopId: shopId } }]).then((e) => Object.values(e.slots));
                coins -= 3;
                console.log('Обновили магазин. Осталось монет: ' + coins);
                if (shopSlots.error) {
                    coins = 0;
                }
            } else {
                break;
                return;
            }
        }
    }

    async function buyHeroesAndPets (shopId, heroIds, heroFragments, pets) {
        console.log('Зашли в магазин');
        console.log('heroIds ', JSON.stringify(heroIds));
        console.log('heroFragments ', JSON.stringify(heroFragments));
        console.log('pets ', JSON.stringify(pets));


        let coins = await Caller.send('inventoryGet').then((e) => e.coin[1080]);
        console.log('Монеты: ' + coins);

        let shopSlots = null;

        while (coins >= 9) {
            //Получить состояние магазина
            if (!shopSlots) {
                shopSlots = await Caller.send([{ name: 'shopGet', args: { shopId: shopId } }]).then((e) => Object.values(e.slots));
            }
            for (let slot of shopSlots) {
                //Пропустить скрытые лоты
                if (slot.reward.invasionFragmentHeroRand) {
                    continue;
                }
                let boughtHero = false;
                //Купить героев
                for (let t = 0; t < heroIds.length; t++) {
                    if (slot.reward.invasionFragmentHero?.[heroIds[t]] && heroFragments[t] < 7) {
                        if (coins >= slot.cost.coin[1080]) {
                            let shopBuy = await Caller.send({ name: 'shopBuy', args: { cost: {}, reward: {}, shopId: shopId, slot: slot.id } });
                            console.log('%cКуплен герой ', 'color: green; font-weight: bold;');
                            coins -= slot.cost.coin[1080];
                            heroFragments[t] += slot.reward.invasionFragmentHero?.[heroIds[t]];

                            //Если c первым героем есть другой
                            for (let i = t+1; i < heroIds.length; i++) {
                                if (slot.reward.invasionFragmentHero?.[heroIds[i]]) {
                                    console.log('%cВторой герой в комплекте ', 'color: green; font-weight: bold;');
                                    heroFragments[i] += slot.reward.invasionFragmentHero?.[heroIds[i]];
                                    break;
                                }
                            }
                        } else {
                            await Caller.send({ name: 'shop_pinSlot', args: { shopId: shopId, slotId: slot.id } });
                        }
                        boughtHero = true;
                        break;
                    }
                }

                //Купить питомцев
                if (!boughtHero) {
                    for (let s = 0; s < pets.length; s++) {
                        if (slot.reward.invasionFragmentPet?.[pets[s]] && pets.length > 0) {
                            if (coins >= slot.cost.coin[1080]) {
                                let shopBuy = await Caller.send({ name: 'shopBuy', args: { cost: {}, reward: {}, shopId: shopId, slot: slot.id } });
                                console.log('%cКуплен питомец ', 'color: green; font-weight: bold;');
                                coins -= slot.cost.coin[1080];
                                pets = pets.filter((e) => e !== pets[s])
                            } else {
                                await Caller.send({ name: 'shop_pinSlot', args: { shopId: shopId, slotId: slot.id } });
                            }
                            break;
                        }
                    }
                }

                //Если ГЕРОИ и питомцы собраны
                let heroF = false;
                for (let tf of heroFragments) {
                    if (tf < 7) {
                        heroF = false;
                        break;
                    }
                    heroF = true;
                }
                if ( heroF && pets.length == 0) {
                    return;
                }
            }
            //Обновить магазин
            if (coins >= 15) {
                shopSlots = await Caller.send([{ name: 'shopRefresh', args: { shopId: shopId } }]).then((e) => Object.values(e.slots));
                coins -= 3;
                console.log('Обновили магазин. Осталось монет: ' + coins);
                if (shopSlots.error) {
                    coins = 0;
                }
            } else {
                break;
                return;
            }
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    async function attackTitanMission(missionId, chapterId, heroes, firstSpiritSkills, boss = false) {
        console.log('heroes ', JSON.stringify(heroes));
        console.log('firstSpiritSkills ', JSON.stringify(firstSpiritSkills));
        const startBattle = await Caller.send({
            name: 'invasion_bossStart',
            args: {
                id: missionId,
                chapterId: chapterId,
                heroes: heroes,
                //firstSpiritElement: "earth",
                firstSpiritSkills: firstSpiritSkills,
                favor: {},
            },
        });
        const calcBattle = await Calc(startBattle);

        if (!calcBattle.result.win) {
            const cloneBattle = structuredClone(startBattle);
            const bFix = new WinFixBattle(cloneBattle);
            let result = await bFix.start(cloneBattle.endTime, Infinity);
            if (result.result?.win) {
                calcBattle.result = result.result;
                calcBattle.progress = result.progress;
                calcBattle.battleTimer = result.battleTimer;
            }
        }

        if (!calcBattle.result.win && boss == true) {
            //Босса не убили
            console.log('%cБосса не убили ', 'color: red; font-weight: bold;');
            return;
        }
        if (boss == true) {
            let timer = calcBattle.battleTimer * 1.2;
            console.log('%cУбили босса', 'color: green; font-weight: bold;');
            await countdownTimer(timer, `${I18N('NEWTITAN_BOSSWASKILLED')}`);
        }

        const endBattle = await Caller.send({
            name: 'invasion_bossEnd',
            args: {
                id: missionId,
                result: calcBattle.result,
                progress: calcBattle.progress,
            },
        });
    }

    async function attackHeroMission(missionId, chapterId, heroes, pet, boss = false) {
        const startBattle = await Caller.send({
            name: 'invasion_bossStart',
            args: {
                id: missionId,
                chapterId: chapterId,
                heroes: heroes,
                pet: pet,
                favor: {},
            },
        });
        const calcBattle = await Calc(startBattle);

        if (!calcBattle.result.win) {
            const cloneBattle = structuredClone(startBattle);
            const bFix = new WinFixBattle(cloneBattle);
            let result = await bFix.start(cloneBattle.endTime, Infinity);
            if (result.result?.win) {
                calcBattle.result = result.result;
                calcBattle.progress = result.progress;
                calcBattle.battleTimer = result.battleTimer;
            }
        }

        if (!calcBattle.result.win && boss == true) {
            //Босса не убили
            console.log('%cБосса не убили ', 'color: red; font-weight: bold;');
            return;
        }
        if (boss == true) {
            let timer = calcBattle.battleTimer * 1.2;
            console.log('%cУбили босса', 'color: green; font-weight: bold;');
            await countdownTimer(timer, `${I18N('NEWTITAN_BOSSWASKILLED')}`);
        }

        await Caller.send({
            name: 'invasion_bossEnd',
            args: {
                id: missionId,
                result: calcBattle.result,
                progress: calcBattle.progress,
            },
        });
    }
})();