// ==UserScript== // @name [银河奶牛]DPS显示 // @namespace destiny // @version 0.11 // @description 显示DPS,魔改自ponchain Ched佬的代码 // @author Truth_Light // @match https://www.milkywayidle.com/* // @grant none // @license Ched // @require https://cdn.jsdelivr.net/npm/chart.js@3.7.0/dist/chart.min.js // @require https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.0.0/dist/chartjs-plugin-datalabels.min.js // @note 本脚本基于ponchain Ched的代码进行修改,由Truth_Light进一步完善。 // @downloadURL none // ==/UserScript== (function () { "use strict"; // 代理 WebSocket const OriginalWebSocket = window.WebSocket; const handlerQueue = []; function MyWebSocket(url, protocols) { const ws = new OriginalWebSocket(url, protocols); ws.addEventListener("message", function (event) { const msgData = JSON.parse(event.data); handlerQueue.reduce((prev, handler) => { return handler(prev); }, msgData); }); return ws; } window.WebSocket = MyWebSocket; let totalDamage = []; let totalDuration = 0; let startTime = null; let endTime = null; let monstersHP = []; let players = []; const updatePlayerDPS = () => { const totalTime = totalDuration + ((endTime - startTime) / 1000); // 总时间,秒 const dps = totalDamage.map((damage) => (totalTime ? Math.round(damage / totalTime) : 0)); const playersContainer = document.querySelector('.BattlePanel_combatUnitGrid__2hTAM'); if (playersContainer) { players.forEach((player, index) => { const playerElement = playersContainer.children[index]; if (playerElement) { const statusElement = playerElement.querySelector('.CombatUnit_status__3bH7W'); if (statusElement) { let dpsElement = statusElement.querySelector('.dps-info'); if (!dpsElement) { dpsElement = document.createElement('div'); dpsElement.className = 'dps-info'; statusElement.appendChild(dpsElement); } dpsElement.textContent = `DPS: ${dps[index].toLocaleString()}`; playerElement.title = `总伤害: ${totalDamage[index].toLocaleString()}`; } } }); } }; const calculateDamage = (msgData) => { if (msgData.type === "new_battle") { if (startTime && endTime) { totalDuration += (endTime - startTime) / 1000; } startTime = Date.now(); endTime = null; monstersHP = msgData.monsters.map((monster) => monster.currentHitpoints); players = msgData.players; if (!totalDamage.length) { totalDamage = new Array(players.length).fill(0); } } else if (msgData.type === "battle_updated" && monstersHP.length) { const mMap = msgData.mMap; monstersHP.forEach((mHP, mIndex) => { const monster = mMap[mIndex]; if (monster) { const playerIndices = Object.keys(msgData.pMap); playerIndices.forEach((userIndex) => { const hpDiff = mHP - monster.cHP; if (hpDiff > 0) { totalDamage[userIndex] += hpDiff; } }); monstersHP[mIndex] = monster.cHP; } }); endTime = Date.now(); updatePlayerDPS(); } else if (msgData.type === "actions_updated") { monstersHP = []; startTime = null; endTime = null; } }; handlerQueue.push(calculateDamage); })();