cmds.tin 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907
  1. #nop vim: set filetype=tt:;
  2. /*
  3. 本文件属于 PaoTin++ 的一部分。
  4. PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
  5. 你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
  6. */
  7. #nop 本文件是 xtintin 的一部分,实现了一些实用命令。;
  8. ///=== {
  9. ///// 实用命令:
  10. //
  11. // ## clear
  12. // 清屏。类似于 DOS/Unix,也可以用 cls,作用相同。
  13. // };
  14. #alias {cls} {clear};
  15. #alias {clear} {
  16. #buffer clear;
  17. #buffer end;
  18. tmux.SetTheme GAME;
  19. prompt.refresh;
  20. };
  21. #var gLastQuitTime {0};
  22. ///=== {
  23. // ## quit
  24. // 退出客户端,但不退出游戏角色。也可以写作 exit,作用相同。
  25. // 一些中文 MUD 服务器在接收到 quit 命令时会让角色从服务器上下线,
  26. // 这往往会导致玩家丢失背包里的物品,或者强制放弃正在进行的任务。新手玩家常常因此懊恼万分。
  27. // 为了避免悲剧发生,这里特别映射一下,改成仅断开连接,而不退出服务器角色。
  28. // 如果玩家真的需要向服务器发送 quit 指令,请输入全大写的 QUIT。exit 同理要写作 EXIT。
  29. // };
  30. #alias {quit} {
  31. #if { @time.Now{} - $gLastQuitTime < 5 } {
  32. #end;
  33. };
  34. #else {
  35. xtt.Usage quit {<169>注意,本命令的用法可能和你的理解不同,<519>如果你真的需要 quit,请在 5 秒内再输入一遍。<088><169>具体参考下文:<000>};
  36. #var gLastQuitTime {@time.Now{}};
  37. };
  38. };
  39. #alias {exit} {quit};
  40. #alias {QUIT} {xtt.Send quit};
  41. #alias {EXIT} {xtt.Send exit};
  42. ///=== {
  43. // ## xtt.Tick <ID> <代码> <间隔时间> [<触发次数>]
  44. // 跟 #tick 功能类似,但是会立即执行一次代码。对于间隔时间比较长的定时器来说尤其有用。
  45. // 可选的触发次数会导致定时器在次数达到限制后自动销毁。省略此参数时将不限制触发次数。
  46. // 你也可以通过 Tick 别名来使用本别名。
  47. // };
  48. #alias {Tick} {xtt.Tick};
  49. #alias {xtt.Tick} {
  50. #local id {%1};
  51. #local code {%2};
  52. #local interval {%3};
  53. #local times {@defaultNum{%4;0}};
  54. #math times {$times - 1};
  55. #line sub var #untick {$id};
  56. #if { $times > 0 } {
  57. #line sub {var;escapes;functions} #line multishot {$times} #tick {$id} {$code} $interval;
  58. };
  59. #elseif { $times < 0 } {
  60. #line sub var #tick {$id} {$code} $interval;
  61. };
  62. #line sub {var;escapes;functions} $code;
  63. };
  64. ///=== {
  65. // ## xtt.ListTicker
  66. // 列出系统中所有的定时器。因为定时器一般不会很多因此暂时没有做过滤功能。
  67. // 你也可以通过 TICKS 别名来使用本别名。
  68. // };
  69. #alias {TICKS} {xtt.ListTicker};
  70. #alias {xtt.ListTicker} {
  71. #info tickers save;
  72. #echo {<128> %-30s %+20s %+10s %+20s} {所属模块} {定时器名称} {执行周期(s)} {距离下次执行(s)};
  73. #draw Yellow scroll line 1 1 1 90;
  74. #format utime %U;
  75. #local index {};
  76. #loop {1} {&info[TICKERS][]} {index} {
  77. #local uval {};
  78. #math uval $info[TICKERS][+$index][arg3] * 1000000;
  79. #local name {$info[TICKERS][+$index][arg1]};
  80. #echo { %-30s %+20s %+10s %+20m}
  81. {@genModuleLink{$info[TICKERS][+$index][class];MOD}}
  82. {$name @mslp.Exec{{xtt.delTrigger tick $name};<119>✗<269>;false}}
  83. {$info[TICKERS][+$index][arg3]}
  84. {($uval - ($utime - $info[TICKERS][+$index][arg4]) % $uval) / 1000000.00};
  85. };
  86. };
  87. ///=== {
  88. // ## xtt.ListAlias [<正则表达式>]
  89. // 列出系统中符合条件的别名,如果省略条件则列出所有别名。
  90. // 一些不够规整的别名不会被列出。只有符合 PaoTin++ 规范的别名才会被列出。
  91. // 正则表达式会被运用到别名所属模块名称和别名名称上,两者符合其一即可被列出。
  92. // 你也可以通过 ALIS 别名来使用本别名。
  93. // };
  94. #alias {ALIS} {xtt.ListAlias};
  95. #alias {xtt.ListAlias} {
  96. #local pattern {%1};
  97. #info aliases save;
  98. #local aliasTable {};
  99. #local index {};
  100. #loop {1} {&info[ALIASES][]} {index} {
  101. #local name {$info[ALIASES][+$index][arg1]};
  102. #local class {$info[ALIASES][+$index][class]};
  103. #if { "$class" == "" && "$pattern" != "all" } {
  104. #continue;
  105. };
  106. #if { "$class" == "" } {
  107. #local class {未分组};
  108. };
  109. #if { "$name" == "%*{[^a-zA-Z0-9-_.]}%*" } {
  110. #continue;
  111. };
  112. #if { "$pattern" != "{|all}" && "$class/$name" != "%*$pattern%*" } {
  113. #continue;
  114. };
  115. #list {aliasTable[$class]} sort {$name};
  116. };
  117. #local format { %-35s %-40s %-10s};
  118. #echo {<128>$format} {class} {别名} {类型};
  119. #draw Yellow scroll line 1 1 1 90;
  120. #local classList {@slist.Sort{*aliasTable[]}};
  121. #local class {};
  122. #foreach {$classList} {class} {
  123. #local name {};
  124. #foreach {${aliasTable[$class][]}} {name} {
  125. #local type {<139>自定义<299>};
  126. #if { "$name" == "%*.{[A-Z][a-zA-Z0-9]+}" } {
  127. #local type {<129>开放API<299>};
  128. };
  129. #if { "$name" == "{[a-z]+}" } {
  130. #local type {<159>伪装的服务器命令<299>};
  131. };
  132. #if { "$class" == "module-loader" } {
  133. #if { "$name" == "{[A-Z]+}" } {
  134. #local type {<169>快捷方式<299>};
  135. };
  136. #else {
  137. #local type {<229>语法增强<299>};
  138. }
  139. };
  140. #if { "${class}.$name" == "main.class.%*" } {
  141. #local type {<229>语法增强<299>};
  142. };
  143. #if { "${class}.$name" == "main.load-{file|config}" } {
  144. #local type {<229>语法增强<299>};
  145. };
  146. #if { "${class}.$name" == "main.%*Log" } {
  147. #local type {<129>日志接口<299>};
  148. };
  149. #if { "$pattern" == "" && "$type" == "%*自定义%*" } {
  150. #continue;
  151. };
  152. #echo {<060>$format}
  153. {@genModuleLink{$class;MOD}<060>}
  154. {@mslp.Exec{{xtt.delTrigger alias $name};<119>✗<269>;false} @linkToHelp{$class;$name}}
  155. {$type};
  156. };
  157. };
  158. };
  159. ///=== {
  160. // ## xtt.ListVar [<正则表达式>]
  161. // 列出系统中符合条件的变量,如果省略条件则列出所有变量。
  162. // 一些不够规整的变量不会被列出。只有符合 PaoTin++ 规范的变量才会被列出。
  163. // 正则表达式会被运用到变量所属模块名称和变量名称上,两者符合其一即可被列出。
  164. // 你也可以通过 VARS 别名来使用本别名。
  165. // };
  166. #alias {VARS} {xtt.ListVar};
  167. #alias {xtt.ListVar} {
  168. #local pattern {%1};
  169. #info variable save;
  170. #local varTable {};
  171. #local index {};
  172. #loop {1} {&info[VARIABLES][]} {index} {
  173. #local name {$info[VARIABLES][+$index][arg1]};
  174. #local class {$info[VARIABLES][+$index][class]};
  175. #local value {$info[VARIABLES][+$index][arg2]};
  176. #local nest {$info[VARIABLES][+$index][nest]};
  177. #local cnName {};
  178. #if { "$class" == "" && "$pattern" != "all" } {
  179. #continue;
  180. };
  181. #if { "$class" == "" } {
  182. #local class {未分组};
  183. };
  184. #if { &gPaoTinVars[$name][] > 0 } {
  185. #local cnName {$gPaoTinVars[$name][cnName]};
  186. };
  187. #if { "$pattern" != "{|all}" && "$class/$name/$cnName" != "%*$pattern%*" } {
  188. #continue;
  189. };
  190. #local {varTable[$class][$name]} {
  191. {nest}{$nest}
  192. {value}{$value}
  193. };
  194. };
  195. #local format { %-35s %-30s %-10s %s};
  196. #echo {<128>$format} {class} {变量} {类型} {值};
  197. #draw Yellow scroll line 1 1 1 95;
  198. #local classList {@slist.Sort{*varTable[]}};
  199. #local class {};
  200. #foreach {$classList} {class} {
  201. #local name {};
  202. #local nameList {@slist.Sort{*varTable[$class][]}};
  203. #foreach {$nameList} {name} {
  204. #local type {<229>字符串<299>};
  205. #local value {<169>$varTable[$class][$name][value]<299>};
  206. #local nest {$varTable[$class][$name][nest]};
  207. #if { $nest > 0 } {
  208. #local type {<259>表格<299>};
  209. #local value {@mslp.Var{$name;<139>[... 共 $nest 项数据]<299>}};
  210. };
  211. #local showClass {$class};
  212. #replace showClass {^data/} {};
  213. #echo {<060>$format}
  214. {@genModuleLink{$showClass;MOD}<060>}
  215. {@mslp.Exec{{xtt.delTrigger var $name};<119>✗<269>;false} @linkToHelp{$showClass;$name}}
  216. {$type}
  217. {$value};
  218. #if { &gPaoTinVars[$name][] > 0 } {
  219. #echo {$format}
  220. {}
  221. { ╰── $gPaoTinVars[$name][cnName]}
  222. {}
  223. {};
  224. };
  225. };
  226. };
  227. };
  228. #alias {xtt.delTrigger} {
  229. #local type {%1};
  230. #local trigger {%2};
  231. #local cmd {#un$type {$trigger}};
  232. #replace cmd {\\} {};
  233. $cmd;
  234. };
  235. ///=== {
  236. // ## xtt.ListFunc [<正则表达式>]
  237. // 列出系统中符合条件的函数,如果省略条件则列出所有函数。
  238. // 正则表达式会被运用到函数所属模块名称和函数名称上,两者符合其一即可被列出。
  239. // 一些不够规整的函数不会被列出。只有符合 PaoTin++ 规范的函数才会被列出。
  240. // 你也可以通过 FUNCS 别名来使用本别名。
  241. // };
  242. #alias {FUNCS} {xtt.ListFunc};
  243. #alias {xtt.ListFunc} {
  244. #local pattern {%1};
  245. #info functions save;
  246. #local funcsTable {};
  247. #local index {};
  248. #loop {1} {&info[FUNCTIONS][]} {index} {
  249. #local name {$info[FUNCTIONS][+$index][arg1]};
  250. #local class {$info[FUNCTIONS][+$index][class]};
  251. #if { "$class" == "" && "$pattern" != "all" } {
  252. #continue;
  253. };
  254. #if { "$class" == "" } {
  255. #local class {未分组};
  256. };
  257. #if { "$name" == "%*{[^a-zA-Z0-9_./-]}%*" } {
  258. #continue;
  259. };
  260. #if { "$pattern" != "{|all}" && "$class/$name" != "%*$pattern%*" } {
  261. #continue;
  262. };
  263. #list {funcsTable[$class]} sort {$name};
  264. };
  265. #local format { %-35s %-40s %-10s};
  266. #echo {<128>$format} {class} {函数} {类型};
  267. #draw Yellow scroll line 1 1 1 90;
  268. #local classList {@slist.Sort{*funcsTable[]}};
  269. #local class {};
  270. #foreach {$classList} {class} {
  271. #local name {};
  272. #foreach {${funcsTable[$class][]}} {name} {
  273. #local type {<139>自定义<299>};
  274. #if { "$name" == "%*.{[A-Z][a-zA-Z0-9]+}" } {
  275. #local type {<129>开放API<299>};
  276. };
  277. #if { "$class" == "{lib/xtintin|main}" } {
  278. #local type {<229>语法增强<299>};
  279. };
  280. #if { "${class}.$name" == "main.%*Log" } {
  281. #local type {<129>日志接口<299>};
  282. };
  283. #if { "$pattern" == "" && "$type" == "%*自定义%*" } {
  284. #continue;
  285. };
  286. #echo {<060>$format}
  287. {@genModuleLink{$class;MOD}<060>}
  288. {@mslp.Exec{{xtt.delTrigger func $name};<119>✗<269>;false} @linkToHelp{$class;$name}}
  289. {$type};
  290. };
  291. };
  292. };
  293. ///=== {
  294. // ## xtt.ListAction [<正则表达式>]
  295. // 列出系统中符合条件的文本触发,如果省略条件则列出所有文本触发。
  296. // 正则表达式会被运用到文本触发所属模块名称和文本触发的条件上,两者符合其一即可被列出。
  297. // 你也可以通过 ACTS 别名来使用本别名。
  298. // };
  299. #alias {ACTS} {xtt.ListAction};
  300. #alias {xtt.ListAction} {
  301. #local pattern {%1};
  302. #info actions save;
  303. #local actionTable {};
  304. #local index {};
  305. #loop {1} {&info[ACTIONS][]} {index} {
  306. #local name {$info[ACTIONS][+$index][arg1]};
  307. #local class {$info[ACTIONS][+$index][class]};
  308. #local priority {$info[ACTIONS][+$index][arg3]};
  309. #if { "$class" == "" && "$pattern" != "all" } {
  310. #continue;
  311. };
  312. #if { "$class" == "" } {
  313. #local class {未分组};
  314. };
  315. #if { "$pattern" != "{|all}" && "$class/$name" != "%*$pattern%*" } {
  316. #continue;
  317. };
  318. #list {actionTable[$class]} add {{{name}{$name}{priority}{$priority}}};
  319. };
  320. #local format { %-35s %-5s %-40s %-10s};
  321. #echo {<128>$format} {class} {优先级} {文本触发};
  322. #draw Yellow scroll line 1 1 1 90;
  323. #local classList {@slist.Sort{*actionTable[]}};
  324. #local class {};
  325. #foreach {$classList} {class} {
  326. #list {actionTable[$class]} indexate {name};
  327. #list {actionTable[$class]} sort;
  328. #local act {};
  329. #foreach {${actionTable[$class][]}} {act} {
  330. #local name {$act[name]};
  331. #local priority {$act[priority]};
  332. #echo {<060>$format}
  333. {@genModuleLink{$class;MOD}<060>}
  334. {$priority}
  335. {@mslp.Exec{{xtt.delTrigger action {$name}};<119>✗<269>;false} $name}
  336. };
  337. };
  338. };
  339. ///=== {
  340. // ## xtt.Var <变量中文含义> <变量名> <值>
  341. // 声明并初始化变量。和 #var 不同,如果该变量已存在,则不会修改它的值。
  342. // 另外,如果在模块中使用本方法,则声明的变量会自动存放在 #class data/\$MODULE 中。
  343. // 这意味着即使你重新载入模块代码,也不会破坏该变量的值。
  344. // 因此建议将通过触发抓取到的任务进度信息用本方法存储,可以有效避免机器代码迭代
  345. // 开发过程中,丢失任务信息从而导致任务失败。
  346. //
  347. // 也可以通过短名称 VAR 来使用本命令,效果相同。
  348. // };
  349. #alias {VAR} {xtt.Var};
  350. #alias {xtt.Var} {
  351. #local cnName {%1};
  352. #local name {%2};
  353. #local value {%3};
  354. #if { @existsVar{$name} } {
  355. #return;
  356. };
  357. #if { @existsVar{MODULE} } {
  358. #class data/$MODULE open;
  359. #var {$name} {$value};
  360. #class data/$MODULE close;
  361. };
  362. #else {
  363. #var {$name} {$value};
  364. };
  365. #var gPaoTinVars[$name] {
  366. {name} {$name}
  367. {cnName} {$cnName}
  368. };
  369. };
  370. VAR {用 VAR 关键字定义的 PaoTin++ 变量清单,包含其中文含义} gPaoTinVars {};
  371. ///=== {
  372. // ## xtt.Send <命令> [<参数> ...]
  373. // 向服务器发送命令。如果命令拦截总开关被打开,则不会真的向服务器发送。
  374. // };
  375. #alias {xtt.Send} {
  376. #if { @option.IsEnable{DisableOutput} } {
  377. #echo {<169>命令已被抑制: <429>%p<299>} {%0};
  378. #return;
  379. };
  380. #send %0;
  381. };
  382. ///=== {
  383. // ## xtt.SendBatch <分号分隔的命令序列>
  384. // 一次性向服务器发送多条命令。
  385. // 有的 MUD 服务器专门为这种方式开辟了通道,本方法可以使用这种通道。
  386. // 如果服务器不支持,则退化为重复调用多次 xtt.Send。
  387. // TODO: 需要区分 MUD,需要支持定制的命令分隔符。
  388. // };
  389. #alias {xtt.SendBatch} {
  390. #local cmds {%1};
  391. #foreach {$cmds} {cmd} {
  392. xtt.Send {$cmd};
  393. };
  394. };
  395. ///=== {
  396. // ## xtt.Answer <问题答复>
  397. // 如果游戏中有需要回答的问题,并且给出了特定的提示符(就是不带换行的文本),
  398. // 那么由于 TinTin++ 的某种机制,导致回答的内容和问题就会有重叠,不能正确显示。
  399. // 此时建议用 xtt.Answer 来回答此类问题。将会留下美观的 buffer 记录。
  400. // };
  401. #alias {xtt.Answer} {
  402. #delay 0 {
  403. #echo {};
  404. #buffer end;
  405. xtt.Send {%1};
  406. };
  407. };
  408. ///=== {
  409. // ## xtt.DoBusyDo <命令序列> [<机器名称>]
  410. // 启动一个 do-busy-do 型的简易机器。
  411. // 这种机器会在执行完一次命令序列后,进入 busy 状态,然后玩家期待 busy 结束之后,
  412. // 能够重复执行命令序列。最典型的比如打坐、修炼、凭吊,都是如此。
  413. // 这种模式是如此地常见,以至于我将其命名为 do-busy-do,并且提供了本别名。
  414. //
  415. // 为了进一步简化使用,本别名允许省略机器名称,此时将使用第一条命令作为机器名称。
  416. // 想要停止机器,可以使用 xtt.DoBusyDo.Stop 命令。
  417. //
  418. // 用法举例:
  419. //
  420. // xtt.DoBusyDo pingdiao
  421. // 将启动一个凭吊机器,机器名为 pingdiao;
  422. // xtt.DoBusyDo {xiulian taiji-shengong}
  423. // 启动一个修炼机器,机器名为 xiulian,即命令的名称,不包括参数部分;
  424. // xtt.DoBusyDo {dazuo max; dazuo 10}
  425. // 启动一个打坐机器,机器名为 dazuo,即第一条命令 dazuo max 的命令部分;
  426. // xtt.DoBusyDo {yun regenerate; tuna max; tuna 10} tuna;
  427. // 启动一个吐纳机器,机器名为 tuna,即第二个参数。
  428. //
  429. // 本别名也可以简写成 DBD。
  430. // };
  431. #alias {xtt.DoBusyDo} {
  432. #local cmds {%1};
  433. #local bot {%2};
  434. #local yun {@default{%3;true}};
  435. #if { "$cmds" == "" } {
  436. xtt.Usage %90;
  437. #return;
  438. };
  439. #if { "$bot" == "" } {
  440. #local bot {@slist.Get{{$cmds};1}};
  441. #replace bot {^%S{| .*}$} {&1};
  442. };
  443. #var bot.DoBusyDo.${bot}.lastRun {0};
  444. #line sub var #alias {bot.DoBusyDo.$bot} {
  445. #if { @char.IsBusy{} } {
  446. #delay {bot.DoBusyDo.$bot} {bot.DoBusyDo.$bot} 1;
  447. #return;
  448. };
  449. #local now {@time.Now{}};
  450. #if { $${bot.DoBusyDo.${bot}.lastRun} > 0 && $$now <= $${bot.DoBusyDo.${bot}.lastRun} } {
  451. #delay {bot.DoBusyDo.$bot} {bot.DoBusyDo.$bot} 3;
  452. #return;
  453. };
  454. #else {
  455. #var bot.DoBusyDo.${bot}.lastRun {@time.Now{}};
  456. };
  457. #if { @isTrue{$yun} } {
  458. #if { $$char[HP][气血百分比] < 30 } {
  459. yun recover;
  460. };
  461. #if { $$char[HP][精神百分比] < 30 } {
  462. yun regenerate;
  463. };
  464. };
  465. #if { "$$char[HP][饥饿]" != "{正常|很饱}" } {
  466. eat $$char[favorite][food];
  467. };
  468. #if { "$$char[HP][口渴]" != "{正常|很饱}" } {
  469. drink $$char[favorite][water];
  470. };
  471. $cmds;
  472. busy.Wait {bot.DoBusyDo.$bot};
  473. };
  474. bot.DoBusyDo.$bot;
  475. okLog 机器 $bot 已启动,你可以用 xtt.DoBusyDo.Stop $bot 来停止它。;
  476. };
  477. ///=== {
  478. // ## xtt.DoBusyDo/noyun <命令序列> [<机器名称>]
  479. // 启动一个 do-busy-do 型的简易机器。
  480. // 跟 xtt.DoBusyDo 类似,但是不会主动恢复气血和精神。
  481. // 本别名也可以简写成 DBD/noyun。
  482. // };
  483. #alias {xtt.DoBusyDo/noyun} {
  484. xtt.DoBusyDo {%1} {%2} false;
  485. };
  486. ///=== {
  487. // ## xtt.DoBusyDo.Stop <机器名称>
  488. // 停止一个 do-busy-do 型的简易机器。
  489. // 本别名也可以简写成 DBDS。
  490. // 参见 HELP xtt.DoBusyDo
  491. // };
  492. #alias {xtt.DoBusyDo.Stop} {
  493. #local bot {%1};
  494. #if { "$bot" == "" } {
  495. xtt.Usage %90;
  496. #return;
  497. };
  498. #line oneshot #alias bot.DoBusyDo.$bot {#0};
  499. #unvar bot.DoBusyDo.${bot}.lastRun;
  500. okLog 机器 $bot 将会在 busy 结束后停止。;
  501. };
  502. ///=== {
  503. // ## DBD <命令序列> [<机器名称>]
  504. // 启动一个 do-busy-do 型的简易机器。
  505. // xtt.DoBusyDo 的缩写。参见 HELP xtt.DoBusyDo。
  506. //
  507. // ## DBD/noyun <命令序列> [<机器名称>]
  508. // 启动一个 do-busy-do 型的简易机器。
  509. // xtt.DoBusyDo/noyun 的缩写。参见 HELP xtt.DoBusyDo/noyun。
  510. //
  511. // ## DBDS <机器名称>
  512. // 停止一个 do-busy-do 型的简易机器。
  513. // 参见 HELP xtt.DoBusyDo 和 xtt.DoBusyDo.Stop。
  514. // };
  515. #alias {DBD} {xtt.DoBusyDo};
  516. #alias {DBD/noyun} {xtt.DoBusyDo/noyun};
  517. #alias {DBDS} {xtt.DoBusyDo.Stop};
  518. ///=== {
  519. // ## xtt.Stop <命令>
  520. // 暂时阻断某个命令的执行。
  521. // 某些基于触发的机器会周而复始地执行动作。本命令可以用来终止它的运行,并保留状态。
  522. // 例如新手机器会循环执行 ask job/do/finish 流程,那么只需要输入 xtt.Stop ask,
  523. // 就可以在下一次 ask NPC 时,暂停机器执行,但并不影响机器状态。此时玩家可以手动
  524. // 操作角色,临时去做点别的,比如收个包袱之类的,然后回到房间,手动执行一次 ask 命令,
  525. // 就可以继续机器运行了。
  526. // };
  527. #alias {xtt.Stop} {
  528. #if { "%1" == "" } {
  529. xtt.Usage xtt.Stop;
  530. #return;
  531. };
  532. #line oneshot #alias {%1} {halt; #echo {<119>任务已暂停,请输入 <139>%1 %s <119>继续运行。<299>} {%%0}}
  533. };
  534. ///=== {
  535. // ## xtt.DisableAllCommands
  536. // 禁止发送任何命令。
  537. // 某些游戏模式下,玩家必须小心地输入,否则一旦输错会造成损失。此时可以用本
  538. // 命令来禁止所有的触发、定时器、事件,防止误发命令。
  539. // 此时玩家只能用 #send {.....} 命令来发送命令。
  540. // 注意快捷键并不会被禁止,所以玩家可以通过快捷键来切换状态。
  541. // };
  542. #alias {xtt.DisableAllCommands} {
  543. #local carefully {@default{%1;true}};
  544. #class disable-all-commands open;
  545. option.Enable DisableAllCommands;
  546. warnLog 所有定时器、触发器和事件句柄已被禁用。;
  547. warnLog 600 秒后自动解除该状态。;
  548. #if { @isTrue{$carefully} } {
  549. #alias {^%*{|ID=paotin/disable-all-commands}$} {
  550. #echo {<119>命令已被抑制,可用 <129>#send<119> 强制发送。撤销请用 <129>xtt.UndoDisableAllCommands<119> : <139>%s<299>} {%%0}
  551. } {1.002};
  552. };
  553. #else {
  554. #alias {^%*{|ID=paotin/disable-all-commands}$} {
  555. #echo {%s} {%%0};
  556. #send %%0;
  557. #line gag;
  558. } {1.002};
  559. };
  560. #gts {#delay 600 {#ats xtt.UndoDisableAllCommands}};
  561. #line quiet #ignore actions on;
  562. #line quiet #ignore tickers on;
  563. #line quiet #ignore events on;
  564. #class disable-all-commands close;
  565. };
  566. ///=== {
  567. // ## xtt.UndoDisableAllCommands
  568. // 取消 xtt.DisableAllCommands 效果,恢复正常状态。
  569. // 参见 HELP xtt.DisableAllCommands
  570. // };
  571. #alias {xtt.UndoDisableAllCommands} {
  572. #class disable-all-commands kill;
  573. #line quiet #ignore actions off;
  574. #line quiet #ignore tickers off;
  575. #line quiet #ignore events off;
  576. okLog 命令已恢复正常。;
  577. option.Disable DisableAllCommands;
  578. } {1.000};
  579. ///=== {
  580. // ## xtt.ToggleDisableCommands
  581. // 在禁止和打开所有的定时器、触发器和事件句柄之间来回切换。
  582. // 本命令可用作绑定快捷键使用。
  583. // };
  584. #alias {xtt.ToggleDisableCommands} {
  585. #if { @option.IsEnable{DisableAllCommands} } {
  586. xtt.UndoDisableAllCommands;
  587. };
  588. #else {
  589. xtt.DisableAllCommands;
  590. };
  591. } {1.000};
  592. ///=== {
  593. // ## xtt.MultiLineEdit
  594. // 进入多行编辑模式。
  595. // };
  596. #alias {xtt.MultiLineEdit} {
  597. xtt.DisableAllCommands false;
  598. #class multi-edit open;
  599. #alias {^x$} {
  600. #class multi-edit kill;
  601. #echo {%s} {%%0};
  602. #send x;
  603. #line gag;
  604. xtt.UndoDisableAllCommands;
  605. } {1.000};
  606. #alias {^c$} {
  607. #class multi-edit kill;
  608. #echo {%s} {%%0};
  609. #send c;
  610. #line gag;
  611. xtt.UndoDisableAllCommands;
  612. } {1.000};
  613. #class multi-edit close;
  614. };
  615. #action {^结束离开用 'x',取消输入用 'c'。$} {xtt.MultiLineEdit};
  616. #func {linkToHelp} {
  617. #local module {%1};
  618. #local keyword {%2};
  619. #local text {$keyword};
  620. #local cmd {HELP $keyword};
  621. #if { "$keyword" == "" } {
  622. #local text {$module};
  623. #local keyword {MODULE};
  624. #local cmd {HELP $module};
  625. };
  626. #if { "$module" == "" } {
  627. #return {$text};
  628. };
  629. #if { &xtt.module-doc[$module][] == 0 } {
  630. #return {$text};
  631. };
  632. #if { &xtt.module-doc[$module][$keyword][] == 0 } {
  633. #return {$text};
  634. };
  635. #return {<149>@mslp.Exec{{$cmd};{$text}}<299>};
  636. };
  637. ///=== {
  638. // ## cli.SmartToggle
  639. // 命令行智能切换。
  640. // 出于方便起见,该命令实际上集成了三个作用,并推荐使用快捷键来调用本命令。
  641. // - 作用1: 当命令行尚未输入内容时,用来切换 PaoTin++ 的调试开关。
  642. // 调试开关开启时,玩家可以看到触发的执行细节,方便调试代码。
  643. // - 作用2: 当命令行输入了 #alias/#action 等 TinTin++ 可被取消的触发时,会
  644. // 自动修改成对应的 #unalias/#unaction 命令,利用这一点可以方便取
  645. // 消已有触发。可被取消的触发列表见下方完整清单。
  646. // - 作用3: 当命令行输入了其它命令时,会自动开启或关闭以调试方式执行该命令。
  647. // 该切换并不会影响全局调试开关。因此不会受到来自其它触发的干扰,
  648. // 内容更精准,方便查看。
  649. //
  650. // 作用2中可被取消的命令清单:
  651. // - 常用 TinTin++ 命令: action alias tick variable delay gag
  652. // - 不常用 TinTin++ 命令: button event function highlight macro pathdir
  653. // prompt substitute tab
  654. // 以上命令的 3 字母以上简写,无论大小写,都会被自动添加或者删除 un,
  655. // 以达到切换的目的。
  656. // - 常用的 PaoTin++ 命令: event.Handle/event.HandleOnce VS event.UnHandle
  657. // };
  658. #alias {cli.SmartToggle} {
  659. #local input {};
  660. #cursor get input;
  661. #line quiet #ignore function on;
  662. #if { {$input} == {} } {
  663. #line quiet #ignore function off;
  664. xtt.ToggleDebug;
  665. #return;
  666. };
  667. #if { {$input} == {#line debug %*} } {
  668. #replace input {^#line debug } {};
  669. };
  670. #elseif { {$input} == {{|#line quiet }#debug %S on} } {
  671. #replace input {^{|#line quiet }#debug %S on$} {&1#debug &2 off};
  672. };
  673. #elseif { {$input} == {{|#line quiet }#debug %S off} } {
  674. #replace input {^{|#line quiet }#debug %S off$} {&1#debug &2 on};
  675. };
  676. #else {
  677. #local cmds {act(|i(|o(|n)))|ali(|a(|s))|tic(|k(|e(|r)))
  678. |var(|i(|a(|b(|l(|e)))))
  679. |del(|a(|y))|gag|tab
  680. |but(|t(|o(|n)))|eve(|n(|t))
  681. |fun(|c(|t(|i(|o(|n)))))
  682. |hig(|h(|l(|i(|g(|h(|t))))))
  683. |mac(|r(|o))|pat(|h(|d(|i(|r))))
  684. |pro(|m(|p(|t)))
  685. |sub(|s(|t(|i(|t(|u(|t(|e)))))))};
  686. #replace cmds { } {};
  687. #if { {$input} == {{?i}#un{$cmds} %*} } {
  688. #replace input {{?i}#un} {#};
  689. };
  690. #elseif { {$input} == {{?i}#{$cmds} %*} } {
  691. #replace input {^#} {#un};
  692. };
  693. #elseif { {$input} == {{tt|}event.{Class|}Handle{|Once} %*} } {
  694. #replace input {^{tt|}event.{Class|}Handle{Once|}} {&1event.UnHandle};
  695. };
  696. #elseif { {$input} == {{tt|}event.UnHandle %*} } {
  697. #replace input {^{tt|}event.UnHandle} {&1event.Handle};
  698. };
  699. #else {
  700. #local input {#line debug $input};
  701. };
  702. };
  703. #cursor clear;
  704. #local cmd {
  705. #line quiet #ignore variable on;
  706. #line quiet #line sub escapes #cursor set {$input};
  707. #line quiet #ignore variable off;
  708. };
  709. $cmd;
  710. #line quiet #ignore function off;
  711. };
  712. ///=== {
  713. // ## xtt.Ping [<次数>]
  714. // 计算服务器延迟,输出以毫秒为单位的统计数据;
  715. // };
  716. #alias {PING} {xtt.Ping};
  717. #alias {xtt.Ping} {
  718. #class xtt.Ping open;
  719. #list xtt-ping-samples create {};
  720. #var xtt-ping-send-time {};
  721. #var xtt-ping-times {10};
  722. #alias {xtt.Ping.ping} {
  723. #if { $xtt-ping-times <= 0 } {
  724. xtt.Ping.done;
  725. #return;
  726. };
  727. #var xtt-ping-send-time {@str.Format{%U}};
  728. sync.Wait xtt.Ping.pong;
  729. };
  730. #alias {xtt.Ping.pong} {
  731. #math xtt-ping-times {$xtt-ping-times - 1};
  732. #list xtt-ping-samples add {@math.Eval{ @str.Format{%U} - $xtt-ping-send-time }};
  733. xtt.Ping.ping;
  734. };
  735. #alias {xtt.Ping.done} {
  736. #list xtt-ping-samples order;
  737. #list xtt-ping-samples delete -1;
  738. #list xtt-ping-samples delete 1;
  739. #local min {@math.Eval{ $xtt-ping-samples[1] / 1000 }};
  740. #local max {@math.Eval{ $xtt-ping-samples[-1] / 1000 }};
  741. #local avg {@math.Eval{ @math.Sum{$xtt-ping-samples[]} / &xtt-ping-samples[] / 1000 }};
  742. #class xtt.Ping kill;
  743. okLog 网络测速结果如右:最大值 $max 毫秒,最小值 $min 毫秒,平均值 $avg 毫秒;
  744. };
  745. #class xtt.Ping close;
  746. sync.Wait {xtt.Ping.ping};
  747. };
  748. ///=== {
  749. // ## xtt.ConvertMeta <命令> [<参数> ...]
  750. // 执行命令,并且将其输出全部用原始文本格式显示,方便制作颜色触发。
  751. // 本命令也可以写成 CCM,方便使用。
  752. // };
  753. #alias {CCM} {xtt.ConvertMeta};
  754. #alias {xtt.ConvertMeta} {
  755. #if { "%0" == "" } {
  756. xtt.Usage xtt.ConvertMeta;
  757. #return;
  758. };
  759. warnLog 开启原始文本显示模式,一秒钟后自动关闭。;
  760. #config {convert meta} on;
  761. #delay 1 {
  762. #config {convert meta} off;
  763. okLog 已关闭原始文本显示模式。;
  764. ga.Sync;
  765. };
  766. %0;
  767. };