工匠放置小工具之1:事件提醒

工匠提醒 + 下一个事件

目前為 2025-09-10 提交的版本,檢視 最新版本

// ==UserScript==
// @name         工匠放置小工具之1:事件提醒
// @namespace    http://tampermonkey.net/
// @version      1.07
// @description  工匠提醒 + 下一个事件
// @author       Stella
// @match        https://idleartisan.com/*
// @grant        GM_getValue
// @grant        GM_setValue
// @license      CC-BY-NC-SA-4.0
// ==/UserScript==

(function() {
    'use strict';

    const COOLDOWN = 30 * 1000; // 30秒全局冷却
    let cooldownUntil = 0;

    // 默认配置
    const defaultConfig = {
        CB: true,       // Crafting Bonus
        Siege: true,    // Siege
        TS: true,       // Trade Ship
        M: true,        // Merchant
        GLOBAL: true,   // 全局开关
        IDLE: false     // 摸鱼模式
    };

    const config = {
        CB: GM_getValue('CB', defaultConfig.CB),
        Siege: GM_getValue('Siege', defaultConfig.Siege),
        TS: GM_getValue('TS', defaultConfig.TS),
        M: GM_getValue('M', defaultConfig.M),
        GLOBAL: GM_getValue('GLOBAL', defaultConfig.GLOBAL),
        IDLE: GM_getValue('IDLE', defaultConfig.IDLE)
    };

    // ========== 中英文事件映射表 ==========
    const eventDict = {
        "Mining Bonus": "采矿加成",
        "Woodcutting Bonus": "伐木加成",
        "Thief": "盗贼",
        "Battling Bonus": "战斗加成",
        "Crafting Bonus": "制作加成",
        "Merchant": "商人",
        "Purchasing Agent": "采购代理",
        "Tax Season": "税收季节",
        "Distant war drums": "遥远的战鼓",
        "Goblin Siege": "哥布林围攻",
        "Boss Fight": "Boss对抗",
        "Ancient Treant": "远古树人",
        "Runic Golem": "符文魔像",
        "Trade ship": "贸易船"
    };

    // 事件顺序(英文作为基准)
    const eventOrder = [
        "Mining Bonus",
        "Woodcutting Bonus",
        "Thief",
        "Battling Bonus",
        "Crafting Bonus",
        "Merchant",
        "Purchasing Agent",
        "Tax Season",
        "Distant war drums",
        "Goblin Siege",
        "Boss Fight",
        "Ancient Treant",
        "Runic Golem",
        "Trade ship"
    ];

    // 判断当前语言模式 (en / zh)
    function getLangMode(currentText) {
        const asciiOnly = /^[\x00-\x7F]*$/; // 纯ASCII认为是英文
        return asciiOnly.test(currentText) ? "en" : "zh";
    }

    // 根据语言返回正确事件名
    function getEventName(enName, lang) {
        if (lang === "en") return enName;
        return eventDict[enName] || enName;
    }

    // ========== UI面板 ==========
    const panel = document.createElement('div');
    panel.style.position = 'fixed';
    panel.style.bottom = '20px';
    panel.style.right = '20px';
    panel.style.background = 'rgba(0,0,0,0.8)';
    panel.style.color = 'white';
    panel.style.padding = '12px';
    panel.style.borderRadius = '10px';
    panel.style.zIndex = 9999;
    panel.style.fontFamily = 'sans-serif';
    panel.style.fontSize = '14px';
    panel.style.boxShadow = '0 4px 12px rgba(0,0,0,0.5)';

    function createSwitch(labelText, key) {
        const container = document.createElement('div');
        container.style.marginBottom = '8px';
        container.style.display = 'flex';
        container.style.alignItems = 'center';
        container.style.justifyContent = 'space-between';

        const label = document.createElement('span');
        label.textContent = labelText;

        const switchContainer = document.createElement('div');
        switchContainer.style.width = '50px';
        switchContainer.style.height = '24px';
        switchContainer.style.background = config[key] ? '#4caf50' : '#ccc';
        switchContainer.style.borderRadius = '12px';
        switchContainer.style.position = 'relative';
        switchContainer.style.cursor = 'pointer';
        switchContainer.style.transition = 'background 0.3s';

        const knob = document.createElement('div');
        knob.style.width = '20px';
        knob.style.height = '20px';
        knob.style.background = '#fff';
        knob.style.borderRadius = '50%';
        knob.style.position = 'absolute';
        knob.style.top = '2px';
        knob.style.left = config[key] ? '28px' : '2px';
        knob.style.transition = 'left 0.3s';

        switchContainer.appendChild(knob);
        switchContainer.addEventListener('click', () => {
            config[key] = !config[key];
            GM_setValue(key, config[key]);
            switchContainer.style.background = config[key] ? '#4caf50' : '#ccc';
            knob.style.left = config[key] ? '28px' : '2px';
        });

        container.appendChild(label);
        container.appendChild(switchContainer);
        panel.appendChild(container);
    }

    // 开关顺序
    createSwitch('制作提醒', 'CB');
    createSwitch('围攻提醒', 'Siege');
    createSwitch('商船提醒', 'TS');
    createSwitch('商人提醒', 'M');
    panel.appendChild(document.createElement('hr')); // 分隔线
    createSwitch('全局开关', 'GLOBAL');
    createSwitch('摸鱼模式', 'IDLE');

    document.body.appendChild(panel);

    // 请求通知权限
    if (Notification.permission !== "granted") {
        Notification.requestPermission();
    }

    // 定时检测提醒
    setInterval(() => {
        if (!config.GLOBAL) return;

        const now = Date.now();
        if (now < cooldownUntil) return;

        const title = document.title.trim();
        let notified = false;

        // 检测语言模式
        const langMode = getLangMode(title);

        const notify = (msg) => {
            if (config.IDLE) msg = langMode === "en" ? "Windows Update Reminder" : "Windows 更新提醒";
            new Notification(config.IDLE ? (langMode === "en" ? "Windows Update" : "Windows 更新") : "Idle Artisan", {
                body: msg,
                icon: "https://idleartisan.com/favicon.ico"
            });
            cooldownUntil = now + COOLDOWN;
            notified = true;
        };

        if (config.CB && (title.includes("CB") || title.includes("制作") || title.includes("Crafting"))) {
            notify(langMode === "en" ? "Crafting Bonus!" : "制作加成来了!");
        } else if (config.Siege && (title.includes("Siege") || title.includes("围攻"))) {
            notify(langMode === "en" ? "Prepare for Siege!" : "准备 BOSS 战斗!");
        } else if (config.TS && (title.includes("TS") || title.includes("商船") || title.includes("Trade ship"))) {
            notify(langMode === "en" ? "Trade Ship arrived!" : "商船来了!");
        } else if (config.M && (title === "Idle Artisan - M" || title.includes("商人") || title.includes("Merchant"))) {
            notify(langMode === "en" ? "Merchant arrived!" : "商人来了!");
        }

    }, 10000);

    // ========= 新增功能:下一个事件显示 =========
    const nextEventLabel = document.createElement('div');
    nextEventLabel.style.marginLeft = "15px";
    nextEventLabel.style.color = "#ff4d4d"; // 或 "#ff0000"
    nextEventLabel.style.fontWeight = "bold";
    nextEventLabel.style.fontSize = "14px";
    nextEventLabel.textContent = "Next Event: ...";

    const eventWrapper = document.getElementById("event-wrapper");
    if (eventWrapper && eventWrapper.parentNode) {
        eventWrapper.parentNode.insertBefore(nextEventLabel, eventWrapper.nextSibling);
    }

    // 定时更新下一个事件(2秒一次)
    setInterval(() => {
        const currentNameElem = document.getElementById("event-name");
        if (!currentNameElem) return;

        const currentEventRaw = currentNameElem.textContent.trim();
        const langMode = getLangMode(currentEventRaw);

        // 找到英文事件基准
        let currentEn = Object.keys(eventDict).find(en => en === currentEventRaw || eventDict[en] === currentEventRaw);
        if (!currentEn) return;

        const idx = eventOrder.findIndex(e => e === currentEn);
        if (idx >= 0) {
            const nextEventEn = eventOrder[(idx + 1) % eventOrder.length];
            const nextEventName = getEventName(nextEventEn, langMode);
            nextEventLabel.textContent = langMode === "en" ? "Next Event: " + nextEventName : "下一个事件: " + nextEventName;
        } else {
            nextEventLabel.textContent = langMode === "en" ? "Next Event: Unknown" : "下一个事件: 未知";
        }
    }, 2000);

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址