// ==UserScript==
// @name 宝可梦挂机游戏 - 进化条件显示增强版
// @namespace https://github.com/jinwind1/pokemon-idle
// @version 2.0.0
// @description 显示详细进化条件:进化后种族值、属性、地区解锁要求及进化链
// @author 人民当家做主
// @match https://jinwind1.github.io/pokemon-idle/
// @match https://jinwind1.github.io/pokemon-idle/*
// @grant GM_addStyle
// @run-at document-start
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// 添加样式
GM_addStyle(`
.dex-evolution-section {
margin-top: 10px;
padding: 8px 10px;
background: rgba(0, 0, 0, 0.25);
border-radius: 8px;
font-size: 11px;
border-left: 3px solid #f39c12;
}
.dex-evolution-title {
font-weight: bold;
color: #f39c12;
margin-bottom: 6px;
display: flex;
align-items: center;
gap: 6px;
}
.dex-evolution-chain {
margin-bottom: 6px;
font-size: 10px;
color: var(--text-secondary);
background: rgba(0,0,0,0.2);
padding: 4px 6px;
border-radius: 4px;
}
.dex-evolution-item {
margin-bottom: 8px;
border-bottom: 1px dashed rgba(255,255,255,0.1);
padding-bottom: 6px;
}
.dex-evolution-item:last-child {
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}
.evo-target-name {
font-weight: bold;
color: #2ecc71;
}
.evo-details {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 4px;
margin-left: 12px;
}
.evo-detail {
background: rgba(0,0,0,0.2);
padding: 2px 6px;
border-radius: 4px;
font-size: 10px;
}
.evo-detail span {
color: #f1c40f;
}
.region-lock {
color: #e74c3c;
font-size: 10px;
}
.team-evolution-info {
font-size: 9px;
color: #f39c12;
background: rgba(243, 156, 18, 0.15);
border-radius: 4px;
padding: 1px 5px;
margin-left: 6px;
white-space: nowrap;
display: inline-block;
vertical-align: middle;
cursor: help;
}
`);
// 获取宝可梦的种族值总和
function getBaseStatTotal(pokemonId) {
const data = POKEMON_DATA[pokemonId];
if (!data) return 0;
const bs = data.baseStats;
return bs.hp + bs.atk + bs.def + bs.spAtk + bs.spDef + bs.speed;
}
// 获取宝可梦的属性类型文字
function getTypeNames(pokemonId) {
const data = POKEMON_DATA[pokemonId];
if (!data) return '';
return data.types.map(t => TYPE_NAMES[t] || t).join('/');
}
// 判断进化目标是否需要解锁地区(跨代进化)
function getRegionRequirement(evoId) {
if (evoId >= 152 && evoId <= 251) return '城都地区';
if (evoId >= 252 && evoId <= 386) return '丰缘地区';
if (evoId >= 387 && evoId <= 493) return '神奥地区';
if (evoId >= 494 && evoId <= 649) return '合众地区';
if (evoId >= 650 && evoId <= 721) return '卡洛斯地区';
if (evoId >= 722 && evoId <= 809) return '阿罗拉地区';
if (evoId >= 810 && evoId <= 905) return '伽勒尔地区';
if (evoId >= 906 && evoId <= 1025) return '帕底亚地区';
return null;
}
// 获取进化链(从当前宝可梦开始,一直追溯到最终形态)
function getEvolutionChain(pokemonId, maxDepth = 5) {
const chain = [{ id: pokemonId, name: POKEMON_DATA[pokemonId]?.name || `#${pokemonId}` }];
let current = pokemonId;
for (let i = 0; i < maxDepth; i++) {
const data = POKEMON_DATA[current];
if (!data || !data.evolvesTo) break;
const evos = Array.isArray(data.evolvesTo) ? data.evolvesTo : [data.evolvesTo];
if (evos.length === 0) break;
// 取第一个进化目标(简化显示主链)
const next = evos[0];
chain.push({ id: next.id, name: POKEMON_DATA[next.id]?.name || `#${next.id}`, level: next.level });
current = next.id;
}
return chain;
}
// 生成进化链文字
function formatEvolutionChain(chain) {
if (chain.length <= 1) return '最终形态';
return chain.map((item, idx) => {
if (idx === 0) return item.name;
return `${item.name} (Lv.${item.level})`;
}).join(' → ');
}
// 获取进化条件HTML(增强版)
function getEnhancedEvolutionHtml(pokemonId) {
const data = POKEMON_DATA[pokemonId];
if (!data) return '';
const evolvesTo = data.evolvesTo;
if (!evolvesTo || (Array.isArray(evolvesTo) && evolvesTo.length === 0)) {
// 最终形态,显示进化链回溯
const chain = getEvolutionChain(pokemonId);
if (chain.length > 1) {
return `
🌱 进化路径
${formatEvolutionChain(chain)}
✨ 最终形态,无法继续进化
`;
}
return '';
}
const evoList = Array.isArray(evolvesTo) ? evolvesTo : [evolvesTo];
let itemsHtml = '';
for (const evo of evoList) {
const targetId = evo.id;
const targetName = POKEMON_DATA[targetId]?.name || `#${targetId}`;
const targetTotal = getBaseStatTotal(targetId);
const currentTotal = getBaseStatTotal(pokemonId);
const statChange = targetTotal - currentTotal;
const statChangeText = statChange > 0 ? `+${statChange}` : `${statChange}`;
const targetTypes = getTypeNames(targetId);
const currentTypes = getTypeNames(pokemonId);
const typeChange = (currentTypes !== targetTypes) ? ` → ${targetTypes}` : '';
const regionReq = getRegionRequirement(targetId);
const regionHtml = regionReq ? `🔒 需要解锁: ${regionReq}
` : '';
itemsHtml += `
➜ Lv.${evo.level} 进化成 ${targetName}
📊 种族值: ${currentTotal} → ${targetTotal} (${statChangeText})
🎭 属性: ${currentTypes}${typeChange}
${regionHtml}
`;
}
// 显示完整进化链(可选)
const chain = getEvolutionChain(pokemonId);
const chainHtml = chain.length > 1 ? `📈 进化链: ${formatEvolutionChain(chain)}
` : '';
return `
🌱 进化条件
${chainHtml}
${itemsHtml}
`;
}
// 队伍卡片徽章(保持简洁,悬浮显示更多)
function getEnhancedTeamBadge(pokemonId) {
const data = POKEMON_DATA[pokemonId];
if (!data) return '';
const evolvesTo = data.evolvesTo;
if (!evolvesTo || (Array.isArray(evolvesTo) && evolvesTo.length === 0)) return '';
const evoList = Array.isArray(evolvesTo) ? evolvesTo : [evolvesTo];
let minLevel = Infinity;
let targetName = '';
for (const evo of evoList) {
if (evo.level < minLevel) {
minLevel = evo.level;
targetName = POKEMON_DATA[evo.id]?.name || `#${evo.id}`;
}
}
if (minLevel === Infinity) return '';
// 悬浮显示更详细信息
const targetTotal = getBaseStatTotal(evoList[0].id);
const currentTotal = getBaseStatTotal(pokemonId);
const statChange = targetTotal - currentTotal;
const tooltip = `Lv.${minLevel} → ${targetName} | 种族值 ${currentTotal} → ${targetTotal} (${statChange>0?'+':''}${statChange})`;
return `🌱 Lv.${minLevel}`;
}
// 劫持图鉴渲染方法
const originalRenderBatch = GameUI.prototype._renderPokedexBatch;
if (originalRenderBatch) {
GameUI.prototype._renderPokedexBatch = function(grid, count) {
originalRenderBatch.call(this, grid, count);
const newCards = grid.querySelectorAll('.pokedex-entry:not([data-evo-injected])');
newCards.forEach(card => {
const pokemonId = card.dataset.pokemonId;
if (pokemonId) {
const detailDiv = card.querySelector('.dex-detail');
if (detailDiv) {
const evoHtml = getEnhancedEvolutionHtml(parseInt(pokemonId));
if (evoHtml) {
detailDiv.insertAdjacentHTML('beforeend', evoHtml);
}
}
}
card.setAttribute('data-evo-injected', 'true');
});
};
} else {
// 降级:MutationObserver
const observer = new MutationObserver(() => {
document.querySelectorAll('.pokedex-entry:not([data-evo-injected])').forEach(card => {
const pokemonId = card.dataset.pokemonId;
if (pokemonId) {
const detailDiv = card.querySelector('.dex-detail');
if (detailDiv) {
const evoHtml = getEnhancedEvolutionHtml(parseInt(pokemonId));
if (evoHtml) {
detailDiv.insertAdjacentHTML('beforeend', evoHtml);
}
}
}
card.setAttribute('data-evo-injected', 'true');
});
});
observer.observe(document.getElementById('pokedex-grid'), { childList: true, subtree: true });
}
// 劫持队伍渲染
const originalRenderTeam = GameUI.prototype.renderTeam;
GameUI.prototype.renderTeam = function() {
originalRenderTeam.call(this);
const team = this.game.gameState.team;
const slots = document.querySelectorAll('.team-slot');
for (let i = 0; i < slots.length && i < team.length; i++) {
const pokemonId = team[i];
const badge = getEnhancedTeamBadge(pokemonId);
if (!badge) continue;
const slotNameDiv = slots[i].querySelector('.slot-name');
if (slotNameDiv && !slotNameDiv.querySelector('.team-evolution-info')) {
slotNameDiv.insertAdjacentHTML('beforeend', badge);
}
}
};
// 初始执行
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
setTimeout(() => {
if (window.gameUI) {
window.gameUI.renderTeam();
document.querySelectorAll('.pokedex-entry').forEach(card => {
if (!card.hasAttribute('data-evo-injected')) {
const pokemonId = card.dataset.pokemonId;
if (pokemonId) {
const detailDiv = card.querySelector('.dex-detail');
if (detailDiv) {
const evoHtml = getEnhancedEvolutionHtml(parseInt(pokemonId));
if (evoHtml) {
detailDiv.insertAdjacentHTML('beforeend', evoHtml);
}
}
}
card.setAttribute('data-evo-injected', 'true');
}
});
}
}, 1000);
});
} else {
setTimeout(() => {
if (window.gameUI) {
window.gameUI.renderTeam();
document.querySelectorAll('.pokedex-entry').forEach(card => {
if (!card.hasAttribute('data-evo-injected')) {
const pokemonId = card.dataset.pokemonId;
if (pokemonId) {
const detailDiv = card.querySelector('.dex-detail');
if (detailDiv) {
const evoHtml = getEnhancedEvolutionHtml(parseInt(pokemonId));
if (evoHtml) {
detailDiv.insertAdjacentHTML('beforeend', evoHtml);
}
}
}
card.setAttribute('data-evo-injected', 'true');
}
});
}
}, 1000);
}
})();