自动孵蛋模块
// ==UserScript==
// @name 自动孵蛋模块
// @namespace PokeClickerHelper
// @version 0.1.2
// @description 全自动高效孵化宝可梦、宝可梦蛋、化石
// @author 超超
// @match https://pokemon.ccox.cc/
// @icon data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAP8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA/319hf99fYX/fX2F/319hf8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////////////////////99fYX/fX2F/319hf8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////////wAAAP8AAAD/fX2F/319hf99fYX/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////8AAAD/AAAA/wAAAP99fYX/fX2F/wAAAP8AAAD/AAAA/319hf8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/HBT//xwU//8AAAD//////319hf8AAAD/Dgim/w4Ipv8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAD/HBT//xwU//8cFP//HBT//wAAAP8AAAD/Dgim/w4Ipv8OCKb/Dgim/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAA/xwU//8cFP//HBT//xwU/44cFP//HBT//xwU//8cFP//Dgim/w4Ipv8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/HBT//xwU/47/////HBT/jhwU//8cFP//HBT//w4Ipv8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/xwU//8cFP//HBT/jhwU//8OCKb/Dgim/w4Ipv8OCKb/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA/xwU//8OCKb/Dgim/w4Ipv8AAAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA/wAAAP8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAPw/AADwDwAA4AcAAOAHAADAAwAAwAMAAMADAADAAwAA4AcAAOAHAADwDwAA/D8AAP//AAD//wAA//8AAA==
// @grant none
// @license MIT
// @run-at document-end
// ==/UserScript==
/* global App, $, PokeClickerHelper, Underground, PartyController, GameConstants, player, ItemList, CaughtStatus, PokemonHelper, Settings, pokemonMap, PokemonCategories, SortOptionConfigs */
if (typeof PokeClickerHelper == typeof void 0) {
alert('宝可梦点击(Poke Clicker)辅助脚本 自动地牢/道馆模块加载失败\n\n未找到核心模块,需要先安装核心模块才可正常使用\n\n论坛主页:https://scriptcat.org/script-show-page/1228')
window.open("https://scriptcat.org/script-show-page/1228")
return
}
//UI相关
PokeClickerHelper.UIDOM.push(`
<div id="PokeClickerHelperBreeding" class="custom-row">
<div>
<div class="form-row mb-1">
<div class="col-auto align-self-center">
<label class="m-0">自动培育:</label>
</div>
<div class="col">
<button id="PokeClickerHelperToggleBreeding" class="btn btn-sm btn-primary mr-1" value="开始">开始</button>
<label class="form-check-label ml-4 mr-1" title="降序:从大到小 升序:从小到大"><input id="PokeClickerHelperBreedingInvert" type="checkbox" value="false">升序</label>
<label class="form-check-label ml-4 mr-1" title="使用新排序算法减少孵化计算量 加快孵化效率 测试功能 不保证无BUG 炸档不负责 使用前强烈建议备份存档"><input id="PokeClickerHelperBreedingNewAlg" type="checkbox" value="false">新排序算法</label>
<label class="form-check-label ml-4 d-none"><input id="PokeClickerHelperBreedingUncaught" type="checkbox" value="false">只孵化未捕捉</label>
</div>
</div>
<div class="form-row">
<div class="col">
<label>孵化类型</label>
<select id="PokeClickerHelperBreedingType" class="custom-select">
<option value="BreadingPokemon">宝可梦</option>
<option value="BreadingEgg">蛋</option>
<option value="BreadingFossil">化石</option>
</select>
</div>
<div class="col">
<label>排序</label>
<select id="PokeClickerHelperBreedingSortOption" class="custom-select">
</select>
</div>
<div class="col">
<label>闪光状态</label>
<select id="PokeClickerHelperBreedingShiny" class="custom-select">
<option value="all">全部</option>
<option value="true">闪光</option>
<option value="false">非闪光</option>
</select>
</div>
<div class="col" id="PokeClickerHelperBreedingRegionDebuffDiv">
<label>地区减益</label>
<select id="PokeClickerHelperBreedingRegionDebuff" class="custom-select">
<option value="-1">无</option>
<option value="0">关东地区</option>
<option value="1">城都地区</option>
<option value="2">丰缘地区</option>
<option value="3">神奥地区</option>
<option value="4">合众地区</option>
<option value="5">卡洛斯地区 </option>
<option value="6">阿罗拉地区</option>
<option value="7">伽勒尔地区</option>
<option value="8">最终</option>
</select>
</div>
</div>
<div class="mt-2 mb-1 border-top border-secondary opacity-25"></div>
<div class="form-row" id="PokeClickerHelperBreedingRow2">
<div class="col-3">
<label>孵化属性1</label>
<select id="PokeClickerHelperBreedingTypeFilter1" class="custom-select" title="选择后仅孵化第一第二属性完全符合的宝可梦"></select>
</div>
<div class="col-3">
<label>孵化属性2</label>
<select id="PokeClickerHelperBreedingTypeFilter2" class="custom-select" title="选择后仅孵化第一第二属性完全符合的宝可梦"></select>
</div>
<div class="col-3"><label>优先类别</label><select id="PokeClickerHelperBreedingPriority" class="custom-select" title="无视其他设定 能够孵化时优先孵化该类别宝可梦"></select></div>
</div>
</div>
</div>
<div class="mt-2 mb-1 border-top border-secondary"></div>
`)
const fuc = () => {
//非挑战模式区域减益隐藏
if (!App.game.challenges.list.regionalAttackDebuff.active()) $('#PokeClickerHelperBreedingRegionDebuffDiv').addClass('invisible')
//读取孵化属性标签
$('[name="breedingTypeFilter1"] option').clone().each((_, i) => $(i).attr('data-bind', null).attr('selected', null)).appendTo($("#PokeClickerHelperBreedingTypeFilter1,#PokeClickerHelperBreedingTypeFilter2"))
//读取孵蛋类别
PokemonCategories.categories().map(i => i.name()).forEach((i, index) => {
$('#PokeClickerHelperBreedingPriority').append(`<option value="${index}">${i}</option>`)
})
//读取孵蛋排序
Object.values(SortOptionConfigs).forEach(({text},index) => {
$('#PokeClickerHelperBreedingSortOption').append(`<option value="${index}">${text}</option>`)
})
}
const listener = () => {
$('#PokeClickerHelperToggleBreeding').on('click', function () {
if (this.value == '结束') {
PokeClickerHelper.restoreHook(PokeClickerHelper.hookGame.breeding) //还原hook方法
$('#PokeClickerHelperToggleBreeding').text(this.value = '开始')
} else {
PokeClickerHelper.applyHook(PokeClickerHelper.hookGame.breeding) //应用hook方法
$('#PokeClickerHelperToggleBreeding').text(this.value = '结束')
}
})
$("#PokeClickerHelperBreedingType").on('change', function () {
const isPokemon = this.value == 'BreadingPokemon'
$("label:has(#PokeClickerHelperBreedingInvert)").toggleClass('d-none', !isPokemon)
$("label:has(#PokeClickerHelperBreedingNewAlg)").toggleClass('d-none', !isPokemon)
$("label:has(#PokeClickerHelperBreedingUncaught)").toggleClass('d-none', isPokemon)
$("#PokeClickerHelperBreedingType").parent().siblings().find('select').attr('disabled', !isPokemon)
$("#PokeClickerHelperBreedingRow2 select").attr('disabled', !isPokemon)
})
}
PokeClickerHelper.UICustomFuc.push(fuc);
PokeClickerHelper.UIlistener.push(listener);
//暴露对象方法到全局
const BreedingHelper = {};
PokeClickerHelper.BreedingHelper = BreedingHelper;
//满步数自动孵蛋、有空位自动孵蛋 hook方法
const autoHatch = function (Game) {
const replacement = [
['this._queueList().length && ', ''],
[/^/, "PokeClickerHelper.BreedingHelper.AutoBreeding();"],
];
PokeClickerHelper.HookFuc(Game.breeding, 'progressEggs', replacement, 'amount');
PokeClickerHelper.restoreHook(PokeClickerHelper.hookGame.breeding)
}
PokeClickerHelper.addHook('Game', autoHatch)
let newAlgLastOptions
let newAlgLastPokemonArr = []
//委托函数 利用语法糖配合解构减少冗余代码
BreedingHelper.AutoBreeding = () => {
if (!App.game.breeding.hasFreeEggSlot()) return
let value = [...document.querySelectorAll('#PokeClickerHelperBreeding select')].map(i => i.value)
const newAlg = document.querySelector("#PokeClickerHelperBreedingNewAlg").checked
if (newAlg) {
value.push(true)
const newAlgOptions = value.join()
if (newAlgOptions == newAlgLastOptions) value.push(true)
newAlgLastOptions = newAlgOptions
}
if (value.length > 0) BreedingHelper[value.shift()](value)
}
//利用解构减少代码
//孵宝可梦
BreedingHelper.BreadingPokemon = ([sortOption, shiny, region, type1, type2, Priority, newAlg = false, newAlgMark = false]) => {
if (shiny != 'all') shiny = JSON.parse(shiny)
if (newAlg && newAlgMark) {
for (const pokemon of newAlgLastPokemonArr) {
if (!App.game.breeding.hasFreeEggSlot()) return
if (pokemon.shiny != shiny) break
if (pokemon.level >= 100 && !pokemon.breeding) {
//console.log('新算法孵宝可梦',pokemon.displayName,pokemon)
App.game.breeding.addPokemonToHatchery(pokemon)
}
}
}
if (!App.game.breeding.hasFreeEggSlot()) return
const direction = !document.querySelector("#PokeClickerHelperBreedingInvert").checked
let typeFlag
if (type1 + type2 != '-2-2') {
typeFlag = true
type1 = type1 * 1
type2 = type2 * 1
if (type1 == -1) type1 = void 0
if (type2 == -1) type2 = void 0
}
const pokemonArr = App.game.party.caughtPokemon
//优先孵化 不排序
const pokemonPriorityArr = (Priority != '0' && (!newAlg || (newAlg && !newAlgMark) || (newAlg && newAlgMark && newAlgLastPokemonArr.length == 0))) ? pokemonArr.filter(i => i.category == Priority) : []
for (const pokemon of pokemonPriorityArr) {
if (!App.game.breeding.hasFreeEggSlot()) return (newAlgLastPokemonArr = pokemonPriorityArr)//优先孵化满槽后直接中断不再进行排序 减少计算量
if (pokemon.level >= 100 && !pokemon.breeding) {
//console.log('优先孵宝可梦',pokemon.displayName,pokemon)
App.game.breeding.addPokemonToHatchery(pokemon)
}
}
if (!App.game.breeding.hasFreeEggSlot()) return
//普通孵化 排序
const pokemonFilterArr = shiny == 'all' && !typeFlag ? pokemonArr : pokemonArr.filter(i => {
let flag = true
if (shiny != 'all') flag = i.shiny == shiny
if (flag && typeFlag) {
const pokemonType = pokemonMap[i.name].type
flag = (type1 < 0 || (type1 >= 0 && pokemonType.includes(type1))) && (type2 < 0 || (type2 >= 0 && pokemonType.includes(type2)))
}
return flag
})
pokemonFilterArr.sort(PartyController.compareBy(sortOption * 1, direction, region * 1))
for (const pokemon of pokemonFilterArr) {
if (!App.game.breeding.hasFreeEggSlot()) return (newAlgLastPokemonArr = Priority == '0' ? pokemonFilterArr : pokemonPriorityArr)
if (pokemon.level >= 100 && !pokemon.breeding) {
//console.log('孵宝可梦',pokemon.displayName,pokemon)
App.game.breeding.addPokemonToHatchery(pokemon)
}
}
}
//孵蛋
BreedingHelper.BreadingEgg = () => {
let avaiableEgg = Object.keys(GameConstants.EggItemType).filter(e => isNaN(e)).filter(x => player._itemList[x]());
const onlyUncaught = document.querySelector("#PokeClickerHelperBreedingUncaught").value == 'true'
if (onlyUncaught) avaiableEgg = avaiableEgg.filter(i => ItemList[i].getCaughtStatus() == CaughtStatus.NotCaught)
avaiableEgg = avaiableEgg.flatMap(i => Array(Math.min(player._itemList[i](), 4)).fill(i))
for (const egg of avaiableEgg) {
if (!App.game.breeding.hasFreeEggSlot()) break
ItemList[egg].use();
}
}
//孵化石
BreedingHelper.BreadingFossil = () => {
let avaiableFossil = Object.keys(GameConstants.FossilToPokemon).map(f => player.mineInventory().find(i => i.name == f)).filter(f => f ? f.amount() : false)
const onlyUncaught = document.querySelector("#PokeClickerHelperBreedingUncaught").value == 'true'
avaiableFossil = avaiableFossil.filter(i => {
let flag = PokemonHelper.calcNativeRegion(GameConstants.FossilToPokemon[i.name]) <= player.highestRegion()
if (onlyUncaught) flag = flag && PartyController.getCaughtStatusByName(GameConstants.FossilToPokemon[i.name]) == CaughtStatus.NotCaught
return flag
})
avaiableFossil = avaiableFossil.map(i => Array(i.amount()).fill(i.id)).flat()
for (const fossil of avaiableFossil) {
if (!App.game.breeding.hasFreeEggSlot()) break
Underground.sellMineItem(fossil)
}
}