HWHhuntFragmentExt

Extension for HeroWarsHelper script

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 or Violentmonkey 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			HWHhuntFragmentExt
// @name:en			HWHhuntFragmentExt
// @name:ru			HWHhuntFragmentExt
// @namespace		HWHhuntFragmentExt
// @version			0.0.49
// @description		Extension for HeroWarsHelper script
// @description:en	Extension for HeroWarsHelper script
// @description:ru	Расширение для скрипта HeroWarsHelper
// @author			dimaka1256
// @license 		Copyright dimaka1256
// @homepage		none
// @icon			https://zingery.ru/scripts/VaultBoyIco16.ico
// @icon64			https://zingery.ru/scripts/VaultBoyIco64.png
// @match			https://www.hero-wars.com/*
// @match			https://apps-1701433570146040.apps.fbsbx.com/*
// @run-at			document-start
// ==/UserScript==

(function () {

    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 {
		setProgress,
		getSaveVal,
		setSaveVal,
		popup,
        I18N,
		getUserInfo,
	} = HWHFuncs;

let {buttons,i18nLangData} = HWHData;

let ruLang ={
    FRAGMENT_HUNT: 'Слить энку',
    FRAGMENT_HUNT_TITLE: 'Добывать фрагменты шмоток/рецептов',
	FRAGMENT_HUNT_SETUP: '⚙️',
    FRAGMENT_HUNT_SETUP_TITLE: 'Выбор фрагмента/миссии',
	FRAGMENT_HUNT_ENERGY: '⚡️',
    FRAGMENT_HUNT_FR: '🧩',
    FRAGMENT_HUNT_MISSION: 'миссия',
	FRAGMENT_HUNT_WORLD: 'Глава',
	FRAGMENT_HUNT_SPENT: 'Потратили ',
    FRAGMENT_HUNT_GOTFRAGMENTS: ', получили такой лут:',
    FRAGMENT_HUNT_PCS: 'шт',
    FRAGMENT_HUNT_WEHUNT: 'Добываем предметы',
    FRAGMENT_HUNT_ENOUGH1: ', хватит на ',
    FRAGMENT_HUNT_ENOUGH2: ' рейдов x10',
    FRAGMENT_HUNT_CHANGE: 'Выбрать',
    FRAGMENT_HUNT_PARTS1: 'Фиол шмот',
    FRAGMENT_HUNT_PARTS2: 'Фиол свитки А-О',
    FRAGMENT_HUNT_PARTS3: 'Фиол свитки П-Я',
    FRAGMENT_HUNT_PARTS4: 'Жёлтый шмот',
    FRAGMENT_HUNT_PARTS5: 'Жёлтые свитки А-К',
    FRAGMENT_HUNT_PARTS6: 'Жёлтые свитки Л-Я',
    FRAGMENT_HUNT_PARTS7: 'Красный шмот',
    FRAGMENT_HUNT_PARTS8: 'Красные свитки',
    FRAGMENT_HUNT_CHOOSEPART: 'Какую категорию шмотки ищём?',
    FRAGMENT_HUNT_CHOOSEITEM: 'Какую шмотку ищём?',
    FRAGMENT_HUNT_CHOOSEMISSION: 'В какой миссии? (см. ещё дроп)',
	FRAGMENT_HUNT_NOTENOUGH: 'Недостаточно энергии',
	FRAGMENT_HUNT_NOMISSION: 'Не выбрана миссия, нечего добывать',
	FRAGMENT_HUNT_DOALL: 'Слить энку на миссию',
	FRAGMENT_HUNT_NOVIP: 'Сорри, без VIP1 не работает',
	FRAGMENT_HUNT_SMALLVIP: 'Без VIP5 бьёт одиночными рейдами',
}
let enLang ={
    FRAGMENT_HUNT: 'Spend Stamina',
    FRAGMENT_HUNT_TITLE: 'Hunt for Item/Scroll fragment',
	FRAGMENT_HUNT_SETUP: '⚙️',
    FRAGMENT_HUNT_SETUP_TITLE: 'Choose fragment/mission',
	FRAGMENT_HUNT_ENERGY: '⚡️',
	FRAGMENT_HUNT_SPENT: 'Spent ',
    FRAGMENT_HUNT_FR: '🧩',
    FRAGMENT_HUNT_MISSION: 'mission',
	FRAGMENT_HUNT_WORLD: 'World',
    FRAGMENT_HUNT_GOTFRAGMENTS: ',g ot this loot:',
    FRAGMENT_HUNT_PCS: 'pcs',
    FRAGMENT_HUNT_WEHUNT: 'We hunt for items',
    FRAGMENT_HUNT_ENOUGH1: ', enough for ',
    FRAGMENT_HUNT_ENOUGH2: ' raids x10',
    FRAGMENT_HUNT_CHANGE: 'Choose',
    FRAGMENT_HUNT_PARTS1: 'Purple gear',
    FRAGMENT_HUNT_PARTS2: 'Purple scrolls 1',
    FRAGMENT_HUNT_PARTS3: 'Purple scrolls 2',
    FRAGMENT_HUNT_PARTS4: 'Yellow gear',
    FRAGMENT_HUNT_PARTS5: 'Yellow scrolls 1',
    FRAGMENT_HUNT_PARTS6: 'Yellow scrolls 2',
    FRAGMENT_HUNT_PARTS7: 'Red gear',
    FRAGMENT_HUNT_PARTS8: 'Red scrolls',
    FRAGMENT_HUNT_CHOOSEPART: 'Choose fragment category:',
    FRAGMENT_HUNT_CHOOSEITEM: 'Choose fragment:',
    FRAGMENT_HUNT_CHOOSEMISSION: 'Choose mission(look at other drop)',
	FRAGMENT_HUNT_NOTENOUGH: 'Not enough stamina',
	FRAGMENT_HUNT_NOMISSION: 'Mission not chosen',
	FRAGMENT_HUNT_DOALL: 'Consume stamina to a mission',
	FRAGMENT_HUNT_NOVIP: 'This requires at least VIP1 to run',
	FRAGMENT_HUNT_SMALLVIP: 'Only single raids without VIP5',
}
Object.assign(i18nLangData.ru, ruLang)
Object.assign(i18nLangData.en, enLang)
this.HWHData.i18nLangData = i18nLangData;

const fragmentHuntButton = {
    fragmentHuntButton: {
		isCombine: true,
		combineList: [
			{
				get name() { return I18N('FRAGMENT_HUNT'); }, 
				get title() { return I18N('FRAGMENT_HUNT_TITLE'); },
        		onClick: gohuntFragment,
				hide: false,
				color: 'red'
			},
			{
        		get name() { return I18N('FRAGMENT_HUNT_SETUP'); }, 
				get title() { return I18N('FRAGMENT_HUNT_SETUP_TITLE'); },
        		onClick: setuphuntFragment,
				hide: false,
				color: 'red'
			},
		]
}}

Object.assign(buttons,fragmentHuntButton)
this.HWHData.buttons = buttons;


function setuphuntFragment() {
		let fragment= new huntFragment();
		fragment.setup();
}

function gohuntFragment() {
		let fragment= new huntFragment();
		fragment.start();
}

//добавить галочку в "сделать всё"
//я буду гореть за это в аду
const task = {
			name: 'gohuntFragment',
			label: I18N('FRAGMENT_HUNT_DOALL'),
			checked: false
		}
const functions2 = {
		gohuntFragment
}

const {doYourBest} = HWHClasses;
const doIt = new doYourBest();
	let myfuncList=doIt.funcList
	myfuncList.splice (-3,0,task);
	let myfunctions = doIt.functions
	Object.assign(myfunctions, functions2)

	class extdoYourBest extends doYourBest {
		funcList = myfuncList
		functions = myfunctions
	}
this.HWHClasses.doYourBest = extdoYourBest;


class huntFragment {

	inventoryGet = []
	droptable = []
	stamina = 0
    raids = 0
    missionID = 0
    energyNeeded = 0

missionEnergy (id) {
		if (id == 0) {return 999999};
        if (id > 145) {return 10};
	    if (id  < 86) {return 6};
		return 8
}

checkvip() {
	let currentVipPoints = (getUserInfo()).vipPoints;
	if (currentVipPoints >999) {return 5}
	if (currentVipPoints >9) {return 1}
	return 0
}

isWithinRange(value, min, max) {
  return value >= min && value <= max;
}

generateArray(start, size) {
  return Array.from({length: size}, (_, index) => index + start);
}

getType(id){
	let type = "oops"
	if (this.isWithinRange (id, 21, 55) || this.isWithinRange (id, 56, 99) || this.isWithinRange (id, 167, 178) || this.isWithinRange (id, 221, 232)) {type="Gear"}
	if (this.isWithinRange (id, 141, 166) || this.isWithinRange (id, 190, 220) || this.isWithinRange (id, 244, 254)) {type="Scroll"}
	return type
}

getColor(id){
    if (this.isWithinRange (id, 21, 55)) {return "green"}
    if (this.isWithinRange (id, 141, 145)) {return "green"}
    if (this.isWithinRange (id, 56, 90)) {return "blue"}
	if (this.isWithinRange (id, 91, 166)) {return "purple"}
	if (this.isWithinRange (id, 167, 220)) {return "orange"}
	if (this.isWithinRange (id, 221, 254)) {return "red"}
	console.log ("getColor oops", id); return "white"
}

getName(id){
	this.updatemyData()
	let itemAvailable = 0
	let fullitemAvailable = 0;
	switch (this.getType(id)) {
	 case "Gear": {
		itemAvailable = this.inventoryGet.fragmentGear[id] ?? 0;
		fullitemAvailable = this.inventoryGet.gear[id] ?? 0; break;
	}
	 case "Scroll": {
		itemAvailable = this.inventoryGet.fragmentScroll[id] ?? 0;
		fullitemAvailable = this.inventoryGet.scroll[id] ?? 0; break;
	}
	}

	let color = this.getColor(id)
	let name = cheats.translate(`LIB_${(this.getType(id)).toUpperCase()}_NAME_${id}`);
	let words = name.split(" ")
	for (let i in words) {if (words[i].length > 8){name=name.replace(words[i],(words[i]).substring(0,5)+".")}}
	name = name.replace(" - Рецепт","-р"); 
	name = name.replace(", уровень ","-"); 
	name = name.replace(" уровень ","-");//эти сокращения локалить впадлу, совсем
	let out =""
    //out+=id //если нужен ид шмотки
	out+=' <span style="color:'+color+';">'+name+'</span> ('+fullitemAvailable+'+'+itemAvailable+I18N('FRAGMENT_HUNT_FR')+')';
	return out
}

generateitembuttons(itemids) {
	const buttons = [];
	for (let itemid in itemids) {
		let gearID = itemids[itemid]
		let name = this.getName(gearID);
		buttons.push({
					msg:  name,
					result: itemids[itemid],
					get title() { return name },
				});
	}
	buttons.push({msg: I18N('BTN_CANCEL'), result: false, isCancel: true})
	return buttons
}

generatemissionbuttons(missions, itemid) {
	const buttons = [];
	for (let mission in missions) {
		let missionID = missions[mission]
		let thismission = this.droptable.filter(m=>m.id===missionID)[0]
		let otheritems = thismission.drop.filter(d=>d != itemid) 
		let name = I18N('FRAGMENT_HUNT_WORLD')+" "+thismission.world+" "+I18N('FRAGMENT_HUNT_MISSION')+" "+thismission.index+"   "+this.missionEnergy(thismission.id)+I18N('FRAGMENT_HUNT_ENERGY')+"<br>"
		// I18N('FRAGMENT_HUNT_MISSION')+" "+ thismission.id
		for(let i in otheritems) {if (this.getType(otheritems[i]) === "oops"){continue;};name+=this.getName(otheritems[i])+"<br>";} 
		buttons.push({
					msg:  name,
					result: missionID,
					get title() { return name },
				});
	}
	buttons.push({msg: I18N('BTN_CANCEL'), result: false, isCancel: true})
	return buttons
}

async updatemyData(){
		let calls = [{
			name: "userGetInfo",
			args: {},
			ident: "userGetInfo"
		},{
			name: "inventoryGet",
			args: {},
			ident: "inventoryGet"
		}];
		let result = await Send(JSON.stringify({ calls }));
		let infos = result.results;
		this.stamina = (infos[0].result.response.refillable.find(n => n.id == 1)).amount;
		this.inventoryGet = infos[1].result.response;

	    this.energyNeeded = this.missionEnergy(this.missionID)
        //if (this.missionID > 145) {this.energyNeeded = 10};
	    //if (this.missionID  < 86) {this.energyNeeded = 6};
		//console.log ("vip",this.checkvip())
        switch (this.checkvip()){
			case 5: {this.raids = Math.floor(this.stamina/(this.energyNeeded*10)); break;}
			case 1: {this.raids = Math.floor(this.stamina/(this.energyNeeded)); break}
			case 0: {this.raids = 0; setProgress(I18N('FRAGMENT_HUNT_NOVIP'))}
		}
		return "ok"
}

async makeMission(mission,count){
	let nrg = this.energyNeeded*count;
	let calls = []

			switch (this.checkvip()){
			case 5: {calls.push({name: "missionRaid",args: {id: mission.id,times: (count)},ident: "body"}); break;}
			case 1: {
					for (let i = 0; i < count; i++)
					{
						calls.push({name: "missionRaid",args: {id: mission.id,times: 1},ident: "body"+"i"})
					}
					
				}
			}
			let result = await Send({ calls })
            console.log(result)
			let loot2 = []
			for (let j in result.results)
			{
				let loot = result.results[j].result.response
				for (let i in loot){
					if (!!loot[i].fragmentScroll) {loot2.push(loot[i].fragmentScroll)}
					if (!!loot[i].fragmentGear) {loot2.push(loot[i].fragmentGear)}
				}
			}
				let loot3=[]
                //console.log("loot2",loot2)
				for (let i in loot2) {
                    for (let j in Object.keys(loot2[i])) {loot3.push(Object.keys(loot2[i])[j])}                    
			}
			await this.updatemyData()
            //console.log("loot3",loot3)
			let str = I18N('FRAGMENT_HUNT_SPENT')+nrg+I18N('FRAGMENT_HUNT_ENERGY')+ I18N('FRAGMENT_HUNT_GOTFRAGMENTS')+"<br>"
			let usedids = []
			let loot4=[]
			for (let i in loot3) {
				if (!usedids.includes(loot3[i])){loot4.push({id:loot3[i],qty:1}); usedids.push(loot3[i])}
				else {(loot4.find(e => e.id== loot3[i])).qty++}
			}
			for (let i in loot4){
				str+=this.getName(loot4[i].id)+": "+loot4[i].qty+ I18N('FRAGMENT_HUNT_PCS')+"<br>"
			}
			setProgress(str)
            //if (this.raids >0) {this.start(false)}
}

updateDroptable(){
  const dropTable2 = ((types = ['gear', 'fragmentGear', 'scroll', 'fragmentScroll']) => {
  return Object.values(lib.data.mission).map(e => {
  const lastWave = e.normalMode?.waves?.at(-1);
  const lastEnemy = lastWave?.enemies?.at(-1);
  let dropList = lastEnemy?.drop ?? [];
  let heromissions = []
  for(const i of dropList) {
	const type = Object.keys(i.reward)[0]
	if (type == 'fragmentHero') {
		//console.log('heromission',e.id); 
		heromissions.push(e.id)
	}
  }
  const drop = [];
  for(const d of dropList) {
    const type = Object.keys(d.reward).pop()
    if (d.chance && types.includes(type) && !(heromissions.includes(e.id))) {
      const id = Object.keys(d.reward[type]).pop()
      if (id>90) {drop.push(+id)}
    }
  }
  return {id: e.id, world: e.world, index: e.index, drop}
}).filter(n => n.drop.length)
})()
//console.log("dropTable2",dropTable2)
this.droptable = dropTable2
}

async start() {
	this.updateDroptable()
	this.missionID = getSaveVal('huntFragmentMission', 999)
	let mission = this.droptable.filter(m=>m.id===this.missionID)[0]
	//console.log ("start missionID",this.missionID,mission)
    if (!mission) {console.log("nomission"); this.setup();} //если в конфиге кака сначала настройка
	await this.updatemyData()
		console.log("Энки у нас",this.stamina," рейдов доступно",this.raids)

		if (this.raids >0) {
			 if (this.checkvip() == 5){this.makeMission(mission,this.raids*10); }
			 else {this.makeMission(mission,this.raids); }
		} 
		else {setProgress(I18N('FRAGMENT_HUNT_NOTENOUGH'))}
	}

async setup() {
	this.updateDroptable()
	//console.log("droptable2 updated",this.droptable)
	this.missionID = getSaveVal('huntFragmentMission', 999)
	let mission = this.droptable.filter(m=>m.id===this.missionID)[0]
	//console.log ("setup missionID",this.missionID)
	let message = ""; let maxraid =""; let target="";
	if (this.checkvip() != 5) {message+=I18N('FRAGMENT_HUNT_SMALLVIP')}

	if (!mission) {
		this.raids = 0; 
		message = I18N('FRAGMENT_HUNT_NOMISSION')} //костыль чтоб точно выбрали миссию
	else {
		await this.updatemyData()
		for (let i in mission.drop){let id=mission.drop[i]; target+=this.getName(id)+"<br>";}
		maxraid = I18N('RAID')+" х"
		if (this.checkvip()==5) {maxraid+=this.raids*10} else {maxraid+=this.raids}
		message = I18N('FRAGMENT_HUNT_WEHUNT')+":<br> "+target+" <br>"+I18N('FRAGMENT_HUNT_WORLD')+" "+mission.world+" "+I18N('FRAGMENT_HUNT_MISSION')+" "+mission.index+"    "+this.energyNeeded+" "+I18N('FRAGMENT_HUNT_ENERGY')+"<br>"+I18N('FRAGMENT_HUNT_ENERGY')+" "+this.stamina+I18N('FRAGMENT_HUNT_ENOUGH1')+this.raids+I18N('FRAGMENT_HUNT_ENOUGH2')
	}
	
	let buttons0 = []
	if (this.raids > 0 && this.checkvip()==5) {buttons0.push({msg: I18N('RAID')+" х10", result: "1"})}
	if (this.raids > 1) {buttons0.push({msg: maxraid, result: "2"})}
	buttons0.push({msg: I18N('FRAGMENT_HUNT_CHANGE'), result: "3"})
	buttons0.push({msg: I18N('BTN_CANCEL'), result: false})

	this.answerr = await popup.confirm(message, buttons0);
	
	const parts = [I18N('FRAGMENT_HUNT_PARTS1'),I18N('FRAGMENT_HUNT_PARTS2'),I18N('FRAGMENT_HUNT_PARTS3'),I18N('FRAGMENT_HUNT_PARTS4'),I18N('FRAGMENT_HUNT_PARTS5'),I18N('FRAGMENT_HUNT_PARTS6'),I18N('FRAGMENT_HUNT_PARTS7'),I18N('FRAGMENT_HUNT_PARTS8')]
	const buttons = [];
	for (let i in parts ) {
		buttons.push({
					msg: parts[i],
					result: i,
					get title() { return "test" },
				});
	}
	buttons.push({msg: I18N('BTN_CANCEL'), result: false, isCancel: true})
	let answer=0;
	switch (this.answerr) { 
		case "1": {
			//console.log("тут будет рейд х10",mission.id);
			this.makeMission(mission,10)
			break;
			}
		case "2": {
			//console.log("тут будет макс рейд",mission.id); 
			this.makeMission(mission,this.raids*10)
			break;}
		case "3": {answer = await popup.confirm(I18N('FRAGMENT_HUNT_CHOOSEPART'), buttons); break;}
		default: {return;}
	}
	if (!answer) {return}

	let array=[]
	switch (answer) { 
		case "0": { array=this.generateArray(91,8);break;}
		case "1": { array=[158,153,162,164,165,157,152,166]; break;} //(152,15)
		case "2": { array=[163,159,154,161,156,160,155]; break;}
		case "3": { array=this.generateArray(167,12);break;}
		case "4": { array=[190,194,197,205,204,215,214,196,218,193,219,217,206]; break;}
		case "5": { array=[198,220,195,192,216,191,199,200]; break;}
		case "6": { array=this.generateArray(221,12); break;}
		case "7": { array=this.generateArray(244,11); break;}
		default: {console.log("oops"); break;}
	}
	let answer2 = await popup.confirm(I18N('FRAGMENT_HUNT_CHOOSEITEM'), this.generateitembuttons(array));
	if (!answer2) {return}

	let missions = this.droptable.filter(m=>m.drop.includes(answer2))
	let missarray = []
	for (let i in missions) {missarray.push(missions[i].id)}
	let answer3 = await popup.confirm(I18N('FRAGMENT_HUNT_CHOOSEMISSION')+"<br>"+this.getName(answer2), this.generatemissionbuttons(missarray,answer2));
	if (!answer3) {return}

	setSaveVal('huntFragmentMission', answer3)
	this.setup()
}
}
this.HWHClasses.huntFragment = huntFragment;
})();

//TODO:
// формат "одной кнопки" для "сделать всё"