無劍Mud輔助

無劍Mud輔助,由在線版移植而來,順便略改

目前為 2023-08-26 提交的版本,檢視 最新版本

// ==UserScript==
// @name              无剑Mud辅助
// @name:zh-TW        無劍Mud輔助
// @description       无剑Mud辅助,由在线版移植而来,順便略改
// @description:zh-TW 無劍Mud輔助,由在線版移植而來,順便略改
// @namespace         http://tampermonkey.net/
// @version           0.0.14beta15
// @iconURL           http://res.yytou.cn/lunjian_tw/img/icon1.png
// @author            燕飞,東方鳴
// @match             http://swordman-s1.yytou.com/*
// @grant             unsafeWindow
// @grant             GM_xmlhttpRequest
// @connect           orchin.cn
// @run-at            document-end
// ==/UserScript==

"use strict";
//相容一下低版本瀏覽器flat函式
if (!Array.prototype.flat) {
  Array.prototype.flat = function (count) {
    let c = count || 1;
    let len = this.length;
    let exe = [];
    if (this.length == 0) return this;
    while (c--) {
      let _arr = [];
      let flag = false;
      if (exe.length == 0) {
        flag = true;
        for (let i = 0; i < len; i++) {
          if (this[i] instanceof Array) {
            exe.push(...this[i]);
          } else {
            exe.push(this[i]);
          }
        }
      } else {
        for (let i = 0; i < exe.length; i++) {
          if (exe[i] instanceof Array) {
            flag = true;
            _arr.push(...exe[i]);
          } else {
            _arr.push(exe[i]);
          }
        }
        exe = _arr;
      }
      if (!flag && c == Infinity) {
        break;
      }
    }
    return exe;
  };
}

$(() => {
  function init() {
    // 跨域
    GM_xmlhttpRequest({
      method: "GET",
      url: "http://orchin.cn/wujian/game/js/yfdata.json",
      responseType: "json",
      onload: function (res) {
        PLU.YFUI = YFUI;
        PLU.UTIL = UTIL;
        PLU.YFD = JSON.parse(res.responseText);
        PLU.YFD.cityList = [
          "雪亭鎮",
          "洛陽",
          "華山村",
          "華山",
          "揚州",
          "丐幫",
          "喬陰縣",
          "峨眉山",
          "恆山",
          "武當山",
          "晚月莊",
          "水煙閣",
          "少林寺",
          "唐門",
          "青城山",
          "逍遙林",
          "開封",
          "光明頂",
          "全真教",
          "古墓",
          "白駝山",
          "嵩山",
          "梅莊",
          "泰山",
          "鐵血大旗門",
          "大昭寺",
          "黑木崖",
          "星宿海",
          "茅山",
          "桃花島",
          "鐵雪山莊",
          "慕容山莊",
          "大理",
          "斷劍山莊",
          "冰火島",
          "俠客島",
          "絕情谷",
          "碧海山莊",
          "天山",
          "苗疆",
          "白帝城",
          "墨家機關城",
          "掩月城",
          "海雲閣",
          "幽冥山莊",
          "花街",
          "西涼城",
          "高昌迷宮",
          "京城",
          "越王劍宮",
          "江陵",
          "天龍寺",
          "西夏",
          "南詔國",
        ];
        PLU.YFD.qlList = [
          { n: "書房", v: "jh 1;e;n;e;e;e;e;n" },
          { n: "打鐵鋪子", v: "jh 1;e;n;n;w" },
          { n: "桑鄰藥鋪", v: "jh 1;e;n;n;n;w" },
          { n: "南市", v: "jh 2;n;n;e" },
          { n: "繡樓", v: "jh 2;n;n;n;n;w;s;w" },
          { n: "北大街", v: "jh 2;n;n;n;n;n;n;n" },
          { n: "錢莊", v: "jh 2;n;n;n;n;n;n;;n;e" },
          { n: "雜貨鋪", v: "jh 3;s;s;e" },
          { n: "祠堂大門", v: "jh 3;s;s;w" },
          { n: "廳堂", v: "jh 3;s;s;w;n" },
        ];
        PLU.YFD.mjList = [
          { n: "山坳", v: "jh 1;e;n;n;n;n;n;" },
          { n: "桃花泉", v: "jh 3;s;s;s;s;s;nw;n;n;e;" },
          { n: "千尺幢", v: "jh 4;n;n;n;n" },
          { n: "猢猻愁", v: "jh 4;n;n;n;n;n;n;e;n;n;" },
          { n: "潭畔草地", v: "jh 4;n;n;n;n;n;n;n;event_1_91604710;s;s;s;" },
          { n: "玉女峰", v: "jh 4;n;n;n;n;n;n;n;n;w;" },
          { n: "長空棧道", v: "jh 4;n;n;n;n;n;n;n;n;n;e;" },
          { n: "臨淵石台", v: "jh 4;n;n;n;n;n;n;n;n;n;e;n;" },
          {
            n: "沙丘小洞",
            v: "jh 6;event_1_98623439;ne;n;ne;ne;ne;event_1_97428251;",
          },
          {
            n: "九老洞",
            v: "jh 8;w;nw;n;n;n;n;e;e;n;n;e;kill emei_shoushan;;n;;n;n;n;w;n;n;n;n;n;n;n;n;n;nw;sw;w;nw;w;",
          },
          { n: "懸根松", v: "jh 9;n;w;" },
          { n: "夕陽嶺", v: "jh 9;n;n;e;" },
          { n: "青雲坪", v: "jh 13;e;s;s;w;w;" },
          { n: "玉壁瀑布", v: "jh 16;s;s;s;s;e;n;e;" },
          { n: "湖邊", v: "jh 16;s;s;s;s;e;n;e;event_1_5221690;s;w;" },
          {
            n: "碧水寒潭",
            v: "jh 18;n;nw;n;n;n;n;n;ne;n;n;n;n;n;e;e;se;se;e;",
          },
          { n: "寒水潭", v: "jh 20;w;w;s;e;s;s;s;s;s;sw;sw;s;e;se;" },
          { n: "懸崖", v: "jh 20;w;w;s;e;s;s;s;s;s;sw;sw;s;s;e;" },
          { n: "戈壁", v: "jh 21;" },
          { n: "盧崖瀑布", v: "jh 22;n;n;n;n;e;n" },
          { n: "啟母石", v: "jh 22;n;n;w;w;" },
          { n: "無極老姆洞", v: "jh 22;n;n;w;n;n;n;n;" },
          { n: "山溪畔", v: "jh 22;n;n;w;n;n;n;n;event_1_88705407;s;s;" },
          { n: "奇槐坡", v: "jh 23;n;n;n;n;n;n;n;n;" },
          { n: "天梯", v: "jh 24;n;n;n;" },
          { n: "小洞天", v: "jh 24;n;n;n;n;e;e;" },
          { n: "雲步橋", v: "jh 24;n;n;n;n;n;n;n;n;n;" },
          { n: "觀景台", v: "jh 24;n;n;n;n;n;n;n;n;n;n;n;n;e;e;n;" },
          { n: "危崖前", v: "jh 25;w;" },
          { n: "草原", v: "jh 26;w;" },
          {
            n: "無名山峽谷",
            v: "jh 29;n;n;n;n;event_1_60035830;place?平台;event_1_65661209;place?無名山峽谷;",
          },
        ];
        PLU.YFD.prizeList = [
          [
            "明月鞋",
            "月光寶甲衣",
            "明月戒",
            "明月帽",
            "明月項鍊",
            "明月手鐲",
            "屠龍刀",
            "倚天劍",
            "冰魄銀針",
            "墨玄掌套",
            "碧磷鞭",
            "烈日棍",
            "西毒蛇杖",
            "星月大斧",
            "碧玉錘",
            "霸王槍",
          ],
          [
            "烈日寶靴",
            "日光寶甲衣",
            "烈日寶戒",
            "烈日帽",
            "烈日寶鏈",
            "烈日寶鐲",
            "斬神刀",
            "誅仙劍",
            "暴雨梨花針",
            "龍象拳套",
            "七星鞭",
            "殘陽棍",
            "伏虎杖",
            "破冥斧",
            "撼魂錘",
            "赤焰槍",
          ],
          [
            "斬龍寶靴",
            "龍皮至尊甲衣",
            "斬龍寶戒",
            "斬龍帽",
            "斬龍寶鏈",
            "斬龍寶鐲",
            "飛宇天怒刀",
            "九天龍吟劍",
            "小李飛刀",
            "天罡掌套",
            "烏金玄火鞭",
            "開天寶棍",
            "達摩杖",
            "天雷斷龍斧",
            "燭幽鬼煞錘",
            "斬龍鎏金槍",
          ],
          [
            "君影草",
            "矢車菊",
            "忘憂草",
            "仙客來",
            "雪英",
            "朝開暮落花",
            "夕霧草",
            "鳳凰木",
            "熙顏花",
            "晚香玉",
            "凌霄花",
            "彼岸花",
            "洛神花",
            "百宜雪梅",
            "胤天寶帽碎片",
            "胤天項鍊碎片",
            "胤天寶戒碎片",
            "魚腸碎片",
            "軒轅劍碎片",
            "破嶽拳套碎片",
            "胤天寶鐲碎片",
            "胤天寶靴碎片",
            "胤天紫金衣碎片",
            "昊天龍旋鎧碎片",
            "水羽雲裳碎片",
            "奉天金帶碎片",
            "鳳羽乾坤盾碎片",
            "玄冰凝魄槍碎片",
            "雷霆誅神刀碎片",
            "天雨玄鏢碎片",
            "天神杖碎片",
            "轟天巨棍碎片",
            "神龍怒火鞭碎片",
            "胤武伏魔斧碎片",
            "九天滅世錘碎片",
          ],
        ];
        PLU.YFD.masterList = [
          {
            n: _("九阴", "九陰"),
            in: "九陰派",
            npc1: "baituo_chenxuanfeng",
            v1: "jh 28;sw;nw;sw;sw;nw;nw;se;sw",
          },
          {
            n: _("白驼", "白馱"),
            in: "白馱山派",
            npc1: "btshan_ouyangfeng",
            v1: "jh 21;nw;w;w;nw;n;n;n;n;n;n;n",
          },
          {
            n: _("唐门", "唐門"),
            in: "唐門",
            npc1: "tangmen_madam",
            v1: "jh 14;w;n;n;n;e;e;n;n;ask tangmen_tangmei;ask tangmen_tangmei;e;event_1_8413183;event_1_39383240;e;s;e;n;w;n;n",
          },
          {
            n: "魔教",
            in: "魔教",
            npc1: "heimuya_dfbb",
            v1: "jh 27;ne;nw;w;nw;w;w;kill heimuya_shaogong;get?船夫的屍體;yell;w;nw;n;n;n;n;n;n;n;w;n;n;n;n;n;n;n;n;n;n;yell;n;n;n;n;n;n;n;n;n;n;n;n;n;event_1_57107759;e;e;n;w",
          },
          {
            n: "青城",
            in: "青城派",
            npc1: "qingcheng_mudaoren",
            v1: "jh 15;s;s;s;s;s;s;w",
          },
          {
            n: "星宿",
            in: "天宿派",
            npc1: "xingxiu_ding",
            v1: "jh 28;n;n;n;n;n",
          },
          {
            n: "天邪",
            in: "天邪派",
            npc1: "fighter_champion",
            v1: "jh 12;n;n;n;w;n;nw;e;n",
          },
          {
            n: "大招",
            in: "大招寺",
            npc1: "lama_gelun",
            v1: "jh 26;w;w;w;w;w;w;w;w;w;w;ask?lama_master;event_1_91837538",
          },
          {
            n: "晚月",
            in: "晚月莊",
            npc1: "dancer_eelon",
            v1: "jh 11;e;e;s;sw;se;w;w;s;s;s;e;s;s;e",
          },
          { n: "花紫", in: "花紫會", npc1: "beggar_master", v1: "jh 7;s" },
          {
            n: "少林",
            in: "少林派",
            npc1: "shaolin_dmlzh",
            v1: "jh 13;n;n;n;n;n;n;n;n;n;n;n;n;w;n;get_silver",
          },
          {
            n: _("华山", "華山"),
            in: "華山派",
            npc1: "huashan_feng",
            v1: "jh 4;n;n;n;n;n;n;n;n;w;w;n;get_xiangnang2",
          },
          {
            n: "大理",
            in: "大理段家",
            npc1: "dali_yideng",
            v1: "jh 33;sw;sw;s;s;s;s;s;s;s;s;s;s;s;s;s;s",
          },
          {
            n: _("武当", "武當"),
            in: "武當派",
            npc1: "wudang_zhang",
            v1: "jh 10;w;n;n;w;w;w;n;n;n;n;n;n;n;n;n",
          },
          {
            n: _("铁旗", "鐵旗"),
            in: "大旗門",
            npc1: "tieflag_yedi",
            v1: "jh 25;e;e;e;e;s;yell;s;e;event_1_81629028;s;e;n;w;w",
          },
          {
            n: "明教",
            in: "明教",
            npc1: "mingjiao_zhang",
            v1: "jh 18;n;nw;n;n;n;n;n;ne;n;n;n;n;n;n;n;n;n;n",
          },
          {
            n: "全真",
            in: "全真派",
            npc1: "quanzhen_wantong",
            v1: "jh 19;s;s;s;sw;s;e;n;nw;n;n;n;n;n;n;n;n;n;w;w;n",
          },
          {
            n: _("丐帮", "丐幫"),
            in: "丐幫",
            npc1: "gaibang_hong",
            v1: "jh 2;n;n;n;n;n;e;n;op1",
          },
          {
            n: "峨眉",
            in: "峨嵋派",
            npc1: "houshan_miejue",
            v1: "jh 8;w;nw;n;n;n;n;e;e;n;n;e;kill emei_shoushan;n;n;n;n;w;n;n;n;n;n;n;n;n;n;ne;ne;n",
          },
          {
            n: "步玄",
            in: "步玄派",
            npc1: "scholar_master",
            v1: "jh 7;s;s;s;s;s;s;s;s;e;n;e;s;e",
          },
          {
            n: _("逍遥", "逍遙"),
            in: "逍遙派",
            npc1: "xiaoyao_tonglao",
            v1: "jh 16;s;s;s;s;e;n;e;event_1_5221690;s;w;event_1_57688376;n;n;e;n;event_1_88625473;event_1_82116250;event_1_90680562;event_1_38586637",
          },
          {
            n: "慕容",
            in: "慕容世家",
            npc1: "murong_murongbo",
            v1: "jh 32;n;n;se;n;n;n;n;w;w;w;n;event_1_72278818;event_1_35141481;event_1_35141481;event_1_35141481;event_1_35141481;event_1_35141481;event_1_35141481;w",
          },
          { n: "古墓", in: "古墓派", npc1: "gumu_yangguo", v1: "jh 30;n;n;ne" },
          {
            n: "桃花",
            in: "桃花島",
            npc1: "taohua_huang",
            v1: "jh 30;n;n;n;n;n;n;n;n;n;n;n;n;n;n",
          },
          {
            n: "茅山",
            in: "茅山派",
            npc1: "taoist_zhangtianshi",
            v1: "jh 29;n;n;n;n;event_1_60035830;place?平台;event_1_65661209;place?無名山峽谷;n",
          },
          {
            n: _("铁雪", "鐵雪"),
            in: "鐵雪山莊",
            npc1: "resort_master",
            v1: "jh 31;n;n;n;w;w;w;w;n;n;n",
          },
          {
            n: "封山",
            in: "封山劍派",
            npc1: "swordsman_master",
            v1: "jh 1;e;n;e;e;e",
          },
          {
            n: _("断剑", "斷劍"),
            in: "斷劍山莊",
            npc1: "duanjian_feng",
            v1: "jh 34;ne;e;e;e;e;e;n;n;n;w;w;w;n;n;yell;n;n;n;n;n;n;e;e;event_1_10251226",
          },
          {
            n: _("风花", "風花"),
            in: "風花牧場",
            npc1: "wujinshenyuan_songhou",
            v1: "jh 1;e;n;n;n;n;w;event_1_90287255 go 6;e;s;sw;se;ne;se;s;event_1_90371900;",
          },
          {
            n: "天波",
            in: "天波楊門",
            npc1: "kaifeng_yangyanzhao",
            v1: "jh 17;n;n;n;n;w;w;w;w",
          },
          {
            n: _("燕云", "燕雲"),
            in: "燕雲世家",
            npc1: "bihaishanzhuang_yelvchuge",
            v1: "jh 38;n;n;n;n;n;n;n;n;n",
          },
          {
            n: "西夏",
            in: "西夏堂",
            npc1: "jueqinggu_kmyh",
            v1: "jh 37;n;e;e;nw;nw;w;n;e;n;e;e;e;ne;nw;w;n;nw;n;ne;e;ne;se",
          },
          { n: _("自动", "自動"), v1: "eval_PLU.master_auto()" },
        ];
        PLU.YFD.mapsLib.Map = [
          {
            jh: "1",
            loc: "全圖",
            name: "雪亭鎮",
            way: "jh 1;inn_op1;w;e;n;s;e;w;s;e;s;w;s;n;w;e;e;e;ne;ne;sw;sw;n;w;n;w;e;e;e;n;s;e;e;n;s;s;n;e;w;w;w;w;w;n;w;e;n;w;e;e;e;w;w;n;e;w;w;e;n",
            desc: "采集者:王辉",
          },
          {
            jh: "2",
            loc: "全圖",
            name: "洛陽",
            way: "jh 2;n;n;e;s;luoyang317_op1;n;n;w;n;w;putuan;n;e;e;s;n;w;n;e;s;n;w;w;event_1_98995501;n;w;e;n;e;w;s;s;s;s;w;e;n;e;n;w;s;luoyang111_op1;e;n;w;n;w;get_silver;s;e;n;n;e;get_silver;n;w;s;s;s;e;n;n;w;e;s;s;e;e;n;op1;s;s;e;n;n;w;e;e;n;s;w;n;w;e;n;e;w;n;w;e;s;s;s;s;s;w;w;n;w;e;e;n;s;w;n;e;w;n;w;luoyang14_op1;n;e;e;w;n;e;n;n;n;s;s;s;w;n;w;w;w;w;e;e;e;e;n;n;n;n",
            desc: "采集者:王辉",
          },
          {
            jh: "3",
            loc: "全圖",
            name: "華山村",
            way: "jh 3;n;e;w;s;w;n;s;event_1_59520311;n;n;w;get_silver;s;e;n;n;e;get_silver;n;w;n;e;w;s;s;s;s;s;e;e;s;e;n;s;w;s;e;s;huashancun24_op2;w;n;w;w;n;s;e;s;s;w;get_silver;n;n;s;e;huashancun15_op1;event_1_46902878;kill?藏劍樓殺手;@藏劍樓殺手的屍體;w;w;s;e;w;nw;n;n;e;get_silver;s;w;n;w;give huashancun_huashancun_fb9;e;e;n;n;w;e;n;s;e",
            desc: "采集者:戴爽",
          },
          {
            jh: "4",
            loc: "全圖",
            name: "華山",
            way: "jh 4;n;n;w;e;n;e;w;n;n;n;n;event_1_91604710;s;s;s;w;get_silver;s;e;s;e;w;n;n;n;n;nw;s;s;w;n;n;w;s;n;w;n;get_xiangnang2;w;s;e;e;n;e;n;n;w;w;event_1_26473707;e;e;e;n;e;s;event_1_11292200;n;n;w;n;e;w;n;s;s;s;s;s;w;n;n;n;w;e;n;get_silver;s;s;e;n;n;s;s;s;s;n;n;w;s;s;w;event_1_30014247;s;w;e;s;e;w;s;s;s;e",
            desc: "采集者:王辉",
          },
          {
            jh: "5",
            loc: "全圖",
            name: "揚州",
            way: "jh 5;n;w;w;n;s;e;e;e;w;n;w;e;e;w;n;w;e;e;n;w;e;n;w;n;get_silver;s;s;e;e;get_silver;n;w;n;n;s;e;w;s;s;s;w;n;w;yangzhou16_op1;e;e;n;e;n;n;n;s;s;w;n;e;n;n;s;s;w;n;n;e;n;n;event_1_89774889;s;s;s;e;s;s;s;w;s;w;w;w;n;n;w;n;n;n;s;s;s;e;n;get_silver;s;s;e;e;w;w;s;s;s;s;n;n;e;e;n;w;e;e;n;n;n;n;s;s;e;w;w;e;s;s;w;n;w;e;e;get_silver;s;w;n;w;w;n;get_silver;s;s;w;s;w;e;e;e;s;s;e;e;s;s;s;n;n;n;w;w;n;n;w;w;n;e;e;e;n;e;s;e;s;s;s;n;n;n;w;n;w;n;ne;sw;s;w;s;n;w;n;w;e;e;w;n;n;w;n;s;e;e;s;n;w;n;s;s;s;s;e;e;s;s;s;w;event_1_69751810",
            desc: "采集者:王辉",
          },
          {
            jh: "6",
            loc: "全圖",
            name: "丐幫",
            way: "jh 6;event_1_98623439;s;w;e;n;ne;n;ne;ne;ne;event_1_97428251;n;sw;sw;sw;s;ne;ne;event_1_16841370",
            desc: "采集者:王辉",
          },
          {
            jh: "7",
            loc: "全圖",
            name: "喬陰縣",
            way: "jh 7;s;s;s;w;s;w;w;w;e;e;e;e;event_1_65599392;n;s;w;e;ne;s;s;e;n;n;e;w;s;s;w;s;w;w;w;n;s;s;e;n;s;e;ne;s;e;n;e;s;e",
            desc: "采集者:树",
          },
          {
            jh: "8",
            loc: "全圖",
            name: "峨眉山",
            way: "jh 8;w;nw;n;n;n;n;w;e;se;nw;e;n;s;e;n;n;e;kill?看山弟子;n;n;n;n;e;e;w;w;w;n;n;n;w;w;s;e;w;w;e;s;e;w;w;e;n;n;w;w;n;s;sw;ne;e;e;n;e;w;w;e;n;e;w;w;e;n;w;w;w;n;n;n;s;s;s;e;e;e;e;e;s;s;s;e;e;s;w;e;e;w;s;w;e;e;w;n;n;e;e;w;w;n;w;e;e;w;n;w;e;e;w;n;e;e;w;w;w;w;n;w;w;e;n;s;s;n;e;n;n;n;n;s;s;nw;nw;n;n;s;s;se;sw;w;nw;w;e;se;e;ne;se;ne;se;s;se;nw;n;nw;ne;n;s;se;e",
            desc: "采集者:王辉",
          },
          {
            jh: "9",
            loc: "全圖",
            name: "恆山",
            way: "jh 9;n;w;e;n;e;get_silver;w;w;n;w;e;n;henshan15_op1;e;e;w;n;event_1_85624865;n;w;event_1_27135529;e;e;e;w;n;n;n;s;henshan_zizhiyu11_op1;e;s;s;s;w;n;n;w;n;s;s;n;e;e;e;w;n;s;w;n;n;w;n;e;n;s;w;n;n;w;get_silver;s;e;n",
            desc: "采集者:王辉",
          },
          {
            jh: "10",
            loc: "全圖",
            name: "武當山",
            way: "jh 10;w;n;n;w;w;w;n;n;n;n;e;e;e;e;s;e;s;e;n;s;s;n;e;e;n;s;e;w;s;s;s;n;n;n;w;w;w;n;w;n;w;w;w;w;n;w;n;s;e;e;e;s;n;e;e;w;w;w;w;n;n;n;n;jh 10;w;n;event_1_74091319;ne;n;sw;nw;w;ne;n;w;nw;sw;ne;n;nw;event_1_5824311",
            desc: "采集者:王辉",
          },
          {
            jh: "11",
            loc: "全圖",
            name: "晚月莊",
            way: "jh 11;e;e;s;sw;se;w;n;s;w;w;s;n;w;e;e;s;w;e;s;e;e;e;w;w;w;w;s;n;w;n;s;s;n;e;e;s;w;w;e;e;e;e;w;w;s;e;e;w;w;n;e;n;n;w;n;n;n;e;e;s;s;s;w;s;s;w;e;se;e;se;ne;n;nw;w;s;s;s;se;s",
            desc: "采集者:戴爽",
          },
          {
            jh: "12",
            loc: "全圖",
            name: "水煙閣",
            way: "jh 12;n;e;w;n;n;n;s;w;n;n;e;w;s;nw;e;e;sw;n;s;s;e;w;n;ne;w;n",
            desc: "采集者:王辉",
          },
          {
            jh: "13",
            loc: "全圖",
            name: "少林寺",
            way: "jh 13;e;s;s;w;w;w;event_1_38874360;jh 13;n;w;w;n;shaolin012_op1;s;s;e;e;n;w;e;e;w;n;n;w;e;e;w;n;n;w;e;e;w;n;shaolin27_op1;event_1_34680156;s;w;n;w;e;e;w;n;shaolin25_op1;w;n;w;s;s;s;get_silver;w;s;s;s;s;s;n;n;n;n;n;n;n;n;e;e;s;s;s;s;get_silver;w;s;s;s;get_silver;w;s;n;n;n;n;n;n;n;n;w;n;w;e;e;w;n;e;w;w;n;get_silver",
            desc: "采集者:王辉",
          },
          {
            jh: "14",
            loc: "全圖",
            name: "唐門",
            way: "jh 14;e;w;w;n;n;n;n;s;w;n;s;s;n;w;n;s;s;n;w;n;s;s;n;w;e;e;e;e;e;s;n;e;n;e;w;n;n;s;ask tangmen_tangmei;ask tangmen_tangmei;e;event_1_8413183;event_1_39383240;e;s;e;n;w;n;n;s;s;e",
            desc: "采集者:王辉",
          },
          {
            jh: "15",
            loc: "全圖",
            name: "青城山",
            way: "jh 15;s;ne;sw;s;e;w;w;n;s;e;s;e;w;w;w;n;s;s;s;n;n;w;w;w;n;s;w;e;e;e;e;e;e;s;e;w;w;e;s;e;w;s;w;s;ne;s;s;s;e;s;n;w;n;n;n;n;n;n;n;n;n;n;nw;w;nw;w;s;s;s;kill?申月富;w;w;n;w;e;e;w;n;w;s;w;s;e;s;n;e;e;e;n;n;n;e;n;event_1_14401179",
            desc: "采集者:東方鳴",
          },
          {
            jh: "16",
            loc: "全圖",
            name: "逍遙林",
            way: "jh 16;s;s;s;s;e;e;s;w;n;s;s;s;n;n;w;n;n;s;s;s;s;n;n;w;w;n;s;s;n;w;e;e;e;e;e;e;n;n;e;event_1_5221690;s;w;event_1_57688376;n;n;w;w;e;n;s;e;e;n;event_1_88625473;event_1_82116250;event_1_90680562;event_1_38586637;s;s;e;n;n;w;n;e;jh 16;s;s;s;s;e;n;e;event_1_56806815;jh 16;s;s;s;s;e;n;e;event_1_5221690;s;w;event_1_57688376;n;n;#8 event_1_38333366;",
            desc: "采集者:『空白』",
          },
          {
            jh: "17",
            loc: "全圖",
            name: "開封",
            way: "jh 17;n;w;e;e;s;n;w;n;w;s;n;n;n;s;s;e;e;e;s;n;n;n;s;s;w;s;s;s;w;e;s;w;e;n;e;n;s;s;n;e;e;jh 17;n;n;n;e;w;n;e;w;n;e;se;s;n;nw;n;n;n;event_1_27702191;jh 17;n;n;n;n;w;w;n;s;s;n;w;w;e;n;n;w;e;s;s;s;s;w;jh 17;sw;nw;se;s;sw;nw;ne;event_1_38940168;jh 17;e;s;s;s;e;kaifeng_yuwangtai23_op1;s;w;s;s;w;jh 17;n;n;e;e;n;get_silver",
            desc: "采集者:王辉",
          },
          {
            jh: "18",
            loc: "全圖",
            name: "明教",
            way: "jh 18;w;n;s;e;e;w;n;nw;sw;ne;n;n;w;e;n;n;n;ne;n;n;e;w;w;e;n;e;w;w;e;n;n;e;e;se;se;e;w;nw;nw;n;w;w;w;w;s;s;n;e;w;n;n;n;e;nw;nw;se;se;e;s;w;e;e;w;n;e;e;se;e;w;sw;s;w;w;n;e;w;n;n;n;n;n;w;e;n;event_1_90080676;event_1_56007071;ne;n;nw;se;s;s;e;n;w;nw;sw;se;e;se;nw;s;s;s;s;w;nw;nw;event_1_70957287;event_1_39374335;kill?九幽毒童;event_1_2077333",
            desc: "采集者:淼淼淼、戴爽",
          },
          {
            jh: "19",
            loc: "全圖",
            name: "全真教",
            way: "jh 19;s;s;s;sw;s;e;n;nw;n;n;n;n;w;e;e;w;n;w;w;w;s;n;w;s;n;e;e;e;e;e;n;s;e;n;n;s;s;e;w;w;w;n;n;n;w;e;e;s;n;e;n;n;n;n;s;e;s;n;n;n;w;n;w;w;w;s;s;s;s;s;e;n;n;n;s;w;s;n;w;n;s;s;s;w;n;n;n;s;w;s;s;s;s;e;s;s;n;n;e;s;s;n;n;e;e;n;n;n;n;w;w;w;n;n;e;n;e;e;n;n",
            desc: "采集者:24叶欣贤、戴爽",
          },
          {
            jh: "20",
            loc: "全圖",
            name: "古墓",
            way: "jh 20;s;s;n;n;w;w;s;e;s;s;s;s;s;sw;sw;s;e;se;nw;w;s;w;e;e;w;s;s;w;w;e;e;s;w;sw;ne;e;s;s;s;n;w;w;e;e;e;e;e;e;s;e;w;n;w;n;n;s;e;w;w;s;n;n;event_1_3723773;se;n;e;s;e;s;e;",
            desc: "采集者:東方鳴",
          },
          {
            jh: "21",
            loc: "全圖",
            name: "白馱山",
            way: "jh 21;nw;s;n;ne;ne;sw;n;n;ne;w;e;n;n;n;s;w;w;jh 21;nw;w;n;s;w;nw;e;w;nw;nw;n;w;sw;ne;s;event_1_47975698;s;sw;s;ne;e;s;s;jh 21;nw;w;w;nw;n;e;w;n;n;w;e;n;n;e;e;w;nw;se;e;ne;sw;e;se;nw;w;n;s;s;n;w;w;n;n;n;n;s;s;s;s;e;e;e;n;n;w;e;e;e;w;w;n;nw;se;ne;w;e;e;w;n",
            desc: "采集者:王辉",
          },
          {
            jh: "22",
            loc: "全圖",
            name: "嵩山",
            way: "jh 22;n;n;w;w;s;s;e;w;s;s;w;e;s;n;n;n;n;n;e;n;n;n;n;n;e;n;e;e;w;w;n;w;n;s;e;n;n;n;e;songshan33_op1;n;w;w;w;e;n;w;e;n;s;s;e;n;e;w;n;e;w;n;get_silver;jh 22;n;n;n;n;e;n;event_1_1412213;s;event_1_29122616;jh 22;n;n;n;n;n;n;n",
            desc: "采集者:王辉",
          },
          {
            jh: "23",
            loc: "全圖",
            name: "寒梅莊",
            way: "jh 23;n;n;e;w;n;n;n;n;n;w;w;e;e;e;s;n;w;n;w;n;s;w;e;e;e;n;s;w;n;n;e;w;event_1_8188693;n;n;w;e;n;e;n;s;w;n;s;s;s;s;s;w;n",
            desc: "采集者:@远",
          },
          {
            jh: "24",
            loc: "全圖",
            name: "泰山",
            way: "jh 24;se;nw;n;n;n;n;w;e;e;e;w;s;n;w;n;n;w;e;e;w;n;e;w;n;w;n;n;n;n;n;s;s;w;n;s;e;s;s;s;e;n;e;w;n;w;e;n;n;e;s;n;e;n;e;w;n;w;e;e;w;n;n;s;s;s;s;s;w;w;n;n;w;e;e;w;n;n;w;e;e;w;n;s;s;s;s;s;w;n;e;w;n;w;e;n;n;e",
            desc: "采集者:王辉",
          },
          {
            jh: "25",
            loc: "全圖",
            name: "大旗門",
            way: "jh 11;e;e;s;n;nw;w;nw;e;e;e;n;w;e;s;se;jh 25;w;e;e;e;e;e;s;yell;n;s;e;ne;se;e;e;e;e;w;w;w;w;nw;sw;w;s;e;event_1_81629028;s;e;n;w;w;s;w",
            desc: "采集者:24叶欣贤",
          },
          {
            jh: "26",
            loc: "全圖",
            name: "大昭寺",
            way: "jh 26;w;w;w;w;w;n;s;w;s;w;e;e;e;w;w;s;w;w;w;s;n;w;n;n;n;n;n;e;e;e;e;e;w;s;s;w;w;n;w;e;e;w;s;w;n;s;s;n;w;ask?lama_master;event_1_91837538",
            desc: "采集者:王辉",
          },
          {
            jh: "27",
            loc: "全圖",
            name: "魔教",
            way: "jh 27;se;e;e;e;w;w;w;nw;ne;w;e;n;ne;sw;s;nw;w;nw;w;w;kill?船夫;@船夫的屍體;yell;w;nw;sw;ne;n;n;n;n;n;n;n;w;n;n;n;n;n;n;n;n;n;n;yell;n;n;n;n;w;e;e;w;n;e;n;s;w;n;nw;n;s;se;ne;n;s;sw;w;ne;n;s;ne;n;n;s;s;nw;n;s;se;w;n;s;e;sw;n;s;ne;se;n;s;nw;e;e;n;s;s;n;e;n;s;s;n;e;n;s;s;n;e;n;s;s;n;e;n;s;s;n;w;w;w;w;w;n;n;n;n;n;w;w;w;w;w;e;e;e;e;e;e;e;e;e;e;w;w;w;w;w;n;n;event_1_57107759;e;e;n;w",
            desc: "采集者:王辉",
          },
        ];
        // 路径没完整
        PLU.YFD.mapsLib.Map.push(
          ...[
            {
              jh: "28",
              loc: "全圖",
              name: "星宿海",
              way: "jh 28;sw;nw;sw;se;ne;nw;nw;w;e;e;n;w;w;w;w;n;w;se;n;n;se;n;n;n;n;nw;w;ne;se;n;n;n;n;se",
              desc: "",
            },
            {
              jh: "29",
              loc: "全圖",
              name: "茅山",
              way: "jh 29;n;n;n;n;event_1_60035830;event_1_65661209;n;n;n;n;n;e;n;n;n;event_1_98579273;w;nw;e;n;e;e",
              desc: "",
            },
            {
              jh: "30",
              loc: "全圖",
              name: "桃花島",
              way: "jh 30;n;n;ne;n;n;n;w;e;n;n;w;w;e;n;s;n;n;n;w;w;s;s;e;n;s;e;n;e;n;s;nw;w;n;n;n;e;e;n;se;s",
              desc: "",
            },
            {
              jh: "31",
              loc: "全圖",
              name: "鐵雪山莊",
              way: "jh 31;n;n;n;w;w;w;w;n;n;n;n;w;e",
              desc: "",
            },
            {
              jh: "32",
              loc: "全圖",
              name: "慕容山莊",
              way: "jh 32;n;n;se;e;s;s;n;w;ne;n;n;n;e;n;w;s;w;w;n;event_1_72278818;event_1_35141481;event_1_35141481;event_1_35141481;event_1_35141481;w;w;n;e;n;e;n;w;e;n;event_1_55226665;n;event_1_99232080;e;e;s;e;s;e;e;e;n;s",
              desc: "",
            },
            {
              jh: "33",
              loc: "全圖",
              name: "大理",
              way: "jh 33;sw;sw;s;s;s;nw;n;nw;n;n;n;n;n;e;n;s;e;sw;w;w;s;s;e;s;w;se;e;s;s;s;w;w;se;e;s;ne;e;se;n;n;n;n;n;w;ne;se;s;w;w;n;se;w;w;s;nw;n;e;se;n;n;w;se;e;se;e;se;e;e;n;s;e;e;se;e;e;se;n;n;n;n;n;n;e;n;n;n;e;e;se;e;s;ne;e;se;e;e;s;ne;e;n;sw;s;s;e;n;e;n;e;s;e;s;e;e;e;s;w;n;n;s;s;s;w;n;n;n;n;w;e;n;e;n;se;w;n;w;e;n;e;e;s;n;n;w;e;n;ne;n;e;e;n;s;e;ne;se;se;n;n;n;e;s;w;w;e;n;e;s;s;e;n;s;w;n;se;n;ne;s;w;e;n;s;s;e;s;w;se;s;s;s;e;n;sw;sw;w;s;n;n;s;e;n;n;n;s;e;se;s;sw;n;w;s",
              desc: "",
            },
            {
              jh: "34",
              loc: "全圖",
              name: "斷劍山莊",
              way: "jh 34;ne;e;e;e;e;e;n;n;n;w;w;w;n;n;n;n;w;n;e;e;n;n",
              desc: "",
            },
            {
              jh: "35",
              loc: "全圖",
              name: "冰火島",
              way: "jh 35;nw;nw;nw;n;ne;nw;w;nw;e;e;e;e;e;se;s;se;w;nw;s;s;s;s;s;s;w;w;n;e;n;w;w;s;s",
              desc: "",
            },
            { jh: "36", loc: "全圖", name: "俠客島", way: "", desc: "" },
            {
              jh: "37",
              loc: "全圖",
              name: "絕情谷",
              way: "jh 37;n;e;e;nw;nw;w;n;nw;n;n;ne;n;nw;se;s;sw;s;s;se;e;n;e;e;e;ne;ne;ne;se;s;s;s;w;e;n;n;n;nw;sw;sw;nw;w;n;nw;n;ne;e;ne;se;nw;sw;w;sw;nw;w;n;nw;n;s;se;s;e;n;nw;n;nw;se;s;se;s;ne;n;ne;sw;s;sw;n;ne;e;ne;e;n",
              desc: "",
            },
            {
              jh: "38",
              loc: "全圖",
              name: "碧海山莊",
              way: "jh 38;n;n;n;n;w;w;e;e;n;n;n;w;w;nw;w;w;n;n;s;s;e;e;se;e;e;n;n;e;se;s;e;w;n;nw;w;n;n;e;e;se;se;e;n;n;n;s;s;s;w;nw;nw;w;w;n;n;n;n",
              desc: "",
            },
            {
              jh: "39",
              loc: "全圖",
              name: "天山",
              way: "jh 39;ne;e;n;nw;nw;w;s;s;sw;n;nw;e;sw;w;s;w;n;w;",
              desc: "",
            },
            {
              jh: "40",
              loc: "全圖",
              name: "苗疆",
              way: "jh 40;s;s;s;s;e;s;se;sw;s;s;s;e;e;sw;se;sw;se",
              desc: "",
            },
            {
              jh: "41",
              loc: "全圖",
              name: "白帝城",
              way: "jh 41;se;e;e;se;se;se;se;se;se;event_1_57976870;e;e;w;w;n;n;n;s;s;s;w;w;w",
              desc: "",
            },
            {
              jh: "42",
              loc: "全圖",
              name: "墨家機關城",
              way: "jh 42;nw;ne;n;e;nw;e;nw;w;ne;se;n;nw;e;n;w;n;n;n;n;w;w;n;n;n;e;w;s;s;s;e;e;e;e;n;n;n;w",
              desc: "",
            },
            {
              jh: "43",
              loc: "全圖",
              name: "掩月城",
              way: "jh 43;n;ne;ne;n;n;n;nw;n;ne;ne;n;n;w;nw;nw;n;n;n;n;ne;ne;nw;ne;ne;n;n;ne;e;se;se;se;sw;sw;s;e;s;s;s",
              desc: "",
            },
            {
              jh: "44",
              loc: "全圖",
              name: "海雲閣",
              way: "jh 44;n;n;n;n;w;w;nw;n;n;ne;n;n;e;n;n;n;e;e;e;e;e;e;n;n;n;n;n;n;n;n;n;n;n;n;n;e;e;ne;ne;e;se;se;se;ne;ne;n;n;n;n;nw",
              desc: "",
            },
            {
              jh: "45",
              loc: "全圖",
              name: "幽冥山莊",
              way: "jh 45;ne;ne;n;n;ne;ne;e;ne;n;n;n;n;n;ne;ne;n;n;n;nw;nw;n;e;e;e;e;e",
              desc: "",
            },
            {
              jh: "46",
              loc: "全圖",
              name: "花街",
              way: "jh 46;e;e;e;e;e;e;e;e;e;e;e;e;e;e;e;w;w;w;w;w;w;w;n;n;n;e;e;e;w;w;e;s;n;n",
              desc: "",
            },
            {
              jh: "47",
              loc: "全圖",
              name: "西涼城",
              way: "jh 47;ne;n;n;n;ne;ne;e;e;e;e;ne;n;ne;e;e;n;n;n;n;n;n;ne;n",
              desc: "",
            },
            {
              jh: "48",
              loc: "全圖",
              name: "高昌迷宮",
              way: "jh 48;e;se;se;e;ne;se;e;e;e;ne;se;se;s;s;s;sw;sw;s;sw;se",
              desc: "",
            },
            { jh: "49", loc: "全圖", name: "京城", way: "", desc: "" },
            {
              jh: "50",
              loc: "全圖",
              name: "越王劍宮",
              way: "jh 50;ne;ne;n;n;n;ne;ne;ne;n;n;n;s;s;s;se;se;se;s;s;s;s;sw;sw;sw;ne;ne;ne;se;se;e;n;n;n;e;w;n;n;n;n;n;w;e;n;n;n",
              desc: "",
            },
            {
              jh: "51",
              loc: "全圖",
              name: "江陵",
              way: "jh 51;n;n;w;e;e;w;n;n;w;w;n;n;s;s;e;e;e;e;e;e;s;s;n;n;e;e;e;e;se;e;e;w;w;nw;w;w;s;s;s;se;se;e;e;w;w;nw;nw;n;n;n;w;w;n;n;e;w;w;w;e;e;n;n;nw;n;n;n;e;e",
              desc: "",
            },
            { jh: "52", loc: "全圖", name: "天龍寺", way: "", desc: "" },
            { jh: "53", loc: "全圖", name: "西夏", way: "", desc: "" },
            { jh: "54", loc: "全圖", name: "南詔國", way: "", desc: "" },
          ],
        );
        PLU.YFD.qixiaList = [
          "宇文無敵",
          "李玄霸",
          "夏嶽卿",
          "玄月研",
          "穆妙羽",
          "烈九州",
          "厲滄若",
          "八部龍將",
          "妙無心",
          "巫夜姬",
          "狼居胥",
          "風行騅",
          "風無痕",
          "吳縝",
          "狐蒼雁",
          "護竺",
          "李宇飛",
          "龐統",
          "逆風舞",
          "王蓉",
          "浪喚雨",
          "火雲邪神",
          "風南",
          "郭濟",
          "步驚鴻",
        ];
        PLU.YFD.qixiaFriend = [
          { name: "宇文無敵", skillFN: 40000 },
          { name: "李玄霸", skillFN: 40000 },
          { name: "夏嶽卿", skillFN: 40000 },
          { name: "玄月研", skillFN: 40000 },
          { name: "穆妙羽", skillFN: 40000 },
          { name: "烈九州", skillFN: 40000 },
          { name: "厲滄若", skillFN: 40000 },
          { name: "八部龍將", skillFN: 40000 },
          { name: "妙無心", skillFN: 40000 },
          { name: "巫夜姬", skillFN: 40000 },
          { name: "狼居胥", skillFN: 40000 },
          { name: "風行騅", skillFN: 40000 },
          { name: "風無痕", skillFN: 40000 },
          { name: "吳縝", skillFN: 40000 },
          { name: "狐蒼雁", skillFN: 35000 },
          { name: "護竺", skillFN: 35000 },
          { name: "李宇飛", skillFN: 25000 },
          { name: "龐統", skillFN: 25000 },
          { name: "逆風舞", skillFN: 25000 },
          { name: "王蓉", skillFN: 25000 },
          { name: "浪喚雨", skillFN: 25000 },
          { name: "火雲邪神", skillFN: 25000 },
          { name: "風南", skillFN: 25000 },
          { name: "郭濟", skillFN: 25000 },
          { name: "步驚鴻", skillFN: 25000 },
        ];
        PLU.YFD.youxiaList = [
          {
            n: "門客",
            v: [
              "王語嫣",
              "範蠡",
              "程靈素",
              "水靈光",
              "霍青桐",
              "石青璇",
              "李紅袖",
              "宋玉緻",
              "華佗",
              "魯妙子",
              "顧倩兮",
              "水笙",
              "林仙兒",
              "郭襄",
              "程瑛",
              "任盈盈",
              "阿朱",
              "袁紫衣",
              "趙敏",
              "小昭",
              "韋小寶",
            ],
          },
          {
            n: "邪武",
            v: [
              "林遠圖",
              "厲工",
              "金輪法王",
              "鳩摩智",
              "上官金虹",
              "封寒",
              "卓淩昭",
              "厲若海",
              "乾羅",
              "孫恩",
              "婠婠",
              "練霓裳",
              "成昆",
              "侯希白",
              "夜魔",
            ],
          },
          {
            n: "俠客",
            v: [
              "0柯鎮惡",
              "哈瑪雅",
              "喬峰",
              "盧雲",
              "虛竹",
              "徐子陵",
              "虛夜月",
              "雲夢璃",
              "花無缺",
              "風行烈",
              "黃藥師",
              "洪七公",
              "石破天",
              "寧不凡",
              "獨孤求敗",
            ],
          },
          { n: "魔尊", v: ["龐斑", "楊肅觀", "歐陽鋒", "葉孤城", "燕狂徒"] },
          { n: "宗師", v: ["宋缺", "逍遙子", "李尋歡", "令東來", "楚留香"] },
        ];
        PLU.YFD.youxiaSkillMap = [
          {
            skill: "長春不老功",
            name: "逍遙子",
            kind: "宗師",
            type: "內功",
            pre: [
              {
                skill: "龍象般若功",
                name: "金輪法王",
                kind: "邪武",
                type: "內功",
                lvl: 40,
              },
              {
                skill: "紫血大法",
                name: "厲工",
                kind: "邪武",
                type: "內功",
                lvl: 40,
              },
            ],
          },
          {
            skill: "九陰逆",
            name: "歐陽鋒",
            kind: "魔尊",
            type: "內功",
            pre: [
              {
                skill: "白首太玄經",
                name: "石破天",
                kind: "俠客",
                type: "內功",
                lvl: 40,
              },
              {
                skill: "彈指神通",
                name: "黃藥師",
                kind: "俠客",
                type: "掌法",
                lvl: 40,
              },
            ],
          },
          {
            skill: "鳳舞九天",
            name: "宮九",
            kind: "魔尊",
            type: "輕功",
            pre: [
              {
                skill: "天魔妙舞",
                name: "婠婠",
                kind: "邪武",
                type: "輕功",
                lvl: 120,
              },
              {
                skill: "雲夢歸月",
                name: "雲夢璃",
                kind: "俠客",
                type: "輕功",
                lvl: 120,
              },
              {
                skill: "飛鴻鞭法",
                name: "哈瑪雅",
                kind: "俠客",
                type: "鞭法",
                lvl: 120,
              },
              {
                skill: "踏月留香",
                name: "楚留香",
                kind: "宗師",
                type: "輕功",
                lvl: 120,
                pre: [
                  {
                    skill: "天魔妙舞",
                    name: "婠婠",
                    kind: "邪武",
                    type: "輕功",
                    lvl: 40,
                  },
                  {
                    skill: "雲夢歸月",
                    name: "雲夢璃",
                    kind: "俠客",
                    type: "輕功",
                    lvl: 40,
                  },
                  {
                    skill: "降魔杖法",
                    name: "0柯鎮惡",
                    kind: "俠客",
                    type: "杖法",
                    lvl: 40,
                  },
                  {
                    skill: "飛鴻鞭法",
                    name: "哈瑪雅",
                    kind: "俠客",
                    type: "鞭法",
                    lvl: 40,
                  },
                ],
              },
            ],
          },
          {
            skill: "無劍之劍",
            name: "白雲天",
            kind: "宗師",
            type: "劍法",
            pre: [
              {
                skill: "天魔妙舞",
                name: "婠婠",
                kind: "邪武",
                type: "輕功",
                lvl: 120,
              },
              {
                skill: "神劍慧芒",
                name: "卓淩昭",
                kind: "邪武",
                type: "劍法",
                lvl: 120,
              },
              {
                skill: "不凡三劍",
                name: "寧不凡",
                kind: "俠客",
                type: "劍法",
                lvl: 120,
              },
              {
                skill: "天外飛仙",
                name: "葉孤城",
                kind: "魔尊",
                type: "劍法",
                lvl: 120,
                pre: [
                  {
                    skill: "紫虛辟邪劍",
                    name: "林遠圖",
                    kind: "邪武",
                    type: "劍法",
                    lvl: 40,
                  },
                  {
                    skill: "神劍慧芒",
                    name: "卓淩昭",
                    kind: "邪武",
                    type: "劍法",
                    lvl: 40,
                  },
                  {
                    skill: "不凡三劍",
                    name: "寧不凡",
                    kind: "俠客",
                    type: "劍法",
                    lvl: 40,
                  },
                ],
              },
            ],
          },
          {
            skill: "披羅紫氣",
            name: "伍定遠",
            kind: "宗師",
            type: "掌法",
            pre: [
              {
                skill: "雲夢歸月",
                name: "雲夢璃",
                kind: "俠客",
                type: "輕功",
                lvl: 120,
              },
              {
                skill: "降龍廿八掌",
                name: "喬峰",
                kind: "俠客",
                type: "掌法",
                lvl: 120,
              },
              {
                skill: "彈指神通",
                name: "黃藥師",
                kind: "俠客",
                type: "掌法",
                lvl: 120,
              },
              {
                skill: "天魔策",
                name: "龐斑",
                kind: "魔尊",
                type: "掌法",
                lvl: 120,
                pre: [
                  {
                    skill: "降龍廿八掌",
                    name: "喬峰",
                    kind: "俠客",
                    type: "掌法",
                    lvl: 40,
                  },
                  {
                    skill: "無相六陽掌",
                    name: "虛竹",
                    kind: "俠客",
                    type: "掌法",
                    lvl: 40,
                  },
                  {
                    skill: "折花百式",
                    name: "侯希白",
                    kind: "邪武",
                    type: "掌法",
                    lvl: 40,
                  },
                  {
                    skill: "釋迦拈花指",
                    name: "鳩摩智",
                    kind: "邪武",
                    type: "掌法",
                    lvl: 40,
                  },
                ],
              },
            ],
          },
          {
            skill: "火貪一刀",
            name: "方子敬",
            kind: "魔尊",
            type: "刀法",
            pre: [
              {
                skill: "天魔妙舞",
                name: "婠婠",
                kind: "邪武",
                type: "輕功",
                lvl: 120,
              },
              {
                skill: "左手刀法",
                name: "封寒",
                kind: "邪武",
                type: "刀法",
                lvl: 120,
              },
              {
                skill: "移花接玉刀",
                name: "花無缺",
                kind: "俠客",
                type: "刀法",
                lvl: 120,
              },
              {
                skill: "天刀八訣",
                name: "宋缺",
                kind: "宗師",
                type: "刀法",
                lvl: 120,
                pre: [
                  {
                    skill: "左手刀法",
                    name: "封寒",
                    kind: "邪武",
                    type: "刀法",
                    lvl: 40,
                  },
                  {
                    skill: "移花接玉刀",
                    name: "花無缺",
                    kind: "俠客",
                    type: "刀法",
                    lvl: 40,
                  },
                ],
              },
            ],
          },
          {
            skill: "天雷落",
            name: "石剛",
            kind: "魔尊",
            type: "暗器",
            pre: [
              {
                skill: "雲夢歸月",
                name: "雲夢璃",
                kind: "俠客",
                type: "輕功",
                lvl: 120,
              },
              {
                skill: "九字真言印",
                name: "徐子陵",
                kind: "俠客",
                type: "暗器",
                lvl: 120,
              },
              {
                skill: "九星定形針",
                name: "練霓裳",
                kind: "邪武",
                type: "暗器",
                lvl: 120,
              },
              {
                skill: "小李飛刀",
                name: "李尋歡",
                kind: "宗師",
                type: "暗器",
                lvl: 120,
                pre: [
                  {
                    skill: "九字真言印",
                    name: "徐子陵",
                    kind: "俠客",
                    type: "暗器",
                    lvl: 40,
                  },
                  {
                    skill: "九星定形針",
                    name: "練霓裳",
                    kind: "邪武",
                    type: "暗器",
                    lvl: 40,
                  },
                  {
                    skill: "子母龍鳳環",
                    name: "上官金虹",
                    kind: "邪武",
                    type: "暗器",
                    lvl: 40,
                  },
                ],
              },
            ],
          },
          {
            skill: "孤帆鞭影",
            name: "陸孤瞻",
            kind: "魔尊",
            type: "鞭法",
            pre: [
              {
                skill: "彈指神通",
                name: "黃藥師",
                kind: "俠客",
                type: "掌法",
                lvl: 120,
              },
              {
                skill: "降魔杖法",
                name: "0柯鎮惡",
                kind: "俠客",
                type: "杖法",
                lvl: 120,
              },
              {
                skill: "飛鴻鞭法",
                name: "哈瑪雅",
                kind: "俠客",
                type: "鞭法",
                lvl: 120,
              },
              {
                skill: "冰玄鞭法",
                name: "乾羅",
                kind: "邪武",
                type: "鞭法",
                lvl: 120,
              },
            ],
          },
          {
            skill: "無雙連錘",
            name: "瓦耳拉齊",
            kind: "魔尊",
            type: "錘法",
            pre: [
              {
                skill: "游龍劍",
                name: "孫恩",
                kind: "邪武",
                type: "劍法",
                lvl: 120,
              },
              {
                skill: "幻陰指錘",
                name: "成昆",
                kind: "邪武",
                type: "錘法",
                lvl: 120,
              },
              {
                skill: "正道十七",
                name: "盧雲",
                kind: "俠客",
                type: "錘法",
                lvl: 120,
              },
              {
                skill: "玉石俱焚",
                name: "燕狂徒",
                kind: "魔尊",
                type: "錘法",
                lvl: 120,
                pre: [
                  {
                    skill: "幻陰指錘",
                    name: "成昆",
                    kind: "邪武",
                    type: "錘法",
                    lvl: 40,
                  },
                  {
                    skill: "正道十七",
                    name: "盧雲",
                    kind: "俠客",
                    type: "錘法",
                    lvl: 40,
                  },
                ],
              },
            ],
          },
          {
            skill: "暗山神斧",
            name: "0六先生",
            kind: "魔尊",
            type: "斧法",
            pre: [
              {
                skill: "雲夢歸月",
                name: "雲夢璃",
                kind: "俠客",
                type: "輕功",
                lvl: 120,
              },
              {
                skill: "彈指神通",
                name: "黃藥師",
                kind: "俠客",
                type: "掌法",
                lvl: 120,
              },
              {
                skill: "降魔杖法",
                name: "0柯鎮惡",
                kind: "俠客",
                type: "杖法",
                lvl: 120,
              },
              {
                skill: "獨孤斧訣",
                name: "獨孤求敗",
                kind: "俠客",
                type: "斧法",
                lvl: 120,
              },
            ],
          },
          {
            skill: "六道輪迴",
            name: "楊肅觀",
            kind: "魔尊",
            type: "斧法",
            pre: [
              {
                skill: "天魔妙舞",
                name: "婠婠",
                kind: "邪武",
                type: "輕功",
                lvl: 40,
              },
              {
                skill: "青冥血斧",
                name: "夜魔",
                kind: "邪武",
                type: "斧法",
                lvl: 40,
              },
              {
                skill: "獨孤斧訣",
                name: "獨孤求敗",
                kind: "俠客",
                type: "斧法",
                lvl: 40,
              },
            ],
          },
          {
            skill: "溫候戟舞",
            name: "韓毅",
            kind: "魔尊",
            type: "槍法",
            pre: [
              {
                skill: "彈指神通",
                name: "黃藥師",
                kind: "俠客",
                type: "掌法",
                lvl: 120,
              },
              {
                skill: "冰月破魔槍",
                name: "風行烈",
                kind: "俠客",
                type: "槍法",
                lvl: 120,
              },
              {
                skill: "燎原百擊",
                name: "厲若海",
                kind: "邪武",
                type: "槍法",
                lvl: 120,
              },
              {
                skill: "神龍東來",
                name: "令東來",
                kind: "宗師",
                type: "槍法",
                lvl: 120,
                pre: [
                  {
                    skill: "冰月破魔槍",
                    name: "風行烈",
                    kind: "俠客",
                    type: "槍法",
                    lvl: 40,
                  },
                  {
                    skill: "燎原百擊",
                    name: "厲若海",
                    kind: "邪武",
                    type: "槍法",
                    lvl: 40,
                  },
                  {
                    skill: "月夜鬼蕭",
                    name: "虛夜月",
                    kind: "俠客",
                    type: "棍法",
                    lvl: 40,
                  },
                ],
              },
            ],
          },
        ];
        PLU.YFD.QuestAnsLibs["首次通过桥阴县不可以获得那种奖励?"] = "a";
        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;
  }

  function Base64() {
    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)));
  }
  //=================================================================================
  // UTIL模組
  //=================================================================================
  unsafeWindow.PLU = {
    version: "0.0.14beta15(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,
    },
    FLK: null,
    TMP: {},
    logHtml: "",
    signInMaps: null,
    //================================================================================================
    init() {
      this.accId = UTIL.getAccId();
      // 是否爲開發者
      this.devmode = [
        "8429379(1)",
        "8432668(1)",
        "8432667(1)",
        "8432616(1)",
      ].includes(this.accId);
      if (this.devmode) {
        UTIL.addSysListener("developer", (b, type, subtype, msg) => {
          if (type.indexOf("attr") == 0) return;
          if (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輔助")}
        ${_(
          "脚本开发",
          "腳本開發",
        )}:燕飞,<a onclick='clickButton(\"telluser u8429379(1)_U_東方鳴\", 1)'>東方鳴${_(
          "(点击反馈)",
          "(點擊反饋)",
        )}</a>
        ${_("脚本版本:", "腳本版本:")}${this.version}
        ${_("当前角色:", "當前角色:")}${this.nickName}${
          this.devmode ? _("(已开启开发者模式)", "(已開啓開發者模式)") : ""
        }
        角 色 ID :${this.accId}
        +===========================+</span>`,
      );
      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("autoLX") == 1)
        autosets += _("连续练习,", "連續練習, ");
      if (PLU.getCache("autoBF") == 1)
        autosets += _("加入帮四,", "加入幫四, ");
      if (PLU.getCache("autoB6") == 1)
        autosets += _("加入帮六,", "加入幫六, ");
      if (PLU.getCache("autoB5F") == 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")
            ? 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 YFBackupDispatchMsg = gSocketMsg.dispatchMessage;
      gSocketMsg.YFBackupDispatchMsg = YFBackupDispatchMsg;
      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);
      };
      PLU.initListeners();
      if (unsafeWindow.clickButton) {
        PLU.Base64 = new Base64();
        var proxy_clickButton = unsafeWindow.clickButton;
        unsafeWindow.clickButton = function () {
          let args = arguments;
          if (PLU.devmode) {
            console.log(args);
          }
          // 解除四海商店限制
          if (
            (args[0].indexOf("reclaim recl ") == 0 ||
              args[0].indexOf("reclaim buy ") == 0) &&
            !args[0].match(" page ")
          ) {
            let cmd = args[0].match(/^reclaim (recl|buy) (\d+) (go )?(.+)$/);
            if (cmd[1]) {
              let n = Number(cmd[2]);
              switch (cmd[1]) {
                case "recl":
                  for (; n > 50000; n -= 50000) {
                    proxy_clickButton(`reclaim recl 50000 go ${cmd[4]}`, 1);
                  }
                  proxy_clickButton(`reclaim recl ${n} go ${cmd[4]}`, 1);
                  break;
                case "buy":
                  for (; n > 50000; n -= 50000) {
                    proxy_clickButton(`reclaim buy 50000 go ${cmd[4]}`, 1);
                  }
                  proxy_clickButton(`reclaim buy ${n} go ${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((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: p.v,
          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.master_auto = () => {
        let family =
          g_obj_map.get("msg_attrs") &&
          g_obj_map.get("msg_attrs").get("family_name");
        var master = PLU.YFD.masterList.find((e) => e.in == family);
        PLU.execActions(master.v1 + ";apprentice " + master.npc1, () => {
          PLU.autoFight({
            targetKey: master.npc1,
            fightKind: "fight",
            autoSkill: "multi",
            onEnd() {
              PLU.execActions("chushi " + master.npc1);
            },
          });
        });
      };
      let masterArray = PLU.YFD.masterList.map((p, i) => {
        if (i == 32)
          return {
            id: "bt_master_33",
            text: p.n,
            extend: p.v1,
            style: { "background-color": "#FBB", width: "143px" },
          };
        let colr = i < 10 ? "#FCF" : i < 20 ? "#CFF" : "#FFC";
        return {
          id: "bt_master_" + (i + 1),
          text: p.n,
          extend: p.v1,
          style: { "background-color": colr },
        };
      });
      PathsArray.push({
        id: "bt_masters",
        text: _("出师", "出師"),
        style: { background: "#FCF", width: "40px", padding: "5px 2px" },
        menuStyle: { width: "160px", "margin-top": "-100px" },
        children: masterArray,
      });

      let dailyArray = PLU.YFD.dailyList.map((p, i) => {
        let colr = i < 6 ? "#FFC" : i < 20 ? "#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 },
        },
      ];
      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: { 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: "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" },
      });
      somethingArray.push({
        id: "bt_autoJHYL",
        text: "九花原料",
        extend: { func: PLU.buyJHYL },
        style: { background: "#DEF" },
      });
      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_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_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_autoQuitTeam",
        text: _("进塔离队", "進塔離隊"),
        extend: { key: "autoQuitTeam" },
        style: { background: "#EEF" },
      });
      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_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) {
            //$(".menu").hide()
            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,
          },
        ],
      });
      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 == "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);
          }
        },
      });
      //Sign
      let signArray = [];
      // signArray.push({id:"bt_answerQues", text:"自動答題", extend:{func:PLU.answerQues}})
      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_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 == "autoSignIn") {
              return PLU.setListen($btn, $btn.$extend.key);
            } else {
              $(".menu").hide();
              $btn.$extend.func($btn);
            }
          }
        },
      });
      //sys
      let sysArray = [];
      sysArray.push({
        id: "bt_openTeam",
        text: _("开队伍", "開隊伍"),
        extend: "team",
      });
      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_openQixia",
        text: "奇俠列表",
        extend: "open jhqx",
      });
      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: "hr_sys",
        text: "",
        style: { width: "160px", opacity: 0 },
        boxStyle: { "font-size": 0 },
      });
      sysArray.push({
        id: "bt_showMPFZ",
        text: _("纷争显示", "紛爭顯示"),
        extend: { func: PLU.showMPFZ },
        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.saveSetting },
        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 && $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.devmode) {
        let flagArray = [];
        flagArray.push({
          id: "bt_intervene",
          text: "介入戰鬥",
          extend: { func: PLU.intervene },
        });
        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_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) {
      let res = PLU.CACHE[key];
      return res == undefined || res == null ? "" : res;
    },
    //================================================================================================
    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;
        if (PLU.getCache("listenChat") == 1)
          PLU.setListen($("#btn_bt_listenChat"), "listenChat", 1);
        if (PLU.getCache("listenQL") == 1)
          PLU.setListen($("#btn_bt_listenQL"), "listenQL", 1);
        if (PLU.getCache("listenTF") == 1)
          PLU.setListen($("#btn_bt_listenTF"), "listenTF", 1);
        if (PLU.getCache("listenKFQL") == 1)
          PLU.setListen($("#btn_bt_listenKFQL"), "listenKFQL", 1);
        if (PLU.getCache("listenYX") == 1)
          PLU.setListen($("#btn_bt_listenYX"), "listenYX", 1);
        if (PLU.getCache("autoDZ") == 1)
          PLU.setListen($("#btn_bt_autoDZ"), "autoDZ", 1);
        if (PLU.getCache("autoHYC") == 1)
          PLU.setListen($("#btn_bt_autoHYC"), "autoHYC", 1);
        if (PLU.getCache("auto9H") == 1)
          PLU.setListen($("#btn_bt_auto9H"), "auto9H", 1);
        if (PLU.getCache("autoTP") == 1)
          PLU.setListen($("#btn_bt_autoTP"), "autoTP", 1);
        if (PLU.getCache("autoLX") == 1)
          PLU.setListen($("#btn_bt_autoLX"), "autoLX", 1);
        if (PLU.getCache("autoBF") == 1)
          PLU.setListen($("#btn_bt_autoBF"), "autoBF", 1);
        if (PLU.getCache("autoB5F") == 1)
          PLU.setListen($("#btn_bt_autoB5F"), "autoB5F", 1);
        if (PLU.getCache("autoB6") == 1)
          PLU.setListen($("#btn_bt_autoB6"), "autoB6", 1);
        if (PLU.getCache("autoConnect") == 1)
          PLU.setListen($("#btn_bt_autoConnect"), "autoConnect", 1);
        if (PLU.getCache("autoSignIn") == 1)
          PLU.setListen($("#btn_bt_autoSignIn"), "autoSignIn", 1);
        if (PLU.getCache("autoQuitTeam") == 1)
          PLU.setListen($("#btn_bt_autoQuitTeam"), "autoQuitTeam", 1);
        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);
                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"));
              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();
              }
            }, 300);
          }
        }
        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("你今天使用九花玉露丸次數已經達到上限了")) {
          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施展力量,本會願出(.*)的戰利品獎勵給本場戰鬥的最終獲勝者。/,
          );
          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場逃犯任務/);
          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.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,
                  });
              }
            }
          }
        } else if (
          msgTxt.match("開啟了幫派副本") &&
          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) {
            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]+)/,
          );
          if (l && l.length > 4) {
            UTIL.log({
              msg: "【逃犯】" + l[2] + "-" + l[4] + " : " + l[1],
              type: "TF",
              time: new Date().getTime(),
            });
            //111
            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(),
            });
            return;
            l[2] = l[2].substring(4);
            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.devmode && l[3].match(reg) && UTIL.inHome()) {
                UTIL.addSysListener("KuaFu", (b, type, subtype, msg) => {
                  if (type == "g_login" && subtype == "status" && msg == "1") {
                    goQinglong(
                      l[1],
                      l[2],
                      l[3],
                      PLU.getCache("listenKFQL_keys").split("|")[0],
                      true,
                    );
                    PLU.actions("home;");
                    UTIL.delSysListener("KuaFu");
                  }
                  clickButton("change_server world;");
                });
              }
            }
            //}else{
          }
        }
        //江湖紛爭
        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(PLU.fixYxName(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 != "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+)層/) ||
            sn.match(/拱辰樓(\D+)層/) ||
            sn.match(/陳異叔(\D+)層/) ||
            sn.match(/無為寺(\D+)層/) ||
            sn.match(/一品堂(\D+)層/) ||
            sn.match(/名將堂(\D+)層/) ||
            sn.match(/魔皇殿(\D+)層/) ||
            sn.match(/藏典塔(\D+)層/) ||
            sn.match(/無相樓(\D+)層/) ||
            sn.match(/葬劍谷(\D+)層/) ||
            sn.match(/霹靂堂(\D+)層/) ||
            sn.match(/鑄劍洞(\D+)層/) ||
            sn.match(/劍樓(\D+)層/) ||
            sn.match(/紅螺寺(\D+)層/) ||
            sn.match(/通天塔(\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;
          }
        }

        return;
      });
      // 監聽閒聊
      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
         */
        let text = msg.match(
          /^[^:]+:.*?([\u2E80-\u2EFF\u3400-\u4DBF\u4E00-\u9FFF\-]+道:.+)\[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級讀書識字】" + 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級讀書識字】" + text,
              type: "TIPS",
              time: new Date().getTime(),
            });
          } else if (text.match(/追風棍|木棉袈裟/)) {
            UTIL.log({
              msg: "【謎題-木棉袈裟】" + text,
              type: "TIPS",
              time: new Date().getTime(),
            });
          }
        }
        text = msg.match(/[^:]+:(.+)\[2;37;0m/)[1];
        if (
          PLU.getCache("listenChat") == 1 &&
          text != "哈哈,我也來闖盪江湖啦!" &&
          text != "哈哈,我去也……"
        )
          YFUI.writeToOut(msg);
      });
      //監聽練習
      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;";
            if (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") return;
        if (!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 != "channel" && type != "attrs_changed") console.log(b,"TYPE:",type," SUBTYPE:",subtype," MSG:",msg);
        //if(type=='g_login') console.log(b,"TYPE:",type," SUBTYPE:",subtype," MSG:",msg)
        if (type == "g_login" && subtype == "login_ret" && msg == "1") {
          //console.log('%c%s','color:#FFF;background:#F00;','[ '+UTIL.getNow()+' ] ======掉線重連了!!!=====')
          YFUI.writeToOut(
            "<span style='color:#FFF;background:#F00;'>[" +
              UTIL.getNow() +
              "] 斷線重連了 </span>",
          );
          PLU.TMP.reConnectTime = 0;
        }
      });
      unsafeWindow.sock.on("disconnect", () => {
        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) PLU.TMP.reConnectTime = 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+)級/)[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);

        if (
          PLU.TMP.reConnectTime &&
          PLU.getCache("autoConnect") == 1 &&
          PLU.TMP.reConnectTime > 0
        ) {
          PLU.TMP.reConnectTime--;
          if (PLU.TMP.reConnectTime <= 0) {
            location.reload();
          }
        }
      }, 1000);
    },
    //================================================================================================
    toSignIn() {
      // this.signIn(0)
      // return;
      if (!this.signInMaps) this.initSignInMaps();
      let ckeds = PLU.getCache("signInArray")
        ? 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>";
      htm +=
        '<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(","));
          //console.log(checkeds)//--
          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);
            });
          });
        },
      });
    },
    //================================================================================================
    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") &&
        vipInfo.get("saodang_fb_1").split(",")[2] % 1000 < 2
      )
        acts += "#2 vip finish_fb dulongzhai;";
      if (
        vipInfo.get("saodang_fb_2") &&
        vipInfo.get("saodang_fb_2").split(",")[2] % 1000 < 2
      )
        acts += "#2 vip finish_fb junying;";
      if (
        vipInfo.get("saodang_fb_3") &&
        vipInfo.get("saodang_fb_3").split(",")[2] % 1000 < 2
      )
        acts += "#2 vip finish_fb beidou;";
      if (
        vipInfo.get("saodang_fb_4") &&
        vipInfo.get("saodang_fb_4").split(",")[2] % 1000 < 2
      )
        acts += "#2 vip finish_fb youling;";
      if (
        vipInfo.get("saodang_fb_5") &&
        vipInfo.get("saodang_fb_5").split(",")[2] % 1000 < 1
      )
        acts += "vip finish_fb siyu;";
      if (
        vipInfo.get("saodang_fb_6") &&
        vipInfo.get("saodang_fb_6").split(",")[2] % 1000 < 1
      )
        acts += "vip finish_fb changleweiyang;";
      if (
        vipInfo.get("saodang_fb_7") &&
        vipInfo.get("saodang_fb_7").split(",")[2] % 1000 < 1
      )
        acts += "vip finish_fb heishuihuangling;";
      if (
        vipInfo.get("saodang_fb_8") &&
        vipInfo.get("saodang_fb_8").split(",")[2] % 1000 < 1
      )
        acts += "vip finish_fb jiandangfenglingdu;";
      if (
        vipInfo.get("saodang_fb_9") &&
        vipInfo.get("saodang_fb_9").split(",")[2] % 1000 < 1
      )
        acts += "vip finish_fb tianshanlongxue;";
      if (
        vipInfo.get("saodang_fb_10") &&
        vipInfo.get("saodang_fb_10").split(",")[2] % 1000 < 1
      )
        acts += "vip finish_fb sizhanguangmingding;";
      acts += "home;";
      PLU.execActions(acts, () => {
        callback && callback();
      });
    },
    autoVipShaodan(callback) {
      let acts = "";
      let vipInfo = g_obj_map.get("msg_vip");
      if (
        vipInfo.get("saodang_fb_1") &&
        vipInfo.get("saodang_fb_1").split(",")[2] % 1000 < 2
      )
        acts += "#2 vip finish_fb dulongzhai;";
      if (
        vipInfo.get("saodang_fb_2") &&
        vipInfo.get("saodang_fb_2").split(",")[2] % 1000 < 2
      )
        acts += "#2 vip finish_fb junying;";
      if (
        vipInfo.get("saodang_fb_3") &&
        vipInfo.get("saodang_fb_3").split(",")[2] % 1000 < 2
      )
        acts += "#2 vip finish_fb beidou;";
      if (
        vipInfo.get("saodang_fb_4") &&
        vipInfo.get("saodang_fb_4").split(",")[2] % 1000 < 2
      )
        acts += "#2 vip finish_fb youling;";
      if (
        vipInfo.get("saodang_fb_5") &&
        vipInfo.get("saodang_fb_5").split(",")[2] % 1000 < 1
      )
        acts += "vip finish_fb siyu;";
      if (
        vipInfo.get("saodang_fb_6") &&
        vipInfo.get("saodang_fb_6").split(",")[2] % 1000 < 1
      )
        acts += "vip finish_fb changleweiyang;";
      if (
        vipInfo.get("saodang_fb_7") &&
        vipInfo.get("saodang_fb_7").split(",")[2] % 1000 < 1
      )
        acts += "vip finish_fb heishuihuangling;";
      if (
        vipInfo.get("saodang_fb_8") &&
        vipInfo.get("saodang_fb_8").split(",")[2] % 1000 < 1
      )
        acts += "vip finish_fb jiandangfenglingdu;";
      if (
        vipInfo.get("saodang_fb_9") &&
        vipInfo.get("saodang_fb_9").split(",")[2] % 1000 < 1
      )
        acts += "vip finish_fb tianshanlongxue;";
      if (
        vipInfo.get("saodang_fb_10") &&
        vipInfo.get("saodang_fb_10").split(",")[2] % 1000 < 1
      )
        acts += "vip finish_fb sizhanguangmingding;";
      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_48246976;event_1_85373703;home;",
        },
        { n: "潛龍禮包", go: "jh 1;w;event_1_76648488;event_1_21318613;home;" },
        { n: "續約會員", go: "jh 1;event_1_45018293;home;" },
        {
          n: "分享獎勵",
          go: "share_ok 1;share_ok 2;share_ok 3;share_ok 4;share_ok 5;share_ok 7;home;",
        },
        {
          n: "南詔投資",
          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: "消費積分",
          go: "jh 1;e;n;e;e;event_1_44731074;event_1_8041045;event_1_8041045;event_1_29721519;home;",
        },
        { n: "吃九花丸", go: "items use obj_jiuhuayulouwan;home;" },
        {
          n: "打坐睡床",
          go: "home;exercise stop;exercise;golook_room;sleep_hanyuchuang;home;",
        },
        { n: "買引路蜂", go: "shop money_buy mny_shop2_N_10;home;" },
        {
          n: "領取工資",
          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: "爬樓獎勵",
          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: "VIP 福利",
          c: function () {
            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: "VIP 排行",
          c: function () {
            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;home;",
        },
        {
          n: "VIP 尋寶",
          c: function () {
            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;home;",
        },
        {
          n: "VIP 釣魚",
          c: function () {
            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;home;",
        },
        {
          n: "VIP 暴擊",
          c: function () {
            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
            );
          },
          go: "#10 vip finish_big_task;home;",
        },
        {
          n: "VIP 師門",
          c: function () {
            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
            );
          },
          go: "#25 vip finish_family;home;",
        },
        {
          n: "VIP 幫派",
          c: function () {
            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;home;",
        },
        {
          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: "銀兩上香",
          c: function () {
            return !!g_obj_map.get("msg_clan_view");
          },
          go: "#20 clan incense yx;home;",
        },
        { n: "洛陽採蓮", go: "jh 2;#19 n;e;n;n;n;w;event_1_31320275;home;" },
        {
          n: "破陣採礦",
          go: "jh 26;w;w;n;e;e;event_1_18075497;w;w;n;event_1_14435995;home;",
        },
        {
          n: "冰火玄鐵",
          go: "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 37;n;e;e;nw;nw;w;n;e;n;e;e;e;ne;ne;ne;se;n;event_1_97487911;home;",
        },
        { n: "唐門冰月", fn: PLU.autoBingyue },
        { n: _("自动答题", "自動答題"), fn: PLU.loopAnswerQues },
        { n: "", go: "home" },
      ];
    },

    //================================================================================================
    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>",
        );
      });
    },
    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?吐蕃國師的屍體;;",
          (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?蒙面人頭目的屍體;;",
              () => {
                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) {
      PLU.execActions("rank go 236;nw;n;n;n;n;n;n;", () => {
        PLU.autoFight({
          targetKey: "tianlongsi_lidazui",
          onEnd() {
            PLU.execActions("get?李大嘴的屍體", (f) => {
              if (!f) return endCallback && endCallback(1);
            });
            PLU.execActions("nw;nw;n;", () => {
              PLU.autoFight({
                targetKey: "tianlongsi_baikaixin",
                onEnd() {
                  PLU.execActions("get?白開心的屍體", (f2) => {
                    if (!f2) return endCallback && endCallback(2);
                    PLU.execActions("prev_combat;home;");
                  });
                },
              });
            });
          },
        });
      });
    },
    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");
    },
    //================================================================================================
    execActions(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;
        });
      PLU.actions({
        paths: acs,
        idx: 0,
        onPathsEnd() {
          PLU.STATUS.isBusy = false;
          endcallback && endcallback(true);
        },
        onPathsFail() {
          PLU.STATUS.isBusy = false;
          endcallback && endcallback(false);
        },
      });
    },
    //================================================================================================
    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];
      //null
      if (!curAct) {
        setTimeout(() => {
          params.idx++;
          PLU.actions(params);
        }, 250);
        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,
          fightKind: "kill",
          autoSkill: kt,
          onFail() {
            //params.retry = (params.retry||0) + 1;
            //if(params.retry>0){
            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("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.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" &&
              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;
      }
      //行動
      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();
          }
        },
      });
    },
    //================================================================================================
    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才可以直接去往此地") > -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 == "fight" ? "fight" : "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+)秒後才能攻擊這個人/);
            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;
    },
    loopAnswerQues($btn) {
      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
          ) {
            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;
    },
    //================================================================================================
    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);
        },
      });
    },
    //================================================================================================
    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");
            }
          }
        }
      });
    },
    //================================================================================================
    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 ? 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")
            ),
        );
        let myNum = 0;
        eqItems &&
          eqItems.forEach((eq) => {
            myNum += eq.num;
          });
        console.log(eqItems);
        YFUI.showPop({
          title: "自動摹刻所有明月",
          text:
            "一鍵自動摹刻所有明月裝備!<br><span style='color:#F00;font-weight:bold;'>注意準備足夠的刻刀!!!</span><br>當前玄鐵刻刀數量 <span style='color:#F00;'>" +
            daoNum +
            "</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>",
        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>`,
        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>",
        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>",
        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>;
						`,
        value:
          PLU.getCache("lookKillNames") ||
          "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>
						`,
        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>
						`,
        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);
    },
    //================================================================================================
    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>
						`,
        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] ? 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>
							<select id="slowClickSec" style="font-size:16px;height:30px;width:15%;">
								<option selected>1</option>
								<option>2</option>
								<option>3</option>
								<option>5</option>
								<option>10</option>
								<option>30</option>
								<option>60</option>
							</select>
							<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)) 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] ? 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);
        },
      });
    },
    //================================================================================================
    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>`,
        width: "382px",
        okText: "開始",
        onOk() {
          let startLvl = Number($("#startGemLvl").val()),
            delay = Number($("#combineSec").val());
          PLU.autoCombineMasterGem(startLvl, delay * 1000);
          //console.log(startLvl,delay)
        },
        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 + "";
        // PLU.execActions(cmds, ()=>{})
        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>
						`,
        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>
						`,
        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>
						`,
        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);
        },
      });
    },
    //================================================================================================
    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>
						`,
        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>
						時間間隔:省略則默認5(5秒)<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 = 5,
            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]) || 5;
            } 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: "自動對話所有有親密度的奇俠, 請在做完20次贊助金錠後再進行<br><b style='color:#F00;'>是否現在進行?</b>",
        autoOk: autoTime ? 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>
						` +
          '<div style="text-align:right;"><label>不要掃盪秘境:<input type="checkbox" id="if_auto_mj" name="noamj" value="1"/></label></div>',
        value: PLU.getCache("visitQixiaName") || "15|風無痕",
        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");
          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, (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" +
                    PLU.TMP.todayGetXT +
                    "</span>",
                );
                UTIL.log({
                  msg: " 今日一共獲得玄鐵令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, 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
          ? 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, 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:" +
                            mapid +
                            "--</span>",
                        );
                        if (mapid == "public") {
                          PLU.execActions("secret_op1;", () => {
                            PLU.TMP.goingQixiaMijing = false;
                            PLU.tryVisitQixia(
                              qxName,
                              giveNum,
                              objectFN,
                              ifAutoMj,
                              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 + ";;", () => {
                              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,
                                    callback,
                                  );
                                });
                              } else if (shortName == "無盡深淵") {
                                PLU.goWuJinShenYuan(() => {
                                  PLU.TMP.goingQixiaMijing = false;
                                  PLU.tryVisitQixia(
                                    qxName,
                                    giveNum,
                                    objectFN,
                                    ifAutoMj,
                                    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\)/);
            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,
                        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+)/,
              )
            ) {
              PLU.STO.listenVisit && clearTimeout(PLU.STO.listenVisit);
              callback &&
                callback({ code: 1, msg: "今日奇俠友好度操作已經完畢" });
              return;
            }
            if (msgTxt.match("掃盪成功,獲得:")) {
              let xtnum = parseInt(msgTxt.split("、")[0].split("玄鐵令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")[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, 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")[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) {
      //無盡深淵
      //'e;e;s;w;w;s;s;e;n;e;s;e;e;n;w;n;e;n;w;fight henshan_guguai_laozhe'
      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>",
        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>地點:" +
                      PLU.TMP.DATA_MPFZ.p +
                      "<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秒,進入戰鬥!--</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.master_auto();
            }, 500);
          },
          onEnd() {
            PLU.TMP.DATA_MPFZ = null;
            PLU.setBtnRed($("#btn_bt_waitCDKill"), 0);
            setTimeout((t) => {
              PLU.master_auto();
            }, 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>;
                            `,
          value:
            PLU.getCache(listenKey + "_keys") ||
            "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>
                            `,
          value:
            PLU.getCache(listenKey + "_keys") ||
            "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>;
                            `,
          value:
            PLU.getCache(listenKey + "_keys") ||
            "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>
                            `,
          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>
                            `,
          value:
            PLU.getCache(listenKey + "_keys") ||
            "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 == "autoConnect") {
        YFUI.showInput({
          title: "自動重連",
          text: `請輸入斷線後自動重連的時間,重連方式為到時間自動刷新頁面。<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>
						`,
          onOk() {
            let v = $.trim($("#autoSignInTime").val());
            if (v == "") return PLU.setBtnRed($btn, 0);
            //console.log($('#autoSignInTime').val(),$('#autoSignInTime'))
            // setCache
            PLU.setCache(listenKey, 1);
          },
          onNo() {
            PLU.setCache(listenKey, 0);
            PLU.setBtnRed($btn, 0);
          },
        });
      } else if (listenKey == "autoQuitTeam") {
        //進塔離隊
        YFUI.showPop({
          title: "進塔自動離隊",
          text: `是否進塔自動離隊?<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 < 44) {
            setTimeout(() => {
              PLU.killQinglong(npcId, tryNum + 1);
            }, 500);
            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) {
      let npcObj = UTIL.findRoomNpc(npcName, Number(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]*) 激烈爭鬥中/);
          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;
    },
    fixYxName(name) {
      switch (name) {
        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>",
              );
              //npcObj.key
              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({
        //autoFight(p
        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)\|)?(.*)/);
              console.debug(cs);
              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));
              console.debug(skobj);
              if (skobj) tpList.push(Object.assign({}, skobj, sk));
              console.debug(tpList);
            });
            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() {
      PLU.toggleFollowKill($("#btn_bt_kg_followKill"), "followKill", 1);
      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:你獲得:三生石
         */

        if (type == "home" && subtype == "index") {
          UTIL.delSysListener("listenBangFive");
          YFUI.writeToOut("<span style='color:white;'> ==幫五完畢!== </span>");
          PLU.execActions("golook_room;home");
        }
      });
    },
    intervene() {
      setTimeout((o) => {
        $(document).one("click", (o) => {
          eval(
            $(o.target)
              .closest("button")[0]
              .getAttributeNode("onclick")
              .value.replace("score", "watch_vs"),
          );
          console.log(g_obj_map);
        });
      }, 500);
      while (g_obj_map && g_obj_map.get("msg_vs_info")) {
        if (g_obj_map.get("msg_vs_info").get("vs2_pos1")) {
          clickButton("fight" + g_obj_map.get("msg_vs_info").get("vs2_pos1"));
          clickButton("kill" + g_obj_map.get("msg_vs_info").get("vs2_pos1"));
          break;
        }
      }
    },

    //================================================================================================
    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.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>
                            `,
          value:
            PLU.getCache(listenKey + "_keys") || "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|九天龍吟劍法",
          ];
        }
        YFUI.showInput({
          title: "自動技能",
          text: `格式:觸發氣值|技能詞組,以英文逗號分割多個關鍵詞。<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>",
        );
      }, 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>
                            `,
          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",
            "fight",
            "kill",
            "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) {
        if (PLU.TMP.firstSync) PLU.startSync($btn);
        else {
          YFUI.showPop({
            title: "隊伍同步",
            text: "<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.leaderTeamSync = false;
        UTIL.delSysListener("syncTeamChannel");
      }
    },
    //================================================================================================
    commandTeam(args) {
      if (!PLU.TMP.leaderTeamSync) return;
      let cmd = args[0];
      if (
        !g_gmain.is_fighting &&
        (PLU.allowedcmds.indexOf(cmd.split(" ")[0]) > -1 ||
          cmd.indexOf("find_") == 0 ||
          cmd.indexOf("event_") == 0 ||
          cmd.indexOf("give_") == 0 ||
          cmd.indexOf("get_") == 0 ||
          cmd.indexOf("op1") >= 0 ||
          cmd.indexOf("_op2") > 0 ||
          ["nw", "n", "ne", "w", "e", "sw", "s", "se"].includes(cmd))
      ) {
        cmd = PLU.Base64.encode(args[0]).split("").join("-");
        clickButton("team chat " + cmd + "\n");
      }
    },
    //================================================================================================
    listenTeamSync(leaderId) {
      UTIL.addSysListener("syncTeamChannel", (b, type, subtype, msg) => {
        if (
          type == "channel" &&
          subtype == "team" &&
          msg.indexOf(leaderId) > 0 &&
          msg.indexOf("【隊伍】") > 0
        ) {
          var cmd = PLU.Base64.decode(
            msg.split(":")[1].replace("", "").replace(/-/g, ""),
          ).replace(/\n/g, "");
          if (
            PLU.allowedcmds.indexOf(cmd.split(" ")[0]) > -1 ||
            cmd.indexOf("find_") == 0 ||
            cmd.indexOf("event_") == 0 ||
            cmd.indexOf("give_") == 0 ||
            cmd.indexOf("get_") == 0 ||
            cmd.indexOf("op1") >= 0 ||
            cmd.indexOf("_op2") > 0 ||
            ["nw", "n", "ne", "w", "e", "sw", "s", "se"].includes(cmd)
          ) {
            clickButton(cmd);
          }
          if (cmd == "change_server world") {
            clickButton("team join " + leaderId + "-1a1a");
          }
        }
      });
    },
    //================================================================================================
    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>
                        `,
        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>");
        });
      });
    },
    //================================================================================================
    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() {
      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";
      if (act)
        PLU.execActions(act, () => {
          PLU.goHJS();
        });
    },
    //================================================================================================
    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>(当前仅支持简体中文)",
          "輸入NPC名字,可模糊匹配,支持<a target='_blank' href='https://zh.wikipedia.org/wiki/正則表達式'>正則表達式</a>(當前僅支持簡體中文,把繁体特有的字替换成点也可以用)",
        ),
        value: PLU.getCache("prevSearchStr") || "^.?(男|女)[孩童]",
        onOk(val) {
          if (!$.trim(val)) return;
          let str = $.trim(val);
          PLU.setCache("prevSearchStr", str);
          PLU.queryNpc(str);
        },
        onNo() {},
      });
    },
    //================================================================================================
    queryNpc(name) {
      if (!name) return;
      let npcLib = PLU.YFD.mapsLib.Npc;
      let findList = npcLib.filter((e) => {
        if (e.name.match(name)) return true;
        return false;
      });
      if (findList && findList.length > 0) {
        findList.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>");
      } else {
        YFUI.writeToOut("<span style='color:#F66;'>查詢不到相關數據</span>");
      }
    },
    //================================================================================================
    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",
        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>`,
        onOk() {
          let mapStr = $.trim($("#pathFindMap").val()),
            npcStr = $.trim($("#pathFindNpc").val());
          console.log(mapStr, npcStr);
          if (!npcStr) return;
          PLU.setCache("pathFindMap", mapStr);
          PLU.setCache("pathFindNpc", npcStr);
          let jhMap = PLU.YFD.mapsLib.Map.find((e) => e.jh == mapStr);
          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!...已搜索完地圖--</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已找到--</span>",
              );
            } else {
              params.idx++;
              PLU.goPathFindNpc(params);
            }
          }, 100);
        },
        onPathsFail() {
          setTimeout(() => {
            PLU.execActions("home");
          }, 500);
          YFUI.writeToOut(
            "<span style='color:#FFF;'>--找不到目標NPC!...路徑中斷--</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) {
      YFUI.showPop({
        title: "路徑詳情:" + desc,
        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>",
        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>`;
      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 "";
        while (combineNum > 0) {
          if (combineNum >= 30) {
            combineStr += "items hecheng " + gemCode + "_N_10;";
            combineNum -= 30;
          } else {
            combineStr += "items hecheng " + gemCode + "_N_1;";
            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 ? 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" +
            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);
    },
    //================================================================================================
    saveSetting() {
      YFUI.showPop({
        title: "設置上傳",
        text: "<b style='color:red;'>確定要上傳當前角色腳本設置嗎?</b>",
        onOk() {
          let cacheData = UTIL.getMem("CACHE");
          $.ajax({
            url: "http://www.jiaozis.work:8765/comm/save",
            type: "POST",
            data: {
              data_key: btoa(escape(PLU.accId)),
              data_type: "CACHE",
              data_value: btoa(escape(cacheData)),
            },
            dataType: "json",
            success: (res) => {
              if (res.code == "00000") {
                YFUI.writeToOut(
                  "<span><span style='color:#AF0;'>本地腳本設置上傳成功!</span></span>",
                );
              } else {
                YFUI.writeToOut(
                  "<span><span style='color:#F80;'>上傳失敗!(" +
                    res.msg +
                    ")</span></span>",
                );
              }
            },
          });
        },
        onNo() {},
      });
    },
    //================================================================================================
    loadSetting() {
      $.ajax({
        url: "http://www.jiaozis.work:8765/comm/load",
        type: "POST",
        data: { data_key: btoa(escape(PLU.accId)) },
        dataType: "json",
        success: (res) => {
          if (res.code == "00000") {
            let cacheData = unescape(atob(res.data[0].data_value));
            YFUI.showPop({
              title: "設置下載",
              text: "<span style='color:#360;'>角色腳本設置下載成功!是否替換本地設置?</span>",
              autoOk: 10,
              onOk() {
                UTIL.setMem("CACHE", cacheData);
                PLU.initStorage();
                YFUI.writeToOut(
                  "<span><span style='color:#AF0;'>本地腳本設置替換成功!</span></span>",
                );
              },
              onNo() {},
            });
          } else {
            YFUI.writeToOut(
              "<span><span style='color:#F80;'>下載失敗!(" +
                res.msg +
                ")</span></span>",
            );
          }
        },
      });
    },
  };
  //=================================================================================
  // 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) {
      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 - 1);
            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;
    },
    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 roomInfo = g_obj_map.get("msg_room");
      if (!roomInfo) return;
      let item = roomInfo.elements.find(
        (it) => it.key.substring(0, 4) == "item" && it.value.indexOf(name) >= 0,
      );
      if (item) {
        clickButton("get " + item.value.split(",")[0]);
      }
    },
    inHome() {
      return $(".out .cmd_main_jh").length;
    },
  };
  //=================================================================================
  // 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);
      //$('#cmd').append($('<table align="center" border="0" style="width:100%"><tbody><tr><td style="width:65%" align="left"><input id="chat_msg" class="chat_input" type="text" value=""></td><td style="width:35%" align="left"><button type="button" cellpadding="0" cellspacing="0" onclick="clickButton(\'send_chat\', 0)" class="cmd_click3"><span class="out2">發送</span></button></td></tr></tbody></table>'))
    },
    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 +=
            params.type == "textarea"
              ? `<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%;"><textarea id="myTools_popup_input_${i}" rows="4" style="${inpstyle}">${val}</textarea></div></div>`
              : `<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%;"><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);
    },
  };
  init();
});