// ==UserScript== // @name [Pokechill] 星象系统大改 (修复预览队伍计数) // @namespace http://tampermonkey.net/ // @version 1.0 // @description 星象系统大改,通过修改队伍属性动态调整星象概率。 // @author 人民当家做主 // @match https://play-pokechill.github.io/* // @match https://g1tyx.github.io/play-pokechill/* // @icon https://play-pokechill.github.io/img/icons/icon.png // @grant none // ==/UserScript== (function() { 'use strict'; const scriptContent = ` (function() { 'use strict'; console.log('[星象] 注入脚本执行 (修复预览队伍计数)'); // ---------- 配置 ---------- const ATTRIBUTE_TO_STAR = { 'fire': 'sol', 'fighting': 'sol', 'steel': 'sol', 'water': 'luna', 'ice': 'luna', 'fairy': 'luna', 'ghost': 'pluto', 'dark': 'pluto', 'poison': 'pluto', 'grass': 'ceres', 'ground': 'ceres', 'rock': 'ceres', 'electric': 'terra', 'flying': 'terra', 'bug': 'terra', 'psychic': 'eris', 'dragon': 'eris', 'normal': 'eris' }; const STAR_LIST = ['sol', 'luna', 'pluto', 'ceres', 'terra', 'eris']; const LUCKY_MULTIPLIER = 2; const BASE_RATE = 1 / 4000; const STAR_TO_ATTRIBUTES = {}; for (const [attr, star] of Object.entries(ATTRIBUTE_TO_STAR)) { if (!STAR_TO_ATTRIBUTES[star]) STAR_TO_ATTRIBUTES[star] = []; STAR_TO_ATTRIBUTES[star].push(attr); } // 备用格式化函数 function safeFormat(str) { if (typeof format === 'function') { return format(str); } return str.charAt(0).toUpperCase() + str.slice(1); } // 等待所有游戏对象就绪 function waitForGame() { if (typeof team !== 'undefined' && typeof pkmn !== 'undefined' && typeof saved !== 'undefined' && typeof starsign !== 'undefined') { console.log('[星象] 游戏对象已就绪'); initStarSignSystem(); } else { console.log('[星象] 等待游戏对象...'); setTimeout(waitForGame, 200); } } waitForGame(); // ---------- 核心函数 ---------- function isTeamValid(targetTeam) { if (!targetTeam || typeof targetTeam !== 'object') return false; for (let slot in targetTeam) { if (targetTeam[slot]?.pkmn) return true; } return false; } function getEffectiveTeam() { console.log('[星象] 开始寻找有效队伍...'); if (saved.previewTeams && saved.currentPreviewTeam) { console.log('[星象] saved.previewTeams 存在,当前预览队伍索引:', saved.currentPreviewTeam); const currentPreview = saved.previewTeams[saved.currentPreviewTeam]; if (currentPreview) { console.log('[星象] 当前预览队伍对象:', currentPreview); if (isTeamValid(currentPreview)) { console.log('[星象] 使用当前预览队伍'); return currentPreview; } else { console.log('[星象] 当前预览队伍为空'); } } } if (saved.previewTeams) { for (let key in saved.previewTeams) { const preview = saved.previewTeams[key]; if (isTeamValid(preview)) { console.log('[星象] 使用预览队伍:', key); return preview; } } } for (let i = 1; i <= 6; i++) { const oldKey = 'preview' + i; if (saved[oldKey] && isTeamValid(saved[oldKey])) { console.log('[星象] 使用旧版预览队伍:', oldKey); return saved[oldKey]; } } if (isTeamValid(team)) { console.log('[星象] 使用战斗队伍'); return team; } console.log('[星象] 警告:未找到任何有效队伍'); return null; } // 计算指定队伍中每个星象的属性数量(兼容字符串ID或对象) function calculateStarCountsFromTeam(targetTeam) { const counts = { sol:0, luna:0, pluto:0, ceres:0, terra:0, eris:0 }; if (!targetTeam || typeof targetTeam !== 'object') return counts; for (let slot in targetTeam) { const slotData = targetTeam[slot]; if (!slotData) continue; // 获取宝可梦ID(可能是字符串或对象) let pokemonId = null; if (typeof slotData.pkmn === 'string') { pokemonId = slotData.pkmn; } else if (slotData.pkmn && typeof slotData.pkmn === 'object' && slotData.pkmn.id) { pokemonId = slotData.pkmn.id; } if (!pokemonId) continue; const pkmnData = pkmn[pokemonId]; if (!pkmnData?.type) continue; pkmnData.type.forEach(type => { const star = ATTRIBUTE_TO_STAR[type]; if (star) counts[star]++; }); } return counts; } function calculateBaseWeight(count) { if (count === 0) return 0; return (5/108) * count * count + (7/36) * count; } function calculateStarWeightsFromTeam(targetTeam) { const counts = calculateStarCountsFromTeam(targetTeam); const weights = {}; STAR_LIST.forEach(star => { let weight = calculateBaseWeight(counts[star]); if (star === saved.luckyStarSign) weight *= LUCKY_MULTIPLIER; weights[star] = weight; }); return weights; } function getMillisToNextMidnight() { const now = new Date(); const next = new Date(now); next.setDate(now.getDate() + 1); next.setHours(0, 0, 0, 0); return next - now; } function updateLuckyStar() { saved.luckyStarSign = STAR_LIST[Math.floor(Math.random() * STAR_LIST.length)]; saved.luckyStarLastUpdate = Date.now(); if (typeof saveGame === 'function') saveGame(); console.log('[星象] 幸运星象更新为:', safeFormat(saved.luckyStarSign)); } function checkAndRefreshLuckyStar() { const now = Date.now(); if (!saved.luckyStarLastUpdate) { updateLuckyStar(); return; } const last = new Date(saved.luckyStarLastUpdate); const today = new Date(); if (last.getDate() !== today.getDate() || last.getMonth() !== today.getMonth() || last.getFullYear() !== today.getFullYear()) { updateLuckyStar(); } } function scheduleMidnightUpdate() { const ms = getMillisToNextMidnight(); setTimeout(() => { updateLuckyStar(); scheduleMidnightUpdate(); }, ms); } // ---------- UI ---------- function createStarSignDisplay() { const menuParent = document.getElementById('menu-button-parent'); if (!menuParent) { setTimeout(createStarSignDisplay, 500); return; } if (document.getElementById('star-sign-display')) return; console.log('[星象] 找到主菜单容器,插入悬浮框'); const display = document.createElement('div'); display.id = 'star-sign-display'; display.style.cssText = 'position: absolute; top: 0.5rem; left: 50%; transform: translateX(-50%); display: flex; flex-direction: column; align-items: center; justify-content: center; background: rgba(10, 15, 30, 0.85); backdrop-filter: blur(4px); border: 1.5px solid #4a7ab0; border-radius: 2rem; padding: 0.2rem 1rem; cursor: pointer; font-size: 0.9rem; color: white; text-shadow: 0 0 8px #7ab0ff, 0 0 12px #2a5a9a; box-shadow: 0 0 20px rgba(74, 122, 176, 0.6); z-index: 1000; transition: all 0.3s ease;'; display.addEventListener('mouseenter', () => { display.style.transform = 'scale(1.05)'; display.style.boxShadow = '0 0 30px rgba(100, 180, 255, 0.9)'; }); display.addEventListener('mouseleave', () => { display.style.transform = 'scale(1)'; display.style.boxShadow = '0 0 20px rgba(74, 122, 176, 0.6)'; }); const luckyStar = saved.luckyStarSign || 'sol'; const hue = starsign[luckyStar]?.hue || 0; const row = document.createElement('div'); row.style.cssText = 'display: flex; align-items: center; gap: 0.3rem; margin-bottom: 0.1rem;'; const nameSpan = document.createElement('span'); nameSpan.id = 'lucky-star-name'; nameSpan.style.fontSize = '0.9rem'; nameSpan.style.fontWeight = 'bold'; nameSpan.textContent = safeFormat(luckyStar); const iconSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); iconSvg.setAttribute('width', '16'); iconSvg.setAttribute('height', '16'); iconSvg.setAttribute('viewBox', '0 0 24 24'); iconSvg.style.color = 'white'; iconSvg.style.filter = 'hue-rotate(' + hue + 'deg)'; const path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); path.setAttribute('fill', 'currentColor'); path.setAttribute('d', 'M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z'); iconSvg.appendChild(path); row.appendChild(nameSpan); row.appendChild(iconSvg); const timer = document.createElement('div'); timer.id = 'lucky-star-timer'; timer.style.cssText = 'font-size: 0.8rem; text-align: center; width: 100%; text-shadow: 0 0 5px cyan;'; timer.textContent = '00:00:00'; display.appendChild(row); display.appendChild(timer); menuParent.appendChild(display); display.addEventListener('click', showProbabilityTooltip); } function updateStarSignDisplay() { const nameSpan = document.getElementById('lucky-star-name'); const timerSpan = document.getElementById('lucky-star-timer'); if (!nameSpan || !timerSpan) return; const luckyStar = saved.luckyStarSign || 'sol'; nameSpan.textContent = safeFormat(luckyStar); const svg = document.querySelector('#star-sign-display svg'); if (svg) { const hue = starsign[luckyStar]?.hue || 0; svg.style.filter = 'hue-rotate(' + hue + 'deg)'; } const ms = getMillisToNextMidnight(); const hours = Math.floor(ms / 3600000); const minutes = Math.floor((ms % 3600000) / 60000); const seconds = Math.floor((ms % 60000) / 1000); timerSpan.textContent = hours.toString().padStart(2,'0') + ':' + minutes.toString().padStart(2,'0') + ':' + seconds.toString().padStart(2,'0'); } // ---------- 详细概率显示 ---------- function showProbabilityTooltip() { const effectiveTeam = getEffectiveTeam(); console.log('[星象] showProbabilityTooltip: 有效队伍 =', effectiveTeam); let counts, weights; let noTeamMessage = ''; if (effectiveTeam) { counts = calculateStarCountsFromTeam(effectiveTeam); weights = calculateStarWeightsFromTeam(effectiveTeam); console.log('[星象] counts =', counts); console.log('[星象] weights =', weights); } else { counts = { sol:0, luna:0, pluto:0, ceres:0, terra:0, eris:0 }; weights = { sol:0, luna:0, pluto:0, ceres:0, terra:0, eris:0 }; noTeamMessage = '
| 星象 | 包含属性 | 数量 | 基础权重 | 最终权重 | 实际概率 |
|---|---|---|---|---|---|
| ' + starName + ' | '; content += '' + attrNames + ' | '; content += '' + count + ' | '; content += '' + baseWeight.toFixed(3) + ' | '; content += '' + finalWeight.toFixed(3) + ' | '; content += '' + actualProb + ' | '; content += '