1.传奇挂机多功能脚本 - 重构版

传奇挂机多功能脚本 - 优化版本,提高代码可维护性和效率

// ==UserScript==
// @name         1.传奇挂机多功能脚本 - 重构版
// @namespace    https://linux.do/u/ziyun
// @version      1.5.1
// @author       am (优化 传奇挂机多功能脚本)
// @description  传奇挂机多功能脚本 - 优化版本,提高代码可维护性和效率
// @license      MIT
// @icon         https://www.google.com/s2/favicons?sz=64&domain=e-hai.one
// @match        http://cq.e-hai.one/play?*
// @match        http://chuanqi.proxy2world.com/play?*
// @grant        GM_addStyle
// ==/UserScript==

(o => {
    if (typeof GM_addStyle == "function") {
        GM_addStyle(o);
        return;
    }
    const t = document.createElement("style");
    t.textContent = o, document.head.append(t);
  })(" .control-panel{position:fixed;bottom:0;left:0;min-width:auto;z-index:9999;background-color:rgba(0,0,0,0.7);padding:5px;border-radius:5px}.control-panel .control-group{display:flex;flex-wrap:wrap;}.control-panel .control-group .button{color:#ece6cf;background-color:#084552;padding:.3rem;border:none;cursor:pointer;border-radius:.2rem;transition:background-color 0.3s;}.control-panel .control-group .button:hover{background-color:#0a5566;} .control-panel .control-group input{border-radius: 1rem; appearance: none; border: 1px solid #ccc; background-color: #f8f8f8; color: #333; width: 1rem; text-align:center;} .control-panel .control-group .input-group{display:flex;align-items:center;margin:0.2rem;} ");

  (function() {
    'use strict';

    // --- 配置项 ---
    const CONFIG = {
        // UI相关
        ui: {
            buttonColorActive: "#55b47d",
            buttonColorInactive: "#084552",
            toastColorSuccess: "0x00ff60",
            toastColorWarning: "0xffa500",
            toastColorError: "0xff0000",
        },
        // 地图相关
        maps: {
            FENG_MO_GU: {
                id: 9,
                sendId: 12,
                name: "封魔谷"
            },
            CANG_YUE_DAO: {
                id: 4,
                sendId: 4,
                name: "苍月岛"
            },
            TIAN_CHI: {
                id: 349,
                sendId: 235,
                name: "天池"
            },
            CHEN_MO_ZHI_LU_5: {
                id: 347,
                sendId: 233,
                name: "沉默之路5"
            },
            HUN_SHUI_ZHI_DI_5: {
                id: 348,
                sendId: 234,
                name: "昏睡之地5"
            },
            ZHUANG_YUAN: {
                id: 150,
                sendId: 118,
                name: "庄园"
            },
        },
        // 安全区域
        safeZones: {
            FENG_MO_GU: [
                [162, 60],
                [208, 95],
                [155, 130],
                [110, 100]
            ]
        },
        // 技能和物品ID
        skills: {
            FIRE_WALL: 14,
            FLY_SHOES: 58,
        },
        items: {
            EXP_5X: 462,
        },
        // 定时器间隔
        intervals: {
            FIRE_WALL: 9000,
            AUTO_FLY: 3000,
            RANDOM_FARM: 4000,
            AUTO_BOSS: 1000,
            AUTO_QL_FLY: 5000,
            AUTO_EXP: 1200000, // 20分钟
            AUTO_MANOR: 20000, // 1分钟
            FIXED_POINT: 300,
        },
        // 庄园设置
        manor: {
            scheduledMinute: 50,
            xPoint: 40,
            yPoint: 31,
            checkQingLongDelay: 180000, // 3分钟后返回苍月岛
            pathFindingDelay: 1000, // 传送后等待寻路的延迟
            checkAfterPathDelay: 5000, // 寻路后等待到达目的地的延迟
            qingLongCheckInterval: 3000, // 每3秒检测一次青龙
            pathFindingRetryInterval: 2000, // 寻路重试间隔
            maxPathFindingRetries: 5, // 最大寻路重试次数
        },
        // 互斥功能组
        exclusiveGroups: {
            farmMode: ["randomFarm", "toCangYue", "toTianChi", "toChenMo", "toHunShui", "autoQLFly"]
        }
    };

    // --- 工具类 ---
    class Icons {
        static startIcon = '<svg class="icon" style="width: 1em;height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path d="M823.8 603.5l-501.2 336c-50.7 34-119.3 20.4-153.2-30.2-12.2-18.2-18.7-39.6-18.7-61.5v-672c0-61 49.5-110.4 110.4-110.4 21.9 0 43.3 6.5 61.5 18.7l501.1 336c50.7 34 64.2 102.6 30.2 153.2-7.8 11.9-18.1 22.2-30.1 30.2z m0 0"></path></svg>';
        static stopIcon = '<svg class="icon" style="width: 1em;height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M941.967463 109.714286v804.571428q0 14.857143-10.857143 25.714286t-25.714286 10.857143H100.824606q-14.857143 0-25.714286-10.857143t-10.857143-25.714286V109.714286q0-14.857143 10.857143-25.714286t25.714286-10.857143h804.571428q14.857143 0 25.714286 10.857143t10.857143 25.714286z"></path></svg>';
    }

    class Rectangle {
        constructor(vertices) {
            this.vertices = vertices;
        }

        crossProduct(x, y, z) {
            return (z[1] - y[1]) * (y[0] - x[0]) - (z[0] - y[0]) * (y[1] - x[1]);
        }

        isOnSameSide(p1, p2, a, b) {
            const cp1 = this.crossProduct(a, b, p1);
            const cp2 = this.crossProduct(a, b, p2);
            return cp1 * cp2 >= 0;
        }

        isInside(x, y) {
            const[A, B, C, D] = this.vertices;
            const p = [x, y];
            return this.isOnSameSide(p, A, B, C) &&
                   this.isOnSameSide(p, B, C, D) &&
                   this.isOnSameSide(p, C, D, A) &&
                   this.isOnSameSide(p, D, A, B);
        }
    }

    // 初始化安全区域
    const safeZones = {};
    for (const key in CONFIG.safeZones) {
        safeZones[key] = new Rectangle(CONFIG.safeZones[key]);
    }

    // 消息提示函数
    function toast(message, color = CONFIG.ui.toastColorSuccess) {
        if (typeof app !== 'undefined' && app.uMEZy && app.uMEZy.ins) {
            app.uMEZy.ins().IrCm(`|C:${color}&T:${message}|`);
        } else {
            console.warn("Toast message:", message, "Color:", color);
        }
    }

    // --- 状态管理 ---
    class ScriptState {
        constructor() {
            this.timers = {};
            this.buttonStatus = {};
            this.activeFarmMode = null;
            this.timerFunctions = {}; // 存储定时器回调函数
        }

        setButtonActive(buttonName, isActive) {
            this.buttonStatus[buttonName] = isActive;
            // 如果是挂机模式按钮,并且被激活,则更新当前激活的挂机模式
            if (isActive && CONFIG.exclusiveGroups.farmMode.includes(buttonName)) {
                this.activeFarmMode = buttonName;
            } else if (!isActive && this.activeFarmMode === buttonName) {
                this.activeFarmMode = null;
            }
        }

        isButtonActive(buttonName) {
            return !!this.buttonStatus[buttonName];
        }

        startTimer(timerName, interval, callback) {
            this.stopTimer(timerName);
            // 保存回调函数的引用
            this.timerFunctions[timerName] = callback;

            // 创建一个闭包来保持对回调的引用
            const boundCallback = function() {
                if (typeof callback === 'function') {
                    try {
                        callback();
                    } catch (e) {
                        console.error(`Timer ${timerName} error:`, e);
                    }
                }
            };

            this.timers[timerName] = window.setInterval(boundCallback, interval);
            console.log(`Timer ${timerName} started with ID ${this.timers[timerName]}`);
        }

        stopTimer(timerName) {
            if (this.timers[timerName]) {
                console.log(`Stopping timer ${timerName} with ID ${this.timers[timerName]}`);
                window.clearInterval(this.timers[timerName]);
                delete this.timers[timerName];
                delete this.timerFunctions[timerName];
            }
        }

        stopAllTimers() {
            console.log("Stopping all timers");
            for (const timerName in this.timers) {
                this.stopTimer(timerName);
            }
        }
    }

    const scriptState = new ScriptState();

    // --- 游戏工具类 ---
    const gameUtils = {
        getPlayer: function() {
            if (typeof app !== 'undefined' && app.NWRFmB && app.NWRFmB.ins) {
                return app.NWRFmB.ins().getPayer;
            } else {
                console.warn("游戏API (app.NWRFmB)不可用.");
                return null;
            }
        },

        getCharRole: function(obj) {
            if (typeof app !== 'undefined' && app.NWRFmB && app.NWRFmB.ins) {
                return app.NWRFmB.ins().getCharRole(obj);
            } else {
                console.warn("游戏API(app.NWRFmB)不可用.");
                return null;
            }
        },

        getNearMonster: function() {
            if (typeof app !== 'undefined' && app.qTVCL && app.qTVCL.ins) {
                return app.qTVCL.ins().getNearestMonster();
            } else {
                console.warn("游戏API (app.qTVCL)不可用.");
                return null;
            }
        },

        checkMonster: function() {
            if (typeof app !== 'undefined' && app.NWRFmB && app.NWRFmB.ins) {
                const all = app.NWRFmB.ins().YUwhM();
                let count = 0;
                for (const a in all) {
                    const monster = all[a];
                    if (monster && monster.propSet && monster.propSet.getRace() == 1) {
                        count++;
                    }
                }
                return count;
            } else {
                console.warn("游戏API (app.NWRFmB) 不可用.");
                return 0;
            }
        },

        checkDropCount: function() {
            if (typeof app !== 'undefined' && app.NWRFmB && app.NWRFmB.ins) {
                const drops = app.NWRFmB.ins().dropList;
                let count = 0;
                for (const _ in drops) {
                    if (drops.hasOwnProperty(_)) {
                        count++;
                    }
                }
                return count;
            } else {
                console.warn("游戏API (app.NWRFmB) 不可用, 返回0.");
                return 0;
            }
        },

        checkEdcwsp: function() {
            if (typeof app !== 'undefined' && app.qTVCL && app.qTVCL.ins) {
                if (!app.qTVCL.ins().isOpen) {
                    app.GameMap.scenes.isHook = 1;
                    app.qTVCL.ins().edcwsp();
                    toast("开始挂机", CONFIG.ui.toastColorSuccess);
                }
            } else {
                console.error("游戏API (app.qTVCL) 不可用.");
            }
        },

        inMap: function(mapId) {
            if (typeof app !== 'undefined' && app.GameMap) {
                return app.GameMap.mapID === mapId;
            } else {
                console.warn("游戏API (app.GameMap)不可用.");
                return false;
            }
        },

        send: function(recog, mapId) {
            if (typeof app !== 'undefined' && app.PKRX && app.PKRX.ins) {
                  app.PKRX.ins().send_1_7(recog, mapId);
              } else {
                  console.warn("游戏API (app.PKRX)不可用.");
              }
        },

        ingotSend: function(recog, mapId) {
            if (typeof app !== 'undefined' && app.PKRX && app.PKRX.ins) {
                app.PKRX.ins().s_1_6(recog, mapId)
              } else {
                  console.warn("游戏API (app.PKRX)不可用.");
              }
        },

        fly: function() {
            if (typeof app !== 'undefined' && app.EhSWiR) {
                app.EhSWiR.m_clickSkillId = CONFIG.skills.FLY_SHOES
            } else {
                console.warn("游戏API (app.EhSWiR)不可用.");
            }
        },

        useFireWall: function() {
            if (typeof app !== 'undefined' && app.EhSWiR) {
                app.EhSWiR.m_clickSkillId = CONFIG.skills.FIRE_WALL;
            } else {
                console.warn("游戏API (app.EhSWiR)不可用.");
            }
        },

        useExp: function(itemId, count = 1) {
            if (typeof app !== 'undefined' && app.ThgMu && app.ThgMu.ins && app.pWFTj && app.pWFTj.ins) {
                const item = app.ThgMu.ins().getItemById(itemId);
                if (item) {
                    app.pWFTj.ins().useItem(item.series, itemId, count);
                    console.log(`已使用五倍经验`);
                } else {
                    console.log(`在仓库中没有找到五倍经验`);
                }
            } else {
                console.warn("游戏API(app.ThgMu or app.pWFTj)不可用.");
            }
        },

        checkQingLong: function() {
            if (typeof app !== 'undefined' && app.NWRFmB && app.NWRFmB.ins) {
                const all = app.NWRFmB.ins().YUwhM();
                for (const a in all) {
                    const monster = all[a];
                    if (monster && monster.propSet && monster.propSet.getRace() == 1) {
                        if (monster.propSet.getName() === "[神话]青龙") {
                            return true; // 找到青龙
                        }
                    }
                }
                return false; // 未找到青龙
            } else {
                console.warn("游戏API (app.NWRFmB) 不可用.");
                return false; // API 不可用时默认未找到青龙
            }
        },

        checkBossMonster: function() {
            if (typeof app !== 'undefined' && app.qTVCL && app.qTVCL.ins) {
                app.qTVCL.ins().YFOmNj(); // VIP BOSS 交互函数
                return true;
            }
            return false;
        }
    };

    // --- 辅助函数 ---
    function convertButton(btn, color, icon) {
        if (!btn) return;
        btn.style.backgroundColor = color;
        btn.innerHTML = icon;
    }

    function autoFlyAction(player) {
        if (!player || !player.propSet) return;
        const flyShoesCount = player.propSet.getFlyshoes();
        if (flyShoesCount > 0) {
            toast(`周围无怪,飞鞋启动,剩余飞鞋点数:${flyShoesCount - 1}`, CONFIG.ui.toastColorSuccess);
            gameUtils.fly();
        } else {
            toast("飞鞋点数不足,请补充", CONFIG.ui.toastColorError);
            scriptState.stopTimer("autoFlyTimer");
            scriptState.stopTimer("randomFarmTimer");
            scriptState.setButtonActive("autoFly", false);
            scriptState.setButtonActive("randomFarm", false);
            resetAllButtons();
        }
    }

    function stopExclusiveFarmMode(exceptButtonName) {
        if (scriptState.activeFarmMode && scriptState.activeFarmMode !== exceptButtonName) {
            const activeBtn = document.getElementById(scriptState.activeFarmMode);
            if (activeBtn) {
                buttonHandlers[scriptState.activeFarmMode](activeBtn);
            }
        }
    }

    function mapFarmHandler(buttonName, mapKey, btn) {
        // 停止其他互斥的挂机模式
        stopExclusiveFarmMode(buttonName);
        const isActive = scriptState.isButtonActive(buttonName);
        if (isActive) {
            scriptState.stopTimer(`${buttonName}Timer`);
            scriptState.setButtonActive(buttonName, false);
            convertButton(btn, CONFIG.ui.buttonColorInactive, Icons.startIcon);
        } else {
            toast(`开始${CONFIG.maps[mapKey].name}挂机,传送中...`, CONFIG.ui.toastColorSuccess);
            scriptState.setButtonActive(buttonName, true);
            convertButton(btn, CONFIG.ui.buttonColorActive, Icons.stopIcon);
            const farmLogic = function() {
                try {
                    if (!gameUtils.inMap(CONFIG.maps[mapKey].id)) {
                        toast(`不在${CONFIG.maps[mapKey].name},开始传送`, CONFIG.ui.toastColorSuccess);
                        const player = gameUtils.getPlayer();
                        if (player && buttonName == "toCangYue") {
                            gameUtils.ingotSend(player.recog, CONFIG.maps[mapKey].sendId);
                        } else if(player) {
                             gameUtils.send(player.recog, CONFIG.maps[mapKey].sendId);
                        }
                    } else {
                        gameUtils.checkEdcwsp();
                        if (gameUtils.checkMonster() < 1 && gameUtils.checkDropCount() < 1) {
                            const player = gameUtils.getPlayer();
                            if (player) {
                                autoFlyAction(player);
                            }
                        }
                    }
                } catch (e) {
                    console.error(`Error in ${buttonName} farm logic:`, e);
                }
            };
            scriptState.startTimer(`${buttonName}Timer`, CONFIG.intervals.RANDOM_FARM, farmLogic);
        }
    }

    function resetAllButtons() {
        const panel = document.getElementById("control-panel");
        if (!panel) return;
        const buttons = panel.querySelectorAll('.button');
        buttons.forEach(btn => {
            convertButton(btn, CONFIG.ui.buttonColorInactive, Icons.startIcon);
        });
    }

    // --- 按钮处理程序 ---
    const buttonHandlers = {
        toggleFireWall: function(btn) {
            const isFireWallActive = scriptState.isButtonActive("toggleFireWall");
            if (isFireWallActive) {
                scriptState.stopTimer("fireWallTimer");
                scriptState.setButtonActive("toggleFireWall", false);
                convertButton(btn, CONFIG.ui.buttonColorInactive, Icons.startIcon);
            } else {
                toast("自动火墙已开启", CONFIG.ui.toastColorSuccess);
                scriptState.setButtonActive("toggleFireWall", true);
                convertButton(btn, CONFIG.ui.buttonColorActive, Icons.stopIcon);
                const fireWallLogic = function() {
                    try {
                        gameUtils.useFireWall();
                    } catch (e) {
                        console.error("Error in fireWall logic:", e);
                    }
                };
                scriptState.startTimer("fireWallTimer", CONFIG.intervals.FIRE_WALL, fireWallLogic);
            }
        },

        randomFarm: function(btn) {
            stopExclusiveFarmMode("randomFarm");
            const isRandomFarmActive = scriptState.isButtonActive("randomFarm");
            if (isRandomFarmActive) {
                scriptState.stopTimer("randomFarmTimer");
                scriptState.setButtonActive("randomFarm", false);
                convertButton(btn, CONFIG.ui.buttonColorInactive, Icons.startIcon);
            } else {
                toast("封魔谷全自动挂机已开启", CONFIG.ui.toastColorSuccess);
                scriptState.setButtonActive("randomFarm", true);
                convertButton(btn, CONFIG.ui.buttonColorActive, Icons.stopIcon);
                const farmLogic = function() {
                    try {
                        const player = gameUtils.getPlayer();
                        if (!player) return;
                        if (gameUtils.inMap(CONFIG.maps.FENG_MO_GU.id)) {
                            gameUtils.checkEdcwsp();
                            if (safeZones.FENG_MO_GU.isInside(player.lastX, player.lastY)) {
                                toast(`角色在安全区[${player.lastX},${player.lastY}],飞鞋避险`, CONFIG.ui.toastColorWarning);
                                gameUtils.fly();
                            } else if (gameUtils.checkMonster() < 1 && gameUtils.checkDropCount() < 1) {
                                autoFlyAction(player);
                            }
                        } else {
                            toast("不在封魔谷,开始传送", CONFIG.ui.toastColorSuccess);
                            gameUtils.send(player.recog, CONFIG.maps.FENG_MO_GU.sendId);
                        }
                    } catch (e) {
                        console.error("Error in randomFarm logic:", e);
                    }
                };
                scriptState.startTimer("randomFarmTimer", CONFIG.intervals.RANDOM_FARM, farmLogic);
            }
        },

        toCangYue: function(btn) {
            mapFarmHandler("toCangYue", "CANG_YUE_DAO", btn);
        },

        toTianChi: function(btn) {
            mapFarmHandler("toTianChi", "TIAN_CHI", btn);
        },

        toChenMo: function(btn) {
            mapFarmHandler("toChenMo", "CHEN_MO_ZHI_LU_5", btn);
        },

        toHunShui: function(btn) {
            mapFarmHandler("toHunShui", "HUN_SHUI_ZHI_DI_5", btn);
        },

        autoFly: function(btn) {
            const isAutoFlyActive = scriptState.isButtonActive("autoFly");
            if (isAutoFlyActive) {
                scriptState.stopTimer("autoFlyTimer");
                scriptState.setButtonActive("autoFly", false);
                convertButton(btn, CONFIG.ui.buttonColorInactive, Icons.startIcon);
            } else {
                toast("3秒后开启无怪自动飞鞋", CONFIG.ui.toastColorSuccess);
                scriptState.setButtonActive("autoFly", true);
                convertButton(btn, CONFIG.ui.buttonColorActive, Icons.stopIcon);
                const autoFlyLogic = function() {
                    try {
                        gameUtils.checkEdcwsp();
                        if (gameUtils.checkMonster() < 1 && gameUtils.checkDropCount() < 1) {
                            const player = gameUtils.getPlayer();
                            if (player) {
                                autoFlyAction(player);
                            }
                        }
                    } catch (e) {
                        console.error("Error in autoFly logic:", e);
                    }
                };
                scriptState.startTimer("autoFlyTimer", CONFIG.intervals.AUTO_FLY, autoFlyLogic);
            }
        },

        autoBoss: function(btn) {
            const isAutoBossActive = scriptState.isButtonActive("autoBoss");
            if (isAutoBossActive) {
                scriptState.stopTimer("autoBossTimer");
                scriptState.setButtonActive("autoBoss", false);
                convertButton(btn, CONFIG.ui.buttonColorInactive, Icons.startIcon);
            } else {
                scriptState.setButtonActive("autoBoss", true);
                convertButton(btn, CONFIG.ui.buttonColorActive, Icons.stopIcon);
                const autoBossLogic = function() {
                    try {
                        if (gameUtils.checkMonster() < 1 && gameUtils.checkDropCount() < 1 && gameUtils.inMap(CONFIG.maps.FENG_MO_GU.id)) {
                            if (typeof app !== 'undefined' && app.qTVCL && app.qTVCL.ins) {
                                app.qTVCL.ins().YFOmNj(); // VIP BOSS 交互函数
                                toast("停止挂机,搜寻BOSS", CONFIG.ui.toastColorSuccess);
                            }
                        } else if (gameUtils.checkMonster() > 0 && !gameUtils.inMap(CONFIG.maps.FENG_MO_GU.id)) {
                            gameUtils.checkEdcwsp();
                            const nearMonster = gameUtils.getNearMonster();
                            const charRole = gameUtils.getCharRole(nearMonster);
                            if (!charRole || !charRole.propSet) {
                                toast(`开始挂机, 怪物数量: ${gameUtils.checkMonster()}`, CONFIG.ui.toastColorSuccess);
                            } else {
                                toast(`开始挂机, 怪物数量: ${gameUtils.checkMonster()}, 目标: ${charRole.propSet.getName()}`, CONFIG.ui.toastColorSuccess);
                            }
                        }
                    } catch (e) {
                        console.error("Error in autoBoss logic:", e);
                    }
                };
                scriptState.startTimer("autoBossTimer", CONFIG.intervals.AUTO_BOSS, autoBossLogic);
            }
        },

        autoQLFly: function(btn) {
            stopExclusiveFarmMode("autoQLFly");
            const isAutoQLFlyActive = scriptState.isButtonActive("autoQLFly");
            if (isAutoQLFlyActive) {
                scriptState.stopTimer("autoQLFlyTimer");
                scriptState.setButtonActive("autoQLFly", false);
                convertButton(btn, CONFIG.ui.buttonColorInactive, Icons.startIcon);
            } else {
                toast("麒麟/炼狱魔龙监测已开启", CONFIG.ui.toastColorSuccess);
                scriptState.setButtonActive("autoQLFly", true);
                convertButton(btn, CONFIG.ui.buttonColorActive, Icons.stopIcon);
                const autoQLFlyLogic = function() {
                    try {
                        gameUtils.checkEdcwsp();
                        const nearMonster = gameUtils.getNearMonster();
                        if (nearMonster) {
                            const charRole = gameUtils.getCharRole(nearMonster);
                            if (charRole && charRole.propSet) {
                                const monsterName = charRole.propSet.getName();
                                if (monsterName === "[神话]麒麟" || monsterName === "[妖兽]妖化麒麟" || monsterName === "[神话]炼狱魔龙") {
                                    toast(`检测到${monsterName},飞鞋避让`, CONFIG.ui.toastColorWarning);
                                    const player = gameUtils.getPlayer();
                                    if (player) {
                                        autoFlyAction(player);
                                    }
                                }
                            }
                        }
                        if (gameUtils.checkMonster() < 1 && gameUtils.checkDropCount() < 1) {
                            const player = gameUtils.getPlayer();
                            if (player) {
                                autoFlyAction(player);
                            }
                        }
                    } catch (e) {
                        console.error("Error in autoQLFly logic:", e);
                    }
                };
                scriptState.startTimer("autoQLFlyTimer", CONFIG.intervals.AUTO_QL_FLY, autoQLFlyLogic);
            }
        },

        autoFivefoldExp: function(btn) {
            const isAutoFivefoldExpActive = scriptState.isButtonActive("autoFivefoldExp");
            if (isAutoFivefoldExpActive) {
                scriptState.stopTimer("autoExpTimer");
                scriptState.setButtonActive("autoFivefoldExp", false);
                convertButton(btn, CONFIG.ui.buttonColorInactive, Icons.startIcon);
            } else {
                toast("自动五倍经验已开启", CONFIG.ui.toastColorSuccess);
                scriptState.setButtonActive("autoFivefoldExp", true);
                convertButton(btn, CONFIG.ui.buttonColorActive, Icons.stopIcon);
                const autoExpLogic = function() {
                    try {
                        gameUtils.useExp(CONFIG.items.EXP_5X, 1);
                    } catch (e) {
                        console.error("Error in autoExp logic:", e);
                    }
                };
                scriptState.startTimer("autoExpTimer", CONFIG.intervals.AUTO_EXP, autoExpLogic);
            }
        },

        autoManorFarm: function(btn) {
            const isAutoManorFarmActive = scriptState.isButtonActive("autoManorFarm");
            if (isAutoManorFarmActive) {
                scriptState.stopTimer("scheduledManorTimer");
                scriptState.stopTimer("manorQingLongCheckTimer");
                scriptState.stopTimer("frequentQingLongCheckTimer");
                scriptState.stopTimer("pathFindingRetryTimer");  // 停止寻路重试定时器
                scriptState.setButtonActive("autoManorFarm", false);
                convertButton(btn, CONFIG.ui.buttonColorInactive, Icons.startIcon);
                toast("庄园自动打怪已关闭", CONFIG.ui.toastColorSuccess);
                toast("庄园自动打怪已关闭", CONFIG.ui.toastColorSuccess);
            } else {
                toast("庄园自动打怪已开启", CONFIG.ui.toastColorSuccess);
                scriptState.setButtonActive("autoManorFarm", true);
                convertButton(btn, CONFIG.ui.buttonColorActive, Icons.stopIcon);

                // 庄园管理逻辑
                const manorManager = {
                    // 检查青龙并决定行动
                    checkQingLongAndAct: function(now) {
                        gameUtils.checkEdcwsp();
                        if (gameUtils.checkQingLong()) {
                            toast(`[${now.getHours()}:${now.getMinutes()}]庄园检测到青龙,开始挂机`, CONFIG.ui.toastColorSuccess);
                            gameUtils.checkEdcwsp();
                            return true;
                        } else {
                            toast(`[${now.getHours()}:${now.getMinutes()}]庄园未检测到青龙,开始频繁检测`, CONFIG.ui.toastColorWarning);
                            this.startFrequentQingLongCheck();
                            return false;
                        }
                    },

                    // 开始频繁检测青龙(每3秒一次,持续3分钟)
                    startFrequentQingLongCheck: function() {
                        let checkCount = 0;
                        const maxChecks = Math.floor(CONFIG.manor.checkQingLongDelay / CONFIG.manor.qingLongCheckInterval);

                        // 停止之前可能存在的频繁检测定时器
                        scriptState.stopTimer("frequentQingLongCheckTimer");

                        scriptState.startTimer("frequentQingLongCheckTimer", CONFIG.manor.qingLongCheckInterval, () => {
                            try {
                                if (!gameUtils.inMap(CONFIG.maps.ZHUANG_YUAN.id)) {
                                    scriptState.stopTimer("frequentQingLongCheckTimer");
                                    return;
                                }

                                checkCount++;
                                const currentTime = new Date();
                                console.log(`[庄园青龙检测] 第${checkCount}次检测,共${maxChecks}次`);

                                if (gameUtils.checkQingLong()) {
                                    toast(`[${currentTime.getHours()}:${currentTime.getMinutes()}]庄园检测到青龙,开始挂机`, CONFIG.ui.toastColorSuccess);
                                    gameUtils.checkEdcwsp();
                                    scriptState.stopTimer("frequentQingLongCheckTimer");
                                    return;
                                }

                                // 如果达到最大检测次数且仍未发现青龙,返回苍月岛
                                if (checkCount >= maxChecks) {
                                    toast(`[${currentTime.getHours()}:${currentTime.getMinutes()}]庄园3分钟未检测到青龙,返回苍月岛`, CONFIG.ui.toastColorSuccess);
                                    const player = gameUtils.getPlayer();
                                    if (player) {
                                        gameUtils.ingotSend(player.recog, CONFIG.maps.CANG_YUE_DAO.sendId);
                                    }
                                    scriptState.stopTimer("frequentQingLongCheckTimer");
                                }
                            } catch (e) {
                                console.error("Error in frequent QingLong check:", e);
                            }
                        });
                    },

                    // 传送到庄园并寻路到指定位置
                    teleportToManor: function(now) {
                        const player = gameUtils.getPlayer();
                        if (!player) return;

                        toast(`[${now.getHours()}:${now.getMinutes()}]传送到庄园`, CONFIG.ui.toastColorSuccess);
                        gameUtils.send(player.recog, CONFIG.maps.ZHUANG_YUAN.sendId);

                        // 短暂延迟后开始寻路过程,确保传送完成
                        setTimeout(() => {
                            this.startPathFindingProcess();
                        }, CONFIG.manor.pathFindingDelay);
                    },

                    // 寻路过程管理
                    startPathFindingProcess: function() {
                        let retryCount = 0;

                        // 停止可能存在的寻路重试定时器
                        scriptState.stopTimer("pathFindingRetryTimer");

                        // 创建寻路函数
                        const attemptPathFinding = () => {
                            try {
                                const player = gameUtils.getPlayer();
                                if (!player || !gameUtils.inMap(CONFIG.maps.ZHUANG_YUAN.id)) {
                                    scriptState.stopTimer("pathFindingRetryTimer");
                                    return;
                                }

                                // 检查是否已经到达目标位置
                                const distanceToTarget = Math.sqrt(
                                    Math.pow(player.currentX - CONFIG.manor.xPoint, 2) +
                                    Math.pow(player.currentY - CONFIG.manor.yPoint, 2)
                                );

                                // 如果已经接近目标位置,停止寻路并开始检测青龙
                                if (distanceToTarget < 5) {
                                    toast(`已到达目标位置附近[${player.currentX},${player.currentY}],开始检测青龙`, CONFIG.ui.toastColorSuccess);
                                    scriptState.stopTimer("pathFindingRetryTimer");

                                    // 开始检测青龙
                                    const currentTime = new Date();
                                    this.checkQingLongAndAct(currentTime);
                                    return;
                                }

                                // 如果还未到达目标位置,继续尝试寻路
                                retryCount++;
                                toast(`寻路尝试 ${retryCount}/${CONFIG.manor.maxPathFindingRetries} 到[${CONFIG.manor.xPoint},${CONFIG.manor.yPoint}]`, CONFIG.ui.toastColorSuccess);
                                player.pathFinding(CONFIG.manor.xPoint, CONFIG.manor.yPoint);

                                // 如果达到最大重试次数,停止重试并开始检测青龙
                                if (retryCount >= CONFIG.manor.maxPathFindingRetries) {
                                    toast(`达到最大寻路尝试次数,在当前位置[${player.currentX},${player.currentY}]开始检测青龙`, CONFIG.ui.toastColorWarning);
                                    scriptState.stopTimer("pathFindingRetryTimer");

                                    // 开始检测青龙
                                    const currentTime = new Date();
                                    this.checkQingLongAndAct(currentTime);
                                }
                            } catch (e) {
                                console.error("Error in pathFinding retry:", e);
                                scriptState.stopTimer("pathFindingRetryTimer");
                            }
                        };

                        // 立即执行一次寻路
                        attemptPathFinding();

                        // 设置定时器进行寻路重试
                        scriptState.startTimer("pathFindingRetryTimer", CONFIG.manor.pathFindingRetryInterval, attemptPathFinding);
                    },

                    // 主要定时检查逻辑
                    scheduledCheck: function() {
                        try {
                            const now = new Date();
                            console.log(`[庄园定时]当前分钟: ${now.getMinutes()}, 设定分钟: ${CONFIG.manor.scheduledMinute}`);

                            // 如果是指定时间,执行庄园传送和检查
                            if (now.getMinutes() === CONFIG.manor.scheduledMinute) {
                                if (!gameUtils.inMap(CONFIG.maps.ZHUANG_YUAN.id)) {
                                    this.teleportToManor(now);
                                } else {
                                    toast(`[${now.getHours()}:${now.getMinutes()}]已在庄园,检查青龙`, CONFIG.ui.toastColorSuccess);
                                    this.checkQingLongAndAct(now);
                                }
                            }
                            // 如果不是指定时间但已在庄园,也检查青龙
                            else if (gameUtils.inMap(CONFIG.maps.ZHUANG_YUAN.id)) {
                                // 静默检查,只有发现青龙才挂机
                                if (gameUtils.checkQingLong()) {
                                    gameUtils.checkEdcwsp();
                                }else{
                                    const player = gameUtils.getPlayer();
                                    if (player) {
                                        gameUtils.ingotSend(player.recog, CONFIG.maps.CANG_YUE_DAO.sendId);
                                    }
                                    scriptState.stopTimer("frequentQingLongCheckTimer");
                                }
                            }
                        } catch (e) {
                            console.error("Error in scheduledCheck:", e);
                        }
                    }
                };

                // 启动庄园定时检查
                scriptState.startTimer("scheduledManorTimer", CONFIG.intervals.AUTO_MANOR, () => {
                    try {
                        manorManager.scheduledCheck();
                    } catch (e) {
                        console.error("Error in manor scheduled check:", e);
                    }
                });

                // 立即执行一次检查
                manorManager.scheduledCheck();
            }
        },

        fixedPointFarm: function(btn) {
            const isFixedPointFarmActive = scriptState.isButtonActive("fixedPointFarm");
            if (isFixedPointFarmActive) {
                scriptState.stopTimer("fixedPointTimer");
                scriptState.setButtonActive("fixedPointFarm", false);
                convertButton(btn, CONFIG.ui.buttonColorInactive, Icons.startIcon);
            } else {
                toast("定点挂机已开启", CONFIG.ui.toastColorSuccess);
                scriptState.setButtonActive("fixedPointFarm", true);
                convertButton(btn, CONFIG.ui.buttonColorActive, Icons.stopIcon);

                const player = gameUtils.getPlayer();
                const fixedPoint = player ? {
                    x: player.currentX,
                    y: player.currentY
                } : {
                    x: 0,
                    y: 0
                };

                const fixedPointLogic = function() {
                    try {
                        if (typeof app !== 'undefined' && app.GameMap && app.GameMap.scenes && app.GameMap.scenes.hook) {
                            for (let i = 0; i < app.GameMap.scenes.hook.length; i++) {
                                app.GameMap.scenes.hook[i] = fixedPoint;
                            }
                        } else {
                            console.warn("游戏 API(app.GameMap.scenes.hook)不可用.");
                        }
                        gameUtils.checkEdcwsp();
                    } catch (e) {
                        console.error("Error in fixedPoint logic:", e);
                    }
                };

                scriptState.startTimer("fixedPointTimer", CONFIG.intervals.FIXED_POINT, fixedPointLogic);
            }
        },

        setManorTime: function(inputElement) {
            const minute = parseInt(inputElement.value, 10);
            if (!isNaN(minute) && minute >= 0 && minute <= 59) {
                CONFIG.manor.scheduledMinute = minute;
                toast(`庄园定时已设置为每小时${minute}分`, CONFIG.ui.toastColorSuccess);
            } else {
                toast("无效的分钟数,请输入0-59之间的数字", CONFIG.ui.toastColorError);
                inputElement.value = CONFIG.manor.scheduledMinute;
            }
        },

        setXPointInput: function(inputElement) {
            const xPoint = parseInt(inputElement.value, 10);
            if (!isNaN(xPoint) && xPoint >= 0 && xPoint <= 1000) {
                CONFIG.manor.xPoint = xPoint;
                toast(`庄园寻路X坐标已设置为 ${xPoint}`, CONFIG.ui.toastColorSuccess);
            } else {
                toast("无效的X坐标,请输入0-1000之间的数字", CONFIG.ui.toastColorError);
                inputElement.value = CONFIG.manor.xPoint;
            }
        },

        setYPointInput: function(inputElement) {
            const yPoint = parseInt(inputElement.value, 10);
            if (!isNaN(yPoint) && yPoint >= 0 && yPoint <= 1000) {
                CONFIG.manor.yPoint = yPoint;
                toast(`庄园寻路Y坐标已设置为 ${yPoint}`, CONFIG.ui.toastColorSuccess);
            } else {
                toast("无效的Y坐标,请输入0-1000之间的数字", CONFIG.ui.toastColorError);
                inputElement.value = CONFIG.manor.yPoint;
            }
        },
    };

    // --- UI创建 ---
    function createControlPanel() {
        const controlPanel = document.createElement("div");
        controlPanel.id = "control-panel";
        controlPanel.className = "control-panel";
        controlPanel.innerHTML = `
            <div class="control-group">
                <button id="toggleFireWall" class="button" title="自动释放火墙">${Icons.startIcon}</button>
                <button id="randomFarm" class="button" title="封魔谷全自动挂机">${Icons.startIcon}</button>
                <button id="toCangYue" class="button" title="苍月岛全自动挂机">${Icons.startIcon}</button>
                <button id="toTianChi" class="button" title="天池全自动挂机">${Icons.startIcon}</button>
                <button id="toChenMo" class="button" title="沉默之路5全自动挂机">${Icons.startIcon}</button>
                <button id="toHunShui" class="button" title="昏睡之地5全自动挂机">${Icons.startIcon}</button>
                <button id="autoFly" class="button" title="周围无怪自动飞鞋">${Icons.startIcon}</button>
                <button id="autoBoss" class="button" title="自动刷VIP BOSS">${Icons.startIcon}</button>
                <button id="autoQLFly" class="button" title="麒麟/炼狱魔龙飞鞋避让">${Icons.startIcon}</button>
                <button id="autoFivefoldExp" class="button" title="自动使用五倍经验">${Icons.startIcon}</button>
                <button id="autoManorFarm" class="button" title="自动庄园打怪">${Icons.startIcon}</button>
                <input type="text" id="manor-time-input" value="${CONFIG.manor.scheduledMinute}" min="0" max="59" title="设置每小时的哪一分钟定时执行庄园传送"/>
                <input type="text" id="manor-x-point" value="${CONFIG.manor.xPoint}" title="设置X坐标位置"/>
                <input type="text" id="manor-y-point" value="${CONFIG.manor.yPoint}" title="设置Y坐标位置"/>
                <button id="fixedPointFarm" class="button" title="定点挂机打怪">${Icons.startIcon}</button>
            </div>
        `;

        const btnActions = {
            "toggleFireWall": buttonHandlers.toggleFireWall,
            "randomFarm": buttonHandlers.randomFarm,
            "toCangYue": buttonHandlers.toCangYue,
            "toTianChi": buttonHandlers.toTianChi,
            "toChenMo": buttonHandlers.toChenMo,
            "toHunShui": buttonHandlers.toHunShui,
            "autoFly": buttonHandlers.autoFly,
            "autoBoss": buttonHandlers.autoBoss,
            "autoQLFly": buttonHandlers.autoQLFly,
            "autoFivefoldExp": buttonHandlers.autoFivefoldExp,
            "autoManorFarm": buttonHandlers.autoManorFarm,
            "fixedPointFarm": buttonHandlers.fixedPointFarm,
        };

        for (const btnId in btnActions) {
            const btn = controlPanel.querySelector(`#${btnId}`);
            if (btn) {
                btn.addEventListener("click", function() {
                    try {
                        btnActions[btnId](this);
                    } catch (e) {
                        console.error(`Error in button handler ${btnId}:`, e);
                    }
                });
            }
        }

        const manorTimeInput = controlPanel.querySelector("#manor-time-input");
        if (manorTimeInput) {
            manorTimeInput.addEventListener("change", function() {
                try {
                    buttonHandlers.setManorTime(this);
                } catch (e) {
                    console.error("Error in manor time input handler:", e);
                }
            });
        }

        const xPointInput = controlPanel.querySelector("#manor-x-point");
        if (xPointInput) {
            xPointInput.addEventListener("change", function() {
                try {
                    buttonHandlers.setXPointInput(this);
                } catch (e) {
                    console.error("Error in X point input handler:", e);
                }
            });
        }

        const yPointInput = controlPanel.querySelector("#manor-y-point");
        if (yPointInput) {
            yPointInput.addEventListener("change", function() {
                try {
                    buttonHandlers.setYPointInput(this);
                } catch (e) {
                    console.error("Error in Y point input handler:", e);
                }
            });
        }

        return controlPanel;
    }

    // --- 初始化 ---
    window.addEventListener("load", function() {
        try {
            document.body.appendChild(createControlPanel());
            console.log("传奇挂机多功能脚本已加载");
        } catch (e) {
            console.error("脚本初始化错误:", e);
        }
    });

    // 保存原始定时器函数
    const originalSetInterval = window.setInterval;
    const originalClearInterval = window.clearInterval;

    // 防止游戏环境干扰定时器
    window.setInterval = function(callback, delay) {
        return originalSetInterval.call(window, callback, delay);
    };

    window.clearInterval = function(id) {
        return originalClearInterval.call(window, id);
    };

    // 在脚本卸载时清理所有定时器
    window.addEventListener("beforeunload", function() {
        scriptState.stopAllTimers();
    });
  })();