Greasy Fork is available in English.

wsmud_Raid

武神传说 MUD

  1. // ==UserScript==
  2. // @name wsmud_Raid
  3. // @namespace cqv
  4. // @version 2.4.65
  5. // @date 23/12/2018
  6. // @modified 26/7/2024
  7. // @homepage https://greasyfork.org/zh-CN/scripts/375851
  8. // @description 武神传说 MUD
  9. // @author Bob.cn, 初心, 白三三
  10. // @match http://*.wsmud.com/*
  11. // @match http://*.wamud.com/*
  12. // @run-at document-end
  13. // @require https://s4.zstatic.net/ajax/libs/vue/2.2.2/vue.min.js
  14. // @grant unsafeWindow
  15. // @grant GM_getValue
  16. // @grant GM_setValue
  17. // @grant GM_deleteValue
  18. // @grant GM_listValues
  19. // @grant GM_setClipboard
  20.  
  21. // ==/UserScript==
  22.  
  23. (function () {
  24.  
  25. 'use strict';
  26.  
  27. /***********************************************************************************\
  28. 工具层
  29. \***********************************************************************************/
  30.  
  31. //---------------------------------------------------------------------------
  32. // Message Output
  33. //---------------------------------------------------------------------------
  34.  
  35. var Message = {
  36. append: function (msg) {
  37. console.log(msg);
  38. },
  39. clean: function () { },
  40. cmdLog: function (title, cmd) {
  41. let msg = `&nbsp;&nbsp;<hic>${title}</hic>`
  42. if (cmd != null) {
  43. msg += `: ${cmd}`;
  44. }
  45. this.append(msg);
  46. }
  47. };
  48.  
  49. function CopyObject(obj) {
  50. return JSON.parse(JSON.stringify(obj));
  51. }
  52.  
  53. /**
  54. * @param {Array} list
  55. * @param {*} value
  56. * @param {Function} assert function(previous, current)
  57. */
  58. const SortInsert = function (list, value, assert) {
  59. let index = list.length;
  60. while (index >= 0) {
  61. if (index == 0) {
  62. list.splice(index, 0, value);
  63. break;
  64. }
  65. const previous = list[index - 1];
  66. if (assert(previous, value)) {
  67. list.splice(index, 0, value);
  68. break;
  69. }
  70. index -= 1;
  71. }
  72. };
  73.  
  74. //---------------------------------------------------------------------------
  75. // Source Split Helper
  76. //---------------------------------------------------------------------------
  77.  
  78. const SourceCodeHelper = {
  79. split: function (source) {
  80. var cmds = source.split(/\s*\n+/g);
  81. var first = cmds[0];
  82. if (first != null && /\S/.test(first) == false) {
  83. cmds.splice(0, 1);
  84. }
  85. var last = cmds[cmds.length - 1];
  86. if (last != null && /\S/.test(last) == false) {
  87. cmds.splice(cmds.length - 1, 1);
  88. }
  89. return cmds;
  90. },
  91. appendHeader: function (header, text) {
  92. let result = `\n${text}`;
  93. result = result.replace(/(\n)/g, `$1${header}`);
  94. result = result.replace(/\n\s*\n/g, "\n");
  95. result = result.replace(/^\s*\n/, "");
  96. return result;
  97. }
  98. };
  99.  
  100. //---------------------------------------------------------------------------
  101. // Persistent Cache Interface
  102. //---------------------------------------------------------------------------
  103.  
  104. class PersistentCache {
  105. constructor(save, getAll, remove) {
  106. this._save = save;
  107. this._getAll = getAll;
  108. this._remove = remove;
  109. }
  110. save(key, value) {
  111. this._save(key, value);
  112. }
  113. get(key) {
  114. return this.getAll()[key];
  115. }
  116. getAll() {
  117. return this._getAll();
  118. }
  119. remove(key) {
  120. this._remove(key);
  121. }
  122. }
  123.  
  124. /***********************************************************************************\
  125. 控制逻辑编译层
  126. \***********************************************************************************/
  127.  
  128. //---------------------------------------------------------------------------
  129. // Precompiler
  130. //---------------------------------------------------------------------------
  131.  
  132. class PrecompileRule {
  133. constructor(handle, priority) {
  134. this._handle = handle;
  135. this.priority = priority;
  136. }
  137. handle(cmds) {
  138. return this._handle(cmds);
  139. }
  140. }
  141.  
  142. class PrecompileRuleCenter extends PrecompileRule {
  143. constructor() {
  144. const handle = function (cmds) {
  145. var result = cmds;
  146. for (const rule of this._rules) {
  147. result = rule.handle(result);
  148. }
  149. return result;
  150. };
  151. super(handle, -1);
  152. this._rules = [];
  153. this.instance = this;
  154. }
  155. static shared() {
  156. if (!this.instance) {
  157. this.instance = new PrecompileRuleCenter();
  158. }
  159. return this.instance;
  160. }
  161. addRule(rule) {
  162. SortInsert(this._rules, rule, (p, c) => {
  163. return p.priority >= c.priority;
  164. });
  165. }
  166. };
  167.  
  168. class Precompiler {
  169. precompile(source) {
  170. var cmds = SourceCodeHelper.split(source);
  171. if (cmds.length <= 0) return cmds;
  172.  
  173. var result = PrecompileRuleCenter.shared().handle(cmds);
  174.  
  175. // console.log("<<<============================");
  176. // console.log("预编译最终代码:");
  177. // for (let k = 0; k < result.length; k++) {
  178. // console.log(k + " " + result[k]);
  179. // }
  180. // console.log("============================>>>");
  181. return result;
  182. }
  183. }
  184.  
  185. //---------------------------------------------------------------------------
  186. // Compiler
  187. //---------------------------------------------------------------------------
  188.  
  189. const ControlKeys = {
  190. while: "while",
  191. continue: "continue",
  192. break: "break",
  193. if: "if",
  194. elseif: "elseif",
  195. else: "else",
  196. exit: "exit",
  197. };
  198.  
  199. class Compiler {
  200. constructor() {
  201. this._cc = "CC";
  202. this._pc = "PC";
  203. this._breakStacks = [];
  204. }
  205.  
  206. compile(source) {
  207. if (source == null) return [];
  208.  
  209. var precompiler = new Precompiler();
  210. var cmds = precompiler.precompile(source);
  211.  
  212. var blockCmds = ["[if] true"];
  213. cmds.forEach(cmd => {
  214. blockCmds.push(" " + cmd);
  215. });
  216. var result = this._handleBlock(blockCmds, 0).cmds;
  217. result.push("%exit");
  218.  
  219. // console.log("<<<============================");
  220. // console.log("编译最终代码:");
  221. // for (let k = 0; k < result.length; k++) {
  222. // console.log(k + " " + result[k]);
  223. // }
  224. // console.log("============================>>>");
  225. return result;
  226. }
  227.  
  228. /**
  229. * @param {string[]} cmds
  230. * @param {number} start block 首句在的 index
  231. * @param {number} loopStart 最邻近的 while 的首句索引
  232. */
  233. _handleBlock(cmds, start, loopStart) {
  234. var realLoopStart = loopStart;
  235.  
  236. var result = [];
  237. var r = this._handleCondition(cmds[0]);
  238. var callback = function () { };
  239. var self = this;
  240. switch (r.type) {
  241. case ControlKeys.while:
  242. this._breakStacks.push([]);
  243. result.push(r.cmd);
  244. result.push(null);
  245. callback = function () {
  246. result.push(`%${self._pc}=${start}`);
  247. var truePC = start + 2;
  248. var falsePC = result.length + start;
  249. result[1] = `%${self._pc}=${self._cc}?${truePC}:${falsePC}`;
  250. var breakStack = self._breakStacks.pop();
  251. breakStack.forEach(index => {
  252. result[index - start] = `%${self._pc}=${falsePC}`;
  253. });
  254. };
  255. realLoopStart = start;
  256. break;
  257. case ControlKeys.if:
  258. result.push(r.cmd);
  259. result.push(null);
  260. callback = function () {
  261. result.push("%pass");
  262. var truePC = start + 2;
  263. var falsePC = result.length + start;
  264. result[1] = `%${self._pc}=${self._cc}?${truePC}:${falsePC}`;
  265. };
  266. break;
  267. case ControlKeys.elseif:
  268. result.push(r.cmd);
  269. result.push(null);
  270. callback = function () {
  271. result.push("%pass");
  272. var truePC = start + 2;
  273. var falsePC = result.length + start;
  274. result[1] = `%${self._pc}=${self._cc}?${truePC}:${falsePC}`;
  275. };
  276. break;
  277. case ControlKeys.else:
  278. result.push(null);
  279. callback = function () {
  280. var truePC = start + 1;
  281. var falsePC = result.length + start;
  282. result[0] = `%${self._pc}=${self._cc}?${falsePC}:${truePC}`;
  283. };
  284. break;
  285. case ControlKeys.continue:
  286. result.push(`%${self._pc}=${loopStart}`);
  287. return { type: "continue", cmds: result };
  288. case ControlKeys.break:
  289. result.push(null);
  290. var breakStack = this._breakStacks[this._breakStacks.length - 1];
  291. breakStack.push(start);
  292. return { type: "break", cmds: result };
  293. case ControlKeys.exit:
  294. result.push("%exit");
  295. return { type: "exit", cmds: result };
  296. default:
  297. throw "未知的控制关键字: " + r.type;
  298. }
  299.  
  300. var cmdsLength = cmds.length;
  301. var i = 1;
  302. while (i < cmdsLength) {
  303. var cmd = cmds[i];
  304. var header = /^\s*/g.exec(cmd)[0];
  305. var headerLength = header.length;
  306. if (cmd[headerLength] == "[") {
  307. var blockCmds = [cmd];
  308. var j = i + 1;
  309. while (j < cmdsLength) {
  310. var next = cmds[j];
  311. if (next[headerLength] != " ") break;
  312. blockCmds.push(next);
  313. j += 1;
  314. }
  315. var lastCmdIndex = result.length - 1;
  316. var blockStart = result.length + start;
  317. var k = this._handleBlock(blockCmds, blockStart, realLoopStart);
  318. k.cmds.forEach(cmd1 => {
  319. result.push(cmd1);
  320. });
  321. if (k.type == "elseif") {
  322. result[lastCmdIndex] = `%${this._pc}=${result.length + start - 1}`;
  323. } else if (k.type == "else") {
  324. result[lastCmdIndex] = `%${this._pc}=${result.length + start}`;
  325. }
  326. i = j;
  327. } else {
  328. result.push(cmd.substring(headerLength));
  329. i += 1;
  330. }
  331. }
  332.  
  333. callback();
  334. return { type: r.type, cmds: result };
  335. }
  336. _handleCondition(condition) {
  337. var type = null;
  338. var cmd = null;
  339. var formats = [
  340. { type: ControlKeys.while, regexp: /^\s*\[while\]/g },
  341. { type: ControlKeys.if, regexp: /^\s*\[if\]/g },
  342. { type: ControlKeys.elseif, regexp: /^\s*\[else\s?if\]/g },
  343. { type: ControlKeys.else, regexp: /^\s*\[else\]/g },
  344. { type: ControlKeys.continue, regexp: /^\s*\[continue\]/g },
  345. { type: ControlKeys.break, regexp: /^\s*\[break\]/g },
  346. { type: ControlKeys.exit, regexp: /^\s*\[exit\]/g },
  347. ];
  348. for (const format of formats) {
  349. var r = format.regexp.exec(condition);
  350. if (r) {
  351. type = format.type;
  352. var exp = condition.substring(r[0].length);
  353. cmd = `%${this._cc}=${exp}`
  354. break;
  355. }
  356. }
  357. if (type == null) {
  358. throw "编译失败: " + condition;
  359. }
  360. return { type: type, cmd: cmd };
  361. }
  362. }
  363.  
  364. /***********************************************************************************\
  365. 预编译实现层
  366. \***********************************************************************************/
  367.  
  368. const PrecompileRulePriority = {
  369. subflow: 100,
  370. call: 90,
  371. annatition: 80,
  372. compatible: 70,
  373. guard: 60,
  374. emptyLine: 50,
  375.  
  376. // 层外使用
  377. high: 30,
  378. ordinary: 20,
  379. low: 10
  380. };
  381.  
  382. //---------------------------------------------------------------------------
  383. // Precompile Annatitions
  384. //---------------------------------------------------------------------------
  385.  
  386. (function () {
  387. const handle = function (cmds) {
  388. var result = [];
  389. for (const cmd of cmds) {
  390. if (/^\s*\/\//.test(cmd)) continue;
  391. result.push(cmd);
  392. }
  393. return result;
  394. };
  395. const rule = new PrecompileRule(handle, PrecompileRulePriority.annatition);
  396. PrecompileRuleCenter.shared().addRule(rule);
  397. })();
  398.  
  399. (function () {
  400. const handle = function (cmds) {
  401. var result = [];
  402. var ignore = false;
  403. for (const cmd of cmds) {
  404. if (/^\s*\/\*/.test(cmd)) {
  405. ignore = true;
  406. continue;
  407. }
  408. if (ignore && /\*\/\s*$/.test(cmd)) {
  409. ignore = false;
  410. continue;
  411. }
  412. if (!ignore) {
  413. result.push(cmd);
  414. }
  415. }
  416. return result;
  417. };
  418. const rule = new PrecompileRule(handle, PrecompileRulePriority.annatition);
  419. PrecompileRuleCenter.shared().addRule(rule);
  420. })();
  421.  
  422. //---------------------------------------------------------------------------
  423. // Precompile Subflows
  424. //---------------------------------------------------------------------------
  425.  
  426. (function () {
  427. const handle = function (cmds) {
  428. let result = [];
  429. let collecting = false;
  430. let subflowCmd = null;
  431. for (const cmd of cmds) {
  432. var r = /^(\s*)<===+\s*$/.exec(cmd);
  433. if (r != null) {
  434. collecting = true;
  435. subflowCmd = "<===";
  436. continue;
  437. }
  438. if (collecting) {
  439. var r2 = /^\s*=+==>\s*$/.exec(cmd);
  440. if (r2 != null) {
  441. collecting = false;
  442. subflowCmd += "===>";
  443. result.push(subflowCmd);
  444. } else {
  445. subflowCmd += `\n${cmd}`;
  446. }
  447. continue;
  448. }
  449. result.push(cmd);
  450. }
  451. return result;
  452. };
  453. const rule = new PrecompileRule(handle, PrecompileRulePriority.subflow);
  454. PrecompileRuleCenter.shared().addRule(rule);
  455. })();
  456.  
  457. //---------------------------------------------------------------------------
  458. // Precompile Guards
  459. //---------------------------------------------------------------------------
  460.  
  461. (function () {
  462. const handle = function (cmds) {
  463. var result = [];
  464. // {headerLength: Number, cmds: [String]}
  465. var guards = [];
  466. var guarding = false;
  467. for (const cmd of cmds) {
  468. var r = /^(\s*)<---+/.exec(cmd);
  469. if (r != null) {
  470. guarding = true;
  471. const guard = {
  472. headerLength: r[1].length,
  473. cmds: []
  474. }
  475. guards.push(guard);
  476. continue;
  477. }
  478. if (guarding) {
  479. var r2 = /^\s*-+-->/.exec(cmd);
  480. if (r2 == null) {
  481. const guard = guards[guards.length - 1];
  482. guard.cmds.push(cmd.substring(guard.headerLength));
  483. } else {
  484. guarding = false;
  485. }
  486. continue;
  487. }
  488. result.push(cmd);
  489. var r3 = /^(\s*)[^\[\s]/.exec(cmd);
  490. if (r3 != null) {
  491. var header = r3[1];
  492. var hasGuard = false;
  493. for (let j = guards.length; j > 0; j--) {
  494. const guard = guards[j - 1];
  495. if (header.length < guard.headerLength) {
  496. guards.pop();
  497. continue;
  498. }
  499. if (!hasGuard) {
  500. result.push(`${header}%guardStart`);
  501. hasGuard = true;
  502. }
  503. guard.cmds.forEach(cmd1 => {
  504. result.push(`${header}${cmd1}`);
  505. });
  506. }
  507. if (hasGuard) result.push(`${header}%guardEnd`);
  508. }
  509. }
  510. return result;
  511. };
  512. const rule = new PrecompileRule(handle, PrecompileRulePriority.guard);
  513. PrecompileRuleCenter.shared().addRule(rule);
  514. })();
  515.  
  516. //---------------------------------------------------------------------------
  517. // Precompile Calls
  518. //---------------------------------------------------------------------------
  519.  
  520. var __CallCounter = 0;
  521. var FlowStore = null; // PersistentCache
  522.  
  523. // TODO: 尚不支持嵌套调用
  524. // @call 函数名 参数1,参数2,参数3,...
  525. (function () {
  526. const handle = function (cmds) {
  527. let result = [];
  528. cmds.forEach(cmd => {
  529. var r = /^(\s*)@call\s(\S+)(\s*(\S.*)+\s*|\s*)$/.exec(cmd);
  530. if (r == null) {
  531. result.push(cmd);
  532. return;
  533. }
  534. const paramsField = r[4];
  535. let args = "";
  536. if (paramsField != null && paramsField.length > 0) {
  537. const params = paramsField.split(",");
  538. for (let i = 0; i < params.length; i++) {
  539. const param = params[i];
  540. args += `($arg${i})=${param}\n`;
  541. }
  542. }
  543. const flowName = r[2];
  544. let source = FlowStore.get(flowName);
  545. if (source == null) {
  546. Message.append(`<ord>未找到调用的流程 ${flowName}</ord>`);
  547. //throw `未找到调用的流程 ${flowName}`;
  548. }
  549. let callSource = `[if] true\n` + SourceCodeHelper.appendHeader(" ", `${args}\n${source}`);
  550. const callId = __CallCounter; __CallCounter += 1;
  551. callSource = callSource.replace(/\(\$([_a-z][a-zA-Z0-9_]*?)\)/g, `($__x${callId}_$1)`);
  552. callSource = callSource.replace(/\(([_a-z][a-zA-Z0-9_]*?)\)/g, `(__x${callId}_$1)`);
  553. const callCmds = SourceCodeHelper.split(callSource);
  554. const header = r[1];
  555. for (const callCmd of callCmds) {
  556. if (/^\s*#/.test(callCmd)) continue;
  557. result.push(`${header}${callCmd}`);
  558. }
  559. });
  560. return result;
  561. };
  562. const rule = new PrecompileRule(handle, PrecompileRulePriority.call);
  563. PrecompileRuleCenter.shared().addRule(rule);
  564. })();
  565.  
  566. //---------------------------------------------------------------------------
  567. // Precompile Empty Line
  568. //---------------------------------------------------------------------------
  569.  
  570. (function () {
  571. const handle = function (cmds) {
  572. var result = [];
  573. for (const cmd of cmds) {
  574. if (!/\S+/.test(cmd)) continue;
  575. result.push(cmd);
  576. }
  577. return result;
  578. };
  579. const rule = new PrecompileRule(handle, PrecompileRulePriority.emptyLine);
  580. PrecompileRuleCenter.shared().addRule(rule);
  581. })();
  582.  
  583. //---------------------------------------------------------------------------
  584. // Precompile Raid 1.x.x
  585. //---------------------------------------------------------------------------
  586.  
  587. (function addCompatibleGuardRule() {
  588. const handle = function (cmds) {
  589. var result = [];
  590. cmds.forEach(cmd => {
  591. var r = /^\s*#(\[.*)$/.exec(cmd);
  592. if (r == null) {
  593. result.push(cmd);
  594. return;
  595. }
  596. var c1 = `<---`;
  597. var c2 = r[1];
  598. var c3 = `--->`;
  599. result.push(c1, c2, c3);
  600. });
  601. return result;
  602. };
  603. const rule = new PrecompileRule(handle, PrecompileRulePriority.compatible);
  604. PrecompileRuleCenter.shared().addRule(rule);
  605. })();
  606.  
  607. function CompatibleOperator(exp) {
  608. var result = exp;
  609. result = result.replace(/([^&])[&]([^&])/g, "$1&&$2");
  610. result = result.replace(/([^\|])[\|]([^\|])/g, "$1||$2");
  611. result = result.replace(/([^=<>!])[=]([^=])/g, "$1==$2");
  612. return result;
  613. }
  614.  
  615. (function addCompatibleUntilRule() {
  616. const handle = function (cmds) {
  617. var result = [];
  618. cmds.forEach(cmd => {
  619. var r = /^(\s*)\[=(.+?)\](.*)$/.exec(cmd);
  620. if (r == null) {
  621. result.push(cmd);
  622. return;
  623. }
  624. var header = r[1];
  625. var condition = r[2];
  626. condition = CompatibleOperator(condition);
  627. var command = r[3];
  628. var c1 = `${header}@until ${condition}`;
  629. result.push(c1);
  630. if (!/\S/.test(command)) return;
  631. var c2 = `${header}${command}`;
  632. result.push(c2);
  633. });
  634. return result;
  635. };
  636. const rule = new PrecompileRule(handle, PrecompileRulePriority.compatible);
  637. PrecompileRuleCenter.shared().addRule(rule);
  638. })();
  639.  
  640. (function addCompatibleIfRule() {
  641. const handle = function (cmds) {
  642. var result = [];
  643. cmds.forEach(cmd => {
  644. var r = /^(\s*)\[(.*?[=<>].*?|true|false)\](.*)$/i.exec(cmd);
  645. if (r == null) {
  646. result.push(cmd);
  647. return;
  648. }
  649. var command = r[3];
  650. if (!/\S/.test(command)) return;
  651. var header = r[1];
  652. var condition = r[2];
  653. condition = CompatibleOperator(condition);
  654. var c1 = `${header}[if] ${condition}`;
  655. var c2 = `${header} ${command}`;
  656. result.push(c1, c2);
  657. });
  658. return result;
  659. };
  660. const rule = new PrecompileRule(handle, PrecompileRulePriority.compatible);
  661. PrecompileRuleCenter.shared().addRule(rule);
  662. })();
  663.  
  664. (function addCompatibleNextRule() {
  665. const handle = function (cmds) {
  666. var result = [];
  667. cmds.forEach(cmd => {
  668. var r = /^(\s*)@next(.*)$/i.exec(cmd);
  669. if (r == null) {
  670. result.push(cmd);
  671. return;
  672. }
  673. var header = r[1];
  674. result.push(`${header}[continue]`);
  675. });
  676. return result;
  677. };
  678. const rule = new PrecompileRule(handle, PrecompileRulePriority.compatible);
  679. PrecompileRuleCenter.shared().addRule(rule);
  680. })();
  681.  
  682. (function addCompatibleExitRule() {
  683. const handle = function (cmds) {
  684. var result = [];
  685. cmds.forEach(cmd => {
  686. var r = /^(\s*)@exit(.*)$/i.exec(cmd);
  687. if (r == null) {
  688. result.push(cmd);
  689. return;
  690. }
  691. var header = r[1];
  692. result.push(`${header}[break]`);
  693. });
  694. return result;
  695. };
  696. const rule = new PrecompileRule(handle, PrecompileRulePriority.compatible);
  697. PrecompileRuleCenter.shared().addRule(rule);
  698. })();
  699.  
  700. /***********************************************************************************\
  701. 代码执行器层
  702. \***********************************************************************************/
  703.  
  704. //---------------------------------------------------------------------------
  705. // Handle Condition
  706. //---------------------------------------------------------------------------
  707.  
  708. var AssertLeftMarkHandlerCenter = {
  709. /**
  710. * @param {Function} handler function(leftMark)->{handle: Bool, value: string}
  711. */
  712. addHandler: function (handler) {
  713. this._leftMarkHandlers.push(handler);
  714. },
  715. getValue(leftMark) {
  716. for (let i = 0; i < this._leftMarkHandlers.length; i++) {
  717. const handler = this._leftMarkHandlers[i];
  718. var result = handler.handle(leftMark);
  719. if (!result.handle) continue;
  720. return result.value;
  721. }
  722. return leftMark;
  723. },
  724. _leftMarkHandlers: []
  725. };
  726.  
  727. class AssertWrapper {
  728. /**
  729. * @param {Function} assert1 function(string)->Bool
  730. * @param {string} text
  731. */
  732. constructor(assert1) {
  733. var theSelf = this;
  734. this.assert = function () {
  735. return assert1(theSelf.text);
  736. };
  737. }
  738. setText(text) {
  739. this.text = text;
  740. }
  741. }
  742.  
  743. class AssertHolder {
  744. /**
  745. * @param {Function} match function(expression)->Bool
  746. * @param {Function} getAssertWrapper function()->AssertWrapper
  747. */
  748. constructor(match, getAssertWrapper) {
  749. this.match = match;
  750. this._getAssertWrapper = getAssertWrapper;
  751. }
  752. getAssertWrapper() {
  753. return this._getAssertWrapper();
  754. }
  755. }
  756.  
  757. var AssertHolderCenter = {
  758. /**
  759. * @param {AssertHolder} holder
  760. */
  761. addAssertHolder: function (holder) {
  762. this._assertHolders.push(holder);
  763. },
  764. /**
  765. * @param {string} expression
  766. * @returns {Function} assert: function()
  767. */
  768. get: function (expression) {
  769. var exp = expression.replace(/^\s*|\s*$/g, "");
  770. var theSelf = this;
  771. var relationIndex = exp.search(/&&|\|\|/g);
  772. if (relationIndex != -1) {
  773. var relation = exp.substring(relationIndex, relationIndex + 2);
  774. var left = exp.substring(0, relationIndex);
  775. var right = exp.substring(relationIndex + 2);
  776. var assert = function () {
  777. var leftAssert = theSelf.get(left);
  778. var rightAssert = theSelf.get(right);
  779. switch (relation) {
  780. case "&&":
  781. return leftAssert() && rightAssert();
  782. case "||":
  783. return leftAssert() || rightAssert();
  784. }
  785. };
  786. return assert;
  787. }
  788. var not = exp[0];
  789. if (not == "!") {
  790. var assert = function () {
  791. return !theSelf.get(exp.substring(1))();
  792. }
  793. return assert;
  794. }
  795. for (let i = 0; i < this._assertHolders.length; i++) {
  796. const holder = this._assertHolders[i];
  797. if (holder.match(exp)) {
  798. var wrapper = holder.getAssertWrapper();
  799. wrapper.setText(exp);
  800. return wrapper.assert;
  801. }
  802. }
  803. return null;
  804. },
  805. _assertHolders: []
  806. };
  807.  
  808. (function addTureAssertHolder() {
  809. var match = function (text) {
  810. return text == "true";
  811. };
  812. var assert = function (text) {
  813. return true;
  814. };
  815. var holder = new AssertHolder(match, function () { return new AssertWrapper(assert); });
  816. AssertHolderCenter.addAssertHolder(holder);
  817. })();
  818.  
  819. (function addFalseAssertHolder() {
  820. var match = function (text) {
  821. return text == "false";
  822. };
  823. var assert = function (text) {
  824. return false;
  825. };
  826. var holder = new AssertHolder(match, function () { return new AssertWrapper(assert); });
  827. AssertHolderCenter.addAssertHolder(holder);
  828. })();
  829.  
  830. (function addPresetConfigAssertHolder() {
  831. var patt = new RegExp(">=?|<=?|!=|==?");
  832. var match = function (text) {
  833. return patt.test(text);
  834. };
  835. var assert = function (text) {
  836. let validText = text;
  837. validText = validText.replace(/<(\w+)>/g, "「$1」");
  838. validText = validText.replace(/<(\/\w+)>/g, "「¿$1」");
  839. var result = patt.exec(validText);
  840. var opt = result[0];
  841. var parts = validText.split(opt);
  842. var left = parts[0].replace(/^\s*|\s*$/g, "");
  843. var lvalue = AssertLeftMarkHandlerCenter.getValue(left);
  844. var rvalue = parts[1].replace(/^\s*|\s*$/g, "");;
  845. var lfloat = parseFloat(lvalue);
  846. var rfloat = parseFloat(rvalue);
  847. var byDigit = false;
  848. if (!isNaN(lfloat) && !isNaN(rfloat)) {
  849. lvalue = lfloat;
  850. rvalue = rfloat;
  851. byDigit = true;
  852. }
  853. switch (opt) {
  854. case "=":
  855. case "==":
  856. if (byDigit) {
  857. return Math.abs(lvalue - rvalue) < 0.001;
  858. } else {
  859. return lvalue == rvalue;
  860. }
  861. case ">":
  862. return lvalue > rvalue;
  863. case "<":
  864. return lvalue < rvalue;
  865. case ">=":
  866. return lvalue >= rvalue;
  867. case "<=":
  868. return lvalue <= rvalue;
  869. case "!=":
  870. if (byDigit) {
  871. return Math.abs(lvalue - rvalue) > 0.001;
  872. } else {
  873. return lvalue != rvalue;
  874. }
  875. default:
  876. return false;
  877. }
  878. };
  879. var holder = new AssertHolder(match, function () { return new AssertWrapper(assert); });
  880. AssertHolderCenter.addAssertHolder(holder);
  881. })();
  882.  
  883. //---------------------------------------------------------------------------
  884. // Cmd Prehandler
  885. //---------------------------------------------------------------------------
  886.  
  887. const CmdPrehandlerPriority = {
  888. ordinary: 50,
  889. };
  890.  
  891. class CmdPrehandler {
  892. /**
  893. * @param {Function} handle function(performer: Performer, cmd: String) -> String
  894. * @param {Number} [priority]
  895. */
  896. constructor(handle, priority) {
  897. this._handle = handle;
  898. this.priority = priority ? priority : CmdPrehandlerPriority.ordinary;
  899. }
  900. handle(performer, cmd) {
  901. return this._handle(performer, cmd);
  902. }
  903. }
  904.  
  905. class CmdPrehandleCenter extends CmdPrehandler {
  906. constructor() {
  907. const handle = function (performer, cmd) {
  908. var result = cmd;
  909. for (const handler of this._handlers) {
  910. result = handler.handle(performer, result);
  911. }
  912. return result;
  913. };
  914. super(handle, -1);
  915. this._handlers = [];
  916. this.instance = this;
  917. }
  918. static shared() {
  919. if (!this.instance) {
  920. this.instance = new CmdPrehandleCenter();
  921. }
  922. return this.instance;
  923. }
  924. addHandler(handler) {
  925. SortInsert(this._handlers, handler, (p, c) => {
  926. return p.priority >= c.priority;
  927. });
  928. }
  929. }
  930.  
  931. //---------------------------------------------------------------------------
  932. // Cmd Executor
  933. //---------------------------------------------------------------------------
  934.  
  935. const CmdExecutorPriority = {
  936. compiler: 90,
  937.  
  938. // 层外使用
  939. high: 30,
  940. ordinary: 20,
  941. low: 10
  942. };
  943.  
  944. class CmdExecutor {
  945. /**
  946. * @param {Function} appropriate function(cmd: String) -> Boolean
  947. * @param {Function} execute function(performer: Performer, cmd: String)
  948. * @param {Number} priority
  949. */
  950. constructor(appropriate, execute, priority) {
  951. this._appropriate = appropriate;
  952. this._execute = execute;
  953. this.priority = priority ? priority : CmdExecutorPriority.ordinary;
  954. }
  955. appropriate(cmd) {
  956. return this._appropriate(cmd);
  957. }
  958. execute(performer, cmd) {
  959. return this._execute(performer, cmd);
  960. }
  961. }
  962.  
  963. var CmdExecuteCenter = {
  964. addExecutor: function (executor) {
  965. SortInsert(this._executors, executor, (p, c) => {
  966. return p.priority >= c.priority;
  967. });
  968. },
  969. execute: function (performer, cmd) {
  970. var valid = null;
  971. for (const executor of this._executors) {
  972. if (executor.appropriate(cmd)) {
  973. valid = executor;
  974. break;
  975. }
  976. }
  977. if (valid == null) {
  978. throw `无法处理此命令: ${cmd}`;
  979. }
  980. return valid.execute(performer, cmd);
  981. },
  982. _executors: []
  983. };
  984.  
  985. //---------------------------------------------------------------------------
  986. // Performer
  987. //---------------------------------------------------------------------------
  988.  
  989. class Performer {
  990. /**
  991. * @param {String} source
  992. */
  993. constructor(name, source) {
  994. this._name = name;
  995. this._source = source;
  996. this._log = false;
  997. this._running = false;
  998. this._pausing = false;
  999. }
  1000.  
  1001. name() {
  1002. return this._name;
  1003. }
  1004. runing() {
  1005. return this._running;
  1006. }
  1007. pausing() {
  1008. return this._pausing;
  1009. }
  1010. log(value) {
  1011. if (value == null) return this._log;
  1012. if (/\/\/\s*~silent\s*\n/.test(this._source) == true) return this._log;
  1013. this._log = value;
  1014. }
  1015.  
  1016. start(callback) {
  1017. if (this._running) return;
  1018.  
  1019. try {
  1020. var compiler = new Compiler();
  1021. var start = new Date().getTime();
  1022. this._cmds = compiler.compile(this._source);
  1023. var end = new Date().getTime();
  1024. console.log(`编译总耗时: ${end - start} 毫秒`);
  1025. } catch (err) {
  1026. Message.append(`<ord>编译错误</ord>: ${err}`);
  1027. return;
  1028. }
  1029.  
  1030. if (this._log) Message.append(`<hiy>开始执行,流程: ${this._name}...</hiy>`);
  1031. this._running = true;
  1032. this._pausing = false;
  1033.  
  1034. this._callback = callback;
  1035.  
  1036. this._pc = 0;
  1037. this._cc = true;
  1038.  
  1039. this._guarding = false;
  1040. this._subflows = [];
  1041.  
  1042. this._perform();
  1043. }
  1044. stop() {
  1045. if (!this._running) return;
  1046. this._running = false;
  1047. for (const subflow of this._subflows) {
  1048. subflow.stop();
  1049. }
  1050. if (this._log) Message.append(`<hiy>执行完毕,流程: ${this._name}。</hiy>`);
  1051. if (this._callback) this._callback();
  1052. }
  1053. pause() {
  1054. if (!this._running) return;
  1055. if (this._log) Message.append(`<hiy>暂停执行,流程: ${this._name}...</hiy>`);
  1056. this._pausing = true;
  1057. for (const subflow of this._subflows) {
  1058. subflow.pause();
  1059. }
  1060. }
  1061. resume() {
  1062. if (!this._running || !this._pausing) return;
  1063. if (this._log) Message.append(`<hiy>恢复执行,流程: ${this._name}。</hiy>`);
  1064. this._pausing = false;
  1065. for (const subflow of this._subflows) {
  1066. subflow.resume();
  1067. }
  1068. this._perform();
  1069. }
  1070.  
  1071. guarding() {
  1072. return this._guarding;
  1073. }
  1074. timeSeries(timestamp) {
  1075. if (timestamp != null) {
  1076. if (!this.guarding()) this._systemCmdTimeSeries = timestamp;
  1077. return;
  1078. }
  1079. return this._systemCmdTimeSeries;
  1080. }
  1081.  
  1082. async _perform() {
  1083. if (!this._running || this._pausing) return;
  1084. if (this._doing) return;
  1085.  
  1086. var cmd = this._cmds[this._pc];
  1087. // console.log(`>>> ${this._name}, ${this._pc}, ${this._cc}, ${cmd}`);
  1088. this._pc += 1;
  1089.  
  1090. try {
  1091. this._doing = true;
  1092. await CmdExecuteCenter.execute(this, cmd);
  1093. } catch (err) {
  1094. Message.append(`<ord>执行错误</ord>: ${err}`);
  1095. this.stop();
  1096. return;
  1097. } finally {
  1098. this._doing = false;
  1099. }
  1100. this._perform();
  1101. }
  1102. }
  1103.  
  1104. // Compile Cmd Executor
  1105.  
  1106. (function () {
  1107. const appropriate = function (cmd) {
  1108. return cmd == "%exit";
  1109. };
  1110. const execute = function (performer, cmd) {
  1111. performer.stop();
  1112. };
  1113. const executor = new CmdExecutor(appropriate, execute, CmdExecutorPriority.compiler);
  1114. CmdExecuteCenter.addExecutor(executor);
  1115. })();
  1116.  
  1117. (function () {
  1118. const appropriate = function (cmd) {
  1119. return cmd == "%pass";
  1120. };
  1121. const execute = function (performer, cmd) { };
  1122. const executor = new CmdExecutor(appropriate, execute, CmdExecutorPriority.compiler);
  1123. CmdExecuteCenter.addExecutor(executor);
  1124. })();
  1125.  
  1126. (function () {
  1127. const appropriate = function (cmd) {
  1128. return cmd.indexOf("%PC=CC") == 0;
  1129. };
  1130. const execute = function (performer, cmd) {
  1131. performer._pc = eval(`performer._cc${cmd.substring(6)}`);
  1132. };
  1133. const executor = new CmdExecutor(appropriate, execute, CmdExecutorPriority.compiler);
  1134. CmdExecuteCenter.addExecutor(executor);
  1135. })();
  1136.  
  1137. (function () {
  1138. const appropriate = function (cmd) {
  1139. return cmd.indexOf("%PC=") == 0;
  1140. };
  1141. const execute = function (performer, cmd) {
  1142. performer._pc = eval(cmd.substring(4));
  1143. };
  1144. const executor = new CmdExecutor(appropriate, execute, CmdExecutorPriority.compiler);
  1145. CmdExecuteCenter.addExecutor(executor);
  1146. })();
  1147.  
  1148. (function () {
  1149. const appropriate = function (cmd) {
  1150. return cmd.indexOf("%CC=") == 0;
  1151. };
  1152. const execute = function (performer, cmd) {
  1153. const validCmd = CmdPrehandleCenter.shared().handle(performer, cmd);
  1154. var assert = AssertHolderCenter.get(validCmd.substring(4));
  1155. performer._cc = assert();
  1156. };
  1157. const executor = new CmdExecutor(appropriate, execute, CmdExecutorPriority.compiler);
  1158. CmdExecuteCenter.addExecutor(executor);
  1159. })();
  1160.  
  1161. (function () {
  1162. const appropriate = function (cmd) {
  1163. return cmd == "%guardStart";
  1164. };
  1165. const execute = function (performer, cmd) {
  1166. performer._guarding = true;
  1167. };
  1168. const executor = new CmdExecutor(appropriate, execute, CmdExecutorPriority.compiler);
  1169. CmdExecuteCenter.addExecutor(executor);
  1170. })();
  1171.  
  1172. (function () {
  1173. const appropriate = function (cmd) {
  1174. return cmd == "%guardEnd";
  1175. };
  1176. const execute = function (performer, cmd) {
  1177. performer._guarding = false;
  1178. };
  1179. const executor = new CmdExecutor(appropriate, execute, CmdExecutorPriority.compiler);
  1180. CmdExecuteCenter.addExecutor(executor);
  1181. })();
  1182.  
  1183. (function () {
  1184. const appropriate = function (cmd) {
  1185. return /^<===[^爫]*===>$/.test(cmd);
  1186. };
  1187. const execute = function (performer, cmd) {
  1188. const source = cmd.slice(4, -4);
  1189. const p = new Performer("subflow", source);
  1190. performer._subflows.push(p);
  1191. p.start();
  1192. };
  1193. const executor = new CmdExecutor(appropriate, execute, CmdExecutorPriority.compiler);
  1194. CmdExecuteCenter.addExecutor(executor);
  1195. })();
  1196.  
  1197. //---------------------------------------------------------------------------
  1198. // Variable
  1199. //---------------------------------------------------------------------------
  1200.  
  1201. function TryCalculate(expression) {
  1202. if (/^[0-9\+\-\*\/% ]*$/g.test(expression)) {
  1203. return eval(expression);
  1204. }
  1205. return expression;
  1206. }
  1207.  
  1208. var PersistentVariables = null; // PersistentCache
  1209.  
  1210. function UpdateVariable(performer, name, exp) {
  1211. if (/^_*[A-Z][a-zA-Z0-9_]*$/.test(name)) {
  1212. PersistentVariables.save(name, TryCalculate(exp));
  1213. } else if (/^_*[a-z][a-zA-Z0-9_]*$/.test(name)) {
  1214. if (performer.tempParams == null) {
  1215. performer.tempParams = {};
  1216. }
  1217. performer.tempParams[name] = TryCalculate(exp);
  1218. }
  1219. }
  1220.  
  1221. (function () {
  1222. var patt = /^\(\$([A-Za-z_][a-zA-Z0-9_]*?)\)\s*=\s*(.+)\s*/;
  1223. const appropriate = function (cmd) {
  1224. return patt.test(cmd);
  1225. };
  1226. const execute = function (performer, cmd) {
  1227. const validCmd = CmdPrehandleCenter.shared().handle(performer, cmd);
  1228. var result = patt.exec(validCmd);
  1229. var name = result[1];
  1230. var exp = result[2];
  1231. UpdateVariable(performer, name, exp);
  1232. };
  1233. const executor = new CmdExecutor(appropriate, execute);
  1234. CmdExecuteCenter.addExecutor(executor);
  1235. })();
  1236.  
  1237. var VariableStore = {
  1238. register: function (getAll) {
  1239. this._allGetAll.push(getAll);
  1240. },
  1241. getAll: function () {
  1242. var result = {};
  1243. for (const getAll of this._allGetAll) {
  1244. const all = getAll();
  1245. for (const key in all) {
  1246. if (!all.hasOwnProperty(key)) continue;
  1247. result[key] = all[key];
  1248. }
  1249. }
  1250. return result;
  1251. },
  1252. _allGetAll: []
  1253. };
  1254.  
  1255. (function () {
  1256. const _assignVariables = function (expression, params) {
  1257. var placeholders = [];
  1258. var patt = /\([:a-zA-Z0-9_]+?\)/g;
  1259. var result = patt.exec(expression);
  1260. while (result != null) {
  1261. placeholders.push(result[0]);
  1262. result = patt.exec(expression);
  1263. }
  1264. let assignedExp = expression;
  1265. for (let i = 0; i < placeholders.length; i++) {
  1266. const placeholder = placeholders[i];
  1267. var key = placeholder.substring(1, placeholder.length - 1);
  1268. var value = params[key];
  1269. if (value == null) value = "null";
  1270. assignedExp = assignedExp.replace(placeholder, value);
  1271. }
  1272.  
  1273. let placeholders2 = [];
  1274. let patt2 = /\((:[a-zA-Z0-9_]+?)\s+([^\(\)\s][^\(\)]*?)\s*\)/g;
  1275. let r2 = patt2.exec(assignedExp);
  1276. while (r2 != null) {
  1277. placeholders2.push({ value: r2[0], key: `${r2[1]} `, params: r2[2] });
  1278. r2 = patt2.exec(assignedExp);
  1279. }
  1280. for (const p of placeholders2) {
  1281. const func = params[p.key];
  1282. let value = "null";
  1283. if (func != null && typeof func == "function") {
  1284. value = func(p.params);
  1285. }
  1286. assignedExp = assignedExp.replace(p.value, value);
  1287. }
  1288.  
  1289. return assignedExp;
  1290. };
  1291. const assignVariables = function (expression, params) {
  1292. let result = expression;
  1293. while (true) {
  1294. const assigned = _assignVariables(result, params);
  1295. if (assigned == result) return result;
  1296. result = assigned;
  1297. }
  1298. };
  1299. const handle = function (performer, cmd) {
  1300. let allParam = {};
  1301. Object.assign(allParam, VariableStore.getAll(), performer.tempParams);
  1302. const result = assignVariables(cmd, allParam);
  1303. return result;
  1304. };
  1305. const handler = new CmdPrehandler(handle)
  1306. CmdPrehandleCenter.shared().addHandler(handler);
  1307. })();
  1308.  
  1309. /***********************************************************************************\
  1310. System Library
  1311. \***********************************************************************************/
  1312.  
  1313. class AtCmdExecutor extends CmdExecutor {
  1314. constructor(key, execute, priority) {
  1315. const appropriate = function (cmd) {
  1316. return cmd.indexOf(`@${key}`) == 0;
  1317. };
  1318. const superExecute = function (performer, cmd) {
  1319. const validCmd = CmdPrehandleCenter.shared().handle(performer, cmd);
  1320. let param = /^\s*(.*)\s*$/.exec(validCmd.substring(key.length + 1))[1];
  1321. if (param && param.length == 0) param = null;
  1322. return execute(performer, param);
  1323. };
  1324. super(appropriate, superExecute, priority);
  1325. }
  1326. }
  1327.  
  1328. (function () {
  1329. const executor = new AtCmdExecutor("wait", function (performer, param) {
  1330. if (performer.log()) Message.cmdLog(`等待 ${(param / 1000).toFixed(2)} 秒`);
  1331. return new Promise(resolve => {
  1332. setTimeout(() => resolve(), param);
  1333. });
  1334. });
  1335. CmdExecuteCenter.addExecutor(executor);
  1336. })();
  1337.  
  1338. (function () {
  1339. const executor = new AtCmdExecutor("await", function (performer, param) {
  1340. function createWorker(f) {
  1341. var blob = new Blob(['(function(){' + f.toString() + '})()']);
  1342. var url = window.URL.createObjectURL(blob);
  1343. var worker = new Worker(url);
  1344. return worker;
  1345. }
  1346. return new Promise(resolve => {
  1347. var wa = createWorker("setTimeout(() => postMessage('0'), "+param+")")
  1348. wa.onmessage = function (event) {
  1349. // console.log(new Date,event.data);
  1350. wa.terminate();
  1351. resolve();
  1352. };
  1353. });
  1354. });
  1355. CmdExecuteCenter.addExecutor(executor);
  1356. })();
  1357.  
  1358. (function () {
  1359. const executor = new AtCmdExecutor("debug", function (performer, param) {
  1360. let text = param;
  1361. if (text[0] == ">") {
  1362. text = JSON.stringify(eval(text.substring(1)));
  1363. }
  1364. var message = `&nbsp;&nbsp;[debug]: <hiz>${text}</hiz>`;
  1365. Message.append(message);
  1366. // console.log(message);
  1367. });
  1368. CmdExecuteCenter.addExecutor(executor);
  1369. })();
  1370.  
  1371. (function () {
  1372. const executor = new AtCmdExecutor("print", function (performer, param) {
  1373. Message.append(param);
  1374. });
  1375. CmdExecuteCenter.addExecutor(executor);
  1376. })();
  1377.  
  1378. class UntilAtCmdExecutor extends CmdExecutor {
  1379. constructor(key, assert, priority, tryAgain, timeout) {
  1380. const appropriate = function (cmd) {
  1381. return cmd.indexOf(`@${key}`) == 0;
  1382. };
  1383. const superExecute = function (performer, cmd) {
  1384. const tryExecute = function (callback) {
  1385. const validCmd = CmdPrehandleCenter.shared().handle(performer, cmd);
  1386. let param = /^\s*(.*)\s*$/.exec(validCmd.substring(key.length + 1))[1];
  1387. if (param != null && param.length == 0) param = null;
  1388. const result = assert(performer, param);
  1389. if (result == true) {
  1390. if (timeout != null) {
  1391. setTimeout(_ => { callback(); }, timeout);
  1392. } else {
  1393. callback();
  1394. }
  1395. } else {
  1396. setTimeout(_ => { tryExecute(callback); }, tryAgain != null ? tryAgain : 500);
  1397. }
  1398. };
  1399. if (performer.log()) Message.cmdLog("等待,直至符合条件", cmd);
  1400. return new Promise(resolve => {
  1401. tryExecute(resolve);
  1402. });
  1403. };
  1404. super(appropriate, superExecute, priority);
  1405. this._key = key;
  1406. this._assert = assert;
  1407. }
  1408. }
  1409.  
  1410. (function () {
  1411. const executor = new UntilAtCmdExecutor("until", function (performer, param) {
  1412. const assert = AssertHolderCenter.get(param);
  1413. return assert();
  1414. });
  1415. CmdExecuteCenter.addExecutor(executor);
  1416. })();
  1417.  
  1418. (function () {
  1419. const appropriate = function (cmd) {
  1420. return cmd.indexOf("@js ") == 0;
  1421. };
  1422. const execute = function (performer, cmd) {
  1423. const validCmd = CmdPrehandleCenter.shared().handle(performer, cmd);
  1424. let exp = validCmd.substring(4);
  1425. if (performer.log()) Message.cmdLog("调用 js", exp);
  1426. const result = /^\(\$([A-Za-z_][a-zA-Z0-9_]*?)\)\s*=\s*/.exec(exp);
  1427. if (result == null) {
  1428. eval(exp);
  1429. return;
  1430. }
  1431. const name = result[1];
  1432. exp = exp.substring(result[0].length);
  1433. UpdateVariable(performer, name, eval(exp));
  1434. };
  1435. const executor = new CmdExecutor(appropriate, execute);
  1436. CmdExecuteCenter.addExecutor(executor);
  1437. })();
  1438. (function () {
  1439. const appropriate = function (cmd) {
  1440. return cmd.indexOf("@stop ") == 0;
  1441. };
  1442. const execute = function (performer, cmd) {
  1443. const validCmd = CmdPrehandleCenter.shared().handle(performer, cmd);
  1444. let exp = validCmd.substring(6);
  1445. if (performer.log()) Message.cmdLog("停止流程", exp);
  1446. const result = /^\(\$([A-Za-z_][a-zA-Z0-9_]*?)\)\s*=\s*/.exec(exp);
  1447. if (result == null) {
  1448. ManagedPerformerCenter.getAll().filter(x => x.name() == exp).forEach(x => x.stop())
  1449. return;
  1450. }
  1451. const name = result[1];
  1452. exp = exp.substring(result[0].length);
  1453. UpdateVariable(performer, name, ManagedPerformerCenter.getAll().filter(x => x.name() == exp).forEach(x => x.stop()));
  1454. };
  1455. const executor = new CmdExecutor(appropriate, execute);
  1456. CmdExecuteCenter.addExecutor(executor);
  1457. })();
  1458.  
  1459. /***********************************************************************************\
  1460. Time Variables
  1461. \***********************************************************************************/
  1462.  
  1463. VariableStore.register(_ => {
  1464. return {
  1465. ":date": new Date().getDate(),
  1466. ":day": new Date().getDay(),
  1467. ":hour": new Date().getHours(),
  1468. ":minute": new Date().getMinutes(),
  1469. ":second": new Date().getSeconds()
  1470. }
  1471. });
  1472.  
  1473. /***********************************************************************************\
  1474. Compatible With wsmud_pluginss
  1475. \***********************************************************************************/
  1476.  
  1477. /**
  1478. * @param {String} source
  1479. * @param {Function} callback function(resolve)->void
  1480. */
  1481. function PerformerPromise(source, callback, log) {
  1482. return new Promise(resolve => {
  1483. const p = new Performer("", source);
  1484. if (log) p.log(log);
  1485. p.start(_ => {
  1486. if (callback) {
  1487. callback(resolve);
  1488. } else {
  1489. resolve();
  1490. }
  1491. });
  1492. });
  1493. }
  1494.  
  1495. (function () {
  1496. const appropriate = function (cmd) {
  1497. return cmd.indexOf("$wait ") == 0;
  1498. };
  1499. const execute = function (performer, cmd) {
  1500. return PerformerPromise(`@wait ${cmd.substring(6)}`, null, performer.log());
  1501. };
  1502. const executor = new CmdExecutor(appropriate, execute);
  1503. CmdExecuteCenter.addExecutor(executor);
  1504. })();
  1505.  
  1506. /***********************************************************************************\
  1507. User Config Param
  1508. \***********************************************************************************/
  1509.  
  1510. var __ConfigDomIdCounter = 0;
  1511. function GetConfigDomId() {
  1512. const id = __ConfigDomIdCounter;
  1513. __ConfigDomIdCounter += 1;
  1514. return `wsmud_raid_config_dom_id_${id}`;
  1515. }
  1516.  
  1517. var __ConfigPanelHtml = "";
  1518. var __ConfigPanelInits = [];
  1519. var __ConfigPanelActions = [];
  1520.  
  1521. class HashCmdExecutor extends CmdExecutor {
  1522. constructor(key, handle) {
  1523. const appropriate = function (cmd) {
  1524. return cmd.indexOf(`#${key}`) == 0;
  1525. };
  1526. const superHandle = function (performer, cmd) {
  1527. const validCmd = CmdPrehandleCenter.shared().handle(performer, cmd);
  1528. const param = validCmd.substring(this._key.length + 2);
  1529. const result = handle(performer, cmd, param);
  1530. if (result == null) return;
  1531. if (result.html) __ConfigPanelHtml += result.html;
  1532. if (result.init) __ConfigPanelInits.push(result.init);
  1533. if (result.action) __ConfigPanelActions.push(result.action);
  1534. };
  1535. super(appropriate, superHandle);
  1536. this._key = key;
  1537. }
  1538. }
  1539.  
  1540. (function () {
  1541. const executor = new HashCmdExecutor("input", function (performer, cmd, param) {
  1542. const result = /^\(\$([a-zA-Z0-9_]+)\)\s?=\s?([^,]+?),(.*)\s*$/.exec(param);
  1543. if (result == null) {
  1544. throw `错误的格式: ${cmd}`;
  1545. }
  1546. const variableName = result[1];
  1547. const desc = result[2];
  1548. const defaultValue = result[3] == null ? "" : result[3];
  1549. const id = GetConfigDomId();
  1550. const html = `
  1551. <p>
  1552. <label for="${id}">&nbsp;* ${desc}:&nbsp;</label><input style='width:80px' id ="${id}" type="text">
  1553. </p>`;
  1554. const init = function () {
  1555. $(`#${id}`).val(defaultValue);
  1556. };
  1557. const action = function () {
  1558. let result = {};
  1559. result[variableName] = $(`#${id}`).val();
  1560. return result;
  1561. };
  1562. return { html: html, init: init, action: action };
  1563. });
  1564. CmdExecuteCenter.addExecutor(executor);
  1565. })();
  1566.  
  1567. (function () {
  1568. const executor = new HashCmdExecutor("select", function (performer, cmd, param) {
  1569. const result = /^\(\$([a-zA-Z0-9_]+)\)\s?=\s?([^,]+?),([^,]+?),([^,]+?)\s*$/.exec(param);
  1570. if (result == null) {
  1571. throw `错误的格式: ${cmd}`;
  1572. }
  1573. const variableName = result[1];
  1574. const desc = result[2];
  1575. const options = result[3].split("|");
  1576. const defaultValue = result[4];
  1577. const id = GetConfigDomId();
  1578. let optionsHtml = "";
  1579. options.forEach(option => {
  1580. optionsHtml += `<option value="${option}">${option}</option>`;
  1581. });
  1582. const html = `
  1583. <p>
  1584. <label for="${id}">&nbsp;* ${desc}:&nbsp;</label><select style='width:80px' id="${id}">
  1585. ${optionsHtml}
  1586. </select>
  1587. </p>`;
  1588. const init = function () {
  1589. $(`#${id}`).val(defaultValue);
  1590. };
  1591. const action = function () {
  1592. let result = {};
  1593. result[variableName] = $(`#${id}`).val();
  1594. return result;
  1595. };
  1596. return { html: html, init: init, action: action };
  1597. });
  1598. CmdExecuteCenter.addExecutor(executor);
  1599. })();
  1600.  
  1601. (function () {
  1602. const appropriate = function (cmd) {
  1603. return /^#config\s*$/.test(cmd);
  1604. };
  1605. const execute = function (performer, cmd) {
  1606. return new Promise(resolve => {
  1607. var index = layer.open({
  1608. type: 1,
  1609. skin: "layui-layer-rim", //加上边框
  1610. area: "350px",
  1611. title: "配置参数",
  1612. content: __ConfigPanelHtml,
  1613. offset: "auto",
  1614. shift: 2,
  1615. move: false,
  1616. closeBtn: 0,
  1617. success: function (layero, index) {
  1618. __ConfigPanelInits.forEach(init => { init(); });
  1619. for (const node of layero[0].children) {
  1620. if (node.className != "layui-layer-content") continue;
  1621. node.setAttribute("style", "max-height: 370px;color: rgb(0, 128, 0);");
  1622. }
  1623. },
  1624. end: function () {
  1625. __ConfigPanelHtml = "";
  1626. __ConfigPanelInits = [];
  1627. __ConfigPanelActions = [];
  1628. },
  1629. btn: ['运行流程', '取消'],
  1630. yes: function () {
  1631. __ConfigPanelActions.forEach(action => {
  1632. const params = action();
  1633. for (const key in params) {
  1634. if (!params.hasOwnProperty(key)) continue;
  1635. UpdateVariable(performer, key, params[key]);
  1636. }
  1637. });
  1638. layer.close(index);
  1639. resolve();
  1640. },
  1641. btn2: function () {
  1642. performer.stop();
  1643. resolve();
  1644. }
  1645. });
  1646. });
  1647. };
  1648. const executor = new CmdExecutor(appropriate, execute);
  1649. CmdExecuteCenter.addExecutor(executor);
  1650. })();
  1651.  
  1652. /***********************************************************************************\
  1653. WSMUD
  1654. \***********************************************************************************/
  1655.  
  1656. var WG = null;
  1657. var messageAppend = null;
  1658. var messageClear = null;
  1659. var T = null;
  1660. var L = null;
  1661.  
  1662. Message.append = function (msg) {
  1663. messageAppend(msg);
  1664. };
  1665. Message.clean = function () {
  1666. messageClear();
  1667. };
  1668.  
  1669. const RoleState = {
  1670. none: "发呆",
  1671. liaoshang: "疗伤",
  1672. dazuo: "打坐",
  1673. wakuang: "挖矿",
  1674. gongzuo: "工作",
  1675. lianxi: "练习",
  1676. xuexi: "学习",
  1677. biguan: "闭关",
  1678. lianyao: "炼药",
  1679. lingwu: "领悟",
  1680. dushu: "读书",
  1681. juhun: "聚魂",
  1682. tuiyan: "推演"
  1683. };
  1684.  
  1685. /**
  1686. * @param {string} itemName
  1687. * @param {Boolean} blurry
  1688. * @param {string} [quality] white(w), green(g), blue(b), yellow(y), purple(p), orange(o), red(r)
  1689. */
  1690. function FindItem(list, itemName, blurry, quality, filterExp) {
  1691. var pattStr = blurry ? itemName : "^" + itemName + "$";
  1692. if (/<[a-zA-Z]{3}>.+<\/[a-zA-Z]{3}>/g.test(itemName)) {
  1693. pattStr = "^" + itemName + "$";
  1694. } else if (quality != null) {
  1695. var map = {
  1696. "white": "wht",
  1697. "w": "wht",
  1698. "green": "hig",
  1699. "g": "hig",
  1700. "blue": "hic",
  1701. "b": "hic",
  1702. "yellow": "hiy",
  1703. "y": "hiy",
  1704. "purple": "HIZ",
  1705. "p": "HIZ",
  1706. "orange": "hio",
  1707. "o": "hio",
  1708. "red": "ord",
  1709. "r": "ord"
  1710. };
  1711. var tag = map[quality];
  1712. if (tag != null) {
  1713. if (blurry) {
  1714. pattStr = "<" + tag + ">.*" + itemName + ".*</" + tag + ">";
  1715. } else {
  1716. pattStr = "<" + tag + ">" + itemName + "</" + tag + ">";
  1717. }
  1718. }
  1719. }
  1720. var patt = new RegExp(pattStr);
  1721. for (const item of list) {
  1722. if (patt.test(item.name) && !FilterCenter.filter(filterExp, item)) {
  1723. return item;
  1724. }
  1725. }
  1726. return null;
  1727. }
  1728.  
  1729. var Role = {
  1730. id: null,
  1731. name: null,
  1732. grade: null,
  1733. family: null,
  1734. energy: 0,
  1735. money: 0,
  1736.  
  1737. hp: 0,
  1738. maxHp: 0,
  1739. mp: 0,
  1740. maxMp: 0,
  1741.  
  1742. status: {},
  1743. equipments: [],
  1744. items: {}, // {id: object}
  1745. stores: {}, // {id: object}
  1746. _weaponType: '',
  1747. skills:{},
  1748. profitInfo : null,
  1749. kongfu: {
  1750. quan: null,
  1751. nei: null,
  1752. zhao: null,
  1753. qing: null,
  1754. jian: null,
  1755. dao: null,
  1756. gun: null,
  1757. zhang: null,
  1758. bian: null,
  1759. an: null
  1760. },
  1761.  
  1762. init: function () {
  1763. WG.add_hook("login", function (data) {
  1764. Role.id = data.id;
  1765. Role.status = [];
  1766. setTimeout(function () {
  1767. $("span[command=skills]").click();
  1768. setTimeout(_ => { $(".glyphicon-remove-circle").click(); }, 500);
  1769. }, 2000); // 查看装备技能
  1770. // if (GM_getValue(`###CodeTranslator@${Role.id}`, null) != "did") {
  1771. // CodeTranslator.run();
  1772. // GM_setValue(`###CodeTranslator@${Role.id}`, "did");
  1773. // }
  1774. UI.showToolbar();
  1775. setTimeout(_ => { Server.getNotice(); }, 3000);
  1776. });
  1777. $("li[command=SelectRole]").on("click", function () {
  1778. Role.name = $('.role-list .select').text().split(/\s+/).pop();
  1779. //Role.grade = $('.role-list .select').text().split(/\s+/).slice(-2)[0];
  1780. });
  1781. Role._monitorHpMp();
  1782. Role._monitorStatus();
  1783. Role._monitorState();
  1784. Role._monitorDeath();
  1785. Role._monitorSkillCD();
  1786. Role._monitorSkills();
  1787. Role._monitorGains();
  1788. Role._monitorItems();
  1789. Role._monitorCombat();
  1790. Role._monitorInfo();
  1791. Role._monitorWeapon();
  1792. },
  1793.  
  1794. hasStatus: function (s) {
  1795. var stamp = Role.status[s];
  1796. if (stamp == null) return false;
  1797. if (stamp < new Date().getTime()) return false;
  1798. return true;
  1799. },
  1800. isFree: function () {
  1801. return !Role.hasStatus("busy") && !Role.hasStatus("faint") && !Role.hasStatus("rash");
  1802. },
  1803.  
  1804. gains(from, to) {
  1805. var theGains = Role._gains.slice();
  1806. var start = -1;
  1807. var end = -1;
  1808. for (let i = 0; i < theGains.length; i++) {
  1809. const gain = theGains[i];
  1810. if (gain.timestamp >= from) { start = i; break; }
  1811. }
  1812. for (let j = theGains.length - 1; j >= 0; j--) {
  1813. const gain = theGains[j];
  1814. if (gain.timestamp <= to) { end = j; break; }
  1815. }
  1816. if (start == -1 || end == -1) return [];
  1817. return theGains.slice(start, end + 1);
  1818. },
  1819.  
  1820. state: RoleState.none,
  1821.  
  1822. wearing: function (eqId) {
  1823. for (const eq of this.equipments) {
  1824. if (eq != null && eq.id == eqId) return true;
  1825. }
  1826. return false;
  1827. },
  1828.  
  1829. getEqId: function (index) {
  1830. const eq = this.equipments[index];
  1831. if (eq == null) return null;
  1832. return eq.id;
  1833. },
  1834.  
  1835. living: true,
  1836.  
  1837. combating: false,
  1838.  
  1839. rtime: false,
  1840.  
  1841. shimen: function (callback) {
  1842. var timestamp = new Date().getTime();
  1843. Role._shimen(0, timestamp, callback);
  1844. },
  1845.  
  1846. atPath: function (p) {
  1847. switch (arguments.length) {
  1848. case 0:
  1849. return Room.path;
  1850. case 1:
  1851. return p == Room.path;
  1852. }
  1853. },
  1854. inRoom: function (n) {
  1855. switch (arguments.length) {
  1856. case 0:
  1857. return Room.name;
  1858. case 1:
  1859. return n == Room.name;
  1860. }
  1861. },
  1862.  
  1863. findItem: function (itemName, blurry, quality, filterExp) {
  1864. return FindItem(Object.values(Role.items), itemName, blurry, quality, filterExp);
  1865. },
  1866.  
  1867. renew: function (callback) {
  1868. const source = `
  1869. stopstate;$to 扬州城-武庙
  1870. @liaoshang
  1871. [if] (:mpPer)<0.8
  1872. @dazuo
  1873. stopstate
  1874. `;
  1875. const p = new Performer("", source);
  1876. p.start(callback);
  1877. },
  1878.  
  1879. cleanBag: function (callback) {
  1880. WG.clean_all();
  1881. if (callback) callback();
  1882. },
  1883.  
  1884. tidyBag: function (callback) {
  1885. Role._tidyBag(0, callback);
  1886. },
  1887.  
  1888. hasCoolingSkill: function () {
  1889. return Role._coolingSkills.length > 0;
  1890. },
  1891. coolingSkills: function () {
  1892. var result = [];
  1893. for (const mark of Role._coolingSkills) {
  1894. result.push(mark.split("_")[0]);
  1895. }
  1896. return result;
  1897. },
  1898. coolingSkill: function (skill) {
  1899. return this.coolingSkills().indexOf(skill) != -1
  1900. },
  1901. hasSkill: function (skill) {
  1902. var combatStr = $('.combat-commands').html()
  1903. if (combatStr.indexOf(skill) != -1) {
  1904. return true;
  1905. } else {
  1906. return false;
  1907. }
  1908. },
  1909. weapon: function () {
  1910. return Role._weaponType
  1911. },
  1912.  
  1913. _renewHookIndex: null,
  1914. _renewStatus: "resting",
  1915.  
  1916. _coolingSkills: [],
  1917. _gains: [], // [{timestamp: number, name: string, count: number, unit: string}]
  1918.  
  1919. _shimen: function (counter, timestamp, callback) {
  1920. if (counter == 0) {
  1921. WG.SendCmd("stopstate");
  1922. WG.sm_button();
  1923. }
  1924. var result = SystemTips.search("你先去休息|和本门毫无瓜葛|你没有", timestamp);
  1925. if (result != null) { callback(); return; }
  1926. setTimeout(function () { Role._shimen(counter + 1, timestamp, callback) }, 1000);
  1927. },
  1928.  
  1929. _tidyBag: function (counter, callback) {
  1930. if (counter == 0) WG.sell_all();
  1931.  
  1932. if (!WG.packup_listener) {
  1933. window.setTimeout(callback, 1000);
  1934. return;
  1935. }
  1936. if (counter > 10) {
  1937. if (WG.packup_listener) WG.sell_all();
  1938. callback();
  1939. return;
  1940. }
  1941. window.setTimeout(function () { Role._tidyBag(counter + 1, callback); }, 1000);
  1942. },
  1943.  
  1944. _monitorHpMp: function () {
  1945. WG.add_hook(["items", "sc", "itemadd"], function (data) {
  1946. switch (data.type) {
  1947. case "items":
  1948. if (data.items == null) break;
  1949. for (var i = data.items.length - 1; i >= 0; i--) {
  1950. var item = data.items[i];
  1951. if (item.id == Role.id) {
  1952. Role.hp = item.hp;
  1953. Role.maxHp = item.max_hp;
  1954. Role.mp = item.mp;
  1955. Role.maxMp = item.max_mp;
  1956. break;
  1957. }
  1958. }
  1959. break;
  1960. case "itemadd":
  1961. case "sc":
  1962. if (data.id != Role.id) break;
  1963. if (data.hp != null) Role.hp = data.hp;
  1964. if (data.max_hp != null) Role.maxHp = data.max_hp;
  1965. if (data.mp != null) Role.mp = data.mp;
  1966. if (data.max_mp != null) Role.maxMp = data.max_mp;
  1967. break;
  1968. }
  1969. });
  1970. },
  1971. _monitorStatus: function () {
  1972. WG.add_hook(["items", "status", "itemadd"], function (data) {
  1973. switch (data.type) {
  1974. case "items":
  1975. if (data.items == null) break;
  1976. for (var i = data.items.length - 1; i >= 0; i--) {
  1977. var item = data.items[i];
  1978. if (item.id != Role.id) continue;
  1979. if (item.status == null) break;
  1980. Role.status = {};
  1981. var timestamp = new Date().getTime();
  1982. for (var j = item.status.length - 1; j >= 0; j--) {
  1983. var s = item.status[j];
  1984. Role.status[s.sid] = timestamp + s.duration - s.overtime;
  1985. }
  1986. break;
  1987. }
  1988. break;
  1989. case "status":
  1990. if (data.id != Role.id) break;
  1991. var timestamp1 = new Date().getTime();
  1992. if (data.action == "add") {
  1993. Role.status[data.sid] = timestamp1 + data.duration;
  1994. } else if (data.action == "remove") {
  1995. delete Role.status[data.sid];
  1996. }
  1997. break;
  1998. case "itemadd":
  1999. if (data.id != Role.id) break;
  2000. if (data.status == null) break;
  2001. Role.status = {};
  2002. var timestamp2 = new Date().getTime();
  2003. for (var k = data.status.length - 1; k >= 0; k--) {
  2004. var s1 = data.status[k];
  2005. Role.status[s1.sid] = timestamp2 + s1.duration - s1.overtime;
  2006. }
  2007. break;
  2008. }
  2009. });
  2010. },
  2011. _monitorState: function () {
  2012. WG.add_hook("state", function (data) {
  2013. var text = data.state;
  2014. if (text == null) {
  2015. Role.state = RoleState.none;
  2016. return;
  2017. }
  2018. for (const key in RoleState) {
  2019. if (!RoleState.hasOwnProperty(key)) continue;
  2020. const keyword = RoleState[key];
  2021. if (text.indexOf(keyword) != -1) {
  2022. Role.state = keyword;
  2023. return;
  2024. }
  2025. }
  2026. Role.state = RoleState.none;
  2027. });
  2028. },
  2029. _monitorDeath: function () {
  2030. WG.add_hook("die", function (data) {
  2031. if (data.relive == true) {
  2032. Role.living = true;
  2033. } else {
  2034. Role.living = false;
  2035. }
  2036. });
  2037. },
  2038. _monitorInfo: function () {
  2039. WG.add_hook("dialog", function (data) {
  2040. if (data.dialog == "score" && data.id == Role.id) {
  2041. if (data.level != null) {
  2042. var dd = data.level.replace(/<\/?.+?>/g, "");
  2043. Role.grade = dd.replace(/ /g, "");
  2044. }
  2045. if (data.family != null) {
  2046. Role.family = data.family;
  2047. }
  2048. if (data.jingli != null) {
  2049. var dd = data.jingli.split("/");
  2050. Role.energy = dd[0];
  2051. }
  2052. }
  2053. });
  2054. },
  2055. _monitorItems: function () {
  2056. WG.add_hook("dialog", function (data) {
  2057. if (data.dialog == null) return;
  2058. if (data.dialog == "pack") {
  2059. if (data.items != null) {
  2060. Role.items = {};
  2061. for (const item of data.items) {
  2062. if (item.id) Role.items[item.id] = item;
  2063. }
  2064. } else if (data.id != null) {
  2065. if (data.remove == null && data.count != null) {
  2066. Role.items[data.id] = data;
  2067. return;
  2068. } else if (data.remove != null) {
  2069. var item = Role.items[data.id];
  2070. if (item == null) return; // 从随从那里那回东西
  2071. if (item.count != null) {
  2072. item.count -= data.remove;
  2073. } else {
  2074. item.count = 0;
  2075. }
  2076. if (item.count == 0) delete Role.items[data.id];
  2077. }
  2078. }
  2079. if (data.eqs != null) {
  2080. Role.equipments = CopyObject(data.eqs);
  2081. } else if (data.uneq != null && data.id != null) {
  2082. let item = Role.equipments[data.uneq];
  2083. item.count = 1;
  2084. item.id = data.id;
  2085. Role.items[item.id] = item;
  2086. Role.equipments[data.uneq] = null;
  2087. } else if (data.eq != null && data.id != null) {
  2088. let item = Role.items[data.id];
  2089. Role.equipments[data.eq] = item;
  2090. delete Role.items[data.id];
  2091. }
  2092. if (data.money != null) {
  2093. Role.money = data.money;
  2094. }
  2095. }
  2096. if (data.dialog == "list") {
  2097. if (data.stores != null) {
  2098. Role.stores = {};
  2099. for (const item of data.stores) {
  2100. if (item.id) Role.stores[item.id] = item;
  2101. }
  2102. } else if (data.id != null && data.storeid != null && data.store != null) {
  2103. var item = Role.items[data.id];
  2104. var store = Role.stores[data.storeid];
  2105. if (item == null) {
  2106. item = Object.assign({}, store, { count: 0 });
  2107. item.id = data.id;
  2108. Role.items[item.id] = item;
  2109. }
  2110. if (store == null) {
  2111. store = Object.assign({}, item, { count: 0 });
  2112. Role.stores[store.id] = store;
  2113. }
  2114. item.count -= data.store;
  2115. store.count += data.store;
  2116. if (item.count <= 0) delete Role.items[data.id];
  2117. if (store.count <= 0) delete Role.stores[data.storeid];
  2118. }
  2119. }
  2120. });
  2121. },
  2122. _monitorGains: function () {
  2123. WG.add_hook("dialog", function (data) {
  2124. if (data.dialog != "pack" || data.id == null || data.name == null || data.unit == null || data.count == null || data.remove != null) return;
  2125. var timestamp = new Date().getTime();
  2126. // [{timestamp: number, name: string, count: number, unit: string}]
  2127. var old = Role.items[data.id];
  2128. var count = data.count;
  2129. if (old != null && old.count != null) {
  2130. count -= old.count;
  2131. }
  2132. var gain = { timestamp: timestamp, name: data.name, count: count, unit: data.unit };
  2133. Role._gains.push(gain);
  2134. });
  2135. },
  2136. _monitorSkillCD: function () {
  2137. WG.add_hook("dispfm", function (data) {
  2138. var timestamp = Date.parse(new Date());
  2139. var mark = data.id + "_" + timestamp;
  2140. Role._coolingSkills.push(mark);
  2141. window.setTimeout(function () {
  2142. var index = Role._coolingSkills.indexOf(mark);
  2143. if (index != -1) Role._coolingSkills.splice(index, 1);
  2144. }, data.distime);
  2145. if (data.rtime != null && data.rtime != 0) {
  2146. if (Role._rtimer != null) clearTimeout(Role._rtimer);
  2147. Role.rtime = true;
  2148. Role._rtimer = setTimeout(_ => {
  2149. Role.rtime = false;
  2150. }, data.rtime);
  2151. }
  2152. });
  2153. },
  2154. _monitorSkills: function () {
  2155. var action = function (id, value, s_name) {
  2156. switch (id) {
  2157. case "unarmed":
  2158. Role.kongfu.quan = value;Role.kongfu.quan_c = s_name; break;
  2159. case "force":
  2160. Role.kongfu.nei = value; Role.kongfu.nei_c = s_name; break;
  2161. case "parry":
  2162. Role.kongfu.zhao = value; Role.kongfu.zhao_c = s_name; break;
  2163. case "dodge":
  2164. Role.kongfu.qing = value; Role.kongfu.qing_c = s_name; break;
  2165. case "sword":
  2166. Role.kongfu.jian = value; Role.kongfu.jian_c = s_name; break;
  2167. case "blade":
  2168. Role.kongfu.dao = value; Role.kongfu.dao_c = s_name; break;
  2169. case "club":
  2170. Role.kongfu.gun = value; Role.kongfu.gun_c = s_name; break;
  2171. case "staff":
  2172. Role.kongfu.zhang = value; Role.kongfu.zhang_c = s_name; break;
  2173. case "whip":
  2174. Role.kongfu.bian = value; Role.kongfu.bian_c = s_name; break;
  2175. case "throwing":
  2176. Role.kongfu.an = value; Role.kongfu.an_c = s_name; break;
  2177. default:
  2178. break;
  2179. }
  2180. };
  2181. WG.add_hook("dialog", function (data) {
  2182. if (data.dialog == null || data.dialog != "skills") return;
  2183. if (data.items != null) {
  2184. for (const item of data.items) {
  2185. var value = item.enable_skill ? item.enable_skill : null;
  2186. var s_name = "";
  2187. Role.skills = data.items;
  2188. for (const sklii_item of data.items) {
  2189. if (sklii_item.id == value) {
  2190. s_name = /<([^<>]*)>/.exec(sklii_item.name)[1]
  2191. }
  2192. }
  2193. action(item.id, value, s_name.toLocaleLowerCase());
  2194. }
  2195. }
  2196. if (data.id != null && data.enable != null) {
  2197. var value = data.enable;
  2198. if (value == false) value = "none";
  2199. var s_name = ""
  2200. for (const sklii_item of Role.skills) {
  2201. if (sklii_item.id == value) {
  2202. s_name = /<([^<>]*)>/.exec(sklii_item.name)[1]
  2203. }
  2204. }
  2205. action(data.id, value, s_name);
  2206. }
  2207. });
  2208. },
  2209. _monitorCombat: function () {
  2210. WG.add_hook("combat", function (data) {
  2211. if (data.start != null && data.start == 1) {
  2212. Role.combating = true;
  2213. } else if (data.end != null && data.end == 1) {
  2214. Role.combating = false;
  2215. }
  2216. });
  2217. WG.add_hook("text", function (data) {
  2218. if (data.msg == null) return;
  2219. if (data.msg.indexOf('只能在战斗中使用') != -1 || data.msg.indexOf('这里不允许战斗') != -1 || data.msg.indexOf('没时间这么做') != -1) {
  2220. Role.combating = false;
  2221. }
  2222. if (data.msg.indexOf('战斗中打坐,你找死吗?') != -1 || data.msg.indexOf('你正在战斗') != -1) {
  2223. Role.combating = true;
  2224. }
  2225. });
  2226.  
  2227. },
  2228. _monitorWeapon: function () {
  2229. WG.add_hook("perform", function (data) {
  2230. if (data.skills != null) {
  2231. if (JSON.stringify(data.skills).indexOf("sword") != -1) {
  2232. Role._weaponType = 'sword'
  2233. } else if (JSON.stringify(data.skills).indexOf("blade") != -1) {
  2234. Role._weaponType = 'blade'
  2235. } else {
  2236. Role._weaponType = ''
  2237. }
  2238. }
  2239.  
  2240. });
  2241.  
  2242. }
  2243. };
  2244.  
  2245. var Room = {
  2246. name: null,
  2247. path: null,
  2248.  
  2249. updateTimestamp: null,
  2250.  
  2251. init: function () {
  2252. this._monitorLocation();
  2253. this._monitorItemsInRoom();
  2254. this._monitorDeath();
  2255. },
  2256. getItem: function (id) {
  2257. return this._itemsInRoom[id];
  2258. },
  2259. getItemId: function (name, blurry, living, filterExp) {
  2260. for (const item of Object.values(this._itemsInRoom)) {
  2261. if (blurry == true) {
  2262. if (item.name.indexOf(name) != -1) {
  2263. if (living == true && item.name.indexOf("的尸体") != -1) {
  2264. continue;
  2265. }
  2266. if (FilterCenter.filter(filterExp, item)) {
  2267. continue;
  2268. }
  2269. return item.id;
  2270. }
  2271. } else {
  2272. if (item.name == name && !FilterCenter.filter(filterExp, item)) {
  2273. return item.id;
  2274. }
  2275. }
  2276. }
  2277. return null;
  2278. },
  2279. /**
  2280. * @param {{name: string, blurry: Boolean}[]} itemNameInfos
  2281. * @returns {Boolean}
  2282. */
  2283. didKillItemsInRoom: function (itemNameInfos) {
  2284. var deadItems = this._deadItemsInRoom.slice();
  2285. for (const info of itemNameInfos) {
  2286. var found = false;
  2287. for (let j = 0; j < deadItems.length; j++) {
  2288. const deadItem = deadItems[j];
  2289. if (info.blurry == true) {
  2290. if (deadItem.name.indexOf(info.name) != -1) found = true;
  2291. } else {
  2292. if (deadItem.name == info.name) found = true;
  2293. }
  2294. if (found) {
  2295. deadItems.splice(j, 1);
  2296. break;
  2297. }
  2298. }
  2299. if (!found) return false;
  2300. }
  2301. return true;
  2302. },
  2303.  
  2304. _itemsInRoom: {},
  2305. _deadItemsInRoom: [],
  2306.  
  2307. _monitorLocation: function () {
  2308. WG.add_hook("room", function (data) {
  2309. Room.name = data.name;
  2310. Room.path = data.path;
  2311. Room.updateTimestamp = new Date().getTime();
  2312. Room._itemsInRoom = {};
  2313. Room._deadItemsInRoom = [];
  2314. });
  2315. },
  2316. _monitorItemsInRoom: function () {
  2317. WG.add_hook(["items", "itemadd", "itemremove", "sc", "status"], function (data) {
  2318. switch (data.type) {
  2319. case "items":
  2320. if (data.items == null) break;
  2321. for (const item of data.items) {
  2322. if (item.name == null || item.id == null) continue;
  2323. Room._itemsInRoom[item.id] = item;
  2324. }
  2325. break;
  2326. case "itemadd":
  2327. if (data.name == null || data.id == null) break;
  2328. Room._itemsInRoom[data.id] = data;
  2329. break;
  2330. case "itemremove":
  2331. if (data.id == null) break;
  2332. delete Room._itemsInRoom[data.id];
  2333. break;
  2334. case "sc": {
  2335. if (data.id == null) break;
  2336. const item = Room._itemsInRoom[data.id];
  2337. if (item == null) break;
  2338. if (data.hp != null) item.hp = data.hp;
  2339. if (data.max_hp != null) item.max_hp = data.max_hp;
  2340. if (data.mp != null) item.mp = data.mp;
  2341. if (data.max_mp != null) item.max_mp = data.max_mp;
  2342. break;
  2343. }
  2344. case "status": {
  2345. if (data.action == null || data.id == null || data.sid == null) return;
  2346. const item = Room._itemsInRoom[data.id];
  2347. if (item == null) break;
  2348. if (data.action == "add") {
  2349. if (item.status == null) item.status = [];
  2350. item.status.push({ sid: data.sid, name: data.name, duration: data.duration, overtime: 0 });
  2351. } else if (data.action == "remove") {
  2352. for (let i = 0; i < item.status.length; i++) {
  2353. const s = item.status[i];
  2354. if (s.sid == data.sid) {
  2355. item.status.splice(i, 1);
  2356. break;
  2357. }
  2358. }
  2359. }
  2360. break;
  2361. }
  2362. }
  2363. });
  2364. },
  2365. _monitorDeath: function () {
  2366. WG.add_hook("sc", function (data) {
  2367. if (data.id == null || data.hp == null || data.hp != 0) return;
  2368. for (const item of Object.values(Room._itemsInRoom)) {
  2369. if (item.id == data.id) {
  2370. Room._deadItemsInRoom.push(item);
  2371. return;
  2372. }
  2373. }
  2374. });
  2375. }
  2376. };
  2377.  
  2378. class SystemTip {
  2379. constructor(text) {
  2380. this.timestamp = new Date().getTime();
  2381. this.text = text;
  2382. }
  2383. }
  2384.  
  2385. var SystemTips = {
  2386. init: function () {
  2387. this._monitorSystemTips();
  2388. },
  2389. search: function (regex, from) {
  2390. var patt = new RegExp(regex);
  2391. var tips = this._tips.slice();
  2392. for (let index = tips.length - 1; index >= 0; index--) {
  2393. const tip = tips[index];
  2394. if (tip.timestamp < from) break;
  2395. var result = patt.exec(tip.text);
  2396. if (result) return result;
  2397. }
  2398. return null;
  2399. },
  2400. clean: function (to) {
  2401. while (true) {
  2402. if (this._tips.length <= 0) break;
  2403. var tip = this._tips[0];
  2404. if (tip.timestamp > to) break;
  2405. this._tips.shift();
  2406. }
  2407. },
  2408. rejectTimestamp: null,
  2409.  
  2410. _monitorSystemTips: function () {
  2411. var theSelf = this;
  2412. WG.add_hook("text", function (data) {
  2413. var tip = new SystemTip(data.msg);
  2414. theSelf._push(tip);
  2415.  
  2416. if (data.msg == "不要急,慢慢来。") {
  2417. theSelf.rejectTimestamp = new Date().getTime();
  2418. }
  2419. });
  2420. WG.add_hook("item", function (data) {
  2421. var desc = data.desc;
  2422. if (desc == null) return;
  2423. var tip = new SystemTip(desc);
  2424. theSelf._push(tip);
  2425. });
  2426. },
  2427. _push: function (tip) {
  2428. if (this._tips.length >= this._maxCapacity) {
  2429. this._tips.shift();
  2430. }
  2431. this._tips.push(tip);
  2432. },
  2433. _tips: [],
  2434. _maxCapacity: 100,
  2435. };
  2436. class MsgTip {
  2437. constructor(content, ch, name, uid) {
  2438. this.timestamp = new Date().getTime();
  2439. this.content = content;
  2440. this.ch = ch;
  2441. this.name = name;
  2442. this.uid = uid;
  2443. }
  2444. }
  2445.  
  2446. var MsgTips = {
  2447. init: function () {
  2448. this._monitorSystemTips();
  2449. },
  2450. search: function (regex, from) {
  2451. var patt = new RegExp(regex);
  2452. var tips = this._tips.slice();
  2453. for (let index = tips.length - 1; index >= 0; index--) {
  2454. const tip = tips[index];
  2455. if (tip.timestamp < from) break;
  2456. var result = patt.exec(tip.content);
  2457. if (result) return result;
  2458. }
  2459. return null;
  2460. },
  2461. clean: function (to) {
  2462. while (true) {
  2463. if (this._tips.length <= 0) break;
  2464. var tip = this._tips[0];
  2465. if (tip.timestamp > to) break;
  2466. this._tips.shift();
  2467. }
  2468. },
  2469. rejectTimestamp: null,
  2470.  
  2471. _monitorSystemTips: function () {
  2472. var theSelf = this;
  2473. WG.add_hook("msg", function (data) {
  2474. // console.log(data)
  2475. var tip = new MsgTip(data.content, data.ch, data.name, data.uid);
  2476. theSelf._push(tip);
  2477. });
  2478. },
  2479. _push: function (tip) {
  2480. if (this._tips.length >= this._maxCapacity) {
  2481. this._tips.shift();
  2482. }
  2483. this._tips.push(tip);
  2484. },
  2485. _tips: [],
  2486. _maxCapacity: 100,
  2487. };
  2488.  
  2489. var DialogList = {
  2490. init: function () {
  2491. this._monitorDialogList();
  2492. },
  2493. timestamp: null,
  2494. findItem: function (itemName, blurry, quality, filterExp) {
  2495. return FindItem(this._list, itemName, blurry, quality, filterExp);
  2496. },
  2497.  
  2498. _list: [],
  2499. _monitorDialogList: function () {
  2500. const self = this;
  2501. WG.add_hook("dialog", function (data) {
  2502. let list = null;
  2503. if (data.selllist != null) {
  2504. list = data.selllist;
  2505. } else if (data.stores != null) {
  2506. list = data.stores;
  2507. } else if (data.dialog == "pack2" && data.items != null) {
  2508. list = data.items;
  2509. }
  2510. if (list == null) return;
  2511. self.timestamp = new Date().getTime();
  2512. self._list = list;
  2513. });
  2514. },
  2515. };
  2516.  
  2517. var TaskList = {
  2518. init: function () {
  2519. this._monitorTasksList();
  2520. },
  2521. search: function (regex, from) {
  2522. if (this._timestamp < from) return null;
  2523. var patt = new RegExp(regex);
  2524. for (const task of this._list) {
  2525. const result = patt.exec(task);
  2526. if (result) return result;
  2527. }
  2528. return null;
  2529. },
  2530.  
  2531. _timestamp: null,
  2532. _list: [],
  2533. _monitorTasksList: function () {
  2534. const self = this;
  2535. WG.add_hook("dialog", function (data) {
  2536. if (data.dialog == null || data.dialog != "tasks" || data.items == null) return;
  2537. let list = [];
  2538. for (const item of data.items) {
  2539. list.push(item.desc);
  2540. }
  2541. self._timestamp = new Date().getTime();
  2542. self._list = list;
  2543. });
  2544. }
  2545. };
  2546.  
  2547. var Xiangyang = {
  2548. init: function () {
  2549. this._monitorXiangyang();
  2550. },
  2551. search: function (regex, from) {
  2552. if (this._timestamp < from) return null;
  2553. var patt = new RegExp(regex);
  2554. const result = patt.exec(this._desc);
  2555. if (result) return result;
  2556. return null;
  2557. },
  2558.  
  2559. _timestamp: null,
  2560. _desc: '',
  2561. _monitorXiangyang: function () {
  2562. const self = this;
  2563. WG.add_hook('dialog', function (data) {
  2564. if (data.dialog == null || data.t != 'fam' || data.index != 8 || data.desc == null) return;
  2565. self._timestamp = new Date().getTime();
  2566. self._desc = data.desc;
  2567. });
  2568. }
  2569. };
  2570.  
  2571. /***********************************************************************************\
  2572. Persistent Cache
  2573. \***********************************************************************************/
  2574.  
  2575. (function () {
  2576. const FlowStoreKey = function () { return `flow_store@${Role.id}`; };
  2577. const getMap = function () {
  2578. let map = GM_getValue(FlowStoreKey(), null);
  2579. if (map == null) {
  2580. // 之前 FlowStoreKey 会错误地一只返回 flow_store@null
  2581. map = GM_getValue("flow_store@null", {});
  2582. }
  2583. return map;
  2584. };
  2585. FlowStore = new PersistentCache((key, value) => {
  2586. let map = getMap();
  2587. map[key] = value;
  2588. GM_setValue(FlowStoreKey(), map);
  2589. }, _ => {
  2590. return getMap();
  2591. }, key => {
  2592. let map = getMap();
  2593. delete map[key];
  2594. GM_setValue(FlowStoreKey(), map);
  2595. });
  2596. FlowStore.corver = function (value) {
  2597. GM_setValue(FlowStoreKey(), value);
  2598. };
  2599. })();
  2600.  
  2601. (function () {
  2602. const PersistentVariablesKey = function () { return `global_params@${Role.id}`; };
  2603. const getMap = function () {
  2604. let map = GM_getValue(PersistentVariablesKey(), null);
  2605. if (map == null) {
  2606. // 之前 PersistentVariablesKey 会错误地一只返回 global_params@null
  2607. map = GM_getValue("global_params@null", {});
  2608. }
  2609. return map;
  2610. };
  2611. PersistentVariables = new PersistentCache((key, value) => {
  2612. let map = getMap();
  2613. map[key] = value;
  2614. GM_setValue(PersistentVariablesKey(), map);
  2615. }, _ => {
  2616. return getMap();
  2617. }, key => {
  2618. let map = getMap();
  2619. delete map[key];
  2620. GM_setValue(PersistentVariablesKey(), map);
  2621. });
  2622. VariableStore.register(_ => { return PersistentVariables.getAll(); });
  2623. })();
  2624.  
  2625. VariableStore.register(_ => {
  2626. return {
  2627. ":online": WG.online,
  2628. ":id": Role.id,
  2629. ":name": Role.name,
  2630. ":grade": Role.grade,
  2631. ":family": Role.family,
  2632. ":energy": Role.energy,
  2633. ":money": Role.money,
  2634. ":hp": Role.hp,
  2635. ":maxHp": Role.maxHp,
  2636. ":hpPer": Role.hp / Role.maxHp, // 0-1
  2637. ":mp": Role.mp,
  2638. ":maxMp": Role.maxMp,
  2639. ":mpPer": Role.mp / Role.maxMp, // 0-1
  2640. ":living": Role.living, // true/false
  2641. ":state": Role.state, // RoleState
  2642. ":combating": Role.combating, // true/false
  2643. ":free": Role.isFree,
  2644. ":gains": Role.profitInfo,
  2645.  
  2646. ":room": Room.name,
  2647. ":path": Room.path,
  2648.  
  2649. ":eq0": Role.getEqId(0),
  2650. ":eq1": Role.getEqId(1),
  2651. ":eq2": Role.getEqId(2),
  2652. ":eq3": Role.getEqId(3),
  2653. ":eq4": Role.getEqId(4),
  2654. ":eq5": Role.getEqId(5),
  2655. ":eq6": Role.getEqId(6),
  2656. ":eq7": Role.getEqId(7),
  2657. ":eq8": Role.getEqId(8),
  2658. ":eq9": Role.getEqId(9),
  2659. ":eq10": Role.getEqId(10),
  2660.  
  2661. ":kf_quan": Role.kongfu.quan,
  2662. ":kf_nei": Role.kongfu.nei,
  2663. ":kf_zhao": Role.kongfu.zhao,
  2664. ":kf_qing": Role.kongfu.qing,
  2665. ":kf_jian": Role.kongfu.jian,
  2666. ":kf_dao": Role.kongfu.dao,
  2667. ":kf_gun": Role.kongfu.gun,
  2668. ":kf_zhang": Role.kongfu.zhang,
  2669. ":kf_bian": Role.kongfu.bian,
  2670. ":kf_an": Role.kongfu.an,
  2671.  
  2672. ":kf_quan_c": Role.kongfu.quan_c,
  2673. ":kf_nei_c": Role.kongfu.nei_c,
  2674. ":kf_zhao_c": Role.kongfu.zhao_c,
  2675. ":kf_qing_c": Role.kongfu.qing_c,
  2676. ":kf_jian_c": Role.kongfu.jian_c,
  2677. ":kf_dao_c": Role.kongfu.dao_c,
  2678. ":kf_gun_c": Role.kongfu.gun_c,
  2679. ":kf_zhang_c": Role.kongfu.zhang_c,
  2680. ":kf_bian_c": Role.kongfu.bian_c,
  2681. ":kf_an_c": Role.kongfu.an_c
  2682. };
  2683. });
  2684.  
  2685. VariableStore.register(_ => {
  2686. return {
  2687. ":room ": function (param) {
  2688. const parts = param.split(",");
  2689. for (const part of parts) {
  2690. if (Room.name.indexOf(part) != -1) return true;
  2691. }
  2692. return false;
  2693. },
  2694. ":cd ": function (sid) {
  2695. return Role.coolingSkill(sid);
  2696. },
  2697. ":status ": function (param) {
  2698. const parts = param.split(",");
  2699. if (parts.length > 1) {
  2700. const status = parts[0];
  2701. const id = parts[1];
  2702. const item = Room.getItem(id);
  2703. if (item == null || item.status == null) return false;
  2704. for (const s of item.status) {
  2705. if (s.sid == status) return true;
  2706. }
  2707. return false;
  2708. }
  2709. return Role.hasStatus(param);
  2710. },
  2711. ":hp ": function (id) {
  2712. const item = Room.getItem(id);
  2713. if (item != null) return item.hp;
  2714. return -1;
  2715. },
  2716. ":weapon ": function (id) {
  2717. return id == Role.weapon()
  2718. },
  2719. ":maxHp ": function (id) {
  2720. const item = Room.getItem(id);
  2721. if (item != null) return item.max_hp;
  2722. return -1;
  2723. },
  2724. ":mp ": function (id) {
  2725. const item = Room.getItem(id);
  2726. if (item != null) return item.mp;
  2727. return -1;
  2728. },
  2729. ":maxMp ": function (id) {
  2730. const item = Room.getItem(id);
  2731. if (item != null) return item.max_mp;
  2732. return -1;
  2733. },
  2734. ":exist ": function (id) {
  2735. if (id == null) return false;
  2736. const item = Room.getItem(id);
  2737. return item != null;
  2738. },
  2739. ":findName ": function (id) {
  2740. if (id == null) return null;
  2741. const item = Room.getItem(id);
  2742. //if (item != null) return item.name.match(/.*\s([\u4e00-\u9fa5]+)/)[1];
  2743. if (item != null) return item.name.replace(/<.+?>|&lt.*/g, '').split(' ').pop();
  2744. //if (item != null) return item.name.replace(/<.+?>|&lt.*/g, '').match(/(\p{Script=Han}\s)*(\p{Script=Han}*)/u)[2]
  2745. //if (item != null) return item.name.match(/(\p{Script=Han}\s)*(\p{Script=Han}*)/u)[2];
  2746. return null;
  2747. }
  2748. };
  2749. });
  2750.  
  2751. /***********************************************************************************\
  2752. WSMUD Cmd Prehandler And Handler
  2753. \***********************************************************************************/
  2754.  
  2755. //---------------------------------------------------------------------------
  2756. // WSMUD Raid 占位符
  2757. //---------------------------------------------------------------------------
  2758.  
  2759. const FilterCenter = {
  2760. filter: function (filterExp, obj) {
  2761. if (filterExp == null) {
  2762. return false;
  2763. }
  2764. const exp = filterExp.substring(1, filterExp.length - 2);
  2765. const yes = eval(`${exp}`);
  2766. return yes;
  2767. }
  2768. }
  2769.  
  2770. function ReplacePlaceholder(exp) {
  2771. var patt = /\{([a-z]?)([^a-z%#]+?|<\w+>[^a-z%#]+?<\/\w+>)([a-z]?)(%?)(#?)\}\??(#[^#{}]*#)?/g;
  2772. var placeholders = [];
  2773. var result = patt.exec(exp);
  2774. while (result != null) {
  2775. placeholders.push({
  2776. text: result[0],
  2777. location: result[1] == "" ? null : result[1],
  2778. name: result[2],
  2779. blurry: result[4] != "%",
  2780. quality: result[3] == "" ? null : result[3],
  2781. type: result[5] != "#" ? "id" : "amount",
  2782. filterExp: result[6]
  2783. });
  2784. result = patt.exec(exp);
  2785. }
  2786. const getValue = function (p) {
  2787. let locationOrder = [];
  2788. if (p.location == null) {
  2789. locationOrder = p.quality == null ? ["r", "b", "d"] : ["b", "d"];
  2790. } else {
  2791. locationOrder = [p.location];
  2792. }
  2793. for (const location of locationOrder) {
  2794. let value = null;
  2795. switch (location) {
  2796. case "r":
  2797. value = Room.getItemId(p.name, p.blurry, false, p.filterExp);
  2798. break;
  2799. case "b": {
  2800. let item = Role.findItem(p.name, p.blurry, p.quality, p.filterExp);
  2801. if (item) {
  2802. value = p.type == "id" ? item.id : item.count;
  2803. }
  2804. break;
  2805. }
  2806. case "d": {
  2807. let item = DialogList.findItem(p.name, p.blurry, p.quality, p.filterExp);
  2808. if (item) {
  2809. value = p.type == "id" ? item.id : item.count;
  2810. }
  2811. break;
  2812. }
  2813. }
  2814. if (value != null) return value;
  2815. }
  2816. return null;
  2817. };
  2818. let realExp = exp;
  2819. for (const p of placeholders) {
  2820. let value = getValue(p);
  2821. realExp = realExp.replace(p.text, value);
  2822. }
  2823. return realExp;
  2824. }
  2825.  
  2826. (function () {
  2827. const handle = function (performer, cmd) {
  2828. return ReplacePlaceholder(cmd);
  2829. };
  2830. const handler = new CmdPrehandler(handle)
  2831. CmdPrehandleCenter.shared().addHandler(handler);
  2832. })();
  2833.  
  2834. (function () {
  2835. const handle = function (cmds) {
  2836. var result = [];
  2837. var tempcmds = "";
  2838. var inString = false;
  2839. for (const cmd of cmds) {
  2840. if (cmd.indexOf("`")==0 || inString){
  2841. var ccmd = cmd
  2842. if (cmd.indexOf("`")==0){
  2843. ccmd=cmd.substr(1);
  2844. }
  2845. if (cmd[cmd.length-1]=="`"){
  2846. ccmd=cmd.substr(0,cmd.length-1);
  2847. }
  2848. tempcmds = tempcmds +" "+ccmd
  2849. inString= true;
  2850. }
  2851. if(cmd[cmd.length-1]=="`"){
  2852. result[result.length-1] = result[result.length-1] +tempcmds
  2853. tempcmds = "";
  2854. inString = false;
  2855. continue;
  2856. }
  2857. if(inString){
  2858. continue;
  2859. }
  2860. const header = /^\s*/.exec(cmd)[0];
  2861. let patt = /(\{[^\}]+\})([^\?]|$)/g;
  2862. let r = patt.exec(cmd);
  2863. let j = cmd.indexOf("@js")
  2864. while (r != null && j == -1) {
  2865. result.push(`${header}@until ${r[1]}? != null`);
  2866. r = patt.exec(cmd);
  2867. }
  2868. result.push(cmd);
  2869. }
  2870. return result;
  2871. };
  2872. const rule = new PrecompileRule(handle, PrecompileRulePriority.low);
  2873. PrecompileRuleCenter.shared().addRule(rule);
  2874. })();
  2875.  
  2876. //---------------------------------------------------------------------------
  2877. // WSMUD Raid 命令
  2878. //---------------------------------------------------------------------------
  2879.  
  2880. (function () {
  2881. const executor = new CmdExecutor(cmd => {
  2882. return cmd.indexOf("<-stopSSAuto") == 0 || cmd.indexOf("@stopSSAuto") == 0;
  2883. }, (performer, _) => {
  2884. if (performer.log()) Message.cmdLog("暂停自动婚宴和自动Boss", "目前手动终止流程不会自动恢复");
  2885. WG.stopAllAuto();
  2886. })
  2887. CmdExecuteCenter.addExecutor(executor);
  2888. })();
  2889.  
  2890. (function () {
  2891. const executor = new CmdExecutor(cmd => {
  2892. return cmd.indexOf("stopSSAuto->") == 0 || cmd.indexOf("@recoverSSAuto") == 0;
  2893. }, (performer, _) => {
  2894. if (performer.log()) Message.cmdLog("恢复自动婚宴和自动Boss设置");
  2895. WG.reSetAllAuto();
  2896. })
  2897. CmdExecuteCenter.addExecutor(executor);
  2898. })();
  2899.  
  2900. var __RecordGainsFrom = null;
  2901. (function () {
  2902. const executor = new CmdExecutor(cmd => {
  2903. return cmd.indexOf("<-recordGains") == 0;
  2904. }, (performer, _) => {
  2905. if (performer.log()) Message.cmdLog("开始记录物品获取");
  2906. __RecordGainsFrom = new Date().getTime();
  2907. })
  2908. CmdExecuteCenter.addExecutor(executor);
  2909. })();
  2910.  
  2911. (function () {
  2912. const executor = new CmdExecutor(cmd => {
  2913. return cmd.indexOf("recordGains->") == 0;
  2914. }, (_, cmd) => {
  2915. const gains = Role.gains(__RecordGainsFrom, new Date().getTime());
  2916. var result = {};
  2917. gains.forEach(gain => {
  2918. var oldCount = 0;
  2919. var old = result[gain.name];
  2920. if (old) oldCount = old.count;
  2921. result[gain.name] = { count: oldCount + gain.count, unit: gain.unit };
  2922. });
  2923. var content = "";
  2924. if (cmd.indexOf("recordGains->silent") == -1) {
  2925. Message.clean();
  2926. Message.append("&nbsp;&nbsp;> 战利品列表如下:");
  2927. }
  2928. for (const name in result) {
  2929. if (!result.hasOwnProperty(name)) continue;
  2930. const gain = result[name];
  2931. if (cmd.indexOf("recordGains->silent") == -1) {
  2932. Message.append("&nbsp;&nbsp;* " + name + " <wht>" + gain.count + gain.unit + "</wht>");
  2933. }
  2934. content += `&nbsp;&nbsp;* ${name} <wht>${gain.count}${gain.unit}</wht><br>`;
  2935. }
  2936.  
  2937. Role.profitInfo = content != "" ? content : null;
  2938.  
  2939. if (cmd.indexOf("recordGains->nopopup") == 0 || cmd.indexOf("recordGains->silent") == 0) return;
  2940. layer.open({
  2941. type: 1,
  2942. area: ["380px", "300px"],
  2943. title: "战利品列表",
  2944. content: content,
  2945. offset: 'auto',
  2946. shift: 2
  2947. });
  2948. })
  2949. CmdExecuteCenter.addExecutor(executor);
  2950. })();
  2951.  
  2952. (function () {
  2953. const executor = new AtCmdExecutor("toolbar", function (performer, param) {
  2954. performer.timeSeries(new Date().getTime());
  2955. $(`span[command=${param}]`).click();
  2956. return new Promise(resolve => {
  2957. setTimeout(_ => {
  2958. $(".glyphicon-remove-circle").click();
  2959. resolve();
  2960. }, 500);
  2961. });
  2962. });
  2963. CmdExecuteCenter.addExecutor(executor);
  2964. })();
  2965.  
  2966. (function () {
  2967. const executor = new UntilAtCmdExecutor("liaoshang", function (performer, param) {
  2968. if (Role.hp / Role.maxHp >= 1) {
  2969. WG.SendCmd("stopstate");
  2970. return true;
  2971. }
  2972. if (Role.state != RoleState.liaoshang) {
  2973. WG.SendCmd("stopstate;liaoshang");
  2974. }
  2975. return false;
  2976. }, null, 1000);
  2977. CmdExecuteCenter.addExecutor(executor);
  2978. })();
  2979.  
  2980. (function () {
  2981. const executor = new UntilAtCmdExecutor("dazuo", function (performer, param) {
  2982. if (Role.mp / Role.maxMp > 0.99) {
  2983. WG.SendCmd("stopstate");
  2984. return true;
  2985. }
  2986. if (Role.state != RoleState.dazuo) {
  2987. WG.SendCmd("stopstate;dazuo");
  2988. }
  2989. return false;
  2990. }, null, 1000);
  2991. CmdExecuteCenter.addExecutor(executor);
  2992. })();
  2993.  
  2994. (function () {
  2995. const executor = new UntilAtCmdExecutor("eq", function (performer, param) {
  2996. const eqIds = param.split(",");
  2997. let cmds = [];
  2998. eqIds.forEach(eqId => {
  2999. if (!Role.wearing(eqId)) cmds.push(`eq ${eqId}`);
  3000. });
  3001. if (cmds.length > 0) {
  3002. WG.SendCmd("stopstate;" + cmds.join(";"));
  3003. return false;
  3004. }
  3005. return true;
  3006. }, null, 1000);
  3007. CmdExecuteCenter.addExecutor(executor);
  3008. })();
  3009.  
  3010. (function () {
  3011. const executor = new UntilAtCmdExecutor("cd", function (performer, param) {
  3012. if (param == null) {
  3013. return !Role.hasCoolingSkill();
  3014. }
  3015.  
  3016. let validParam = param;
  3017. let isBlack = false;
  3018. if (validParam[0] == "^") {
  3019. validParam = validParam.substring(1);
  3020. isBlack = true;
  3021. }
  3022. const skills = validParam.split(",");
  3023. if (isBlack) {
  3024. for (const cooling of Role.coolingSkills()) {
  3025. if (skills.indexOf(cooling) == -1) {
  3026. return false;
  3027. }
  3028. }
  3029. } else {
  3030. let coolings = Role.coolingSkills();
  3031. for (const skill of skills) {
  3032. if (coolings.indexOf(skill) != -1) {
  3033. return false;
  3034. }
  3035. }
  3036. }
  3037. return true;
  3038. });
  3039. CmdExecuteCenter.addExecutor(executor);
  3040. })();
  3041.  
  3042. class UntilSearchedAtCmdExecutor extends UntilAtCmdExecutor {
  3043. constructor(key, search) {
  3044. const assert = function (performer, param) {
  3045. let placeholders = [];
  3046. let patt = /\(\$[a-zA-Z0-9_]+?\)/g;
  3047. let result = patt.exec(param);
  3048. while (result != null) {
  3049. placeholders.push(result[0]);
  3050. result = patt.exec(param);
  3051. }
  3052. let regex = param;
  3053. for (let i = 0; i < placeholders.length; i++) {
  3054. const placeholder = placeholders[i];
  3055. regex = regex.replace(placeholder, "(.+?)");
  3056. }
  3057. let result2 = search(regex, performer.timeSeries());
  3058. if (result2 == null) {
  3059. return false;
  3060. }
  3061. for (let j = 0; j < placeholders.length; j++) {
  3062. const placeholder = placeholders[j];
  3063. let key = placeholder.substring(2, placeholder.length - 1);
  3064. let value = result2[j + 1];
  3065. if (value != null) {
  3066. UpdateVariable(performer, key, value);
  3067. }
  3068. }
  3069. return true;
  3070. };
  3071. super(key, assert);
  3072. }
  3073. }
  3074.  
  3075. (function () {
  3076. const executor = new UntilSearchedAtCmdExecutor("tip", (regex, from) => {
  3077. return SystemTips.search(regex, from);
  3078. });
  3079. CmdExecuteCenter.addExecutor(executor);
  3080. })();
  3081.  
  3082. (function () {
  3083. const executor = new UntilSearchedAtCmdExecutor("msgtip", (regex, from) => {
  3084. return MsgTips.search(regex, from);
  3085. });
  3086. CmdExecuteCenter.addExecutor(executor);
  3087. })();
  3088.  
  3089. (function () {
  3090. const executor = new UntilSearchedAtCmdExecutor("task", (regex, from) => {
  3091. return TaskList.search(regex, from);
  3092. });
  3093. CmdExecuteCenter.addExecutor(executor);
  3094. })();
  3095.  
  3096. (function () {
  3097. const executor = new UntilSearchedAtCmdExecutor("xy", (regex, from) => {
  3098. return Xiangyang.search(regex, from);
  3099. });
  3100. CmdExecuteCenter.addExecutor(executor);
  3101. })();
  3102.  
  3103. (function () {
  3104. const executor = new UntilAtCmdExecutor("kill", function (performer, param) {
  3105. const parts = param.split(",");
  3106. let infos = [];
  3107. for (let i = 0; i < parts.length; i++) {
  3108. const name = parts[i];
  3109. let blurry = true;
  3110. if (name.substring(name.length - 1) == "%") {
  3111. name = name.substring(0, name.length - 1);
  3112. blurry = false;
  3113. }
  3114. infos.push({ name: name, blurry: blurry });
  3115. }
  3116. const finish = Room.didKillItemsInRoom(infos);
  3117. if (finish) {
  3118. return true;
  3119. } else {
  3120. let cmd = "";
  3121. infos.forEach(info => {
  3122. const itemId = Room.getItemId(info.name, info.blurry, true);
  3123. if (itemId != null) {
  3124. cmd += "kill " + itemId + ";";
  3125. }
  3126. });
  3127. WG.SendCmd(cmd);
  3128. return false;
  3129. }
  3130. }, null, 1000, 1000);
  3131. CmdExecuteCenter.addExecutor(executor);
  3132. })();
  3133.  
  3134. /* 等待,直到 dialog 打开,在打开 dialog 后调用,便于后续使用占位符 */
  3135. (function () {
  3136. const executor = new UntilAtCmdExecutor("dialog", function (performer, param) {
  3137. return DialogList.timestamp > performer.timeSeries();
  3138. });
  3139. CmdExecuteCenter.addExecutor(executor);
  3140. })();
  3141.  
  3142. function UntilRoleFreePerformerPromise(callback, log) {
  3143. return PerformerPromise("@until (:free) == true", callback, log);
  3144. }
  3145.  
  3146. (function () {
  3147. const executor = new AtCmdExecutor("cleanBag", function (performer, param) {
  3148. if (performer.log()) Message.cmdLog("清理包裹");
  3149. return UntilRoleFreePerformerPromise(resolve => {
  3150. WG.SendCmd("$cleanall");
  3151. setTimeout(resolve, 1000);
  3152. });
  3153. });
  3154. CmdExecuteCenter.addExecutor(executor);
  3155. })();
  3156.  
  3157. (function () {
  3158. const executor = new AtCmdExecutor("tidyBag", function (performer, param) {
  3159. if (performer.log()) Message.cmdLog("整理包裹");
  3160. return UntilRoleFreePerformerPromise(resolve => {
  3161. Role.tidyBag(_ => { setTimeout(resolve, 1000); });
  3162. });
  3163. });
  3164. CmdExecuteCenter.addExecutor(executor);
  3165. })();
  3166.  
  3167. (function () {
  3168. const executor = new AtCmdExecutor("shimen", function (performer, param) {
  3169. if (performer.log()) Message.cmdLog("自动完成允许放弃的放弃师门");
  3170. return UntilRoleFreePerformerPromise(resolve => {
  3171. Role.shimen(_ => { setTimeout(resolve, 1000); });
  3172. });
  3173. });
  3174. CmdExecuteCenter.addExecutor(executor);
  3175. })();
  3176.  
  3177. (function () {
  3178. const executor = new AtCmdExecutor("renew", function (performer, param) {
  3179. if (performer.log()) Message.cmdLog("恢复角色气血和内力");
  3180. return UntilRoleFreePerformerPromise(resolve => {
  3181. Role.renew(_ => { setTimeout(resolve, 1000); });
  3182. });
  3183. });
  3184. CmdExecuteCenter.addExecutor(executor);
  3185. })();
  3186.  
  3187. (function () {
  3188. const executor = new AtCmdExecutor("beep", function (performer, param) {
  3189. Beep();
  3190. });
  3191. CmdExecuteCenter.addExecutor(executor);
  3192. })();
  3193.  
  3194. (function () {
  3195. const executor = new AtCmdExecutor("push", function (performer, param) {
  3196. Push(param);
  3197. });
  3198. CmdExecuteCenter.addExecutor(executor);
  3199. })();
  3200.  
  3201. //---------------------------------------------------------------------------
  3202. // Skill State Machine
  3203. //---------------------------------------------------------------------------
  3204.  
  3205. var SkillStateMachine = {
  3206. perform: function (skill, force) {
  3207. // if (!Role.hasSkill(skill)) return;
  3208. const timestamp = new Date().getTime();
  3209. this._perform(skill, force, timestamp);
  3210. },
  3211. _perform: function (skill, force, timestamp) {
  3212. if (this._skillStack[skill] != null && this._skillStack[skill] > timestamp) return;
  3213. const self = this;
  3214. if ((!Role.isFree() && !force) || Role.coolingSkill(skill) || Role.rtime) {
  3215. setTimeout(_ => {
  3216. self._perform(skill, force, timestamp);
  3217.  
  3218. }, 200);
  3219. return;
  3220. }
  3221. // if (!Role.hasSkill(skill)) {
  3222. // if( self._performNum < 10){
  3223. // setTimeout(_ => {
  3224. // self._perform(skill, force, timestamp);
  3225. // }, 200);
  3226. // }else{
  3227. // self._performNum = 0;
  3228. // return;
  3229. // }
  3230. // self._performNum = self._performNum + 1;
  3231. // return;
  3232. // }
  3233. this._skillStack[skill] = timestamp;
  3234. WG.SendCmd(`perform ${skill}`);
  3235. const timer = setInterval(_ => {
  3236. if (Role.coolingSkill(skill) || Role.combating == false) {
  3237. clearInterval(timer);
  3238. if (self._skillStack[skill] != null && self._skillStack[skill] == timestamp) {
  3239. delete self._skillStack[skill];
  3240. }
  3241. return;
  3242. }
  3243. if (!Role.isFree() || Role.rtime) return;
  3244. WG.SendCmd(`perform ${skill}`);
  3245. }, 1000);
  3246. },
  3247. reset: function () {
  3248. this._skillStack = {};
  3249. },
  3250. _skillStack: {},
  3251. _performNum : 0
  3252. }
  3253.  
  3254. //---------------------------------------------------------------------------
  3255. // Send System Cmd
  3256. //---------------------------------------------------------------------------
  3257.  
  3258. var __systemCmdDelay = 1500;
  3259.  
  3260. (function () {
  3261. const executor = new AtCmdExecutor("cmdDelay", function (performer, param) {
  3262. performer._cmdDelay = parseInt(param);
  3263. });
  3264. CmdExecuteCenter.addExecutor(executor);
  3265. })();
  3266.  
  3267. const UnpackSystemCmd = function (cmd) {
  3268. let result = cmd;
  3269. let patt = /([^;]+)\[(\d+?)\]/g;
  3270. let r = patt.exec(cmd);
  3271. while (r != null) {
  3272. const packedCmd = r[1];
  3273. const count = parseInt(r[2]);
  3274. const temp = (new Array(count)).fill(packedCmd);
  3275. const unpackedCmd = temp.join(";");
  3276. result = result.replace(r[0], unpackedCmd);
  3277. r = patt.exec(cmd);
  3278. }
  3279. return result;
  3280. };
  3281.  
  3282. (function () {
  3283. function createWorker(f) {
  3284. var blob = new Blob(['(function(){' + f.toString() + '})()']);
  3285. var url = window.URL.createObjectURL(blob);
  3286. var worker = new Worker(url);
  3287. return worker;
  3288. }
  3289. const executor = new CmdExecutor(_ => {
  3290. return true;
  3291. }, (performer, cmd) => {
  3292. let validCmd = CmdPrehandleCenter.shared().handle(performer, cmd);
  3293. validCmd = UnpackSystemCmd(validCmd);
  3294. return UntilRoleFreePerformerPromise(resolve => {
  3295. const timestamp = new Date().getTime();
  3296. let delay = 0;
  3297. const fromReject = timestamp - SystemTips.rejectTimestamp;
  3298. if (fromReject < 1500) {
  3299. // console.log(fromReject);
  3300. delay = fromReject;
  3301. }
  3302. var wa = createWorker("setTimeout(() => postMessage('0'), " + delay + ")")
  3303. wa.onmessage = function (event) {
  3304. // console.log(new Date, event.data);
  3305. wa.terminate();
  3306. if (performer.log()) Message.cmdLog("执行系统命令", validCmd);
  3307. performer.timeSeries(timestamp);
  3308. performer.systemCmdTimestamp = timestamp;
  3309. WG.SendCmd(validCmd);
  3310. const cmdDelay = performer._cmdDelay == null ? __systemCmdDelay : performer._cmdDelay;
  3311. setTimeout(resolve, cmdDelay);
  3312. };
  3313. });
  3314. }, CmdExecutorPriority.low);
  3315. CmdExecuteCenter.addExecutor(executor);
  3316. })();
  3317.  
  3318. (function () {
  3319. const executor = new AtCmdExecutor("force", function (performer, param) {
  3320. return new Promise(resolve => {
  3321. if (performer.log()) Message.cmdLog("强行执行系统命令", param);
  3322. WG.SendCmd(param);
  3323. const cmdDelay = performer._cmdDelay == null ? __systemCmdDelay : performer._cmdDelay;
  3324. setTimeout(resolve, cmdDelay);
  3325. });
  3326. });
  3327. CmdExecuteCenter.addExecutor(executor);
  3328. })();
  3329.  
  3330. (function () {
  3331. const executor = new AtCmdExecutor("perform", function (performer, param) {
  3332. const skills = param.split(",");
  3333. for (const skill of skills) {
  3334. SkillStateMachine.perform(skill, false);
  3335. }
  3336. });
  3337. CmdExecuteCenter.addExecutor(executor);
  3338. })();
  3339.  
  3340. //---------------------------------------------------------------------------
  3341. // Manage Trigger
  3342. //---------------------------------------------------------------------------
  3343.  
  3344. (function () {
  3345. const executor = new AtCmdExecutor("on", function (performer, param) {
  3346. unsafeWindow.TriggerCenter.activate(param);
  3347. });
  3348. CmdExecuteCenter.addExecutor(executor);
  3349. })();
  3350.  
  3351. (function () {
  3352. const executor = new AtCmdExecutor("off", function (performer, param) {
  3353. unsafeWindow.TriggerCenter.deactivate(param);
  3354. });
  3355. CmdExecuteCenter.addExecutor(executor);
  3356. })();
  3357.  
  3358. /***********************************************************************************\
  3359. Dungeons
  3360. \***********************************************************************************/
  3361.  
  3362. const GetDungeonFlow = function (name) {
  3363. for (const d of Dungeons) {
  3364. if (d.name == name) {
  3365. return d.source;
  3366. }
  3367. }
  3368. return null;
  3369. };
  3370.  
  3371. // params: name subtype
  3372. const AutoDungeonName = function (params) {
  3373. const parts = params.split(' ');
  3374. const name = parts[0];
  3375. const type = parts[1];
  3376. let totalName = '';
  3377. switch (type) {
  3378. case '0':
  3379. if (GetDungeonFlow(name)) {
  3380. return name;
  3381. }
  3382. totalName = `${name}(简单)`;
  3383. if (GetDungeonFlow(totalName)) {
  3384. return totalName;
  3385. }
  3386. break;
  3387. case '1':
  3388. totalName = `${name}(困难)`;
  3389. if (GetDungeonFlow(totalName) != null) {
  3390. return totalName;
  3391. };
  3392. break;
  3393. case '2':
  3394. totalName = `${name}(组队)`;
  3395. if (GetDungeonFlow(totalName) != null) {
  3396. return totalName;
  3397. };
  3398. break;
  3399. default:
  3400. break;
  3401. }
  3402. return null;
  3403. };
  3404.  
  3405. (function () {
  3406. const executor = new AtCmdExecutor("fb", function (performer, param) {
  3407. const name = AutoDungeonName(param);
  3408. if (name == null) {
  3409. Message.append('暂不支持次副本哦,欢迎到论坛分享此副本流程。');
  3410. } else {
  3411. const source = GetDungeonSource(name);
  3412. return new Promise(resolve => {
  3413. const p = new Performer(`自动副本-${name}`, source);
  3414. p.log(true);
  3415. p.start(_ => {
  3416. resolve();
  3417. });
  3418. });
  3419. }
  3420. });
  3421. CmdExecuteCenter.addExecutor(executor);
  3422. })();
  3423.  
  3424. function GetDungeonSource(name) {
  3425. let source = GetDungeonFlow(name);
  3426. if (source == null) {
  3427. return null;
  3428. }
  3429. const result = `
  3430. [if] (_DungeonHpThreshold) == null
  3431. ($_DungeonHpThreshold) = 50
  3432. [if] (_DungeonWaitSkillCD) == null
  3433. ($_DungeonWaitSkillCD) = 打开
  3434. [if] (_DungeonBagCleanWay) == null
  3435. ($_DungeonBagCleanWay) = 存仓及售卖
  3436. [if] (_DungeonRecordGains) == null
  3437. ($_DungeonRecordGains) =
  3438. #select ($_DungeonHpThreshold) = 副本内疗伤,当气血低于百分比,100|90|80|70|60|50|40|30|20|10,(_DungeonHpThreshold)
  3439. #select ($_DungeonWaitSkillCD) = Boss战前等待技能冷却,打开|关闭,(_DungeonWaitSkillCD)
  3440. #select ($_DungeonBagCleanWay) = 背包清理方案,不清理|售卖|存仓及售卖,(_DungeonBagCleanWay)
  3441. #select ($_DungeonRecordGains) = 结束后显示收益统计,是|否,(_DungeonRecordGains)
  3442. #input ($_repeat) = 重复次数,1
  3443. #config
  3444. [if] (arg0) != null
  3445. ($_DungeonHpThreshold) = (arg0)
  3446. [if] (arg1) != null
  3447. ($_DungeonWaitSkillCD) = (arg1)
  3448. [if] (arg2) != null
  3449. ($_DungeonBagCleanWay) = (arg2)
  3450. [if] (arg3) != null
  3451. ($_repeat) = (arg3)
  3452. <-stopSSAuto
  3453. stopstate
  3454. <---
  3455. [if] (_DungeonHpThreshold) == null
  3456. ($_DungeonHpThreshold) = 50
  3457. ($hpPer) = (_DungeonHpThreshold)/100
  3458. [if] (:hpPer) < (hpPer)
  3459. @liaoshang
  3460. --->
  3461. [if] (_DungeonRecordGains) ==
  3462. <-recordGains
  3463. ($_i) = 0
  3464. [if] (_repeat) == null
  3465. ($_repeat) = 1
  3466. [while] (_i) < (_repeat)
  3467. @renew
  3468. [if] (_DungeonBagCleanWay) == 售卖
  3469. @cleanBag
  3470. [else if] (_DungeonBagCleanWay) == 存仓及售卖
  3471. @tidyBag
  3472. ${SourceCodeHelper.appendHeader(" ", source)}
  3473. cr;cr over
  3474. ($_i) = (_i) + 1
  3475. [if] (_DungeonBagCleanWay) == 售卖
  3476. @cleanBag
  3477. [else if] (_DungeonBagCleanWay) == 存仓及售卖
  3478. @tidyBag
  3479. $to 住房-练功房;dazuo
  3480. [if] (_DungeonRecordGains) ==
  3481. recordGains->
  3482. stopSSAuto->`
  3483. return result;
  3484. }
  3485.  
  3486. const Dungeons = [
  3487. {
  3488. name: "华山论剑",
  3489. source: `
  3490. @print 👑 感谢 koyodaklafreesunny 对此副本代码提供的帮助。
  3491. jh fb 30 start1;cr huashan/lunjian/leitaixia
  3492. [if] (_DungeonWaitSkillCD) == 打开
  3493. @cd
  3494. go up
  3495. @tip 恭喜你战胜了五绝
  3496. @wait 1000
  3497. jump bi
  3498. get all from {r五绝宝箱}`
  3499. },
  3500. {
  3501. name: "光明顶(组队)",
  3502. source: `
  3503. @print 👑 感谢 dtooboss 分享此副本代码。
  3504. jh fb 26 start3;cr mj/shanmen 2 0
  3505. go north;go west;go northwest
  3506. @kill 冷谦
  3507. go north
  3508. @kill 张中
  3509. go north
  3510. @kill 周颠
  3511. go north;go north
  3512. @kill 颜垣
  3513. go east
  3514. @kill 唐洋
  3515. go north
  3516. @kill 辛然
  3517. go west;go west
  3518. @kill 庄铮
  3519. go south
  3520. @kill 闻苍松
  3521. go east;go south
  3522. @kill 说不得,彭莹玉
  3523. [if] (_DungeonWaitSkillCD) == 打开
  3524. @cd
  3525. go north[2]
  3526. @kill 韦一笑,殷天正
  3527. [if] (_DungeonWaitSkillCD) == 打开
  3528. @cd
  3529. go north[2]
  3530. @kill 张无忌,杨逍,范遥`
  3531. },
  3532. {
  3533. name: "光明顶",
  3534. source: `
  3535. @print 👑 感谢 dtooboss 分享此副本代码。
  3536. jh fb 26 start1;cr mj/shanmen
  3537. go north;go west;go northwest
  3538. @kill 冷谦
  3539. go north
  3540. @kill 张中
  3541. go north
  3542. @kill 周颠
  3543. go north;go north
  3544. @kill 颜垣
  3545. go east
  3546. @kill 唐洋
  3547. go north
  3548. @kill 辛然
  3549. go west;go west
  3550. @kill 庄铮
  3551. go south
  3552. @kill 闻苍松
  3553. go east;go south
  3554. @kill 说不得,彭莹玉
  3555. [if] (_DungeonWaitSkillCD) == 打开
  3556. @cd
  3557. go north[2]
  3558. @kill 韦一笑,殷天正
  3559. [if] (_DungeonWaitSkillCD) == 打开
  3560. @cd
  3561. go north[2]
  3562. @kill 张无忌,杨逍,范遥`
  3563. },
  3564. {
  3565. name: "燕子坞(困难)",
  3566. source: `
  3567. jh fb 23 start2;cr murong/anbian 1 0
  3568. go east;go east
  3569. @kill 包不同
  3570. go east;go south;go east;go south;go south
  3571. @kill 王夫人
  3572. go north;go north;go west;go north
  3573. [if] (_DungeonWaitSkillCD) == 打开
  3574. @cd
  3575. go east;go east;go east
  3576. @kill 慕容复
  3577. go west;go north
  3578. look pai;bai pai[3]
  3579. go north;search
  3580. [if] (_DungeonWaitSkillCD) == 打开
  3581. @cd
  3582. go south
  3583. @kill 慕容博
  3584. go east
  3585. @kill 阿朱`
  3586. },
  3587. {
  3588. name: "燕子坞(简单)",
  3589. source: `
  3590. jh fb 23 start1;cr murong/anbian
  3591. go east;go east
  3592. @kill 包不同
  3593. go east;go south;go east;go south;go south
  3594. @kill 王夫人
  3595. go north;go north;go west;go north
  3596. [if] (_DungeonWaitSkillCD) == 打开
  3597. @cd
  3598. go east;go east;go east
  3599. @kill 慕容复
  3600. go west;go north
  3601. look pai;bai pai[3]
  3602. go north;search
  3603. [if] (_DungeonWaitSkillCD) == 打开
  3604. @cd
  3605. go south
  3606. @kill 慕容博
  3607. go east
  3608. @kill 阿朱`
  3609. },
  3610. {
  3611. name: "燕子坞(偷书)",
  3612. source: `
  3613. @print 👑 感谢 Airson 分享此副本代码。
  3614. jh fb 23 start1;cr murong/anbian
  3615. go east;go east
  3616. @kill 包不同
  3617. go east;go east;go east;go north
  3618. look pai;bai pai[3]
  3619. go north;search`
  3620. },
  3621. {
  3622. name: "移花宫(困难)",
  3623. source: `
  3624. jh fb 22 start2;cr huashan/yihua/shandao 1 0
  3625. go south[5]
  3626. go south[5]
  3627. go south[5]
  3628. @kill 花月奴
  3629. go south;go south
  3630. @kill 移花宫女弟子,移花宫女弟子
  3631. go south
  3632. @kill 移花宫女弟子,移花宫女弟子
  3633. [if] (_DungeonWaitSkillCD) == 打开
  3634. @cd
  3635. go southeast
  3636. @kill 涟星
  3637. [if] {r邀月}? != null
  3638. @kill 邀月
  3639. [if] {邀月的尸体}? == null
  3640. [if] (_DungeonWaitSkillCD) == 打开
  3641. @cd
  3642. go northwest;go southwest
  3643. [if] {r邀月}? != null
  3644. @kill 邀月
  3645. [if] {b火折子g}? != null
  3646. look hua
  3647. @tip 你数了下大概有($number)朵花
  3648. go southeast
  3649. look bed;pushstart bed
  3650. pushleft bed[(number)]
  3651. @await 1000
  3652. pushright bed[8]
  3653. @await 1000
  3654. go down;fire;go west
  3655. @kill 花无缺
  3656. look xia;open xia`
  3657. },
  3658. {
  3659. name: "移花宫(简单)",
  3660. source: `
  3661. jh fb 22 start1;cr huashan/yihua/shandao
  3662. go south[5]
  3663. go south[5]
  3664. go south[5]
  3665. @kill 花月奴
  3666. go south;go south
  3667. @kill 移花宫女弟子,移花宫女弟子
  3668. go south
  3669. @kill 移花宫女弟子,移花宫女弟子
  3670. [if] (_DungeonWaitSkillCD) == 打开
  3671. @cd
  3672. go southeast
  3673. @kill 涟星
  3674. [if] (_DungeonWaitSkillCD) == 打开
  3675. @cd
  3676. go northwest;go southwest
  3677. @kill 邀月
  3678. [if] {b火折子g}? != null
  3679. look hua
  3680. @tip 你数了下大概有($number)朵花
  3681. go southeast
  3682. look bed;pushstart bed
  3683. pushleft bed[(number)]
  3684. @await 1000
  3685. pushright bed[8]
  3686. @await 1000
  3687. go down;fire;go west
  3688. @kill 花无缺
  3689. look xia;open xia`
  3690. },
  3691. {
  3692. name: "冰火岛(困难)",
  3693. source: `
  3694. @print 👑 感谢 WanJiaQi 分享此副本代码。
  3695. jh fb 21 start2;cr mj/bhd/haibian 1 0
  3696. go west
  3697. @kill 炎龙
  3698. go west
  3699. @kill 炎龙
  3700. go west
  3701. @kill 炎龙王
  3702. @liaoshang
  3703. go west;search
  3704. @tip 你找到了
  3705. go east[4];go north
  3706. @kill 白熊
  3707. go north
  3708. @kill 白熊
  3709. @liaoshang
  3710. go north;go west;zuan dong
  3711. [if] (_DungeonWaitSkillCD) == 打开
  3712. @cd
  3713. @kill 张翠山
  3714. @kill 谢逊`
  3715. },
  3716. {
  3717. name: "冰火岛(简单)",
  3718. source: `
  3719. @print 👑 感谢 WanJiaQi 分享此副本代码。
  3720. jh fb 21 start1;cr mj/bhd/haibian 0 0
  3721. go west
  3722. @kill 炎龙
  3723. go west
  3724. @kill 炎龙
  3725. go west
  3726. @kill 炎龙王
  3727. @liaoshang
  3728. //go west;search
  3729. //@tip 你找到了
  3730. go east[3];go north
  3731. @kill 白熊
  3732. go north
  3733. @kill 白熊
  3734. @liaoshang
  3735. go north;go west;zuan dong
  3736. [if] (_DungeonWaitSkillCD) == 打开
  3737. @cd
  3738. @kill 谢逊`
  3739. },
  3740. {
  3741. name: "星宿海",
  3742. source: `
  3743. jh fb 20 start1;cr xingxiu/xxh6
  3744. go northeast
  3745. @kill 星宿派
  3746. go north
  3747. @kill 星宿派
  3748. go northwest
  3749. @kill 星宿派
  3750. go southwest
  3751. @kill 星宿派
  3752. go south
  3753. @kill 星宿派
  3754. [if] (_DungeonWaitSkillCD) == 打开
  3755. @cd
  3756. go north;go northeast;go north
  3757. @kill 丁春秋`
  3758. },
  3759. {
  3760. name: "白驼山",
  3761. source: `
  3762. jh fb 19 start1;cr baituo/damen
  3763. [if] (_DungeonWaitSkillCD) == 打开
  3764. @cd
  3765. go north[4]
  3766. @kill 欧阳锋
  3767. [if] (_DungeonWaitSkillCD) == 打开
  3768. @cd
  3769. go south
  3770. @kill 欧阳克,白衣少女
  3771. go south[2];go west[3]
  3772. @kill 毒蛇
  3773. go north
  3774. @kill 毒蛇
  3775. go north;go north
  3776. @kill 蟒蛇`
  3777. },
  3778. {
  3779. name: "白驼山(组队)",
  3780. source: `
  3781. jh fb 19 start3;cr baituo/damen 2 0
  3782. [if] (_DungeonWaitSkillCD) == 打开
  3783. @cd
  3784. go north[4]
  3785. @kill 欧阳锋
  3786. [if] (_DungeonWaitSkillCD) == 打开
  3787. @cd
  3788. go south
  3789. @kill 欧阳克,白衣少女
  3790. go south[2];go west[3]
  3791. @kill 毒蛇
  3792. go north
  3793. @kill 毒蛇
  3794. go north;go north
  3795. @kill 蟒蛇`
  3796. },
  3797. {
  3798. name: "桃花岛(困难)",
  3799. source: `
  3800. jh fb 18 start2;cr taohua/haitan 1 0
  3801. @until (:path) == taohua/haitan
  3802. @taohualin
  3803. @wait 1000
  3804. go south
  3805. @kill 陆乘风
  3806. go east;go east
  3807. @kill 曲灵风
  3808. [if] (_DungeonWaitSkillCD) == 打开
  3809. @cd
  3810. go east;go east
  3811. @kill 黄药师
  3812. go west;go north
  3813. @kill 黄蓉`
  3814. },
  3815. {
  3816. name: "桃花岛(简单)",
  3817. source: `
  3818. jh fb 18 start1;cr taohua/haitan
  3819. @until (:path) == taohua/haitan
  3820. @taohualin
  3821. @wait 1000
  3822. go south
  3823. @kill 陆乘风
  3824. go east;go east
  3825. @kill 曲灵风
  3826. go east;go north
  3827. ok {黄蓉}
  3828. @zhoubotong
  3829. @kill 周伯通
  3830. look xia;search xia
  3831. go east[2]
  3832. go northwest;go southeast;go southeast;go northwest
  3833. go southwest;go northeast;go northeast;go southwest
  3834. @until (:path) == taohua/haitan
  3835. @taohualin
  3836. @wait 2000
  3837. go south;go east
  3838. go east;go east;go north
  3839. select {黄蓉};give1 {黄蓉}
  3840. @kill 黄蓉`
  3841. },
  3842. {
  3843. name: "云梦沼泽(组队)",
  3844. source: `
  3845. @print 👑 感谢 leiyulin 分享此副本代码。
  3846. jh fb 17 start3;cr cd/yunmeng/senlin 2 0
  3847. $wait 500
  3848. go east
  3849. @kill 巨鳄
  3850. go north
  3851. @kill 巨鳄,巨鳄
  3852. go east
  3853. @kill 巨鳄,巨鳄
  3854. go west;go north
  3855. @kill 巨鳄,巨鳄
  3856. look lu;kan lu;go north
  3857. @kill 火龙
  3858. go north
  3859. @kill 火龙
  3860. go north
  3861. @kill 火龙
  3862. [if] (_DungeonWaitSkillCD) == 打开
  3863. @cd
  3864. go north
  3865. @kill 火龙王`
  3866. },
  3867. {
  3868. name: "云梦沼泽",
  3869. source: `
  3870. @print 👑 感谢 leiyulin 分享此副本代码。
  3871. jh fb 17 start1;cr cd/yunmeng/senlin
  3872. $wait 500
  3873. go east
  3874. @kill 巨鳄
  3875. go north
  3876. @kill 巨鳄,巨鳄
  3877. go east
  3878. @kill 巨鳄,巨鳄
  3879. go west;go north
  3880. @kill 巨鳄,巨鳄
  3881. look lu;kan lu;go north
  3882. @kill 火龙
  3883. go north
  3884. @kill 火龙
  3885. go north
  3886. @kill 火龙
  3887. [if] (_DungeonWaitSkillCD) == 打开
  3888. @cd
  3889. go north
  3890. @kill 火龙王`
  3891. },
  3892. {
  3893. name: "嵩山",
  3894. source: `
  3895. jh fb 16 start1;cr wuyue/songshan/taishi
  3896. [if] (_DungeonWaitSkillCD) == 打开
  3897. @cd
  3898. go north[2]
  3899. @kill 十三太保
  3900. [if] (_DungeonWaitSkillCD) == 打开
  3901. @cd
  3902. go northup;go northeast;go northup[2]
  3903. @kill 十三太保,十三太保
  3904. [if] (_DungeonWaitSkillCD) == 打开
  3905. @cd
  3906. go northup;go north
  3907. @kill 十三太保,十三太保,十三太保
  3908. [if] (_DungeonWaitSkillCD) == 打开
  3909. @cd
  3910. go north
  3911. @kill 十三太保,十三太保,十三太保,十三太保
  3912. [if] (_DungeonWaitSkillCD) == 打开
  3913. @cd
  3914. go north
  3915. @kill 左冷禅`
  3916. },
  3917. {
  3918. name: "泰山",
  3919. source: `
  3920. jh fb 15 start1;cr wuyue/taishan/daizong
  3921. go northup[2]
  3922. @kill 玉磬子
  3923. go northup[2]
  3924. @kill 玉音子
  3925. go northup[2]
  3926. go northup[2]
  3927. @kill 玉玑子`
  3928. },
  3929. {
  3930. name: "衡山",
  3931. source: `
  3932. jh fb 14 start1;cr wuyue/henshan/hengyang
  3933. go west;go north
  3934. @kill 嵩山弟子,嵩山弟子
  3935. go north;go north
  3936. @kill 费彬
  3937. @kill 史登达,丁勉
  3938. @kill 刘正风
  3939. go south[3];go west[2]
  3940. @kill 曲洋,曲非烟
  3941. go east[4];go southeast;go south;go east;go south
  3942. @kill 莫大`
  3943. },
  3944. {
  3945. name: "青城山",
  3946. source: `
  3947. @print 👑 感谢 矮大瓜 分享此副本代码。
  3948. jh fb 13 start1;cr wuyue/qingcheng/shanlu
  3949. go westup
  3950. @kill 青城派弟子,青城派弟子
  3951. go north
  3952. go northup
  3953. go eastup
  3954. @kill 青城派弟子,青城派弟子
  3955. go northup
  3956. @kill 洪人雄
  3957. go north[3]
  3958. @kill 于人豪
  3959. go north
  3960. @kill 侯人英,罗人杰
  3961. go south
  3962. go east
  3963. @kill 余人彦
  3964. [if] (_DungeonWaitSkillCD) == 打开
  3965. @cd
  3966. go north
  3967. @kill 余沧海`
  3968. },
  3969. {
  3970. name: "恒山",
  3971. source: `
  3972. @print 👑 感谢 .min-A 分享此副本代码。
  3973. jh fb 12 start1;cr wuyue/hengshan/daziling
  3974. go northup;go northwest;go northwest;go northup;go northup
  3975. @kill 不戒和尚,仪琳,哑婆婆
  3976. go north;go north
  3977. @kill 定静师太,定闲师太,定仪师太
  3978.  
  3979. ($path)=(:path)
  3980. [while] true
  3981. <---
  3982. @until (path)!=(:path)
  3983. ($path)=(:path)
  3984. ($guy) = {r采花大盗 田伯光}?
  3985. [if] (guy) != null
  3986. @kill 采花大盗 田伯光
  3987. [if] {田伯光的尸体}? != null
  3988. [break]
  3989. --->
  3990. go south
  3991. go west
  3992. go north
  3993. go south
  3994. go east
  3995. go east
  3996. go north
  3997. go south
  3998. go west
  3999. go south
  4000. go southdown
  4001. go east
  4002. go southeast
  4003. go northup
  4004. go southdown
  4005. go southeast
  4006. go southdown
  4007.  
  4008. go northup
  4009. go northwest
  4010. go northup
  4011. go southdown
  4012. go northwest
  4013. go northup
  4014. go northup
  4015. go north
  4016. go north`
  4017. },
  4018. {
  4019. name: "五毒教(组队)",
  4020. source: `
  4021. @print 👑 感谢 矮大瓜 分享此副本代码。
  4022. jh fb 11 start3;cr cd/wudu/damen 2 0
  4023. @kill 五毒教徒,五毒教徒,五毒教徒,五毒教徒
  4024. go east
  4025. @kill 沙千里
  4026. go south
  4027. @kill 藏獒
  4028. go west
  4029. @kill 白髯老者
  4030. go east
  4031. go south
  4032. @kill 毒郎中
  4033. go north
  4034. go north
  4035. [if](_DungeonWaitSkillCD) == 打开
  4036. @cd
  4037. go east
  4038. @kill 潘秀达,岑其斯,齐云敖
  4039. [if](_DungeonWaitSkillCD) == 打开
  4040. @cd
  4041. go east
  4042. @kill 何红药
  4043. [if](_DungeonWaitSkillCD) == 打开
  4044. @cd
  4045. go east
  4046. @kill 何铁手`
  4047. },
  4048. {
  4049. name: "五毒教",
  4050. source: `
  4051. @print 👑 感谢 矮大瓜 分享此副本代码。
  4052. jh fb 11 start1;cr cd/wudu/damen
  4053. @kill 五毒教徒,五毒教徒,五毒教徒,五毒教徒
  4054. go east
  4055. @kill 沙千里
  4056. go south
  4057. @kill 藏獒
  4058. go west
  4059. @kill 白髯老者
  4060. go east
  4061. go south
  4062. @kill 毒郎中
  4063. go north
  4064. go north
  4065. [if](_DungeonWaitSkillCD) == 打开
  4066. @cd
  4067. go east
  4068. @kill 潘秀达,岑其斯,齐云敖
  4069. [if](_DungeonWaitSkillCD) == 打开
  4070. @cd
  4071. go east
  4072. @kill 何红药
  4073. [if](_DungeonWaitSkillCD) == 打开
  4074. @cd
  4075. go east
  4076. @kill 何铁手`
  4077. },
  4078. {
  4079. name: "温府",
  4080. desc: "温府(2k+闪避)",
  4081. source: `
  4082. @print 👑 感谢 JiaQi Wan 分享此副本代码。
  4083. jh fb 10 start1;cr cd/wen/damen
  4084. look tree;climb tree;go north;go northeast
  4085. [while] true
  4086. [if] (:path) != cd/wen/zoulang4
  4087. go northeast
  4088. [else]
  4089. [break]
  4090. go north[2];go northwest;go north
  4091. look zhuang;tiao zhuang
  4092. @kill 温方义,温方山,温方施,温方南
  4093. [if] {r温家老大 温方达%}? != null
  4094. @kill 温方达
  4095. @wait 2000
  4096. [if] (_DungeonWaitSkillCD) == 打开
  4097. @cd
  4098. look zhuang;tiao zhuang
  4099. @until (:path) == cd/wen/xiaoyuan
  4100. @wait 500
  4101. [if] {r夏雪宜}? != null
  4102. @kill 夏雪宜
  4103. go north
  4104. @kill 温仪`
  4105. },
  4106. {
  4107. name: "关外",
  4108. source: `
  4109. @print 👑 感谢 老实人 分享此副本代码。
  4110. jh fb 9 start1;cr bj/guanwai/damen
  4111. go northeast
  4112. @kill 金雕
  4113. go east
  4114. @kill 金雕
  4115. go southeast
  4116. @kill 金雕
  4117. go east
  4118. @kill 平四
  4119. go north
  4120. select {r胡斐}
  4121. ask {r胡斐} about 阎基
  4122. @tip 胡斐说道:阎基是我的杀父仇人($chat)
  4123. [if] (chat) ==
  4124. give {r胡斐} {b阎基的头颅}
  4125. ask {r胡斐} about 胡家刀谱
  4126. [if] (_DungeonWaitSkillCD) == 打开
  4127. @cd
  4128. @kill 胡斐
  4129. go south;go east
  4130. @kill 东北虎
  4131. go eastup
  4132. @kill 东北虎
  4133. go southup
  4134. @kill 东北虎
  4135. [if] (_DungeonWaitSkillCD) == 打开
  4136. @cd
  4137. go eastup
  4138. @kill 黑熊
  4139. go westdown;go northdown;go west[2];go northwest
  4140. go west;go southwest;go west
  4141. give {r船夫} 10000 money
  4142. @until (:room)==关外-船厂(副本区域)
  4143. @wait 500
  4144. @kill 船夫
  4145. go south;go west[5];go north
  4146. @kill 江湖医生 阎基`
  4147. },
  4148. {
  4149. name: "神龙教(组队)",
  4150. source: `
  4151. jh fb 8 start3;cr bj/shenlong/haitan 2 0;go north
  4152. @kill 毒蛇,竹叶青
  4153. look bush;kan bush;go north
  4154. @kill 毒蛇,竹叶青
  4155. go north
  4156. @kill 神龙教弟子,神龙教弟子
  4157. go north
  4158. @kill 神龙教军师 陆高轩
  4159. go south;go east
  4160. @kill 神龙教青龙使 许雪亭
  4161. go east
  4162. @kill 神龙教女弟子,神龙教女弟子
  4163. go north[2]
  4164. @kill 神龙教弟子,神龙教弟子
  4165. [if] (_DungeonWaitSkillCD) == 打开
  4166. @cd
  4167. go north
  4168. @kill 洪安通,张淡月,无根道长`
  4169. },
  4170. {
  4171. name: "神龙教",
  4172. source: `
  4173. jh fb 8 start1;cr bj/shenlong/haitan;go north
  4174. @kill 毒蛇,竹叶青
  4175. look bush;kan bush;go north
  4176. @kill 毒蛇,竹叶青
  4177. go north
  4178. @kill 神龙教弟子,神龙教弟子
  4179. go north
  4180. @kill 神龙教军师 陆高轩
  4181. go south;go east
  4182. @kill 神龙教青龙使 许雪亭
  4183. go east
  4184. @kill 神龙教女弟子,神龙教女弟子
  4185. go north[2]
  4186. @kill 神龙教弟子,神龙教弟子
  4187. [if] (_DungeonWaitSkillCD) == 打开
  4188. @cd
  4189. go north
  4190. @kill 洪安通,张淡月,无根道长`
  4191. },
  4192. {
  4193. name: "天地会",
  4194. source: `
  4195. @print 👑 感谢 jicki 分享此副本代码,感谢 andyfosmma1996 协助完成。
  4196. jh fb 7 start1;cr bj/tdh/hct
  4197. @kill 药铺伙计
  4198. @kill 天地会青木堂护法 徐天川
  4199. go west
  4200. @kill 关夫子 关安基
  4201. knock;knock;knock
  4202. go down
  4203. @until {r尸体}? != null
  4204. go west[5]
  4205. @until {r尸体}? != null
  4206. go north
  4207. @liaoshang
  4208. [if] (_DungeonWaitSkillCD) == 打开
  4209. @cd
  4210. @kill 陈近南
  4211. go east
  4212. get {r一}?
  4213. @wait 500
  4214. get {r一}?
  4215. go west
  4216. go north
  4217. go east
  4218. @tip 拔刀相助,贫尼感激不尽。
  4219. @wait 1000
  4220. select {r神尼};cha {r神尼}
  4221. @wait 1000
  4222. @kill 独臂神尼`
  4223. },
  4224. {
  4225. name: "鳌拜府",
  4226. source: `
  4227. @print 👑 感谢 Jeaepan 分享此副本代码。
  4228. jh fb 6 start1;cr bj/ao/damen
  4229. @kill 官兵,官兵
  4230. go west
  4231. @kill 吴之荣
  4232. go north
  4233. @kill 厨师
  4234. go south;go west
  4235. @kill 家将,家将,女管家
  4236. [if] (_DungeonWaitSkillCD) == 打开
  4237. @cd
  4238. go west
  4239. @kill 满洲第一勇士 鳌拜
  4240. go east;go north
  4241. look shu;open shu
  4242. @tip 发现扉页的($pos)下角被鳌拜写了一个大大的杀字
  4243. look hua
  4244. $wait 500
  4245. [if] (pos) ==
  4246. tleft hua
  4247. [if] (pos) ==
  4248. $wait 500
  4249. tright hua
  4250. go north
  4251. select {r四十二章经g}?
  4252. get {r四十二章经g}?
  4253. go south;go south
  4254. ($open) = 没开
  4255. look men;unlock men
  4256. @tip 你用一把钥匙($open)了牢房门|你不会撬锁
  4257. [if] (open) == 打开
  4258. go south
  4259. select {r庄允城}?
  4260. ask {r庄允城}? about 吴之荣
  4261. @kill 庄允城`
  4262. },
  4263. {
  4264. name: "庄府",
  4265. source: `
  4266. @print 👑 感谢 qwer68588 分享此副本代码。
  4267. jh fb 5 start1;cr bj/zhuang/xiaolu
  4268. go north
  4269. @kill 土匪
  4270. go north
  4271. look men;break men
  4272. go north
  4273. @kill 神龙教弟子,神龙教弟子
  4274. go north
  4275. @kill 神龙教弟子
  4276. @kill 神龙教小头目 章老三
  4277. go west
  4278. @kill 神龙教弟子
  4279. go east;go east
  4280. @kill 神龙教弟子`
  4281. },
  4282. {
  4283. name: "兵营",
  4284. source: `
  4285. @print 👑 感谢 qwer68588 分享此副本代码。
  4286. jh fb 4 start1;cr yz/by/damen
  4287. @kill 官兵,官兵
  4288. $wait 1000
  4289. @liaoshang
  4290. [if] (_DungeonWaitSkillCD) == 打开
  4291. @cd
  4292. go south
  4293. @kill 官兵,官兵,官兵,武将,武将,史青山
  4294. $wait 1000
  4295. look men;open men
  4296. go south;search`
  4297. },
  4298. {
  4299. name: "流氓巷(组队)",
  4300. source: `
  4301. jh fb 2 start3;cr yz/lmw/xiangzi1 2 0
  4302. @kill 小流氓,小流氓
  4303. go east
  4304. @kill 流氓,流氓
  4305. go north
  4306. @kill 流氓头,流氓,流氓
  4307. go south;go east
  4308. @kill 流氓,流氓
  4309. go east
  4310. @kill 流氓头领`
  4311. },
  4312. {
  4313. name: "流氓巷",
  4314. source: `
  4315. jh fb 2 start1;cr yz/lmw/xiangzi1
  4316. @kill 小流氓,小流氓
  4317. go east
  4318. @kill 流氓,流氓
  4319. go north
  4320. @kill 流氓头,流氓,流氓
  4321. go south;go east
  4322. @kill 流氓,流氓
  4323. go east
  4324. @kill 流氓头领`
  4325. },
  4326. {
  4327. name: "丽春院",
  4328. source: `
  4329. jh fb 3 start1;cr yz/lcy/dating
  4330. @kill 韦春芳
  4331. go up
  4332. @kill 龟公
  4333. go west
  4334. @kill 史松
  4335. look tai;tui tai;go enter
  4336. @kill 茅十八`
  4337. },
  4338. {
  4339. name: "财主家(困难)",
  4340. source: `
  4341. jh fb 1 start2;cr yz/cuifu/caizhu 1 0
  4342. @kill 大狼狗,大狼狗
  4343. go north
  4344. @kill 管家,家丁,家丁
  4345. [if] (_DungeonWaitSkillCD) == 打开
  4346. @cd
  4347. go north
  4348. @kill 财主 崔员外
  4349. ($open) = 没开
  4350. look men;open men
  4351. @tip 你不会撬锁|钥匙($open)了秘门
  4352. [if] (open) == 打开
  4353. go east
  4354. ok {丫鬟}
  4355. go west;go south;go south
  4356. ok {丫鬟}?
  4357. go north;go north;go west
  4358. select {财主女儿 崔莺莺};ask {财主女儿 崔莺莺} about 东厢
  4359. [else]
  4360. go west
  4361. @kill 财主女儿 崔莺莺
  4362. [if] (open) == 打开
  4363. go east;go east;look gui;search gui`
  4364. },
  4365. {
  4366. name: "财主家(简单)",
  4367. source: `
  4368. jh fb 1 start1;cr yz/cuifu/caizhu
  4369. @kill 大狼狗,大狼狗
  4370. go north
  4371. @kill 管家,家丁,家丁
  4372. [if] (_DungeonWaitSkillCD) == 打开
  4373. @cd
  4374. go north
  4375. @kill 财主 崔员外
  4376. ($open) = 没开
  4377. look men;open men
  4378. @tip 你不会撬锁|钥匙($open)了秘门
  4379. [if] (open) == 打开
  4380. go east
  4381. ok {丫鬟}
  4382. go west;go south;go south
  4383. ok {丫鬟}?
  4384. go north;go north;go west
  4385. select {财主女儿 崔莺莺};ask {财主女儿 崔莺莺} about 东厢
  4386. [else]
  4387. go west
  4388. @kill 财主女儿 崔莺莺
  4389. [if] (open) == 打开
  4390. go east;go east;look gui;search gui` }
  4391. ];
  4392.  
  4393. /***********************************************************************************\
  4394. Server
  4395. \***********************************************************************************/
  4396.  
  4397. const Server = {
  4398. uploadConfig: function () {
  4399. let all = {};
  4400. let keys = GM_listValues();
  4401. keys.forEach(key => {
  4402. if (key != "roles") {
  4403. all[key] = GM_getValue(key);
  4404. }
  4405. });
  4406. if (unsafeWindow.TriggerConfig != null) {
  4407. const tConfig = unsafeWindow.TriggerConfig.get();
  4408. all["@@@trigger"] = tConfig;
  4409. }
  4410. let value = JSON.stringify(all);
  4411. Server._sync("uploadConfig", { id: Role.id, value: value }, pass => {
  4412. GM_setClipboard(pass);
  4413. alert(`wsmud_Raid 配置上传成功,该浏览器所有角色配置会在服务器保存 24 小时。\n配置获取码:${pass},已复制到系统剪切板。`);
  4414. Message.append(`<hiy>角色配置获取码:${pass}</hiy>`);
  4415. Message.append(`<div class="item-commands"><span cmd = "@js prompt('请手动复制下面的数据','${pass}');" >
  4416. 我无法复制 </span></div>`);
  4417. }, _ => {
  4418. alert("wsmud_Raid 配置上传失败!");
  4419. });
  4420. },
  4421. downloadConfig: function (pass) {
  4422. Server._sync("downloadConfig", { pass: pass }, data => {
  4423. let config = JSON.parse(data);
  4424. for (const key in config) {
  4425. if (key == "@@@trigger") {
  4426. if (unsafeWindow.TriggerConfig != null) {
  4427. unsafeWindow.TriggerConfig.set(config[key]);
  4428. }
  4429. continue;
  4430. }
  4431. if (key != "roles") {
  4432. GM_setValue(key, config[key]);
  4433. }
  4434. }
  4435. alert("wsmud_Raid 配置下载成功!");
  4436. }, _ => {
  4437. alert("wsmud_Raid 配置下载失败!");
  4438. });
  4439. },
  4440. uploadFlows: function () {
  4441. const flows = FlowStore.getAll();
  4442. const map = WorkflowConfig._rootList();
  4443. const data = { map: map, flows: flows };
  4444. const value = JSON.stringify(data);
  4445. Server._sync("uploadFlows", { id: Role.id, value: value }, pass => {
  4446. GM_setClipboard(pass);
  4447. alert(`角色流程上传成功,该角色流程会在服务器保存 24 小时。\n角色流程获取码:${pass},已复制到系统剪切板。`);
  4448. Message.append(`<hiy>角色流程获取码:${pass}</hiy>`);
  4449. Message.append(`<div class="item-commands"><span cmd = "@js prompt('请手动复制下面的数据','${pass}');" >
  4450. 我无法复制 </span></div>`);
  4451. }, _ => {
  4452. alert("角色流程上传失败!");
  4453. });
  4454. },
  4455. downloadFlows: function (pass) {
  4456. Server._sync("downloadFlows", { pass: pass }, value => {
  4457. let data = JSON.parse(value);
  4458. FlowStore.corver(data.flows);
  4459. WorkflowConfig._rootList(data.map);
  4460. // console.log(data);
  4461. alert("拷贝角色流程成功!");
  4462. }, _ => {
  4463. alert("错误的角色流程获取码!");
  4464. });
  4465. },
  4466. uploadTriggers: function () {
  4467. const triggers = unsafeWindow.TriggerCenter.getAllData();
  4468. const value = JSON.stringify(triggers);
  4469. Server._sync("uploadTriggers", { id: Role.id, value: value }, pass => {
  4470. GM_setClipboard(pass);
  4471. alert(`角色触发器上传成功,该角色触发会在服务器保存 24 小时。\n角色触发器获取码:${pass},已复制到系统剪切板。`);
  4472. Message.append(`<hiy>角色触发获取码:${pass}</hiy>`);
  4473. Message.append(`<div class="item-commands"><span cmd = "@js prompt('请手动复制下面的数据','${pass}');" >
  4474. 我无法复制 </span></div>`);
  4475. }, _ => {
  4476. alert("角色触发器上传失败!");
  4477. });
  4478. },
  4479. downloadTriggers: function (pass) {
  4480. Server._sync("downloadTriggers", { pass: pass }, value => {
  4481. let data = JSON.parse(value);
  4482. unsafeWindow.TriggerCenter.corver(data);
  4483. // console.log(data);
  4484. alert("拷贝角色触发器成功!");
  4485. }, _ => {
  4486. alert("错误的角色触发器获取码!");
  4487. });
  4488. },
  4489. getNotice: function () {
  4490. const noticeDataKey = "NoticeDataKey";
  4491. const oldData = GM_getValue(noticeDataKey, { version: "0.0.0", type: "0", value: "欢迎使用 wsmud_Raid" });
  4492. Server._async("notice", { version: oldData.version,id:Role.id }, data => {
  4493. let validData = oldData;
  4494. if (data.version > oldData.version) {
  4495. GM_setValue(noticeDataKey, data);
  4496. validData = data;
  4497. }
  4498. if (validData.type == "0") {
  4499. L.msg(`
  4500. <div>
  4501. <p><hig>Raid:</hig>${validData.value}</p>
  4502. <p style="text-align:center">(v-${GM_info.script.version})</p>
  4503. </div>`);
  4504. } else {
  4505. const HideVersionNoticeKey = "HideVersionNoticeKey";
  4506. if (GM_getValue(HideVersionNoticeKey, null) == validData.version) {
  4507. return;
  4508. }
  4509. layer.open({
  4510. type: 1,
  4511. skin: "layui-layer-rim", //加上边框
  4512. area: ["380px"],
  4513. title: `wsmud_Raid 提示`,
  4514. content: validData.value,
  4515. offset: "auto",
  4516. shift: 2,
  4517. move: false,
  4518. closeBtn: 0,
  4519. btn: ['确认', '不再显示'],
  4520. yes: function (index) {
  4521. layer.close(index);
  4522. },
  4523. btn2: function () {
  4524. GM_setValue(HideVersionNoticeKey, validData.version);
  4525. }
  4526. });
  4527. }
  4528. });
  4529. },
  4530.  
  4531. shareFlowTrigger: function (username, password, type, data) {
  4532.  
  4533. Server._getPhone((phoneNum) => {
  4534. if (phoneNum == '') {
  4535. alert("请先绑定手机号!");
  4536. return;
  4537. }else{
  4538. let value = data;
  4539. value["author"] = username;
  4540. const params = {
  4541. username: username,
  4542. password: password,
  4543. name: data.name,
  4544. phone: phoneNum,
  4545. type: type,
  4546. value: JSON.stringify(value)
  4547. };
  4548. // console.log(params);
  4549. Server._sync("uploadSingle", params, token => {
  4550. GM_setClipboard(token);
  4551. alert(`${type}分享成功,该${type}会在服务器保存 30 \n每次下载会延长保存 始于下载时刻的 30 \n分享码:${token}\n已复制到系统剪切板。`);
  4552. Message.append(`<hiy>${type}分享码:${token}</hiy>`);
  4553. Message.append(`<div class="item-commands"><span cmd = "@js prompt('请手动复制下面的数据','${token}');" >
  4554. 我无法复制 </span></div>`);
  4555. }, error => {
  4556. alert(error);
  4557. });
  4558. }},()=>{
  4559. alert("请先绑定手机号!");
  4560. });
  4561. },
  4562. importFlow: function (token, target) {
  4563. if (token.indexOf("·流程") == -1) {
  4564. alert("错误的流程分享码!");
  4565. return;
  4566. }
  4567. const params = { token: token };
  4568. Server._sync("downloadSingle", params, data => {
  4569. const flow = JSON.parse(data);
  4570. const result = WorkflowConfig.createWorkflow(flow.name, flow.source, target);
  4571. if (result == true) {
  4572. //alert(`导入流程 ${flow.name} 成功!`);
  4573. Message.append(`<hiy>导入流程 ${flow.name} 成功!</hiy>`);
  4574. } else {
  4575. alert(result);
  4576. }
  4577. }, _ => {
  4578. alert("错误的流程分享码!");
  4579. });
  4580. },
  4581. importTrigger: function (token) {
  4582. if (token.indexOf("·触发") == -1) {
  4583. alert("错误的触发器分享码!");
  4584. return;
  4585. }
  4586. const params = { token: token };
  4587. Server._sync("downloadSingle", params, data => {
  4588. const trigger = JSON.parse(data);
  4589. const result = unsafeWindow.TriggerCenter.create(trigger.name, trigger.event, trigger.conditions, trigger.source, trigger.active);
  4590. if (result == true) {
  4591. //alert(`导入触发器 ${trigger.name} 成功!`);
  4592. Message.append(`<hiy>导入触发器 ${trigger.name} 成功!</hiy>`);
  4593. } else {
  4594. alert(result);
  4595. }
  4596. }, _ => {
  4597. alert("错误的触发器分享码!");
  4598. });
  4599. },
  4600.  
  4601. _address: "wsmud.ii74.com/S",
  4602. _async(uri, params, success, fail) {
  4603. this._get(true, uri, params, success, fail);
  4604. },
  4605. _sync(uri, params, success, fail) {
  4606. this._get(false, uri, params, success, fail);
  4607. },
  4608. _get(async, uri, params, success, fail) {
  4609. $.ajax({
  4610. type: "post",
  4611. url: `http://${Server._address}/${uri}`,
  4612. data: params,
  4613. async: async,
  4614. success: function (data) {
  4615. if (data.code == 200) {
  4616. if (success != null) success(data.data);
  4617. } else {
  4618. let error = data.code;
  4619. if (data.data != null) error = data.data;
  4620. if (fail != null) fail(error);
  4621. }
  4622. },
  4623. dataType: "json"
  4624. });
  4625. },
  4626. _getPhone(success,fail){
  4627. $.ajax({
  4628. type: "post",
  4629. url: `/UserAPI/GetPhone`,
  4630. async: true,
  4631. xhrFields: {
  4632. withCredentials: true
  4633. },
  4634. success :function(data){
  4635. if(data){
  4636. //去掉*
  4637. data = data.replace(/\"/g,"");
  4638. if(success != null) success(data);
  4639. }else{
  4640. fail(data);
  4641. }
  4642. }
  4643. });
  4644. }
  4645. };
  4646.  
  4647. /***********************************************************************************\
  4648. UI
  4649. \***********************************************************************************/
  4650.  
  4651. //---------------------------------------------------------------------------
  4652. // 兼容 1.x.x
  4653. //---------------------------------------------------------------------------
  4654.  
  4655. var CmdGroupManager = {
  4656. /**
  4657. * @returns {{ id: number, name: string }[]}
  4658. */
  4659. getAll: function () {
  4660. var result = [];
  4661. GM_listValues().map(function (key) {
  4662. if (key.indexOf(CmdGroupManager._prefix) == 0) {
  4663. var id = CmdGroupManager._id(key);
  4664. var name = CmdGroupManager.getName(id);
  4665. result.push({ id: id, name: name });
  4666. }
  4667. });
  4668. return result;
  4669. },
  4670. getName: function (id) {
  4671. var value = GM_getValue(this._key(id));
  4672. if (value == null) return null;
  4673. var obj = JSON.parse(value);
  4674. return obj.name;
  4675. },
  4676. getCmdsText: function (id) {
  4677. var value = GM_getValue(this._key(id));
  4678. if (value == null) return "";
  4679. var obj = JSON.parse(value);
  4680. var cmdsStr = obj.cmdsStr;
  4681. return cmdsStr;
  4682. },
  4683. /**
  4684. * @returns {string[]}
  4685. */
  4686. getCmds: function (id) {
  4687. var text = this.getCmdsText(id);
  4688. var cmds = text.split(/^\s*|\s*\n+\s*/g);
  4689. var first = cmds[0];
  4690. if (first != null && first.length == 0) {
  4691. cmds.splice(0, 1);
  4692. }
  4693. var last = cmds[cmds.length - 1];
  4694. if (last != null && last.length == 0) {
  4695. cmds.splice(cmds.length - 1, 1);
  4696. }
  4697. return cmds;
  4698. },
  4699. createCmdGroup: function (name, cmdsStr) {
  4700. var id = new Date().getTime();
  4701. return this.updateCmdGroup(id, name, cmdsStr);
  4702. },
  4703. updateCmdGroup: function (id, name, cmdsStr) {
  4704. if (name == null || !/\S+/g.test(name)) {
  4705. alert("命令组想要一个名字...");
  4706. return false;
  4707. }
  4708. if (cmdsStr == null || !/\S+/g.test(cmdsStr)) {
  4709. alert("命令组不想没有任何内容...");
  4710. return false;
  4711. }
  4712. // 存储格式
  4713. var value = {
  4714. name: name,
  4715. cmdsStr: cmdsStr
  4716. };
  4717. GM_setValue(this._key(id), JSON.stringify(value));
  4718. return true;
  4719. },
  4720. removeCmdGroup: function (id) {
  4721. GM_deleteValue(this._key(id));
  4722. },
  4723.  
  4724. _prefix: "@cmdgroup",
  4725. _key: function (id) {
  4726. return this._prefix + id;
  4727. },
  4728. _id: function (key) {
  4729. return parseInt(key.substring(this._prefix.length));
  4730. }
  4731. };
  4732.  
  4733. var WorkflowConfigManager = {
  4734. /**
  4735. * @returns {{ id: number, name: string }[]}
  4736. */
  4737. getAll: function () {
  4738. var result = [];
  4739. GM_listValues().map(function (key) {
  4740. if (WorkflowConfigManager._isMyKey(key)) {
  4741. var id = WorkflowConfigManager._id(key);
  4742. var name = WorkflowConfigManager.getName(id);
  4743. result.push({ id: id, name: name });
  4744. }
  4745. });
  4746. return result;
  4747. },
  4748. getName: function (id) {
  4749. var value = GM_getValue(this._key(id));
  4750. if (value == null) return null;
  4751. var obj = JSON.parse(value);
  4752. return obj.name;
  4753. },
  4754. /**
  4755. * @returns {{ id: number, repeat: number }[]}
  4756. */
  4757. getCmdGroupInfos: function (id) {
  4758. var value = GM_getValue(this._key(id));
  4759. if (value == null) return null;
  4760. var obj = JSON.parse(value);
  4761. return obj.infos;
  4762. },
  4763. /**
  4764. * @returns {Workflow}
  4765. */
  4766. getWorkflow: function (id) {
  4767. var cmdGroupInfos = this.getCmdGroupInfos(id);
  4768. var items = [];
  4769. for (const info of cmdGroupInfos) {
  4770. var name = CmdGroupManager.getName(info.id);
  4771. var cmds = CmdGroupManager.getCmds(info.id);
  4772. var commandWorkflow = new CommandWorkflow(name, cmds, info.repeat);
  4773. items.push(commandWorkflow);
  4774. }
  4775. var workflow = new Workflow(this.getName(id), items, 1);
  4776. return workflow;
  4777. },
  4778. /**
  4779. * @param {string} name
  4780. * @param {{ id: string, repeat: number }[]} cmdGroupInfos
  4781. */
  4782. createWorkflowConfig: function (name, cmdGroupInfos) {
  4783. var id = new Date().getTime();
  4784. return this.updateWorkflowConfig(id, name, cmdGroupInfos);
  4785. },
  4786. /**
  4787. * @param {number} id
  4788. * @param {string} name
  4789. * @param {{ id: string, repeat: number }[]} cmdGroupInfos
  4790. */
  4791. updateWorkflowConfig: function (id, name, cmdGroupInfos) {
  4792. if (name == null || !/\S+/g.test(name)) {
  4793. alert("工作流想要一个名字...");
  4794. return false;
  4795. }
  4796. if (cmdGroupInfos == null || cmdGroupInfos.length <= 0) {
  4797. alert("工作流不想没有任何内容...");
  4798. return false;
  4799. }
  4800. // 存储格式
  4801. var value = {
  4802. name: name,
  4803. infos: cmdGroupInfos
  4804. };
  4805. GM_setValue(this._key(id), JSON.stringify(value));
  4806. return true;
  4807. },
  4808. removeWorkflowConfig: function (id) {
  4809. GM_deleteValue(this._key(id));
  4810. },
  4811.  
  4812. _prefix: "workflow@",
  4813. _isMyKey: function (key) {
  4814. return key.indexOf(this._prefix + Role.id) == 0;
  4815. },
  4816. _key: function (id) {
  4817. return this._prefix + Role.id + id;
  4818. },
  4819. _id: function (key) {
  4820. return parseInt(key.substring((this._prefix + Role.id).length));
  4821. }
  4822. };
  4823.  
  4824. const CodeTranslator = {
  4825. run: function () {
  4826. const oldFinder1 = this._getFinder("原命令组");
  4827. if (oldFinder1) {
  4828. WorkflowConfig.removeFinder(oldFinder1);
  4829. }
  4830. WorkflowConfig.createFinder("原命令组");
  4831. const oldFinder2 = this._getFinder("原工作流程");
  4832. if (oldFinder2) {
  4833. WorkflowConfig.removeFinder(oldFinder2);
  4834. }
  4835. WorkflowConfig.createFinder("原工作流程");
  4836.  
  4837. let allCmdGroup = CmdGroupManager.getAll();
  4838. let allWorkflow = WorkflowConfigManager.getAll();
  4839. const result = this._newSingleName(allCmdGroup, allWorkflow);
  4840. allCmdGroup = result.group;
  4841. allWorkflow = result.flow;
  4842.  
  4843. allCmdGroup.forEach(g => {
  4844. const cmdsText = CmdGroupManager.getCmdsText(g.id);
  4845. const header = " ";
  4846. const cmdsTextHasHeader = this._appendHeader(header, cmdsText);
  4847. const source = `($_i) = 0\n[while] (_i) < (arg0)\n${cmdsTextHasHeader}\n${header}($_i) = (_i) + 1`;
  4848. WorkflowConfig.createWorkflow(g.name, source, "原命令组");
  4849. });
  4850.  
  4851. allWorkflow.forEach(f => {
  4852. const infos = WorkflowConfigManager.getCmdGroupInfos(f.id);
  4853. let source = "";
  4854. infos.forEach(info => {
  4855. let cmdGroupName = null;
  4856. for (const cmdGroup of allCmdGroup) {
  4857. if (cmdGroup.id == info.id) {
  4858. cmdGroupName = cmdGroup.name;
  4859. break;
  4860. }
  4861. }
  4862. source += `@call ${cmdGroupName} ${info.repeat}\n`;
  4863. });
  4864. WorkflowConfig.createWorkflow(f.name, source, "原工作流程");
  4865. });
  4866. },
  4867. _newSingleName: function (cmdGroups, workflows) {
  4868. let allCmdGroup = this._singleName(cmdGroups);
  4869. let allWorkflow = this._singleName(workflows);
  4870. allCmdGroup.forEach(cmdGroup => {
  4871. const name = cmdGroup.name;
  4872. for (const flow of allWorkflow) {
  4873. if (flow.name == name) {
  4874. cmdGroup.name = `芫${name}`;
  4875. break;
  4876. }
  4877. }
  4878. });
  4879. return { group: allCmdGroup, flow: allWorkflow };
  4880. },
  4881. _singleName: function (list) {
  4882. for (const item of list) {
  4883. item.name = item.name.replace(/[^_a-zA-Z0-9\u4e00-\u9fa5]/g, "");
  4884. }
  4885. for (let i = 0; i < list.length; i++) {
  4886. const item = list[i];
  4887. let name = item.name;
  4888. let number = 1;
  4889. for (let j = i + 1; j < list.length; j++) {
  4890. const item1 = list[j];
  4891. if (item1.name == name) {
  4892. item1.name = `${name}_${number}`;
  4893. number += 1;
  4894. }
  4895. }
  4896. }
  4897. return list;
  4898. },
  4899. _getFinder: function (name) {
  4900. let list = WorkflowConfig._rootList();
  4901. const index = WorkflowConfig._findFinder(name, list);
  4902. if (index == null) return null;
  4903. return list[index];
  4904. },
  4905. _appendHeader: function (header, text) {
  4906. let result = `\n${text}`;
  4907. result = result.replace(/(\n)/g, `$1${header}`);
  4908. result = result.replace(/\n\s*\n/g, "\n");
  4909. result = result.replace(/^\s*\n/, "");
  4910. // console.log(result);
  4911. return result;
  4912. }
  4913. };
  4914.  
  4915. //---------------------------------------------------------------------------
  4916. // 2.1.x UI
  4917. //---------------------------------------------------------------------------
  4918.  
  4919. var WorkflowConfig = {
  4920. rootFinderName: "根文件夹",
  4921. rootFinderSortWay: function (value) {
  4922. const key = "__WorkflowRootFinderSortWay";
  4923. if (value == null) {
  4924. return GM_getValue(key, "nameAsc");
  4925. }
  4926. GM_setValue(key, value);
  4927. },
  4928. finderList: function (finderName) {
  4929. let result = [];
  4930. if (finderName == this.rootFinderName) {
  4931. result = this._rootList();
  4932. } else {
  4933. const list = this._rootList();
  4934. const index = this._findFinder(finderName, list);
  4935. if (index != null) {
  4936. const finder = list[index];
  4937. result = finder.flows;
  4938. }
  4939. }
  4940. result.forEach(item => {
  4941. if (item.type == "flow") {
  4942. item.finder = finderName;
  4943. }
  4944. });
  4945. switch (this.rootFinderSortWay()) {
  4946. case "updateDesc":
  4947. result.reverse();
  4948. break;
  4949. case "nameAsc":
  4950. result.sort(function (a, b) {
  4951. return a.name.localeCompare(b.name);
  4952. });
  4953. break;
  4954. case "nameDesc":
  4955. result.sort(function (a, b) {
  4956. return b.name.localeCompare(a.name);
  4957. });
  4958. break;
  4959. case "updateAsc":
  4960. default:
  4961. break;
  4962. }
  4963. return result;
  4964. },
  4965. createFinder: function (name, flows) {
  4966. const result = this._checkName(null, name, true);
  4967. if (result != true) return result;
  4968.  
  4969. let list = this._rootList();
  4970. const finder = { name: name, type: "finder", flows: flows ? flows : [] };
  4971. list.push(finder);
  4972. this._rootList(list);
  4973. return true;
  4974. },
  4975. modifyFinder: function (finder, newName) {
  4976. const result = this._checkName(finder.name, newName, true);
  4977. if (result != true) return result;
  4978.  
  4979. if (finder.name == newName) return true;
  4980.  
  4981. this.removeFinder(finder);
  4982. return this.createFinder(newName, finder.flows);
  4983. },
  4984. removeFinder: function (finder) {
  4985. let list = this._rootList();
  4986. const index = this._findFinder(finder.name, list);
  4987. if (index == null) return;
  4988.  
  4989. list.splice(index, 1);
  4990. this._rootList(list);
  4991.  
  4992. for (const flow of finder.flows) {
  4993. FlowStore.remove(flow.name);
  4994. }
  4995. },
  4996. createWorkflow: function (name, source, finderName) {
  4997. const result = this._checkName(null, name, false);
  4998. if (result != true) return result;
  4999.  
  5000. const flow = { name: name, type: "flow" };
  5001. let list = this._rootList();
  5002. let success = false;
  5003. if (finderName == this.rootFinderName) {
  5004. list.push(flow);
  5005. success = true;
  5006. } else {
  5007. const index = this._findFinder(finderName, list);
  5008. if (index != null) {
  5009. const finder = list[index];
  5010. finder.flows.push(flow);
  5011. success = true;
  5012. }
  5013. }
  5014. if (success) {
  5015. FlowStore.save(name, source);
  5016. this._rootList(list);
  5017. return true;
  5018. } else {
  5019. return `未找到名为"${finderName}"的文件夹。`;
  5020. }
  5021. },
  5022. modifyWorkflow: function (flow, newName, newSource, newFinderName) {
  5023. const result = this._checkName(flow.name, newName, false);
  5024. if (result != true) return result;
  5025.  
  5026. if (flow.name != newName || flow.finder != newFinderName) {
  5027. this.removeWorkflow(flow);
  5028. return this.createWorkflow(newName, newSource, newFinderName);
  5029. } else if (FlowStore.get(flow.name) != newSource) {
  5030. FlowStore.save(flow.name, newSource);
  5031. }
  5032. return true;
  5033. },
  5034. removeWorkflow: function (flow) {
  5035. let list = this._rootList();
  5036. if (flow.finder == this.rootFinderName) {
  5037. for (let i = 0; i < list.length; i++) {
  5038. const item = list[i];
  5039. if (item.type == "flow" && item.name == flow.name) {
  5040. list.splice(i, 1);
  5041. break;
  5042. }
  5043. }
  5044. } else {
  5045. const index = this._findFinder(flow.finder, list);
  5046. if (index != null) {
  5047. const finder = list[index];
  5048. const flows = finder.flows;
  5049. for (let k = 0; k < flows.length; k++) {
  5050. const flow1 = flows[k];
  5051. if (flow1.name == flow.name) {
  5052. flows.splice(k, 1);
  5053. break;
  5054. }
  5055. }
  5056. }
  5057. }
  5058. this._rootList(list);
  5059.  
  5060. FlowStore.remove(flow.name);
  5061. },
  5062. getFinderNames: function () {
  5063. let result = [this.rootFinderName];
  5064. let list = this._rootList();
  5065. list.forEach(item => {
  5066. if (item.type == "finder") {
  5067. result.push(item.name);
  5068. }
  5069. });
  5070. return result;
  5071. },
  5072. _rootList: function (list) {
  5073. const key = `WorkflowConfig_${Role.id}`;
  5074. if (list != null) {
  5075. GM_setValue(key, list);
  5076. }
  5077. return GM_getValue(key, []);
  5078. },
  5079. _checkName: function (oldName, name, isFinder) {
  5080. if (name == oldName) return true;
  5081. const itemName = isFinder ? "文件夹" : "工作流程";
  5082. if (!/\S+/.test(name)) return `${itemName}的名称不能为空。`;
  5083. if (name.indexOf(this.rootFinderName) != -1) return `${itemName}的名称中不能包含"${this.rootFinderName}"。`;
  5084. if (!/^[_a-zA-Z0-9\u4e00-\u9fa5]+$/.test(name)) return `${itemName}的名称只能使用中文、英文和数字字符。`;
  5085. let list = this._rootList();
  5086. const type = isFinder ? "finder" : "flow";
  5087. for (const item of list) {
  5088. if (item.type == type && item.name == name) {
  5089. return `已经存在此名称的${itemName}。`;
  5090. }
  5091. if (item.type == "finder" && !isFinder) {
  5092. for (const flow of item.flows) {
  5093. if (flow.name == name) {
  5094. return `已经存在此名称的${itemName}。`;
  5095. }
  5096. }
  5097. }
  5098. }
  5099. return true;
  5100. },
  5101. _findFinder: function (name, list) {
  5102. for (let i = 0; i < list.length; i++) {
  5103. const item = list[i];
  5104. if (item.type == "finder" && item.name == name) {
  5105. return i;
  5106. }
  5107. }
  5108. return null;
  5109. }
  5110. };
  5111.  
  5112. var ManagedPerformerCenter = {
  5113. start: function (name, source, log, callback) {
  5114. const p = new Performer(name, source);
  5115. p.log(log != null ? log : true);
  5116. const key = `key${this._counter}`;
  5117. this._counter += 1;
  5118. this._performers[key] = p;
  5119. p.start(_ => {
  5120. delete ManagedPerformerCenter._performers[key];
  5121. if (ManagedPerformerCenter.getAll().length == 0) {
  5122. $("#workflows-button").css("border-color", "inherit");
  5123. }
  5124. if (callback) callback();
  5125. });
  5126. $("#workflows-button").css("border-color", "#00FF00");
  5127. },
  5128. getAll: function () {
  5129. return Object.values(this._performers);
  5130. },
  5131. _counter: 0,
  5132. _performers: {}
  5133. };
  5134.  
  5135. const UI = {
  5136. showToolbar: function () {
  5137. if (!UI._toolbarHidden) return;
  5138. UI._toolbarHidden = false;
  5139. var raidToolbar = `
  5140. <style>
  5141. .raid-item{
  5142. display: inline-block;
  5143. border: solid 1px gray;
  5144. color: gray;
  5145. background-color: black;
  5146. text-align: center;
  5147. cursor: pointer;
  5148. border-radius: 0.25em;
  5149. //min-width: 2.5em;
  5150. margin-right: 0em;
  5151. //margin-left: 0.4em;
  5152. position: relative;
  5153. padding-left: 0.3em;
  5154. padding-right: 0.3em;
  5155. line-height: 28px;
  5156. }
  5157. </style>
  5158. <div id="raidToolbar">
  5159. <div class="raidToolbar" style="width:calc(100% - 40px);margin:5px 0 5px 0">
  5160. <span class="raid-item hideRaidToolbar" style="width:10px">\<</span>
  5161. <span class="raid-item forum">🐟 <hiy>咸鱼</hiy></span>
  5162. <span class="raid-item shortcut">🍯 <hiz>捷径</hiz></span>
  5163. <span class="raid-item trigger">🍟 <hio>触发</hio></span>
  5164. <span class="raid-item customFlow" id="workflows-button">🥗 <hig>流程</hig></span>
  5165. <span class="raid-item moreRaid">🍺 <hic>副本</hic></span>
  5166. <!--<span class="raid-item hideRaidToolbar" style="float:right;"><wht>测试</wht></span>-->
  5167. </div>
  5168. </div>`
  5169. $(".WG_log").before(raidToolbar);
  5170. $(".customFlow").on('click', UI.workflows);
  5171. $(".trigger").on('click', UI.trigger);
  5172. $(".forum").on('click', UI.forum);
  5173. $(".shortcut").on('click', UI.shortcut);
  5174. $(".moreRaid").on('click', UI.dungeons);
  5175. $(".hideRaidToolbar").on('click', UI.hideToolbar);
  5176. },
  5177. hideToolbar: function () {
  5178. var toolbar = document.getElementById("raidToolbar");
  5179. if (toolbar != null) {
  5180. toolbar.parentNode.removeChild(toolbar);
  5181. L.msg("单击右键,选择流程菜单可恢复显示。");
  5182. }
  5183. UI._toolbarHidden = true;
  5184. },
  5185.  
  5186. trigger: function () {
  5187. if (unsafeWindow.TriggerUI == null) {
  5188. const content = `
  5189. <span class = "zdy-item install-trigger" style="width:120px"> 前往安装 </span>
  5190. `;
  5191. UI._appendHtml("🍟 <hio>触发器</hio>", content);
  5192. $(".install-trigger").on('click', function () {
  5193. window.open("https://greasyfork.org/zh-CN/scripts/378984", '_blank').location;
  5194. });
  5195. } else {
  5196. unsafeWindow.TriggerUI.triggerHome();
  5197. }
  5198. },
  5199. forum: function () {
  5200. var content = `
  5201. <span class = "zdy-item xianyu-xyjq" style="width:120px"> 🤌 襄阳捐钱 </span>
  5202. <span class = "zdy-item xianyu-ksyb" style="width:120px"> 🦆 快速运镖 </span>
  5203. <span class="zdy-item xianyu-sdyt" style="width:120px"> 🐉 扫荡妖塔</span>
  5204. <span class="zdy-item xianyu-mghyj" style="width:120px"> 🍟 门贡换元晶</span>
  5205. <br><br>
  5206. <span class="zdy-item xianyu-xybm" style="width:120px"> 🐘 襄阳报名</span>
  5207. <span class="zdy-item xianyu-ltbm" style="width:120px"> 🏆 擂台报名</span>
  5208. <span class="zdy-item xianyu-cbt" style="width:120px"> 💎 藏宝图</span>
  5209. <span class = "zdy-item xianyu-setting" style="width:120px"> 🔧 参数设置 </span>
  5210. <br><br>
  5211. <hr style="background-color: gray; height: 1px; width: calc(100% - 4em); border: none;"><br>
  5212. <span class = "zdy-item about-script" style="width:120px"> 🦶 <wht>脚本教程</wht> </span>
  5213. <!--<span class = "zdy-item about-flow" style="width:120px"> <wht>流程讨论</wht> </span>-->
  5214. <!--<span class = "zdy-item about-trigger" style="width:120px"> <wht>触发器讨论</wht> </span>-->
  5215. <span class = "zdy-item about-bug" style="width:120px"> 🐞 <wht>Bug 提交</wht> </span>
  5216. <!--<br><br>-->
  5217. <!--<hr style="background-color: gray; height: 1px; width: calc(100% - 4em); border: none;"><br>-->
  5218. <span class = "zdy-item about-yaofang" style="width:120px"> 💊 药方清单 </span>
  5219. <span class = "zdy-item suqingHome" style="width:120px"> 🍿 <hig>苏</hig><hio>轻</hio><hiy>工</hiy><wht>具</wht><hic>包</hic> </span>`;
  5220. // UI._appendHtml("🍱 <hiy>江湖客栈</hiy>", content);
  5221. UI._appendHtml("🐟 <hiy>一键咸鱼</hiy>", content);
  5222. $(".xianyu-xyjq").on("click", function () {
  5223. DungeonsShortcuts.xianyu_xyjq();
  5224. });
  5225. $(".xianyu-ksyb").on("click", function () {
  5226. DungeonsShortcuts.xianyu_ksyb();
  5227. });
  5228. $(".xianyu-sdyt").on("click", function () {
  5229. DungeonsShortcuts.xianyu_sdyt();
  5230. });
  5231. $(".xianyu-mghyj").on("click", function () {
  5232. DungeonsShortcuts.xianyu_mghyj();
  5233. });
  5234. $(".xianyu-cbt").on("click", function () {
  5235. DungeonsShortcuts.cangbaotu();
  5236. });
  5237. $(".xianyu-xybm").on("click", function () {
  5238. DungeonsShortcuts.xianyu_xybm();
  5239. });
  5240. $(".xianyu-ltbm").on("click", function () {
  5241. DungeonsShortcuts.xianyu_ltbm();
  5242. });
  5243. $(".xianyu-setting").on("click", function () {
  5244. DungeonsShortcuts.xianyu_setting();
  5245. });
  5246. $(".about-script").on('click', function () {
  5247. window.open("https://www.yuque.com/wsmud/doc", '_blank').location;
  5248. });
  5249. $(".about-bug").on('click', function () {
  5250. window.open("https://www.yuque.com/wsmud/doc/gr9gyy", '_blank').location;
  5251. });
  5252. $(".about-yaofang").on('click', function () {
  5253. window.open("https://emeisuqing.github.io/wsmud.old/", '_blank').location;
  5254. });
  5255. $(".suqingHome").on('click', function () {
  5256. window.open("https://emeisuqing.github.io/wsmud/", '_blank').location;
  5257. });
  5258. },
  5259. shortcut: function () {
  5260. var content = `
  5261. <span class = "zdy-item outMaze" style="width:120px"> 走出桃花林 </span>
  5262. <span class = "zdy-item zhoubotong" style="width:120px"> 找到周伯通 </span>
  5263. <span class = "zdy-item cihang" style="width:120px"> 慈航七重门 </span>
  5264. <span class = "zdy-item zhanshendian" style="width:120px"> 战神殿解谜 </span>
  5265. <span class = "zdy-item guzongmen" style="width:120px"> 古宗门寻路 </span>
  5266. <span class = "zdy-item cangbaotu" style="width:120px"> 藏宝图寻宝 </span>
  5267. <span class = "zdy-item uploadConfig" style="width:120px"> 上传本地配置 </span>
  5268. <span class = "zdy-item downloadConfig" style="width:120px"> 下载云端配置 </span>
  5269. <span class = "zdy-item uploadFlows" style="width:120px"> 分享角色流程 </span>
  5270. <span class = "zdy-item downloadFlows" style="width:120px"> 拷贝角色流程 </span>
  5271. <span class = "zdy-item uploadTriggers" style="width:120px"> 分享角色触发 </span>
  5272. <span class = "zdy-item downloadTriggers" style="width:120px"> 拷贝角色触发 </span>
  5273. <span class = "zdy-item importFlow" style="width:120px"> 导入流程 </span>
  5274. <span class = "zdy-item importTrigger" style="width:120px"> 导入触发器 </span>
  5275. <!--<span class = "zdy-item translateCode" style="width:120px"> 流程转换修复 </span>-->
  5276. <span class = "zdy-item raidVersion" style="width:120px"> 🏹 ${GM_info.script.version} </span>`
  5277. UI._appendHtml("🍯 <hiz>捷径</hiz>", content);
  5278.  
  5279. $(".outMaze").on('click', function () {
  5280. WG.SendCmd('stopstate');
  5281. THIsland.outMaze();
  5282. });
  5283. $(".zhoubotong").on('click', function () {
  5284. WG.SendCmd('stopstate');
  5285. THIsland.zhoubotong();
  5286. });
  5287. $(".cihang").on('click', function () {
  5288. WG.SendCmd('stopstate');
  5289. DungeonsShortcuts.cihang();
  5290. });
  5291. $(".zhanshendian").on('click', function () {
  5292. WG.SendCmd('stopstate');
  5293. DungeonsShortcuts.zhanshendian();
  5294. });
  5295. $(".guzongmen").on('click', function () {
  5296. WG.SendCmd('stopstate');
  5297. DungeonsShortcuts.guzongmen();
  5298. });
  5299. $(".cangbaotu").on('click', function () {
  5300. WG.SendCmd('stopstate');
  5301. DungeonsShortcuts.cangbaotu();
  5302. });
  5303. $(".uploadConfig").on('click', _ => {
  5304. Server.uploadConfig();
  5305. });
  5306. $(".downloadConfig").on('click', _ => {
  5307. layer.confirm('下载成功将会完全覆盖该浏览器所有角色配置!', {
  5308. title: "<red>! 警告</red>",
  5309. btn: ['那还是算了', '好的继续'],
  5310. shift: 2,
  5311. }, function (index) {
  5312. layer.close(index);
  5313. }, function () {
  5314. layer.prompt({ title: '输入配置获取码', formType: 0, shift: 2 }, function (pass, index) {
  5315. layer.close(index);
  5316. Server.downloadConfig(pass);
  5317. });
  5318. });
  5319. });
  5320. $(".uploadFlows").on('click', _ => {
  5321. Server.uploadFlows();
  5322. });
  5323. $(".downloadFlows").on('click', _ => {
  5324. layer.confirm('拷贝成功将会完全覆盖原有角色流程!', {
  5325. title: "<red>! 警告</red>",
  5326. btn: ['那还是算了', '好的继续'],
  5327. shift: 2,
  5328. }, function (index) {
  5329. layer.close(index);
  5330. }, function () {
  5331. layer.prompt({ title: '输入角色流程获取码', formType: 0, shift: 2 }, function (pass, index) {
  5332. layer.close(index);
  5333. Server.downloadFlows(pass);
  5334. });
  5335. });
  5336. });
  5337. $(".uploadTriggers").on('click', _ => {
  5338. Server.uploadTriggers();
  5339. });
  5340. $(".downloadTriggers").on('click', _ => {
  5341. layer.confirm('拷贝成功将会完全覆盖原有角色触发器!', {
  5342. title: "<red>! 警告</red>",
  5343. btn: ['那还是算了', '好的继续'],
  5344. shift: 2,
  5345. }, function (index) {
  5346. layer.close(index);
  5347. }, function () {
  5348. layer.prompt({ title: '输入角色触发获取码', formType: 0, shift: 2 }, function (pass, index) {
  5349. layer.close(index);
  5350. Server.downloadTriggers(pass);
  5351. });
  5352. });
  5353. });
  5354.  
  5355. $(".importFlow").on('click', _ => {
  5356. let allFinder = WorkflowConfig.getFinderNames().join("|");
  5357. let source = `
  5358. #input ($token)=分享码,
  5359. #select ($target)=目标文件夹,${allFinder},${WorkflowConfig.rootFinderName}
  5360. #config
  5361. @js Server.importFlow("(token)", "(target)");
  5362. `
  5363. const p = new Performer("导入流程", source);
  5364. p.log(false);
  5365. p.start();
  5366. });
  5367.  
  5368. $(".importTrigger").on('click', _ => {
  5369. let source = `
  5370. #input ($token)=分享码,
  5371. #config
  5372. @js Server.importTrigger("(token)");
  5373. `
  5374. const p = new Performer("导入触发器", source);
  5375. p.log(false);
  5376. p.start();
  5377. });
  5378.  
  5379. $(".translateCode").on('click', _ => {
  5380. layer.prompt({ title: '客栈->流程讨论,阅读使用说明后操作', formType: 0, shift: 2 }, function (pass, index) {
  5381. if (pass == "我确认开始转换") {
  5382. layer.close(index);
  5383. CodeTranslator.run();
  5384. }
  5385. });
  5386. });
  5387.  
  5388. $(".raidVersion").on('click', _ => {
  5389. Server.getNotice();
  5390. });
  5391. },
  5392. dungeons: function () {
  5393. UI._appendHtml("🍺 <hic>自动副本</hic>", "");
  5394. const model = UI._dungeonsContentModel();
  5395. UI._mountableDiv().appendChild(model.$el);
  5396. },
  5397.  
  5398. workflows: function () {
  5399. if (ManagedPerformerCenter.getAll().length == 0) {
  5400. UI.workflowsHome();
  5401. } else {
  5402. UI.runningFlows();
  5403. }
  5404. },
  5405. workflowsHome: function () {
  5406. // const leftText = `
  5407. // <select style='width:80px' id="workflows-sort">
  5408. // <option value="updateAsc">更新时间升序</option>
  5409. // <option value="updateDesc">更新时间降序</option>
  5410. // <option value="nameAsc">名称升序</option>
  5411. // <option value="nameDesc">名称降序</option>
  5412. // </select>
  5413. // `
  5414. const leftText = `<wht>运行中</wht>`;
  5415. const rightText = `
  5416. <select style='width:80px' id="workflows-opts">
  5417. <option value="none">选择操作</option>
  5418. <option value="createFinder">新建文件夹</option>
  5419. <option value="createFlow">新建流程</option>
  5420. </select>`
  5421. // const getMoreFlows = function() {
  5422. // window.open("http://wsmud.bobcn.me:4567/category/2", '_blank').location;
  5423. // };
  5424. UI._appendHtml("🥗 <hig>工作流程</hig>", "", rightText, null, leftText, UI.runningFlows);
  5425. $('#workflows-opts').val("none");
  5426. $("#workflows-opts").change(function () {
  5427. switch ($('#workflows-opts').val()) {
  5428. case "createFinder":
  5429. UI.createFinder();
  5430. break;
  5431. case "createFlow":
  5432. UI.createWorkflow(WorkflowConfig.rootFinderName);
  5433. break;
  5434. case "none":
  5435. default:
  5436. break;
  5437. };
  5438. });
  5439. // $('#workflows-sort').val(WorkflowConfig.rootFinderSortWay());
  5440. // $("#workflows-sort").change(function () {
  5441. // WorkflowConfig.rootFinderSortWay($('#workflows-sort').val());
  5442. // UI.workflows();
  5443. // });
  5444. const model = UI._workflowContentModel(WorkflowConfig.finderList(WorkflowConfig.rootFinderName));
  5445. UI._mountableDiv().appendChild(model.$el);
  5446. },
  5447. runningFlows: function () {
  5448. UI._appendHtml("🥗 <hig>运行中流程</hig>", "", null, null, UI._backTitle, UI.workflowsHome);
  5449. const model = UI._runningFlowsContentModel();
  5450. UI._mountableDiv().appendChild(model.$el);
  5451. },
  5452. createFinder: function () {
  5453. const content = `
  5454. <div style="margin: 0 2em 5px 2em;text-align:center;width:calc(100% - 4em)">
  5455. <label for="create-finder-name"> 名称:</label><input id ="create-finder-name" style='width:120px' type="text" name="create-finder-name" value="">
  5456. </div>`;
  5457. const save = function () {
  5458. const name = $("#create-finder-name").val();
  5459. const result = WorkflowConfig.createFinder(name);
  5460. if (result == true) {
  5461. UI.workflowsHome();
  5462. } else {
  5463. alert(result);
  5464. }
  5465. };
  5466. UI._appendHtml("🥗 <hig>新建文件夹</hig>", content, "<wht>保存</wht>", save, UI._backTitle, UI.workflowsHome);
  5467. },
  5468. modifyFinder: function (finder) {
  5469. const content = `
  5470. <div style="margin: 0 2em 5px 2em;text-align:center;width:calc(100% - 4em)">
  5471. <label for="modify-finder-name"> 名称:</label><input id ="modify-finder-name" style='width:120px' type="text" name="modify-finder-name" value="">
  5472. </div>`;
  5473. const remove = function () {
  5474. var verify = confirm("删除文件夹将删除其中的所有流程,确认删除吗?");
  5475. if (verify) {
  5476. WorkflowConfig.removeFinder(finder);
  5477. UI.workflowsHome();
  5478. }
  5479. };
  5480. const back = function () {
  5481. const name = $("#modify-finder-name").val();
  5482. const result = WorkflowConfig.modifyFinder(finder, name);
  5483. if (result != true) {
  5484. alert(result);
  5485. return;
  5486. }
  5487. UI.workflowsHome();
  5488. };
  5489. UI._appendHtml("🥗 <hig>修改文件夹</hig>", content, "删除", remove, UI._backSaveTitle, back);
  5490. $('#modify-finder-name').val(finder.name);
  5491. },
  5492. openFinder: function (finderName) {
  5493. if (finderName == WorkflowConfig.rootFinderName) {
  5494. UI.workflowsHome();
  5495. return;
  5496. }
  5497. const list = WorkflowConfig.finderList(finderName);
  5498. UI._appendHtml(`<wht>📂 ${finderName}</wht>`, "", null, null, UI._backTitle, UI.workflowsHome);
  5499. const model = UI._workflowContentModel(list);
  5500. UI._mountableDiv().appendChild(model.$el);
  5501. },
  5502. createWorkflow: function (finderName) {
  5503. const content = `
  5504. <div style="margin: 0 2em 5px 2em;text-align:left;width:calc(100% - 4em)">
  5505. <label for="create-flow-name"> 名称:</label><input id ="create-flow-name" style='width:120px' type="text" name="create-flow-name" value="">
  5506. </div>
  5507. <textarea class = "settingbox hide" style = "height:5rem;display:inline-block;font-size:0.8em;width:calc(100% - 4em)" id = "create-flow-source"></textarea>`;
  5508. const save = function () {
  5509. const name = $("#create-flow-name").val();
  5510. const source = $("#create-flow-source").val();
  5511. const result = WorkflowConfig.createWorkflow(name, source, finderName);
  5512. if (result == true) {
  5513. UI.workflowsHome();
  5514. } else {
  5515. alert(result);
  5516. }
  5517. };
  5518. UI._appendHtml("🥗 <hig>新建流程</hig>", content, "<wht>保存</wht>", save, UI._backTitle, UI.workflowsHome);
  5519. },
  5520. modifyWorkflow: function (flow) {
  5521. let options = "";
  5522. WorkflowConfig.getFinderNames().forEach(finderName => {
  5523. options += `<option value="${finderName}">${finderName}</option>`;
  5524. });
  5525. const content = `
  5526. <div style="margin: 0 2em 5px 2em;text-align:left;width:calc(100% - 4em)">
  5527. <label for="modify-flow-name"> 名称:</label><input id ="modify-flow-name" style='width:120px' type="text" name="modify-flow-name" value="">
  5528. <label for="modify-flow-finder">移动至</label><select id="modify-flow-finder">
  5529. ${options}
  5530. </select>
  5531. </div>
  5532. <textarea class = "settingbox hide" style = "height:5rem;display:inline-block;font-size:0.8em;width:calc(100% - 4em)" id = "modify-flow-source"></textarea>
  5533. <span class="raid-item shareFlow">分享此流程</span>`;
  5534. const remove = function () {
  5535. var verify = confirm("确认删除此工作流程吗?");
  5536. if (verify) {
  5537. WorkflowConfig.removeWorkflow(flow);
  5538. UI.workflowsHome();
  5539. }
  5540. };
  5541. const back = function () {
  5542. const name = $("#modify-flow-name").val();
  5543. const source = $("#modify-flow-source").val();
  5544. const finderName = $("#modify-flow-finder").val();
  5545. const result = WorkflowConfig.modifyWorkflow(flow, name, source, finderName);
  5546. if (result != true) {
  5547. alert(result);
  5548. return;
  5549. }
  5550. UI.openFinder(finderName);
  5551. };
  5552. UI._appendHtml("🥗 <hig>修改流程</hig>", content, "删除", remove, UI._backSaveTitle, back);
  5553. $("#modify-flow-name").val(flow.name);
  5554. $("#modify-flow-source").val(FlowStore.get(flow.name));
  5555. $("#modify-flow-finder").val(flow.finder);
  5556. $(".shareFlow").on('click', function () {
  5557. const data = {
  5558. name: $("#modify-flow-name").val(),
  5559. source: $("#modify-flow-source").val()
  5560. };
  5561. UI._share("流程", data);
  5562. });
  5563. },
  5564.  
  5565. _toolbarHidden: true,
  5566. _backTitle: "<wht>< 返回</wht>",
  5567. _backSaveTitle: "<wht>< 保存&返回</wht>",
  5568.  
  5569. _appendHtml(title, content, rightText, rightAction, leftText, leftAction) {
  5570. var realLeftText = leftText == null ? "" : leftText;
  5571. var realRightText = rightText == null ? "" : rightText;
  5572. var html = `
  5573. <div class = "item-commands" style="text-align:center">
  5574. <div style="margin-top:0.5em">
  5575. <div style="width:8em;float:left;text-align:left;padding:0px 0px 0px 2em;height:1.23em" id="wsmud_raid_left">${realLeftText}</div>
  5576. <div style="width:calc(100% - 16em);float:left;height:1.23em">${title}</div>
  5577. <div style="width:8em;float:left;text-align:right;padding:0px 2em 0px 0px;height:1.23em" id="wsmud_raid_right">${realRightText}</div>
  5578. </div>
  5579. <br><br>
  5580. ${content}
  5581. </div>`;
  5582. Message.clean();
  5583. Message.append(html);
  5584. $("#wsmud_raid_left").on('click', function () {
  5585. if (leftAction) leftAction();
  5586. });
  5587. $("#wsmud_raid_right").on('click', function () {
  5588. if (rightAction) rightAction();
  5589. });
  5590. },
  5591. _mountableDiv: function () {
  5592. var wg_log = document.getElementsByClassName("WG_log")[0];
  5593. var pre = wg_log.getElementsByTagName("pre")[0];
  5594. var div = pre.getElementsByTagName("div")[0];
  5595. return div;
  5596. },
  5597. _workflowContentModel: function (items) {
  5598. const contentModel = new Vue({
  5599. el: '#WorkflowsContentModel',
  5600. methods: {
  5601. createSpan: function (createElement, item) {
  5602. let style = {
  5603. width: "120px",
  5604. "background-color": "#12e4a0",
  5605. border: "solid 1px rgb(107, 255, 70)",
  5606. color: "#000dd4"
  5607. };
  5608. if (item.type == "finder") {
  5609. style = {
  5610. width: "120px",
  5611. "background-color": "#0359c3",
  5612. border: "solid 1px rgb(107, 203, 255)",
  5613. color: "white"
  5614. };
  5615. }
  5616. var properties = {
  5617. attrs: { class: "zdy-item" },
  5618. style: style
  5619. };
  5620. var play = function () {
  5621. if (item.type == "finder") {
  5622. UI.openFinder(item.name);
  5623. } else {
  5624. ManagedPerformerCenter.start(item.name, FlowStore.get(item.name));
  5625. }
  5626. };
  5627. var edit = function () {
  5628. if (item.type == "finder") {
  5629. UI.modifyFinder(item);
  5630. } else {
  5631. UI.modifyWorkflow(item);
  5632. }
  5633. };
  5634. const leftProperties = {
  5635. style: {
  5636. width: "30px",
  5637. float: "left",
  5638. "background-color": "#ffffff4f",
  5639. "border-radius": "4px"
  5640. },
  5641. on: { click: edit }
  5642. };
  5643. var leftNode = createElement("div", leftProperties, "⚙");
  5644. var mainProperties = {
  5645. attrs: { class: "breakText" },
  5646. style: { width: "85px", float: "right" },
  5647. on: { click: play }
  5648. };
  5649. const title = item.type == "finder" ? item.name : `▶️${item.name}`;
  5650. const mainNode = createElement("div", mainProperties, title);
  5651. return createElement("span", properties, [leftNode, mainNode]);
  5652. },
  5653. },
  5654. render: function (createElement) {
  5655. var self = this;
  5656. let flows = [];
  5657. let finders = [];
  5658. items.forEach(item => {
  5659. if (item.type == "finder") finders.push(self.createSpan(createElement, item));
  5660. if (item.type == "flow") flows.push(self.createSpan(createElement, item));
  5661. });
  5662. let nodes = [];
  5663. if (flows.length > 0) nodes.push(flows);
  5664. if (finders.length > 0) {
  5665. nodes.push(createElement("hr", { style: { "background-color": "gray", height: "1px", width: "calc(100% - 4em)", border: "none" } }));
  5666. nodes.push(finders);
  5667. }
  5668. const style = createElement("style", ".breakText {word-break:keep-all;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}");
  5669. nodes.push(style);
  5670. return createElement(
  5671. "div",
  5672. { attrs: { class: "item-commands" } },
  5673. nodes
  5674. );
  5675. }
  5676. });
  5677. return contentModel;
  5678. },
  5679. _dungeonsContentModel: function () {
  5680. const contentModel = new Vue({
  5681. el: '#DungeonsContentModel',
  5682. methods: {
  5683. getItems: function () {
  5684. return Dungeons;
  5685. },
  5686. createSpan: function (createElement, item) {
  5687. var properties = {
  5688. attrs: { class: "zdy-item" },
  5689. style: { width: "120px" },
  5690. on: {
  5691. click: function () {
  5692. ManagedPerformerCenter.start(`自动副本-${item.name}`, GetDungeonSource(item.name));
  5693. }
  5694. },
  5695. };
  5696. return createElement('span', properties, item.desc != null ? item.desc : item.name);
  5697. },
  5698. },
  5699. render: function (createElement) {
  5700. var items = this.getItems();
  5701. var theSelf = this;
  5702. var spans = items.map(function (item) {
  5703. return theSelf.createSpan(createElement, item);
  5704. });
  5705. return createElement(
  5706. "div",
  5707. { attrs: { class: "item-commands" } },
  5708. spans
  5709. );
  5710. }
  5711. });
  5712. return contentModel;
  5713. },
  5714. _runningFlowsContentModel: function () {
  5715. const contentModel = new Vue({
  5716. el: '#WorkflowsContentModel',
  5717. methods: {
  5718. createSpan: function (createElement, flow) {
  5719. let style = {
  5720. width: "120px",
  5721. "background-color": "#05b77d",
  5722. border: "solid 1px rgb(107, 255, 70)",
  5723. color: "white"
  5724. };
  5725. var properties = {
  5726. attrs: { class: "zdy-item" },
  5727. style: style
  5728. };
  5729. var stop = function () {
  5730. flow.stop();
  5731. };
  5732. var pause = function () {
  5733. if (flow.pausing()) {
  5734. flow.resume();
  5735. } else {
  5736. flow.pause();
  5737. }
  5738. UI.runningFlows();
  5739. if (flow.pausing()) {
  5740. Message.append(`<hiy>暂停执行,流程: ${flow.name()}...</hiy>`);
  5741. } else {
  5742. Message.append(`<hiy>恢复执行,流程: ${flow.name()}。</hiy>`);
  5743. }
  5744. };
  5745. const leftProperties = {
  5746. style: {
  5747. width: "30px",
  5748. float: "left",
  5749. "background-color": "#ffffff4f",
  5750. "border-radius": "4px"
  5751. },
  5752. on: { click: pause }
  5753. };
  5754. var leftNode = createElement("div", leftProperties, flow.pausing() ? "▶️" : "⏸");
  5755. var mainProperties = {
  5756. attrs: { class: "breakText" },
  5757. style: { width: "85px", float: "right" },
  5758. on: { click: stop }
  5759. };
  5760. const mainNode = createElement("div", mainProperties, `⏹${flow.name()}`);
  5761. return createElement("span", properties, [leftNode, mainNode]);
  5762. },
  5763. },
  5764. render: function (createElement) {
  5765. var items = ManagedPerformerCenter.getAll();
  5766. var theSelf = this;
  5767. var spans = items.map(function (item) {
  5768. return theSelf.createSpan(createElement, item);
  5769. });
  5770. const style = createElement("style", ".breakText {word-break:keep-all;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}");
  5771. spans.push(style);
  5772. return createElement(
  5773. "div",
  5774. { attrs: { class: "item-commands" } },
  5775. spans
  5776. );
  5777. }
  5778. });
  5779. return contentModel;
  5780. },
  5781.  
  5782. _shareData: null,
  5783. /**
  5784. * @param {String} type 流程 触发
  5785. * @param {Object} value
  5786. */
  5787. _share: function (type, value) {
  5788. UI._shareData = value;
  5789. let source = `
  5790. [if] (__FormUserName) == null
  5791. (__FormUserName) = (:name)
  5792. #input ($__FormUserName)=当前角色名,(:name)
  5793. #config
  5794. ($__FormUserName)=(:name)
  5795. ($password)=233
  5796. @js Server.shareFlowTrigger("(__FormUserName)", "(password)", "${type}", UI._shareData);
  5797. `
  5798. const p = new Performer(`分享${type}`, source);
  5799. p.log(false);
  5800. p.start();
  5801. }
  5802. }
  5803.  
  5804. /***********************************************************************************\
  5805. TaoHua Island
  5806. \***********************************************************************************/
  5807.  
  5808. // 暂时保留给桃花岛解密用
  5809. class AncientCmdExecuter {
  5810. constructor(cmds, willStartExecute, didFinishExecute, willPerformCmd, didPerformCmd, interval) {
  5811. this.cmds = cmds;
  5812. this.willStartExecute = willStartExecute;
  5813. this.didFinishExecute = didFinishExecute;
  5814. this.willPerformCmd = willPerformCmd;
  5815. this.didPerformCmd = didPerformCmd;
  5816. this.interval = interval ? interval : 1000;
  5817. }
  5818. execute() {
  5819. if (this.isWorking) return;
  5820. this.isWorking = true;
  5821. if (this.willStartExecute) this.willStartExecute();
  5822. this._performCmd(0);
  5823. }
  5824. _performCmd(index) {
  5825. if (index >= this.cmds.length) { this._finishExecute(); return; }
  5826. if (!Role.isFree()) { this._delayPerformCmd(index); return; }
  5827. var cmd = this.cmds[index];
  5828. if (this.willPerformCmd) {
  5829. var lastCmd = null;
  5830. if (index > 0) lastCmd = this.cmds[index - 1];
  5831. var valid = this.willPerformCmd(lastCmd, cmd);
  5832. if (!valid) { this._delayPerformCmd(index); return; }
  5833. cmd = valid;
  5834. }
  5835. // @开头,虚命令,不真正执行
  5836. if (cmd.indexOf("@") == -1 && cmd.indexOf("kill?") == -1) WG.SendCmd(cmd);
  5837. if (this.didPerformCmd) this.didPerformCmd(cmd);
  5838. // [exit] 保留命令,立即退出执行器
  5839. if (cmd.indexOf("[exit]") != -1) {
  5840. this._finishExecute();
  5841. return;
  5842. }
  5843. this._delayPerformCmd(index + 1);
  5844. }
  5845. _delayPerformCmd(index) {
  5846. var executer = this;
  5847. window.setTimeout(function () {
  5848. executer._performCmd(index);
  5849. }, executer.interval);
  5850. }
  5851. _finishExecute() {
  5852. this.isWorking = false;
  5853. WG.remove_hook(AncientCmdExecuter._hookIndex);
  5854. if (this.didFinishExecute) this.didFinishExecute();
  5855. }
  5856. }
  5857.  
  5858. const THIsland = {
  5859. outMaze: function (callback) {
  5860. if (!Role.atPath("taohua/haitan")) {
  5861. Message.append("只有在 桃花岛的海滩 才能使用此虫洞。");
  5862. return;
  5863. }
  5864.  
  5865. var cmds = [
  5866. "go south",
  5867. "@look 1",
  5868. "@look 5"
  5869. ];
  5870. var willStartExecute = function () {
  5871. THIsland._monitorMaze();
  5872. };
  5873. var didFinishExecute = function () {
  5874. THIsland._cancelMonitorMaze();
  5875. if (callback) callback();
  5876. };
  5877. var willPerformCmd = function (lastCmd, cmd) {
  5878. if (cmd == "@look 1") {
  5879. if (THIsland._goCenterCmd) {
  5880. return THIsland._goCenterCmd;
  5881. } else {
  5882. return null;
  5883. }
  5884. }
  5885. if (cmd == "@look 5") {
  5886. if (THIsland._decodedMaze) {
  5887. return THIsland._outMazeCmd();
  5888. } else {
  5889. return null;
  5890. }
  5891. }
  5892. return cmd;
  5893. };
  5894. var executer = new AncientCmdExecuter(
  5895. cmds,
  5896. willStartExecute,
  5897. didFinishExecute,
  5898. willPerformCmd,
  5899. undefined,
  5900. 1000
  5901. );
  5902. executer.execute();
  5903. },
  5904. zhoubotong: function (callback) {
  5905. if (!Role.atPath("taohua/wofang")) {
  5906. Message.append("只有在 蓉儿的卧室 才能使用此虫洞。");
  5907. return;
  5908. }
  5909.  
  5910. var cmds = [
  5911. "go south;go west;go west;go west;go north;go north;go north",
  5912. "go west;go east;go west;go east;go west",
  5913. "go south",
  5914. "@look 1",
  5915. "@look 5",
  5916. "@go 2",
  5917. "@go 3",
  5918. "@go 4",
  5919. "@go 6",
  5920. "@go 7",
  5921. "@go 8",
  5922. "@end"
  5923. ];
  5924. var willStartExecute = function () {
  5925. THIsland._monitorMaze();
  5926. THIsland._exitsHookIndex = WG.add_hook("exits", function (data) {
  5927. if (THIsland._lastCoord == undefined || THIsland._lastCoord == [0, 0]) return;
  5928. if (Object.keys(data.items).length != 4) return;
  5929. for (var key in data.items) {
  5930. if (data.items[key] != "桃花林") return;
  5931. }
  5932. var normalExistMap = [
  5933. [["north", "northeast", "east"], ["east", "north", "south"], ["east", "south", "southeast"],],
  5934. [["east", "north", "west"], [], ["west", "east", "south"],],
  5935. [["west", "northwest", "north"], ["west", "south", "north"], ["west", "southwest", "south"],]
  5936. ];
  5937. var x = THIsland._lastCoord[0] + 1;
  5938. var y = THIsland._lastCoord[1] + 1;
  5939. var normalExists = normalExistMap[x][y];
  5940. for (var key2 in data.items) {
  5941. if (normalExists.indexOf(key2) != -1) continue;
  5942. THIsland._goCave = "go " + key2;
  5943. return;
  5944. }
  5945. });
  5946. };
  5947. var didFinishExecute = function () {
  5948. THIsland._lastCoord = undefined;
  5949. THIsland._lastGo = undefined;
  5950. THIsland._goCave = undefined;
  5951. THIsland._cancelMonitorMaze();
  5952. WG.remove_hook(THIsland._exitsHookIndex);
  5953. if (callback) callback();
  5954. };
  5955. var willPerformCmd = function (lastCmd, cmd) {
  5956. if (THIsland._goCave) return THIsland._goCave + ";go west;[exit]";
  5957.  
  5958. var number = 0;
  5959. switch (cmd) {
  5960. case "@look 1":
  5961. if (THIsland._goCenterCmd) {
  5962. return THIsland._goCenterCmd;
  5963. } else {
  5964. return null;
  5965. }
  5966. break;
  5967. case "@look 5":
  5968. if (!THIsland._decodedMaze) return null;
  5969. break;
  5970. case "@go 2":
  5971. THIsland._lastCoord = THIsland._mazeCoords[2];
  5972. THIsland._lastGo = THIsland._mazePath(THIsland._lastCoord);
  5973. return THIsland._lastGo;
  5974. case "@go 3": number = 3; break;
  5975. case "@go 4": number = 4; break;
  5976. case "@go 6": number = 6; break;
  5977. case "@go 7": number = 7; break;
  5978. case "@go 8": number = 8; break;
  5979. }
  5980. if (number != 0) {
  5981. var back = THIsland._mazeBackPath(THIsland._lastGo);
  5982. THIsland._lastCoord = THIsland._mazeCoords[number];
  5983. THIsland._lastGo = THIsland._mazePath(THIsland._lastCoord);
  5984. return back + ";" + THIsland._lastGo;
  5985. }
  5986. return cmd;
  5987. };
  5988. var executer = new AncientCmdExecuter(
  5989. cmds,
  5990. willStartExecute,
  5991. didFinishExecute,
  5992. willPerformCmd,
  5993. undefined,
  5994. 1000
  5995. );
  5996. executer.execute();
  5997. },
  5998.  
  5999. _outMazeCmd: function () {
  6000. var cmd = "";
  6001. for (var i = 2; i <= 9; i++) {
  6002. var coord = THIsland._mazeCoords[i];
  6003. var go = THIsland._mazePath(coord);
  6004. if (i == 9) {
  6005. cmd += go + ";" + go;
  6006. } else {
  6007. cmd += go + ";" + THIsland._mazeBackPath(go) + ";";
  6008. }
  6009. }
  6010. cmd += ";go south";
  6011. return cmd;
  6012. },
  6013. _mazePath: function (coord) {
  6014. var pathMap = [
  6015. ["go southwest", "go west", "go northwest"],
  6016. ["go south", "", "go north"],
  6017. ["go southeast", "go east", "go northeast"]
  6018. ];
  6019. var x = coord[0] + 1;
  6020. var y = coord[1] + 1;
  6021. return pathMap[x][y];
  6022. },
  6023. _mazeBackPath: function (path) {
  6024. var backMap = {
  6025. "": "",
  6026. "go southwest": "go northeast",
  6027. "go west": "go east",
  6028. "go northwest": "go southeast",
  6029. "go south": "go north",
  6030. "go north": "go south",
  6031. "go southeast": "go northwest",
  6032. "go east": "go west",
  6033. "go northeast": "go southwest"
  6034. };
  6035. return backMap[path];
  6036. },
  6037. _monitorMaze: function () {
  6038. THIsland._mazeCoords = [
  6039. [2, 2], // unused
  6040. [2, 2],
  6041. [2, 2],
  6042. [2, 2],
  6043. [2, 2],
  6044. [0, 0],
  6045. [2, 2],
  6046. [2, 2],
  6047. [2, 2],
  6048. [2, 2]
  6049. ];
  6050. THIsland._atFirst = false;
  6051. THIsland._goCenterCmd = undefined;
  6052. THIsland._decodedMaze = false;
  6053.  
  6054. var index1 = WG.add_hook(["room", "exits"], function (data) {
  6055. if (THIsland._goCenterCmd != undefined) return;
  6056.  
  6057. if (data.type == "room") {
  6058. if (data.desc == undefined) return;
  6059. var patt = new RegExp("四周栽了大概有一棵桃树");
  6060. var result = patt.exec(data.desc);
  6061. if (result) THIsland._atFirst = true;
  6062. } else if (data.type == "exits") {
  6063. if (data.items == undefined) return;
  6064. if (THIsland._atFirst) {
  6065. if (data.items.north && data.items.south) {
  6066. if (data.items.west) {
  6067. THIsland._mazeCoords[1] = [1, 0];
  6068. THIsland._goCenterCmd = "go west";
  6069. } else {
  6070. THIsland._mazeCoords[1] = [-1, 0];
  6071. THIsland._goCenterCmd = "go east";
  6072. }
  6073. } else if (data.items.west && data.items.east) {
  6074. if (data.items.north) {
  6075. THIsland._mazeCoords[1] = [0, -1];
  6076. THIsland._goCenterCmd = "go north";
  6077. } else {
  6078. THIsland._mazeCoords[1] = [0, 1];
  6079. THIsland._goCenterCmd = "go south";
  6080. }
  6081. }
  6082. }
  6083. }
  6084. });
  6085. var index2 = WG.add_hook("room", function (data) {
  6086. if (THIsland._decodedMaze) return;
  6087.  
  6088. if (data.desc == undefined) return;
  6089. var patt = new RegExp("能看到东南方向大概有.(?=棵桃树)");
  6090. var count = patt.exec(data.desc);
  6091. if (!count) return;
  6092. var text = count.toString();
  6093. switch (text.substring(text.length - 1)) {
  6094. case "二": THIsland._mazeCoords[2] = [1, -1]; break;
  6095. case "四": THIsland._mazeCoords[4] = [1, -1]; break;
  6096. case "六": THIsland._mazeCoords[6] = [1, -1]; break;
  6097. case "八": THIsland._mazeCoords[8] = [1, -1]; break;
  6098. }
  6099.  
  6100. THIsland._mazeCoords[9] = [-THIsland._mazeCoords[1][0], -THIsland._mazeCoords[1][1]];
  6101. while (true) {
  6102. if (THIsland._mazeCoords[2][0] != 2) {
  6103. THIsland._mazeCoords[8] = [-THIsland._mazeCoords[2][0], -THIsland._mazeCoords[2][1]];
  6104. }
  6105. if (THIsland._mazeCoords[8][0] != 2) {
  6106. if (THIsland._mazeCoords[8][0] == THIsland._mazeCoords[1][0]) {
  6107. THIsland._mazeCoords[6] = [THIsland._mazeCoords[8][0], -THIsland._mazeCoords[8][1]];
  6108. } else {
  6109. THIsland._mazeCoords[6] = [-THIsland._mazeCoords[8][0], THIsland._mazeCoords[8][1]];
  6110. }
  6111. }
  6112. if (THIsland._mazeCoords[6][0] != 2) {
  6113. THIsland._mazeCoords[4] = [-THIsland._mazeCoords[6][0], -THIsland._mazeCoords[6][1]];
  6114. }
  6115. if (THIsland._mazeCoords[4][0] != 2) {
  6116. if (THIsland._mazeCoords[4][0] == THIsland._mazeCoords[9][0]) {
  6117. THIsland._mazeCoords[2] = [THIsland._mazeCoords[4][0], -THIsland._mazeCoords[4][1]];
  6118. } else {
  6119. THIsland._mazeCoords[2] = [-THIsland._mazeCoords[4][0], THIsland._mazeCoords[4][1]];
  6120. }
  6121. }
  6122. if (THIsland._mazeCoords[2][0] != 2 &&
  6123. THIsland._mazeCoords[4][0] != 2 &&
  6124. THIsland._mazeCoords[6][0] != 2 &&
  6125. THIsland._mazeCoords[8][0] != 2) {
  6126. break;
  6127. }
  6128. }
  6129. if (THIsland._mazeCoords[8][0] == THIsland._mazeCoords[4][0]) {
  6130. THIsland._mazeCoords[3] = [THIsland._mazeCoords[8][0], 0];
  6131. } else {
  6132. THIsland._mazeCoords[3] = [0, THIsland._mazeCoords[8][1]];
  6133. }
  6134. THIsland._mazeCoords[7] = [-THIsland._mazeCoords[3][0], -THIsland._mazeCoords[3][1]];
  6135.  
  6136. THIsland._decodedMaze = true;
  6137. });
  6138. THIsland._mazeHookIndexes = [index1, index2];
  6139. },
  6140. _cancelMonitorMaze: function () {
  6141. for (var i = THIsland._mazeHookIndexes.length - 1; i >= 0; i--) {
  6142. var index = THIsland._mazeHookIndexes[i];
  6143. WG.remove_hook(index);
  6144. }
  6145. },
  6146. };
  6147.  
  6148. //---------------------------------------------------------------------------
  6149.  
  6150. /* @taohualin 走出桃花林 */
  6151. (function () {
  6152. const executor = new AtCmdExecutor("taohualin", function (performer, param) {
  6153. return new Promise(resolve => {
  6154. THIsland.outMaze(resolve);
  6155. });
  6156. });
  6157. CmdExecuteCenter.addExecutor(executor);
  6158. })();
  6159.  
  6160. /* @zhoubotong 找到周伯通 */
  6161. (function () {
  6162. const executor = new AtCmdExecutor("zhoubotong", function (performer, param) {
  6163. return new Promise(resolve => {
  6164. THIsland.zhoubotong(resolve);
  6165. });
  6166. });
  6167. CmdExecuteCenter.addExecutor(executor);
  6168. })();
  6169.  
  6170. const DungeonsShortcuts = {
  6171. xianyu_xyjq: function() {
  6172. let source = `
  6173. [if] (:room 副本区域,忧愁谷)==true || (:state)==推演 || (:state)==领悟
  6174. @print <ord>当前状态无法进行一键咸鱼,自动停止!</ord>
  6175. [exit]
  6176. @print 🐟 一键咸鱼 => <hic>襄阳捐钱</hic>
  6177. @cmdDelay 500
  6178. stopstate;jh fam 8 start
  6179. @await 500
  6180. [if] (:room)==襄阳城-广场
  6181. juanxian {r郭靖}?;juanxian2 {r郭靖}?
  6182. @print 已完成:襄阳捐钱
  6183. $zdwk
  6184. `
  6185. const p = new Performer("襄阳捐钱", source);
  6186. p.log(false);
  6187. p.start();
  6188. },
  6189. xianyu_xybm: function () {
  6190. let source = `
  6191. [if] (:room 副本区域,忧愁谷)==true || (:state)==推演 || (:state)==领悟
  6192. @print <ord>当前状态无法进行一键咸鱼,自动停止!</ord>
  6193. [exit]
  6194. @print 🐟 一键咸鱼 => <hic>襄阳报名</hic>
  6195. @cmdDelay 500
  6196. stopstate;jh fam 8 start
  6197. @await 500
  6198. [if] (:room)==襄阳城-广场
  6199. baoming {r郭靖}?
  6200. @tip 你可以去($xyBM)附近查看敌情|这位($xyBM)已经报名了。|才可以再次($xyOver)襄阳守城|最近没($xyNone)战事
  6201. [if] (xyBM) != null
  6202. @print 襄阳已报名,请选择守门位置:
  6203. @js Message.append('<div class="item-commands"><span cmd="$wait 350;jh fam 8 start;go north;go north;go north;go north;go north;">⬆️ 守北门</span><span cmd="$wait 350;jh fam 8 start;go south;go south;go south;go south;go south;">⬇️ 守南门</span><span cmd="$wait 350;jh fam 8 start;go east;go east;go east;go east;go east;">➡️ 守东门</span><span cmd="$wait 350;jh fam 8 start;go west;go west;go west;go west;go west;">⬅️ 守西门</span></div>')
  6204. [else if] (xyNone) != null
  6205. @print 襄阳尚未开启。
  6206. $zdwk
  6207. [else if] (xyOver) != null
  6208. @print 襄阳已经完成。
  6209. $zdwk
  6210. [else]
  6211. $zdwk
  6212. `
  6213. const p = new Performer("襄阳报名", source);
  6214. p.log(false);
  6215. p.start();
  6216. },
  6217. xianyu_ksyb: function () {
  6218. let source = `
  6219. [if] (:room 副本区域,忧愁谷)==true || (:state)==推演 || (:state)==领悟
  6220. @print <ord>当前状态无法进行一键咸鱼,自动停止!</ord>
  6221. [exit]
  6222. @print 🐟 一键咸鱼 => <hic>快速运镖</hic>
  6223. @cmdDelay 500
  6224. stopstate
  6225. $to 扬州城-镖局正厅
  6226. ksyb {r林震南}
  6227. @tip 最近暂时($done)委托,你先休息下吧|你需要支付($charges)黄金的雇佣费用|只有总镖头才($can)雇佣镖师|如果你不能把镖银($escort)送到|你不是($escort)运镖吗
  6228. [if] (charges)!=null
  6229. <-recordGains
  6230. task yunbiao {r林震南} qkstart
  6231. @await 11000
  6232. @tidyBag
  6233. recordGains->nopopup
  6234. [else if] (can)!=null
  6235. tm 运镖环数不到200环,无法快速运镖。
  6236. [else if] (escort)!=null
  6237. tm 当前有未完成的运镖任务,无法快速运镖。
  6238. $zdwk
  6239. `
  6240. const p = new Performer("快速运镖", source);
  6241. p.log(false);
  6242. p.start();
  6243. },
  6244. xianyu_sdyt: function () {
  6245. let source = `
  6246. [if] (:room 副本区域,忧愁谷)==true || (:state)==推演 || (:state)==领悟
  6247. @print <ord>当前状态无法进行一键咸鱼,自动停止!</ord>
  6248. [exit]
  6249. @print 🐟 一键咸鱼 => <hic>扫荡妖塔</hic>
  6250. @print <hic>如果想自己静默式调用扫荡妖塔功能,请先设定变量扫荡次数 <hiy>SDYTnum</hiy> 和 单次消耗精力上限 <hiy>SDYTjlsx</hiy> 的值。</hic>
  6251. [if] (SDYTjlsx) == 0 || (SDYTjlsx) == null || (SDYTjlsx) == undefined
  6252. @js ($SDYTjlsx) = prompt("请输入单次消耗精力上限,超过后将自动停止:", "85");
  6253. [if] (SDYTnum) == 0 || (SDYTnum) == null || (SDYTnum) == undefined
  6254. @js ($SDYTnum) = prompt("请输入本轮扫荡次数,注意:单次消耗精力达到上限后将自动停止。","5")
  6255. ($sdyt_num) = (SDYTnum)
  6256. //($SDYTnum) = null
  6257. [if] (sdyt_num) == 0 || (sdyt_num) == null || (sdyt_num) == undefined
  6258. @print <ord>扫荡次数为0,取消扫荡。</ord>
  6259. [exit]
  6260. @print <hiy>计划扫荡(sdyt_num)次妖塔。</hiy>
  6261. stopstate
  6262. [if] (:room) != 古大陆-墓园
  6263. $goyt
  6264. @await 1500
  6265. [if] (:room) != 古大陆-墓园
  6266. @print <ord>无法前往古大陆,请重试或确定当前角色是否已解锁古大陆。</ord>
  6267. $zdwk
  6268. [exit]
  6269. [if] {b扫荡符#}? < (sdyt_num) || {b扫荡符}? == null
  6270. shop 0 (sdyt_num)
  6271. ($num) = 0
  6272. @cmdDelay 500
  6273. ($ytWeek) = null
  6274. [while] (num) < (sdyt_num)
  6275. ss muyuan
  6276. @tip 你即将消耗一个扫荡符,($jl_yt)精力快速完成一次弑妖塔|你即将消耗($jl_yt)精力快速完成一次弑妖塔|你尚未($ytJS)弑妖塔|你已达到($ytWeek)上限
  6277. [if] (ytJS) != null
  6278. @print <hiy>妖塔未解锁,无法扫荡。</hiy>
  6279. [break]
  6280. [if] (ytWeek) != null
  6281. @print <hiy>妖塔扫荡已达到本周上限。</hiy>
  6282. [break]
  6283. [if] (jl_yt) > (SDYTjlsx) && (jl_yt) != null
  6284. @print <ord>单次扫荡精力超过(SDYTjlsx),自动停止。</ord>
  6285. [break]
  6286. [else]
  6287. saodang muyuan
  6288. @tip 你消耗一个扫荡符|精力快速完成弑妖塔|你的($lack)不够|你已达到($ytWeek)上限
  6289. [if] (ytWeek) != null
  6290. @print <hiy>妖塔扫荡已达到本周上限。</hiy>
  6291. [break]
  6292. [if] (lack) != null
  6293. @print <ord>(lack)不足,自动停止扫荡妖塔。</ord>
  6294. [break]
  6295. ($num) = (num) + 1
  6296. @await 1000
  6297. $zdwk
  6298. `
  6299. const p = new Performer("扫荡妖塔", source);
  6300. p.log(false);
  6301. p.start();
  6302. },
  6303. xianyu_mghyj: function () {
  6304. let source = `
  6305. [if] (:room 副本区域,忧愁谷)==true || (:state)==推演 || (:state)==领悟
  6306. @print <ord>当前状态无法进行一键咸鱼,自动停止!</ord>
  6307. [exit]
  6308. @print 🐟 一键咸鱼 => <hic>门贡换元晶</hic>
  6309. @cmdDelay 500
  6310. stopstate
  6311. ($hqName) = 门派后勤管理员
  6312. [if] (:family) == 武当派
  6313. ($hqMap) = 武当派-石阶
  6314. [else if] (:family) == 少林派
  6315. ($hqMap) = 少林派-山门殿
  6316. [else if] (:family) == 华山派
  6317. ($hqMap) = 华山派-练武场
  6318. [else if] (:family) == 峨眉派
  6319. ($hqMap) = 峨眉派-走廊
  6320. [else if] (:family) == 逍遥派
  6321. ($hqMap) = 逍遥派-林间小道
  6322. [else if] (:family) == 丐帮
  6323. ($hqMap) = 丐帮-暗道
  6324. [else if] (:family) == 杀手楼
  6325. ($hqMap) = 杀手楼-休息室
  6326. [else]
  6327. ($hqMap) = 扬州城-扬州武馆
  6328. ($hqName) = 武馆后勤
  6329. [while] (:room) != (hqMap)
  6330. $to (hqMap)
  6331. [if] (:family) == 丐帮
  6332. @await 300
  6333. go east
  6334. @await 500
  6335. [if] {r(hqName)}? == null
  6336. @print 后勤失踪,请稍后再试。
  6337. [else]
  6338. ask1 {r(hqName)}?
  6339. @dialog
  6340. buy 1 {d元晶o}? from {r(hqName)}?
  6341. @tip 你从门派后勤管理员购买了|这里没有($mgYJ)多的|你没有那么多的($mgGJ)功绩
  6342. [if] (mgGJ) != null
  6343. @print 门贡不足,无法购买。
  6344. [else if] (mgYJ) != null
  6345. @print 元晶已售空,无法购买。
  6346. [else]
  6347. @print 已购买一个<hio>元晶</hio>。
  6348. $zdwk
  6349. `
  6350. const p = new Performer("门贡换元晶", source);
  6351. p.log(false);
  6352. p.start();
  6353. },
  6354. xianyu_ltbm: function () {
  6355. let source = `
  6356. [if] (:room 副本区域,忧愁谷)==true || (:state)==推演 || (:state)==领悟
  6357. @print <ord>当前状态无法进行一键咸鱼,自动停止!</ord>
  6358. [exit]
  6359. @print 🐟 一键咸鱼 => <hic>擂台报名</hic>
  6360. @cmdDelay 500
  6361. stopstate;$to 扬州城-擂台
  6362. @await 500
  6363. select {r擂台比武报名}?
  6364. askbiwu {r擂台比武报名}?
  6365. @tip 你使用当前装备和技能($ltBM)参加比武|你已经报名参加比武,($ltGX)更新你的技能和装备|你已报名或更新状态,请勿连续报名。
  6366. [if] (ltGX) != null
  6367. biwu record ok
  6368. $zdwk
  6369. `
  6370. const p = new Performer("擂台报名", source);
  6371. p.log(false);
  6372. p.start();
  6373. },
  6374. xianyu_setting: function () {
  6375. let source = `
  6376. [(SDYTjlsx)==null]($SDYTjlsx)=85
  6377. [(SDYTnum)==null]($SDYTnum)=5
  6378. @print 🐟 一键咸鱼 => <hic>参数设置</hic>
  6379. #input ($SDYTjlsx)=<hiz>一键设置各种常用流程(陆续更新添加)参数</hiz><br/>&nbsp*&nbsp<ord>🐉 扫荡妖塔</ord> 参数<br/>&nbsp*&nbsp妖塔单次消耗精力上限,(SDYTjlsx)
  6380. #input ($SDYTnum)=每轮妖塔扫荡次数,(SDYTnum)
  6381. #config
  6382. @print 已完成参数设置
  6383. `
  6384. const p = new Performer("参数设置", source);
  6385. p.log(false);
  6386. p.start();
  6387. },
  6388. cangbaotu: function () {
  6389. let source = `
  6390. [if] (:room 副本区域,忧愁谷)==true || (:state)==推演 || (:state)==领悟
  6391. @print <ord>当前状态无法进行一键咸鱼,自动停止!</ord>
  6392. [exit]
  6393. @print 🐟 一键咸鱼 => <hic>藏宝图</hic>
  6394. [if] {b藏宝图}? == null
  6395. tm 背包中无藏宝图,取消本次寻宝。
  6396. [exit]
  6397. @cmdDelay 500
  6398. stopstate
  6399. @toolbar jh
  6400. @toolbar pack
  6401. ($money1) = (:money)
  6402. ($ebony1) = {b玄晶#}?
  6403. ($number)=1
  6404. ($cbt_n) = 0
  6405. @stopSSAuto
  6406. <-recordGains
  6407. [while] {b藏宝图}? != null
  6408. <---
  6409. ($pos)=null
  6410. use {b藏宝图}?
  6411. @tip 发现上面的图案所绘的方位似乎($pos)。|你找到了
  6412. [if] (pos) == 就在你这里
  6413. use {b藏宝图}?
  6414. ($cbt_n) = (cbt_n) + 1
  6415. [continue]
  6416. [else if] (pos) == null
  6417. [continue]
  6418. --->
  6419. jh fam (number) start
  6420. [if] (pos) != 离你所在的位置挺远的
  6421. // 武当
  6422. [if] (number)=1
  6423. [if] (pos) == 在你的北方
  6424. go north
  6425. go south;go west;go northup;go north;go east
  6426. [else if] (pos) == 在你的西方
  6427. go west
  6428. go west
  6429. [else]
  6430. go west;go northup
  6431. go north
  6432. go west
  6433. go northup
  6434. go northup
  6435. go northup
  6436. [while] (pos) == 在你的北方
  6437. go north
  6438. // 少林
  6439. [else if] (number)=2
  6440. [if] (pos) == 在你的北方
  6441. go north
  6442. go north
  6443. go northup
  6444. go southdown;go northwest;go northeast
  6445. [while] (pos) == 在你的北方
  6446. go north
  6447. [else if] (pos) == 在你的西北方向
  6448. go north;go west
  6449. go east;go north;go northwest
  6450. go northeast;go north;go west
  6451. go east;go north;go west
  6452. go east;go north;go west
  6453. [else]
  6454. go north;go east
  6455. go west;go north;go northeast
  6456. go northwest;go north;go east
  6457. go west;go north;go east
  6458. // 华山
  6459. [else if] (number)=3
  6460. [if] (pos) == 在你的北方
  6461. go westup;go north;go east
  6462. go west;go north;go east
  6463. [else if] (pos) == 在你的西北方向
  6464. go westup;go north
  6465. go north
  6466. go north
  6467. [else if] (pos) == 在你的西方
  6468. go westup
  6469. go west
  6470. [else if] (pos) == 在你东方
  6471. go eastup
  6472. [else if] (pos) == 在你的东南方向
  6473. go eastup;go southup
  6474. jumpdown
  6475. go southup
  6476. go south
  6477. go east
  6478. [else]
  6479. go westup
  6480. go south
  6481. go southup
  6482. go southup
  6483. break bi;go enter
  6484. go westup
  6485. go westup
  6486. jumpup
  6487. // 峨眉
  6488. [else if] (number)=4
  6489. go west;go south;go west
  6490. [if] (pos) == 在你东方
  6491. go east
  6492. go east
  6493. go east
  6494. [else if] (pos) == 在你的西方
  6495. go west
  6496. [else if] (pos) == 在你的南方
  6497. go south
  6498. go south
  6499. [else if] (pos) == 在你的北方
  6500. go north
  6501. go north
  6502. [else if] (pos) == 在你的东北方向
  6503. go east;go north
  6504. go east
  6505. go northup
  6506. go east
  6507. [else]
  6508. go east;go south
  6509. go north;go east;go south
  6510. // 逍遥
  6511. [else if] (number)=5
  6512. [if] (pos) == 在你东方
  6513. go east
  6514. [else if] (pos) == 在你的西方
  6515. go west
  6516. [else if] (pos) == 在你的南方
  6517. go south
  6518. go south
  6519. [else if] (pos) == 在你的北方
  6520. go north
  6521. go north
  6522. [else if] (pos) == 在你的东北方向
  6523. go east;go north
  6524. [else if] (pos) == 在你的东南方向
  6525. go east;go south
  6526. go south
  6527. [else if] (pos) == 在你的西南方向
  6528. go west;go south
  6529. [else]
  6530. go down
  6531. go down
  6532. // 丐帮
  6533. [else]
  6534. [if] (pos) == 在你东方
  6535. go down;go east;go east;go east;go up
  6536. go down;go east;go east;go up
  6537. [else if] (pos) == 在你的南方
  6538. go down
  6539. [else]
  6540. go down;go east
  6541. go east
  6542. go east
  6543. go east
  6544. go east
  6545. [else if] (number)<6
  6546. ($number) = (number) + 1
  6547. [else]
  6548. ($number)=1
  6549. //结束后自动挖矿或者闭关
  6550. @await 1000
  6551. @tidyBag
  6552. @wait 2000
  6553. $zdwk
  6554. recordGains->nopopup
  6555. @recoverSSAuto
  6556. @toolbar pack
  6557. ($money2) = (:money)
  6558. @js ($income_m) = parseInt(((money2) - (money1))/10000)
  6559. ($ebony2) = {b玄晶#}?
  6560. [if] (ebony1) != null
  6561. ($income_e) = (ebony2) - (ebony1)
  6562. [else]
  6563. ($income_e) = (ebony2)
  6564. tm 挖宝 (cbt_n) 次,收益 (income_e)个玄晶,(income_m) 两黄金
  6565. @print 挖宝 (cbt_n) 次,收益 <hiy>(income_e)</hiy> 个玄晶,<hiy>(income_m)</hiy> 两黄金
  6566. `
  6567. const p = new Performer("藏宝图寻宝", source);
  6568. p.log(false);
  6569. p.start();
  6570. },
  6571. cihang: function () {
  6572. let source = `
  6573. [if] (:room 慈航静斋) == false
  6574. @print <hiy>请先进入慈航副本再运行。</hiy>
  6575. [exit]
  6576. [else]
  6577. [if] (:room) != 慈航静斋-山门(副本区域) && (:room) != 慈航静斋-帝踏峰(副本区域)
  6578. @print <hiy>请在山门或帝踏峰运行。</hiy>
  6579. [exit]
  6580. ($go) = 'east','west','south','north'
  6581. ($qiku) = '老','病','死','爱别离','怨憎会','求不得'
  6582. ($num1) = 0
  6583. [if] (:room) == 慈航静斋-山门(副本区域)
  6584. go south
  6585. [else if] (:room) == 慈航静斋-帝踏峰(副本区域)
  6586. go south[2]
  6587. @print <hiy>开始自动寻路,寻路期间请勿点击地图……</hiy>
  6588. @cmdDelay 500
  6589. [while] (num1) < 6
  6590. @js ($ku) = [(qiku)][(num1)]
  6591. ($num2) = 0
  6592. [while] true
  6593. [if] (map) != null && (retry) == true
  6594. (map)
  6595. @await 500
  6596. @js ($fx) = [(go)][(num2)]
  6597. [if] (fx) == null
  6598. @print <hiy>自动寻路失败,请回到山门重新运行!</hiy>
  6599. [exit]
  6600. go (fx)
  6601. [if] (:room) == 慈航静斋-七重门(副本区域)
  6602. @js ($ku_now) = $(".room_desc").text().match(",是名([^%]+)苦。")[1]
  6603. [if] (ku) != (ku_now)
  6604. [while] true
  6605. go west
  6606. [if] (:room) == 慈航静斋-七重门(副本区域)
  6607. @js ($dir_gc) = $("text:contains('广场')").attr("dir")
  6608. [if] (dir_gc) == south
  6609. go south
  6610. @await 200
  6611. [if] (:room) == 慈航静斋-山门(副本区域)
  6612. [break]
  6613. [else if] (:room) == 慈航静斋-广场(副本区域)
  6614. @print <hiy>已走出七重门!</hiy>
  6615. [exit]
  6616. go south
  6617. ($num2) = (num2) + 1
  6618. ($retry) = true
  6619. [else]
  6620. [if] (map) == null
  6621. ($map) = go (fx)
  6622. [else]
  6623. ($map) = (map);go (fx)
  6624. ($retry) = false
  6625. [break]
  6626. [else if] (:room) == 慈航静斋-广场(副本区域)
  6627. @print <hiy>已走出七重门!</hiy>
  6628. [exit]
  6629. ($num1) = (num1) + 1
  6630. go south
  6631. [if] (:room) == 慈航静斋-广场(副本区域)
  6632. @print <hiy>已走出七重门!</hiy>
  6633. `
  6634. const p = new Performer("慈航七重门", source);
  6635. p.log(false);
  6636. p.start();
  6637. },
  6638. zhanshendian: function () {
  6639. let source = `
  6640. [if] (:room 战神殿) == false
  6641. @print <hiy>请先进入战神殿副本再运行。</hiy>
  6642. [exit]
  6643. [if] (:room) != 战神殿-左雁翼(副本区域)
  6644. @print <hiy>请先手动向左走到左雁翼。</hiy>
  6645. @until (:room) == 战神殿-左雁翼(副本区域)
  6646. look shi
  6647. @tip 和外面星空星宿位置一一对应,($star_0),($star_1),($star_2),($star_3),($star_4),($star_5),($star_6),($star_7)这些星宿依次闪烁
  6648. ($stars) = "(star_0)","(star_1)","(star_2)","(star_3)","(star_4)","(star_5)","(star_6)","(star_7)"
  6649. ($dirs) = {"star":"角亢室","dir":1,"eswn":"东北↗︎","go":"northeast"},{"star":"氏房心","dir":0,"eswn":"东→","go":"east"},{"star":"尾箕轸","dir":2,"eswn":"东南↘︎","go":"southeast"},{"star":"井鬼参","dir":4,"eswn":"西南↙︎","go":"southwest"},{"star":"柳星张翼","dir":3,"eswn":"南↓","go":"south"},{"star":"奎娄斗牛","dir":6,"eswn":"西北↖︎","go":"northwest"},{"star":"胃昴毕觜","dir":5,"eswn":"西←","go":"west"},{"star":"女虚危壁","dir":7,"eswn":"北↑","go":"north"}
  6650. @cmdDelay 100
  6651. ($num_1) = 0
  6652. [while] (num_1) < 8
  6653. @js ($star) = [(stars)][(num_1)]
  6654. ($num_2) = 0
  6655. [while] (num_2) < 28
  6656. ($dir) = null
  6657. @js ($dir) = var d=[(dirs)];var s=d[(num_2)]["star"].indexOf("(star)");if(s>=0){d[(num_2)]["dir"]}
  6658. [if] (dir) != null
  6659. [break]
  6660. ($num_2) = (num_2) + 1
  6661. push (dir)
  6662. ($num_1) = (num_1) + 1
  6663. look shi
  6664. @tip 殿顶的星图依旧,却仅剩一颗($last)宿星孤零零的闪烁着
  6665. ($num_3) = 0
  6666. [while] (num_3) < 28
  6667. ($dir_l) = null
  6668. ($go_l) = null
  6669. @js ($dir_l) = var d=[(dirs)];var s=d[(num_3)]["star"].indexOf("(last)");if(s>=0){d[(num_3)]["eswn"]}
  6670. @js ($go_l) = var d=[(dirs)];var s=d[(num_3)]["star"].indexOf("(last)");if(s>=0){d[(num_3)]["go"]}
  6671. [if] (dir_l) != null && (go_l) != null
  6672. [break]
  6673. ($num_3) = (num_3) + 1
  6674. @print <hiy>(last)宿,最后一个方位是【(dir_l)】</hiy>
  6675. tm (last)宿,最后一个方位是【(dir_l)】60秒倒计时已开始,请抓紧开打。
  6676. @print <ord>打完右雁翼最后一波守卫后会自动进秘道【(go_l)】</ord>
  6677. @until (:room) == 战神殿-右雁翼(副本区域) || (:room 副本区域) == false
  6678. @until (:combating) == true || (:room 副本区域) == false
  6679. @until (:combating) == false || (:room 副本区域) == false
  6680. [if] (:room 副本区域) == false
  6681. [exit]
  6682. [while] (:room) == 战神殿-右雁翼(副本区域) && (:living) == true
  6683. go (go_l);$wait 100
  6684. `
  6685. const p = new Performer("战神殿解谜", source);
  6686. p.log(false);
  6687. p.start();
  6688. },
  6689. guzongmen: function () {
  6690. let source = `
  6691. @print <hiy>如果寻路一直失败,请检查设置中<ord>【切换房间时不清空上房间信息】</ord>是否开启。</hiy>
  6692. [if] (:room 副本区域,忧愁谷) == true
  6693. @print <ord>当前处于副本中,无法寻路!</ord>
  6694. [exit]
  6695. @cmdDelay 500
  6696. stopstate
  6697. jh fam 9 start
  6698. go enter
  6699. go up
  6700. @tip 打败我,你就($pass)上去|聚魂成功|踏过长生门|你已堪破生死|古老的大陆寻找真相|你连($pass)都没聚合|你想($pass)为神吗
  6701. [if] (pass) != null
  6702. @print <ord>不符合前往古大陆要求,流程终止。</ord>
  6703. [exit]
  6704. ggdl {r疯癫的老头}
  6705. go north[3]
  6706. go north[3]
  6707. look shi
  6708. tiao1 shi;tiao1 shi;tiao2 shi
  6709. @until (:room) == 古大陆-断山
  6710. @js ($ylfx) = $(".room_desc").text().match(/[东南西北],/g)
  6711. @js ($ylfx) = var f="(ylfx)";f.replace(/,/g,"")
  6712. @js ($ylfx) = var f="(ylfx)";f.replace(/东/g,"west")
  6713. @js ($ylfx) = var f="(ylfx)";f.replace(/西/g,"east")
  6714. @js ($ylfx) = var f="(ylfx)";f.replace(/南/g,"north")
  6715. @js ($ylfx) = var f="(ylfx)";f.replace(/北/g,"south")
  6716. @js ($ylfx) = var f="(ylfx)";f.replace(/,/g,"','")
  6717. @js ($ylfx) = var f=['(ylfx)'];f.reverse()
  6718. @js ($ylfx) = var f="(ylfx)";f.replace(/,/g,"','")
  6719. @js ($ylfx) = "'"+"(ylfx)"+"'"
  6720. @js ($fl) = [(ylfx)].length
  6721. go down
  6722. go south[3]
  6723. go south[2]
  6724. go west
  6725. ($go) = 'east','west','south','north'
  6726. ($num) = 0
  6727. [while] (num) < 4
  6728. @await 500
  6729. @js $(".content-message pre").html("");
  6730. @await 500
  6731. @js ($fx1) = [(go)][(num)]
  6732. go (fx1)
  6733. @js ($lost) = $(".content-message").text().match("你似乎迷路了")
  6734. [if] (lost) != null
  6735. go south[3]
  6736. go south[3]
  6737. go west
  6738. ($num) = (num) + 1
  6739. [else]
  6740. [break]
  6741. [if] (fl) == 5
  6742. ($num) = 0
  6743. [while] (num) < 5
  6744. @js ($fx) = [(ylfx)][(num)]
  6745. go (fx)
  6746. ($num) = (num) + 1
  6747. [else if] (fl) == 4
  6748. @js ($fx2) = [(ylfx)][0]
  6749. @js ($fx3) = [(ylfx)][1]
  6750. @js ($fx4) = [(ylfx)][2]
  6751. @js ($fx5) = [(ylfx)][3]
  6752. ($lxjh) = {"lx":"go (fx2);go (fx3);go (fx4);go (fx5);go (fx5)"},{"lx":"go (fx2);go (fx3);go (fx4);go (fx4);go (fx5)"},{"lx":"go (fx2);go (fx3);go (fx3);go (fx4);go (fx5)"},{"lx":"go (fx2);go (fx2);go (fx3);go (fx4);go (fx5)"}
  6753. [else if] (fl) == 3
  6754. @js ($fx2) = [(ylfx)][0]
  6755. @js ($fx3) = [(ylfx)][1]
  6756. @js ($fx4) = [(ylfx)][2]
  6757. ($lxjh) = {"lx":"go (fx2);go (fx3);go (fx4);go (fx4);go (fx4)"},{"lx":"go (fx2);go (fx3);go (fx3);go (fx3);go (fx4)"},{"lx":"go (fx2);go (fx2);go (fx2);go (fx3);go (fx4)"},{"lx":"go (fx2);go (fx3);go (fx3);go (fx4);go (fx4)"},{"lx":"go (fx2);go (fx2);go (fx3);go (fx4);go (fx4)"},{"lx":"go (fx2);go (fx2);go (fx3);go (fx3);go (fx4)"}
  6758. [else if] (fl) == 2
  6759. @js ($fx2) = [(ylfx)][0]
  6760. @js ($fx3) = [(ylfx)][1]
  6761. ($lxjh) = {"lx":"go (fx2);go (fx3);go (fx3);go (fx3);go (fx3)"},{"lx":"go (fx2);go (fx2);go (fx3);go (fx3);go (fx3)"},{"lx":"go (fx2);go (fx2);go (fx2);go (fx3);go (fx3)"},{"lx":"go (fx2);go (fx2);go (fx2);go (fx2);go (fx3)"}
  6762. [else if] (fl) == 1
  6763. @js ($fx2) = [(ylfx)][0]
  6764. ($lxjh) = {"lx":"go (fx2);go (fx2);go (fx2);go (fx2);go (fx2)"}
  6765. [if] (fl) < 5
  6766. @js ($fxlen) = [(lxjh)].length
  6767. ($num) = 0
  6768. [while] (num) < (fxlen)
  6769. @js ($map) = var f=[(lxjh)];f[(num)]["lx"]
  6770. (map)
  6771. [if] (:room) != 古大陆-药林
  6772. [while] (:room) != 古大陆-平原
  6773. go south
  6774. @await 350
  6775. go north;go west
  6776. go (fx1)
  6777. ($num) = (num) + 1
  6778. [else]
  6779. [break]
  6780. tiao bush
  6781. [if] (:room) == 古大陆-山脚
  6782. @print <ord>古宗门自动寻路已完成!</ord>
  6783. [else]
  6784. @print <ord>寻路失败,请重新运行或换个时间。</ord>
  6785. `
  6786. const p = new Performer("古宗门寻路", source);
  6787. p.log(false);
  6788. p.start();
  6789. },
  6790. };
  6791.  
  6792. /***********************************************************************************\
  6793. Ready
  6794. \***********************************************************************************/
  6795.  
  6796. const ToRaid = {
  6797. menu: UI.showToolbar,
  6798.  
  6799. perform: function (content, name, log) {
  6800. const realName = name ? name : "第三方调用";
  6801. ManagedPerformerCenter.start(realName, content, log);
  6802. },
  6803.  
  6804. existAutoDungeon: function (params) {
  6805. return AutoDungeonName(params) != null;
  6806. },
  6807.  
  6808. shareTrigger: function (triggerData) {
  6809. UI._share("触发", triggerData);
  6810. }
  6811. };
  6812.  
  6813. $(document).ready(function () {
  6814. __init__();
  6815. if (WG == undefined || WG == null) {
  6816. setTimeout(__init__, 300);
  6817. }
  6818. });
  6819.  
  6820. function __init__() {
  6821. WG = unsafeWindow.WG;
  6822. if (WG == undefined || WG == null) {
  6823. setTimeout(() => { __init__() }, 300);
  6824. return;
  6825. }
  6826. messageAppend = unsafeWindow.messageAppend;
  6827. messageClear = unsafeWindow.messageClear;
  6828. T = unsafeWindow.T;
  6829. L = unsafeWindow.L;
  6830.  
  6831. unsafeWindow.ToRaid = ToRaid;
  6832. unsafeWindow.Role = Role;
  6833.  
  6834. Role.init();
  6835. Room.init();
  6836. SystemTips.init();
  6837. MsgTips.init();
  6838. DialogList.init();
  6839. TaskList.init();
  6840. Xiangyang.init();
  6841. }
  6842. })();