台服无剑Mud辅助

无剑Mud辅助,由在线版移植而来,順便《略改》

As of 2024-04-04. See the latest version.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name              台服无剑Mud辅助
// @name:zh-TW        台服無劍Mud輔助
// @description       无剑Mud辅助,由在线版移植而来,順便《略改》
// @description:zh-TW 無劍Mud輔助,由在線版移植而來,順便《略改》
// @namespace         http://tampermonkey.net/
// @version           0.1.50
// @iconURL           http://res.yytou.cn/lunjian_tw/img/icon1.png
// @author            九
// @match             http://swordman-s1.yytou.com/*
// @match             http://swordman-inter.yytou.com/*
// @grant             unsafeWindow
// @grant             GM_info
// @grant             GM_setClipboard
// @grant             GM_xmlhttpRequest
// @grant             GM_openInTab
// @connect           greatest.deepsurf.us
// @run-at            document-end
// @compatible        Chrome >= 80
// @compatible        Edge >= 80
// @compatible        Firefox PC >= 74
// @compatible        Opera >= 67
// @compatible        Safari MacOS >= 13.1
// @compatible        Firefox Android >= 79
// @compatible        Opera Android >= 57
// @compatible        Safari iOS >= 13.4
// @compatible        WebView Android >= 80  那一堆萬年不更新WebView的國產安卓手機不會在這出問題吧(
// @require https://update.greatest.deepsurf.us/scripts/445697/1244619/Greasy%20Fork%20API.js
// @license MIT
// ==/UserScript==

"use strict";
// 取消屏蔽
var KEYWORD_PATTERNS = g_gmain.KEYWORD_PATTERNS;
g_gmain.KEYWORD_PATTERNS = [];

$(() => {
  function init() {
    GreasyFork.getScriptData('490959').then(data => {
      if (GM_info.script.version !== data.version) {
        YFUI.showPop({
          title: "發現版本更新!是否前往版本更新?",
          text: "當前版本: " + GM_info.script.version + "<br>最新版本: " + data.version,
          onOk() {
            GreasyFork.installScript('490959');
          },
          onNo() {
            console.log('不更新');
          }
        });
      }
    });
    const dataFile = localStorage.getItem('dataFile');
    console.log('文件已從本地緩存加載');
    PLU.YFUI = YFUI;
    PLU.UTIL = UTIL;
    PLU.YFD = eval(dataFile);

    let waitGameSI = setInterval(() => {
      if (g_obj_map && g_obj_map.get("msg_attrs")) {
        clearInterval(waitGameSI);
        PLU.init();
      }
    }, 500);
  }

  // 本地化
  function _(c, t) {
    return navigator.language == "zh-CN" || !t ? c : t;
  }

  class Base64 {
    constructor() {
      let Encoder = new TextEncoder();
      let Decoder = new TextDecoder();
      this.encode = (s) => btoa(Array.from(Encoder.encode(s), (x) => String.fromCodePoint(x)).join(""));
      this.decode = (s) => Decoder.decode(Uint8Array.from(atob(s), (m) => m.codePointAt(0)));
    }
  }
  
  function log(type, subtype) {
    var msg = new Map();
    msg.set('type', type);
    msg.set('subtype', subtype);
    let custom_b = {
      elements: [],
      
      size: function() {
          return this.elements.length;
      },
      
      isEmpty: function() {
          return this.elements.length < 1;
      },
      
      clear: function() {
          this.elements = [];
      },
      
      random_elements: function() {
          for (var i = this.elements.length - 1; i > 0; i--) {
              var j = Math.floor(Math.random() * (i + 1));
              var temp = this.elements[i];
              this.elements[i] = this.elements[j];
              this.elements[j] = temp;
          }
      },
      
      put: function(key, value) {
          var found = false;
          for (var i = 0; i < this.elements.length; i++) {
              if (this.elements[i].key === key) {
                  found = true;
                  this.elements[i].value = value;
                  break;
              }
          }
          if (!found) {
              this.elements.push({ key: key, value: value });
          }
      },
      
      remove: function(key) {
          var found = false;
          for (var i = 0; i < this.elements.length; i++) {
              if (this.elements[i].key === key) {
                  this.elements.splice(i, 1);
                  found = true;
                  break;
              }
          }
          return found;
      },
      
      get: function(key) {
          for (var i = 0; i < this.elements.length; i++) {
              if (this.elements[i].key === key) {
                  return this.elements[i].value;
              }
          }
          return null;
      },
      
      copy: function() {
          var newMap = Object.create(customMap);
          newMap.elements = this.elements.slice();
          return newMap;
      },
      
      putAll: function(map) {
          if (map) {
              for (var i = 0; i < map.elements.length; i++) {
                  this.put(map.elements[i].key, map.elements[i].value);
              }
          }
      },
      
      element: function(index) {
          if (index >= 0 && index < this.elements.length) {
              return this.elements[index];
          }
          return null;
      },
      
      containsKey: function(key) {
          for (var i = 0; i < this.elements.length; i++) {
              if (this.elements[i].key === key) {
                  return true;
              }
          }
          return false;
      },
      
      containsValue: function(value) {
          for (var i = 0; i < this.elements.length; i++) {
              if (this.elements[i].value === value) {
                  return true;
              }
          }
          return false;
      },
      
      values: function() {
          var values = [];
          for (var i = 0; i < this.elements.length; i++) {
              values.push(this.elements[i].value);
          }
          return values;
      },
      
      keys: function() {
          var keys = [];
          for (var i = 0; i < this.elements.length; i++) {
              keys.push(this.elements[i].key);
          }
          return keys;
      }
    };
    msg.set('b', custom_b);
    window._dispatch_message = webSocketMsg.prototype.old = gSocketMsg.dispatchMessage;
    _dispatch_message(msg);
  }
  
  function MiGongNavi() {
    return {
      Append: function (name, cmd) {
        if ($("#out #MiGongNaviPanel").length == 0) {
          $("#out table:eq(1)").after('<div id="MiGongNaviPanel"><div>馬車:</div></div>')
        }
        // button.setAttribute("onClick", 'go("' + arr[i].way + '")');
        $("#out #MiGongNaviPanel").append('<button type="button" cellpadding="0" cellspacing="0" onclick="PLU.execActions(\'' + cmd + '\')" class="cmd_click3"><font style="color:yellow">' + name + "</font></button>")
      },
      Clear: function () {
        $("#out #MiGongNaviPanel").remove()
      }
    }
  }

  //=================================================================================
  // UTIL模組
  //=================================================================================
  unsafeWindow.PLU = {
    version: GM_info.script.version + "(v2.72.0622.01)",
    accId: null,
    nickName: null,
    battleData: null,
    MPFZ: {},
    TODO: [], //待辦列表
    STO: {},
    SIT: {},
    ONOFF: {},
    STATUS: {
      inBattle: 0,
      isBusy: 0,
    },
    CACHE: {
      autoDZ: 1,
      autoHYC: 1,
      auto9H: 1,
      autoLX: 1,
      autoBF: 1,
      autoB6: 1,
      autoB5F: 1,
      autoDY: 0,
      develop: 0,
      puzzleTimeOut: 60,
    },
    FLK: null,
    TMP: { autotask: false, iBatchAskModel: 0 },
    logHtml: "",
    signInMaps: null,
    //================================================================================================
    init() {
      this.accId = UTIL.getAccId();
      this.developerMode =
        (UTIL.getMem("CACHE") && JSON.parse(UTIL.getMem("CACHE")).developer) || ["8429379(1)", "8432668(1)", "8432667(1)", "8432616(1)"].includes(this.accId);
      if (this.developerMode) {
        this.GM_info = GM_info;
        UTIL.addSysListener("developer", (b, type, subtype, msg) => {
          if (type && type == "attrs_changed") return;
          if (type && type == "channel" && subtype == "rumor") return;
          console.log(b);
        });
      }
      this.initMenu();
      this.initTickTime();
      this.initStorage();
      this.initHistory();
      this.initSocketMsgEvent();
      this.initVersion();

      addEventListener("keydown", (key) => {
        if (key.altKey || key.ctrlKey || key.metaKey || key.shiftKey) return; // 不考慮組合鍵
        if (document.activeElement && document.activeElement.tagName == "INPUT") return;
        switch (key.keyCode) {
          case 81: // q
            clickButton("nw");
            break;
          case 87: // w
            clickButton("n");
            break;
          case 69: // e
            clickButton("ne");
            break;
          case 65: // a
            clickButton("w");
            break;
          case 83: // s
            clickButton("s");
            break;
          case 68: // d
            clickButton("e");
            break;
          case 90: // z
            clickButton("sw");
            break;
          case 67: // c
            clickButton("se");
            break;
        }
      });
    },

    //================================================================================================
    initVersion() {
      this.nickName = g_obj_map.get("msg_attrs").get("name");
      YFUI.writeToOut(
        `<span style='color:yellow;'>
        +===========================+
        ${_("脚本名称: 无剑Mud辅助", "腳本名稱:無劍Mud輔助")}
        ${_("脚本开发", "腳本開發")}:燕飞,東方鳴,懒人,九
        ${_("脚本版本:", "腳本版本:")}${this.version}
        ${_("当前角色:", "當前角色:")}${this.nickName}${this.developerMode ? _("(已开启开发者模式)", "(已開啓開發者模式)") : ""}
        角 色 ID :${this.accId}
        +===========================+</span>`,
      );
      var playerName = this.removeColorCode(this.nickName); //窗口標題
      document.title = playerName;
      YFUI.writeToOut("<span style='color:#FFF;'>" + _("监听设定", "監聽設定") + ":</span>");
      let autosets = "";
      if (PLU.getCache("autoDZ") == 1) autosets += _("连续打坐,", "連續打坐, ");
      if (PLU.getCache("autoHYC") == 1) autosets += _("连续睡床,", "連續睡床, ");
      if (PLU.getCache("auto9H") == 1) autosets += _("持续九花,", "持續九花,");
      if (PLU.getCache("autoDY") == 1) autosets += _("持续钓鱼,", "持續釣魚,");
      if (PLU.getCache("autoLX") == 1) autosets += _("连续练习,", "連續練習, ");
      if (PLU.getCache("autoBF") == 1) autosets += _("加入帮四,", "加入幫四, ");
      if (PLU.getCache("autoB6") == 1) autosets += _("加入帮六,", "加入幫六, ");
      if (PLU.getCache("autoB5F") == 1) autosets += _("帮五跟杀,", "幫五跟殺, ");
      if (PLU.getCache("listenPuzzle") == 1) autosets += _("暴击谜题,", "暴擊謎題, ");
      YFUI.writeToOut("<span style='color:#CFF;'>" + autosets + "</span>");
      if (PLU.getCache("autoTP") == 1) {
        YFUI.writeToOut("<span style='color:#CFF;'>" + _("自动突破", "自動突破") + ": <span style='color:#FF9;'>" + PLU.getCache("autoTP_keys") + "</span></span>");
      }
      if (PLU.getCache("listenQL") == 1) {
        YFUI.writeToOut("<span style='color:#CFF;'>" + _("自动青龙", "自動青龍") + ": <span style='color:#FF9;'>" + PLU.getCache("listenQL_keys") + "</span></span>");
      }
      if (PLU.getCache("listenKFQL") == 1) {
        YFUI.writeToOut("<span style='color:#CFF;'>" + _("跨服青龙", "跨服青龍") + ": <span style='color:#FF9;'>" + PLU.getCache("listenKFQL_keys") + "</span></span>");
      }
      if (PLU.getCache("listenTF") == 1) {
        YFUI.writeToOut("<span style='color:#CFF;'>" + _("自动逃犯", "自動逃犯") + ": <span style='color:#FF9;'>" + PLU.getCache("listenTF_keys") + "</span></span>");
      }
      if (!g_gmain.is_fighting) {
        PLU.getSkillsList((allSkills, tupoSkills) => {
          if (tupoSkills.length > 0) {
            YFUI.writeToOut("<span style='color:white;'>突破中技能:</span>");
            let topos = "";
            tupoSkills.forEach((sk, i) => {
              topos += "<span style='color:#CCF;min-width:100px;display:inline-block;'>" + (i + 1) + " : " + sk.name + "</span>";
            });
            YFUI.writeToOut("<span style='color:#CCF;'> " + topos + "</span>");
            YFUI.writeToOut("<span style='color:yellow;'>+------------------------------+</span>");
          } else {
            YFUI.writeToOut("<span style='color:white;'>突破中技能: " + _("无", "無") + "</span>");
            YFUI.writeToOut("<span style='color:yellow;'>+------------------------------+</span>");
          }
          let lxSkill = g_obj_map.get("msg_attrs")?.get("practice_skill") || 0;
          if (lxSkill) {
            let sk = allSkills.find((s) => s.key == lxSkill);
            if (sk) {
              YFUI.writeToOut(
                "<span style='color:white;'>" + _("练习中的技能", "練習中技能") + ": <span style='color:#F0F;'>" + sk.name + "</span> (" + sk.level + ")</span>",
              );
              YFUI.writeToOut("<span style='color:yellow;'>+------------------------------+</span>");
            }
          } else {
            YFUI.writeToOut("<span style='color:white;'>" + _("练习中的技能:无", "練習中技能:無") + "</span>");
            YFUI.writeToOut("<span style='color:yellow;'>+------------------------------+</span>");
          }
        });
      }
    },
    //================================================================================================
    initSocketMsgEvent() {
      if (!gSocketMsg) {
        console.log("%c%s", "background:#C33;color:#FFF;", " ERROR:Not found gSocketMsg!! ");
        return;
      }
      var miGongNavi = new MiGongNavi();
      window.oldgSocketMsg2 = gSocketMsg2;
      gSocketMsg2.old_show_room = gSocketMsg2.show_room;
      gSocketMsg2.show_room = function () {
        gSocketMsg2.old_show_room();
        miGongNavi.Clear();
        switch (g_obj_map.get("msg_room").get("map_id")) {
          case "mojiajiguancheng":
            if (g_obj_map.get("msg_room").get("short") == _("墨攻禦阵", "墨攻禦陣") && g_obj_map.get("msg_room").get("south") == "雲海山谷") {
              miGongNavi.Append(_("机关城", "機關城"), "w;n;e;e;nw;w;ne;se;n;nw");
            }
            if (g_obj_map.get("msg_room").get("short") == _("变化道", "變化道") && g_obj_map.get("msg_room").get("west") == "神龍山") {
              miGongNavi.Append("石板大道", "n;e;s;e;n;nw;e;nw");
              miGongNavi.Append(_("盘龙湖", "盤龍湖"), "s;e;s;ne;s;sw;nw;s;se;s");
            }
            if (g_obj_map.get("msg_room").get("short") == _("变化道", "變化道") && g_obj_map.get("msg_room").get("northwest") == "石板大道") {
              miGongNavi.Append(_("神龙山", "神龍山"), "e;se;s;w");
            }
            if (g_obj_map.get("msg_room").get("short") == _("变化道", "變化道") && g_obj_map.get("msg_room").get("south") == "盤龍湖") {
              miGongNavi.Append(_("神龙山", "神龍山"), "nw;w;ne;n;w");
            }
            break;
          case "miaojiang":
            if (g_obj_map.get("msg_room").get("obj_p") == "4583") {
              miGongNavi.Append(_("江边小路", "江邊小路"), "sw;e;e;sw;se;sw");
            }
            if (g_obj_map.get("msg_room").get("obj_p") == "4540") {
              miGongNavi.Append(_("噬生沼泽", "噬生沼澤"), "s;s;e;n;n;e");
            }
            if (g_obj_map.get("msg_room").get("obj_p") == "4600") {
              miGongNavi.Append("上山小路", "s;e;ne;s;sw;e;e;ne");
            }
            if (g_obj_map.get("msg_room").get("obj_p") == "4568") {
              miGongNavi.Append(_("澜沧江南岸", "瀾滄江南岸"), "event_1_41385370;e;ne;nw;e;sw;se;s;ne;e;e;n;nw");
            }
            break;
          case "xiakedao":
            if (g_obj_map.get("msg_room").get("obj_p") == "4018") {
              miGongNavi.Append("平原平地", "e;s;s;s");
              miGongNavi.Append(_("养心居", "養心居"), "e;e;e;e");
              miGongNavi.Append("石壁", "e;s;n;e;s");
            }
            if (g_obj_map.get("msg_room").get("obj_p") == "3987") {
              miGongNavi.Append("土路", "n;w;w;w;s;w");
              miGongNavi.Append(_("养心居", "養心居"), "n;n;e;e");
              miGongNavi.Append("石壁", "n;w;n;e;s");
            }
            if (g_obj_map.get("msg_room").get("obj_p") == "4028") {
              miGongNavi.Append("平原平地", "w;s;s;s;s");
              miGongNavi.Append("土路", "w;w;w;w;s;w");
            }
            if (g_obj_map.get("msg_room").get("obj_p") == "3998") {
              miGongNavi.Append("平原平地", "n;e;s;s");
              miGongNavi.Append("土路", "n;w;w;s;w");
            }
            if (g_obj_map.get("msg_room").get("obj_p") == "3994") {
              miGongNavi.Append("山頂", "n;n;n;e;ne;nw");
              miGongNavi.Append("摩天崖", "n;e;e;ne");
              miGongNavi.Append("木屋", "n;n;n;w;w");
            }
            if (g_obj_map.get("msg_room").get("obj_p") == "3992") {
              miGongNavi.Append(_("后山山路", "後山山路"), "se;s;s;s");
            }
            if (g_obj_map.get("msg_room").get("obj_p") == "3980") {
              miGongNavi.Append(_("后山山路", "後山山路"), "sw;s;s;s");
            }
            if (g_obj_map.get("msg_room").get("obj_p") == "3982") {
              miGongNavi.Append(_("后山山路", "後山山路"), "e;s;s;s");
            }
            break;
          case "binghuo":
            if (g_obj_map.get("msg_room").get("obj_p") == "3931") {
              miGongNavi.Append("彩虹瀑布", "nw;s;s;s;s;s;s;e");
              miGongNavi.Append(_("雪松林海深处", "雪松林海深處"), "nw;s;s;s;s;s;s;w;w;n;e;n;w;w;s");
            }
            if (g_obj_map.get("msg_room").get("obj_p") == "3881") {
              miGongNavi.Append(_("雪松林海深处", "雪松林海深處"), "w;w;w;n;e;n;w;w;s");
              miGongNavi.Append(_("雪原温泉", "雪原溫泉"), "w;n;e;e;n;se");
            }
            if (g_obj_map.get("msg_room").get("obj_p") == "3930") {
              miGongNavi.Append("彩虹瀑布", "n;n;s;s;s;s;e");
              miGongNavi.Append(_("雪原温泉", "雪原溫泉"), "n;n;s;s;s;s;n;e;e;n;se");
            }
            break;
          case "wudang":
            if (g_obj_map.get("msg_room").get("short") == "山谷通道" && g_obj_map.get("msg_room").get("south") == "山谷口") {
              miGongNavi.Append(_("环山之地", "環山之地"), "sw;nw;w;ne");
            }
            break;
          case "baituo":
            if (g_obj_map.get("msg_room").get("short") == "密林" && g_obj_map.get("msg_room").get("north") == _("山庄大门", "山莊大門")) {
              miGongNavi.Append("正堂", "sw;s;ne;e;s;s");
            }
            if (g_obj_map.get("msg_room").get("short") == "戈壁" && g_obj_map.get("msg_room").get("north") == "戈壁") {
              miGongNavi.Append("天山", "jh 39");
            }
            break;
          case "tianshan":
            if (g_obj_map.get("msg_room").get("short") == "官道" && g_obj_map.get("msg_room").get("northeast") == "官道") {
              miGongNavi.Append(_("星星峡", "星星峽"), "ne;e;n;ne;ne;n;ne;nw;ne;nw;event_1_17801939");
            }
            if (g_obj_map.get("msg_room").get("obj_p") == "4448") {
              miGongNavi.Append(_("大漠深处", "大漠深處"), "s;s;sw;n;nw;e;sw");
            }
            if (g_obj_map.get("msg_room").get("short") == "雪谷" && g_obj_map.get("msg_room").get("southeast") == "雪谷") {
              miGongNavi.Append(_("失足岩", "失足巖"), "se;s;e;n;ne;nw;event_1_58460791");
              miGongNavi.Append(_("星星峡", "星星峽"), "se;s;e;n;ne;nw;ne;nw;event_1_17801939");
            }
            break;
          case "luoyang":
            if (g_obj_map.get("msg_room").get("obj_p") == "112") {
              miGongNavi.Append(_("五鼠广场", "五鼠廣場"), "n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n;n");
            }
            break;
          case "baidicheng":
            if (g_obj_map.get("msg_room").get("short") == _("岸边路", "岸邊路") && g_obj_map.get("msg_room").get("southeast") == _("岸边路", "岸邊路")) {
              miGongNavi.Append(_("璇玑宫", "璇璣宮"), "se;e;e;se;se;se;se;se;se;event_1_57976870;n;n;n;event_1_91914705");
            }
            break;
          case "haiyunge":
            if (g_obj_map.get("msg_room").get("short") == _("海运镇", "海運鎮") && g_obj_map.get("msg_room").get("north") == _("海运镇", "海運鎮")) {
              miGongNavi.Append(_("雪山山脚", "雪山山腳"), "n;n;n;n;w;n;nw;n;n;ne;n;n;e;n;n;n;n;e;n;n;n;n;n;w;w;n;n;n;n;n;n;e;e;e;e;e;e;s;e;e;ne;ne;e;se;se;se");
            }
            break;
          case "snow":
            if (g_obj_map.get("msg_room").get("obj_p") == "18") {
              var btn = '<button type="button" cellpadding="0" cellspacing="0" id="Choujiangbtn" class="cmd_click3"><font style="color:yellow">' + _('抽奖', '抽獎') + '</font></button>';
              $("#out .out .cmd_click3:first").before(btn).before("<br>");
              $("body").off("click", "#Choujiangbtn").on("click", "#Choujiangbtn",
                function () {
                  PLU.toChoujiang();	
                })
            }
            if (g_obj_map.get("msg_room").get("obj_p") == "47") {
              miGongNavi.Append(_("兑换刻刀", "兌換刻刀"), "event_1_58404606");		
            }
          case "nanzhaoguo":
            if (g_obj_map.get("msg_room").get("short") == _("忘忧酒馆", "忘憂酒館")) {
              miGongNavi.Append(_("洱海桥", "洱海橋"), "n;#5 e;#4 s;#2 e");
            }
            if (g_obj_map.get("msg_room").get("short") == _("洱海桥", "洱海橋") && g_obj_map.get("msg_room").get("east") == _("南蛮沼泽", "南蠻沼澤")) {
              miGongNavi.Append("密林", "e;e;e;se;ne;sw;nw;e;ne;e");
            }
            if (g_obj_map.get("msg_room").get("short") == "密林" && g_obj_map.get("msg_room").get("west") == _("南蛮沼泽", "南蠻沼澤")) {
              miGongNavi.Append(_("洱海桥", "洱海橋"), "w;w;se;n;nw;s;e;w;sw;w");
              miGongNavi.Append("巍山", "e;n;e;event_1_30634412;e;ne;e;e");
            }
            if (g_obj_map.get("msg_room").get("short") == "巍山山道" && g_obj_map.get("msg_room").get("west") == "巍山山道" && g_obj_map.get("msg_room").get("north") == "巍山山道" && g_obj_map.get("msg_room").get("south") == "巍山山道") {
              miGongNavi.Append("密林", "w;w;sw;w;event_1_69046360;w;s;s;w");
            }
            break;
          case "tangmen":
            if (g_obj_map.get("msg_room").get("obj_p") == "1372") {
              miGongNavi.Append(_("七杀剑阁", "七殺劍閣"), "sw;s;e;s;s;sw;sw;w;w;s;s;e;e;e;n;ne;e;se;");
            }
            break;
          case "murong":
            if (g_obj_map.get("msg_room").get("obj_p") == "3197") {
              miGongNavi.Append(_("孔府大门", "孔府大門"), "n;n;se;e;s;s;event_1_99232080;e;e;s;e;s;e;e;e")
            }
            break;
          case "huajie":
            if (g_obj_map.get("msg_room").get("short") == _("藏娇阁", "藏嬌閣")) {
              miGongNavi.Append(_("观舞", "觀舞"), "event_1_5392021 go")
            }
            if (g_obj_map.get("msg_room").get("short") == _("沁芳阁", "沁芳閣")) {
              miGongNavi.Append(_("观舞", "觀舞"), "event_1_48561012 go")
            }
            if (g_obj_map.get("msg_room").get("short") == _("凝香阁", "凝香閣")) {
              miGongNavi.Append(_("观舞", "觀舞"), "event_1_29896809 go")
            }
            break;
          case "ymsz_qianyuan":
            if (g_obj_map.get("msg_room").get("short") == _("幽冥山庄前院", "幽冥山莊前院")) {
              miGongNavi.Append(_("开始", "開始"), _("e;kill?绛衣杀手;e;kill?绛衣杀手;n;kill?绛衣剑客;s;s;kill?绛衣剑客;n;e;kill?绛衣杀手;e;kill?绛衣杀手;ne;kill?绛衣剑客;sw;s;kill?绛衣杀手;s;kill?绛衣杀手;s;kill?绛衣杀手;e;kill?巨鹏;", 
              "e;kill?絳衣殺手;e;kill?絳衣殺手;n;kill?絳衣劍客;s;s;kill?絳衣劍客;n;e;kill?絳衣殺手;e;kill?絳衣殺手;ne;kill?絳衣劍客;sw;s;kill?絳衣殺手;s;kill?絳衣殺手;s;kill?絳衣殺手;e;kill?巨鵬;"))
            }
            break;
          case "ymsz_huayuan":
            if (g_obj_map.get("msg_room").get("short") == _("幽冥山庄花园", "幽冥山莊花園")) {
              miGongNavi.Append(_("开始", "開始"), _("e;kill?白骨秀士;e;kill?白骨秀士;ne;kill?白骨秀士;nw;kill?血剑客;se;ne;kill?白骨秀士;ne;kill?血剑客;sw;se;kill?白骨秀士;se;kill?白骨秀士;e;kill?血剑客;w;sw;kill?白骨秀士;sw;kill?白骨秀士;se;kill?血剑客;nw;sw;kill?白骨秀士;sw;kill?宇文秀;", 
              "e;kill?白骨秀士;e;kill?白骨秀士;ne;kill?白骨秀士;nw;kill?血劍客;se;ne;kill?白骨秀士;ne;kill?血劍客;sw;se;kill?白骨秀士;se;kill?白骨秀士;e;kill?血劍客;w;sw;kill?白骨秀士;sw;kill?白骨秀士;se;kill?血劍客;nw;sw;kill?白骨秀士;sw;kill?宇文秀;"))
            }
            break;
          case "ymsz_houyuan":
            if (g_obj_map.get("msg_room").get("short") == _("幽冥山庄后院", "幽冥山莊後院")) {
              miGongNavi.Append(_("开始", "開始"), _("se;kill?鬼杀;se;kill?鬼杀;s;kill?鬼杀;w;kill?幽冥鬼杀;e;e;kill?幽冥鬼杀;w;s;kill?鬼杀;s;kill?鬼杀;s;kill?鬼杀;w;kill?幽冥鬼杀;e;e;kill?鬼杀;s;kill?幽冥鬼杀;n;e;kill?鬼杀;e;kill?鬼杀;n;kill?幽冥鬼杀;s;e;kill?鬼杀;e;kill?鬼杀;n;kill?石幽冥;", 
              "se;kill?鬼殺;se;kill?鬼殺;s;kill?鬼殺;w;kill?幽冥鬼殺;e;e;kill?幽冥鬼殺;w;s;kill?鬼殺;s;kill?鬼殺;s;kill?鬼殺;w;kill?幽冥鬼殺;e;e;kill?鬼殺;s;kill?幽冥鬼殺;n;e;kill?鬼殺;e;kill?鬼殺;n;kill?幽冥鬼殺;s;e;kill?鬼殺;e;kill?鬼殺;n;kill?石幽冥;"))
            }
            break;
          case "bajieshendian":
            if (g_obj_map.get("msg_room").get("short") == "初心之地") {
              miGongNavi.Append(_("开始", "開始"), _("n;kill?食圣易牙;s;ne;kill?杀圣冉闵;sw;e;kill?盗圣温韬;w;se;kill?邪圣夜叉;nw;s;kill?【胡说】商宝震;n;sw;kill?酒仙李白;ne;w;kill?隋炀帝杨广;e;nw;kill?万历帝朱翊钧;nw;kill?陈抟老祖;se;se;n;n;kill?食神彭祖;s;s;ne;ne;kill?杀神白起;sw;sw;e;e;kill?盗神五道将军;w;w;se;se;kill?邪神刑天;nw;nw;s;s;kill?【八道】马行空;n;n;sw;sw;kill?酒神仪狄;ne;ne;w;w;kill?秦始皇嬴政;wait?20;kill?乱之心魔;event_1_68529291;", 
              "n;kill?食聖易牙;s;ne;kill?殺聖冉閔;sw;e;kill?盜聖溫韜;w;se;kill?邪聖夜叉;nw;s;kill?【胡說】商寶震;n;sw;kill?酒仙李白;ne;w;kill?隋煬帝楊廣;e;nw;kill?萬歷帝朱翊鈞;nw;kill?陳摶老祖;se;se;n;n;kill?食神彭祖;s;s;ne;ne;kill?殺神白起;sw;sw;e;e;kill?盜神五道將軍;w;w;se;se;kill?邪神刑天;nw;nw;s;s;kill?【八道】馬行空;n;n;sw;sw;kill?酒神儀狄;ne;ne;w;w;kill?秦始皇嬴政;wait?20;kill?亂之心魔;event_1_68529291;"))
            }
            break;;
          case "taohua":
            if (g_obj_map.get("msg_room").get("obj_p") == "3073") {
              miGongNavi.Append(_("巨石阵", "巨石陣"), "event_1_84563112;s;sw;s;w;n;nw;w;sw;nw;n")
            }
            break;
          };
          // 地圖對齊
          if (g_obj_map.get("msg_room").get("type") == "jh" && g_obj_map.get("msg_room").get("subtype") == "info") {
            $("#out .out table:eq(1)").closest("table").attr("id", "centertr");
          
            let textAndColors = [];	
            let combinedText = '  ';
            var spantext = $("#centertr").prevUntil("hr")
          
            if (spantext.length > 1) {
              spantext.each((index, element) =>  {
                const sText = $(element).text();
                const sColor = $(element).css('color');
                textAndColors.push({text: sText, color: sColor});
                combinedText += `<span style="color: ${sColor}">${sText}</span>`;
                $(element).remove();
              });
              $("#out .out").html($("#out .out").html().replace("&nbsp;&nbsp;&nbsp;", ""));
            } else {
              spantext.first().remove();
              $("#out .out").html($("#out .out").html().replace("&nbsp;&nbsp;&nbsp;" + g_obj_map.get("msg_room").get("long"), ""));
              combinedText = "&nbsp;&nbsp;&nbsp" + g_obj_map.get("msg_room").get("long");
            };		
            const $newDiv = $('<div>').html(combinedText).css({
              'overflow-y': 'scroll',
              'overflow-x': 'hidden',
              'height': '80px',
            });

            $('#centertr').before($newDiv);
            
            var centertr = $("#out .out table:eq(1) td:has(.cmd_click_room)").parent("tr");
            if (centertr.prev().length == 0) {
              centertr.before("<tr><td></td><td></td><td></td></tr>")
            }
            if (centertr.next().length == 0) {
              centertr.after("<tr><td></td><td></td><td></td></tr>")
            }
            $("#out .out table:eq(1) td").css({
              "width": $(".cmd_click_room").width(),
              "height": $(".cmd_click_room").height()
            })
                return;
            }
        };
      gSocketMsg2.old_show_items = gSocketMsg2.show_items;
      gSocketMsg2.show_items = function (b) {
        gSocketMsg2.old_show_items(b);
        $(".out table:eq(1) tbody:eq(0) td:eq(0)").css("vertical-align", "top");
        var cangkuclone = $(".out table:eq(1) table:eq(1) tr[onclick]").clone();
        cangkuclone = cangkuclone.sort(function (a, b) {
          return ansi_up.ansi_to_text($(a).text()) > ansi_up.ansi_to_text($(b).text()) ? 1 : -1
        });
        $(".out table:eq(1) table:eq(1) tr[onclick]").remove();
        $(".out table:eq(1) table:eq(1)").prepend(cangkuclone);

        // var baoclone = $(".out table:eq(1) table:eq(0) tr[onclick]").clone();
        // baoclone = baoclone.sort(function (a, b) {
        //     return ansi_up.ansi_to_text($(a).text()) > ansi_up.ansi_to_text($(b).text()) ? 1 : -1
        // });
        // $(".out table:eq(1) table:eq(0) tr[onclick]").remove();
        // $(".out table:eq(1) table:eq(0)").prepend(baoclone);

        if ($("#items-div #items-zhengli1").length == 0) {
          $("#out .out table:first").after("<div id='items-div'><button id='items-zhengli1' class='cmd_click3'><span class='out2'>整理背包</span></button><button id='wine_make1' class='cmd_click3'><span class='out2'>釀造汾酒</span></button><button id='wine_make2' class='cmd_click3'><span class='out2'>釀茉莉花韻酒</span></button><button id='wine_make3' class='cmd_click3'><span class='out2'>釀九花醉月酒</span></button><button id='items-huangjin' class='cmd_click3'><span class='out2'>開黃金</span></button><button id='items-bojin' class='cmd_click3'><span class='out2'>開鉑金</span></button><button id='items-yaoyu' class='cmd_click3'><span class='out2'>開曜玉</span></button><button id='items-chili' class='cmd_click3'><span class='out2'>開赤璃</span></button></div>");
          $("#items-div #items-zhengli1").off("click").on("click",
            function () {
              // 入庫
              var stores = g_obj_map.get("msg_items").elements.filter(function (item) {
                return item.key.indexOf("stores") > -1
              });
              var items = g_obj_map.get("msg_items").elements.filter(function (item) {
                return item.key.indexOf("items") > -1
              });
              let put_val = "";
              for (var i = 0; i < stores.length; i++) {
                var name = stores[i].value.split(",")[1];
                var sameitems = items.filter(function (item) {
                  return item.value.indexOf("," + name + ",") > -1
                });
                for (var j = 0; j < sameitems.length; j++) {
                  put_val += ("items put_store " + sameitems[j].value.split(",")[0] + ";")
                }
              };
              // 出售
              let sell_val = 
              _("破烂衣服,水草,木盾,铁盾,藤甲盾,青铜盾,鞶革,军袍,麻带,破披风,长斗篷,牛皮带,锦缎腰带,丝质披风,逆钩匕,匕首,铁甲,重甲,精铁甲,逆钩匕,银丝甲,梅花匕,软甲衣,羊角匕,金刚杖,白蟒鞭,天寒项链,天寒手镯,新月棍,天寒戒,天寒帽,天寒鞋,金弹子,拜月掌套,玄武盾,破军盾,金丝宝甲衣,夜行披风,羊毛斗篷,残雪戒,残雪项链,残雪手镯,残雪鞋,残雪帽,金丝甲,宝玉甲,月光宝甲,虎皮腰带,沧海护腰,红光匕,毒龙鞭,玉清棍,霹雳掌套,疯魔杖,星河剑,金狮盾,白玉腰束,天寒匕,无心匕,生死符,血屠刀,貂皮斗篷,红色长衫,船篙,全真道袍,钢杖,草帽,铁戒,斩空刀,竹剑,布衣,单刀,铁项链,桃符纸,绣花针,锦衣,水烟阁司事帽,阿拉伯弯刀,桃木剑,铁手镯,长剑,丝绸衣,长斗篷", 
              "破爛衣服,水草,木盾,鐵盾,藤甲盾,青銅盾,鞶革,軍袍,麻帶,破披風,長斗篷,牛皮帶,錦緞腰帶,絲質披風,逆鉤匕,匕首,鐵甲,重甲,精鐵甲,逆鉤匕,銀絲甲,梅花匕,軟甲衣,羊角匕,金剛杖,白蟒鞭,天寒項鏈,天寒手鐲,新月棍,天寒戒,天寒帽,天寒鞋,金彈子,拜月掌套,玄武盾,破軍盾,金絲寶甲衣,夜行披風,羊毛鬥篷,殘雪戒,殘雪項鏈,殘雪手鐲,殘雪鞋,殘雪帽,金絲甲,寶玉甲,月光寶甲,虎皮腰帶,滄海護腰,紅光匕,毒龍鞭,玉清棍,霹靂掌套,瘋魔杖,星河劍,金獅盾,白玉腰束,天寒匕,無心匕,生死符,血屠刀,貂皮鬥篷,紅色長衫,船篙,全真道袍,鋼杖,草帽,鐵戒,斬空刀,竹劍,布衣,單刀,鐵項鏈,桃符紙,繡花針,錦衣,水煙閣司事帽,阿拉伯彎刀,桃木劍,鐵手鐲,長劍,絲綢衣,長鬥篷");
              let str = $.trim(sell_val);
              PLU.setCache("sellItemNames", str);
              let keysList = str.split(",");
              let itemsTimeOut = setTimeout(() => {
                UTIL.delSysListener("listItems");
              }, 5000);
              UTIL.addSysListener("listItems", function (b, type, subtype, msg) {
                if (type != "items") return;
                UTIL.delSysListener("listItems");
                clearTimeout(itemsTimeOut);
                let iId = 1,
                  itemList = [];
                while (b.get("items" + iId)) {
                  let it = UTIL.filterMsg(b.get("items" + iId)).split(",");
                  if (it && it.length > 4 && it[3] == "0" && keysList.includes(it[1]))
                    itemList.push({
                      key: it[0],
                      name: it[1],
                      num: Number(it[2]),
                    });
                  iId++;
                }
                PLU.loopSortItems(put_val,itemList);
              });
            clickButton("items", 0);
            });
          $("#items-div #wine_make1").off("click").on("click",
            function () {
              PLU.execActions("event_1_20635853");
            });
          $("#items-div #wine_make2").off("click").on("click",
            function () {
              PLU.execActions("event_1_85652966");
            });
          $("#items-div #wine_make3").off("click").on("click",
            function () {
              PLU.execActions("event_1_62174415");
            });
          $("#items-div #items-huangjin").off("click").on("click",
            function () {
              PLU.openXiang(_("黄金宝箱", "黃金寶箱"), _("黄金钥匙", "黃金鑰匙"));
            });
          $("#items-div #items-bojin").off("click").on("click",
            function () {
              PLU.openXiang(_("铂金宝箱", "鉑金寶箱"), _("铂金钥匙", "鉑金鑰匙"));
            });
          $("#items-div #items-yaoyu").off("click").on("click",
            function () {
              PLU.openXiang(_("曜玉宝箱", "曜玉寶箱"), _("曜玉钥匙", "曜玉鑰匙"));
            });
          $("#items-div #items-chili").off("click").on("click",
            function () {
              PLU.openXiang(_("赤璃宝箱", "赤璃寶箱"), _("赤璃钥匙", "赤璃鑰匙"));
            });
          }
      };
      gSocketMsg2.old_show_item_info = gSocketMsg2.show_item_info;
      gSocketMsg2.show_item_info = function () {
        gSocketMsg2.old_show_item_info();
        var item = g_obj_map.get("msg_item");
        var foundsplit = false;
        var founduse = false;
        var foundhecheng = false;
        var foundhechengys = false;
        var foundsellall = false;
        var foundmoke = false;
        if (item) {
          for (var i = 1; i <= item.size(); i++) {
            if (item.containsKey("cmd" + i) && item.get("cmd" + i).indexOf("client_prompt items splite") == 0) {
                foundsplit = true;
                continue
            }
            if (item.containsKey("cmd" + i) && item.get("cmd" + i).indexOf("items use") == 0 && !item.containsValue("use_all")) {
                founduse = true;
                continue
            }
            if (item.containsKey("cmd" + i) && item.get("cmd" + i).indexOf("moke ") >= 0) {
                foundmoke = true;
                continue
            }
          }
          if (foundmoke) {
            if ($("#out .out table:last tr:last td").length == 4) {
              $("#out .out table:last").append('<tr algin="center"></tr>')
            }
            $("#out .out table:last tr:last").append('<td align="center"><button id="foundmoke" type="button" class="cmd_click2">全部<br>摩刻</button></td>')
          }
          if (foundsplit) {
            if ($("#out .out table:last tr:last td").length == 4) {
              $("#out .out table:last").append('<tr algin="center"></tr>')
            }
            $("#out .out table:last tr:last").append('<td align="center"><button id="foundsplit" type="button" class="cmd_click2">全部<br>分解</button></td>')
          }
          if (founduse) {
            if ($("#out .out table:last tr:last td").length == 4) {
              $("#out .out table:last").append('<tr algin="center"></tr>')
            }
            $("#out .out table:last tr:last").append('<td align="center"><button id="founduse" type="button" class="cmd_click2">全部<br>使用</button></td>')
          }
          $("#foundmoke").off("click").on("click",
            function () {
              let id = item.get("id");
              let amount = item.get("amount");
              PLU.execActions("#" + amount + ' ' + "moke " + id + ";");
            });
          $("#foundsplit").off("click").on("click",
            function () {
              let id = item.get("id");
              let amount = item.get("amount");
              let cmds = "";
              if (amount > 100) {
                var useTimes = amount / 100;
                var useLeast = amount % 100;
                useTimes = parseInt(useTimes);
                for (var i = 0; i < useTimes; i++) {
                  cmds += ('items splite ' + id + '_N_100;');
                }
                if (useLeast > 0) {
                  cmds += ('items splite ' + id + '_N_' + useLeast + ";");
                }
              } else {
                cmds += ('items splite ' + id + '_N_' + amount + ";");
              }
              PLU.execActions(cmds);
            });
          $("#founduse").off("click").on("click",
            function () {
              let id = item.get("id");
              let amount = item.get("amount");
              let useLeast = amount % 1000;
              PLU.execActions('items use ' + id + '_N_' + amount);
              let listenItemNoticeTimeOut = setTimeout(() => {
                UTIL.delSysListener("listenItemNotice");
              }, 5000);
              UTIL.addSysListener("listenItemNotice", function (b, type, subtype, msg) {
                if (type != "notice") return;
                let msgTxt = UTIL.filterMsg(msg);
                UTIL.delSysListener("listenItemNotice");
                clearTimeout(listenItemNoticeTimeOut);
                if (msgTxt.match("不能一次使用多")) {
                  PLU.execActions("#" + amount + ' ' + "items use " + id + ";");
                } else {
                  if (amount > 1000) {
                    let useTimes = amount / 1000;
                    useTimes = parseInt(useTimes);
                    if (useTimes > 0) {
                      PLU.execActions("#" + useTimes + " items use " + id + "_N_1000;"); 
                    };
                  }
                }
              });
              clickButton("items", 0);
            });
         }
      }
      gSocketMsg.YFBackupDispatchMsg = gSocketMsg.dispatchMessage;
      gSocketMsg.dispatchMessage = (b) => {
        gSocketMsg.YFBackupDispatchMsg(b);
        let type = b.get("type");
        let subtype = b.get("subtype");
        let msg = b.get("msg");
        UTIL.sysDispatchMsg(b, type, subtype, msg);
      };
      gSocketMsg.change_skill_button = function (m, is_del) {
        var m_vs_info = g_obj_map.get("msg_vs_info"),
          m2 = g_obj_map.get("msg_attrs");
        if (!m_vs_info || !m2) return 0;
        if (is_del) {
          g_obj_map.remove("skill_button" + is_del);
          return 1;
        }
        var id = this.get_combat_user_id();
        if (id != m.get("uid")) return 0;
        var pos = parseInt(m.get("pos"));
        if (pos <= 0 || pos > this._skill_btn_cnt) return 0;
        g_obj_map.put("skill_button" + pos, m);
        this.refresh_skill_button();
      };
      PLU.initListeners();
      if (g_gmain.is_fighting) {
        PLU.STATUS.inBattle = 1;
        if (!PLU.battleData)
          PLU.battleData = {
            skills: {},
            xdz: 12,
            mySide: "vs1",
            performTime: 0,
            cureTimes: 0,
          };

        PLU.TMP.loopUseSkill = setInterval(() => {
          PLU.checkUseSkills();
        }, 250);
      }
      if (unsafeWindow.clickButton) {
        PLU.Base64 = new Base64();
        var proxy_clickButton = unsafeWindow.clickButton;
        unsafeWindow.clickButton = function () {
          let args = arguments;
          if (PLU.developerMode) {
            console.log(args);
          }
          // 指令录制
          if (
            PLU.TMP.cmds &&
            !g_gmain.is_fighting &&
            ["attrs", "none", "jh", "fb", "prev_combat", "home_prompt", "jhselect", "fbselect", "send_chat"].indexOf(args[0]) < 0 &&
            args[0].indexOf("look_npc ") &&
            !args[0].match(/^(jh|fb)go /) &&
            args[0].indexOf("go_chat")
          ) {
            if (
              args[0].indexOf("go southeast.") == 0 ||
              args[0].indexOf("go southwest.") == 0 ||
              args[0].indexOf("go northeast.") == 0 ||
              args[0].indexOf("go northwest.") == 0
            )
              PLU.TMP.cmds.push(args[0][3] + args[0][8]);
            else if (args[0].indexOf("go east.") == 0 || args[0].indexOf("go west.") == 0 || args[0].indexOf("go south.") == 0 || args[0].indexOf("go north.") == 0)
              PLU.TMP.cmds.push(args[0][3]);
            else PLU.TMP.cmds.push(args[0]);
          }
          if (args[0].indexOf("ask ") == 0) {
            UTIL.addSysListener("ask", (b, type, subtype, msg) => {
              if ((type == "jh" && subtype == "info") || UTIL.inHome()) {
                UTIL.delSysListener("ask");
              }
              if (type != "main_msg" || msg.indexOf(_("嗯,相遇即是缘,你是练武奇才,我送点东西给你吧。", "嗯,相遇即是緣,你是練武奇才,我送點東西給你吧。")) == -1) return;
              proxy_clickButton(args[0]);
              UTIL.delSysListener("ask");
            });
            setTimeout(() => {
              UTIL.delSysListener("ask");
            }, 500);
            proxy_clickButton(args[0]);
          }
          // 解除聊天屏蔽,對非腳本玩家可用
          else if (PLU.developerMode && args[0].indexOf("chat ") == 0) {
            let msg = args[0].substring(5);
            for (var PATTERN of KEYWORD_PATTERNS) msg = msg.replace(PATTERN, (s) => Array.from(s).join("\f"));
            proxy_clickButton("chat " + msg);
          }
          // 解除四海商店限制
          else if ((args[0].indexOf("reclaim recl ") == 0 || args[0].indexOf("reclaim buy ") == 0) && !args[0].match(" page ")) {
            var cmd = args[0].match(/^reclaim (recl|buy) (\d+) (go )?(.+)$/);
            if (cmd[1]) {
              var n = Number(cmd[2]);
              switch (cmd[1]) {
                case "recl":
                  for (; n > 50000; n -= 50000) {
                    proxy_clickButton("reclaim recl 50000 go ".concat(cmd[4]), 1);
                  }
                  proxy_clickButton("reclaim recl ".concat(n, " go ").concat(cmd[4]), 1);
                  break;
                case "buy":
                  for (; n > 50000; n -= 50000) {
                    proxy_clickButton("reclaim buy 50000 go ".concat(cmd[4]), 1);
                  }
                  proxy_clickButton("reclaim buy ".concat(n, " go ").concat(cmd[4]), 1);
                  break;
              }
            }
          } else {
            proxy_clickButton(...args);
          }
          if (PLU.TMP.leaderTeamSync) {
            PLU.commandTeam(args);
          }
        };
      }
    },

    //================================================================================================
    initMenu() {
      YFUI.init();
      YFUI.addBtn({
        id: "ro",
        text: _("▲隐", "▲隱"),
        style: {
          width: "30px",
          opacity: ".6",
          background: "#333",
          color: "#FFF",
          border: "1px solid #CCC",
          borderRadius: "8px 0 0 0",
        },
        onclick($btn) {
          $("#pluginMenus").toggle();
          $("#pluginMenus").is(":hidden") ? $btn.text(_("▼显", "▼顯")) : $btn.text(_("▲隐", "▲隱"));
          $(".menu").hide();
        },
      });
      YFUI.addBtnGroup({ id: "pluginMenus" });
      //Paths
      let PathsArray = [];
      PathsArray.push({
        id: "bt_home",
        groupId: "pluginMenus",
        text: _("首页", "首頁"),
        style: { background: "#FFFF99", padding: "5px 2px", width: "40px" },
        onclick(e) {
          $(".menu").hide();
          PLU.STATUS.isBusy = false;
          clickButton("home", 1);
        },
      });
      let citysArray = PLU.YFD.cityList.map(function (c, i) {
        return {
          id: "bt_jh_" + (i + 1),
          text: c,
          extend: "jh " + (i + 1)
        };
      });
      PathsArray.push({
        id: "bt_citys",
        text: _("地图", "地圖"),
        style: {
          background: "#FFE",
          width: "40px",
          padding: "5px 2px"
        },
        menuStyle: {
          width: "240px",
          "margin-top": "-25px"
        },
        children: citysArray
      });
      let qlArray = PLU.YFD.qlList.map((p, i) => {
        return {
          id: "bt_ql_" + (i + 1),
          text: p.n,
          extend: { func: () => PLU.execActions(PLU.minPath(PLU.queryRoomPath(), p.v)) },
          style: { "background-color": "#CFF" },
        };
      });
      if (PLU.developerMode)
        qlArray.push({
          id: "bt_ql_xunluo",
          text: _("巡逻", "巡邏"),
          extend: { func: PLU.qlxl },
          style: { "background-color": "#CFF" },
        });
      PathsArray.push({
        id: "bt_qls",
        text: _("青龙", "青龍"),
        style: { background: "#DFF", width: "40px", padding: "5px 2px" },
        menuStyle: { width: "160px", "margin-top": "-50px" },
        children: qlArray,
      });

      let mjArray = PLU.YFD.mjList.map((p, i) => {
        return {
          id: "bt_mj_" + (i + 1),
          text: p.n,
          extend: p.v,
          style: { "background-color": "#EFD" },
        };
      });
      PathsArray.push({
        id: "bt_mjs",
        text: "秘境",
        style: { background: "#EFD", width: "40px", padding: "5px 2px" },
        menuStyle: { width: "160px", "margin-top": "-75px" },
        children: mjArray,
      });
      PLU.autoChushi = () => {
        let family = g_obj_map.get("msg_attrs") && g_obj_map.get("msg_attrs").get("family_name");
        let master = PLU.YFD.masterList.slice(0, 32).find((e) => e.in == family);
        if (master == undefined) return;
        let npc = PLU.queryNpc("^" + master.npc.slice(-1)[0] + "$", true);
        if (!npc.length) return;
        let way = npc[0].way;
        //PLU.ONOFF["bt_kg_teamSync"] = 0;
        PLU.execActions(way, () => {
          let npc = UTIL.findRoomNpcReg("^" + master.npc.slice(-1)[0] + "$");
          if (!npc) return;
          let key = npc.key;
          PLU.execActions("apprentice " + key, () => {
            PLU.autoFight({
              targetKey: key,
              fightKind: "fight",
              autoSkill: "multi",
              onEnd() {
                PLU.execActions("chushi " + key, () => {
                  if (family == _("铁雪山庄", "鐵雪山莊")) PLU.execActions("chushi resort_master");
                });
              },
              onFail() {
                PLU.autoFight({
                  targetKey: key,
                  fightKind: "chushi",
                  autoSkill: "multi",
                  onEnd() {
                    PLU.execActions("chushi " + key);
                  },
                });
              },
            });
          });
        });
      };
      let masterArray = PLU.YFD.masterList.map((p, i) => {
        if (i == 32)
          return {
            id: "bt_master_33",
            text: p.n,
            extend: p.v,
            style: {
              "background-color": "#FBB",
              width: "88px",
              padding: "5px 2px",
            },
          };
        let colr = i < 10 ? "#FCF" : i < 20 ? "#CFF" : "#FFC";
        return {
          id: "bt_master_" + (i + 1),
          text: p.n,
          children: (() => {
            if (!PLU.developerMode) return [];
            return [
              {
                id: "bt_master_" + (i + 1) + "_0",
                text: "拜入" + p.n,
                extend: {
                  func: () => send_prompt(_("是否确定要加入", " 是否確定要加入") + p.in + "\n\n\n\n", "home apprentice " + p.in, _("确定", "確定"), 0),
                },
                style: { "background-color": colr },
              },
            ];
          })().concat(
            p.npc.map((name, j) => {
              return {
                id: "bt_master_" + (i + 1) + "_" + (j + 1),
                text: name.split("@").slice(-1)[0],
                extend: PLU.queryNpc(name + "道", true)[0].way,
                style: { "background-color": colr },
              };
            }),
          ),
          style: {
            "background-color": colr,
            width: "40px",
            padding: "5px 2px",
          },
          menuStyle: (function () {
            if (i & 1) return { right: "101px", width: "160px" };
            return { width: "160px" };
          })(),
        };
      });
      PathsArray.push({
        id: "bt_masters",
        text: _("师门", "師門"),
        style: { background: "#FCF", width: "40px", padding: "5px 2px" },
        menuStyle: { width: "96px", "margin-top": "-125px" },
        children: masterArray,
      });

      let dailyArray = PLU.YFD.dailyList.map((p, i) => {
        let colr = i < 6 ? "#FFC" : i < 22 ? "#FCF" : "#CFF";
        return {
          id: "bt_daily_" + (i + 1),
          text: p.n,
          extend: p.v,
          style: { "background-color": colr },
        };
      });
      PathsArray.push({
        id: "bt_daily",
        text: "日常",
        style: { background: "#FED", width: "40px", padding: "5px 2px" },
        menuStyle: { width: "160px", "margin-top": "-125px" },
        children: dailyArray,
      });

      let usualArray = PLU.YFD.usualList.map((p, i) => {
        let sty = p.style || { "background-color": "#CDF" };
        return {
          id: "bt_usual_" + (i + 1),
          text: p.n,
          extend: p.v,
          style: sty,
        };
      });
      PathsArray.push({
        id: "bt_usual",
        text: "常用",
        style: { background: "#CDF", width: "40px", padding: "5px 2px" },
        menuStyle: { width: "160px", "margin-top": "-150px" },
        children: usualArray,
      });

      let cts = [],
        libCity = PLU.YFD.mapsLib.Npc.filter((e) => {
          if (!cts.includes(e.jh)) {
            cts.push(e.jh);
            return true;
          }
          return false;
        }).map((e) => e.jh);
      let queryJHMenu = libCity.map((c, i) => {
        return {
          id: "bt_queryjh_" + (i + 1),
          text: c,
          style: {
            width: "50px",
            whiteSpace: "nowrap",
            overflow: "hidden",
            fontSize: "12px",
          },
          extend: { func: PLU.queryJHMenu, param: c },
        };
      });
      let queryArray = [
        {
          id: "bt_queryJHList",
          text: _("章节", "章節"),
          children: queryJHMenu,
          style: { width: "40px", "background-color": "#9ED" },
          menuStyle: { width: "180px", "margin-top": "-180px" },
        },
        {
          id: "bt_queryHistory",
          text: _("历史", "歷史"),
          style: { width: "40px", "background-color": "#FDD" },
          extend: { func: PLU.toQueryHistory },
        },
        {
          id: "bt_queryNpc",
          text: _("寻人", "尋人"),
          style: { width: "40px", "background-color": "#FDD" },
          extend: { func: PLU.toQueryNpc },
        },
        {
          id: "bt_pathNpc",
          text: _("扫图", "掃圖"),
          style: { width: "40px", "background-color": "#FE9" },
          extend: { func: PLU.toPathNpc },
        },
      ];
      if (PLU.developerMode) {
        queryArray.push({
          id: "bt_pathNpc",
          text: _("谜题", "謎題"),
          style: { width: "40px", "background-color": "#FE9" },
          extend: { func: PLU.toQueryMiTi },
        });
      }
      PathsArray.push({
        id: "bt_query",
        text: "查找",
        style: { background: "#9ED", width: "40px", padding: "5px 2px" },
        menuStyle: { "margin-top": "-30px" },
        children: queryArray,
      });
      YFUI.addMenu({
        id: "m_paths",
        groupId: "pluginMenus",
        text: _("导航", "導航"),
        style: { background: "#CCFFFF", width: "40px", padding: "5px 2px" },
        multiCol: true,
        menuStyle: { width: "80px", "margin-top": "-25px" },
        children: PathsArray,
        onclick($btn, $box) {
          if ($btn.$extend) {
            $(".menu").hide();
            if ($btn.$extend.func) {
              if ($btn.$extend.param) $btn.$extend.func($btn, $btn.$extend.param);
              else $btn.$extend.func($btn);
              return;
            }
            PLU.execActions($btn.$extend, () => {
              if ($btn.text() == "去哈日") PLU.goHaRi();
              if ($btn.text() == "杭界山") PLU.goHJS();
            });
            // clickButton($btn.$extend)
          }
        },
      });
      let somethingArray = [];
      somethingArray.push({
        id: "bt_autoTeach",
        text: _("传授技能", "傳授技能"),
        extend: { func: PLU.toAutoTeach },
        style: { background: "#BFF" },
      });
      somethingArray.push({
        id: "bt_autoUpgrade",
        text: _("升级游侠", "升級遊俠"),
        extend: { func: PLU.toAutoUpgrade },
        style: { background: "#BFF" },
      });
      somethingArray.push({
        id: "hr_null2",
        text: "",
        style: { display: "none" },
        boxStyle: { display: "block", height: "5px" },
      });
      somethingArray.push({
        id: "bt_autoLearn",
        text: _("一键学习", "一鍵學習"),
        extend: { func: PLU.toAutoLearn },
        style: { background: "#FBF" },
      });
      somethingArray.push({
        id: "bt_autoChuaiMo",
        text: _("自动揣摩", "自動揣摩"),
        extend: { func: PLU.toAutoChuaiMo },
        style: { background: "#FBF" },
      });
      somethingArray.push({
        id: "hr_null2",
        text: "",
        style: { display: "none" },
        boxStyle: { display: "block", height: "5px" },
      });
      somethingArray.push({
        id: "bt_loopScript",
        text: _("循环执行", "循環執行"),
        extend: { func: PLU.toLoopScript },
        style: { background: "#FBB" },
      });
      somethingArray.push({
        id: "bt_loopKillByN",
        text: _("计数击杀", "計數擊殺"),
        extend: { func: PLU.toLoopKillByN },
        style: { background: "#FBB" },
      });
      somethingArray.push({
        id: "bt_waitCDKill",
        text: _("倒计时杀", "倒計時殺"),
        extend: { func: PLU.toWaitCDKill },
        style: { background: "#FBB" },
      });

      somethingArray.push({
        id: "bt_loopKillName",
        text: _("名字连杀", "名字連殺"),
        extend: { func: PLU.toLoopKillName },
        style: { background: "#FBB" },
      });
      somethingArray.push({
        id: "bt_loopClick",
        text: _("自动点击", "自動點擊"),
        extend: { func: PLU.toLoopClick },
        style: { background: "#FBB" },
      });
      somethingArray.push({
        id: "bt_loopSlowClick",
        text: _("慢速点击", "慢速點擊"),
        extend: { func: PLU.toLoopSlowClick },
        style: { background: "#FBB" },
      });
      somethingArray.push({
        id: "bt_record",
        text: _("自动练习", "自動練習"),
        extend: { func: PLU.toAutoLianXi },
        style: { background: "#FBB" },
      });
      somethingArray.push({
        id: "bt_record",
        text: _("指令录制", "指令錄製"),
        extend: { func: PLU.toRecord },
        style: { background: "#FBB" },
      });
      somethingArray.push({
        id: "hr_null2",
        text: "",
        style: { display: "none" },
        boxStyle: { display: "block", height: "5px" },
      });
      somethingArray.push({
        id: "bt_sellLaji",
        text: "批量出售",
        extend: { func: PLU.toSellLaji },
        style: { background: "#DEF" },
      });
      somethingArray.push({
        id: "bt_splitItem",
        text: "批量分解",
        extend: { func: PLU.toSplitItem },
        style: { background: "#DEF" },
      });
      somethingArray.push({
        id: "bt_putStore",
        text: _("批量入库", "批量入庫"),
        extend: { func: PLU.toPutStore },
        style: { background: "#DEF" },
      });
      somethingArray.push({
        id: "bt_autoUse",
        text: "批量使用",
        extend: { func: PLU.toAutoUse },
        style: { background: "#DEF" },
      });
      somethingArray.push({
        id: "bt_combineGem",
        text: _("合成宝石", "合成寶石"),
        extend: { func: PLU.openCombineGem },
        style: { background: "#DEF" },
      });
      somethingArray.push({
        id: "bt_autoMasterGem",
        text: _("一键合天神", "一鍵合天神"),
        extend: { func: PLU.autoMasterGem },
        style: { background: "#DEF" },
      });
      somethingArray.push({
        id: "hr_null2",
        text: "",
        style: { display: "none" },
        boxStyle: { display: "block", height: "5px" },
      });
      somethingArray.push({
        id: "bt_autoXTL1",
        text: "刷琅嬛玉洞",
        extend: { func: PLU.autoXTL1 },
        style: { background: "#FED" },
      });
      somethingArray.push({
        id: "bt_autoXTL2",
        text: "刷山崖",
        extend: { func: PLU.autoXTL2 },
        style: { background: "#FED" },
      });
      somethingArray.push({
        id: "bt_autoERG",
        text: _("刷恶人谷", "刷惡人谷"),
        extend: { func: PLU.autoERG },
        style: { background: "#FED" },
      });
      if (PLU.developerMode)
        somethingArray.push({
          id: "bt_searchBangQS",
          text: _("扫暴击", "掃暴擊"),
          extend: { func: PLU.scanPuzzle },
          style: { background: "#BBF" },
        });
      somethingArray.push({
        id: "hr_null2",
        text: "",
        style: { display: "none" },
        boxStyle: { display: "block", height: "5px" },
      });
      somethingArray.push({
        id: "bt_autoGetKey",
        text: _("自动捡钥匙", "自動撿鑰匙"),
        extend: { func: PLU.toAutoGetKey },
        style: { background: "#EBC" },
      });
      somethingArray.push({
        id: "bt_autoMoke",
        text: _("一键摹刻", "一鍵摹刻"),
        extend: { func: PLU.toAutoMoke },
        style: { background: "#EFD" },
      });
      somethingArray.push({
        id: "bt_autoKillZYY",
        text: "刷祝玉妍",
        extend: { func: PLU.toAutoKillZYY },
        style: { background: "#FBF" },
      });
      somethingArray.push({
        id: "bt_autoJHYL",
        text: "九花原料",
        extend: { func: PLU.buyJHYL },
        style: { background: "#DEF" },
      });
      somethingArray.push({
        id: "bt_checkYouxia",
        text: _("技能检查", "技能檢查"),
        extend: { func: PLU.checkYouxia },
        style: { background: "#DEF" },
      });
      somethingArray.push({
        id: "bt_loopReadBase",
        text: _("读技能书", "讀技能書"),
        extend: { func: PLU.toLoopReadBase },
        style: { background: "#FBB" },
      });
      somethingArray.push({
        id: "bt_searchFamilyQS",
        text: _("搜师门任务", "搜師門任務"),
        extend: { func: PLU.toSearchFamilyQS },
        style: { background: "#BBF" },
      });
      somethingArray.push({
        id: "bt_searchBangQS",
        text: _("搜帮派任务", "搜幫派任務"),
        extend: { func: PLU.toSearchBangQS },
        style: { background: "#BBF" },
      });
      // somethingArray.push({id:"bt_autoFB11", text:"自動本11", extend:{func:PLU.toAutoFB11}, style:{background:"#FC9"}})
      YFUI.addMenu({
        id: "m_autoDoSomething",
        groupId: "pluginMenus",
        text: _("自动", "自動"),
        style: { width: "40px" },
        multiCol: true,
        menuStyle: { width: "160px", "margin-top": "-61px" },
        children: somethingArray,
        onclick($btn, $box) {
          if ($btn.$extend) {
            $(".menu").hide();
            $btn.$extend.func($btn);
          }
        },
      });
      //listens
      let listensArray = [];
      listensArray.push({
        id: "bt_autoBF",
        text: _("自动帮四", "自動幫四"),
        extend: { key: "autoBF" },
        style: { background: "#EDC" },
      });
      listensArray.push({
        id: "bt_autoB6",
        text: _("自动帮六", "自動幫六"),
        extend: { key: "autoB6" },
        style: { background: "#ECD" },
      });
      listensArray.push({
        id: "bt_autoB5F",
        text: _("帮五跟杀", "幫五跟殺"),
        extend: { key: "autoB5F" },
        style: { background: "#CEF" },
      });
      listensArray.push({
        id: "bt_autoDZ",
        text: _("持续打坐", "持續打坐"),
        extend: { key: "autoDZ" },
        style: { background: "#CEC" },
      });
      listensArray.push({
        id: "bt_autoHYC",
        text: _("持续睡床", "持續睡床"),
        extend: { key: "autoHYC" },
        style: { background: "#CEC" },
      });
      listensArray.push({
        id: "bt_auto9H",
        text: _("持续九花", "持續九花"),
        extend: { key: "auto9H" },
        style: { background: "#CEC" },
      });
      listensArray.push({
        id: "bt_autoLX",
        text: _("持续练习", "持續練習"),
        extend: { key: "autoLX" },
        style: { background: "#CEC" },
      });
      listensArray.push({
        id: "bt_autoTP",
        text: _("持续突破", "持續突破"),
        extend: { key: "autoTP" },
        style: { background: "#BEF" },
      });
      listensArray.push({
        id: "bt_autoDY",
        text: _("持续钓鱼", "持續釣魚"),
        extend: { key: "autoDY" },
        style: { background: "#CEC" },
      });
      listensArray.push({
        id: "bt_autoQuitTeam",
        text: _("进塔离队", "進塔離隊"),
        extend: { key: "autoQuitTeam" },
        style: { background: "#EEF" },
      });
      if (PLU.developerMode)
        listensArray.push({
          id: "bt_autoSignIn",
          text: _("定時签到", "定時簽到"),
          extend: { key: "autoSignIn" },
          style: { background: "#BEF" },
        });
      listensArray.push({
        id: "bt_autoConnect",
        text: _("自动重连", "自動重連"),
        extend: { key: "autoConnect" },
        style: { background: "#FED" },
      });
      listensArray.push({
        id: "hr_listen",
        text: "",
        style: { width: "160px", opacity: 0 },
        boxStyle: { "font-size": 0 },
      });
      listensArray.push({
        id: "bt_listenQL",
        text: _("本服青龙", "本服青龍"),
        extend: { key: "listenQL" },
      });
      listensArray.push({
        id: "bt_listenKFQL",
        text: _("跨服青龙", "跨服青龍"),
        extend: { key: "listenKFQL" },
      });
      listensArray.push({
        id: "bt_listenYX",
        text: "遊俠",
        extend: { key: "listenYX" },
      });
      listensArray.push({
        id: "bt_listenTF",
        text: "夜魔逃犯",
        extend: { key: "listenTF" },
      });
      listensArray.push({
        id: "bt_showMPFZ",
        text: _("纷争显示", "紛爭顯示"),
        extend: { func: PLU.showMPFZ },
        style: { background: "#EEEEFF" },
      });
      listensArray.push({
        id: "bt_listenChat",
        text: _("闲聊", "閒聊"),
        extend: { key: "listenChat" },
      });
      YFUI.addMenu({
        id: "m_listens",
        groupId: "pluginMenus",
        text: _("监听", "監聽"),
        style: { background: "#DDFFDD", width: "40px" },
        multiCol: true,
        menuStyle: { width: "160px", "margin-top": "-25px" },
        children: listensArray,
        onclick($btn, $box) {
          if ($btn.$extend) PLU.setListen($btn, $btn.$extend.key);
        },
      });

      //fightset
      let fightSetsArray = [];
      fightSetsArray.push({
        id: "bt_enableSkills",
        text: _("技 能 组", "技 能 組"),
        style: { background: "#FBE" },
        menuStyle: { "margin-top": "-25px" },
        children: [
          {
            id: "bt_enableSkill1",
            text: _("技能组1", "技能組1"),
            extend: { key: "enable1" },
          },
          {
            id: "bt_enableSkill2",
            text: _("技能组2", "技能組2"),
            extend: { key: "enable2" },
          },
          {
            id: "bt_enableSkill3",
            text: _("技能组3", "技能組3"),
            extend: { key: "enable3" },
          },
        ],
      });
      fightSetsArray.push({
        id: "bt_wearEquip",
        text: _("装备切换", "裝備切換"),
        style: { background: "#FEB" },
        children: [{
          id: "bt_wearEquip1",
          text: _("装备组1", "裝備組1"),
          extend: {
            key: "equip1"
          },
          canSet: true
        }, {
          id: "bt_wearEquip2",
          text: _("装备组2", "裝備組2"),
          extend: {
            key: "equip2"
          },
          canSet: true
        }, {
          id: "bt_zbjianshen",
          text: _("剑神套", "劍神套"),
          extend: {
            key: "zbjianshentao"
          },
          style: {
            background: "#FEB"
          },
        }, {
          id: "bt_zbchuidiao",
          text: _("垂钓套", "垂釣套"),
          extend: {
            key: "zbchuidiaotao"
          },
          style: {
            background: "#FBE"
          },
        }, {
          id: "bt_zbxianzhe",
          text: _("贤者套", "賢者套"),
          extend: {
            key: "zbxianzhetao"
          },
          style: {
            background: "#CCF"
          },
        }]
      });
      fightSetsArray.push({
        id: "bt_followKill",
        text: _("跟杀设置", "跟殺設置"),
        extend: { key: "followKill" },
        style: { background: "#FCC" },
      });
      fightSetsArray.push({
        id: "bt_autoCure",
        text: _("血蓝设置", "血藍設置"),
        extend: { key: "autoCure" },
        style: { background: "#CCF" },
      });
      fightSetsArray.push({
        id: "bt_autoPerform",
        text: _("技能设置", "技能設置"),
        extend: { key: "autoPerform" },
        style: { background: "#CFC" },
      });
      YFUI.addMenu({
        id: "m_fightsets",
        groupId: "pluginMenus",
        text: _("战斗", "戰鬥"),
        style: { background: "#FFDDDD", width: "40px" },
        //multiCol: true,
        menuStyle: { width: "80px", "margin-top": "-50px" },
        children: fightSetsArray,
        onclick($btn, $box, BtnMode) {
          if ($btn.$extend) {
            if ($btn.$extend.key && PLU.getCache($btn.$extend.key) == 0) $(".menu").hide();
            if ($btn.$extend.key.match("enable")) return PLU.setSkillGroup($btn.$extend.key.substr(-1));
            if ($btn.$extend.key.match("equip")) {
              let equipKey = "equip_" + $btn.$extend.key.substr(-1) + "_keys";
              let equipsStr = PLU.getCache(equipKey);
              $(".menu").hide();
              if (equipsStr && BtnMode != "setting") {
                return PLU.wearEquip(equipsStr);
              }
              return PLU.setWearEquip($btn.$extend.key.substr(-1));
            }
            if ($btn.$extend.key == "zbjianshentao") return PLU.zbjianshen($btn, $btn.$extend.key);
            if ($btn.$extend.key == "zbchuidiaotao") return PLU.zbchuidiao($btn, $btn.$extend.key);
            if ($btn.$extend.key == "zbxianzhetao") return PLU.zbxianzhe($btn, $btn.$extend.key);
            if ($btn.$extend.key == "followKill") return PLU.setFightSets($btn, $btn.$extend.key);
            if ($btn.$extend.key == "autoCure") return PLU.setAutoCure($btn, $btn.$extend.key);
            if ($btn.$extend.key == "autoPerform") return PLU.setAutoPerform($btn, $btn.$extend.key);
          }
        },
      });
      // puzzle
      let puzzleArray = [];
      if (PLU.developerMode)
        puzzleArray.push({
          id: "bt_puzzle_key",
          text: _("通告设置", "通告設置"),
          extend: { key: "" },
        });
      puzzleArray.push({
        id: "bt_puzzle_Key",
        text: _("论剑外传#1", "外傳#1"),
        extend: { func: PLU.sword_quest_1 },
      });
      if (PLU.developerMode)
        puzzleArray.push({
          id: "bt_puzzle_key",
          text: _("进度设置", "進度設置"),
          extend: { func: PLU.key },
        });
      puzzleArray.push({
        id: "bt_puzzle_key",
        text: _("超时设置", "超時設置"),
        extend: { func: PLU.puzzleTimeOut },
      });
      YFUI.addMenu({
        id: "m_puzzle",
        groupId: "pluginMenus",
        text: _("攻略", "攻略"),
        style: { background: "#CCC", width: "40px" },
        menuStyle: { "margin-top": "-75px" },
        children: puzzleArray,
        onclick($btn, $box) {
          if ($btn.$extend) {
            $(".menu").hide();
            $btn.$extend.func($btn);
          }
        },
      });
      //Sign
      let signArray = [];
      signArray.push({
        id: "bt_autoAskQixia",
        text: _("自动问奇侠", "自動問奇俠"),
        extend: { func: PLU.toAutoAskQixia },
      });
      signArray.push({
        id: "bt_autoVisitQixia",
        text: _("亲近奇侠", "親近奇俠"),
        style: { background: "#CFC" },
        extend: { func: PLU.toAutoVisitQixia },
      });
      signArray.push({
        id: "hr_dlus",
        text: "",
        style: { width: "240px", opacity: 0 },
      });
      signArray.push({
        id: "bt_ricrw",
        text: "日常周常",
        extend: {
          key: "ricrw"
        },
        style: {
          background: "#FBE"
        }
      });
      signArray.push({
        id: "bt_sign",
        text: _("一键签到", "一鍵簽到"),
        extend: { key: "signIn" },
        style: { background: "#CCFFFF" },
      });
      YFUI.addMenu({
        id: "m_signs",
        groupId: "pluginMenus",
        text: _("签到", "簽到"),
        style: { background: "#DDFFFF", width: "40px" },
        menuStyle: { "margin-top": "-92px" },
        children: signArray,
        onclick($btn, $box) {
          if ($btn.$extend) {
            if ($btn.$extend.key == "signIn") {
              $(".menu").hide();
              return PLU.toSignIn();
            } else if ($btn.$extend.key == "ricrw") {
              $(".menu").hide();
              return PLU.toricrw();
            } else if ($btn.$extend.key == "autoricrw") {
              return PLU.setListen($btn, $btn.$extend.key);
            } else if ($btn.$extend.key == "autoSignIn") {
              return PLU.setListen($btn, $btn.$extend.key);
            } else {
              $(".menu").hide();
              $btn.$extend.func($btn);
            }
          }
        },
      });
      //sys
      let sysArray = [];
      sysArray.push({
        id: "bt_openTeam",
        text: _("开队伍", "開隊伍"),
        children: [{
          id: "bt_openTeam1",
          text: _("加入队伍", "加入隊伍"),
          extend: {
              func: PLU.asJirudw
          },
          style: {
              background: "#DEF"
          },
        }, {
          id: "bt_openTeam2",
          text: _("退出队伍", "退出隊伍"),
          extend: "team quit",
        }, {
          id: "bt_openTeam3",
          text: _("重开队伍", "重開隊伍"),
          extend: "team create",
          style: {
            background: "#00ff00"
          },
        }
      ]
      });
      sysArray.push({
        id: "bt_openFudi",
        text: _("开府邸", "開府邸"),
        extend: "fudi",
      });
      sysArray.push({
        id: "bt_openShop",
        text: _("开商城", "開商城"),
        extend: "shop",
      });
      sysArray.push({
        id: "bt_openJFShop",
        text: _("积分商城", "積分商城"),
        extend: "shop xf_shop",
      });
      sysArray.push({
        id: "bt_open4HShop",
        text: _("四海商店", "四海商店"),
        children: [
          {
            id: "bt_open4HShop1",
            text: "回收",
            extend: "reclaim recl",
          },
          {
            id: "bt_open4HShop2",
            text: _("兑换", "兌換"),
            extend: "reclaim buy",
          },
        ],
      });
      sysArray.push({
        id: "bt_clanShop",
        text: _("帮派商店	", "幫會商店"),
        extend: "clan;clan_shop",
      });
      sysArray.push({
        id: "hr_sys",
        text: "",
        style: { width: "160px", opacity: 0 },
        boxStyle: { "font-size": 0 },
      });
      sysArray.push({
        id: "bt_cleartask",
        text: _("清谜题", "清謎題"),
        extend: "auto_tasks cancel",
      });
      sysArray.push({
        id: "bt_task",
        text: _("谜题列表", "謎題列表"),
        extend: "task_quest",
      });
      sysArray.push({
        id: "bt_intervene",
        text: _("杀隐藏怪", "殺隱藏怪"),
        extend: { func: PLU.intervene },
      });
      sysArray.push({
        id: "bt_openQixia",
        text: "奇俠列表",
        extend: "open jhqx",
      });
      sysArray.push({
        id: "hr_sys",
        text: "",
        style: { width: "160px", opacity: 0 },
        boxStyle: { "font-size": 0 },
      });
      sysArray.push({
        id: "set_profile",
        text: _("个人设置", "個人設置"),
        extend: { key: "profileSetting" },
        style: { background: "#EEEEFF" },
      });
      sysArray.push({
        id: "bt_log",
        text: _("消息日志", "消息日誌"),
        extend: { func: PLU.showLog },
        style: { background: "#99CC00" },
      });
      sysArray.push({
        id: "bt_upset",
        text: _("备份设置", "備份設置"),
        extend: { func: PLU.backupSetting },
        style: { background: "#FFAAAA" },
      });
      sysArray.push({
        id: "bt_dlset",
        text: _("载入设置", "載入設置"),
        extend: { func: PLU.loadSetting },
        style: { background: "#FFCC00" },
      });
      YFUI.addMenu({
        id: "m_sys",
        groupId: "pluginMenus",
        text: "工具",
        multiCol: true,
        style: { background: "#FFFFDD", width: "40px" },
        menuStyle: { width: "160px", "margin-top": "-117px" },
        children: sysArray,
        onclick($btn, $box) {
          if ($btn.$extend) {
            if ($btn.$extend.key == "profileSetting") {
              $(".menu").hide();
              return PLU.profileSetting();
            } else if ($btn.$extend && $btn.$extend.func) {
              $(".menu").hide();
              $btn.$extend.func($btn);
            } else if ($btn.$extend) {
              $(".menu").hide();
              PLU.execActions($btn.$extend);
            }
          }
        },
      });
      //================================================================================
      //  活動
      //================================================================================
      // let activeArray=[]
      // activeArray.push({id:"bt_goShop1", text:"去小二", extend:"jh 1;"})
      // activeArray.push({id:"bt_buyItem1", text:"買四樣", extend:"#21 buy_npc_item go 0;#21 buy_npc_item go 1;#21 buy_npc_item go 2;#21 buy_npc_item go 3;"})
      // activeArray.push({id:"bt_goShop2", text:"去掌櫃", extend:"jh 5;n;n;n;w", style:{background:"#FDD"}})
      // activeArray.push({id:"bt_buyItem2", text:"買紅粉", extend:"#6 buy_npc_item go 0;", style:{background:"#FDD"}})
      // activeArray.push({id:"bt_goShop3", text:"去小販", extend:"jh 2;n;n;n;n;e", style:{background:"#DEF"}})
      // activeArray.push({id:"bt_buyItem3", text:"買黃粉", extend:"#6 event_1_17045611 go 0;", style:{background:"#DEF"}})
      // activeArray.push({id:"bt_goShop4", text:"去峨眉", extend:"jh 8;w;nw;n;n;n;n;e;e;n;n;e;;kill?看山弟子;n;n;n;n;w", style:{background:"#EFE"}})
      // activeArray.push({id:"bt_buyItem4", text:"買藍粉", extend:"#6 event_1_39153184 go 0;", style:{background:"#EFE"}})
      // activeArray.push({id:"bt_goAll", text:"一鍵買材料", extend:"jh 1;#21 buy_npc_item go 0;#21 buy_npc_item go 1;#21 buy_npc_item go 2;#21 buy_npc_item go 3;jh 5;n;n;n;w;#6 buy_npc_item go 0;jh 2;n;n;n;n;e;#6 event_1_17045611 go 0;jh 8;w;nw;n;n;n;n;e;e;n;n;e;;kill?看山弟子;n;n;n;n;w;#6 event_1_39153184 go 0;", style:{background:"#9F9"}})
      // activeArray.push({id:"bt_goShoot", text:"去放煙花", extend:"jh 2;n;n;n;", style:{background:"#FD9"}})
      // // activeArray.push({id:"bt_n", text:"", style:{opacity:0}})
      // // activeArray.push({id:"hr_sys", text:"", style:{width:"160px",opacity:0}, boxStyle:{"font-size":0}})
      // activeArray.push({id:"bt_goShoot1", text:"一鍵璀璨", extend:"#5 event_1_99582507;#15 event_1_48376442;", style:{background:"#F9D"}})
      // activeArray.push({id:"bt_goShoot2", text:"一鍵四款", extend:"#5 event_1_74166959;#5 event_1_10053782;#5 event_1_25918230;#5 event_1_48376442;", style:{background:"#D9F"}})

      // YFUI.addMenu({
      //     id: "m_active",
      //     groupId:"pluginMenus",
      //     text: "元宵",
      //     multiCol: true,
      //     style:{"background":"#FFFF55","width":"40px","margin-top":"25px"},
      //     menuStyle: {width: "160px","margin-top":"-22px"},
      //     children: activeArray,
      //     onclick($btn,$box){
      //         if($btn.$extend && $btn.$extend.func){
      //             //$(".menu").hide()
      //             $btn.$extend.func($btn)
      //}else if($btn.$extend){
      //             //$(".menu").hide()
      // 			PLU.execActions($btn.$extend,()=>{
      // 				YFUI.writeToOut("<span style='color:#FFF;'>========== OK ==========</span>")
      // 			})
      // 		}
      //}
      //})
      if (PLU.developerMode) {
        let flagArray = [];
        flagArray.push({
          id: "bt_npcDataUpdate",
          text: "npc數據更新",
          extend: { func: PLU.npcDataUpdate },
        });
        YFUI.addMenu({
          id: "m_flag",
          groupId: "pluginMenus",
          text: _("实验", "實驗"),
          multiCol: true,
          style: { background: "#FBB", width: "40px" },
          menuStyle: { width: "160px", "margin-top": "-117px" },
          children: flagArray,
          onclick($btn, $box) {
            if ($btn.$extend && $btn.$extend.func) {
              $(".menu").hide();
              $btn.$extend.func($btn);
            } else if ($btn.$extend) {
              $(".menu").hide();
              PLU.execActions($btn.$extend);
            }
          },
        });
      }
      //================================================================================
      //================================================================================

      let gh = parseInt($("#page").height() * $("#page").height() * 0.00025);
      YFUI.addBtn({
        id: "bt_col_null",
        groupId: "pluginMenus",
        text: "",
        style: {
          background: "transparent",
          height: gh + "px",
          width: "0px",
          visibility: "hidden",
        },
        boxStyle: { "pointer-events": "none" },
      });
      //戰鬥按鈕
      YFUI.addBtn({
        id: "bt_kg_autoEscape",
        groupId: "pluginMenus",
        text: "逃跑",
        style: { background: "#DDCCEE", height: "20px", width: "40px" },
        // boxStyle:{"margin-bottom":"15px"},
        onclick($btn) {
          let btnFlag = PLU.setBtnRed($btn);
          if (btnFlag) {
            PLU.autoEscape({
              onEnd() {
                PLU.setBtnRed($btn);
              },
            });
          } else UTIL.delSysListener("onAutoEscape");
        },
      });
      YFUI.addBtn({
        id: "bt_kg_loopKill",
        groupId: "pluginMenus",
        text: _("循环杀", "循環殺"),
        style: { background: "#EECCCC", height: "20px", width: "40px" },
        // boxStyle:{"margin-bottom":"15px"},
        onclick($btn) {
          PLU.toLoopKill($btn);
        },
      });
      YFUI.addBtn({
        id: "bt_kg_teamSync",
        groupId: "pluginMenus",
        text: "同步",
        style: { background: "#DDCCEE", height: "20px", width: "40px" },
        boxStyle: { "margin-bottom": "15px" },
        onclick($btn) {
          PLU.toggleTeamSync($btn);
        },
      });
      YFUI.addBtn({
        id: "bt_kg_followKill",
        groupId: "pluginMenus",
        text: _("跟杀", "跟殺"),
        style: { background: "#FFDDDD", height: "25px", width: "40px" },
        onclick($btn) {
          PLU.toggleFollowKill($btn, "followKill");
        },
      });
      YFUI.addBtn({
        id: "bt_kg_autoCure",
        groupId: "pluginMenus",
        text: _("血蓝", "血藍"),
        style: { background: "#CCCCFF", height: "25px", width: "40px" },
        onclick($btn) {
          PLU.toggleAutoCure($btn, "autoCure");
        },
      });
      YFUI.addBtn({
        id: "bt_kg_autoPerform",
        groupId: "pluginMenus",
        text: _("连招", "連招"),
        style: { background: "#FFCCFF", height: "25px", width: "40px" },
        onclick($btn) {
          PLU.toggleAutoPerform($btn, "autoPerform");
        },
      });
      //monitor
      let momaxW = $("#page").width() - $("#out").width() > 4 && $("#out").width() > 634 ? 475 : Math.floor($("#out").width() * 0.75);
      let leftSty = $("#page").width() - $("#out").width() > 4 && $("#page").width() > 634 ? "79px" : "12%";
      YFUI.addBtnGroup({
        id: "topMonitor",
        style: {
          position: "fixed",
          top: 0,
          left: leftSty,
          width: "75%",
          height: "15px",
          maxWidth: momaxW + "px",
          lineHeight: "1.2",
          fontSize: "11px",
          textAlign: "left",
          color: "#FF9",
          background: "rgba(0,0,0,0)",
          display: "none",
        },
      });
    },
    //================================================================================================
    getCache(key) {
      return PLU.CACHE[key] ?? "";
    },
    //================================================================================================
    setCache(key, val) {
      PLU.CACHE[key] = val;
      UTIL.setMem("CACHE", JSON.stringify(PLU.CACHE));
      return val;
    },
    //================================================================================================
    initStorage() {
      if (!UTIL.getMem("CACHE")) UTIL.setMem("CACHE", JSON.stringify(PLU.CACHE));
      let caObj,
        ca = UTIL.getMem("CACHE");
      try {
        caObj = JSON.parse(ca);
      } catch (err) { }
      if (caObj) {
        PLU.CACHE = caObj;
        let listen = [
          "listenPuzzle",
          "listenChat",
          "listenQL",
          "listenTF",
          "listenKFQL",
          "listenYX",
          "autoDZ",
          "autoHYC",
          "auto9H",
          "autoDY",
          "autoTP",
          "autoLX",
          "autoBF",
          "autoB5F",
          "autoB6",
          "autoConnect",
          "autoSignIn",
          "autoQuitTeam",
        ];
        for (var i = 0, len = listen.length; i < len; i++) {
          if (PLU.getCache(listen[i]) == 1) PLU.setListen($("#btn_bt_" + listen[i]), listen[i], 1);
        }
        if (PLU.getCache("listenPuzzle") == 0) {
          PLU.TMP.autotask = false;
        }
        if (PLU.getCache("followKill") == 1) {
          PLU.toggleFollowKill($("#btn_bt_kg_followKill"), "followKill", 1);
        }
        if (PLU.getCache("autoCure") == 1) {
          PLU.toggleAutoCure($("#btn_bt_kg_autoCure"), "autoCure", 1);
        }
        if (PLU.getCache("autoPerform") >= 1) {
          PLU.toggleAutoPerform($("#btn_bt_kg_autoPerform"), "autoPerform", PLU.getCache("autoPerform"));
        }
        if (PLU.getCache("showTopMonitor") == 1) {
          PLU.showMPFZ($("#btn_bt_showMPFZ"));
        }
      }
    },
    //================================================================================================
    initHistory() {
      //---------------------
      document.addEventListener("addLog", PLU.updateShowLog);
      //---------------------
      let hisArr = [],
        hstr = UTIL.getMem("HISTORY");
      if (hstr)
        try {
          hisArr = JSON.parse(hstr);
        } catch (err) { }
      if (hisArr && hisArr.length) {
        let nowTs = new Date().getTime();
        let newArr = hisArr.filter((h) => {
          UTIL.log(Object.assign({}, h, { isHistory: true }));
          if (nowTs - h.time > 43200000) return false;
          return true;
        });
        UTIL.logHistory = newArr;
        UTIL.setMem("HISTORY", JSON.stringify(newArr));
      }
      PLU.MPFZ = UTIL.getMem("MPFZ") ? JSON.parse(UTIL.getMem("MPFZ")) : {};
    },
    //================================================================================================
    initListeners() {
      //監聽戰鬥消息
      UTIL.addSysListener("listenAllFight", (b, type, subtype, msg) => {
        if (type == "vs") {
          switch (subtype) {
            case "vs_info":
              if (b.containsKey("is_watcher")) {
                PLU.STATUS.inBattle = 2;
                break;
              }
              PLU.STATUS.inBattle = 1;
              if (!PLU.battleData)
                PLU.battleData = {
                  skills: {},
                  xdz: 0,
                  myPos: 0,
                  mySide: "",
                  performTime: 0,
                  cureTimes: 0,
                };

              for (let i = b.elements.length - 1; i > -1; i--) {
                let val = b.elements[i].value + "";
                if (!val || val.indexOf(PLU.accId) < 0) continue;
                PLU.battleData.myPos = b.elements[i].key.charAt(7);
                PLU.battleData.mySide = b.elements[i].key.substring(0, 3);
                console.log(b.elements[i])
                break;
              }
              PLU.STATUS.isBusy = true;
              break;
            case "ready_skill":
              if (b.get("uid").indexOf(PLU.accId) < 0 || b.get("skill") == "fight_item") break;
              if (!PLU.battleData)
                PLU.battleData = {
                  skills: {},
                  xdz: 0,
                  myPos: 0,
                  mySide: "",
                  performTime: 0,
                  cureTimes: 0,
                };
              PLU.battleData.skills[b.get("pos") - 1] = {
                name: UTIL.filterMsg(b.get("name")),
                skill: b.get("skill"),
                xdz: b.get("xdz"),
                key: "playskill " + b.get("pos"),
              };
              break;
            case "add_xdz":
              if (b.get("uid").indexOf(PLU.accId) < 0) break;
              if (!PLU.battleData)
                PLU.battleData = {
                  skills: {},
                  xdz: 0,
                  myPos: 0,
                  mySide: "",
                  performTime: 0,
                  cureTimes: 0,
                };
              PLU.battleData.xdz = parseInt(b.get("xdz"));
              if (PLU.STATUS.inBattle == 1 && PLU.battleData && PLU.battleData.xdz > 1) {
                PLU.checkUseSkills();
              }
              break;
            case "playskill":
              if (b.get("uid").indexOf(PLU.accId) < 0) break;
              if (!PLU.battleData)
                PLU.battleData = {
                  skills: {},
                  xdz: 0,
                  myPos: 0,
                  mySide: "",
                  performTime: 0,
                  cureTimes: 0,
                };
              let x = PLU.battleData.xdz - parseInt(b.get("lose_xdz"));
              if (parseInt(b.get("lose_xdz"))) PLU.battleData.xdz = x > 0 ? x : 0;
              break;
            case "out_watch":
              PLU.STATUS.inBattle = 0;
              PLU.STATUS.isBusy = false;
              break;
            case "combat_result":
              PLU.STATUS.inBattle = 0;
              PLU.battleData = null;

              PLU.STATUS.isBusy = false;
              if (PLU.TMP.loopUseSkill) {
                clearInterval(PLU.TMP.loopUseSkill);
                PLU.TMP.loopUseSkill = null;
              }
              break;
            default:
              break;
          }
          if (PLU.STATUS.inBattle == 1 && !PLU.TMP.loopUseSkill) {
            PLU.TMP.loopUseSkill = setInterval(() => {
              if (PLU.STATUS.inBattle == 1 && PLU.battleData && PLU.battleData.xdz > 1) {
                PLU.checkUseSkills();
              }
            }, 250);
          }
        }
        if (g_gmain.is_fighting && PLU.STATUS.inBattle == 1) {
          if (type == "vs" || type == "attrs_changed") {
            //自動療傷及自動技能
            if (PLU.battleData && PLU.battleData.xdz > 1 && PLU.STATUS.inBattle == 1) {
              PLU.checkUseSkills();
            }
          }
        }
      });
      //監聽場景消息
      UTIL.addSysListener("listenNotice", (b, type, subtype, msg) => {
        if (type != "notice" && type != "main_msg") return;
        if (msg.match(_(/闲聊|告诉|队伍/, /閒聊|告訴|隊伍/))) return;
        let msgTxt = UTIL.filterMsg(msg);
        if (msgTxt.match(_("你打坐完毕", "你打坐完畢")) && PLU.getCache("autoDZ") == 1) {
          if (UTIL.inHome()) clickButton("exercise", 0);
          else
            PLU.TODO.push({
              type: "cmds",
              cmds: "exercise",
              timeout: new Date().getTime() + 8 * 60 * 60 * 1000,
            });
        } else if ((msgTxt.match(_("你从寒玉床上爬起", "你從寒玉床上爬起")) || msgTxt.match(_("你从地髓石乳中出来", "你從地髓石乳中出來"))) && PLU.getCache("autoHYC") == 1) {
          if (UTIL.inHome()) PLU.execActions("golook_room;sleep_hanyuchuang;home");
          else
            PLU.TODO.push({
              type: "cmds",
              cmds: "golook_room;sleep_hanyuchuang;home",
              timeout: new Date().getTime() + 8 * 60 * 60 * 1000,
            });
        } else if (msgTxt.match(_("你中了【黑蛭异毒】", "你中了【黑蛭異毒】"))) {
          PLU.execActions("items use obj_zuixianwan");
        } else if (msgTxt.match(_("开始观舞了,请不要离开此处", "開始觀舞了,請不要離開此處"))) {
          PLU.setCache("watch_dance", 0);
        } else if (msgTxt.match(_("【观舞中】", "【觀舞中】"))) {
          let watch_dance = PLU.getCache("watch_dance");
          watch_dance = watch_dance + 1;
          if (watch_dance == 50) {
            setTimeout(function() {
              YFUI.writeToOut("<span style='color:yellow;'>==" + _("观舞结束", "觀舞結束") + "!==</span>");
            }, 200);
          } else {
            PLU.setCache("watch_dance", watch_dance);
          }
        } else if (msgTxt.match(_("你今天採得太多了,明天再来吧", "你今天採得太多了,明天再來吧"))) {
          if (PLU.accId == "8137847(1)") {
            PLU.execActions("rank go 232;#6 s;sw;diaoyu");
          } else {
            PLU.execActions("rank go 232;#6 s;diaoyu");
          }
        } else if (msgTxt.match(_("你今天使用九花玉露丸次数已经达到上限了", "你今天使用九花玉露丸次數已經達到上限了"))) {
          YFUI.writeToOut("<span style='color:yellow;'>" + _("九花玉露丸次数已达到上限!取消监听九花玉露丸", "九花玉露丸次數已達到上限!取消監聽九花玉露丸") + "...</span>");
          PLU.setListen($("#btn_bt_auto9H"), "auto9H", 0);
        } else if (msgTxt.match("九花玉露丸效果:") && PLU.getCache("auto9H") == 1) {
          PLU.execActions("items use obj_jiuhuayulouwan");
        } else if (msgTxt.match(/你的(.*)成功向前突破了/) && PLU.getCache("autoTP") == 1) {
          if (UTIL.inHome()) PLU.toToPo();
          else {
            let checktp = PLU.TODO.find((e) => e.cmds == "toToPo");
            if (!checktp)
              PLU.TODO.push({
                type: "func",
                cmds: "toToPo",
                timeout: new Date().getTime() + 8 * 60 * 60 * 1000,
              });
          }
        } else if ((msgTxt.match(_("你现在正突破", "你現在正突破")) && msgTxt.match(_("同时突破", "同時突破"))) || msgTxt.match("此次突破需要")) {
          //突破失敗
          PLU.TMP.stopToPo = true;
        } else if (msgTxt.match(_("青龙会组织:", "青龍會組織:"))) {
          //本服青龍
          let l = msgTxt.match(_(/青龙会组织:(.*)正在\003href;0;([\w\d\s]+)\003(.*)\0030\003施展力量,本会愿出(.*)的战利品奖励给本场战斗的最终获胜者。/, /青龍會組織:(.*)正在\003href;0;([\w\d\s]+)\003(.*)\0030\003施展力量,本會願出(.*)的戰利品獎勵給本場戰鬥的最終獲勝者。/));
          if (l && l.length > 3) {
            UTIL.log({
              msg: _("【青龙】", "【青龍】") + l[3].padStart(5) + " - " + l[1].padEnd(4) + _("  奖品:", "  獎品:") + l[4],
              type: "QL",
              time: new Date().getTime(),
            });
            if (PLU.getCache("listenQL") == 1) {
              let keysStr = PLU.getCache("listenQL_keys")
                .split("|")[1]
                .split(",")
                .map((e) => (e == "*" ? ".*" : e.replace("*", "\\*")))
                .join("|");
              let reg = new RegExp(keysStr);
              if (l[4].match(reg) && UTIL.inHome()) {
                PLU.goQinglong(l[1], l[3], PLU.getCache("listenQL_keys").split("|")[0], false);
              }
            }
          }
        } else if (msgTxt.match(_("这是你今天完成的第", "這是你今天完成的第"))) {
          //逃犯完成
          let l = msgTxt.match(_(/这是你今天完成的第(\d)\/\d场逃犯任务/, /這是你今天完成的第(\d)\/\d場逃犯任務/));
          if (l && l.length > 0 && l[1] == 5) {
            YFUI.writeToOut('<span style="color:yellow;">' + _('逃犯任务已达到上限!取消逃犯监听...', '逃犯任務已達到上限!取消逃犯監聽...') + '</span>');
            UTIL.log({
              msg: _(" 逃犯任务已达到上限!取消逃犯监听...", " 逃犯任務已達到上限!取消逃犯監聽..."),
              type: "TIPS",
              time: new Date().getTime(),
            });
            PLU.setListen($("#btn_bt_listenTF"), "listenTF", 0);
          }
        } else if (msgTxt.match(_("对你悄声道:你现在去", "對你悄聲道:你現在去")) && !PLU.TMP.autoQixiaMijing) {
          //奇俠說秘境
          let l = msgTxt.match(_(/(.*)对你悄声道:你现在去(.*),应当会有发现/, /(.*)對你悄聲道:你現在去(.*),應當會有發現/));
          if (l && l.length > 2) {
            let placeData = PLU.YFD.mjList.find((e) => e.n == l[2]);
            if (placeData) {
              YFUI.writeToOut(
                "<span>" + _("奇侠秘境", "奇俠秘境") + ": <a style='text-decoration:underline;color:yellow;cursor:pointer;' onclick='PLU.execActions(\"" +
                placeData.v +
                "\")'>" +
                placeData.n +
                "</a></span>",
              );
              YFUI.showPop({
                title: _("奇侠秘境", "奇俠秘境"),
                text: "秘境:" + placeData.n,
                okText: "去秘境",
                onOk() {
                  PLU.execActions(placeData.v + ";find_task_road secret;", () => {
                    YFUI.writeToOut(
                      "<span>:: <a style='text-decoration:underline;color:yellow;cursor:pointer;' onclick='clickButton(\"open jhqx\", 0)'>" + _("奇侠列表", "奇俠列表") + "</a></span>",
                    );
                  });
                },
                onNo() { },
              });
            }
          }
        } else if (msgTxt.match(_("你赢了这场宝藏秘图之战!", "你贏了這場寶藏秘圖之戰!"))) {
          PLU.execActions("clan bzmt puzz");
        } else if (msgTxt.match(_("开启了帮派副本", "開啟了幫派副本"))) {
          if (PLU.getCache("autoBF") == 1) {
            //幫四開啟
            let ll = msg.match(_(/开启了帮派副本.*十月围城.*【(.*)】/, /開啟了幫派副本.*十月圍城.*【(.*)】/));
            if (ll) {
              let n = "一二三".indexOf(ll[1]);
              UTIL.log({
                msg: _("【帮四】帮四(", "【幫四】幫四(") + ll[1] + _(")开启 ", ")開啟 "),
                type: "BF",
                time: new Date().getTime(),
              });
              if (n >= 0) {
                if (!g_gmain.is_fighting) {
                  PLU.toBangFour(n + 1);
                } else {
                  let checktodo = PLU.TODO.find((e) => e.cmds == "toBangFour");
                  if (!checktodo)
                    PLU.TODO.push({
                      type: "func",
                      cmds: "toBangFour",
                      param: [n + 1],
                      timeout: new Date().getTime() + 5 * 60 * 1000,
                    });
                }
              }
            }
          }
          if (PLU.getCache("autoB6") == 1) {
            //幫六開啟
            let ls = msg.match(_(/开启了帮派副本.*蛮荒七神寨.*/, /開啟了幫派副本.*蠻荒七神寨.*/));
            if (ls) {
              if (!g_gmain.is_fighting) {
                PLU.toBangSix();
              } else {
                let checktodo = PLU.TODO.find((e) => e.cmds == "toBangSix");
                if (!checktodo)
                  PLU.TODO.push({
                    type: "func",
                    cmds: "toBangSix",
                    param: [""],
                    timeout: new Date().getTime() + 5 * 60 * 1000,
                  });
              }
            }
          }
        } else if (msgTxt.match(_("十月围城】帮派副本胜利", "十月圍城】幫派副本勝利"))) {
          //幫四完成
          PLU.STO.bangFourTo && clearTimeout(PLU.STO.bangFourTo);
          if (!g_gmain.is_fighting) {
            setTimeout(() => {
              PLU.execActions("home;");
            }, 2000);
          }
        } else if (msgTxt.match(_("蛮荒七神寨】帮派副本胜利", "蠻荒七神寨】幫派副本勝利"))) {
          //幫六完成
          PLU.STO.bangSixTo && clearTimeout(PLU.STO.bangSixTo);
          if (!g_gmain.is_fighting) {
            setTimeout(() => {
              PLU.execActions("home;");
            }, 2000);
          }
        } else if (msgTxt.match(_("你今天进入此副本的次数已达到上限了", "你今天進入此副本的次數已達到上限了"))) {
          //幫四六無法進入
          PLU.STO.bangFourTo && clearTimeout(PLU.STO.bangFourTo);
          PLU.STO.bangSixTo && clearTimeout(PLU.STO.bangSixTo);
          UTIL.log({
            msg: " !!副本超量!!",
            type: "TIPS",
            time: new Date().getTime(),
          });
        } else if (msgTxt.match(_(/你已进入帮派副本\*\*可汗金帐\*\*/, /你已進入幫派副本\*\*可汗金帳\*\*/)) && PLU.getCache("autoB5F") == 1) {
          //幫五進入
          PLU.inBangFiveEvent();
        } else if (msgTxt.match(_("成功消灭了守将府内的所有敌人", "成功消滅了守將府內的所有敵人"))) {
          //幫二完成
          let l = msgTxt.match(_(/守城成功】(.*)成功消灭了守将府内的所有敌人,帮派副本完成/, /守城成功】(.*)成功消滅了守將府內的所有敵人,幫派副本完成/));
          if (l && l.length > 1 && !g_gmain.is_fighting) {
            setTimeout(() => {
              PLU.execActions("home;");
            }, 3000);
          }
        } else if (msgTxt.match(_("你没有精良鱼饵,无法钓鱼", "你沒有精良魚餌,無法釣魚"))) {
          //釣魚完成
          if (!UTIL.inHome() && !g_gmain.is_fighting) {
            if (PLU.getCache("autoDY") == 1) {
              let attr = g_obj_map.get("msg_attrs");
              if (attr.get("yuanbao") >= PLU.getCache("autoDY_key") + 50) PLU.execActions("shop buy shop45;diaoyu;");
              else
                setTimeout(() => {
                  PLU.execActions("home;");
                }, 1000);
            }
          } else
            setTimeout(() => {
              PLU.execActions("home;");
            }, 1000);
        }
      });

      //監聽頻道消息
      UTIL.addSysListener("listenChannel", (b, type, subtype, msg) => {
        if (type != "channel" || subtype != "sys") return;
        let msgTxt = UTIL.filterMsg(msg);
        //本服逃犯
        if (msgTxt.match(_("慌不择路", "慌不擇路")) && msgTxt.indexOf("跨服") < 0) {
          var l = msgTxt.match(_(/系统】([\u4e00-\u9fa5|\*]+).*慌不择路,逃往了(.*)-\003href;0;([\w\d\s]+)\003([\u4e00-\u9fa5]+)/, /系統】([\u4e00-\u9fa5|\*]+).*慌不擇路,逃往了(.*)-\003href;0;([\w\d\s]+)\003([\u4e00-\u9fa5]+)/));
          if (l && l.length > 4) {
            UTIL.log({
              msg: "【逃犯】" + l[2] + "-" + l[4] + " : " + l[1],
              type: "TF",
              time: new Date().getTime(),
            });
            if (PLU.getCache("listenTF") == 1 && UTIL.inHome()) {
              if (!PLU.TMP.lis_TF_list) {
                PLU.splitTFParam();
              }
              if (PLU.TMP.lis_TF_list.includes(l[1])) {
                let idx = PLU.TMP.lis_TF_list.findIndex((k) => k == l[1]);
                if (idx >= 0) {
                  let gb = Number(PLU.getCache("listenTF_keys").split("|")[0]) || 0;
                  PLU.goTaofan(l[1], l[2], l[3], gb, PLU.TMP.lis_TF_force[idx]);
                }
              }
            }
          }
        } else if (msgTxt.match(_("跨服时空", "跨服時空"))) {
          let l = msgTxt.match(_(/跨服:(.*)逃到了跨服时空(.*)之中,青龙会组织悬赏(.*)惩治恶人,众位英雄快来诛杀。/, /跨服:(.*)逃到了跨服時空(.*)之中,青龍會組織懸賞(.*)懲治惡人,眾位英雄快來誅殺。/));
          if (l && l.length > 3) {
            UTIL.log({
              msg: _("【跨服青龙】", "【跨服青龍】") + l[2] + " - " + l[1].padEnd(8) + _("  奖品:", "  獎品:") + l[3],
              type: "KFQL",
              time: new Date().getTime(),
            });
            if (PLU.getCache("listenKFQL") == 1) {
              let keysStr = PLU.getCache("listenKFQL_keys")
                .split("|")[1]
                .split(",")
                .map((e) => (e == "*" ? ".*" : e.replace("*", "\\*")))
                .join("|");
              let reg = new RegExp(keysStr);
              if (PLU.developerMode && l[3].match(reg) && UTIL.inHome()) {
                UTIL.addSysListener("KuaFu", (b, type, subtype, msg) => {
                  if (b.get("map_id") == "kuafu") {
                    UTIL.delSysListener("KuaFu");
                    PLU.goQinglong(l[1], l[2], PLU.getCache("listenKFQL_keys").split("|")[0], true);
                  }
                });
                setTimeout(() => {
                  clickButton("change_server world;");
                }, 500);
              }
            }
          }
        }
        //江湖紛爭
        else if (msgTxt.match(_("江湖纷争", "江湖紛爭"))) {
          let fz = msgTxt.match(
            _(/【江湖纷争】:(.*)(门派|流派)的(.*)剑客伤害同门,欺师灭组,判师而出,却有(.*)坚持此种另有别情而强行庇护,两派纷争在(.*)-(.*)一触即发,江湖同门速速支援!/, /【江湖紛爭】:(.*)(門派|流派)的(.*)劍客傷害同門,欺師滅組,判師而出,卻有(.*)堅持此種另有別情而強行庇護,兩派紛爭在(.*)-(.*)一觸即發,江湖同門速速支援!/),
          );
          if (!fz) return;
          let ro = fz[3];
          let pl = fz[5] + "-" + fz[6];
          let vs = fz[1] + " VS " + fz[4];
          let tp = fz[2];
          let logType = tp == _("门派", "門派") ? "MPFZ" : "LPFZ";
          UTIL.log({
            msg: "【" + tp + _("之争】 ", "之爭】 ") + ro + _("  地点:[", "  地點:[") + pl + "]  " + vs,
            type: logType,
            time: new Date().getTime(),
          });
          if (tp == _("门派", "門派")) {
            let nowTime = new Date().getTime();
            for (let k in PLU.MPFZ) {
              if (k < nowTime) delete PLU.MPFZ[k];
            }
            let extime = new Date().getTime() + 1560000;
            PLU.MPFZ[extime] = { n: ro, p: pl, v: vs, t: new Date().getTime() };
            UTIL.setMem("MPFZ", JSON.stringify(PLU.MPFZ));
          }
        }
        //遊俠
        else if (msgTxt.match(_("出来闯盪江湖了", "出來闖盪江湖了"))) {
          let yx = msgTxt.match(_(/【系統】遊俠會:聽說(.*)出來闖盪江湖了,目前正在前往(.*)的路上/, /【系統】遊俠會:聽說(.*)出來闖盪江湖了,目前正在前往(.*)的路上/));
          if (!yx) return;
          let yn = $.trim(yx[1]);
          let yp = yx[2];
          let yr = "";
          PLU.YFD.youxiaList.forEach((g) => {
            if (g.v.includes(yn)) yr = g.n;
          });
          UTIL.log({
            msg: _("【游侠-", "【遊俠-") + yr + "】 " + yn + _("  地点:[", "  地點:[") + yp + "]  ",
            type: "YX",
            time: new Date().getTime(),
          });
          if (PLU.getCache("listenYX") == 1 && UTIL.inHome()) {
            if (!PLU.TMP.listenYX_list) {
              PLU.TMP.listenYX_list = PLU.getCache("listenYX_keys").split(",");
            }
            if (PLU.TMP.listenYX_list && PLU.TMP.listenYX_list.includes(yn)) {
              let jhName = PLU.fixJhName(yp);
              let jhMap = PLU.YFD.mapsLib.Map.find((e) => e.name == jhName);
              if (!jhMap) return;
              else {
                let ways = jhMap.way.split(";");
                PLU.goFindYouxia({ paths: ways, idx: 0, objectNPC: yn });
              }
            }
          }
        }
      });
      //監聽場景
      UTIL.addSysListener("listenRoomInfo", (b, type, subtype, msg) => {
        if (type == "prompt" && msg.indexOf("想要加入你的") >= 0) {
          PLU.execActions(b.get("cmd1"));
          PLU.execActions("prev;prev");
        }
        if (type == "notice" && subtype == "notify_fail" && msg.indexOf(_("必须杀完所有的怪物才可以打开宝箱", "必須殺完所有的怪物才可以打開寶箱")) >= 0) {
          PLU.execActions("ak;;ka;;event_1_68529291;");
        }
        if (type == "notice" && msg.indexOf(_("完成子关卡*八戒神殿*获得武林名望值x50", "完成子關卡*八戒神殿*獲得武林名望值x50")) >= 0) {
          var mapNamefb = UTIL.filterMsg(g_obj_map.get("msg_room").get("short"));
          if (mapNamefb.match(/本源之心/)) {
            setTimeout(function () {
              PLU.execActions("home;");
            }, 2500);
          }
        }
        if (type != "jh") return;
        //奇俠加按鈕
        $("#out .out>button.cmd_click3").each((i, e) => {
          if (PLU.YFD.qixiaList.includes(e.innerText)) {
            let snpc = e.outerHTML.match(/clickButton\('look_npc (\w+)'/i);
            if (snpc && snpc.length >= 2) {
              $(e).css({ position: "relative" });
              let $btnAsk = $(
                '<span style="position:absolute;display:inline-block;left:0;top:0;padding:3% 5%;text-align:center;background:#39F;color:#fff;border-radius:3px;font-size:1.2em;">' + _('问', '問') + '<span>',
              );
              let $btnGold = $(
                '<span style="position:absolute;display:inline-block;right:0;bottom:0;padding:3% 5%;text-align:center;background:#F93;color:#fff;border-radius:3px;font-size:1.2em;">金<span>',
              );
              $(e).append($btnAsk);
              $(e).append($btnGold);
              $btnAsk.click((e) => {
                e.stopPropagation();
                PLU.execActions("ask " + snpc[1] + ";");
              });
              $btnGold.click((e) => {
                e.stopPropagation();
                let ename = snpc[1].split("_")[0];
                PLU.execActions("auto_zsjd20_" + ename + ";golook_room");
              });
            }
          }
        });
        //監聽入隊靈鷲和塔
        if (type == "jh" && subtype == "info" && PLU.getCache("autoQuitTeam") == 1) {
          let sn = g_obj_map.get("msg_room").get("short");
          if (
            sn.match(_(/灵鹫宫(\D+)层/, /靈鷲宮(\D+)層/)) ||
            sn.match(_(/拱辰楼(\D+)层/, /拱辰樓(\D+)層/)) ||
            sn.match(_(/陈异叔(\D+)层/, /陳異叔(\D+)層/)) ||
            sn.match(_(/无为寺(\D+)层/, /無為寺(\D+)層/)) ||
            sn.match(_(/一品堂(\D+)层/, /一品堂(\D+)層/)) ||
            sn.match(_(/名将堂(\D+)层/, /名將堂(\D+)層/)) ||
            sn.match(_(/魔皇殿(\D+)层/, /魔皇殿(\D+)層/)) ||
            sn.match(_(/藏典塔(\D+)层/, /藏典塔(\D+)層/)) ||
            sn.match(_(/无相楼(\D+)层/, /無相樓(\D+)層/)) ||
            sn.match(_(/葬剑谷(\D+)层/, /葬劍谷(\D+)層/)) ||
            sn.match(_(/霹雳堂(\D+)层/, /霹靂堂(\D+)層/)) ||
            sn.match(_(/铸剑洞(\D+)层/, /鑄劍洞(\D+)層/)) ||
            sn.match(_(/剑楼(\D+)层/, /劍樓(\D+)層/)) ||
            sn.match(_(/红螺寺(\D+)层/, /紅螺寺(\D+)層/)) ||
            sn.match(_(/通天塔(\D+)层/, /通天塔(\D+)層/))
          ) {
            //退出隊伍
            let quitTeamPrevTimeOut = setTimeout(() => {
              UTIL.delSysListener("quitTeamPrev");
            }, 5000);
            UTIL.addSysListener("quitTeamPrev", (b, type, subtype, msg) => {
              if (type == "team" && subtype == "info") {
                UTIL.delSysListener("quitTeamPrev");
                clearTimeout(quitTeamPrevTimeOut);
                clickButton("prev");
              }
            });
            clickButton("team quit");
          }
        }
        //刷新後恢復監聽幫五
        if (type == "jh" && subtype == "info" && PLU.TMP.listenBangFive == undefined) {
          let roomName = UTIL.filterMsg(g_obj_map.get("msg_room").get("short"));
          if (roomName.match(_(/蒙古高原|成吉思汗的金帐/, /蒙古高原|成吉思汗的金帳/))) {
            PLU.inBangFiveEvent();
          } else {
            PLU.TMP.listenBangFive = false;
          }
        }
      });
      // 谜题密码
      UTIL.addSysListener("key", (b, type, subtype, msg) => {
        if (type != "channel" || subtype != "tell") return;
        let key = msg.match(_(/告诉你:谜题密码:(\d+)/, /告訴你:謎題密碼:(\d+)/))[1];
        if (key)
          PLU.TODO.push({
            type: "cmds",
            cmds: "jh 1;e;n;n;n;n;w;event_1_65953349 " + key + ";home;",
            timeout: new Date().getTime() + 8 * 60 * 60 * 1000,
          });
      });
      // 監聽閒聊
      UTIL.addSysListener("listenChat", (b, type, subtype, msg) => {
        if (type != "channel" || subtype != "chat") return;
        /** UNICODE 15.0
         * CJK Radicals Supplement 2E80–2EFF
         * CJK Unified Ideographs (Han) 4E00–9FFF
         * CJK Extension A 3400-4DBF
         * CJK Extension B 20000–2A6DF
         * CJK Extension C 2A700–2B739
         * CJK Extension D 2B740–2B81D
         * CJK Extension E 2B820–2CEA1
         * CJK Extension F 2CEB0–2EBE0
         * CJK Extension G 30000–3134A
         * CJK Extension H 31350–323AF
         */
        msg = msg.replace("\f", "");
        let text = msg.match(/^[^:]+:.*?([\u2E80-\u2EFF\u3400-\u4DBF\u4E00-\u9FFF\-,”'!!]+道:.+)\x1B\[2;37;0m/);
        if (text) {
          text = text[1];
          if (text.match(_(/柴绍|李秀宁|大鹳淜洲/, /柴紹|李秀寧|大鸛淜洲/))) {
            /**
             * 李秀寧昨天撿到了我幾十輛銀子
             * 李秀寧鬼鬼祟祟的叫人生疑
             * 李秀寧竟對我橫眉瞪眼的
             * 竟然吃了李秀寧的虧
             * 李秀寧竟敢得罪我
             * 被李秀寧搶走了
             * 李秀寧好大膽
             * 想找李秀寧
             * 藏在了(天龍寺-)?大鸛淜洲
             * 想要一件天羅紫芳衣
             */
            UTIL.log({
              msg: _("【谜题-天命丹】", "【謎題-天命丹】") + text,
              type: "TIPS",
              time: new Date().getTime(),
            });
          } else if (text.match(_(/阴九幽|潜龙|谷底石室/, /陰九幽|潛龍|谷底石室/))) {
            UTIL.log({
              msg: _("【谜题-鬼杀剑】", "【謎題-鬼殺劍】") + text,
              type: "TIPS",
              time: new Date().getTime(),
            });
          } else if (text.match(_(/打坐老僧|牟尼楼|牟尼洞/, /打坐老僧|牟尼樓|牟尼洞/))) {
            UTIL.log({
              msg: _("【谜题-700级读书识字】", "【謎題-700級讀書識字】") + text,
              type: "TIPS",
              time: new Date().getTime(),
            });
          } else if (text.match(_(/本恆禅师|无相堂/, /本恆禪師|無相堂/))) {
            UTIL.log({
              msg: _("【谜题-木棉袈裟】", "【謎題-木棉袈裟】") + text,
              type: "TIPS",
              time: new Date().getTime(),
            });
          } else if (text.match((/天罗紫芳衣/, /天羅紫芳衣/))) {
            UTIL.log({
              msg: _("【谜题-天命丹】", "【謎題-天命丹】") + text,
              type: "TIPS",
              time: new Date().getTime(),
            });
          } else if (text.match(_(/鬼杀剑|金凤翅盔/, /鬼殺劍|金鳳翅盔/))) {
            UTIL.log({
              msg: _("【谜题-鬼杀剑】", "【謎題-鬼殺劍】") + text,
              type: "TIPS",
              time: new Date().getTime(),
            });
          } else if (text.match(/麻布僧衣/)) {
            UTIL.log({
              msg: _("【谜题-700级读书识字】", "【謎題-700級讀書識字】") + text,
              type: "TIPS",
              time: new Date().getTime(),
            });
          } else if (text.match(_(/追风棍|木棉袈裟/, /追風棍|木棉袈裟/))) {
            UTIL.log({
              msg: _("【谜题-木棉袈裟】", "【謎題-木棉袈裟】") + text,
              type: "TIPS",
              time: new Date().getTime(),
            });
          }
        }
        let text2 = msg.match(/[^:]+:(.+)\x1B\[2;37;0m/)[1];
        if (PLU.getCache("listenChat") == 1 && text2 != _("哈哈,我也来闯盪江湖啦!", "哈哈,我也來闖盪江湖啦!") && text2 != "哈哈,我去也……") YFUI.writeToOut(msg);
        let text3 = msg.match(/^[^:]+:(.+道):(.+)\x1B\[2;37;0m/);
        if (text3) var tmp = PLU.queryNpc(text3[1], true);
        else {
          let text3 = msg.match(_(/^[^:]+:(.+)的谜题\x1B\[2;37;0m/, /^[^:]+:(.+)的謎題\x1B\[2;37;0m/));
          if (text3) var tmp = PLU.queryNpc(text3[1] + "道", true);
        }

        if (tmp && tmp.length && PLU.getCache("listenPuzzle") == 1) {
          PLU.TMP.autotask = true;
          for (var npc of tmp) {
            PLU.TODO.push({
              type: "func",
              cmds: "execActions",
              param: [
                npc.way,
                (code, name) => {
                  let npcObj = UTIL.findRoomNpc(name, 0, 1);
                  if (npcObj) PLU.execActions("ask " + npcObj.key);
                },
                npc.name_new ?? npc.name_tw ?? npc.name,
              ],
              timeout: new Date().getTime() + 15 * 60 * 1000,
            });
          }
        }
      });
      //監聽練習
      UTIL.addSysListener("listenPractice", (b, type, subtype, msg) => {
        if (type == "practice" && subtype == "stop_practice" && PLU.getCache("autoLX") == 1) {
          let skillId = b.get("sid"),
            lxcmds = "enable " + skillId + ";practice " + skillId;
          if (UTIL.inHome()) PLU.execActions(lxcmds);
          else
            PLU.TODO.push({
              type: "cmds",
              cmds: lxcmds,
              timeout: new Date().getTime() + 8 * 60 * 60 * 1000,
            });
        }
      });
      //監聽劍陣
      UTIL.addSysListener("listenJianzhen", (b, type, subtype, msg) => {
        if (type != "notice") return;
        if (msg.indexOf(_("阵升级完毕!", "陣升級完畢!")) < 0) return;
        let msgTxt = UTIL.filterMsg(msg);
        if (msgTxt.match(_(/(.*)阵升级完毕!成功升级到/, /(.*)陣升級完畢!成功升級到/))) {
          setTimeout(() => {
            let jzcmds = "hhjz xiulian go;;;hhjz speedup go;";
            let room = g_obj_map.get("msg_room")?.get("short");
            if (room == _("桃溪", "桃溪") || room == _("后山茶园", "後山茶園") || UTIL.inHome()) PLU.execActions(jzcmds);
            else
              PLU.TODO.push({
                type: "cmds",
                cmds: jzcmds,
                timeout: new Date().getTime() + 8 * 60 * 60 * 1000,
              });
          }, 8000);
        }
      });
      //監聽跟殺
      UTIL.addSysListener("listenFightKill", (b, type, subtype, msg) => {
        if (type != "main_msg" || !msg) return;
        if (msg.indexOf(_("对着", "對著")) < 0) return;
        if (PLU.getCache("followKill") != 1) return;
        let msgTxt = UTIL.filterMsg(msg);
        var matchKill = msgTxt.match(_(/(.*)对着(.*)喝道:「(.*)!今日不是你死就是我活!」/, /(.*)對著(.*)喝道:「(.*)!今日不是你死就是我活!」/));
        if (matchKill && $.trim(matchKill[1]) != "你" && $.trim(matchKill[2]) != "你" && !g_gmain.is_fighting) {
          PLU.toCheckFollowKill($.trim(matchKill[1]), $.trim(matchKill[2]), "kill", msgTxt);
          return;
        }
        var matchFight = msgTxt.match(_(/(.*)对着(.*)说道:(.*),领教(.*)的高招!/, /(.*)對著(.*)說道:(.*),領教(.*)的高招!/));
        if (matchFight && $.trim(matchFight[1]) != "你" && $.trim(matchFight[2]) != "你" && !g_gmain.is_fighting) {
          PLU.toCheckFollowKill($.trim(matchFight[1]), $.trim(matchFight[2]), "fight", msgTxt);
          return;
        }
      });
      //test
      UTIL.addSysListener("testListener", (b, type, subtype, msg) => {
        if (type == "g_login" && subtype == "login_ret" && msg == "1") {
          YFUI.writeToOut("<span style='color:#FFF;background:#F00;'>[" + UTIL.getNow() + _("] 断线重连了 </span>", "] 斷線重連了 </span>"));
        }
      });
      UTIL.addSysListener("disconnect", (b, type, subtype, msg) => {
        if (type == "disconnect" && subtype == "change") {
          console.log("%c%s", "color:#F00", ">>>>>>>sock disconnected");
          //sock && sock.close(); sock = 0
          if (PLU.getCache("autoConnect") == 1) {
            let recTime = Number(PLU.getCache("autoConnect_keys"));
            if (recTime) g_gmain.g_delay_connect = recTime;
          }
        }
      });
      unsafeWindow.sock.on("telnet_connected", () => {
        console.log("%c%s", "color:#0F0", ">>>>>>>sock connected");
      });
      UTIL.addSysListener("YXSkillsListener", (b, type, subtype, msg) => {
        if (type != "show_html_page") return;
        if (msg.indexOf(_("须传授技能", "須傳授技能")) < 0) return;
        let list = msg.match(/\x1B\[1;36m(\d+)\/(\d+)[\s\S]{1,200}(fudi juxian up_skill .* 10)/g);
        let outList = null;
        if (list && list.length) {
          outList = list.map((s) => {
            let r = s.match(/\x1B\[1;36m(\d+)\/(\d+)[\s\S]{1,200}(fudi juxian up_skill .* 10)/);
            return { lvl: r[1], max: r[2], cmd: r[3] + "0" };
          });
        }
        PLU.TMP.CUR_YX_SKILLS = outList;
        let matchNameLine = msg.match(/<span class="out2">([\s\S]+)<\/span><span class="out2">/);
        let npcNameLine = matchNameLine ? UTIL.filterMsg(matchNameLine[1]) : "";
        let dg = npcNameLine.match(_(/(\d+)级/, /(\d+)級/))[1];
        PLU.TMP.CUR_YX_LEVEL = Number(dg);
        let nn = msg.match(/fudi juxian upgrade (\S+) 1/)[1];
        PLU.TMP.CUR_YX_ENG = nn;
      });
      UTIL.addSysListener("masterSkillsListener", (b, type, subtype, msg) => {
        if (type != "master_skills" || subtype != "list") return;
        let masterSkills = PLU.parseSkills(b);

        PLU.TMP.MASTER_ID = b.get("id");
        PLU.TMP.MASTER_SKILLS = masterSkills;
      });
    },
    //================================================================================================
    initTickTime() {
      setInterval(() => {
        let nowDate = new Date();
        let nowTime = nowDate.getTime();
        if (PLU.TODO.length > 0 && !PLU.STATUS.isBusy && UTIL.inHome()) {
          //待辦
          let ctd = PLU.TODO.shift();
          if (nowDate.getTime() < ctd.timeout) {
            if (ctd.type == "cmds") {
              PLU.execActions(ctd.cmds);
            } else if (ctd.type == "func") {
              if (ctd.param) PLU[ctd.cmds](...ctd.param);
              else PLU[ctd.cmds]();
            }
          }
        }
        if ($("#topMonitor").text() != "") $("#topMonitor").empty();
        let bi = 0;
        for (let k in PLU.MPFZ) {
          if (k < nowTime) delete PLU.MPFZ[k];
          else {
            let f = PLU.MPFZ[k];
            let dt = Math.floor((k - nowTime) / 1000);
            let flo = bi % 2 == 1 ? "float:right;text-align:right;" : "";
            $("#topMonitor").append(
              `<div title="${f.v}" style="display:inline-block;width:40%;${flo}">${f.n.substr(0, 1)} <span style="color:#9CF;">[${f.p
              }]</span> <span style="color:#DDD;">${dt}</span></div>`,
            );
            bi++;
          }
        }
        if (PLU.ONOFF["btn_bt_waitCDKill"] && PLU.TMP.DATA_MPFZ) PLU.toCheckAndWaitCDKill(nowTime);
      }, 1000);
    },
    //================================================================================================
    toSignIn() {
      if (!this.signInMaps) this.initSignInMaps();
      let ckeds = PLU.getCache("signInArray")?.split(",") || this.signInMaps.map((e, i) => i);

      let htm = '<div style="display:flex;flex-direction:row;flex-wrap: wrap;justify-content: space-between;width: 100%;align-content: flex-start;line-height:2;">';
      this.signInMaps.forEach((e, i) => {
        if (!e.n) htm += '<span style="width:92px;">&nbsp;</span>';
        else
          htm += `<span><button class="signInBtn" data-sid="${i}" style="font-size:12px;padding:1px 2px;cursor:pointer;">GO</button>
            <label data-id="${i}" style="font-size:13px;margin:0 3px 5px 0;">${e.n}<input type="checkbox" name="signInId" value="${i}"
             ${ckeds.includes(i + "") || e.f ? "checked" : ""} ${e.f ? "disabled" : ""} /></label></span>`;
      });
      htm += '</div><button class="signInAll" style="cursor:pointer;position:absolute;left:15px;bottom:10px;">全選</button>';
      YFUI.showPop({
        title: _("签到", "簽到"),
        text: htm,
        width: "360px",
        okText: _("一键签到", "一鍵簽到"),
        onOk(e) {
          let checkeds = [];
          e.find('input[name="signInId"]:checked').each((i, b) => {
            checkeds.push(b.value);
          });
          PLU.setCache("auto9H", 1);
          PLU.setCache("signInArray", checkeds.join(","));
          PLU.goSign(checkeds);
        },
        onNo() { },
        afterOpen($el) {
          $el.find(".signInBtn").click((e) => {
            let btnSid = $(e.currentTarget).attr("data-sid");
            PLU.goSign(btnSid);
          });
          $el.find(".signInAll").click((e) => {
            $el.find('input[name="signInId"]').each(function () {
              $(this).prop("checked", true);
            });
          });
        },
      });
    },
    //================================================================================================
    toricrw() {
      var _PLU$getCache2;
      if (!this.rcrenwu) this.initrichangrenwu();
      var ckeds = ((_PLU$getCache2 = PLU.getCache("signInArrayrc")) === null || _PLU$getCache2 === void 0 ? void 0 : _PLU$getCache2.split(",")) || this.rcrenwu.map(function (e, i) {
        return i;
      });
      var htm = '<div style="display:flex;flex-direction:row;flex-wrap: wrap;justify-content: space-between;width: 100%;align-content: flex-start;line-height:2;">';
      this.rcrenwu.forEach(function (e, i) {
        if (!e.n) htm += '<span style="width:92px;">&nbsp;</span>'; else htm += '<span><button class="signInBtn" data-sid="'.concat(i, '" style="font-size:12px;padding:1px 2px;cursor:pointer;">GO</button>\n            <label data-id="').concat(i, '" style="font-size:13px;margin:0 3px 5px 0;">').concat(e.n, '<input type="checkbox" name="signInId" value="').concat(i, '"\n             ').concat(ckeds.includes(i + "") || e.f ? "checked" : "", " ").concat(e.f ? "disabled" : "", " /></label></span>");
      });
      htm += '</div><button class="signInAll" style="cursor:pointer;position:absolute;left:15px;bottom:10px;">全選</button>';
      YFUI.showPop({
        title: "日常周常",
        text: htm,
        width: "360px",
        okText: _("开始", "開始"),
        onOk: function onOk(e) {
          var checkeds = [];
          e.find('input[name="signInId"]:checked').each(function (i, b) {
            checkeds.push(b.value);
          });
          PLU.setCache("signInArrayrc", checkeds.join(","));
          PLU.goSign(checkeds, true);
        },
        onNo: function onNo() { },
        afterOpen: function afterOpen($el) {
          $el.find(".signInBtn").click(function (e) {
            var btnSid = $(e.currentTarget).attr("data-sid");
            PLU.goSign(btnSid, true);
          });
          $el.find(".signInAll").click(function (e) {
            $el.find('input[name="signInId"]').each(function () {
              $(this).prop("checked", true);
            });
          });
        }
      });
    },
    //================================================================================================
    autoSwords(callback) {
      UTIL.addSysListener("sword", (b, type, subtype, msg) => {
        if (type != "notice" || msg.indexOf(_("试剑", "試劍")) == -1) return;
        if (msg.indexOf("5/5") > 0 || !msg.indexOf(_("你今天试剑次数已达限额", "你今天試劍次數已達限額"))) {
          UTIL.delSysListener("sword");
          callback && callback();
        } else PLU.execActions("swords fight_test go");
      });
      PLU.execActions("swords;swords select_member heimuya_dfbb;swords select_member qingcheng_mudaoren;swords select_member tangmen_madam;swords fight_test go");
    },
    //================================================================================================
    autoGetVipReward(callback) {
      let acts = "";
      let vipInfo = g_obj_map.get("msg_vip");
      if (vipInfo.get("get_vip_drops") == 0) acts += "vip drops;";
      if (vipInfo.get("finish_sort") % 1000 < 5) acts += "#5 vip finish_sort;";
      if (vipInfo.get("finish_dig") % 1000 < 10) acts += "#10 vip finish_dig;";
      if (vipInfo.get("finish_diaoyu") % 1000 < 10) acts += "#10 vip finish_diaoyu;";
      if (vipInfo.get("do_task_num") % 1000 < 10) acts += "#10 vip finish_big_task;";
      if (vipInfo.get("family_quest_count") % 1000 < 25) acts += "#25 vip finish_family;";
      if (g_obj_map.get("msg_clan_view") && vipInfo.get("clan_quest_count") % 1000 < 20) acts += "#20 vip finish_clan;";
      if (vipInfo.get("saodang_fb_1")?.split(",")[2] || 0 % 1000 < 2) acts += "#2 vip finish_fb dulongzhai;";
      if (vipInfo.get("saodang_fb_2")?.split(",")[2] || 0 % 1000 < 2) acts += "#2 vip finish_fb junying;";
      if (vipInfo.get("saodang_fb_3")?.split(",")[2] || 0 % 1000 < 2) acts += "#2 vip finish_fb beidou;";
      if (vipInfo.get("saodang_fb_4")?.split(",")[2] || 0 % 1000 < 2) acts += "#2 vip finish_fb youling;";
      if (vipInfo.get("saodang_fb_5")?.split(",")[2] || 0 % 1000 < 1) acts += "vip finish_fb siyu;";
      if (vipInfo.get("saodang_fb_6")?.split(",")[2] || 0 % 1000 < 1) acts += "vip finish_fb changleweiyang;";
      if (vipInfo.get("saodang_fb_7")?.split(",")[2] || 0 % 1000 < 1) acts += "vip finish_fb heishuihuangling;";
      if (vipInfo.get("saodang_fb_8")?.split(",")[2] || 0 % 1000 < 1) acts += "vip finish_fb jiandangfenglingdu;";
      if (vipInfo.get("saodang_fb_9")?.split(",")[2] || 0 % 1000 < 1) acts += "vip finish_fb tianshanlongxue;";
      if (vipInfo.get("saodang_fb_10")?.split(",")[2] || 0 % 1000 < 1) acts += "vip finish_fb sizhanguangmingding;";
      acts += "home;";
      PLU.execActions(acts, () => {
        callback && callback();
      });
    },
    autoShaodan(callback) {
      let acts = "";
      let vipInfo = g_obj_map.get("msg_vip");
      let isVip = vipInfo.get("vip_tm") > 0;
      if (vipInfo.get("saodang_fb_1")?.split(",")[2] || 0 % 1000 < 2) {
        if (isVip) acts += "#2 vip finish_fb dulongzhai;";
        else
          acts +=
            _("team create;fb 1;;kill?独龙寨土匪;n;;kill?独龙寨土匪;n;;kill?独龙寨土匪;n;;kill?独龙寨土匪;n;;kill?傅一镖;", "team create;fb 1;;kill?獨龍寨土匪;n;;kill?獨龍寨土匪;n;;kill?獨龍寨土匪;n;;kill?獨龍寨土匪;n;;kill?傅一鏢;") +
            _("team create;fb 1;;kill?独龙寨土匪;n;;kill?独龙寨土匪;n;;kill?独龙寨土匪;n;;kill?独龙寨土匪;n;;kill?傅一镖;", "team create;fb 1;;kill?獨龍寨土匪;n;;kill?獨龍寨土匪;n;;kill?獨龍寨土匪;n;;kill?獨龍寨土匪;n;;kill?傅一鏢;");
      }
      if (vipInfo.get("saodang_fb_2")?.split(",")[2] || 0 % 1000 < 2)
        if (isVip) acts += "#2 vip finish_fb junying;";
        else
          acts +=
            _("team create;fb 2;;kill?护卫;;kill?小兵;;kill?小兵;e;n;event_1_48728674;fb 2;e;s;event_1_41361248;fb 2;e;e;;kill?护卫;event_1_43484736;;kill?护卫;@赫造基的尸体;@严廷殷的尸体;", "team create;fb 2;;kill?護衛;;kill?小兵;;kill?小兵;e;n;event_1_48728674;fb 2;e;s;event_1_41361248;fb 2;e;e;;kill?護衛;event_1_43484736;;kill?護衛;@赫造基的屍體;@嚴廷殷的屍體;") +
            _("team create;fb 2;;kill?护卫;;kill?小兵;;kill?小兵;e;n;event_1_48728674;fb 2;e;s;event_1_41361248;fb 2;e;e;;kill?护卫;event_1_43484736;;kill?护卫;", "team create;fb 2;;kill?護衛;;kill?小兵;;kill?小兵;e;n;event_1_48728674;fb 2;e;s;event_1_41361248;fb 2;e;e;;kill?護衛;event_1_43484736;;kill?護衛;");
      if (vipInfo.get("saodang_fb_3")?.split(",")[2] || 0 % 1000 < 2) {
        if (isVip) acts += "#2 vip finish_fb beidou;";
        else
          acts +=
            _("team create;fb 3;w;;kill?天璇剑客;e;s;;kill?玉衡剑客;n;e;;kill?瑶光剑客;event_1_9777898;;kill?天枢剑客;@天枢剑客的尸体;", "team create;fb 3;w;;kill?天璇劍客;e;s;;kill?玉衡劍客;n;e;;kill?瑤光劍客;event_1_9777898;;kill?天樞劍客;@天樞劍客的屍體;") +
            _("team create;fb 3;w;;kill?天璇剑客;e;s;;kill?玉衡剑客;n;e;;kill?瑶光剑客;event_1_9777898;;kill?天枢剑客;", "team create;fb 3;w;;kill?天璇劍客;e;s;;kill?玉衡劍客;n;e;;kill?瑤光劍客;event_1_9777898;;kill?天樞劍客;");
      }
      if (vipInfo.get("saodang_fb_4")?.split(",")[2] || 0 % 1000 < 2) {
        if (isVip) acts += "#2 vip finish_fb youling;";
        else
          acts +=
            _("team create;fb 4;n;;kill?翻云刀神;n;;kill?织冰女侠;n;;kill?复雨剑神;n;;kill?排云狂神;n;;kill?九天老祖;", "team create;fb 4;n;;kill?翻雲刀神;n;;kill?織冰女俠;n;;kill?覆雨劍神;n;;kill?排雲狂神;n;;kill?九天老祖;") +
            _("team create;fb 4;n;;kill?翻云刀神;n;;kill?织冰女侠;n;;kill?复雨剑神;n;;kill?排云狂神;n;;kill?九天老祖;", "team create;fb 4;n;;kill?翻雲刀神;n;;kill?織冰女俠;n;;kill?覆雨劍神;n;;kill?排雲狂神;n;;kill?九天老祖;");
      }
      if (vipInfo.get("saodang_fb_5")?.split(",")[2] || 0 % 1000 < 1) {
        if (isVip) acts += "vip finish_fb siyu;";
        else
          acts +=
            _("team create;fb 5;event_1_26662342;;kill?勾陈教香主;se;;kill?勾陈教掌教;nw;nw;event_1_15727082;;kill?紫薇教香主;nw;;kill?紫薇教掌教;se;se;event_1_12238479;;kill?长生教香主;sw;;kill?长生教掌教;ne;ne;event_1_889199;;kill?后土教香主;ne;;kill?后土教掌教;sw;sw;;;;;;;event_1_77337496;;kill?后土真人;", "team create;fb 5;event_1_26662342;;kill?勾陳教香主;se;;kill?勾陳教掌教;nw;nw;event_1_15727082;;kill?紫薇教香主;nw;;kill?紫薇教掌教;se;se;event_1_12238479;;kill?長生教香主;sw;;kill?長生教掌教;ne;ne;event_1_889199;;kill?後土教香主;ne;;kill?後土教掌教;sw;sw;;;;;;;event_1_77337496;;kill?後土真人;");
      }
      if (vipInfo.get("saodang_fb_6")?.split(",")[2] || 0 % 1000 < 1) {
        if (isVip) acts += "vip finish_fb changleweiyang;";
        else
          acts +=
            _("team create;fb 6;event_1_94101353;;kill?黄门丞;event_1_8221898;;kill?少府卿;event_1_18437151;;kill?羽林卫;event_1_74386803;;kill?舞乐令;event_1_39816829;event_1_92691681;event_1_19998221;event_1_62689078;;kill?羽林中郎将;event_1_85127800;;ask changleweiyang_jiangzuodajiang;event_1_39026868;;kill?大司马;s;;kill?未央公主;", "team create;fb 6;event_1_94101353;;kill?黃門丞;event_1_8221898;;kill?少府卿;event_1_18437151;;kill?羽林衛;event_1_74386803;;kill?舞樂令;event_1_39816829;event_1_92691681;event_1_19998221;event_1_62689078;;kill?羽林中郎將;event_1_85127800;;ask changleweiyang_jiangzuodajiang;event_1_39026868;;kill?大司馬;s;;kill?未央公主;");
      }
      if (vipInfo.get("saodang_fb_7")?.split(",")[2] || 0 % 1000 < 1)
        if (isVip) acts += "vip finish_fb heishuihuangling;";
        else
          acts +=
            _("team create;fb 7;event_1_20980858;;kill?断龙斧卫;fb 7;event_1_81463220;;kill?金锤力士;fb 7;event_1_5770640;;kill?重甲矛士;fb 7;event_1_56340108;;kill?大夏神箭;event_1_21387224;s;;kill?金锤虎将;event_1_94902320;", "team create;fb 7;event_1_20980858;;kill?斷龍斧衛;fb 7;event_1_81463220;;kill?金錘力士;fb 7;event_1_5770640;;kill?重甲矛士;fb 7;event_1_56340108;;kill?大夏神箭;event_1_21387224;s;;kill?金錘虎將;event_1_94902320;");
      if (vipInfo.get("saodang_fb_8")?.split(",")[2] || 0 % 1000 < 1)
        if (isVip) acts += "vip finish_fb jiandangfenglingdu;";
        else
          acts +=
            _("team create;fb 8;n;;kill?夜伤;n;;kill?百里伤;fb 8;e;;kill?夜幽女;e;;kill?千夜女使;fb 8;w;kill?夜杀;w;;kill?烛夜长老;fb 8;s;;kill?夜刺;s;;kill?千夜刺将;event_1_28034211;;kill?风陵总管;event_1_17257217;", "team create;fb 8;n;;kill?夜傷;n;;kill?百裡傷;fb 8;e;;kill?夜幽女;e;;kill?千夜女使;fb 8;w;kill?夜殺;w;;kill?燭夜長老;fb 8;s;;kill?夜刺;s;;kill?千夜刺將;event_1_28034211;;kill?風陵總管;event_1_17257217;");
      if (vipInfo.get("saodang_fb_9")?.split(",")[2] || 0 % 1000 < 1)
        if (isVip) acts += "vip finish_fb tianshanlongxue;";
        else acts += _("team create;fb 9;;kill?剑影;n;;kill?剑浪;n;;kill?剑豹;n;;kill?剑蟒;n;;kill?剑飞;n;;kill?剑神;", "team create;fb 9;;kill?劍影;n;;kill?劍浪;n;;kill?劍豹;n;;kill?劍蟒;n;;kill?劍飛;n;;kill?劍神;");
	  if (vipInfo.get("saodang_fb_10")?.split(",")[2] || 0 % 1000 < 1)
        if (isVip) acts += "vip finish_fb sizhanguangmingding;";
	  if (vipInfo.get("saodang_fb_11")?.split(",")[2] || 0 % 1000 < 1)
        if (isVip) acts += "vip finish_fb bajieshendian;";
      acts += "home;";
      PLU.execActions(acts, () => {
        callback && callback();
      });
    },
    //================================================================================================
    getClanInfo(callback) {
      let openClanTimeout = setTimeout(() => {
        UTIL.delSysListener("listenOpenClan");
        callback && callback(0);
      }, 5000);
      UTIL.addSysListener("listenOpenClan", (b, type, subtype, msg) => {
        if (type == "clan") {
          UTIL.delSysListener("listenOpenClan");
          clearTimeout(openClanTimeout);
          clickButton("prev");
          //console.log(g_obj_map.get("msg_clan_view"))
          callback && callback(1);
        }
      });
      clickButton("clan");
    },
    getVipInfo(callback) {
      let openVipTimeout = setTimeout(() => {
        UTIL.delSysListener("listenOpenVip");
        callback && callback(0);
      }, 5000);
      UTIL.addSysListener("listenOpenVip", (b, type, subtype, msg) => {
        if (type == "vip") {
          UTIL.delSysListener("listenOpenVip");
          clearTimeout(openVipTimeout);
          clickButton("prev");
          //console.log(g_obj_map.get("msg_vip"))
          callback && callback(1);
        }
      });
      clickButton("vip");
    },
    //================================================================================================
    goSign(param) {
      if (!param) {
        return YFUI.writeToOut("<span style='color:#FFF;'>--" + _("结束", "結束") + "--</span>");
      } else if (param.length == 0) {
        return YFUI.writeToOut("<span style='color:#FFF;'>--" + _("签到结束", "簽到結束") + "--</span>");
      }
      let sid = null;
      if (typeof param == "object") {
        sid = param.shift();
      } else {
        sid = param;
        param = null;
      }
      let signD = PLU.signInMaps[sid];
      if (signD.c != undefined) {
        if (signD.c()) {
          if (signD.fn) {
            signD.fn(() => {
              PLU.goSign(param);
            });
          } else if (signD.go) {
            PLU.execActions(signD.go, () => {
              PLU.goSign(param);
            });
          }
        } else {
          PLU.goSign(param);
        }
      } else {
        if (signD.fn) {
          signD.fn(() => {
            PLU.goSign(param);
          });
        } else if (signD.go) {
          PLU.execActions(signD.go, () => {
            PLU.goSign(param);
          });
        }
      }
    },
    //================================================================================================
    initSignInMaps() {
      let _this = this;
      this.getVipInfo((b) => {
        _this.getClanInfo((a) => { });
      });
      this.signInMaps = [{
        n: _("扬州签到", "揚州簽到"),
        f: true,
        go: "jh 5;n;n;n;w;look_npc yangzhou_yangzhou4;sign7;home;"
      }, {
        n: _("每日礼包", "每日禮包"),
        f: true,
        go: "jh 1;event_1_57222966;event_1_48246976;event_1_85373703;home;fudi houshan fetch;fudi juxian mpay;fudi juxian fetch_zhuguo;home;swords report go;"
      }, {
        n: _("潜龙礼包", "潛龍禮包"), 
        f: true,
        go: "jh 1;event_1_16472313;event_1_38436482;w;event_1_26383297;event_1_21318613;#4 w;n;event_1_66563556;home;"
      }, {
        n: _("分享奖励", "分享獎勵"),
        f: true,
        go: "share_ok 1;share_ok 2;share_ok 3;share_ok 4;share_ok 5;share_ok 7;home;clan fb open shenshousenlin;clan fb open daxuemangongdao;clan fb open longwulianmoge;clan fb open_go2 kehanjinzhang2;"
      }, {
        n: _("南诏投资", "南詔投資"),
        f: true,
        go: "jh 54;#4 nw;#2 w;#4 n;#2 e;n;#2 e;event_1_62143505 go;;;event_1_62143505 get;event_1_63750325 get;home;"
      }, {
        n: _("消费积分", "消費積分"),
        f: true,
        go: "jh 1;e;n;e;e;event_1_44731074;event_1_8041045;event_1_8041045;event_1_29721519;home;"
      }, {
        n: "打坐睡床",
        f: true,
        go: "home;exercise stop;exercise;golook_room;sleep_hanyuchuang;fudi shennong fetch;home;"
      }, {
        n: _("买引路蜂", "買引路蜂"),
        f: true,
        go: "shop money_buy mny_shop2_N_10;home;vip;"
      }, {
        n: _("续约会员", "續約會員"),
        go: "jh 1;event_1_45018293;home;"
      }, {
        n: _("领取工资", "領取工資"),
        f: true,
        go: "home;work click maikuli;work click duancha;work click dalie;work click baobiao;work click maiyi;work click xuncheng;work click datufei;work click dalei;work click kangjijinbin;work click zhidaodiying;work click dantiaoqunmen;work click shenshanxiulian;work click jianmenlipai;work click dubawulin;work click youlijianghu;work click yibangmaoxiang;work click zhengzhanzhongyuan;work click taofamanyi;public_op3;home;"
      }, {
        n: _("爬楼奖励", "爬樓獎勵"),
        f: true,
        go: "home;cangjian get_all;xueyin_shenbinggu blade get_all;xueyin_shenbinggu unarmed get_all;xueyin_shenbinggu throwing get_all;xueyin_shenbinggu spear get_all;xueyin_shenbinggu hammer get_all;xueyin_shenbinggu axe get_all;xueyin_shenbinggu whip get_all;xueyin_shenbinggu stick get_all;xueyin_shenbinggu staff get_all;home;"
      }, {
        n: _("领取矿镐", "領取礦鎬"),
        fn: PLU.DailyOres
      }, {
        n: ("银两上香", "銀兩上香"),
        c: function c() {
          return !!g_obj_map.get("msg_clan_view");
        },
        go: "#20 clan incense yx;home;"
      }, {
        n: _("会员福利", "會員福利"),
        c: function c() {
          return g_obj_map.get("msg_vip") && g_obj_map.get("msg_vip").get("vip_tm") > 0 && g_obj_map.get("msg_vip").get("get_vip_drops") == 0;
        },
        go: "vip drops;home;"
      }, {
        n: _("会员暴击", "會員暴擊"),
        c: function c() {
          return g_obj_map.get("msg_vip") && g_obj_map.get("msg_vip").get("vip_tm") > 0 && g_obj_map.get("msg_vip").get("do_task_num") % 1000 < 10;
        },
        fn: PLU.saodbj
      }, {
        n: _("会员师门", "會員師門"),
        c: function c() {
          return g_obj_map.get("msg_vip") && g_obj_map.get("msg_vip").get("vip_tm") > 0 && g_obj_map.get("msg_vip").get("family_quest_count") % 1000 < 25;
        },
        fn: PLU.saodsm
      }, {
        n: _("会员帮派", "會員幫派"),
        c: function c() {
          return g_obj_map.get("msg_vip") && g_obj_map.get("msg_vip").get("vip_tm") > 0 && g_obj_map.get("msg_clan_view") && g_obj_map.get("msg_vip").get("clan_quest_count") % 1000 < 20;
        },
        go: "#20 vip finish_clan;#3 clan fb go_saodang shenshousenlin;#3 clan fb go_saodang daxuemangongdao;#3 clan fb go_saodang longwulianmoge;#3 clan fb go_saodang kehanjinzhang2;"
      }, {
        n: _("会员排行", "會員排行"),
        c: function c() {
          return g_obj_map.get("msg_vip") && g_obj_map.get("msg_vip").get("vip_tm") > 0 && g_obj_map.get("msg_vip").get("finish_sort") % 1000 < 5;
        },
        go: "#5 vip finish_sort;"
      }, {
        n: _("会员寻宝", "會員尋寶"),
        c: function c() {
          return g_obj_map.get("msg_vip") && g_obj_map.get("msg_vip").get("vip_tm") > 0 && g_obj_map.get("msg_vip").get("finish_dig") % 1000 < 10;
        },
        go: "#10 vip finish_dig;"
      }, {
        n: _("会员钓鱼", "會員釣魚"),
        c: function c() {
          return g_obj_map.get("msg_vip") && g_obj_map.get("msg_vip").get("vip_tm") > 0 && g_obj_map.get("msg_vip").get("finish_diaoyu") % 1000 < 10;
        },
        go: "#10 vip finish_diaoyu;"
      },
      //{n:'VIP 掃蕩',c:function(){return g_obj_map.get("msg_vip")&&g_obj_map.get("msg_vip").get("vip_tm")>0},fn:PLU.autoVipShaodan},
      {
        n: _("扫荡副本", "掃蕩副本"),
        fn: PLU.autoShaodan
      }, {
        n: _("会员纷争", "會員紛爭"),
        c: function c() {
          return g_obj_map.get("msg_vip") && g_obj_map.get("msg_vip").get("vip_tm") > 0 && g_obj_map.get("msg_vip").get("finish_fenzheng") % 1000 < 5;
        },
        go: "#5 vip finish_fenzheng;"
      }, {
        n: _("打小龙人", "打小龍人"),
        fn: PLU.saoxlr
      }, {
        n: _("玄铁采矿", "玄鐵采礦"),
        go: "jh 26;w;w;n;e;e;event_1_18075497;w;w;n;event_1_14435995;home;jh 35;nw;nw;nw;n;ne;nw;w;nw;e;e;e;e;e;se;n;n;w;n;w;event_1_53278632;sousuo;sousuo;home;"
      }, {
        n: "求教阿不",
        go: "jh 31;n;se;e;se;s;s;sw;se;se;e;nw;e;ne;n;ne;n;n;n;n;n;n;n;n;n;w;w;event_1_57281457;event_1_10395181;;home;"
      }, {
        n: _("绝情鳄鱼", "絕情鱷魚"),
        go: "jh 37;n;e;e;nw;nw;w;n;e;n;e;e;e;ne;ne;ne;se;n;event_1_97487911;home;"
      }, {
        n: "少林渡劫",
        go: "jh 13;e;s;s;w;w;w;;event_1_38874360;;kill?渡風神識;;home;"
      }, {
        n: _("天山七侠", "天山七俠"),
        fn: PLU.TianShan7Xia
      }, {
        n: "明教毒魔",
        go: "jh 18;n;nw;n;n;n;n;n;ne;n;n;n;n;n;n;n;n;n;w;nw;nw;event_1_70957287;;kill?九幽毒魔;;home;"
      }, {
        n: _("论剑试剑", "論劍試劍"),
        fn: PLU.autoSwords
      }, {
        n: _("唐门冰月", "唐門冰月"),
        fn: PLU.autoBingyue
      }, {
        n: _("垂钓一夏", "垂釣一夏"),
        go: "jh 5;n;w;event_1_3144437;home;"
      }, {
        n: _("华山祭酒", "華山祭酒"),
        go: "jh 4;n;n;n;n;n;n;n;n;n;e;n;n;n;n;n;event_1_355715;event_1_355715;"
      },{
        n: _("清明礼包", "清明禮包"),
        go: "jh 1;#4 w;n;event_1_85364899;home;"
      },{
        n: _("龙辰礼包", "龍辰禮包"),
        go: "items get_store /obj/quest/jinyuhufusuipian;=200;jh 1;e;#3 n;n;w;event_1_90287255 go go_lsyj;#6 event_1_56364978;#6 event_1_49251725;home;"
      },{
        n: _("自动答题", "自動答題"),
        fn: PLU.loopAnswerQues
      }, {
        n: "",
        go: "home;"
      }];
    },
    saoxlr(callback) {//刷小龍人
      PLU.execActions("items get_store /obj/shop/meiguihua;items info meigui hua;jh 2;event_1_69287816;ak;");
      UTIL.addSysListener("saoxlr", function (b, type, subtype, msg,) {
      if (type == "items" && subtype == "info" && UTIL.filterMsg(b.get("name")) == "玫瑰花" || type == "notice" && subtype == "notify_fail" && msg.indexOf(_("你的背包里没有这个物品", "你的背包裡沒有這個物品")) == 0) {
        UTIL.delSysListener("meigui");
        var meigui = parseInt(b.get("amount")) || 0;
        if (meigui < 140) {
          PLU.execActions("#".concat(Math.ceil((140 - meigui) / 10), " shop buy shop28_N_10"));
        }
      } else if ((type === "jh" && subtype === "info")) {
            PLU.execActions("=1500;kill snow_xiaolongren;");
      } else if ((type === "vs" && subtype === "text" && msg.indexOf(_("\n\x1B[1;33m小龙人\x1B[2;37;0m死了。", "\n\x1B[1;33m小龍人\x1B[2;37;0m死了。")) !== -1)) {
            setTimeout(function () {
              PLU.execActions("=1500;kill snow_xiaolongren;");
            }, 400);
        } else if ((type === "notice" && msg.indexOf(_("你今天挑战太多了", "你今天挑戰太多了")) !== -1)) {
          UTIL.delSysListener("saoxlr");
          PLU.execActions("ka;log?完成小龍人;hoame;", callback);
        }
      });
    },
    saodsm(callback) {//掃蕩VIP師門
      PLU.execActions("items get_store /obj/shop/shimenling;items info obj_shimenling;");
      UTIL.addSysListener("saodsm", function (b, type, subtype, msg) {
        if ((type === "items" && subtype === "info" && UTIL.filterMsg(b.get("name")) === _("师门令", "師門令")) || (type === "notice" && subtype === "notify_fail" && msg.indexOf(_("你的仓库里没有这个物品", "你的倉庫裡沒有這個物品")) === 0)) {
            PLU.execActions("items use obj_shimenling;");
          } else if ((type === "notice" && msg.indexOf(_("使用师门令成功,师门任务次数+", "使用師門令成功,師門任務次數+")) !== -1)) {
            setTimeout(function () {
              PLU.execActions("items use obj_shimenling;");
            }, 200);
          } else if ((type === "notice" && subtype === "notify_fail" && msg.indexOf(_("你目前不能使用师门令", "你目前不能使用師門令")) !== -1)) {
            setTimeout(function () {
              PLU.execActions("vip finish_family;");
            }, 200);
          } else if ((type === "notice" && msg.indexOf(_("本源无上心经残页x1", "本源無上心經殘頁x1")) !== -1)) {
            setTimeout(function () {
              PLU.execActions("vip finish_family;");
            }, 200);
        } else if ((type === "notice" && subtype === "notify_fail" && msg.indexOf(_("今日师门任务已做完。", "今日師門任務已做完。")) !== -1)) {
          UTIL.delSysListener("saodsm");
          PLU.execActions(_("log?完成VIP师门;", "log?完成VIP師門;"), callback);
        }
      });
    },
    saodbjst(callback) {//吃石頭點暴擊
      PLU.execActions("event_1_69809751;event_1_88152825;items info obj_mitiling;");
      UTIL.addSysListener("saodbjst", function (b, type, subtype, msg) {
        if ((type === "items" && subtype === "info" && UTIL.filterMsg(b.get("name")) === _("谜题令", "謎題令"))) {
          PLU.execActions("items use obj_mitiling;");
        } else if ((type === "notice" && msg.indexOf(_("使用谜题令成功,可使用谜题卡次数+", "使用謎題令成功,可使用謎題卡次數+")) !== -1)) {
          setTimeout(function () {
            PLU.execActions("items use obj_mitiling;");
          }, 200);
        } else if ((type === "notice" && subtype === "notify_fail" && msg.indexOf(_("你目前不能使用\x1B[1;32m谜题令", "你目前不能使用\x1B[1;32m謎題令")) !== -1)) {
          setTimeout(function () {
            PLU.execActions("vip finish_big_task;");
          }, 200);
        } else if ((type === "main_msg" && msg.indexOf(_("恭喜你,额外获得", "恭喜你,額外獲得")) !== -1)) {
          setTimeout(function () {
            PLU.execActions("vip buy_task;vip finish_big_task;");
          }, 200);
        } else if ((type === "notice" && msg.indexOf(_("今日谜题任务已做完。", "今日謎題任務已做完。")) !== -1)) {
          UTIL.delSysListener("saodbjst");
          PLU.execActions(_("log?完成VIP暴击扫荡第二次;", "log?完成VIP暴擊掃蕩第二次;"), callback);
        }
      });
    },
    saodbj(callback) {
      PLU.execActions("wear obj_zhongzuiduxing;wear obj_qingtianwanshi;wear obj_lankeyimeng;wear obj_shanyecunfu;wear obj_xianzhe-xianglian;wear obj_xianzhe-shouzhuo;wear obj_xianzhe-jiezhi;items get_store /obj/shop/mitiling;items info obj_mitiling;");
      UTIL.addSysListener("saodbj", function (b, type, subtype, msg) {
        if ((type === "items" && subtype === "info" && UTIL.filterMsg(b.get("name")) === _("谜题令", "謎題令"))) {
          PLU.execActions("items use obj_mitiling;");
        } else if ((type === "notice" && msg.indexOf(_("使用谜题令成功,可使用谜题卡次数+", "使用謎題令成功,可使用謎題卡次數+")) !== -1)) {
          setTimeout(function () {
            PLU.execActions("items use obj_mitiling;");
          }, 200);
        } else if ((type === "notice" && subtype === "notify_fail" && msg.indexOf(_("你目前不能使用\x1B[1;32m谜题令", "你目前不能使用\x1B[1;32m謎題令")) !== -1)) {
          setTimeout(function () {
            PLU.execActions("vip finish_big_task;");
          }, 200);
        } else if ((type === "main_msg" && msg.indexOf(_("恭喜你,额外获得", "恭喜你,額外獲得")) !== -1)) {
          setTimeout(function () {
            PLU.execActions("vip buy_task;vip finish_big_task;");
          }, 200);
        } else if ((type === "notice" && msg.indexOf(_("今日谜题任务已做完。", "今日謎題任務已做完。")) !== -1)) {
          UTIL.delSysListener("saodbj");
          PLU.execActions(_("log?完成VIP暴击扫荡;", "log?完成VIP暴擊掃蕩;"), callback);
        }
      });
    },
    DailyOres(callback) {
      PLU.execActions("jh 2;#10 n;#2 w;event_1_85264690;items info obj_tbg;");
      UTIL.addSysListener("DailyOres", function (b, type, subtype, msg) {
        if ((type === "items" && subtype === "info" && UTIL.filterMsg(b.get("name")) === _("探宝镐", "探寶鎬"))) {
          PLU.execActions("#2 w;event_1_37287831;event_1_49475184;home;", callback);
        } else if (type == "notice" && subtype == "notify_fail" && msg.indexOf(_("你的背包里没有这个物品", "你的背包裡沒有這個物品")) == 0) {
          PLU.execActions("home;", callback);
        }
      });
    },
    initrichangrenwu() {
      var _this = this;
      this.getVipInfo(function (b) {
        _this.getClanInfo(function (a) { });
      });
      this.rcrenwu = [
        //{ n: "副本十一", fn: PLU.killFB11 },
        {
          n: "副本十一",
          go: "fb 11;ak;nw;=400;se;n;=400;s;ne;=400;sw;e;=400;w;se;=400;nw;s;=400;n;sw;=400;ne;w;=400;w;=400;e;e;nw;nw;=400;se;se;n;n;=400;s;s;ne;ne;=400;sw;sw;e;e;=400;w;w;se;se;=400;nw;nw;s;s;=400;n;n;sw;sw;=4000;ka;vs:event_1_68529291;"
        }, {
          n: _("幽冥后院", "幽冥後院"),
          go: "jh 45;ne;ne;n;n;ne;ne;e;ne;#5 n;ne;ne;#3 n;nw;nw;n;#5 e;event_1_77775145 ymsz_houyuan;se;ak;=400;se;=400;s;=400;w;=400;e;e;=400;w;s;=400;s;=400;s;=400;w;=400;e;e;=400;s;=400;n;e;=400;e;=400;n;=400;s;e;=400;e;=400;n;=500;ka;"
        }, {
          n: _("西凉铁剑", "西涼鐵劍"),
          go: "jh 47;ne;n;n;n;ne;ne;e;e;e;e;ne;n;ne;n;n;n;n;n;nw;nw;ne;n;ne;n;vs:event_1_10117215;"
        }, {
          n: _("四大绝杀", "四大絕殺"),
          go: "jh 44;n;n;n;n;e;ne;ne;ne;n;n;n;n;n;nw;nw;nw;w;n;n;n;n;e;n;n;n;n;n;w;w;n;n;n;n;n;n;n;n;vs:event_1_33144912;"
        }, {
          n: _("剑宫白猿", "劍宮白猿"),
          go: "rank go 204;e;s;s;s;s;s;s;s;s;w;w;n;n;n;n;nw;nw;nw;n;n;n;vs:event_1_79113775;"
        }, {
          n: "十八木人",
          go: "jh 41;se;e;e;se;se;se;se;se;se;event_1_57976870;n;n;n;event_1_91914705;e;e;e;vs:event_1_85950082;"
        }, {
          n: _("阎王十殿", "閻王十殿"),
          go: "rank go 223;nw;event_1_42827171;=200;kill yanwangshidian_zhuanlunwang;ak;;ka;;vs:event_1_45876452;=3500;vs:event_1_45876452;"
        }, {
          n: _("格斗五十", "格鬥五十"),
          fn: PLU.gedou50
        }, {
          n: _("生死双修", "生死雙修"),
          fn: PLU.piapiapia
        }, {
          n: _("讨天命丹", "討天命丹"),
          fn: PLU.askTianmd
        }, {
          n: _("天龙塔林", "天龍塔林"),
          fn: PLU.killtalin
        }, {
          n: "拱辰十三",
          go: "jh 1;e;#4 n;w;event_1_90287255 go 9;n;#3 w;n;event_1_63249896;=500;ak;=500;ka;=500;event_1_23639130;=500;golook_room"
        }, {
          n: _("南诏宝斋", "南詔寶齋"),
          fn: PLU.rongbaoz
        }, {
          n: _("南诏奏乐", "南詔奏樂"),
          fn: PLU.nanzzouy
        }, {
          n: _("南诏问诊", "南詔問診"),
          fn: PLU.nanzwenz
        }, {
          n: _("修补长城", "修補長城"),
          go: "rank go 311;s;s;sw;se;se;se;e;se;se;sw;sw;=500;event_1_71928780;"
        }, {
          n: _("西夏灵鹫", "西夏靈鷲"),
          go: "rank go 311;event_1_57364318;=500;ak;;ka;=500;event_1_86741439;"
        }, {
          n: "西夏哈日",
          fn: PLU.goHaRi
        }, {
          n: "西夏九翼",
          go: _("rank go 311;s;s;sw;log?自己换脱装备打吧;", "rank go 311;s;s;sw;log?自己換脫裝備打吧;")
        }, {
          n: "",
          go: "home;"
        },
      ];
    },
    TianShan7Xia(callback) {
      PLU.execActions(_("jh 39;ne;e;n;ne;ne;n;ne;nw;ne;nw;event_1_17801939;place?星星峡;ne;ne;nw;nw", "jh 39;ne;e;n;ne;ne;n;ne;nw;ne;nw;event_1_17801939;place?星星峽;ne;ne;nw;nw"), () => {
        PLU.autoFight({
          targetKey: "\nevent_1_37376258", // 懒的改函数了,直接注入(
          fightKind: " ",
          onFail() {
            PLU.execActions("home;", () => {
              callback && callback();
            });
          },
          onEnd() {
            PLU.execActions("home;", () => {
              callback && callback();
            });
          },
        });
      });
    },
    loopAnswerQues(callback) {
      let setAnswerTimeout = function () {
        PLU.STO.ansTo && clearTimeout(PLU.STO.ansTo);
        PLU.STO.ansTo = setTimeout(() => {
          UTIL.delSysListener("onAnswerQuestions");
          YFUI.writeToOut("<span style='color:#FFF;'>--" + _("答案超时", "答案超時") + "!--</span>");
        }, 5000);
      };
      UTIL.addSysListener("onAnswerQuestions", function (b, type, subtype, msg) {
        if (type == "notice" && msg.indexOf(_("每日武林知识问答次数已经达到限额", "每日武林知識問答次數已經達到限額")) > -1) {
          if (callback) callback();
          else clickButton("home");
          UTIL.delSysListener("onAnswerQuestions");
          PLU.STO.ansTo && clearTimeout(PLU.STO.ansTo);
          return;
        }
        if (type != "show_html_page") return;
        var qs = msg.split("\n");
        if (!qs) return;
        if (qs[0].indexOf(_("知识问答第", "知識問答第")) < 0) return;
        setAnswerTimeout();
        var qus = "";
        for (var i = 1; i < qs.length; i++) {
          qus = $.trim(UTIL.filterMsg(qs[i]));
          if (qus.length > 0) break;
        }
        if (qus.indexOf(_("回答正确", "回答正確")) >= 0) {
          clickButton("question");
          return;
        }
        var answer = PLU.getAnswer2Question(qus);
        if (answer == null) {
          UTIL.delSysListener("onAnswerQuestions");
          PLU.STO.ansTo && clearTimeout(PLU.STO.ansTo);
          PLU.setBtnRed($btn, 0);
          YFUI.writeToOut("<span style='color:#FFF;'>--未找到答案:" + qus + "--</span>");
          return;
        }
        setTimeout(() => {
          clickButton("question " + answer);
        }, 300);
      });
      setAnswerTimeout();
      clickButton("question");
    },
    //================================================================================================
    getAnswer2Question(localQuestion) {
      var answer = PLU.YFD.QuestAnsLibs[localQuestion];
      if (answer) return answer;
      var halfQuestion = localQuestion.substring(localQuestion.length / 2);
      for (var quest in PLU.YFD.QuestAnsLibs) {
        if (quest.indexOf(halfQuestion) == 0) {
          return PLU.YFD.QuestAnsLibs[quest];
        }
      }
      return null;
    },
    //================================================================================================
    autoBingyue(callback) {
      PLU.execActions("jh 14;w;n;n;n;n;event_1_32682066;;;", () => {
        setTimeout(() => {
          PLU.killBingYue(() => {
            if (callback) callback();
            else clickButton("home");
          });
        });
      });
    },
    //================================================================================================
    killBingYue(endCallback) {
      if (parseInt(PLU.getCache("autoPerform")) < 1) {
        PLU.toggleAutoPerform($("#btn_bt_kg_autoPerform"), "autoPerform", 1);
      }
      let tryKill = function (kname, cb, er) {
        PLU.autoFight({
          targetName: kname,
          fightKind: "kill",
          onFail() {
            er && er();
          },
          onEnd() {
            cb && cb();
          },
        });
      };
      PLU.execActions("event_1_48044005;;;;", () => {
        tryKill(
          _("冰麟兽", "冰麟獸"),
          () => {
            PLU.execActions("event_1_95129086;;;;", () => {
              tryKill(
                _("玄武机关兽", "玄武機關獸"),
                () => {
                  PLU.execActions("event_1_17623983;event_1_41741346;;;;", () => {
                    tryKill(
                      _("九幽魔灵", "九幽魔靈"),
                      () => {
                        PLU.execActions("s;;;;", () => {
                          tryKill(
                            "冰月仙人",
                            () => {
                              endCallback && endCallback();
                            },
                            () => {
                              endCallback && endCallback();
                            },
                          );
                        });
                      },
                      () => {
                        endCallback && endCallback();
                      },
                    );
                  });
                },
                () => {
                  endCallback && endCallback();
                },
              );
            });
          },
          () => {
            endCallback && endCallback();
          },
        );
      });
    },
    //================================================================================================
    autoXTL1() {
      clickButton("team create");
      PLU.killLHYD((err) => {
        return YFUI.writeToOut("<span style='color:#FFF;'>結束--" + err + "</span>");
      });
    },
    autoXTL2() {
      clickButton("team create");
      PLU.killSY((err) => {
        return YFUI.writeToOut("<span style='color:#FFF;'>結束--" + err + "</span>");
      });
    },
    autoERG() {
      PLU.killERG((err) => {
        return YFUI.writeToOut("<span style='color:#FFF;'>結束--" + err + "</span>");
      });
    },
    scanPuzzle() {
      PLU.TMP.autoscan = true;
      PLU.TMP.autotask = true;
      UTIL.addSysListener("reload", (b, type, subtype, msg) => {
        if (type == "notice" && subtype == "notify_fail" && msg == _("你的背包里没有这个物品。\n", "你的背包裡沒有這個物品。\n")) location.reload();
      });
      if (!PLU.TMP.index) PLU.TMP.index = 0;
      PLU.TMP.func = () => {
        PLU.execActions(PLU.linkPath(PLU.queryRoomPath(), PLU.YFD.mapsLib.Npc_New[PLU.TMP.index].way), () => {
          PLU.execActions(";;ask " + PLU.YFD.mapsLib.Npc_New[PLU.TMP.index].id, () => {
            PLU.TMP.puzzleTimeOut = setTimeout(() => {
              if (!PLU.TMP.puzzleWating.status) {
                PLU.TMP.index++;
                PLU.TMP.func();
              }
            }, PLU.getCache("puzzleTimeOut") * 1000);
          });
        });
      };
      PLU.TMP.func();
    },
    sword_quest_1() {
      YFUI.showPop({
        title: "論劍外傳#1",
        text: "1:承接上文,24小時后對話楊掌櫃<br>2:對話第一章花不為<br>3:對話水煙閣司事<br>4:對話魔教楊延慶,對話魔教花想容<br>5:去星宿山洞(採藥人右下角),對話看門的刀妖(一定要 對話,不然摸不到雪芝),殺了看門的進去,獲得雪芝(想搜索到雪芝需要50+福緣)<br>6:去找花落雲(是新門派碧落城祖師,洛陽蓑衣男子進入行界山找吧),把雪芝給她,獲得紙條, 玄鐵鑰匙,金錠20,這時候可以打開箱子了,使用玄鐵鑰匙打開神秘寶匣,獲得百年紫芝x1、高級狂暴丹x1、高級大還丹x1、高級乾坤再造丹x1、普通寶石x1<br>7:去唐門,進門 右,對話高一毅,點錦屏之巔(上去要求身法100+),直上對話張之岳,再對話高一毅<br>8:去青城,進門往上,都江堰上,點進去(要求200萬+敏捷),進去殺孽龍( 相當於削弱版極武聖,分身無限刷新,不難),獲得:龍神赤魂x1。 PS:一定要對話高,不然打了沒有龍神赤魄,每天都能打一次,贏了60萬潛能。<br>9:把東西給張之岳,獲得:突破丹x1、高級突破丹x1<br>10:去水煙,進門上右邊無名洞穴點搜索,獲得龍脈寶箱<br>11:回唐門,給予高一毅,獲得銀兩1000萬<br>12:回去梅莊 放鶴亭那進入岳王廟,對話武悼,獲得普通寶石一顆<br>13:去魔教找楊延慶,對花想容,然後去魔教進門往上的黃土小徑那對話冉無望(魔教子午樓店小二那附近)<br>14:對話冉無望, 再比試冉無望,然後再對話。<br>15:要你殺鮮卑首領,很明顯就是慕容世家(看過天龍八部的應該都清楚,一個復國慕容複背負一生),砍了倆父子(殺個慕容博就好了),回去對話冉無望,獲得虎皮袋<br>16:給予高一毅,要你殺副本四boss九天老祖獲得九天符<br>17:給予高一毅,回去對話梅莊武悼,獲得:『天地風雨卷』x1、狂暴丹x5<br>",
        onOk() {},
        onNo() {},
      });
    },
    puzzleTimeOut() {
      YFUI.showInput({
        title: "超時設置",
        text: "一條謎題最多耗時(單位:秒),0爲不超時,暫不推薦設置爲0",
        value: PLU.getCache("puzzleTimeOut") || 60,
        onOk(val) {
          PLU.setCache("puzzleTimeOut", val);
        },
        onNo() { },
      });
    },
    path4FHMJ(endCallback) {
      PLU.execActions("jh");
      if (g_obj_map.get("msg_jh_list") && g_obj_map.get("msg_jh_list").get("finish43") == 0) {
        return "jh 1;e;n;n;n;n;w;event_1_90287255 go 6;e;s;sw;se;ne;se;s;";
      } else {
        return "jh 43;sw;sw;sw;s;se;se;se;e;s;sw;se;ne;se;s;";
      }
    },
    //琅嬛玉洞
    killLHYD(endCallback) {
      PLU.execActions(PLU.path4FHMJ() + "event_1_52732806", (f) => {
        if (!f) return endCallback && endCallback(1);
        PLU.execActions("kill langhuanyudong_qixing;;kill langhuanyudong_benkuangxiao;;sw;;kill murong_tuboguoshi;;;" + _("get?吐蕃国师的尸体;;", "get?吐蕃國師的屍體;;"), (f2) => {
          if (!f2) return endCallback && endCallback(2);
          PLU.execActions("ne;n;;event_1_96023188;w;event_1_39972900;w;event_1_92817399;w;event_1_91110342;s;event_1_74276536;se;event_1_14726005;se;se;;;", () => {
            let sd = g_obj_map.get("msg_room").elements.find((e) => e.value.indexOf(_("掃蕩", "掃盪")) >= 0);
            if (sd) {
              let cmd_sd = g_obj_map.get("msg_room").get(sd.key.split("_")[0]);
              PLU.doSaoDang("langhuanyudong", cmd_sd, () => {
                PLU.killLHYD(endCallback);
              });
            } else {
              endCallback && endCallback(5);
            }
          });
        });
      });
    },
    //山崖
    killSY(endCallback) {
      PLU.execActions(PLU.path4FHMJ() + "event_1_64526228", (f) => {
        if (!f) return endCallback && endCallback(1);
        PLU.execActions("kill shanya_muzhaoxue;;kill shanya_qiongduwu;;kill shanya_yuanzhenheshang;;;", (f2) => {
          if (!f2) return endCallback && endCallback(2);
          PLU.execActions("w;event_1_61179401;n;event_1_93134350;n;event_1_60227051;n;event_1_66986009;;kill mingjiao_mengmianrentoumu;;;;" + _("get?蒙面人头目的尸体;;", "get?蒙面人頭目的屍體;;"), () => {
            PLU.execActions("n;event_1_53067175;n;event_1_58530809;w;event_1_86449371;event_1_66983665;;", () => {
              let sd = g_obj_map.get("msg_room").elements.find((e) => e.value.indexOf(_("掃蕩", "掃盪")) >= 0);
              if (sd) {
                let cmd_sd = g_obj_map.get("msg_room").get(sd.key.split("_")[0]);
                PLU.doSaoDang("shanya", cmd_sd, () => {
                  PLU.killSY(endCallback);
                });
              } else {
                endCallback && endCallback(5);
              }
            });
          });
        });
      });
    },
    // 恶人谷
    killERG(endCallback) {
      var flag = false;
      PLU.execActions("rank go 236;", (f) => {
        if (!f) return endCallback && endCallback(1);
        PLU.execActions("nw;n;n;n;n;n;n;wait#kill tianlongsi_lidazui;" + _("get?李大嘴的尸体;", "get?李大嘴的屍體;"), (f2) => {
          if (!f2) return endCallback && endCallback(2);
          PLU.execActions("nw;nw;n;wait#kill tianlongsi_baikaixin;" + _("get?白开心的尸体", "get?白開心的屍體"), (f3) => {
            if (!f3) return endCallback && endCallback(3);
          });
        });
      });
    },
    buyJHYL() {
      UTIL.addSysListener("9HYL", (b, type, subtype, msg) => {
        if (type != "show_html_page") return;
        var sp = msg.match(/你有四海商票\u001b\[1;32mx(\d+)\u001b\[2;37;0m/);
        if (!sp) return;
        sp = sp[1];
        if (sp < 21750) return YFUI.writeToOut("<span style='color:#FF0;'>--你的商票不足21750--</span>");
        else
          PLU.execActions(
            "reclaim buy 27 go 45;" + // 矢車菊
            "reclaim buy 46 go 45;" + // 雪英
            "reclaim buy 45 go 45;" + // 忘憂草
            "reclaim buy 29 go 15;" + // 鳳凰木
            "reclaim buy 36 go 5;" + // 洛神花
            "reclaim buy 31 go 45;" + // 君影草
            "reclaim buy 32 go 45;" + // 仙客來
            "reclaim buy 33 go 15;" + // 淩霄花
            "reclaim buy 34 go 15;" + // 夕霧草
            (UTIL.inHome() ? "go_lookroom" : "home"),
          );
        UTIL.delSysListener("9HYL");
      });
      PLU.execActions("reclaim recl");
    },
    //============日常任務===================================================================
    tiejian() {
      //西涼鐵劍
      PLU.execActions("jh 47;ne;n;n;n;ne;ne;e;e;e;e;ne;n;ne;n;n;n;n;n;nw;nw;ne;n;ne;n;event_1_10117215;;");
    },
    baiyuan() {
      //劍宮白猿
      PLU.execActions("rank go 204;e;s;s;s;s;s;s;s;s;w;w;n;n;n;n;nw;nw;nw;n;n;n;event_1_79113775;;");
    },
    yanwang10() {
      //閻王十殿
      PLU.execActions("rank go 223;nw;event_1_42827171;ak;;ka;event_1_45876452;;");
    },
    gedou50(callback) {
      // 格鬥五十
      var sjindi = 1;
      UTIL.addSysListener("gedou50", function (b, type, subtype, msg) {
        if (type == "notice") {
          var msgTxt = UTIL.filterMsg(msg);
          if (msgTxt.match("你抽到了")) {
            if (msgTxt.match(_(/此轮游戏结束/, /此輪遊戲結束/))) {
              PLU.execActions("event_1_36867949 get;event_1_36867949 pay;event_1_36867949 take;"); //拿錢走人再開
            }
            var sjindi = msgTxt.match(_(/奖池提升至(\d+)金锭/, /獎池提升至(\d+)金錠/));
            var sjindiNumber = sjindi[1];
            if (sjindiNumber >= 30) {
              YFUI.writeToOut("<span style='color:#FFF;'>--到達--</span>"); //到達地下格鬥場
              UTIL.delSysListener("gedou50");
              PLU.execActions("event_1_36867949 get;event_1_23520182;event_1_70249808 go 50;=24400;;attrs;", callback);
            } else {
              PLU.execActions("=300;event_1_36867949 take;"); //抽牌
            }
          }
        }
      });
      PLU.execActions("rank go 195;event_1_36867949 pay;event_1_36867949 take;");
    },
    gongcheng13() {
      //拱辰13
      PLU.execActions("jh 1;e;#4 n;w;event_1_90287255 go 9;n;#3 w;n;event_1_63249896;ak;;ka;;event_1_23639130;;");
    },
    rongbaoz(callback) {
      var _g_obj_map$get3;
      //容寶齋
      PLU.execActions("golook_room;");
      var curName = UTIL.filterMsg(((_g_obj_map$get3 = g_obj_map.get("msg_room")) === null || _g_obj_map$get3 === void 0 ? void 0 : _g_obj_map$get3.get("short")) || "");
      if (curName == _("拱辰楼十三层", "拱辰樓十三層")) {
        PLU.execActions("event_1_87723605;=500;s;w;w;#10 s;w;w;n;event_1_27429615;", callback);
      } else {
        PLU.execActions("jh 1;e;#4 n;w;event_1_90287255 go 9;n;#5 w;#10 s;w;w;n;event_1_27429615;", callback);
      }
    },
    nanzzouy(callback) {
      var _g_obj_map$get4;
      //南詔奏樂
      PLU.execActions("golook_room;");
      var curName = UTIL.filterMsg(((_g_obj_map$get4 = g_obj_map.get("msg_room")) === null || _g_obj_map$get4 === void 0 ? void 0 : _g_obj_map$get4.get("short")) || "");
      if (curName == _("容宝斋", "容寶齋")) {
        PLU.execActions("s;e;e;n;n;w;n;event_1_41100562;;", callback);
      } else {
        PLU.execActions("jh 1;e;#4 n;w;event_1_90287255 go 9;n;#5 w;#8 s;w;n;event_1_41100562;;attrs;", callback);
      }
    },
    killtalin(callback) {
      var _g_obj_map$get5;
      //天龍塔林
      PLU.execActions("golook_room;");
      var curName = UTIL.filterMsg(((_g_obj_map$get5 = g_obj_map.get("msg_room")) === null || _g_obj_map$get5 === void 0 ? void 0 : _g_obj_map$get5.get("short")) || "");
      var cmd = "";
      if (curName == _("大鹳淜洲", "大鸛淜洲")) {
        cmd = "w;sw;s;s;sw;sw;sw;get tianlongsi_putiguo;se;se;se;ne;get tianlongsi_xiaoxianglu;ne;ne;;get tianlongsi_putiguo;nw;nw;nw;";
      } else {
        cmd = "rank go 236;nw;n;n;n;n;n;n;nw;nw;n;n;nw;nw;n;n;nw;ne;event_1_1996692;event_1_10567243;w;sw;s;s;sw;sw;sw;get tianlongsi_putiguo;se;se;se;ne;get tianlongsi_xiaoxianglu;ne;ne;;get tianlongsi_putiguo;nw;nw;nw;";
      }
      PLU.execActions(cmd, function () {
        PLU.execActions("ak;ka;=1500;home;", callback);
        YFUI.writeToOut("<span style='color:#FFF;'>--塔林完成--</span>");
        callback && callback();
      });
    },
    askTianmd(callback) {
      //討天命丹
      var countttmd = 0;
      PLU.execActions("rank go 236;nw;n;n;n;n;n;n;nw;nw;n;n;nw;nw;n;n;nw;ne;event_1_1996692;event_1_10567243", function () {
        UTIL.addSysListener("asktmd", function (b, type, subtype, msg) {
          if (type == "notice" && msg.startsWith("你得到天命丹x1")) {
            countttmd++;
            YFUI.writeToOut("<span style='color:yellow;'>=====" + _("获", "獲") + "得天命丹:" + countttmd + " 次=====</span>");
            if (countttmd >= 10) {
              UTIL.delSysListener("asktmd");
              YFUI.writeToOut("<span style='color:yellow;'>=====討天命丹完成=====</span>");
              PLU.execActions("golook_room;", function () {
                callback && callback();
              });
            }
          } else if (type == "main_msg" && msg.indexOf(_("柴绍", "柴紹")) >= 0) {
            PLU.execActions(";ask tianlongsi_chaishao;");
          }
        });
        PLU.execActions("ask tianlongsi_chaishao");
      });
    },
    //============周常任務===================================================================
    nanzwenz(callback) {
      var _g_obj_map$get6;
      // 南詔問診
      PLU.execActions("golook_room;");
      var curName = UTIL.filterMsg(((_g_obj_map$get6 = g_obj_map.get("msg_room")) === null || _g_obj_map$get6 === void 0 ? void 0 : _g_obj_map$get6.get("short")) || "");
      var addNanzwenzListener = function addNanzwenzListener() {
          UTIL.addSysListener("nanzwenz", function (b, type, subtype, msg) {
            if (type === "main_msg") {
              var msgTxt = UTIL.filterMsg(msg);
              if (msgTxt.match(_("问诊完成,获得", "問診完成,獲得")) || msgTxt.match(_("你完成了每周的问诊任务", "你完成了每周的問診任務"))) {
                UTIL.delSysListener("nanzwenz");
                PLU.execActions(_("log?完成问诊;", "log?完成問診;"), callback);
              } else if (msgTxt.match(_("你正在诊治中,请耐心对待病人。", "你正在診治中,請耐心對待病人。")) || msgTxt.match(_("于是你拿起医圣的银针", "於是你拿起醫聖的銀針"))) {
                PLU.execActions("=2400;event_1_27222525;");
              }
            }
          });
          PLU.execActions("event_1_27222525;");
        };
      if (curName === _("元帅府", "元帥府")) {
        PLU.execActions("s;e;#8 n;w;w;s", addNanzwenzListener);
      } else {
        PLU.execActions("jh 1;e;n;n;n;n;w;event_1_90287255 go 9;n;#7 w;s;event_1_12050280;", addNanzwenzListener);
      }
    },
    piapiapia(callback) {
      PLU.execActions("rank go 233;#3 s;e;ne;event_1_66728795", function () {
        UTIL.addSysListener("waitVS", function(b, type, subtype, msg) {
          if (type == "vs" && subtype == "vs_info") {
            UTIL.delSysListener("waitVS");
            PLU.autoFight({
              targetCommand: "none",
              onFail: function onFail() {
                setTimeout(callback, 1000);
              },
              onEnd: function onEnd() {
                setTimeout(callback, 500);
              }
            });
          }
        })
      });
    },
    //全殺了
    allkill(params) {
      var npcs = UTIL.getRoomAllNpc().filter(function (e) {
        return !(["金甲符兵", "玄陰符兵", "玄陰符兵"].indexOf(e.name) >= 0);
      });
      //let npcs = UTIL.getRoomAllNpc().filter(e=>!(UTIL.filterMsg(e.name).match(/(金甲|玄陰)符兵/)))
      //let npcs = UTIL.getRoomAllNpc()
      if (npcs.length) {
        PLU.autoFight({
          targetKey: npcs[0].key,
          onEnd: function onEnd() {
            setTimeout(function () {
              PLU.allkill(params);
            }, 500);
          }
        });
      } else {
        params.idx++;
        if (params.paths[params.idx] != "ka") {
          params.paths.splice(params.idx + 1, 0, "ak");
        } else {
          params.idx++;
        }
        setTimeout(function () {
          //PLU.allkill(params);
          PLU.actions(params);
        }, 400);
      }
    },
    //================================================================================================
    execActions(str, endcallback, params) {
      var acs = str
        .split(";")
        .map((e) => {
          let np = e.match(/^#(\d+)\s(.*)/);
          if (np) {
            let r = [];
            for (let i = 0; i < np[1]; i++) r.push(np[2]);
            return r;
          }
          return e;
        })
        .flat()
        .map((e) => {
          if (PLU.YFD.pathCmds[e]) return PLU.YFD.pathCmds[e] + "." + UTIL.rnd();
          return e;
        });
      PLU.actions({
        paths: acs,
        idx: 0,
        onPathsEnd() {
          PLU.STATUS.isBusy = false;
          endcallback && endcallback(true, params);
        },
        onPathsFail() {
          PLU.STATUS.isBusy = false;
          endcallback && endcallback(false, params);
        },
      });
    },
    //================================================================================================
    actions(params) {
      PLU.STATUS.isBusy = true;
      //params:{paths,idx,onPathsEnd,onPathsFail}
      if (params.idx >= params.paths.length) {
        return params.onPathsEnd && params.onPathsEnd();
      }
      let curAct = params.paths[params.idx];
      // 等
      if (!curAct || curAct.startsWith("=")) {
        setTimeout(function () {
          params.idx++;
          PLU.actions(params);
        }, parseInt(curAct.substring(1)) || 250);
        return;
      }
      // 優先處理移動
      if (curAct.startsWith("go")) {
        clickButton(curAct);
        setTimeout(function () {
          params.idx++;
          PLU.actions(params);
        }, 400);
        return;
      }
      // 畫面通知
      if (curAct.indexOf("log?") > -1) {
        YFUI.writeToOut("<span style='color:yellow;'>==" + curAct.substring(4) + "==</span>");
        params.idx++;
        PLU.actions(params);
        return;
      }
      // 等待復活
      if (curAct.indexOf("wait#") > -1 || curAct.indexOf("wait ") > -1) {
        let npc = curAct.substring(curAct.indexOf(" ") + curAct.indexOf("?") + 2);
        if (UTIL.getRoomAllNpc().some((e) => e.name == npc || e.key == npc)) {
          if (params.paths[params.idx].indexOf("wait ") > -1) params.idx++;
          else params.paths[params.idx] = params.paths[params.idx].substring(5);
          PLU.actions(params);
        } else
          UTIL.addSysListener("wait", (b, type, subtype, msg) => {
            if (UTIL.inHome()) {
              UTIL.delSysListener("wait");
              params.idx = params.paths.length;
              PLU.actions(params);
            }
            if (type != "jh") return;
            if (subtype == "info") {
              UTIL.delSysListener("wait");
              params.idx = params.paths.length;
              PLU.actions(params);
            }
            if (subtype != "new_npc") return;
            if (b.get("id") == npc || b.get("name") == npc) {
              UTIL.delSysListener("wait");
              if (curAct.indexOf("wait ") > -1) params.idx++;
              else params.paths[params.idx] = params.paths[params.idx].substring(5);
              PLU.actions(params);
            }
          });
        return;
      }
      //停頓
      if (curAct.indexOf("wait?") > -1) {
        setTimeout(() => {
          params.idx++;
          PLU.actions(params);
        }, parseInt(curAct.substring(5)) * 100);
        return;
      }
      //對話
      if (curAct.indexOf("ask#") > -1) {
        if (curAct.indexOf("?") > -1) {
          var npc = UTIL.findRoomNpc(curAct.substring(curAct.indexOf("?") + 1), 0, 1)?.key;
        } else {
          var npc = curAct.substring(curAct.indexOf(" ") + 1);
        }
        npc && clickButton("ask " + npc);
        params.paths[params.idx] = params.paths[params.idx].substring(4);
        PLU.actions(params);
        return;
      }
      //去比試
      if (curAct.indexOf("fight?") > -1 || curAct.indexOf("fight ") > -1) {
        let kt = parseInt(PLU.getCache("autoPerform")) < 1 ? "multi" : "";
        PLU.autoFight({
          targetName: curAct.indexOf("fight?") > -1 ? curAct.substring(6) : null,
          targetKey: curAct.indexOf("fight ") > -1 ? curAct.substring(6) : null,
          fightKind: "fight",
          autoSkill: kt,
          onFail() {
            setTimeout(() => {
              params.idx++;
              PLU.actions(params);
            }, 500);
          },
          onEnd() {
            setTimeout(() => {
              params.idx++;
              PLU.actions(params);
            }, 500);
          },
        });
        return;
      }
      //去殺
      if (curAct.indexOf("kill?") > -1 || curAct.indexOf("kill ") > -1) {
        let kt = parseInt(PLU.getCache("autoPerform")) < 1 ? "multi" : "";
        PLU.autoFight({
          targetName: curAct.indexOf("kill?") > -1 ? curAct.substring(5) : null,
          targetKey: curAct.indexOf("kill ") > -1 ? curAct.substring(5) : null,
          autoSkill: kt,
          onFail() {
            setTimeout(() => {
              params.idx++;
              PLU.actions(params);
            }, 500);
          },
          onEnd() {
            setTimeout(() => {
              params.idx++;
              PLU.actions(params);
            }, 500);
          },
        });
        return;
      }
      // 去摸屍體
      if (curAct.indexOf("get?") > -1) {
        UTIL.getItemFrom(curAct.substring(4));
        setTimeout(() => {
          params.idx++;
          PLU.actions(params);
        }, 500);
        return;
      }
      // 去摸屍體
      if (curAct.indexOf("@") > -1) {
        UTIL.getItemFrom(curAct.substring(1));
        setTimeout(() => {
          params.idx++;
          PLU.actions(params);
        }, 500);
        return;
      }
      // 叫船
      if (curAct.indexOf("yell") > -1) {
        let yellBoatTimeout = setTimeout((e) => {
          clearTimeout(yellBoatTimeout);
          UTIL.delSysListener("goYellBoat");
          params.idx++;
          PLU.actions(params);
        }, 120000);
        UTIL.addSysListener("goYellBoat", function (b, type, subtype, msg) {
          if (type == "main_msg" && msg.indexOf(_("还没有达到这", "還沒有達到這")) > -1) {
            setTimeout(() => {
              clearTimeout(yellBoatTimeout);
              UTIL.delSysListener("goYellBoat");
              PLU.actions(params);
            }, 2000);
            return;
          }
          if (type == "notice" && msg.indexOf(_("这儿没有船可以喊", "這兒沒有船可以喊")) > -1) {
            setTimeout(() => {
              clearTimeout(yellBoatTimeout);
              UTIL.delSysListener("goYellBoat");
              params.idx++;
              PLU.actions(params);
            }, 500);
            return;
          }
          if (type != "jh" || subtype != "info") return;
          for (var key of b.keys()) {
            var val = b.get(key);
            if (val.indexOf("yell") < 0) continue;
            clearTimeout(yellBoatTimeout);
            UTIL.delSysListener("goYellBoat");
            params.idx++;
            PLU.actions(params);
            break;
          }
        });
        clickButton(curAct);
        return;
      }
      if (curAct.indexOf("vs:") > -1) {
        PLU.autoFight({
          targetCommand: curAct.substring(3) || "none",
          onFail: function onFail() {
            setTimeout(function () {
              params.idx++;
              PLU.actions(params);
            }, 500);
          },
          onEnd: function onEnd() {
            setTimeout(function () {
              params.idx++;
              PLU.actions(params);
            }, 500);
          }
        });
        return;
      }
      //函式
      if (curAct.indexOf("eval_") > -1) {
        eval(curAct.substring(5));
        setTimeout(() => {
          params.idx++;
          PLU.actions(params);
        }, 500);
        return;
      }
      //檢查地點重走
      if (curAct.indexOf("place?") > -1) {
        var pName = curAct.split(/[?:]/)[1];
        var curName = UTIL.filterMsg(g_obj_map.get("msg_room").get("short") || "");
        var backStep = curAct.split(/[?:]/)[2];
        // 未到達指定地,重新走
        if (pName != curName) {
          if (backStep) {
            //退後幾步
            params.idx -= Number(backStep);
            PLU.actions(params);
            return;
          }
          params.idx = 0;
          PLU.actions(params);
          return;
        }
        // 已到達指定地點,繼續下一個
        params.idx++;
        PLU.actions(params);
        return;
      }

      //迷宫
      if (curAct.match(/^(.+):(.+\^.+)$/)) {
        let cmd = curAct.match(/^(.+):(.+\^.+)$/);
        PLU.execActions(PLU.YFD.mapsLib.Labyrinth[cmd[1]][cmd[2]], () => {
          params.idx++;
          PLU.actions(params);
        });
        return;
      }

      //稱號飛修正
      if (curAct.indexOf("rank go") > -1) {
        let m = curAct.match(/rank go (\d+)/);
        if (m && m[1]) {
          curAct = "rank go " + (Number(m[1]) + 1);
        }
      }

      //look,ask,
      if (curAct.match(/look|ask|get|buy|home|prev|moke|sort|share|sign|sleep|exercise|clan|work|chushi |vip |event_|lq_|wear |wield |remove |unwield/)) {
        if (curAct == "ask?lama_master") {
          UTIL.addSysListener("lama", (b, type, subtype, msg) => {
            if (type == "main_msg")
              if (msg.indexOf(_("葛伦师傅在幻境之中", "葛倫師傅在幻境之中")) == -1) clickButton("ask lama_master");
              else {
                params.idx++;
                PLU.actions(params);
                UTIL.delSysListener("lama");
              }
          });
          clickButton("ask lama_master");
        } else {
          clickButton(curAct);
          setTimeout(() => {
            params.idx++;
            PLU.actions(params);
          }, 300);
        }
        return;
      }
      
      if (curAct.indexOf("ak") > -1) {
        PLU.allkill(params);
        return;
      }
      
      //look,ask,
      if (curAct.match(/items use|items put_store|items get_store/)) {
        clickButton(curAct);
        setTimeout(() => {
          params.idx++;
          PLU.actions(params);
        }, 500);
        return;
      }
      
      if (curAct == "飛雪連天射白鹿,笑書神俠倚碧鴛。" || curAct == "飞雪连天射白鹿,笑书神侠倚碧鸳。") {
        if (PLU.developerMode) {
          PLU.setCache("developer", 0);
          YFUI.writeToOut("<span style='color:white;'>==已關閉開發者模式部分功能,刷新後關閉開發者模式全部功能==</span>");
          setTimeout(() => location.reload(), 300);
        } else {
          YFUI.showPop({
            title: "!!!警告!!!",
            text: _(
              "你将开启本脚本开发者模式<br>" +
              "开发者模式功能清单:<br>" +
              "浏览器控制台(F12)输出按键指令、变量g_obj_map的实时变化<br>" +
              "闲聊允许向非脚本玩家打印屏蔽词(屏蔽词不会转为“*”,单字、特殊字符除外)<br>" +
              "可在非首页、非师傅所在地拜入门派,包括未开图的隐藏门派(掌握空间法则(误))<br>" +
              "显示全自动暴击开关(掌握时间法则(延长寿命(<br>" +
              "<b>实验功能可能会导致封号,是否继续?</b>",
              "你將開啟本腳本開發者模式<br>" +
              "開發者模式功能清單:<br>" +
              "瀏覽器控制檯(F12)輸出按鍵指令、變量g_obj_map的實時變化<br>" +
              "閒聊允許向非腳本玩家打印屏蔽詞(屏蔽詞不會轉為“*”,單字、特殊字符除外)<br>" +
              "可在非首頁、非師傅所在地拜入門派,包括未開圖的隱藏門派(掌握空間法則(誤))<br>" +
              "顯示全自動暴擊開關(掌握時間法則(延長壽命(<br>" +
              "<b>實驗功能可能會導致封號,是否繼續?</b>",
            ),
            okText: _("继续", "繼續"),
            onOk() {
              PLU.setCache("developer", 1);
              location.reload();
            },
            onNo() {
              params.idx++;
              PLU.actions(params);
            },
          });
        }
        return;
      }
      //行動
      PLU.go({
        action: curAct,
        onEnd() {
          if (params.idx + 1 >= params.paths.length) {
            return params.onPathsEnd && params.onPathsEnd();
          }
          params.idx++;
          PLU.actions(params);
        },
        onFail(flag) {
          if (flag && PLU.STATUS.inBattle) {
            PLU.autoEscape({
              onEnd() {
                setTimeout(() => {
                  PLU.actions(params);
                }, 1000);
              },
            });
            return;
          } else if (flag) {
            if (PLU.STO.REGO) {
              clearTimeout(PLU.STO.REGO);
              PLU.STO.REGO = null;
            }
            PLU.STO.REGO = setTimeout(() => {
              params.idx++;
              PLU.actions(params);
            }, 1000);
          } else {
            params.onPathsFail && params.onPathsFail();
          }
        },
      });
    },
    //================================================================================================
    openXiang(obj, obj1) {
      var items = g_obj_map.get("msg_items").elements.filter(function (item) {
        return item.key.indexOf("items") > -1
      });
      var cmds = [];
      var itemId = null;
      var itemName = null;
      var itemNums = 0;
      var itemNums0 = 0;

      var itemId1 = null;
      var itemName1 = null;
      var itemNums1 = 0;

      for (var i = 0; i < items.length; i++) {
        var id = items[i].value.split(",")[0];
        var name = items[i].value.split(",")[1];
        var nums = items[i].value.split(",")[2];
        var txt = g_simul_efun.replaceControlCharBlank(
          name.replace(/\u0003.*?\u0003/g, "")
        );
        if (txt.indexOf(obj) != '-1') {
          itemId = id;
          itemName = txt;
          itemNums = nums;
          break;
        }
      }
      itemNums0 = itemNums;
      if (obj1) {
        for (var i = 0; i < items.length; i++) {
          var id = items[i].value.split(",")[0];
          var name = items[i].value.split(",")[1];
          var nums = items[i].value.split(",")[2];
          var txt = g_simul_efun.replaceControlCharBlank(
            name.replace(/\u0003.*?\u0003/g, "")
          );
          // console.log(id + '----' + txt)
          if (txt.indexOf(obj1) != '-1') {
            itemId1 = id;
            itemName1 = txt;
            itemNums1 = nums;
            break;
          }
        }
        if (itemNums1) {
          if (itemNums1 * 1 > itemNums * 1) {
            itemNums0 = itemNums;
          } else {
            itemNums0 = itemNums1;
          }
          PLU.openXiangCode(itemId, itemNums0)
        }
      } else {
        PLU.openXiangCode(itemId, itemNums0)
      }
      clickButton("items", 0);
    },
    openXiangCode(id, num) {
      console.log(id + '--' + num);
      PLU.execActions('items use ' + id + "_N_" + num);

      //clickButton(\'items use ' + item.get("id") + "_N_" + item.get("amount") + '\', 1)
      //clickButton('items use obj_yaoyubaoxiang', 0)
    },
    //================================================================================================
    go({ action, onEnd, onFail }) {
      if (!action) return onEnd && onEnd(false);
      let clearGoTimeout = function (timeoutKey) {
        clearTimeout(timeoutKey);
        timeoutKey = null;
        UTIL.delSysListener("goMove");
      };
      let goTimeout = setTimeout(function () {
        clearGoTimeout(goTimeout);
        onEnd && onEnd(false);
      }, 2000);
      UTIL.addSysListener("goMove", function (b, type, subtype, msg) {
        if (type == "notice" && subtype == "notify_fail") {
          if (msg.indexOf(_("你正忙着呢", "你正忙著呢")) > -1) {
            clearGoTimeout(goTimeout);
            return onFail && onFail(true);
          }
          if (
            msg.indexOf(_("无法走动", "無法走動")) > -1 ||
            msg.indexOf(_("没有这个方向", "沒有這個方向")) > -1 ||
            msg.indexOf(_("只有VIP才可以直接去往此地", "只有VIP才可以直接去往此地")) > -1 ||
            msg.indexOf(_("你什麽都没发觉", "你什麼都沒發覺")) > -1 ||
            msg.indexOf("就此鑽入恐有辱墓主") > -1 ||
            msg.indexOf(_("你虽知这松林内有乾坤,但并没发现任何线索", "你雖知這松林內有乾坤,但並沒發現任何線索")) > -1 ||
            msg.indexOf(_("此地图还未解锁,请先通关前面的地图。", "此地圖還未解鎖,請先通關前面的地圖。")) > -1
          ) {
            clearGoTimeout(goTimeout);
            return onFail && onFail(false, msg);
          }
        }
        if (type == "unknow_command" || (type == "jh" && subtype == "info")) {
          clearGoTimeout(goTimeout);
          setTimeout(function () {
            onEnd && onEnd(true);
          }, 200);
          return;
        }
      });
      clickButton(action);
    },
    //================================================================================================
    fastExec(str, endcallback) {
      var acs = str
        .split(";")
        .map((e) => {
          let np = e.match(/^#(\d+)\s(.*)/);
          if (np) {
            let r = [];
            for (let i = 0; i < np[1]; i++) r.push(np[2]);
            return r;
          }
          return e;
        })
        .flat()
        .map((e) => {
          if (PLU.YFD.pathCmds[e]) return PLU.YFD.pathCmds[e] + "." + UTIL.rnd();
          return e;
        });
      let fastFunc = (acts, idx) => {
        if (idx >= acts.length) {
          setTimeout(() => {
            endcallback && endcallback(true);
          }, 1000);
          return;
        }
        let curAct = acts[idx];
        if (!curAct) return fastFunc(acts, idx + 1);
        clickButton(curAct);
        setTimeout(() => {
          fastFunc(acts, idx + 1);
        }, 200);
        return;
      };
      fastFunc(acs, 0);
    },
    //================================================================================================
    selectSkills(skillName) {
      if (!PLU.battleData || !PLU.battleData.skills) return null;
      let keys = Object.keys(PLU.battleData.skills);
      if (skillName) {
        for (let i = 0; i < keys.length; i++) {
          let sk = PLU.battleData.skills[keys[i]];
          if (sk && sk.name && sk.name.match(skillName)) return sk;
        }
      } else {
        let n = Math.floor(keys.length * Math.random());
        return PLU.battleData.skills[keys[n]];
      }
      return null;
    },
    //================================================================================================
    autoFight(params) {
      if (PLU.STO.autoF) {
        clearTimeout(PLU.STO.autoF);
        PLU.STO.autoF = null;
      }
      if (!params.targetKey && !params.targetName) {
        params.onFail && params.onFail(0);
        YFUI.writeToOut("<span style='color:#FFF;'>--" + _("战斗参数缺失", "戰鬥參數缺失") + "--</span>");
        return;
      }
      if (params.targetName && !params.targetKey) {
        let npcObj = UTIL.findRoomNpc(params.targetName, false, true);
        if (npcObj) {
          params.targetKey = npcObj.key;
        } else {
          params.onFail && params.onFail(1);
          YFUI.writeToOut("<span style='color:#FFF;'>--找不到NPC--</span>");
          return;
        }
      }
      let fightAct = params.fightKind ?? "kill";
      let performTime = 0;
      UTIL.addSysListener("onAutoFight", function (b, type, subtype, msg) {
        if (type == "vs" && subtype == "vs_info") {
          setTimeout(() => {
            if (params.autoSkill && PLU.battleData) PLU.battleData.autoSkill = params.autoSkill;
          }, 100);
          if (PLU.TMP.loopCheckFight) {
            clearInterval(PLU.TMP.loopCheckFight);
            PLU.TMP.loopCheckFight = null;
          }
          PLU.TMP.loopCheckFight = setInterval(() => {
            if (!g_gmain.is_fighting) {
              UTIL.delSysListener("onAutoFight");
              if (PLU.STO.autoF) {
                clearTimeout(PLU.STO.autoF);
                PLU.STO.autoF = null;
              }
              if (PLU.TMP.loopCheckFight) {
                clearInterval(PLU.TMP.loopCheckFight);
                PLU.TMP.loopCheckFight = null;
              }
              params.onEnd && params.onEnd();
            }
          }, 2000);
          params.onStart && params.onStart();
        } else if (type == "vs" && (subtype == "add_xdz" || subtype == "text" || subtype == "attack")) {
          let curTime = new Date().getTime();
          if (curTime - performTime < 500) return;
          performTime = curTime;
          let useSkill = null;
          if (params.autoSkill) {
            if (!PLU.battleData || PLU.battleData.xdz < 2) return;
            if (params.autoSkill == "item") {
              if (PLU.battleData.xdz >= 6) useSkill = { key: "playskill 7" };
              else useSkill = {};
            } else if (params.autoSkill == "dodge") {
              if (PLU.battleData.xdz > 9) useSkill = PLU.selectSkills(_(/乾坤大挪移|凌波微步|无影毒阵|九妙飞天术/, /乾坤大挪移|淩波微步|無影毒陣|九妙飛天術/));
            } else if (params.autoSkill == "multi") {
              if (PLU.battleData.xdz > 2) useSkill = PLU.selectSkills(_(/破军棍法|千影百伤棍|八荒功|月夜鬼萧|打狗棒法/, /破軍棍法|千影百傷棍|八荒功|月夜鬼蕭|打狗棒法/));
            } else if (params.autoSkill == "fast") {
              if (PLU.battleData.xdz >= 2) useSkill = PLU.selectSkills(_(/吸星大法|斗转星移|无影毒阵|空明拳|乾坤大挪移/, /吸星大法|斗轉星移|無影毒陣|空明拳|乾坤大挪移/));
            }
            if (!useSkill) {
              if (PLU.getCache("autoPerform") >= 1) {
                PLU.battleData.autoSkill = "";
                return;
              }
              if (params.autoSkill) PLU.battleData.autoSkill = "";
              useSkill = PLU.selectSkills();
            }
            if (params.onFighting) {
              let block = params.onFighting(useSkill);
              if (block) return;
            }
            useSkill && clickButton(useSkill.key, 0);
          } else {
            params.onFighting && params.onFighting();
          }
        } else if (type == "vs" && subtype == "combat_result") {
          performTime = 0;
          UTIL.delSysListener("onAutoFight");
          if (PLU.STO.autoF) {
            clearTimeout(PLU.STO.autoF);
            PLU.STO.autoF = null;
          }
          if (PLU.TMP.loopCheckFight) {
            clearInterval(PLU.TMP.loopCheckFight);
            PLU.TMP.loopCheckFight = null;
          }
          clickButton("prev_combat");
          params.onEnd && params.onEnd();
        } else if (type == "notice" && subtype == "notify_fail") {
          let errCode = 0;
          if (msg.indexOf(_("没有这个人", "沒有這個人")) > -1) {
            errCode = 1;
          } else if (msg.indexOf(_("你正忙着呢", "你正忙著呢")) > -1) {
            errCode = 2;
          } else if (msg.indexOf(_("已经超量", "已經超量")) > -1) {
            errCode = 3;
          } else if (msg.indexOf(_("已达到上限", "已達到上限")) > -1) {
            errCode = 4;
          } else if (msg.indexOf("太多人了") > -1) {
            errCode = 5;
          } else if (msg.indexOf(_("不能战斗", "不能戰鬥")) > -1) {
            errCode = 6;
          } else if (msg.indexOf(_("秒后才能攻击这个人", "秒後才能攻擊這個人")) > -1) {
            let sat = msg.match(_(/(\d+)秒后才能攻击这个人/, /(\d+)秒後才能攻擊這個人/));
            if (sat) errCode = "delay_" + sat[1];
            else errCode = 77;
          } else if (msg.indexOf(_("先观察一下", "先觀察一下")) > -1) {
            errCode = 88;
          } else {
            if (!PLU.STATUS.inBattle) {
              errCode = 99;
            }
          }
          UTIL.delSysListener("onAutoFight");
          if (PLU.STO.autoF) {
            clearTimeout(PLU.STO.autoF);
            PLU.STO.autoF = null;
          }
          if (PLU.TMP.loopCheckFight) {
            clearInterval(PLU.TMP.loopCheckFight);
            PLU.TMP.loopCheckFight = null;
          }
          params.onFail && params.onFail(errCode);
        }
      });
      PLU.STO.autoF = setTimeout(() => {
        PLU.STO.autoF = null;
        if (!g_gmain.is_fighting) {
          UTIL.delSysListener("onAutoFight");
          if (PLU.TMP.loopCheckFight) {
            clearInterval(PLU.TMP.loopCheckFight);
            PLU.TMP.loopCheckFight = null;
          }
          return params.onFail && params.onFail(100);
        }
      }, 300000);
      clickButton(fightAct + " " + params.targetKey, 0);
    },
    //================================================================================================
    autoEscape(params) {
      if (!PLU.STATUS.inBattle) return params.onEnd && params.onEnd();
      let lastEscapeTime = new Date().getTime();
      UTIL.addSysListener("onAutoEscape", function (b, type, subtype, msg) {
        if (type == "vs" && subtype == "combat_result") {
          UTIL.delSysListener("onAutoEscape");
          clickButton("prev_combat");
          return params.onEnd && params.onEnd();
        } else if (type == "vs" && (subtype == "add_xdz" || subtype == "text" || subtype == "attack")) {
          let nt = new Date().getTime();
          if (nt - lastEscapeTime > 500) {
            lastEscapeTime = nt;
            clickButton("escape");
          }
        }
      });
    },
    //================================================================================================
    setBtnRed($btn, flag, sColr) {
      if (!PLU.ONOFF[$btn[0].id + "_color"]) {
        PLU.ONOFF[$btn[0].id + "_color"] = $btn.css("background-color");
        let carr = PLU.ONOFF[$btn[0].id + "_color"].split(/[\D\s]+/);
        carr.pop();
        carr.shift();
        if (carr[0] == carr[1] && carr[1] == carr[2]) {
          carr[1] = carr[1] - 32;
          carr[2] = carr[2] - 32;
        }
        let m = carr.reduce((a, b) => (Number(a) + Number(b)) / 2);
        let narr = carr.map((e) => {
          return Math.min(e - 96 + 4 * (e - m), 256);
        });
        PLU.ONOFF[$btn[0].id + "_colorDark"] = "rgb(" + narr.join(",") + ")";
      }
      if (flag == undefined) {
        if (PLU.ONOFF[$btn[0].id]) {
          PLU.ONOFF[$btn[0].id] = 0;
          $btn.css({
            background: PLU.ONOFF[$btn[0].id + "_color"],
            color: "#000",
          });
          return 0;
        } else {
          PLU.ONOFF[$btn[0].id] = 1;
          $btn.css({
            background: PLU.ONOFF[$btn[0].id + "_colorDark"],
            color: "#FFF",
          });
          return 1;
        }
      } else {
        PLU.ONOFF[$btn[0].id] = flag;
        let colr = sColr || PLU.ONOFF[$btn[0].id + "_color"],
          fcolr = "#000";
        if (flag) {
          colr = sColr || PLU.ONOFF[$btn[0].id + "_colorDark"];
          fcolr = "#FFF";
        }
        $btn.css({ background: colr, color: fcolr });
        return flag;
      }
    },
    getBtnRed($btn) {
      if (PLU.ONOFF[$btn[0].id]) return 1;
      return 0;
    },
    //================================================================================================
    toAutoChuaiMo($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        PLU.STATUS.isBusy = false;
        PLU.TMP.CMSkill = null;
        return;
      }
      YFUI.showPop({
        title: _("自动揣摩技能", "自動揣摩技能"),
        text: _("一键自动揣摩所有能揣摩的技能!(除了六阴追魂剑法)", "一鍵自動揣摩所有能揣摩的技能!(除了六陰追魂劍法)"),
        onOk() {
          PLU.autoChuaiMo();
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },
    //================================================================================================
    toAutoLianXi($btn) {
      var btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        PLU.STATUS.isBusy = false;
        PLU.TMP.CMSkill = null;
        return;
      }
      YFUI.showPop({
        title: _("自动练习技能", "自動練習技能"),
        text: _("开启自动练习技能!(除了六阴剑、九阴爪、九阴刀)", "開啟自動練習技能!(除了六陰劍、九陰爪、九陰刀)"),
        onOk: function onOk() {
          PLU.autoLianXi();
        },
        onNo: function onNo() {
          PLU.setBtnRed($btn, 0);
        }
      });
    },
    //================================================================================================
    toAutoGetKey($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        return UTIL.delSysListener("listenGetKey");
      }
      clickButton("get yin yaoshi");
      UTIL.addSysListener("listenGetKey", function (b, type, subtype, msg) {
        if (g_obj_map.get("msg_room") && g_obj_map.get("msg_room").get("short").match(_(/匾后/, /匾後/))) {
          if (type == "jh") {
            if (subtype == "new_item") {
              if (b.get("id") == "yin yaoshi") clickButton("get yin yaoshi");
            } else if (subtype == "info") {
              clickButton("get yin yaoshi");
            }
          }
        }
      });
    },
    //================================================================================================
    toChoujiang() {
      PLU.getAllItems((list) => {
        let ChoujiangItems = list.find((it) => !!it.name.match(_("抽奖券", "抽獎券")));
        let ChoujiangNum = ChoujiangItems?.num || 0;
        let item1 = 0;
        let item2 = 0;
        let item3 = 0;
        let ChoujiangCount = 0;
        PLU.execActions("go_choujiang 10");
        UTIL.addSysListener("listenChoujiang", function (b, type, subtype, msg) {
          if (type != "notice") return;
          if (msg.indexOf(_("今天的抽奖次数已经用完", "今天的抽獎次數已經用完")) >= 0 || 
          msg.indexOf(_("你身上没有抽奖券", "你身上沒有抽獎券")) >= 0) {
            UTIL.delSysListener("listenChoujiang");
            YFUI.writeToOut("<span style='color:yellow;'>==" + _("抽奖结束", "抽獎結束") + "!==</span>");
            YFUI.writeToOut("<span style='color:lightgreen;'>" + _("本次抽奖次数: ", "本次抽獎次數: ") + ChoujiangCount + "</span>");
            YFUI.writeToOut("<span style='color:red;'>" + _("获得神秘鱼护: ", "獲得神秘魚護: ") + item1 + "</span>");
            YFUI.writeToOut("<span style='color:red;'>" + _("获得龙神试炼锦囊: ", "獲得龍神試煉錦囊: ") + item2 + "</span>");
            YFUI.writeToOut("<span style='color:red;'>" + _("获得龙神试炼福袋: ", "獲得龍神試煉福袋: ") + item3 + "</span>");
            YFUI.writeToOut("<span style='color:yellow;'>=============</span>");  
          } else if (msg.indexOf(_("抽奖10次额外获得", "抽獎10次額外獲得")) >= 0) {
            ChoujiangCount += 10;
            PLU.execActions("go_choujiang 10");
          } else if (msg.indexOf(_("今天的剩馀抽奖次数不够", "今天的剩餘抽獎次數不夠")) >= 0) {
            ChoujiangCount++;
            PLU.execActions("#" + ChoujiangNum % 10 + " go_choujiang 1");
          } else {
            let item = msg.match(_(/抽奖\((?:.*?)\)获得:(.*)x/, /抽獎\((?:.*?)\)獲得:(.*)x/))[1].match(/[\u4e00-\u9fa5\s]+/g).join('');
            switch (item) {
              case _("神秘 渔 护", "神秘 漁 護"):
                item1++;
                break
              case _("龙 神 试炼 锦囊", "龍 神 試煉 錦囊"):
                item2++;
                break
              case _("龙 神 试炼 福袋", "龍 神 試煉 福袋"):
                item3++;
                break
              default:
                break
            }
          }
        });
      });
    },
    zbjianshen() {
      //劍神套
      PLU.execActions("wear obj_jianxinbumie;wear obj_jianyironghen;wear obj_jiandaozhangcun;wear obj_wuyinglou-xianglian;wear obj_wuyinglou-shouzhuo;wear obj_wuyinglou-jiezhi;wear obj_wuwozhijian;log?劍神套穿戴完畢!;");
    },
    zbchuidiao() {
      //垂釣套
      PLU.execActions("wear obj_fushenbanxian;wear obj_yinqingruanque;wear obj_chuidiaozhe-shouzhuo;wear obj_chuidiaozhe-xianglian;wear obj_chuidiaozhe-jiezhi;wear obj_hanjianguyin;wear obj_zhouyebufen;log?垂釣套穿戴完畢!;");
    },
    zbxianzhe() {
      //賢者套
      PLU.execActions("wear obj_zhongzuiduxing;wear obj_qingtianwanshi;wear obj_lankeyimeng;wear obj_shanyecunfu;wear obj_xianzhe-xianglian;wear obj_xianzhe-shouzhuo;wear obj_xianzhe-jiezhi;log?賢者套穿戴完畢!;");
    },
    //================================================================================================
    asJirudw() {
      YFUI.showInput({
        title: _("队伍加入", "隊伍加入"),
        text: _("请输入你要加入队伍的角色ID: 比如:3070884(1)  4512928(1)", "請輸入你要加入隊伍的角色ID: 比如:3070884(1)  4512928(1)"),
        value: PLU.getCache("defaultValue") || "3070884(1)",
        onOk: function onOk(val) {
          PLU.setCache("defaultValue", val);
          PLU.execActions("team join u".concat(val)); // 加入隊伍
        },
        onNo: function onNo() { }
      });
    },
    //================================================================================================
    toAutoMoke($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        PLU.STATUS.isBusy = false;
        return;
      }
      PLU.getAllItems((list) => {
        let daoItems = list.find((it) => !!it.name.match(_("玄铁刻刀", "玄鐵刻刀")));
        let daoNum = daoItems?.num || 0;
        let eqItems = list.filter((it) => !!(it.key.match(/(equip|weapon)_\S+8/) && !it.key.match("_moke_") && !it.key.match("_xinwu") && !it.key.match("_barcer") && !it.key.match("_beixin")));
        let myNum = 0;
        eqItems &&
          eqItems.forEach((eq) => {
            myNum += eq.num;
          });
        YFUI.showPop({
          title: _("自动摹刻所有明月装备", "自動摹刻所有明月裝備"),
          text:
            _("一键自动摹刻所有明月装备!<br><span style='color:#F00;font-weight:bold;'>注意准备足够的刻刀!!!</span><br>当前玄铁刻刀数量 <span style='color:#F00;'>", "一鍵自動摹刻所有明月裝備!<br><span style='color:#F00;font-weight:bold;'>注意準備足夠的刻刀!!!</span><br>當前玄鐵刻刀數量 <span style='color:#F00;'>") +
            daoNum +
            _("</span><br>当前未摹刻明月装备数量 <span style='color:#F00;'>", "</span><br>當前未摹刻明月裝備數量 <span style='color:#F00;'>") +
            myNum +
            "</span>",
          onOk() {
            PLU.autoMoke(eqItems);
          },
          onNo() {
            PLU.setBtnRed($btn, 0);
          },
        });
      });
    },
    autoMoke(eqList) {
      if (!PLU.ONOFF["btn_bt_autoMoke"]) return YFUI.writeToOut("<span style='color:#F0F;'> ==" + _("摹刻暂停", "摹刻暫停") + "!== </span>");
      if (eqList && eqList.length > 0) {
        let eq = eqList.pop(),
          mokeCmds = "";
        mokeCmds;
        for (var i = 0; i < eq.num; i++) {
          mokeCmds += "moke " + eq.key + ";";
        }
        PLU.execActions(mokeCmds, () => PLU.autoMoke(eqList));
      } else {
        PLU.setBtnRed($("#btn_bt_autoMoke"), 0);
        YFUI.writeToOut("<span style='color:yellow;'> ==" + _("摹刻完毕", "摹刻完畢") + "!== </span>");
      }
    },
    //================================================================================================
    toAutoKillZYY($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        return UTIL.delSysListener("listenLoopKillZYY");
      }
      YFUI.showPop({
        title: _("自动去刷祝玉妍", "自動去刷祝玉妍"),
        text: _("自动去刷祝玉妍", "自動去刷祝玉妍") + "!<br><span style='color:#FFF;background:#F00;font-weight:bold;'>----- 注意: -----</span><br><span style='color:#F00;font-weight:bold;'>" + _("1、准备足够的邪帝舍利!!!<br>2、不要有队伍!!!<br>3、切记要打开自动技能阵!!!<br>4、要上足够的保险卡!!!</span>", "1、準備足夠的邪帝舍利!!!<br>2、不要有隊伍!!!<br>3、切記要打開自動技能陣!!!<br>4、要上足夠的保險卡!!!</span>"),
        onOk() {
          PLU.execActions("rank go 232;s;s;;;", () => {
            PLU.loopKillZYY();
          });
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
          UTIL.delSysListener("listenLoopKillZYY");
        },
      });
    },
    loopKillZYY() {
      UTIL.addSysListener("listenLoopKillZYY", function (b, type, subtype, msg) {
        if (type == "vs" && subtype == "combat_result") {
          if (!PLU.ONOFF["btn_bt_autoKillZYY"]) {
            PLU.execActions(";;;n;", () => {
              YFUI.writeToOut("<span style='color:yellow;'>=====" + _("刷祝玉妍结束", "刷祝玉妍結束") + "!!=====</span>");
              UTIL.delSysListener("listenLoopKillZYY");
            });
          } else {
            PLU.execActions(";;;n;s");
          }
        }
      });
      clickButton("s");
    },
    //================================================================================================
    toAutoFB11($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        return UTIL.delSysListener("listenFB11");
      }
      YFUI.showPop({
        title: "自動副本11",
        text: `自動打副本11!<br>
					<span style='color:#F00;font-weight:bold;'>----- 選擇要打的門 -----</span><br>
					<div style="font-size:12px;line-height:2;box">
					<label style="display:inline-block;width: 31%;text-align:center;border:1px solid #333;">8 懶惰<input type="checkbox" name="chkfb11" value="nw" checked/></label>
					<label style="display:inline-block;width: 31%;text-align:center;border:1px solid #333;">1非時食<input type="checkbox" name="chkfb11" value="n" checked/></label>
					<label style="display:inline-block;width: 31%;text-align:center;border:1px solid #333;">2 殺生<input type="checkbox" name="chkfb11" value="ne" checked/></label>
					<br>
					<label style="display:inline-block;width: 31%;text-align:center;border:1px solid #333;">7 奢華<input type="checkbox" name="chkfb11" value="w" checked/></label>
					<span style="display:inline-block;width: 31%;color:#999;text-align:center;border:1px solid transparent;">初心之地</span>
					<label style="display:inline-block;width: 31%;text-align:center;border:1px solid #333;">3 偷盜<input type="checkbox" name="chkfb11" value="e" checked/></label>
					<br>
					<label style="display:inline-block;width: 31%;text-align:center;border:1px solid #333;">6 飲酒<input type="checkbox" name="chkfb11" value="sw" checked/></label>
					<label style="display:inline-block;width: 31%;text-align:center;border:1px solid #333;">5 妄語<input type="checkbox" name="chkfb11" value="s" checked/></label>
					<label style="display:inline-block;width: 31%;text-align:center;border:1px solid #333;">4 淫邪<input type="checkbox" name="chkfb11" value="se" checked/></label><br>
					</div>
					<span style='color:#F00;font-weight:bold;'>1、在副本外開始腳本<br>2、記得要組隊<br></span>`,
        okText: "開始",
        onOk() {
          let chks = $('input[name="chkfb11"]:checked');
          let selects = [];
          $.each(chks, (i, e) => {
            selects.push(e.value);
          });
          if (selects.length == 0) return false;
          console.log(selects);
          //PLU.TMP.chkTmpList=[]
          //PLU.execActions('rank go 232;s;s;;;', ()=>{
          PLU.autoFB11(selects);
          //})
          //UTIL.findRoomNpcReg
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
          UTIL.delSysListener("listenFB11");
        },
      });
    },
    autoFB11() { },
    killAllNpc(callback) {
      let npcObj = UTIL.findRoomNpcReg("");
      if (npcObj) {
        let needAutoSkill = PLU.getCache("autoPerform") >= 1 ? null : "multi";
        PLU.autoFight({
          targetKey: npcObj.key,
          fightKind: "kill",
          autoSkill: needAutoSkill,
          onFail() {
            setTimeout((t) => {
              PLU.killAllNpc(callback);
            }, 1000);
          },
          onEnd() {
            setTimeout((t) => {
              PLU.killAllNpc(callback);
            }, 500);
          },
        });
      } else {
        callback && callback();
      }
    },
    //================================================================================================
    checkYouxia($btn) {
      YFUI.showPop({
        title: _("检查入室游侠技能", "檢查入室遊俠技能"),
        text: _(`选择需要的对应技能:<br>
				<div style="font-size:15px;">
					<label style="display:inline-block;">内功:<input type="checkbox" name="chkskiyx" value="内功" checked/></label>&nbsp;
					<label style="display:inline-block;">轻功:<input type="checkbox" name="chkskiyx" value="轻功" checked/></label>&nbsp;
					<label style="display:inline-block;">剑法:<input type="checkbox" name="chkskiyx" value="剑法" checked/></label>&nbsp;
					<label style="display:inline-block;">掌法:<input type="checkbox" name="chkskiyx" value="掌法" checked/></label>&nbsp;
					<label style="display:inline-block;">刀法:<input type="checkbox" name="chkskiyx" value="刀法" checked/></label>&nbsp;
					<label style="display:inline-block;">暗器:<input type="checkbox" name="chkskiyx" value="暗器"/></label>&nbsp;
					<label style="display:inline-block;">鞭法:<input type="checkbox" name="chkskiyx" value="鞭法"/></label>&nbsp;
					<label style="display:inline-block;">枪法:<input type="checkbox" name="chkskiyx" value="枪法"/></label>&nbsp;
					<label style="display:inline-block;">锤法:<input type="checkbox" name="chkskiyx" value="锤法"/></label>&nbsp;
					<label style="display:inline-block;">斧法:<input type="checkbox" name="chkskiyx" value="斧法"/></label>
				</div>`,
        `選擇需要的對應技能:<br>
				<div style="font-size:15px;">
					<label style="display:inline-block;">內功:<input type="checkbox" name="chkskiyx" value="內功" checked/></label>&nbsp;
					<label style="display:inline-block;">輕功:<input type="checkbox" name="chkskiyx" value="輕功" checked/></label>&nbsp;
					<label style="display:inline-block;">劍法:<input type="checkbox" name="chkskiyx" value="劍法" checked/></label>&nbsp;
					<label style="display:inline-block;">掌法:<input type="checkbox" name="chkskiyx" value="掌法" checked/></label>&nbsp;
					<label style="display:inline-block;">刀法:<input type="checkbox" name="chkskiyx" value="刀法" checked/></label>&nbsp;
					<label style="display:inline-block;">暗器:<input type="checkbox" name="chkskiyx" value="暗器"/></label>&nbsp;
					<label style="display:inline-block;">鞭法:<input type="checkbox" name="chkskiyx" value="鞭法"/></label>&nbsp;
					<label style="display:inline-block;">槍法:<input type="checkbox" name="chkskiyx" value="槍法"/></label>&nbsp;
					<label style="display:inline-block;">錘法:<input type="checkbox" name="chkskiyx" value="錘法"/></label>&nbsp;
					<label style="display:inline-block;">斧法:<input type="checkbox" name="chkskiyx" value="斧法"/></label>
				</div>`),
        onOk() {
          let chks = $('input[name="chkskiyx"]:checked');
          let selects = [];
          PLU.TMP.chkTmpList = [];
          $.each(chks, (i, e) => {
            selects.push(e.value);
          });
          PLU.getSkillsList((allSkills, tupoSkills) => {
            PLU.getYouxiaList((yxs) => {
              PLU.checkMySkills(allSkills, yxs, selects);
            });
          });
        },
        onNo() { },
      });
    },
    checkMySkills(mySkills, myYouxia, checkList) {
      // console.log(mySkills, myYouxia, checkList)
      let clstr = "";
      checkList.forEach((c) => (clstr += "【" + c[0] + "】"));
      YFUI.writeToOut("<span style='color:#FFF;'>--" + _("技能检测", "技能檢測") + " <span style='color:yellow;'>" + clstr + "</span>--</span>");
      checkList.forEach((cn) => {
        let carr = PLU.YFD.youxiaSkillMap.filter((r) => r.type == cn);
        carr.forEach((n) => {
          PLU.checkPreSKill(n, mySkills, myYouxia);
        });
      });
      if (PLU.TMP.chkTmpList.length == 0) {
        YFUI.writeToOut("<span style='color:yellow;'>" + _("检查的技能都准备好了", "檢查的技能都準備好了") + "!</span>");
      }
    },
    checkPreSKill(node, mySkills, myYouxia) {
      let ms = mySkills.find((s) => s.name == node.skill);
      if (!ms && !PLU.TMP.chkTmpList.includes(node.skill)) {
        PLU.TMP.chkTmpList.push(node.skill);
        let clr = node.kind == _("宗师", "宗師") || node.kind == _("侠客", "俠客") ? "#E93" : "#36E";
        let htm = '<span style="color:' + clr + ';">【' + node.type[0] + "】" + node.skill + " ";
        // htm+= ms?'<span style="color:#3F3;display:inline-block;">('+ms.level+')</span>':'(缺)';
        htm += '<span style="color:#F00;display:inline-block;">(未學)</span>';
        let myx = myYouxia.find((y) => y.name.match(node.name));
        htm +=
          " - " +
          (myx
            ? '<span style="color:#3F3;display:inline-block;">' + myx.name + "[" + myx.level + "]</span>"
            : '<span style="color:#F36;display:inline-block;">需要:<span style="color:#FFF;background:' +
            clr +
            ';"> ' +
            node.kind +
            "-" +
            node.name +
            " </span></span>");
        htm += "</span>";
        YFUI.writeToOut(htm);
      }
      if (node.pre) {
        node.pre.forEach((n) => {
          PLU.checkPreSKill(n, mySkills, myYouxia);
        });
      }
    },
    getYouxiaList(callback) {
      UTIL.addSysListener("getYouxiaList", function (b, type, subtype, msg) {
        if (type != "fudi" && subtype != "juxian") return;
        UTIL.delSysListener("getYouxiaList");
        clickButton("prev");
        let youxias = [];
        for (var i = 0; i < 41; i++) {
          let str = b.get("yx" + i);
          if (str) {
            let attr = str.split(",");
            let ns = UTIL.filterMsg(attr[1]).split("】");
            let nam = ns.length > 1 ? ns[1] : ns[0];
            youxias.push({
              key: attr[0],
              name: nam,
              level: Number(attr[4]),
              kind: attr[3],
            });
          }
        }
        callback(youxias);
      });
      clickButton("fudi juxian");
    },
    //================================================================================================
    toAutoLearn($btn) {
      if (!PLU.TMP.MASTER_SKILLS) {
        return YFUI.showPop({
          title: _("缺少数据", "缺少數據"),
          text: _("需要打开师傅技能界面", "需要打開師傅技能界面"),
          // onOk(){
          //},
        });
      }
      // console.log(PLU.TMP.MASTER_ID, PLU.TMP.MASTER_SKILLS)
      let needSkills = [];
      PLU.getSkillsList((allSkills, tupoSkills) => {
        PLU.TMP.MASTER_SKILLS.forEach((ms) => {
          let sk = allSkills.find((s) => s.key == ms.key) || { level: 0 };
          if (sk.level < ms.level) {
            needSkills.push({
              key: ms.key,
              name: ms.name,
              lvl: ms.level - sk.level,
              cmd: "learn " + ms.key + " from " + PLU.TMP.MASTER_ID + " to 10",
            });
          }
        });
        //console.log(needSkills.map(e=>e.name))
        loopLearn(needSkills);
      });
      let curSkill = null;
      UTIL.addSysListener("loopLearnSkill", function (b, type, subtype, msg) {
        if (type == "notice" && msg.indexOf(_("不愿意教你", "不願意教你")) >= 0) {
          //UTIL.delSysListener("loopLearnSkill");
          if (curSkill) curSkill.lvl = -1;
        }
        return;
      });
      let loopLearn = function (list) {
        if (list.length > 0) {
          if (list[0].lvl > 0) {
            list[0].lvl -= 10;
            curSkill = list[0];
            clickButton(list[0].cmd);
          } else {
            list.shift();
          }
          setTimeout(() => {
            loopLearn(list);
          }, 200);
        } else {
          UTIL.delSysListener("loopLearnSkill");
          YFUI.writeToOut("<span style='color:#FFF;'>----" + _("自动学习结束,记得检查噢", "自動學習結束,記得檢查噢") + "!----</span>");
        }
      };
    },
    //================================================================================================
    autoChuaiMo() {
      if (!PLU.ONOFF["btn_bt_autoChuaiMo"]) return;
      PLU.STATUS.isBusy = true;
      if (!PLU.TMP.CMSkill) {
        PLU.getSkillsList((allSkills, tupoSkills) => {
          if (!PLU.TMP.CANTCMS) PLU.TMP.CANTCMS = [];
          PLU.TMP.CMSkill = allSkills.find(
            (e) =>
              e.level >= 500 &&
              e.level < 600 &&
              e.name != _("六阴追魂剑法", "六陰追魂劍法") &&
              (e.kind == "attack" || e.kind == "recovery" || e.kind == "force") &&
              !PLU.TMP.CANTCMS.includes(e.name),
          );
          if (!PLU.TMP.CMSkill) {
            PLU.STATUS.isBusy = false;
            PLU.TMP.CMSkill = null;
            PLU.setBtnRed($("#btn_bt_autoChuaiMo"), 0);
          } else {
            clickButton("enable " + PLU.TMP.CMSkill.key);
            UTIL.addSysListener("listenChuaiMo", function (b, type, subtype, msg) {
              if (type == "notice" && (msg.indexOf(_("揣摩最高等级为", "揣摩最高等級為")) >= 0 || msg.indexOf(_("这项技能不能揣摩", "這項技能不能揣摩")) >= 0)) {
                UTIL.delSysListener("listenChuaiMo");
                if (msg.indexOf(_("这项技能不能揣摩", "這項技能不能揣摩")) >= 0) {
                  PLU.TMP.CANTCMS.push(PLU.TMP.CMSkill.name);
                }
                YFUI.writeToOut("<span style='color:#FFF;'>--" + _("揣摩结束", "揣摩結束") + "--</span>");
                PLU.TMP.CMSkill = null;
              }
              return;
            });
          }
          PLU.autoChuaiMo();
        });
      } else {
        clickButton("chuaimo go," + PLU.TMP.CMSkill.key, 0);
        setTimeout((e) => {
          PLU.autoChuaiMo();
        }, 250);
      }
    },
    //================================================================================================
    toAutoTeach($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        PLU.STATUS.isBusy = false;
        PLU.TMP.TeachSkill = null;
        return;
      }
      YFUI.showPop({
        title: _("自动传授游侠技能", "自動傳授遊俠技能"),
        text: _("一键自动传授游侠技能!<b style='color:#F00;'>需要点开游侠技能界面,需要传授的技能不能为0级</b>",
        "一鍵自動傳授遊俠技能!<b style='color:#F00;'>需要點開遊俠技能界面,需要傳授的技能不能為0級</b>"),
        onOk() {
          PLU.autoTeach();
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },
    //================================================================================================
    autoTeach() {
      if (!PLU.ONOFF["btn_bt_autoTeach"]) return;
      PLU.STATUS.isBusy = true;
      if (PLU.TMP.CUR_YX_SKILLS) {
        let ac = PLU.TMP.CUR_YX_SKILLS.find((e) => Number(e.lvl) > 0 && Number(e.lvl) < Number(e.max));
        if (ac) {
          clickButton(ac.cmd, 0);
          setTimeout((e) => {
            PLU.autoTeach();
          }, 200);
        } else {
          YFUI.writeToOut("<span style='color:#FFF;'>--" + _("传授结束", "傳授結束") + "--</span>");
          PLU.STATUS.isBusy = false;
          PLU.setBtnRed($("#btn_bt_autoTeach"), 0);
        }
      } else {
        PLU.STATUS.isBusy = false;
        PLU.setBtnRed($("#btn_bt_autoTeach"), 0);
      }
    },
    //================================================================================================
    toAutoUpgrade($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        PLU.STATUS.isBusy = false;
        PLU.TMP.TeachSkill = null;
        return;
      }
      YFUI.showPop({
        title: _("自动升级游侠等级", "自動升級遊俠等級"),
        text: _("一键升级游侠等级!<b style='color:#F00;'>需要点开游侠技能界面</b>", "一鍵升級遊俠等級!<b style='color:#F00;'>需要點開遊俠技能界面</b>"),
        onOk() {
          PLU.autoUpgrade();
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },
    // 今天提升鳩摩智等級的次數已達到上限了。
    //不能提升阿朱的等級。
    //遊俠等級超過上限了。
    //================================================================================================
    autoUpgrade() {
      if (!PLU.ONOFF["btn_bt_autoUpgrade"]) return;
      PLU.STATUS.isBusy = true;
      if (PLU.TMP.CUR_YX_LEVEL && PLU.TMP.CUR_YX_SKILLS && PLU.TMP.CUR_YX_ENG) {
        if (PLU.TMP.CUR_YX_SKILLS.length > 4 && PLU.TMP.CUR_YX_LEVEL < 2000) {
          var canUpgrade = true;
          UTIL.addSysListener("listenAutoUpgrade", function (b, type, subtype, msg) {
            if (type == "notice" && (msg.indexOf(_("等级的次数已达到上限了", "等級的次數已達到上限了")) >= 0 || msg.indexOf("不能提升") >= 0 || msg.indexOf(_("等级超过上限了", "等級超過上限了")) >= 0)) {
              UTIL.delSysListener("listenAutoUpgrade");
              canUpgrade = false;
              PLU.STATUS.isBusy = false;
              YFUI.writeToOut("<span style='color:#FFF;'>--" + _("升级结束", "升級結束") + "--</span>");
              PLU.setBtnRed($("#btn_bt_autoUpgrade"), 0);
            }
            return;
          });
          clickButton("fudi juxian upgrade go " + PLU.TMP.CUR_YX_ENG + " 100");
          setTimeout((e) => {
            if (canUpgrade) PLU.autoUpgrade();
          }, 500);
        } else {
          YFUI.writeToOut("<span style='color:#FFF;'>--" + _("升级结束", "升級結束") + "--</span>");
          PLU.STATUS.isBusy = false;
          PLU.setBtnRed($("#btn_bt_autoUpgrade"), 0);
        }
      } else {
        PLU.STATUS.isBusy = false;
        PLU.setBtnRed($("#btn_bt_autoUpgrade"), 0);
      }
    },
    //================================================================================================
    toLoopKillByN($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        $("#btn_bt_loopKillByN").text(_("计数击杀", "計數擊殺"));
        return;
      }
      clickButton("golook_room");
      YFUI.showInput({
        title: _("计数击杀", "計數擊殺"),
        text: _("输入数量,确定后单击怪!!(数量后带小数点为比试)", "輸入數量,確定後單擊怪!!(數量後帶小數點為比試)"),
        value: PLU.getCache("lookKillNum") || 20,
        onOk(val) {
          if (!Number(val)) return;
          setTimeout((o) => {
            $(document).one("click", (o) => {
              let snpc = $(o.target)
                .closest("button")[0]
                .outerHTML.match(/clickButton\('look_npc (\w+)'/i);
              if (snpc && snpc.length >= 2) {
                let kf = String(val).indexOf(".") > 0 ? "fight" : "kill";
                PLU.setCache("lookKillNum", Number(val));
                PLU.loopKillByN(snpc[1], parseInt(val), kf);
              } else {
                PLU.setBtnRed($btn, 0);
              }
            });
          }, 500);
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },
    //================================================================================================
    loopKillByN(npcId, killN, killorfight) {
      if (killN <= 0 || !PLU.ONOFF["btn_bt_loopKillByN"]) return;
      $("#btn_bt_loopKillByN").text("停(" + killN + ")");
      PLU.autoFight({
        targetKey: npcId,
        fightKind: killorfight,
        autoSkill: "fast",
        onFail() {
          setTimeout((t) => {
            PLU.loopKillByN(npcId, killN, killorfight);
          }, 500);
        },
        onEnd() {
          if (killN <= 1) {
            PLU.setBtnRed($("#btn_bt_loopKillByN"), 0);
            $("#btn_bt_loopKillByN").text(_("计数击杀", "計數擊殺"));
            clickButton("home", 1);
            return;
          } else {
            setTimeout((t) => {
              PLU.loopKillByN(npcId, killN - 1, killorfight);
            }, 500);
          }
        },
      });
    },
    //================================================================================================
    toLoopKillName($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        $("#btn_bt_loopKillName").text(_("名字连杀", "名字連殺"));
        return;
      }
      YFUI.showInput({
        title: _("名字连杀", "名字連殺"),
        text: _(`格式:次数|人物词组<br>
						次数:省略则默认1次<br>
						人物词组:以英文逗号分割多个关键词<br>
						<span style="color:red;">例如:</span><br>
						[例1] <span style="color:blue;">99|铁狼军,银狼军,金狼军,金狼将,十夫长,百夫长,千夫长</span><br>
						[例2] <span style="color:blue;">醉汉,收破烂的</span>;
						`,
        `格式:次數|人物詞組<br>
						次數:省略則默認1次<br>
						人物詞組:以英文逗號分割多個關鍵詞<br>
						<span style="color:red;">例如:</span><br>
						[例1] <span style="color:blue;">99|鐵狼軍,銀狼軍,金狼軍,金狼將,十夫長,百夫長,千夫長</span><br>
						[例2] <span style="color:blue;">醉漢,收破爛的</span>;
						`),
        value: PLU.getCache("lookKillNames") || _("299|铁狼军,银狼军,金狼军,金狼将,十夫长,百夫长,千夫长", "299|鐵狼軍,銀狼軍,金狼軍,金狼將,十夫長,百夫長,千夫長"),
        onOk(val) {
          if (!$.trim(val)) return;
          let str = $.trim(val),
            times = 1,
            names = "",
            arr = str.split("|");
          if (arr.length > 1) {
            times = Number(arr[0]) || 1;
            names = arr[1];
          } else {
            names = arr[0];
          }
          PLU.setCache("lookKillNames", str);
          PLU.loopKillName(names, Number(times));
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },
    //================================================================================================
    loopKillName(names, killN) {
      if (killN <= 0 || !PLU.ONOFF["btn_bt_loopKillName"]) return;
      $("#btn_bt_loopKillName").text(_("停击杀(", "停擊殺(") + killN + ")");
      let npcObj = null,
        namesArr = names.split(",");
      for (let i = 0; i < namesArr.length; i++) {
        npcObj = UTIL.findRoomNpc(namesArr[i], false, true);
        if (npcObj) break;
      }
      if (npcObj) {
        let needAutoSkill = PLU.getCache("autoPerform") >= 1 ? null : "multi";
        PLU.autoFight({
          targetKey: npcObj.key,
          fightKind: "kill",
          autoSkill: needAutoSkill,
          onFail() {
            setTimeout((t) => {
              PLU.loopKillName(names, killN);
            }, 1000);
          },
          onEnd() {
            if (killN <= 1) {
              PLU.setBtnRed($("#btn_bt_loopKillName"), 0);
              $("#btn_bt_loopKillName").text(_("名字连杀", "名字連殺"));
              return;
            } else {
              setTimeout((t) => {
                PLU.loopKillName(names, killN - 1);
              }, 1000);
            }
          },
        });
      } else {
        setTimeout((t) => {
          PLU.loopKillName(names, killN);
        }, 2000);
      }
    },
    //================================================================================================
    toLoopKill($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        // $("#btn_bt_kg_loopKill").text('循環殺')
        return;
      }
      YFUI.showInput({
        title: _("循环杀", "循環殺"),
        text: _(`格式:名字词组<br>
						名字词组:以英文逗号分割多个关键词, <b style="color:red;">可模糊匹配!</b><br>
						<span style="color:red;">不需要战斗时建议关闭以节省性能!!</span><br>
						[例1] <span style="color:blue;">铁狼军,银狼军,金狼军,金狼将,十夫长,百夫长,千夫长,蛮荒铁,蛮荒银,蛮荒金,寨近卫,蛮荒近卫</span><br>
						`,
        `格式:名字詞組<br>
						名字詞組:以英文逗號分割多個關鍵詞, <b style="color:red;">可模糊匹配!</b><br>
						<span style="color:red;">不需要戰鬥時建議關閉以節省性能!!</span><br>
						[例1] <span style="color:blue;">鐵狼軍,銀狼軍,金狼軍,金狼將,十夫長,百夫長,千夫長,蠻荒鐵,蠻荒銀,蠻荒金,寨近衛,蠻荒近衛</span><br>
						`),
        type: "textarea",
        value: PLU.getCache("lookKillKeys") || _("怯薛军,蒙古突骑,草原枪骑,重装铁骑,狼军,狼将,夫长,蛮荒,近卫", "怯薛軍,蒙古突騎,草原槍騎,重裝鐵騎,狼軍,狼將,夫長,蠻荒,近衛"),
        onOk(val) {
          if (!$.trim(val)) return;
          let str = $.trim(val),
            names = str.split(/[,,#]/);
          PLU.setCache("lookKillKeys", str);
          PLU.loopKills(str);
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },
    //================================================================================================
    loopKills(names) {
      if (!PLU.ONOFF["btn_bt_kg_loopKill"]) return;
      // $("#btn_bt_kg_loopKill").text('停循環');
      let npcObj = null,
        namesArr = names.split(/[,,#]/);
      for (let i = 0; i < namesArr.length; i++) {
        npcObj = UTIL.findRoomNpcReg(namesArr[i]);
        if (npcObj) break;
      }
      if (npcObj) {
        let needAutoSkill = PLU.getCache("autoPerform") >= 1 ? null : "multi";
        PLU.autoFight({
          targetKey: npcObj.key,
          fightKind: "kill",
          autoSkill: needAutoSkill,
          onFail() {
            setTimeout((t) => {
              PLU.loopKills(names);
            }, 1000);
          },
          onEnd() {
            setTimeout((t) => {
              PLU.loopKills(names);
            }, 500);
          },
        });
      } else {
        setTimeout((t) => {
          PLU.loopKills(names);
        }, 1000);
      }
    },
    //================================================================================================
    toLoopReadBase($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        // $("#btn_bt_loopReadBase").text('讀技能書')
        return;
      }
      YFUI.showInput({
        title: _("读书还神", "讀書還神"),
        text: _(`格式:比试NPC名称|基础秘籍名称<br>
						比试NPC名称:要比试进行回神的NPC名字<br>
						基础秘籍名称:基础秘籍名称关键词<br>
						<span style="color:red;">战斗必刷道具栏必须用还神丹</span><br>
						<span style="color:red;">例如:</span><br>
						[例1] <span style="color:blue;">地痞|基本剑法秘籍</span>
						`,
        `格式:比試NPC名稱|基礎秘籍名稱<br>
						比試NPC名稱:要比試進行回神的NPC名字<br>
						基礎秘籍名稱:基礎秘籍名稱關鍵詞<br>
						<span style="color:red;">戰鬥必刷道具欄必須用還神丹</span><br>
						<span style="color:red;">例如:</span><br>
						[例1] <span style="color:blue;">地痞|基本劍法秘籍</span>
						`),
        value: PLU.getCache("loopReadBase") || _("地痞|基本剑法秘籍", "地痞|基本劍法秘籍"),
        onOk(val) {
          if (!$.trim(val)) return;
          let str = $.trim(val),
            npcName = "",
            bookName = "",
            arr = str.split("|");
          if (arr.length > 1) {
            npcName = arr[0];
            bookName = arr[1];
            PLU.setCache("loopReadBase", str);
            PLU.getAllItems((list) => {
              let bookItem = list.find((it) => !!it.name.match(bookName));
              let reN = Math.floor(g_obj_map.get("msg_attrs").get("max_shen_value") / 55) || 1;
              console.log(npcName, bookItem.key, reN);
              if (bookItem) {
                PLU.toggleAutoPerform($("#btn_bt_kg_autoPerform"), "autoPerform", 0);
                PLU.loopReadBase(npcName, bookItem.key, reN);
              }
            });
          } else {
            PLU.setBtnRed($btn, 0);
            return;
          }
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },
    loopReadBase(npcName, bookKey, reN) {
      //你使用了一本

      //你的神值不足:10以上。
      //你目前不能使用
      //使用技能等級為
      if (!PLU.ONOFF["btn_bt_loopReadBase"]) {
        UTIL.delSysListener("listenLoopReadBase");
        YFUI.writeToOut("<span style='color:#FFF;'>--" + _("读基本技能书停止", "讀基本技能書停止") + "--</span>");
        PLU.setBtnRed($("#btn_bt_loopReadBase"), 0);
        return;
      }
      UTIL.addSysListener("listenLoopReadBase", function (b, type, subtype, msg) {
        if (type == "main_msg" && msg.indexOf("你使用了一本") >= 0) {
          UTIL.delSysListener("listenLoopReadBase");
          setTimeout(() => {
            PLU.loopReadBase(npcName, bookKey, reN);
          }, 500);
        } else if (type == "notice" && msg.indexOf("你的神值不足") >= 0) {
          UTIL.delSysListener("listenLoopReadBase");
          setTimeout(() => {
            let refreshNumber = 0;
            PLU.autoFight({
              targetName: npcName,
              fightKind: "fight",
              autoSkill: "item",
              onStart() {
                console.log("start fight==");
              },
              onFighting(ps) {
                if (refreshNumber >= reN) return true;
                if (ps && ps.key == "playskill 7") {
                  refreshNumber++;
                  console.log(ps.key, refreshNumber, reN);
                  if (refreshNumber >= reN) {
                    PLU.autoEscape({});
                  }
                }
              },
              onFail(err) {
                console.log(err);
                setTimeout(() => {
                  PLU.loopReadBase(npcName, bookKey, reN);
                }, 1000);
              },
              onEnd(e) {
                setTimeout(() => {
                  PLU.loopReadBase(npcName, bookKey, reN);
                }, 1000);
              },
            });
          }, 500);
        } else if (type == "notice" && msg.indexOf(_("使用技能等级为", "使用技能等級為")) >= 0) {
          UTIL.delSysListener("listenLoopReadBase");
          YFUI.writeToOut("<span style='color:#FFF;'>--" + _("读基本技能书结束", "讀基本技能書結束") + "--</span>");
          PLU.setBtnRed($("#btn_bt_loopReadBase"), 0);
        } else if (type == "notice" && msg.indexOf(_("你的背包里没有这个物品", "你的背包裡沒有這個物品")) >= 0) {
          YFUI.writeToOut("<span style='color:#FFF;'>--" + _("读基本技能书结束", "讀基本技能書結束") + "--</span>");
          PLU.setBtnRed($("#btn_bt_loopReadBase"), 0);
        }
        return;
      });
      let cmds = "items use " + bookKey;
      PLU.execActions(cmds);
    },
    //================================================================================================
    toSearchFamilyQS($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) return;
      YFUI.showInput({
        title: _("搜索师门任务", "搜索師門任務"),
        text: _(`格式:任务包含的关键字,多个以英文逗号分隔<br>
						<span style="color:red;">例如:</span><br>
						[例1] <span style="color:blue;">硫磺,黝黑山洞</span>
            [例2] <span style="color:blue;">茅山,</span>
						`, 
            `格式:任務包含的關鍵字,多個以英文逗號分隔<br>
						<span style="color:red;">例如:</span><br>
						[例1] <span style="color:blue;">硫磺,黝黑山洞</span>
            [例2] <span style="color:blue;">茅山,</span>
						`),
        value: PLU.getCache("searchFamilyQS") || "硫磺,黝黑山洞",
        onOk(val) {
          if (!$.trim(val)) return;
          let str = $.trim(val),
            arr = str.split(",");
          if (arr.length > 1) {
            PLU.setCache("searchFamilyQS", str);
            clickButton("family_quest", 0);
            PLU.TMP.master = g_obj_map?.get("msg_attrs")?.get("master_name");
            PLU.loopSearchFamilyQS(arr);
          } else {
            PLU.setBtnRed($btn, 0);
            return;
          }
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },
    loopSearchFamilyQS(keys, cmd) {
      if (!PLU.ONOFF["btn_bt_searchFamilyQS"]) {
        UTIL.delSysListener("listenLoopSearchFamilyQS");
        YFUI.writeToOut("<span style='color:#FFF;'>--停止搜索--</span>");
        PLU.setBtnRed($("#btn_bt_searchFamilyQS"), 0);
        return;
      }
      UTIL.addSysListener("listenLoopSearchFamilyQS", function (b, type, subtype, msg) {
        if (type == "main_msg") {
          if (msg.indexOf(`${PLU.TMP.master}一拂袖`) >= 0 || msg.indexOf(_("你现在没有师门任务。", "你現在沒有師門任務。")) >= 0) {
            UTIL.delSysListener("listenLoopSearchFamilyQS");
            setTimeout(() => {
              PLU.loopSearchFamilyQS(keys);
            }, 250);
          } else if (msg.indexOf(_("你现在的任务是", "你現在的任務是")) >= 0 || msg.indexOf(PLU.TMP.master) >= 0) {
            UTIL.delSysListener("listenLoopSearchFamilyQS");
            let qsStr = msg.replace(/\x03(0)?|href;0;|[\033|\27|\0x1b]\[[0-9|;]+m/gi, "");
            for (let i = 0; i < keys.length; i++) {
              let key = $.trim(keys[i]);
              if (key && qsStr.indexOf(key) >= 0) {
                YFUI.writeToOut("<span style='color:#FF0;'>========= " + _("结束搜索", "結束搜索") + " =========</span>");
                delete PLU.TMP.master;
                PLU.setBtnRed($("#btn_bt_searchFamilyQS"), 0);
                break;
              } else {
                setTimeout(() => {
                  PLU.loopSearchFamilyQS(keys, "family_quest cancel go");
                }, 250);
              }
            }
          }
        }
      });
      if (cmd) clickButton(cmd);
      else clickButton("family_quest", 0);
    },
    //================================================================================================
    toSearchBangQS($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) return;
      YFUI.showInput({
        title: _("搜索帮派任务", "搜索幫派任務"),
        text: _(`格式:任务包含的关键字,多个以英文逗号分隔<br>
						<span style="color:red;">例如:</span><br>
						[例1] <span style="color:blue;">硫磺,黝黑山洞</span>
						`,
            `格式:任務包含的關鍵字,多個以英文逗號分隔<br>
						<span style="color:red;">例如:</span><br>
						[例1] <span style="color:blue;">硫磺,黝黑山洞</span>
						`),
        value: PLU.getCache("searchBangQS") || "硫磺,黝黑山洞",
        onOk(val) {
          if (!$.trim(val)) return;
          let str = $.trim(val),
            arr = str.split(",");
          if (arr.length > 1) {
            PLU.setCache("searchBangQS", str);
            clickButton("clan scene", 0);
            PLU.loopSearchBangQS(arr);
          } else {
            PLU.setBtnRed($btn, 0);
            return;
          }
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },
    loopSearchBangQS(keys, cmd) {
      if (!PLU.ONOFF["btn_bt_searchBangQS"]) {
        UTIL.delSysListener("listenLoopSearchBangQS");
        YFUI.writeToOut("<span style='color:#FFF;'>--停止搜索--</span>");
        PLU.setBtnRed($("#btn_bt_searchBangQS"), 0);
        return;
      }
      UTIL.addSysListener("listenLoopSearchBangQS", function (b, type, subtype, msg) {
        if (type == "main_msg") {
          if (msg.indexOf(_("帮派使者一拂袖", "幫派使者一拂袖")) >= 0 || msg.indexOf(_("帮派使者:现在没有任务", "幫派使者:現在沒有任務")) >= 0) {
            UTIL.delSysListener("listenLoopSearchBangQS");
            setTimeout(() => {
              PLU.loopSearchBangQS(keys);
            }, 250);
          } else if (msg.indexOf(_("你现在的任务是", "你現在的任務是")) >= 0 || msg.indexOf(_("帮派使者:", "幫派使者:")) >= 0) {
            UTIL.delSysListener("listenLoopSearchBangQS");
            let qsStr = msg.replace(/\x03(0)?|href;0;|[\033|\27|\0x1b]\[[0-9|;]+m/gi, "");
            for (let i = 0; i < keys.length; i++) {
              let key = $.trim(keys[i]);
              if (key && qsStr.indexOf(key) >= 0) {
                YFUI.writeToOut("<span style='color:#FF0;'>========= " + _("结束搜索", "結束搜索") + " =========</span>");
                PLU.setBtnRed($("#btn_bt_searchBangQS"), 0);
                break;
              } else {
                setTimeout(() => {
                  PLU.loopSearchBangQS(keys, "clan cancel_task go");
                }, 250);
              }
            }
          }
        }
      });
      if (cmd) clickButton(cmd);
      else clickButton("clan task", 0);
    },
    //================================================================================================
    toLoopClick($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        $("#btn_bt_loopClick").text(_("自动点击", "自動點擊"));
        return;
      }
      YFUI.showInput({
        title: _("自动点击", "自動點擊"),
        text: _("输入自动点击的次数,确定后点击要点按钮", "輸入自動點擊的次數,確定後點擊要點按鈕"),
        value: PLU.getCache("autoClickNum") || 20,
        onOk(val) {
          if (!Number(val)) return;
          setTimeout((o) => {
            $(document).one("click", (o) => {
              let snpc = $(o.target)
                .closest("button")[0]
                .outerHTML.match(/clickButton\([\'\"](.+)[\'\"](,\s*(\d+))*\)/i);
              if (snpc && snpc.length >= 2) {
                let param = snpc[3] ?? 0;
                PLU.setCache("autoClickNum", Number(val));
                PLU.loopClick(snpc[1], param, Number(val));
              } else {
                PLU.setBtnRed($btn, 0);
              }
            });
          }, 500);
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },
    //================================================================================================
    loopClick(btnCmd, param, clickNum) {
      if (!clickNum || clickNum < 1 || !PLU.ONOFF["btn_bt_loopClick"]) {
        PLU.setBtnRed($("#btn_bt_loopClick"), 0);
        $("#btn_bt_loopClick").text(_("连续点击", "連續點擊"));
        return;
      }
      $("#btn_bt_loopClick").text(_("停点击(", "停點擊(") + clickNum + ")");
      clickButton(btnCmd, param);
      clickNum--;
      setTimeout(() => {
        PLU.loopClick(btnCmd, param, clickNum);
      }, 250);
    },
    //================================================================================================
    loopSlowClick(btnCmd, param, clickNum, delay) {
      if (!delay) delay = 1000;
      if (!clickNum || clickNum < 1 || !PLU.ONOFF["btn_bt_loopSlowClick"]) {
        PLU.setBtnRed($("#btn_bt_loopSlowClick"), 0);
        $("#btn_bt_loopSlowClick").text(_("慢速点击", "慢速點擊"));
        return;
      }
      $("#btn_bt_loopSlowClick").text("停(" + clickNum + ")");
      clickButton(btnCmd, param);
      clickNum--;
      setTimeout(() => {
        PLU.loopSlowClick(btnCmd, param, clickNum, delay);
      }, delay);
    },
    //================================================================================================
    toLoopSlowClick($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        $("#btn_bt_loopSlowClick").text(_("自動点击", "自動點擊"));
        return;
      }
      YFUI.showPop({
        title: _("自動点击", "自動點擊"),
        text: _(`输入自动点击的次数,输入点击速度,确定后点击游戏中要点的按钮<br>
						<div style='margin:10px 0;'>
							<span>速度(几秒一次): </span>
							<input id="slowClickSec" value="0.5" style="font-size:16px;height:30px;width:15%;"></input>
							<span>次数: </span>
							<input id="slowClickTimes" value="${PLU.getCache("autoClickNum") || 20}" style="font-size:16px;height:26px;width:40%;"></input>
						</div>`,
            `輸入自動點擊的次數,输入點擊速度,確定後點擊遊戲中要點的按鈕<br>
						<div style='margin:10px 0;'>
							<span>速度(幾秒一次): </span>
							<input id="slowClickSec" value="0.5" style="font-size:16px;height:30px;width:15%;"></input>
							<span>次數: </span>
							<input id="slowClickTimes" value="${PLU.getCache("autoClickNum") || 20}" style="font-size:16px;height:26px;width:40%;"></input>
						</div>`),
        onOk() {
          let times = Number($("#slowClickTimes").val()),
            delay = Number($("#slowClickSec").val());
          if (Number(times) <= 0 || Number(delay) <= 0) return;
          setTimeout((o) => {
            $(document).one("click", (o) => {
              let snpc = $(o.target)
                .closest("button")[0]
                .outerHTML.match(/clickButton\([\'\"](.+)[\'\"](,\s*(\d+))*\)/i);
              if (snpc && snpc.length >= 2) {
                let param = snpc[3] ?? 0;
                PLU.setCache("autoClickNum", times);
                PLU.loopSlowClick(snpc[1], param, times, delay * 1000);
              } else {
                PLU.setBtnRed($btn, 0);
              }
            });
          }, 500);
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },
    toRecord($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (btnFlag) {
        PLU.TMP.cmds = [];
        $("#btn_record").text(_("停止录制", "停止錄製"));
        return;
      }
      let cmds = PLU.TMP.cmds;
      delete PLU.TMP.cmds;
      // 指令壓縮算法
      var count = 1;
      for (var index = 0; index < cmds.length; index++) {
        if (cmds[index] == cmds[index + 1]) {
          count++;
          continue;
        }
        if (count >= 2 + cmds[index].length == 1) {
          index -= count - 1;
          cmds.splice(index, count, "#" + count + " " + cmds[index]);
        }
        count = 1;
      }
      cmds = cmds
        .map((e) => {
          let res = e.match(/#\d+ ((jh|fb) \d+)/);
          return res ? res[1] : e;
        })
        .join(";");
      YFUI.showPop({
        title: _("指令详情", "指令詳情"),
        text: cmds,
        okText: _("复制", "複製"),
        onOk() {
          if (GM_setClipboard) GM_setClipboard(cmds);
          else YFUI.writeToOut("<span>" + _("权限不足", "權限不足") + "!</span>");
          $("#btn_record").text(_("指令录制", "指令錄製"));
        },
      });
    },
    //================================================================================================
    autoMasterGem($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        $("#btn_bt_autoMasterGem").text(_("一键合天神", "一鍵合天神"));
        return;
      }
      let arr = [
      "碎裂的", 
      _("裂开的", "裂開的"), 
      _("无前缀", "無前綴"), 
      _("无暇的", "無暇的"), 
      "完美的", 
      "君王的", 
      "皇帝的"
      ];
      let sel1 = '<select id="startGemLvl" style="font-size:16px;height:30px;width:25%;">';
      arr.forEach((p, pi) => {
        sel1 += '<option value="' + pi + '" ' + (pi == 0 ? "selected" : "") + ">" + p + "</option>";
      });
      sel1 += "</select>";
      YFUI.showPop({
        title: _("一键合天神", "一鍵合天神"),
        text: _(`选择合成起始宝石等级,选择速度(请根据网速和游戏速度选择),确定后自动向上合成所有<br>
						<div style='margin:10px 0;'>
							<span>起始等级: </span>${sel1}
							<span>速度(秒): </span>
							<select id="combineSec" style="font-size:16px;height:30px;width:15%;">
								<option selected>0.5</option>
								<option>1</option>
								<option>2</option>
								<option>3</option>
							</select>
						</div>`,
            `選擇合成起始寶石等級,選擇速度(請根據網速和遊戲速度選擇),確定後自動向上合成所有<br>
						<div style='margin:10px 0;'>
							<span>起始等級: </span>${sel1}
							<span>速度(秒): </span>
							<select id="combineSec" style="font-size:16px;height:30px;width:15%;">
								<option selected>0.5</option>
								<option>1</option>
								<option>2</option>
								<option>3</option>
							</select>
						</div>`),
        width: "382px",
        okText: _("开始", "開始"),
        onOk() {
          let startLvl = Number($("#startGemLvl").val()),
            delay = Number($("#combineSec").val());
          PLU.autoCombineMasterGem(startLvl, delay * 1000);
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },
    autoCombineMasterGem(startLvl, delay, gemCode, count) {
      if (!PLU.ONOFF["btn_bt_autoMasterGem"]) {
        PLU.setBtnRed($("#btn_bt_autoMasterGem"), 0);
        $("#btn_bt_autoMasterGem").text(_("一键合天神", "一鍵合天神"));
        YFUI.writeToOut("<span style='color:white;'>==" + _("停止合成宝石", "停止合成寶石") + "!==</span>");
        return;
      }
      if (!UTIL.sysListeners["listenCombineMasterGem"]) {
        UTIL.addSysListener("listenCombineMasterGem", function (b, type, subtype, msg) {
          if (type == "notice" && msg.indexOf(_("合成宝石需要", "合成寶石需要")) >= 0) {
            UTIL.delSysListener("listenCombineMasterGem");
            YFUI.writeToOut("<span style='color:#F00;'>--" + _("缺少银两, 合成结束", "缺少銀兩, 合成結束") + "--</span>");
            PLU.setBtnRed($("#btn_bt_autoMasterGem"), 0);
          }
          return;
        });
      }
      //合成寶石需要5萬銀兩。
      //沒有這麼多的完美的藍寶石
      if (!gemCode || count < 3) {
        PLU.getGemList((gemList) => {
          // console.log(gemList)
          let g = gemList.find((e) => e.key.indexOf("" + (startLvl + 1)) > 0 && e.num >= 3);
          if (g) {
            PLU.autoCombineMasterGem(startLvl, delay, g.key, g.num);
          } else {
            if (startLvl < 6) PLU.autoCombineMasterGem(startLvl + 1, delay);
            else {
              PLU.setBtnRed($("#btn_bt_autoMasterGem"), 0);
              YFUI.writeToOut("<span style='color:white;'>==" + _("合成宝石结束", "合成寶石結束") + "!==</span>");
            }
          }
        });
      } else {
        let cd = (delay / 4) | 250,
          n = 1;
        cd = cd > 250 ? cd : 250;
        if (count >= 30000) {
          n = 10000;
          cd = delay;
        } else if (count >= 15000) {
          n = 5000;
          cd = delay;
        } else if (count >= 9000) {
          n = 3000;
          cd = delay;
        } else if (count >= 3000) {
          n = 1000;
          cd = delay;
        } else if (count >= 300) {
          n = 100;
          cd = delay;
        } else if (count >= 150) {
          n = 50;
          cd = delay;
        } else if (count >= 90) {
          n = 30;
          cd = (delay / 2) | 0;
        } else if (count >= 30) {
          n = 10;
          cd = (delay / 3) | 0;
        }
        let cmd = "items hecheng " + gemCode + "_N_" + n + "";
        clickButton(cmd);
        setTimeout(() => {
          PLU.autoCombineMasterGem(startLvl, delay, gemCode, count - n * 3);
        }, cd);
      }
    },
    //================================================================================================
    toSellLaji($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        //$("#btn_bt_sellLaji").text('清理垃圾')
        return;
      }
      let defaultList =
      _("破烂衣服,水草,木盾,铁盾,藤甲盾,青铜盾,鞶革,军袍,麻带,破披风,长斗篷,牛皮带,锦缎腰带,丝质披风,逆钩匕,匕首,铁甲,重甲,精铁甲,逆钩匕,银丝甲,梅花匕,软甲衣,羊角匕,金刚杖,白蟒鞭,天寒项链,天寒手镯,新月棍,天寒戒,天寒帽,天寒鞋,金弹子,拜月掌套,玄武盾,破军盾,金丝宝甲衣,夜行披风,羊毛斗篷,残雪戒,残雪项链,残雪手镯,残雪鞋,残雪帽,金丝甲,宝玉甲,月光宝甲,虎皮腰带,沧海护腰,红光匕,毒龙鞭,玉清棍,霹雳掌套,疯魔杖,星河剑,金狮盾,白玉腰束,天寒匕,无心匕,生死符,血屠刀,貂皮斗篷,红色长衫,船篙,全真道袍,钢杖,草帽,铁戒,斩空刀,竹剑,布衣,单刀,铁项链,桃符纸,绣花针,锦衣,水烟阁司事帽,阿拉伯弯刀,桃木剑,铁手镯,长剑,丝绸衣,长斗篷",
        "破爛衣服,水草,木盾,鐵盾,藤甲盾,青銅盾,鞶革,軍袍,麻帶,破披風,長斗篷,牛皮帶,錦緞腰帶,絲質披風,逆鉤匕,匕首,鐵甲,重甲,精鐵甲,逆鉤匕,銀絲甲,梅花匕,軟甲衣,羊角匕,金剛杖,白蟒鞭,天寒項鏈,天寒手鐲,新月棍,天寒戒,天寒帽,天寒鞋,金彈子,拜月掌套,玄武盾,破軍盾,金絲寶甲衣,夜行披風,羊毛鬥篷,殘雪戒,殘雪項鏈,殘雪手鐲,殘雪鞋,殘雪帽,金絲甲,寶玉甲,月光寶甲,虎皮腰帶,滄海護腰,紅光匕,毒龍鞭,玉清棍,霹靂掌套,瘋魔杖,星河劍,金獅盾,白玉腰束,天寒匕,無心匕,生死符,血屠刀,貂皮鬥篷,紅色長衫,船篙,全真道袍,鋼杖,草帽,鐵戒,斬空刀,竹劍,布衣,單刀,鐵項鏈,桃符紙,繡花針,錦衣,水煙閣司事帽,阿拉伯彎刀,桃木劍,鐵手鐲,長劍,絲綢衣,長鬥篷");
      YFUI.showInput({
        title: "清理垃圾",
        text: _(`格式:物品词组<br>
						物品词组:以英文逗号分割多个关键词<br>
						<span style="color:red;">例如:</span><br>
						[例1] <span style="color:blue;">${defaultList}</span><br>
						`,
            `格式:物品詞組<br>
						物品詞組:以英文逗號分割多個關鍵詞<br>
						<span style="color:red;">例如:</span><br>
						[例1] <span style="color:blue;">${defaultList}</span><br>
						`),
        value: PLU.getCache("sellItemNames") || defaultList,
        type: "textarea",
        onOk(val) {
          if (!$.trim(val)) return;
          let str = $.trim(val);
          PLU.setCache("sellItemNames", str);
          let keysList = str.split(",");
          let itemsTimeOut = setTimeout(() => {
            UTIL.delSysListener("listItems");
          }, 5000);
          UTIL.addSysListener("listItems", function (b, type, subtype, msg) {
            if (type != "items") return;
            UTIL.delSysListener("listItems");
            clearTimeout(itemsTimeOut);
            clickButton("prev");
            let iId = 1,
              itemList = [];
            while (b.get("items" + iId)) {
              let it = UTIL.filterMsg(b.get("items" + iId)).split(",");
              if (it && it.length > 4 && it[3] == "0" && keysList.includes(it[1]))
                itemList.push({
                  key: it[0],
                  name: it[1],
                  num: Number(it[2]),
                });
              iId++;
            }
            PLU.loopSellItems(itemList);
          });
          clickButton("items", 0);
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },  
    //================================================================================================
    loopSellItems(itemList) {
      if (itemList.length <= 0) {
        PLU.setBtnRed($("#btn_bt_sellLaji"), 0);
        return YFUI.writeToOut("<span style='color:#F66;'>--" + _("无", "無") + "出售物件!--</span>");
      }
      let ac = [];
      itemList.forEach((it) => {
        let ct = it.num;
        while (ct > 0) {
          if (ct >= 10000) {
            ac.push("items sell " + it.key + "_N_10000");
            ct -= 10000;
          } else if (ct >= 1000) {
            ac.push("items sell " + it.key + "_N_1000");
            ct -= 1000;
          } else if (ct >= 100) {
            ac.push("items sell " + it.key + "_N_100");
            ct -= 100;
          } else if (ct >= 50) {
            ac.push("items sell " + it.key + "_N_50");
            ct -= 50;
          } else if (ct >= 10) {
            ac.push("items sell " + it.key + "_N_10");
            ct -= 10;
          } else {
            ac.push("items sell " + it.key + "");
            ct -= 1;
          }
        }
      });
      let acs = ac.join(";");
      PLU.fastExec(acs, () => {
        PLU.setBtnRed($("#btn_bt_sellLaji"), 0);
        YFUI.writeToOut("<span style='color:white;'>==出售完成!==</span>");
      });
    },
    //================================================================================================
    toSplitItem($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) return;
      let defaultList =
        _("玄武盾,破军盾,金丝宝甲衣,夜行披风,羊毛斗篷,残雪戒,残雪项鍊,残雪手镯,残雪鞋,金丝甲,宝玉甲,月光宝甲,虎皮腰带,沧海护腰,红光匕,毒龙鞭,玉清棍,霹雳掌套",
        "玄武盾,破軍盾,金絲寶甲衣,夜行披風,羊毛斗篷,殘雪戒,殘雪項鍊,殘雪手鐲,殘雪鞋,金絲甲,寶玉甲,月光寶甲,虎皮腰帶,滄海護腰,紅光匕,毒龍鞭,玉清棍,霹靂掌套");
      YFUI.showInput({
        title: _("分解装备", "分解裝備"),
        text: _(`格式:物品词组<br>
						物品词组:以英文逗号分割多个关键词<br>
						<span style="color:red;">例如:</span><br>
						[例1] <span style="color:blue;">${defaultList}</span><br>
						`,
            `格式:物品詞組<br>
						物品詞組:以英文逗號分割多個關鍵詞<br>
						<span style="color:red;">例如:</span><br>
						[例1] <span style="color:blue;">${defaultList}</span><br>
						`),
        value: PLU.getCache("splitItemNames") || defaultList,
        type: "textarea",
        onOk(val) {
          if (!$.trim(val)) return;
          let str = $.trim(val);
          PLU.setCache("splitItemNames", str);
          let keysList = str.split(",");
          let itemsTimeOut = setTimeout(() => {
            UTIL.delSysListener("listItems_si");
          }, 5000);
          UTIL.addSysListener("listItems_si", function (b, type, subtype, msg) {
            if (type != "items") return;
            UTIL.delSysListener("listItems_si");
            clearTimeout(itemsTimeOut);
            clickButton("prev");
            let iId = 1,
              itemList = [];
            while (b.get("items" + iId)) {
              let it = UTIL.filterMsg(b.get("items" + iId)).split(",");
              if (it && it.length > 4 && it[3] == "0" && keysList.includes(it[1]))
                itemList.push({
                  key: it[0],
                  name: it[1],
                  num: Number(it[2]),
                });
              iId++;
            }
            PLU.loopSplitItem(itemList);
          });
          clickButton("items", 0);
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },
    //================================================================================================
    loopSplitItem(itemList) {
      if (itemList.length <= 0) {
        PLU.setBtnRed($("#btn_bt_splitItem"), 0);
        return YFUI.writeToOut("<span style='color:#F66;'>--" + _("无", "無") + "分解物件!--</span>");
      }
      let ac = [];
      itemList.forEach((it) => {
        let ct = it.num;
        while (ct > 0) {
          if (ct >= 100) {
            ac.push("items splite " + it.key + "_N_100");
            ct -= 100;
          } else if (ct >= 50) {
            ac.push("items splite " + it.key + "_N_50");
            ct -= 50;
          } else if (ct >= 10) {
            ac.push("items splite " + it.key + "_N_10");
            ct -= 10;
          } else {
            ac.push("items splite " + it.key + "");
            ct -= 1;
          }
        }
      });
      let acs = ac.join(";");
      PLU.fastExec(acs, () => {
        PLU.setBtnRed($("#btn_bt_splitItem"), 0);
        YFUI.writeToOut("<span style='color:white;'>==分解完成!==</span>");
      });
    },
    //================================================================================================
    toPutStore($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) return;
      let defaultList = 
      _("树枝,碎片,璞玉,青玉,墨玉,白玉,秘籍木盒,锦袋,瑞雪针釦,武穆遗书,隐武竹笺,空识卷轴,技能书,开元宝票,霹雳弹,舞鸢尾,百宜雪梅",
      "樹枝,碎片,璞玉,青玉,墨玉,白玉,秘籍木盒,錦袋,瑞雪針釦,武穆遺書,隱武竹箋,空識卷軸,技能書,開元寶票,霹靂彈,舞鳶尾,百宜雪梅");
      YFUI.showInput({
        title: _("物品入库", "物品入庫"),
        text: _(`格式:物品词组<br>
						物品词组:以英文逗号分割多个关键词<br>
						<span style="color:red;">例如:</span><br>
						[例1] <span style="color:blue;">${defaultList}</span><br>
						`,
            `格式:物品詞組<br>
						物品詞組:以英文逗號分割多個關鍵詞<br>
						<span style="color:red;">例如:</span><br>
						[例1] <span style="color:blue;">${defaultList}</span><br>
						`),
        value: PLU.getCache("putStoreNames") || defaultList,
        type: "textarea",
        onOk(val) {
          if (!$.trim(val)) return;
          let str = $.trim(val);
          PLU.setCache("putStoreNames", str);
          let keysList = str.split(",").join("|");
          let itemsTimeOut = setTimeout(() => {
            UTIL.delSysListener("listItems_ps");
          }, 5000);
          UTIL.addSysListener("listItems_ps", function (b, type, subtype, msg) {
            if (type != "items") return;
            UTIL.delSysListener("listItems_ps");
            clearTimeout(itemsTimeOut);
            clickButton("prev");
            let iId = 1,
              itemList = [];
            while (b.get("items" + iId)) {
              let it = UTIL.filterMsg(b.get("items" + iId)).split(",");
              if (it && it.length > 4 && it[3] == "0" && it[1].match(keysList) && it[1] != _("青龙碎片", "青龍碎片") && it[1] != _("玄铁碎片", "玄鐵碎片"))
                itemList.push({
                  key: it[0],
                  name: it[1],
                  num: Number(it[2]),
                });
              iId++;
            }
            PLU.loopPutStore(itemList);
          });
          clickButton("items", 0);
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },  
    //================================================================================================
    loopSortItems(put_itemList, sell_itemList) {
      if (put_itemList.length <= 0) {
        PLU.setBtnRed($("#btn_bt_putStore"), 0);
        YFUI.writeToOut("<span style='color:#F66;'>--" + _("无物件入库", "無物件入庫") + "!--</span>");
        PLU.loopSellItems(sell_itemList);
        return
      }
      PLU.fastExec(put_itemList, () => {
        PLU.setBtnRed($("#btn_bt_putStore"), 0);
        YFUI.writeToOut("<span style='color:white;'>==" + _("入库完成", "入庫完成") + "!==</span>");
        setTimeout(() => {
          PLU.loopSellItems(sell_itemList);
        }, 0);
      });
    },
    //================================================================================================
    loopPutStore(itemList) {
      if (itemList.length <= 0) {
        PLU.setBtnRed($("#btn_bt_putStore"), 0);
        return YFUI.writeToOut("<span style='color:#F66;'>--" + _("无物件入库", "無物件入庫") + "!--</span>");
      }
      let ac = [];
      itemList.forEach((it) => {
        ac.push("items put_store " + it.key + "");
      });
      PLU.fastExec(ac.join(";"), () => {
        PLU.setBtnRed($("#btn_bt_putStore"), 0);
        YFUI.writeToOut("<span style='color:white;'>==" + _("入库完成", "入庫完成") + "!==</span>");
      });
    },
    //================================================================================================
    toAutoUse($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) return;
      let defaultList =
      _("*神秘宝箱,灵草,紫芝,狂暴丹,小还丹,大还丹,高级大还丹,高级狂暴丹,高级乾坤再造丹,百年灵草,百年紫芝,特级大还丹,特级狂暴丹,特级乾坤再造丹,千年灵草,千年紫芝,顶级大还丹,顶级狂暴补丸,顶级乾坤补丸,万年灵草,万年紫芝",
      "*神秘寶箱,靈草,紫芝,狂暴丹,小還丹,大還丹,高級大還丹,高級狂暴丹,高級乾坤再造丹,百年靈草,百年紫芝,特級大還丹,特級狂暴丹,特級乾坤再造丹,千年靈草,千年紫芝,頂級大還丹,頂級狂暴補丸,頂級乾坤補丸,萬年靈草,萬年紫芝");
      YFUI.showInput({
        title: "物品使用",
        text: _(`格式:物品词组<br>
						物品词组:以英文逗号分割多个关键词, 只能单个使用的物品前面加*星号<br>
						<span style="color:red;">例如:</span><br>
						[例1] <span style="color:blue;">${defaultList}</span><br>
						`,
            `格式:物品詞組<br>
						物品詞組:以英文逗號分割多個關鍵詞, 只能單個使用的物品前面加*星號<br>
						<span style="color:red;">例如:</span><br>
						[例1] <span style="color:blue;">${defaultList}</span><br>
						`),
        value: PLU.getCache("autoUseNames") || defaultList,
        type: "textarea",
        onOk(val) {
          if (!$.trim(val)) return;
          let str = $.trim(val);
          PLU.setCache("autoUseNames", str);
          let keysList = str.split(",");
          let itemsTimeOut = setTimeout(() => {
            UTIL.delSysListener("listItems_au");
          }, 5000);
          UTIL.addSysListener("listItems_au", function (b, type, subtype, msg) {
            if (type != "items") return;
            UTIL.delSysListener("listItems_au");
            clearTimeout(itemsTimeOut);
            clickButton("prev");
            let iId = 1,
              itemList = [];
            while (b.get("items" + iId)) {
              let it = UTIL.filterMsg(b.get("items" + iId)).split(",");
              if (!it[1]) continue;
              if (it && it.length > 4 && it[3] == "0") {
                if (keysList.includes(it[1]))
                  itemList.push({
                    key: it[0],
                    name: it[1],
                    num: Number(it[2]),
                    multi: true,
                  });
                else if (keysList.includes("*" + it[1]))
                  itemList.push({
                    key: it[0],
                    name: it[1],
                    num: Number(it[2]),
                    multi: false,
                  });
              }
              iId++;
            }
            PLU.loopAutoUse(itemList);
          });
          clickButton("items", 0);
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },
    //================================================================================================
    loopAutoUse(itemList) {
      if (itemList.length <= 0) {
        PLU.setBtnRed($("#btn_bt_autoUse"), 0);
        return YFUI.writeToOut("<span style='color:#F66;'>--" + _("无", "無") + "物件使用!--</span>");
      }
      let ac = [];
      itemList.forEach((it) => {
        let ct = it.num;
        while (ct > 0) {
          if (it.multi && ct >= 100) {
            ac.push("items use " + it.key + "_N_100");
            ct -= 100;
          } else if (it.multi && ct >= 50) {
            ac.push("items use " + it.key + "_N_50");
            ct -= 50;
          } else if (it.multi && ct >= 10) {
            ac.push("items use " + it.key + "_N_10");
            ct -= 10;
          } else {
            ac.push("items use " + it.key + "");
            ct -= 1;
          }
        }
      });
      PLU.fastExec(ac.join(";"), () => {
        PLU.setBtnRed($("#btn_bt_autoUse"), 0);
        YFUI.writeToOut("<span style='color:white;'>==使用完成!==</span>");
      });
    },
    //================================================================================================
    toLoopScript($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        $("#btn_bt_loopScript").text(_("循环执行", "循環執行"));
        PLU.STO.loopScTo && clearTimeout(PLU.STO.loopScTo) && delete PLU.STO.loopScTo;
        return;
      }
      YFUI.showInput({
        title: _("循环执行", "循環執行"),
        text: _(`格式:循环次数@时间间隔|执行指令<br>
						循环次数:省略则默认1次<br>
						时间间隔:省略则默认1(1秒)<br>
						执行指令:以分号分隔的指令<br>
						<span style="color:red;">例如</span><br>
						[例1] 3@5|jh 1;e;n;home;<br>
						[例2] jh 5;n;n;n;w;sign7;
						`,
            `格式:循環次數@時間間隔|執行指令<br>
						循環次數:省略則默認1次<br>
						時間間隔:省略則默認1(1秒)<br>
						執行指令:以分號分隔的指令<br>
						<span style="color:red;">例如</span><br>
						[例1] 3@5|jh 1;e;n;home;<br>
						[例2] jh 5;n;n;n;w;sign7;
						`),
        value: PLU.getCache("loopScript") || "home;",
        type: "textarea",
        onOk(val) {
          if (!$.trim(val)) return;
          let str = $.trim(val),
            scripts = "",
            times = 1,
            interval = 1,
            arr = str.split("|");
          if (arr.length > 1) {
            scripts = arr[1];
            if (arr[0].indexOf("@") >= 0) {
              times = Number(arr[0].split("@")[0]) || 1;
              interval = Number(arr[0].split("@")[1]) || 1;
            } else {
              times = Number(arr[0]) || 1;
            }
          } else {
            scripts = arr[0];
          }
          PLU.setCache("loopScript", str);
          PLU.loopScript(scripts, times, interval);
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },
    //================================================================================================
    loopScript(scripts, times, interval) {
      times--;
      $("#btn_bt_loopScript").text("停執行(" + times + ")");
      PLU.execActions(scripts, () => {
        if (times <= 0 || !PLU.ONOFF["btn_bt_loopScript"]) {
          PLU.setBtnRed($("#btn_bt_loopScript"), 0);
          $("#btn_bt_loopScript").text(_("循环执行", "循環執行"));
          PLU.STO.loopScTo && clearTimeout(PLU.STO.loopScTo) && delete PLU.STO.loopScTo;
          return;
        } else {
          PLU.STO.loopScTo = setTimeout(() => {
            PLU.loopScript(scripts, times, interval);
          }, interval * 1000);
        }
      });
    },
    //================================================================================================
    toAutoAskQixia($btn, autoTime) {
      if (g_gmain.is_fighting) return;
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) return;
      $(".menu").hide();
      YFUI.showPop({
        title: _("自动访问奇侠", "自動訪問奇俠"),
        text: _("自动对话所有有亲密度的奇侠<br>请在做完20次赞助金锭后再进行<br><b style='color:#F00;'>是否现在进行?</b>", "自動對話所有有親密度的奇俠<br>請在做完20次讚助金錠後再進行<br><b style='color:#F00;'>是否現在進行?</b>"),
        autoOk: autoTime ?? null,
        onOk() {
          let jhqxTimeOut = setTimeout(() => {
            UTIL.delSysListener("listQixia");
            PLU.setBtnRed($btn, 0);
          }, 5000);
          UTIL.addSysListener("listQixia", function (b, type, subtype, msg) {
            if (type != "show_html_page" || msg.indexOf(_("江湖奇侠成长信息", "江湖奇俠成長信息")) < 0) return;
            UTIL.delSysListener("listQixia");
            clearTimeout(jhqxTimeOut);
            let listHtml = msg;
            clickButton("prev");
            let str = "find_task_road qixia (\\d+)\x03(.{2,4})\x030\x03\\((\\d+)\\)(.{15,25}朱果)?.{30,50}" + _("已出师", "已出師"),
              rg1 = new RegExp(str, "g"),
              rg2 = new RegExp(str),
              visQxs = [];
            listHtml.match(rg1).forEach((e) => {
              let a = e.match(rg2);
              if (a)
                visQxs.push({
                  key: a[1],
                  name: a[2],
                  num: Number(a[3]),
                  link: "find_task_road qixia " + a[1],
                  fast: a[4] ? "open jhqx " + a[1] : null,
                });
            });
            visQxs = visQxs.sort((a, b) => {
              if (a.fast && b.num >= 25000) return -1;
              else return 2;
            });
            visQxs.reverse();
            PLU.toAskQixia(visQxs, 0);
          });
          clickButton("open jhqx", 0);
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },
    //================================================================================================
    toAskQixia(qxList, idx) {
      clickButton("home");
      if (idx >= qxList.length || !PLU.ONOFF["btn_bt_autoAskQixia"]) {
        PLU.setBtnRed($("#btn_bt_autoAskQixia"), 0);
        YFUI.writeToOut("<span style='color:#FFF;'>--" + _("奇侠访问结束", "奇俠訪問結束") + "!--</span>");
        return;
      }
      let qxObj = qxList[idx];
      if (qxObj.fast) {
        clickButton(qxObj.fast, 0);
        setTimeout(() => {
          PLU.toAskQixia(qxList, idx + 1);
        }, 500);
      } else {
        PLU.execActions(qxObj.link + ";golook_room;", () => {
          let objNpc = UTIL.findRoomNpc(qxObj.name, false, true);
          if (objNpc) {
            PLU.execActions("ask " + objNpc.key + ";ask " + objNpc.key + ";ask " + objNpc.key + ";ask " + objNpc.key + ";ask " + objNpc.key + ";golook_room;", () => {
              setTimeout(() => {
                PLU.toAskQixia(qxList, idx + 1);
              }, 500);
            });
          } else {
            YFUI.writeToOut("<span style='color:#FFF;'>--" + _("找不到奇侠:", "找不到奇俠:") + qxObj.name + "--</span>");
            setTimeout(() => {
              PLU.toAskQixia(qxList, idx + 1);
            }, 500);
          }
        });
      }
    },
    //================================================================================================
    getQixiaList(callback) {
      let jhQixiaTimeOut = setTimeout(() => {
        UTIL.delSysListener("getlistQixia");
      }, 5000);
      UTIL.addSysListener("getlistQixia", function (b, type, subtype, msg) {
        if (type != "show_html_page" || msg.indexOf(_("江湖奇侠成长信息", "江湖奇俠成長信息")) < 0) return;
        UTIL.delSysListener("getlistQixia");
        clearTimeout(jhQixiaTimeOut);
        window.ttttt = msg;
        let listHtml = msg.replace(/\x03(0)?|href;0;|[\033|\27|\0x1b]\[[0-9|;]+m/gi, "");
        clickButton("prev");
        let str =
          "find_task_road qixia (\\d+)(.{2,4})(\\((\\d*)\\))?(open jhqx \\d+朱果)?<\\/td><td.{20,35}>(.{1,10})<\\/td><td.{20,35}>(.{1,15})<\\/td><td .{20,40}" + _("领悟", "領悟") + "(.{2,10})<\\/td><\\/tr>";
        let rg1 = new RegExp(str, "g"),
          rg2 = new RegExp(str),
          qxList = [];
        listHtml.match(rg1).forEach((e) => {
          let a = e.match(rg2);
          if (a)
            qxList.push({
              index: a[1],
              name: a[2],
              num: Number(a[4]) || 0,
              link: "find_task_road qixia " + a[1],
              fast: a[5] ? "open jhqx " + a[1] : null,
              inJh: a[6] && a[6].indexOf("未出世") < 0 ? true : false,
            });
        });
        callback && callback(qxList);
      });
      clickButton("open jhqx", 0);
    },
    //================================================================================================
    toAutoVisitQixia($btn) {
      if (g_gmain.is_fighting) return;
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        //$("#btn_bt_autoVisitQixia").text('親近奇俠')
        PLU.TMP.autoQixiaMijing = false;
        return;
      }
      $(".menu").hide();
      clickButton("open jhqx", 0);
      YFUI.showInput({
        title: _("奇侠秘境", "奇俠秘境"),
        text:_(`请输入要提升亲密度的游侠的姓名<br>
                        格式:金锭数量|游侠姓名@目标友好度<br>
						金锭数量:给予1或5或15金锭,可省略则只对话<br>
						游侠姓名:只能输入一个游侠姓名<br>
						目标友好度:省略则以可学技能的友好度为目标<br>
						<span style="color:red;">例如</span><br>
						[例1] 15|风无痕 <span style="color:blue;">访问风无痕赠与15金锭</span><br>
						[例2] 火云邪神 <span style="color:blue;">访问火云邪神对话</span><br>
						[例2] 15|步惊鸿@30000 <span style="color:blue;">访问步惊鸿对话赠与15金锭到30000友好度</span><br>
						`,
          `請輸入要提升親密度的遊俠的姓名<br>
                        格式:金錠數量|遊俠姓名@目標友好度<br>
						金錠數量:給予1或5或15金錠,可省略則只對話<br>
						遊俠姓名:只能輸入一個遊俠姓名<br>
						目標友好度:省略則以可學技能的友好度為目標<br>
						<span style="color:red;">例如</span><br>
						[例1] 15|風無痕 <span style="color:blue;">訪問風無痕贈與15金錠</span><br>
						[例2] 火雲邪神 <span style="color:blue;">訪問火雲邪神對話</span><br>
						[例2] 15|步驚鴻@30000 <span style="color:blue;">訪問步驚鴻對話贈與15金錠到30000友好度</span><br>
						`) +
          '<div style="text-align:right;"><label>自動挖寶:<input type="checkbox" id="if_auto_wb" name="awb" value="1"/></label><label>不要掃盪秘境:<input type="checkbox" id="if_auto_mj" name="noamj" value="1"/></label></div>',
        value: PLU.getCache("visitQixiaName") || _("15|风无痕@40000", "15|風無痕@40000"),
        onOk(val) {
          if (!$.trim(val)) return;
          let str = $.trim(val),
            arr = str.split("|"),
            giveNum = 15,
            qxName = "",
            objectFN = 0;
          let ifAutoMj = $("#if_auto_mj").is(":checked");
          let ifAutoWb = $("#if_auto_wb").is(":checked");
          if (arr.length > 1) {
            giveNum = Number(arr[0]) || 15;
            let nn = arr[1].split("@");
            qxName = nn[0].trim();
            if (nn.length > 1) objectFN = Number(nn[1]);
          } else {
            giveNum = 0;
            let nn = arr[0].split("@");
            qxName = nn[0].trim();
            if (nn.length > 1) objectFN = Number(nn[1]);
          }
          PLU.setCache("visitQixiaName", str);
          PLU.TMP.todayGetXT = 0;
          UTIL.delSysListener("listenVisitNotice");
          PLU.STO.listenVisit && clearTimeout(PLU.STO.listenVisit);
          PLU.TMP.goingQixiaMijing = false;
          PLU.tryVisitQixia(qxName, giveNum, objectFN, ifAutoMj, ifAutoWb, (err) => {
            if (err) {
              if (err.code == 1) {
                PLU.setBtnRed($btn, 0);
                UTIL.delSysListener("listenVisitNotice");
                PLU.toAutoAskQixia($("#btn_bt_autoAskQixia"), 10);
                YFUI.writeToOut("<span style='color:yellow;'> " + _("今日一共获得玄铁令x", "今日一共獲得玄鐵令x") + PLU.TMP.todayGetXT + "</span>");
                UTIL.log({
                  msg: _(" 今日一共获得玄铁令x ", " 今日一共獲得玄鐵令x ") + PLU.TMP.todayGetXT + "  ",
                  type: "TIPS",
                  time: new Date().getTime(),
                });
              } else {
                YFUI.showPop({
                  title: "提示",
                  text: "<b style='color:#F00;'>" + err.msg + "</b>",
                  onOk() {
                    PLU.setBtnRed($btn, 0);
                    PLU.toAutoVisitQixia($btn);
                  },
                  onX() {
                    PLU.setBtnRed($btn, 0);
                  },
                });
              }
            }
          });
        },
        onNo() {
          PLU.setBtnRed($btn, 0);
        },
        onX() {
          PLU.setBtnRed($btn, 0);
        },
      });
    },
    //================================================================================================
    tryVisitQixia(qxName, giveNum, objectFN, ifAutoMj, ifAutoWb, callback) {
      PLU.TMP.autoQixiaMijing = true;
      //發現
      PLU.getQixiaList((qxlist) => {
        let testDone = qxlist.find((e) => !!e.fast);
        if (testDone) {
          PLU.STO.listenVisit && clearTimeout(PLU.STO.listenVisit);
          callback && callback({ code: 1, msg: _("今日奇侠友好度操作已经完毕", "今日奇俠友好度操作已經完畢") });
          return;
        }
        let qx = qxlist.find((e) => e.name == qxName);
        if (!qx) {
          callback && callback({ code: 2, msg: _("没有这个奇侠!", "沒有這個奇俠!") });
          return;
        }
        if (!qx.inJh) {
          callback && callback({ code: 3, msg: _("这个奇侠还没出师!", "這個奇俠還沒出師!") });
          return;
        }
        let objectFriendNum = objectFN ?? PLU.YFD.qixiaFriend.find((e) => e.name == qxName).skillFN;
        if (qx.num >= objectFriendNum) {
          callback && callback({ code: 4, msg: _("奇侠友好度已足够", "奇俠友好度已足夠") });
          return;
        }
        let listenVisitTimeout = function () {
          if (!PLU.TMP.goingQixiaMijing) PLU.tryVisitQixia(qxName, giveNum, objectFN, ifAutoMj, ifAutoWb, callback);
        };
        UTIL.delSysListener("listenVisitNotice");
        //監聽場景消息
        UTIL.addSysListener("listenVisitNotice", function (b, type, subtype, msg) {
          if (type != "notice" && type != "main_msg") return;
          let msgTxt = UTIL.filterMsg(msg);
          if (msgTxt.match(_("对你悄声道:你现在去", "對你悄聲道:你現在去"))) {
            //奇俠說秘境
            let l = msgTxt.match(_(/(.*)對你悄聲道:你現在去(.*),應當會有發現/, /(.*)對你悄聲道:你現在去(.*),應當會有發現/));
            if (l && l.length > 2) {
              PLU.TMP.goingQixiaMijing = true;
              let placeData = PLU.YFD.mjList.find((e) => e.n == l[2]);
              if (placeData) {
                PLU.execActions(placeData.v + ";;find_task_road secret;;", () => {
                  setTimeout(() => {
                    let mapid = g_obj_map.get("msg_room").get("map_id");
                    let shortName = g_obj_map.get("msg_room").get("short");
                    YFUI.writeToOut("<span style='color:#FFF;'>--" + _("地图ID:", "地圖ID:") + mapid + "--</span>");
                    if (mapid == "public") {
                      PLU.execActions("secret_op1;", () => {
                        PLU.TMP.goingQixiaMijing = false;
                        PLU.tryVisitQixia(qxName, giveNum, objectFN, ifAutoMj, ifAutoWb, callback);
                      });
                    } else if (ifAutoMj) {
                      UTIL.delSysListener("listenVisitNotice");
                      PLU.setBtnRed($("#btn_bt_autoVisitQixia"), 0);
                      YFUI.writeToOut("<span style='color:yellow;'> ===== " + _("进", "進") + "入了秘境! ===== </span>");
                    } else {
                      let ss = g_obj_map.get("msg_room").elements.find((e) => e.value == "仔细搜索", "仔細搜索");
                      if (ss) {
                        let cmd_ss = g_obj_map.get("msg_room").get(ss.key.split("_")[0]);
                        PLU.execActions(cmd_ss + ";;", () => {
                          if (ifAutoWb) {
                            let wb = g_obj_map.get("msg_room").elements.find((e) => e.value.indexOf("秘境挖宝", "秘境挖寶") >= 0);
                            if (wb) {
                              PLU.execActions("mijing_wb;;");
                            }
                          }

                          let sd = g_obj_map.get("msg_room").elements.find((e) => e.value.indexOf(_("扫荡", "掃盪")) >= 0);
                          if (sd) {
                            let cmd_sd = g_obj_map.get("msg_room").get(sd.key.split("_")[0]);
                            PLU.doSaoDang(mapid, cmd_sd, () => {
                              PLU.TMP.goingQixiaMijing = false;
                              PLU.tryVisitQixia(qxName, giveNum, objectFN, ifAutoMj, ifAutoWb, callback);
                            });
                          } else if (shortName == _("无尽深渊", "無盡深淵")) {
                            PLU.goWuJinShenYuan(() => {
                              PLU.TMP.goingQixiaMijing = false;
                              PLU.tryVisitQixia(qxName, giveNum, objectFN, ifAutoMj, ifAutoWb, callback);
                            });
                          } else {
                            UTIL.delSysListener("listenVisitNotice");
                            PLU.setBtnRed($("#btn_bt_autoVisitQixia"), 0);
                            YFUI.writeToOut("<span style='color:yellow;'> ===" + _("进入了未通关秘境","進入了未通關秘境") + "!=== </span>");
                          }
                        });
                      }
                    }
                  }, 1500);
                });
              }
              return;
            }
          }
          let vis = msgTxt.match(_(/今日親密度操作次數\((\d+)\/20\)/, /今日親密度操作次數\((\d+)\/20\)/));
          if (vis) {
            PLU.STO.listenVisit && clearTimeout(PLU.STO.listenVisit);
            setTimeout(() => {
              if (!PLU.TMP.goingQixiaMijing) {
                PLU.STO.listenVisit = setTimeout(listenVisitTimeout, 4000);
                let objNpc = UTIL.findRoomNpc(qxName, false, true);
                if (objNpc) {
                  PLU.doVisitAction(objNpc.key, giveNum);
                } else {
                  YFUI.writeToOut("<span style='color:#FFF;'>--" + _("找不到奇侠", "找不到奇俠") + "!--</span>");
                  setTimeout(() => {
                    PLU.tryVisitQixia(qxName, giveNum, objectFN, ifAutoMj, ifAutoWb, callback);
                  }, 500);
                }
              }
            }, 500);
            return;
          }
          if (msgTxt.match(_("今日做了太多关于亲密度的操作", "今日做了太多關於親密度的操作"))) {
            PLU.STO.listenVisit && clearTimeout(PLU.STO.listenVisit);
            callback && callback({ code: 1, msg: _("今日奇侠友好度操作已经完毕", "今日奇俠友好度操作已經完畢") });
            return;
          }
          if (msgTxt.match(_(/今日奇俠贈送次數(\d+)\/(\d+),.*贈送次數(\d+)\/(\d+)/, /今日奇俠贈送次數(\d+)\/(\d+),.*贈送次數(\d+)\/(\d+)/))) {
            PLU.STO.listenVisit && clearTimeout(PLU.STO.listenVisit);
            callback && callback({ code: 1, msg: _("今日奇侠友好度操作已经完毕", "今日奇俠友好度操作已經完畢") });
            return;
          }
          if (msgTxt.match(_("扫荡成功,获得:", "掃盪成功,獲得:"))) {
            let xtnum = parseInt(msgTxt.split("、")[0].split(_("玄铁令x", "玄鐵令x"))[1]);
            if (xtnum) PLU.TMP.todayGetXT += xtnum;
            xtnum && YFUI.writeToOut("<span>--" + _("玄铁令+", "玄鐵令+") + xtnum + "--</span>");
            return;
          }
          if (msgTxt.match(_("你开始四处搜索……你找到了", "你開始四處搜索……你找到了"))) {
            let xtnum = parseInt(msgTxt.split("、")[0].split(_("玄铁令x", "玄鐵令x"))[1]);
            if (xtnum) PLU.TMP.todayGetXT += xtnum;
            xtnum && YFUI.writeToOut("<span>--" + _("玄铁令+", "玄鐵令+") + xtnum + "--</span>");
            return;
          }
        });
        PLU.execActions(qx.link + ";;", () => {
          let objNpc = UTIL.findRoomNpc(qxName, false, true);
          if (objNpc) {
            PLU.STO.listenVisit = setTimeout(listenVisitTimeout, 3000);
            PLU.doVisitAction(objNpc.key, giveNum);
          } else {
            YFUI.writeToOut("<span style='color:#FFF;'>--" + _("找不到奇侠:", "找不到奇俠:") + qxName + "--</span>");
            setTimeout(() => {
              PLU.tryVisitQixia(qxName, giveNum, objectFN, ifAutoMj, ifAutoWb, callback);
            }, 500);
          }
        });
      });
    },
    //================================================================================================
    doVisitAction(qxKey, giveNum) {
      if (giveNum == 0) {
        PLU.execActions("ask " + qxKey + ";");
      } else if (giveNum == 1) {
        PLU.execActions("auto_zsjd_" + qxKey.split("_")[0] + ";");
      } else if (giveNum == 5) {
        PLU.execActions("auto_zsjd5_" + qxKey.split("_")[0] + ";");
      } else {
        PLU.execActions("auto_zsjd20_" + qxKey.split("_")[0] + ";");
      }
    },
    //================================================================================================
    doSaoDang(mapid, cmd, callback) {
      UTIL.addSysListener("listenVisitSaodang", function (b, type, subtype, msg) {
        if (type != "prompt") return;
        let xtnum = parseInt(msg.split("、")[0].split(_("玄铁令x", "玄鐵令x"))[1]);
        if (["yaowanggu", "leichishan"].includes(mapid)) {
          if (xtnum < 5)
            return setTimeout(() => {
              clickButton(cmd);
            }, 300);
        } else if (["liandanshi", "lianhuashanmai", "qiaoyinxiaocun", "duzhanglin", "shanya", "langhuanyudong", "dixiamigong"].includes(mapid)) {
          if (xtnum < 3)
            return setTimeout(() => {
              clickButton(cmd);
            }, 300);
        }
        UTIL.delSysListener("listenVisitSaodang");
        PLU.execActions(cmd + " go;", () => {
          callback && callback();
        });
      });
      setTimeout(() => {
        clickButton(cmd);
      }, 300);
    },
    //================================================================================================
    goWuJinShenYuan(endcallback) {
      //無盡深淵
      let paths = "e;e;s;w;w;s;s;e;n;e;s;e;e;n;w;n;e;n;w".split(";");
      var sidx = 0;
      let gostep = function (pathArray, stepFunc) {
        let ca = pathArray[sidx];
        PLU.execActions(ca + "", () => {
          stepFunc && stepFunc();
          sidx++;
          if (sidx >= pathArray.length) {
            endcallback && endcallback();
          } else {
            setTimeout(() => {
              gostep(pathArray, stepFunc);
            }, 250);
          }
        });
      };
      gostep(paths, () => {
        let fc = g_obj_map.get("msg_room").elements.find((e) => e.value == "翻查");
        if (fc) {
          let cmd_fc = g_obj_map.get("msg_room").get(fc.key.split("_")[0]);
          PLU.execActions(cmd_fc + "");
        }
      });
    },
    //================================================================================================
    toWaitCDKill($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        //$("#btn_bt_waitCDKill").text('')
        return;
      }
      clickButton("golook_room");
      YFUI.showPop({
        title: _("倒计时叫杀门派纷争", "倒計時叫殺門派紛爭"),
        text: _("倒计时最后5秒叫杀最近结束时间的门派纷争!,确定后单击NPC<br>", "倒計時最後5秒叫殺最近結束時間的門派紛爭!,確定後單擊NPC<br>"),
        onOk() {
          setTimeout((o) => {
            $(document).one("click", (o) => {
              let npcbtn = $(o.target).closest("button");
              let snpc = npcbtn[0].outerHTML.match(/clickButton\('look_npc (\w+)'/i);
              if (snpc && snpc.length >= 2) {
                let nowTime = new Date().getTime(),
                  cMPFZ = null;
                for (let k in PLU.MPFZ) {
                  if (!cMPFZ || cMPFZ.t > PLU.MPFZ[k].t) cMPFZ = PLU.MPFZ[k];
                }
                if (cMPFZ) {
                  PLU.TMP.DATA_MPFZ = Object.assign({}, cMPFZ, {
                    killId: snpc[1],
                  });
                  YFUI.showPop({
                    title: _("倒计时叫杀门派纷争", "倒計時叫殺門派紛爭"),
                    text:
                      '<div style="line-height:2;">人物:' +
                      npcbtn.text() +
                      _("<br>地点:", "<br>地點:") +
                      PLU.TMP.DATA_MPFZ.p +
                      _("<br>对决:", "<br>對決:") +
                      PLU.mp2icon(PLU.TMP.DATA_MPFZ.v) +
                      "</div>",
                    okText: "好的",
                    onOk() { },
                    onNo() {
                      PLU.TMP.DATA_MPFZ = null;
                      PLU.setBtnRed($btn, 0);
                    },
                  });
                }
              } else {
                PLU.TMP.DATA_MPFZ = null;
                PLU.setBtnRed($btn, 0);
              }
            });
          }, 500);
        },
        onNo() {
          PLU.TMP.DATA_MPFZ = null;
          PLU.setBtnRed($btn, 0);
        },
      });
    },
    //================================================================================================
    mp2icon(mplist) {
      let htm = "",
        zfarr = mplist.split(" VS "),
        zarr = zfarr[0].split("、"),
        farr = zfarr[1].split("、");
      zarr.forEach((zm) => {
        htm += '<span style="display:inline-block;background:#F66;border-radius:2px;padding:0 2px;margin:1px;color:#FFF;">' + zm + "</span>";
      });
      htm += '<span style="color:#FFF;background:#F00;font-weight:bold;border-radius:50%;padding:2px;">VS</span>';
      farr.forEach((fm) => {
        htm += '<span style="display:inline-block;background:#66F;border-radius:2px;padding:0 2px;margin:1px;color:#FFF;">' + fm + "</span>";
      });
      return htm;
    },
    //================================================================================================
    toCheckAndWaitCDKill(nowTime) {
      let k = PLU.TMP.DATA_MPFZ.t + 1560000;
      let dt = Math.floor((k - nowTime) / 1000);
      if (dt == 5) {
        YFUI.writeToOut("<span style='color:#F99;'>--" + _("最后5秒,进入战斗", "最後5秒,進入戰鬥") + "!--</span>");
        //PLU.TMP.DATA_MPFZ = null
        //PLU.setBtnRed($btn,0)
        PLU.autoFight({
          targetKey: PLU.TMP.DATA_MPFZ.killId,
          fightKind: "kill",
          onFail() {
            PLU.TMP.DATA_MPFZ = null;
            PLU.setBtnRed($("#btn_bt_waitCDKill"), 0);
            setTimeout((t) => {
              PLU.autoChushi();
            }, 500);
          },
          onEnd() {
            PLU.TMP.DATA_MPFZ = null;
            PLU.setBtnRed($("#btn_bt_waitCDKill"), 0);
            setTimeout((t) => {
              PLU.autoChushi();
            }, 500);
          },
        });
      }
    },
    //================================================================================================
    setListen($btn, listenKey, stat) {
      let btnFlag = 0;
      if (stat != undefined) {
        btnFlag = PLU.setBtnRed($btn, stat);
        PLU.setCache(listenKey, stat);
        return;
      } else {
        btnFlag = PLU.setBtnRed($btn);
      }
      if (!btnFlag) {
        PLU.setCache(listenKey, 0);
        return;
      }
      if (listenKey == "listenQL") {
        //監聽青龍
        YFUI.showInput({
          title: _("监听本服青龙", "監聽本服青龍"),
          text: _(`格式:击杀类型|物品词组<br>
                            击杀类型:0杀守方(好人),1杀攻方(坏人)。<br>
                            物品词组:以英文逗号分割多个关键词<br>
                            <span style="color:red;">例如:</span><br>
                            [例1] <span style="color:blue;">0|斩龙,斩龙宝镯,碎片</span><br>
                            [例2] <span style="color:blue;">1|*</span>;
                            `,
                            `格式:擊殺類型|物品詞組<br>
                            擊殺類型:0殺守方(好人),1殺攻方(壞人)。<br>
                            物品詞組:以英文逗號分割多個關鍵詞<br>
                            <span style="color:red;">例如:</span><br>
                            [例1] <span style="color:blue;">0|斬龍,斬龍寶鐲,碎片</span><br>
                            [例2] <span style="color:blue;">1|*</span>;
                            `),
          value: PLU.getCache(listenKey + "_keys") || _("0|斩龙,开天宝棍,天罡掌套,龙皮至尊甲衣", "0|斬龍,開天寶棍,天罡掌套,龍皮至尊甲衣"),
          type: "textarea",
          onOk(val) {
            let str = $.trim(val);
            if (!str || str.indexOf("|") < 0) return PLU.setBtnRed($btn, 0);
            PLU.setCache(listenKey + "_keys", str);
            PLU.setCache(listenKey, 1);
          },
          onNo() {
            PLU.setCache(listenKey, 0);
            PLU.setBtnRed($btn, 0);
          },
        });
      } else if (listenKey == "listenTF") {
        //監聽夜魔
        YFUI.showInput({
          title: _("监听逃犯", "監聽逃犯"),
          text: _(`格式:击杀类型|逃犯词组<br>
                            击杀类型:0杀守方(逃犯),1杀攻方(捕快)。<br>
                            逃犯词组:以英文逗号分割多个关键词<br>
                            <span style="color:#F00;">【新人】以#开头则等候他人开杀再进</span><br>
                            <span style="color:#933;">例如:</span><br>
                            [例1] <span style="color:blue;">0|夜魔*段老大,#夜魔*流寇</span>
                            `,
                            `格式:擊殺類型|逃犯詞組<br>
                            擊殺類型:0殺守方(逃犯),1殺攻方(捕快)。<br>
                            逃犯詞組:以英文逗號分割多個關鍵詞<br>
                            <span style="color:#F00;">【新人】以#開頭則等候他人開殺再進</span><br>
                            <span style="color:#933;">例如:</span><br>
                            [例1] <span style="color:blue;">0|夜魔*段老大,#夜魔*流寇</span>
                            `),
          value: PLU.getCache(listenKey + "_keys") || _("0|夜魔*段老大,夜魔*二娘,#夜魔*嶽老三,#夜魔*云老四,#夜魔*流寇,#夜魔*恶棍,#夜魔*剧盗", "0|夜魔*段老大,夜魔*二娘,#夜魔*嶽老三,#夜魔*雲老四,#夜魔*流寇,#夜魔*惡棍,#夜魔*劇盜"),
          type: "textarea",
          onOk(val) {
            let str = $.trim(val);
            if (!str || str.indexOf("|") < 0) return PLU.setBtnRed($btn, 0);
            PLU.setCache(listenKey + "_keys", str);
            PLU.setCache(listenKey, 1);
            PLU.splitTFParam();
          },
          onNo() {
            PLU.setCache(listenKey, 0);
            PLU.setBtnRed($btn, 0);
          },
        });
      } else if (listenKey == "listenKFQL") {
        //監聽廣場青龍
        YFUI.showInput({
          title: _("监听广场青龙", "監聽廣場青龍"),
          text: _(`格式:击杀类型|物品词组<br>
                            击杀类型:0杀守方(好人),1杀攻方(坏人)。<br>
                            物品词组:以英文逗号分割多个关键词<br>
                            <span style="color:red;">例如:</span><br>
                            [例1] <span style="color:blue;">0|斩龙,斩龙宝镯,碎片</span><br>
                            [例2] <span style="color:blue;">1|*</span>;
                            `,
                            `格式:擊殺類型|物品詞組<br>
                            擊殺類型:0殺守方(好人),1殺攻方(壞人)。<br>
                            物品詞組:以英文逗號分割多個關鍵詞<br>
                            <span style="color:red;">例如:</span><br>
                            [例1] <span style="color:blue;">0|斬龍,斬龍寶鐲,碎片</span><br>
                            [例2] <span style="color:blue;">1|*</span>;
                            `),
          value: PLU.getCache(listenKey + "_keys") || _("1|斩龙,开天宝棍,天罡掌套,龙皮至尊甲衣", "1|斬龍,開天寶棍,天罡掌套,龍皮至尊甲衣"),
          type: "textarea",
          onOk(val) {
            let str = $.trim(val);
            if (!str || str.indexOf("|") < 0) return PLU.setBtnRed($btn, 0);
            PLU.setCache(listenKey + "_keys", str);
            PLU.setCache(listenKey, 1);
          },
          onNo() {
            PLU.setCache(listenKey, 0);
            PLU.setBtnRed($btn, 0);
          },
        });
      } else if (listenKey == "listenYX") {
        //監聽遊俠
        YFUI.showInput({
          title: _("监听游侠", "監聽遊俠"),
          text: _(`格式:游侠词组<br>
                            游侠词组:以英文逗号分割多个关键词<br>
                            <span style="color:red;">例如:</span><br>
                            [例1] <span style="color:blue;">王语嫣,厉工,金轮法王,虚夜月,云梦璃,叶孤城</span><br>
                            `,
                            `格式:遊俠詞組<br>
                            遊俠詞組:以英文逗號分割多個關鍵詞<br>
                            <span style="color:red;">例如:</span><br>
                            [例1] <span style="color:blue;">王語嫣,厲工,金輪法王,虛夜月,雲夢璃,葉孤城</span><br>
                            `),
          value: PLU.getCache(listenKey + "_keys") || [].concat(...PLU.YFD.youxiaList.map((e) => e.v)).join(","),
          type: "textarea",
          onOk(val) {
            let str = $.trim(val);
            if (!str) return PLU.setBtnRed($btn, 0);
            PLU.setCache(listenKey + "_keys", str);
            PLU.setCache(listenKey, 1);
          },
          onNo() {
            PLU.setCache(listenKey, 0);
            PLU.setBtnRed($btn, 0);
          },
        });
      } else if (listenKey == "autoTP") {
        //監聽突破
        YFUI.showInput({
          title: _("持续突破", "持續突破"),
          text: _(`请输入需要自动突破的技能,以英文逗号分割,自动突破将在当前全部突破完后才开始。<br>
                            以1|开头使用金刚舍利加速<br>
                            以2|开头使用通天丸加速<br>
                            以3|开头使用突破宝典加速<br>
                            以4|开头使用三生石加速(未开发)<br>
                            <span style="color:red;">例如:</span><br>
                            [例1] <span style="color:blue;">千影百伤棍,1|排云掌法,2|无相金刚掌,3|九天龙吟剑法,独孤九剑</span>
                            `,
                            `請輸入需要自動突破的技能,以英文逗號分割,自動突破將在當前全部突破完後才開始。<br>
                            以1|開頭使用金剛舍利加速<br>
                            以2|開頭使用通天丸加速<br>
                            以3|開頭使用突破寶典加速<br>
                            以4|開頭使用三生石加速(未開發)<br>
                            <span style="color:red;">例如:</span><br>
                            [例1] <span style="color:blue;">千影百傷棍,1|排雲掌法,2|無相金剛掌,3|九天龍吟劍法,獨孤九劍</span>
                            `),
          value: PLU.getCache(listenKey + "_keys") || _("1|千影百伤棍,1|排云掌法,1|不动明王诀", "1|千影百傷棍,1|排雲掌法,1|不動明王訣"),
          type: "textarea",
          onOk(val) {
            let str = $.trim(val);
            if (!str) return PLU.setBtnRed($btn, 0);
            PLU.setCache(listenKey + "_keys", str);
            PLU.setCache(listenKey, 1);
            PLU.getSkillsList((allSkills, tupoSkills) => {
              if (tupoSkills.length == 0) {
                PLU.toToPo();
              }
            });
          },
          onNo() {
            PLU.setCache(listenKey, 0);
            PLU.setBtnRed($btn, 0);
          },
        });
      } else if (listenKey == "autoDY") {
        //監聽突破
        YFUI.showInput({
          title: _("持续钓鱼", "持續釣魚"),
          text: _("请输入需要保留的元宝数", "請輸入需要保留的元寶數"),
          value: PLU.getCache(listenKey + "_key") || 100000,
          onOk(val) {
            let num = Number($.trim(val));
            PLU.setCache(listenKey + "_key", num);
            PLU.setCache(listenKey, 1);
            let room = g_obj_map.get("msg_room");
            if (room) room = room.get("short");
            if (room != "桃溪" || UTIL.inHome()) {
              let path = ["rank go 233;#6 s", "sw;se", "sw", "se", "s", "s"];
              // 人满是啥提示...,不知道...(那就随机选位置吧(
              PLU.execActions(path.slice(0, Math.floor(Math.random() * 6) + 1).join(";") + ";diaoyu");
            }
          },
          onNo() {
            PLU.setCache(listenKey, 0);
            PLU.setBtnRed($btn, 0);
          },
        });
      } else if (listenKey == "autoConnect") {
        YFUI.showInput({
          title: _("自动重连", "自動重連"),
          text: _(`请输入断线后自动重连的时间,重连方式为到时间自动刷新页面。<br>单位为秒,0代表不自动重连。<br>
                            <span style="color:red;">例如:</span><br>
                            [例1] <span style="color:blue;">60</span> 代表60秒后刷新页面
                            `,
                            `請輸入斷線後自動重連的時間,重連方式為到時間自動刷新頁面。<br>單位為秒,0代表不自動重連。<br>
                            <span style="color:red;">例如:</span><br>
                            [例1] <span style="color:blue;">60</span> 代表60秒後刷新頁面
                            `),
          value: PLU.getCache(listenKey + "_keys") || "0",
          //type:"textarea",
          onOk(val) {
            let v = Number(val);
            if (val == "") return PLU.setBtnRed($btn, 0);
            PLU.setCache(listenKey + "_keys", v);
            PLU.setCache(listenKey, 1);
          },
          onNo() {
            PLU.setCache(listenKey, 0);
            PLU.setBtnRed($btn, 0);
          },
        });
      } else if (listenKey == "autoSignIn") {
        //YFUI.showPop(
        YFUI.showPop({
          title: _("定时一键签到", "定時一鍵簽到"),
          text: _(`请输入自动签到的时间。<br>
						<div><span style="font-size:18px;line-height:2;">每日: </span><input id="autoSignInTime" type="time" style="font-size:20px;border-radius:5px;margin:10px 0"/></div>
						`,
            `請輸入自動簽到的時間。<br>
						<div><span style="font-size:18px;line-height:2;">每日: </span><input id="autoSignInTime" type="time" style="font-size:20px;border-radius:5px;margin:10px 0"/></div>
						`),
          onOk() {
            let v = $.trim($("#autoSignInTime").val());
            if (v == "") return PLU.setBtnRed($btn, 0);
            PLU.setCache(listenKey, 1);
          },
          onNo() {
            PLU.setCache(listenKey, 0);
            PLU.setBtnRed($btn, 0);
          },
        });
      } else if (listenKey == "autoQuitTeam") {
        //進塔離隊
        YFUI.showPop({
          title: _("进塔自动离队", "進塔自動離隊"),
          text: _(`是否进塔自动离队?<br>`, `是否進塔自動離隊?<br>`),
          onOk() {
            PLU.setCache(listenKey, 1);
          },
          onNo() {
            PLU.setCache(listenKey, 0);
            PLU.setBtnRed($btn, 0);
          },
        });
      } else {
        PLU.setCache(listenKey, 1);
        return;
      }
    },
    //================================================================================================
    splitTFParam() {
      let ltl = (PLU.getCache("listenTF_keys").split("|")[1] || "").split(",");
      PLU.TMP.lis_TF_list = [];
      PLU.TMP.lis_TF_force = [];
      ltl.map((e, i) => {
        if (e.charAt(0) == "#") {
          PLU.TMP.lis_TF_list.push(e.substring(1));
          PLU.TMP.lis_TF_force.push(0);
        } else {
          PLU.TMP.lis_TF_list.push(e);
          PLU.TMP.lis_TF_force.push(1);
        }
      });
    },
    //================================================================================================
    goQinglong(npcName, place, gb, kf) {
      let placeData = PLU.YFD.qlList.find((e) => e.n == place);
      if (kf || (UTIL.inHome() && placeData)) {
        PLU.execActions(placeData.v + ";golook_room", () => {
          let objNpc = UTIL.findRoomNpc(npcName, !Number(gb));
          if (objNpc) {
            PLU.killQinglong(objNpc.key, 0);
          } else {
            YFUI.writeToOut("<span style='color:#FFF;'>--" + _("寻找目标失败", "尋找目標失敗") + "!--</span>");
            PLU.execActions("golook_room;home");
          }
        });
      }
    },
    //================================================================================================
    killQinglong(npcId, tryNum) {
      PLU.autoFight({
        targetKey: npcId,
        fightKind: "kill",
        autoSkill: "random",
        onFail(errCode) {
          if (errCode >= 88 && tryNum < 100) {
            setTimeout(() => {
              PLU.killQinglong(npcId, tryNum + 1);
            }, 250);
            return;
          }
          YFUI.writeToOut("<span style='color:#FFF;'>--" + _("抢青龙失败", "搶青龍失敗") + "!--</span>");
          PLU.execActions("home;");
        },
        onEnd() {
          PLU.execActions("prev_combat;home;");
        },
      });
    },
    //================================================================================================
    goTaofan(npcName, npcPlace, flyLink, gb, force) {
      if (UTIL.inHome()) {
        let ctn = 0,
          gocmd = flyLink;
        PLU.YFD.cityList.forEach((e, i) => {
          if (e == npcPlace) ctn = i + 1;
        });
        if (ctn > 0) gocmd = "jh " + ctn;
        PLU.execActions(gocmd + ";golook_room;", (e) => {
          setTimeout((t) => {
            PLU.killTaofan(npcName, -Number(gb), force, 0);
          }, 1000);
        });
      }
    },
    //================================================================================================
    killTaofan(npcName, gb, force, tryCount) {
      console.debug(gb);
      let npcObj = UTIL.findRoomNpc(npcName, gb);
      if (npcObj) {
        if (force) {
          PLU.autoFight({
            targetKey: npcObj.key,
            fightKind: "kill",
            autoSkill: "random",
            onFail(errCode) {
              if (errCode == 4) {
                YFUI.writeToOut("<span style='color:#FFF;'>--" + _("已达到上限!取消逃犯监听", "已達到上限!取消逃犯監聽") + "!--</span>");
                PLU.setListen($("#btn_bt_listenTF"), "listenTF", 0);
              } else if (errCode > 1 && tryCount < 36) {
                setTimeout(() => {
                  PLU.killTaofan(npcName, gb, force, tryCount + 1);
                }, 500);
                return;
              }
              PLU.execActions("golook_room;home;");
            },
            onEnd() {
              PLU.execActions("prev_combat;home;");
            },
          });
        } else {
          PLU.waitDaLaoKill({
            targetId: npcObj.key,
            onFail(ec) { },
            onOk() {
              PLU.autoFight({
                targetKey: npcObj.key,
                fightKind: "kill",
                autoSkill: "random",
                onFail(errCode) {
                  if (errCode == 4) {
                    YFUI.writeToOut("<span style='color:#FFF;'>--" + _("已达到上限!取消逃犯监听", "已達到上限!取消逃犯監聽") + "--</span>");
                    PLU.setListen($("#btn_bt_listenTF"), "listenTF", 0);
                  } else YFUI.writeToOut("<span style='color:#FFF;'>--'ERR=" + errCode + "--</span>");
                  PLU.execActions("golook_room;home;");
                },
                onEnd() {
                  PLU.execActions("prev_combat;home;");
                },
              });
            },
          });
        }
      } else {
        YFUI.writeToOut("<span style='color:#FFF;'>--找不到NPC!--</span>");
        if (tryCount < 4) {
          return setTimeout(() => {
            PLU.killTaofan(npcName, gb, force, tryCount + 1);
          }, 500);
        }
        PLU.execActions("golook_room;home;");
      }
    },
    //================================================================================================

    waitDaLaoKill({ targetId, onOk, onFail }) {
      let tryTimes = 0;
      UTIL.addSysListener("lookNpcWait", function (b, type, subtype, msg) {
        if (type == "notice" && subtype == "notify_fail" && msg.indexOf(_("没有这个人", "沒有這個人")) >= 0) {
          YFUI.writeToOut("<span style='color:#FFF;'>--" + _("目标已丢失" , "目標已丟失") + "!--</span>");
          UTIL.delSysListener("lookNpcWait");
          return onFail && onFail(1);
        }
        if (type == "look_npc") {
          let desc = UTIL.filterMsg(b.get("long"));
          let lookInfo = desc.match(_(/[他|她]正与 (\S*)([\S\s]*) 激烈争斗中/, /[他|她]正與 (\S*)([\S\s]*) 激烈爭鬥中/));
          if (lookInfo && lookInfo.length > 2 && $.trim(lookInfo[2]) != "") {
            YFUI.writeToOut("<span style='color:#9F9;'>--" + _("目标已被大佬攻击,可以跟进", "目標已被大佬攻擊,可以跟進") + "--</span>");
            UTIL.delSysListener("lookNpcWait");
            return onOk && onOk();
          }
          tryTimes++;
          if (tryTimes > 30) {
            UTIL.delSysListener("lookNpcWait");
            return onFail && onFail(30);
          } else {
            setTimeout(() => {
              clickButton("look_npc " + targetId);
            }, 500);
          }
        }
        //如提前進入戰鬥可能是因為殺氣, 逃跑後繼續
        if (type == "vs" && subtype == "vs_info" && b.get("vs2_pos1") != targetId) {
          PLU.autoEscape({
            onEnd() {
              setTimeout(() => {
                clickButton("look_npc " + targetId);
              }, 500);
            },
          });
        }
      });
      clickButton("look_npc " + targetId);
    },

    //================================================================================================
    fixJhName(name) {
      switch (name) {
        case _("白驼山", "白駝山"):
          return _("白驮山", "白馱山");
        case "黑木崖":
          return "魔教";
        case _("光明顶", "光明頂"):
          return "明教";
        case _("铁血大旗门", "鐵血大旗門"):
          return _("大旗门", "大旗門");
        case _("梅庄", "梅莊"):
          return _("寒梅庄", "寒梅莊");
      }
      return name;
    },
    //================================================================================================
    goFindYouxia(params) {
      //{paths,idx,objectNPC}
      if (params.idx >= params.paths.length) {
        setTimeout(() => {
          PLU.execActions("home");
        }, 500);
        YFUI.writeToOut("<span style='color:#FFF;'>--" + _("找不到游侠!...已搜索完地图", "找不到遊俠!...已搜索完地圖") + "--</span>");
        return;
      }
      let acs = [params.paths[params.idx]];
      PLU.actions({
        paths: acs,
        idx: 0,
        onPathsEnd() {
          setTimeout(() => {
            let npcObj = UTIL.findRoomNpc(params.objectNPC, false, true);
            if (npcObj) {
              YFUI.writeToOut("<span style='color:#FFF;'>--" + _("游侠已找到", "遊俠已找到") + "--</span>");
              PLU.killYouXia(npcObj.key, 0);
            } else {
              params.idx++;
              PLU.goFindYouxia(params);
            }
          }, 300);
        },
        onPathsFail() {
          setTimeout(() => {
            PLU.execActions("home");
          }, 500);
          YFUI.writeToOut("<span style='color:#FFF;'>--" + _("找不到游侠!...路径中断", "找不到遊俠!...路徑中斷") + "--</span>");
          return;
        },
      });
    },
    //================================================================================================
    killYouXia(npcId, tryNum) {
      PLU.autoFight({
        targetKey: npcId,
        fightKind: "kill",
        autoSkill: "multi",
        onFail(errCode) {
          if (String(errCode).indexOf("delay_") >= 0) {
            let mc = String(errCode).match(/delay_(\d+)/);
            if (mc) {
              let wtime = 500 + 1000 * Number(mc[1]);
              PLU.execActions("follow_play " + npcId + ";");
              YFUI.writeToOut("<span style='color:#FFF;'>▶" + _("开始尝试做游侠跟班", "開始嘗試做遊俠跟班") + "!!</span>");
              setTimeout(() => {
                PLU.execActions("follow_play none", () => {
                  YFUI.writeToOut("<span style='color:#FFF;'>◼" + _("停止做游侠跟班!!准备开杀", "停止做遊俠跟班!!準備開殺") + "!!</span>");
                  PLU.killYouXia(npcId, tryNum + 1);
                });
              }, wtime);
              return;
            }
          } else if (errCode >= 88 && tryNum < 44) {
            setTimeout(() => {
              PLU.killYouXia(npcId, tryNum + 1);
            }, 1000);
            return;
          } else if (errCode == 1) {
            YFUI.writeToOut("<span style='color:#F99;'>--" + _("现场找不到游侠了", "現場找不到遊俠了") + "!--</span>");
          } else {
            YFUI.writeToOut("<span style='color:#F99;'>--" + _("攻击游侠失败", "攻擊遊俠失敗") + "!--</span>");
          }
          PLU.execActions("home;");
        },
        onEnd() {
          PLU.execActions("prev_combat;home;");
        },
      });
    },
    //================================================================================================
    getSkillsList(callback) {
      UTIL.addSysListener("getSkillsList", function (b, type, subtype, msg) {
        if (type != "skills" && subtype != "list") return;
        UTIL.delSysListener("getSkillsList");
        clickButton("prev");
        let all = [],
          tupo = [];
        all = PLU.parseSkills(b);
        all.forEach((skill) => {
          if (skill.state >= 4) {
            tupo.push(skill);
          }
        });
        callback(all, tupo);
      });
      clickButton("skills");
    },
    //================================================================================================
    parseSkills(b) {
      let allSkills = [];
      for (var i = b.elements.length - 1; i > -1; i--) {
        if (b.elements[i].key && b.elements[i].key.match(/skill(\d+)/)) {
          var attr = b.elements[i].value.split(",");
          var skill = {
            key: attr[0],
            name: $.trim(UTIL.filterMsg(attr[1])),
            level: Number(attr[2]),
            kind: attr[4],
            prepare: Number(attr[5]),
            state: Number(attr[6]),
            from: attr[7],
          };
          allSkills.push(skill);
        }
      }
      allSkills = allSkills.sort((a, b) => {
        if (a.kind == "known") return -1;
        else if (b.kind != "known" && a.from == _("基础武功", "基礎武功")) return -1;
        else if (b.kind != "known" && b.from != _("基础武功", "基礎武功") && a.kind == "force") return -1;
        else return 1;
      });
      return allSkills;
    },
    //================================================================================================
    toToPo() {
      setTimeout(function () {
        if (UTIL.inHome()) {
          PLU.getSkillsList((allSkills, tupoSkills) => {
            if (tupoSkills.length > 0) {
              if (PLU.STO.outSkillList) clearTimeout(PLU.STO.outSkillList);
              PLU.STO.outSkillList = setTimeout(() => {
                PLU.STO.outSkillList = null;
                if (!!$("#out_top").height() && $("#out_top .outtitle").text() == "我的技能") clickButton("home");
              }, 200);
              return;
            }
            let tpArr = PLU.getCache("autoTP_keys").split(",");
            let tpList = [];
            tpArr.forEach((s) => {
              let sk = {};
              let cs = s.match(/((\d)\|)?(.*)/);
              if (cs) {
                sk.name = cs[3];
                sk.sp = Number(cs[2]);
              } else {
                sk.name = s;
                sk.sp = 0;
              }
              let skobj = allSkills.find((e) => e.name.match(sk.name));
              if (skobj) tpList.push(Object.assign({}, skobj, sk));
            });
            PLU.TMP.stopToPo = false;
            PLU.toPo(tpList, 0);
          });
        }
      }, 500);
    },
    //================================================================================================
    toPo(tpList, skIdx) {
      if (skIdx < tpList.length && !PLU.TMP.stopToPo) {
        let acts = "enable " + tpList[skIdx].key + ";tupo go," + tpList[skIdx].key + ";";
        if (tpList[skIdx].sp == 1) acts += "tupo_speedup4_1 " + tpList[skIdx].key + " go;";
        else if (tpList[skIdx].sp == 2) acts += "tupo_speedup3_1 " + tpList[skIdx].key + " go;";
        else if (tpList[skIdx].sp == 3) acts += "tupo_up " + tpList[skIdx].key + " go;";
        else if (tpList[skIdx].sp == 4) acts += "items info obj_sanshengshi;event_1_66830905 " + tpList[skIdx].key + " go;";

        PLU.execActions(acts, () => {
          setTimeout(() => {
            if (PLU.STO.outSkillList) clearTimeout(PLU.STO.outSkillList);
            PLU.STO.outSkillList = null;
            PLU.toPo(tpList, skIdx + 1);
          }, 300);
        });
      } else {
        YFUI.writeToOut("<span style='color:yellow;'> ==" + _("突破完毕", "突破完畢") + "!== </span>");
        clickButton("home");
      }
    },
    //================================================================================================
    toBangFour(n) {
      UTIL.log({
        msg: _(" 进入帮四(", " 進入幫四(") + n + ") ",
        type: "TIPS",
        time: new Date().getTime(),
      });
      PLU.STO.bangFourTo && clearTimeout(PLU.STO.bangFourTo);
      PLU.STO.bangFourTo = setTimeout(function () {
        clickButton("home");
      }, 30 * 60 * 1000);
      clickButton("clan fb enter shiyueweiqiang-" + n, 0);
    },
    toBangSix() {
      UTIL.log({ msg: _(" 进入帮六 ", " 進入幫六 "), type: "TIPS", time: new Date().getTime() });
      PLU.STO.bangSixTo && clearTimeout(PLU.STO.bangSixTo);
      PLU.STO.bangSixTo = setTimeout(function () {
        clickButton("home");
      }, 30 * 60 * 1000);
      clickButton("clan fb enter manhuanqishenzhai", 0);
    },
    //================================================================================================
    inBangFiveEvent() {
      var moving = false;
      PLU.TMP.listenBangFive = true;
      UTIL.addSysListener("listenBangFive", function (b, type, subtype, msg) {
        if (!moving && type == "jh" && (subtype == "dest_npc" || subtype == "info")) {
          moving = true;
          let roomName = UTIL.filterMsg(g_obj_map.get("msg_room").get("short"));
          if (roomName.match(_(/蒙古高原|成吉思汗的金帐/, /蒙古高原|成吉思汗的金帳/)) && !UTIL.roomHasNpc()) {
            PLU.execActions(";;n;", () => {
              moving = false;
            });
          } else {
            moving = false;
          }
        }
        /*
        type:main_msg
        msg:你獲得:\x1B[34m三\x1B[2;37;0m\x1B[35m生\x1B[2;37;0m\x1B[31m石
         */

        if (type == "home" && subtype == "index") {
          UTIL.delSysListener("listenBangFive");
          YFUI.writeToOut("<span style='color:white;'> ==" + _("帮五完毕", "幫五完畢") + "!== </span>");
          PLU.execActions("golook_room;home");
        }
      });
    },
    intervene($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        UTIL.delSysListener("intervene");
        UTIL.delSysListener("score");
        return;
      }
      let Fight = function (b, num) {
        PLU.autoFight({
          targetKey: b.get("vs2_pos" + num),
          fightKind: "fight",
          onEnd() {
            UTIL.delSysListener("intervene");
            UTIL.delSysListener("score");
            PLU.setBtnRed($btn);
          },
          onFail() {
            PLU.autoFight({
              targetKey: b.get("vs2_pos" + num),
              onEnd() {
                UTIL.delSysListener("intervene");
                UTIL.delSysListener("score");
                PLU.setBtnRed($btn);
              },
              onFail() {
                if (num <= 7) {
                  Fight(++num);
                } else {
                  UTIL.delSysListener("intervene");
                  UTIL.delSysListener("score");
                }
              },
            });
          },
        });
      };
      UTIL.addSysListener("intervene", (b, type, subtype, msg) => {
        if (type == "vs" && subtype == "vs_info") {
          UTIL.delSysListener("intervene");
          UTIL.delSysListener("score");
          Fight(b, 1);
        }
      });
      UTIL.addSysListener("score", (b, type, subtype, msg) => {
        if (type == "score" && subtype == "user") {
          if (b.get("long").indexOf(_("激烈争斗中...", "激烈爭鬥中...")) == -1) {
            PLU.execActions("score " + b.get("id"));
            return;
          }
          UTIL.delSysListener("score");
          PLU.execActions("watch_vs " + b.get("id"));
        }
      });
      YFUI.showPop({
        title: _("杀隐藏怪", "殺隱藏怪"),
        text: _("自动观战,自动加入战斗<br>确认后,点开要跟的玩家页面", "自動觀戰,自動加入戰鬥<br>確認後,點開要跟的玩家頁面"),
        onNo() {
          UTIL.delSysListener("intervene");
          UTIL.delSysListener("score");
          PLU.setBtnRed($btn);
        },
      });
    },
    // 字符串相似度算法
    getSimilarity(str1, str2) {
      let sameNum = 0;
      for (let i = 0; i < str1.length; i++)
        for (let j = 0; j < str2.length; j++)
          if (str1[i] === str2[j]) {
            sameNum++;
            break;
          }
      let length = Math.max(str1.length, str2.length);
      return (sameNum / length) * 100 || 0;
    },
    npcDataUpdate() {
      var wayList = [...new Set(PLU.YFD.mapsLib.Npc.map((e) => e.way))];
      if (PLU.YFD.mapsLib.Npc_New[PLU.YFD.mapsLib.Npc_New.length - 1]) var i = wayList.indexOf(PLU.YFD.mapsLib.Npc_New[PLU.YFD.mapsLib.Npc_New.length - 1].way);
      else var i = 0;
      PLU.UTIL.addSysListener("look_npc", (b, type, subtype, msg) => {
        if (type != "look_npc") return;
        if (b.get("id").indexOf("bad_target_") == 0) return;
        if (b.get("id").indexOf("hero_") == 0) return;
        if (b.get("id").indexOf("eren_") == 0) return;
        if (b.get("id").indexOf("bukuai") == 0) return;
        if (PLU.YFD.qixiaList.includes(ansi_up.ansi_to_text(b.get("name")))) return;
        let roomInfo = g_obj_map.get("msg_room");
        let jh = PLU.YFD.cityId[roomInfo.get("map_id")] ?? roomInfo.get("map_id");
        let curName = UTIL.filterMsg(roomInfo.get("short") || "");
        PLU.YFD.mapsLib.Npc_New.push({
          jh: jh,
          loc: curName,
          name_new: ansi_up.ansi_to_text(b.get("name")),
          id: b.get("id") || "",
          desc: ansi_up.ansi_to_text(b.get("long")?.split("\n")[1]),
          way: wayList[i],
        });
      });

      func = () => {
        PLU.execActions(wayList[i], () => {
          for (var npc of PLU.UTIL.getRoomAllNpc()) PLU.execActions("look_npc " + npc.key);
          setTimeout(() => {
            i++;
            func();
          }, 1500);
        });
      };
      func();
    },
    //================================================================================================
    checkUseSkills() {
      let curTime = new Date().getTime();
      if (!PLU.battleData.performTime || curTime - PLU.battleData.performTime >= 400) {
        PLU.battleData.performTime = curTime;
        if (!PLU.battleData.mySide) {
          let vsInfo = g_obj_map.get("msg_vs_info");
          for (let i = vsInfo.elements.length - 1; i > -1; i--) {
            let val = vsInfo.elements[i].value + "";
            if (!val || val.indexOf(PLU.accId) < 0) continue;
            PLU.battleData.myPos = vsInfo.elements[i].key.charAt(7);
            PLU.battleData.mySide = vsInfo.elements[i].key.substring(0, 3);
            break;
          }
        }
        if (PLU.getCache(_("pSetting_快速连招", "pSetting_快速連招")) == "true") {
          if (PLU.getCache("autoPerform") >= 1) {
            PLU.AutoCombat();
          }
        } else {
          if (PLU.battleData.mySide) {
            if (PLU.getCache("autoCure") == 1) {
              PLU.checkAutoCure();
            }
            if (PLU.getCache("autoPerform") >= 1) {
              PLU.checkAutoPerform();
            }
          }
        }
      }
    },
    //================================================================================================
    setAutoCure($btn, listenKey, stat) {
      if (listenKey == "autoCure") {
        //自動加血藍
        YFUI.showInput({
          title: _("自动加血加蓝", "自動加血加藍"),
          text: _(`格式:血百分比|加血技能,蓝百分比|加蓝技能,以英文逗号分割,每样只能设置一个技能。<br>
                            <span style="color:red;">例如:</span><br>
                            [例1] <span style="color:blue;">50|道种心魔经,10|不动明王诀</span><br> 血低于50%自动加血,蓝低于10%自动加蓝<br>
                            [例2] <span style="color:blue;">30|紫血大法</span><br> 血低于30%自动加血技能,不自动加蓝<br>
                            `,
                            `格式:血百分比|加血技能,藍百分比|加藍技能,以英文逗號分割,每樣只能設置一個技能。<br>
                            <span style="color:red;">例如:</span><br>
                            [例1] <span style="color:blue;">50|道種心魔經,10|不動明王訣</span><br> 血低於50%自動加血,藍低於10%自動加藍<br>
                            [例2] <span style="color:blue;">30|紫血大法</span><br> 血低於30%自動加血技能,不自動加藍<br>
                            `),
          value: PLU.getCache(listenKey + "_keys") || _("10|道种心魔经,10|不动明王诀", "10|道種心魔經,10|不動明王訣"),
          onOk(val) {
            let str = $.trim(val);
            PLU.setCache(listenKey + "_keys", str);
            PLU.splitCureSkills();
          },
          onNo() { },
        });
      }
    },
    toggleAutoCure($btn, listenKey, stat) {
      let btnFlag = 0;
      if (stat != undefined) {
        btnFlag = PLU.setBtnRed($btn, stat);
        PLU.setCache(listenKey, stat);
      } else {
        btnFlag = PLU.setBtnRed($btn);
      }
      if (!btnFlag) {
        return PLU.setCache(listenKey, 0);
      } else {
        PLU.setCache(listenKey, 1);
        setTimeout(() => {
          YFUI.writeToOut("<span style='color:yellow;'>" + _("自动血蓝: ", "自動血藍: ") + PLU.getCache(listenKey + "_keys") + " </span>");
        }, 100);
      }
    },
    //================================================================================================
    splitCureSkills() {
      let kf = (PLU.getCache("autoCure_keys") || "").split(",");
      PLU.TMP.autoCure_percent = "";
      PLU.TMP.autoCure_skills = "";
      PLU.TMP.autoCure_force_percent = "";
      PLU.TMP.autoCure_force_skills = "";
      if (kf.length > 0) {
        let acp = kf[0].split("|");
        PLU.TMP.autoCure_percent = Number(acp[0]) || 50;
        PLU.TMP.autoCure_skills = acp[1];
        if (kf.length > 1) {
          let acf = kf[1].split("|");
          PLU.TMP.autoCure_force_percent = Number(acf[0]) || 10;
          PLU.TMP.autoCure_force_skills = acf[1];
        }
      }
    },
    //================================================================================================
    checkAutoCure() {
      let vsInfo = g_obj_map.get("msg_vs_info");
      let userInfo = g_obj_map.get("msg_attrs");
      let keePercent = ((100 * Number(vsInfo.get(PLU.battleData.mySide + "_kee" + PLU.battleData.myPos))) / Number(userInfo.get("max_kee"))).toFixed(2);
      let forcePercent = ((100 * Number(vsInfo.get(PLU.battleData.mySide + "_force" + PLU.battleData.myPos))) / Number(userInfo.get("max_force"))).toFixed(2);
      if (!PLU.TMP.autoCure_percent) {
        PLU.splitCureSkills();
      }
      if (PLU.TMP.autoCure_force_skills && Number(forcePercent) < PLU.TMP.autoCure_force_percent) {
        PLU.autoCureByKills(PLU.TMP.autoCure_force_skills, forcePercent);
      } else if (PLU.TMP.autoCure_skills && Number(keePercent) < PLU.TMP.autoCure_percent && PLU.battleData.cureTimes < 3) {
        PLU.autoCureByKills(PLU.TMP.autoCure_skills, forcePercent);
      }
    },
    //================================================================================================
    autoCureByKills(skill, forcePercent) {
      if (PLU.battleData && PLU.battleData.xdz > 2) {
        let rg = new RegExp(skill);
        let useSkill = PLU.selectSkills(rg);
        if (useSkill) {
          clickButton(useSkill.key, 0);
          if (Number(forcePercent) > 1) PLU.battleData.cureTimes++;
        }
      }
    },
    //================================================================================================
    setAutoPerform($btn, listenKey, stat) {
      if (listenKey == "autoPerform") {
        //自動技能
        let skillsList = [];
        try {
          skillsList = JSON.parse(PLU.getCache(listenKey + "_keysList"));
        } catch (error) {
          skillsList = [_("6|千影百伤棍,九天龙吟剑法", "", "", "", "3|九天龙吟剑法", "6|千影百傷棍,九天龍吟劍法", "", "", "", "3|九天龍吟劍法")];
        }
        YFUI.showInput({
          title: _("自动技能", "自動技能"),
          text: _(`格式:触发气值|技能词组,以英文逗号分割多个关键词。<br>
                            <span style="color:red;">例如:</span><br>
                            [例1] <span style="color:blue;">9|千影百伤棍,九天龙吟剑法,排云掌法</span><br> 气大于等于9时自动使用技能<br>
                            `,
                            `格式:觸發氣值|技能詞組,以英文逗號分割多個關鍵詞。<br>
                            <span style="color:red;">例如:</span><br>
                            [例1] <span style="color:blue;">9|千影百傷棍,九天龍吟劍法,排雲掌法</span><br> 氣大於等於9時自動使用技能<br>
                            `),
          value: skillsList,
          inputs: ["技能1", "技能2", "技能3", "技能4"],
          onOk(val) {
            PLU.setCache(listenKey + "_keysList", JSON.stringify(val));
            if (PLU.getCache(listenKey)) {
              PLU.setPerformSkill(PLU.getCache(listenKey));
            }
          },
          onNo() { },
        });
      }
    },
    toggleAutoPerform($btn, listenKey, stat) {
      let curIdx = Number(PLU.getCache(listenKey));
      if (stat != undefined) {
        if (stat > 0) {
          PLU.setBtnRed($btn, 1);
          PLU.setPerformSkill(stat);
        } else PLU.setBtnRed($btn, 0);
        $btn.text([_("连招", "連招"), "技一", "技二", "技三", "技四"][stat]);
        PLU.setCache(listenKey, stat);
        if (stat > 0) PLU.TMP.lastAutoPerformSet = stat;
      } else {
        let nowTime = Date.now();
        if (curIdx == 0 && nowTime - (PLU.TMP.lastClickAutoPerform || 0) < 350) {
          curIdx = PLU.TMP.lastAutoPerformSet || 1;
          curIdx++;
          if (curIdx > 4) curIdx = 1;
        } else {
          curIdx = curIdx == 0 ? PLU.TMP.lastAutoPerformSet || 1 : 0;
        }
        PLU.TMP.lastClickAutoPerform = nowTime;
        if (curIdx > 0) PLU.TMP.lastAutoPerformSet = curIdx;
        PLU.setCache(listenKey, curIdx);
        if (curIdx == 0) {
          PLU.setBtnRed($btn, 0);
          $btn.text(_("连招", "連招"));
        } else {
          PLU.setBtnRed($btn, 1);
          $btn.text([_("连招", "連招"), "技一", "技二", "技三", "技四"][curIdx]);
          PLU.setPerformSkill(curIdx);
        }
      }
    },
    setPerformSkill(idx) {
      let skillsList = [];
      idx = idx - 1;
      try {
        skillsList = JSON.parse(PLU.getCache("autoPerform_keysList"));
      } catch (error) {
        skillsList = [];
      }
      let str = skillsList[idx] || "";
      let aps = str.split("|");
      if (aps && aps.length == 2) {
        PLU.TMP.autoPerform_xdz = Number(aps[0]);
        PLU.TMP.autoPerform_skills = aps[1].split(",");
      } else {
        PLU.TMP.autoPerform_xdz = 0;
        PLU.TMP.autoPerform_skills = [];
      }
      setTimeout(() => {
        let setCh = ["一", "二", "三", "四"][idx];
        YFUI.writeToOut(
          "<span style='color:yellow;'>" + _("自动技能[", "自動技能[") + setCh + "] : " + str + _(" </span><br><span style='color:white;'>** 双击自动技能按钮切换技能设置 **</span>", " </span><br><span style='color:white;'>** 雙擊自動技能按鈕切換技能設置 **</span>"),
        );
      }, 100);
    },
    //================================================================================================
    AutoCombat() {
      // if(PLU.battleData.autoSkill) return;
      if (!PLU.TMP.autoPerform_xdz) return;
      // if(!PLU.TMP.autoPerform_xdz){
      //     let aps = PLU.getCache("autoPerform_keys").split('|')
      //     PLU.TMP.autoPerform_xdz = Number(aps[0])
      //     PLU.TMP.autoPerform_skills = aps[1].split(',')
      //}
      let skillIdA = ['1', '2', '3', '4', '5', '6', '7'];
      let skillArr = PLU.TMP.autoPerform_skills;
      // 回血
      if (PLU.getCache("autoCure") == 1) {
        let vsInfo = g_obj_map.get("msg_vs_info");
        let userInfo = g_obj_map.get("msg_attrs");
        let keePercent = ((100 * Number(vsInfo.get(PLU.battleData.mySide + "_kee" + PLU.battleData.myPos))) / Number(userInfo.get("max_kee"))).toFixed(2);
        let forcePercent = ((100 * Number(vsInfo.get(PLU.battleData.mySide + "_force" + PLU.battleData.myPos))) / Number(userInfo.get("max_force"))).toFixed(2);
        if (!PLU.TMP.autoCure_percent) {
          PLU.splitCureSkills();
        }
        if (PLU.TMP.autoCure_force_skills && Number(forcePercent) < PLU.TMP.autoCure_force_percent) {
          PLU.autoCureByKills(PLU.TMP.autoCure_force_skills, forcePercent);
        } else if (PLU.TMP.autoCure_skills && Number(keePercent) < PLU.TMP.autoCure_percent && PLU.battleData.cureTimes < 3) {
          PLU.autoCureByKills(PLU.TMP.autoCure_skills, forcePercent);
        }
      }
      PLU.battleData.xdz = gSocketMsg.get_xdz();
      if (PLU.battleData.xdz >= PLU.TMP.autoPerform_xdz) {
        $.each(skillArr, function (index, val) {
          var skillName = val;

          for (var i = 0; i < skillIdA.length; i++) {
            var btnNum = skillIdA[i];
            var btn = $('#skill_' + btnNum);
            var btnName = btn.text();

            if (btnName.indexOf(skillName) > -1 ) {
              btn.find('button').trigger('click');
              break;
            }
          }
        });
      }
      
      

      // if (PLU.battleData.xdz >= PLU.TMP.autoPerform_xdz) {
        // if (PLU.TMP.autoPerform_skills && PLU.TMP.autoPerform_skills.length > 0) {
          // PLU.TMP.autoPerform_skills.forEach((skn, idx) => {
            // let useSkill = PLU.selectSkills(skn);
            // if (useSkill) {
              // setTimeout((e) => {
                // clickButton(useSkill.key, 0);
              // }, idx * 100);
            // }
          // });
        // }
      // }
    },
    //================================================================================================
    checkAutoPerform() {
      // if(PLU.battleData.autoSkill) return;
      if (!PLU.TMP.autoPerform_xdz) return;
      // if(!PLU.TMP.autoPerform_xdz){
      //     let aps = PLU.getCache("autoPerform_keys").split('|')
      //     PLU.TMP.autoPerform_xdz = Number(aps[0])
      //     PLU.TMP.autoPerform_skills = aps[1].split(',')
      //}
      if (PLU.battleData.xdz >= PLU.TMP.autoPerform_xdz) {
        if (PLU.TMP.autoPerform_skills && PLU.TMP.autoPerform_skills.length > 0) {
          PLU.TMP.autoPerform_skills.forEach((skn, idx) => {
            let useSkill = PLU.selectSkills(skn);
            if (useSkill) {
              setTimeout((e) => {
                clickButton(useSkill.key, 0);
              }, idx * 100);
            }
          });
        }
      }
    },
    //================================================================================================
    setFightSets($btn, listenKey, stat) {
      if (listenKey == "followKill") {
        //開跟殺
        YFUI.showInput({
          title: _("开跟杀", "開跟殺"),
          text: _(`格式:跟杀的人名词组,以英文逗号分割多个关键词,人名前带*为反跟杀。<br>
                            <span style="color:red;">例如:</span><br>
                            [例1] <span style="color:blue;">步惊鸿,*醉汉</span><br> 步惊鸿攻击(杀or比试)谁我攻击谁;谁攻击醉汉我攻击谁<br>
                            `,
                            `格式:跟殺的人名詞組,以英文逗號分割多個關鍵詞,人名前帶*為反跟殺。<br>
                            <span style="color:red;">例如:</span><br>
                            [例1] <span style="color:blue;">步驚鴻,*醉漢</span><br> 步驚鴻攻擊(殺or比試)誰我攻擊誰;誰攻擊醉漢我攻擊誰<br>
                            `),
          value: PLU.getCache(listenKey + "_keys") || _("☆,★,人", "風,豹,劍,門,豆,七,星,虎,影,貓"), // 顺序怎么随口怎么来 XD
          //type:"textarea",
          onOk(val) {
            let str = $.trim(val);
            PLU.setCache(listenKey + "_keys", str);
            PLU.splitFollowKillKeys();
          },
          onNo() { },
        });
      }
    },
    toggleFollowKill($btn, listenKey, stat) {
      let btnFlag = 0;
      if (stat != undefined) {
        btnFlag = PLU.setBtnRed($btn, stat);
        PLU.setCache(listenKey, stat);
      } else {
        btnFlag = PLU.setBtnRed($btn);
      }
      if (!btnFlag) {
        return PLU.setCache(listenKey, 0);
      } else {
        PLU.splitFollowKillKeys();
        PLU.setCache(listenKey, 1);
        setTimeout(() => {
          YFUI.writeToOut("<span style='color:yellow;'>" + _("自动跟杀: ", "自動跟殺: ") + PLU.getCache(listenKey + "_keys") + " </span>");
        }, 100);
      }
    },
    //================================================================================================
    splitFollowKillKeys() {
      let keystr = PLU.getCache("followKill_keys") || "";
      let keys = keystr.split(/[,,]/);
      PLU.FLK = {
        followList: [],
        defendList: [],
      };
      keys.forEach((e) => {
        if (!e) return;
        if (e.charAt(0) == "*") {
          PLU.FLK.defendList.push(e.substring(1));
        } else {
          PLU.FLK.followList.push(e);
        }
      });
    },
    //================================================================================================
    toCheckFollowKill(attacker, defender, fightType, msgText) {
      if (!PLU.FLK) PLU.splitFollowKillKeys();
      for (let i = 0; i < PLU.FLK.followList.length; i++) {
        let flname = PLU.FLK.followList[i];
        if (attacker.match(flname)) {
          PLU.autoFight({
            targetName: defender,
            fightKind: fightType,
            onFail() { },
            onEnd() { },
          });
          return;
        }
      }
      for (let i = 0; i < PLU.FLK.defendList.length; i++) {
        let dfname = PLU.FLK.defendList[i];
        if (defender.match(dfname)) {
          PLU.autoFight({
            targetName: attacker,
            fightKind: fightType,
            onFail() { },
            onEnd() { },
          });
          return;
        }
      }
    },
    //================================================================================================
    startSync($btn) {
      PLU.getTeamInfo((t) => {
        if (!t) PLU.setBtnRed($btn);
        else {
          YFUI.writeToOut("<span style='color:yellow;'>===" + _("队伍同步开始", "隊伍同步開始") + (t.is_leader ? ", <b style='color:#F00;'>" + _("我是队长", "我是隊長") + "</b>" : "") + " ===</span>");
          PLU.allowedcmds = ["go", "fb", "yell", "rank", "escape", "jh", "ask", "npc_datan", "give", "room_sousuo", "change_server"];
          if (t.is_leader) {
            PLU.TMP.leaderTeamSync = true;
          } else {
            PLU.listenTeamSync(t.leaderId);
          }
        }
      });
    },
    toggleTeamSync($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (btnFlag) {
        PLU.TMP.teamSync = true;
        if (PLU.TMP.firstSync) PLU.startSync($btn);
        else {
          YFUI.showPop({
            title: _("队伍同步", "隊伍同步"),
            text: _("<b style='color:#F00;'>入队后再打开队伍同步!!</b><br>队长发布指令, 队员监听同步指令!", "<b style='color:#F00;'>入隊後再打開隊伍同步!!</b><br>隊長發布指令, 隊員監聽同步指令!"),
            okText: "同步",
            onOk(e) {
              PLU.TMP.firstSync = 1;
              PLU.startSync($btn);
            },
            onNo() {
              PLU.setBtnRed($btn);
            },
            onX() {
              PLU.setBtnRed($btn);
            },
          });
        }
      } else {
        PLU.TMP.teamSync = false;
        PLU.TMP.leaderTeamSync = false;
        UTIL.delSysListener("syncTeamChannel");
      }
    },
    //================================================================================================
    commandTeam(args) {
      if (!PLU.TMP.leaderTeamSync) return;
      if (!g_gmain.is_fighting && !args[0].match(/team chat|send_chat|attr|watch\_vs/)) {
        var cmdStr = args[0].replace(/\s/g, "$");
        clickButton("team chat synCmd=" + cmdStr);
        clickButton("send_chat", 0);
      }
    },
    //================================================================================================
    listenTeamSync(leaderId) {
      UTIL.addSysListener("syncTeamChannel", function (b, type, subtype, msg) {
        if (type != "main_msg" || !msg.match(_(/\003href;0;team\003【队伍】\0030\003/, /\003href;0;team\003【隊伍】\0030\003/))) return;
        var l = msg.match(_(/\003href;0;team\003【队伍】.*href;0;score ([\w\(\)]+)\003(.*)\0030\003:(.*)/, /\003href;0;team\003【隊伍】.*href;0;score ([\w\(\)]+)\003(.*)\0030\003:(.*)/));
        if (l && l[1] == leaderId) {
          var synCmd = l[3].replace("synCmd=", "").replace("。", ".").replace(/\$/g, " ");
          clickButton(synCmd);
        }
      });
    },
    //================================================================================================
    getTeamInfo(callback) {
      UTIL.addSysListener("checkTeam", (b, type, subtype, msg) => {
        if (type != "team" && subtype != "info") return;
        UTIL.delSysListener("checkTeam");
        if (b.get("team_id")) {
          if (b.get("is_member_of") == "1") {
            callback &&
              callback({
                is_leader: parseInt(b.get("is_leader")),
                leaderId: b.get("member1").split(",")[0],
              });
          } else {
            callback && callback(0);
          }
        } else {
          callback && callback(0);
        }
        clickButton("prev");
      });
      clickButton("team");
    },
    //================================================================================================
    setSkillGroup(idx) {
      if (g_gmain.is_fighting) return;
      $(".menu").hide();
      let lsgTimeOut = setTimeout(() => {
        UTIL.delSysListener("loadSkillGroup");
      }, 5000);
      UTIL.addSysListener("loadSkillGroup", (b, type, subtype, msg) => {
        if (type != "enable" && subtype !== "list") return;
        UTIL.delSysListener("loadSkillGroup");
        clearTimeout(lsgTimeOut);
        clickButton("prev");
      });
      clickButton("enable mapped_skills restore go " + idx);
    },
    //================================================================================================
    setWearEquip(idx) {
      if (g_gmain.is_fighting) return;
      $(".menu").hide();
      let equipKey = "equip_" + idx + "_keys";
      YFUI.showInput({
        title: _("装备组-", "裝備組-") + idx,
        text: _(`格式:武器装备词组,以英文逗号分割多个关键词,<br>
						<span style="color:#D60;">武器名前必须带上*,入脉武器名前带**。<br>
						卸下武器名前带上#。</span><br>
                        <span style="color:red;">例如:</span><br>
                        [例1] <span style="color:blue;">剑神之铠,剑神之带,剑神之盔,剑神之镯,剑神之戒,剑神之靴,剑神之链</span><br>
                        [例2] <span style="color:blue;">隐居贤者之铠,隐居贤者之带,隐居贤者之盔,隐居贤者之镯,隐居贤者之戒,隐居贤者之靴,隐居贤者之链</span><br>
                        `,
                        `格式:武器裝備詞組,以英文逗號分割多個關鍵詞,<br>
						<span style="color:#D60;">武器名前必須帶上*,入脈武器名前帶**。<br>
						卸下武器名前帶上#。</span><br>
                        <span style="color:red;">例如:</span><br>
                        [例1] <span style="color:blue;">劍神之鎧,劍神之帶,劍神之盔,劍神之鐲,劍神之戒,劍神之靴,劍神之鏈</span><br>
                        [例2] <span style="color:blue;">隱居賢者之鎧,隱居賢者之帶,隱居賢者之盔,隱居賢者之鐲,隱居賢者之戒,隱居賢者之靴,隱居賢者之鏈</span><br>
                        `),
        value: PLU.getCache(equipKey) || "",
        type: "textarea",
        onOk(val) {
          let str = $.trim(val);
          if (!str) return;
          PLU.setCache(equipKey, str);
          PLU.wearEquip(str);
        },
        onNo() { },
      });
    },
    wearEquip(equipsStr) {
      PLU.getAllItems((list) => {
        let equips = equipsStr.split(","),
          equipCmds = "";
        let equipArr = equips.forEach((e) => {
          let eqObj = {};
          if (e.substr(0, 1) == "#") {
            eqObj = { type: -1, name: e.substr(1) };
          } else if (e.substr(0, 2) == "**") {
            eqObj = { type: 2, name: e.substr(2) };
          } else if (e.substr(0, 1) == "*") {
            eqObj = { type: 1, name: e.substr(1) };
          } else {
            eqObj = { type: 0, name: e };
          }
          let bagItem = list.find((it) => !!it.name.match(eqObj.name));
          if (bagItem) {
            if (eqObj.type == -1) equipCmds += "unwield " + bagItem.key + ";";
            else if (eqObj.type == 2) equipCmds += "wield " + bagItem.key + " rumai;";
            else if (eqObj.type == 1) equipCmds += "wield " + bagItem.key + ";";
            else equipCmds += "wear " + bagItem.key + ";";
          }
        });
        PLU.execActions(equipCmds, () => {
          YFUI.writeToOut("<span style='color:yellow;'> ==" + _("装备完毕", "裝備完畢") + "!== </span>");
          if (g_gmain.is_fighting) gSocketMsg.go_combat();
        });
      });
    },
    //================================================================================================
    showLog() {
      if ($("#myTools_InfoPanel").length > 0) return $("#myTools_InfoPanel").remove();
      let $logPanel = YFUI.showInfoPanel({
        text: "",
        onOpen() {
          $("#myTools_InfoPanel .infoPanel-wrap").html(PLU.logHtml);
          $("#myTools_InfoPanel .infoPanel-wrap").scrollTop($("#myTools_InfoPanel .infoPanel-wrap")[0].scrollHeight);
        },
        onNo() {
          PLU.logHtml = "";
          UTIL.logHistory = [];
          UTIL.setMem("HISTORY", JSON.stringify(this.logHistory));
          $("#myTools_InfoPanel .infoPanel-wrap").empty();
        },
        onClose() { },
      });
    },
    //================================================================================================
    updateShowLog(e) {
      let html = `<div style="${e.ext.style}">${UTIL.getNow(e.ext.time)} ${e.ext.msg}</div>`;
      PLU.logHtml += html;
      if ($("#myTools_InfoPanel").length < 1) return;
      $("#myTools_InfoPanel .infoPanel-wrap").append(html);
      $("#myTools_InfoPanel .infoPanel-wrap").scrollTop($("#myTools_InfoPanel .infoPanel-wrap")[0].scrollHeight);
    },
    //================================================================================================
    goHJS(where, npc) {
      let roomInfo = g_obj_map.get("msg_room");
      let curName = UTIL.filterMsg(roomInfo.get("short") || "");
      let act = "";
      if (curName == _("青苔石阶", "青苔石階") && roomInfo.get("northwest") == _("青苔石阶", "青苔石階")) act = "nw";
      else if (curName == _("青苔石阶", "青苔石階") && roomInfo.get("northeast") == _("青苔石阶", "青苔石階")) act = "ne";
      else if (curName == _("青苔石阶", "青苔石階") && roomInfo.get("southwest") == _("青苔石阶", "青苔石階")) act = "sw";
      else if (curName == _("榆叶林", "榆葉林") && roomInfo.get("north") == _("榆叶林", "榆葉林")) act = "n";
      else if (curName == _("榆叶林", "榆葉林") && roomInfo.get("south") == _("榆叶林", "榆葉林")) act = "s";
      else if (curName == "世外桃源" && where == _("镜星府", "鏡星府")) act = "nw";
      else if (curName == "世外桃源" && where == _("荣威镖局", "榮威鏢局")) act = "ne";
      else if (curName == "世外桃源" && where == "碧落城") act = "s";
      if (act)
        PLU.execActions(act, () => {
          let npcObj = roomInfo.get("npc1");
          if (npcObj) {
            var npcName = npcObj.split(",")[1];
          }
          if (npc && ((npcName && npcName != npc) || !npcObj))
            PLU.execActions("jh 2;n;n;e;s;luoyang317_op1;go_hjs go;se;se;ne;w;n;", () => {
              PLU.goHJS(where, npc);
            });
          else PLU.goHJS(where, npc);
        });
    },
    //================================================================================================
    goHaRi() {
      let roomInfo = g_obj_map.get("msg_room");
      let curName = UTIL.filterMsg(roomInfo.get("short") || "");
      let act = "";
      if (curName == _("沙漠迷宫", "沙漠迷宮")) {
        if (roomInfo.get("east") == _("沙漠迷宫", "沙漠迷宮")) act = "e";
        else if (roomInfo.get("north") == _("沙漠迷宫", "沙漠迷宮")) act = "n";
        else if (roomInfo.get("west") == _("沙漠迷宫", "沙漠迷宮")) act = "w";
        else if (roomInfo.get("south") == _("沙漠迷宫", "沙漠迷宮")) act = "s";
        if (act)
          PLU.execActions(act, () => {
            PLU.goHaRi();
          });
      } else if (curName == "荒漠") {
        PLU.execActions("n;n;nw;n;ne", () => {
          YFUI.writeToOut("<span style='color:#FFF;'>--到達--</span>");
        });
      } else {
        PLU.execActions("rank go 263;e;s;w;w;s;sw;sw;sw;sw;nw;nw;n;nw;ne;", () => {
          PLU.goHaRi();
        });
      }
    },
    //================================================================================================
    queryJHMenu($btn, jhname) {
      let npcList = PLU.YFD.mapsLib.Npc.filter((e) => e.jh == jhname);
      npcList.forEach((e) => {
        let str = [e.jh, e.loc, e.name].filter((s) => !!s).join("-");
        YFUI.writeToOut(
          "<span><a style='text-decoration:underline;color:yellow;cursor:pointer;' onclick='PLU.goNpcWay(\"" +
          str +
          '","' +
          e.way +
          "\")'>" +
          str +
          "</a> &nbsp;&nbsp;<a style='text-decoration:underline;color:yellow;cursor:pointer;' onclick='PLU.showNpcWay(\"" +
          str +
          '","' +
          e.way +
          "\")'>" + _("路径详情", "路徑詳情") + "</a></span>",
        );
      });
      YFUI.writeToOut("<span>----------</span>");
    },
    //================================================================================================
    toQueryNpc() {
      YFUI.showInput({
        title: "查找NPC",
        text: _(
          "输入NPC名字,可模糊匹配,支持<a target='_blank' href='https://www.runoob.com/regexp/regexp-syntax.html'>正则表达式</a>,同時支持简体(不包括地址名)和繁体<br>" +
          "正则表达式之外语法例子:<br>" +
          "[例1] 開封@毒蛇<br>" +
          "[例2] 星宿海@百龍山@毒蛇",
          "輸入NPC名字,可模糊匹配,支持<a target='_blank' href='https://zh.wikipedia.org/wiki/正則表達式'>正則表達式</a>,同時支持簡體和繁體<br>" +
          "正則表達式之外語法例子:<br>" +
          "[例1] 開封@毒蛇<br>" +
          "[例2] 星宿海@百龍山@毒蛇",
        ),
        value: PLU.getCache("prevSearchStr") || "^.?(男|女)[孩童]",
        onOk(val) {
          if (!$.trim(val)) return;
          let str = $.trim(val);
          PLU.setCache("prevSearchStr", str);
          PLU.queryNpc(str + "道");
        },
        onNo() { },
      });
    },
    // 查询房间路径
    queryRoomPath() {
      if (UTIL.inHome()) return;
      let jh = PLU.YFD.cityId[g_obj_map?.get("msg_room")?.get("map_id")];
      if (jh) {
        let room = ansi_up.ansi_to_text(g_obj_map?.get("msg_room")?.get("short"));
        return PLU.queryNpc(jh + "@" + room + "@.*道", true)[0]?.way;
      }
    },
    // 链接两个路径终点
    linkPath(pathA, pathB) {
      if (!pathA) return pathB;
      let arrayA = pathA.split(";");
      let arrayB = pathB.split(";");
      let len = Math.min(arrayA.length, arrayB.length);
      for (var index = 0; index < len; index++) if (arrayA[index] != arrayB[index]) break;
      if (!index) return pathB;
      return arrayA
        .slice(index)
        .reverse()
        .map((e) => {
          let cmd = e.match(/^(#\d+ )?([ns]?[we]?)$/);
          if (cmd) {
            if (!cmd[1]) cmd[1] = "";
            if (cmd[2].indexOf("n") == 0) {
              var way = cmd[2].replace("n", "s");
            } else {
              var way = cmd[2].replace("s", "n");
            }
            if (way.indexOf("w") >= 0) {
              way = way.replace("w", "e");
            } else {
              way = way.replace("e", "w");
            }
            return cmd[1] + way;
          }
          // 迷宫反走
          cmd = e.match(/^(.+):(.+)\^(.+)$/);
          if (cmd) return cmd[1] + ":" + cmd[3] + "^" + cmd[2];
          return e;
        })
        .concat(arrayB.slice(index))
        .join(";");
    },
    // 最短路径
    minPath(pathA, pathB) {
      let linkPath = PLU.linkPath(pathA, pathB);
      if (linkPath == "" || linkPath == pathB) return linkPath;
      let a = linkPath.split(";");
      let len = a.length;
      for (var index = 0; index < len; index++) {
        let cmd = a[index].match(/^(.+):(.+\^.+)$/);
        if (cmd) a[index] = PLU.YFD.mapsLib.Labyrinth[cmd[1]][cmd[2]];
      }
      a = a.join(";").split(";");
      let b = pathB.split(";");
      len = b.length;
      for (var index = 0; index < len; index++) {
        let cmd = b[index].match(/^(.+):(.+\^.+)$/);
        if (cmd) b[index] = PLU.YFD.mapsLib.Labyrinth[cmd[1]][cmd[2]];
      }
      b = b.join(";").split(";");
      return a.length <= b.length ? linkPath : pathB;
    },
    //================================================================================================
    formatNpcData(text) {
      let npc = text.match(/^(.*)@(.*)@(.*)道$/);
      if (npc) {
        var jh = npc[1];
        var loc = npc[2];
        var name = "^" + npc[3] + "$";
      } else {
        npc = text.match(/^([^*-]*)[@*-](.*)道$/);
        if (npc) {
          if (npc[1] == _("茶圣", "茶聖") || npc[1] == _("青衣剑士", "青衣劍士")) {
            var name = "^" + npc[1] + "-" + npc[2] + "$";
          } else {
            var jh = npc[1];
            var name = "^" + npc[2] + "$";
          }
        } else {
          npc = text.match(/^(.*)道$/);
          if (npc) {
            var name = npc[1];
          } else {
            var name = text;
          }
        }
      }
      return [jh, loc, name];
    },
    queryNpc(name, quiet) {
      if (!name) return;
      let [jh, loc, tmpName] = PLU.formatNpcData(name);
      name = tmpName;
      let npcLib = PLU.YFD.mapsLib.Npc;
      let findList = npcLib.filter((e) => {
        if (e.jh == jh && e.loc == loc && (e.name.match(name) || (e.name_tw && e.name_tw.match(name)) || (e.name_new && e.name_new.match(name)))) return true;
        return false;
      });
      if (findList.length == 0)
        findList = npcLib.filter((e) => {
          if ((e.jh == jh || !jh) && (e.name.match(name) || (e.name_tw && e.name_tw.match(name)) || (e.name_new && e.name_new.match(name)))) return true;
          return false;
        });
      if (findList.length == 0)
        findList = npcLib.filter((e) => {
          if (e.name.match(name) || (e.name_tw && e.name_tw.match(name)) || (e.name_new && e.name_new.match(name))) return true;
          return false;
        });
      let res = [];
      if (findList && findList.length > 0) {
        findList.forEach((e) => {
          let str = [e.jh, e.loc, _(e.name, e.name_tw)].filter((s) => !!s).join("-");
          if (!quiet)
            YFUI.writeToOut(
              "<span><a style='text-decoration:underline;color:yellow;cursor:pointer;' onclick='PLU.goNpcWay(\"" +
              str +
              '","' +
              e.way +
              "\")'>" +
              str +
              "</a> &nbsp;&nbsp;<a style='text-decoration:underline;color:yellow;cursor:pointer;' onclick='PLU.showNpcWay(\"" +
              str +
              '","' +
              e.way +
              "\")'>" + _("路径详情", "路徑詳情") + "</a></span>",
            );
          res.push(e);
        });
        if (!quiet) YFUI.writeToOut("<span>----------</span>");
      } else if (!quiet) {
        YFUI.writeToOut("<span style='color:#F66;'>" + _("查询不到相关数据", "查詢不到相關數據") + "</span>");
      }
      return res;
    },
    //================================================================================================
    toPathNpc() {
      let defaultMapId = PLU.getCache("pathFindMap") || "1";
      let citys = PLU.YFD.cityList
        .map((c, i) => {
          let issel = i + 1 == defaultMapId ? "selected" : "";
          return '<option value="' + (i + 1) + '" ' + issel + ">" + c + "</option>";
        })
        .join("");
      YFUI.showPop({
        title: _("全图找NPC", "全圖找NPC"),
        text: _(`选择地图, 输入NPC名字,可模糊匹配<br>
				<div style='margin:10px 0;'>
					<span>地图: </span>
					<select id="pathFindMap" style="font-size:15px;height:32px;width:81%;border:1px solid #444;">
						${citys}
					</select>
				</div>
				<div style='margin:10px 0;'>
					<span>名字: </span>
					<input id="pathFindNpc" value="${PLU.getCache("pathFindNpc") || "小龙人"}" style="font-size:14px;height:26px;width:80%;border:1px solid #444;"></input>
				</div>`,
        `選擇地圖, 輸入NPC名字,可模糊匹配<br>
				<div style='margin:10px 0;'>
					<span>地圖: </span>
					<select id="pathFindMap" style="font-size:15px;height:32px;width:81%;border:1px solid #444;">
						${citys}
					</select>
				</div>
				<div style='margin:10px 0;'>
					<span>名字: </span>
					<input id="pathFindNpc" value="${PLU.getCache("pathFindNpc") || "小龍人"}" style="font-size:14px;height:26px;width:80%;border:1px solid #444;"></input>
				</div>`),
        onOk() {
          let mapStr = $.trim($("#pathFindMap").val()),
            npcStr = $.trim($("#pathFindNpc").val());
          if (!npcStr) return;
          PLU.setCache("pathFindMap", mapStr);
          PLU.setCache("pathFindNpc", npcStr);
          let jhMap = PLU.YFD.mapsLib.Map[parseInt(mapStr) - 1];
          if (!jhMap) {
            return YFUI.writeToOut("<span style='color:#F66;'>---" + _("无地图数据", "無地圖數據") + "---</span>");
          } else {
            let ways = jhMap.way.split(";");
            console.log({ paths: ways, idx: 0, objectNPC: npcStr });
            PLU.goPathFindNpc({ paths: ways, idx: 0, objectNPC: npcStr });
          }
        },
        onNo() { },
      });
    },
    goPathFindNpc(params) {
      //goFindYouxia
      if (params.idx >= params.paths.length) {
        setTimeout(() => {
          PLU.execActions("home");
        }, 100);
        YFUI.writeToOut("<span style='color:#FFF;'>--" + _("找不到目标NPC!...已搜索完地图", "找不到目標NPC!...已搜索完地圖") + "--</span>");
        return;
      }
      let acs = [params.paths[params.idx]];
      PLU.actions({
        paths: acs,
        idx: 0,
        onPathsEnd() {
          setTimeout(() => {
            let npcObj = UTIL.findRoomNpcReg(params.objectNPC);
            if (npcObj) {
              YFUI.writeToOut("<span style='color:#FFF;'>--" + _("目标NPC已找到", "目標NPC已找到") + "--</span>");
            } else {
              params.idx++;
              PLU.goPathFindNpc(params);
            }
          }, 100);
        },
        onPathsFail() {
          setTimeout(() => {
            PLU.execActions("home");
          }, 500);
          YFUI.writeToOut("<span style='color:#FFF;'>--" + _("找不到目标NPC!...路径中断", "找不到目標NPC!...路徑中斷") + "--</span>");
          return;
        },
      });
    },
    //================================================================================================
    toQueryMiTi() {
      let defaultMapId = PLU.getCache("pathFindMiTi") || "1";
      let citys = PLU.YFD.cityList
        .map((c, i) => {
          let issel = i + 1 == defaultMapId ? "selected" : "";
          return '<option value="' + (i + 1) + '" ' + issel + ">" + c + "</option>";
        })
        .join("");
      YFUI.showPop({
        title: _("全图找谜题", "全圖找謎題"),
        text: _(`选择地图, 输入关键词(人物,地点,物品)列表(英文逗号隔开)<br>可模糊匹配<br>
            <div style='margin:10px 0;'>
              <span>去哪找: </span>
              <select id="pathFindMap" style="font-size:15px;height:32px;width:81%;border:1px solid #444;">
                ${citys}
              </select>
            </div>
            <div style='margin:10px 0;'>
              <span>要找啥: </span>
              <input id="pathFindKeyword" value="${PLU.getCache("pathFindKeyword") || "柴绍,李秀宁,大鹳淜洲,天罗紫芳衣"
          }" style="font-size:14px;height:26px;width:80%;border:1px solid #444;"></input>
            </div>`,
            `選擇地圖, 輸入關鍵詞(人物,地點,物品)列表(英文逗號隔開)<br>可模糊匹配<br>
            <div style='margin:10px 0;'>
              <span>去哪找: </span>
              <select id="pathFindMap" style="font-size:15px;height:32px;width:81%;border:1px solid #444;">
                ${citys}
              </select>
            </div>
            <div style='margin:10px 0;'>
              <span>要找啥: </span>
              <input id="pathFindKeyword" value="${PLU.getCache("pathFindKeyword") || "柴紹,李秀寧,大鸛淜洲,天羅紫芳衣"
          }" style="font-size:14px;height:26px;width:80%;border:1px solid #444;"></input>
            </div>`),
        onOk() {
          let mapStr = $.trim($("#pathFindMap").val()),
            KeywordStr = $.trim($("#pathFindKeyword").val());
          if (!KeywordStr) return;
          PLU.setCache("pathFindMap", mapStr);
          PLU.setCache("pathFindKeyword", KeywordStr);
          let jhMap = PLU.YFD.mapsLib.Map[parseInt(mapStr) - 1];
          if (!jhMap) {
            return YFUI.writeToOut("<span style='color:#F66;'>---" + _("无地图数据", "無地圖數據") + "---</span>");
          } else {
            let ways = jhMap.way.split(";");
            console.log({ paths: ways, idx: 0, objectKeyword: KeywordStr });
            PLU.MiTiArray = [];
            PLU.goPathFindMiTi({
              paths: ways,
              idx: 0,
              objectKeyword: KeywordStr,
            });
          }
        },
        onNo() { },
      });
    },
    goPathFindMiTi(params) {
      //goFindYouxia
      if (params.idx >= params.paths.length) {
        setTimeout(() => {
          PLU.execActions("home");
        }, 100);
        YFUI.writeToOut("<span style='color:#FFF;'>--" + _("找不到目标谜题!...已搜索完地图", "找不到目標謎題!...已搜索完地圖") + "--</span>");
        return;
      }
      let acs = [params.paths[params.idx]];
      PLU.actions({
        paths: acs,
        idx: 0,
        onPathsEnd() {
          let npcArray = UTIL.getRoomAllNpc();
          UTIL.addSysListener("MiTi", (b, type, subtype, msg) => {
            if (type != "main_msg") return;
            if (msg.match(params.objectKeyword)) PLU.MiTiArray.push(msg);
          });
          for (var npc of npcArray) {
            PLU.execActions("auto_tasks cancel;ask " + npc.key);
          }
          UTIL.delSysListener("MiTi");
          if (PLU.MiTiArray.length) {
            YFUI.writeToOut("<span style='color:#FFF;'>--" + _("目标谜题已找到", "目標謎題已找到") + "--</span>");
            return;
          } else {
            setTimeout(() => {
              params.idx++;
              PLU.goPathFindMiTi(params);
            }, 500);
          }
        },
        onPathsFail() {
          setTimeout(() => {
            PLU.execActions("home");
          }, 500);
          YFUI.writeToOut("<span style='color:#FFF;'>--" + _("路径中断", "路徑中斷") + "--</span>");
          return;
        },
      });
    },
    //================================================================================================
    goNpcWay(desc, way) {
      let goList = PLU.getCache("prevQueryList") || [];
      let newList = goList.filter((e) => e.desc != desc);
      let len = newList.unshift({ desc: desc, way: way });
      if (len > 10) newList.length = 10;
      PLU.setCache("prevQueryList", newList);
      PLU.execActions(way);
    },

    //================================================================================================
    //================================================================================================
    showNpcWay(desc, way) {
      let text = "<span style='color:blue;background:rgba(255,255,244,0.8);padding:1px 10px;display:inline-block;word-break:break-all;'>" + way + "</span></br>";
      let way2 = PLU.linkPath(PLU.queryRoomPath(), way);
      let way3 = PLU.minPath(PLU.queryRoomPath(), way);
      if (way != way2) {
        text +=
          "<span style='color:blue;background:rgba(255,255,244,0.8);padding:1px 10px;display:inline-block;word-break:break-all;'>同图路径(?):" +
          way2 +
          "</span></br>";
        text +=
          "<span style='color:blue;background:rgba(255,255,244,0.8);padding:1px 10px;display:inline-block;word-break:break-all;'>最短路径(?):" +
          way3 +
          "</span></br>";
      }
      YFUI.showPop({
        title: _("路径详情:", "路徑詳情:") + desc,
        text: text,
        autoOk: 10,
        okText: _("关闭", "關閉"),
        noText: "前往",
        onOk() { },
        onNo() {
          PLU.goNpcWay(desc, way);
        },
      });
    },
    //================================================================================================
    toQueryHistory() {
      let prevList = PLU.getCache("prevQueryList") || [];
      if (prevList.length == 0) return YFUI.writeToOut("<span style='color:#F66;'>---" + _("无历史数据", "無歷史數據") + "---</span>");
      for (let i = prevList.length - 1; i >= 0; i--) {
        let e = prevList[i];
        YFUI.writeToOut(
          "<span><a style='text-decoration:underline;color:yellow;cursor:pointer;' onclick='PLU.goNpcWay(\"" +
          e.desc +
          '","' +
          e.way +
          "\")'>" +
          e.desc +
          "</a> &nbsp;&nbsp;<a style='text-decoration:underline;color:yellow;cursor:pointer;' onclick='PLU.showNpcWay(\"" +
          e.desc +
          '","' +
          e.way +
          "\")'>" + _("路径详情:", "路徑詳情:") + "</a></span>",
        );
      }
      YFUI.writeToOut("<span>----------</span>");
    },
    //================================================================================================
    showMPFZ($btn) {
      let btnFlag = PLU.setBtnRed($btn);
      if (!btnFlag) {
        $("#topMonitor").hide();
        $("#btn_bt_showMPFZ").text(_("纷争显示", "紛爭顯示"));
        PLU.setCache("showTopMonitor", 0);
        return;
      }
      $("#topMonitor").show();
      $("#btn_bt_showMPFZ").text(_("纷争隐藏", "紛爭隱藏"));
      PLU.setCache("showTopMonitor", 1);
    },
    
    //================================================================================================
    openCombineGem() {
      let htm = "<div>";
      PLU.YFD.gemType.forEach((t, ti) => {
        htm += "<div>";
        PLU.YFD.gemPrefix.forEach((p, pi) => {
          if (pi > 2)
            htm +=
              '<button onclick="PLU.combineGem(' +
              ti +
              "," +
              pi +
              ')" style="color:' +
              t.color +
              ';width:18%;margin:2px 1%;padding:3px;">' +
              (p.substr(0, 2) + t.name.substr(0, 1)) +
              "</button>";
        });
        htm += "</div>";
      });
      htm += "</div>";
      htm += _(`<div style="margin:10px 0 0 3px;position:absolute;left:15px;bottom:10px;">每次连续合成最多 <input id="maxCombine" type="number" value="1" style="width:50px;height:25px;line-height:25px;" maxlength="3" min=1 max=9999 oninput="if(value.length>4)value=value.substr(0,4)"/> 颗宝石。</div>`, `<div style="margin:10px 0 0 3px;position:absolute;left:15px;bottom:10px;">每次連續合成最多 <input id="maxCombine" type="number" value="1" style="width:50px;height:25px;line-height:25px;" maxlength="3" min=1 max=9999 oninput="if(value.length>4)value=value.substr(0,4)"/> 顆寶石。</div>`);
      YFUI.showPop({
        title: _("合成宝石", "合成寶石"),
        text: htm,
        width: "382px",
        okText: _("关闭", "關閉"),
        onOk() { },
      });
    },
    //================================================================================================
    combineGem(type, grade) {
      if (PLU.TMP.combineTooFast) return YFUI.writeToOut("<span style='color:#F66;'>--" + _("点击不要太快", "點擊不要太快") + "!--</span>");
      PLU.TMP.combineTooFast = setTimeout(() => {
        PLU.TMP.combineTooFast = null;
      }, 600000);
      let targetNum = parseInt($("#maxCombine").val()) || 1;
      let getNum = 0;
      let countString = (combineNum, gemCode) => {
        let combineStr = "";
        if (combineNum % 3 != 0) return "";
        combineStr += "items hecheng " + gemCode + "_N_" + Math.floor(combineNum / 3) + ";";
        return combineStr;
      };
      let needGem = (gemGrade, needNum, gemList) => {
        if (gemGrade < 0) return null;
        let gemName = PLU.YFD.gemPrefix[gemGrade] + PLU.YFD.gemType[type].name;
        let gemCode = PLU.YFD.gemType[type].key + "" + (gemGrade + 1);
        let objGem = gemList.find((e) => e.name == gemName);
        let gemNum = objGem?.num ?? 0;
        if (gemNum >= needNum) {
          return countString(needNum, gemCode);
        } else {
          let dtNum = needNum - gemNum;
          let next = needGem(gemGrade - 1, 3 * dtNum, gemList);
          if (next) return next + countString(needNum, gemCode);
          return null;
        }
      };
      let countCombine = function (cb) {
        PLU.getGemList((gemList) => {
          let runStr = needGem(grade - 1, 3, gemList);
          if (runStr) {
            PLU.fastExec(runStr + "items", () => {
              YFUI.writeToOut("<span style='color:white;'>==" + _("合成宝石", "合成寶石") + "x1==</span>");
              getNum++;
              targetNum--;
              if (targetNum > 0) {
                countCombine(() => {
                  cb && cb(true);
                });
              } else {
                cb && cb(true);
              }
            });
          } else {
            YFUI.writeToOut("<span style='color:#F66;'>--" + _("没有足够的宝石", "沒有足夠的寶石") + "!--</span>");
            cb && cb(false);
          }
        });
      };
      countCombine((end) => {
        clearTimeout(PLU.TMP.combineTooFast);
        PLU.TMP.combineTooFast = null;
        YFUI.writeToOut("<span style='color:white;'>==" + ("合成宝石结束! 得到宝石x", "合成寶石結束! 得到寶石x") + getNum + "==</span>");
      });
    },
    //================================================================================================
    getGemList(callback) {
      let getItemsTimeOut = setTimeout(() => {
        UTIL.delSysListener("getListItems");
      }, 5000);
      UTIL.addSysListener("getListItems", (b, type, subtype, msg) => {
        if (type != "items" || subtype != "list") return;
        UTIL.delSysListener("getListItems");
        clearTimeout(getItemsTimeOut);
        //clickButton("prev");
        let iId = 1,
          itemList = [];
        while (b.get("items" + iId)) {
          let it = UTIL.filterMsg(b.get("items" + iId)).split(",");
          if (it && it.length > 4 && it[3] == "0" && it[1].match(_("宝石", "寶石")))
            itemList.push({
              key: it[0],
              name: it[1],
              num: Number(it[2]),
            });
          iId++;
        }
        callback && callback(itemList);
      });
      clickButton("items", 0);
    },
    //================================================================================================
    getAllItems(callback) {
      let getItemsTimeOut = setTimeout(() => {
        UTIL.delSysListener("getListItems");
      }, 5000);
      UTIL.addSysListener("getListItems", (b, type, subtype, msg) => {
        if (type != "items" || subtype != "list") return;
        UTIL.delSysListener("getListItems");
        clearTimeout(getItemsTimeOut);
        clickButton("prev");
        let iId = 1,
          itemList = [];
        while (b.get("items" + iId)) {
          let it = UTIL.filterMsg(b.get("items" + iId)).split(",");
          if (it && it.length > 4)
            itemList.push({
              key: it[0],
              name: it[1],
              num: Number(it[2]),
              equipped: it[3] == "0",
            });
          iId++;
        }
        callback && callback(itemList);
      });
      clickButton("items", 0);
    },
    //================================================================================================
    profileSetting() {
      if (!this.pSettingMaps) this.initpSettingMaps();
      let ckeds = PLU.getCache("pSettingArray")?.split(",") || this.pSettingMaps.map((e, i) => i);

      let htm = '<div style="display:flex;flex-direction:row;flex-wrap: wrap;justify-content: space-between;width: 100%;align-content: flex-start;line-height:2;">';
      this.pSettingMaps.forEach((e, i) => {
        if (!e.n) htm += '<span style="width:92px;">&nbsp;</span>';
        else
          htm += `<span><label data-id="${i}" style="font-size:13px;margin:0 3px 5px 0;">${e.n}<input type="checkbox" name="pSettingId" value="${i}"
             ${ckeds.includes(i + "") || e.f ? "checked" : ""} ${e.f ? "disabled" : ""} /></label></span>`;
      });
      YFUI.showPop({
        title: _("个人设置", "個人設置"),
        text: htm,
        width: "260px",
        okText: "完成",
        onOk(e) {
          let checkeds = [];
          e.find('input[name="pSettingId"]:checked').each((i, b) => {
            checkeds.push(b.value);
          });
          PLU.setCache("pSettingArray", checkeds.join(","));
          PLU.saveSetting(checkeds);
          console.log(checkeds);
        },
        onNo() { },
        afterOpen($el) {
          $el.find(".pSettingAll").click((e) => {
            $el.find('input[name="pSettingId"]').each(function () {
              $(this).prop("checked", true);
            });
          });
        },
      });
    },
    //================================================================================================
    saveSetting(checkeds) {
      for (let psid in PLU.pSettingMaps) {
        let pSettingD = PLU.pSettingMaps[psid];
        let pms = (checkeds.includes(psid)) ? "true" : "false";
        PLU.setCache("pSetting_" + pSettingD.n, pms);
        console.log(PLU.getCache("pSetting_" + pSettingD.n))
      }
    },
    //================================================================================================
    initpSettingMaps() {
      let _this = this;
      this.pSettingMaps = [
        {
          n: _("专属称号", "專屬稱號"),
        },
        {
          n: _("快速连招", "快速連招"),
        },
      ];
    },
    //================================================================================================
    backupSetting() {
      let config = {};
      config.GM = GM_info;
      config.GM.scriptMetaStr = undefined;
      config.GM.script.header = undefined;
      config.PLU = {};
      config.PLU.CACHE = UTIL.getMem("CACHE");
      config.PLU.HISTORY = UTIL.getMem("HISTORY");
      config.PLU.STATUS = PLU.STATUS;
      config.PLU.TMP = PLU.TMP;
      const reader = new FileReader();
      reader.readAsDataURL(new Blob([JSON.stringify(config)], { type: "application/json" }));
      reader.onload = (e) => {
        let a = document.createElement("a");
        a.download = _("无剑配置-", "無劍配置-") + PLU.accId + "-" + new Date().getTime() + ".json";
        a.style.display = "none";
        a.href = reader.result;
        a.click();
      };
    },
    //================================================================================================
    loadSetting() {
      let input = document.createElement("input");
      input.type = "file";
      input.id = "config";
      input.accept = "application/json";
      input.style.display = "none";
      input.onchange = () => {
        const reader = new FileReader();
        reader.readAsText(input.files[0]);
        reader.onload = (e) => {
          const config = JSON.parse(reader.result);
          UTIL.setMem("CACHE", config.PLU.CACHE);
          UTIL.setMem("HISTORY", config.PLU.HISTORY);
          PLU.initStorage();
          PLU.TMP = config.PLU.TMP;
          PLU.STATUS = config.PLU.STATUS;
          YFUI.writeToOut("<span style='color:yellow;'>==" + _("加载完成", "加載完成") + "==</span>");
        };
      };
      input.click();
    },
  };
  //=================================================================================
  // UTIL模塊
  //=================================================================================
  window.UTIL = {
    //================
    accId: null,
    sysListeners: {},
    logHistory: [],
    //================
    getUrlParam(key) {
      let res = null,
        au = location.search.split("?"),
        sts = au[au.length - 1].split("&");
      sts.forEach((p) => {
        if (p.split("=").length > 1 && key == p.split("=")[0]) res = unescape(p.split("=")[1]);
      });
      return res;
    },
    getAccId() {
      this.accId = this.getUrlParam("id");
      return this.accId;
    },
    setMem(key, data) {
      localStorage.setItem("PLU_" + this.accId + "_" + key, data);
    },
    getMem(key) {
      return localStorage.getItem("PLU_" + this.accId + "_" + key);
    },
    rnd() {
      return Math.floor(Math.random() * 1000000);
    },
    getuuid: function () {
      return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
        var r = (Math.random() * 16) | 0,
          v = c == "x" ? r : (r & 0x3) | 0x8;
        return v.toString(16);
      });
    },
    getNow(timestamp) {
      var date = timestamp ? new Date(timestamp) : new Date();
      var Y = date.getFullYear();
      var M = (date.getMonth() + 1 + "").padStart(2, "0");
      var D = (date.getDate() + "").padStart(2, "0");
      var h = (date.getHours() + "").padStart(2, "0");
      var m = (date.getMinutes() + "").padStart(2, "0");
      var s = (date.getSeconds() + "").padStart(2, "0");
      return M + "-" + D + " " + h + ":" + m + ":" + s;
    },
    log({ msg, type, time, isHistory }) {
      let style = "color:#333";
      if (type == "TF") {
        let co = msg.match("夜魔") ? "#F0F" : "#666";
        style = "color:" + co;
      } else if (type == "QL") {
        style = "color:#00F";
      } else if (type == "MPFZ") {
        style = "color:#F60";
      } else if (type == "LPFZ") {
        style = "color:#033";
      } else if (type == "KFQL") {
        style = "color:#F00;background:#FF9;";
      } else if (type == "YX") {
        let co2 = msg.match(_("宗师】", "宗師】")) ? "#00F" : msg.match(_("侠客】", "俠客】")) ? "#08F" : msg.match("魔尊】") ? "#F00" : msg.match("邪武】") ? "#F80" : "#999";
        style = "color:" + co2 + ";background:#CFC;";
      } else if (type == "BF") {
        style = "color:#FFF;background:#93C;";
      } else if (type == "TIPS") {
        style = "color:#29F";
      }
      //console.log('%c%s',style,this.getNow(time)+msg)
      if (!isHistory) {
        this.logHistory.push({ msg, type, time });
        this.setMem("HISTORY", JSON.stringify(this.logHistory));
      }
      let evt = new Event("addLog");
      evt.ext = { msg, type, time, style };
      document.dispatchEvent(evt);
    },
    filterMsg(s) {
      if (typeof s == "string") return s.replace(/[\033|\27|\0x1b]\[[0-9|;]+m/gi, "");
      return "";
    },
    sysDispatchMsg(b, type, subtype, msg) {
      for (var key in this.sysListeners) {
        this.sysListeners[key](b, type, subtype, msg);
      }
    },
    addSysListener(key, fn) {
      this.sysListeners[key] = fn;
    },
    delSysListener(key) {
      delete this.sysListeners[key];
    },
    findRoomNpc(npcName, gb, searchAll) {
      console.debug(npcName);
      let roomInfo = g_obj_map.get("msg_room");
      if (!roomInfo) return null;
      for (let i = roomInfo.elements.length - 1; i >= 0; i--) {
        let bNpc = this.getSpNpcByIdx(roomInfo, i, searchAll);
        if (bNpc && bNpc.name == npcName) {
          if (!gb) return bNpc;
          else {
            let gNpc = this.getSpNpcByIdx(roomInfo, i - gb);
            if (gNpc) return gNpc;
          }
        }
      }
      return null;
    },
    roomHasNpc() {
      let roomInfo = g_obj_map.get("msg_room");
      let res = false;
      if (!roomInfo) return null;
      for (let i = roomInfo.elements.length - 1; i >= 0; i--) {
        if (roomInfo.elements[i].key.match("npc")) {
          res = true;
          break;
        }
      }
      return res;
    },
    getRoomAllNpc() {
      let roomInfo = g_obj_map.get("msg_room");
      let res = [];
      if (!roomInfo) return res;
      for (let i = roomInfo.elements.length - 1; i >= 0; i--) {
        let npc = roomInfo.elements[i].key.match(/npc(\d+)/);
        if (npc) {
          let infoArr = roomInfo.elements[i].value.split(",");
          let name = this.filterMsg(infoArr[1]);
          res.push({ name: name, key: infoArr[0] });
        }
      }
      return res;
    },
    findRoomNpcReg(npcName) {
      let roomInfo = g_obj_map.get("msg_room");
      if (!roomInfo) return null;
      for (let i = roomInfo.elements.length - 1; i >= 0; i--) {
        let npc = roomInfo.elements[i].key.match(/npc(\d+)/);
        if (npc) {
          let infoArr = roomInfo.elements[i].value.split(",");
          let name = this.filterMsg(infoArr[1]);
          if (name.match(npcName)) return { name: name, key: infoArr[0] };
        }
      }
      return null;
    },
    getSpNpcByIdx(roomInfo, idx, searchAll) {
      let npcInfo = roomInfo.get("npc" + idx);
      if (npcInfo) {
        let infoArr = npcInfo.split(",");
        let name = this.filterMsg(infoArr[1]);
        if (searchAll) return { name: name, key: infoArr[0] };
        if (name != infoArr[1]) return { name: name, key: infoArr[0] };
      }
      return null;
    },
    getItemFrom(name) {
      if (g_gmain.is_fighting) return;
      var item = g_obj_map.get("msg_room")?.elements.find((it) => it.key.substring(0, 4) == "item" && it.value.indexOf(name) >= 0);
      if (item) {
        clickButton("get " + item.value.split(",")[0]);
      }
    },
    inHome() {
      return gSocketMsg._is_in_home;
    },
  };
  //=================================================================================
  // UI模塊
  //=================================================================================
  window.YFUI = {
    init() {
      let maxW = $("#out").width() > 634 ? 634 : $("#out").width();
      console.log($("#page").width(), $("#out").width());
      let rightStyle = $("#page").width() - $("#out").width() > 4 ? "left:" + (maxW - 76 + 4) + "px;" : "right:0;";
      this.$Panel = $(
        '<div id="WJPlug_Panel" style="pointer-events:none;position:absolute;z-index:9999;' +
        rightStyle +
        ';top:5.5%;font-size:12px;line-height:1.2;text-align:right;list-style:none;">',
      );
      $("body").append(this.$Panel);
    },
    addBtnGroup({ id, style }) {
      let $box = $('<div id="' + id + '" style="position:relative;"></div>');
      style && $box.css(style);
      this.$Panel.append($box);
      return $box;
    },
    addBtn({ id, groupId, text, onclick, style, boxStyle, extend, children, canSet }) {
      let $box = $('<div id="' + id + '" class="btn-box" style="position:relative;pointer-events:auto;"></div>');
      let $btn = $(
        '<button id="btn_' +
        id +
        '" style="padding:4px 2px;box-sizing:content-box;margin:1px 1px;border:1px solid #333;border-radius:4px;width:68px;">' +
        text +
        "</button>",
      );
      style && $btn.css(style);
      boxStyle && $box.css(boxStyle);
      $btn.$extend = extend;
      $btn.click((e) => {
        onclick && onclick($btn, $box);
      });
      $box.append($btn);
      if (children) $box.append($('<b style="position:absolute;left:1px;top:3px;font-size:12px;">≡</b>'));
      if (canSet) {
        let $setbtn = $(
          '<i style="position:absolute;right:-8px;top:2px;font-size:14px;background:#333;color:#fff;font-style:normal;;line-height:1;border:1px solid #CCC;border-radius:100%;padding:2px 6px;cursor:pointer;">S</i>',
        );
        $box.append($setbtn);
        $setbtn.click((e) => {
          onclick && onclick($btn, $box, "setting");
        });
      }
      groupId ? $("#" + groupId).append($box) : this.$Panel.append($box);
      $box.$button = $btn;
      return $box;
    },
    addMenu({ id, groupId, text, extend, style, menuStyle, multiCol, onclick, children }) {
      //{text,id,btnId}
      let $btnBox = this.addBtn({ id, groupId, text, extend, style, children }),
        _this = this;
      function addMenuToBtn({ btnId, $parent, list, menuStyle }) {
        let $listBox = $('<div id="menu_' + btnId + '" class="menu" style="position:absolute;top:0;right:' + $parent.width() + 'px;display:none;"></div>');
        $parent.append($listBox);
        list &&
          list.forEach((sub) => {
            let btnOpt = Object.assign({}, sub, { groupId: "menu_" + btnId });
            if (!btnOpt.onclick) {
              btnOpt.onclick = onclick;
            }
            if (multiCol) btnOpt.boxStyle = Object.assign({}, { display: "inline-block" }, btnOpt.boxStyle);
            let $subBtnBox = _this.addBtn(btnOpt);
            if (sub.children)
              $subBtnBox.$list = addMenuToBtn({
                btnId: sub.id,
                $parent: $subBtnBox,
                list: sub.children,
                menuStyle: sub.menuStyle,
              });
          });
        $parent.$button.click((e) => {
          $listBox.toggle().css({ right: $parent.width() + 5 });
          menuStyle && $listBox.css(menuStyle);
          $listBox.is(":visible") && $listBox.parent().siblings(".btn-box").find(".menu").hide();
          onclick && onclick($parent.$button, $parent);
        });
        return $listBox;
      }
      $btnBox.$list = addMenuToBtn({
        btnId: id,
        $parent: $btnBox,
        list: children,
        menuStyle: menuStyle,
      });
      return $btnBox;
    },
    showPop(params) {
      if ($("#myTools_popup").length) $("#myTools_popup").remove();
      params = params || {};
      let okText = params.okText || _("确定", "確定"),
        noText = params.noText || "取消",
        _this = this;
      _this.SI_autoOk && clearInterval(_this.SI_autoOk);
      _this.SI_autoOk = null;
      let ph = `<div style="z-index:9999;position:fixed;top: 40%;left:50%;width:100%;height:0;font-size:14px;" id="myTools_popup">
			<div class="popup-content" style="width:${params.width || "70%"
        };max-width:512px;background: rgba(255,255,255,.8);border:1px solid #999999;border-radius: 10px;transform: translate(-50%,-50%) scale(.1,.1);transition:all .1s;">
			<div style="padding: 10px 15px;"><span style="font-weight:700;">${params.title || ""
        }</span><span style="float:right;color:#666;cursor:pointer;" class="btncl">✖</span></div>
			<div style="padding: 0 15px;line-height:1.5;max-height:500px;overflow-y:auto;">${params.text || ""}</div>
			<div style="text-align:right;padding: 10px;">`;
      if (params.onNo) ph += `<button style="margin-right: 15px;padding: 5px 20px;border: 1px solid #000;border-radius:5px;" class="btnno">${noText}</button>`;
      ph += `<button style="padding: 5px 20px;background-color: #963;color:#FFF;border: 1px solid #000;border-radius: 5px;" class="btnok">${okText}</button>
			</div></div></div>`;
      let $ph = $(ph);
      $("body").append($ph);
      setTimeout(() => {
        $ph.find(".popup-content").css({ transform: "translate(-50%,-50%) scale(1,1)" });
        params.afterOpen && params.afterOpen($ph);
      }, 100);
      if (params.autoOk) {
        let autoCloseN = Number(params.autoOk);
        $("#myTools_popup .btnok").text(okText + "(" + autoCloseN + "s)");
        _this.SI_autoOk = setInterval(() => {
          autoCloseN--;
          $("#myTools_popup .btnok").text(okText + "(" + autoCloseN + "s)");
          if (autoCloseN < 1) {
            $ph.find(".btnok").click();
          }
        }, 1000);
      } else if (params.autoNo) {
        let autoCloseN = Number(params.autoNo);
        $("#myTools_popup .btnno").text(noText + "(" + autoCloseN + "s)");
        _this.SI_autoOk = setInterval(() => {
          autoCloseN--;
          $("#myTools_popup .btnno").text(noText + "(" + autoCloseN + "s)");
          if (autoCloseN < 1) {
            $ph.find(".btnno").click();
          }
        }, 1000);
      }
      $ph.find(".btncl").click((e) => {
        _this.SI_autoOk && clearInterval(_this.SI_autoOk);
        params.onX && params.onX();
        $ph.remove();
      });
      $ph.find(".btnno").click((e) => {
        _this.SI_autoOk && clearInterval(_this.SI_autoOk);
        params.onNo && params.onNo();
        $ph.remove();
      });
      $ph.find(".btnok").click((e) => {
        _this.SI_autoOk && clearInterval(_this.SI_autoOk);
        params.onOk && params.onOk($ph);
        $ph.remove();
      });
    },
    showInput(params) {
      let popParams = Object.assign({}, params);
      let inpstyle = "font-size:14px;line-height:1.5;width:100%;padding:5px;border:1px solid #999;border-radius:5px;margin:5px 0;outline:none;box-sizing:border-box;";
      if (params.inputs && params.inputs.length > 1) {
        for (let i = 0; i < params.inputs.length; i++) {
          let val = params.value[i] || "";
          popParams.text += `<div><div style="width:20%;float:left;margin:5px 0;line-height:2;text-align:right;">${params.inputs[i]}: </div><div style="width:73%;margin-left:21%;">`;
          popParams.text +=
            params.type == "textarea"
              ? `<textarea id="myTools_popup_input_${i}" rows="4" style="${inpstyle}">${val}</textarea></div></div>`
              : `<input id="myTools_popup_input_${i}" type="text" value="${val}" style="${inpstyle}"/></div></div>`;
        }
        popParams.onOk = () => {
          let val = [];
          for (let i = 0; i < params.inputs.length; i++) {
            val.push($("#myTools_popup_input_" + i).val());
          }
          params.onOk(val);
        };
      } else {
        popParams.text +=
          params.type == "textarea"
            ? `<div><textarea id="myTools_popup_input" rows="4" style="${inpstyle}">${params.value || ""}</textarea></div>`
            : `<div><input id="myTools_popup_input" type="text" value="${params.value || ""}" style="${inpstyle}"/></div>`;
        popParams.onOk = () => {
          let val = $("#myTools_popup_input").val();
          params.onOk(val);
        };
      }
      this.showPop(popParams);
    },
    showInfoPanel(params) {
      if ($("#myTools_InfoPanel").length) $("#myTools_InfoPanel").remove();
      params = params || {};
      let okText = params.okText || _("关闭", "關閉"),
        noText = params.noText || "清空",
        _this = this;
      let $ph = $(`<div style="z-index:9900;position:fixed;top:10%;left:0;width:100%;height:0;font-size:12px;" id="myTools_InfoPanel">
			<div class="infoPanel-content" style="width:${params.width || "75%"
        };max-width:512px;height:620px;background: rgba(255,255,255,.9);border:1px solid #999;border-radius:0 10px 10px 0;transform: translate(-100%,0);transition:all .1s;">
				<div style="padding: 10px 15px;"><span style="font-weight:700;">${params.title || ""
        }</span><span style="float:right;color:#666;cursor:pointer;" class="btncl">✖</span></div>
				<div style="padding: 0 15px;line-height:1.5;height:550px;overflow-y:auto;" class="infoPanel-wrap">${params.text || ""}</div>
				<div style="text-align:right;padding: 10px;">
				<button style="padding: 5px 20px;background-color: #969;color:#FFF;border: 1px solid #000;border-radius: 5px;margin-right:25px;" class="btnno">${noText}</button>
				<button style="padding: 5px 20px;background-color: #963;color:#FFF;border: 1px solid #000;border-radius: 5px;" class="btnok">${okText}</button>
				</div>
			</div></div>`);
      $("body").append($ph);
      setTimeout(() => {
        $ph.find(".infoPanel-content").css({ transform: "translate(0,0)" });
        params.onOpen && params.onOpen();
      }, 100);
      $ph.find(".btncl").click((e) => {
        params.onClose && params.onClose();
        $ph.remove();
      });
      $ph.find(".btnok").click((e) => {
        params.onOk && params.onOk();
        params.onClose && params.onClose();
        $ph.remove();
      });
      $ph.find(".btnno").click((e) => {
        params.onNo && params.onNo();
      });
      return $ph;
    },
    writeToOut(html) {
      var m = new unsafeWindow.Map();
      m.put("type", "main_msg");
      m.put("subtype", "html");
      m.put("msg", html);
      gSocketMsg.dispatchMessage(m);
    },
  };
  // 檢查本地緩存是否存在
  if (!localStorage.getItem('dataFile') || !localStorage.getItem('dataFile_version')) {
    // 本地緩存不存在,從特定網址下載文件
    GreasyFork.getScriptData('491615').then(data => {
      localStorage.setItem('dataFile_version', data.version);
      GreasyFork.getScriptCode('491615').then(data => {
        localStorage.setItem('dataFile', data);
        alert(_("脚本数据库更新完成\n当前版本: ", "腳本數據庫更新完成\n當前版本: ") + localStorage.getItem('dataFile_version'));
        location.reload();
      });
    });
  } else {
    GreasyFork.getScriptData('491615').then(data => {
      if (localStorage.getItem('dataFile_version') == data.version) {
        init();
      } else {
        GreasyFork.getScriptData('491615').then(data => {
          localStorage.setItem('dataFile_version', data.version);
          GreasyFork.getScriptCode('491615').then(data => {
            localStorage.setItem('dataFile', data);
            alert(_("脚本数据库更新完成\n当前版本: ", "腳本數據庫更新完成\n當前版本: ") + localStorage.getItem('dataFile_version'));
            location.reload();
          });
        });
      }
    });
  }
});