您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Redesigned breeding UI and QoL features.
当前为
// ==UserScript== // @name IdlePixel Breeding Overhaul // @namespace com.anwinity.idlepixel // @version 1.0.11 // @description Redesigned breeding UI and QoL features. // @author Anwinity // @license MIT // @match *://idle-pixel.com/login/play* // @grant none // @require https://gf.qytechs.cn/scripts/441206-idlepixel/code/IdlePixel+.js?anticache=20220905 // ==/UserScript== (function() { 'use strict'; const IMAGE_URL = "https://cdn.idle-pixel.com/images/"; const ANIMAL_LIST = ["chicken", "sheep", "spider", "horse", "ant", "camel", "beaver", "dove", "pig", "haron", "toysoldier"]; const ANIMAL_SORT = ANIMAL_LIST.reduce((acc, value, index) => { acc[value] = index; return acc; }, {}); const FOOD_MAP = { Seeds: "breeding_food_seeds", Leaves: "breeding_food_leaves", // breeding_food_strange_leaves Seafood: "breeding_food_fish", // breeding_food_fruits Insects: "breeding_food_insects", Bark: "breeding_food_wood", Metal: "breeding_food_metal", }; class BreedingOverhaulPlugin extends IdlePixelPlusPlugin { constructor() { super("breedingoverhaul", { about: { name: GM_info.script.name, version: GM_info.script.version, author: GM_info.script.author, description: GM_info.script.description } }); } parseAnimals(raw) { if(!raw) { return []; } return raw.split("=").map((rawAnimal) => { const result = { raw: rawAnimal }; const [ slug, animal, gender, tier, millis, isGold, sick, foodPerDay, foodConsumed, lootItemReady, lootItemAmount, xpGained, traitLabel, extraData1, extraData2, extraData3, extraData4, extraData5 ] = rawAnimal.split(","); let food = Breeding.getBreedFoodLabel(animal); if(food == "null") { food = null; } result.slug = slug; result.animal = animal; result.sex = (gender==1 ? "M" : (gender==2 ? "F" : "?")); //result.tier = parseInt(tier); result.birth = parseInt(millis); //result.gold = isGold!=0; result.sick = sick!=0; result.food = food; result.foodPerDay = parseInt(foodPerDay); //result.foodConsumed = parseInt(foodConsumed); result.lootItem = lootItemReady == "none" ? null : lootItemReady; result.lootCount = parseInt(lootItemAmount); result.xp = parseInt(xpGained); result.trait = traitLabel; //result.hornyRate = Breeding.getReproductionRate(animal, null); return result; }).sort((a, b) => { const aSort = ANIMAL_SORT[a.animal] ?? 9999; const bSort = ANIMAL_SORT[b.animal] ?? 9999; if(aSort == bSort) { return a.birth - b.birth; } return aSort - bSort; }); } calculateReproductionRate(animalData, animal) { if(["toysoldier"].includes(animal)) { return Number.POSITIVE_INFINITY; } // calculates expected # of ticks for this species to reproduce let rate = Breeding.getReproductionRate(animal, null); let males = 0; let females = 0; let infertile = 0; let fertile = 0; for(const data of animalData) { if(data.animal != animal) { continue; } if(data.sick) { continue; } if(data.sex == "M") { males++; } else if(data.sex == "F") { females++; } if(data.trait == "Fertile") { fertile++; } else if(data.trait == "Less Fertile") { infertile++; } } let couples = Math.min(males, females); if(infertile > 0) { rate = Math.floor(rate * Math.pow(1.1, infertile)); } if(fertile > 0) { rate = Math.floor(rate * Math.pow(0.9, fertile)); } rate = 600 * Math.floor(1 + (rate / 600 / couples)); return rate; } summarizeAnimals(animalData) { let xp = 0; const animals = []; const loot = {}; const dailyFood = {}; const reproduction = {}; for(const animal of animalData) { xp += animal.xp || 0; if(!animals.includes(animal.animal)) { animals.push(animal.animal); } if(animal.lootItem) { if(animal.lootCount) { loot[animal.lootItem] ??= 0; loot[animal.lootItem] += animal.lootCount; } } if(animal.food && animal.foodPerDay) { dailyFood[animal.food] ??= 0; dailyFood[animal.food] += animal.foodPerDay; } } let result = { xp, animals, loot, dailyFood, reproduction }; for(const animal of animals) { const rate = this.calculateReproductionRate(animalData, animal); result.reproduction[animal] = rate; } // temporary hack until var_ant_capacity_used is fixed let antCount = animalData.filter(animal => animal.animal=="ant").length; window.var_ant_capacity_used = `${antCount}`; return result; } updateAnimalSummary(summary) { if(!summary) { return; } const totalXPElement = document.getElementById("breeding-overhaul-total-xp"); if(totalXPElement) { totalXPElement.innerHTML = `${summary.xp?.toLocaleString(navigator.language)}`; } const dailyFoodElement = document.getElementById("breeding-overhaul-daily-food"); const foodDaysElement = document.getElementById("breeding-overhaul-food-days"); if(dailyFoodElement && summary.dailyFood) { let content = ""; let contentDays = ""; const foodSpans = []; const foodDaysSpans = []; for(const food in summary.dailyFood) { const amount = summary.dailyFood[food]?.toLocaleString(navigator.language); const foodVar = FOOD_MAP[food]; const img = `<img src="${IMAGE_URL}${foodVar}.png" class="inline" />`; let danger = false; let owned = ""; let days = 0; if(foodVar) { owned = IdlePixelPlus.getVarOrDefault(foodVar, 0, "int"); if(owned < amount) { danger = true; } days = amount==0 ? 0 : owned/amount; owned = `/${owned.toLocaleString(navigator.language)}`; } foodSpans.push(`<span class="${danger?'danger':''}" title="${food}: ${amount}/day"> ${img} ${amount}${owned} </span>`); foodDaysSpans.push(`<span class="${danger?'danger':''}" title="${food}: ${days.toFixed(2)} day${days==1?'':'s'}"> ${img} ${days.toFixed(1)} day${days==1?'':'s'} </span>`); } content += foodSpans.join(" "); if(!content) { content = "None"; } if(dailyFoodElement) { dailyFoodElement.innerHTML = content; } contentDays += foodDaysSpans.join(" "); if(!contentDays) { contentDays = "None"; } if(foodDaysElement) { foodDaysElement.innerHTML = contentDays; } } const reproductionElement = document.getElementById("breeding-overhaul-reproduction"); if(reproductionElement && summary.reproduction && summary.animals) { let content = ""; const hornySpans = []; for(const animal of summary.animals) { const img = `<img src="${IMAGE_URL}${animal}_male_1.png" class="inline" />`; let rate = summary.reproduction[animal]; if(Number.isFinite(rate)) { rate = format_time(rate); if(rate < 600) { // animals can reproduce at most once every 10 minutes rate = 600; } rate = rate.replace(/, 0:00$/, ""); } else { rate = "Never"; } hornySpans.push(`<span title="${capitalizeFirstLetter(animal)} Expected Reproduction: ${rate}"> ${img} ${rate} </span>`); } content += hornySpans.join(" "); if(!content) { content = "None"; } reproductionElement.innerHTML = content; } const lootAvailableElement = document.getElementById("breeding-overhaul-loot-available"); if(lootAvailableElement && summary.loot) { let content = ""; const lootSpans = []; for(const loot in summary.loot) { const amount = summary.loot[loot]?.toLocaleString(navigator.language); const img = `<img src="${IMAGE_URL}${loot.toLowerCase()}.png" class="inline" />`; lootSpans.push(`<span title="${loot}: ${amount}"> ${img} ${amount} </span>`); } content += lootSpans.join(" "); let anyLoot = true; if(!content) { content = "None"; anyLoot = false; } lootAvailableElement.innerHTML = content; const lootAllButton = document.getElementById("breeding-overhaul-loot-all"); if(lootAllButton) { lootAllButton.disabled = !anyLoot; } } } clickLootAll() { const animalData = IdlePixelPlus.getVar("animal_data"); if(!animalData) { return; } this.parseAnimals(animalData) .filter(animal => animal.lootCount) .forEach(animal => IdlePixelPlus.sendMessage(`COLLECT_ALL_LOOT_ANIMAL`)); } updateAnimalData(animals) { if(!animals) { return; } const summary = this.summarizeAnimals(animals); this.updateAnimalSummary(summary); } initUI() { const style = document.createElement("style"); style.id = "styles-breeding-overhaul"; style.textContent = ` #panel-breeding #breeding-overhaul-breeding-summary { display: flex; flex-direction: column; } #panel-breeding #breeding-overhaul-breeding-summary .danger { color: red; } #panel-breeding #breeding-overhaul-breeding-summary img.inline { height: 1em; width: auto; } `; document.head.appendChild(style); const panel = document.getElementById("panel-breeding"); if(!panel) { console.error("Breeding Overhaul: Failed to initialize UI - #panel-breeding not found"); return; } const craftableButtons = panel.querySelector(".craftable-btns"); if(craftableButtons) { craftableButtons.insertAdjacentHTML("afterend", ` <div id="breeding-overhaul-breeding-summary"> <div> <strong>Total XP: </strong> <span id="breeding-overhaul-total-xp"></span> </div> <div> <strong>Daily Food: </strong> <span id="breeding-overhaul-daily-food"></span> </div> <div> <strong>Food Days: </strong> <span id="breeding-overhaul-food-days"></span> </div> <div> <strong>Reproduction: </strong> <span id="breeding-overhaul-reproduction"></span> </div> <div> <strong>Loot Available: </strong> <span id="breeding-overhaul-loot-available"></span> </div> <div> <button id="breeding-overhaul-loot-all" type="button" onclick="IdlePixelPlus.plugins.breedingoverhaul.clickLootAll()">Loot All</button> </div> </div> `); } else { console.error("Breeding Overhaul: Failed to fully initialize UI - .craftable-btns not found"); } } onLogin() { // Initialize new ui components this.initUI(); // override refresh function const original_refresh_animals_data = Breeding.refresh_animals_data; Breeding.refresh_animals_data = (...args) => { const animalArea = document.getElementById("breeding-chicken-area"); let raw = args[0] || null; let animals = this.parseAnimals(raw); // rejoin (sorted) for original function if(animals?.length) { raw = animals.map(animal => animal.raw).join("="); } // run original smitty function try { original_refresh_animals_data.apply(this, [raw]); } catch(err) { console.error("Error running original Breeding.refresh_animals_data: ", err); throw err; } // update ui try { this.updateAnimalData(animals); } catch(err) { console.error("Error running BreedingOverhaulPlugin.updateAnimalData: ", err); } } } } const plugin = new BreedingOverhaulPlugin(); IdlePixelPlus.registerPlugin(plugin); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址