// ==UserScript==
// @name DaoVerse Hero Analysis
// @namespace http://tampermonkey.net/
// @version 1.5
// @description Enhanced hero battle power calculator for DaoVerse with display controls
// @author You
// @match https://www.daoverse.pro/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=daoverse.pro
// @grant none
// ==/UserScript==
(function () {
'use strict';
// 职业属性权重配置
const jobs = {
"道士": { main: "悟性", sub: "神識", weights: { main: 1, sub: 0.8 } },
"遊俠": { main: "真氣", sub: "身法", weights: { main: 1, sub: 0.8 } },
"影修": { main: "身法", sub: "真氣", weights: { main: 1, sub: 0.8 } },
"劍修": { main: "真氣", sub: "根骨", weights: { main: 1, sub: 0.8 } },
};
// 线性回归模型参数
const slope = 0.00119457551417354;
const intercept = 0.010624752368260049;
// 样式配置
const STYLES = {
container: `
margin-top:15px;
padding: 6px;
background: rgba(0, 0, 0, 0.7);
border-radius: 4px;
font-size: 16px;
line-height: 1.4;
color: #ffd700;
font-weight: bold;
border: 1px solid #444;
`,
mainValue: `color: #4caf50;`,
subInfo: `font-size: 16px; opacity: 0.9;`,
highlightValue: `color: #ff9800; font-weight: bold;`,
// 完整的简约模式CSS
minimalModeCSS: `
/* 简约模式全局样式 */
.MarketHeroCard_professionImageContainer__V39vZ,
.MarketHeroCard_marketInfo__3aE13,
.MarketHeroCard_attributesSection__b2BgP {
display: none !important;
}
.css-1ylolxj, .MarketHeroCard_header__wL9We {
display: none !important;
}
.MarketHeroCard_card__deSlg {
height: auto !important;
min-height: 100px !important;
}
.HeroMarketTab_heroesGrid__zX4bE {
grid-template-columns: repeat(auto-fill, minmax(229px, 1fr)) !important;
}
.page_contentWrapper__obfCi {
max-width: 100% !important;
}
.MarketHeroCard_professionHeader__3CH84 {
position: absolute;
top: 0;
left: 10px;
}
.MarketHeroCard_professionDetails__xMfae {
position: absolute;
top: 0;
right: 10px;
}
.MarketHeroCard_priceSection__Ki20g {
padding: 0 12px !important;
}
.MarketHeroCard_priceLabel___DZ5U {
display: none !important;
}
`,
// 控制按钮样式
controlButton: `
background: #2c3e50;
color: #ecf0f1;
border: none;
border-radius: 4px;
padding: 8px 12px;
font-size: 12px;
cursor: pointer;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
transition: all 0.3s ease;
margin-bottom: 5px;
width: 120px;
text-align: center;
`,
activeButton: `background: #27ae60;`,
inactiveButton: `background: #e74c3c;`
};
// 显示状态设置
const displaySettings = {
showPower: true,
showAttributes: true,
showWinRate: true
};
// 从本地存储加载设置
function loadSettings() {
const savedSettings = localStorage.getItem('heroAnalysisSettings');
if (savedSettings) {
Object.assign(displaySettings, JSON.parse(savedSettings));
}
}
// 保存设置到本地存储
function saveSettings() {
localStorage.setItem('heroAnalysisSettings', JSON.stringify(displaySettings));
}
// =============== 控制面板 ===============
function createControlPanel() {
// 移除旧的控制面板(如果存在)
const oldPanel = document.getElementById('analysis-control-panel');
if (oldPanel) oldPanel.remove();
// 创建控制面板容器
const controlPanel = document.createElement('div');
controlPanel.id = 'analysis-control-panel';
controlPanel.style.cssText = `
position: fixed;
top: 10px;
left: 10px;
z-index: 10000;
display: flex;
flex-direction: column;
gap: 5px;
background: rgba(0, 0, 0, 0.8);
padding: 10px;
border-radius: 8px;
border: 1px solid #444;
box-shadow: 0 0 10px rgba(0,0,0,0.5);
`;
// 面板标题
const title = document.createElement('div');
title.textContent = '显示控制';
title.style.cssText = `
color: #ffd700;
font-weight: bold;
text-align: center;
margin-bottom: 5px;
border-bottom: 1px solid #444;
padding-bottom: 5px;
`;
controlPanel.appendChild(title);
// 创建控制按钮
const createButton = (text, settingKey) => {
const button = document.createElement('button');
button.textContent = text + (displaySettings[settingKey] ? ': 显示' : ': 隐藏');
button.style.cssText = STYLES.controlButton;
button.style.background = displaySettings[settingKey] ?
STYLES.activeButton : STYLES.inactiveButton;
button.addEventListener('click', () => {
displaySettings[settingKey] = !displaySettings[settingKey];
button.textContent = text + (displaySettings[settingKey] ? ': 显示' : ': 隐藏');
button.style.background = displaySettings[settingKey] ?
STYLES.activeButton : STYLES.inactiveButton;
saveSettings();
updateAllDisplays();
});
return button;
};
// 添加控制按钮
controlPanel.appendChild(createButton('战力', 'showPower'));
controlPanel.appendChild(createButton('总属性', 'showAttributes'));
controlPanel.appendChild(createButton('胜率', 'showWinRate'));
// 简约模式按钮
const minimalToggle = document.createElement('button');
minimalToggle.textContent = '简约模式: ' + (document.getElementById('minimal-mode-style')?.textContent ? '开启' : '关闭');
minimalToggle.style.cssText = STYLES.controlButton;
minimalToggle.style.background = document.getElementById('minimal-mode-style')?.textContent ?
STYLES.activeButton : STYLES.controlButton;
minimalToggle.addEventListener('click', () => {
const styleTag = document.getElementById('minimal-mode-style');
if (!styleTag) return;
const isEnabled = !!styleTag.textContent;
minimalToggle.textContent = '简约模式: ' + (isEnabled ? '关闭' : '开启');
minimalToggle.style.background = isEnabled ?
STYLES.controlButton : STYLES.activeButton;
styleTag.textContent = isEnabled ? '' : STYLES.minimalModeCSS;
});
controlPanel.appendChild(minimalToggle);
// 添加到文档
document.body.appendChild(controlPanel);
}
// =============== 核心函数 ===============
// 属性提取
function extractAttributes(container, selector) {
const attributes = {};
container.querySelectorAll(selector).forEach(attr => {
const text = attr.innerText.trim();
const colonIndex = text.indexOf(':');
if (colonIndex !== -1) {
const attrName = text.substring(0, colonIndex).trim();
const attrValue = parseInt(text.substring(colonIndex + 1).trim());
if (!isNaN(attrValue)) attributes[attrName] = attrValue;
}
});
return attributes;
}
// 战力计算(包含4级/5级胜率计算)
function computeBattlePower(professionName, attributes, level) {
if (!jobs[professionName]) return null;
const { main, sub, weights } = jobs[professionName];
const mainValue = attributes[main] || 0;
const subValue = attributes[sub] || 0;
const totalAttributes = Object.values(attributes).reduce((sum, val) => sum + val, 0);
const otherAttributes = Object.keys(attributes).reduce((sum, key) => {
return (key !== main && key !== sub) ? sum + (attributes[key] || 0) : sum;
}, 0);
// 基础战力计算(不含等级加成)
const basePower = mainValue * weights.main + subValue * weights.sub + otherAttributes * 0.4;
// 当前等级战力
const currentBattlePower = Math.round(basePower * (1 + level / 5));
// 计算各级胜率
const winRate = (slope * currentBattlePower + intercept) * 100;
const level4WinRate = (slope * (basePower * (1 + 4 / 5)) + intercept) * 100;
const level5WinRate = (slope * (basePower * (1 + 5 / 5)) + intercept) * 100;
return {
battlePower: currentBattlePower,
winRate: winRate.toFixed(2),
level4WinRate: level4WinRate.toFixed(2),
level5WinRate: level5WinRate.toFixed(2),
mainValue,
subValue,
otherValue: otherAttributes,
totalAttributes
};
}
// 创建战力显示元素(包含4级/5级胜率)
function createBattlePowerElement(results) {
const container = document.createElement('div');
container.className = 'battle-power-container';
container.style.cssText = STYLES.container;
// 根据设置决定显示内容
container.innerHTML = `
${displaySettings.showPower ? `<div>战力: <span style="${STYLES.mainValue}">${results.battlePower}</span></div>` : ''}
${displaySettings.showAttributes ? `<div>总属性: <span style="${STYLES.highlightValue}">${results.totalAttributes}</span></div>` : ''}
${displaySettings.showWinRate ? `
<div>胜率: ${results.winRate}%</div>
<div style="${STYLES.subInfo}">
4级: ${results.level4WinRate}% | 5级: ${results.level5WinRate}%
</div>
` : ''}
`;
return container;
}
// 更新所有显示
function updateAllDisplays() {
// 移除所有现有的战力容器
document.querySelectorAll('.battle-power-container').forEach(el => el.remove());
// 重新处理所有卡片
processAllCards();
}
// 处理质押卡片
function processStakingCard(card) {
const profession = card.querySelector('.StakingHeroItem_professionName__c7Pl1')?.innerText || '未知职业';
const levelText = card.querySelector('.StakingHeroItem_heroLevel__IBTd0')?.innerText || '等级 0';
const level = parseInt(levelText.replace('等級 ', '')) || 0;
const attributes = extractAttributes(card, '.StakingHeroItem_attributeChip__lEVuu .MuiChip-label');
const results = computeBattlePower(profession, attributes, level);
if (!results) return;
const battlePowerElem = createBattlePowerElement(results);
const rewardInfo = card.querySelector('.StakingHeroItem_rewardInfo__AcbGD');
if (rewardInfo) {
rewardInfo.parentNode.insertBefore(battlePowerElem, rewardInfo.nextSibling);
} else {
card.appendChild(battlePowerElem);
}
}
// 处理市场卡片
function processMarketCard(card) {
const professionElement = card.querySelector('.MarketHeroCard_professionName__TodRS');
const levelElement = card.querySelector('.MarketHeroCard_professionDetails__xMfae');
if (!professionElement || !levelElement) return;
const professionName = professionElement.innerText;
const levelText = levelElement.innerText;
const levelMatch = levelText.match(/等級 (\d+)/);
const level = levelMatch ? parseInt(levelMatch[1]) : 0;
const attributes = extractAttributes(card, '.MuiChip-label');
const results = computeBattlePower(professionName, attributes, level);
if (!results) return;
const battlePowerContainer = createBattlePowerElement(results);
const breedingChip = card.querySelector('.MuiChip-root.MuiChip-filled.MuiChip-colorSuccess');
if (breedingChip) {
breedingChip.parentNode.insertBefore(battlePowerContainer, breedingChip.nextSibling);
} else {
card.appendChild(battlePowerContainer);
}
}
// 处理我的英雄卡片
function processMyCard(card) {
//职业
const professionElement = card.querySelector('.HeroCard_professionName__7Pzm3');
//等级
const levelElement = card.querySelector('.HeroCard_professionDetails__wj_jr');
if (!professionElement || !levelElement) return;
const professionName = professionElement.innerText;
const levelText = levelElement.innerText;
const levelMatch = levelText.match(/等級 (\d+)/);
const level = levelMatch ? parseInt(levelMatch[1]) : 0;
const attributes = extractAttributes(card, '.MuiChip-label');
const results = computeBattlePower(professionName, attributes, level);
if (!results) return;
const battlePowerContainer = createBattlePowerElement(results);
const breedingChip = card.querySelector('.MuiChip-root.MuiChip-filled.MuiChip-colorSuccess');
if (breedingChip) {
breedingChip.parentNode.insertBefore(battlePowerContainer, breedingChip.nextSibling);
} else {
card.appendChild(battlePowerContainer);
}
}
// 主处理函数
function processAllCards() {
// 移除所有现有战力元素
document.querySelectorAll('.battle-power-container').forEach(el => el.remove());
// 处理质押卡片
document.querySelectorAll('.StakingHeroItem_heroCard__1DH_W').forEach(processStakingCard);
// 处理市场卡片
document.querySelectorAll('.MarketHeroCard_cardContent__n4KNW').forEach(processMarketCard);
//处理我的英雄
document.querySelectorAll('.HeroCard_cardContent__jju_k').forEach(processMyCard);
}
// 初始化
function init() {
// 加载设置
loadSettings();
// 初始化简约模式样式
if (!document.getElementById('minimal-mode-style')) {
const styleTag = document.createElement('style');
styleTag.id = 'minimal-mode-style';
document.head.appendChild(styleTag);
}
// 创建控制面板
createControlPanel();
// 执行主处理
processAllCards();
// 使用定时器定期刷新
setInterval(processAllCards, 3000);
}
// 启动脚本
init();
})();