Dead Frontier Tooltip DPS Injector

Injects DPS into #infoBox on hover and also into static boxes for exact weapon name matches, caching data in localStorage for 24 hours.

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Dead Frontier Tooltip DPS Injector
// @author       ils94
// @namespace    http://tampermonkey.net/
// @version      1.4
// @description  Injects DPS into #infoBox on hover and also into static boxes for exact weapon name matches, caching data in localStorage for 24 hours.
// @match        https://fairview.deadfrontier.com/onlinezombiemmo/index.php?page=24
// @match        https://fairview.deadfrontier.com/onlinezombiemmo/index.php?page=25
// @match        https://fairview.deadfrontier.com/onlinezombiemmo/index.php?page=28*
// @match        https://fairview.deadfrontier.com/onlinezombiemmo/index.php?page=35
// @match        https://fairview.deadfrontier.com/onlinezombiemmo/index.php?page=50
// @match        https://fairview.deadfrontier.com/onlinezombiemmo/index.php?page=59
// @match        https://fairview.deadfrontier.com/onlinezombiemmo/index.php?page=82*
// @match        https://fairview.deadfrontier.com/onlinezombiemmo/index.php?page=84
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    let dpsData = {};

    function loadDPS() {
        const cacheKey = 'deadFrontierDPSData';
        const timestampKey = 'deadFrontierDPSTimestamp';
        const cacheDuration = 24 * 60 * 60 * 1000;

        const cachedData = localStorage.getItem(cacheKey);
        const cachedTimestamp = localStorage.getItem(timestampKey);

        if (cachedData && cachedTimestamp) {
            const timeElapsed = Date.now() - parseInt(cachedTimestamp, 10);
            if (timeElapsed < cacheDuration) {
                dpsData = JSON.parse(cachedData);
                console.log('[DPS] Loaded', Object.keys(dpsData).length, 'entries from localStorage');
                startWatcher();
                injectDPSIntoStaticBoxes();
                return;
            }
        }

        fetch('https://fairview.deadfrontier.com/onlinezombiemmo/dfdata/damagepersec.php')
            .then(r => r.text())
            .then(text => {
                const regex = /(.+?)\s*:\s*<b>([\d.]+)<\/b>\s*\(<b>([\d.]+)<\/b>\)<br \/>/g;
                let m;
                while ((m = regex.exec(text)) !== null) {
                    const name = m[1].trim();
                    dpsData[name.toLowerCase()] = {
                        name,
                        base: m[2],
                        mod: m[3]
                    };
                }
                localStorage.setItem(cacheKey, JSON.stringify(dpsData));
                localStorage.setItem(timestampKey, Date.now().toString());
                console.log('[DPS] Loaded', Object.keys(dpsData).length, 'entries from server and saved to localStorage');
                startWatcher();
                injectDPSIntoStaticBoxes();
            })
            .catch(err => {
                console.error('[DPS] Failed to load DPS list:', err);
                if (cachedData) {
                    dpsData = JSON.parse(cachedData);
                    console.log('[DPS] Loaded', Object.keys(dpsData).length, 'entries from localStorage (fallback)');
                    startWatcher();
                    injectDPSIntoStaticBoxes();
                }
            });
    }

    function startWatcher() {
        setInterval(() => {
            const box = document.getElementById('infoBox');
            if (!box || box.style.visibility === 'hidden') return;

            const nameEl = box.querySelector('.itemName');
            if (!nameEl) return;

            const weapon = nameEl.textContent.trim();
            const key = weapon.toLowerCase();

            const entry = dpsData[key];
            if (!entry) {
                const old = box.querySelector('.dpsInjected');
                if (old) old.remove();
                const oldDisclaimer = box.querySelector('.dpsDisclaimer');
                if (oldDisclaimer) oldDisclaimer.remove();
                console.log(`[DPS] ✗ ${weapon} (hover, no exact match)`);
                return;
            }

            const old = box.querySelector('.dpsInjected');
            if (old) old.remove();
            const oldDisclaimer = box.querySelector('.dpsDisclaimer');
            if (oldDisclaimer) oldDisclaimer.remove();

            const line = document.createElement('div');
            line.className = 'itemData dpsInjected';
            line.style.color = '#00FF00';
            line.textContent = `DPS: ${entry.base} (Theoretical: ${entry.mod})`;
            box.appendChild(line);

            const disclaimer = document.createElement('div');
            disclaimer.className = 'itemData dpsDisclaimer';
            disclaimer.style.color = '#FFFF00';
            disclaimer.style.fontSize = '0.9em';
            disclaimer.textContent = 'The values may not match what you see in-game.';
            box.appendChild(disclaimer);

            console.log(`[DPS] ✔ ${weapon} (hover)`);
        }, 1000);
    }

    function injectDPSIntoStaticBoxes() {
        const staticBoxes = document.querySelectorAll('.itemName');

        staticBoxes.forEach(nameEl => {
            const parent = nameEl.parentElement;
            if (!parent || parent.querySelector('.dpsInjected')) return;

            const weapon = nameEl.textContent.trim();
            const key = weapon.toLowerCase();

            const entry = dpsData[key];
            if (!entry) {
                console.log(`[DPS] ✗ ${weapon} (static, no exact match)`);
                return;
            }

            const line = document.createElement('div');
            line.className = 'itemData dpsInjected';
            line.style.color = '#00FF00';
            line.textContent = `DPS: ${entry.base} (Theoretical: ${entry.mod})`;
            parent.appendChild(line);

            const disclaimer = document.createElement('div');
            disclaimer.className = 'itemData dpsDisclaimer';
            disclaimer.style.color = '#FFFF00';
            disclaimer.style.fontSize = '0.9em';
            disclaimer.textContent = 'The values may not match what you see in-game.';
            parent.appendChild(disclaimer);

            console.log(`[DPS] ✔ ${weapon} (static)`);
        });
    }

    loadDPS();
})();