HWHNewCharacterExt

Extension for HeroWarsHelper script

As of 26.10.2025. See апошняя версія.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name             HWHNewCharacterExt
// @name:en          HWHNewCharacterExt
// @name:ru          HWHNewCharacterExt
// @namespace        HWHNewCharacterExt
// @version          1.02
// @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 { buttons } = HWHData;
    const {
        popup,
        confShow,
        getInput,
        setProgress,
        hideProgress,
        I18N,
        send,
        getTimer,
        countdownTimer,
        getUserInfo,
        getSaveVal,
        setSaveVal,
        setIsCancalBattle,
        random,
        EventEmitterMixin,
    } = 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: 'Get the Titans',
        NEWTITAN_GETTITANS_TITLE: 'Get the Titans of the maximum rank by collecting fragments in the shop',
        NEWTITAN_GETHEROES: 'Get the Heroes',
        NEWTITAN_GETHEROES_TITLE: 'Get the Heroes of the maximum rank by collecting fragments in the shop',
        NEWTITAN_GETINFLUENCESKILL: 'Get influence skill',
        NEWTITAN_GETINFLUENCESKILL_TITLE: 'Get the influence skill of the maximum rank by collecting fragments in the shop',
        NEWTITAN_GETTITANSPROGRESS: '<span style="color: green;"> {counter} </span> titans left to collect. Collecting...',
        NEWTITAN_GETTITANSCOLLECTED: 'All titans have been collected',
    };

    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: 'Все титаны собраны',
    };

    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 () {
            let invasionInfo = await Caller.send('invasion_getInfo');
            let invasionInfoId = invasionInfo.id;

            if(invasionInfo){
                let chapters = Object.values(lib.data.invasion.chapter).filter(e => e.invasionId === invasionInfoId)
                let chapterId = chapters[0].id
                let titanShopId = await getShopId(chapters, "titan");
                console.log(titanShopId);
                if (titanShopId){
                    await onClickNewTitanButton();
                }else{
                    await onClickNewHeroButton();
                }
            }else{
                confShow(`${I18N('NEWCHARACTER_NOEVENT')}`);
            }

        },
    });

    async function onClickNewHeroButton() {
        const popupButtons = [
            {
                get msg() { return I18N('NEWHERO_COMPLETETASKS'); },
                get title() { return I18N('NEWHERO_COMPLETETASKS_TITLE'); },
                result:async function () {
                    confShow('Нажата кнопка');
                },
            },
            {
                get msg() { return I18N('NEWHERO_COMPLETECAPTERS'); },
                get title() { return I18N('NEWHERO_COMPLETECAPTERS_TITLE'); },
                result: () => {
                    confShow('Нажата кнопка 2');
                },
            },
        ];
        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 () {
                    //confShow('Нажата кнопка');
                    await newTitanGetTitans();
                },
            },
            {
                get msg() { return I18N('NEWTITAN_GETHEROES'); },
                get title() { return I18N('NEWTITAN_GETHEROES_TITLE'); },
                result: () => {
                    confShow('Нажата кнопка 2');
                },
            },
            {
                get msg() { return I18N('NEWTITAN_GETINFLUENCESKILL'); },
                get title() { return I18N('NEWTITAN_GETINFLUENCESKILL_TITLE'); },
                result: () => {
                    confShow('Нажата кнопка 3');
                },
            },
        ];
        popupButtons.push({ result: false, isClose: true });
        const answer = await popup.confirm(`${I18N('NEWTITAN')} ${I18N('NEWHERO_SELECTACTION')}`, popupButtons);
        if (typeof answer === 'function') {
            answer();
        }
    }


    async function newTitanGetTitans() {

        //Получить состояние на карте
        let invasionInfoId = await Caller.send('invasion_getInfo').then(e => e.id);
        console.log("invasionInfoId " + invasionInfoId);

        //Сброс главы
        await Caller.send('invasion_resetChapter')

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

        //Получить id магазина
        //let heroShopId = await getShopId(chapters, "hero"); //1074; // Магазин героев

        let titanShopId = await getShopId(chapters, "titan"); //1073; // Магазин титанов

        //console.log("Id магазина героев " + heroShopId);
        console.log("Id магазина титанов " + titanShopId);


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

            //Активировать главу
            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);

            //Массив фрагментов для метода покупки
            let fragments = [0, 0];
            //Id титанов, что необходимо купить
            let titanIdsToBuy = [0, 0];
            if (allTitanIdsToBuy.length >= 2){
                titanIdsToBuy = [allTitanIdsToBuy[0], allTitanIdsToBuy[1]];
            }else{
                titanIdsToBuy = [allTitanIdsToBuy[0], Object.keys(haveTitanFragments)[0]];
            }
            if (haveTitanFragments[titanIdsToBuy[0]]){
                fragments[0] = haveTitanFragments[titanIdsToBuy[0]];
            }
            if (haveTitanFragments[titanIdsToBuy[1]]){
                fragments[1] = haveTitanFragments[titanIdsToBuy[1]];
            }

            console.log("titanShopId "+ titanShopId);
            console.log(titanIdsToBuy);
            console.log(fragments);


            while( lives > 0 && missionId <= (firstMissionId+7)){
                //Купить титанов
                await buyTitanInTheStore(titanShopId, titanIdsToBuy, fragments);

                //Не атакуем босса
                if (missionId == (firstMissionId+7)){
                    break;
                }

                //Получить атакующую команду
                let heroes = [];
                haveTitanFragments = await Caller.send('invasion_getInfo').then(e => e.fragments);
                for (let f in haveTitanFragments){
                    heroes.push(Number(f));
                    if(heroes.length == 5){
                        break;
                    }
                }
                console.log(heroes)

                let firstSpiritSkills = {};

                //Проходим миссию
                try {
                    await attackTitanMission(missionId, chapterId, heroes, firstSpiritSkills);
                } catch (e) {
                    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;
                        }
                    }
                    await attackTitanMission(missionId, chapterId, heroes, firstSpiritSkills);
                }

                //Результат атаки
                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;
                    }
                }
                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;
    }

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

    async function buyTitanInTheStore(titanShopId, titanIdsToBuy, fragments) {
        console.log("Зашли в магазин");
        console.log(titanIdsToBuy);
        console.log(fragments);

        //Навыки тотемов
        let titanSkilsIdsToBuy = await getTitanSkillIdsToBuy();
        console.log(titanSkilsIdsToBuy);
        console.log(titanSkilsIdsToBuy.length);

        //Фрагменты навыка
        let titanSkilFragments = 0;

        let coins = await Caller.send('inventoryGet').then(e => e.coin[1080]);
        console.log("coins " + coins);

        while( coins >= 9){
            //Получить состояние магазина
            let result = await Caller.send([{name:'shopGet',args:{shopId: titanShopId}}]).then(e => e.slots);
            let slots = Object.values(result)
            console.log(slots);
            for (let slot of slots){
                //Пропустить скрытые лоты
                if (slot.reward.invasionFragmentTitanRand || slot.reward.invasionFragmentSkillRand){
                    continue;
                }
                //console.log(slot);
                //Купить первого титана
                if (slot.reward.invasionFragmentTitan?.[titanIdsToBuy[0]] && fragments[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];
                        fragments[0] += slot.reward.invasionFragmentTitan?.[titanIdsToBuy[0]];

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

                //Купить второго титана
                if (slot.reward.invasionFragmentTitan?.[titanIdsToBuy[1]] && fragments[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];
                        fragments[1] += slot.reward.invasionFragmentTitan?.[titanIdsToBuy[1]];
                    }
                    else{
                        await Caller.send({name: 'shop_pinSlot', args: {shopId: titanShopId, slotId: slot.id}});
                    }
                    continue;
                }
                //Потратить оставшиеся монеты, если титаны уже куплены
                if (fragments[0] >= 7 && fragments[1] >= 7){
                    console.log("Тратим монеты");
                    //Покупаем часть тотема
                    if (titanSkilsIdsToBuy.length >= 1){
                        //console.log("Покупаем часть тотема");
                        if (slot.reward.invasionFragmentSkill?.[titanSkilsIdsToBuy[0]]){
                            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 += slot.reward.invasionFragmentSkill?.[titanSkilsIdsToBuy[0]];
                                if (titanSkilFragments >= 7){
                                    titanSkilsIdsToBuy = await getTitanSkillIdsToBuy();
                                    titanSkilFragments = 0;
                                }
                            }else{
                                await Caller.send({name: 'shop_pinSlot', args: {shopId: titanShopId, slotId: slot.id}});
                            }
                        }
                    }else{
                        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;
                            }
                        }
                    }
                }
            }
            //Обновить магазин
            if (coins >= 12){
                let shopRefresh = await Caller.send({name: 'shopRefresh', args: {shopId: titanShopId}});
                //await new Promise((e) => setTimeout(e, 1000));
                coins -= 3;
                console.log("Обновили магазин. Осталось монет " + coins);
                if(shopRefresh.error){
                    coins = 0;
                }
            }else{
                break;
                return;
            }
        }
    }


    async function buyHeroInTheStore(heroShopId, herosId) {
        let coins = await Caller.send('inventoryGet').then(e => e.coin[1080]);
        console.log("coins" + coins);
        //Получить состояние магазина
        const result = await Caller.send([{name:'shopGet',args:{shopId: shopId}}]).then(e => e.slots);
        let slots = Object.values(result)
        for (let slot of slots){
            //Пропустить скрытые лоты
            if (slot.reward.invasionFragmentHeroRand){
                continue;
            }
            console.log(slot);
            console.log(slot.id)
            console.log(slot.cost.coin[1080])
        }
    }
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    async function attackTitanMission(missionId, chapterId, heroes, 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;
            }
        }

        /*if (!calcBattle.result.win) {
            // Поражение
            return;
        }*/

        const endBattle = await Caller.send({
            name: 'invasion_bossEnd',
            args: {
                id: missionId,
                result: calcBattle.result,
                progress: calcBattle.progress,
            },
        });
    }
    //////////////////
    async function attackHeroMission(missionId, chapterId, attacHero, pet) {
        const startBattle = await Caller.send({
            name: 'invasion_bossStart',
            args: {
                id: missionId,
                chapterId:chapterId,
                heroes: attacHero,
                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;
            }
        }

        /*if (!calcBattle.result.win) {
            // Поражение
            return;
        }*/

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

})();