diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 6c033b28cb..c95e7ed918 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,7 +1,8 @@ ### PR受影响的平台 - + + ### 诱因和背景 @@ -26,9 +27,10 @@ ### 检查清单 - -- [ ] 我已经进行了充足的测试,且现有的测试都已通过 + - [ ] 我没有把该PR提交到`master`分支 +- [ ] commit中没有无用信息,和没有具体内容的“bugfix” +- [ ] 我已经进行了充足的测试,且现有的测试都已通过 - [ ] 如果此次PR中添加了新的武将,则我已在`character/rank.js`中添加对应的武将强度评级,并对双人武将/复姓武将添加`name:xxx`的参数 - [ ] 如果此次PR中添加了新的语音文件,则我已在`lib.translate`中加入语音文件的文字台词 - [ ] 如果此次PR涉及到新功能的添加,我已在`PR描述`中写入详细文档 diff --git a/.gitignore b/.gitignore index 21f89d74a8..f5b6362b2f 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ package.json Thumbs.db bun.lockb deno.lock +game/*.zip diff --git a/.mise.toml b/.mise.toml new file mode 100644 index 0000000000..126f680735 --- /dev/null +++ b/.mise.toml @@ -0,0 +1,2 @@ +[tools] +node = "20" diff --git a/Dockerfile b/Dockerfile index 5c8d3d46af..94bcab4e40 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,14 @@ -FROM node:18 - -WORKDIR /app - -COPY ./docker/* ./ - -RUN npm install body-parser express minimist - -COPY . . - -EXPOSE 8080 -EXPOSE 8089 - -CMD [ "sh","./start.sh" ] \ No newline at end of file +FROM node:20 + +WORKDIR /app + +COPY ./docker/* ./ + +RUN npm install ws body-parser express minimist + +COPY . . + +EXPOSE 8080 +EXPOSE 8089 + +CMD [ "sh","./start.sh" ] diff --git a/README.md b/README.md index 8d22174bf7..e9290cf1c8 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,6 @@ https://github.com/nonameShijian/noname-server [《无名杀》项目 Pull Request 提交规范](https://github.com/libccy/noname/wiki/%E3%80%8A%E6%97%A0%E5%90%8D%E6%9D%80%E3%80%8B%E9%A1%B9%E7%9B%AE-Pull-Request-%E6%8F%90%E4%BA%A4%E8%A7%84%E8%8C%83) -在线试玩: - -https://spmario233.github.io/noname/index.html (图片素材加载速度较慢,不推荐) - 客户端下载戳这里: GitHub: https://github.com/libccy/noname/releases/tag/chromium85-client @@ -26,7 +22,7 @@ docker: [docker.md](./docker/docker.md) 网页端推荐使用 Chrome 系内核浏览器游玩,不推荐使用低版本 Firefox 浏览器 -请尽量保证游玩的 Chrome 系浏览器或手机 Webview 的`内核版本大于等于77` +请尽量保证游玩的 Chrome 系浏览器或手机 Webview 的`内核版本大于等于85` 提交 Pull Request 时请推送到"PR-Branch"分支! diff --git a/audio/die/bianyue.mp3 b/audio/die/bianyue.mp3 new file mode 100644 index 0000000000..e2dd02d5c7 Binary files /dev/null and b/audio/die/bianyue.mp3 differ diff --git a/audio/die/caoteng.mp3 b/audio/die/caoteng.mp3 new file mode 100644 index 0000000000..c3a40a05ea Binary files /dev/null and b/audio/die/caoteng.mp3 differ diff --git a/audio/die/dc_sb_chengyu.mp3 b/audio/die/dc_sb_chengyu.mp3 new file mode 100644 index 0000000000..6c810bccc9 Binary files /dev/null and b/audio/die/dc_sb_chengyu.mp3 differ diff --git a/audio/die/dc_sb_dianwei.mp3 b/audio/die/dc_sb_dianwei.mp3 new file mode 100644 index 0000000000..d2b522a083 Binary files /dev/null and b/audio/die/dc_sb_dianwei.mp3 differ diff --git a/audio/die/erqiao.mp3 b/audio/die/erqiao.mp3 deleted file mode 100644 index 7c89cf8633..0000000000 Binary files a/audio/die/erqiao.mp3 and /dev/null differ diff --git a/audio/die/erzhang.mp3 b/audio/die/erzhang.mp3 deleted file mode 100644 index 1a06d7f3fd..0000000000 Binary files a/audio/die/erzhang.mp3 and /dev/null differ diff --git a/audio/die/guanxingzhangbao.mp3 b/audio/die/guanxingzhangbao.mp3 deleted file mode 100644 index 672d7143cf..0000000000 Binary files a/audio/die/guanxingzhangbao.mp3 and /dev/null differ diff --git a/audio/die/gz_dengai.mp3 b/audio/die/gz_dengai.mp3 new file mode 100644 index 0000000000..88659ca3af Binary files /dev/null and b/audio/die/gz_dengai.mp3 differ diff --git a/audio/die/huan_jiangwei.mp3 b/audio/die/huan_jiangwei.mp3 new file mode 100644 index 0000000000..183cfbaa7e Binary files /dev/null and b/audio/die/huan_jiangwei.mp3 differ diff --git a/audio/die/huan_zhugeguo.mp3 b/audio/die/huan_zhugeguo.mp3 new file mode 100644 index 0000000000..be6adc5035 Binary files /dev/null and b/audio/die/huan_zhugeguo.mp3 differ diff --git a/audio/die/huaxiong.mp3 b/audio/die/huaxiong.mp3 index bb5bec5749..2287316d52 100644 Binary files a/audio/die/huaxiong.mp3 and b/audio/die/huaxiong.mp3 differ diff --git a/audio/die/jsrg_hejin.mp3 b/audio/die/jsrg_hejin.mp3 new file mode 100644 index 0000000000..0fc1d638d3 Binary files /dev/null and b/audio/die/jsrg_hejin.mp3 differ diff --git a/audio/die/jsrg_liuhong.mp3 b/audio/die/jsrg_liuhong.mp3 new file mode 100644 index 0000000000..7ac38c40f5 Binary files /dev/null and b/audio/die/jsrg_liuhong.mp3 differ diff --git a/audio/die/jsrg_wangyun.mp3 b/audio/die/jsrg_wangyun.mp3 new file mode 100644 index 0000000000..cc80e508e0 Binary files /dev/null and b/audio/die/jsrg_wangyun.mp3 differ diff --git a/audio/die/licaiwei.mp3 b/audio/die/licaiwei.mp3 index dc5e72465c..df3d43f63a 100644 Binary files a/audio/die/licaiwei.mp3 and b/audio/die/licaiwei.mp3 differ diff --git a/audio/die/liutan.mp3 b/audio/die/liutan.mp3 new file mode 100644 index 0000000000..7cb032f80b Binary files /dev/null and b/audio/die/liutan.mp3 differ diff --git a/audio/die/mb_sp_zhenji.mp3 b/audio/die/mb_sp_zhenji.mp3 new file mode 100644 index 0000000000..582f6f88dd Binary files /dev/null and b/audio/die/mb_sp_zhenji.mp3 differ diff --git a/audio/die/mb_zhangfen.mp3 b/audio/die/mb_zhangfen.mp3 new file mode 100644 index 0000000000..e8c01564a4 Binary files /dev/null and b/audio/die/mb_zhangfen.mp3 differ diff --git a/audio/die/ol_sunru.mp3 b/audio/die/ol_sunru.mp3 new file mode 100644 index 0000000000..635d7b0791 Binary files /dev/null and b/audio/die/ol_sunru.mp3 differ diff --git a/audio/die/re_sunshangxiang.mp3 b/audio/die/re_sunshangxiang.mp3 index de3edb0bd2..3e2ddb8d44 100644 Binary files a/audio/die/re_sunshangxiang.mp3 and b/audio/die/re_sunshangxiang.mp3 differ diff --git a/audio/die/sb_jiaxu.mp3 b/audio/die/sb_jiaxu.mp3 new file mode 100644 index 0000000000..fc10e78347 Binary files /dev/null and b/audio/die/sb_jiaxu.mp3 differ diff --git a/audio/die/sb_sunquan.mp3 b/audio/die/sb_sunquan.mp3 index 167431386d..44f82b0650 100644 Binary files a/audio/die/sb_sunquan.mp3 and b/audio/die/sb_sunquan.mp3 differ diff --git a/audio/die/sp_lvfan.mp3 b/audio/die/sp_lvfan.mp3 index 7c1f4d911f..b6241cb84e 100644 Binary files a/audio/die/sp_lvfan.mp3 and b/audio/die/sp_lvfan.mp3 differ diff --git a/audio/die/zhangmancheng.mp3 b/audio/die/tw_zhangmancheng.mp3 similarity index 100% rename from audio/die/zhangmancheng.mp3 rename to audio/die/tw_zhangmancheng.mp3 diff --git a/audio/die/xin_hansui.mp3 b/audio/die/xin_hansui.mp3 deleted file mode 100644 index 5c1b36a8d5..0000000000 Binary files a/audio/die/xin_hansui.mp3 and /dev/null differ diff --git a/audio/die/yue_zoushi.mp3 b/audio/die/yue_zoushi.mp3 new file mode 100644 index 0000000000..7493683d7a Binary files /dev/null and b/audio/die/yue_zoushi.mp3 differ diff --git a/audio/skill/dcbizu1.mp3 b/audio/skill/dcbizu1.mp3 new file mode 100644 index 0000000000..be966ae128 Binary files /dev/null and b/audio/skill/dcbizu1.mp3 differ diff --git a/audio/skill/dcbizu2.mp3 b/audio/skill/dcbizu2.mp3 new file mode 100644 index 0000000000..30f8c33618 Binary files /dev/null and b/audio/skill/dcbizu2.mp3 differ diff --git a/audio/skill/dcchixing1.mp3 b/audio/skill/dcchixing1.mp3 new file mode 100644 index 0000000000..467b4a60a1 Binary files /dev/null and b/audio/skill/dcchixing1.mp3 differ diff --git a/audio/skill/dcchixing2.mp3 b/audio/skill/dcchixing2.mp3 new file mode 100644 index 0000000000..9ead97401b Binary files /dev/null and b/audio/skill/dcchixing2.mp3 differ diff --git a/audio/skill/dcgaojian1.mp3 b/audio/skill/dcgaojian1.mp3 new file mode 100644 index 0000000000..1d7a3003f3 Binary files /dev/null and b/audio/skill/dcgaojian1.mp3 differ diff --git a/audio/skill/dcgaojian2.mp3 b/audio/skill/dcgaojian2.mp3 new file mode 100644 index 0000000000..e2a5d62ad3 Binary files /dev/null and b/audio/skill/dcgaojian2.mp3 differ diff --git a/audio/skill/dchuoxin1.mp3 b/audio/skill/dchuoxin1.mp3 new file mode 100644 index 0000000000..7af82c9007 Binary files /dev/null and b/audio/skill/dchuoxin1.mp3 differ diff --git a/audio/skill/dchuoxin2.mp3 b/audio/skill/dchuoxin2.mp3 new file mode 100644 index 0000000000..299340601b Binary files /dev/null and b/audio/skill/dchuoxin2.mp3 differ diff --git a/audio/skill/dcjingyin1.mp3 b/audio/skill/dcjingyin1.mp3 new file mode 100644 index 0000000000..b89ae8962d Binary files /dev/null and b/audio/skill/dcjingyin1.mp3 differ diff --git a/audio/skill/dcjingyin2.mp3 b/audio/skill/dcjingyin2.mp3 new file mode 100644 index 0000000000..db7d0875fd Binary files /dev/null and b/audio/skill/dcjingyin2.mp3 differ diff --git a/audio/skill/dcsbkangyong1.mp3 b/audio/skill/dcsbkangyong1.mp3 new file mode 100644 index 0000000000..aa4aa85125 Binary files /dev/null and b/audio/skill/dcsbkangyong1.mp3 differ diff --git a/audio/skill/dcsbkangyong2.mp3 b/audio/skill/dcsbkangyong2.mp3 new file mode 100644 index 0000000000..02022d8aee Binary files /dev/null and b/audio/skill/dcsbkangyong2.mp3 differ diff --git a/audio/skill/dcsbkuangzhan1.mp3 b/audio/skill/dcsbkuangzhan1.mp3 new file mode 100644 index 0000000000..85b959919f Binary files /dev/null and b/audio/skill/dcsbkuangzhan1.mp3 differ diff --git a/audio/skill/dcsbkuangzhan2.mp3 b/audio/skill/dcsbkuangzhan2.mp3 new file mode 100644 index 0000000000..f6db502619 Binary files /dev/null and b/audio/skill/dcsbkuangzhan2.mp3 differ diff --git a/audio/skill/dcshizha1.mp3 b/audio/skill/dcshizha1.mp3 new file mode 100644 index 0000000000..c05bfddb54 Binary files /dev/null and b/audio/skill/dcshizha1.mp3 differ diff --git a/audio/skill/dcshizha2.mp3 b/audio/skill/dcshizha2.mp3 new file mode 100644 index 0000000000..de7a7090da Binary files /dev/null and b/audio/skill/dcshizha2.mp3 differ diff --git a/audio/skill/dcwuxie1.mp3 b/audio/skill/dcwuxie1.mp3 new file mode 100644 index 0000000000..a46b13419e Binary files /dev/null and b/audio/skill/dcwuxie1.mp3 differ diff --git a/audio/skill/dcwuxie2.mp3 b/audio/skill/dcwuxie2.mp3 new file mode 100644 index 0000000000..ffc38fd52b Binary files /dev/null and b/audio/skill/dcwuxie2.mp3 differ diff --git a/audio/skill/dcyunzheng1.mp3 b/audio/skill/dcyunzheng1.mp3 new file mode 100644 index 0000000000..ad6bfe2b02 Binary files /dev/null and b/audio/skill/dcyunzheng1.mp3 differ diff --git a/audio/skill/dcyunzheng2.mp3 b/audio/skill/dcyunzheng2.mp3 new file mode 100644 index 0000000000..2dadc89b94 Binary files /dev/null and b/audio/skill/dcyunzheng2.mp3 differ diff --git a/audio/skill/dczhuoli2.mp3 b/audio/skill/dczhuoli2.mp3 new file mode 100644 index 0000000000..52cef17164 Binary files /dev/null and b/audio/skill/dczhuoli2.mp3 differ diff --git a/audio/skill/jsrgchaozheng1.mp3 b/audio/skill/jsrgchaozheng1.mp3 new file mode 100644 index 0000000000..c76f91dc87 Binary files /dev/null and b/audio/skill/jsrgchaozheng1.mp3 differ diff --git a/audio/skill/jsrgchaozheng2.mp3 b/audio/skill/jsrgchaozheng2.mp3 new file mode 100644 index 0000000000..b9792462f2 Binary files /dev/null and b/audio/skill/jsrgchaozheng2.mp3 differ diff --git a/audio/skill/jsrgchaozheng3.mp3 b/audio/skill/jsrgchaozheng3.mp3 new file mode 100644 index 0000000000..5db9823dc3 Binary files /dev/null and b/audio/skill/jsrgchaozheng3.mp3 differ diff --git a/audio/skill/jsrgchaozheng4.mp3 b/audio/skill/jsrgchaozheng4.mp3 new file mode 100644 index 0000000000..ea8923ecec Binary files /dev/null and b/audio/skill/jsrgchaozheng4.mp3 differ diff --git a/audio/skill/jsrgfayi1.mp3 b/audio/skill/jsrgfayi1.mp3 new file mode 100644 index 0000000000..ac4a3e03dd Binary files /dev/null and b/audio/skill/jsrgfayi1.mp3 differ diff --git a/audio/skill/jsrgfayi2.mp3 b/audio/skill/jsrgfayi2.mp3 new file mode 100644 index 0000000000..1a2296ff64 Binary files /dev/null and b/audio/skill/jsrgfayi2.mp3 differ diff --git a/audio/skill/jsrgjulian1.mp3 b/audio/skill/jsrgjulian1.mp3 new file mode 100644 index 0000000000..ea5d3cd6a0 Binary files /dev/null and b/audio/skill/jsrgjulian1.mp3 differ diff --git a/audio/skill/jsrgjulian2.mp3 b/audio/skill/jsrgjulian2.mp3 new file mode 100644 index 0000000000..b5141cf31e Binary files /dev/null and b/audio/skill/jsrgjulian2.mp3 differ diff --git a/audio/skill/jsrgjulian3.mp3 b/audio/skill/jsrgjulian3.mp3 new file mode 100644 index 0000000000..93a23059c5 Binary files /dev/null and b/audio/skill/jsrgjulian3.mp3 differ diff --git a/audio/skill/jsrgjulian4.mp3 b/audio/skill/jsrgjulian4.mp3 new file mode 100644 index 0000000000..4d6a3c252f Binary files /dev/null and b/audio/skill/jsrgjulian4.mp3 differ diff --git a/audio/skill/jsrgshelun1.mp3 b/audio/skill/jsrgshelun1.mp3 new file mode 100644 index 0000000000..8b29c43625 Binary files /dev/null and b/audio/skill/jsrgshelun1.mp3 differ diff --git a/audio/skill/jsrgshelun2.mp3 b/audio/skill/jsrgshelun2.mp3 new file mode 100644 index 0000000000..819b6e0220 Binary files /dev/null and b/audio/skill/jsrgshelun2.mp3 differ diff --git a/audio/skill/jsrgshelun3.mp3 b/audio/skill/jsrgshelun3.mp3 new file mode 100644 index 0000000000..d8c9e4d833 Binary files /dev/null and b/audio/skill/jsrgshelun3.mp3 differ diff --git a/audio/skill/jsrgshelun4.mp3 b/audio/skill/jsrgshelun4.mp3 new file mode 100644 index 0000000000..c47c3bd20e Binary files /dev/null and b/audio/skill/jsrgshelun4.mp3 differ diff --git a/audio/skill/jsrgshenchong1.mp3 b/audio/skill/jsrgshenchong1.mp3 new file mode 100644 index 0000000000..4a825b23fa Binary files /dev/null and b/audio/skill/jsrgshenchong1.mp3 differ diff --git a/audio/skill/jsrgshenchong2.mp3 b/audio/skill/jsrgshenchong2.mp3 new file mode 100644 index 0000000000..360b862d1a Binary files /dev/null and b/audio/skill/jsrgshenchong2.mp3 differ diff --git a/audio/skill/jsrgyanhuo1.mp3 b/audio/skill/jsrgyanhuo1.mp3 new file mode 100644 index 0000000000..7090a2fb0e Binary files /dev/null and b/audio/skill/jsrgyanhuo1.mp3 differ diff --git a/audio/skill/jsrgyanhuo2.mp3 b/audio/skill/jsrgyanhuo2.mp3 new file mode 100644 index 0000000000..d4e8f85c22 Binary files /dev/null and b/audio/skill/jsrgyanhuo2.mp3 differ diff --git a/audio/skill/jsrgzhaobing1.mp3 b/audio/skill/jsrgzhaobing1.mp3 new file mode 100644 index 0000000000..f42dabbbb2 Binary files /dev/null and b/audio/skill/jsrgzhaobing1.mp3 differ diff --git a/audio/skill/jsrgzhaobing2.mp3 b/audio/skill/jsrgzhaobing2.mp3 new file mode 100644 index 0000000000..4a01e1fc5d Binary files /dev/null and b/audio/skill/jsrgzhaobing2.mp3 differ diff --git a/audio/skill/jsrgzhuhuan1.mp3 b/audio/skill/jsrgzhuhuan1.mp3 new file mode 100644 index 0000000000..ea2193cbe5 Binary files /dev/null and b/audio/skill/jsrgzhuhuan1.mp3 differ diff --git a/audio/skill/jsrgzhuhuan2.mp3 b/audio/skill/jsrgzhuhuan2.mp3 new file mode 100644 index 0000000000..77f1ca7d81 Binary files /dev/null and b/audio/skill/jsrgzhuhuan2.mp3 differ diff --git a/audio/skill/mbbojian1.mp3 b/audio/skill/mbbojian1.mp3 new file mode 100644 index 0000000000..9d6c0c3225 Binary files /dev/null and b/audio/skill/mbbojian1.mp3 differ diff --git a/audio/skill/mbbojian2.mp3 b/audio/skill/mbbojian2.mp3 new file mode 100644 index 0000000000..ec4bab8cd1 Binary files /dev/null and b/audio/skill/mbbojian2.mp3 differ diff --git a/audio/skill/mbjiwei1.mp3 b/audio/skill/mbjiwei1.mp3 new file mode 100644 index 0000000000..3b102d3013 Binary files /dev/null and b/audio/skill/mbjiwei1.mp3 differ diff --git a/audio/skill/mbjiwei2.mp3 b/audio/skill/mbjiwei2.mp3 new file mode 100644 index 0000000000..b6799d2369 Binary files /dev/null and b/audio/skill/mbjiwei2.mp3 differ diff --git a/audio/skill/mbjiwei3.mp3 b/audio/skill/mbjiwei3.mp3 new file mode 100644 index 0000000000..f6b2c43c00 Binary files /dev/null and b/audio/skill/mbjiwei3.mp3 differ diff --git a/audio/skill/mbjiwei4.mp3 b/audio/skill/mbjiwei4.mp3 new file mode 100644 index 0000000000..be394675b9 Binary files /dev/null and b/audio/skill/mbjiwei4.mp3 differ diff --git a/audio/skill/mbquchong1.mp3 b/audio/skill/mbquchong1.mp3 new file mode 100644 index 0000000000..53ee200f53 Binary files /dev/null and b/audio/skill/mbquchong1.mp3 differ diff --git a/audio/skill/mbquchong2.mp3 b/audio/skill/mbquchong2.mp3 new file mode 100644 index 0000000000..0eba260d59 Binary files /dev/null and b/audio/skill/mbquchong2.mp3 differ diff --git a/audio/skill/mbquchong3.mp3 b/audio/skill/mbquchong3.mp3 new file mode 100644 index 0000000000..57368f5e9d Binary files /dev/null and b/audio/skill/mbquchong3.mp3 differ diff --git a/audio/skill/mbquchong4.mp3 b/audio/skill/mbquchong4.mp3 new file mode 100644 index 0000000000..5b9b13befc Binary files /dev/null and b/audio/skill/mbquchong4.mp3 differ diff --git a/audio/skill/mbxuetu_re_yangfeng1.mp3 b/audio/skill/mbxuetu3.mp3 similarity index 100% rename from audio/skill/mbxuetu_re_yangfeng1.mp3 rename to audio/skill/mbxuetu3.mp3 diff --git a/audio/skill/mbxuetu_re_yangfeng2.mp3 b/audio/skill/mbxuetu4.mp3 similarity index 100% rename from audio/skill/mbxuetu_re_yangfeng2.mp3 rename to audio/skill/mbxuetu4.mp3 diff --git a/audio/skill/mbxunjie1.mp3 b/audio/skill/mbxunjie1.mp3 new file mode 100644 index 0000000000..94f851732f Binary files /dev/null and b/audio/skill/mbxunjie1.mp3 differ diff --git a/audio/skill/mbxunjie2.mp3 b/audio/skill/mbxunjie2.mp3 new file mode 100644 index 0000000000..ed1fa6d862 Binary files /dev/null and b/audio/skill/mbxunjie2.mp3 differ diff --git a/audio/skill/olchishi1.mp3 b/audio/skill/olchishi1.mp3 new file mode 100644 index 0000000000..fc6b73568f Binary files /dev/null and b/audio/skill/olchishi1.mp3 differ diff --git a/audio/skill/olchishi2.mp3 b/audio/skill/olchishi2.mp3 new file mode 100644 index 0000000000..0e64c91b6d Binary files /dev/null and b/audio/skill/olchishi2.mp3 differ diff --git a/audio/skill/olningwu1.mp3 b/audio/skill/olninge1.mp3 similarity index 100% rename from audio/skill/olningwu1.mp3 rename to audio/skill/olninge1.mp3 diff --git a/audio/skill/olningwu2.mp3 b/audio/skill/olninge2.mp3 similarity index 100% rename from audio/skill/olningwu2.mp3 rename to audio/skill/olninge2.mp3 diff --git a/audio/skill/olqingliu1.mp3 b/audio/skill/olqingliu1.mp3 new file mode 100644 index 0000000000..f7b0ab751f Binary files /dev/null and b/audio/skill/olqingliu1.mp3 differ diff --git a/audio/skill/olqingliu2.mp3 b/audio/skill/olqingliu2.mp3 new file mode 100644 index 0000000000..c82183e8e5 Binary files /dev/null and b/audio/skill/olqingliu2.mp3 differ diff --git a/audio/skill/olweimian1.mp3 b/audio/skill/olweimian1.mp3 new file mode 100644 index 0000000000..1b10dc3561 Binary files /dev/null and b/audio/skill/olweimian1.mp3 differ diff --git a/audio/skill/olweimian2.mp3 b/audio/skill/olweimian2.mp3 new file mode 100644 index 0000000000..c879610dc4 Binary files /dev/null and b/audio/skill/olweimian2.mp3 differ diff --git a/audio/skill/olxuanhui1.mp3 b/audio/skill/olxuanhui1.mp3 new file mode 100644 index 0000000000..7dc1e06d2b Binary files /dev/null and b/audio/skill/olxuanhui1.mp3 differ diff --git a/audio/skill/olxuanhui2.mp3 b/audio/skill/olxuanhui2.mp3 new file mode 100644 index 0000000000..e67bdafb8e Binary files /dev/null and b/audio/skill/olxuanhui2.mp3 differ diff --git a/audio/skill/olyongzu1.mp3 b/audio/skill/olyongzu1.mp3 new file mode 100644 index 0000000000..fd373df65c Binary files /dev/null and b/audio/skill/olyongzu1.mp3 differ diff --git a/audio/skill/olyongzu2.mp3 b/audio/skill/olyongzu2.mp3 new file mode 100644 index 0000000000..5f750bcd85 Binary files /dev/null and b/audio/skill/olyongzu2.mp3 differ diff --git a/audio/skill/xinfu_qianchong2.mp3 b/audio/skill/qc_mingzhe.mp3 similarity index 100% rename from audio/skill/xinfu_qianchong2.mp3 rename to audio/skill/qc_mingzhe.mp3 diff --git a/audio/skill/qc_weimu.mp3 b/audio/skill/qc_weimu.mp3 new file mode 100644 index 0000000000..021d1bdf7c Binary files /dev/null and b/audio/skill/qc_weimu.mp3 differ diff --git a/audio/skill/qibie1.mp3 b/audio/skill/qibie1.mp3 index c8cf3cd9dc..3531954076 100644 Binary files a/audio/skill/qibie1.mp3 and b/audio/skill/qibie1.mp3 differ diff --git a/audio/skill/qibie2.mp3 b/audio/skill/qibie2.mp3 index 774bfc9334..06f555687f 100644 Binary files a/audio/skill/qibie2.mp3 and b/audio/skill/qibie2.mp3 differ diff --git a/audio/skill/rejianxiong_caoteng.mp3 b/audio/skill/rejianxiong_caoteng.mp3 new file mode 100644 index 0000000000..d950f71614 Binary files /dev/null and b/audio/skill/rejianxiong_caoteng.mp3 differ diff --git a/audio/skill/reshizhi1.mp3 b/audio/skill/reshizhi1.mp3 new file mode 100644 index 0000000000..716d5077cc Binary files /dev/null and b/audio/skill/reshizhi1.mp3 differ diff --git a/audio/skill/reshizhi2.mp3 b/audio/skill/reshizhi2.mp3 new file mode 100644 index 0000000000..1b88b80259 Binary files /dev/null and b/audio/skill/reshizhi2.mp3 differ diff --git a/audio/skill/sbduanliang_true1.mp3 b/audio/skill/sbduanliang2.mp3 similarity index 100% rename from audio/skill/sbduanliang_true1.mp3 rename to audio/skill/sbduanliang2.mp3 diff --git a/audio/skill/sbduanliang_true2.mp3 b/audio/skill/sbduanliang3.mp3 similarity index 100% rename from audio/skill/sbduanliang_true2.mp3 rename to audio/skill/sbduanliang3.mp3 diff --git a/audio/skill/sbduanliang_false.mp3 b/audio/skill/sbduanliang4.mp3 similarity index 100% rename from audio/skill/sbduanliang_false.mp3 rename to audio/skill/sbduanliang4.mp3 diff --git a/audio/skill/sbjiuyuan1.mp3 b/audio/skill/sbjiuyuan1.mp3 index fd854502fa..bf41620b53 100644 Binary files a/audio/skill/sbjiuyuan1.mp3 and b/audio/skill/sbjiuyuan1.mp3 differ diff --git a/audio/skill/sbjiuyuan2.mp3 b/audio/skill/sbjiuyuan2.mp3 index c1bc595c4c..fef339b2ac 100644 Binary files a/audio/skill/sbjiuyuan2.mp3 and b/audio/skill/sbjiuyuan2.mp3 differ diff --git a/audio/skill/sbluanwu_jiaxu1.mp3 b/audio/skill/sbluanwu_jiaxu1.mp3 new file mode 100644 index 0000000000..42d612c615 Binary files /dev/null and b/audio/skill/sbluanwu_jiaxu1.mp3 differ diff --git a/audio/skill/sbluanwu_jiaxu2.mp3 b/audio/skill/sbluanwu_jiaxu2.mp3 new file mode 100644 index 0000000000..feb768e654 Binary files /dev/null and b/audio/skill/sbluanwu_jiaxu2.mp3 differ diff --git a/audio/skill/sbluanwu_jiaxu3.mp3 b/audio/skill/sbluanwu_jiaxu3.mp3 new file mode 100644 index 0000000000..6995fb7f8a Binary files /dev/null and b/audio/skill/sbluanwu_jiaxu3.mp3 differ diff --git a/audio/skill/sbluanwu_jiaxu4.mp3 b/audio/skill/sbluanwu_jiaxu4.mp3 new file mode 100644 index 0000000000..963d503ffe Binary files /dev/null and b/audio/skill/sbluanwu_jiaxu4.mp3 differ diff --git a/audio/skill/sbtieji_true1.mp3 b/audio/skill/sbtieji2.mp3 similarity index 100% rename from audio/skill/sbtieji_true1.mp3 rename to audio/skill/sbtieji2.mp3 diff --git a/audio/skill/sbtieji_true2.mp3 b/audio/skill/sbtieji3.mp3 similarity index 100% rename from audio/skill/sbtieji_true2.mp3 rename to audio/skill/sbtieji3.mp3 diff --git a/audio/skill/sbtieji_false.mp3 b/audio/skill/sbtieji4.mp3 similarity index 100% rename from audio/skill/sbtieji_false.mp3 rename to audio/skill/sbtieji4.mp3 diff --git a/audio/skill/sbtongye1.mp3 b/audio/skill/sbtongye1.mp3 index 625ad5e763..987f77c157 100644 Binary files a/audio/skill/sbtongye1.mp3 and b/audio/skill/sbtongye1.mp3 differ diff --git a/audio/skill/sbtongye2.mp3 b/audio/skill/sbtongye2.mp3 index 4b063ed8f6..60557beee4 100644 Binary files a/audio/skill/sbtongye2.mp3 and b/audio/skill/sbtongye2.mp3 differ diff --git a/audio/skill/sbwansha1.mp3 b/audio/skill/sbwansha1.mp3 new file mode 100644 index 0000000000..b42d45e37d Binary files /dev/null and b/audio/skill/sbwansha1.mp3 differ diff --git a/audio/skill/sbwansha2.mp3 b/audio/skill/sbwansha2.mp3 new file mode 100644 index 0000000000..d8fe3841c0 Binary files /dev/null and b/audio/skill/sbwansha2.mp3 differ diff --git a/audio/skill/sbweimu1.mp3 b/audio/skill/sbweimu1.mp3 new file mode 100644 index 0000000000..d2952ca61b Binary files /dev/null and b/audio/skill/sbweimu1.mp3 differ diff --git a/audio/skill/sbweimu2.mp3 b/audio/skill/sbweimu2.mp3 new file mode 100644 index 0000000000..e8f08c4f4c Binary files /dev/null and b/audio/skill/sbweimu2.mp3 differ diff --git a/audio/skill/sbweimu3.mp3 b/audio/skill/sbweimu3.mp3 new file mode 100644 index 0000000000..2256c883dc Binary files /dev/null and b/audio/skill/sbweimu3.mp3 differ diff --git a/audio/skill/sbweimu4.mp3 b/audio/skill/sbweimu4.mp3 new file mode 100644 index 0000000000..3aedef787c Binary files /dev/null and b/audio/skill/sbweimu4.mp3 differ diff --git a/audio/skill/sbzhiheng1.mp3 b/audio/skill/sbzhiheng1.mp3 index 22cde35a39..8be79f284b 100644 Binary files a/audio/skill/sbzhiheng1.mp3 and b/audio/skill/sbzhiheng1.mp3 differ diff --git a/audio/skill/sbzhiheng2.mp3 b/audio/skill/sbzhiheng2.mp3 index 7c556a1cc9..c0db97fcf3 100644 Binary files a/audio/skill/sbzhiheng2.mp3 and b/audio/skill/sbzhiheng2.mp3 differ diff --git a/audio/skill/shizhi1.mp3 b/audio/skill/shizhi1.mp3 new file mode 100644 index 0000000000..1e1501ddf0 Binary files /dev/null and b/audio/skill/shizhi1.mp3 differ diff --git a/audio/skill/shizhi2.mp3 b/audio/skill/shizhi2.mp3 new file mode 100644 index 0000000000..33262af691 Binary files /dev/null and b/audio/skill/shizhi2.mp3 differ diff --git a/audio/skill/spdiancai1.mp3 b/audio/skill/spdiancai1.mp3 index 790b6ac009..2174201fa8 100644 Binary files a/audio/skill/spdiancai1.mp3 and b/audio/skill/spdiancai1.mp3 differ diff --git a/audio/skill/spdiancai2.mp3 b/audio/skill/spdiancai2.mp3 index 670e19be0d..8579e38208 100644 Binary files a/audio/skill/spdiancai2.mp3 and b/audio/skill/spdiancai2.mp3 differ diff --git a/audio/skill/spdiaodu1.mp3 b/audio/skill/spdiaodu1.mp3 index c942a6e35a..95c1f80c95 100644 Binary files a/audio/skill/spdiaodu1.mp3 and b/audio/skill/spdiaodu1.mp3 differ diff --git a/audio/skill/spdiaodu2.mp3 b/audio/skill/spdiaodu2.mp3 index d6aaff7944..333f8d7874 100644 Binary files a/audio/skill/spdiaodu2.mp3 and b/audio/skill/spdiaodu2.mp3 differ diff --git a/audio/skill/spyanji1.mp3 b/audio/skill/spyanji1.mp3 index 4f5f8bfb48..88fb7eadc0 100644 Binary files a/audio/skill/spyanji1.mp3 and b/audio/skill/spyanji1.mp3 differ diff --git a/audio/skill/spyanji2.mp3 b/audio/skill/spyanji2.mp3 index 1ec70c3c14..0d2788a689 100644 Binary files a/audio/skill/spyanji2.mp3 and b/audio/skill/spyanji2.mp3 differ diff --git a/audio/skill/spyanji3.mp3 b/audio/skill/spyanji3.mp3 index 465b0c8b9b..45ec8a5bfe 100644 Binary files a/audio/skill/spyanji3.mp3 and b/audio/skill/spyanji3.mp3 differ diff --git a/audio/skill/tianming_caoteng.mp3 b/audio/skill/tianming_caoteng.mp3 new file mode 100644 index 0000000000..6f04569499 Binary files /dev/null and b/audio/skill/tianming_caoteng.mp3 differ diff --git a/audio/skill/twlingyin1.mp3 b/audio/skill/twlingyin1.mp3 new file mode 100644 index 0000000000..0cfd4dd4bb Binary files /dev/null and b/audio/skill/twlingyin1.mp3 differ diff --git a/audio/skill/twlingyin2.mp3 b/audio/skill/twlingyin2.mp3 new file mode 100644 index 0000000000..941c55472b Binary files /dev/null and b/audio/skill/twlingyin2.mp3 differ diff --git a/audio/skill/twqinghan1.mp3 b/audio/skill/twqinghan1.mp3 new file mode 100644 index 0000000000..20d9e78879 Binary files /dev/null and b/audio/skill/twqinghan1.mp3 differ diff --git a/audio/skill/twqinghan2.mp3 b/audio/skill/twqinghan2.mp3 new file mode 100644 index 0000000000..8c621decc8 Binary files /dev/null and b/audio/skill/twqinghan2.mp3 differ diff --git a/audio/skill/twxianyuan1.mp3 b/audio/skill/twxianyuan1.mp3 new file mode 100644 index 0000000000..f1194cba9f Binary files /dev/null and b/audio/skill/twxianyuan1.mp3 differ diff --git a/audio/skill/twxianyuan2.mp3 b/audio/skill/twxianyuan2.mp3 new file mode 100644 index 0000000000..447a44d3b5 Binary files /dev/null and b/audio/skill/twxianyuan2.mp3 differ diff --git a/audio/skill/twxiayong1_tw_yanliang.mp3 b/audio/skill/twxiayong_tw_yanliang1.mp3 similarity index 100% rename from audio/skill/twxiayong1_tw_yanliang.mp3 rename to audio/skill/twxiayong_tw_yanliang1.mp3 diff --git a/audio/skill/twxiayong2_tw_yanliang.mp3 b/audio/skill/twxiayong_tw_yanliang2.mp3 similarity index 100% rename from audio/skill/twxiayong2_tw_yanliang.mp3 rename to audio/skill/twxiayong_tw_yanliang2.mp3 diff --git a/audio/skill/twzhihuan1.mp3 b/audio/skill/twzhihuan1.mp3 new file mode 100644 index 0000000000..6ed707f881 Binary files /dev/null and b/audio/skill/twzhihuan1.mp3 differ diff --git a/audio/skill/twzhihuan2.mp3 b/audio/skill/twzhihuan2.mp3 new file mode 100644 index 0000000000..7b9c4616bc Binary files /dev/null and b/audio/skill/twzhihuan2.mp3 differ diff --git a/audio/skill/xianfu2.mp3 b/audio/skill/xianfu2.mp3 index 215e43f0b7..237c3918e8 100644 Binary files a/audio/skill/xianfu2.mp3 and b/audio/skill/xianfu2.mp3 differ diff --git a/audio/skill/xianfu4.mp3 b/audio/skill/xianfu4.mp3 index 237c3918e8..04987f537b 100644 Binary files a/audio/skill/xianfu4.mp3 and b/audio/skill/xianfu4.mp3 differ diff --git a/audio/skill/xianfu6.mp3 b/audio/skill/xianfu6.mp3 index 04987f537b..215e43f0b7 100644 Binary files a/audio/skill/xianfu6.mp3 and b/audio/skill/xianfu6.mp3 differ diff --git a/audio/skill/xiaoxi_hansui1.mp3 b/audio/skill/xiaoxi_hansui1.mp3 index bc53933535..1dc8b9d04d 100644 Binary files a/audio/skill/xiaoxi_hansui1.mp3 and b/audio/skill/xiaoxi_hansui1.mp3 differ diff --git a/audio/skill/xiaoxi_hansui2.mp3 b/audio/skill/xiaoxi_hansui2.mp3 index fb88831a1a..944ac8a0bc 100644 Binary files a/audio/skill/xiaoxi_hansui2.mp3 and b/audio/skill/xiaoxi_hansui2.mp3 differ diff --git a/audio/skill/pcaudio_wolong_card.mp3 b/audio/skill/xinfu_pingcai2.mp3 old mode 100755 new mode 100644 similarity index 100% rename from audio/skill/pcaudio_wolong_card.mp3 rename to audio/skill/xinfu_pingcai2.mp3 diff --git a/audio/skill/pcaudio_fengchu_card.mp3 b/audio/skill/xinfu_pingcai3.mp3 old mode 100755 new mode 100644 similarity index 100% rename from audio/skill/pcaudio_fengchu_card.mp3 rename to audio/skill/xinfu_pingcai3.mp3 diff --git a/audio/skill/pcaudio_shuijing_card.mp3 b/audio/skill/xinfu_pingcai4.mp3 old mode 100755 new mode 100644 similarity index 100% rename from audio/skill/pcaudio_shuijing_card.mp3 rename to audio/skill/xinfu_pingcai4.mp3 diff --git a/audio/skill/pcaudio_xuanjian_card.mp3 b/audio/skill/xinfu_pingcai5.mp3 old mode 100755 new mode 100644 similarity index 100% rename from audio/skill/pcaudio_xuanjian_card.mp3 rename to audio/skill/xinfu_pingcai5.mp3 diff --git a/audio/skill/xinfu_qianchong1.mp3 b/audio/skill/xinfu_qianchong1.mp3 index 021d1bdf7c..c9db62cdb9 100644 Binary files a/audio/skill/xinfu_qianchong1.mp3 and b/audio/skill/xinfu_qianchong1.mp3 differ diff --git a/audio/skill/xinfu_qianchong3.mp3 b/audio/skill/xinfu_qianchong3.mp3 deleted file mode 100644 index c9db62cdb9..0000000000 Binary files a/audio/skill/xinfu_qianchong3.mp3 and /dev/null differ diff --git a/audio/skill/xinniluan1.mp3 b/audio/skill/xinniluan1.mp3 deleted file mode 100644 index 4975c2311e..0000000000 Binary files a/audio/skill/xinniluan1.mp3 and /dev/null differ diff --git a/audio/skill/xinniluan2.mp3 b/audio/skill/xinniluan2.mp3 deleted file mode 100644 index d9b971e77a..0000000000 Binary files a/audio/skill/xinniluan2.mp3 and /dev/null differ diff --git a/audio/skill/yaowu1.mp3 b/audio/skill/yaowu1.mp3 index 64eece5567..4b3d42ad4d 100644 Binary files a/audio/skill/yaowu1.mp3 and b/audio/skill/yaowu1.mp3 differ diff --git a/audio/skill/yaowu2.mp3 b/audio/skill/yaowu2.mp3 index 8d4136462a..c58090894f 100644 Binary files a/audio/skill/yaowu2.mp3 and b/audio/skill/yaowu2.mp3 differ diff --git a/audio/skill/yijiao1.mp3 b/audio/skill/yijiao1.mp3 index 7a527b170e..95d4b62c38 100644 Binary files a/audio/skill/yijiao1.mp3 and b/audio/skill/yijiao1.mp3 differ diff --git a/audio/skill/yijiao2.mp3 b/audio/skill/yijiao2.mp3 index 2989e842f5..80e7528228 100644 Binary files a/audio/skill/yijiao2.mp3 and b/audio/skill/yijiao2.mp3 differ diff --git a/card/extra.js b/card/extra.js index baedc81deb..be0927cc38 100644 --- a/card/extra.js +++ b/card/extra.js @@ -10,8 +10,8 @@ game.import("card", function () { subtype: "equip5", nomod: true, onEquip: function () { - if (card && card.cards && card.cards.length) { - player.directgains(card.cards, null, "muniu"); + if (card && card.storages?.length) { + player.directgains(card.storages, null, "muniu"); } player.markSkill("muniu_skill"); }, @@ -19,18 +19,18 @@ game.import("card", function () { onLose: function () { delete player.getStat("skill").muniu_skill; player.unmarkSkill("muniu_skill"); - if (!card || !card.cards || !card.cards.length) return; + if (!card || !card.storages || !card.storages.length) return; if ( - (!event.getParent(2) || event.getParent(2).name != "swapEquip") && + (!event.getParent(3) || event.getParent(3).name != "swapEquip") && (event.getParent().type != "equip" || event.getParent().swapEquip) ) { - player.lose(card.cards, ui.discardPile); - player.$throw(card.cards, 1000); + player.lose(card.storages, ui.discardPile); + player.$throw(card.storages, 1000); player.popup("muniu"); - game.log(card, "掉落了", card.cards); - card.cards.length = 0; + game.log(card, "掉落了", card.storages); + card.storages.length = 0; } else { - player.lose(card.cards, ui.special); + player.lose(card.storages, ui.special); } }, clearLose: true, @@ -39,7 +39,7 @@ game.import("card", function () { skills: ["muniu_skill", "muniu_skill7"], ai: { equipValue: function (card) { - if (card.card) return 7 + card.card.length; + if (card.storages) return 7 + card.storages.length; return 7; }, basic: { @@ -596,6 +596,27 @@ game.import("card", function () { }, basic: { equipValue: 5, + useful: (card, i) => { + let player = get.event().player, num; + if (player.isDamaged() && player.hp < 2 && get.recoverEffect(player, player, player) > 0) return -10; + num = player.hasSkillTag("filterDamage", null, { + card: new lib.element.VCard("sha"), + jiu: true + }, true) ? 0.6 : 1.2; + if ( + player.canAddJudge("shandian") && + get.effect(player, { name: "shandian" }, player, player) < 0 && + !player.hasSkillTag("rejudge") + ) { + if (game.hasPlayer(cur => cur.hasJudge("shandian"))) num += 2; + else num++; + } + num += game.countPlayer(cur => { + if (get.attitude(cur, player) <= 0) return cur.hasSkillTag("damageBonus"); + }); + if (player.isDamaged()) num /= player.getDamagedHp(); + return num; + } }, }, }, @@ -642,20 +663,20 @@ game.import("card", function () { if (game.online) { return; } - if (!muniu.cards) { - muniu.cards = []; + if (!muniu.storages) { + muniu.storages = []; } - for (var i = 0; i < muniu.cards.length; i++) { - if (get.position(muniu.cards[i]) != "s") { - muniu.cards.splice(i--, 1); + for (var i = 0; i < muniu.storages.length; i++) { + if (get.position(muniu.storages[i]) != "s") { + muniu.storages.splice(i--, 1); } } game.broadcast( function (muniu, cards) { - muniu.cards = cards; + muniu.storages = cards; }, muniu, - muniu.cards + muniu.storages ); }, filter: function (event, player) { @@ -678,7 +699,7 @@ game.import("card", function () { cards.splice(i--, 1); } } - var muniu = player.getEquip("muniu"); + var muniu = player.getVEquip("muniu"); if (!muniu || !cards.length) { for (var i = 0; i < cards.length; i++) { cards[i].discard(); @@ -686,18 +707,18 @@ game.import("card", function () { event.finish(); return; } - if (muniu.cards == undefined) muniu.cards = []; - muniu.cards.push(cards[0]); + if (muniu.storages == undefined) muniu.storages = []; + muniu.storages.push(cards[0]); game.broadcast( function (muniu, cards) { - muniu.cards = cards; + muniu.storages = cards; }, muniu, - muniu.cards + muniu.storages ); game.delayx(); "step 2"; - var muniu = player.getEquip("muniu"); + var muniu = player.getVEquip("muniu"); var players = game.filterPlayer(function (current) { if ( current.canEquip(muniu) && @@ -724,9 +745,9 @@ game.import("card", function () { next.set("choice", choice); "step 3"; if (result.bool) { - var card = player.getEquip("muniu"); + var card = player.getVEquip("muniu"); result.targets[0].equip(card); - player.$give(card, result.targets[0]); + player.$give(card.cards, result.targets[0]); player.line(result.targets, "green"); game.delay(); } else { @@ -743,11 +764,11 @@ game.import("card", function () { mod: { cardEnabled2: function (card, player) { if (!ui.selected.cards.length) return; - var muniu = player.getEquip("muniu"); - if (!muniu || !muniu.cards || !muniu.cards.length) return; + var muniu = player.getVEquip("muniu"); + if (!muniu || !muniu.storages || !muniu.storages.length) return; for (var i of ui.selected.cards) { - if (i == muniu && muniu.cards.includes(card)) return false; - if (muniu.cards.includes(i) && card == muniu) return false; + if (muniu.cards?.includes(i) && muniu.storages.includes(card)) return false; + if (muniu.storages.includes(i) && card == muniu) return false; } }, }, @@ -755,26 +776,26 @@ game.import("card", function () { markimage2: "image/card/muniu_small.png", intro: { content: function (storage, player) { - var muniu = player.getEquip("muniu"); - if (!muniu || !muniu.cards || !muniu.cards.length) return "共有零张牌"; + var muniu = player.getVEquip("muniu"); + if (!muniu || !muniu.storages || !muniu.storages.length) return "共有零张牌"; if (player.isUnderControl(true)) { - return get.translation(muniu.cards); + return get.translation(muniu.storages); } else { - return "共有" + get.cnNumber(muniu.cards.length) + "张牌"; + return "共有" + get.cnNumber(muniu.storages.length) + "张牌"; } }, mark: function (dialog, storage, player) { - var muniu = player.getEquip("muniu"); - if (!muniu || !muniu.cards || !muniu.cards.length) return "共有零张牌"; + var muniu = player.getVEquip("muniu"); + if (!muniu || !muniu.storages || !muniu.storages.length) return "共有零张牌"; if (player.isUnderControl(true)) { - dialog.addAuto(muniu.cards); + dialog.addAuto(muniu.storages); } else { - return "共有" + get.cnNumber(muniu.cards.length) + "张牌"; + return "共有" + get.cnNumber(muniu.storages.length) + "张牌"; } }, markcount: function (storage, player) { - var muniu = player.getEquip("muniu"); - if (muniu && muniu.cards) return muniu.cards.length; + var muniu = player.getVEquip("muniu"); + if (muniu && muniu.storages) return muniu.storages.length; return 0; }, }, @@ -786,18 +807,18 @@ game.import("card", function () { //silent:true, filter: function (event, player) { if (!event.ss || !event.ss.length || event.parent.name == "lose_muniu") return false; - var muniu = player.getEquip("muniu"); - if (!muniu || !muniu.cards) return false; + var muniu = player.getVEquip("muniu"); + if (!muniu || !muniu.storages) return false; return ( event.ss.filter(function (card) { - return muniu.cards.includes(card); + return muniu.storages.includes(card); }).length > 0 ); }, content: function () { - var muniu = player.getEquip("muniu"); - if (muniu && muniu.cards) { - muniu.cards.removeArray(trigger.ss); + var muniu = player.getVEquip("muniu"); + if (muniu && muniu.storages) { + muniu.storages.removeArray(trigger.ss); lib.skill.muniu_skill.sync(muniu); } player.updateMarks(); @@ -922,7 +943,7 @@ game.import("card", function () { }, ai: { effect: { - target_use(card, player, target, current) { + target(card, player, target, current) { if (target.hasSkillTag("unequip2")) return; if ( player.hasSkillTag("unequip", false, { @@ -937,12 +958,11 @@ game.import("card", function () { }) ) return; - //if(card.name=='nanman'||card.name=='wanjian'||card.name=='chuqibuyi') return 'zerotarget'; - if (card.name == "nanman" || card.name == "wanjian") return "zerotarget"; + if (card.name == "nanman" || card.name == "wanjian") return "zeroplayertarget"; if (card.name == "sha") { var equip1 = player.getEquip("zhuque"); if (equip1 && equip1.name == "zhuque") return 1.9; - if (!game.hasNature(card)) return "zerotarget"; + if (!game.hasNature(card)) return "zeroplayertarget"; } }, }, @@ -1045,17 +1065,19 @@ game.import("card", function () { ], }, filter: (event, player) => { - if (player.isHealthy() || player.hasSkillTag("unequip2")) return false; - var evt = event.getl(player); - return evt && evt.es.some((card) => card.name == "baiyin"); + return (player.isDamaged() && !player.hasSkillTag("unequip2")) }, - content: function () { - var evt = trigger.getl(player); + getIndex(event, player){ + const evt = event.getl(player); + const lostCards = []; evt.es.forEach((card) => { - if (card.name == "baiyin") { - player.recover(); - } + const VEquip = evt.vcard_map.get(card); + if(VEquip.name === "baiyin") lostCards.add(VEquip); }); + return lostCards.length; + }, + async content(event, trigger, player) { + await player.recover(); }, }, }, @@ -1094,15 +1116,14 @@ game.import("card", function () { }, audio: true, check: function (event, player) { - var eff = 0; - for (var i = 0; i < event.targets.length; i++) { - var target = event.targets[i]; - var eff1 = get.damageEffect(target, player, player); - var eff2 = get.damageEffect(target, player, player, "fire"); - eff += eff2; - eff -= eff1; + let eff = 0, nature = event.card.nature; + for (let i = 0; i < event.targets.length; i++) { + eff -= get.effect(event.targets[i], event.card, player, player); + event.card.nature = "fire"; + eff += get.effect(event.targets[i], event.card, player, player); + event.card.nature = nature; } - return eff >= 0; + return eff > 0; }, prompt2: function (event, player) { return "将" + get.translation(event.card) + "改为火属性"; diff --git a/card/guozhan.js b/card/guozhan.js index 98a91d709a..e881754e1b 100644 --- a/card/guozhan.js +++ b/card/guozhan.js @@ -463,20 +463,7 @@ game.import("card", function () { }, loseDelay: false, onLose: function () { - var next = game.createEvent("taipingyaoshu"); - event.next.remove(next); - var evt = event.getParent(); - if (evt.getlx === false) evt = evt.getParent(); - evt.after.push(next); - next.player = player; - next.setContent(lib.card.taipingyaoshu.onLosex); - }, - onLosex: function () { - "step 0"; - player.logSkill("taipingyaoshu"); - player.draw(2); - "step 1"; - if (player.hp > 1) player.loseHp(); + player.addTempSkill("taipingyaoshu_lose"); }, }, yuxi: { @@ -1476,7 +1463,7 @@ game.import("card", function () { }, ai: { effect: { - target_use(card, player, target, current) { + target(card, player, target, current) { if ( ["huoshaolianying", "huogong"].includes(card.name) || (card.name == "sha" && game.hasNature(card, "fire")) @@ -1838,11 +1825,45 @@ game.import("card", function () { return; if (get.tag(card, "natureDamage")) return "zeroplayertarget"; if (card.name == "tiesuo") { - return [0, 0]; + return 0.01; } }, }, }, + subSkill: { + lose: { + audio: "taipingyaoshu", + forced: true, + charlotte: true, + equipSkill: true, + trigger: { + player: "loseAfter", + global: [ + "equipAfter", + "addJudgeAfter", + "gainAfter", + "loseAsyncAfter", + "addToExpansionAfter", + ], + }, + filter: (event, player) => { + return !player.hasSkillTag("unequip2") + }, + getIndex(event, player){ + const evt = event.getl(player); + const lostCards = []; + evt.es.forEach((card) => { + const VEquip = evt.vcard_map.get(card); + if(VEquip.name === "taipingyaoshu") lostCards.add(VEquip); + }); + return lostCards.length; + }, + async content(event, trigger, player) { + await player.draw(2); + if (player.hp > 1) await player.loseHp(); + }, + }, + }, }, g_taipingyaoshu: {}, yuxi_skill: { diff --git a/card/gwent.js b/card/gwent.js index 7063b7095b..68c91e69b9 100644 --- a/card/gwent.js +++ b/card/gwent.js @@ -13,6 +13,7 @@ game.import("card", function () { cardimage: "gw_dieyi", type: "equip", subtype: "equip1", + //TODO: 维护所有水乎武将的onLose事件 onLose: function () { lib.skill.gw_dieyi.process(player); }, @@ -1960,7 +1961,7 @@ game.import("card", function () { nodamage: true, effect: { target: function (card, player, target, current) { - if (get.tag(card, "damage") && !get.tag(card, "natureDamage")) return [0, 0]; + if (get.tag(card, "damage") && !get.tag(card, "natureDamage")) return "zeroplayertarget"; }, }, }, @@ -2002,7 +2003,11 @@ game.import("card", function () { weather: true, effect: { player_use(card, player) { - if (!player.needsToDiscard()) return "zeroplayertarget"; + return [1, (player.needsToDiscard(0, (i, p) => { + if (p.canIgnoreHandcard(i)) return false; + if (i === card || card.cards && card.cards.includes(i)) return false; + return true; + }) ? -0.4 : -1)]; }, }, }, diff --git a/card/huanlekapai.js b/card/huanlekapai.js index 94360748e3..5d12ab7799 100644 --- a/card/huanlekapai.js +++ b/card/huanlekapai.js @@ -167,7 +167,7 @@ game.import("card", function () { noturnOver: true, effect: { target: function (card, player, target, current) { - if (get.tag(card, "turnOver")) return [0, 0]; + if (get.tag(card, "turnOver")) return "zeroplayertarget"; }, }, }, diff --git a/card/standard.js b/card/standard.js index 5e55c0a57b..0083a86e5f 100644 --- a/card/standard.js +++ b/card/standard.js @@ -383,7 +383,7 @@ game.import("card", function () { num = 1; if (isLink) { let cache = _status.event.getTempCache("sha_result", "eff"); - if (typeof cache !== "object" || cache.card !== get.translation(card)) + if (typeof cache !== "object" || cache.card !== ai.getCacheKey(card, true)) return eff; if (cache.odds < 1.35 && cache.bool) return 1.35 * cache.eff; return cache.odds * cache.eff; @@ -392,7 +392,7 @@ game.import("card", function () { player.hasSkill("jiu") || player.hasSkillTag("damageBonus", true, { target: target, - card: card, + card: card }) ) { if ( @@ -432,7 +432,7 @@ game.import("card", function () { ); _status.event.putTempCache("sha_result", "eff", { bool: target.hp > num && get.attitude(player, target) > 0, - card: get.translation(card), + card: ai.getCacheKey(card, true), eff: eff, odds: odds, }); @@ -778,6 +778,15 @@ game.import("card", function () { type: "equip", subtype: "equip3", distance: { globalTo: 1 }, + battleOfWancheng() { + //宛城之战 + const date = new Date(); + if (date.getMonth() != 6) return false; + let day = date.getDate(); + if (day == 5) return date.getHours() >= 8; + return day > 5 && day < 22; + }, + global: "jueying_wancheng" }, dilu: { fullskin: true, @@ -1059,8 +1068,16 @@ game.import("card", function () { return; } if (event.dialog.buttons.length > 1) { - var next = target.chooseButton(true, function (button) { - return get.value(button.link, _status.event.player); + var next = target.chooseButton(true); + next.set("ai", button => { + let player = _status.event.player, card = button.link, val = get.value(card, player); + if (get.tag(card, "recover")) { + val += game.countPlayer(target => { + return target.hp < 2 && get.attitude(player, target) > 0 && lib.filter.cardSavable(card, player, target); + }); + if (player.hp <= 2 && game.checkMod(card, player, "unchanged", "cardEnabled2", player)) val *= 2; + } + return val; }); next.set("dialog", event.preResult); next.set("closeDialog", false); @@ -1166,18 +1183,16 @@ game.import("card", function () { result: { target: function (player, target) { var sorter = _status.currentPhase || player; + let opt = 6 + 0.75 * (game.countPlayer() - 2 * get.distance(sorter, target, "absolute")); if (get.is.versus()) { - if (target == sorter) return 1.5; - return 1; + if (target !== sorter && get.attitude(player, player.next) < get.attitude(player, player.previous)) { + opt = 6 + 0.75 * (2 * get.distance(sorter, target, "absolute") - game.countPlayer()); + } } if (player.hasUnknown(2)) { return 0; } - return (1 - get.distance(sorter, target, "absolute") / game.countPlayer()) * - get.attitude(player, target) > - 0 - ? 0.5 - : 0.7; + return opt / 6; }, }, tag: { @@ -1420,15 +1435,6 @@ game.import("card", function () { result: { player(player, target) { if (player._nanman_temp || player.hasSkillTag("jueqing", false, target)) return 0; - player._nanman_temp = true; - let eff = get.effect( - target, - new lib.element.VCard({ name: "nanman" }), - player, - target - ); - delete player._nanman_temp; - if (eff >= 0) return 0; if ( target.hp > 2 || (target.hp > 1 && @@ -1438,6 +1444,15 @@ game.import("card", function () { target != game.falseZhu) ) return 0; + player._nanman_temp = true; + let eff = get.effect( + target, + new lib.element.VCard({ name: "nanman" }), + player, + target + ); + delete player._nanman_temp; + if (eff >= 0) return 0; if (target.hp > 1 && target.hasSkillTag("respondSha", true, "respond", true)) return 0; let known = target.getKnownCards(player); @@ -1714,15 +1729,6 @@ game.import("card", function () { player(player, target) { if (player._wanjian_temp || player.hasSkillTag("jueqing", false, target)) return 0; - player._wanjian_temp = true; - let eff = get.effect( - target, - new lib.element.VCard({ name: "wanjian" }), - player, - target - ); - delete player._wanjian_temp; - if (eff >= 0) return 0; if ( target.hp > 2 || (target.hp > 1 && @@ -1732,6 +1738,15 @@ game.import("card", function () { target != game.falseZhu) ) return 0; + player._wanjian_temp = true; + let eff = get.effect( + target, + new lib.element.VCard({ name: "wanjian" }), + player, + target + ); + delete player._wanjian_temp; + if (eff >= 0) return 0; if (target.hp > 1 && target.hasSkillTag("respondShan", true, "respond", true)) return 0; let known = target.getKnownCards(player); @@ -2007,13 +2022,13 @@ game.import("card", function () { }), "count" ); - if (ts < 1 && ts << 3 < Math.pow(player.hp, 2)) return 0; + if (ts < 1 && ts * 8 < Math.pow(player.hp, 2)) return 0; if (att > 0) { if (ts < 1) return 0; return -2; } - if (ts - ps + Math.exp(0.8 - player.hp) < 1) return -ts; if (pd >= 0) return pd / get.attitude(player, player); + if (ts - ps + Math.exp(0.8 - player.hp) < 1) return -ts; return -2 - ts; }, target(player, target, card) { @@ -2049,8 +2064,8 @@ game.import("card", function () { ); if (ts < 1) return -1.5; if (att > 0) return -2; - if (ts - ps < 1) return -2 - ts; if (pd >= 0) return -1; + if (ts - ps < 1) return -2 - ts; return -ts; }, }, @@ -2712,40 +2727,40 @@ game.import("card", function () { ); }, target: (player, target, card) => { - let targets = [].concat(ui.selected.targets); + let targets = ui.selected.targets.slice(); if (_status.event.preTarget) targets.add(_status.event.preTarget); if (targets.length) { - let preTarget = targets.lastItem, + let preTarget = targets.at(-1), pre = _status.event.getTempCache("jiedao_result", preTarget.playerid); - if (pre && pre.card === card && pre.target.isIn()) - return target === pre.target ? pre.eff : 0; + if (pre && pre.target && pre.target.isIn() && pre.card === ai.getCacheKey(card, true)) + return target === pre.target ? pre.res : 0; return ( - get.effect(target, { name: "sha" }, preTarget, player) / - get.attitude(player, target) + get.effect(target, { name: "sha" }, preTarget, target) / + get.attitude(target, target) * + preTarget.mayHaveSha(player, "use", null, "odds") ); } - let arms = - (target.hasSkillTag("noe") ? 0.32 : -0.15) * - target.getEquips(1).reduce((num, i) => { - return num + get.value(i, target); - }, 0); - if (!target.mayHaveSha(player, "use")) return arms; - let sha = game.filterPlayer(get.info({ name: "jiedao" }).filterAddedTarget), - addTar = null; - sha = sha.reduce((num, current) => { - let eff = get.effect(current, { name: "sha" }, target, player); - if (eff <= num) return num; - addTar = current; - return eff; - }, -100); - if (!addTar) return arms; - sha /= get.attitude(player, target); + let odds = target.mayHaveSha(player, "use", null, "odds"), + addTar = null, + sha = game.filterPlayer(cur => { + return get.info({ name: "jiedao" }).filterAddedTarget(null, player, cur, target); + }).reduce((num, current) => { + let eff = get.effect(current, { name: "sha" }, target, player); + if (eff < num) return num; + addTar = current; + return eff; + }, -Infinity); + if (addTar) sha = get.effect(addTar, { name: "sha" }, target, target) / 10; + let res = target.getEquips(1).reduce((num, i) => { + return num + get.value(i, target); + }, 0) / (target.hasSkillTag("noe") ? -2 : -4); + if (odds > 0.06 && sha > res) res += (sha - res) * odds; _status.event.putTempCache("jiedao_result", target.playerid, { - card: card, target: addTar, - eff: sha, + card: ai.getCacheKey(card, true), + res: res }); - return Math.max(arms, sha); + return res; }, }, tag: { @@ -3067,7 +3082,18 @@ game.import("card", function () { var target = event.player; var eff = get.damageEffect(target, player, player, event.nature); if (get.attitude(player, target) > 0) { - if (eff >= 0) return false; + if ( + eff >= 0 || + event.nature && + target.isLinked() && + game.hasPlayer(cur => { + return ( + cur !== target && + cur.isLinked() && + get.damageEffect(cur, player, player, event.nature) > 0 + ); + }) + ) return false; return true; } if (eff <= 0) return true; @@ -3138,7 +3164,7 @@ game.import("card", function () { }, ai: { effect: { - target_use(card, player, target) { + target(card, player, target) { if (typeof card !== "object" || target.hasSkillTag("unequip2")) return; if ( player.hasSkillTag("unequip", false, { @@ -3696,6 +3722,35 @@ game.import("card", function () { }, }, }, + jueying_wancheng: { + trigger: { + player: "damageBegin4" + }, + filter(event, player) { + return player.getEquips("jueying").length && lib.card.jueying.battleOfWancheng(); + }, + check(event, player) { + if (event.num <= 0) return false; + let eff = get.damageEffect(player, event.source, get.event().player, event.nature); + if ( + eff >= 0 || + event.source && + event.source.isIn() && + get.attitude(get.event().player, event.source) > 0 && + get.damageEffect(player, event.source, event.source, event.nature) > 0 + ) return false; + if (event.num >= player.hp + (event.source && event.source.hasSkillTag("jueqing", false, player) ? 0 : player.hujia)) return true; + return eff + player.getEquips("jueying").reduce((acc, i) => acc + get.value(i, player), 0) < 0; + }, + prompt: "是否发动〖绝影〗,将装备区内的【绝影】置入弃牌堆并防止此伤害?", + async content(event, trigger, player) { + var e3 = player.getEquips("jueying"); + if (e3.length) { + await player.loseToDiscardpile(e3); + } + trigger.cancel(); + }, + }, _wuxie: { trigger: { player: ["useCardToBegin", "phaseJudge"] }, priority: 5, @@ -4504,6 +4559,7 @@ game.import("card", function () { bagua_bg: "卦", bagua_skill: "八卦阵", jueying: "绝影", + jueying_wancheng: "绝影", dilu: "的卢", zhuahuang: "爪黄飞电", jueying_bg: "+马", @@ -4579,6 +4635,7 @@ game.import("card", function () { bagua_skill_info: "当你需要使用或打出一张【闪】时,你可以进行判定。若结果为红色,则你视为使用或打出一张【闪】。", jueying_info: "锁定技,其他角色计算与你的距离+1。", + jueying_append: '【绝影】于7月5日8时-7月21日24时位于装备区时,可以将【绝影】置入弃牌堆防止一次伤害。', dilu_info: "锁定技,其他角色计算与你的距离+1。", zhuahuang_info: "锁定技,其他角色计算与你的距离+1。", chitu_info: "锁定技,你计算与其他角色的距离-1。", diff --git a/card/swd.js b/card/swd.js index 8db3fad3d1..b4b37307b3 100644 --- a/card/swd.js +++ b/card/swd.js @@ -15,55 +15,6 @@ game.import("card", function () { useful: [7.5, 5, 2], }, }, - // yihuajiemu:{ - // fullskin:true, - // type:'trick', - // enable:true, - // singleCard:true, - // filterTarget:function(card,player,target){ - // if(target.isMin()) return false; - // if(ui.selected.targets.length){ - // return target.getCards('e',{subtype:'equip5'}).length==0; - // } - // else{ - // return target.getCards('e',{subtype:'equip5'}).length>0; - // } - // }, - // selectTarget:2, - // multitarget:true, - // complexTarget:true, - // multicheck:function(){ - // return game.hasPlayer(function(current){ - // return current.getEquip(5); - // })&&game.hasPlayer(function(current){ - // return !current.getEquip(5); - // }); - // }, - // content:function(){ - // if(target.getEquip(5)){ - // target.$give(target.getEquip(5),event.addedTarget); - // event.addedTarget.equip(target.getEquip(5)); - // game.delay(); - // } - // }, - // ai:{ - // order:1, - // result:{ - // target:function(player,target){ - // if(target.getCards('e',{subtype:'equip5'}).length){ - // if(get.attitude(target,player)>0){ - // return -0.5; - // } - // return -1; - // } - // return 1; - // } - // }, - // tag:{ - // loseCard:1 - // } - // } - // }, liuxinghuoyu: { fullskin: true, type: "trick", @@ -3447,65 +3398,6 @@ game.import("card", function () { trigger.player.chooseToDiscard(true, "he"); }, }, - shouhua: { - mode: ["identity", "infinity"], - enable: "phaseUse", - filter: function (event, player) { - return player == game.me; - }, - usable: 1, - filterTarget: function (card, player, target) { - return target != game.zhu && target != game.me && target.hp < target.maxHp; - }, - filterCard: true, - check: function (card) { - return get.value(card); - }, - discard: false, - prepare: "throw", - content: function () { - "step 0"; - target.$turn2(); - target.style.left = "calc(50% - 120px)"; - target.style.top = "calc(50% - 60px)"; - game.delay(0, 2500); - "step 1"; - target.removeAttribute("style"); - if ( - Math.random() < - ((get.value(cards[0]) + 1) * (target.maxHp - target.hp)) / (60 * target.maxHp) - ) { - event.position = target.dataset.position; - target.dataset.position = player.dataset.position; - target.delete(); - event.success = true; - } - game.delay(); - "step 2"; - if (event.success) { - player.popup("收化成功"); - game.log(player, "将", target, "收化"); - target.dataset.position = event.position; - var card = player.getEquip("lianyaohu"); - if (!card.storage.shouhua) card.storage.shouhua = []; - card.storage.shouhua.push(target); - game.removePlayer(target); - game.checkResult(); - } else { - player.popup("收化失败"); - target.gain(cards); - target.$gain2(cards); - } - game.delay(); - }, - ai: { - result: { - player: function () { - return Math.random() - 0.4; - }, - }, - }, - }, haotianta: { trigger: { global: "judgeBefore" }, direct: true, @@ -5214,8 +5106,6 @@ game.import("card", function () { g_hufu_shan: "符闪", g_hufu_jiu: "符酒", hufu_info: "你可以将一张玉符当作杀、闪或酒使用或打出。", - // yihuajiemu:'移花接木', - // yihuajiemu_info:'对一名装备区内有宝物的角色使用,将其宝物牌转移至另一名角色。', liuxinghuoyu: "流星火羽", liuxinghuoyu_info: "出牌阶段,对一名角色使用,令目标弃置两张牌,或受到1点火焰伤害。", g_yuchan_equip: "玉蝉", @@ -5642,9 +5532,6 @@ game.import("card", function () { ["heart", 1, "hufu"], ["spade", 1, "hufu"], ["club", 1, "qiankundai"], - // ['heart',3,'yihuajiemu'], - // ['diamond',1,'yihuajiemu'], - // ['diamond',7,'yihuajiemu'], ["diamond", 3, "liuxinghuoyu", "fire"], ["heart", 6, "liuxinghuoyu", "fire"], diff --git a/card/xianxia.js b/card/xianxia.js new file mode 100644 index 0000000000..2bdb57f0b1 --- /dev/null +++ b/card/xianxia.js @@ -0,0 +1,576 @@ +import { lib, game, ui, get, ai, _status } from "../noname.js"; +game.import("card", function () { + return { + name: "xianxia", + card: { + tiejili: { + fullskin: true, + derivation: "ty_shamoke", + type: "equip", + subtype: "equip1", + distance: { + attackRange(card, player) { + return player.storage.tiejili_skill || 2; + }, + attackFrom: -1, + }, + ai: { + basic: { + equipValue: 2, + }, + }, + skills: ["tiejili_skill"], + onLose() { + delete player.storage.tiejili_skill; + player.unmarkSkill("tiejili_skill"); + }, + onEquip() { + if (!card.storage.tiejili_skill) card.storage.tiejili_skill = 2; + player.storage.tiejili_skill = card.storage.tiejili_skill; + player.markSkill("tiejili_skill"); + }, + }, + lx_huoshaolianying: { + audio: true, + fullskin: true, + type: "trick", + derivation: "ty_luxun", + cardimage: "huoshaolianying", + enable: true, + filterTarget(card, player, target) { + return target.countCards("he") > 0; + }, + async content(event, trigger, player) { + const target = event.target; + if (target.countCards("he") == 0) return; + let result; + if (target.countCards("he") == 1) result = { bool: true, cards: target.getCards("he") }; + else { + result = await player + .choosePlayerCard(target, true, "he") + .set("ai", function (card) { + if (_status.event.getRand() < 0.5) return Math.random(); + return get.value(card); + }) + .forResult(); + } + if (!result || !result.bool) return; + await target.showCards(result.cards).setContent(function () { }); + event.dialog = ui.create.dialog(get.translation(target) + "展示的手牌", result.cards); + event.videoId = lib.status.videoId++; + + game.broadcast( + "createDialog", + event.videoId, + get.translation(target) + "展示的手牌", + result.cards + ); + game.addVideo("cardDialog", null, [ + get.translation(target) + "展示的手牌", + get.cardsInfo(result.cards), + event.videoId, + ]); + game.log(target, "展示了", result.cards); + game.addCardKnower(result.cards, "everyone"); + const result2 = await player + .chooseToDiscard({ suit: get.suit(result.cards[0]) }, function (card) { + var evt = _status.event.getParent(); + if (get.damageEffect(evt.target, evt.player, evt.player, "fire") > 0) { + return 6.2 + Math.min(4, evt.player.hp) - get.value(card, evt.player); + } + return -1; + }) + .set("prompt", false) + .forResult(); + await game.delay(); + if (result2.bool) { + await target.discard(result.cards); + await target.damage("fire"); + if (target.isLinked() && event.cards?.someInD()) await player.gain(event.cards.filterInD(), "gain2"); + } + else target.addTempSkill("huogong2"); + event.dialog.close(); + game.addVideo("cardDialog", null, event.videoId); + game.broadcast("closeDialog", event.videoId); + }, + ai: { + basic: { + order: 9.2, + value: [3, 1], + useful: 0.6, + }, + wuxie(target, card, player, viewer, status) { + if (get.attitude(viewer, player._trueMe || player) > 0) return 0; + if ( + status * + get.attitude(viewer, target) * + get.effect(target, card, player, target) >= + 0 + ) + return 0; + if (_status.event.getRand("huogong_wuxie") * 4 > player.countCards("h")) return 0; + }, + result: { + player(player) { + var nh = player.countCards("h"); + if (nh <= player.hp && nh <= 4 && _status.event.name == "chooseToUse") { + if ( + typeof _status.event.filterCard == "function" && + _status.event.filterCard( + new lib.element.VCard({ name: "lx_huoshaolianying" }), + player, + _status.event + ) + ) { + return -10; + } + if (_status.event.skill) { + var viewAs = get.info(_status.event.skill).viewAs; + if (viewAs == "lx_huoshaolianying") return -10; + if (viewAs && viewAs.name == "huogong") return -10; + } + } + return 0; + }, + target(player, target) { + if (target.hasSkill("huogong2") || target.countCards("h") == 0) return 0; + if (player.countCards("h") <= 1) return 0; + if (_status.event.player == player) { + if (target.isAllCardsKnown(player)) { + if ( + !target.countCards("h", (card) => { + return player.countCards("h", (card2) => { + return get.suit(card2) == get.suit(card); + }); + }) + ) { + return 0; + } + } + } + if (target == player) { + if ( + typeof _status.event.filterCard == "function" && + _status.event.filterCard( + new lib.element.VCard({ name: "lx_huoshaolianying" }), + player, + _status.event + ) + ) { + return -1.15; + } + if (_status.event.skill) { + var viewAs = get.info(_status.event.skill).viewAs; + if (viewAs == "lx_huoshaolianying") return -1.15; + if (viewAs && viewAs.name == "lx_huoshaolianying") return -1.15; + } + return 0; + } + return -1.15; + }, + }, + tag: { + damage: 1, + fireDamage: 1, + natureDamage: 1, + norepeat: 1, + }, + }, + }, + suibozhuliu: { + audio: true, + fullskin: true, + type: "delay", + modTarget(card, player, target) { + return lib.filter.judge(card, player, target); + }, + enable(card, player) { + return player.canAddJudge(card); + }, + filterTarget(card, player, target) { + return lib.filter.judge(card, player, target) && player == target; + }, + selectTarget: [-1, -1], + toself: true, + judge(card) { + if (get.suit(card) == "diamond") return -2; + return 1; + }, + judge2(result) { + if (result.bool == false) return true; + return false; + }, + effect() { + "step 0" + if (result.bool == false && player.countCards("e")) { + player + .choosePlayerCard("e", player, true) + .set("filterButton", button => { + let player = get.player(), + filter = (card) => ["equip3", "equip4", "equip6"].includes(get.subtype(card)); + if (player.countCards("e", card => filter(card))) return filter(button.link); + return true; + }) + .set("ai", button => { + let player = get.player(), + att = get.attitude(player, player.getNext()); + if (att > 0) return player.getNext().getUseValue(button.link) - player.getUseValue(button.link); + return 6 - get.value(button.link); + }); + + } + else event.goto(2); + "step 1" + if (result.cards) { + let target = player.getNext(), card = result.cards[0]; + if (target.canEquip(card)) { + target.equip(card); + player.$give(card, target); + } + else player.give(card, target); + } + "step 2" + player.addJudgeNext(event.card); + }, + cancel() { + player.addJudgeNext(card); + }, + ai: { + basic: { + order: 1, + value: 1, + useful: 1, + }, + result: { + target(player, target) { + var num = game.countPlayer(function (current) { + for (var j = 0; j < current.skills.length; j++) { + var rejudge = get.tag(current.skills[j], "rejudge", current); + if (rejudge != undefined) { + if ( + get.attitude(target, current) > 0 && + get.attitude(current, target) > 0 + ) { + return rejudge; + } else { + return -rejudge; + } + } + } + }); + if (num > 0) return num; + return 1; + }, + }, + }, + }, + ty_feilongduofeng: { + fullskin: true, + type: "equip", + subtype: "equip1", + distance: { attackFrom: -1 }, + ai: { + basic: { + equipValue: 2, + }, + }, + skills: ["ty_feilongduofeng_skill"], + }, + shangfangbaojian: { + fullskin: true, + type: "equip", + subtype: "equip1", + distance: { attackFrom: -1 }, + ai: { + basic: { + equipValue: 2, + }, + }, + skills: ["shangfangbaojian_skill"], + }, + qingmingjian: { + fullskin: true, + type: "equip", + subtype: "equip1", + distance: { attackFrom: -2 }, + ai: { + basic: { + equipValue: 2, + }, + }, + skills: ["qingmingjian_skill"], + }, + mengchong: { + audio: true, + fullskin: true, + type: "equip", + subtype: "equip6", + subtypes: ["equip3", "equip4"], + nomod: true, + nopower: true, + skills: ["mengchong_skill"], + onLose() { + delete player.storage.mengchong_skill; + player.unmarkSkill("mengchong_skill"); + }, + ai: { + equipValue: function (card, player) { + if (player.countCards("e", { subtype: ["equip3", "equip4"] }) > 1) return 1; + return 7.2; + }, + basic: { + equipValue: 7.2, + }, + }, + }, + }, + skill: { + //12345 + tiejili_skill: { + trigger: { + player: "phaseZhunbeiBegin", + }, + equipSkill: true, + intro: { + content(storage, player) { + return "此牌攻击范围为" + (storage || 2); + }, + }, + check(event, player) { + if (player.hasSkill("gzjili")) return player.hp > 2 && player.hp < 5; + return player.storage.tiejili_skill < player.hp; + }, + onremove: true, + filter(event, player) { + return player.storage.tiejili_skill != player.hp; + }, + async content(event, trigger, player) { + player.storage.tiejili_skill = player.hp; + player.markSkill(event.name); + }, + }, + ty_feilongduofeng_skill: { + equipSkill: true, + trigger: { player: "useCardToPlayered" }, + audio: true, + usable: 1, + logTarget: "target", + filter: function (event, player) { + if (event.card.name != "sha") return false; + return true; + }, + async cost(event, trigger, player) { + let choice = ["选项一"]; + if (trigger.target.countCards("he")) choice.push("选项二"); + choice.push("cancel2"); + const result = await player + .chooseControl(choice) + .set("prompt", get.prompt(event.name.slice(0, -5), trigger.target)) + .set("choiceList", [ + "摸一张牌", + "令其弃置一张牌", + ]) + .set("res", function () { + if (get.attitude(player, trigger.target) > 0 || trigger.target.hasSkillTag("noh")) return "选项一"; + return choice[choice.length - 2]; + }()) + .set("ai", () => get.event("res")) + .forResult(); + event.result = { + bool: result.control != "cancel2", + targets: [trigger.target], + cost_data: result.control, + }; + }, + async content(event, trigger, player) { + const result = event.cost_data; + if (result == "选项一") await player.draw(); + else { + await trigger.target.chooseToDiscard("弃置一张牌", "he", true); + } + }, + }, + shangfangbaojian_skill: { + equipSkill: true, + trigger: { global: "useCardToPlayered" }, + audio: true, + logTarget: "target", + filter: function (event, player) { + if (event.card.name != "sha") return false; + if (event.player.countCards("h") + player.countCards("h") == 0) return false; + return event.player.group == player.group && event.player != player; + }, + async cost(event, trigger, player) { + let choice = []; + if (player.countCards("h")) choice.push("交给其一张手牌"); + if (trigger.player.countCards("h")) choice.push("获得其一张手牌"); + choice.push("cancel2"); + const result = await player + .chooseControl(choice) + .set("prompt", get.prompt2(event.name.slice(0, -5), trigger.player)) + .set("res", function () { + if (get.attitude(player, trigger.player) <= 0 && trigger.player.countCards("h")) return "获得其一张手牌"; + if (player.countCards("h") >= trigger.player.countCards("h") || player.hasSkill("tyxibei")) return "交给其一张手牌"; + return "获得其一张手牌"; + }()) + .set("ai", () => get.event("res")) + .forResult(); + event.result = { + bool: result.control != "cancel2", + targets: [trigger.player], + cost_data: result.control, + }; + }, + async content(event, trigger, player) { + const result = event.cost_data; + if (result == "交给其一张手牌") await player.chooseToGive(event.targets[0], true, 1, "h"); + else { + await player.gainPlayerCard(event.targets[0], true, 1, "h"); + } + }, + group: "shangfangbaojian_skill_discard", + subSkill: { + discard: { + equipSkill: true, + trigger: { + player: "loseBefore", + }, + forced: true, + filter(event, player) { + if (event.type != "discard") return false; + var cards = player.getEquips("shangfangbaojian"); + return event.cards.some(card => cards.includes(card)); + }, + content() { + trigger.cards.removeArray(player.getEquips("shangfangbaojian")); + }, + }, + }, + }, + qingmingjian_skill: { + equipSkill: true, + trigger: { + player: "loseAfter", + global: "loseAsyncAfter", + }, + filter(event, player) { + if (event.type != "discard" || player != _status.currentPhase) return false; + if (player.getHistory("lose", evt => evt.type == "discard").indexOf(event) != 0) return false; + var evt = event.getl(player); + return evt?.cards2?.length > 1; + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2(event.name.slice(0, -5)), lib.filter.notMe) + .set("ai", target => { + return get.damageEffect(target, get.player(), get.player()) + }) + .forResult(); + }, + async content(event, trigger, player) { + await event.targets[0].damage(); + }, + }, + mengchong_skill: { + trigger:{ + player:"useCardAfter", + }, + locked:true, + async cost(event,trigger,player){ + if(!player.storage.mengchong_skill) player.storage.mengchong_skill=0; + let num=player.storage.mengchong_skill; + const result=await player + .chooseControl("+1","-1") + .set("prompt",`艨艟:请修改与其他角色计算距离(当前:${num>0?"+":""}${num})`) + .set("ai",()=>{ + const player=get.player(); + const num=player.countCards(card=>{ + return player.hasUseTarget(card,true,true)&&player.hasUseValue(card,true,true); + }); + return num>2?"-1":"+1"; + }) + .forResult(); + event.result={ + bool:true, + cost_data:result.index, + } + }, + async content(event,trigger,player){ + if(event.cost_data==1&&player.storage.mengchong_skill>-2) player.storage.mengchong_skill--; + if(event.cost_data==0&&player.storage.mengchong_skill<2) player.storage.mengchong_skill++; + player.markSkill(event.name); + }, + intro:{ + content(storage){ + if(!storage) return "无距离变化"; + return "与其他角色互相计算距离"+(storage>0?"+":"")+storage; + }, + }, + equipSkill:true, + mod: { + globalFrom(from,to,distance){ + const num=from.storage.mengchong_skill; + return distance+num; + }, + globalTo(from,to,distance){ + const num=to.storage.mengchong_skill; + return distance+num; + }, + canBeReplaced: function (card, player) { + if (player.getEquips("mengchong").includes(card)) return false; + }, + }, + group:"mengchong_skill_clear", + subSkill:{ + clear:{ + equipSkill:true, + forced:true, + direct:true, + trigger:{ + player:"phaseBegin", + }, + content:function(){ + player.storage.mengchong_skill=0; + player.unmarkSkill("mengchong_skill"); + }, + }, + }, + }, + }, + translate: { + tiejili: "铁蒺藜骨朵", + tiejili_info: "准备阶段,你可以将此牌本回合的攻击范围改为x,直到此牌离开你的装备区(x为你的体力值)。", + tiejili_skill: "铁蒺藜骨朵", + tiejili_skill_info: "准备阶段,你可以将此牌本回合的攻击范围改为x,直到此牌离开你的装备区(x为你的体力值)。", + lx_huoshaolianying: "火烧连营", + lx_huoshaolianying_info: "出牌阶段,对一名角色使用。你展示目标角色的一张牌,然后你可以弃置一张与展示的牌花色相同的手牌。若如此做,你弃置其被展示的牌并对其造成一点火焰伤害,然后若其处于横置状态,你获得弃置堆中的此牌。", + suibozhuliu: "随波逐流", + suibozhuliu_info: "出牌阶段,对你自己使用,你将此牌置于判定区。判定阶段,你进行判断,若结果为♦️,你将一张装备牌移动至下家的装备区里(若你的装备区里有坐骑牌,则你须选择其中一张坐骑牌),若无法移动则改为下家获得此装备牌。判定结束后,你将判定区里的此牌置于下家的判定区。", + ty_feilongduofeng: "飞龙夺凤", + ty_feilongduofeng_info: "每回合限一次,当你使用【杀】指定一个目标后,你可以选择一项:1.摸一张牌;2.令其弃置一张牌。", + ty_feilongduofeng_skill: "飞龙夺凤", + ty_feilongduofeng_skill_info: "每回合限一次,当你使用【杀】指定一个目标后,你可以选择一项:1.摸一张牌;2.令其弃置一张牌。", + shangfangbaojian: "尚方宝剑", + shangfangbaojian_info: "当装备区里的此牌被弃置时,你防止之。与你势力相同的角色使用【杀】指定目标后,你可以选择一项:1:交给其一张手牌;2:获得其一张手牌。", + shangfangbaojian_skill: "尚方宝剑", + shangfangbaojian_skill_info: "与你势力相同的角色使用【杀】指定目标后,你可以选择一项:1:交给其一张手牌;2:获得其一张手牌。", + qingmingjian: "青冥剑", + qingmingjian_info: "当你于回合内首次弃置至少两张牌时,你可以对一名其他角色造成一点伤害 。", + qingmingjian_skill: "青冥剑", + qingmingjian_skill_info: "当你于回合内首次弃置至少两张牌时,你可以对一名其他角色造成一点伤害 。", + mengchong: "艨艟", + mengchong_info: "锁定技,当你使用牌结算结束后,你选择与其他角色互相计算距离+1或-1直到你的下个回合开始(至多+2/-2)。", + mengchong_skill: "艨艟", + mengchong_skill_info: "锁定技,当你使用牌结算结束后,你选择与其他角色互相计算距离+1或-1直到你的下个回合开始(至多+2/-2)。", + }, + list: [ + ["diamond", 6, "suibozhuliu"], + ["diamond", 9, "suibozhuliu"], + ["spade", 2, "ty_feilongduofeng"], + ["heart", 3, "lx_huoshaolianying"], + ["spade", 5, "shangfangbaojian"], + ["spade", 5, "qingmingjian"], + ["club", 5, "mengchong"], + ], + }; +}); diff --git a/card/yingbian.js b/card/yingbian.js index 52ea6f60f1..ef8bf909d9 100644 --- a/card/yingbian.js +++ b/card/yingbian.js @@ -485,10 +485,16 @@ game.import("card", function () { trigger: { player: "equipAfter" }, forced: true, equipSkill: true, - filter: (event, player) => - event.card.name == "tianjitu" && player.hasCard((card) => card != event.card, "he"), + getIndex(event, player){ + return event.vcards.filter(card => card.name === "tianjitu").length; + }, + filter: (event, player) => { + return player.hasCard(card => { + return !event.cards.includes(card) && lib.filter.cardDiscardable(card, player, "tianjitu_skill"); + }, "he") + }, content: () => { - player.chooseToDiscard(true, (card) => card != _status.event.getTrigger().card, "he"); + player.chooseToDiscard(true, (card) => !get.event().getTrigger().cards?.includes(card), "he"); }, subSkill: { lose: { @@ -507,9 +513,16 @@ game.import("card", function () { ], }, filter: (event, player) => { - if (player.countCards("h") >= 5) return false; - var evt = event.getl(player); - return evt && evt.es.some((card) => card.name == "tianjitu"); + return (player.countCards("h") < 5); + }, + getIndex(event, player){ + const evt = event.getl(player); + const lostCards = []; + evt.es.forEach((card) => { + const VEquip = evt.vcard_map.get(card); + if(VEquip.name === "tianjitu") lostCards.add(VEquip); + }); + return lostCards.length; }, content: function () { player.drawTo(5); @@ -750,7 +763,7 @@ game.import("card", function () { heiguangkai_ai: { ai: { effect: { - player_use(card, player, target) { + player(card, player, target) { if ( typeof card !== "object" || !target || diff --git a/card/yongjian.js b/card/yongjian.js index 89f1c7e116..2d323e3363 100644 --- a/card/yongjian.js +++ b/card/yongjian.js @@ -509,24 +509,25 @@ game.import("card", function () { }, }, qixingbaodao: { - trigger: { player: "equipBegin" }, + trigger: { player: "equipAfter" }, forced: true, equipSkill: true, - filter: function (event, player) { - return ( - event.card.name == "qixingbaodao" && - player.hasCard(function (card) { - return card != event.card; - }, "ej") - ); + filter(event, player){ + const baodaos = player.getVCards("e").filter(card => { + return card.name == "qixingbaodao"; + }); + return baodaos.length > 0 && player.hasCard(card => { + return !baodaos.some(baodao => baodao.cards?.includes(card)) && lib.filter.cardDiscardable(card, player, "qixingbaodao"); + }, "ej"); }, - content: function () { - var cards = player.getCards("ej", function (card) { - return ( - card != trigger.card && lib.filter.cardDiscardable(card, player, "qixingbaodao") - ); + async content(event, trigger, player) { + const baodaos = player.getVCards("e").filter(card => { + return card.name == "qixingbaodao"; + }); + const cards = player.getCards("ej", card => { + return !baodaos.some(baodao => baodao.cards?.includes(card)) && lib.filter.cardDiscardable(card, player, "qixingbaodao"); }); - if (cards.length) player.discard(cards); + if (cards.length > 0) await player.discard(cards); }, }, g_du: { @@ -738,6 +739,7 @@ game.import("card", function () { if (!player.needsToDiscard() && get.position(card) == "h") return 0; return 1 + Math.random(); }, + prompt: "出牌阶段,你可将一张拥有“赠”标签的手牌区装备牌置于一名其他角色的装备区内,或将一张拥有“赠”标签的手牌区非装备牌正面朝上交给一名其他角色。", content: () => { player.gift(cards, target); }, @@ -839,7 +841,7 @@ game.import("card", function () { yitianjian_info: "当你因执行【杀】的效果而造成伤害后,若你已受伤,则你可弃置一张手牌,然后回复1点体力。", qixingbaodao: "七星宝刀", - qixingbaodao_info: "锁定技。当此牌进入你的装备区时,你弃置装备区和判定区内的所有其他牌。", + qixingbaodao_info: "锁定技。当此牌进入你的装备区后,你弃置装备区和判定区内的所有其他牌。", duanjian: "断剑", duanjian_info: "这是一把坏掉的武器……", duanjian_append: '不要因为手快而装给自己。', @@ -861,8 +863,6 @@ game.import("card", function () { xinge_append: '咕咕咕。', _gifting: "赠予", - _gifting_info: - "出牌阶段,你可将一张拥有“赠”标签的手牌区装备牌置于一名其他角色的装备区内,或将一张拥有“赠”标签的手牌区非装备牌正面朝上交给一名其他角色。", }, list: [ ["spade", 1, "guaguliaodu"], diff --git a/card/yunchou.js b/card/yunchou.js index 4c9799cfcc..b4aa1992d8 100644 --- a/card/yunchou.js +++ b/card/yunchou.js @@ -151,7 +151,9 @@ game.import("card", function () { value: [5, 1], }, result: { - player: 1, + player: (player, target) => { + return 1 / game.countPlayer(); + }, target: function (player, target) { if (target.countCards("h") == 0) return 0; return ( diff --git a/character/clan/characterReplace.js b/character/clan/characterReplace.js index 9dc1723d51..a0d8490cb6 100644 --- a/character/clan/characterReplace.js +++ b/character/clan/characterReplace.js @@ -1,5 +1,5 @@ const characterReplaces = { - wuban: ["clan_wuban", "dc_wuban", "wuban", "xin_wuban"], + wuban: ["clan_wuban", "dc_wuban", "wuban", "xin_wuban", "ty_wuban"], }; export default characterReplaces; diff --git a/character/clan/skill.js b/character/clan/skill.js index 2003c6b634..c33f4a7cbd 100644 --- a/character/clan/skill.js +++ b/character/clan/skill.js @@ -270,7 +270,7 @@ const skills = { async content(event, trigger, player) { const target = event.targets[0]; await target.damage(); - await game.asyncDelayx(); + await game.delayx(); }, mod: { aiOrder(player, card, num) { @@ -294,6 +294,44 @@ const skills = { } }, }, + group: "clantanque_mark", + init(player) { + var history = player.getAllHistory("useCard"); + if (history.length) { + var trigger = history[history.length - 1]; + if (typeof get.number(trigger.card, player) != "number") return; + player.storage.clantanque_mark = trigger.card; + player.markSkill("clantanque_mark"); + } + }, + onremove(player) { + player.unmarkSkill("clantanque_mark"); + delete player.storage.clantanque_mark; + }, + subSkill: { + mark: { + charlotte: true, + trigger: { player: "useCard1" }, + forced: true, + popup: false, + firstDo: true, + content() { + if (typeof get.number(trigger.card, player) != "number") player.unmarkSkill("clantanque_mark"); + else { + player.storage.clantanque_mark = trigger.card; + player.markSkill("clantanque_mark"); + } + }, + intro: { + markcount(card, player) { + return get.strNumber(get.number(card, player)); + }, + content(card, player) { + return "上一张牌的点数:" + get.strNumber(get.number(card, player)); + }, + }, + }, + }, }, clanshengmo: { audio: 2, @@ -480,7 +518,7 @@ const skills = { if (bool) { const card = links[0]; player.$gain2(card, false); - await game.asyncDelayx(); + await game.delayx(); await player.chooseUseTarget(true, card, false); } } @@ -773,7 +811,7 @@ const skills = { result: { target(player, target) { var cards = player.getCards("hs", card => { - if (get.name(card, player) != "sha" && get.type(card, player) != "trick") return false; + if (get.name(card, player) != "sha" && get.type(card, null, player) != "trick") return false; return player.hasValueTarget(card); }); if (cards.some(card => player.canUse(card, target) && get.effect(target, card, player, player) > 0)) { @@ -835,9 +873,7 @@ const skills = { var target = event.targets.shift(); event.target = target; var list = []; - const nameFilter = trigger.card.name == "sha" - ? name => get.type(name) == "trick" - : name => name == "sha"; + const nameFilter = trigger.card.name == "sha" ? name => get.type(name) == "trick" : name => name == "sha"; for (var name of lib.inpile) { if (name != "sha" && get.type(name) != "trick") continue; if (!nameFilter(name)) continue; @@ -1008,7 +1044,7 @@ const skills = { if (player.getHistory("useSkill", evt => evt.skill == "clanhuanghan").length > 1 && player.hasSkill("clanbaozu", null, false, false) && player.awakenedSkills.includes("clanbaozu")) { player.restoreSkill("clanbaozu"); player.popup("保族"); - game.log(player, "恢复了技能", "#【保族】"); + game.log(player, "恢复了技能", "#g【保族】"); } }, ai: { @@ -1017,7 +1053,7 @@ const skills = { target(card, player, target) { if (!get.tag(card, "damage") || player.hasSkillTag("jueqing", false, target)) return; let num = get.cardNameLength(card) - target.getDamagedHp(); - if (num > 0) return [1, num + 0.1]; + if (num > 0) return [1, 0.8 * num + 0.1]; }, }, }, @@ -1178,6 +1214,9 @@ const skills = { aiOrder(player, card, num) { if (player.isPhaseUsing() && get.type(card) == "equip" && get.equipValue(card, player) > 0) return num + 3; }, + cardUsable(card) { + if (card.storage?.clanfuxun) return Infinity; + }, }, locked: false, audio: 2, @@ -1273,6 +1312,7 @@ const skills = { var card = { name: result.links[0][2], nature: result.links[0][3], + storage: { clanfuxun: true }, }; game.broadcastAll(function (card) { lib.skill.clanfuxun_backup.viewAs = card; @@ -1456,9 +1496,14 @@ const skills = { if (!lib.skill[skill]) { lib.skill[skill] = { charlotte: true, + onremove: true, mark: true, marktext: "戒", - intro: { content: "已被$指定为【铭戒】目标" }, + intro: { + markcount: () => 0, + content: storage => "已被" + get.translation(storage[0]) + "指定为【铭戒】目标", + }, + group: "clanmingjie_clear", }; lib.translate[skill] = "铭戒"; lib.translate[skill + "_bg"] = "戒"; @@ -1471,17 +1516,22 @@ const skills = { enable: "phaseUse", limited: true, filterTarget(card, player, target) { - return !target.hasSkill("clanmingjie_" + player.playerid); + return !Object.keys(target.storage).some(skill => { + return skill.startsWith("clanmingjiex_" + player.playerid + "_") && target.storage[skill] === 1 + (_status.currentPhase === target); + }); }, skillAnimation: true, animationColor: "thunder", content() { player.awakenSkill("clanmingjie"); player.addSkill("clanmingjie_effect"); - var skill = "clanmingjie_" + player.playerid; + let skill; + do { + skill = "clanmingjiex_" + player.playerid + "_" + Math.random().toString(36).slice(-8); + } while (lib.skill[skill] != null); game.broadcastAll(lib.skill.clanmingjie.initSkill, skill); - target.addTempSkill(skill, { player: "phaseAfter" }); - target.storage[skill] = player; + target.addSkill(skill); + target.storage[skill] = _status.currentPhase === target ? 2 : 1; }, ai: { order: 10, @@ -1527,7 +1577,7 @@ const skills = { if (info.allowMultiple == false) return false; if (event.targets && !info.multitarget) { return game.filterPlayer().some(current => { - if (!current.hasSkill("clanmingjie_" + player.playerid)) return false; + if (!Object.keys(current.storage).some(skill => skill.startsWith("clanmingjiex_" + player.playerid + "_"))) return false; return !event.targets.includes(current) && lib.filter.targetEnabled2(card, player, current) && lib.filter.targetInRange(card, player, current); }); } @@ -1542,7 +1592,7 @@ const skills = { "令任意【铭戒】目标角色成为" + get.translation(trigger.card) + "的目标", function (card, player, target) { var trigger = _status.event.getTrigger(); - if (trigger.targets.includes(target) || !target.isIn() || !target.hasSkill("clanmingjie_" + player.playerid)) return false; + if (trigger.targets.includes(target) || !Object.keys(target.storage).some(skill => skill.startsWith("clanmingjiex_" + player.playerid + "_"))) return false; return lib.filter.targetEnabled2(trigger.card, player, target) && lib.filter.targetInRange(trigger.card, player, target); }, [1, Infinity] @@ -1562,30 +1612,31 @@ const skills = { }, group: "clanmingjie_targeted", }, + clear: { + charlotte: true, + trigger: { player: "phaseAfter" }, + filter(event, player) { + return Object.keys(player.storage).some(i => i.startsWith("clanmingjiex_")); + }, + forced: true, + popup: false, + firstDo: true, + content() { + const storages = Object.keys(player.storage).filter(i => i.startsWith("clanmingjiex_")); + for (const skill of storages) { + player.storage[skill]--; + if (!player.storage[skill]) player.removeSkill(skill); + } + }, + }, targeted: { charlotte: true, trigger: { global: "phaseEnd" }, filter(event, player) { - var cards = player.getStorage("clanmingjie_record").slice(); - cards = cards.filterInD("d"); - if (!cards.length) return false; - var history = player.getHistory("useSkill", evt => evt.skill == "clanmingjie"); - if (history.length) { - var targets = history.reduce((list, evt) => list.addArray(evt.targets), []); - if (event.player != player && targets.includes(event.player)) return true; - } - if (player.actionHistory.length >= 2) { - for (var i = player.actionHistory.length - 2; i >= 0; i--) { - if (!player.actionHistory[i].isMe) continue; - var history2 = player.actionHistory[i].useSkill.filter(evt => evt.skill == "clanmingjie"); - if (history2.length) { - var targets2 = history2.reduce((list, evt) => list.addArray(evt.targets), []); - if (targets2.includes(event.player)) return true; - } - break; - } - } - return false; + if (!Object.keys(event.player.storage).some(skill => { + return skill.startsWith("clanmingjiex_" + player.playerid + "_") && event.player.storage[skill] == 1; + })) return false; + return player.getStorage("clanmingjie_record").someInD("d"); }, forced: true, popup: false, @@ -1623,25 +1674,28 @@ const skills = { record: { charlotte: true, trigger: { - global: ["shaMiss", "eventNeutralized", "useCard1", "phaseAfter"], + global: ["useCard", "respond", "useCard1", "phaseAfter"], }, - filter(event, player) { - if (event.name == "useCard") { - return get.suit(event.card) == "spade"; - } + filter(event, player, name) { + if (name == "useCard1") return get.suit(event.card) == "spade"; if (event.name == "phase") return true; - if (event.type != "card") return false; - return true; + if (!Array.isArray(event.respondTo)) return false; + return get.type(event.respondTo[1]) != "trick" || ["caochuan", "wuxie"].includes(event.card.name); }, silent: true, forced: true, content() { - "step 0"; if (trigger.name == "phase") { delete player.storage.clanmingjie_record; - return; + } else { + player.markAuto( + "clanmingjie_record", + game.getGlobalHistory("everything", evt => { + if (event.triggername == "useCard1") return evt == trigger; + return evt.name == "useCard" && evt.card == trigger.respondTo[1]; + })[0].cards + ); } - player.markAuto("clanmingjie_record", trigger.cards); }, }, }, @@ -3522,7 +3576,7 @@ const skills = { filter(event, player) { if (event.phaseList[event.num].startsWith("phaseUse")) return false; var num1 = player.getHandcardLimit() - 1, - num2 = event.num; + num2 = event.num - player.getHistory("skipped").length; return num1 == num2; }, content() { diff --git a/character/clan/translate.js b/character/clan/translate.js index b616b94b81..8fe446225c 100644 --- a/character/clan/translate.js +++ b/character/clan/translate.js @@ -86,7 +86,7 @@ const translates = { clanjiexuan: "解悬", clanjiexuan_info: "限定技,转换技。阴:你可以将一张红色牌当【顺手牵羊】使用;阳:你可以将一张黑色牌当【过河拆桥】使用。", clanmingjie: "铭戒", - clanmingjie_info: "限定技。出牌阶段,你可以选择一名角色,然后你获得此下效果:①你使用牌时你可以指定其为额外目标直到其下个回合结束。②其下个回合结束时(若该角色为你则改为你的下下个回合结束时),你可以使用本回合使用过的黑桃牌和被抵消过的牌。", + clanmingjie_info: "限定技。出牌阶段,你可以选择一名角色,然后你获得此下效果:①你使用牌时你可以指定其为额外目标直到其下个回合结束。②其下个回合结束时,你可以使用本回合使用过的黑桃牌和被抵消过的牌。", clan_wanghun: "族王浑", clanfuxun: "抚循", clanfuxun_info: "出牌阶段限一次。你可以获得或交给一名其他角色一张手牌,然后若其手牌数与你相等且于此阶段仅以此法获得或失去过牌,你可以将一张牌当任意基本牌使用。", diff --git a/character/collab/character.js b/character/collab/character.js index 7a253daba5..48287b4c9b 100644 --- a/character/collab/character.js +++ b/character/collab/character.js @@ -1,4 +1,5 @@ const characters = { + liuxiecaojie: ["male", "qun", 2, ["dcjuanlv", "dcqixin"]], dc_zhaoyun: ["male", "shen", 1, ["boss_juejing", "dclonghun", "dczhanjiang"], ["shu", "InitFilter:noZhuHp:noZhuSkill"]], dc_sunce: ["male", "wu", 4, ["dcshuangbi"]], nezha: ["male", "qun", 3, ["dcsantou", "dcfaqi"], ["InitFilter:noZhuHp", "name:李|哪吒"]], @@ -24,7 +25,6 @@ const characters = { xin_sunquan: ["male", "wu", 3, ["dchuiwan", "dchuanli"]], wuhujiang: ["male", "shu", 4, ["olhuyi"], ["name:关|羽-张|飞-赵|云-马|超-黄|忠", "die:true", "die:5"]], dc_noname: ["male", "qun", 3, ["dcchushan"], ["name:null|null"]], - dc_xunyuxunyou: ["male", "wei", 3, ["dczhinang", "dcgouzhu"], ["name:荀|彧-荀|攸"]], }; export default characters; diff --git a/character/collab/dynamicTranslate.js b/character/collab/dynamicTranslate.js index 60937eac81..976c37340a 100644 --- a/character/collab/dynamicTranslate.js +++ b/character/collab/dynamicTranslate.js @@ -5,8 +5,21 @@ const dynamicTranslates = { return "当你受到伤害后,你可以摸" + get.cnNumber(player.countMark("dcjianxiong") + 1) + "张牌并获得对你造成伤害的牌,然后你令此技能摸牌数+1(至多为5)。"; }, dcbenxi(player) { - if(player.storage.dcbenxi) return "转换技,锁定技。当你失去手牌后,阴:系统随机检索出一句转换为拼音后包含“wu,yi”的技能台词,然后你念出此台词。阳:你获得上次所念出的台词对应的技能;若你已拥有该技能,则改为对其他角色各造成1点伤害。"; - return "转换技,锁定技。当你失去手牌后,阴:系统随机检索出一句转换为拼音后包含“wu,yi”的技能台词,然后你念出此台词。阳:你获得上次所念出的台词对应的技能;若你已拥有该技能,则改为对其他角色各造成1点伤害。"; + if (player.storage.dcbenxi) return "转换技,锁定技。当你失去手牌后,阴:系统随机检索出一句转换为拼音后包含“wu,yi”的技能台词,然后你念出此台词。阳:你获得上次所念出的台词对应的技能直到你的下个回合开始;若你已拥有该技能,则改为对其他角色各造成1点伤害。"; + return "转换技,锁定技。当你失去手牌后,阴:系统随机检索出一句转换为拼音后包含“wu,yi”的技能台词,然后你念出此台词。阳:你获得上次所念出的台词对应的技能直到你的下个回合开始;若你已拥有该技能,则改为对其他角色各造成1点伤害。"; + }, + dcqixin(player) { + const storage = player.storage["dcqixin"]; + const banned = player.storage.dcqixin_die; + if (banned) return '' + lib.translate.dcqixin_info + ""; + let str = "转换技。①出牌阶段,你可以将性别变更为:"; + if (!storage) str += ''; + str += "阴,曹节--女;"; + if (!storage) str += ""; + if (storage) str += ''; + str += "阳,刘协--男。"; + if (storage) str += ""; + return str + "②当你即将死亡时,你取消之并将性别变更为〖齐心①〗的转换状态,将体力调整至此状态的体力,然后你本局游戏不能发动〖齐心〗。"; }, }; export default dynamicTranslates; diff --git a/character/collab/index.js b/character/collab/index.js index 7e04ed6628..9357a240ad 100644 --- a/character/collab/index.js +++ b/character/collab/index.js @@ -19,6 +19,11 @@ game.import("character", function () { characterSort: { collab: characterSort, }, + characterSubstitute: { + liuxiecaojie: [ + ["liuxiecaojie_shadow", []], + ], + }, characterFilter: { ...characterFilters }, characterInitFilter: { ...characterInitFilters }, characterTitle: {}, diff --git a/character/collab/intro.js b/character/collab/intro.js index c68ee20e3d..d2ddc0333e 100644 --- a/character/collab/intro.js +++ b/character/collab/intro.js @@ -1,6 +1,6 @@ const characterIntro = { + liuxiecaojie: "请分别查看「刘协」和「曹节」的武将介绍。", dc_noname: " ", - dc_xunyuxunyou: "请分别查看「荀彧」和「荀攸」的武将介绍。", wuhujiang: "请分别查看「关羽」、「张飞」、「赵云」、「马超」和「黄忠」的武将介绍。", quyuan: "屈原(约前340年~前278年),芈姓(一作嬭姓),屈氏,名平,字原,又自云名正则,字灵均,出生于楚国丹阳秭归(今湖北省宜昌市),战国时期楚国诗人、政治家。楚武王熊通之子屈瑕的后代(一说屈氏的来源是西周前期的楚国人屈紃)。屈原少年时受过良好的教育,博闻强识,志向远大。早年受楚怀王信任,任左徒、三闾大夫,兼管内政外交大事。提倡“美政”,主张对内举贤任能,修明法度,对外力主联齐抗秦。因遭贵族排挤诽谤,被先后流放至汉北和沅湘流域。前278年,楚国郢都被秦军攻破后,自沉于汨罗江,以身殉楚国。屈原是中国历史上一位伟大的爱国诗人,中国浪漫主义文学的奠基人,“楚辞”的创立者和代表作家,开辟了“香草美人”的传统,被誉为“楚辞之祖”,楚国有名的辞赋家宋玉、唐勒、景差都受到屈原的影响。屈原作品的出现,标志着中国诗歌进入了一个由大雅歌唱到浪漫独创的新时代,其主要作品有《离骚》《九歌》《九章》《天问》等。以屈原作品为主体的《楚辞》是中国浪漫主义文学的源头之一,对后世诗歌产生了深远影响。成为中国文学史上的璀璨明珠,“逸响伟辞,卓绝一世”。“路漫漫其修远兮,吾将上下而求索”,屈原的“求索”精神,成为后世仁人志士所信奉和追求的一种高尚精神。", sunwukong: "孙悟空是中国古典小说《西游记》的主人公,也是中国神话中的民俗神祇之一,明代百回本《西游记》书中最为深入人心的形象之一。《西游记》中的孙悟空本是天地生成的一个石猴,率领群猴在花果山水帘洞过着逍遥自在的日子,后来为学习长生的法术而拜菩提祖师为师,学会了七十二变和筋斗云等绝技。后来他前往东海龙宫夺取如意金箍棒,又大闹地府勾了生死簿,惊动天庭,天庭两次派兵征讨花果山,仍然降他不得,只好请西天如来佛祖前来助阵。如来佛祖以五行山将悟空压在山下五百年。五百年后,悟空在观音菩萨的指点下拜唐僧为师,并跟随唐僧前往西天求取真经。路上唐僧又收了猪八戒、沙和尚两个徒弟,众人在途中斩妖除魔、历经磨难,终于取得真经,修成正果。", diff --git a/character/collab/skill.js b/character/collab/skill.js index ae1ded654b..098f961c5e 100644 --- a/character/collab/skill.js +++ b/character/collab/skill.js @@ -2,143 +2,139 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { - //荀彧荀攸 - dczhinang: { - getMap() { - if (!_status.dczhinang_map) { - _status.dczhinang_map = { - name: {}, - info: {}, - }; - let list; - if (_status.connectMode) { - list = get.charactersOL(); - } else { - list = get.gainableCharacters(); - } - list.forEach(name => { - if (name !== "dc_xunyuxunyou") { - const skills = get.character(name, 3); - skills.forEach(skill => { - const info = get.info(skill); - if (!info || (info.ai && info.ai.combo)) return; - if (skill in _status.dczhinang_map) return; - if (get.translation(skill).includes("谋")) _status.dczhinang_map.name[skill] = name; - const voices = game.parseSkillText(skill, name); - if (voices.some(data => data.includes("谋"))) { - _status.dczhinang_map.info[skill] = name; - } - }); - } - }); - } - return _status.dczhinang_map; - }, - trigger: { - player: "useCardAfter", - }, + //刘协曹节 + //我们意念合一×2 + dcjuanlv: { + audio: 2, + equipSkill: false, + inherit: "cixiong_skill", filter(event, player) { - return ["trick", "equip"].includes(get.type2(event.card)); - }, - frequent: true, - async content(event, trigger, player) { - const map = lib.skill.dczhinang.getMap(), - type = get.type2(trigger.card) == "equip" ? "name" : "info", - list = Object.keys(map[type]); - if (list.length > 0) { - const skill = list.randomGet(), - voiceMap = game.parseSkillTextMap(skill, map[type][skill]); - if (type == "info") { - findaudio: for (let data of voiceMap) { - if (!data.text) continue; - if (data.text.includes("谋")) { - player.chat(data.text); - game.broadcastAll(file => game.playAudio(file), data.file); - break findaudio; - } - } - } - else player.flashAvatar("dczhinang", map[type][skill]) - player.popup(skill); - await player.addSkills(skill); - } + return player.differentSexFrom(event.target); }, }, - dcgouzhu: { - trigger: { - player: ["useSkillAfter", "logSkill"], - }, + dcqixin: { + audio: 2, + enable: "phaseUse", filter(event, player) { - if (["global", "equip"].includes(event.type)) return false; - let skill = event.sourceSkill || event.skill; - if (!skill || skill == "dcgouzhu") return false; - let info = get.info(skill); - while (true) { - if (!info || info.charlotte || info.equipSkill) return false; - if (info && !info.sourceSkill) break; - skill = info.sourceSkill; - info = get.info(skill); - } - let list = get.skillCategoriesOf(skill, player); - return list.length && list.some(item => item in lib.skill.dcgouzhu.effectMap); + return !player.storage.dcqixin_die; }, - frequent: true, - effectMap: { - "锁定技": async function () { - let player = _status.event.player; - if (player.isDamaged()) await player.recover(); - }, - "觉醒技": async function () { - let player = _status.event.player; - let card = get.cardPile(card => get.type(card) == "basic"); - if (card) await player.gain(card, "gain2"); - }, - "限定技": async function () { - let player = _status.event.player; - let target = game.filterPlayer(current => current != player).randomGet(); - if (target) { - player.line(target, "green"); - await target.damage(player); - } - }, - "转换技": async function () { - let player = _status.event.player; - player.addMark("dcgouzhu", 1, false); - game.log(player, '手牌上限+1'); - await game.asyncDelay(); - }, - "主公技": async function () { - let player = _status.event.player; - await player.gainMaxHp(); - }, + filterCard: false, + selectCard: [0, 1], + prompt() { + const player = get.player(); + return "将性别变更为" + (Boolean(player.storage["dcqixin"]) ? "刘协--男" : "曹节--女"); }, - mod: { - maxHandcard: function (player, num) { - return num + player.countMark("dcgouzhu"); - }, + *content(event, map) { + const player = map.player; + player.changeZhuanhuanji("dcqixin"); + player.storage.dcqixin_hp[1 - Boolean(player.storage["dcqixin"])] = player.hp; + const hp = player.storage.dcqixin_hp[0 + Boolean(player.storage["dcqixin"])]; + if (player.hp != hp) yield player.changeHp(hp - player.hp); + player.tempBanSkill( + "dcqixin", + { + player: ["useCard1", "useSkillBegin", "phaseUseEnd"], + global: ["phaseAfter", "phaseBeforeStart"], + }, + false + ); + const sex = player.storage["dcqixin"] ? "female" : "male"; + game.broadcastAll( + (player, sex) => { + player.sex = sex; + }, + player, + sex + ); + game.log(player, "将性别变为了", "#y" + get.translation(sex) + "性"); + }, + mark: true, + zhuanhuanji: true, + markimage: "image/character/liuxie.jpg", + init(player) { + if (_status.gameStarted && !player.storage.dcqixin_hp) player.storage.dcqixin_hp = [player.maxHp, player.maxHp]; + }, + $zhuanhuanji(skill, player) { + const image = Boolean(player.storage[skill]) ? "caojie" : "liuxie"; + const mark = player.marks[skill]; + if (mark) mark.setBackground(image, "character"); + player.changeSkin({ characterName: "liuxiecaojie" }, "liuxiecaojie" + (player.storage[skill] ? "_shadow" : "")); }, intro: { - content: "手牌上限+#", + content(storage, player) { + const str = "当前性别:" + (Boolean(!storage) ? "刘协--男" : "曹节--女"); + const hp = player.storage.dcqixin_hp || [player.maxHp, player.maxHp]; + return player.storage.dcqixin_die ? str : "
  • " + str + "
  • " + (Boolean(storage) ? "刘协" : "曹节") + "体力值:" + hp[1 - Boolean(storage)]; + }, }, - locked: false, - onremove: true, - async content(event, trigger, player) { - let skill = trigger.sourceSkill || trigger.skill, - info = get.info(skill); - while (true) { - if (info && !info.sourceSkill) break; - skill = info.sourceSkill; - info = get.info(skill); - } - let list = get.skillCategoriesOf(skill, player); - for (const item of list) { - if (item in lib.skill.dcgouzhu.effectMap) { - const next = game.createEvent("dcgouzhu_effect", false); - next.player = player; - next.setContent(lib.skill.dcgouzhu.effectMap[item]); - await next; - } - } + ai: { + order: 10, + result: { + player(player) { + const cards = player.getCards("hs"); + const target = game + .filterPlayer(i => i != player) + .sort((a, b) => { + return ( + cards + .filter(j => player.canUse(j, b, true, true) && get.effect(b, j, player, player) > 0) + .reduce((sum, card) => { + return sum + get.effect(card, b, player, player); + }, 0) - + cards + .filter(j => player.canUse(j, a, true, true) && get.effect(a, j, player, player) > 0) + .reduce((sum, card) => { + return sum + get.effect(card, a, player, player); + }, 0) + ); + })[0]; + return player.differentSexFrom(target) ? 0 : 1; + }, + }, + }, + derivation: "dcqixin_faq", + group: ["dcqixin_die", "dcqixin_mark"], + subSkill: { + die: { + audio: "dcqixin", + trigger: { player: "dieBefore" }, + filter(event, player) { + return !player.storage.dcqixin_die && player.maxHp > 0; + }, + forced: true, + locked: false, + content() { + trigger.cancel(); + player.storage.dcqixin_die = true; + player.changeZhuanhuanji("dcqixin"); + const sex = player.storage["dcqixin"] ? "female" : "male"; + game.broadcastAll( + (player, sex) => { + player.sex = sex; + }, + player, + sex + ); + game.log(player, "将性别变为了", "#y" + get.translation(sex) + "性"); + player.storage.dcqixin_hp[1 - Boolean(player.storage["dcqixin"])] = player.hp; + const hp = player.storage.dcqixin_hp[0 + Boolean(player.storage["dcqixin"])]; + if (player.hp != hp) player.changeHp(hp - player.hp); + }, + }, + //双武将牌--梦回橙续缘双面武将 + mark: { + charlotte: true, + trigger: { global: "gameStart" }, + filter(event, player) { + return !player.storage.dcqixin_hp; + }, + forced: true, + popup: false, + firstDo: true, + content() { + player.storage.dcqixin_hp = [player.maxHp, player.maxHp]; + }, + }, }, }, //五虎将 @@ -677,7 +673,7 @@ const skills = { game.log(i, "未进行回答"); } } - await game.asyncDelay(); + await game.delay(); //处理结果 if (answer_ok && answer_ok.countCards("h")) await answer_ok.showHandcards(); if (gaifa.length) { @@ -685,7 +681,7 @@ const skills = { i.addTempSkill("dclisao_gaifa"); i.markAuto("dclisao_gaifa", [player]); } - await game.asyncDelay(); + await game.delay(); } }, chooseControl(question, current, eventId) { @@ -1230,17 +1226,17 @@ const skills = { maixie_hp: true, effect: { target(card, player, target) { - if (player.hasSkillTag("jueqing", false, target)) return [1, -1]; if (get.tag(card, "damage") && player != target) { + if (player.hasSkillTag("jueqing", false, target)) return [1, -1]; var cards = card.cards, evt = _status.event; if (evt.player == target && card.name == "damage" && evt.getParent().type == "card") cards = evt.getParent().cards.filterInD(); if (target.hp <= 1) return; if (get.itemtype(cards) != "cards") return; for (var i of cards) { - if (get.name(i, target) == "tao") return [1, 5 + player.countMark("dcjianxiong") / 2]; + if (get.name(i, target) == "tao") return [1, 2.5 + player.countMark("dcjianxiong") / 2]; } - if (get.value(cards, target) >= 7 - player.countMark("dcjianxiong") / 2 + target.getDamagedHp()) return [1, 3 + player.countMark("dcjianxiong") / 2]; + if (get.value(cards, target) >= 7 - player.countMark("dcjianxiong") / 2 + target.getDamagedHp()) return [1, 1.5 + player.countMark("dcjianxiong") / 2]; return [1, 0.6 + player.countMark("dcjianxiong") / 2]; } }, @@ -1572,7 +1568,7 @@ const skills = { if (result.bool) { await player.logSkill("dctongliao"); player.addGaintag(result.cards, "dctongliao"); - await game.asyncDelayx(); + await game.delayx(); } }, mod: { @@ -1711,7 +1707,7 @@ const skills = { nofire: true, effect: { target(card, player, target, current) { - if (get.tag(card, "fireDamage")) return "zerotarget"; + if (get.tag(card, "fireDamage")) return "zeroplayertarget"; }, }, }, @@ -2024,7 +2020,7 @@ const skills = { await player.discardPlayerCard(target, true, "e", num); } else { await target.loseHp(); - await game.asyncDelayx(); + await game.delayx(); } } } @@ -2067,7 +2063,7 @@ const skills = { player.discardPlayerCard(target, true, "h", num); } else { target.loseHp(); - game.delayex(); + await game.delayex(); } } }, @@ -2168,7 +2164,7 @@ const skills = { if (player.getEquips("ruyijingubang").includes(card)) return false; }, canBeReplaced(card, player) { - if (player.getEquips("ruyijingubang").includes(card)) return false; + if (player.getVEquips("ruyijingubang").includes(card)) return false; }, cardname(card) { if (get.subtype(card, false) == "equip1") return "sha"; @@ -2341,7 +2337,7 @@ const skills = { .set("card", trigger.card) .forResult(); if (result.bool) { - if (!event.isMine() && !event.isOnline()) await game.asyncDelayx(); + if (!event.isMine() && !event.isOnline()) await game.delayx(); await player.logSkill("ruyijingubang_effect", result.targets); trigger.targets.addArray(result.targets); } diff --git a/character/collab/sort.js b/character/collab/sort.js index f189ba6d59..246a6c6832 100644 --- a/character/collab/sort.js +++ b/character/collab/sort.js @@ -4,8 +4,8 @@ const characterSort = { collab_duanwu_2023: ["sunwukong", "longwang", "taoshen"], collab_decade: ["libai", "xiaoyuehankehan", "zhutiexiong", "wu_zhutiexiong"], collab_remake: ["dc_caocao", "dc_liubei", "dc_sunquan", "nezha", "dc_sunce", "dc_zhaoyun", "dc_wuyi"], - collab_duanwu_2024: ["quyuan", "xin_sunquan"], - collab_dcdoudizhui: ["dc_noname", "dc_xunyuxunyou"], + collab_duanwu_2024: ["quyuan"], + collab_dcdoudizhui: ["dc_noname", "xin_sunquan", "liuxiecaojie"], collab_oldoudizhu: ["wuhujiang"], }; diff --git a/character/collab/translate.js b/character/collab/translate.js index 47f17614fa..cc08cfdbe4 100644 --- a/character/collab/translate.js +++ b/character/collab/translate.js @@ -98,7 +98,7 @@ const translates = { dc_wuyi: "经典吴懿", dc_wuyi_prefix: "经典", dcbenxi: "奔袭", - dcbenxi_info: "转换技,锁定技。当你失去手牌后,阴:系统随机检索出一句转换为拼音后包含“wu,yi”的技能台词,然后你念出此台词。阳:你获得上次所念出的台词对应的技能;若你已拥有该技能,则改为对其他角色各造成1点伤害。", + dcbenxi_info: "转换技,锁定技。当你失去手牌后,阴:系统随机检索出一句转换为拼音后包含“wu,yi”的技能台词,然后你念出此台词。阳:你获得上次所念出的台词对应的技能直到你的下个回合开始;若你已拥有该技能,则改为对其他角色各造成1点伤害。", quyuan: "屈原", dcqiusuo: "求索", dcqiusuo_info: "当你造成或受到伤害后,你可以从牌堆或弃牌堆中获得一张【铁索连环】。", @@ -117,11 +117,13 @@ const translates = { wuhujiang_prefix: "魂", olhuyi: "虎翼", olhuyi_info: "①游戏开始时,你从随机三个五虎将技能中选择一个获得。②当你使用或打出一张基本牌后,若你因此技能获得的技能数小于5,你随机获得一个技能描述中包含此牌名的五虎将技能。③回合结束时,你可以失去一个以此法获得的技能。", - dc_xunyuxunyou: "荀彧荀攸", - dczhinang: "智囊", - dczhinang_info: "当你使用锦囊牌后,你可以获得一个技能台词包含“谋”的技能;当你使用装备牌后,你可以获得一个技能名包含“谋”的技能。", - dcgouzhu: "苟渚", - dcgouzhu_info: "你发动技能后,若此技能为:锁定技,回复1点体力;觉醒技,获得一张基本牌;限定技,对随机一名其他角色造成1点伤害;转换技,手牌上限+1;主公技,增加1点体力上限。", + liuxiecaojie: "刘协曹节", + dcjuanlv: "眷侣", + dcjuanlv_info: "当你使用牌指定异性角色为目标后,你可以令其选择一项:①弃置一张牌;②令你摸一张牌。", + dcqixin: "齐心", + dcqixin_info: "转换技。①出牌阶段,你可以将性别变更为:阴,曹节--女;阳,刘协--男。②当你即将死亡时,你取消之并将性别变更为〖齐心①〗的转换状态,将体力调整至此状态的体力,然后你本局游戏不能发动〖齐心〗。", + dcqixin_faq: "关于齐心", + dcqixin_faq_info: "
    〖齐心①〗的两种状态各拥有初始体力上限的体力值,初始状态为“刘协--男”,且两种状态的体力值分别计算。", }; export default translates; diff --git a/character/ddd/skill.js b/character/ddd/skill.js index edbf3ba0a6..7e77b10c0c 100644 --- a/character/ddd/skill.js +++ b/character/ddd/skill.js @@ -1404,7 +1404,7 @@ const skills = { intro: { content: "本回合不能使用或打出手牌" }, mod: { cardEnabled2(card) { - return false; + if (get.position(card) == "h") return false; }, }, }, @@ -2029,7 +2029,7 @@ const skills = { if (event.type != "discard") return false; var cards = event.getd(); for (var i of cards) { - if (get.position(i, true) == "d" && get.color(i, false) == "black" && get.type(i, null, true) == "basic") { + if (get.position(i, true) == "d" && get.color(i, false) == "black" && get.type(i) == "basic") { var card = get.autoViewAs({ name: "bingliang" }, [i]); if ( game.hasPlayer(function (current) { @@ -2045,7 +2045,7 @@ const skills = { "step 0"; if (!event.cards) event.cards = []; var cards = trigger.getd().filter(function (i) { - if (!event.cards.includes(i) && get.position(i, true) == "d" && get.color(i, false) == "black" && get.type(i, null, true) == "basic") { + if (!event.cards.includes(i) && get.position(i, true) == "d" && get.color(i, false) == "black" && get.type(i) == "basic") { var card = get.autoViewAs({ name: "bingliang" }, [i]); if ( game.hasPlayer(function (current) { @@ -3965,6 +3965,7 @@ const skills = { delete event.player; event.trigger("compare"); } else { + event.iwhile = 0; game.delay(0, 1000); event.goto(9); } @@ -3975,13 +3976,27 @@ const skills = { event.goto(7); "step 9"; event.player = event.tempplayer; + event.trigger("compareFixing"); + "step 10"; + if (event.player) delete event.player; + if (event.iwhile < targets.length) { + event.target = targets[event.iwhile]; + event.trigger("compareFixing"); + } else { + event.goto(12); + } + "step 11"; + event.iwhile++; + event.goto(10); + "step 12"; + event.player = event.tempplayer; delete event.tempplayer; var str; var num1 = event.result.num1.reduce((p, c) => p + c, 0) / event.result.num1.length, num2 = event.result.num2.reduce((p, c) => p + c, 0) / event.result.num2.length; game.log(event.player, "方的点数均值为", "#y" + Math.floor(num1 * 100) / 100); game.log(event.targetx, "方的点数均值为", "#y" + Math.floor(num2 * 100) / 100); - if (num1 > num2) { + if (event.players.includes(event.forceWinner) || (!event.targetsx.includes(event.forceWinner) && num1 > num2)) { str = get.translation(event.players) + "拼点成功"; event.players.forEach(i => i.popup("胜")); event.targetsx.forEach(i => i.popup("负")); @@ -3989,7 +4004,7 @@ const skills = { event.result.loser = event.targetsx; } else { str = get.translation(event.players) + "拼点失败"; - if (num1 == num2) { + if (!event.targetsx.includes(event.forceWinner) && num1 == num2) { event.players.forEach(i => i.popup("平")); event.targetsx.forEach(i => i.popup("平")); event.result.loser = event.players.addArray(event.targetsx); @@ -4008,9 +4023,9 @@ const skills = { }, 1000); }, str); game.delay(3); - ("step 10"); + "step 13"; game.broadcastAll(ui.clear); - ("step 11"); + "step 14"; event.cards.add(event.card1); }, contentx() { @@ -5589,7 +5604,7 @@ const skills = { filter(event, player) { if (event.player == player) return false; if (event.name == "recover") return player.isDamaged(); - return get.type(event.card, false) == "equip" && event.cards.some(i => get.position(i, true) == "o" && player.canEquip(i, true)); + return get.type(event.card, null, false) == "equip" && event.cards.some(i => get.position(i, true) == "o" && player.canEquip(i, true)); }, limited: true, skillAnimation: true, @@ -5621,7 +5636,7 @@ const skills = { trigger: { player: ["recoverAfter", "useCardAfter"] }, filter(event, player) { if (event.getParent().name == "dddjiexing") return false; - if (event.name == "useCard") return get.type(event.card, false) == "equip"; + if (event.name == "useCard") return get.type(event.card, null, false) == "equip"; return true; }, forced: true, diff --git a/character/diy/character.js b/character/diy/character.js index f5185b7601..23b970fc61 100644 --- a/character/diy/character.js +++ b/character/diy/character.js @@ -75,11 +75,6 @@ const characters = { ns_yujisp: ["male", "qun", 3, ["nsguhuo"]], ns_yangyi: ["male", "shu", 3, ["nsjuanli", "nsyuanchou"]], ns_liuzhang: ["male", "qun", 3, ["nsanruo", "nsxunshan", "nskaicheng"]], - // ns_zhaoyun:['male','qun',3,[]], - // ns_lvmeng:['male','qun',3,[]], - // ns_zhaoyunshen:['male','qun',3,[]], - // ns_lisu:['male','qun',3,[]], - // ns_sunhao:['male','qun',3,[]], ns_xinnanhua: ["male", "qun", 3, ["ns_xiandao", "ns_xiuzheng", "ns_chuanshu"], ["name:庄|周"]], ns_caimao: ["male", "qun", 4, ["nsdingzhou"]], ns_luyusheng: ["female", "wu", 3, ["nshuaishuang", "nsfengli"]], diff --git a/character/diy/characterReplace.js b/character/diy/characterReplace.js index 144fe6da72..a76eebd148 100644 --- a/character/diy/characterReplace.js +++ b/character/diy/characterReplace.js @@ -1,6 +1,6 @@ const characterReplaces = { key_yuri: ["key_yuri", "sp_key_yuri"], - kanade: ["sp_key_kanade", "kanade"], + sp_key_kanade: ["sp_key_kanade", "kanade"], }; export default characterReplaces; diff --git a/character/diy/characterTitles.js b/character/diy/characterTitles.js index 534b7b72b9..777aed35bf 100644 --- a/character/diy/characterTitles.js +++ b/character/diy/characterTitles.js @@ -27,7 +27,6 @@ export default { ns_huamulan: "#p哎别管我是谁", ns_jinke: "#p哎别管我是谁", ns_huangzu: "#r小芯儿童鞋", - ns_lisu: "#r小芯儿童鞋", ns_yanliang: "#r丶橙续缘", ns_wenchou: "#r丶橙续缘", ns_caocao: "#r一瞬间丶遗忘", diff --git a/character/diy/skill.js b/character/diy/skill.js index de1180dacb..1340ed7605 100644 --- a/character/diy/skill.js +++ b/character/diy/skill.js @@ -216,7 +216,7 @@ const skills = { return player.hasHistory("lose", function (evt) { if (evt.type != "discard" || evt.getParent("phaseDiscard") != event) return false; for (var i of evt.cards2) { - if (get.type(i, false) == "basic" && get.position(i, true) == "d" && player.hasUseTarget(i)) return true; + if (get.type(i, null, false) == "basic" && get.position(i, true) == "d" && player.hasUseTarget(i)) return true; } return false; }); @@ -227,7 +227,7 @@ const skills = { player.getHistory("lose", function (evt) { if (evt.type != "discard" || evt.getParent("phaseDiscard") != trigger) return false; for (var i of evt.cards2) { - if (get.type(i, false) == "basic" && get.position(i, true) == "d") cards.push(i); + if (get.type(i, null, false) == "basic" && get.position(i, true) == "d") cards.push(i); } return false; }); @@ -291,7 +291,7 @@ const skills = { "step 1"; if (result.index == 0) { var card = get.cardPile2(function (card) { - return get.type(card, false) == "basic"; + return get.type(card, null, false) == "basic"; }); if (card) player.gain(card, "gain2"); event.finish(); @@ -693,6 +693,7 @@ const skills = { discard: false, lose: false, delay: false, + derivation: ["noname_retieji", "noname_jiang"], content() { "step 0"; var stat = player.getStat(); @@ -920,7 +921,7 @@ const skills = { delay: false, check(card) { var player = _status.event.player; - if (get.type(card, player) == "basic") { + if (get.type(card) == "basic") { if ( game.hasPlayer(function (current) { return get.attitude(current, player) > 0 && current.getUseValue(card) > player.getUseValue(card, null, true); @@ -1487,7 +1488,7 @@ const skills = { game.addGlobalSkill("nslongyue_ai"); }, onremove: () => { - if (!game.hasPlayer(i => i.hasSkill("nslongyue"), true)) game.removeGlobalSkill("nslongyue_ai"); + if (!game.hasPlayer(i => i.hasSkill("nslongyue", null, null, false), true)) game.removeGlobalSkill("nslongyue_ai"); }, trigger: { global: "useCard" }, filter(event, player) { @@ -1519,7 +1520,7 @@ const skills = { }, trigger: { player: "dieAfter" }, filter: () => { - return !game.hasPlayer(i => i.hasSkill("nslongyue"), true); + return !game.hasPlayer(i => i.hasSkill("nslongyue", null, null, false), true); }, silent: true, forceDie: true, @@ -2731,6 +2732,58 @@ const skills = { }, }, }, + ns_xiandao: { + audio: ["huashen", 2], + forced: true, + noRemove: true, + trigger: { + player: "damageBefore", + }, + filter(event, player) { + return event.nature; + }, + content() { + trigger.cancel(); + }, + ai: { + nofire: true, + nothunder: true, + effect: { + target(card, player, target) { + if (get.tag(card, "natureDamage")) return "zeroplayertarget"; + } + } + }, + group: "ns_xiandao_add", + subSkill: { + add: { + audio: ["huashen", 2], + forced: true, + priority: 10, + trigger: { + global: "gameStart", + player: ["phaseEnd", "enterGame"], + }, + content() { + var n = [1, 2].randomGet(); + if (n == 1) { + player.addTempSkill("releiji", { + player: "phaseUseBegin", + }); + player.markSkill("releiji", { + player: "phaseUseBegin", + }); + } + else { + player.addTempSkill("guidao", { + player: "phaseUseBegin", + }); + player.markSkill("guidao", { player: "phaseUseBegin" }); + } + }, + }, + } + }, ns_chuanshu: { audio: ["xingshuai", 2], trigger: { @@ -2763,75 +2816,6 @@ const skills = { player.awakenSkill("ns_chuanshu"); }, }, - ns_xiandao1: { - audio: ["huashen", 2], - forced: true, - //noLose:true, - //locked:true, - //noRemove:true, - //noDisable:true, - priority: 10, - trigger: { - global: "gameStart", - player: ["phaseEnd", "enterGame"], - }, - //filter (event,player){ - // return player.isAlive(); - //}, - content() { - var n = [1, 2].randomGet(); - if (n == 1) { - player.addTempSkill("releiji", { - player: "phaseUseBegin", - }); - player.markSkill("releiji", { - player: "phaseUseBegin", - }); - } - if (n == 2) { - player.addTempSkill("guidao", { - player: "phaseUseBegin", - }); - player.markSkill("guidao", { player: "phaseUseBegin" }); - } - }, - }, - ns_xiandao2: { - audio: ["huashen", 2], - forced: true, - //noLose:true, - //locked:true, - //noRemove:true, - //noDisable:true, - trigger: { - player: "damageBefore", - }, - filter(event, player) { - if (!event.nature) return false; - return true; - }, - content() { - trigger.cancel(); - //event.finish(); - }, - ai: { - nofire: true, - nothunder: true, - effect: { - target(card, player, target) { - if (get.tag(card, "natureDamage")) return "zerotarget"; - } - } - } - }, - ns_xiandao: { - forced: true, - //noLose:true, - //locked:true, - noRemove: true, - //noDisable:true, - group: ["ns_xiandao1", "ns_xiandao2"], - }, ns_chuanshu2: { audio: ["songwei", 2], mark: "character", @@ -3864,20 +3848,36 @@ const skills = { ai: { order: 10, result: { + player(player, target) { + if ( + ui.selected.targets.length && + Math.abs(target.hp - ui.selected.targets[0].hp) === 1 + ) return get.effect(player, {name: "losehp"}, player, player) / 10; + return 0; + }, target(player, target) { - if (target == game.zhu) return -1; - if (get.attitude(player, target) > 3) { - var num = game.zhu.hp - target.hp; - if (num == 1) { - return 1; - } - if (num > 1) { - if (player.hp == 1) return num; - if (target.hp == 1) return num; - if (num >= 3) return num; - } + let att = get.attitude(player, target), max; + if (!ui.selected.targets.length) { + let search = false; + game.countPlayer(cur => { + if ( + player === cur || + target === cur || + (cur.hp - target.hp) * (get.attitude(player, cur) - att) >= 0 + ) return false; + if (!search) { + max = Math.min(cur.hp, target.maxHp) - target.hp; + search = true; + } + else if (att > 0) max = Math.max(max, Math.min(cur.hp, target.maxHp) - target.hp); + else max = Math.min(max, Math.min(cur.hp, target.maxHp) - target.hp); + }); + if (target === get.zhu(player)) return 2 * max; + return max; } - return 0; + max = Math.min(ui.selected.targets[0].hp, target.maxHp) - target.hp; + if (target === get.zhu(player)) return 2 * max; + return max; }, }, }, @@ -4615,7 +4615,7 @@ const skills = { }, ai: { effect: { - target_use(card, player, target, current) { + target(card, player, target, current) { if (get.type(card, "trick") == "trick" && _status.currentPhase == player) return "zeroplayertarget"; }, }, @@ -6252,7 +6252,7 @@ const skills = { effect: { target_use(card, player, target) { if (get.tag(card, "multineg")) { - return "zerotarget"; + return "zeroplayertarget"; } if (get.tag(card, "multitarget")) { var info = get.info(card); @@ -6741,7 +6741,7 @@ const skills = { }, ai: { effect: { - target_use(card, player, target) { + target(card, player, target) { if (get.color(card) == "red") return [1, 1]; }, } @@ -6805,32 +6805,6 @@ const skills = { threaten: 1.3, }, }, - diyzaiqi: { - trigger: { player: "phaseDrawBegin" }, - forced: true, - filter(event, player) { - return player.hp < player.maxHp; - }, - content() { - trigger.num += player.maxHp - player.hp; - }, - ai: { - threaten(player, target) { - if (target.hp == 1) return 2.5; - if (target.hp == 2) return 1.8; - return 0.5; - }, - maixie: true, - effect: { - target(card, player, target) { - if (get.tag(card, "damage")) { - if (target.hp == target.maxHp) return [0, 1]; - } - if (get.tag(card, "recover") && player.hp >= player.maxHp - 1) return [0, 0]; - }, - }, - }, - }, diykuanggu: { trigger: { source: "damageEnd" }, forced: true, @@ -7043,7 +7017,7 @@ const skills = { }, ai: { effect: { - target(card) { + target_use(card) { if (get.type(card) == "delay") return [0, 0.5]; }, }, @@ -7143,8 +7117,8 @@ const skills = { ai: { effect: { target(card, player, target, current) { - if (card.name == "tiesuo") return 0; - if (get.tag(card, "thunderDamage")) return 0; + if (card.name == "tiesuo") return 0.1; + if (get.tag(card, "thunderDamage")) return "zeroplayertarget"; }, }, threaten: 0.5, @@ -7638,7 +7612,7 @@ const skills = { ai: { effect: { target(card, player, target) { - if (get.type(card) == "delay") return "zerotarget"; + if (get.type(card) == "delay") return "zeroplayertarget"; }, }, }, diff --git a/character/diy/translate.js b/character/diy/translate.js index 393edec280..98638bbf2c 100644 --- a/character/diy/translate.js +++ b/character/diy/translate.js @@ -58,7 +58,6 @@ const translates = { ns_lvmeng: "吕蒙", ns_yujisp: "于吉", - ns_lisu: "李肃", ns_yangyi: "杨仪", ns_liuzhang: "刘璋", ns_xinnanhua: "南华老仙", @@ -156,16 +155,8 @@ const translates = { nsxuezhu_info: "当你受到伤害或造成伤害后,你可以令受到伤害的角色摸两张牌并翻面。", ns_chuanshu: "传术", ns_chuanshu_info: "限定技 当一名其他角色进入濒死状态时,你可以令其选择获得技能〖雷击〗或〖鬼道〗,其回复体力至1并摸两张牌。当该被【传术】的角色造成或受到一次伤害后,你摸一张牌。其阵亡后,你重置技能〖传术〗。", - ns_xiandao1: "仙道", - ns_xiandao1_info: "锁定技 游戏开始和回合结束阶段,你随机获得技能〖雷击〗或〖鬼道〗,直到下个出牌阶段开始。", - ns_xiandao2: "仙道", - ns_xiandao2_info: "锁定技 你防止受到任何属性伤害。", ns_xiandao: "仙道", ns_xiandao_info: "锁定技 游戏开始、你进入游戏时和回合结束阶段,你随机获得技能〖雷击〗或〖鬼道〗,直到下个出牌阶段阶段开始。你防止受到任何属性伤害。", - ns_chuanshu2: "术", - ns_chuanshu2_info: "锁定技 当你造成或受到一次伤害后,南华老仙摸一张牌。", - ns_chuanshu3: "术", - ns_chuanshu3_info: "锁定技 当你【传术】的角色阵亡后,你重置技能〖传术〗。", ns_xiuzheng: "修真", ns_xiuzheng_info: "出牌阶段限一次,你可选择一名其他角色,然后亮出牌堆顶的两张牌,若同为红色,则其受到1点火焰伤害;若同为黑色,其受到1点雷电伤害;若颜色不相同,你弃置其一张牌。然后你获得这两张展示的牌后再弃置两张牌。", nsanruo: "暗弱", @@ -342,7 +333,6 @@ const translates = { diyduanliang2: "断粮", diyqiangxi: "强袭", diykuanggu: "狂骨", - diyzaiqi: "再起", batu: "霸图", zaiqix: "再起", diy_jiaoxia: "皎霞", @@ -351,7 +341,6 @@ const translates = { diy_jiaoxia_info: "每当你成为红色牌的目标,你可以摸一张牌。", zaiqix_info: "摸牌阶段,若你已受伤,你可以改为亮出牌堆顶的X+1张牌,X为你已损失的体力值,其中每有一张♥牌,你回复1点体力,然后弃掉这些♥牌,将其余的牌收入手牌。", batu_info: "结束阶段,你可以将手牌数补至X,X为现存的势力数。", - diyzaiqi_info: "锁定技,你摸牌阶段额外摸X张牌,X为你已损失的体力值。", diykuanggu_info: "锁定技,每当你造成1点伤害,你在其攻击范围内,你回复1点体力,否则你摸一张牌。", diyqiangxi_info: "出牌阶段,你可以自减1点体力或弃一张武器牌,然后你对你攻击范围内的一名角色造成1点伤害并弃置其一张牌,每回合限一次。", diyduanliang_info: "出牌阶段限一次,你可以将一张黑色的基本牌当兵粮寸断对一名角色使用,然后摸一张牌。你的兵粮寸断可以指定距离2以内的角色作为目标。", diff --git a/character/extra/card.js b/character/extra/card.js index 46fead2cfb..8b7e8e1336 100644 --- a/character/extra/card.js +++ b/character/extra/card.js @@ -8,10 +8,12 @@ const cards = { subtype: "equip1", distance: { attackFrom: -5 }, onLose() { - card.fix(); - card.remove(); - card.destroyed = true; - game.log(card, "被销毁了"); + cards.forEach(card => { + card.fix(); + card.remove(); + card.destroyed = true; + game.log(card, "被销毁了"); + }); player.addTempSkill("changandajian_destroy"); }, ai: { @@ -45,10 +47,12 @@ const cards = { type: "equip", subtype: "equip2", onLose() { - card.fix(); - card.remove(); - card.destroyed = true; - game.log(card, "被销毁了"); + cards.forEach(card => { + card.fix(); + card.remove(); + card.destroyed = true; + game.log(card, "被销毁了"); + }); player.addTempSkill("changandajian_destroy"); }, ai: { @@ -83,10 +87,12 @@ const cards = { subtype: "equip3", distance: { globalTo: 2 }, onLose() { - card.fix(); - card.remove(); - card.destroyed = true; - game.log(card, "被销毁了"); + cards.forEach(card => { + card.fix(); + card.remove(); + card.destroyed = true; + game.log(card, "被销毁了"); + }); player.addTempSkill("changandajian_destroy"); }, ai: { @@ -121,10 +127,12 @@ const cards = { subtype: "equip4", distance: { globalFrom: -2 }, onLose() { - card.fix(); - card.remove(); - card.destroyed = true; - game.log(card, "被销毁了"); + cards.forEach(card => { + card.fix(); + card.remove(); + card.destroyed = true; + game.log(card, "被销毁了"); + }); player.addTempSkill("changandajian_destroy"); }, ai: { @@ -159,10 +167,12 @@ const cards = { subtype: "equip5", skills: ["changandajian_equip5"], onLose() { - card.fix(); - card.remove(); - card.destroyed = true; - game.log(card, "被销毁了"); + cards.forEach(card => { + card.fix(); + card.remove(); + card.destroyed = true; + game.log(card, "被销毁了"); + }); player.addTempSkill("changandajian_destroy"); }, ai: { @@ -197,10 +207,12 @@ const cards = { subtype: "equip6", distance: { globalTo: 2, globalFrom: -2 }, onLose() { - card.fix(); - card.remove(); - card.destroyed = true; - game.log(card, "被销毁了"); + cards.forEach(card => { + card.fix(); + card.remove(); + card.destroyed = true; + game.log(card, "被销毁了"); + }); player.addTempSkill("changandajian_destroy"); }, ai: { diff --git a/character/extra/character.js b/character/extra/character.js index 130f53375c..bb2916df08 100644 --- a/character/extra/character.js +++ b/character/extra/character.js @@ -1,4 +1,5 @@ const characters = { + shen_huangzhong: ["male", "shen", 4, ["1!5!", 'chiren'], ["shu"]], new_simayi: ["male", "shen", 4, ["jilin", "yingyou", "yingtian"], ["wei", "name:司马|懿"]], xin_simayi: ["male", "shen", 4, ["xinrenjie", "xinbaiyin", "xinlianpo"], ["tempname:shen_simayi", "wei", "name:司马|懿"]], dc_shen_huatuo: ["male", "shen", 3, ["jingyu", "lvxin", "huandao"], ["qun"]], diff --git a/character/extra/characterReplace.js b/character/extra/characterReplace.js index d0f1200710..1bcb838d00 100644 --- a/character/extra/characterReplace.js +++ b/character/extra/characterReplace.js @@ -1,7 +1,7 @@ const characterReplaces = { shen_zhangliao: ["ol_zhangliao", "shen_zhangliao"], shen_zhaoyun: ["shen_zhaoyun", "dc_zhaoyun", "old_shen_zhaoyun", "boss_zhaoyun"], - shen_guanyu: ["shen_guanyu", "tw_shen_guanyu"], + shen_guanyu: ["shen_guanyu", "tw_shen_guanyu", "ty_shen_guanyu"], shen_sunquan: ["shen_sunquan", "junk_sunquan"], shen_lvmeng: ["shen_lvmeng", "tw_shen_lvmeng"], shen_machao: ["shen_machao", "ps_shen_machao"], @@ -10,6 +10,8 @@ const characterReplaces = { shen_zhangjiao: ["shen_zhangjiao", "junk_zhangjiao"], shen_huatuo: ["dc_shen_huatuo", "shen_huatuo"], shen_simayi: ["shen_simayi", "xin_simayi", "new_simayi"], + shen_liubei: ["shen_liubei", "ty_shen_liubei"], + shen_zhangfei: ["shen_zhangfei", "ty_shen_zhangfei"] }; export default characterReplaces; diff --git a/character/extra/skill.js b/character/extra/skill.js index 3a19788321..2820eff61e 100644 --- a/character/extra/skill.js +++ b/character/extra/skill.js @@ -2,6 +2,353 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { + //神黄忠 + //丁真神将,赤矢神将,爆头神将,吃人神将 + "1!5!": { + audio: 2, + trigger: { source: "damageSource" }, + filter(event, player) { + return event.player.isIn() && event.source != event.player; + }, + logTarget: "player", + prompt2: (event, player) => ("击伤其一个部位"), + async content(event, trigger, player) { + const target = trigger.player; + const places = lib.skill["1!5!"].derivation + .slice() + .filter(i => { + let storage = target.getStorage("1!5!_injury"); + if (!storage.length && i == "1!5!_place1") { + return false; + } + return true; + }) + if (!places.length) return; + //射击部位-by 鸽子 + //牢萌负责精修断后 + //一个团队要有XX的X,YY的Y,ZZ的Z... + await Promise.all(event.next); + event.videoId = lib.status.videoId++; + if (player.isUnderControl()) game.swapPlayerAuto(player); + const switchToAuto = function () { + setTimeout(function () { + _status.imchoosing = false; + if (event.dialog) event.dialog.close(); + if (event.control) event.control.close(); + game.resume(); + return Promise.resolve({ + bool: true, + hurt: places.randomGet(), + }); + }, 5000); + }; + const chooseButton = (places, target) => { + const { promise, resolve } = Promise.withResolvers(); + const event = _status.event; + event.switchToAuto = function () { + _status.imchoosing = false; + resolve({ + bool: true, + hurt: places.randomGet(), + }); + if (event.dialog) event.dialog.close(); + }; + const dialog = ui.create.dialog("forcebutton", "hidden"); + event.dialog = dialog; + //白底大图不加textPrompt了 + //dialog.textPrompt = dialog.add('
    毅武:选择击伤' + get.translation(target) +'的一个部位
    '); + dialog.style.display = "flex"; + dialog.style.justifyContent = "center"; + dialog.style.alignItems = "center"; + dialog.style.position = "relative"; + dialog.style.width = "100%"; + dialog.style.height = "100%"; + dialog.id = "1!5!"; + dialog.classList.add("fixed"); + dialog.classList.add("scroll1"); + dialog.classList.add("scroll2"); + dialog.classList.add("center"); + dialog.classList.add("scroll3"); + dialog.classList.add("fullwidth"); + dialog.classList.add("fullheight"); + const target_img = document.createElement("div"); + const position = lib.skill["1!5!"].derivation; + target_img.style.width = "50%"; + target_img.style.height = "100%"; + target_img.style.position = "relative"; + target_img.style.overflow = "visible"; + target_img.style.boxSizing = "border-box"; + target_img.style.border = "1px solid black"; + target_img.style.backgroundColor = "rgb(255,178,102)"; + dialog.appendChild(target_img); + target_img.style.backgroundImage = "url(" + lib.assetURL + "image/card/yiwu_" + (target.hasSex("male") ? "male" : "female") + ".png)"; + target_img.style.backgroundSize = "cover"; + target_img.style.backgroundRepeat = "no-repeat"; + target_img.style.backgroundSize = "contain"; + target_img.style.backgroundRepeat = "no-repeat"; + target_img.style.backgroundPosition = "center center"; + const number = target.hasSex("male") + ? [ + ["7", "1"], + //["5", "3"], + //["4", "7"], + ["9", "5"], + ["9", "13"], + ["7", "3"], + ["7", "6"], + ] + : [ + ["7", "1"], + //["8", "3"], + //["4", "7"], + ["9", "5"], + ["9", "13"], + ["6", "3"], + ["6", "6"], + ]; + let list = []; + for (let i = 0; i < position.length; i++) { + const num_px = document.createElement("div"); + num_px.style.width = "15%"; + num_px.style.height = "15%"; + num_px.id = position[i]; + num_px.style.position = "absolute"; + num_px.style.left = `${number[i][0] * 6}%`; + num_px.style.top = `${number[i][1] * 6}%`; + num_px.style.boxSizing = "border-box"; + num_px.style.backgroundImage = "url(" + lib.assetURL + "image/card/yiwu_click.png)"; + num_px.style.backgroundSize = "cover"; + num_px.style.backgroundRepeat = "no-repeat"; + num_px.style.backgroundSize = "contain"; + num_px.style.backgroundRepeat = "no-repeat"; + num_px.style.backgroundPosition = "center center"; + num_px.addEventListener(lib.config.touchscreen ? "touchend" : "click", a => { + event._result = { + bool: true, + hurt: a.target.id, + }; + dialog.close(); + game.resume(); + dialog.close(); + game.resume(); + _status.imchoosing = false; + resolve(event._result); + }); + list.push(num_px); + } + const selectedList = list.filter(i => places.includes(i.id)) + for (const i of selectedList) target_img.appendChild(i); + dialog.open(); + game.pause(); + game.countChoose(); + return promise; + }; + let next; + if (event.isMine()) { + next = chooseButton(places, target); + } else if (event.isOnline()) { + const { promise, resolve } = Promise.withResolvers(); + event.player.send(chooseButton, places, target); + event.player.wait(async result => { + if (result == "ai") result = await switchToAuto(); + resolve(result); + }); + game.pause(); + next = promise; + } else { + next = switchToAuto(); + } + const result = await next; + game.resume(); + if (result.bool) { + player.line(target); + const place = result.hurt; + player.popup(place, "fire"); + game.log(player, "击伤了", target, "的", "#y" + get.translation(place)); + target.addSkill("1!5!_injury"); + target.markAuto("1!5!_injury", [place]); + switch (parseInt(place.slice("1!5!_place".length))) { + case 1: + if (target.getHp() > 0) { + await target.loseHp(target.getHp()); + if (game.getGlobalHistory("everything", evt => { + if (evt.name != "die" || evt.player != target) return false; + return evt.reason?.getParent() == event; + }).length > 0) { + await player.gainMaxHp(); + } + } + break; + case 2: + const cards = target + .getEquips(1) + .slice() + .concat(target.getEquips("equip3_4")) + .filter(card => lib.filter.canBeDiscarded(card, player, target)); + if (cards.length) await target.discard(cards).set("discarder", player); + break; + case 3: + target.addTempSkill("1!5!_maxhand", { player: "phaseEnd" }); + break; + case 4: + const cardx = target.getDiscardableCards(target, "h"); + const num = Math.floor(cardx.length / 2); + if (cardx.length) await target.discard(cardx.randomGets(num)); + break; + case 5: + target.addTempSkill("1!5!_damage", { player: "phaseEnd" }); + break; + case 6: + target.addTempSkill("1!5!_use", { player: "phaseEnd" }); + break; + case 7: + target.addTempSkill("1!5!_respond", { player: "phaseEnd" }); + break; + } + } + }, + marktext: "赤", + intro: { content: "mark" }, + frequent: true, + derivation: ["1!5!_place1", "1!5!_place4", "1!5!_place5", "1!5!_place6", "1!5!_place7"], + subSkill: { + injury: { + charlotte: true, + }, + maxhand: { + charlotte: true, + mark: true, + marktext: "伤", + intro: { + name: "中伤 - 手部", + content: "手牌上限变为原来的一半(向下取整)", + }, + mod: { + maxHandcard(player, num) { + if (_status["1!5!_maxhand"]) return; + _status["1!5!_maxhand"] = true; + const numx = player.getHandcardLimit(); + delete _status["1!5!_maxhand"]; + return num - Math.ceil(numx); + }, + }, + }, + damage: { + charlotte: true, + mark: true, + marktext: "伤", + intro: { + name: "中伤 - 下肢", + content: "体力值大于1时,受到的伤害+1", + }, + trigger: { player: "damageBegin2" }, + filter(event, player) { + return player.getHp() > 1; + }, + forced: true, + popup: false, + content() { + trigger.num++; + }, + }, + use: { + charlotte: true, + forced:true, + mark: true, + marktext: "伤", + intro: { + name: "中伤 - 胸部", + content: (_, player) => (_status.currentPhase === player ? "" : "下回合") + "使用伤害牌造成的伤害-1", + }, + trigger:{ + source: "damageBegin2", + }, + filter(event, player){ + if (get.tag(event.card, "damage")) return true; + }, + async content(event, trigger, player) { + trigger.num -= 1; + } + }, + respond: { + charlotte: true, + mark: true, + marktext: "伤", + intro: { + name: "中伤 - 腹部", + content: (_, player) => "不能使用【闪】和【桃】", + }, + mod: { + cardEnabled(card) { + if (card.name == "shan" || card.name == "tao") return false; + }, + cardSavable(card) { + if (card.name == "tao") return false; + }, + }, + }, + }, + }, + chiren: { + audio: 2, + trigger:{ + player: "phaseUseBegin", + }, + async cost (event, trigger, player) { + let list = ["摸体力值张牌,此阶段【杀】无距离限制且不能被响应。", "摸已损失体力值张牌,此阶段造成伤害后,回复1点体力。"]; + let result = await player.chooseControlList(list).set("ai", function(){ + //等157优化) + return Math.random(); + }).forResult(); + event.result = { + bool: result.control != "cancel2", + cost_data: result.control, + } + }, + async content(event, trigger, player) { + if (event.cost_data == "选项一") { + player.draw(player.getHp()); + player.addTempSkill("chiren_directHit", {player:"phaseUseEnd"}); + } else { + player.draw(player.getDamagedHp()); + player.addTempSkill("chiren_recover", {player:"phaseUseEnd"}); + } + }, + subSkill:{ + directHit: { + charlotte:true, + forced:true, + mod:{ + targetInRange:function(card){ + if(card.name == "sha") return true; + } + }, + trigger: { + player: "useCard", + }, + filter:function(event, player){ + return event.card.name == "sha"; + }, + content:async function (event, trigger, player) { + trigger.directHit.addArray(game.players); + game.log(trigger.card, "不可被响应"); + } + }, + recover: { + trigger: { + source: "damageSource", + }, + forced:true, + charlotte:true, + filter:function(event, player){ + return player.isDamaged(); + }, + content:async function (event, trigger, player) { + player.recover(); + } + }, + } + }, //应天司马懿!肯定又要修改 jilin: { audio: 5, @@ -9,13 +356,14 @@ const skills = { global: "phaseBefore", player: "enterGame", }, - forced: true, - locked: false, filter(event, player) { return event.name != "phase" || game.phaseNumber == 0; }, + forced: true, + locked: false, + logAudio: () => 1, async content(event, trigger, player) { - const cards = get.cards(3); + const cards = get.cards(get.mode() == "doudizhu" ? 1 : 2); const next = player.addToExpansion(cards, "draw"); next.gaintag.add(event.name); await next; @@ -62,6 +410,7 @@ const skills = { subSkill: { kanpo: { audio: "jilin", + logAudio: () => ["jilin2.mp3", "jilin3.mp3"], trigger: { target: "useCardToTarget", }, @@ -113,6 +462,7 @@ const skills = { }, change: { audio: "jilin", + logAudio: () => ["jilin4.mp3", "jilin5.mp3"], trigger: { player: "phaseBegin", }, @@ -198,6 +548,7 @@ const skills = { cost_data: links, }; }, + logAudio: () => 2, async content(event, trigger, player) { event.cost_data[0].storage.jilin = true; const num = player.getExpansions("jilin").filter(card => card.storage.jilin).length; @@ -210,6 +561,7 @@ const skills = { subSkill: { draw: { audio: "yingyou", + logAudio: () => ["yingyou3.mp3", "yingyou4.mp3"], trigger: { player: "loseAfter", global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], @@ -281,13 +633,13 @@ const skills = { if (player.getRoundHistory("useSkill", evt => evt.skill == "xinrenjie").length >= 4) return false; if (event.name == "useCard") { //...... - if (get.type(event.card) != "trick") return false; + if (event.player == player || get.type(event.card) != "trick") return false; const history = game.getGlobalHistory("everything", evt => evt.player == player && ["useCard", "respond"].includes(evt.name)); return !history.some(evt => Array.isArray(evt.respondTo) && evt.respondTo[1] == event.card && evt.card.name == "wuxie"); } const evt = event.getParent(2); - if (!evt || evt.name != "useCard") return false; - return !event.result.bool; + if (!evt || evt.name != "useCard" || evt.player == player) return false; + return event.respondTo && !event.result.bool; }, forced: true, async content(event, trigger, player) { @@ -486,7 +838,7 @@ const skills = { ["shu", "rejizhi"], ["wu", "rezhiheng"], ["qun", "rewansha"], - ["key", "hiroto_zonglve"] + ["key", "hiroto_zonglve"], ]); if (Array.from(groupList.keys()).includes(player.group)) skills.push(groupList.get(player.group)); skills = skills.filter(skill => !player.hasSkill(skill, null, null, false)); @@ -587,7 +939,8 @@ const skills = { return lib.filter.cardDiscardable(card, target, "lvxin"); }); if (cards.length > 0) { - const evt = await target.discard(cards.randomGets(round)).set("discarder", target); + const evt = target.discard(cards.randomGets(round)).set("discarder", target); + await evt; cards2 = evt.done.cards2; } } @@ -733,7 +1086,7 @@ const skills = { if (!bool) { target.chat("拒绝"); game.log(target, "拒绝获得技能", `#g【${get.translation(skillToGain)}】`); - await game.asyncDelay(); + await game.delay(); return; } await target.addSkills(skillToGain); @@ -858,24 +1211,22 @@ const skills = { if (current.hasMark("zhengqing")) current.clearMark("zhengqing"); }); const [num, players] = lib.skill.zhengqing.getMostInfoLastRound(); - player.line(players, "thunder"); - const onlyMe = players.length === 1 && players[0] === player; + let target; + if (players.length === 1) target = players[0]; + else if (players.includes(player)) target = player; + else target = players.randomGet(); + player.line(target, "thunder"); const isMax = (player .getAllHistory("custom", evt => evt && evt.zhengqing_count) .map(evt => evt.zhengqing_count) .sort((a, b) => b - a)[0] || 0) <= num; - players.forEach(current => { - current.addMark("zhengqing", num); - }); - if (onlyMe && isMax) { + target.addMark("zhengqing", num); + if (target === player && isMax) { player.draw(Math.min(5, num)); player.getHistory("custom").push({ zhengqing_count: num }); } else { - const drawers = [player].concat(players).sortBySeat(trigger.player); - for (const drawer of drawers) { - await drawer.draw(); - } + await game.asyncDraw([player, target].sortBySeat(trigger.player)); } }, marktext: "擎", @@ -1151,15 +1502,11 @@ const skills = { ], ], ]); - next.set("processAI", list => { - const listx = list[0][1][0]; - const me = listx.find(info => parseInt(info.split("|")[0]) == get.player().getSeatNum()); - listx.randomSort(); - if (me) { - listx.remove(me); - listx.unshift(me); - } - return [listx]; + next.set("toSortPlayers", toSortPlayers.slice(0)); + next.set("processAI", () => { + const players = get.event("toSortPlayers"), player = get.player(); + players.randomSort().sort((a, b) => get.attitude(player, b) - get.attitude(player, a)); + return [players.map(i => `${i.getSeatNum()}|${i.name}`)]; }); const { result } = await next; if (!result.bool) return; @@ -1200,7 +1547,7 @@ const skills = { } }); } - await game.asyncDelay(); + await game.delay(); }, }, //什么均贫卡 @@ -1254,7 +1601,7 @@ const skills = { lose_list: lose_list, }) .setContent("chooseToCompareLose"); - await game.asyncDelay(); + await game.delay(); cards = cards.filterInD(); const pcards = cards.randomGets(Math.ceil(cards.length / 2)); const tcards = cards.removeArray(pcards); @@ -1596,42 +1943,44 @@ const skills = { game.addGlobalSkill("jxlianpo_global"); }, onremove: () => { - if (!game.hasPlayer(i => i.hasSkill("jxlianpo"), true)) game.removeGlobalSkill("jxlianpo_global"); + if (!game.hasPlayer(i => i.hasSkill("jxlianpo", null, null, false), true)) game.removeGlobalSkill("jxlianpo_global"); }, trigger: { global: "dieAfter" }, filter(event, player) { - if (lib.skill.jxlianpo.getMax().length <= 1) return false; + if (lib.skill.jxlianpo.getMax(event.player).length <= 1) return false; return event.source && event.source.isIn(); }, forced: true, logTarget: "source", - getMax: () => { + getMax: dead => { + let curs = game.players.slice(0); + if (get.itemtype(dead) === "player" && !curs.includes(dead)) curs.push(dead); const map = { - zhu: game.countPlayer(current => { + zhu: curs.filter(current => { const identity = current.identity; let num = 0; if (identity == "zhu" || identity == "zhong" || identity == "mingzhong") num++; num += current.countMark("jxlianpo_mark_zhong"); return num; - }), - fan: game.countPlayer(current => { + }).length, + fan: curs.filter(current => { let num = 0; if (current.identity == "fan") num++; num += current.countMark("jxlianpo_mark_fan"); return num; - }), - nei: game.countPlayer(current => { + }).length, + nei: curs.filter(current => { let num = 0; if (current.identity == "nei") num++; num += current.countMark("jxlianpo_mark_nei"); return num; - }), - commoner: game.countPlayer(current => { + }).length, + commoner: curs.filter(current => { let num = 0; if (current.identity == "commoner") num++; num += current.countMark("jxlianpo_mark_commoner"); return num; - }), + }).length, }; let population = 0, identities = []; @@ -1785,7 +2134,7 @@ const skills = { }, trigger: { player: "dieAfter" }, filter: () => { - return !game.hasPlayer(i => i.hasSkill("jxlianpo"), true); + return !game.hasPlayer(i => i.hasSkill("jxlianpo", null, null, false), true); }, silent: true, forceDie: true, @@ -1992,12 +2341,13 @@ const skills = { list ); var cards = list.map(function (name) { - var card = game.createCard("qiexie_" + name, "none", get.infoMaxHp(lib.character[name][2])); + var card = game.createCard("qiexie_" + name, "none", "none"); return card; }); player.$gain2(cards); game.delayx(); - for (var card of cards) player.equip(card); + player.equip(cards); + //for (var card of cards) player.equip(card); } }, $createButton(item, type, position, noclick, node) { @@ -2489,15 +2839,11 @@ const skills = { ai: { effect: { player(card, player, target) { - if ( - !get.tag(card, "damage") || - player.countMark("dcxianjin") % 2 || - !player.hasSkillTag("jueqing", false, target) - ) return; + if (!get.tag(card, "damage") || player.countMark("dcxianjin") % 2 || player.hasSkillTag("jueqing", false, target)) return; if (player.isMaxHandcard()) return [1, 1]; return [1, Math.min(3, 1 + player.getStorage("dctuoyu").length)]; - } - } + }, + }, }, }, dcqijing: { @@ -2570,7 +2916,7 @@ const skills = { audio: 2, trigger: { player: "useCardAfter" }, filter(event, player) { - if (!event._dccuixin || get.type(event.card, false) == "delay" || get.type(event.card, false) == "equip") return false; + if (!event._dccuixin || get.type(event.card, null, false) == "delay" || get.type(event.card, null, false) == "equip") return false; var card = { name: event.card.name, nature: event.card.nature, @@ -3058,7 +3404,12 @@ const skills = { ai: { effect: { target(card, player, target, current) { - if (get.tag(card, "damage") && current < 0) return 1.6; + if (get.tag(card, "damage") && current < 0 && !target._shencai_losehp_effect) { + target._shencai_losehp_effect = true; + let eff = get.effect(target, { name: "losehp" }, target, target) / 10; + delete target._shencai_losehp_effect; + return [1, eff]; + } }, }, }, @@ -4063,7 +4414,7 @@ const skills = { ai: { effect: { target(card) { - if (get.type(card) == "delay") return "zerotarget"; + if (get.type(card) == "delay") return "zeroplayertarget"; }, }, }, @@ -4224,7 +4575,7 @@ const skills = { trigger: { player: "useCardToTargeted" }, forced: true, filter(event, player) { - if (get.type(event.card, false) != "equip" || player != event.target || event.card.name.indexOf("changandajian_equip") == 0) return false; + if (get.type(event.card, null, false) != "equip" || player != event.target || event.card.name.indexOf("changandajian_equip") == 0) return false; if (!player.storage.yuheng) return false; var list = ["xinfu_guanchao", "drlt_jueyan", "lanjiang"]; for (var i of list) { @@ -4265,7 +4616,7 @@ const skills = { }, }, ai: { - combo: "yuheng" + combo: "yuheng", }, }, yuheng: { @@ -4559,7 +4910,7 @@ const skills = { return 0; }, }, - combo: "tianren" + combo: "tianren", }, subSkill: { effect: { @@ -4797,7 +5148,7 @@ const skills = { }, ai: { effect: { - target_use(card, player, target) { + target(card, player, target) { if (card && card.name == "qizhengxiangsheng") return "zeroplayertarget"; }, }, @@ -4928,7 +5279,7 @@ const skills = { let num = 0, nohave = true; game.countPlayer(i => { - if (i.hasSkill("lingce")) { + if (i.hasSkill("lingce", null, null, false)) { nohave = false; if (i.isIn() && lib.skill.lingce.filter({ card: card }, i)) num += get.sgnAttitude(player, i); } @@ -5059,7 +5410,7 @@ const skills = { group: ["tspowei_init", "tspowei_move", "tspowei_achieve", "tspowei_fail", "tspowei_use", "tspowei_remove"], subSkill: { remove: { - audio: "tspowei3", + audio: "tspowei3.mp3", trigger: { global: "damageEnd" }, filter(event, player) { return event.player && event.player.isIn() && event.player.hasMark("dulie"); @@ -5071,7 +5422,7 @@ const skills = { }, }, use: { - audio: "tspowei3", + audio: "tspowei3.mp3", trigger: { global: "phaseBegin" }, direct: true, filter(event, player) { @@ -5134,7 +5485,7 @@ const skills = { }, }, init: { - audio: "tspowei3", + audio: "tspowei3.mp3", trigger: { global: "phaseBefore", player: "enterGame", @@ -5152,7 +5503,7 @@ const skills = { }, }, move: { - audio: "tspowei3", + audio: "tspowei3.mp3", trigger: { player: "phaseBegin" }, forced: true, filter(event, player) { @@ -5174,7 +5525,7 @@ const skills = { }, }, achieve: { - audio: "tspowei1", + audio: "tspowei1.mp3", trigger: { player: "phaseBegin" }, forced: true, skillAnimation: true, @@ -5191,7 +5542,7 @@ const skills = { }, }, fail: { - audio: "tspowei2", + audio: "tspowei2.mp3", trigger: { player: "dying" }, forced: true, content() { @@ -5206,9 +5557,6 @@ const skills = { }, }, }, - tspowei1: { audio: true }, - tspowei2: { audio: true }, - tspowei3: { audio: true }, shenzhu: { audio: 2, trigger: { player: "useCardAfter" }, @@ -6119,7 +6467,7 @@ const skills = { ? event.numFixed : !game.hasPlayer(function (current) { return current.hasEnabledSlot(); - }) + }) ) return false; return ( @@ -6278,7 +6626,8 @@ const skills = { effect: { target: (card, player, target) => { if (!target.hasFriend()) return; - let rec = get.tag(card, "recover"), damage = get.tag(card, "damage"); + let rec = get.tag(card, "recover"), + damage = get.tag(card, "damage"); if (!rec && !damage) return; if (damage && player.hasSkillTag("jueqing", false, target)) return 1.7; let die = [null, 1], @@ -6856,7 +7205,7 @@ const skills = { combo: "sbaiyin", effect: { target(card, player, target) { - if (!target.hasSkill("sbaiyin") && !target.hasSkill("jilue") || !target.hasFriend()) return; + if ((!target.hasSkill("sbaiyin") && !target.hasSkill("jilue")) || !target.hasFriend()) return; if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; if (get.tag(card, "damage")) { if (target.hp == target.maxHp) { @@ -8127,9 +8476,8 @@ const skills = { if (filter(get.autoViewAs({ name: "wuxie" }, "unsure"), player, event) && player.countCards("hs", { suit: "spade" })) return true; return false; }, - precontent() { - delete event.result.skill; - player.logSkill("longhun" + (4 - lib.suit.indexOf(get.suit(event.result.cards[0], player)))); + logAudio(event, player) { + return "longhun" + (4 - lib.suit.indexOf(get.suit(event.cards[0], player))) + ".mp3"; }, ai: { respondSha: true, diff --git a/character/extra/sort.js b/character/extra/sort.js index 9cafd46f9b..42938761ba 100644 --- a/character/extra/sort.js +++ b/character/extra/sort.js @@ -5,7 +5,7 @@ const characterSort = { extra_shan: ["shen_zhaoyun", "shen_simayi"], extra_yin: ["shen_liubei", "shen_luxun"], extra_lei: ["shen_ganning", "shen_zhangliao"], - extra_decade: ["shen_jiangwei", "shen_machao", "shen_zhangfei", "shen_zhangjiao", "shen_dengai", "shen_xuzhu", "dc_shen_huatuo"], + extra_decade: ["shen_huangzhong", "shen_jiangwei", "shen_machao", "shen_zhangfei", "shen_zhangjiao", "shen_dengai", "shen_xuzhu", "dc_shen_huatuo"], extra_ol: ["ol_zhangliao", "shen_caopi", "shen_zhenji", "shen_sunquan"], extra_mobilezhi: ["shen_guojia", "shen_xunyu"], extra_mobilexin: ["shen_taishici", "shen_sunce"], diff --git a/character/extra/translate.js b/character/extra/translate.js index 4c9cbf0da7..d993ca09c6 100644 --- a/character/extra/translate.js +++ b/character/extra/translate.js @@ -313,7 +313,7 @@ const translates = { juanjia: "捐甲", juanjia_info: "锁定技。游戏开始时,你废除一个防具栏,然后获得一个额外的武器栏。", qiexie: "挈挟", - qiexie_info: "锁定技。准备阶段,你在剩余武将牌堆中随机观看五张牌,选择其中的任意张,将其按照如下规则转化为武器牌置入你的武器栏:{⒈此牌不具有花色,且其攻击范围和点数等于此武将牌的体力上限。⒉此武器牌的技能为该武将牌上所有描述中包含“【杀】”且不具有锁定技以外的标签的技能。⒊此武器牌离开你的装备区时,改为放回武将牌堆。}", + qiexie_info: "锁定技。准备阶段,你在剩余武将牌堆中随机观看五张牌,选择其中的任意张,将其按照如下规则转化为武器牌置入你的武器栏:{⒈此牌不具有花色和点数,且其攻击范围等于此武将牌的体力上限。⒉此武器牌的技能为该武将牌上所有描述中包含“【杀】”且不具有锁定技以外的标签的技能。⒊此武器牌离开你的装备区时,改为放回武将牌堆。}", cuijue: "摧决", cuijue_info: "每回合每名角色限一次。出牌阶段,你可以弃置一张牌,然后对攻击范围内距离最远的一名其他角色造成1点伤害(没有则不选)。", le_shen_jiaxu: "神贾诩", @@ -345,7 +345,7 @@ const translates = { shen_xuzhu: "神许褚", shen_xuzhu_prefix: "神", zhengqing: "争擎", - zhengqing_info: "锁定技。一轮游戏开始时,你移去所有角色的“擎”标记,令上一轮于一回合内造成伤害值最多的角色各获得X枚“擎”,且你与这些角色各摸一张牌(X为这些角色该回合内造成的伤害值)。若该角色为你且本次获得的“擎”数为本局游戏最多的一次,你改为摸X张牌(至多摸五张)。", + zhengqing_info: "锁定技。一轮游戏开始时,你移去所有角色的“擎”标记,令上一轮于一回合内造成伤害值最高的角色获得此值数量枚“擎”,然后你与其各摸一张牌(多名角色则随机选择,优先为你)。若该角色为你且本次获得的“擎”数为本局游戏最多的一次,你改为摸X张牌(至多摸五张)。", zhuangpo: "壮魄", zhuangpo_info: "你可以将牌名为【杀】或牌面信息中包含“【杀】”的牌当【决斗】使用,然后你获得如下效果:1.当此【决斗】指定目标后,若你有“擎”,你可以移去任意枚“擎”,令目标角色弃置等量的牌;2.当你造成渠道为此牌的伤害时,若此牌的所有目标角色中存在有“擎”的角色,此伤害+1。", dc_shen_huatuo: "神华佗", @@ -360,7 +360,7 @@ const translates = { xin_simayi_ab: "手杀神司马懿", xin_simayi_prefix: "手杀神", xinrenjie: "忍戒", - xinrenjie_info: "锁定技,当你需要响应一张牌时,若你未响应此牌,你获得1枚“忍”标记(你每轮以此法至多获得4枚“忍”标记)。", + xinrenjie_info: "锁定技,当你需要响应其他角色的一张牌时,若你未响应此牌,你获得1枚“忍”标记(你每轮以此法至多获得4枚“忍”标记)。", xinbaiyin: "拜印", xinbaiyin_info: "觉醒技,准备阶段,若你的“忍”标记数不小于4,你减少1点体力上限,然后获得〖极略〗。", xinlianpo: "连破", @@ -371,11 +371,33 @@ const translates = { new_simayi_ab: "手杀神司马懿", new_simayi_prefix: "手杀神", jilin: "戢鳞", - jilin_info: "①游戏开始时,将牌堆顶三张牌暗置于你的武将牌上,称为“志”。②当你成为其他角色使用牌的目标时,你可以明置一张暗置的“志”令此牌对你无效。③回合开始时,你可用任意张手牌替换等量暗置的“志”。", + jilin_info: "①游戏开始时,你将牌堆顶两张牌暗置于你的武将牌上,称为“志”。②当你成为其他角色使用牌的目标时,你可以明置一张暗置的“志”令此牌对你无效。③回合开始时,你可用任意张手牌替换等量暗置的“志”。", + //太幽默了我超 + jilin_info_doudizhu: "①游戏开始时,你将牌堆顶一张牌暗置于你的武将牌上,称为“志”。②当你成为其他角色使用牌的目标时,你可以明置一张暗置的“志”令此牌对你无效。③回合开始时,你可用任意张手牌替换等量暗置的“志”。", yingyou: "英猷", yingyou_info: "①出牌阶段开始时,你可明置一张“志”然后摸X张牌(X为明置的“志”的数量)。②当你失去与明置的“志”其中一张花色相同的牌时,你摸一张牌。", yingtian: "应天", yingtian_info: "觉醒技。一名角色死亡后,若场上势力数不大于2,则你获得〖鬼才〗、〖完杀〗、〖连破〗并失去〖英猷〗且你本局游戏使用牌没有距离限制。", + shen_huangzhong: "神黄忠", + shen_huangzhong_prefix: "神", + "1!5!": "毅武", + "1!5!_info": "当你对一名其他角色造成伤害后,你可以在任意部位中选择一个“击伤”;若你击伤了一名角色,则再次击伤该角色时出现“头部”选项。", + "1!5!_place1": "头部", + "1!5!_place1_info": "令其失去所有体力", + //"1!5!_place2": "肩部", + //"1!5!_place2_info": "令其弃置装备区里的武器牌和坐骑牌", + //"1!5!_place3": "手部", + //"1!5!_place3_info": "令其手牌上限视为原来的一半(向下取整)直到其下个回合结束。", + "1!5!_place4": "上肢", + "1!5!_place4_info": "令其随机弃置一半手牌(向下取整)", + "1!5!_place5": "下肢", + "1!5!_place5_info": "令其体力值大于1时受到的伤害+1直到其下个回合结束", + "1!5!_place6": "胸部", + "1!5!_place6_info": "令其下个回合不能使用伤害牌", + "1!5!_place7": "腹部", + "1!5!_place7_info": "令其不能使用【闪】和【桃】直到其下个回合结束", + chiren: "赤刃", + chiren_info: "出牌阶段开始时,你可以选择一项:1.摸体力值张牌,此阶段【杀】无距离限制且不能被响应。2.摸已损失体力值张牌,此阶段造成伤害后,回复1点体力。", }; export default translates; diff --git a/character/gujian.js b/character/gujian.js index 5637a621e7..effcc05bd1 100644 --- a/character/gujian.js +++ b/character/gujian.js @@ -657,20 +657,6 @@ game.import("character", function () { }, }, }, - xunjian_old: { - trigger: { player: "phaseEnd" }, - filter(event, player) { - return player.storage.lingyan && player.storage.lingyan.length == 13; - }, - forced: true, - unique: true, - skillAnimation: true, - content() { - player.awakenSkill("xunjian"); - player.removeSkill("lingyan"); - player.addSkill("tongtian"); - }, - }, xunjian: { trigger: { player: ["useCard", "respond"] }, forced: true, @@ -686,33 +672,6 @@ game.import("character", function () { } }, }, - tongtian: { - trigger: { player: ["useCardAfter", "respondAfter"] }, - forced: true, - filter(event, player) { - var name = event.card.name; - var enemies = player.getEnemies(); - for (var i = 0; i < enemies.length; i++) { - if (enemies[i].countCards("h", name)) { - return true; - } - } - }, - content() { - var list = []; - var name = trigger.card.name; - var enemies = player.getEnemies(); - for (var i = 0; i < enemies.length; i++) { - list.addArray(enemies[i].getCards("h", name)); - } - if (list.length) { - var card = list.randomGet(); - var owner = get.owner(card); - player.line(owner, "green"); - owner.give(card, player, true); - } - }, - }, lingyan: { enable: "phaseUse", usable: 1, @@ -1273,7 +1232,7 @@ game.import("character", function () { }, ai: { effect: { - target_use(card, player, target, current) { + target(card, player, target, current) { if (get.color(card) == "red" && target.isDamaged()) return [1, 1]; }, }, @@ -1464,7 +1423,7 @@ game.import("character", function () { ai: { halfneg: true, effect: { - player_use(card, player, target, current) { + player(card, player, target, current) { if (get.color(card) == "red") return [1, 0, 1, -2]; }, }, @@ -2312,67 +2271,6 @@ game.import("character", function () { threaten: 1.1, }, }, - jizhan: { - enable: "phaseUse", - usable: 1, - changeSeat: true, - filterTarget(card, player, target) { - return player != target && player.next != target && player.canUse("sha", target, false); - }, - filter(event, player) { - var min = Math.max(1, player.maxHp - player.hp); - return lib.filter.filterCard({ name: "sha" }, player); - }, - content() { - game.swapSeat(player, target, true, true); - player.useCard({ name: "sha" }, target, false); - }, - ai: { - result: { - target(player, target) { - return get.effect(target, { name: "sha" }, player, target); - }, - }, - order: 4, - }, - }, - qianjun: { - trigger: { player: "useCard" }, - direct: true, - filter(event, player) { - if (event.card.name != "sha") return false; - if (event.targets.length != 1) return false; - if (!player.countCards("he")) return false; - var target = event.targets[0]; - return game.hasPlayer(function (current) { - return player != current && target != current && get.distance(target, current) <= 1; - }); - }, - content() { - "step 0"; - event.targets = game.filterPlayer(function (current) { - var target = trigger.targets[0]; - return player != current && target != current && get.distance(target, current) <= 1; - }); - var num = 0; - for (var i = 0; i < event.targets.length; i++) { - num += get.effect(event.targets[i], { name: "sha" }, player, player); - } - var next = player.chooseToDiscard(get.prompt("qianjun", event.targets), "he"); - next.logSkill = ["qianjun", event.targets]; - next.ai = function (card) { - if (num <= 0) return -1; - return 7 - get.value(card); - }; - "step 1"; - if (result.bool) { - for (var i = 0; i < targets.length; i++) { - trigger.targets.add(targets[i]); - // targets[i].classList.add('selected'); - } - } - }, - }, xuanning: { group: ["xuanning1", "xuanning2"], intro: { @@ -2680,7 +2578,7 @@ game.import("character", function () { threaten: 0.8, effect: { target(card, player, target) { - if (card.name == "bingliang") return 0; + if (card.name == "bingliang") return [0, 0]; if (card.name == "lebu") return 1.5; if (card.name == "guohe") { if (!target.countCards("e")) return 0; @@ -2801,9 +2699,6 @@ game.import("character", function () { xunjian: "寻剑", xunjian_info: "锁定技,每当你使用或打出一张牌,若牌堆中有同名牌,你有X的机率获得之,X为你的“灵偃”牌数/13。", - xunjian_old_info: "觉醒技,结束阶段,若你武将牌上有十三张牌,你失去技能灵偃并获得技能通天。", - tongtian: "通天", - tongtian_info: "锁定技,在你使用或打出一张牌后,若敌方角色手中有同名牌,你随机获得其中一张。", xianju: "仙居", xianju_info: "锁定技,奇数游戏轮次开始时,你获得潜行直到下一轮开始;偶数游戏轮次开始时,你随机获得一张机关牌。", @@ -2905,11 +2800,6 @@ game.import("character", function () { boyun2: "拨云", boyun_info: "在你的回合内,你可以弃置一张装备牌,并展示牌堆顶的一张牌,若其为装备牌,你须将其交给任意一张角色并对其造成1点伤害,否则你摸一张牌。", - jizhan: "疾战", - jizhan_info: - "出牌阶段限一次,你可以移动到任意一名角色的前一位,视为对其使用了一张不计入出杀次数的【杀】。", - qianjun: "千军", - qianjun_info: "每当你使用一张【杀】,你可以弃置一张牌,令距离目标1以内的所有角色成为额外目标。", xuanning: "玄凝", xuanning1: "玄凝", xuanning2: "玄凝", diff --git a/character/gwent.js b/character/gwent.js index 8cd92d6f45..17f67b9686 100644 --- a/character/gwent.js +++ b/character/gwent.js @@ -208,6 +208,7 @@ game.import("character", function () { filter(event, player) { return player.countCards("h") > 0; }, + derivation: ["sqlongnu", "sqlonghuo"], content() { "step 0"; var max = 1; @@ -1109,10 +1110,10 @@ game.import("character", function () { target.countCards("he") && current < 0 ) { - return 0; + return [1, 2]; } }, - player(card, player) { + player_use(card, player) { if (player.hujia >= 3) return; if (_status.event.name != "chooseToUse" || _status.event.player != player) return; if (get.type(card) == "basic") return; @@ -1237,7 +1238,7 @@ game.import("character", function () { nodamage: true, effect: { target(card, player, target, current) { - if (get.tag(card, "damage")) return [0, 0]; + if (get.tag(card, "damage")) return "zeroplayertarget"; }, }, }, @@ -1249,6 +1250,7 @@ game.import("character", function () { }, unique: true, onremove: true, + derivation: "gwzhongmo", group: "gwfutian_discard", subSkill: { discard: { @@ -1517,6 +1519,7 @@ game.import("character", function () { gwchenshui: { trigger: { player: "damageBefore", source: "damageBefore" }, forced: true, + derivation: "gwliedi", init(player) { player.storage.gwchenshui = 0; }, @@ -2284,7 +2287,7 @@ game.import("character", function () { effect: { target(card, player, target) { if (game.roundNumber % 3 != 0 && get.tag(card, "damage")) { - return [0, 0]; + return "zeroplayertarget"; } }, }, @@ -3161,58 +3164,6 @@ game.import("character", function () { player.draw(); }, }, - gwchuanxin_old: { - trigger: { player: "shaAfter" }, - filter(event, player) { - if (player.storage.gwchuanxin && player.storage.gwchuanxin.length >= 4) return false; - return event.target.isAlive(); - }, - check(event, player) { - return get.effect(event.target, { name: "sha" }, player, player) > 0; - }, - logTarget: "target", - logLine: false, - content() { - "step 0"; - event.card = get.cards()[0]; - player.showCards( - event.card, - get.translation(player) + "对" + get.translation(trigger.player) + "发动了【穿心】" - ); - "step 1"; - if ( - player.storage.gwchuanxin && - !player.storage.gwchuanxin.includes(get.suit(event.card)) - ) { - player.useCard({ name: "sha" }, [event.card], trigger.target, false); - } - }, - group: ["gwchuanxin_count1", "gwchuanxin_count2"], - subSkill: { - count1: { - trigger: { global: "phaseBegin" }, - silent: true, - content() { - player.storage.gwchuanxin = []; - }, - }, - count2: { - trigger: { player: "useCard" }, - silent: true, - // filter(event){ - // return event.card&&event.card.name=='sha'; - // }, - content() { - for (var i = 0; i < trigger.cards.length; i++) { - player.storage.gwchuanxin.add(get.suit(trigger.cards[i])); - } - }, - }, - }, - ai: { - presha: true, - }, - }, gwchuanxin: { trigger: { player: "shaAfter" }, filter(event, player) { @@ -4774,7 +4725,6 @@ game.import("character", function () { kuanglie: "狂猎", kuanglie_info: "锁定技,每当你使用黑色牌指定其他角色为目标后,目标随机弃置一张牌;每当你以此法累计弃置两张牌后,你摸一张牌。", - // kuanglie_info:'锁定技,每当一名敌方角色成为你的黑色牌的目标,你视为对其使用【刺骨寒霜】;在一名角色受到【刺骨寒霜】的影响后,你随机获得一张【狂猎】牌。', lingshuang: "凛霜", lingshuang_info: "每当你失去最后一张基本牌,你可以视为对距离2以内的所有敌方角色使用【刺骨寒霜】;在一名角色受到【刺骨寒霜】影响时,你可以弃置一张手牌将其效果改为“摸牌数-2”。", diff --git a/character/hearth.js b/character/hearth.js index b314ead876..4fa29cbe65 100644 --- a/character/hearth.js +++ b/character/hearth.js @@ -82,18 +82,13 @@ game.import("character", function () { hs_walian: ["male", "shu", 4, ["wzhanyi"]], hs_pengpeng: ["male", "qun", 4, ["yindan"]], hs_yashaji: ["male", "qun", 4, ["ysjqisha"]], - // hs_wolazi:['male','wei',3,[]], hs_tanghangu: ["male", "shu", 5, ["zhongji"]], hs_aya: ["female", "wu", 3, ["ayuling", "qingzun"]], hs_barnes: ["male", "shu", 4, ["hsnitai"]], - // hs_nuogefu:['male','wei',3,[]], hs_kazhakusi: ["male", "shu", 3, ["lianjin"]], - // hs_lazi:['male','wei',3,[]], hs_shaku: ["male", "wei", 3, ["shouji"]], hs_laxiao: ["male", "shu", 3, ["hsguimou", "yingxi", "hlongyi"]], - // hs_xiangyaqishi:['male','wei',3,[]], - // hs_fenjie:['male','shu',3,['hsguimou','yingxi']], hs_mojinbaozi: ["male", "wei", 3, ["jingcu", "shengzhang"]], hs_shuiwenxuejia: ["male", "wu", 3, ["kekao"]], hs_shizugui: ["male", "wu", 3, ["szbianshen"]], @@ -115,10 +110,6 @@ game.import("character", function () { hs_tgolem: ["male", "wu", 4, ["xinwuyan", "guozaix"]], hs_heifengqishi: ["male", "qun", 4, ["hstianqi"]], - // hs_yuhuozhe:['male','qun',4,['hstianqi']], - // hs_wuyaowang:['male','qun',4,['hstianqi']], - // hs_aerfusi:['male','qun',4,['hstianqi']], - // hs_baiguyoulong:['male','qun',4,['hstianqi']], hs_yangyanwageli: ["female", "qun", 3, ["hspuzhao", "hsyanxin"]], hs_aiqinvyao: ["female", "qun", 4, ["nsaiqi", "nsbeiming"]], @@ -128,7 +119,6 @@ game.import("character", function () { hs_ashamoer: ["female", "wei", 3, ["asyouzhang"]], hs_fengjianhuanfengzhe: ["male", "wei", 3, ["tuteng", "huanfeng"]], hs_taisi: ["female", "wei", 3, ["hsxingyi", "hshuanling"]], - // hs_bingshuangnvwang:['female','wei',3,['hsshuangshi','hs']] hs_hajiasha: ["female", "wu", 3, ["zhoujiang", "muyin"]], hs_tuoqi: ["female", "shu", 3, ["tqchuanyue"]], @@ -2251,7 +2241,7 @@ game.import("character", function () { effect: { target(card, player, target, current) { if (get.tag(card, "damage") && !get.tag(card, "fireDamage")) - return [0, 0]; + return "zeroplayertarget"; }, }, }, @@ -2496,7 +2486,7 @@ game.import("character", function () { }, ai: { effect: { - target_use(card, player, target) { + target(card, player, target) { if (get.type(card, "trick") == "trick" && player == target) return [1, 1]; }, }, @@ -2666,81 +2656,6 @@ game.import("character", function () { threaten: 1.5, }, }, - mengye_old: { - trigger: { player: "phaseAfter" }, - priority: -50, - direct: true, - filter(event, player) { - if ( - get.mode() == "identity" && - _status.mode == "zhong" && - game.zhu && - !game.zhu.isZhu && - player == game.zhong - ) { - return false; - } - if (_status.noswap) { - return false; - } - return !player.isTurnedOver(); - }, - content() { - "step 0"; - player.chooseTarget(get.prompt("mengye"), function (card, player, target) { - if (target == player) { - return false; - } - if ( - get.mode() == "identity" && - _status.mode == "zhong" && - game.zhu && - !game.zhu.isZhu - ) { - return target == game.zhong; - } - if (target.identity == "zhu" || get.is.jun(target)) return false; - return true; - }).ai = function (target) { - var att = -get.attitude(player, target); - if (att <= 0) return 0; - if (target.needsToDiscard()) att += 3; - else if (target.needsToDiscard(1)) att++; - else if (target.countCards() <= 3) { - return 0; - } - return att + target.countCards("h") + get.threaten(target); - }; - "step 1"; - if (result.bool) { - var target = result.targets[0]; - player.logSkill("mengye", target); - target.storage.mengye2 = player; - target.storage.mengye4 = target.ai.shown; - target.addSkill("mengye2"); - event.target = target; - player.turnOver(); - } else { - event.finish(); - } - "step 2"; - game.delay(); - "step 3"; - var target = event.target; - if (player == game.me) { - game.swapPlayerAuto(target); - target.storage.mengye3 = true; - } else { - target.addSkill("mad"); - target.unmarkSkill("mad"); - } - player.out("mengye"); - target.insertPhase(); - }, - ai: { - threaten: 2, - }, - }, mengye2: { temp: true, mark: "character", @@ -3028,38 +2943,6 @@ game.import("character", function () { event.goto(1); }, }, - gfuhun: { - trigger: { player: "phaseEnd" }, - direct: true, - filter(event, player) { - return player.countCards("h") > 0 && !player.isTurnedOver(); - }, - content() { - "step 0"; - player.chooseTarget(get.prompt("gfuhun"), function (card, player, target) { - return target != player && target.countCards("h") > 0; - }).ai = function (target) { - return -get.attitude(player, target); - }; - "step 1"; - if (result.bool) { - player.logSkill("gfuhun", result.targets); - event.target = result.targets[0]; - player.chooseToCompare(event.target); - } else { - event.finish(); - } - "step 2"; - if (result.bool) { - event.target.goMad({ player: "phaseAfter" }); - if (!player.isTurnedOver()) player.turnOver(); - } - }, - ai: { - expose: 0.2, - threaten: 1.5, - }, - }, qianhou: { trigger: { player: "phaseBegin" }, forced: true, @@ -3326,6 +3209,7 @@ game.import("character", function () { enable: "phaseUse", filterCard: true, position: "he", + derivation: ["yushou_misha", "yushou_huofu", "yushou_leiouke"], check(card) { var player = _status.event.player; var num = 0; @@ -4185,6 +4069,7 @@ game.import("character", function () { unique: true, trigger: { player: "phaseBegin" }, forced: true, + derivation: "nuyan2", skillAnimation: true, animationColor: "fire", filter(event, player) { @@ -4403,6 +4288,13 @@ game.import("character", function () { filter(event, player) { return !player.countCards("h", { type: "hsdusu" }); }, + derivation: [ + "hsdusu_xueji", + "hsdusu_huangxuecao", + "hsdusu_kuyecao", + "hsdusu_shinancao", + "hsdusu_huoyanhua", + ], content() { var list = [ "hsdusu_xueji", @@ -4428,6 +4320,13 @@ game.import("character", function () { oldduxin: { trigger: { player: ["phaseBegin", "phaseEnd"] }, frequent: true, + derivation: [ + "hsdusu_xueji", + "hsdusu_huangxuecao", + "hsdusu_kuyecao", + "hsdusu_shinancao", + "hsdusu_huoyanhua", + ], content() { var list = [ "hsdusu_xueji", @@ -4465,124 +4364,6 @@ game.import("character", function () { player.removeSkill("hsdusu_shinancao"); }, }, - kuangluan_old: { - group: ["kuangluan_count1", "kuangluan_count2", "kuangluan_use"], - subSkill: { - count1: { - trigger: { player: "useCard" }, - silent: true, - filter(event, player) { - return _status.currentPhase == player && get.type(event.card) == "trick"; - }, - content() { - player.storage.kuangluan++; - }, - }, - count2: { - trigger: { player: "phaseBegin" }, - silent: true, - content() { - player.storage.kuangluan = 0; - }, - }, - use: { - trigger: { player: "phaseUseEnd" }, - forced: true, - filter(event, player) { - return player.storage.kuangluan > 0; - }, - content() { - var list = []; - for (var i = 0; i < lib.inpile.length; i++) { - if (lib.filter.filterCard({ name: lib.inpile[i] }, player)) { - var info = lib.card[lib.inpile[i]]; - if (info.type == "trick" && !info.multitarget && !info.notarget) { - if (Array.isArray(info.selectTarget)) { - if ( - info.selectTarget[0] > 0 && - info.selectTarget[1] >= info.selectTarget[0] - ) { - list.push(lib.inpile[i]); - } - } else if (typeof info.selectTarget == "number") { - list.push(lib.inpile[i]); - } - } - } - } - var n = player.storage.kuangluan; - delete player.storage.kuangluan; - while (list.length) { - var card = { name: list.randomRemove() }; - var info = get.info(card); - var targets = game.filterPlayer(function (current) { - return lib.filter.filterTarget(card, player, current); - }); - if (targets.length) { - targets.sort(lib.sort.seat); - if (info.selectTarget == -1) { - player.useCard(card, targets); - } else { - var num = info.selectTarget; - if (Array.isArray(num)) { - if (targets.length < num[0]) continue; - num = num[0] + Math.floor(Math.random() * (num[1] - num[0] + 1)); - } else { - if (targets.length < num) continue; - } - player.useCard(card, targets.randomGets(num)); - } - if (--n <= 0) break; - } - } - }, - }, - }, - }, - kuangluan: { - trigger: { player: "damageEnd" }, - forced: true, - priority: 10, - filter(event, player) { - return event.source && event.source.isIn() && event.source != player; - }, - intro: { - content: "players", - }, - content() { - trigger.source.goMad("phaseAfter"); - // if(!player.storage.kuangluan){ - // player.storage.kuangluan=[]; - // } - // player.storage.kuangluan.add(trigger.source); - // player.markSkill('kuangluan'); - }, - ai: { - maixie_defend: true, - threaten: 0.3, - }, - // group:['kuangluan2','kuangluan3'] - }, - kuangluan2: { - trigger: { player: "phaseBegin" }, - priority: 10, - forced: true, - filter(event, player) { - return player.storage.kuangluan && player.storage.kuangluan.length >= 2; - }, - content() { - player.recover(player.maxHp); - player.goMad("phaseAfter"); - }, - }, - kuangluan3: { - trigger: { player: "phaseBegin" }, - silent: true, - content() { - player.storage.kuangluan = []; - player.unmarkSkill("kuangluan"); - }, - }, xiubu: { trigger: { player: "equipEnd" }, frequent: true, @@ -5027,84 +4808,6 @@ game.import("character", function () { }, }, yiwen2: {}, - tanbao_old: { - enable: "phaseUse", - usable: 1, - filter(event, player) { - if (player.hp == player.maxHp) return false; - var hs = player.getCards("h"); - if (hs.length == 0) return false; - var types = []; - for (var i = 0; i < hs.length; i++) { - var type = get.type(hs[i], "trick"); - if (types.includes(type)) { - return false; - } else { - types.push(type); - } - } - return true; - }, - content() { - "step 0"; - player.showHandcards(); - "step 1"; - player.recover(player.countCards("h")); - }, - ai: { - order: 10, - result: { - player: 1, - }, - }, - }, - tanbao_old2: { - enable: "phaseUse", - usable: 10, - filterCard: true, - position: "he", - check(card) { - if (_status.event.player.hp == 1) { - return 7 - get.value(card); - } - return 6 - get.value(card); - }, - selectCard: 3, - filter(event, player) { - return player.countCards("he") >= 3; - }, - content() { - "step 0"; - event.cards = get.cards(3); - if (!event.isMine()) player.showCards(event.cards); - "step 1"; - player.chooseCardButton("获得任意张类别不同的牌", [1, 3], event.cards).filterButton = - function (button) { - var type = get.type(button.link, "trick"); - for (var i = 0; i < ui.selected.buttons.length; i++) { - if (get.type(ui.selected.buttons[i].link, "trick") == type) { - return false; - } - } - return true; - }; - "step 2"; - if (result.bool) player.gain(result.links, "gain2"); - var types = []; - for (var i = 0; i < event.cards.length; i++) { - types.add(get.type(event.cards[i], "trick")); - } - if (types.length == 3) { - player.recover(player.maxHp - player.hp); - } - }, - ai: { - order: 5, - result: { - player: 1, - }, - }, - }, qianghuax: { enable: "phaseUse", usable: 1, @@ -5309,11 +5012,6 @@ game.import("character", function () { }, ai: { threaten: 1.3, - effect: { - target(card, player, target) { - if (card.name == "guiyoujie") return [0, 1]; - }, - }, }, }, fbeifa: { @@ -5632,78 +5330,6 @@ game.import("character", function () { } }, }, - byuhuo: { - unique: true, - trigger: { player: "dying" }, - priority: 6, - forced: true, - mark: true, - skillAnimation: true, - animationColor: "fire", - init(player) { - player.storage.byuhuo = false; - }, - filter(event, player) { - if (player.hp > 0) return false; - if (player.storage.byuhuo) return false; - return true; - }, - content() { - player.storage.byuhuo = true; - player.addSkill("byuhuo2"); - player.maxHp = 2; - player.hp = 2; - player.update(); - if (!player.isTurnedOver()) { - player.turnOver(); - } - }, - ai: { - threaten(player, target) { - if (!target.storage.byuhuo) return 0.6; - }, - }, - intro: { - content(storage, player) { - if (storage) { - if (player.hasSkill("byuhuo2")) { - return "不能成为其他角色卡牌的目标;在下一准备阶段,对所有其他角色造成2点火焰伤害"; - } - return "已发动"; - } else { - return "未发动"; - } - }, - }, - }, - byuhuo2: { - trigger: { player: "phaseBegin" }, - forced: true, - content() { - "step 0"; - var targets = game.filterPlayer(); - targets.remove(player); - targets.sort(lib.sort.seat); - event.targets = targets; - event.num = 0; - player.unmarkSkill("byuhuo"); - "step 1"; - if (num < event.targets.length) { - // if(event.targets[num].countCards('hej')){ - // player.gainPlayerCard(event.targets[num],'hej',true); - // } - player.line(event.targets[num], "fire"); - event.targets[num].damage(2, "fire"); - event.num++; - event.redo(); - } - }, - mod: { - targetEnabled(card, player, target) { - if (player != target) return false; - }, - }, - }, yulu: { enable: "phaseUse", usable: 1, @@ -6026,7 +5652,7 @@ game.import("character", function () { }, ai: { effect: { - player(card, player) { + player_use(card, player) { if (_status.currentPhase != player) return; if (get.type(card) == "equip" && get.equipValueNumber(card) < 7) { if (player.needsToDiscard(2)) return; @@ -6437,6 +6063,13 @@ game.import("character", function () { bimeng: { trigger: { player: "phaseEnd" }, frequent: true, + derivation: [ + "hsmengjing_feicuiyoulong", + "hsmengjing_huanxiaojiemei", + "hsmengjing_suxing", + "hsmengjing_mengye", + "hsmengjing_mengjing", + ], content() { var list = [ "hsmengjing_feicuiyoulong", @@ -7262,7 +6895,7 @@ game.import("character", function () { nofire: true, effect: { target(card, player, target, current) { - if (get.tag(card, "fireDamage")) return 0; + if (get.tag(card, "fireDamage")) return "zeroplayertarget"; }, }, }, @@ -7385,25 +7018,6 @@ game.import("character", function () { }, }, }, - qiaodong: { - enable: ["chooseToUse", "chooseToRespond"], - filterCard: { type: "equip" }, - filter(event, player) { - return player.countCards("he", { type: "equip" }) > 0; - }, - viewAs: { name: "shan" }, - position: "he", - prompt: "将一张装备牌当闪使用或打出", - check() { - return 1; - }, - ai: { - respondShan: true, - skillTagFilter(player) { - if (!player.countCards("he", { type: "equip" })) return false; - }, - }, - }, hsmengjing_mengye: { trigger: { player: "phaseEnd" }, forced: true, @@ -8288,115 +7902,6 @@ game.import("character", function () { threaten: 1.2, }, }, - tzhenji: { - trigger: { player: "discardAfter" }, - direct: true, - filter(event, player) { - if (player.hasSkill("tzhenji2")) { - return false; - } - if (event.cards) { - for (var i = 0; i < event.cards.length; i++) { - if (get.color(event.cards[i]) == "black") return true; - } - } - return false; - }, - content() { - "step 0"; - player.chooseTarget(get.prompt("tzhenji")).ai = function (target) { - var bool = get.attitude(player, target) > 0; - return get.damageEffect(target, player, player, "thunder") - (bool ? 1 : 0); - }; - "step 1"; - if (result.bool) { - game.delay(0.5); - var target = result.targets[0]; - player.logSkill("tzhenji", target, "thunder"); - var cs = target.getCards("he"); - if (cs.length) { - target.discard(cs.randomGet()); - } - target.damage("thunder"); - player.addTempSkill("tzhenji2"); - } - }, - ai: { - threaten: 1.2, - expose: 0.3, - effect: { - target(card, player, target) { - if (get.tag(card, "loseCard") && target.countCards("he")) { - return 0.7; - } - }, - }, - }, - }, - tzhenji2: {}, - tzhenji_old: { - trigger: { player: ["useCard", "respondEnd"] }, - filter(event) { - return get.suit(event.card) == "spade"; - }, - direct: true, - content() { - "step 0"; - player.chooseTarget(get.prompt("tzhenji_old")).ai = function (target) { - return get.damageEffect(target, player, player, "thunder") - 1; - }; - "step 1"; - if (result.bool) { - player.logSkill("tzhenji", result.targets, "thunder"); - event.target = result.targets[0]; - event.target.judge(); - } else { - event.finish(); - } - "step 2"; - if (result.color == "red") { - event.target.damage("fire"); - } else { - event.target.damage("thunder"); - var cs = event.target.getCards("he"); - if (cs.length) { - event.target.discard(cs.randomGet()); - } - cs = player.getCards("he"); - if (cs.length) { - player.discard(cs.randomGet()); - } - } - }, - ai: { - expose: 0.2, - threaten: 1.2, - effect_old: { - target(card, player, target) { - if (get.tag(card, "respondShan")) { - var hastarget = game.hasPlayer(function (current) { - return get.attitude(player, current) < 0; - }); - var ns = target.countCards("h", "shan"); - var nh = target.countCards("h"); - if (ns > 1) { - return [0, hastarget ? 1 : 0]; - } - if (ns && nh >= 2) { - return [0, 0]; - } - if (nh > 3) { - return [0, 0]; - } - if (nh == 0) { - return 1.5; - } - return [1, 0.05]; - } - }, - }, - }, - }, tuteng_s: { trigger: { player: "phaseUseBegin" }, forced: true, @@ -8859,46 +8364,6 @@ game.import("character", function () { }, }, }, - fenliu: { - enable: "phaseUse", - prompt: "失去1点体力并摸三张牌", - usable: 1, - content() { - "step 0"; - player.loseHp(1); - "step 1"; - player.draw(3); - }, - ai: { - order: 4, - result: { - player(player) { - var nh = player.countCards("h"); - if (nh >= player.hp) return -1; - if (player.hp <= 2) { - if (player.hp == 2 && nh == 0) return 1; - return -1; - } - return 1; - }, - }, - effect: { - target(card) { - if (get.tag(card, "damage") || get.tag(card, "loseHp")) { - return 1.5; - } - }, - }, - threaten: 1.2, - }, - }, - fenliu2: { - mod: { - maxHandcard(player, num) { - return num + 1; - }, - }, - }, hongxi: { trigger: { global: "dieAfter" }, filter(event, player) { @@ -9626,7 +9091,12 @@ game.import("character", function () { ai: { order: 9.5, result: { - player: 1, + player: (player, target) => { + return lib.card.shunshou.ai.result.player(player, target) - 3 / game.countPlayer(); + }, + target: (player, target) => { + return lib.card.shunshou.ai.result.target(player, target); + } }, tag: { multitarget: 1, @@ -10057,19 +9527,15 @@ game.import("character", function () { hs_selajin: "瑟拉金", hs_bannabusi: "班纳布斯", hs_amala: "阿玛拉", - hs_nuogefu: "诺格弗", hs_kazhakusi: "卡扎库斯", - hs_lazi: "拉兹", hs_shaku: "沙库尔", hs_laxiao: "拉希奥", hs_yashaji: "亚煞极", hs_khadgar: "卡德加", hs_tyrande: "泰兰德", - hs_fenjie: "芬杰", hs_kalimosi: "卡利莫斯", hs_yogg: "尤格萨隆", hs_xialikeer: "夏克里尔", - hs_wolazi: "沃拉兹", hs_tanghangu: "唐·汉古", hs_barnes: "巴内斯", hs_kchromaggus: "克洛玛古斯", @@ -10092,7 +9558,6 @@ game.import("character", function () { hs_hudunren: "护盾机甲", hs_nate: "纳特", hs_shifazhe: "嗜法者", - hs_xiangyaqishi: "象牙骑士", hs_wujiyuansu: "无羁元素", hs_mojinbaozi: "魔晶孢子", hs_shuiwenxuejia: "水文学家", @@ -10106,10 +9571,6 @@ game.import("character", function () { hs_manyututeng: "蛮鱼图腾", hs_tgolem: "图腾魔像", hs_heifengqishi: "黑锋骑士", - hs_yuhuozhe: "浴火者", - hs_wuyaowang: "巫妖王", - hs_aerfusi: "阿尔福斯", - hs_baiguyoulong: "白骨幼龙", hs_yangyanwageli: "阳焰瓦格里", hs_aiqinvyao: "哀泣女妖", hs_ashamoer: "阿莎摩尔", @@ -10277,10 +9738,6 @@ game.import("character", function () { mengye: "梦魇", mengye_info: "结束阶段,你可以选择一名有手牌的角色将其一张随机的非毒手牌转化为毒,然后令其获得1点护甲。", - mengye_old: "梦魇", - mengye_old2: "梦魇", - mengye_old_info: - "回合结束后,你可以翻面并指定一名的非主公角色,由你控制其进行一个额外的回合。在此回合中,你的本体不参与游戏。", fuhua: "腐化", fuhua2: "腐化", fuhua_info: @@ -10288,9 +9745,6 @@ game.import("character", function () { moxie: "魔血", moxie_info: "锁定技,当你因【毒】失去体力时,你改为摸两张牌;结束阶段,你将一张随机手牌转化为毒。", - gfuhun: "附魂", - gfuhun_info: - "结束阶段,若你未翻面,你可以和一名其他角色拼点,若你赢,你将武将牌翻至背面,该角色进入混乱状态直到下一回合结束。", hlongyi: "龙裔", hlongyi_info: "锁定技,你的黑色牌不占用手牌上限。", zhongji: "重击", @@ -10383,10 +9837,6 @@ game.import("character", function () { oldduxin: "毒心", oldduxin_info: "准备阶段和结束阶段,你可以获得一张随机毒素牌。", hstuteng: "图腾", - kuangluan: "狂乱", - kuangluan2: "狂乱", - // kuangluan_info:'锁定技,每当你于回合内使用一张普通锦囊牌,便于出牌阶段结束时随机使用一张普通锦囊牌(随机指定目标)。', - kuangluan_info: "锁定技,每当一名其他角色对你造成伤害,该角色进入混乱状态直到当前回合结束。", zengli: "赠礼", zengli_info: "出牌阶段限一次,你指定一名其他角色与你各装备一把武器。", xiubu: "修补", @@ -10409,9 +9859,6 @@ game.import("character", function () { yiwen: "轶闻", yiwen_info: "锁定技,每当其他角色于回合内首次使用非特殊卡牌指定你为惟一目标,你获得一张此牌的复制。", - tanbao_old: "探宝", - tanbao_old_info: - "出牌阶段限一次,你可以弃置三张牌,然后展示牌堆顶的三张牌,然后获得其中任意张类别不同的牌;若三张牌类别均不相同,你回复全部体力值。", qianghuax: "强化", qianghuax_info: "出牌阶段限一次,你可以弃置任意张不同类别的牌,然后展示并获得与弃置的牌类别相同且价值更高的牌。", @@ -10467,10 +9914,6 @@ game.import("character", function () { yuanzheng_info: "每当你对距离1以外的角色使用一张牌,你可以弃置目标区域内的一张牌。", bzhuiji: "追击", bzhuiji_info: "每当一名角色死亡,你可以摸两张牌,并视为对杀死该角色的人使用一张决斗。", - byuhuo: "浴火", - byuhuo2: "浴火", - byuhuo_info: - "觉醒技,当你进入濒死状态时,你须将体力和体力上限变为2,并将武将牌翻至背面;在你的下一准备阶段,你对所有其他角色造成2点火焰伤害,在此之前,你不能成为其他角色的卡牌的目标。", yulu: "雨露", yulu_info: "出牌阶段限一次,你可以指定任意名角色各摸一张牌,然后各弃置区域内的一张牌。", oldyulu: "雨露", @@ -10649,8 +10092,6 @@ game.import("character", function () { dunji: "盾击", dunji_info: "出牌阶段限一次,你可以对攻击范围内的至多X名其他角色各造成1点伤害,并失去等量的护甲,X为你的护甲数。", - qiaodong: "巧动", - qiaodong_info: "你可以将一张装备牌当作闪使用或打出。", fengxian: "奉献", fengxian_info: "出牌阶段限一次,你可以令场上所有角色各弃置一张手牌。", zhanhou: "战吼", @@ -10707,11 +10148,6 @@ game.import("character", function () { tuteng7_info: "结束阶段,你令一名其他角色回复1点体力。", tuteng8: "图腾魔像", tuteng8_info: "你的进攻距离+1。", - tzhenji: "震击", - tzhenji_info: - "每当你因弃置而失去黑色牌,可对一名角色造成1点雷电伤害,并随机弃置其一张牌,每回合限发动一次。", - fenliu: "分流", - fenliu_info: "出牌阶段限一次,你可以失去1点体力并获得三张牌。", hongxi: "虹吸", hongxi_info: "锁定技,每当有一名角色死亡,你将体力回复至体力上限。", jihuo: "激活", diff --git a/character/huicui/character.js b/character/huicui/character.js index 2ed130eab8..9099bba4cb 100644 --- a/character/huicui/character.js +++ b/character/huicui/character.js @@ -11,7 +11,6 @@ const characters = { yue_daqiao: ["female", "wu", 3, ["dcqiqin", "dczixi"], ["name:桥|null"]], dc_kongrong: ["male", "qun", 3, ["dckrmingshi", "lirang"]], dc_sp_menghuo: ["male", "qun", 4, ["dcmanwang"]], - dc_lingcao: ["male", "wu", "4/5", ["dcdufeng"]], yue_xiaoqiao: ["female", "wu", 3, ["dcqiqin", "dcweiwan"], ["name:桥|null"]], dc_dongzhao: ["male", "wei", 3, ["dcyijia", "dcdingji"]], kuaiqi: ["male", "wei", 3, ["dcliangxiu", "dcxunjie"]], @@ -97,7 +96,7 @@ const characters = { dc_caiyang: ["male", "wei", 4, ["dcxunji", "dcjiaofeng"]], xiahoujie: ["male", "wei", 5, ["liedan", "zhuangdan"], ["name:夏侯|杰"]], caoxing: ["male", "qun", 4, ["cxliushi", "zhanwan"]], - re_chunyuqiong: ["male", "qun", 4, ["recangchu", "reliangying", "reshishou"]], + re_chunyuqiong: ["male", "qun", 4, ["recangchu", "reliangying", "reshishou"], ["name:淳于|琼"]], xingdaorong: ["male", "qun", "4/6", ["xuxie"]], re_panfeng: ["male", "qun", 4, ["xinkuangfu"]], jiangfei: ["male", "shu", 3, ["dcshengxi", "dcshoucheng"], ["name:蒋|琬-费|祎"]], diff --git a/character/huicui/characterReplace.js b/character/huicui/characterReplace.js index 87d6e47f44..4aa81b94a1 100644 --- a/character/huicui/characterReplace.js +++ b/character/huicui/characterReplace.js @@ -5,7 +5,8 @@ const characterReplaces = { gaoxiang: ["gaoxiang", "jsrg_gaoxiang"], zhangchu: ["zhangchu", "jsrg_zhangchu"], mamidi: ["mamidi", "xin_mamidi"], - re_chunyuqiong: ["re_chunyuqiong", "re_chunyuqiong", "chunyuqiong", "jsrg_chunyuqiong"], + re_chunyuqiong: ["re_chunyuqiong", "chunyuqiong", "jsrg_chunyuqiong"], + chengui: ["chengui", "mb_chengui"], }; export default characterReplaces; diff --git a/character/huicui/skill.js b/character/huicui/skill.js index 0120f139a3..196e97ba55 100644 --- a/character/huicui/skill.js +++ b/character/huicui/skill.js @@ -182,7 +182,7 @@ const skills = { await game.cardsGotoOrdering(cards); const next = player.chooseToMove(); next.set("list", [["牌堆顶", cards], ["牌堆底"]]); - next.set("prompt", "羲笛:点击将牌移动到牌堆顶或牌堆底"); + next.set("prompt", "羲笛:点击或拖动将牌移动到牌堆顶或牌堆底"); next.processAI = list => { const cards = list[0][1], player = _status.event.player; @@ -224,7 +224,7 @@ const skills = { }); player.popup(get.cnNumber(top.length) + "上" + get.cnNumber(bottom.length) + "下"); game.log(player, "将" + get.cnNumber(top.length) + "张牌置于牌堆顶"); - await game.asyncDelayx(); + await game.delayx(); }, }, }, @@ -313,12 +313,14 @@ const skills = { ) return false; return game.hasPlayer(target => { + if (player === target) return false; return target.hasCard(card => card.hasGaintag("dcyunzheng_tag"), "h") == !target.hasSkill("dcyunzheng_block"); }); }, logTarget(event, player) { return game .filterPlayer(target => { + if (player === target) return false; return target.hasCard(card => card.hasGaintag("dcyunzheng_tag"), "h") == !target.hasSkill("dcyunzheng_block"); }) .sortBySeat(); @@ -327,6 +329,7 @@ const skills = { content() { const targets = game .filterPlayer(target => { + if (player === target) return false; return target.hasCard(card => card.hasGaintag("dcyunzheng_tag"), "h") == !target.hasSkill("dcyunzheng_block"); }) .sortBySeat(); @@ -345,40 +348,26 @@ const skills = { }, dchuoxin: { audio: 2, - trigger: { player: "useCardToPlayered" }, + trigger: { player: "useCard" }, filter(event, player) { - if ( - !player.hasHistory("lose", evt => { - if (evt.getParent() != event.getParent()) return false; - return event.cards.some(card => (evt.hs || []).includes(card)); - }) - ) - return false; - return event.isFirstTarget && event.targets.some(current => current != player && current.countCards("h")); + return get.type(event.card) !== "equip" && game.hasPlayer(current => current.countCards("h")); }, locked: true, async cost(event, trigger, player) { - if (trigger.targets.length == 1) { - event.result = { - bool: true, - targets: trigger.targets, - }; - } else { - event.result = await player - .chooseTarget( - get.prompt2("dchuoxin"), - (card, player, target) => { - return target != player && target.countCards("h") && get.event("targets").includes(target); - }, - true - ) - .set("ai", target => { - const player = get.player(); - return -get.attitude(player, target); - }) - .set("targets", trigger.targets) - .forResult(); - } + event.result = await player + .chooseTarget( + "请选择【惑心】的目标", + lib.translate.dchuoxin_info, + (card, player, target) => { + return target.countCards("h"); + }, + true + ) + .set("ai", target => { + const player = get.player(); + return -get.attitude(player, target); + }) + .forResult(); }, async content(event, trigger, player) { const target = event.targets[0]; @@ -580,6 +569,15 @@ const skills = { canBeDiscarded(card, player) { if (get.position(card) == "h") return false; }, + aiOrder(player, card, num) { + if (num > 0 && get.name(card, player) == "huogong") return 0; + }, + aiValue(player, card, num) { + if (num > 0 && get.name(card, player) == "huogong") return 0.01; + }, + aiUseful(player, card, num) { + if (num > 0 && get.name(card, player) == "huogong") return 0; + } }, group: "dctunchu_limit", subSkill: { @@ -658,11 +656,10 @@ const skills = { return !target.countCards("h") && !get.event("list").some(list => list[0] == target); }, ai1(card) { - if (!ui.selected.targets.length) return false; - const target = ui.selected.targets[0]; - if (card.name == "du" && !target.hasSkillTag("nodu") && get.attitude(player, target) < 0) return 200; - if (target.canUse(card, target) && get.attitude(player, target) > 0) return 5 + target.getUseValue(card); - return 1 + Math.random(); + if (card.name == "du") return 200; + let info = get.info(card); + if (info && info.toself) return 10; + return get.unuseful(card); }, ai2(target) { const player = get.event("player"), @@ -1260,12 +1257,12 @@ const skills = { if (!result.bool) return; const target = result.targets[0]; player.logSkill("dczhenrao", target); - await target.damage(); - await game.asyncDelayx(); if (!player.storage.dczhenrao) { player.when({ global: "phaseAfter" }).then(() => player.unmarkSkill("dczhenrao")); } player.markAuto("dczhenrao", target); + await target.damage(); + await game.delayx(); }, intro: { content: "已以此法对$造成过伤害", @@ -1304,7 +1301,7 @@ const skills = { await game.loseAsync({ lose_list }).setContent("chooseToCompareLose"); } sishiList.addArray(cards.filter(isSishi)); - if (lose_list.length) await game.asyncDelayx(); + if (lose_list.length) await game.delayx(); player.gain(sishiList, "gain2"); player .when("phaseEnd") @@ -1431,7 +1428,7 @@ const skills = { const evtx = evt.event; return evt.skill === "dcjichou" && evtx.givenCards && evtx.givenCards.length; })[0].event.givenCards.length; - await game.asyncDelayx(); + await game.delayx(); await player.draw(toDraw); } } @@ -1518,18 +1515,14 @@ const skills = { enable: "phaseUse", usable: 1, filter(event, player) { - return game.hasPlayer(current => { - if (current == player || !current.hasSkill("dcshiju")) return false; - return player.countCards("he"); - }); + if (!player.countCards("he")) return false; + return game.hasPlayer(current => current.hasSkill("dcshiju")); }, filterTarget(card, player, target) { - return target != player && target.hasSkill("dcshiju"); + return target.hasSkill("dcshiju"); }, selectTarget() { - const num = game.countPlayer(current => { - return current.hasSkill("dcshiju"); - }); + const num = game.countPlayer(current => current.hasSkill("dcshiju")); return num > 1 ? 1 : -1; }, filterCard: true, @@ -1541,7 +1534,7 @@ const skills = { let valueFix = 0; if ( game.hasPlayer(current => { - if (current == player || !current.hasSkill("dcshiju")) return false; + if (!current.hasSkill("dcshiju")) return false; if (current.hasUseTarget(card) && !player.countEmptySlot(subtype)) return true; }) ) @@ -1562,12 +1555,13 @@ const skills = { discard: false, lose: false, prepare(cards, player, targets) { - player.$give(cards, targets[0], false); + if (targets[0] != player) player.$give(cards, targets[0], false); }, async content(event, trigger, player) { const card = event.cards[0], target = event.target; - await player.give(card, target); + if (target != player) await player.give(card, target); + else await player.showCards(card, get.translation(player) + "发动了【势举】"); if (!target.getCards("h").includes(card) || get.type(card) !== "equip") return; const bool = await target.chooseUseTarget(card).forResultBool(); if (!bool) return; @@ -1616,56 +1610,34 @@ const skills = { trigger: { player: "useCardToPlayered" }, filter(event, player) { if (!event.isFirstTarget) return false; - if (get.type(event.card) !== "trick") return false; - if (!player.hasSkill(`dcyingshi_choice1`)) return true; - return !player.hasSkill(`dcyingshi_choice2`) && player.countCards("e"); + if (event.card.storage && event.card.storage.dcyingshi) return false; + return get.type(event.card) === "trick"; }, async cost(event, trigger, player) { - let prompt2 = "令一名目标角色", - str = get.translation(trigger.card); - const goon1 = !player.hasSkill(`dcyingshi_choice1`), - goon2 = !player.hasSkill(`dcyingshi_choice2`) && player.countCards("e"); - if (goon1 && goon2) prompt2 += "选择一项:①"; - if (goon2) { - prompt2 += "弃置" + get.cnNumber(player.countCards("e")) + "张牌,令" + str + "对其无效"; - prompt2 += goon1 ? ";②" : "。"; - } - if (goon1) prompt2 += "于此牌结算完毕后视为其使用一张同名牌。"; event.result = await player .chooseTarget() - .set("prompt", get.prompt("dcyingshi")) - .set("prompt2", prompt2) + .set("prompt", get.prompt2("dcyingshi")) .set("filterTarget", (card, player, target) => { return get.event().getTrigger().targets.includes(target); }) .set("ai", target => { const player = get.player(), - trigger = get.event().getTrigger(), - att = get.attitude(player, target); - const goon1 = !player.hasSkill(`dcyingshi_choice1`), - goon2 = !player.hasSkill(`dcyingshi_choice2`) && player.countCards("e"); + trigger = get.event().getTrigger(); + const num = player.countCards("e"); const effect = get.effect(target, trigger.card, player, player); - if (effect == 0 || att == 0) return 0; - if (effect > 0) { - if (att > 0 && goon1) return att; - return 0; - } - if (att < 0 && !goon1) return -att; - if (att > 0 && !goon2) return att; - return 0; + if (!num) return effect; + return Math.max(eff, get.effect(target, { name: "guohe_copy2" }, target, player) * num); }) .forResult(); }, async content(event, trigger, player) { const target = event.targets[0], count = player.countCards("e"); - const goon1 = !player.hasSkill(`dcyingshi_choice1`), - goon2 = !player.hasSkill(`dcyingshi_choice2`) && count > 0; let bool; - if (goon2) { - const prompt = `###${get.translation(player)}对你发动了【应时】###${!goon1 ? "请" : "是否"}弃置${get.cnNumber(count)}张牌,令${get.translation(trigger.card)}对你无效${!goon1 ? "。" : "?或点击“取消”,令其与此牌结算后视为对你使用一张同名牌。"}`; + if (count > 0) { + const prompt = `###${get.translation(player)}对你发动了【应时】###弃置${get.cnNumber(count)}张牌,令其本回合不能再发动〖应时〗,或令其于此牌结算后视为对你使用一张同名牌"`; bool = await target - .chooseToDiscard(prompt, count, !goon1, "he") + .chooseToDiscard(prompt, count, "he") .set("ai", card => { if (get.event("goon")) return 15 - get.value(card); return 0; @@ -1674,7 +1646,7 @@ const skills = { .forResultBool(); } else bool = false; if (bool) { - trigger.excluded.add(target); + player.tempBanSkill("dcyingshi"); } else { player .when({ global: "useCardAfter" }) @@ -1694,11 +1666,6 @@ const skills = { if (trigger.addedTargets && trigger.addedTargets.length) next.addedTargets = trigger.addedTargets.slice(0); }); } - player.addTempSkill(`dcyingshi_choice${bool + 1}`); - }, - subSkill: { - choice1: { charlotte: true }, - choice2: { charlotte: true }, }, }, //公孙修 @@ -1754,11 +1721,23 @@ const skills = { } }, ai: { + order() { + return get.order({ name: "sha" }) + 1; + }, result: { + player(player, target) { + let eff = get.effect(player, { name: "juedou" }, target, player), + shas = target.mayHaveSha(player, "respond", null, "count") - player.mayHaveSha(player, "respond", null, "count"); + if (shas > 0) eff += shas * get.effect(target, { name: "shunshou"}, player, player); + return eff; + }, target(player, target) { - const [juedouEff, loseEff] = [get.effect(player, { name: "juedou" }, target, player), get.effect(target, { name: "losehp" }, target, player)]; - if (juedouEff > 0) return (loseEff * get.attitude(player, target)) / 10; - return 0; + let eff = get.effect(player, { name: "juedou" }, target, target), + shas = target.mayHaveSha(player, "respond", null, "count") - player.mayHaveSha(player, "respond", null, "count"); + if (shas < -1) + eff += get.effect(target, { name: "losehp" }, target, target); + else if (shas > 0) eff += shas * get.effect(target, { name: "shunshou"}, player, target); + return eff; }, }, }, @@ -1866,8 +1845,10 @@ const skills = { .set("ai", target => { const player = get.event("player"), num = target.getAttackRange(); - if (get.event("goon")) return -num; - return -get.sgn(get.attitude(player, target)) * (target.getAttackRange() + (num <= 0 ? -num + 0.5 : num)); + if (get.attitude(player, target) > 0) return -1; + if (get.event("goon")) return num; + if (num < 1) return 1 / (1 - num); + return 5 / num; }) .set("goon", goon); if (bool) { @@ -1878,7 +1859,7 @@ const skills = { player .when(["phaseBegin", "dieBegin"]) .then(() => { - target.removeMark("dcfuli_range", 1, false); + target.removeMark("dcfuli_range", target.countMark("dcfuli_range"), false); if (!target.hasMark("dcfuli_range")) target.removeSkill("dcfuli_range"); }) .vars({ target: target }); @@ -2099,6 +2080,27 @@ const skills = { ); }, zixiList: ["lebu", "bingliang", "shandian"], + selectAi(player, names) { + let max = [null, 0, null, null]; + for (let name of names) { + let res = [null, null, 0]; + player.getCards("h", i => { + if (!i.hasGaintag("dcqiqin_tag") || get.value(i) >= 7) return false; + game.countPlayer(target => { + if (!target.canAddJudge(get.autoViewAs({ name: "dczixi_" + name }, [i]))) return; + let eff = get.effect(target, get.autoViewAs({ name }, [i]), player, player); + if (get.attitude(player, target) > 0) { + if (-eff > res[2]) res = [target, i, -eff / 16]; //避免人机一直贴队友 + } + else { + if (eff > res[2]) res = [target, i, eff]; + } + }); + }); + if (res[0] && res[2] > max[1]) max = [get.translation(name), res[2], res[1], res[0]]; + } + return max; + }, direct: true, async content(event, trigger, player) { game.addVideo("skill", player, ["dczixi", []]); @@ -2111,6 +2113,7 @@ const skills = { for (const name of names) { map[get.translation(name)] = name; } + let max = lib.skill.dczixi.selectAi(player, Object.values(map)); const { result: { bool, links }, } = await player @@ -2128,26 +2131,14 @@ const skills = { ); }) .set("ai", button => { - const player = get.event("player"), - list = Object.keys(get.event("map")); if (typeof button.link == "string") { - const card = player - .getCards("h", card => { - if (get.value(card) >= 7) return false; - return card.hasGaintag("dcqiqin_tag") && game.hasPlayer(target => target.canAddJudge(get.autoViewAs({ name: "dczixi_" + button.link }, [card]))); - }) - .sort((a, b) => get.value(a) - get.value(b))[0]; - if ( - game.hasPlayer(current => { - return get.attitude(player, current) < 0 && lib.skill.dczixi.zixiList.some(name => current.canAddJudge(get.autoViewAs({ name: "dczixi_" + button.link }, [card]))); - }) - ) - return list.indexOf(button.link) + 1; - return 1 / (list.indexOf(button.link) + 1); + if (button.link == get.event("max")[0]) return 1; + return 0; } - return 7 - get.value(button.link); + if (button.link == get.event("max")[2]) return 1; + return 0; }) - .set("map", map); + .set("max", max); if (bool) { const name = links.find(i => typeof i == "string"), card = links.find(j => j != name), @@ -2163,23 +2154,17 @@ const skills = { true ) .set("ai", target => { - const player = get.event("player"), - card = get.event("card"); - if ( - game.hasPlayer(current => { - return get.attitude(player, current) < 0 && current.canAddJudge(get.autoViewAs({ name: "dczixi_" + get.event("cardname") }, [card])); - }) - ) - return -target.countCards("j") - 1; - return target.countCards("j") + 1; + if (target == get.event("max")[3]) return 1; + return 0; }) .set("card", card) - .set("cardname", cardname); + .set("cardname", cardname) + .set("max", max); if (bool) { const target = targets[0]; player.logSkill("dczixi", target); player.$give(card, target, false); - await game.asyncDelay(0.5); + await game.delay(0.5); target.addJudge({ name: "dczixi_" + cardname }, [card]); } } @@ -2240,6 +2225,22 @@ const skills = { break; } }, + ai: { + effect: { + player_use(card, player, target) { + if (player._dczixi_effect_use || get.tag(card, "multitarget")) return; + let js = target.countCards("j"); + if (js == 1) return [2, 0, 2, 0]; + else if (js == 2) return [1, 2]; + else if (js == 3 && get.attitude(player, target) < 0) { + player._dczixi_effect_use = true; + let eff = get.damageEffect(target, player, player); + delete player._dczixi_effect_use; + if (eff > 0) return [1, 0, 1, -6]; + } + } + } + } }, }, }, @@ -2267,10 +2268,10 @@ const skills = { }, ai: { effect: { - target_use(card, player, target, current) { + target(card, player, target, current) { if (get.tag(card, "damage") && target != player) { if (_status.event.name == "dckrmingshi") return; - if (get.attitude(player, target) > 0 && current < 0) return "zerotarget"; + if (get.attitude(player, target) > 0 && current < 0) return "zeroplayertarget"; var bs = player.getCards("h"); bs.remove(card); if (card.cards) bs.removeArray(card.cards); @@ -2368,56 +2369,6 @@ const skills = { }, }, }, - //凌操 - dcdufeng: { - audio: 2, - trigger: { player: "phaseUseBegin" }, - forced: true, - async content(event, trigger, player) { - const list = []; - for (let i = 1; i < 6; i++) { - if (player.isDisabled(i)) continue; - list.push("equip" + i); - } - list.push("cancel2"); - const next = player.chooseControl(list); - next.set("prompt", "独锋:请废除一个装备栏,或点击“取消”失去1点体力"); - next.set("ai", () => { - const list = get.event().list.slice(), - player = get.player(); - if (player.hp <= 2 && list.length > 1) list.remove("cancel2"); - const listx = list.filter(subtype => !player.getEquips(subtype).length); - if (listx.length) return listx.randomGet(); - return list.randomGet(); - }); - next.set("list", list); - const { result } = await next; - if (result.control == "cancel2") await player.loseHp(); - else await player.disableEquip(result.control); - if (!player.isIn()) return; - const num = Math.min(player.countDisabled() + player.getDamagedHp(), player.maxHp); - await player.draw(num); - player.addTempSkill("dcdufeng_effect"); - player.addMark("dcdufeng_effect", num, false); - }, - subSkill: { - effect: { - charlotte: true, - onremove: true, - intro: { - content: "本回合攻击范围与使用【杀】的次数上限均为#", - }, - mod: { - attackRangeBase(player, num) { - return player.countMark("dcdufeng_effect"); - }, - cardUsable(card, player, num) { - if (card.name == "sha") return player.countMark("dcdufeng_effect"); - }, - }, - }, - }, - }, //小乔 dcqiqin: { audio: 2, @@ -3018,7 +2969,7 @@ const skills = { } if (player.countCards("h", card => card.hasGaintag("dcjiaowei_tag")) <= len) { player.storage.counttrigger.dcfeibai--; - game.log(player, "重置了", "#【飞白】"); + game.log(player, "重置了", "#g【飞白】"); } }, mod: { @@ -3042,7 +2993,7 @@ const skills = { }, prompt2: function (event, player) { const num = Math.pow(2, player.countMark("dccaisi_more")); - return `从${player == _status.currentPhase ? "牌堆" : "弃牌"}堆中随机获得${get.cnNumber(num)}张非基本牌`; + return `从${player == _status.currentPhase ? "" : "弃"}牌堆中随机获得${get.cnNumber(num)}张非基本牌`; }, content: function* (event, map) { const player = map.player, @@ -4151,8 +4102,8 @@ const skills = { effect: { player_use: function (card, player, target, current) { if (_status.currentPhase != player) return; - if (get.type(card) == "equip" && get.cardtag(card, "gifts")) return; - if (player.countCards("h") > Math.max(1, player.countCards("e"))) return [1, 3]; + let cha = player.countCards("h") - Math.max(1, player.countCards("e")); + if (cha == 0 || cha < 0 && !player.hasSkill("dczuowei_ban")) return [1, 2]; }, }, }, @@ -4414,7 +4365,7 @@ const skills = { filter: function (event, player) { if (!player.hasMark("dcgonghu_basic") || !player.hasMark("dcgonghu_damage")) return false; var card = event.card; - if (get.color(card, false) != "red" || get.type(card, null, true) != "trick") return false; + if (get.color(card, false) != "red" || get.type(card, null, false) != "trick") return false; var info = get.info(card); if (info.allowMultiple == false) return false; if (event.targets && !info.multitarget) { @@ -4677,7 +4628,7 @@ const skills = { game.addGlobalSkill("oldmoyu_ai"); }, onremove: () => { - if (!game.hasPlayer(i => i.hasSkill("oldmoyu"), true)) game.removeGlobalSkill("oldmoyu_ai"); + if (!game.hasPlayer(i => i.hasSkill("oldmoyu", null, null, false), true)) game.removeGlobalSkill("oldmoyu_ai"); }, enable: "phaseUse", filter: function (event, player) { @@ -4733,7 +4684,7 @@ const skills = { ai: { trigger: { player: "dieAfter" }, filter: () => { - return !game.hasPlayer(i => i.hasSkill("oldmoyu"), true); + return !game.hasPlayer(i => i.hasSkill("oldmoyu", null, null, false), true); }, silent: true, forceDie: true, @@ -4875,7 +4826,7 @@ const skills = { check(event, player) { const target = event.targets[0]; if (target.hasMark("dcjizhong")) { - return get.effect(target, { name: "shunshou_copy" }, event, player) > 0; + return get.effect(target, { name: "shunshou_copy" }, player, player) > 0; } else { const card = { name: event.card.name, nature: event.card.nature, isCard: true }; let eff = 0; @@ -5292,7 +5243,6 @@ const skills = { audio: 2, trigger: { global: "phaseEnd" }, filter: function (event, player) { - if (player.hasSkill("dcsigong_round")) return false; if (event.player == player || !event.player.isIn()) return false; if (!player.canUse("sha", event.player, false)) return false; var respondEvts = []; @@ -5349,7 +5299,6 @@ const skills = { } }, subSkill: { - round: { charlotte: true }, check: { charlotte: true, forced: true, @@ -5359,7 +5308,7 @@ const skills = { return event.card && event.card.name == "sha" && event.getParent(3).name == "dcsigong"; }, content: function () { - player.addTempSkill("dcsigong_round", "roundStart"); + player.tempBanSkill("dcsigong", "roundStart"); }, }, }, @@ -6210,7 +6159,7 @@ const skills = { Math.min( 5, player.countCards("h", function (card) { - return get.type(card, player) == "basic"; + return get.type(card, null, player) == "basic"; }) ) ); @@ -6228,7 +6177,7 @@ const skills = { var num = Math.min( 5, player.countCards("h", function (cardx) { - var type = get.type(cardx, player); + var type = get.type(cardx, null, player); return (name == "dcneifa_basic") != (type == "basic") && type != "equip"; }) ); @@ -7064,12 +7013,14 @@ const skills = { audio: 2, trigger: { player: "phaseUseEnd" }, filter: function (event, player) { - return ( - player.getCardUsable("sha", true) > - player.getHistory("useCard", evt => { - return evt.getParent("phaseUse") == event && evt.card.name == "sha" && evt.addCount !== false; - }).length - ); + return ["sha", "jiu"].some(name => { + return ( + player.getCardUsable(name, true) > + player.getHistory("useCard", evt => { + return evt.getParent("phaseUse") == event && evt.card.name == name && evt.addCount !== false; + }).length + ); + }); }, direct: true, content: function () { @@ -7122,7 +7073,14 @@ const skills = { ai: { effect: { player_use: function (card, player, target) { - if (typeof card == "object" && player.isPhaseUsing() && card.name == "sha" && player.getCardUsable("sha") == 1) return "zeroplayertarget"; + if ( + typeof card == "object" && + player.isPhaseUsing() && + ["sha", "jiu"].some(name => { + return card.name == name && player.getCardUsable(name) == 1 && !player.getCardUsable(name == "sha" ? "jiu" : "sha"); + }) + ) + return "zeroplayertarget"; }, target_use: function (card, player, target) { if (card.name == "jiu" && player.getCardUsable("sha") == 2) return [1, 1]; @@ -8358,12 +8316,7 @@ const skills = { }, draw: { audio: "dcquanjian", - filterTarget: function (card, player, target) { - if (target == player) return false; - var num = target.countCards("h"); - if (num > target.getHandcardLimit()) return true; - return num < Math.min(5, target.getHandcardLimit()); - }, + filterTarget: lib.filter.notMe, filterCard: () => false, selectCard: -1, content: function () { @@ -8377,7 +8330,7 @@ const skills = { num = num1 - num2; target .chooseControl() - .set("choiceList", ["弃置" + get.cnNumber(num) + "张手牌", "本回合下次受到的伤害+1"]) + .set("choiceList", ["弃置" + get.cnNumber(num) + "张手牌,且本回合内不能使用或打出手牌", "本回合下次受到的伤害+1"]) .set("ai", function () { var player = _status.event.player; if ( @@ -8393,27 +8346,29 @@ const skills = { } else { event.index = 1; num = Math.min(num2, 5) - num1; - if (num <= 0) event.finish(); - else - target - .chooseControl() - .set("choiceList", ["摸" + get.cnNumber(num) + "张牌,且本回合内不能使用或打出手牌", "本回合下次受到的伤害+1"]) - .set("ai", function () { - return 0; - }); + target + .chooseControl() + .set("choiceList", [ + (num > 0 ? "摸" + get.cnNumber(num) + "张牌且" : "") + "本回合内不能使用或打出手牌", + "本回合下次受到的伤害+1" + ]) + .set("ai", () => get.event().idx) + .set("idx", function () { + if (num > 0) return 0; + if (get.damageEffect(target, player, target) > 20) return 0; + return 1; + }()); } event.num = num; "step 1"; if (result.index == 0) { if (event.index == 0) target.chooseToDiscard("h", true, num); else target.draw(num); + target.addTempSkill("dcquanjian_disable"); } else { target.addMark("dcquanjian_effect", 1, false); target.addTempSkill("dcquanjian_effect"); - event.finish(); } - "step 2"; - target.addTempSkill("dcquanjian_disable"); }, ai: { result: { @@ -8442,17 +8397,8 @@ const skills = { disable: { charlotte: true, mod: { - cardEnabled(card, player) { - if (card.cards) { - const hs = player.getCards("h"); - if (card.cards.some(card => hs.includes(card))) return false; - } - }, - cardSavable(card, player) { - if (card.cards) { - const hs = player.getCards("h"); - if (card.cards.some(card => hs.includes(card))) return false; - } + cardEnabled2(card, player) { + if (get.position(card) == "h") return false; }, }, mark: true, @@ -8595,15 +8541,23 @@ const skills = { } }, ai: { - order: 1, + order(item, player) { + if (player.hasUnknown()) return 0; + let list = []; + for (let i of cards) { + list.add(get.suit(i, player)); + if (list.length >= 3) return 10; + } + return 0; + }, result: { + player: 1.8, target: function (player, target) { - if (player.hasUnknown()) return 0; - var zhu = get.zhu(player); + let zhu = get.zhu(player); if (zhu && get.attitude(player, zhu) > 0) { if (target == zhu) return 4; } - return 1; + return 1.8; }, }, }, @@ -10183,6 +10137,7 @@ const skills = { player.chooseControl(list).set("ai", function () { var controls = _status.event.controls; if (controls.includes("cslilu")) return "cslilu"; + if (controls.includes("zhichi")) return "zhichi"; return controls[0]; }); } @@ -10450,7 +10405,7 @@ const skills = { charlotte: true, logTarget: "target", filter: function (event, player) { - return event.target != player && (event.card.name == "sha" || get.type(event.card, false) == "trick") && event.target.countCards("he") > 0; + return event.target != player && (event.card.name == "sha" || get.type(event.card, null, false) == "trick") && event.target.countCards("he") > 0; }, content: function () { "step 0"; @@ -10464,7 +10419,7 @@ const skills = { ai: { effect: { player_use(card, player, target) { - if (player !== target && get.itemtype(target) === "player" && (card.name === "sha" || get.type(card, false) === "trick") && target.countCards("he") && !target.hasSkillTag("noh")) return [1, 0, 1, -1]; + if (player !== target && get.itemtype(target) === "player" && (card.name === "sha" || get.type(card, null, false) === "trick") && target.countCards("he") && !target.hasSkillTag("noh")) return [1, 0, 1, -1]; }, }, }, @@ -11994,7 +11949,13 @@ const skills = { }, }, ai: { - order: 4, + order: (item, player) => { + if (game.hasPlayer(cur => { + if (player === cur || get.attitude(player, cur) <= 0) return false; + return Math.min(5, target.maxHp) - cur.countCards("h") > 2; + })) return get.order({ name: "nanman" }, player) - 0.1; + return 10; + }, result: { target: function (player, target) { if (get.attitude(player, target) > 0) return Math.max(0, Math.min(5, target.maxHp) - target.countCards("h")); @@ -12067,12 +12028,12 @@ const skills = { trigger: { target: "useCardToTargeted" }, filter: function (event, player) { if (player == event.player || event.targets.length != 1) return false; - return player.countCards("h") >= 2; + return event.player.isIn() && player.countCards("h") >= 2; }, usable: 2, async cost(event, trigger, player) { event.result = await player - .chooseToDiscard("he", [2, Infinity], get.prompt("reshejian", trigger.player), '
    弃置至少两张手牌,然后选择一项:
    ⒈弃置其等量的牌。⒉对其造成1点伤害。
    ') + .chooseToDiscard("h", [2, Infinity], get.prompt("reshejian", trigger.player), '
    弃置至少两张手牌,然后选择一项:
    ⒈弃置其等量的牌。⒉对其造成1点伤害。
    ') .set( "ai", function (card) { @@ -12563,7 +12524,7 @@ const skills = { game.addGlobalSkill("fengxiang_use"); }, onremove: function (player) { - if (!game.hasPlayer(current => current.hasSkill("fengxiang"), true)) game.removeGlobalSkill("fengxiang_use"); + if (!game.hasPlayer(current => current.hasSkill("fengxiang", null, null, false), true)) game.removeGlobalSkill("fengxiang_use"); }, trigger: { player: "damageEnd" }, forced: true, @@ -12611,7 +12572,7 @@ const skills = { }, trigger: { player: "dieAfter" }, filter: function (event, player) { - return !game.hasPlayer(current => current.hasSkill("fengxiang"), true); + return !game.hasPlayer(current => current.hasSkill("fengxiang", null, null, false), true); }, silent: true, forceDie: true, @@ -12859,7 +12820,7 @@ const skills = { filter: function (event, player) { if (!player.hasMark("zhtongyuan_basic") || !player.hasMark("zhtongyuan_trick")) return false; var card = event.card; - if (get.color(card, false) != "red" || get.type(card, null, true) != "basic") return false; + if (get.color(card, false) != "red" || get.type(card, null, false) != "basic") return false; var info = get.info(card); if (info.allowMultiple == false) return false; if (event.targets && !info.multitarget) { @@ -13213,7 +13174,7 @@ const skills = { filter: function (event, player) { if (player == event.player || event.targets.length != 1) return false; var bool = function (card) { - return (card.name == "sha" || get.type(card, false) == "trick") && get.color(card, false) == "black"; + return (card.name == "sha" || get.type(card, null, false) == "trick") && get.color(card, false) == "black"; }; if (!bool(event.card)) return false; var evt = event.getParent("phaseUse"); @@ -13828,7 +13789,7 @@ const skills = { trigger: { global: "phaseZhunbeiBegin" }, forced: true, filter: function (event, player) { - return (player != event.player || player.countMark("liedan") > 4) && !player.hasSkill("zhuangdan_mark"); + return (player != event.player || player.countMark("liedan") > 4); }, logTarget: "player", content: function () { @@ -13859,6 +13820,7 @@ const skills = { }, content: function () { player.addTempSkill("zhuangdan_mark", { player: "phaseEnd" }); + player.tempBanSkill("liedan", { player: "phaseEnd" }); }, ai: { combo: "zhuangdan", diff --git a/character/huicui/sort.js b/character/huicui/sort.js index 3a247da766..9376d847d3 100644 --- a/character/huicui/sort.js +++ b/character/huicui/sort.js @@ -1,7 +1,7 @@ const characterSort = { sp_baigei: ["re_panfeng", "xingdaorong", "caoxing", "re_chunyuqiong", "xiahoujie", "dc_caiyang", "zhoushan"], sp_caizijiaren: ["dc_kongrong", "re_dongbai", "re_sunluyu", "heyan", "zhaoyan", "wangtao", "wangyue", "zhangxuan", "tengyin", "zhangyao", "xiahoulingnv", "dc_sunru", "pangshanmin", "kuaiqi"], - sp_zhilan: ["dc_liuli", "liuyong", "wanniangongzhu", "zhanghu", "lvlingqi", "tenggongzhu", "panghui", "dc_zhaotongzhaoguang", "yuantanyuanxiyuanshang", "yuechen", "dc_lingcao"], + sp_zhilan: ["dc_liuli", "liuyong", "wanniangongzhu", "zhanghu", "lvlingqi", "tenggongzhu", "panghui", "dc_zhaotongzhaoguang", "yuantanyuanxiyuanshang", "yuechen"], sp_guixin: ["zangba", "re_kanze", "re_chendeng", "caimaozhangyun", "dc_lvkuanglvxiang", "dc_gaolan", "yinfuren", "chengui", "chenjiao", "dc_sp_jiaxu", "qinlang", "dc_dongzhao"], sp_daihan: ["mamidi", "dc_jiling", "zhangxun", "dc_yuejiu", "leibo", "qiaorui", "dongwan", "yuanyin"], sp_jianghu: ["guanning", "huzhao", "dc_huangchengyan", "mengjie", "wanglie"], diff --git a/character/huicui/translate.js b/character/huicui/translate.js index 1f029452e4..b5298f8eba 100644 --- a/character/huicui/translate.js +++ b/character/huicui/translate.js @@ -286,7 +286,7 @@ const translates = { liupi: "新杀刘辟", liupi_prefix: "新杀", dcjuying: "踞营", - dcjuying_info: "出牌阶段结束时,若你于此阶段内使用【杀】的次数未达到上限,你可以选择任意项:1.下回合使用【杀】的次数上限+1;2.本回合手牌上限+2;3.摸三张牌。若你选择的项数超过了你的体力值,你弃置一张牌。", + dcjuying_info: "出牌阶段结束时,若你于此阶段内使用【杀】或【酒】的次数未达到上限,你可以选择任意项:1.下回合使用【杀】的次数上限+1;2.本回合手牌上限+2;3.摸三张牌。若你选择的项数超过了你的体力值,你弃置一张牌。", dc_huanghao: "新杀黄皓", dc_huanghao_prefix: "新杀", dcqinqing: "寝情", @@ -464,10 +464,6 @@ const translates = { dcqiqin_info: "锁定技。①游戏开始时,你将所有手牌标记为“琴”。②你的“琴”牌不计入手牌上限。③准备阶段,你获得位于弃牌堆的所有“琴”。", dcweiwan: "媦婉", dcweiwan_info: "出牌阶段限一次,你可以弃置一张“琴”并随机获得一名其他角色区域内花色与此牌不相同的牌各一张,若你获得了:一张牌,其失去1点体力;两张牌,本回合你对其使用牌无距离和次数限制;三张牌,本回合你不能对其使用牌。", - dc_lingcao: "新杀凌操", - dc_lingcao_prefix: "新杀", - dcdufeng: "独锋", - dcdufeng_info: "锁定技。出牌阶段开始时,你失去1点体力或废除一个装备栏,摸X张牌,然后你的攻击范围与使用【杀】的次数上限均为X直到回合结束(X为你已废除的装备栏数与损失的体力值之和,至多为你的体力上限)。", dc_sp_menghuo: "新杀SP孟获", dc_sp_menghuo_prefix: "新杀SP", dcmanwang: "蛮王", @@ -497,9 +493,9 @@ const translates = { dckuizhen: "溃阵", dckuizhen_info: "出牌阶段限一次。你可以令一名手牌数或体力值不小于你的角色视为对你使用一张【决斗】。若你:受到渠道为此牌的伤害,你观看其手牌并获得其中所有的【杀】(你使用以此法得到的牌无任何次数限制);未受到渠道为此牌的伤害,其失去1点体力。", dcshiju: "势举", - dcshiju_info: "其他角色的出牌阶段限一次。其可以交给你一张牌,若此牌为装备牌,你可以使用之,然后其本回合攻击范围+X(X为你装备区里的牌数)。若你以此法替换了装备,你与其各摸两张牌。", + dcshiju_info: "一名角色的出牌阶段限一次。其可以交给你一张牌(若其为你则改为展示一张牌),若此牌为装备牌,你可以使用之,然后其本回合攻击范围+X(X为你装备区里的牌数)。若你以此法替换了装备,你与其各摸两张牌。", dcyingshi: "应时", - dcyingshi_info: "每回合每项各限一次。当你使用普通锦囊牌指定目标后,你可令其中一个目标选择一项:⒈令你于此牌结算结束后视为对其使用一张与此牌牌名相同的牌;⒉弃置X张牌,此牌对其无效(X为你装备区里的牌数)。", + dcyingshi_info: "当你不因〖应时〗使用普通锦囊牌指定目标后,你可令其中一个目标选择一项:⒈令你于此牌结算结束后视为对其使用一张与此牌牌名相同的牌;⒉弃置X张牌,你本回合不能再发动〖应时〗(X为你装备区里的牌数)。", dcjichou: "集筹", dcjichou_info: "出牌阶段结束时,若你于此阶段使用过牌且这些牌的牌名均不同,你可以观看位于弃牌堆中的这些牌,选择任意张牌并选择等量角色,将这些牌交给这些角色各一张,然后你摸X张牌(X为你本局游戏首次发动〖集筹〗给出的牌数)。", dcmouli: "谋立", @@ -528,7 +524,6 @@ const translates = { dcshicao_info: "出牌阶段,你可以声明一种类型,然后选择从牌堆顶或牌堆底摸一张牌。若此牌类型与你声明的类型不同,你观看牌堆另一端的两张牌,此技能本回合失效。", dc_lifeng: "李丰", dctunchu: "囤储", - //dctunchu_info: "锁定技。①你的起始手牌数为游戏人数的四倍。②你的手牌不能被弃置。③准备阶段,若你的手牌数大于你的体力上限,则你本回合至多使用三张牌。", dctunchu_info: "锁定技。①游戏开始时,你将手牌数摸至游戏人数的四倍。②你的手牌不能被弃置。③准备阶段,若你的手牌数大于你的体力值,则你本回合至多使用三张牌。", dcshuliang: "输粮", dcshuliang_info: "一名角色的回合结束时,你可以将任意张牌交给任意名没有手牌的角色各一张,然后本次获得可以指定自己为目标的牌的角色可以依次选择是否使用本次获得的牌。", @@ -542,9 +537,9 @@ const translates = { yue_zoushi_prefix: "乐", dcyunzheng: "韵筝", dcyunzheng_tag: "筝", - dcyunzheng_info: "锁定技。①游戏开始时,你将所有手牌标记为“筝”。②你的“筝”牌不计入手牌上限。③手牌中有“筝”的角色的非锁定技失效。", + dcyunzheng_info: "锁定技。①游戏开始时,你将所有手牌标记为“筝”。②你的“筝”牌不计入手牌上限。③手牌中有“筝”的其他角色的非锁定技失效。", dchuoxin: "惑心", - dchuoxin_info: "锁定技,当你使用手牌指定其他角色为目标后,你展示其中一名角色一张手牌。若此牌为“筝”牌或与你使用牌花色相同,你获得之;否则你将此牌标记为“筝”。", + dchuoxin_info: "锁定技,当你使用非装备牌时,你选择一名有手牌的角色,然后展示其一张手牌。若此牌为“筝”牌或与你使用牌花色相同,你获得之;否则将此牌标记为“筝”。", yue_zhugeguo: "乐诸葛果", yue_zhugeguo_prefix: "乐", dcxidi: "羲笛", diff --git a/character/huicui/voices.js b/character/huicui/voices.js index c279818816..91762d1101 100644 --- a/character/huicui/voices.js +++ b/character/huicui/voices.js @@ -1,4 +1,9 @@ export default { + "#dcyunzheng1": "佳人弄青丝,柔荑奏鸣筝。", + "#dcyunzheng2": "玉柱冷寒雪,清商怨羽声。", + "#dchuoxin1": "闻君精通音律,与我合奏一曲如何?", + "#dchuoxin2": "知君有心意,此筝寄我情。", + "#yue_zoushi:die": "雁归衡阳,良人当还……", "#dcduanti1": "流水不腐,户枢不蠹。", "#dcduanti2": "五禽锻体,百病不侵。", "#dcshicao1": "掌中非药,乃活人之根本。", @@ -61,8 +66,9 @@ export default { "#kuaiqi:die": "泉下万事休,人间雪满头……", "#dccaisi1": "扶耒耜,植桑陌,习诗书,以传家。", "#dccaisi2": "惟楚有才,于庞门为盛。", - "#dczhuoli1": "良子千万,当擢才而用。", - "#pangshanmin:die": "九品中正后,庙堂无寒门……", + "#dczhuoli1": "良梓千万,当擢才而用。", + "#dczhuoli2": "任人唯才,不妨寒门入上品。", + "#pangshanmin:die": "九品中正后,庙堂无寒门。", "#dcbeini1": "臣等忠心耿耿,陛下何故谋反?", "#dcbeini2": "公等养汝,正拟今日,复何疑?", "#dcshizong1": "成济、王经已死,独我安享富贵。", diff --git a/character/jiange.js b/character/jiange.js index ddf8d18d6b..d45ddcb20a 100644 --- a/character/jiange.js +++ b/character/jiange.js @@ -379,7 +379,7 @@ game.import("character", function () { nodamage: true, effect: { target: function (card, player, target, current) { - if (get.tag(card, "damage") && !get.tag(card, "thunderDamage")) return [0, 0]; + if (get.tag(card, "damage") && !get.tag(card, "thunderDamage")) return "zeroplayertarget"; }, }, }, diff --git a/character/jsrg/character.js b/character/jsrg/character.js index 0af3481cda..3e20f63045 100644 --- a/character/jsrg/character.js +++ b/character/jsrg/character.js @@ -173,6 +173,7 @@ const characters = { hp: 4, skills: ["jsrgcangchu", "jsrgshishou"], dieAudios: ["re_chunyuqiong"], + names: "淳于|琼", }, //转 jsrg_guojia: { diff --git a/character/jsrg/skill.js b/character/jsrg/skill.js index 8f009e9c1f..bf0aa98523 100644 --- a/character/jsrg/skill.js +++ b/character/jsrg/skill.js @@ -54,7 +54,7 @@ const skills = { let hasSomeoneUsed = false; for (const target of targets) { const cardName = event.result.card.name; - const chooseToRespondEvent = target.chooseToRespond("是否替" + get.translation(player) + "打出一张" + get.translation(cardName) + "?", {name: cardName}); + const chooseToRespondEvent = target.chooseToRespond("是否替" + get.translation(player) + "打出一张" + get.translation(cardName) + "?", { name: cardName }); chooseToRespondEvent.set("ai", () => { const event = _status.event; return get.attitude(event.player, event.source) - 2; @@ -63,8 +63,8 @@ const skills = { chooseToRespondEvent.set("skillwarn", "替" + get.translation(player) + "打出一张" + get.translation(cardName)); chooseToRespondEvent.noOrdering = true; chooseToRespondEvent.autochoose = (cardName === "sha" ? lib.filter.autoRespondSha : lib.filter.autoRespondShan); - const { bool, card, cards } = (await chooseToRespondEvent).result; - if(bool){ + const { bool, card, cards } = await chooseToRespondEvent.forResult(); + if (bool) { hasSomeoneUsed = true; event.result.card = card; event.result.cards = cards; @@ -74,7 +74,7 @@ const skills = { break; } } - if(!hasSomeoneUsed){ + if (!hasSomeoneUsed) { evt.goto(0); } }, @@ -160,7 +160,7 @@ const skills = { check(event, player) { if ( event.targets.reduce((p, c) => { - return p + get.effect_use(c, event.card, event.player, player) > 0; + return p + get.effect(c, event.card, event.player, player); }, 0) >= 0 ) return false; @@ -193,7 +193,7 @@ const skills = { target.line(source); trigger.targets.add(target); game.log(target, "也成为了", trigger.card, "的目标"); - await game.asyncDelayx(); + await game.delayx(); } } await source.showHandcards(); @@ -385,7 +385,7 @@ const skills = { for (const current of targets) { player.line(current); await current.damage("nocard"); - await game.asyncDelayx(); + await game.delayx(); } }, ai: { @@ -412,7 +412,6 @@ const skills = { jsrgyansha: { trigger: { player: "phaseZhunbeiBegin" }, async cost(event, trigger, player) { - //AI摆了,交给157了 event.result = await player .chooseTarget(get.prompt("jsrgyansha"), "你可以选择任意名角色,视为对这些角色使用【五谷丰登】,然后未被选择的角色依次可以将一张装备牌当作【杀】对目标角色使用。", [1, Infinity], (card, player, target) => { return player.canUse({ name: "wugu", isCard: true }, target); @@ -623,6 +622,7 @@ const skills = { player(player, target) { let tars = _status.event.getTempCache("jsrgguanshi", "targets"); if (!tars) return lib.card.juedou.ai.result.player(player, target); + return 0; }, target(player, target) { let tars = _status.event.getTempCache("jsrgguanshi", "targets"); @@ -721,7 +721,7 @@ const skills = { } else { get.owner(card).$giveAuto(card, player, false); } - await game.asyncDelayx(); + await game.delayx(); await player.addJudge({ name: "xumou_jsrg" }, [card]); if (player.isPhaseUsing()) await player.draw(); }, @@ -834,7 +834,7 @@ const skills = { player, target ); - await game.asyncDelay(3); + await game.delay(3); game.broadcastAll("closeDialog", videoId); for (let i = 0; i < 5; i++) { const discarded = await target @@ -934,7 +934,7 @@ const skills = { } }); }) - ).catch(() => {}); + ).catch(() => { }); game.broadcastAll("cancel", eventId); } //再处理单机的他人控制玩家/AI玩家 @@ -964,7 +964,7 @@ const skills = { async content(event, trigger, player) { const { giver, cards } = event.cost_data; await giver.give(cards, trigger.source); - await trigger.cancel(); + trigger.cancel(); }, chooseTarget(target, source, current, eventId, eventNum) { const goon = (() => { @@ -1155,13 +1155,13 @@ const skills = { }, check(event, player) { //理论上是小完杀+卖血 - //先粗略地写一写,后面等157补 + //我没意见 return get.attitude(player, event.player) < 0; }, async content(event, trigger, player) { const target = trigger.player; const targets = await target - .chooseTarget([1, 2], true, "请选择至多两名角色", `${get.translation(player)}对你发动了【纵害】。你可以选择至多两名角色,只有这两名角色可以使用牌拯救你,且当此次濒死结算结束后,这两名角色均会受到来自${get.translation(player)}的1点伤害。`) + .chooseTarget([1, 2], true, "请选择至多两名角色", `${get.translation(player)}对你发动了【纵害】。你可以选择至多两名角色,只有他(们)可以使用牌拯救你,且当此次濒死结算结束后,他(们均)会受到来自${get.translation(player)}的1点伤害。`) .set("ai", target => { //自救还要挨一刀,最好的反制方法就是跟对面爆了 const evt = get.event(), @@ -1183,29 +1183,64 @@ const skills = { target.markAuto("jsrgzonghai_blocker", [id]); } }); - target - .when("dyingAfter") - .vars({ id, allPlayers, targets, source: player }) - .assign({ forceDie: true }) - .then(() => { - allPlayers.forEach(target => { - target.unmarkAuto("jsrgzonghai_blocker", [id]); - if (!target.getStorage("jsrgzonghai_blocker").length) target.removeSkill("jsrgzonghai_blocker"); - }); - if (source.isIn()) { - targets.forEach(target => target.damage(source)); - } - }); + target.addSkill("jsrgzonghai_damage"); + if (!target.storage.jsrgzonghai_damage) target.storage.jsrgzonghai_damage = []; + target.storage.jsrgzonghai_damage.push({ + id: id, + targets: targets, + source: player + }); }, subSkill: { blocker: { charlotte: true, onremove: true, mod: { - cardSavable: () => false, - cardEnabled: () => false, + cardSavable: (card, player) => { + if (player.getStorage("jsrgzonghai_blocker").includes(get.event().getParent()._jsrgzonghai_id)) + return false; + }, + cardEnabled: (card, player) => { + if (player.getStorage("jsrgzonghai_blocker").includes(get.event().getParent()._jsrgzonghai_id)) + return false; + }, }, }, + damage: { + trigger: { + player: "dyingAfter" + }, + filter(event, player) { + let storage = player.getStorage("jsrgzonghai_damage"); + for (let i of storage) { + if (i.id == event._jsrgzonghai_id) return true; + } + return false; + }, + silent: true, + forceDie: true, + charlotte: true, + async content(event, trigger, player) { + let storage; + for (let i = 0; i < player.storage.jsrgzonghai_damage.length; i++) { + if (player.storage.jsrgzonghai_damage[i].id == trigger._jsrgzonghai_id) { + storage = player.storage.jsrgzonghai_damage[i]; + player.storage.jsrgzonghai_damage.splice(i, 1); + break; + } + } + if (!storage) return; + game.countPlayer(target => { + target.unmarkAuto("jsrgzonghai_blocker", [storage.id]); + if (!target.getStorage("jsrgzonghai_blocker").length) target.removeSkill("jsrgzonghai_blocker"); + }); + if (storage.source.isIn()) while (storage.targets.length) { + let target = storage.targets.shift(); + if (target.isIn()) await target.damage(storage.source); + } + if (!player.storage.jsrgzonghai_damage.length) player.removeSkill("jsrgzonghai_damage"); + } + } }, }, jsrgjueyin: { @@ -1290,7 +1325,7 @@ const skills = { videoId, player ); - await game.asyncDelay(4); + await game.delay(4); game.broadcastAll("closeDialog", videoId); //展示完了 开始拿牌 const suitsMap = {}; @@ -1432,10 +1467,8 @@ const skills = { game.log(source, forceTargets.includes(source) ? "自愿选择" : "选择了", current, "作为讨伐目标"); ticketsMap.set(current, (ticketsMap.get(current) || 0) + 1); }); - console.log(ticketsMap); let maxTicket = 0; const target = ticketsMap.entries().reduce((target, data) => { - console.log(data); const [current, ticket] = data; if (ticket > maxTicket) { maxTicket = ticket; @@ -1445,7 +1478,7 @@ const skills = { }, false); //上Buff if (target) { - game.log(target, "成为了", "#g【执盟】", "的讨伐目标"); + game.log(target, "成为了", "#g【诛逆】", "的讨伐目标"); player.addTempSkill("jsrgzhuni_effect"); player.markAuto("jsrgzhuni_effect", [target]); } @@ -1456,7 +1489,7 @@ const skills = { threaten: 1.8, }, chooseTarget(player, source) { - const next = player.chooseTarget(`${get.translation(source)}发动了【执盟】,请选择一名讨伐目标`, (card, player, target) => target !== source, true); + const next = player.chooseTarget(`${get.translation(source)}发动了【诛逆】,请选择一名讨伐目标`, (card, player, target) => target !== source, true); next.set("ai", target => -get.attitude(get.player(), target)); next.set("animate", false); next.set("_global_waiting", true); @@ -1526,7 +1559,7 @@ const skills = { } const next = player.chooseToMove(); next.set("list", [["牌堆顶", cards.filterInD()], ["牌堆底"]]); - next.set("prompt", "问天:点击将牌移动到牌堆顶或牌堆底"); + next.set("prompt", "问天:点击或拖动将牌移动到牌堆顶或牌堆底"); next.processAI = list => { const cards = list[0][1], player = _status.event.player; @@ -1568,7 +1601,7 @@ const skills = { }); player.popup(get.cnNumber(top.length) + "上" + get.cnNumber(bottom.length) + "下"); game.log(player, "将" + get.cnNumber(top.length) + "张牌置于牌堆顶"); - game.asyncDelayx(); + await game.delayx(); }, subSkill: { viewas: { @@ -1843,7 +1876,7 @@ const skills = { next.set("_backupevent", "jsrgfumou_backup"); next.set("custom", { add: {}, - replace: { window: function () {} }, + replace: { window: function () { } }, }); next.backup("jsrgfumou_backup"); }, @@ -1996,12 +2029,14 @@ const skills = { async content(event, trigger, player) { await player.showHandcards(); await player.draw(2); - const evt = event.getParent("phase"); + const evt = event.getParent("phase", true); if (evt) { - game.resetSkills(); - _status.event = evt; - _status.event.finish(); - _status.event.untrigger(true); + game.log(player, "结束了回合"); + evt.finish(); + } + const evtx = event.getParent("phaseUse", true); + if (evtx) { + evtx.skipped = true; } }, ai: { @@ -2091,7 +2126,7 @@ const skills = { .set("logSkill", ["jsrglonglin", trigger.player]); if (result.bool) { trigger.excluded.addArray(trigger.targets); - game.asyncDelayx(); + await game.delayx(); if (trigger.player.canUse(juedou, player)) { const { result } = await trigger.player.chooseBool(`是否视为对${get.translation(player)}使用一张【决斗】?`).set("choice", get.effect(player, juedou, trigger.player, trigger.player) >= 0); if (result.bool) { @@ -2276,7 +2311,7 @@ const skills = { game.cardsGotoOrdering(cards); const next = player.chooseToMove(); next.set("list", [["牌堆顶"], ["牌堆底", cards.reverse()]]); - next.set("prompt", "鹰眎:点击将牌移动到牌堆顶或牌堆底"); + next.set("prompt", "鹰眎:点击或拖动将牌移动到牌堆顶或牌堆底"); next.processAI = list => { const cards = list[1][1], player = _status.event.player; @@ -2318,7 +2353,7 @@ const skills = { }); player.popup(get.cnNumber(top.length) + "上" + get.cnNumber(bottom.length) + "下"); game.log(player, "将" + get.cnNumber(top.length) + "张牌置于牌堆顶"); - game.asyncDelayx(); + await game.delayx(); }, }, jsrgtuigu: { @@ -3156,7 +3191,7 @@ const skills = { videoId, player ); - await game.asyncDelay(4); + await game.delay(4); game.broadcastAll("closeDialog", videoId); let clock = -1, anticlock = -1; @@ -3275,7 +3310,7 @@ const skills = { if (result.bool && result.links) { const time2 = 1000 - (get.utc() - time); if (time2 > 0) { - await game.asyncDelay(0, time2); + await game.delay(0, time2); } game.broadcastAll("closeDialog", videoId); player.gain(result.links, "gain2"); @@ -3309,16 +3344,20 @@ const skills = { ai: { order: 6, result: { - target(player, target) { + player(player, target) { const targets = game.filterPlayer(current => target.inRange(current) && current != player); let eff = 0; for (const targetx of targets) { - let effx = get.effect(targetx, { name: "guohe_copy2" }, player, target); - if (get.attitude(player, targetx) < 0) effx /= 2; + let effx = get.effect(targetx, { name: "guohe_copy2" }, targetx, player); eff += effx; } - return eff * (get.attitude(player, target) <= 0 ? 0.75 : 1); + return eff; }, + target(player, target) { + return game.countPlayer(current => { + return current !== player && target.inRange(current) && current.countCards("h"); + }) / 2 * get.effect(target, { name: "draw" }, target, target); + } }, }, }, @@ -4213,7 +4252,7 @@ const skills = { game.addGlobalSkill("jsrgninghan_frozen"); }, onremove: player => { - if (!game.hasPlayer(current => current.hasSkill("jsrgninghan"), true)) game.removeGlobalSkill("jsrgninghan_frozen"); + if (!game.hasPlayer(current => current.hasSkill("jsrgninghan", null, null, false), true)) game.removeGlobalSkill("jsrgninghan_frozen"); }, trigger: { global: "damageEnd" }, filter: function (event, player) { @@ -4240,7 +4279,7 @@ const skills = { }, trigger: { player: "dieAfter" }, filter: (event, player) => { - return !game.hasPlayer(current => !current.hasSkill("jsrgninghan"), true); + return !game.hasPlayer(current => !current.hasSkill("jsrgninghan", null, null, false), true); }, silent: true, forceDie: true, @@ -4452,7 +4491,7 @@ const skills = { next.set("logSkill", "jsrgchuanxin"); next.set("custom", { add: {}, - replace: { window: function () {} }, + replace: { window: function () { } }, }); next.backup("jsrgchuanxin_backup"); }, @@ -5270,6 +5309,7 @@ const skills = { var damaged = get.event("damaged"); return damaged.includes(target) ^ (ui.selected.cards.length > 0); }, + complexSelect: true, selectTarget: 1, ai1: function (card) { if (get.event("damaged").includes(get.event("aiTarget"))) return 0; @@ -5360,7 +5400,7 @@ const skills = { game.addGlobalSkill("jsrgjiemeng_effect"); }, onremove: () => { - if (!game.hasPlayer(i => i.hasSkill("jsrgjiemeng"), true)) game.removeGlobalSkill("jsrgjiemeng_effect"); + if (!game.hasPlayer(i => i.hasSkill("jsrgjiemeng", null, null, false), true)) game.removeGlobalSkill("jsrgjiemeng_effect"); }, subSkill: { effect: { @@ -5373,7 +5413,7 @@ const skills = { }, trigger: { player: "dieAfter" }, filter: () => { - return !game.hasPlayer(i => i.hasSkill("jsrgjiemeng"), true); + return !game.hasPlayer(i => i.hasSkill("jsrgjiemeng", null, null, false), true); }, silent: true, forceDie: true, @@ -6585,7 +6625,6 @@ const skills = { enable: ["chooseToUse", "chooseToRespond"], filter: function (event, player) { if (!player.countCards("hes")) return false; - if (player.hasSkill("jsrgnianen_blocker")) return false; for (var name of lib.inpile) { if (get.type2(name) != "basic") continue; var card = { name: name }; @@ -6642,6 +6681,7 @@ const skills = { delete event.result.skill; var card = event.result.card; if (get.color(card, player) != "red" || get.name(card) != "sha" || get.natureList(card).length) { + player.tempBanSkill("jsrgnianen"); player.addTempSkill("jsrgnianen_blocker"); player.addAdditionalSkill("jsrgnianen_blocker", "mashu"); } @@ -6655,14 +6695,14 @@ const skills = { hiddenCard: function (player, name) { if (!lib.inpile.includes(name)) return false; var type = get.type2(name); - return type == "basic" && player.countCards("hes") > 0 && !player.hasSkill("jsrgnianen_blocker"); + return type == "basic" && player.countCards("hes") > 0 && !player.isTempBanned("jsrgnianen"); }, ai: { fireAttack: true, respondSha: true, respondShan: true, skillTagFilter: function (player) { - if (!player.countCards("hes") || player.hasSkill("jsrgnianen_blocker")) return false; + if (!player.countCards("hes") || player.isTempBanned("jsrgnianen")) return false; }, order: 1, result: { @@ -7422,7 +7462,6 @@ const skills = { global: "phaseJieshuBegin", }, filter: function (event, player) { - if (player.hasSkill("jsrgshishou_blocker")) return false; return player.getHistory("gain").length; }, direct: true, @@ -7505,6 +7544,7 @@ const skills = { return event.hasNature("fire"); }, content: function () { + player.tempBanSkill("jsrgshishou", { player: "phaseEnd" }); player.addTempSkill("jsrgshishou_blocker", { player: "phaseEnd" }); }, }, @@ -7759,12 +7799,13 @@ const skills = { }, }, jsrgchaozheng: { - audio: 2, + audio: 4, trigger: { player: "phaseZhunbeiBegin" }, logTarget: function (event, player) { return game.filterPlayer(i => i != player); }, prompt: "是否发动【朝争】?", + logAudio: index => typeof index === "number" ? "jsrgchaozheng" + index + ".mp3" : 2, content: function () { player.chooseToDebate(game.filterPlayer(i => i != player)).set("callback", lib.skill.jsrgchaozheng.callback); }, @@ -7774,6 +7815,7 @@ const skills = { var opinion = result.opinion, targets = result.red.map(i => i[0]); targets.sortBySeat(); + if (opinion) player.logSkill('jsrgchaozheng', targets, null, null, [opinion == "red" ? 3 : 4]); targets.forEach(i => i[opinion == "red" ? "recover" : "loseHp"]()); if (targets.length == 0 || result.black.length == 0) player.draw(result.targets.length); } @@ -7784,6 +7826,7 @@ const skills = { enable: "phaseUse", limited: true, filterTarget: lib.filter.notMe, + derivation: ["jsrgfeiyang", "jsrgbahu"], skillAnimation: true, animationColor: "soil", content: function () { @@ -7874,13 +7917,14 @@ const skills = { }, }, jsrgjulian: { - audio: 2, + audio: 4, trigger: { player: "phaseJieshuBegin" }, filter: function (event, player) { return player.hasZhuSkill("jsrgjulian") && lib.skill.jsrgjulian.logTarget(null, player).length; }, prompt: "是否发动【聚敛】?", prompt2: "你可以获得其他所有群势力角色的各一张牌", + logAudio: () => ["jsrgjulian3.mp3", "jsrgjulian4.mp3"], logTarget: function (event, player) { return game.filterPlayer(current => { return current.group == "qun" && current.countGainableCards(player, "he") > 0 && current != player; @@ -7909,6 +7953,7 @@ const skills = { }, direct: true, usable: 2, + logAudio: () => 2, content: function () { "step 0"; var source = trigger.player; @@ -7987,7 +8032,7 @@ const skills = { }, }, jsrgzhuhuan: { - audio: "mouzhu", + audio: 2, trigger: { player: "phaseZhunbeiBegin" }, filter: function (event, player) { var hs = player.getCards("h", "sha"); @@ -8035,6 +8080,7 @@ const skills = { }, jsrgyanhuo: { inherit: "spyanhuo", + audio: 2, forced: true, }, //孙坚 @@ -8094,10 +8140,10 @@ const skills = { filter: function (event, player) { return player.countCards("he") && event.card.name == "sha"; }, - direct: true, - content: function () { - "step 0"; - player + logTarget: "target", + logAudio: () => ["jsrgjuelie3.mp3", "jsrgjuelie4.mp3"], + async cost(event, trigger, player) { + event.result = await player .chooseToDiscard(get.prompt("jsrgjuelie", trigger.target), "当你使用【杀】指定一名角色为目标后,你可以弃置任意张牌,然后弃置其等量的牌", [1, Infinity], "he") .set("ai", card => { if (ui.selected.cards.length >= _status.event.max) return 0; @@ -8106,12 +8152,13 @@ const skills = { }) .set("max", trigger.target.countDiscardableCards(player, "he")) .set("goon", get.attitude(player, trigger.target) < 0) - .set("logSkill", ["jsrgjuelie", trigger.target]); - "step 1"; - if (result.bool) { - var num = result.cards.length; - if (trigger.target.countDiscardableCards(player, "he")) player.discardPlayerCard("平讨:弃置" + get.translation(trigger.target) + get.cnNumber(num) + "张牌", num, "he", trigger.target, true); - } + .forResult(); + }, + async content(event, trigger, player) { + const num = event.cards.length; + if (trigger.target.countDiscardableCards(player, "he")) + await player.discardPlayerCard("平讨:弃置" + get.translation(trigger.target) + get.cnNumber(num) + "张牌", num, "he", trigger.target, true); + /* else event.finish(); 'step 2' @@ -8144,6 +8191,8 @@ const skills = { group: "jsrgjuelie_pojun", subSkill: { pojun: { + audio: "jsrgjuelie", + logAudio: () => ["jsrgjuelie1.mp3", "jsrgjuelie2.mp3"], trigger: { source: "damageBegin1" }, filter: function (event, player) { if (!player.isMinHandcard() && !player.isMinHp()) return false; @@ -8833,7 +8882,7 @@ const skills = { }, ai: { effect: { - target: function (card, player, target, current) { + target_use: function (card, player, target, current) { if (get.type(card) == "delay" && current < 0) { if (target.countCards("j")) return; return "zerotarget"; @@ -9151,10 +9200,10 @@ const skills = { } }, cardRespondable: function (card, player) { - return lib.skill.jsrgfendi.cardEnabled.apply(this, arguments); + return lib.skill.jsrgfendi_blocker.mod.cardEnabled.apply(this, arguments); }, cardSavable: function (card, player) { - return lib.skill.jsrgfendi.cardEnabled.apply(this, arguments); + return lib.skill.jsrgfendi_blocker.mod.cardEnabled.apply(this, arguments); }, }, }, @@ -9297,6 +9346,7 @@ const skills = { check: function (event, player) { return get.damageEffect(event.player, event.source, _status.event.player, event.nature) * event.num < get.effect(player, { name: "losehp" }, player, _status.event.player) + get.effect(player, { name: "draw" }, player, _status.event.player) + get.effect(event.player, { name: "draw" }, player, _status.event.player) / 2; }, + logAudio: () => 2, group: "jsrgjishan_recover", content: function () { "step 0"; @@ -9323,22 +9373,19 @@ const skills = { }); }, usable: 1, - direct: true, - content: function () { - "step 0"; - player + logAudio: () => ["jsrgjishan3.mp3", "jsrgjishan4.mp3"], + async cost(event, trigger, player) { + event.result = await player .chooseTarget(get.prompt("jsrgjishan_recover"), "令一名体力值最小且你对其发动过〖积善①〗的角色回复1点体力", (card, player, target) => { return target.isMinHp() && player.getStorage("jsrgjishan").includes(target); }) .set("ai", target => { return get.recoverEffect(target, _status.event.player, _status.event.player); - }); - "step 1"; - if (result.bool) { - var target = result.targets[0]; - player.logSkill("jsrgjishan_recover", target); - target.recover(); - } else player.storage.counttrigger.jsrgjishan_recover--; + }) + .forResult(); + }, + async content(event, trigger, player) { + await event.targets[0].recover(); }, }, }, @@ -9382,7 +9429,7 @@ const skills = { }, //王允 jsrgshelun: { - audio: 2, + audio: 4, enable: "phaseUse", usable: 1, filter: function (event, player) { @@ -9391,6 +9438,7 @@ const skills = { filterTarget: function (card, player, target) { return player.inRange(target); }, + logAudio: index => typeof index === "number" ? "jsrgshelun" + index + ".mp3" : 2, content: function () { var num = player.countCards("h"); var targets = game.filterPlayer(current => { @@ -9403,6 +9451,7 @@ const skills = { if (result.bool && result.opinion) { var opinion = result.opinion; var target = event.getParent(2).target; + if (opinion) player.logSkill('jsrgshelun', target, null, null, [opinion == "red" ? 3 : 4]); if (opinion == "red") player.discardPlayerCard(target, "he", true); else target.damage(); } @@ -9656,6 +9705,7 @@ const skills = { if (num == 0) return "你可以摸一张牌"; return "你可以摸一张牌并令" + get.cnNumber(num) + "名角色获得“猎”标记"; }, + logAudio: () => 2, content: function () { "step 0"; player.draw(); @@ -9694,6 +9744,7 @@ const skills = { subSkill: { damage: { audio: "jsrgzhenglve", + logAudio: () => ["jsrgzhenglve3.mp3", "jsrgzhenglve4.mp3"], trigger: { source: "damageSource" }, usable: 1, filter: function (event, player) { @@ -9746,41 +9797,39 @@ const skills = { }, }, jsrgpingrong: { - audio: 2, + audio: 3, trigger: { global: "phaseEnd" }, filter: function (event, player) { return !player.hasSkill("jsrgpingrong_used") && game.hasPlayer(current => current.hasMark("jsrgzhenglve_mark")); }, - direct: true, - content: function () { - "step 0"; - player + logAudio: () => 2, + async cost(event, trigger, player) { + event.result = await player .chooseTarget(get.prompt("jsrghuilie"), "移去一名角色的“猎”,然后你执行一个额外回合。若你在此额外回合内未造成伤害,则你失去1点体力。", (card, player, target) => { return target.hasMark("jsrgzhenglve_mark"); }) .set("ai", target => { return get.attitude(_status.event.player, target); - }); - ("step 1"); - if (result.bool) { - var target = result.targets[0]; - player.logSkill("jsrgpingrong", target); - player.addTempSkill("jsrgpingrong_used", "roundStart"); - target.removeMark("jsrgzhenglve_mark", target.countMark("jsrgzhenglve_mark")); - player.insertPhase(); - player.addSkill("jsrgpingrong_check"); - } + }) + .forResult(); + }, + async content(event, trigger, player) { + const target = result.targets[0]; + player.addTempSkill("jsrgpingrong_used", "roundStart"); + target.removeMark("jsrgzhenglve_mark", target.countMark("jsrgzhenglve_mark")); + player.insertPhase(); + player.addSkill("jsrgpingrong_check"); }, subSkill: { used: { charlotte: true }, check: { - audio: "jsrgpingrong", - trigger: { player: "phaseAfter" }, charlotte: true, - forced: true, + audio: "jsrgpingrong3.mp3", + trigger: { player: "phaseAfter" }, filter: function (event, player) { return event.skill == "jsrgpingrong" && !player.getHistory("sourceDamage").length; }, + forced: true, content: function () { player.loseHp(); }, diff --git a/character/jsrg/voices.js b/character/jsrg/voices.js index aa4a808e4f..b94b75487b 100644 --- a/character/jsrg/voices.js +++ b/character/jsrg/voices.js @@ -1,4 +1,29 @@ export default { + "#jsrgchaozheng1": "何故争论无休?朝堂自有公论。", + "#jsrgchaozheng2": "今日之言,无是无非,皆为我大汉社稷。", + "#jsrgchaozheng3": "诸卿一心为公,大汉中兴可期!", + "#jsrgchaozheng4": "朝野皆论朋党之私,欲置朕于何处!", + "#jsrgshenchong1": "天子近前,岂曰无人?赏!", + "#jsrgshenchong2": "诸臣皆为己利,唯汝独讨朕心。", + "#jsrgjulian1": "朕聚天下之财,岂不为天下之事乎?", + "#jsrgjulian2": "若为汉家中兴,朕又何惜此金银之物!", + "#jsrgjulian3": "天下既无贤才,不知民有闲财否?哈哈哈!", + "#jsrgjulian4": "府仓国库,皆归朕有!", + "#jsrg_liuhong:die": "中兴无望,唯将大志托于此剑……", + "#jsrgzhaobing1": "此事,便依本初之言。", + "#jsrgzhaobing2": "诸侯兵马,皆听我调遣。", + "#jsrgzhuhuan1": "杀了你们,天下都是我说了算!", + "#jsrgzhuhuan2": "整顿天下,为国除害!", + "#jsrgyanhuo1": "附肉之蛆,也想弑主?", + "#jsrgyanhuo2": "陛下在哪儿?陛下在哪儿!", + "#jsrg_hejin:die": "太后诏我入宫,汝等这是何意?!", + "#jsrgshelun1": "董贼既死,凉州旧部当有处置。", + "#jsrgshelun2": "此事甚难定夺,还请诸公共议。", + "#jsrgshelun3": "此辈何罪?但为其主,不足杀之。", + "#jsrgshelun4": "今不屠此逆军,何慰关东义士之心?", + "#jsrgfayi1": "吾除董贼,朝野自是吾一言之堂。", + "#jsrgfayi2": "念私惠而忘公义,其与董贼同罪!", + "#jsrg_wangyun:die": "罢兵不成,新乱又起……老夫当以死谢天下……", "#jsrgzhenglve1": "臣奉陛下之命,以伐乱臣。", "#jsrgzhenglve2": "陛下且安坐宫中,待臣之捷报。", "#jsrgzhenglve3": "齐桓之功,唯霸可彰王道。", diff --git a/character/key/skill.js b/character/key/skill.js index 70af577186..04cfd2062e 100644 --- a/character/key/skill.js +++ b/character/key/skill.js @@ -110,7 +110,7 @@ const skills = { player.showCards(cards, get.translation(player) + "发动了【天全】"); game.cardsGotoOrdering(cards).relatedEvent = trigger.getParent(); var num = cards.filter(function (card) { - return get.type(card, false) == "basic"; + return get.type(card, null, false) == "basic"; }).length; if (num) { if (trigger.card.name == "sha") { @@ -138,7 +138,7 @@ const skills = { ) player.gain( cards.filter(function (card) { - return get.type(card, false) != "basic"; + return get.type(card, null, false) != "basic"; }), "gain2" ); @@ -278,7 +278,7 @@ const skills = { charlotte: true, filter(event, player) { if (event.card.name == "sha") return true; - return get.type(event.card, false) == "trick" && get.tag(event.card, "damage") > 0; + return get.type(event.card, null, false) == "trick" && get.tag(event.card, "damage") > 0; }, content() { player.draw(); @@ -461,180 +461,6 @@ const skills = { if (player.maxHp > 3) player.loseMaxHp(player.maxHp - 3); }, }, - //加纳天善(旧) - tenzen_yixing: { - unique: true, - forceunique: true, - trigger: { - global: "damageEnd", - }, - filter(event, player) { - if (!event.card || (event.card.name != "sha" && event.card.name != "juedou")) return false; - var hairi = event.source; - if (hairi && (hairi == player || player.inRangeOf(hairi)) && hairi.isIn() && hairi.name1 != "key_shizuku" && hairi.name2 != "key_shizuku") return true; - hairi = event.player; - return hairi && (hairi == player || player.inRange(hairi)) && hairi.isIn() && hairi.name1 != "key_shizuku" && hairi.name2 != "key_shizuku"; - }, - frequent: true, - content() { - "step 0"; - player.draw(); - "step 1"; - if (player.countCards("he") > 0) { - player.chooseCard("he", true, "将一张牌作为“兴”置于武将牌上"); - } else event.finish(); - "step 2"; - if (result.bool) { - var cards = result.cards; - player.addToExpansion(cards, player, "give").gaintag.add("tenzen_yixing"); - } - }, - intro: { - content: "expansion", - onunmark: "expansion", - }, - onremove(player, skill) { - var cards = player.getExpansions(skill); - if (cards.length) player.loseToDiscardpile(cards); - }, - group: "tenzen_yixing_counter", - subSkill: { - counter: { - trigger: { target: "useCardToTargeted" }, - filter(event, player) { - if (player == event.player || !player.getExpansions("tenzen_yixing").length) return false; - return event.targets.length == 1 && (event.card.name == "sha" || get.type(event.card) == "trick"); - }, - prompt2(event) { - return "获得一张“兴”,且" + get.translation(event.card) + "结算完成后可以弃置两张牌,视为对" + get.translation(event.player) + "使用一张同名牌"; - }, - check(event, player) { - if (!player.storage.tenzen_lingyu && player.getExpansions("tenzen_yixing").length < 3) return false; - var card = { - name: event.card.name, - nature: event.card.nature, - isCard: true, - }; - return player.canUse(card, event.player, false) && get.effect(event.player, card, player, player) > 0; - }, - content() { - "step 0"; - player.chooseButton(["选择获得一张“兴”", player.getExpansions("tenzen_yixing")], true); - "step 1"; - if (result.bool) { - player.gain(result.links, "gain2"); - } - var next = game.createEvent("tenzen_yixing_insert"); - event.next.remove(next); - trigger.getParent().after.push(next); - next.player = player; - next.target = trigger.player; - next.setContent(lib.skill.tenzen_yixing.content_extra); - }, - }, - }, - content_extra() { - "step 0"; - var card = event.getParent().card; - event.card = { - name: card.name, - nature: card.nature, - isCard: true, - }; - if (player.countCards("he") > 1 && target && target.isIn() && player.canUse(event.card, target, false)) { - player.chooseToDiscard("he", 2, "是否弃置两张牌,视为对" + get.translation(target) + "使用" + get.translation(event.card) + "?").set("ai", function (card) { - return 5 - get.value(card); - }); - } else event.finish(); - "step 1"; - if (result.bool) player.useCard(card, target, false, "tenzen_yixing"); - }, - }, - tenzen_lingyu: { - trigger: { player: "phaseZhunbeiBegin" }, - forced: true, - juexingji: true, - skillAnimation: true, - animationColor: "water", - filter(event, player) { - return player.getExpansions("tenzen_yixing").length >= player.hp; - }, - content() { - player.awakenSkill("tenzen_lingyu"); - player.storage.tenzen_lingyu = true; - player.loseMaxHp(); - if (player.isHealthy()) player.draw(2); - player.addSkills("tenzen_tianquan"); - }, - ai: { - combo: "tenzen_yixing", - }, - }, - tenzen_tianquan: { - trigger: { player: "useCardToPlayered" }, - filter(event, player) { - return (event.card.name == "sha" || event.card.name == "juedou") && event.targets.length == 1 && player.getExpansions("tenzen_yixing").length > 1; - }, - logTarget: "target", - usable: 1, - check(event, player) { - return get.attitude(player, event.target) < 0; - }, - content() { - "step 0"; - //player.viewHandcards(trigger.target); - player.chooseButton(["选择移去两张“兴”", player.getExpansions("tenzen_yixing")], true, 2); - "step 1"; - if (result.bool) { - player.loseToDiscardpile(result.links); - var cards = get.cards(5); - player.showCards(cards, get.translation(player) + "发动了【天全】"); - game.cardsGotoOrdering(cards).relatedEvent = trigger.getParent(); - var num = cards.filter(function (card) { - return get.type(card, false) == "basic"; - }).length; - if (num) { - if (trigger.card.name == "sha") { - var id = trigger.target.playerid; - var map = trigger.getParent().customArgs; - if (!map[id]) map[id] = {}; - if (typeof map[id].shanRequired == "number") { - map[id].shanRequired += num; - } else { - map[id].shanRequired = 1 + num; - } - } else { - var idt = trigger.target.playerid; - var map = trigger.getParent().customArgs; - if (!map[idt]) map[idt] = {}; - if (!map[idt].shaReq) map[idt].shaReq = {}; - if (!map[idt].shaReq[idt]) map[idt].shaReq[idt] = 1; - map[idt].shaReq[idt]++; - } - } - if (num < 5) { - var next = game.createEvent("tenzen_lingyu_gain"); - next.cards = cards; - next.player = player; - event.next.remove(next); - trigger.getParent().after.push(next); - next.setContent(function () { - if ( - player.getHistory("sourceDamage", function (evt) { - return evt.card == event.parent.card; - }).length > 0 - ) - player.gain( - cards.filter(function (card) { - return get.type(card, false) != "basic"; - }), - "gain2" - ); - }); - } - } - }, - }, //伊座并杏子 kyouko_rongzhu: { trigger: { global: "gainEnd" }, @@ -1064,7 +890,7 @@ const skills = { enable: "phaseUse", usable: 1, filter(event, player) { - return !player.getExpansions("kud_qiaoshou_equip").length && player.countCards("h") > 0; + return !player.hasVCard(card => card.storage?.kud_qiaoshou, "e") }, chooseButton: { dialog() { @@ -1138,20 +964,20 @@ const skills = { check(event, player) { return 6 - get.value(card); }, - content() { - "step 0"; - player.addToExpansion(cards, player, "give").gaintag.add("kud_qiaoshou_equip"); - "step 1"; - if (!player.getExpansions("kud_qiaoshou_equip").length) return; + async content(event, trigger, player) { + const name = lib.skill.kud_qiaoshou_backup.cardname, card = { + name, + subtypes: [], + storage: {kud_qiaoshou: true}, + } + game.log(player, "声明了", "#y" + get.translation(name)); + player.$throw(event.cards); + await game.delay(0, 300); + await player.equip(get.autoViewAs(card, event.cards)); player.addTempSkill("kud_qiaoshou_equip", { player: ["phaseUseEnd", "phaseZhunbeiBegin"], }); - var name = lib.skill.kud_qiaoshou_backup.cardname; - player.storage.kud_qiaoshou_equip2 = name; - var info = lib.card[name].skills; - if (info && info.length) player.addAdditionalSkill("kud_qiaoshou_equip", info); - player.draw(); - game.log(player, "声明了", "#y" + get.translation(name)); + await player.draw(); }, ai: { result: { @@ -1161,27 +987,12 @@ const skills = { }, kud_qiaoshou_equip: { charlotte: true, - mod: { - globalFrom(from, to, distance) { - var info = lib.card[from.storage.kud_qiaoshou_equip2]; - if (info && info.distance && info.distance.globalFrom) return distance + info.distance.globalFrom; - }, - globalTo(from, to, distance) { - var info = lib.card[to.storage.kud_qiaoshou_equip2]; - if (info && info.distance && info.distance.globalTo) return distance + info.distance.globalTo; - }, - attackRange(from, distance) { - var info = lib.card[from.storage.kud_qiaoshou_equip2]; - if (info && info.distance && info.distance.attackFrom) return distance - info.distance.attackFrom; - }, - attackTo(from, to, distance) { - var info = lib.card[to.storage.kud_qiaoshou_equip2]; - if (info && info.distance && info.distance.attackTo) return distance + info.distance.attackTo; - }, - }, onremove(player, skill) { - var cards = player.getExpansions(skill); - if (cards.length) player.loseToDiscardpile(cards); + const cards = player.getVCards("e", card => card.storage?.kud_qiaoshou).reduce((cards, vcard) => { + if (vcard?.cards.length) cards.addArray(vcard.cards); + return cards; + }, []); + if(cards.length) player.loseToDiscardpile(cards); }, intro: { markcount: "expansion", @@ -1194,11 +1005,6 @@ const skills = { else dialog.addText(str2); } }, - onunmark(storage, player) { - player.removeAdditionalSkill("kud_qiaoshou_equip"); - delete player.storage.kud_qiaoshou_equip2; - player.addEquipTrigger(); - }, }, }, kud_qiaoshou_end: { @@ -1253,26 +1059,25 @@ const skills = { } }, async content(event, trigger, player) { - const next = player.addToExpansion(event.cards, player, "give"); - next.gaintag.add("kud_qiaoshou_equip"); - await next; - if (!player.getExpansions("kud_qiaoshou_equip").length) return; + const name = event.cost_data.cardname, card = { + name, + subtypes: [], + storage: {kud_qiaoshou: true}, + } + game.log(player, "声明了", "#y" + get.translation(name)); + player.$throw(event.cards); + await game.delay(0, 300); + await player.equip(get.autoViewAs(card, event.cards)); player.addTempSkill("kud_qiaoshou_equip", { player: ["phaseUseEnd", "phaseZhunbeiBegin"], }); - const name = event.cost_data.cardname; - player.storage.kud_qiaoshou_equip2 = name; - player.markAuto("kud_qiaoshou_equip", event.cards); - const info = lib.card[name].skills; - if (info && info.length) player.addAdditionalSkill("kud_qiaoshou_equip", info); - game.log(player, "声明了", "#y" + get.translation(name)); await player.draw(); }, }, kud_buhui: { enable: "chooseToUse", filter(event, player) { - return event.type == "dying" && player == event.dying && player.getExpansions("kud_qiaoshou_equip").length + player.countCards("e") > 0; + return event.type == "dying" && player == event.dying && player.countCards("e") > 0; }, skillAnimation: true, limited: true, @@ -1280,7 +1085,7 @@ const skills = { content() { "step 0"; player.awakenSkill("kud_buhui"); - var cards = player.getCards("e").concat(player.getExpansions("kud_qiaoshou_equip")); + var cards = player.getCards("e"); if (cards.length) player.discard(cards); player.removeSkill("kud_qiaoshou_equip"); player.draw(cards.length); @@ -1449,7 +1254,7 @@ const skills = { game.cardsGotoOrdering(cards); var next = player.chooseToMove(); next.set("list", [["牌堆顶", cards], ["牌堆底"]]); - next.set("prompt", "幻梦:点击将牌移动到牌堆顶或牌堆底"); + next.set("prompt", "幻梦:点击或拖动将牌移动到牌堆顶或牌堆底"); next.processAI = function (list) { var cards = list[0][1], player = _status.event.player; @@ -1685,7 +1490,9 @@ const skills = { viewAs() { return { name: "tao" }; }, - filterCard: { name: "tao" }, + filterCard(card){ + return get.name(card, false) === "tao"; + }, ignoreMod: true, filterTarget(card, player, target) { return target != player && target.isDamaged() && target.hasSkill("nao_shouqing"); @@ -1693,18 +1500,19 @@ const skills = { selectTarget() { return game.countPlayer(function (current) { return lib.skill.nao_shouqing2.filterTarget(null, _status.event.player, current); - }) > 1 - ? 1 - : -1; + }) > 1 ? 1 : -1; }, filter(event, player) { return ( - player.countCards("hs", "tao") && + player.hasCard(card => get.name(card, false) === "tao", "hs") && game.hasPlayer(function (current) { return lib.skill.nao_shouqing2.filterTarget(null, player, current); }) ); }, + filterOk(){ + return ui.selected.cards.length === 1 && ui.selected.targets.length === 1; + }, position: "hs", onuse(links, player) { player.addSkill("nao_shouqing3"); @@ -1756,7 +1564,7 @@ const skills = { promptfunc: () => "出牌阶段,你可以赠予一张“米券”,然后执行一项本回合内未被选择过的效果:⒈对其造成1点伤害;⒉摸两张牌;⒊弃置其的两张牌;⒋亮出牌堆顶的一张牌,然后你可以使用之。", check: card => { const player = _status.event.player; - return get.type(card, false) == "equip" && game.hasPlayer(current => player.canGift(card, current, true) && !current.refuseGifts(card, player) && get.effect(current, card, player, player) > 0) ? 2 : 1 + Math.random(); + return get.type(card) == "equip" && game.hasPlayer(current => player.canGift(card, current, true) && !current.refuseGifts(card, player) && get.effect(current, card, player, player) > 0) ? 2 : 1 + Math.random(); }, content() { "step 0"; @@ -2306,7 +2114,7 @@ const skills = { player: ["phaseUseAfter"], global: ["roundStart"], }); - await game.asyncDelayx(); + await game.delayx(); }, subSkill: { round: { charlotte: true }, @@ -2404,94 +2212,6 @@ const skills = { }, }, }, - kiyu_xianyu: { - trigger: { global: "phaseUseBegin" }, - charlotte: true, - round: 1, - filter(event, player) { - return event.player.countCards("h") > 0; - }, - logTarget: "player", - check(event, player) { - var target = event.player; - var next = target.next; - if (target.getSeatNum() > next.getSeatNum()) return true; - if ( - target.countCards("h") < 4 && - target.countCards("h", function (card) { - return target.hasUseTarget(card, null, true); - }) < 2 - ) - return false; - return true; - }, - content() { - "step 0"; - var target = trigger.player, - cards = target.getCards("h"); - var next = player.chooseToMove("先预:预测" + get.translation(target) + "使用牌的顺序", true); - next.set("list", [[get.translation(target) + "的手牌", cards]]); - next.set("processAI", function (list) { - var cards = list[0][1].slice(0); - var target = _status.event.getTrigger().player; - cards.sort(function (a, b) { - return get.order(b, target) - get.order(a, target); - }); - return [cards]; - }); - "step 1"; - if (result.bool) { - var list = result.moved[0]; - player.storage.kiyu_xianyu_lastrun = list; - player.addTempSkill("kiyu_xianyu_lastrun", list); - } - }, - subSkill: { - lastrun: { - trigger: { global: "phaseUseAfter" }, - forced: true, - charlotte: true, - onremove: true, - content() { - var num = 0, - index = -1, - target = trigger.player; - var cards = player.getStorage("kiyu_xianyu_lastrun"); - var history = target.getHistory("useCard", function (event) { - return event.getParent("phaseUse") == trigger; - }); - for (var evt of history) { - var goon = false; - for (var card of evt.cards) { - var index2 = cards.indexOf(card); - if (index2 > index) { - goon = true; - index = index2; - } - } - if (goon) num++; - } - if (num > 0) { - num = Math.min(3, num); - player.draw(num); - if (target.isIn()) { - target.addTempSkill("kiyu_xianyu_effect"); - target.addMark("kiyu_xianyu_effect", num, false); - } - } - }, - }, - effect: { - charlotte: true, - onremove: true, - mod: { - maxHandcard(player, num) { - return num + player.countMark("kiyu_xianyu_effect"); - }, - }, - }, - }, - }, //樱庭星罗 seira_xinghui: { trigger: { player: "phaseZhunbeiBegin" }, @@ -2833,6 +2553,7 @@ const skills = { var source = ui[event.index == 0 ? "discardPile" : "cardPile"].childNodes; var list = []; for (var i = 0; i < source.length; i++) list.push(source[i]); + if(event.index == 0) list.reverse(); player.chooseButton(["请选择要移动的卡牌", list], true).ai = get.buttonValue; } "step 2"; @@ -2888,7 +2609,7 @@ const skills = { } "step 6"; if (event.index2 != 2) { - var node = ui[event.index == 0 ? "discardPile" : "cardPile"]; + var node = ui[event.index2 == 0 ? "discardPile" : "cardPile"]; if (event.target1) { var next = event.target1.lose(card, event.position); if (event.way == "顶部") next.insert_card = true; @@ -4285,6 +4006,7 @@ const skills = { }, forced: true, dutySkill: true, + derivation: "mia_fengfa", filter(event, player) { return event.name != "phase" || game.phaseNumber == 0; }, @@ -5298,7 +5020,7 @@ const skills = { return true; if ( player.getHistory("sourceDamage", function (evt) { - return get.type(evt.card, false) == "trick" && evt.getParent("phaseUse") == event; + return get.type(evt.card, null, false) == "trick" && evt.getParent("phaseUse") == event; }).length == 0 ) return true; @@ -5315,7 +5037,7 @@ const skills = { num++; if ( player.getHistory("sourceDamage", function (evt) { - return get.type(evt.card, false) == "trick" && evt.getParent("phaseUse") == trigger; + return get.type(evt.card, null, false) == "trick" && evt.getParent("phaseUse") == trigger; }).length == 0 ) num++; @@ -5907,7 +5629,7 @@ const skills = { trigger.orderingCards.addArray(cards); game.log(trigger.player, "的判定牌改为", cards[0]); await game.cardsDiscard(oldJudgeCard); - await game.asyncDelay(2); + await game.delay(2); if (!player.getExpansions("shiroha_yuzhao").length) { player.storage.shiroha_jiezhao = true; player.gainMaxHp(); @@ -5949,7 +5671,7 @@ const skills = { .forResult(); }, async content(event, trigger, player) { - await trigger.cancel(); + trigger.cancel(); player.skip("phaseDraw"); await player.useCard({ name: "sha", isCard: true }, event.targets[0], false); }, @@ -5986,7 +5708,7 @@ const skills = { .forResult(); }, async content(event, trigger, player) { - await trigger.cancel(); + trigger.cancel(); await player.discard(event.cards[0]); await player.useCard({ name: "sha", isCard: true }, event.targets[0]); }, @@ -6008,7 +5730,7 @@ const skills = { .forResult(); }, async content(event, trigger, player) { - await trigger.cancel(); + trigger.cancel(); await player.turnOver(); await player.useCard({ name: "sha", isCard: true }, event.targets[0], false); }, @@ -6394,7 +6116,7 @@ const skills = { player(player) { if ( player.countCards("he", function (card) { - if (get.type(card, player) == "equip") return get.value(card) < 6; + if (get.type(card, null, player) == "equip") return get.value(card) < 6; return get.value(card) < 5; }) < 2 ) @@ -6744,12 +6466,12 @@ const skills = { return player.countCards("he", lib.skill.kaori_siyuan.filterCard); }, filterCard(card) { - return ["equip", "delay"].includes(get.type(card, false)); + return ["equip", "delay"].includes(get.type(card)); }, filterTarget(card, player, target) { if (player == target) return false; var card = ui.selected.cards[0]; - if (get.type(card, false) == "delay") return target.canAddJudge({ name: card.name }); + if (get.type(card) == "delay") return target.canAddJudge({ name: get.name(card, player) }); return target.canEquip(card); }, discard: false, @@ -6758,8 +6480,8 @@ const skills = { content() { "step 0"; var card = cards[0]; - if (get.type(card, false) == "equip") target.equip(card); - else target.addJudge(card); + if (get.type(card) == "equip") target.equip(card); + else target.addJudge(get.name(card, player), [card]); "step 1"; var list = []; for (var i of lib.inpile) { @@ -9306,7 +9028,6 @@ const skills = { const cardToUse = { name: "sha", isCard: true }; if (lib.filter.targetEnabled(cardToUse, player, trigger.player)) { const { card } = await player.useCard(cardToUse, trigger.player); - console.log(card); if ( !player.hasHistory("sourceDamage", function (evt) { return evt.card === card; @@ -9506,7 +9227,7 @@ const skills = { async content(event, trigger, player) { const target = event.targets[0]; player.awakenSkill("saya_powei"); - game.asyncDelay(3); + await game.delay(3); var next = game.createEvent("saya_powei_loop", false, trigger); next.playertrue = player; next.playerfalse = target; @@ -10969,6 +10690,12 @@ const skills = { else trigger.bottom = true; } else trigger.directresult = get.bottomCards()[0]; }, + ai: { + abnormalDraw: true, + skillTagFilter: function (player, tag, arg) { + if (tag === "abnormalDraw") return !arg || arg === "bottom"; + } + } }, //此花露西娅 lucia_duqu: { diff --git a/character/key/translate.js b/character/key/translate.js index 2065545054..e22df595cb 100644 --- a/character/key/translate.js +++ b/character/key/translate.js @@ -478,9 +478,9 @@ const translates = { kud_qiaoshou_equip: "巧手", kud_qiaoshou_end: "巧手", kud_qiaoshou_backup: "巧手", - kud_qiaoshou_info: "出牌阶段/结束阶段,若你没有“巧”,则你可以将一张手牌作为“巧”置于武将牌上并摸一张牌,且视为装备了一张你选择的武器牌或进攻坐骑/防具牌或防御坐骑直到“巧”进入弃牌堆。出牌阶段结束时/准备阶段开始时,你将“巧”置入弃牌堆。", + kud_qiaoshou_info: "出牌阶段限一次/结束阶段开始时,若你没有“巧”,则你可以将一张手牌当作任意一张武器牌或进攻坐骑牌/防具牌或防御坐骑牌置入装备区(不占用装备区栏位),称为“巧”。出牌阶段结束时/准备阶段开始时,你将“巧”置入弃牌堆。", kud_buhui: "不悔", - kud_buhui_info: "限定技,当你进入濒死状态时,你可以弃置“巧”和装备区内的所有牌(至少一张)并摸等量的牌,将体力回复至2点,获得技能〖重振〗。", + kud_buhui_info: "限定技,当你进入濒死状态时,你可弃置装备区内的所有牌(至少一张)并摸等量的牌,将体力回复至2点,获得技能〖重振〗。", key_misuzu: "神尾观铃", misuzu_hengzhou: "恒咒", misuzu_hengzhou_info: "锁定技,准备阶段开始时,或当你受到1点伤害或回复1点体力后,你获得一个“诅咒”标记。你的手牌上限和摸牌阶段的额定摸牌数+X。结束阶段开始时,若X大于3,则你移去所有“诅咒”标记并失去1点体力。(X为“诅咒”标记数)", @@ -506,7 +506,7 @@ const translates = { nao_shouqing: "守情", nao_shouqing2: "守情", nao_shouqing3: "守情", - nao_shouqing_info: "其他角色的出牌阶段内可以对你使用【桃】。若如此做,其摸一张牌且本局游戏内的手牌上限+1。", + nao_shouqing_info: "其他角色的出牌阶段内可以对你使用非转化的【桃】。若如此做,其摸一张牌,且本局游戏内的手牌上限+1。", key_yuuki: "冰室忧希", yuuki_yicha: "异插", yuuki_yicha_info: "出牌阶段开始时,你可依次进行两次判定并将判定牌依次置入两行三列方阵的两个随机位置中。然后你依次进行四次判定,每次可将当前判定牌置入空方格,且须与相邻方格的牌颜色均不同。若如此做,你令一名角色获得方阵内的所有牌。", @@ -518,13 +518,6 @@ const translates = { kyouko_gongmian_exchange: "共勉", kyouko_gongmian_info: "①出牌阶段,你可以选择一名未以此法选择过的角色,若其手牌:大于你,你获得其一张牌,然后交给其一张牌;小于你,其交给你一张牌,然后你交给其一张牌;等于你,你与其各摸一张牌。②出牌阶段结束时,你可以获得一名其他角色区域内的至多X张牌,然后交给其等量的牌。③弃牌阶段开始时,若X不小于你的体力值,你可以获得一名手牌数少于你的角色的所有手牌,然后将手牌数的一半(向上取整)交给该角色。(X为你本回合内发动过〖共勉①〗的次数)", key_tenzen: "加纳天善", - tenzen_yixing: "弈兴", - tenzen_yixing_info: "当有角色因【杀】或【决斗】而受到伤害后,若其在你的攻击范围内或你在伤害来源的攻击范围内,你可以摸一张牌,然后将一张牌置于武将牌上,称为“兴”。当你成为其他角色使用【杀】或普通锦囊牌的唯一目标后,你可以获得一张“兴”,并可于此牌结算完成后弃置两张牌,视为对其使用一张名称相同的牌。", - //若对方为水织静久则无法触发〖弈兴〗 - tenzen_lingyu: "领域", - tenzen_lingyu_info: "觉醒技,准备阶段,若你的“兴”不小于你的体力值,则你减1点体力上限并获得技能〖天全〗。若你以此法失去了体力,则你摸两张牌。", - tenzen_tianquan: "天全", - tenzen_tianquan_info: "每回合限一次,当你使用【杀】或【决斗】指定唯一目标后,你可以移去两张“兴”并亮出牌堆顶的五张牌。这些牌中每有一张基本牌,响应此牌需要的【闪】/【杀】的数量便+1。此牌结算完成后,若此牌造成过伤害,则你获得这些牌中的非基本牌。", key_kotarou: "天王寺瑚太朗", kotarou_aurora: "丝刃", kotarou_aurora_info: "锁定技,当扣减体力或增加体力上限后,若你的装备区内:有武器牌,你视为使用一张【杀】;没有武器牌,你使用牌堆中的一张不为赠物的武器牌。", @@ -549,8 +542,6 @@ const translates = { key_kiyu: "露娜Q", kiyu_yuling: "玉灵", kiyu_yuling_info: "锁定技。你不是有距离限制的锦囊牌的合法目标;你成为【杀】的目标后,使用者需弃置X张牌(X为其至你的距离)。", - kiyu_xianyu: "先预", - kiyu_xianyu_info: "每轮限一次。一名角色的出牌阶段开始时,你可观看其手牌并预测其使用这些牌的顺序。此出牌阶段结束时,你摸X张牌,且其本回合的手牌上限+X(X为你的预测与其实际使用顺序的吻合数且至多为3)。", kiyu_rexianyu: "先预", kiyu_rexianyu_info: "每轮限一次。出牌阶段结束时,你可以选择一名其他角色。该角色于下个出牌阶段内使用第X张牌时,其可以将一张牌当做你本阶段内使用的第X张基本牌或普通锦囊牌使用(X至多为3);若如此做,你摸一张牌,且其本回合的手牌上限+1。", key_tomoyo: "坂上智代", diff --git a/character/mobile/card.js b/character/mobile/card.js index 3aca5cf16b..62d75c35a6 100644 --- a/character/mobile/card.js +++ b/character/mobile/card.js @@ -163,5 +163,38 @@ const cards = { }, skills: ["rw_zhuge_skill"], }, + //大攻车 + dagongche_attack: { + cardimage: "dagongche", + fullskin: true, + derivation: "mb_zhangfen", + type: "equip", + subtype: "equip1", + destroyLog: false, + distance: { attackFrom: -8 }, + ai: { basic: { equipValue: 10 } }, + cardPrompt(card) { + if (!card.storage || typeof card.storage.mbquchong != "number") return lib.translate["dagongche_attack_info"]; + let str = "②此牌剩余" + parseFloat(card.storage.mbquchong) + "点耐久度,耐久度为0时销毁此牌。"; + return str + "①当此牌进入你的装备区时,弃置你装备区里的其他牌。②其他装备区进入你的装备区前,改为将这些牌置于弃牌堆。③当你对一名角色造成伤害时,你可减少1点此牌的耐久度,令此伤害+X(X为游戏轮数且至多为3)。④当此牌不因〖渠冲〗离开装备区时,减少1点此牌的耐久度并防止之。"; + }, + skills: ["dagongche_attack_skill", "mbquchong_effect"], + }, + dagongche_defend: { + cardimage: "dagongche", + fullskin: true, + derivation: "mb_zhangfen", + type: "equip", + subtype: "equip1", + destroyLog: false, + distance: { attackFrom: -8 }, + ai: { basic: { equipValue: 10 } }, + cardPrompt(card) { + if (!card.storage || typeof card.storage.mbquchong != "number") return lib.translate["dagongche_defend_info"]; + let str = "②此牌剩余" + parseFloat(card.storage.mbquchong) + "点耐久度,耐久度为0时销毁此牌。"; + return str + "①当此牌进入你的装备区时,弃置你装备区里的其他牌。②其他装备区进入你的装备区前,改为将这些牌置于弃牌堆。③当你受到伤害时,减少X点此牌的耐久度,令此伤害-X(X为伤害值且至多为此牌耐久度)。④当此牌不因〖渠冲〗离开装备区时,减少1点此牌的耐久度并防止之。"; + }, + skills: ["dagongche_defend_skill", "mbquchong_effect"], + }, }; export default cards; diff --git a/character/mobile/character.js b/character/mobile/character.js index 55eb9b7dab..c095a833b8 100644 --- a/character/mobile/character.js +++ b/character/mobile/character.js @@ -1,4 +1,7 @@ const characters = { + mb_sp_zhenji: ["female", "qun", 3, ["mbbojian", "mbjiwei"]], + mb_zhangfen: ["male", "wu", 4, ["mbquchong", "mbxunjie"]], + mb_jiachong: ["male", "qun", 3, ["mbbeini", "mbdingfa"], ["character:jiachong", "die:jiachong"]], mb_simazhou: ["male", "wei", 4, ["mbbifeng", "mbsuwang"], ["name:司马|伷"]], mb_wenqin: ["male", "wei", 4, ["mbbeiming", "mbchoumang"]], mb_simafu: ["male", "wei", 3, ["mbpanxiang", "mbchenjie"], ["name:司马|孚"]], @@ -12,14 +15,13 @@ const characters = { mb_chengui: ["male", "qun", 3, ["guimou", "zhouxian"]], mb_huban: ["male", "wei", 4, ["mbyilie"]], mb_xianglang: ["male", "shu", 3, ["naxue", "yijie"]], - yanxiang: ["male", "qun", 3, ["kujian", "twruilian"], ["die:tw_yanxiang"]], + yanxiang: ["male", "qun", 3, ["kujian", "ruilian"], ["die:tw_yanxiang"]], mb_sunluyu: ["female", "wu", 3, ["mbmeibu", "mbmumu"]], xin_wuban: ["male", "shu", 4, ["xinjintao"], ["clan:陈留吴氏", "character:wuban"]], baoxin: ["male", "qun", 4, ["mutao", "yimou"], ["die:tw_baoxin"]], jiangji: ["male", "wei", 3, ["twjichou", "jilun"], ["character:tw_jiangji", "die:tw_jiangji"]], liwei: ["male", "shu", 4, ["jiaohua"], ["die:tw_liwei"]], laimin: ["male", "shu", 3, ["laishou", "luanqun"]], - yj_zhoubuyi: ["male", "wei", 3, ["mbhuiyao", "mbquesong"]], xin_guozhao: ["female", "wei", 3, ["yichong", "wufei"]], xin_zhangyi: ["male", "shu", 4, ["xinwurong", "shizhi"]], xin_sunliang: ["male", "wu", 3, ["xinzhizheng", "xinkuizhu", "xinlijun"], ["zhu"]], @@ -30,7 +32,6 @@ const characters = { re_yanwen: ["male", "qun", 4, ["reshuangxiong"], ["name:颜|良-文|丑"]], xin_zhoutai: ["male", "wu", 4, ["buqu", "new_fenji"]], re_caozhi: ["male", "wei", 3, ["reluoying", "rejiushi", "chengzhang"]], - yj_weiyan: ["male", "qun", "4/4/1", ["mbguli", "mbaosi"]], re_chenqun: ["male", "wei", 3, ["redingpin", "refaen"]], xin_caoxiu: ["male", "wei", 4, ["qianju", "xinqingxi"]], xin_zhuhuan: ["male", "wu", 4, ["fenli", "xinpingkou"]], @@ -55,7 +56,6 @@ const characters = { re_wuguotai: ["female", "wu", 3, ["reganlu", "buyi"], ["name:丁|null"]], xin_sunxiu: ["male", "wu", 3, ["mobileyanzhu", "mobilexingxue", "zhaofu"], ["zhu"]], sp_maojie: ["male", "wei", 3, ["bingqing", "yingfeng"]], - yj_huangzhong: ["male", "qun", 4, ["spshidi", "spyishi", "spqishe"]], re_yufan: ["male", "wu", 3, ["zhiyan", "rezongxuan"]], sunhanhua: ["female", "wu", 3, ["chongxu", "miaojian", "shhlianhua"]], yanpu: ["male", "qun", 3, ["huantu", "bihuo"]], @@ -80,7 +80,7 @@ const characters = { xin_guohuai: ["male", "wei", 4, ["mobilejingce"]], gongsunkang: ["male", "qun", 4, ["juliao", "taomie"], ["name:公孙|康"]], xin_zhangfei: ["male", "shu", 4, ["new_repaoxiao", "liyong"]], - xin_hansui: ["male", "qun", "4/4/1", ["xinniluan", "xiaoxi_hansui"]], + xin_hansui: ["male", "qun", "4/4/1", ["xinniluan", "xiaoxi_hansui"], ["die:hansui"]], hucheer: ["male", "qun", 4, ["daoji"]], re_lingtong: ["male", "wu", 4, ["rexuanfeng"]], re_liubiao: ["male", "qun", 3, ["zishou", "rezongshi"]], @@ -96,10 +96,6 @@ const characters = { re_dongzhuo: ["male", "qun", 8, ["rejiuchi", "roulin", "benghuai", "baonue"], ["zhu"]], re_xusheng: ["male", "wu", 4, ["repojun"]], sp_sufei: ["male", "qun", 4, ["zhengjian", "gaoyuan"]], - yj_zhangliao: ["male", "qun", 4, ["weifeng"]], - yj_zhanghe: ["male", "qun", 4, ["xinzhilve"]], - yj_xuhuang: ["male", "qun", 4, ["xinxhzhiyan"]], - yj_ganning: ["male", "qun", 4, ["gnjinfan", "gnsheque"]], re_sunjian: ["male", "wu", 4, ["gzyinghun", "repolu"]], zhengxuan: ["male", "qun", 3, ["zhengjing"]], dengzhi: ["male", "shu", 3, ["jimeng", "shuaiyan"]], diff --git a/character/mobile/characterReplace.js b/character/mobile/characterReplace.js index 30f1ee37ed..cd18a507af 100644 --- a/character/mobile/characterReplace.js +++ b/character/mobile/characterReplace.js @@ -1,16 +1,16 @@ const characterReplaces = { caochun: ["caochun", "old_caochun"], - majun: ["majun", "old_majun"], + majun: ["majun", "yj_majun", "old_majun"], zhanggong: ["zhanggong", "re_zhanggong"], baosanniang: ["xin_baosanniang", "re_baosanniang", "baosanniang"], heqi: ["re_heqi", "heqi"], weiwenzhugezhi: ["weiwenzhugezhi", "re_weiwenzhugezhi", "jsrg_weiwenzhugezhi"], xugong: ["xugong", "re_xugong", "jsrg_xugong"], liuzan: ["re_liuzan", "liuzan"], - sufei: ["yj_sufei", "sp_sufei", "xf_sufei"], + yj_sufei: ["yj_sufei", "sp_sufei", "xf_sufei"], jiakui: ["jiakui", "old_jiakui"], shenpei: ["shenpei", "sp_shenpei"], - sunru: ["dc_sunru", "sunru"], + sunru: ["dc_sunru", "ol_sunru", "sunru"], liuye: ["dc_liuye", "liuye"], zhaotongzhaoguang: ["dc_zhaotongzhaoguang", "zhaotongzhaoguang"], yangbiao: ["yangbiao", "dc_yangbiao", "jsrg_yangbiao"], diff --git a/character/mobile/dynamicTranslate.js b/character/mobile/dynamicTranslate.js index 0324353d30..f95b5caed2 100644 --- a/character/mobile/dynamicTranslate.js +++ b/character/mobile/dynamicTranslate.js @@ -11,10 +11,6 @@ const dynamicTranslates = { shhlianhua(player) { return ["当你成为【杀】的目标后,你摸一张牌。", "当你成为【杀】的目标后,你摸一张牌。然后你进行判定,若结果为黑桃,则此【杀】对你无效。", "当你成为【杀】的目标后,你摸一张牌。然后此【杀】的使用者选择一项:①弃置一张牌。②令此【杀】对你无效。"][player.countMark("shhlianhua")]; }, - spshidi(player) { - if (player.countMark("spshidi") % 2 == 0) return '转换技,锁定技。①准备阶段/结束阶段开始时,若你发动此分支的累计次数为奇数/偶数,则你获得一个“☯”。②若你的“☯”数为偶数,则你至其他角色的距离-1,且你使用的黑色【杀】不可被响应。③若你的“☯”数为奇数,则其他角色至你的距离+1,且你不可响应红色【杀】。'; - return '转换技,锁定技。①准备阶段/结束阶段开始时,若你发动此分支的累计次数为奇数/偶数,则你获得一个“☯”。②若你的“☯”数为偶数,则你至其他角色的距离-1,且你使用的黑色【杀】不可被响应。③若你的“☯”数为奇数,则其他角色至你的距离+1,且你不可响应红色【杀】。'; - }, mobilexingxue(player) { return lib.translate[(player.storage.mobileyanzhu ? "mobilexingxuex" : "mobilexingxue") + "_info"]; }, diff --git a/character/mobile/index.js b/character/mobile/index.js index d9ec7e98e8..92472abd7c 100644 --- a/character/mobile/index.js +++ b/character/mobile/index.js @@ -30,6 +30,7 @@ game.import("character", function () { ["mb_caomao_shadow", ["die:mb_caomao"]], ["mb_caomao_dead", ["die:mb_caomao"]], ], + shichangshi: [["shichangshi_dead", []]], }, card: { ...cards }, skill: { ...skills }, diff --git a/character/mobile/skill.js b/character/mobile/skill.js index 800ff45e1d..1ce1e48bca 100644 --- a/character/mobile/skill.js +++ b/character/mobile/skill.js @@ -2,6 +2,603 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { + //SP甄宓 + mbbojian: { + audio: 2, + init(player) { + player.addSkill("mbbojian_record"); + }, + trigger: { + player: "phaseUseEnd", + }, + filter(event, player) { + const record = _status.mbbojian; + if (!record || !record[player.playerid]) return false; + const history = player.getHistory("useCard", evt => evt.getParent("phaseUse", true)); + const num1 = history.length, + num2 = history.map(evt => get.suit(evt.card)).toUniqued().length, + cards = history.reduce((list, evt) => list.addArray(evt.cards.filterInD("d")), []); + return (num1 != record[player.playerid][0] && num2 != record[player.playerid][1]) || cards.length; + }, + forced: true, + async content(event, trigger, player) { + const record = _status.mbbojian; + const history = player.getHistory("useCard", evt => evt.getParent("phaseUse", true)); + const num1 = history.length, + num2 = history.map(evt => get.suit(evt.card)).toUniqued().length, + cards = history.reduce((list, evt) => list.addArray(evt.cards.filterInD("d")), []); + if (num1 != record[player.playerid][0] && num2 != record[player.playerid][1]) await player.draw(2); + else { + const links = + cards.length == 1 + ? cards + : await player + .chooseButton(["博鉴:请选择要分配的牌", cards], true) + .set("ai", button => { + return get.value(button.link); + }) + .forResultLinks(); + const togive = links[0]; + const { result } = await player.chooseTarget("选择获得" + get.translation(togive) + "的角色", true).set("ai", target => { + const player = get.player(); + return get.attitude(player, target); + }); + if (result.bool) { + await result.targets[0].gain(togive, "gain2"); + } + } + }, + subSkill: { + record: { + trigger: { + player: "phaseUseAfter", + }, + firstDo: true, + charlotte: true, + forced: true, + popup: false, + async content(event, trigger, player) { + const history = player.getHistory("useCard", evt => evt.getParent("phaseUse", true)); + const num1 = history.length, + num2 = history.map(evt => get.suit(evt.card)).toUniqued().length; + if (!_status.mbbojian) _status.mbbojian = {}; + _status.mbbojian[player.playerid] = [num1, num2]; + player.markSkill(event.name); + }, + intro: { + markcount: () => 0, + content(storage, player) { + const record = _status.mbbojian; + if (!record || !record[player.playerid]) return "无信息"; + return "上个出牌阶段使用牌情况:①牌数:" + record[player.playerid][0] + ";②花色数:" + record[player.playerid][1]; + }, + }, + }, + }, + }, + mbjiwei: { + audio: 4, + getNum(event, player) { + let num = 0; + if (game.countPlayer2(current => current.hasHistory("lose")) > 1) num++; + if (game.countPlayer2(current => current.hasHistory("damage")) > 1) num++; + if (event.name == "phase") return num; + return Math.max(game.countPlayer(), player.getHp()); + }, + trigger: { + player: "phaseZhunbeiBegin", + global: "phaseEnd", + }, + filter(event, player) { + const num = get.info("mbjiwei").getNum(event, player); + if (event.name == "phaseZhunbei") return player.countCards("h") >= num && game.hasPlayer(current => current != player); + return event.player != player && num > 0; + }, + logAudio(event, player) { + if (event.name == "phaseZhunbei") return ["mbjiwei3.mp3", "mbjiwei4.mp3"]; + return ["mbjiwei1.mp3", "mbjiwei2.mp3"]; + }, + forced: true, + async content(event, trigger, player) { + const num = get.info("mbjiwei").getNum(trigger, player); + if (trigger.name == "phase") await player.draw(num); + else { + const cards = player.getCards("h"), + map = {}; + for (let color of ["red", "black", "none"]) { + if (typeof map[color] != "number") map[color] = 0; + map[color] += cards.filter(card => get.color(card) == color).length; + } + const list = []; + for (var i in map) { + if (map[i] > 0) list.push([`${i}2`, map[i]]); + } + list.sort((a, b) => b[1] - a[1]); + let colors = list.filter(i => i[1] == list[0][1]).map(i => i[0]); + const control = colors.length == 1 ? colors[0] : await player.chooseControl(colors).set("prompt", "济危:请选择一个颜色").forResultControl(); + let togive = player.getCards("h").filter(card => get.color(card) == control.slice(0, -1)); + if (_status.connectMode) game.broadcastAll(() => (_status.noclearcountdown = true)); + let given_map = []; + while (togive.length) { + const { + result: { bool, cards, targets }, + } = await player.chooseCardTarget({ + forced: true, + filterCard(card, player) { + return get.event("togive").includes(card) && !card.hasGaintag("olsujian_given"); + }, + selectCard: [1, Infinity], + position: "h", + filterTarget: lib.filter.notMe, + prompt: "济危:请选择要分配的卡牌和目标", + ai1(card) { + return !ui.selected.cards.length && card.name == "du" ? 1 : 0; + }, + ai2(target) { + const player = get.event("player"); + const card = ui.selected.cards[0]; + if (card) return get.value(card, target) * get.attitude(player, target); + return 0; + }, + togive: togive, + }); + if (bool) { + togive.removeArray(cards); + const target = targets[0]; + if (given_map.some(i => i[0] == target)) { + given_map[given_map.indexOf(given_map.find(i => i[0] == target))][1].addArray(cards); + } else given_map.push([target, cards]); + player.addGaintag(cards, "olsujian_given"); + } else break; + } + if (_status.connectMode) { + game.broadcastAll(() => { + delete _status.noclearcountdown; + game.stopCountChoose(); + }); + } + if (given_map.length) { + await game + .loseAsync({ + gain_list: given_map, + player: player, + cards: given_map.slice().map(list => list[1]), + giver: player, + animate: "giveAuto", + }) + .setContent("gaincardMultiple"); + } + } + }, + }, + //张奋 + mbquchong: { + audio: 4, + trigger: { player: "phaseUseBegin" }, + filter(event, player) { + if ( + !game.hasPlayer(target => { + return target.hasCard(card => card.name.startsWith("dagongche_"), "e"); + }) + ) { + const num = player.getAllHistory("custom", evt => evt.name == "mbquchong").length; + return num < 4 && player.countMark("mbquchong") >= [0, 5, 10, 10][num]; + } + return player.canMoveCard( + null, + true, + game.filterPlayer(target => { + return target.hasCard(card => card.name.startsWith("dagongche_"), "e"); + }), + (card, player) => { + return card.name.startsWith("dagongche_"); + }, + "canReplace" + ); + }, + direct: true, + logAudio: index => (typeof index === "number" ? "mbquchong" + index + ".mp3" : 4), + async content(event, trigger, player) { + if ( + game.hasPlayer(target => { + return target.hasCard(card => card.name.startsWith("dagongche_"), "e"); + }) + ) { + await player + .moveCard( + get.prompt("mbquchong"), + "移动场上的一张【大攻车】", + (card, player) => { + return card.name.startsWith("dagongche_"); + }, + game.filterPlayer(target => { + return target.hasCard(card => card.name.startsWith("dagongche_"), "e"); + }), + "canReplace" + ) + .set("nojudge", true) + .set("logSkill", ["mbquchong", null, null, null, [4]]); + } else { + const numbers = Array.from({ length: 13 }).map((_, i) => get.strNumber(i + 1)); + const costMark = [0, 5, 10, 10][player.getAllHistory("custom", evt => evt.name == "mbquchong").length]; + const result = await player + .chooseButton( + [ + "###" + get.prompt("mbquchong") + '###
    消耗' + parseFloat(costMark) + "点铸造值,制造任意花色和点数的【大攻车·攻】或【大攻车·守】
    ", + [["dagongche_attack", "dagongche_defend"].map(i => [i, get.translation(i)]), "tdnodes"], + [ + lib.suit + .slice() + .reverse() + .map(i => [i, get.translation(i)]), + "tdnodes", + ], + [numbers, "tdnodes"], + ], + 3 + ) + .set("filterButton", button => { + return !ui.selected.buttons.some(but => { + return [["dagongche_attack", "dagongche_defend"], lib.suit, get.event("numbers")].some(list => list.includes(but.link) && list.includes(button.link)); + }); + }) + .set("numbers", numbers) + .set("ai", () => 1 + Math.random()) + .forResult(); //插眼,PZ157 + if (result.bool) { + const equips = result.links.sort((a, b) => { + return lib.suit.includes(a) + (numbers.includes(a) ? 2 : 0) - (lib.suit.includes(b) + (numbers.includes(b) ? 2 : 0)); + }); + const card = game.createCard(equips[0], equips[1], get.numString(equips[2])); + if (!card.storage) card.storage = {}; + if (typeof card.storage.mbquchong != "number") { + card.storage.mbquchong = card.name == "dagongche_attack" ? 1 : 3; + } + lib.skill.mbquchong.broadcast(card); + const resultx = await player + .chooseTarget("令一名角色获得" + get.translation(card) + "并使用之", true) + .set("ai", target => { + const player = get.event().player, + att = get.attitude(player, target); + if (!target.canEquip(get.event().card)) return att; + return att * (2.5 - target.countCards("e")); + }) + .set("card", card) + .forResult(); + if (resultx.bool) { + const target = resultx.targets[0]; + player.logSkill("mbquchong", target, null, null, [card.name == "dagongche_attack" ? 3 : 2]); + if (costMark > 0) player.removeMark("mbquchong", costMark); + player.getHistory("custom").push({ name: "mbquchong" }); + await target.gain(card, "gain2"); + if (get.position(card) == "h" && get.owner(card) == target && target.hasUseTarget(card)) { + await target.chooseUseTarget(card, "nopopup", false, true); + } + } + } + } + }, + broadcast(card) { + game.broadcast( + (card, storage) => { + card.storage = storage; + }, + card, + card.storage + ); + }, + marktext: "铸", + intro: { + name: "铸造点", + content: "当前拥有#铸造点", + }, + group: ["mbquchong_recast", "mbquchong_remove"], + derivation: ["dagongche_attack", "dagongche_defend"], + subSkill: { + recast: { + audio: "mbquchong1.mp3", + inherit: "drlt_huairou", + }, + remove: { + audio: "mbquchong1.mp3", + trigger: { global: "phaseEnd" }, + filter(event, player) { + return get.discardPile(i => get.type(i, false) == "equip"); + }, + forced: true, + locked: false, + async content(event, trigger, player) { + const cards = Array.from(ui.discardPile.childNodes).filter(i => get.type(i, false) == "equip"); + await game.cardsGotoSpecial(cards); + await player.showCards(cards, get.translation(player) + "发动了【渠冲】"); + game.log(cards, "被移出了游戏"); + player.addMark("mbquchong", cards.length); + }, + }, + effect: { + equipSkill: true, + trigger: { + player: ["loseBefore", "mbquchongOnRemove", "equipBefore", "equipAfter"], + }, + filter(event, player, name) { + if (name == "mbquchongOnRemove") { + return player.hasCard(card => card.name.startsWith("dagongche_") && card.storage?.mbquchong <= 0, "e"); + } + if (event.name == "equip") { + if (name == "equipBefore") return true; + if (!event.card.name.startsWith("dagongche_")) return false; + return player.hasCard(card => { + return !event.cards.includes(card) && lib.filter.cardDiscardable(card, player); + }, "e"); + } + if(event.getParent(2).name=="disableEquip") return false; + if (event.getParent(3).name == "mbquchong" || event.getParent(3).name == "mbquchong_recast") return false; + return player.hasCard(card => { + if (!event.cards.includes(card)) return false; + return card.name.startsWith("dagongche_") && card.storage?.mbquchong > 0; + }, "e"); + }, + forced: true, + async content(event, trigger, player) { + if (event.triggername == "mbquchongOnRemove") { + const cards = player.getCards("e", card => card.name.startsWith("dagongche_") && card.storage?.mbquchong <= 0); + await player.lose(cards, ui.special); + for (const card of cards) { + card.fix(); + card.remove(); + card.destroyed = true; + } + game.log(cards, "被移出了游戏"); + } else if (trigger.name == "equip") { + if (event.triggername == "equipBefore") trigger.cancel(); + else await player.discard(player.getCards("e", card => { + return !trigger.cards.includes(card) && lib.filter.cardDiscardable(card, player); + })); + } + else { + const cards = player.getCards("e", card => { + if (!trigger.cards.includes(card)) return false; + return card.name.startsWith("dagongche_") && card.storage?.mbquchong > 0; + }); + trigger.cards.removeArray(cards); + for (const card of cards) { + card.storage.mbquchong--; + game.log(card, '减少了', '#y1点', '#g耐久值'); + lib.skill.mbquchong.broadcast(card); + } + await event.trigger("mbquchongOnRemove"); + } + }, + ai: { + effect: { + target(card, player, target) { + if (!target.hasCard(card => card.name.startsWith("dagongche_"), "e")) return; + if (player == target && get.type(card) == "equip") return 0; + }, + }, + }, + }, + }, + }, + dagongche_attack_skill: { + equipSkill: true, + trigger: { source: "damageBegin3" }, + filter(event, player) { + if ( + !player.hasCard(card => { + return card.name == "dagongche_attack" && card.storage?.mbquchong > 0; + }, "e") + ) + return false; + return game.roundNumber > 0; + }, + logTarget: "player", + prompt2(event, player) { + return "令对" + get.translation(event.player) + "造成的伤害+" + parseFloat(Math.min(3, game.roundNumber)); + }, + check(event, player) { + return get.attitude(player, event.player) < 0 && event.player.hasSkillTag("filterDamage", null, { player: player, card: event.card }); + }, + async content(event, trigger, player) { + trigger.num += Math.min(3, game.roundNumber); + const cards = player.getCards("e", card => { + return card.name == "dagongche_attack" && card.storage?.mbquchong > 0; + }); + for (const card of cards) { + card.storage.mbquchong--; + game.log(card, '减少了', '#y1点', '#g耐久值'); + lib.skill.mbquchong.broadcast(card); + } + await event.trigger("mbquchongOnRemove"); + }, + }, + dagongche_defend_skill: { + equipSkill: true, + trigger: { player: "damageBegin3" }, + filter(event, player) { + if ( + !player.hasCard(card => { + return card.name == "dagongche_defend" && card.storage?.mbquchong > 0; + }, "e") + ) + return false; + return game.roundNumber > 0; + }, + forced: true, + locked: false, + async content(event, trigger, player) { + const cards = player.getCards("e", card => { + return card.name == "dagongche_defend" && card.storage?.mbquchong > 0; + }); + for (const card of cards) { + const num = Math.min(trigger.num, card.storage.mbquchong); + trigger.num -= num; + card.storage.mbquchong -= num; + game.log(card, '减少了', '#y' + num +'点', '#g耐久值'); + lib.skill.mbquchong.broadcast(card); + if (trigger.num <= 0) break; + } + await event.trigger("mbquchongOnRemove"); + }, + }, + mbxunjie: { + audio: 2, + trigger: { player: "damageBegin4" }, + filter(event, player) { + if (!event.source || event.source.getHp() <= player.getHp()) return false; + return !game.hasPlayer(target => { + return target.hasCard(card => card.name.startsWith("dagongche_"), "e"); + }); + }, + forced: true, + logTarget: "source", + async content(event, trigger, player) { + const result = await player + .judge(card => { + return get.suit(card) == "spade" ? -2 : 2; + }) + .set("judge2", result => Boolean(result.bool)) + .forResult(); + if (result.suit != "spade") trigger.num--; + }, + ai: { + combo: "mbquchong", + effect: { + target(card, player, target) { + if ( + player.getHp() <= target.getHp() || + game.hasPlayer(current => { + return current.hasCard(card => card.name.startsWith("dagongche_"), "e"); + }) + ) + return; + if (player.hasSkillTag("jueqing", false, target)) return; + const num = get.tag(card, "damage"); + if (num) { + if (num > 1) return 0.55; + return 0.05; + } + }, + }, + }, + }, + //贾充 + mbbeini: { + audio: "beini", + inherit: "beini", + async content(event, trigger, player) { + const target = event.targets[0]; + const str = get.translation(target); + const { + result: { index }, + } = await player + .chooseControl() + .set("choiceList", [`摸两张牌,然后令${str}视为对自己使用【杀】或弃置自己场上一张牌`, `令${str}摸两张牌,然后视为对其使用【杀】或弃置其场上一张牌`]) + .set("ai", () => { + const evt = _status.event.getParent(), + player = evt.player, + target = evt.target; + const card = { name: "sha", isCard: true }, + att = get.attitude(player, target) > 0; + if (!target.canUse(card, player, false) || get.effect(player, card, target, player) >= 0) return 0; + if (att && (!player.canUse(card, target, false) || get.effect(target, card, player, player) >= 0)) return 1; + if (target.hasSkill("nogain") && player.canUse(card, target, false) && get.effect(target, card, player, player) > 0) return 1; + if (player.hasShan()) return 0; + if (att && target.hasShan()) return 1; + return 0; + }); + const list = [player, target]; + if (index == 1) list.reverse(); + await list[0].draw(2); + const sha = get.autoViewAs({ name: "sha", isCard: true }); + const choices = []; + const choiceList = [`视为对${get.translation(list[0])}使用一张【杀】`, `弃置${get.translation(list[0])}场上一张牌`]; + if (list[1].canUse("sha", list[0], false)) choices.push("选项一"); + else choiceList[0] = '' + choiceList[0] + ""; + if (list[0].countDiscardableCards(list[1], "ej")) choices.push("选项二"); + else choiceList[1] = '' + choiceList[1] + ""; + if (!choices.length) return; + const control = + choices.length == 1 + ? choices[0] + : await list[1] + .chooseControl(choices) + .set("choiceList", choiceList) + .set("prompt", "悖逆:请选择一项") + .set("ai", () => { + const player = get.player(), + target = get.event("target"); + const eff2 = get.effect(target, { name: "sha" }, player, player), + eff1 = get.effect(target, { name: "guohe_copy2" }, player, player); + return eff1 > eff2 ? "选项一" : "选项二"; + }) + .set("target", list[0]) + .forResultControl(); + if (control == "选项一") await list[1].useCard(sha, list[0], false, "noai"); + else await list[1].discardPlayerCard(list[0], "ej", true); + }, + }, + mbdingfa: { + audio: "dingfa", + trigger: { + player: "phaseDiscardAfter", + }, + filter(event, player) { + let num = 0; + player.getHistory("lose", evt => { + num += evt.cards2.length; + }); + return num >= player.hp && (player.isDamaged() || game.hasPlayer(current => current.countDiscardableCards(player, "he"))); + }, + async cost(event, trigger, player) { + const choices = []; + const choiceList = ["回复1点体力", "弃置一名角色至多两张牌"]; + if (player.isDamaged()) choices.push("选项一"); + else choiceList[0] = '' + choiceList[0] + ""; + if (game.hasPlayer(current => current.countDiscardableCards(player, "he"))) choices.push("选项二"); + else choiceList[1] = '' + choiceList[1] + ""; + const control = await player + .chooseControl(choices, "cancel2") + .set("choiceList", choiceList) + .set("prompt", get.prompt(event.name.slice(0, -5))) + .set("ai", () => { + const player = get.player(); + const choices = get.event().controls.slice().remove("cancel2"); + const eff = get.recoverEffect(player, player, player); + if (!game.hasPlayer(current => get.effect(current, { name: "guohe_copy2" }, player, player) > eff)) choices.remove("选项二"); + else if (choices.includes("选项二")) return "选项二"; + if (eff <= 0) choices.remove("选项一"); + if (!choices.length) return "cancel2"; + return choices.randomGet(); + }) + .forResultControl(); + event.result = { + bool: control != "cancel2", + cost_data: control, + }; + }, + async content(event, trigger, player) { + if (event.cost_data == "选项一") await player.recover(); + else { + const targets = await player + .chooseTarget( + "选择一名角色弃置其至多两张牌", + (card, player, target) => { + return target.countDiscardableCards(player, "he"); + }, + true + ) + .set("ai", target => { + const player = get.player(); + return get.effect(target, { name: "guohe_copy2" }, player, player); + }) + .forResultTargets(); + if (!targets || !targets.length) return; + const target = targets[0]; + await player.discardPlayerCard(target, "he", true, [1, 2]); + } + }, + }, //司马伷 mbbifeng: { audio: 3, @@ -14,30 +611,39 @@ const skills = { if (event.targets && event.targets.length > 4) return false; return ["trick", "basic"].includes(get.type(event.card)); }, + logAudio: index => (typeof index === "number" ? "mbbifeng" + index + ".mp3" : 3), async cost(event, trigger, player) { if (event.triggername == "useCardAfter") event.result = { bool: true }; else { let choice = true; if (get.effect(player, trigger.card, trigger.player, player) >= 0) choice = false; - if (get.tag(trigger.card, 'damage') && trigger.targets.length == 1 && player.hp <= 2) choice = false; + if (get.tag(trigger.card, "damage") && trigger.targets.length == 1 && player.hp <= 2) choice = false; event.result = await player.chooseBool(get.prompt2("mbbifeng")).set("choice", choice).forResult(); } }, + popup: false, async content(event, trigger, player) { if (event.triggername == "useCardAfter") { player.unmarkAuto("mbbifeng", trigger.card); - if (game.hasPlayer(current => { - if (current == player) return false; - let respondEvts = []; - respondEvts.addArray(current.getHistory("useCard")).addArray(current.getHistory("respond")); - respondEvts = respondEvts.filter(i => i.respondTo).map(evt => evt.respondTo); - return respondEvts.some(list => { - return list[1] == trigger.card; - }); - })) await player.draw(2); - else await player.loseHp(); - } - else { + if ( + game.hasPlayer(current => { + if (current == player) return false; + let respondEvts = []; + respondEvts.addArray(current.getHistory("useCard")).addArray(current.getHistory("respond")); + respondEvts = respondEvts.filter(i => i.respondTo).map(evt => evt.respondTo); + return respondEvts.some(list => { + return list[1] == trigger.card; + }); + }) + ) { + player.logSkill("mbbifeng", null, null, null, [3]); + await player.draw(2); + } else { + player.logSkill("mbbifeng", null, null, null, [2]); + await player.loseHp(); + } + } else { + player.logSkill("mbbifeng", null, null, null, [1]); trigger.getParent().excluded.add(player); player.markAuto("mbbifeng", trigger.card); } @@ -76,16 +682,22 @@ const skills = { }, async cost(event, trigger, player) { const cards = player.getExpansions("mbsuwang"); - event.result = await player.chooseBool(get.prompt("mbsuwang"), "放弃摸牌并获得" + get.translation(cards)).set("choice", trigger.num <= cards.length).forResult(); + event.result = await player + .chooseBool(get.prompt("mbsuwang"), "放弃摸牌并获得" + get.translation(cards)) + .set("choice", trigger.num <= cards.length) + .forResult(); }, async content(event, trigger, player) { const cards = player.getExpansions("mbsuwang"); trigger.changeToZero(); await player.gain(cards, "gain2"); if (cards.length >= 3) { - const result = await player.chooseTarget("是否令一名其他角色摸两张牌?", lib.filter.notMe).set("ai", function (target) { - return get.effect(target, { name: "draw" }, _status.event.player, _status.event.player); - }).forResult(); + const result = await player + .chooseTarget("是否令一名其他角色摸两张牌?", lib.filter.notMe) + .set("ai", function (target) { + return get.effect(target, { name: "draw" }, _status.event.player, _status.event.player); + }) + .forResult(); if (result.bool) { player.line(result.targets[0], "green"); await result.targets[0].draw(2); @@ -96,7 +708,7 @@ const skills = { }, }, //文钦 - mbbeiming:{ + mbbeiming: { audio: 2, trigger: { global: "phaseBefore", @@ -140,44 +752,53 @@ const skills = { return event.card.name == "sha" && event.targets.length == 1; }, async cost(event, trigger, player) { - const list = ["选项一", "选项二"], target = event.triggername == "useCardToPlayered" ? trigger.target : trigger.player; - if (player.getEquip(1) && target.getEquip(1)) list.push("背水!"); + const list = ["选项一", "选项二"], + target = event.triggername == "useCardToPlayered" ? trigger.target : trigger.player; + if (player.getEquip(1) || target.getEquip(1)) list.push("背水!"); list.push("cancel2"); - const result = await player.chooseControl(list).set("choiceList", [ - "令此【杀】伤害+1", - "若此【杀】被【闪】抵消,你可以获得与你距离为1以内的一名其他角色区域里的一张牌", - "背水!弃置你与其装备区的武器牌并执行所有选项", - ]).set("prompt", get.prompt("mbchoumang")).set("result", function () { - let eff = 0; - for (const targetx of trigger.targets) eff += get.effect(targetx, trigger.card, trigger.player, player); - const bool = game.hasPlayer(current => player != current && get.distance(player, current) <= 1 && get.effect(current, { name: "shunshou_copy2" }, player, player) > 0); - if (list.includes("背水!") && eff > 0 && bool) return "背水!"; - if (bool) return "选项二"; - if (eff > 0) return "选项一"; - return "cancel2"; - }()).set("ai", function () { - return _status.event.result; - }).forResult(); - event.result = { - bool: result.control != "cancel2", - targets: [target], - cost_data: result.control, - }; - }, - async content(event, trigger, player) { - const result = event.cost_data, target = event.targets[0]; + const result = await player + .chooseControl(list) + .set("choiceList", ["令此【杀】伤害+1", "若此【杀】被【闪】抵消,你可以获得与你距离为1以内的一名其他角色区域里的一张牌", "背水!弃置你与其装备区的武器牌并执行所有选项"]) + .set("prompt", get.prompt("mbchoumang")) + .set( + "result", + (function () { + let eff = 0; + for (const targetx of trigger.targets) eff += get.effect(targetx, trigger.card, trigger.player, player); + const bool = game.hasPlayer(current => player != current && get.distance(player, current) <= 1 && get.effect(current, { name: "shunshou_copy2" }, player, player) > 0); + if (list.includes("背水!") && eff > 0 && bool) return "背水!"; + if (bool) return "选项二"; + if (eff > 0) return "选项一"; + return "cancel2"; + })() + ) + .set("ai", function () { + return _status.event.result; + }) + .forResult(); + event.result = { + bool: result.control != "cancel2", + targets: [target], + cost_data: result.control, + }; + }, + async content(event, trigger, player) { + const result = event.cost_data, + target = event.targets[0]; if (result == "背水!") { const list = []; if (player.getEquips(1).length) list.push([player, player.getEquips(1)]); if (target.getEquips(1).length) list.push([target, target.getEquips(1)]); - await game.loseAsync({ - lose_list: list, - discarder: player, - }).setContent("discardMultiple"); + await game + .loseAsync({ + lose_list: list, + discarder: player, + }) + .setContent("discardMultiple"); } if (result != "选项二") { trigger.getParent().baseDamage++; - await game.asyncDelay(); + await game.delay(); } if (result != "选项一") { player.addTempSkill("mbchoumang_effect"); @@ -196,12 +817,15 @@ const skills = { charlotte: true, onremove: true, async cost(event, trigger, player) { - event.result = await player.chooseTarget("仇铓:是否获得与你距离为1以内的一名其他角色区域里的一张牌?", function (card, player, target) { - return player != target && get.distance(player, target) <= 1 && target.countCards("hej"); - }).set("ai", function (target) { - const player = _status.event.player; - return get.effect(target, { name: "shunshou_copy2" }, player, player); - }).forResult(); + event.result = await player + .chooseTarget("仇铓:是否获得与你距离为1以内的一名其他角色区域里的一张牌?", function (card, player, target) { + return player != target && get.distance(player, target) <= 1 && target.countCards("hej"); + }) + .set("ai", function (target) { + const player = _status.event.player; + return get.effect(target, { name: "shunshou_copy2" }, player, player); + }) + .forResult(); }, async content(event, trigger, player) { const target = event.targets[0]; @@ -238,24 +862,34 @@ const skills = { }, async cost(event, trigger, player) { const num = lib.skill.mbchengxiong.phaseUsed(trigger, player); - event.result = await player.chooseTarget(get.prompt2("mbchengxiong"), function (card, player, target) { - const num = get.event("num"); - return target.countCards("he") >= num; - }).set("num", num).set("color", get.color(trigger.card)).set("ai", function (target) { - let player = get.player(), eff = get.effect(target, { name: "guohe_copy2" }, player, player); - const color = get.event("color"); - if (target.getCards("e").some(card => get.color(card) == color)) eff += get.damageEffect(target, player, player) / 2; - return eff; - }).forResult(); + event.result = await player + .chooseTarget(get.prompt2("mbchengxiong"), function (card, player, target) { + const num = get.event("num"); + return target.countCards("he") >= num; + }) + .set("num", num) + .set("color", get.color(trigger.card)) + .set("ai", function (target) { + let player = get.player(), + eff = get.effect(target, { name: "guohe_copy2" }, player, player); + const color = get.event("color"); + if (target.getCards("e").some(card => get.color(card) == color)) eff += get.damageEffect(target, player, player) / 2; + return eff; + }) + .forResult(); }, async content(event, trigger, player) { const target = event.targets[0]; - const result = await player.discardPlayerCard("he", target, true).set("ai", function (button) { - let val = get.buttonValue(button); - if (get.attitude(_status.event.player, get.owner(button.link)) > 0) val *= -1; - if (get.position(button.link) == "e" && get.color(button.link) == get.event("color")) return val *= 2; - return val; - }).set("color", get.color(trigger.card)).forResult(); + const result = await player + .discardPlayerCard("he", target, true) + .set("ai", function (button) { + let val = get.buttonValue(button); + if (get.attitude(_status.event.player, get.owner(button.link)) > 0) val *= -1; + if (get.position(button.link) == "e" && get.color(button.link) == get.event("color")) return (val *= 2); + return val; + }) + .set("color", get.color(trigger.card)) + .forResult(); if (result.bool && get.color(result.links[0]) == get.color(trigger.card)) await target.damage(); }, mod: { @@ -303,7 +937,7 @@ const skills = { if (event.filterCard(get.autoViewAs({ name: "shan" }, "unsure"), player, event) && !player.getStorage("mbzujin").includes("shan")) list.push(["基本", "", "shan"]); if (event.filterCard(get.autoViewAs({ name: "wuxie" }, "unsure"), player, event) && !player.getStorage("mbzujin").includes("wuxie")) list.push(["锦囊", "", "wuxie"]); } - if (!player.isDamaged() || !player.isMinHp() && !player.getStorage("mbzujin").includes("sha")) { + if (!player.isDamaged() || (!player.isMinHp() && !player.getStorage("mbzujin").includes("sha"))) { if (event.filterCard(get.autoViewAs({ name: "sha" }, "unsure"), player, event)) list.push(["基本", "", "sha"]); } return ui.create.dialog("阻进", [list, "vcard"]); @@ -318,15 +952,18 @@ const skills = { }, backup: function (links, player) { return { + audio: "mbzujin", filterCard: card => get.type(card) == "basic", popname: true, check: function (card) { return 8 - get.value(card); }, + logAudio(event, player) { + return "mbzujin" + (["sha", "shan", "wuxie"].indexOf(event.card.name) + 1) + ".mp3"; + }, position: "hse", viewAs: { name: links[0][2], nature: links[0][3] }, precontent: function () { - player.logSkill("mbzujin"); if (!player.storage.mbzujin) { player.storage.mbzujin = []; player.when({ global: "phaseEnd" }).then(() => { @@ -345,7 +982,7 @@ const skills = { if (!player.countCards("she", card => get.type(card) == "basic")) return false; if (player.getStorage("mbzujin").includes(name)) return false; if (["shan", "wuxie"].includes(name)) return player.isDamaged(); - if (name == "sha") return (!player.isDamaged() || !player.isMinHp()); + if (name == "sha") return !player.isDamaged() || !player.isMinHp(); }, ai: { respondSha: true, @@ -363,6 +1000,7 @@ const skills = { }, }, }, + subSkill: { backup: {} }, }, mbjiejian: { audio: 3, @@ -380,29 +1018,33 @@ const skills = { const give_map = {}; let used = []; do { - const result = await player.chooseCardTarget({ - filterCard: function (card) { - return get.itemtype(card) == "card" && !card.hasGaintag("mbjiejian_tag"); - }, - filterTarget: lib.filter.notMe, - selectCard: [1, Infinity], - prompt: used.length ? "是否继续分配手牌?" : get.prompt("mbjiejian"), - prompt2: "请选择要分配的卡牌和目标", - ai1: function (card) { - if (!ui.selected.cards.length) return 8 - get.value(card); - return 0; - }, - ai2: function (target) { - let player = _status.event.player, - card = ui.selected.cards[0]; - let val = get.value(card), att = get.attitude(player, target); - if (val <= 4) { - if (get.event("used").includes(target)) return 0; - return 1 / target.getUseValue(card); - } - return att * (target.getUseValue(card) + 4); - }, - }).set("used", used).forResult(); + const result = await player + .chooseCardTarget({ + filterCard: function (card) { + return get.itemtype(card) == "card" && !card.hasGaintag("mbjiejian_tag"); + }, + filterTarget: lib.filter.notMe, + selectCard: [1, Infinity], + prompt: used.length ? "是否继续分配手牌?" : get.prompt("mbjiejian"), + prompt2: "请选择要分配的卡牌和目标", + ai1: function (card) { + if (!ui.selected.cards.length) return 8 - get.value(card); + return 0; + }, + ai2: function (target) { + let player = _status.event.player, + card = ui.selected.cards[0]; + let val = get.value(card), + att = get.attitude(player, target); + if (val <= 4) { + if (get.event("used").includes(target)) return 0; + return 1 / target.getUseValue(card); + } + return att * (target.getUseValue(card) + 4); + }, + }) + .set("used", used) + .forResult(); if (result.bool && result.targets.length) { const id = result.targets[0].playerid, map = give_map; @@ -410,8 +1052,7 @@ const skills = { map[id].addArray(result.cards); player.addGaintag(result.cards, "mbjiejian_tag"); used.addArray(result.targets); - } - else break; + } else break; } while (player.countCards("h")); if (_status.connectMode) { game.broadcastAll(function () { @@ -419,7 +1060,8 @@ const skills = { game.stopCountChoose(); }); } - const list = [], targets = []; + const list = [], + targets = []; for (const i in give_map) { const source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; player.line(source, "green"); @@ -433,15 +1075,18 @@ const skills = { cost_data: list, }; }, + logAudio: () => 1, async content(event, trigger, player) { const list = event.cost_data; - await game.loseAsync({ - gain_list: list, - player: player, - cards: list.map(i => i[1]).flat(), - giver: player, - animate: "giveAuto", - }).setContent("gaincardMultiple"); + await game + .loseAsync({ + gain_list: list, + player: player, + cards: list.map(i => i[1]).flat(), + giver: player, + animate: "giveAuto", + }) + .setContent("gaincardMultiple"); for (let target of event.targets) { let num = target.hp - target.countMark("mbjiejian_mark"); target.addMark("mbjiejian_mark", num, false); @@ -450,7 +1095,7 @@ const skills = { group: ["mbjiejian_liuli", "mbjiejian_remove"], subSkill: { liuli: { - audio: "mbjiejian", + audio: "mbjiejian2.mp3", trigger: { global: "useCardToTarget", }, @@ -474,7 +1119,7 @@ const skills = { }, }, remove: { - audio: "mbjiejian", + audio: "mbjiejian3.mp3", trigger: { global: "phaseEnd", }, @@ -484,7 +1129,8 @@ const skills = { }, logTarget: "player", async content(event, trigger, player) { - const target = event.targets[0], num = target.countMark("mbjiejian_mark"); + const target = event.targets[0], + num = target.countMark("mbjiejian_mark"); target.removeMark("mbjiejian_mark", num, false); if (target.hp >= num) await player.draw(2); }, @@ -500,7 +1146,7 @@ const skills = { mbpanxiang: { audio: 4, trigger: { - global: "damageBegin3", + global: "damageBegin3", }, async cost(event, trigger, player) { const { player: target, source, card } = trigger; @@ -511,7 +1157,7 @@ const skills = { const choiceTexts = [`⒈令此伤害-1${source && source.isIn() ? "," + get.translation(source) + "摸两张牌" : ""};`, `⒉令此伤害+1,${get.translation(target)}摸三张牌。`]; if (!list.includes(SUB)) choiceTexts[0] = `${choiceTexts[0]}(上次选过)`; if (!list.includes(ADD)) choiceTexts[1] = `${choiceTexts[1]}(上次选过)`; - choiceTexts.forEach(text => prompt += text); + choiceTexts.forEach(text => (prompt += text)); const result = await player .chooseControl(list) .set("prompt", get.prompt("mbpanxiang", target)) @@ -554,7 +1200,8 @@ const skills = { if (att > 0) { if (trigger.num >= target.getHp()) return SUB; if ( - source && !source.countCards("hs", card => { + source && + !source.countCards("hs", card => { return source.canUse(card, target, true) && get.effect(target, card, source, player) > 0; }) ) @@ -580,6 +1227,10 @@ const skills = { }, logTarget: "player", onremove: true, + logAudio(event, player, name, indexedData, evt) { + const { control } = evt.cost_data; + return control == "减伤" ? ["mbpanxiang1.mp3", "mbpanxiang2.mp3"] : ["mbpanxiang3.mp3", "mbpanxiang4.mp3"]; + }, async content(event, trigger, player) { const { control } = event.cost_data; const { player: target, source } = trigger; @@ -614,7 +1265,7 @@ const skills = { await player.draw(4); }, ai: { - combo: "mbpanxiang" + combo: "mbpanxiang", }, }, //李昭焦伯 @@ -706,7 +1357,7 @@ const skills = { targets.forEach(current => { current.addSkill("mbkuangli_mark"); }); - await game.asyncDelayx(); + await game.delayx(); }, subSkill: { target: { @@ -717,9 +1368,12 @@ const skills = { }, forced: true, logTarget: "target", - usable: 2, + get usable() { + return get.mode() == "doudizhu" ? 1 : 2; + }, async content(event, trigger, player) { - const target = trigger.target, list = []; + const target = trigger.target, + list = []; const playerCards = player.getCards("he", card => { return lib.filter.cardDiscardable(card, player, "mbkuangli"); }); @@ -728,13 +1382,15 @@ const skills = { return lib.filter.cardDiscardable(card, target, "mbkuangli"); }); if (targetCards.length > 0) list.push([target, targetCards.randomGets(1)]); - await game.loseAsync({ - lose_list: list, - discarder: player, - }).setContent("discardMultiple"); - await game.asyncDelayx(); + await game + .loseAsync({ + lose_list: list, + discarder: player, + }) + .setContent("discardMultiple"); + await game.delayx(); await player.draw(2); - await game.asyncDelayx(); + await game.delayx(); }, ai: { effect: { @@ -846,9 +1502,9 @@ const skills = { ); }, async cost(event, trigger, player) { - const num = get.mode() === "identity" ? 3 : 2; + const num = 3; event.result = await player - .chooseTarget(get.prompt("mbcuizhen"), "废除至多" + get.cnNumber(num) +"名其他角色的武器栏", [1, num], (card, player, target) => { + .chooseTarget(get.prompt("mbcuizhen"), "废除至多" + get.cnNumber(num) + "名其他角色的武器栏", [1, num], (card, player, target) => { return target !== player && target.hasEnabledSlot(1); }) .set("ai", target => { @@ -862,7 +1518,7 @@ const skills = { for (const target of targets) { await target.disableEquip(1); } - await game.asyncDelay(); + await game.delay(); }, subSkill: { inphase: { @@ -883,7 +1539,7 @@ const skills = { }, async content(event, trigger, player) { await trigger.target.disableEquip(1); - await game.asyncDelayx(); + await game.delayx(); }, }, draw: { @@ -892,19 +1548,14 @@ const skills = { forced: true, locked: false, filter(event, player) { - return ( - !event.numFixed && - game.hasPlayer(current => { - return current.hasDisabledSlot(1); - }) - ); + return !event.numFixed; }, async content(event, trigger, player) { trigger.num += Math.min( - 4, + 3, game.countPlayer(current => { return current.countDisabledSlot(1); - }) + (get.mode() === "identity" ? 1 : 2) + }) + 1 ); }, }, @@ -1176,19 +1827,8 @@ const skills = { audio: "rejiushi", inherit: "rejiushi", persevereSkill: true, - group: ["rejiushi1", "mbcmjiushi_check", "mbcmjiushi_turnback", "mbcmjiushi_gain"], + group: ["rejiushi1", "mbcmjiushi_turnback", "mbcmjiushi_gain"], subSkill: { - check: { - trigger: { player: "damageBegin3" }, - silent: true, - firstDo: true, - filter(event, player) { - return player.isTurnedOver(); - }, - content() { - trigger.mbcmjiushi = true; - }, - }, turnback: { audio: "rejiushi", audioname: ["mb_caomao"], @@ -1289,11 +1929,14 @@ const skills = { const target = event.target; const num = lib.skill.mbcmfangzhu_backup.num; player.storage.mbcmfangzhu = target; - let evt=event.getParent("phaseUse",true); - if(evt) evt.fangzhuUsed=true; - player.when("phaseUseEnd").filter(evtx=>!evtx.fangzhuUsed).then(()=>{ - player.storage.mbcmfangzhu = player; - }); + let evt = event.getParent("phaseUse", true); + if (evt) evt.fangzhuUsed = true; + player + .when("phaseUseEnd") + .filter(evtx => !evtx.fangzhuUsed) + .then(() => { + player.storage.mbcmfangzhu = player; + }); switch (num) { case 1: target.addTempSkill("mbcmfangzhu_ban", { player: "phaseEnd" }); @@ -1462,8 +2105,7 @@ const skills = { }, //杨奉 mbxuetu: { - audio: 2, - audioname: ["re_yangfeng"], + audio: 4, enable: "phaseUse", usable: 2, filter(event, player) { @@ -1476,7 +2118,6 @@ const skills = { position: "he", onremove: ["mbxuetu", "mbxuetu_status"], derivation: ["mbxuetu_achieve", "mbxuetu_fail"], - chooseButton: { dialog() { const dialog = ui.create.dialog("###血途###请选择要执行的项"); @@ -1501,6 +2142,9 @@ const skills = { backup(result, player) { return { audio: "mbxuetu", + logAudio(event, player) { + return player.countMark("mbxuetu_status") == 2 ? ["mbxuetu3.mp3", "mbxuetu4.mp3"] : ["mbxuetu1.mp3", "mbxuetu2.mp3"]; + }, choice: result.control.includes("回复") ? 0 : 1, filterCard: () => false, selectCard: -1, @@ -1538,7 +2182,7 @@ const skills = { const { choice } = get.info("mbxuetu_backup"); const status = player.countMark("mbxuetu_status"); if (status > 1) { - if (player.storage.mbxuetu) return -get.damageEffect(target, player, player) / 10; + if (player.storage.mbxuetu) return get.damageEffect(target, player, target) / 10; return -2; } if (choice === 1) return 2; @@ -1653,7 +2297,7 @@ const skills = { player.awakenSkill("mbweiming"); player.storage.mbxuetu_status = 1; player.unmarkSkill("mbxuetu"); - await game.asyncDelayx(); + await game.delayx(); }, }, fail: { @@ -1670,10 +2314,7 @@ const skills = { game.log(player, "使命失败"); player.awakenSkill("mbweiming"); player.storage.mbxuetu_status = 2; - game.broadcastAll(player => { - player.tempname.add("re_yangfeng"); - }, player); - await game.asyncDelayx(); + await game.delayx(); }, }, }, @@ -1787,7 +2428,7 @@ const skills = { names = []; for (let i = 0; i < ui.discardPile.childElementCount; i++) { let card = ui.discardPile.childNodes[i]; - if (get.type(card, false) == "basic" && !names.includes(card.name)) { + if (get.type(card, null, false) == "basic" && !names.includes(card.name)) { gains.push(card); names.push(card.name); } @@ -1915,7 +2556,7 @@ const skills = { trigger.num++; }, ai: { - combo: "zhoulin" + combo: "zhoulin", }, }, zhoulin: { @@ -2217,10 +2858,10 @@ const skills = { }, ai: { effect: { - target_use: function (card, player, target, current) { + target: function (card, player, target, current) { if (get.tag(card, "damage") && get.attitude(player, target) < 0 && target != player) { if (_status.event.name == "zhouxian") return; - if (get.attitude(player, target) > 0 && current < 0) return "zerotarget"; + if (get.attitude(player, target) > 0 && current < 0) return "zeroplayertarget"; var bs = player.getDiscardableCards(player, "he"); bs.remove(card); if (card.cards) bs.removeArray(card.cards); @@ -2416,6 +3057,7 @@ const skills = { audio: "twkujian", inherit: "twkujian", selectCard: [1, 2], + logAudio: () => "twkujian1.mp3", content: function () { player.give(cards, target).gaintag.add("twkujianx"); player.addSkill("kujian_draw"); @@ -2424,7 +3066,7 @@ const skills = { subSkill: { draw: { charlotte: true, - audio: "twkujian", + audio: "twkujian2.mp3", trigger: { global: ["useCardAfter", "respondAfter"] }, filter: function (event, player) { return event.player.hasHistory("lose", evt => { @@ -2445,6 +3087,92 @@ const skills = { }, }, }, + ruilian: { + audio: "twruilian", + trigger: { global: "roundStart" }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2("ruilian")) + .set("ai", target => { + let player = _status.event.player, + att = get.attitude(player, target), + eff = att / (player == target ? 2 : 1) + 1; + if (att >= 0) { + if (target.hasSkill("yongsi")) return eff * 5; + if (target.hasSkill("zhiheng") || target.hasSkill("rezhiheng")) return eff * 4; + if (target.hasSkill("rekurou")) return eff * 3; + if (target.hasSkill("xinlianji") || target.hasSkill("dclianji")) return eff * 2; + if (target.needsToDiscard()) return eff * 1.5; + return eff; + } + return 0; + }) + .forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + player.addSkill("ruilian_target"); + player.markAuto("ruilian_target", [target]); + }, + subSkill: { + target: { + onremove: true, + intro: { content: "已选择$" }, + trigger: { global: "phaseEnd" }, + filter: function (event, player) { + return player.getStorage("ruilian_target").includes(event.player); + }, + direct: true, + charlotte: true, + async content(event, trigger, player) { + const target = trigger.player; + let cards = []; + player.removeSkill("ruilian_target"); + target.getHistory("lose", evt => { + if (evt.type == "discard") cards.addArray(evt.cards2); + }); + if (!cards.length) return; + let list = []; + for (let type of ["basic", "trick", "equip"]) { + for (let card of cards) { + if (get.type2(card) == type) { + list.push(type); + break; + } + } + } + list.push("cancel2"); + const result = await player + .chooseControl(list) + .set("prompt", "睿敛:是否与" + get.translation(target) + "各获得一种类型的牌?") + .set("ai", function () { + let player = _status.event.player, + list = _status.event.controls; + if (player.hp <= 3 && !player.countCards("h", { name: ["shan", "tao"] }) && list.includes("basic")) return "basic"; + if (player.countCards("he", { type: "equip" }) < 2 && list.includes("equip")) return "equip"; + if (list.includes("trick")) return "trick"; + return list.remove("cancel2").randomGet(); + }) + .forResult(); + if (result.control != "cancel2") { + player.logSkill("ruilian_target", target); + let type = result.control; + list = [target, player].sortBySeat(_status.currentPhase); + cards = []; + for (let current of list) { + let card = get.discardPile(function (card) { + return get.type2(card) == type && !cards.includes(card); + }); + if (card) { + cards.push(card); + await current.gain(card, "gain2"); + } + } + } + }, + }, + }, + }, //手杀差异化孙鲁育 mbmumu: { audio: "mumu", @@ -2493,7 +3221,7 @@ const skills = { } else { if (event.e) { player.gain(event.e, event.target, "give", "bySelf"); - player.addTempSkill("new_mumu2"); + player.addTempSkill("new_mumu_notsha"); } } }, @@ -2906,6 +3634,10 @@ const skills = { return player.maxHp >= num; }, forced: true, + logAudio(event, player) { + if (event.name == "damage") return 2; + return "laishou3.mp3"; + }, content: function () { if (trigger.name == "damage") { player.gainMaxHp(trigger.num); @@ -2920,6 +3652,9 @@ const skills = { return player.countCards("h"); }, usable: 1, + contentBefore: function () { + player.line(game.filterPlayer(current => current.countCards("h"))); + }, content: function () { "step 0"; var targets = game.filterPlayer(current => current.countCards("h")).sortBySeat(); @@ -2967,7 +3702,7 @@ const skills = { var cardx = cards.filter(cardy => cardy != card && get.color(cardy, targets[cards.indexOf(cardy)]) == get.color(card, player)); if (cardx.length) { player - .chooseButton(["乱群:是否获得其中的一张牌", cardx]) + .chooseButton(["乱群:是否获得其中至多四张牌", cardx]) .set("forceAuto", true) .set("ai", function (button) { var cards = _status.event.list[0]; @@ -2976,13 +3711,11 @@ const skills = { if (get.attitude(player, targets[cards.indexOf(button.link)]) > 0) return 0; return get.value(button.link, player); }) + .set("selectButton", [1, 4]) .set("list", [cards, targets]); } else event.goto(4); "step 3"; - if (result.bool) { - var card = result.links[0]; - player.gain(card, get.owner(card), "give"); - } + if (result.bool) player.gain(result.links, "give"); "step 4"; var card = cards[targets.indexOf(player)]; targets = targets.filter(target => get.color(cards[targets.indexOf(target)], target) != get.color(card, player)); @@ -3026,209 +3759,6 @@ const skills = { }, }, }, - //☆周不疑 - mbhuiyao: { - audio: 2, - enable: "phaseUse", - usable: 1, - // filterTarget:lib.filter.notMe, - content: function () { - "step 0"; - player.damage("nosource"); - "step 1"; - if (game.countPlayer() < 2) event.finish(); - if (game.countPlayer() == 2) - event._result = { - bool: true, - targets: [game.findPlayer(i => i != player), player], - }; - else - player - .chooseTarget( - `慧夭:请选择两名角色`, - `令不为你的第一名角色视为对第二名角色造成过1点伤害。`, - (card, player, target) => { - if (!ui.selected.targets.length) return player != target; - return true; - }, - 2, - true - ) - .set("multitarget", true) - .set("targetprompt", ["伤害来源", "受伤角色"]) - .set("ai", target => { - return target == get.event("aiTargets")[ui.selected.targets.length] ? 10 : 0; - }) - .set("aiTargets", lib.skill.mbhuiyao.getUnrealDamageTargets(player, [game.filterPlayer(i => i != player), game.filterPlayer()], true)); - "step 2"; - if (result.bool) { - var targets = result.targets; - player.line2(targets, "green"); - game.delaye(); - targets[1].damage(targets[0], "unreal"); - } - }, - getUnrealDamageTargets: (player, lists, forced) => { - const targets = [null, null]; - let sourceList, targetList; - if (lists.length == 2 && lists.every(l => Array.isArray(l))) { - sourceList = lists[0]; - targetList = lists[1]; - } else { - sourceList = lists.slice(); - targetList = lists.slice(); - } - const list = targetList - .map(current => { - const _hp = current.hp, - _maxhp = current.maxHp; - current.hp = 100; - current.maxHp = 100; - const att = -get.sgnAttitude(player, current); - let val = get.damageEffect(current, player, current) * att; - current.getSkills(null, false, false).forEach(skill => { - const info = get.info(skill); - if (info && info.ai && (info.ai.maixie || info.ai.maixie_hp || info.ai.maixie_defend)) val = Math[val > 0 ? "max" : "min"](val > 0 ? 0.1 : -0.1, val + 2 * att); - }); - const eff = 100 / val + 15; - current.hp = _hp; - current.maxHp = _maxhp; - return [current, eff]; - }) - .sort((a, b) => b[1] - a[1])[0]; - if (list[1] < 0 && !forced) return targets; - const targetx = list[0]; - targets[1] = targetx; - const list2 = sourceList - .filter(i => i != targetx) - .map(current => { - const _hp = targetx.hp, - _maxhp = targetx.maxHp; - targetx.hp = 100; - targetx.maxHp = 100; - const att = -get.sgnAttitude(player, current); - const eff = get.damageEffect(targetx, current, current) * att; - targetx.hp = _hp; - targetx.maxHp = _maxhp; - return [current, eff]; - }) - .sort((a, b) => b[1] - a[1])[0]; - if (!list2) return targets; - targets[0] = list2[0]; - return targets; - }, - ai: { - order: 6, - result: { - player: function (player) { - if (player.getHp() + player.countCards("hs", card => player.canSaveCard(card, player)) <= 1) return 0; - var limit = 25; - var quesong = player.hasSkill("mbquesong") && !player.getStat().damaged; - if (quesong) { - limit -= 7.5; - } - if ( - quesong && - game.hasPlayer(target => { - var att = get.attitude(player, target); - if (att < 0) return false; - return ( - att * - Math.sqrt( - Math.max( - 1, - [1, 2, 3, 4].reduce((p, c) => p + target.countEmptySlot(c), 0) - ) - ) >= - 10 || target.getHp() <= 2 - ); - }) - ) - return 1; - if ( - !quesong && - game.hasPlayer(target => { - if (target == player) return false; - var _hp = target.hp, - _maxhp = target.maxHp; - target.hp = 100; - target.maxHp = 100; - var att = -get.sgnAttitude(player, target); - var val = get.damageEffect(target, player, target) * att; - target.getSkills(null, false, false).forEach(skill => { - var info = get.info(skill); - if (info && info.ai && (info.ai.maixie || info.ai.maixie_hp || info.ai.maixie_defend)) val = Math[val > 0 ? "max" : "min"](val > 0 ? 0.1 : -0.1, val + 2 * att); - }); - var eff = 100 / val; - target.hp = _hp; - target.maxHp = _maxhp; - if (eff < limit) return false; - return true; - }) - ) - return 1; - return 0; - }, - }, - }, - }, - mbquesong: { - audio: 2, - trigger: { global: "phaseJieshuBegin" }, - filter: function (event, player) { - return player.getHistory("damage").length; - }, - direct: true, - content: function () { - "step 0"; - player.chooseTarget(get.prompt2("mbquesong")).set("ai", target => { - var player = _status.event.player; - if (get.attitude(player, target) <= 0) return 0; - var len = lib.skill.mbquesong.getNum(target), - hp = target.getHp(); - return len + target.isTurnedOver() * 2 + (1.5 * Math.min(4, target.getDamagedHp())) / (hp + 1); - }); - "step 1"; - if (result.bool) { - var target = result.targets[0]; - event.target = target; - player.logSkill("mbquesong", target); - var len = lib.skill.mbquesong.getNum(target); - if (target.isHealthy()) event._result = { index: 0 }; - else { - target - .chooseControl() - .set("choiceList", ["摸" + get.cnNumber(len) + "张牌并复原武将牌", "回复1点体力"]) - .set("prompt", "雀颂:请选择一项") - .set("ai", () => { - var player = _status.event.player; - var len = _status.event.len; - return get.effect(player, { name: "draw" }, player, player) * len >= get.recoverEffect(player, player, player) ? 0 : 1; - }) - .set("len", len); - } - } else event.finish(); - "step 2"; - if (result.index == 1) { - target.recover(); - event.finish(); - } else target.draw(lib.skill.mbquesong.getNum(target)); - "step 3"; - target.link(false); - "step 4"; - target.turnOver(false); - }, - getNum: function (player) { - return player.countCards("e", card => get.subtype(card) != "equip5") >= 3 ? 2 : 3; - }, - ai: { - expose: 0.2, - maixie: true, - skillTagFilter: function (player, tag) { - if (player.getStat().damaged) return false; - }, - }, - }, //郭照 yichong: { initSkill: function (skill) { @@ -3345,26 +3875,16 @@ const skills = { }, forced: true, content: function () { - "step 0"; var target = game.findPlayer(function (current) { if (!trigger.getg(current).length || !current.hasSkill("yichong_" + player.playerid)) return false; if (current.countMark("yichong_" + player.playerid) >= lib.skill.yichong.getLimit) return false; return trigger.getg(current).some(card => get.suit(card, current) == player.storage.yichong && lib.filter.canBeGained(card, current, player)); }); - event.target = target; var cards = trigger.getg(target).filter(card => get.suit(card, target) == player.storage.yichong && lib.filter.canBeGained(card, target, player)); - if (cards.length <= lib.skill.yichong.getLimit - target.countMark("yichong_" + player.playerid)) event._result = { bool: true, links: cards }; - else { - var num = lib.skill.yichong.getLimit - target.countMark("yichong_" + player.playerid); - player.chooseButton(["易宠:获得其中的" + get.cnNumber(num) + "张牌", cards], num, true).set("ai", function (button) { - return get.value(button.link); - }); - } - "step 1"; - if (result.bool) { - player.gain(result.links, target, "give"); - target.addMark("yichong_" + player.playerid, result.links.length, false); - } + var num = lib.skill.yichong.getLimit - target.countMark("yichong_" + player.playerid); + cards = cards.randomGets(num); + player.gain(cards, target, "giveAuto"); + target.addMark("yichong_" + player.playerid, cards.length, false); }, }, clear: { @@ -3666,10 +4186,12 @@ const skills = { if (lib.skill.mbdanggu.isSingleShichangshi(player)) { game.broadcastAll(function (player) { player.name1 = player.name; + player.skin.name = player.name; player.smoothAvatar(false); player.node.avatar.setBackground(player.name, "character"); player.node.name.innerHTML = get.slimName(player.name); delete player.name2; + delete player.skin.name2; player.classList.remove("fullskin2"); player.node.avatar2.classList.add("hidden"); player.node.name2.innerHTML = ""; @@ -3804,6 +4326,8 @@ const skills = { player.node.avatar.setBackground(first, "character"); player.node.name.innerHTML = get.slimName(first); player.name2 = chosen; + player.skin.name = first; + player.skin.name2 = chosen; player.classList.add("fullskin2"); player.node.avatar2.classList.remove("hidden"); player.node.avatar2.setBackground(chosen, "character"); @@ -3870,10 +4394,12 @@ const skills = { if (lib.skill.mbdanggu.isSingleShichangshi(player)) { game.broadcastAll(function (player) { player.name1 = player.name; + player.skin.name = player.name; player.smoothAvatar(false); player.node.avatar.setBackground(player.name, "character"); player.node.name.innerHTML = get.slimName(player.name); delete player.name2; + delete player.skin.name2; player.classList.remove("fullskin2"); player.node.avatar2.classList.add("hidden"); player.node.name2.innerHTML = ""; @@ -3895,7 +4421,7 @@ const skills = { audio: 2, trigger: { player: "dieBefore" }, filter: function (event, player) { - return player.getStorage("mbdanggu").length && event.getParent().name != "giveup" && player.maxHp > 0; + return event.getParent().name != "giveup" && player.maxHp > 0; }, derivation: "mbmowang_faq", forced: true, @@ -3906,12 +4432,14 @@ const skills = { if (_status.mbmowang_return && _status.mbmowang_return[player.playerid]) { trigger.cancel(); } else { - player.logSkill("mbmowang"); - game.broadcastAll(function () { - if (lib.config.background_speak) game.playAudio("die", "shichangshiRest"); - }); - trigger.setContent(lib.skill.mbmowang.dieContent); - trigger.includeOut = true; + if (player.getStorage("mbdanggu").length) { + player.logSkill("mbmowang"); + game.broadcastAll(function () { + if (lib.config.background_speak) game.playAudio("die", "shichangshiRest"); + }); + trigger.setContent(lib.skill.mbmowang.dieContent); + trigger.includeOut = true; + } else player.changeSkin("mbmowang", "shichangshi_dead"); } }, ai: { @@ -4011,10 +4539,12 @@ const skills = { player.classList.add("out"); if (list.includes(player.name1) || player.name1 == "shichangshi") { player.smoothAvatar(false); + player.skin.name = player.name1 + "_dead"; player.node.avatar.setBackground(player.name1 + "_dead", "character"); } if (list.includes(player.name2) || player.name2 == "shichangshi") { player.smoothAvatar(true); + player.skin.name2 = player.name2 + "_dead"; player.node.avatar2.setBackground(player.name2 + "_dead", "character"); } }, @@ -4069,10 +4599,12 @@ const skills = { if (!player.getStorage("mbdanggu").length) { game.broadcastAll(function (player) { player.name1 = player.name; + player.skin.name = player.name + "_dead"; player.smoothAvatar(false); player.node.avatar.setBackground(player.name + "_dead", "character"); player.node.name.innerHTML = get.slimName(player.name); delete player.name2; + delete player.skin.name2; player.classList.remove("fullskin2"); player.node.avatar2.classList.add("hidden"); player.node.name2.innerHTML = ""; @@ -4112,10 +4644,16 @@ const skills = { if (player.name1 == "shichangshi") { player.smoothAvatar(false); player.node.avatar.setBackground(player.name1, "character"); + if (!lib.skill.mbdanggu.isSingleShichangshi(player)) { + player.skin.name = player.name1; + } } if (player.name2 == "shichangshi") { player.smoothAvatar(true); player.node.avatar2.setBackground(player.name2, "character"); + if (!lib.skill.mbdanggu.isSingleShichangshi(player)) { + player.skin.name2 = player.name2; + } } }, trigger.player); "step 1"; @@ -5130,120 +5668,16 @@ const skills = { expose: 0.2, }, }, - //☆胃炎 - mbguli: { + // 界曹休 + xinqingxi: { audio: 2, - enable: "phaseUse", - filterCard: true, - selectCard: -1, - position: "h", - filter: function (event, player) { - if (player.hasSkill("mbguli_used")) return false; - var hs = player.getCards("h"); - if (!hs.length) return false; - for (var card of hs) { - var mod2 = game.checkMod(card, player, "unchanged", "cardEnabled2", player); - if (mod2 === false) return false; - } - return event.filterCard(get.autoViewAs({ name: "sha" }, hs)); - }, - viewAs: { - name: "sha", - storage: { mbguli: true }, + usable: 1, + trigger: { source: "damageBegin1" }, + check: function (event, player) { + return get.attitude(player, event.player) < 0; }, - onuse: function (links, player) { - player.addTempSkill("mbguli_used", "phaseUseAfter"); - }, - ai: { - order: 1, - threaten: 1.14, - unequip_ai: true, - skillTagFilter: function (player, tag, arg) { - if (arg && arg.name == "sha" && arg.card && arg.card.storage && arg.card.storage.mbguli) return true; - return false; - }, - }, - subSkill: { - used: { - audio: "mbguli", - trigger: { global: "useCardAfter" }, - charlotte: true, - prompt2: "失去1点体力,然后将手牌摸至体力上限", - check: function (event, player) { - var num = player.maxHp - player.countCards("h"); - return (num >= 3 && player.hp >= 2) || (num >= 2 && player.hp >= 3); - }, - filter: function (event, player) { - return ( - event.card.storage && - event.card.storage.mbguli && - game.hasPlayer2(current => { - return current.hasHistory("sourceDamage", evt => evt.card == event.card); - }) - ); - }, - content: function () { - "step 0"; - player.loseHp(); - "step 1"; - player.drawTo(player.maxHp); - }, - group: "mbguli_unequip", - }, - unequip: { - trigger: { - player: "useCardToPlayered", - }, - filter: function ({ card }) { - return card.name == "sha" && card.storage && card.storage.mbguli; - }, - forced: true, - popup: false, - logTarget: "target", - content: function () { - trigger.target.addTempSkill("qinggang2"); - trigger.target.storage.qinggang2.add(trigger.card); - trigger.target.markSkill("qinggang2"); - }, - }, - }, - }, - mbaosi: { - audio: 2, - trigger: { source: "damageSource" }, - forced: true, - filter: function (event, player) { - return player.inRange(event.player) && player.isPhaseUsing() && event.player.isIn() && !player.getStorage("mbaosi_inf").includes(event.player); - }, - logTarget: "player", - content: function () { - player.addTempSkill("mbaosi_inf", "phaseUseAfter"); - player.markAuto("mbaosi_inf", [trigger.player]); - }, - subSkill: { - inf: { - charlotte: true, - onremove: true, - forced: true, - intro: { content: "对$使用牌无次数限制" }, - mod: { - cardUsableTarget: function (card, player, target) { - if (player.getStorage("mbaosi_inf").includes(target)) return true; - }, - }, - }, - }, - }, - // 界曹休 - xinqingxi: { - audio: 2, - usable: 1, - trigger: { source: "damageBegin1" }, - check: function (event, player) { - return get.attitude(player, event.player) < 0; - }, - filter: function (event, player) { - return event.player != player; + filter: function (event, player) { + return event.player != player; }, content: function () { "step 0"; @@ -5304,7 +5738,7 @@ const skills = { event.redo(); } "step 3"; - var card = get.cardPile2(card => get.type(card, false) == "equip"); + var card = get.cardPile2(card => get.type(card, null, false) == "equip"); if (card) player.gain(card, "gain2"); }, ai: { @@ -5319,8 +5753,6 @@ const skills = { spdaming: { audio: 3, trigger: { global: "phaseBefore", player: "enterGame" }, - forced: true, - locked: false, global: "spdaming_give", filter: function (event, player) { return event.name != "phase" || game.phaseNumber == 0; @@ -5332,6 +5764,9 @@ const skills = { player.markSkill("spdaming"); game.log(player, (num > 0 ? "获得了" : "减少了") + get.cnNumber(Math.abs(num)) + "点“达命”值"); }, + forced: true, + locked: false, + logAudio: () => 2, content: function () { lib.skill.spdaming.change(player, 1); }, @@ -5345,8 +5780,9 @@ const skills = { subSkill: { used: { charlotte: true }, give: { - audio: 2, + audio: ["spdaming", 2], enable: "phaseUse", + forceaudio: true, nopop: true, filter: function (event, player) { if (!player.countCards("he")) return false; @@ -5391,7 +5827,6 @@ const skills = { }, content: function () { "step 0"; - game.trySkillAudio("spdaming", target); player.give(cards, target); if (!game.hasPlayer(current => current != player && current != target)) event.finish(); target.addTempSkill("spdaming_used", "phaseUseAfter"); @@ -5420,6 +5855,9 @@ const skills = { } else { var cards = cards.filter(i => get.owner(i) == target); if (cards.length) target.give(cards, player); + game.broadcastAll(function () { + if (lib.config.background_speak) game.playAudio("skill", "spdaming3"); + }); event.finish(); } } else event.finish(); @@ -5562,24 +6000,19 @@ const skills = { sbanguo: { audio: 3, trigger: { global: "phaseBefore", player: "enterGame" }, - forced: true, - locked: false, - direct: true, group: ["sbanguo_move", "sbanguo_damage", "sbanguo_dying"], + logAudio: () => 2, filter: function (event, player) { return game.hasPlayer(current => current != player) && (event.name != "phase" || game.phaseNumber == 0); }, + async cost(event, trigger, player) { + event.result = await player.chooseTarget("安国:令一名其他角色获得“安国”标记", lib.filter.notMe, true).forResult(); + }, content: function () { - "step 0"; - player.chooseTarget("安国:令一名其他角色获得“安国”标记", lib.filter.notMe, true); - "step 1"; - if (result.bool) { - var target = result.targets[0]; - player.logSkill("sbanguo", target); - target.addMark("sbanguo_mark", 1, false); - target.addAdditionalSkill("sbanguo_" + player.playerid, "sbanguo_mark"); - target.addMark("sbanguo_marked", 1, false); - } + const target = event.targets[0]; + target.addMark("sbanguo_mark", 1, false); + target.addAdditionalSkill("sbanguo_" + player.playerid, "sbanguo_mark"); + target.addMark("sbanguo_marked", 1, false); }, subSkill: { mark: { @@ -5599,6 +6032,7 @@ const skills = { }, move: { audio: "sbanguo", + logAudio: () => ["sbanguo1.mp3", "sbanguo2.mp3"], direct: true, trigger: { player: "phaseUseBegin" }, filter: function (event, player) { @@ -5645,6 +6079,7 @@ const skills = { }, damage: { audio: "sbanguo", + logAudio: () => ["sbanguo1.mp3", "sbanguo2.mp3"], forced: true, locked: false, trigger: { player: "damageBegin4" }, @@ -5673,7 +6108,7 @@ const skills = { }, }, dying: { - audio: "sbanguo", + audio: "sbanguo3.mp3", forced: true, locked: false, trigger: { global: "dying" }, @@ -5721,12 +6156,10 @@ const skills = { filter: function (event, player) { return player.countDiscardableCards(player, "he") > 0; }, - direct: true, - content: function () { - "step 0"; - player + logAudio: () => 1, + async cost(event, trigger, player) { + event.result = await player .chooseToDiscard(get.prompt2("sbbenxi"), [1, Infinity], "he") - .set("logSkill", "sbbenxi") .set("ai", card => { var player = _status.event.player; if (ui.selected.cards.length < _status.event.num) return 100 - (get.useful(card, player) + player.getUseValue(card) / 3); @@ -5769,25 +6202,25 @@ const skills = { if (!list2.length) return 0; return list2.sort((a, b) => b[0] - a[0])[0][1]; })() - ); - "step 1"; - if (result.bool) { - var num = result.cards.length; - player.addTempSkill("sbbenxi_effect", "phaseUseAfter"); - player.addTempSkill("sbbenxi_effect2", "phaseUseAfter"); - player.addMark("sbbenxi_effect2", num, false); - } + ) + .forResult(); + }, + async content(event, trigger, player) { + const num = event.cards.length; + player.addTempSkill("sbbenxi_effect", "phaseUseAfter"); + player.addTempSkill("sbbenxi_effect2", "phaseUseAfter"); + player.addMark("sbbenxi_effect2", num, false); }, subSkill: { effect: { - audio: "sbbenxi", + audio: "sbbenxi2.mp3", trigger: { player: "useCard2" }, forced: true, charlotte: true, direct: true, onremove: true, filter: function (event, player) { - var type = get.type(event.card, false); + var type = get.type(event.card, null, false); return type == "basic" || type == "trick"; }, content: function () { @@ -5845,7 +6278,7 @@ const skills = { }, }, effect2: { - audio: "sbbenxi", + audio: "sbbenxi3.mp3", trigger: { global: "useCardAfter", }, @@ -5996,8 +6429,10 @@ const skills = { yijin: { audio: 3, trigger: { player: "phaseUseBegin" }, - forced: true, - direct: true, + locked: true, + logAudio(_1, _2, _3, _4, result) { + return "yijin" + (["yijin_jinmi", "yijin_guxiong", "yijin_yongbi"].includes(result.cost_data) ? 2 : 1) + ".mp3"; + }, group: ["yijin_upstart", "yijin_die"], filter: function (event, player) { if (!game.hasPlayer(current => current != player && !lib.skill.yijin.getKane(current).length)) return false; @@ -6037,9 +6472,8 @@ const skills = { return (Math.min(5, 2 + target.getDamagedHp()) * get.recoverEffect(target, player, target)) / dis; } }, - content: function () { - "step 0"; - player + async cost(event, trigger, player) { + const { targets } = await player .chooseTarget("亿金:令一名其他角色获得1枚“金”", true, (card, player, target) => { return player != target && !lib.skill.yijin.getKane(target).length; }) @@ -6054,37 +6488,48 @@ const skills = { return att * lib.skill.yijin.getValue(player, i, target); }) ); - }); - "step 1"; - if (result.bool) { - var target = result.targets[0]; - event.target = target; - player.logSkill("yijin", target); - var kane = lib.skill.yijin.getKane(player); - var choiceList = kane.map(i => { - return '
    【' + get.translation(lib.translate[i + "_ab"] || get.translation(i).slice(0, 2)) + "】
    " + "
    " + get.skillInfoTranslation(i, player) + "
    "; - }); - player - .chooseControl(kane) - .set("choiceList", choiceList) - .set("displayIndex", false) - .set("prompt", "选择令" + get.translation(target) + "获得的“金”") - .set("ai", () => { - let controls = _status.event.controls, - player = _status.event.player, - target = _status.event.getParent().target, - att = get.attitude(player, target); - if (Math.abs(att) > 1) att = Math.sign(att) * Math.sqrt(Math.abs(att)); - let list = controls.map(i => { - return [i, att * lib.skill.yijin.getValue(player, i, target)]; - }); - list.sort((a, b) => b[1] - a[1]); - if (list.length) return list[0][0]; - return controls.randomGet(); + }) + .forResult(); + if (!targets.length) { + event.result = { bool: false }; + return; + } + const target = targets[0]; + event.target = target; + const kane = lib.skill.yijin.getKane(player); + const { control } = await player + .chooseControl(kane) + .set( + "choiceList", + kane.map(i => { + return '
    【' + get.translation(lib.translate[i + "_ab"] || get.translation(i).slice(0, 2)) + "】
    " + "
    " + get.skillInfoTranslation(i, player) + "
    "; + }) + ) + .set("displayIndex", false) + .set("prompt", "选择令" + get.translation(target) + "获得的“金”") + .set("ai", () => { + let controls = _status.event.controls, + player = _status.event.player, + target = _status.event.getParent().target, + att = get.attitude(player, target); + if (Math.abs(att) > 1) att = Math.sign(att) * Math.sqrt(Math.abs(att)); + let list = controls.map(i => { + return [i, att * lib.skill.yijin.getValue(player, i, target)]; }); - } else event.finish(); - "step 2"; - var kane = result.control; + list.sort((a, b) => b[1] - a[1]); + if (list.length) return list[0][0]; + return controls.randomGet(); + }) + .forResult(); + event.result = { + bool: true, + targets, + cost_data: control, + }; + }, + async content(event, trigger, player) { + const kane = event.cost_data; + const target = event.targets[0]; player.removeMark(kane, 1); player.popup(kane, "metal"); player.addSkill("yijin_clear"); @@ -6108,7 +6553,7 @@ const skills = { }, }, upstart: { - audio: "yijin", + audio: "yijin1.mp3", trigger: { global: "phaseBefore", player: "enterGame", @@ -6127,7 +6572,7 @@ const skills = { }, }, die: { - audio: "yijin", + audio: "yijin3.mp3", trigger: { player: "phaseBegin" }, forced: true, check: () => false, @@ -6362,13 +6807,13 @@ const skills = { audio: 3, liujing_filter: [ function (card) { - return get.type(card, false) == "trick" && get.tag(card, "damage", null, false) > 0; + return get.type(card, null, false) == "trick" && get.tag(card, "damage", null, false) > 0; }, - card => get.type(card, false) == "basic", + card => get.type(card, null, false) == "basic", card => get.name(card, false) == "wuxie", card => get.name(card, false) == "wuzhong", card => get.name(card, false) == "lebu", - card => get.type(card, false) == "equip", + card => get.type(card, null, false) == "equip", ], getLiujing: function (player, index) { var filter = lib.skill.chengye.liujing_filter[index], @@ -6391,7 +6836,7 @@ const skills = { } else if (event.name != "cardsDiscard") { var cards = event.getd(null, "cards2").filter(function (card) { if (get.position(card, true) != "d") return false; - var type = get.type(card, false); + var type = get.type(card, null, false); return type == "delay" || type == "equip"; }); cards.removeArray(event.getd(player, "cards2")); @@ -6403,7 +6848,7 @@ const skills = { if (evt2.name != "phaseJudge" || evt2.player == player) return; var cards = event.cards.filter(function (card) { if (get.position(card, true) != "d") return false; - var type = get.type(card, false); + var type = get.type(card, null, false); return type == "delay"; }); if (!cards.length) return false; @@ -6424,14 +6869,14 @@ const skills = { } else if (trigger.name != "cardsDiscard") { cards = trigger.getd().filter(function (card) { if (card.original == "j" || get.position(card, true) != "d") return false; - var type = get.type(card, false); + var type = get.type(card, null, false); return type == "delay" || type == "equip"; }); cards.removeArray(trigger.getd(player)); } else { cards = trigger.cards.filter(function (card) { if (get.position(card, true) != "d") return false; - var type = get.type(card, false); + var type = get.type(card, null, false); return type == "delay"; }); } @@ -6838,7 +7283,7 @@ const skills = { filter: function (event, player) { if (!player.countCards("he")) return false; for (var i of lib.inpile) { - if (i != "du" && get.type(i, false) == "basic") { + if (i != "du" && get.type(i, null, false) == "basic") { if (event.filterCard({ name: i }, player, event)) return true; if (i == "sha") { for (var j of lib.inpile_nature) { @@ -6864,7 +7309,7 @@ const skills = { var suit = event.xinjianying_suit || "", str = get.translation(suit); for (var i of lib.inpile) { - if (i != "du" && get.type(i, false) == "basic") { + if (i != "du" && get.type(i, null, false) == "basic") { if (event.filterCard({ name: i }, player, event)) list.push(["基本", str, i]); if (i == "sha") { for (var j of lib.inpile_nature) { @@ -7022,100 +7467,96 @@ const skills = { //蒋干 spdaoshu: { audio: 3, - group: "spdaoshu_effect", + trigger: { global: "phaseUseBegin" }, + filter: function (event, player) { + var goon = event.player != player && (get.mode() == "identity" || get.mode() == "guozhan" || event.player.isEnemyOf(player)); + return goon && event.player.countCards("h") > 0 && event.player.hasUseTarget({ name: "jiu", isCard: true }, null, true); + }, + round: 1, + logTarget: "player", + check: function (event, player) { + var target = event.player; + var att = get.attitude(player, target); + if (att > 0) return false; + if (att == 0) return !player.inRangeOf(target); + return true; + }, + logAudio: () => 1, + content: function () { + "step 0"; + event.target = trigger.player; + event.target.chooseUseTarget("jiu", true); + "step 1"; + if (!target.countCards("h")) { + event.finish(); + return; + } + var list = []; + for (var i of lib.inpile) { + if (get.type(i) == "basic") list.push(i); + } + if (!list.length) { + event.finish(); + return; + } + target + .chooseControl(list) + .set("prompt", "请声明一种基本牌") + .set("ai", () => _status.event.rand) + .set("rand", get.rand(0, list.length - 1)); + "step 2"; + event.cardname = result.control; + target.chat("我声明" + get.translation(event.cardname)); + game.log(target, "声明的牌名为", "#y" + get.translation(event.cardname)); + game.delayx(); + player + .chooseControl("有!", "没有!") + .set("prompt", "你觉得" + get.translation(target) + "的手牌区里有" + get.translation(event.cardname) + "吗?") + .set("ai", function () { + return _status.event.choice; + }) + .set( + "choice", + (function () { + var rand = + { + sha: 0.273, + shan: 0.149, + tao: 0.074, + jiu: 0.031, + }[event.cardname] || 0.1; + return 1 - Math.pow(1 - rand, target.countCards("h")) > 0.5 ? "有!" : "没有!"; + })() + ); + "step 3"; + player.chat(result.control); + game.log(player, "认为", "#y" + result.control); + game.delayx(); + "step 4"; + var bool1 = result.index == 0; + var bool2 = target.hasCard(function (card) { + return get.name(card, target) == event.cardname; + }, "h"); + if (bool1 == bool2) { + player.popup("判断正确", "wood"); + game.broadcastAll(function () { + if (lib.config.background_speak) game.playAudio("skill", "spdaoshu2"); + }); + player.gainPlayerCard(target, "h", 2, true); + //var cards=target.getCards('h',function(card){ + // return lib.filter.canBeGained(card,player,target); + //}).randomGets(5); + //if(cards.length>0) player.gain(cards,target,'giveAuto','bySelf'); + } else { + player.popup("判断错误", "fire"); + game.broadcastAll(function () { + if (lib.config.background_speak) game.playAudio("skill", "spdaoshu3"); + }); + //player.addTempSkill('spdaoshu_respond'); + } + }, + ai: { expose: 0.3 }, subSkill: { - effect: { - audio: "spdaoshu1", - trigger: { global: "phaseUseBegin" }, - filter: function (event, player) { - var goon = event.player != player && (get.mode() == "identity" || get.mode() == "guozhan" || event.player.isEnemyOf(player)); - return goon && event.player.countCards("h") > 0 && event.player.hasUseTarget({ name: "jiu", isCard: true }, null, true); - }, - round: 1, - logTarget: "player", - prompt2: () => lib.translate.spdaoshu_info, - check: function (event, player) { - var target = event.player; - var att = get.attitude(player, target); - if (att > 0) return false; - if (att == 0) return !player.inRangeOf(target); - return true; - }, - content: function () { - "step 0"; - event.target = trigger.player; - event.target.chooseUseTarget("jiu", true); - "step 1"; - if (!target.countCards("h")) { - event.finish(); - return; - } - var list = []; - for (var i of lib.inpile) { - if (get.type(i) == "basic") list.push(i); - } - if (!list.length) { - event.finish(); - return; - } - target - .chooseControl(list) - .set("prompt", "请声明一种基本牌") - .set("ai", () => _status.event.rand) - .set("rand", get.rand(0, list.length - 1)); - "step 2"; - event.cardname = result.control; - target.chat("我声明" + get.translation(event.cardname)); - game.log(target, "声明的牌名为", "#y" + get.translation(event.cardname)); - game.delayx(); - player - .chooseControl("有!", "没有!") - .set("prompt", "你觉得" + get.translation(target) + "的手牌区里有" + get.translation(event.cardname) + "吗?") - .set("ai", function () { - return _status.event.choice; - }) - .set( - "choice", - (function () { - var rand = - { - sha: 0.273, - shan: 0.149, - tao: 0.074, - jiu: 0.031, - }[event.cardname] || 0.1; - return 1 - Math.pow(1 - rand, target.countCards("h")) > 0.5 ? "有!" : "没有!"; - })() - ); - "step 3"; - player.chat(result.control); - game.log(player, "认为", "#y" + result.control); - game.delayx(); - "step 4"; - var bool1 = result.index == 0; - var bool2 = target.hasCard(function (card) { - return get.name(card, target) == event.cardname; - }, "h"); - if (bool1 == bool2) { - player.popup("判断正确", "wood"); - game.broadcastAll(function () { - if (lib.config.background_speak) game.playAudio("skill", "spdaoshu2"); - }); - player.gainPlayerCard(target, "h", 2, true); - //var cards=target.getCards('h',function(card){ - // return lib.filter.canBeGained(card,player,target); - //}).randomGets(5); - //if(cards.length>0) player.gain(cards,target,'giveAuto','bySelf'); - } else { - player.popup("判断错误", "fire"); - game.broadcastAll(function () { - if (lib.config.background_speak) game.playAudio("skill", "spdaoshu3"); - }); - //player.addTempSkill('spdaoshu_respond'); - } - }, - ai: { expose: 0.3 }, - }, respond: { trigger: { global: "useCard1" }, forced: true, @@ -7129,7 +7570,6 @@ const skills = { }, }, }, - spdaoshu1: { audio: true }, mbdaoshu: { audio: 3, group: "mbdaoshu_use", @@ -7138,9 +7578,10 @@ const skills = { audio: "mbdaoshu1", enable: "phaseUse", filter: function (event, player) { - return game.hasPlayer(target => target != player && target.countCards("h") >= 2); + return game.hasPlayer(target => lib.skill.mbdaoshu_use.filterTarget(event, player, target)); }, filterTarget: function (card, player, target) { + if (!["guozhan", "identity"].includes(get.mode()) && target.isFriendOf(player)) return false; return target != player && target.countCards("h") >= 2; }, usable: 1, @@ -7355,8 +7796,7 @@ const skills = { global: "loseAsyncAfter", }, filter: function (event, player, name) { - if (!player.countCards("h")) return false; - return name == "useCard1" || event.getg(player).length; + return name == "useCard1" || (event.getg(player).length && player.countCards("h")); }, direct: true, firstDo: true, @@ -7772,138 +8212,36 @@ const skills = { }, }, }, - //猩黄忠 - spshidi: { - audio: 2, - trigger: { player: ["phaseZhunbeiBegin", "phaseJieshuBegin"] }, - forced: true, - zhuanhuanji: "number", - filter: function (event, player) { - return player.countMark("spshidi") % 2 == ["phaseJieshu", "phaseZhunbei"].indexOf(event.name); - }, + //虞翻 + rezongxuan: { + inherit: "zongxuan", + group: "rezongxuan_place", + }, + rezongxuan_place: { + audio: "rezongxuan", + enable: "phaseUse", + usable: 1, content: function () { - player.changeZhuanhuanji("spshidi"); + "step 0"; + player.draw(); + "step 1"; + player.chooseCard("he", true, "将一张牌置于牌堆顶"); + "step 2"; + if (result && result.cards) { + event.card = result.cards[0]; + player.lose(result.cards, ui.cardPile, "insert"); + game.log(player, "将", get.position(event.card) == "h" ? "一张牌" : event.card, "置于牌堆顶"); + game.broadcastAll(function (player) { + var cardx = ui.create.card(); + cardx.classList.add("infohidden"); + cardx.classList.add("infoflip"); + player.$throw(cardx, 1000, "nobroadcast"); + }, player); + } else event.finish(); }, - mod: { - globalFrom: function (from, to, distance) { - if (from.countMark("spshidi") % 2 == 0) return distance - 1; - }, - globalTo: function (from, to, distance) { - if (to.countMark("spshidi") % 2 == 1) return distance + 1; - }, - aiOrder: function (player, card, num) { - if (player.countMark("spshidi") % 2 == 0 && card.name == "sha" && get.color(card) == "black") return num + 0.1; - }, - }, - mark: true, - marktext: "☯", - intro: { - content: function (storage, player) { - return "已转换过" + (storage || 0) + "次"; - }, - }, - ai: { - directHit_ai: true, - skillTagFilter: function (player, tag, arg) { - if (!arg || !arg.card || !arg.target || arg.card.name != "sha") return false; - return player.countMark("spshidi") % 2 == 0 && get.color(arg.card) == "black"; - }, - }, - group: ["spshidi_use", "spshidi_beused"], - subSkill: { - use: { - trigger: { player: "useCard" }, - forced: true, - filter: function (event, player) { - return event.card.name == "sha" && player.countMark("spshidi") % 2 == 0 && get.color(event.card, false) == "black"; - }, - content: function () { - trigger.directHit.addArray(game.players); - }, - }, - beused: { - trigger: { target: "useCardToTargeted" }, - forced: true, - filter: function (event, player) { - return event.card.name == "sha" && player.countMark("spshidi") % 2 == 1 && get.color(event.card, false) == "red"; - }, - content: function () { - trigger.directHit.add(player); - }, - }, - }, - }, - spyishi: { - audio: 2, - trigger: { source: "damageBegin2" }, - filter: function (event, player) { - return player != event.player && event.player.countCards("e") > 0; - }, - check: function (event, player) { - return ( - get.damageEffect(event.player, player, player) <= 0 || - (get.attitude(player, event.player) <= 0 && - !event.player.hasSkillTag("noe") && - event.player.hasCard(function (card) { - return get.value(card) > 9 - event.player.hp; - }, "e")) - ); - }, - logTarget: "player", - content: function () { - trigger.num--; - player.gainPlayerCard(trigger.player, "e", true); - }, - }, - spqishe: { - enable: "chooseToUse", - viewAs: { name: "jiu" }, - filterCard: { type: "equip" }, - position: "hes", - viewAsFilter: function (player) { - return player.hasCard({ type: "equip" }, "ehs"); - }, - check: function (card) { - if (_status.event.type == "dying") return 1 / (get.value(card) || 0.5); - return 5 - get.value(card); - }, - locked: false, - mod: { - maxHandcard: function (player, num) { - return num + player.countCards("e"); - }, - }, - }, - //虞翻 - rezongxuan: { - inherit: "zongxuan", - group: "rezongxuan_place", - }, - rezongxuan_place: { - audio: "rezongxuan", - enable: "phaseUse", - usable: 1, - content: function () { - "step 0"; - player.draw(); - "step 1"; - player.chooseCard("he", true, "将一张牌置于牌堆顶"); - "step 2"; - if (result && result.cards) { - event.card = result.cards[0]; - player.lose(result.cards, ui.cardPile, "insert"); - game.log(player, "将", get.position(event.card) == "h" ? "一张牌" : event.card, "置于牌堆顶"); - game.broadcastAll(function (player) { - var cardx = ui.create.card(); - cardx.classList.add("infohidden"); - cardx.classList.add("infoflip"); - player.$throw(cardx, 1000, "nobroadcast"); - }, player); - } else event.finish(); - }, - ai: { - order: 1, - result: { player: 1 }, + ai: { + order: 1, + result: { player: 1 }, }, }, //孙寒华 @@ -8615,10 +8953,10 @@ const skills = { effect: { target_use(card, player, target, current) { if (get.type(card) == "equip" && !get.tag(card, "gifts") && target.storage.jueyong && target.storage.jueyong[1].length) { - var result1 = get.equipResult(player, target, card.name), + var result1 = get.equipResult(player, target, card), subtype = get.subtype(card); for (var i of target.storage.jueyong[0]) { - if (get.subtype(i, false) == subtype && get.equipResult(target, target, i.name) >= result1) return "zerotarget"; + if (get.subtype(i, false) == subtype && get.equipResult(target, target, i) >= result1) return "zerotarget"; } } }, @@ -8723,7 +9061,7 @@ const skills = { direct: true, filter: function (event, player) { return ( - get.type(event.card, false) != "delay" && + get.type(event.card, null, false) != "delay" && game.hasPlayer(function (current) { return player != current && (!player.storage.discretesidi || !player.storage.discretesidi.includes(current)); }) @@ -8790,7 +9128,7 @@ const skills = { filter: function (event, player) { if (!player.storage.discretesidi || !player.storage.discretesidi.includes(event.player)) return false; if (event.name == "die") return true; - if (get.type(event.card, false) != "delay") { + if (get.type(event.card, null, false) != "delay") { var index = player.storage.discretesidi.indexOf(event.player); return index != -1 && (player.storage.discretesidi2[index] != event.target || event.targets.length != 1); } @@ -8807,7 +9145,7 @@ const skills = { forced: true, locked: false, filter: function (event, player) { - if (get.type(event.card, false) == "delay" || !player.storage.discretesidi || event.targets.length != 1) return false; + if (get.type(event.card, null, false) == "delay" || !player.storage.discretesidi || event.targets.length != 1) return false; var index = player.storage.discretesidi.indexOf(event.player); return index != -1 && player.storage.discretesidi2[index] == event.target; }, @@ -9566,11 +9904,11 @@ const skills = { return Math.random() < 0.5 ? 0 : 4; }); "step 1"; - var list = [0, 1, 1, 2, 2, 2, 3, 3, 4]; + let list = [0, 1, 1, 2, 2, 2, 3, 3, 4]; if (result.control != "cancel2") list.push(result.index); - var num = list.randomGet(); + let num = list.randomGet(); event.num = num; - var str = get.translation(player) + "抽取的命运签为:" + lib.skill["tiansuan2_" + num].name; + let str = get.translation(player) + "抽取的命运签为:" + lib.skill["tiansuan2_" + num].name; game.log(player, "抽取出了", "#g" + lib.skill["tiansuan2_" + num].name); event.dialog = ui.create.dialog(str); event.videoId = lib.status.videoId++; @@ -9585,15 +9923,18 @@ const skills = { player.chooseTarget(true, "令一名角色获得“" + lib.skill["tiansuan2_" + num].name + "”").set("ai", lib.skill["tiansuan2_" + num].aiCheck); "step 3"; if (result.bool) { - var target = result.targets[0]; + let target = result.targets[0]; player.line(target, "green"); game.log(player, "令", target, "获得了命运签"); player.storage.tiansuan2 = target; player.storage.tiansuan3 = "tiansuan2_" + num; player.addTempSkill("tiansuan2", { player: "phaseBegin" }); target.addSkill("tiansuan2_" + num); - if (num < 2 && target.countGainableCards(player, target == player ? "e" : "he") > 0) { - var next = player.gainPlayerCard(target, target == player ? "e" : "he", true); + let pos = "e"; + if (target != player) pos += "h"; + if (num == 0) pos += "j"; + if (num < 2 && target.countGainableCards(player, pos) > 0) { + let next = player.gainPlayerCard(target, pos, true); if (num == 0) next.visible = true; } else game.delayx(); } @@ -9641,7 +9982,7 @@ const skills = { ai: { effect: { target: function (card, player, target, current) { - if (get.tag(card, "damage") && !player.hasSkillTag("jueqing", false, target)) return "zerotarget"; + if (get.tag(card, "damage") && !player.hasSkillTag("jueqing", false, target)) return "zeroplayertarget"; }, }, }, @@ -9839,13 +10180,10 @@ const skills = { content: function () { "step 0"; target - .chooseToUse( - function (card, player, event) { - if (get.name(card) != "sha") return false; - return lib.filter.filterCard.apply(this, arguments); - }, - "挑衅:对" + get.translation(player) + "使用一张杀,或令其弃置你的一张牌" - ) + .chooseToUse(function (card, player, event) { + if (get.name(card) != "sha") return false; + return lib.filter.filterCard.apply(this, arguments); + }, "挑衅:对" + get.translation(player) + "使用一张杀,或令其弃置你的一张牌") .set("targetRequired", true) .set("complexSelect", true) .set("filterTarget", function (card, player, target) { @@ -11157,6 +11495,7 @@ const skills = { }, //韩遂 xinniluan: { + audio: "niluan", trigger: { global: "phaseJieshuBegin" }, direct: true, filter: function (event, player) { @@ -11471,7 +11810,7 @@ const skills = { var character = lib.character[i]; if (character && character[3]) { for (var j of character[3]) { - if (skills.includes(j) || j == "yuri_wangxi" || target.hasSkill("j")) continue; + if (skills.includes(j) || j == "yuri_wangxi" || target.hasSkill(j)) continue; var info = get.info(j); if (info && info.zhuSkill) { skills.add(j); @@ -11745,6 +12084,7 @@ const skills = { filterTarget: function (card, player, target) { return target != player && target.countCards("h") > 0; }, + logAudio: () => 2, content: function () { "step 0"; player.addTempSkill("beizhu_draw"); @@ -11804,13 +12144,13 @@ const skills = { }, }, beizhu_draw: { - trigger: { player: "damageEnd" }, - forced: true, - popup: false, charlotte: true, + audio: "beizhu3.mp3", + trigger: { player: "damageEnd" }, filter: function (event, player) { - return event.card && event.card.beizhu; + return event.card?.beizhu; }, + forced: true, content: function () { player.draw(trigger.num); }, @@ -12139,14 +12479,11 @@ const skills = { locked: false, audio: "jiuchi", filter: function (event, player) { - return event.card && event.card.name == "sha" && event.getParent(2).jiu == true && !player.hasSkill("rejiuchi_air"); + return event.card && event.card.name == "sha" && event.getParent(2).jiu == true && !player.isTempBanned("benghuai"); }, content: function () { - player.logSkill("jiuchi"); - player.addTempSkill("rejiuchi_air"); - }, - subSkill: { - air: {}, + player.logSkill("rejiuchi"); + player.tempBanSkill("benghuai"); }, }, //苏飞,新贾逵 @@ -13513,7 +13850,10 @@ const skills = { }, filterCard: true, position: "he", - filterTarget: lib.filter.notMe, + filterTarget(card, player, target) { + if (!["identity", "doudizhu"].includes(get.mode()) && target.isFriendOf(player)) return false; + return target != player; + }, check: function (card) { return 6 - get.value(card); }, @@ -13977,22 +14317,24 @@ const skills = { player: "gainAfter", global: "loseAsyncAfter", }, - direct: true, usable: 1, - filter: function (event, player) { - return event.getg(player).length && event.getParent("phaseDraw").player != player && player.countCards("he") > 0; + filter(event, player) { + return event.getg(player).length && event.getParent("phaseDraw").player != player && player.countCards("h") > 0; }, - content: function () { - "step 0"; - player.chooseCard(get.prompt2("xinqingjian"), "he", [1, player.countCards("he")]).ai = function () { - return -1; - }; - "step 1"; - if (result.bool) { - player.logSkill("xinqingjian"); - player.addSkill("xinqingjian2"); - player.addToExpansion(result.cards, "giveAuto", player).gaintag.add("xinqingjian2"); - } else player.storage.counttrigger.xinqingjian--; + async cost(event, trigger, player) { + event.result = await player + .chooseCard(get.prompt2(event.name.slice(0, -5)), "h", [1, player.countCards("h")]) + .set("ai", card => { + if (!game.hasPlayer(target => player != target && get.attitude(player, target) > 0)) return 0; + return 4 - get.value(card); + }) + .forResult(); + }, + async content(event, trigger, player) { + player.addSkill("xinqingjian2"); + const next = player.addToExpansion(event.cards, "giveAuto", player); + next.gaintag.add("xinqingjian2"); + await next; }, }, xinqingjian2: { @@ -14000,29 +14342,81 @@ const skills = { charlotte: true, trigger: { global: "phaseEnd" }, forced: true, - filter: function (event, player) { + filter(event, player) { return player.getExpansions("xinqingjian2").length > 0; }, - onremove: function (player, skill) { + onremove(player, skill) { var cards = player.getExpansions(skill); if (cards.length) player.loseToDiscardpile(cards); }, - content: function () { - "step 0"; - var cards = player.getExpansions("xinqingjian2"); - player.chooseTarget(true, lib.filter.notMe).set("createDialog", ["清俭:将这些牌交给一名角色" + (cards.length > 1 ? ",然后摸一张牌" : ""), cards]); - "step 1"; - if (result.bool) { - var target = result.targets[0]; - player.line(target, "thunder"); - if (player.give(player.getExpansions("xinqingjian2"), target).cards.length > 1) player.draw(); + async content(event, trigger, player) { + if (_status.connectMode) + game.broadcastAll(() => { + _status.noclearcountdown = true; + }); + const given_map = {}; + event.given_map = given_map; + const expansions = player.getExpansions("xinqingjian2"); + const goon = expansions.length > 1; + let result; + while (true) { + if (expansions.length > 1) { + result = await player + .chooseCardButton("清俭:请选择要分配的牌", true, expansions, [1, expansions.length]) + .set("ai", button => { + if (ui.selected.buttons.length) return 0; + return get.value(button.link, get.player()); + }) + .forResult(); + } else if (expansions.length === 1) result = { bool: true, links: expansions.slice(0) }; + else return; + if (!result.bool) return; + const toGive = result.links; + result = await player + .chooseTarget(`选择一名其他角色获得${get.translation(toGive)}`, expansions.length === 1, lib.filter.notMe) + .set("ai", target => { + const att = get.attitude(get.player(), target); + if (get.event("toEnemy")) return Math.max(0.01, 100 - att); + else if (att > 0) return Math.max(0.1, att / Math.sqrt(1 + target.countCards("h") + (get.event().getParent().given_map[target.playerid] || 0))); + else return Math.max(0.01, (100 + att) / 200); + }) + .set("toEnemy", get.value(toGive[0], player, "raw") < 0) + .forResult(); + if (result.bool) { + expansions.removeArray(toGive); + if (result.targets.length) { + const id = result.targets[0].playerid; + if (!given_map[id]) given_map[id] = []; + given_map[id].addArray(toGive); + } + if (!expansions.length) break; + } } - "step 2"; + if (_status.connectMode) + game.broadcastAll(() => { + delete _status.noclearcountdown; + game.stopCountChoose(); + }); + const gain_list = []; + for (const i in given_map) { + const source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; + player.line(source, "green"); + gain_list.push([source, given_map[i]]); + game.log(source, "获得了", given_map[i]); + } + await game + .loseAsync({ + gain_list, + giver: player, + animate: "gain2", + }) + .setContent("gaincardMultiple"); + if (goon) await player.draw(); player.removeSkill("xinqingjian2"); }, intro: { markcount: "expansion", - mark: function (dialog, storage, player) { + mark(dialog, storage, player) { var cards = player.getExpansions("xinqingjian2"); if (player.isUnderControl(true)) dialog.addAuto(cards); else return "共有" + get.cnNumber(cards.length) + "张牌"; @@ -14446,14 +14840,21 @@ const skills = { } else event.finish(); "step 2"; player.gain(event.cards, "gain2"); - "step 3" + "step 3"; if (!player.countCards("he")) event.finish(); - else player.chooseControl().set("choiceList", ["将" + get.cnNumber(event.num) + "张牌交给一名其他角色", "弃置" + get.cnNumber(event.num) + "张牌"]).set("ai", function () { - if (game.hasPlayer(function (current) { - return current != player && get.attitude(player, current) > 2; - })) return 0; - return 1; - }); + else + player + .chooseControl() + .set("choiceList", ["将" + get.cnNumber(event.num) + "张牌交给一名其他角色", "弃置" + get.cnNumber(event.num) + "张牌"]) + .set("ai", function () { + if ( + game.hasPlayer(function (current) { + return current != player && get.attitude(player, current) > 2; + }) + ) + return 0; + return 1; + }); "step 4"; if (result.index == 0) { player.chooseCardTarget({ @@ -14992,7 +15393,6 @@ const skills = { game.updateRoundNumber(); var list = ["nanman", "wanjian", "huogong", "juedou", "sha"]; var list2 = game.players.slice(0); - list2.remove(player); for (var i = 0; i < list.length; i++) { if (!targets[0].canUse(list[i], targets[1], false)) list.splice(i--, 1); } @@ -15120,9 +15520,6 @@ const skills = { group: "liezhi_damage", trigger: { player: "phaseZhunbeiBegin" }, direct: true, - filter: function (event, player) { - return !player.hasSkill("liezhi_disable"); - }, content: function () { "step 0"; player.chooseTarget(get.prompt("liezhi"), "弃置至多两名其他角色区域内的各一张牌", [1, 2], function (card, player, target) { @@ -15144,25 +15541,13 @@ const skills = { if (targets.length) event.redo(); }, subSkill: { - disable: { - sub: true, - trigger: { player: "phaseAfter" }, - forced: true, - silent: true, - popup: false, - charlotte: true, - //filter:function(event){return !event.liezhi}, - content: function () { - player.removeSkill("liezhi_disable"); - }, - }, damage: { trigger: { player: "damage" }, forced: true, silent: true, popup: false, content: function () { - player.addSkill("liezhi_disable"); + player.tempBanSkill("liezhi", { player: "phaseAfter" }); }, }, }, @@ -15217,7 +15602,7 @@ const skills = { xinzhanyi_basic1: { trigger: { player: "useCard" }, filter: function (event, player) { - return get.type(event.card, false) == "basic" && player.hasMark("xinzhanyi_basic1"); + return get.type(event.card, null, false) == "basic" && player.hasMark("xinzhanyi_basic1"); }, forced: true, silent: true, @@ -15488,7 +15873,7 @@ const skills = { }, }, xinfu_qianchong: { - audio: 3, + audio: 1, group: ["qc_weimu", "qc_mingzhe"], subSkill: { effect: { @@ -15510,6 +15895,7 @@ const skills = { player: "phaseUseBegin", }, direct: true, + derivation: ["qc_weimu", "qc_mingzhe"], filter: function (event, player) { var es = player.getCards("e"); if (!es.length) return true; @@ -15545,7 +15931,7 @@ const skills = { }, }, qc_weimu: { - audio: "xinfu_qianchong", + audio: true, mod: { targetEnabled: function (card, player, target) { var bool = true; @@ -15559,7 +15945,7 @@ const skills = { }, }, qc_mingzhe: { - audio: "xinfu_qianchong", + audio: true, trigger: { player: ["useCard", "respond", "loseAfter"], global: "loseAsyncAfter", @@ -15670,18 +16056,20 @@ const skills = { global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], }, filter: (event, player) => { - if (player.hasSkillTag("unequip2")) return false; - var evt = event.getl(player); - return evt && evt.es.some(card => card.name == "rewrite_baiyin"); + return !player.hasSkillTag("unequip2"); }, - content: function () { - var evt = trigger.getl(player); + getIndex(event, player) { + const evt = event.getl(player); + const lostCards = []; evt.es.forEach(card => { - if (card.name == "rewrite_baiyin") { - player.recover(); - player.draw(2); - } + const VEquip = evt.vcard_map.get(card); + if (VEquip.name === "rewrite_baiyin") lostCards.add(VEquip); }); + return lostCards.length; + }, + async content(event, trigger, player) { + await player.recover(); + await player.draw(2); }, }, }, @@ -15708,9 +16096,9 @@ const skills = { }, ai: { effect: { - target_use(card, player, target, current) { + target(card, player, target, current) { if (["tiesuo", "lulitongxin"].includes(card.name)) { - return "zerotarget"; + return "zeroplayertarget"; } }, }, @@ -15733,7 +16121,7 @@ const skills = { }, ai: { effect: { - target_use(card, player, target) { + target(card, player, target) { if (typeof card !== "object" || target.hasSkillTag("unequip2")) return; if ( player.hasSkillTag("unequip", false, { @@ -15766,7 +16154,7 @@ const skills = { inherit: "rw_minguangkai_link", ai: { effect: { - target_use(card, player, target, current) { + target(card, player, target, current) { if (["tiesuo", "lulitongxin"].includes(card.name)) { return "zeroplayertarget"; } @@ -15977,7 +16365,7 @@ const skills = { game.delay(); } }, - audio: true, + audio: 5, enable: "phaseUse", usable: 1, chooseButton: { @@ -16011,7 +16399,7 @@ const skills = { }, backup: function (links, player) { return { - audio: "xinfu_pingcai", + audio: "xinfu_pingcai1.mp3", filterCard: () => false, selectCard: -1, takara: links[0][2], @@ -16287,16 +16675,16 @@ const skills = { }, }, pcaudio_wolong_card: { - audio: true, + audio: "xinfu_pingcai2.mp3", }, pcaudio_fengchu_card: { - audio: true, + audio: "xinfu_pingcai3.mp3", }, pcaudio_shuijing_card: { - audio: true, + audio: "xinfu_pingcai4.mp3", }, pcaudio_xuanjian_card: { - audio: true, + audio: "xinfu_pingcai5.mp3", }, yizan_use: { audio: "yizan_respond_shan", @@ -16848,7 +17236,7 @@ const skills = { nofire: true, effect: { target: function (card, player, target, current) { - if (get.tag(card, "fireDamage")) return "zerotarget"; + if (get.tag(card, "fireDamage")) return "zeroplayertarget"; }, }, }, @@ -17002,7 +17390,7 @@ const skills = { return current != player && current.countCards("he"); }); }, - async cost(event, trigger, player){ + async cost(event, trigger, player) { let str = "令一名其他角色交给你一张牌"; const history = player.getAllHistory("damage", function (evt) { return evt.card && evt.card.name && lib.card[evt.card.name]; @@ -17017,19 +17405,23 @@ const skills = { return player.canUse(event.cardname, current) && get.effect(current, { name: event.cardname }, player, player) > 0; }); } - const result = await player.chooseTarget(get.prompt("choulve"), str, function (card, player, target) { - return target != player && target.countCards("he"); - }).set("ai", function (target) { - const event = get.event(); - if (!event.goon) return 0; - var player = event.player; - if (get.attitude(player, target) >= 0 && get.attitude(target, player) >= 0) { - return Math.sqrt(target.countCards("he")); - } - return 0; - }).set("goon", goon).forResult(); - if(result.bool){ - result.cost_data = {cardname: event.cardname}; + const result = await player + .chooseTarget(get.prompt("choulve"), str, function (card, player, target) { + return target != player && target.countCards("he"); + }) + .set("ai", function (target) { + const event = get.event(); + if (!event.goon) return 0; + var player = event.player; + if (get.attitude(player, target) >= 0 && get.attitude(target, player) >= 0) { + return Math.sqrt(target.countCards("he")); + } + return 0; + }) + .set("goon", goon) + .forResult(); + if (result.bool) { + result.cost_data = { cardname: event.cardname }; event.result = result; } }, @@ -17037,10 +17429,13 @@ const skills = { "step 0"; event.cardname = event.cost_data.cardname; var target = targets[0]; - target.chooseCard("he", "是否交给" + get.translation(player) + "一张牌?", event.cardname ? "若如此做,视为" + get.translation(player) + "使用【" + get.translation(event.cardname) + "】" : null).set("ai", function (card) { - if (_status.event.goon) return 7 - get.value(card); - return 0; - }).set("goon", get.attitude(target, player) > 1); + target + .chooseCard("he", "是否交给" + get.translation(player) + "一张牌?", event.cardname ? "若如此做,视为" + get.translation(player) + "使用【" + get.translation(event.cardname) + "】" : null) + .set("ai", function (card) { + if (_status.event.goon) return 7 - get.value(card); + return 0; + }) + .set("goon", get.attitude(target, player) > 1); event.target = target; "step 1"; if (result.bool) { @@ -17110,604 +17505,15 @@ const skills = { player.discardPlayerCard(trigger.player, "e", true, trigger.player.countCards("e")); }, }, - xinzhilve: { - enable: "phaseUse", - audio: "zhilve", - usable: 1, - chooseButton: { - dialog: function (event, player) { - var list = ["移动场上的一张牌", "摸一张牌并视为使用一张【杀】"]; - var choiceList = ui.create.dialog("知略:失去1点体力并...", "forcebutton", "hidden"); - choiceList.add([ - list.map((item, i) => { - return [i, item]; - }), - "textbutton", - ]); - return choiceList; - }, - filter: function (button, player) { - if (button.link == 0) return player.canMoveCard(); - return player.hasUseTarget({ name: "sha", isCard: true }, false); - }, - check: function (button) { - return button.link; - }, - backup: function (links) { - return lib.skill["xinzhilve_" + ["move", "use"][links[0]]]; - }, - prompt: function () { - return "请选择【杀】的目标"; - }, - }, - ai: { - order: function (item, player) { - return get.order({ name: "sha" }) + 0.1; - }, - result: { - player: function (player) { - if (player.hp > 2 && player.hasValueTarget({ name: "sha" })) return 1; - return 0; - }, - }, - }, - }, - xinzhilve_move: { - audio: "zhilve", - filterCard: function () { - return false; + _mbcmjiushi_check: { + trigger: { player: "damageBegin3" }, + silent: true, + firstDo: true, + filter(event, player) { + return player.isTurnedOver(); }, - selectCard: -1, - delay: false, - content: function () { - "step 0"; - event.forceDie = true; - if (!player.canMoveCard(null, event.nojudge)) { - event.finish(); - return; - } - var next = player.chooseTarget(2, function (card, player, target) { - if (ui.selected.targets.length) { - var from = ui.selected.targets[0]; - var js = from.getCards("j"); - for (var i = 0; i < js.length; i++) { - if (_status.event.nojudge) break; - if (target.canAddJudge(js[i])) return true; - } - if (target.isMin()) return false; - var es = from.getCards("e"); - for (var i = 0; i < es.length; i++) { - if (target.canEquip(es[i])) return true; - } - return false; - } else { - var range = "ej"; - if (_status.event.nojudge) range = "e"; - return target.countCards(range) > 0; - } - }); - next.set("nojudge", event.nojudge || false); - next.set("ai", function (target) { - var player = _status.event.player; - var att = get.attitude(player, target); - var sgnatt = get.sgn(att); - if (ui.selected.targets.length == 0) { - if (att > 0) { - if ( - !_status.event.nojudge && - target.countCards("j", function (card) { - return game.hasPlayer(function (current) { - return current.canAddJudge(card) && get.attitude(player, current) < 0; - }); - }) - ) - return 14; - if ( - target.countCards("e", function (card) { - return ( - get.value(card, target) < 0 && - game.hasPlayer(function (current) { - return current != target && get.attitude(player, current) < 0 && current.canEquip(card); - }) - ); - }) > 0 - ) - return 9; - } else if (att < 0) { - if ( - game.hasPlayer(function (current) { - if (current != target && get.attitude(player, current) > 0) { - var es = target.getCards("e"); - for (var i = 0; i < es.length; i++) { - if (get.value(es[i], target) > 0 && current.canEquip(es[i]) && get.value(es[i], current) > 0) return true; - } - } - }) - ) { - return -att; - } - } - return 0; - } - var es = ui.selected.targets[0].getCards("e"); - var i; - var att2 = get.sgn(get.attitude(player, ui.selected.targets[0])); - for (i = 0; i < es.length; i++) { - if (sgnatt != 0 && att2 != 0 && get.sgn(get.value(es[i], ui.selected.targets[0])) == -att2 && get.sgn(get.value(es[i], target)) == sgnatt && target.canEquip(es[i])) { - return Math.abs(att); - } - } - if ( - i == es.length && - (_status.event.nojudge || - !ui.selected.targets[0].countCards("j", function (card) { - return target.canAddJudge(card); - })) - ) { - return 0; - } - return -att * get.attitude(player, ui.selected.targets[0]); - }); - next.set("multitarget", true); - next.set("targetprompt", _status.event.targetprompt || ["被移走", "移动目标"]); - next.set("prompt", event.prompt || "移动场上的一张牌"); - if (event.prompt2) next.set("prompt2", event.prompt2); - if (event.forced) next.set("forced", true); - "step 1"; - event.result = result; - if (result.bool) { - player.line2(result.targets, "green"); - event.targets = result.targets; - } else { - event.finish(); - } - "step 2"; - game.delay(); - "step 3"; - if (targets.length == 2) { - player - .choosePlayerCard( - "ej", - true, - function (button) { - var player = _status.event.player; - var targets0 = _status.event.targets0; - var targets1 = _status.event.targets1; - if (get.attitude(player, targets0) > 0 && get.attitude(player, targets1) < 0) { - if (get.position(button.link) == "j") return 12; - if (get.value(button.link, targets0) < 0) return 10; - return 0; - } else { - if (get.position(button.link) == "j") return -10; - return get.equipValue(button.link); - } - }, - targets[0] - ) - .set("nojudge", event.nojudge || false) - .set("targets0", targets[0]) - .set("targets1", targets[1]) - .set("filterButton", function (button) { - var targets1 = _status.event.targets1; - if (get.position(button.link) == "j") { - if (_status.event.nojudge) return false; - return targets1.canAddJudge(button.link); - } else { - return targets1.canEquip(button.link); - } - }); - } else { - event.finish(); - } - "step 4"; - if (result.bool && result.links.length) { - player.loseHp(); - } - "step 5"; - if (result.bool && result.links.length) { - var link = result.links[0]; - if (get.position(link) == "e") { - event.targets[1].equip(link); - } else if (link.viewAs) { - event.targets[1].addJudge({ name: link.viewAs }, [link]); - } else { - event.targets[1].addJudge(link); - } - event.targets[0].$give(link, event.targets[1]); - event.result.card = link; - event.result.position = get.position(link); - game.delay(); - player.addTempSkill("xinzhilve_mark"); - player.addMark("xinzhilve_mark", 1, false); - } - }, - }, - xinzhilve_use: { - audio: "zhilve", - filterCard: function () { - return false; - }, - selectCard: -1, - filterTarget: function (card, player, target) { - return player.canUse({ name: "sha", isCard: true }, target, false); - }, - content: function () { - player.loseHp(); - player.draw(); - player.useCard({ name: "sha", isCard: true }, false, target).forceDie = true; - player.addTempSkill("xinzhilve_mark"); - player.addMark("xinzhilve_mark", 1, false); - }, - ai: { - result: { - target: function (player, target) { - return get.effect(target, { name: "sha" }, player, target); - }, - }, - }, - }, - xinzhilve_mark: { - intro: { content: "本回合手牌上限+#" }, - onremove: true, - charlotte: true, - mod: { - maxHandcard: function (player, num) { - return num + player.countMark("xinzhilve_mark"); - }, - }, - }, - xinxhzhiyan: { - audio: "xhzhiyan", - enable: "phaseUse", - filter: function (event, player) { - return (!player.hasSkill("xinxhzhiyan_true") && player.countCards("h") > player.hp) || (!player.hasSkill("xinxhzhiyan_false") && player.countCards("h") < player.maxHp); - }, - filterCard: true, - selectCard: function () { - var player = _status.event.player; - if (player.hasSkill("xinxhzhiyan_true")) return 0; - var num = Math.max(0, player.countCards("h") - player.hp); - if (ui.selected.cards.length || player.hasSkill("xinxhzhiyan_false") || player.countCards("h") >= player.maxHp) return [num, num]; - return [0, num]; - }, - filterTarget: lib.filter.notMe, - selectTarget: function () { - if (ui.selected.cards.length) return [1, 1]; - return [0, 0]; - }, - check: function (card) { - var player = _status.event.player; - var checkx = function (card) { - if ( - player.getUseValue(card, null, true) <= 0 && - game.hasPlayer(function (current) { - return current != player && get.value(card, current) > 0 && get.attitude(player, current) > 0; - }) - ) - return 2; - return 1; - }; - if ( - player.countCards("h", function (card) { - return checkx(card) > 0; - }) < - player.countCards("h") - player.hp - ) - return 0; - return checkx(card); - }, - delay: false, - discard: false, - lose: false, - content: function () { - var bool = cards && cards.length > 0; - player.addTempSkill("xinxhzhiyan_" + bool, "phaseUseEnd"); - if (!bool) { - player.draw(player.maxHp - player.countCards("h")); - } else { - player.give(cards, target); - } - }, - ai: { - order: function (obj, player) { - if (player.countCards("h") > player.hp) return 10; - return 0.5; - }, - result: { - player: function (player, target) { - if (!ui.selected.cards.length && player.countCards("h") < player.maxHp) return 1; - return 0; - }, - target: 1, - }, - }, - }, - xinxhzhiyan_true: {}, - xinxhzhiyan_false: { - mod: { - playerEnabled: function (card, player, target) { - if (player != target && (!get.info(card) || !get.info(card).singleCard || !ui.selected.targets.length)) return false; - }, - }, - mark: true, - intro: { - content: "不能对其他角色使用牌", - }, - }, - weifeng: { - audio: 2, - trigger: { player: "useCardAfter" }, - forced: true, - filter: function (event, player) { - if ( - !event.targets || - !event.targets.filter(function (target) { - return target != player && !target.storage.weifeng2; - }).length - ) - return false; - var evt = event.getParent("phaseUse"); - if (!evt || evt.player != player) return false; - if (!get.tag(event.card, "damage")) return false; - if (!["basic", "trick"].includes(get.type(event.card))) return false; - return ( - player - .getHistory("useCard", function (ev) { - return ev.getParent("phaseUse") == evt && get.tag(ev.card, "damage") && ["basic", "trick"].includes(get.type(ev.card)); - }) - .indexOf(event) == 0 && - game.hasPlayer(function (current) { - return current != player && !current.storage.weifeng2 && event.targets.includes(current); - }) - ); - }, - content: function () { - "step 0"; - player - .chooseTarget(true, "威风:请选择一个目标,令其获得一个【惧(" + get.translation(trigger.card.name) + ")】标记", function (card, player, target) { - return player != target && !target.storage.weifeng2 && _status.event.getTrigger().targets.includes(target); - }) - .set("ai", function (target) { - return -get.attitude(_status.event.player, target); - }); - "step 1"; - if (result.bool) { - var target = result.targets[0]; - target.storage.weifeng2 = trigger.card.name; - player.line(target, "green"); - game.log(target, "获得了一个", "#g【惧(" + get.translation(trigger.card.name) + ")】", "标记"); - target.markSkill("weifeng2"); - player.addSkill("weifeng3"); - } - }, - }, - weifeng2: { - intro: { - content: "当前“惧”标记名称:$", - onunmark: function (storage, player) { - if (player.storage.weifeng2) { - game.log(player, "移去了一个", "#g【惧(" + get.translation(player.storage.weifeng2) + ")】", "标记"); - delete player.storage.weifeng2; - } - }, - }, - marktext: "惧", - }, - weifeng3: { - trigger: { - global: "damageBegin3", - player: ["phaseZhunbeiBegin", "dieBegin"], - }, - forced: true, - popup: false, - filter: function (event, player) { - if (event.name != "damage") return true; - return event.player != player && typeof event.player.storage.weifeng2 == "string"; - }, - content: function () { - if (trigger.name == "damage") { - player.logSkill("weifeng", trigger.player); - if (trigger.card && trigger.card.name == trigger.player.storage.weifeng2) trigger.num++; - else if (trigger.player.countGainableCards(player, "he") > 0) player.gainPlayerCard(trigger.player, "he", true); - trigger.player.unmarkSkill("weifeng2"); - } else { - game.countPlayer(function (current) { - if (current.storage.weifeng2) current.unmarkSkill("weifeng2"); - }); - player.removeSkill("weifeng3"); - } - }, - }, - gnjinfan: { - trigger: { player: "phaseDiscardBegin" }, - direct: true, - locked: false, - audio: 2, - filter: function (event, player) { - var list = []; - player.getCards("s", function (card) { - if (card.hasGaintag("gnjinfan")) list.add(get.suit(card)); - }); - if (list.length >= lib.suit.length) return false; - return ( - player.countCards("h", function (card) { - return _status.connectMode || !list.includes(get.suit(card)); - }) > 0 - ); - }, - content: function () { - "step 0"; - player - .chooseCard( - "h", - get.prompt("gnjinfan"), - "将任意张手牌当做“铃”置于武将牌上", - [ - 1, - (function () { - var list = []; - var list2 = []; - player.getCards("s", function (card) { - if (card.hasGaintag("gnjinfan")) list.add(get.suit(card)); - }); - player.getCards("h", function (card) { - list2.add(get.suit(card)); - }); - list2.removeArray(list); - return Math.max(1, list2.length); - })(), - ], - function (card, player) { - return ( - !player.countCards("s", function (cardx) { - return cardx.hasGaintag("gnjinfan") && get.suit(cardx, false) == get.suit(card, player); - }) && - !ui.selected.cards.filter(function (cardx) { - return get.suit(cardx, player) == get.suit(card, player); - }).length - ); - } - ) - .set("ai", function (card) { - var player = _status.event.player; - if (player.hasUseTarget(card) && !player.hasValueTarget(card)) return 0; - if (["sha", "shan", "wuxie", "caochuan"].includes(card.name)) return 2 + Math.random(); - return 1 + Math.random(); - }) - .set("complexCard", true); - "step 1"; - if (result.bool) { - player.logSkill("gnjinfan"); - game.log(player, "将", result.cards, "放到了武将牌上"); - player.loseToSpecial(result.cards, "gnjinfan").visible = true; - } else event.finish(); - "step 2"; - player.markSkill("gnjinfan"); - }, - group: ["gnjinfan_gain"], - marktext: "铃", - intro: { - mark: function (dialog, storage, player) { - dialog.addAuto( - player.getCards("s", function (card) { - return card.hasGaintag("gnjinfan"); - }) - ); - }, - markcount: function (storage, player) { - return player.getCards("s", function (card) { - return card.hasGaintag("gnjinfan"); - }).length; - }, - onunmark: function (storage, player) { - var cards = player.getCards("s", function (card) { - return card.hasGaintag("gnjinfan"); - }); - if (cards.length) { - player.lose(cards, ui.discardPile); - player.$throw(cards, 1000); - game.log(cards, "进入了弃牌堆"); - } - }, - }, - mod: { - aiOrder: function (player, card, num) { - if (get.itemtype(card) == "card" && card.hasGaintag("gnjinfan")) return num + 0.5; - }, - }, - }, - gnjinfan_gain: { - audio: "gnjinfan", - trigger: { player: "loseAfter" }, - forced: true, - filter: function (event, player) { - if (!event.ss || !event.ss.length) return false; - for (var i in event.gaintag_map) { - if (event.gaintag_map[i].includes("gnjinfan")) return true; - return false; - } - }, - content: function () { - "step 0"; - var cards = []; - for (var i of trigger.ss) { - if (!trigger.gaintag_map[i.cardid] || !trigger.gaintag_map[i.cardid].includes("gnjinfan")) continue; - var suit = get.suit(i, false); - var card = get.cardPile2(function (card) { - return !cards.includes(card) && get.suit(card, false) == suit; - }); - if (card) cards.push(card); - } - if (cards.length) player.gain(cards, "gain2"); - var num = player.getCards("s", function (card) { - return card.hasGaintag("gnjinfan"); - }).length; - if (num) player.markSkill("gnjinfan"); - else player.unmarkSkill("gnjinfan"); - "step 1"; - game.updateRoundNumber(); - }, - }, - gnsheque: { - audio: 2, - trigger: { global: "phaseZhunbeiBegin" }, - direct: true, - filter: function (event, player) { - return event.player.isIn() && event.player.countCards("e") > 0 && lib.filter.targetEnabled({ name: "sha" }, player, event.player) && (player.hasSha() || (_status.connectMode && player.countCards("h") > 0)); - }, - content: function () { - player - .chooseToUse( - function (card, player, event) { - if (get.name(card) != "sha") return false; - return lib.filter.filterCard.apply(this, arguments); - }, - "射却:是否对" + get.translation(trigger.player) + "使用一张杀?" - ) - .set("logSkill", "gnsheque") - .set("complexSelect", true) - .set("filterTarget", function (card, player, target) { - if (target != _status.event.sourcex && !ui.selected.targets.includes(_status.event.sourcex)) return false; - return lib.filter.targetEnabled.apply(this, arguments); - }) - .set("sourcex", trigger.player) - .set("oncard", function (card) { - try { - card.gnsheque_tag = true; - } catch (e) { - alert("发生了一个导致【射却】无法正常触发无视防具效果的错误。请关闭十周年UI/手杀ui等扩展以解决"); - } - }); - }, - ai: { - unequip: true, - unequip_ai: true, - skillTagFilter: function (player, tag, arg) { - if (tag == "unequip_ai") { - if (_status.event.getParent().name != "gnsheque") return false; - } else if (!arg || !arg.card || !arg.card.gnsheque_tag) return false; - }, - }, - }, - _doublegroup_choice: { - trigger: { - global: "gameStart", - player: "enterGame", - }, - forced: true, - charlotte: true, - firstDo: true, - popup: false, - forceLoad:true, - filter: function (event, player) { - return get.mode() != "guozhan" && get.is.double(player.name1) && !player._groupChosen; - }, - content: function () { - "step 0"; - player._groupChosen = true; - player.chooseControl(get.is.double(player.name1, true)).set("prompt", "请选择你的势力"); - "step 1"; - player.changeGroup(result.control); + content() { + trigger.mbcmjiushi = true; }, }, }; diff --git a/character/mobile/sort.js b/character/mobile/sort.js index 9f9f271874..4805462a87 100644 --- a/character/mobile/sort.js +++ b/character/mobile/sort.js @@ -1,7 +1,6 @@ const characterSort = { - mobile_default: ["xin_huojun", "muludawang", "mb_chengui", "mb_huban", "mb_xianglang", "yanxiang", "xin_wuban", "laimin", "baoxin", "jiangji", "liwei", "xin_guozhao", "miheng", "taoqian", "lingcao", "sunru", "lifeng", "zhuling", "liuye", "zhaotongzhaoguang", "majun", "simazhao", "wangyuanji", "pangdegong", "shenpei", "hujinding", "zhangyì", "jiakui", "yangbiao", "chendeng", "dongcheng", "yangyi", "dengzhi", "zhengxuan", "sp_sufei", "furong", "dingyuan", "simashi", "yanghuiyu", "hucheer", "gongsunkang", "nanhualaoxian", "zhouqun", "qiaozhou", "fuqian", "mayuanyi", "yanpu", "sunhanhua", "sp_maojie", "peixiu", "sp_jianggan", "ruanhui", "xin_mamidi", "sp_caosong", "yangfu", "wangjun", "sp_pengyang", "qianzhao", "shichangshi", "yangfeng", "zhangbu"], - mobile_longxue: ["mb_simafu", "mb_wenqin", "mb_simazhou", "mb_sp_guanqiujian", "mb_caomao", "chengji", "lizhaojiaobo", "mb_wangjing"], - mobile_yijiang: ["yj_zhanghe", "yj_zhangliao", "yj_xuhuang", "yj_ganning", "yj_huangzhong", "yj_weiyan", "yj_zhoubuyi"], + mobile_default: ["xin_huojun", "muludawang", "mb_chengui", "mb_huban", "mb_xianglang", "yanxiang", "xin_wuban", "laimin", "baoxin", "jiangji", "liwei", "xin_guozhao", "miheng", "taoqian", "lingcao", "sunru", "lifeng", "zhuling", "liuye", "zhaotongzhaoguang", "majun", "simazhao", "wangyuanji", "pangdegong", "shenpei", "hujinding", "zhangyì", "jiakui", "yangbiao", "chendeng", "dongcheng", "yangyi", "dengzhi", "zhengxuan", "sp_sufei", "furong", "dingyuan", "simashi", "yanghuiyu", "hucheer", "gongsunkang", "nanhualaoxian", "zhouqun", "qiaozhou", "fuqian", "mayuanyi", "yanpu", "sunhanhua", "sp_maojie", "peixiu", "sp_jianggan", "ruanhui", "xin_mamidi", "sp_caosong", "yangfu", "wangjun", "sp_pengyang", "qianzhao", "shichangshi", "yangfeng", "zhangbu", "mb_zhangfen"], + mobile_longxue: ["mb_simafu", "mb_wenqin", "mb_simazhou", "mb_sp_guanqiujian", "mb_caomao", "chengji", "lizhaojiaobo", "mb_wangjing", "mb_jiachong"], mobile_standard: ["xin_xiahoudun", "xin_zhangfei"], mobile_shenhua_feng: ["re_xiaoqiao", "xin_zhoutai"], mobile_shenhua_huo: ["re_pangtong", "re_sp_zhugeliang", "re_xunyu", "re_dianwei", "re_yanwen", "xin_yuanshao"], @@ -16,7 +15,7 @@ const characterSort = { mobile_yijiang5: ["xin_zhangyi", "xin_sunxiu", "xin_quancong", "xin_zhuzhi", "xin_caoxiu"], mobile_yijiang67: ["re_jikang"], mobile_changshi: ["scs_zhangrang", "scs_zhaozhong", "scs_sunzhang", "scs_bilan", "scs_xiayun", "scs_hankui", "scs_lisong", "scs_duangui", "scs_guosheng", "scs_gaowang"], - mobile_sp: ["old_yuanshu", "re_wangyun", "re_baosanniang", "re_weiwenzhugezhi", "re_zhanggong", "re_xugong", "re_heqi", "liuzan", "xin_hansui", "mb_sunluyu"], + mobile_sp: ["old_yuanshu", "re_wangyun", "re_baosanniang", "re_weiwenzhugezhi", "re_zhanggong", "re_xugong", "re_heqi", "liuzan", "xin_hansui", "mb_sunluyu", "mb_sp_zhenji"], }; const characterSortTranslate = { diff --git a/character/mobile/translate.js b/character/mobile/translate.js index b55a6db738..3678708201 100644 --- a/character/mobile/translate.js +++ b/character/mobile/translate.js @@ -42,9 +42,9 @@ const translates = { xinfu_qianchong: "谦冲", xinfu_qianchong_info: "锁定技,若你的装备区内有牌且:均为红色,则你视为拥有技能〖明哲〗。均为黑色,则你视为拥有技能〖帷幕〗。若均不满足,则出牌阶段开始时,你可以选择一种类别的牌,然后你本回合内使用该类别的牌时没有次数和距离限制。", qc_weimu: "帷幕", - qc_weimu_info: "", + qc_weimu_info: "锁定技,你不能成为黑色锦囊牌的目标。", qc_mingzhe: "明哲", - qc_mingzhe_info: "", + qc_mingzhe_info: "当你于回合外因使用、打出或弃置而失去一张红色牌时,你可以摸一张牌。", xinfu_shangjian: "尚俭", xinfu_shangjian_info: "锁定技。一名角色的结束阶段开始时,若你于此回合内不因使用装备牌而失去了X张或更少的牌,则你摸等量的牌(X为你的体力值)。", rw_bagua_skill: "先天八卦阵", @@ -127,7 +127,7 @@ const translates = { xin_xiahoudun_prefix: "手杀界", xinqingjian: "清俭", xinqingjian2: "清俭", - xinqingjian_info: "每回合限一次。当你不因摸牌阶段的额定摸牌而得到牌后,你可以将任意张牌扣置于武将牌上。回合结束时,你将这些牌交给一名其他角色。若这些牌的数量大于1,你摸一张牌。", + xinqingjian_info: "每回合限一次。当你不因摸牌阶段的额定摸牌而得到牌后,你可以将任意张手牌扣置于武将牌上。回合结束时,你将这些牌交给任意名其他角色。若这些牌的数量大于1,你摸一张牌。", zhangyì: "张翼", jiakui: "贾逵", zhiyi: "执义", @@ -229,7 +229,9 @@ const translates = { chendeng_prefix: "手杀", zhouxuan: "周旋", zhouxuan2: "周旋", - zhouxuan_info: "出牌阶段限一次,你可以弃置一张牌并指定一名角色,然后选择一个基本牌的名称或非基本牌的类型。其使用或打出下一张牌时,若此牌的名称或类型和你选择的相同,则你观看牌堆顶的三张牌,然后将这些牌以任意分割方式交给任意名角色。", + zhouxuan_info: "出牌阶段限一次,你可以弃置一张牌并指定一名敌方角色,然后选择一个基本牌的名称或非基本牌的类型。其使用或打出下一张牌时,若此牌的名称或类型和你选择的相同,则你观看牌堆顶的三张牌,然后将这些牌以任意分割方式交给任意名角色。", + zhouxuan_info_identity: "出牌阶段限一次,你可以弃置一张牌并指定一名其他角色,然后选择一个基本牌的名称或非基本牌的类型。其使用或打出下一张牌时,若此牌的名称或类型和你选择的相同,则你观看牌堆顶的三张牌,然后将这些牌以任意分割方式交给任意名角色。", + zhouxuan_info_doudizhu: "出牌阶段限一次,你可以弃置一张牌并指定一名其他角色,然后选择一个基本牌的名称或非基本牌的类型。其使用或打出下一张牌时,若此牌的名称或类型和你选择的相同,则你观看牌堆顶的三张牌,然后将这些牌以任意分割方式交给任意名角色。", fengji: "丰积", fengji_info: "锁定技,回合结束时,你记录你的手牌数。准备阶段开始时,若你的手牌数不小于你记录的手牌数,则你摸两张牌且本回合手牌上限为体力上限。", re_guanqiujian: "手杀毌丘俭", @@ -271,35 +273,6 @@ const translates = { zhengjing_info: "出牌阶段,你可以整理卡牌。然后,你将整理出的卡牌中的至少一张作为“经”置于一名角色的武将牌上,然后获得其余的牌。该角色的准备阶段获得这些牌,且跳过此回合的判定和摸牌阶段。", zhengjing2: "整经", - mobile_yijiang: "将星独具", - yj_zhanghe: "☆张郃", - yj_zhanghe_prefix: "☆", - yj_zhangliao: "☆张辽", - yj_zhangliao_prefix: "☆", - yj_xuhuang: "☆徐晃", - yj_xuhuang_prefix: "☆", - yj_ganning: "☆甘宁", - yj_ganning_prefix: "☆", - xhzhiyan: "治严", - xhzhiyan_info: "出牌阶段,若你的手牌数不等于体力上限,则你可以将手牌摸至/弃至手牌上限,然后本回合不能对其他角色使用牌/可以将弃置的一张牌交给一名其他角色。", - zhilve: "知略", - zhilve_info: "锁定技,准备阶段,你选择一项:1.移动场上装备区的一张牌并失去1点体力。2.移动场上判定区的一张牌并令本回合手牌上限-1。3.本回合摸牌阶段多摸一张牌且使用的第一张【杀】无距离限制且不计入次数限制。", - xinzhilve: "知略", - xinzhilve_backup: "知略", - xinzhilve_mark: "知略", - xinzhilve_info: "出牌阶段限一次,你可以失去1点体力并选择一项:1.移动场上的一张牌;2.视为使用一张无距离限制且不计入次数限制的【杀】并摸一张牌。然后你本回合的手牌上限+1。", - xinxhzhiyan: "治严", - xinxhzhiyan_false: "治严", - xinxhzhiyan_info: "出牌阶段每项各限一次,若你的手牌数:大于体力值,则你可以将X张手牌交给一名其他角色(X为你的手牌数与体力值之差);小于体力上限,则你可以摸X张牌且本阶段内不能再对其他角色使用牌。(X为你的手牌数与体力上限之差)", - weifeng: "威风", - weifeng2: "威风", - weifeng3: "威风", - weifeng_info: "锁定技,当你于出牌阶段内使用第一张伤害性基本牌或普通锦囊牌后,你令此牌的一名没有“惧”的其他目标角色获得一枚名称为此牌牌名的“惧”。有“惧”的角色受到伤害时,其移去“惧”,然后若造成伤害的牌名称和“惧”:相同,此伤害+1;不同,你获得该角色的一张牌。准备阶段开始时或你死亡时,你移去场上的所有“惧”。", - gnjinfan: "锦帆", - gnjinfan_gain: "锦帆", - gnjinfan_info: "弃牌阶段开始时,你可将任意张手牌置于武将牌上,称为“铃”(每种花色的“铃”限一张)。你可以如手牌般使用或打出“铃”。当有“铃”移动到处理区后,你从牌堆中获得与“铃”花色相同的一张牌。", - gnsheque: "射却", - gnsheque_info: "一名其他角色的准备阶段开始时,若其装备区内有牌,则你可以对其使用一张【杀】(无距离关系的限制且无视防具)。", sp_sufei: "手杀苏飞", sp_sufei_prefix: "手杀", zhengjian: "诤荐", @@ -439,7 +412,7 @@ const translates = { relieren_info: "当你使用【杀】指定目标后,你可以和目标角色进行拼点。若你赢,你获得其一张牌。若你没赢,你获得对方的拼点牌,其获得你的拼点牌。", zhouqun: "周群", tiansuan: "天算", - tiansuan_info: "出牌阶段限一次,若场上没有因你产生的“命运签”,则你可以抽取一张“命运签”,然后令一名角色获得“命运签”直到你的下回合开始。若你以此法抽取的“命运签”为:上上签,你观看其手牌;上上签/上签,你获得其区域内的一张牌。", + tiansuan_info: "出牌阶段限一次,若场上没有因你产生的“命运签”,则你可以抽取一张“命运签”,然后令一名角色获得“命运签”直到你的下回合开始。若你以此法抽取的“命运签”为:上上签,你观看其手牌并获得其区域内的一张牌;上签,你获得其一张牌。", tiansuan_faq: "【命运签】说明", tiansuan_faq_info: "当你抽取“命运签”时,你可以令其中一种命运签的权重+1。
    上上签(权重1):当你受到伤害时,防止此伤害。
    上签(权重2):当你受到伤害时,你令伤害值改为1;当你受到1点伤害后,你摸一张牌。
    中签(权重3):当你受到伤害时,你令伤害属性改为火属性并将伤害值改为1。
    下签(权重2):当你受到伤害时,你令此伤害+1。
    下下签(权重1):当你受到伤害时,你令此伤害+1。你不能使用【酒】或【桃】。", tiansuan2_0: "命运签", @@ -531,14 +504,6 @@ const translates = { rezongxuan: "纵玄", rezongxuan_place: "纵玄", rezongxuan_info: "当你的牌因弃置而进入弃牌堆后,你可以将其以任意顺序置于牌堆顶。出牌阶段限一次,你可以摸一张牌,然后将一张牌置于牌堆顶。", - yj_huangzhong: "☆黄忠", - yj_huangzhong_prefix: "☆", - spshidi: "势敌", - spshidi_info: "转换技,锁定技。①准备阶段/结束阶段开始时,若你发动此分支的累计次数为奇数/偶数,则你获得一个“☯”。②若你的“☯”数为偶数,则你至其他角色的距离-1,且你使用的黑色【杀】不可被响应。③若你的“☯”数为奇数,则其他角色至你的距离+1,且你不可响应红色【杀】。", - spyishi: "义释", - spyishi_info: "当你对装备区有牌的其他角色造成伤害时,你可令此伤害-1,然后获得其装备区内的一张牌。", - spqishe: "骑射", - spqishe_info: "你可以将一张装备牌当做【酒】使用。你的手牌上限+X(X为你装备区内的牌数)。", sp_maojie: "毛玠", bingqing: "秉清", bingqing_info: "当你于出牌阶段内使用的牌结算完毕后,若你于本阶段内此前使用的所有牌的花色与此牌花色均不相同,则你可根据X的值执行对应效果:为2,你令一名角色摸两张牌;为3,你弃置一名角色区域内的一张牌;为4,你对一名其他角色造成1点伤害。(X为你于本阶段内此前使用的所有牌包含的花色数+1)", @@ -577,7 +542,7 @@ const translates = { spdaoshu_info_identity: "每轮限一次。一名其他角色的出牌阶段开始时,若其有手牌,则你可以令其视为使用一张【酒】。其须声明一个基本牌的牌名,然后你判断其手牌区内是否有该牌名的牌。若你判断正确,则你获得其两张手牌。", spdaoshu_info_guozhan: "每轮限一次。一名其他角色的出牌阶段开始时,若其有手牌,则你可以令其视为使用一张【酒】。其须声明一个基本牌的牌名,然后你判断其手牌区内是否有该牌名的牌。若你判断正确,则你获得其两张手牌。", mbdaoshu: "盗书", - mbdaoshu_info: "出牌阶段限一次,你可以选择一名手牌数不少于两张的其他角色,其随机获得三个牌名并将一张手牌的牌名伪装成其中一个与原牌名不同的牌名,然后你和队友观看其手牌并猜测其伪装的手牌,猜对的角色对其造成1点伤害,猜错的角色随机弃置两张手牌(手牌数不足两张则改为失去1点体力)。", + mbdaoshu_info: "出牌阶段限一次,你可以选择一名手牌数不少于两张的敌方角色,其随机获得三个牌名并将一张手牌的牌名伪装成其中一个与原牌名不同的牌名,然后你和队友观看其手牌并猜测其伪装的手牌,猜对的角色对其造成1点伤害,猜错的角色随机弃置两张手牌(手牌数不足两张则改为失去1点体力)。", mbdaoshu_info_identity: "出牌阶段限一次,你可以选择一名手牌数不少于两张的其他角色,其随机获得三个牌名并将一张手牌的牌名伪装成其中一个与原牌名不同的牌名,然后你观看其手牌并猜测其伪装的手牌。若猜中,你对其造成1点伤害;若猜错,你随机弃置两张手牌(手牌数不足两张则改为失去1点体力)。", mbdaoshu_info_guozhan: "出牌阶段限一次,你可以选择一名手牌数不少于两张的其他角色,其随机获得三个牌名并将一张手牌的牌名伪装成其中一个与原牌名不同的牌名,然后你观看其手牌并猜测其伪装的手牌。若猜中,你对其造成1点伤害;若猜错,你随机弃置两张手牌(手牌数不足两张则改为失去1点体力)。", spdaizui: "戴罪", @@ -669,12 +634,6 @@ const translates = { xin_caoxiu_prefix: "手杀界", xinqingxi: "倾袭", xinqingxi_info: "每回合限一次。当你对其他角色造成伤害时,你可以令其选择一项:1.弃置X张手牌(X为4减去你至其的距离,至少为1);2.令此伤害+1。", - yj_weiyan: "☆魏延", - yj_weiyan_prefix: "☆", - mbguli: "孤厉", - mbguli_info: "出牌阶段限一次。你可以将所有手牌当做一张无视防具的【杀】使用。此牌结算结束后,若此牌造成过伤害,你可以失去1点体力并将手牌摸至X张(X为你的体力上限)。", - mbaosi: "骜肆", - mbaosi_info: "锁定技。当你于出牌阶段对一名攻击范围内的角色造成伤害后,你于此阶段对其使用牌无次数限制。", xin_zhoutai: "手杀界周泰", xin_zhoutai_prefix: "手杀界", re_yanwen: "手杀界颜良文丑", @@ -749,12 +708,6 @@ const translates = { yichong_info: "①准备阶段,你可以选择一名其他角色并选择一个花色,然后你获得其所有此花色的装备牌和其一张此花色的手牌,移除场上的所有“雀”标记,令其获得“雀”标记直到你的下个回合开始。②拥有“雀”标记的角色获得你最后一次发动〖易宠①〗选择的花色的牌后,你获得这些牌(你至多通过每个“雀”得到一张牌)。", wufei: "诬诽", wufei_info: "若场上存在拥有“雀”标记的角色A,则:①当你使用【杀】或伤害类锦囊牌指定第一个目标后,你令A成为此牌伤害来源。②当你受到伤害后,若A的体力值大于3,则你可以令A受到1点无来源伤害。", - yj_zhoubuyi: "☆周不疑", - yj_zhoubuyi_prefix: "☆", - mbhuiyao: "慧夭", - mbhuiyao_info: "出牌阶段限一次。你可以受到1点无来源伤害,然后你选择一名其他角色,令其视为对另一名角色造成过1点伤害。", - mbquesong: "雀颂", - mbquesong_info: "一名角色的结束阶段,若你于本回合受到过伤害,你可以令一名角色选择一项:1.摸X张牌并复原武将牌(X为3,若其装备区非宝物牌牌数不小于三张则X为2);2.回复1点体力。", xin_yuanshao: "手杀界袁绍", xin_yuanshao_prefix: "手杀界", re_baosanniang: "手杀鲍三娘", @@ -797,7 +750,7 @@ const translates = { laishou: "来寿", laishou_info: "锁定技。①当你受到伤害值大于等于你的体力值的伤害时,若你的体力上限小于9,你防止此伤害并增加等量体力上限。②准备阶段,若你的体力上限不小于9,你死亡。", luanqun: "乱群", - luanqun_info: "出牌阶段限一次,若你有手牌,则你可以令所有有手牌的角色同时展示一张手牌,然后你可以获得其中一张与你展示的牌颜色相同的展示牌,所有本次展示牌颜色与你展示的牌颜色不同的角色的下个出牌阶段使用的第一张【杀】只能对你使用,且此【杀】不可被响应。", + luanqun_info: "出牌阶段限一次,若你有手牌,则你可以令所有有手牌的角色同时展示一张手牌,然后你可以获得其中至多四张与你展示的牌颜色相同的展示牌,所有本次展示牌颜色与你展示的牌颜色不同的角色的下个出牌阶段使用的第一张【杀】只能对你使用,且此【杀】不可被响应。", xin_wuban: "吴班", xinjintao: "进讨", xinjintao_info: "锁定技,你使用【杀】无距离限制且次数上限+1。你于出牌阶段内使用的第一张【杀】不可被响应,第二张【杀】伤害+1。", @@ -814,6 +767,8 @@ const translates = { yanxiang: "阎象", kujian: "苦谏", kujian_info: "出牌阶段限一次,你可以将至多两张手牌称为“谏”并交给一名其他角色,然后你获得以下效果:当其他角色使用或打出牌后,若其中有“谏”,你与其各摸两张牌;当其他角色不因使用或打出而失去牌后,若其中有“谏”,你与其各弃置一张牌。", + ruilian: "睿敛", + ruilian_info: "一轮游戏开始时,你可以选择一名角色。其下回合结束时,若其本回合弃置过牌,你可以选择其本回合弃置过的一种类别,你与其各从弃牌堆中获得一张此类别的牌。", mb_xianglang: "手杀向朗", mb_xianglang_prefix: "手杀", naxue: "纳学", @@ -863,14 +818,14 @@ const translates = { mbshishou_info: "锁定技。当你发动〖佐佑〗后,若目标角色不为你,你执行〖佐佑〗中目标角色未执行的一项。", chengji: "成济", mbkuangli: "狂戾", - mbkuangli_info: "锁定技。①出牌阶段开始时,你随机令场上任意名其他角色获得“狂戾”标记。②出牌阶段限两次。当你使用牌指定有“狂戾”的角色为目标后,你随机弃置你与其各一张牌,然后你摸两张牌。③回合结束时,你移除所有角色的“狂戾”。", + mbkuangli_info: "锁定技。①出牌阶段开始时,你随机令场上任意名其他角色获得“狂戾”标记。②出牌阶段限两次,当你使用牌指定有“狂戾”的角色为目标后,你随机弃置你与其各一张牌,然后你摸两张牌。③回合结束时,你移除所有角色的“狂戾”。", + mbkuangli_info_doudizhu: "锁定技。①出牌阶段开始时,你随机令场上任意名其他角色获得“狂戾”标记。②出牌阶段限一次,当你使用牌指定有“狂戾”的角色为目标后,你随机弃置你与其各一张牌,然后你摸两张牌。③回合结束时,你移除所有角色的“狂戾”。", mbxiongsi: "凶肆", mbxiongsi_info: "限定技。出牌阶段,若你的手牌数不少于三张,你可以弃置所有手牌,然后令所有其他角色依次失去1点体力。", mb_sp_guanqiujian: "玄毌丘俭", mb_sp_guanqiujian_prefix: "玄", mbcuizhen: "摧阵", - mbcuizhen_info: "①游戏开始时,你可以废除至多两名其他角色的武器栏。②当你于出牌阶段使用伤害类牌指定其他角色为目标后,若目标角色的手牌数不小于体力值,你可以废除其武器栏。③摸牌阶段,你令额定摸牌数+X(X为所有角色被废除的武器栏数之和+2,至多为4)。", - mbcuizhen_info_identity: "①游戏开始时,你可以废除至多三名其他角色的武器栏。②当你于出牌阶段使用伤害类牌指定其他角色为目标后,若目标角色的手牌数不小于体力值,你可以废除其武器栏。③摸牌阶段,你令额定摸牌数+X(X为所有角色被废除的武器栏数之和+1,至多为4)。", + mbcuizhen_info: "①游戏开始时,你可以废除至多三名其他角色的武器栏。②当你于出牌阶段使用伤害类牌指定其他角色为目标后,若目标角色的手牌数不小于体力值,你可以废除其武器栏。③摸牌阶段,你令额定摸牌数+X(X为所有角色被废除的武器栏数之和+1,至多为3)。", mbkuili: "溃离", mbkuili_info: "锁定技。当你受到伤害后,若来源有被废除的武器栏,你令其恢复武器栏。", mb_caomao: "手杀曹髦", @@ -880,7 +835,7 @@ const translates = { mbcmqingzheng: "清正", mbcmqingzheng_info: "持恒技。出牌阶段开始时,你可以弃置一种花色的所有手牌,并观看一名有手牌的其他角色的手牌,你弃置其中一种花色的所有牌。若其被弃置的牌数小于你以此法弃置的牌数,你对其造成1点伤害。", mbcmjiushi: "酒诗", - mbcmjiushi_info: "持恒技。①当你需要使用【酒】时,若你的武将牌正面向上,你可以翻面,视为使用一张【酒】。②当你受到伤害后,若你的武将牌背面向上,你可以翻面。③当你翻面后,你获得牌堆里的一张锦囊牌。", + mbcmjiushi_info: "持恒技。①当你需要使用【酒】时,若你的武将牌正面向上,你可以翻面,视为使用一张【酒】。②当你受到伤害后,若你的武将牌于受到伤害时背面向上,你可以翻面。③当你翻面后,你获得牌堆里的一张锦囊牌。", mbcmfangzhu: "放逐", mbcmfangzhu_info: "持恒技。出牌阶段限一次,你可以选择一名不为你上个出牌阶段发动〖放逐〗的目标的其他角色,选择一项:⒈令其不能使用手牌中的非锦囊牌直到其回合结束;⒉令其所有非Charlotte技能失效直到其回合结束。", mbjuejin: "决进", @@ -904,18 +859,43 @@ const translates = { mbjiejian: "节谏", mbjiejian_info: "准备阶段,你可将任意张手牌交给任意名其他角色,并令这些角色获得“节谏”标记。“节谏”角色成为一张非装备牌的唯一目标时,你可将此牌转移给你,然后摸一张牌。“节谏”角色的回合结束时,移去其“节谏”标记,若其体力值不小于X(X为你交给其牌时其的体力值),你摸两张牌。", mbjiejian_tag: "已分配", - mb_wenqin:"玄文钦", - mb_wenqin_prefix:"玄", - mbbeiming:"孛明", - mbbeiming_info:"游戏开始时,你可令至多两名角色获得牌堆中一张攻击范围为X的武器牌(X为其手牌中的花色数)。", - mbchoumang:"仇铓", - mbchoumang_info:"每回合限一次,你使用【杀】指定唯一目标或成为【杀】的唯一目标后,可以选择一项:①令此【杀】伤害+1;②若此【杀】被【闪】抵消,你可以获得与你距离为1以内的一名其他角色区域里的一张牌;③背水:弃置你与其装备栏里的武器牌,然后依次执行上述所有选项。", - mb_simazhou:"手杀司马伷", - mb_simazhou_prefix:"手杀", - mbbifeng:"避锋", - mbbifeng_info:"你成为一张基本牌或普通锦囊牌的目标时,若此牌目标数不大于4,你可取消之。若如此做,此牌结算完成后若没有其他角色响应此牌,你失去1点体力,否则摸两张牌。", - mbsuwang:"宿望", - mbsuwang_info:"一名角色的回合结束时,若其此回合对你使用过牌且你未受到过伤害,你可以将牌堆顶的一张牌置于武将牌上,称为宿望牌。摸牌阶段开始时,若你有宿望牌,可以改为获得之,若不小于三张,你可以令一名其他角色摸两张牌。", + mb_wenqin: "玄文钦", + mb_wenqin_prefix: "玄", + mbbeiming: "孛明", + mbbeiming_info: "游戏开始时,你可令至多两名角色获得牌堆中一张攻击范围为X的武器牌(X为其手牌中的花色数)。", + mbchoumang: "仇铓", + mbchoumang_info: "每回合限一次,你使用【杀】指定唯一目标或成为【杀】的唯一目标后,可以选择一项:①令此【杀】伤害+1;②若此【杀】被【闪】抵消,你可以获得与你距离为1以内的一名其他角色区域里的一张牌;③背水:弃置你与其装备栏里的武器牌,然后依次执行上述所有选项。", + mb_simazhou: "手杀司马伷", + mb_simazhou_prefix: "手杀", + mbbifeng: "避锋", + mbbifeng_info: "你成为一张基本牌或普通锦囊牌的目标时,若此牌目标数不大于4,你可取消之。若如此做,此牌结算完成后若没有其他角色响应此牌,你失去1点体力,否则摸两张牌。", + mbsuwang: "宿望", + mbsuwang_info: "一名角色的回合结束时,若其此回合对你使用过牌且你未受到过伤害,你可以将牌堆顶的一张牌置于武将牌上,称为宿望牌。摸牌阶段开始时,若你有宿望牌,可以改为获得之,若不小于三张,你可以令一名其他角色摸两张牌。", + mb_jiachong: "手杀贾充", + mb_jiachong_prefix: "手杀", + mbbeini: "悖逆", + mbbeini_info: "出牌阶段限一次,你可以选择一名体力值不小于你的角色,令你或其摸两张牌,然后未摸牌的角色选择一项:1.视为对摸牌的角色使用一张【杀】;2.获得摸牌的角色场上的一张牌。", + mbdingfa: "定法", + mbdingfa_info: "弃牌阶段结束时,若本回合你失去的牌数不小于你的体力值,你可以选择一项:1、回复1点体力;2、弃置一名角色至多两张牌。", + mb_zhangfen: "手杀张奋", + mbquchong: "渠冲", + mbquchong_effect: "大攻车", + mbquchong_info: "①出牌阶段,你可以重铸装备牌。②一名角色的回合结束时,你将弃牌堆中的所有装备移出游戏,然后获得等量的铸造值。③出牌阶段开始时,若场上:没有【大攻车】,则你可以依次消耗0、5、10、10点铸造值,从【大攻车·攻】和【大攻车·守】中选择一个令一名角色获得(你任选此牌花色和点数)并令其使用此牌;有【大攻车】,则你可以移动场上的一张【大攻车】(可替换原装备)。", + mbxunjie:'逊节', + mbxunjie_info:'锁定技,当你受到有来源的伤害时,若其体力值大于你且场上没有【大攻车】,则你进行一次判定,若结果不为黑桃,则此伤害-1。', + mb_zhangfen_prefix: "手杀", + dagongche_attack: "大攻车·攻", + dagongche_defend: "大攻车·守", + dagongche_attack_skill: "大攻车", + dagongche_defend_skill: "大攻车", + dagongche_attack_info: "②此牌拥有1点耐久度,耐久度为0时销毁此牌。①当此牌进入你的装备区时,弃置你装备区里的其他牌。②其他装备区进入你的装备区前,改为将这些牌置于弃牌堆。③当你对一名角色造成伤害时,你可减少1点此牌的耐久度,令此伤害+X(X为游戏轮数且至多为3)。④当此牌不因〖渠冲〗离开装备区时,减少1点此牌的耐久度并防止之。", + dagongche_defend_info: "②此牌拥有3点耐久度,耐久度为0时销毁此牌。①当此牌进入你的装备区时,弃置你装备区里的其他牌。②其他装备区进入你的装备区前,改为将这些牌置于弃牌堆。③当你受到伤害时,减少X点此牌的耐久度,令此伤害-X(X为伤害值且至多为此牌耐久度)。④当此牌不因〖渠冲〗离开装备区时,减少1点此牌的耐久度并防止之。", + mb_sp_zhenji: "手杀SP甄宓", + mb_sp_zhenji_prefix: "手杀SP", + mbbojian: "博鉴", + mbbojian_info: "锁定技。若你本阶段使用牌数与花色数与上个出牌阶段皆不同,你摸两张牌;否则你将一张弃牌堆中本阶段你因使用而失去的牌交给一名角色。", + mbjiwei: "济危", + mbjiwei_info: "锁定技。①其他角色的回合结束时,你摸X张牌(X为本回合满足的项数:1.至少两名角色失去过牌;2.至少两名角色受到过伤害)。②准备阶段,若你的手牌数不小于Y,你将手牌中颜色较多的牌分配给任意名其他角色(Y为存活人数与你体力值的最大值)。", }; export default translates; diff --git a/character/mobile/voices.js b/character/mobile/voices.js index dec8fef093..940ac854fb 100644 --- a/character/mobile/voices.js +++ b/character/mobile/voices.js @@ -1,4 +1,18 @@ export default { + "#mbbojian1": "闻古者贤女,未有不学前事成败而以为己诫。", + "#mbbojian2": "视字辄识,方知何为礼义。", + "#mbjiwei1": "乱世之宝,非金银田产,而在仁心。", + "#mbjiwei2": "匹夫怀璧为罪,更况吾豪门大族。", + "#mbjiwei3": "左右乡邻,当共力时艰。", + "#mbjiwei4": "民不逢时,吾又何忍视其饥苦。", + "#mb_sp_zhenji:die": "悔入帝王家,万愿皆成空……", + "#mbquchong1": "器有九距之备,亦有九攻之变。", + "#mbquchong2": "攻城之机变,于此车皆可解之!", + "#mbquchong3": "大攻起兮,可辟山海之艰!", + "#mbquchong4": "破坚阵如朽木,履高城如平地。", + "#mbxunjie1": "藏于心者竭爱,动于身者竭恭。", + "#mbxunjie2": "修身如藏器,大巧若无工。", + "#mb_zhangfen:die": "而立之年,未立功名,实憾也……", "#qiaomeng_xin_gongsunzan1": "夺汝兵刃战马,尔等必败无疑。", "#qiaomeng_xin_gongsunzan2": "摧敌似折枯,荡寇如反掌。", "#mbbifeng1": "众士暂避其锋,万不可冲撞圣驾。", @@ -56,6 +70,8 @@ export default { "#lizhaojiaobo:die": "陛下!尔等乱臣,安敢弑君,呃啊……", "#mbxuetu1": "天子依仗在此,逆贼安扰圣驾。", "#mbxuetu2": "末将救驾来迟,还望陛下恕罪。", + '#mbxuetu3': "徐、扬粮草甚多,众将随我前往。", + '#mbxuetu4': "哈哈哈哈,所过之处,粒粟不留。", "#mbweiming1": "诸位东归洛阳,奉愿随驾以护。", "#mbweiming2": "不遵皇命,视同倡乱之贼。", "#mbweiming3": "布局良久,于今功亏一篑啊!", @@ -86,11 +102,6 @@ export default { "#luanqun1": "年过杖朝,自是从心所欲,何来逾矩之理?", "#luanqun2": "位居执慎,博涉多闻,更应秉性而论!", "#laimin:die": "狂嚣之言,一言十过啊……", - "#mbhuiyao1": "幸有仓舒为伴,吾不至居高寡寒。", - "#mbhuiyao2": "通悟而无笃学之念,则必盈天下之叹也。", - "#mbquesong1": "承白雀之瑞,显周公之德。", - "#mbquesong2": "挽汉室于危亡,继光武之中兴。", - "#yj_zhoubuyi:die": "慧童亡,天下伤……", "#yichong1": "处椒房之尊,得陛下隆宠!", "#yichong2": "三千宠爱?当聚于我一身!", "#wufei1": "巫蛊实乃凶邪之术,陛下不可不察!", @@ -123,11 +134,6 @@ export default { "#chengzhang1": "弦急悲声发,聆我慷慨言。", "#chengzhang2": "盛时不再来,百年忽我遒。", "#re_caozhi:die": "先民谁不死,知命复何忧?", - "#mbguli1": "今若弑此昏聩主,纵蒙恶名又如何?", - "#mbguli2": "韩玄少谋多忌,吾今当诛之!", - "#mbaosi1": "凶慢骜肆,天生狂骨!", - "#mbaosi2": "暴戾恣睢,傲视诸雄!", - "#yj_weiyan:die": "使君为何弃我而去……呃啊!", "#redingpin1": "察举旧制已隳,简拔当立中正。", "#redingpin2": "置州郡中正,以九品进退人才。", "#refaen1": "法不可容之事,情或能原宥。", @@ -242,13 +248,6 @@ export default { "#yingfeng1": "公内奉天子,外令诸侯,则天下可定。", "#yingfeng2": "公怀奉君之心,则民有安固之志。", "#sp_maojie:die": "废立大事,公不可不慎……", - "#spshidi1": "诈败以射之,其必死矣!", - "#spshidi2": "呃啊,中其拖刀计矣!", - "#spyishi1": "昨日释忠之恩,今吾虚射以报。", - "#spyishi2": "君刀不砍头颅,吾箭只射盔缨。", - "#spqishe1": "诱敌之计已成,吾且拈弓搭箭!", - "#spqishe2": "关羽即至吊桥,既已控弦,如何是好?", - "#yj_huangzhong:die": "关云长义释黄某,吾又安忍射之……", "#zhiyan_re_yufan1": "失忠于信,何以侍君!", "#zhiyan_re_yufan2": "恕臣耿直,犯言谏正!", "#rezongxuan1": "凡夫俗子,怎识得卦象玄妙?", @@ -350,11 +349,8 @@ export default { "#taomie2": "韩濊之乱,再无可生之机!", "#taomie3": "颅且远行万里,要席何用?", "#gongsunkang:die": "枭雄一世,何有所憾!", - "#xinniluan1": "绝地反击的时候到了!", - "#xinniluan2": "胜者为王败者为寇。", - "#xiaoxi_hansui1": "先下手为强!", - "#xiaoxi_hansui2": "乌合之众,西凉何惧!", - "#xin_hansui:die": "中了曹贼的离间计……了……", + "#xiaoxi_hansui1": "打你个措手不及!", + "#xiaoxi_hansui2": "两军交战,勇者为胜!", "#daoji1": "八十斤双戟?于我如探囊取物!", "#daoji2": "以汝之矛,攻汝之盾!", "#hucheer:die": "未料一伸手,便被……敌酋捉……", @@ -418,20 +414,6 @@ export default { "#gaoyuan1": "还请告知兴霸,请他务必相助。", "#gaoyuan2": "如今事急,唯有兴霸可救。", "#sp_sufei:die": "本可共图大业,奈何主公量狭器小啊……", - "#weifeng1": "广散惧义,尽泄敌之斗志。", - "#weifeng2": "哼哼,若尔等惧我,自当卷甲以降!", - "#yj_zhangliao:die": "惑于女子而尽失战机,庸主误我啊……", - "#zhilve1": "将者,上不治天,下不治地,中不治人。", - "#zhilve2": "料敌之计,明敌之意,因况反制。", - "#yj_zhanghe:die": "若非小人作梗,何至官渡之败……", - "#xhzhiyan1": "治军严谨,方得精锐之师。", - "#xhzhiyan2": "精兵当严于律己,束身自修。", - "#yj_xuhuang:die": "唉,明主未遇,大功未成……", - "#gnjinfan1": "扬锦帆,劫四方,快意逍遥!", - "#gnjinfan2": "铃声所至之处,再无安宁!", - "#gnsheque1": "看我此箭,取那轻舟冒进之人性命!", - "#gnsheque2": "纵有劲甲良盾,也难挡我神射之威!", - "#yj_ganning:die": "铜铃声……怕是听不到了……", "#yinghun_re_sunjian1": "义定四野,武匡海内。", "#yinghun_re_sunjian2": "江东男儿,皆胸怀匡扶天下之志。", "#re_sunjian:die": "吾身虽死,忠勇须传……", @@ -538,13 +520,17 @@ export default { "#xinfu_zhaoxin1": "吾心昭昭,何惧天下之口!", "#xinfu_zhaoxin2": "公此行欲何为,吾自有量度。", "#simazhao:die": "安世,接下来,就看你的了……", - "#xinfu_qianchong1": "宫闱之内,何必擅涉外事!", - "#xinfu_qianchong2": "谦瑾行事,方能多吉少恙。", - "#xinfu_qianchong3": "细行策划,只盼能助夫君一臂之力。", + "#xinfu_qianchong1": "细行筹划,只盼能助夫君一臂之力。", + "#qc_weimu": "宫闱之内,何必擅涉外事!", + "#qc_mingzhe": "谦瑾行事,方能多吉少恙。", "#xinfu_shangjian1": "如今乱世,当秉俭行之节。", "#xinfu_shangjian2": "百姓尚处寒饥之困,吾等不可奢费财力。", "#wangyuanji:die": "世事沉浮,非是一人可逆啊……", - "#xinfu_pingcai": "吾有众好友,分为卧龙、凤雏、水镜、元直。", + "#xinfu_pingcai1": "吾有众好友,分为卧龙、凤雏、水镜、元直。", + '#xinfu_pingcai2': "孔明能借天火之势。", + '#xinfu_pingcai3': "士元虑事环环相扣。", + '#xinfu_pingcai4': "德操深谙处世之道。", + '#xinfu_pingcai5': "元直侠客惩恶扬善。", "#pangdegong:die": "吾知人而不自知,何等荒唐……", "#shouye1": "敌军攻势渐怠,还望诸位依策坚守。", "#shouye2": "袁幽州不日便至,当行策建功以报之。", diff --git a/character/mtg.js b/character/mtg.js index 694c03582d..db00bf816f 100644 --- a/character/mtg.js +++ b/character/mtg.js @@ -4,25 +4,16 @@ game.import("character", function () { name: "mtg", character: { mtg_jiding: ["male", "qun", 4, ["mbaizhan", "msilian"]], - // mtg_qianzhuo:['female','shu',3,[]], mtg_jiesi: ["male", "wei", 3, ["mtongnian", "msuoling", "mhuanyi"]], mtg_lilianna: ["female", "qun", 3, ["lingyong", "mduohun"]], - // mtg_nisha:['female','wu',3,[]], - // mtg_ayeni:['male','qun',4,[]], }, characterIntro: { mtg_jiding: "这名白色魔法的使用者极其注重忠诚,正义和荣誉。他曾全力追捕茜卓纳拉,如今已不可思议地与这位火焰法师成为伙伴。", - mtg_qianzhuo: - "茜卓纳拉是使用红色法术力的旅法师。她擅长使用火焰:除了火焰,还是火焰。茜卓性格冲动、易怒、富有激情,不断增长的火焰法术能力随时都准备爆发。她的火花在还很年轻时便已点燃,如今已是相当有经验的烈焰术士和旅法师。", mtg_jiesi: "杰斯贝连是使用蓝色法术的鹏洛客。他擅长心灵法术:读取心灵,幻影,知识,以及欺瞒的咒语。", mtg_lilianna: "莉莲娜维斯是一位精通死灵术的旅法师,她擅长用黑色法术力来复活死者,腐化生者,并从死亡中召唤力量。", - mtg_nisha: - "赞迪卡妖精部落玖瑞加的一名战士,做事倾尽全力,与大地有密切的联系,还擅使元素魔法。她能够引导时空的魔法生机地脉,为土地赋予生命。", - mtg_ayeni: - "金鬃阿耶尼是使用白色法术的鹏洛客。他长于净化身体与心灵的法术:用咒语来治疗、强化盟友,以及唤醒他人内在的心灵精华。", }, skill: { mduohun: { @@ -481,11 +472,8 @@ game.import("character", function () { }, translate: { mtg_jiding: "基定", - mtg_qianzhuo: "茜卓", mtg_jiesi: "杰斯", mtg_lilianna: "莉莲娜", - mtg_nisha: "妮莎", - mtg_ayeni: "阿耶尼", mduohun: "夺魂", mduohun_info: "锁定技,当你解除濒死状态后,令你进入濒死状态的角色失去1点体力。", diff --git a/character/newjiang/card.js b/character/newjiang/card.js new file mode 100644 index 0000000000..1fd2fa8b31 --- /dev/null +++ b/character/newjiang/card.js @@ -0,0 +1,10 @@ +import { lib, game, ui, get, ai, _status } from "../../noname.js"; + +const cards = { + lukai_spade: { fullskin: true }, + lukai_heart: { fullskin: true }, + lukai_diamond: { fullskin: true }, + lukai_club: { fullskin: true }, +}; + +export default cards; diff --git a/character/newjiang/character.js b/character/newjiang/character.js new file mode 100644 index 0000000000..5532a921ff --- /dev/null +++ b/character/newjiang/character.js @@ -0,0 +1,32 @@ +const characters = { + yj_sb_guojia: ["male", "wei", 3, ["xianmou", "lunshi"]], + xunyuxunyou: ["male", "wei", 3, ["zhinang", "gouzhu"], ["name:荀|彧-荀|攸"]], + xiahoumao: ["male", "wei", 4, ["tongwei", "cuguo"], ["name:夏侯|楙"]], + chenshi: ["male", "shu", 4, ["qingbei"]], + sunli: ["male", "wei", 4, ["kangli"]], + feiyao: ["male", "wei", 4, ["zhenfeng"]], + wuanguo: ["male", "qun", 4, ["diezhang", "duanwan"]], + hanlong: ["male", "wei", 4, ["duwang", "cibei"]], + yj_qiaozhou: ["male", "shu", 3, ["shiming", "jiangxi"]], + yj_sufei: ["male", "wu", 4, ["shuojian"]], + liwan: ["female", "wei", 3, ["liandui", "biejun"]], + zhugeshang: ["male", "shu", 3, ["sangu", "yizu"], ["name:诸葛|尚"]], + kebineng: ["male", "qun", 4, ["kousheng"], ["name:科比|罐头"]], + lukai: ["male", "wu", 4, ["lkbushi", "lkzhongzhuang"]], + linghuyu: ["male", "wei", 4, ["xvzhi"], ["name:令狐|愚"]], + yj_simafu: ["male", "wei", 4, ["beiyu", "duchi"], ["name:司马|孚"]], + yj_xuangongzhu: ["female", "wei", 3, ["yjqimei", "yjzhuiji"], ["name:司马|null"]], + xukun: ["male", "wu", 4, ["fazhu"]], + yj_zhangliao: ["male", "qun", 4, ["weifeng"]], + yj_zhanghe: ["male", "qun", 4, ["xinzhilve"]], + yj_xuhuang: ["male", "qun", 4, ["xinxhzhiyan"]], + yj_ganning: ["male", "qun", 4, ["gnjinfan", "gnsheque"]], + yj_huangzhong: ["male", "qun", 4, ["spshidi", "spyishi", "spqishe"]], + yj_weiyan: ["male", "qun", "4/4/1", ["mbguli", "mbaosi"]], + yj_zhoubuyi: ["male", "wei", 3, ["mbhuiyao", "mbquesong"]], + mp_wangrong: ["male", "wei", 3, ["mpjianlin", "mpsixiao"]], + mp_liuling: ["male", "jin", 3, ["mpjiusong", "mpmaotao", "mpbishi"], ["doublegroup:wei:qun:jin"]], + yj_majun: ["male", "wei", 3, ["yjgongqiao", "yjjingyi"]], +}; + +export default characters; diff --git a/character/xinghuoliaoyuan/characterFilter.js b/character/newjiang/characterFilter.js similarity index 100% rename from character/xinghuoliaoyuan/characterFilter.js rename to character/newjiang/characterFilter.js diff --git a/character/newjiang/characterReplace.js b/character/newjiang/characterReplace.js new file mode 100644 index 0000000000..88aaacd4a0 --- /dev/null +++ b/character/newjiang/characterReplace.js @@ -0,0 +1,10 @@ +const characterReplaces = { + liwan: ["ol_liwan", "liwan"], + wuxian: ["wuxian", "clan_wuxian"], + simafu: ["mb_simafu", "simafu", "yj_simafu"], + xuangongzhu: ["yj_xuangongzhu", "xuangongzhu"], + kebineng: ["kebineng", "ol_kebineng", "ddd_kebineng"], + hanlong: ["hanlong", "jd_hanlong"], +}; + +export default characterReplaces; diff --git a/character/newjiang/dynamicTranslate.js b/character/newjiang/dynamicTranslate.js new file mode 100644 index 0000000000..390e4e930a --- /dev/null +++ b/character/newjiang/dynamicTranslate.js @@ -0,0 +1,41 @@ +import { lib, game, ui, get, ai, _status } from "../../noname.js"; + +const dynamicTranslates = { + lkbushi(player) { + var list = lib.skill.lkbushi.getBushi(player).map(i => get.translation(i)); + return "①你使用" + list[0] + "牌无次数限制。②当你使用或打出" + list[1] + "牌后,你摸一张牌。③当你成为" + list[2] + "牌的目标后,你可以弃置一张牌,令此牌对你无效。④结束阶段开始时,你从牌堆或弃牌堆获得一张" + list[3] + "牌。⑤准备阶段开始时,你可调整此技能中四种花色的对应顺序。"; + }, + diezhang(player) { + var str = ""; + str += player.storage.duanwan ? "" : "①出牌阶段,你使用【杀】的次数上限+1。②"; + str += "转换技" + (player.storage.duanwan ? ",每回合限一次" : "") + "。"; + var cnNum = get.cnNumber(player.storage.duanwan ? 2 : 1); + var yinStr = "阴:当你使用牌被其他角色抵消后,你可以弃置一张牌,视为对其使用" + cnNum + "张【杀】"; + var yangStr = "阳:当其他角色使用牌被你抵消后,你可以摸" + cnNum + "张牌,视为对其使用一张【杀】"; + if (player.storage.diezhang) { + if (player.storage.duanwan) yinStr = '' + yinStr + ""; + yangStr = '' + yangStr + ""; + } else { + yinStr = '' + yinStr + ""; + if (player.storage.duanwan) yangStr = '' + yangStr + ""; + } + return str + yinStr + ";" + yangStr + "。"; + }, + spshidi(player) { + if (player.countMark("spshidi") % 2 == 0) return '转换技,锁定技。①准备阶段/结束阶段开始时,若你发动此分支的累计次数为奇数/偶数,则你获得一个“☯”。②若你的“☯”数为偶数,则你至其他角色的距离-1,且你使用的黑色【杀】不可被响应。③若你的“☯”数为奇数,则其他角色至你的距离+1,且你不可响应红色【杀】。'; + return '转换技,锁定技。①准备阶段/结束阶段开始时,若你发动此分支的累计次数为奇数/偶数,则你获得一个“☯”。②若你的“☯”数为偶数,则你至其他角色的距离-1,且你使用的黑色【杀】不可被响应。③若你的“☯”数为奇数,则其他角色至你的距离+1,且你不可响应红色【杀】。'; + }, + xianmou(player) { + const storage = player.storage.xianmou; + var str = "转换技,你失去过牌的回合结束时,你可以:"; + if (!storage) str += ''; + str += "阳,观看牌堆顶五张牌并获得至多X张牌,若未获得X张牌则获得〖遗计〗直到再发动此技能;"; + if (!storage) str += ""; + if (storage) str += ''; + str += "阴,观看一名角色手牌并弃置其中至多X张牌,若弃置X张牌则你进行一次【闪电】判定。"; + if (storage) str += ""; + return str+="(X为你本回合失去牌数)"; + }, +}; + +export default dynamicTranslates; diff --git a/character/newjiang/index.js b/character/newjiang/index.js new file mode 100644 index 0000000000..93171438ae --- /dev/null +++ b/character/newjiang/index.js @@ -0,0 +1,39 @@ +import { lib, game, ui, get, ai, _status } from "../../noname.js"; +import characters from "./character.js"; +import cards from "./card.js"; +import pinyins from "./pinyin.js"; +import skills from "./skill.js"; +import translates from "./translate.js"; +import characterIntros from "./intro.js"; +import characterFilters from "./characterFilter.js"; +import characterReplaces from "./characterReplace.js"; +import dynamicTranslates from "./dynamicTranslate.js"; +import perfectPairs from "./perfectPairs.js"; +import voices from "./voices.js"; +import { characterSort, characterSortTranslate } from "./sort.js"; + +game.import("character", function () { + return { + name: "newjiang", + connect: true, + character: { ...characters }, + characterSort: { + newjiang: characterSort, + }, + characterSubstitute: { + yj_sb_guojia: [ + ["yj_sb_guojia_shadow", []], + ], + }, + characterFilter: { ...characterFilters }, + characterTitle: {}, + dynamicTranslate: { ...dynamicTranslates }, + characterIntro: { ...characterIntros }, + characterReplace: { ...characterReplaces }, + card: { ...cards }, + skill: { ...skills }, + perfectPair: { ...perfectPairs }, + translate: { ...translates, ...voices, ...characterSortTranslate }, + pinyins: { ...pinyins }, + }; +}); diff --git a/character/newjiang/intro.js b/character/newjiang/intro.js new file mode 100644 index 0000000000..7b351ea9d3 --- /dev/null +++ b/character/newjiang/intro.js @@ -0,0 +1,19 @@ +const characterIntro = { + liuling: "刘伶(约221年-约300年),字伯伦,西晋沛国(治今安徽濉溪县西北)人,竹林七贤之一,中国魏晋时期作家,名士。
    刘伶自幼便失去了父爱,因其父亲身材矮小,及至长大成人后,刘伶身高也不过六尺。魏齐王曹芳正始之末(249年),刘伶已成为当世名重一时的名士,并且常与嵇康、阮籍、阮咸集会于山阳竹林之下,饮酒赋诗,弹琴作歌。晋武帝司马炎泰始初年(265年)前后,曾做过一段时间的建威参军,不久朝廷下诏,入宫中策问。他大谈老庄,强调无为而治,非但没有得到重用,反而连参军之职也被罢免了,从此再无仕进。晋惠帝司马衷永康元年(300年)前后,以寿而终。
    刘伶有“品酒第一人”的美称,也被酒行业传颂至今,后人以古瀑河边上的井水酿酒,还取刘伶墓地的黄土垒成窖池酿酒,为了纪念刘伶,当地百姓也将“润泉涌”更名为“刘伶醉”。其传世作品仅有《酒德颂》《北芒客舍》两篇,其中《酒德颂》所表现出的藐视一切存在的气概,敌视礼教之士的反抗精神,既高扬了人格的力量,批判了当时的黑暗政治,同时也抒发了压抑的愤世之情,充满了浪漫色彩,气魄豪迈,用辞又骈偶间行,有无意追求而自至的特点,对后代影响极大。", + mp_wangrong: "王戎(234年-305年7月11日),字濬冲。琅玡郡临沂县(今山东省临沂市白沙埠镇诸葛村)人。祖父为三国魏幽州刺史王雄,曹魏凉州刺史王浑的儿子。三国至西晋时期名士、官员,“竹林七贤”之一。
    王戎出身琅玡王氏。自少神采秀美,长于清谈,以精辟的品评与识鉴而著称,以聪颖知名,为父辈好友、名士阮籍器重,后人视之为玄学名士。初袭父爵贞陵亭侯,被大将军司马昭辟为掾属。累官豫州刺史、建威将军,参与晋灭吴之战。战后以功进封安丰县侯,故人称“王安丰”。治理荆州时,他拉拢士人,颇有成效。后历任侍中、光禄勋、吏部尚书、太子太傅、中书令、尚书左仆射等职。元康七年(296年),升任司徒,位列三公。王戎认为天下将乱,于是不理世事,以山水游玩为乐。赵王司马伦发动政变时,王戎被牵连免官。之后被起用为尚书令,再迁司徒。右将军张方劫持晋惠帝入长安后,王戎逃奔郏县。
    永兴二年(305年),王戎去世,时年七十二,谥号为“元”。", + xunyuxunyou: "请分别查看「荀彧」和「荀攸」的武将介绍。", + linghuyu: "令狐愚(?-249年),字公治,太原人。曹魏时期将领, 原名浚。太尉王凌的外甥,弘农太守令狐邵之侄。黄初年间出任和戎护军,后任曹爽府长史、兖州刺史。嘉平年间,与王凌一起密谋废除曹芳,共立楚王曹彪,事未行而病卒。嘉平三年(251年),事泄,王凌服毒自尽,与此事相连者,皆夷三族。王凌及令狐愚被开棺暴尸三日, 亲土埋之。", + xukun: "徐琨,字号不详,吴郡富春县(今浙江省杭州市富阳区)人。三国时期吴国开国功臣,武烈皇帝孙坚的外甥,吴大帝孙权的表兄弟,徐夫人的生父。出身吴郡豪门,最初担任郡吏。投靠舅舅孙坚,参与征伐董卓有功,拜偏将军。孙坚逝后,追随孙策,攻讨扬州刺史刘繇,采取奇袭作战方式,占领丹阳郡,为孙策开拓江东事业奠定基础,领丹杨太守。适逢吴景归附江东,改授督军中郎将。孙权嗣位后,平定庐江太守李术叛乱,击破皖城,册封广德侯,加号平虏将军。后来,随孙权征讨黄祖,身中流矢,不治而亡。", + sunli: "孙礼(?—250年),字德达,涿郡容城县人。三国时期曹魏名将。曹操平定幽州后,孙礼被征召为司空军谋掾。后被任命为河间郡丞,升至荥阳都尉。后孙礼被调为鲁国相。历任山阳、平原、平昌、琅邪郡太守。从大司马曹休在夹石征吴,孙礼谏其不可深入作战,曹休不听遂战败。后孙礼调任阳平郡太守。明帝时入为尚书,受遗诏拜大将军长史,加散骑常侍。曹爽令孙礼出任扬州刺史,加管伏波将军,赐爵关内侯。孙礼率兵御东吴军队,奋不顾身,贼众乃退。朝廷赐绢七百匹,孙礼皆以绢付亡者家,无以入身。后征拜少府,出为荆州刺史,迁冀州牧。爽见礼奏,大怒,劾礼怨望,结刑五岁。在家期年,众人多以为言,除城门校尉。出为并州刺史,加振武将军,使持节,护匈奴中郎将。爽诛后,入为司隶校尉。迁司空,封大利亭侯,邑一百户。嘉平二年(250年),孙礼去世,谥号景侯。其孙孙元继承爵位。《全三国文》录有孙礼文一篇《清河平原争界案图宜属平原疏》。陈寿评曰“孙礼刚断伉厉”。", + xiahoumao: "夏侯楙,字子林,沛国谯县(今安徽省亳州市)人,曹魏名将夏侯惇之子,三国时期魏国官员、将领,其妻为曹操之女清河公主。在魏国历任侍中、尚书、安西将军、镇东将军,假节,封列侯。曾一度驻守曹魏都城长安,但蜀汉北伐后就被调离。", + chenshi: "陈式,生卒年不详,三国时期蜀汉将领。最初为刘备军中重要的基层指挥官,后成长为高级将领。在诸葛亮第三次北伐期间,在诸葛亮的军事指挥下攻克了魏国的武都、阴平二郡。", + feiyao: "费曜(生卒年不详),又作费瑶、费繇,三国时期曹魏将领。魏初,参与平河西之乱。明帝时官任后将军,跟随曹真、司马懿多次对抗蜀汉。《三国演义》中作“费耀”,随曹真和诸葛亮的第二次北伐军作战。怀疑姜维作内应是假,自告奋勇替曹真出征,结果被事先埋伏的姜维包围,自尽而死。", + wuanguo: "武安国,历史小说《三国演义》中人物,是北海太守孔融的部将,兵器为一把长柄铁锤,重五十余斤。诸侯伐董时,双方于虎牢关相峙,吕布撰战,一合而斩穆顺,关东军大惊。北海太守孔融部将武安国,使铁锤飞马而出,吕布挥戟拍马来迎,战到十余合,一戟砍断安国手腕,安国弃锤于地而走,八路军兵齐出,这才救了他性命。", + hanlong: "韩龙,汉末三国时期刺客。韩龙使得魏国北方边得到数十年的安宁,减少魏国的军政压力,得以休养生息。太和二年,豫遣译夏舍诣比能女婿郁筑鞬部,舍为鞬所杀。其秋,豫将西部鲜卑蒲头、泄归泥出塞讨郁筑鞬,大破之。还至马城,比能自将三万骑围豫七日。上谷太守阎志,阎柔之弟也,素为鲜卑所信。志往解喻,即解围去。后幽州刺史王雄并领校尉,抚以恩信。比能数款塞,诣州奉贡献。至青龙元年,比能诱纳步度根,使叛并州,与结和亲,自勒万骑迎其累重於陉北。并州刺史毕轨遣将军苏尚、董弼等击之,比能遣子将骑与尚等会战於楼烦,临陈害尚、弼。至三年中,雄遣勇士韩龙刺杀比能,更立其弟。", + liwan: "李婉(生卒年不详),字淑文,里居不详,贾充之妻,魏晋时期才女,约景元年间(260年前后)在世。著有《典戒》。《隋书·经籍志》载李婉有文集一卷,今失传。", + zhugeshang: "诸葛尚(244年2月-263年11月),琅琊阳都(今山东沂南)人,诸葛瞻长子,诸葛亮之孙。诸葛尚博览兵书且精通武艺。炎兴元年(公元263年),出任先锋,抗拒魏国大将邓艾,与其父诸葛瞻同战死于绵竹,时年十九岁。", + kebineng: "轲比能(?~235年),为中国三国时期的鲜卑首领之一。轲比能出身鲜卑支部,因他作战勇敢,执法公平,不贪财物,所以被鲜卑民众推举为大人。轲比能因其部落近塞,所以他抓住有利条件积极学习汉族先进技术和文化,促进了鲜卑族的进步和北方的民族融合。轲比能统率下的部众,战守有法,战斗力相当强大。自曹操北征后向曹氏进贡表示效忠。魏文帝时,轲比能受封附义王。轲比能在进行部落统一战争时,受魏国干涉,受沉重打击,于是对魏怀贰,献书魏帝表忠,以麻痹魏庭,使之放松警惕。此后,轲比能的部众变得强盛,控弦十余万骑,为害魏国边境。每次钞略得财物,轲比能都公开透明地均平分配,所以得部众死力,各部大人都敬畏之。实力强大后,他继续部落统一战争,于是威行诸部落,建立起强大的鲜卑族政权。深感威胁的魏国幽州刺史王雄派刺客韩龙将其刺杀,其政权立刻崩溃,鲜卑民族再次陷入混战。", + lukai: "陆凯(198-269年),字敬风,吴郡吴县(今江苏省苏州市)人。三国时期吴国重臣,丞相陆逊的族侄,大司马陆抗的族兄。黄武年间,举孝廉出身,曾任永兴县长、诸暨县长,颇有治绩。拜建武都尉、儋耳太守,与聂友率军讨伐朱崖和儋耳,迁建武校尉。五凤二年(255年),讨斩零陵山贼陈毖,拜偏将军、巴丘督,册封都乡侯。迁武昌右部督,随军进入寿春。后拜荡魏将军,加号绥远将军。吴景帝孙休继位,拜征北将军、假节、领豫州牧。孙皓即位,迁任镇西大将军,都督巴丘,又领荆州牧,进封嘉兴侯。宝鼎元年(266年),迁左丞相。以正直及屡次劝谏孙皓而闻名。建衡元年(269年),去世,时年七十二。", +}; + +export default characterIntro; diff --git a/character/newjiang/perfectPairs.js b/character/newjiang/perfectPairs.js new file mode 100644 index 0000000000..ff8b4c5632 --- /dev/null +++ b/character/newjiang/perfectPairs.js @@ -0,0 +1 @@ +export default {}; diff --git a/character/xinghuoliaoyuan/pinyin.js b/character/newjiang/pinyin.js similarity index 100% rename from character/xinghuoliaoyuan/pinyin.js rename to character/newjiang/pinyin.js diff --git a/character/newjiang/skill.js b/character/newjiang/skill.js new file mode 100644 index 0000000000..8f3b7c2bfc --- /dev/null +++ b/character/newjiang/skill.js @@ -0,0 +1,3624 @@ +import { lib, game, ui, get, ai, _status } from "../../noname.js"; + +/** @type { importCharacterConfig['skill'] } */ +const skills = { + //马钧 + yjgongqiao: { + enable: "phaseUse", + usable: 1, + locked: false, + filter(event, player) { + if (!player.countCards("h")) return false; + for (let i = 0; i <= 5; i++){ + if (player.hasEquipableSlot(i)) return true; + } + return false; + }, + chooseButton: { + dialog(event, player){ + return ui.create.dialog("###工巧###你可将一张手牌置于你的任意装备栏内(可替换原装备牌)"); + }, + chooseControl(event, player){ + const choices = []; + for (let i = 0; i <= 5; i++){ + if (player.hasEquipableSlot(i)) choices.push(`equip${i}`); + } + choices.push("cancel2"); + return choices; + }, + backup(result, player){ + return { + audio: "yjgongqiao", + slot: result.control, + filterCard: true, + position: "h", + discard: false, + lose: false, + delay: false, + prepare: "throw", + async content(event, trigger, player){ + const card = get.autoViewAs(event.cards[0]); + card.subtypes = [lib.skill.yjgongqiao_backup.slot]; + await player.equip(card); + }, + } + }, + prompt(result, player){ + return `选择一张手牌置入${get.translation(result.control)}栏`; + }, + }, + mod: { + maxHandcard(player, num){ + if (player.hasCard(card => { + return get.type2(card, false) === "equip"; + }, "e")) return (num + 3); + }, + }, + group: ["yjgongqiao_basic", "yjgongqiao_trick"], + subSkill: { + backup: {}, + basic: { + trigger: {player: "useCard1"}, + forced: true, + popup: false, + filter(event, player){ + return get.type2(event.card, false) === "basic" && player.hasCard(card => { + return get.type2(card, false) === "basic"; + }, "e"); + }, + async content(event, trigger, player){ + trigger.baseDamage++; + game.log(player, "使用的", trigger.card, "牌面数值+1") + }, + }, + trick: { + audio: "yjgongqiao", + trigger: {player: "useCardAfter"}, + forced: true, + filter(event, player){ + const type = get.type2(event.card, false); + if (player.hasHistory("useCard", evt => { + return evt !== event && get.type2(evt.card, false) === type; + }, event)) return false; + return player.hasCard(card => { + return get.type2(card, false) === "trick"; + }, "e"); + }, + async content(event, trigger, player){ + await player.draw(); + }, + }, + }, + }, + yjjingyi: { + trigger: {player: "equipAfter"}, + forced: true, + filter(event, player) { + return event.cards?.length > 0; + }, + async content(event, trigger, player){ + const num = player.countCards("e"); + if (num > 0) await player.draw(num); + if (player.countCards("he") > 0) await player.chooseToDiscard(2, "he", true); + }, + }, + //新谋郭嘉 + xianmou: { + mark: true, + marktext: "☯", + zhuanhuanji(player, skill) { + player.storage[skill] = !player.storage[skill]; + player.changeSkin({ characterName: "yj_sb_guojia" }, "yj_sb_guojia" + (player.storage[skill] ? "_shadow" : "")); + }, + intro: { + content: function (storage) { + if (!storage) return "你失去过牌的回合结束时,你可以观看牌堆顶五张牌并获得至多X张牌,若未获得X张牌则获得〖遗计〗直到再发动此项(X为你本回合失去牌数)"; + return "你失去过牌的回合结束时,你可以观看一名角色手牌并弃置其中至多X张牌,若弃置X张牌则你进行一次【闪电】判定(X为你本回合失去牌数)"; + }, + }, + audio: 2, + audioname: ["yj_sb_guojia_shadow"], + trigger: { + global: "phaseEnd", + }, + filter(event, player) { + return player.getHistory("lose", evt => evt.cards2 && evt.cards2.length).length; + }, + async cost(event, trigger, player) { + let num = 0; + player.getHistory("lose", evt => { + if (evt.cards2) num += evt.cards2.length; + }); + if (player.storage.xianmou) { + event.result = await player.chooseTarget(get.prompt("xianmou"), `观看一名角色手牌并弃置其中至多${num}张牌`, function (card, player, target) { + return target.countCards("h"); + }).set("ai", function (target) { + const player = _status.event.player; + return get.effect(target, { name: "guohe_copy2" }, player, player); + }).forResult(); + } + else { + event.result = await player.chooseBool(get.prompt("xianmou"), `观看牌堆顶五张牌并获得至多${num}张牌`).forResult(); + } + }, + async content(event, trigger, player) { + let num = 0; + player.getHistory("lose", evt => { + if (evt.cards2) num += evt.cards2.length; + }); + player.addAdditionalSkills("xianmou", []); + player.changeZhuanhuanji("xianmou"); + if (player.storage.xianmou) { + let cards = game.cardsGotoOrdering(get.cards(5)).cards; + const result = await player.chooseButton([`是否获得至多${num}张牌?`, cards], [1, num]).set("ai", function (button) { + if (ui.selected.buttons.length + 1 >= _status.event.maxNum) return 0; + return get.value(button.link); + }).set("maxNum", num).forResult(); + if (result.bool){ + await player.gain(result.links, "gain2"); + cards.removeArray(result.links); + } + cards.reverse(); + for (var i = 0; i < cards.length; i++) { + ui.cardPile.insertBefore(cards[i], ui.cardPile.firstChild); + } + if (!result.bool || result.links.length < num) await player.addAdditionalSkills("xianmou", "new_reyiji"); + } + else { + const target = event.targets[0]; + const result = await player.discardPlayerCard(target, "h", `是否弃置${get.translation(target)}至多${num}张牌?`, [1, num], "visible").set("ai", function (button) { + if (ui.selected.buttons.length + 1 >= _status.event.maxNum) return 5 - get.value(button.link); + return get.value(button.link); + }).set("maxNum", num).forResult(); + if (result.bool && result.links.length >= num) await player.executeDelayCardEffect("shandian"); + } + }, + derivation: "new_reyiji", + group: "xianmou_change", + subSkill: { + change: { + audio: "xianmou", + audioname: ["yj_sb_guojia_shadow"], + trigger: { + global: "phaseBefore", + player: "enterGame", + }, + filter(event, player) { + return event.name != "phase" || game.phaseNumber == 0; + }, + prompt2(event, player) { + return "切换【先谋】为状态" + (player.storage.dcsbyingmou ? "阳" : "阴"); + }, + check: () => Math.random() > 0.5, + content() { + player.changeZhuanhuanji("xianmou"); + }, + }, + }, + }, + lunshi: { + audio: 2, + position: "hs", + enable: "chooseToUse", + filter(event, player) { + if (!player.countCards("hs")) return false; + if (player.countCards("h", { color: "black" }) != player.countCards("h", { color: "red" })) return false; + if (event.type != "wuxie") return false; + let info = event.info_map; + if (!info || get.type(info.card) != "trick") return false; + return info.player != info.target; + }, + filterCard: true, + viewAs: { + name: "wuxie", + }, + viewAsFilter(player) { + if (!player.countCards("hs")) return false; + if (player.countCards("h", { color: "black" }) != player.countCards("h", { color: "red" })) return false; + return true; + }, + prompt: "将一张手牌当无懈可击使用", + check: function (card) { + return 8 - get.value(card); + }, + group: "lunshi_nowuxie", + subSkill: { + nowuxie: { + trigger: { + player: "useCard", + }, + forced: true, + locked: false, + popup: false, + filter: function (event, player) { + return event.card.name == "wuxie" && event.skill && event.skill == "lunshi"; + }, + content: function () { + trigger.directHit.addArray(game.players); + }, + }, + }, + }, + //荀彧荀攸 + zhinang: { + getMap() { + if (!_status.zhinang_map) { + _status.zhinang_map = { + name: {}, + info: {}, + }; + let list; + if (_status.connectMode) { + list = get.charactersOL(); + } else { + list = get.gainableCharacters(); + } + list.forEach(name => { + if (name !== "xunyuxunyou") { + const skills = get.character(name, 3); + skills.forEach(skill => { + const info = get.info(skill); + if (!info || (info.ai && info.ai.combo)) return; + if (skill in _status.zhinang_map) return; + if (get.translation(skill).includes("谋")) _status.zhinang_map.name[skill] = name; + const voices = game.parseSkillText(skill, name); + if (voices.some(data => data.includes("谋"))) { + _status.zhinang_map.info[skill] = name; + } + }); + } + }); + } + return _status.zhinang_map; + }, + trigger: { + player: "useCardAfter", + }, + filter(event, player) { + return ["trick", "equip"].includes(get.type2(event.card)); + }, + frequent: true, + async content(event, trigger, player) { + const map = lib.skill.zhinang.getMap(), + type = get.type2(trigger.card) == "equip" ? "name" : "info", + list = Object.keys(map[type]); + if (list.length > 0) { + const skill = list.randomGet(), + voiceMap = game.parseSkillTextMap(skill, map[type][skill]); + if (type == "info") { + findaudio: for (let data of voiceMap) { + if (!data.text) continue; + if (data.text.includes("谋")) { + player.chat(data.text); + game.broadcastAll(file => game.playAudio(file), data.file); + break findaudio; + } + } + } + else player.flashAvatar("zhinang", map[type][skill]) + player.popup(skill); + await player.addSkills(skill); + } + }, + }, + gouzhu: { + trigger: { + player: ["useSkillAfter", "logSkill"], + }, + filter(event, player) { + if (["global", "equip"].includes(event.type)) return false; + let skill = event.sourceSkill || event.skill; + if (!skill || skill == "gouzhu") return false; + let info = get.info(skill); + while (true) { + if (!info || info.charlotte || info.equipSkill) return false; + if (info && !info.sourceSkill) break; + skill = info.sourceSkill; + info = get.info(skill); + } + let list = get.skillCategoriesOf(skill, player); + return list.length && list.some(item => item in lib.skill.gouzhu.effectMap); + }, + frequent: true, + effectMap: { + "锁定技": async function () { + let player = _status.event.player; + if (player.isDamaged()) await player.recover(); + }, + "觉醒技": async function () { + let player = _status.event.player; + let card = get.cardPile(card => get.type(card) == "basic"); + if (card) await player.gain(card, "gain2"); + }, + "限定技": async function () { + let player = _status.event.player; + let target = game.filterPlayer(current => current != player).randomGet(); + if (target) { + player.line(target, "green"); + await target.damage(player); + } + }, + "转换技": async function () { + let player = _status.event.player; + player.addMark("gouzhu", 1, false); + game.log(player, '手牌上限+1'); + await game.asyncDelay(); + }, + "主公技": async function () { + let player = _status.event.player; + await player.gainMaxHp(); + }, + }, + mod: { + maxHandcard: function (player, num) { + return num + player.countMark("gouzhu"); + }, + }, + intro: { + content: "手牌上限+#", + }, + locked: false, + onremove: true, + async content(event, trigger, player) { + let skill = trigger.sourceSkill || trigger.skill, + info = get.info(skill); + while (true) { + if (info && !info.sourceSkill) break; + skill = info.sourceSkill; + info = get.info(skill); + } + let list = get.skillCategoriesOf(skill, player); + for (const item of list) { + if (item in lib.skill.gouzhu.effectMap) { + const next = game.createEvent("gouzhu_effect", false); + next.player = player; + next.setContent(lib.skill.gouzhu.effectMap[item]); + await next; + } + } + }, + }, + //一将2024 + //令狐愚 + xvzhi: { + audio: 2, + enable: "phaseUse", + filter(event, player) { + return ( + game.countPlayer(target => { + return lib.skill.xvzhi.filterTarget(null, player, target); + }) > 1 + ); + }, + filterTarget(card, player, target) { + const stat = player.getStat("xvzhi"); + return target.countCards("h") && (!stat || !stat.includes(target)); + }, + selectTarget: 2, + usable: 1, + multiline: true, + multitarget: true, + async content(event, trigger, player) { + const targets = event.targets; + if (!player.getStat().xvzhi) player.getStat().xvzhi = []; + player.getStat().xvzhi.addArray(targets); + if (targets.some(i => !i.countCards("h"))) return; + const result = await player + .chooseCardOL(targets, "h", true, [1, Infinity], "蓄志:选择任意张手牌并与对方交换") + .set("ai", card => { + const player = get.event("player"), + target = get + .event() + .getParent(2) + .targets.find(i => i != player); + const sha = new lib.element.VCard({ name: "sha" }); + const playerEffect = player.hasUseTarget(sha, false) + ? Math.max( + ...game + .filterPlayer(current => player.canUse(sha, current, false)) + .map(current => { + return get.effect(current, sha, player, player); + }) + ) + : 0; + const targetEffect = target.hasUseTarget(sha, false) + ? Math.max( + ...game + .filterPlayer(current => target.canUse(sha, current, false)) + .map(current => { + return get.effect(current, sha, player, player); + }) + ) + : 0; + return 5 + 2 * get.sgn(playerEffect - targetEffect) - get.value(card); + }) + .forResult(); + await targets[0].swapHandcards(targets[1], result[0].cards, result[1].cards); + if (result[0].cards.length == result[1].cards.length) { + await player.draw(2); + player.getStat("skill").xvzhi--; + } else { + const aim = targets[result[0].cards.length > result[1].cards.length ? 0 : 1]; + const sha = new lib.element.VCard({ name: "sha" }); + if (aim.hasUseTarget(sha, false)) { + await aim.chooseUseTarget(sha, true, false, "nodistance"); + } + } + }, + ai: { + order: 5, + result: { + target(player, target) { + return get.sgn(get.attitude(player, target)) * target.countCards("h"); + }, + }, + }, + }, + //司马孚 + beiyu: { + audio: 2, + enable: "phaseUse", + filter(event, player) { + return player.countCards("h") < player.maxHp; + }, + usable: 1, + async content(event, trigger, player) { + await player.drawTo(player.maxHp); + if (!player.countCards("h")) return; + const suits = player + .getCards("h") + .reduce((list, card) => list.add(get.suit(card)), []) + .sort((a, b) => lib.suit.indexOf(b) - lib.suit.indexOf(a)); + const result = await player + .chooseControl(suits) + .set("prompt", "备预:将一种花色的手牌牌置于牌堆底") + .set("ai", () => { + const player = get.event("player"); + let suits = get.event("controls").slice(); + suits.sort((a, b) => player.countCards("h", { suit: a }) - player.countCards("h", { suit: b })); + return suits[0]; + }) + .forResult(); + if (result.control) { + const suit = result.control, + cards = player.getCards("h", { suit: suit }); + if (cards.length) { + let resultx; + if (cards.length == 1) { + resultx = { bool: true, moved: [cards] }; + } else { + resultx = await player + .chooseToMove("备预:将牌按顺序置于牌堆底", true) + .set("list", [["牌堆底", cards]]) + .set("processAI", list => { + return [list[0][1].slice(0)]; + }) + .forResult(); + } + if (resultx.bool) { + const moved = resultx.moved[0]; + if (moved.length) { + await player.lose(cards, ui.cardPile); + for (let i = 0; i < moved.length; i++) { + const card = moved[i]; + card.fix(); + ui.cardPile.appendChild(card); + } + } + } + } + } + }, + ai: { + order: 0.001, + result: { player: 1 }, + }, + }, + duchi: { + audio: 2, + trigger: { target: "useCardToTargeted" }, + filter(event, player) { + return event.player != player; + }, + usable: 1, + logTarget: "player", + check(event, player) { + return get.effect(player, event.card, event.player, player) <= 0; + }, + async content(event, trigger, player) { + await player.draw().set("bottom", true); + if (player.countCards("h")) { + await player.showHandcards(get.translation(player) + "发动了【督持】"); + const colors = player.getCards("h").reduce((list, card) => list.add(get.color(card)), []); + if (colors.length == 1) { + player.popup("洗具"); + trigger.getParent().excluded.add(player); + return; + } + } + player.popup("杯具"); + }, + ai: { threaten: 0.8 }, + }, + //宣公主 + yjqimei: { + audio: 2, + enable: "phaseUse", + filter(event, player) { + const count = player.getStat("skill").yjqimei; + if (count && count > 0 && !player.hasSkill("yjqimei_rewrite")) return false; + return true; + }, + filterTarget: lib.filter.notMe, + usable: 2, + async content(event, trigger, player) { + const target = event.target; + await player.draw(2, "nodelay"); + await target.draw(2); + const targets = [player, target].filter(current => current.countDiscardableCards(current, "he")); + if (targets.length) { + const result = await player + .chooseCardOL(targets, "he", true, 2, "齐眉:请弃置两张牌", (card, player, target) => { + return lib.filter.cardDiscardable(card, player); + }) + .forResult(); + if (result.length == 1) targets[0].discard(result[0].cards); + else { + await game + .loseAsync({ + lose_list: [ + [targets[0], result[0].cards], + [targets[1], result[1].cards], + ], + }) + .setContent("discardMultiple"); + await game.asyncDelayx(); + } + let cards = result.reduce((list, evt) => { + list.addArray(evt.cards); + return list; + }, []); + const suits = cards.reduce((list, card) => list.add(get.suit(card)), []); + switch (suits.length) { + case 1: + while (cards.length) { + const card = cards.shift(); + if (player.hasUseTarget(card)) { + player.$gain2(card, false); + await game.asyncDelayx(); + await player.chooseUseTarget(true, card, false); + } + } + break; + case 2: + for (const current of [player, target]) { + if (!current.isIn()) continue; + if (current.isLinked()) await current.link(false); + if (current.isTurnedOver()) await current.turnOver(false); + } + break; + case 3: + for (const current of [player, target]) { + if (current.isIn() && !current.isLinked()) await current.link(true); + } + break; + case 4: + await player.draw("nodelay"); + await target.draw(); + player.addTempSkill("yjqimei_rewrite"); + break; + } + } + }, + ai: { + order: 9, + result: { + target(player, target) { + const att = get.sgn(get.attitude(player, target)); + return (2 + att) * att; + }, + }, + }, + subSkill: { rewrite: { charlotte: true } }, + }, + yjzhuiji: { + audio: 2, + trigger: { player: "die" }, + filter(event, player) { + return game.hasPlayer(target => { + return ( + target != player && + Array.from({ length: 5 }) + .map((_, i) => i + 1) + .some(i => target.hasEmptySlot(i)) + ); + }); + }, + forceDie: true, + skillAnimation: true, + animationColor: "water", + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2("yjzhuiji"), (card, player, target) => { + return ( + target != player && + Array.from({ length: 5 }) + .map((_, i) => i + 1) + .some(i => target.hasEmptySlot(i)) + ); + }) + .set("ai", target => { + const player = get.event("player"); + return ( + get.sgn(get.attitude(player, target)) * + Array.from({ length: 5 }) + .map((_, i) => i + 1) + .reduce((sum, i) => sum + target.countEmptySlot(i), 0) + ); + }) + .set("forceDie", true) + .forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + let num = 1, + cards = []; + while (num <= 5) { + while (target.hasEmptySlot(num)) { + const card = get.cardPile2(card => { + return !cards.includes(card) && get.subtype(card) == "equip" + num && target.canUse(card, target); + }); + if (card) { + cards.push(card); + target.$gain2(card, false); + await game.asyncDelayx(); + await target.chooseUseTarget(card, true, "nopopup"); + } else break; + } + num++; + } + if (cards.length) { + target.addSkill("yjzhuiji_buff"); + target.markAuto("yjzhuiji_buff", cards); + } + }, + subSkill: { + buff: { + charlotte: true, + mod: { + aiValue(player, card, num) { + if (player.getStorage("yjzhuiji_buff").includes(card)) return num + 100; + }, + aiUseful(player, card, num) { + if (player.getStorage("yjzhuiji_buff").includes(card)) return num / 114514; + }, + }, + trigger: { + player: "loseAfter", + global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], + }, + filter(event, player) { + const evt = event.getl(player); + return evt && evt.es && evt.es.some(i => player.getStorage("yjzhuiji_buff").includes(i)); + }, + forced: true, + popup: false, + firstDo: true, + content() { + const evt = trigger.getl(player); + const cards = evt.es.filter(i => player.getStorage("yjzhuiji_buff").includes(i)); + player.unmarkAuto("yjzhuiji_buff", cards); + for (const card of cards) player.disableEquip(get.subtype(card)); + }, + intro: { + mark(dialog, storage) { + if (storage && storage.length) dialog.addSmall([storage, "vcard"]); + else return "暂无装备"; + }, + }, + }, + }, + }, + //徐琨(菜不菜我不知道) + fazhu: { + audio: 3, + trigger: { player: "phaseZhunbeiBegin" }, + filter(event, player) { + return player.hasCard(card => !get.tag(card, "damage") && player.canRecast(card), "hej"); + }, + async cost(event, trigger, player) { + event.result = await player + .choosePlayerCard(get.prompt(event.name.slice(0, -5)), player, "hej", [1, Infinity]) + .set("ai", button => { + const card = button.link; + if (get.position(card) == "j") return 10; + return 6 - get.value(card); + }) + .set("filterButton", button => { + const card = button.link; + return !get.tag(card, "damage") && player.canRecast(card); + }) + .forResult(); + }, + async content(event, trigger, player) { + await player.recast(event.cards); + const cards = player + .getHistory("gain", evt => evt.getParent(3) == event) + .reduce((list, evt) => { + list.addArray(evt.cards); + return list; + }, []); + let num = Math.min(cards.length, game.countPlayer()), + list = []; + if (!num) return; + if (_status.connectMode) game.broadcastAll(() => (_status.noclearcountdown = true)); + while (num - list.length > 0 && cards.some(i => get.owner(i) == player && get.position(i) == "h" && !i.hasGaintag("olsujian_given"))) { + const result = await player + .chooseCardTarget({ + prompt: "筏铸:将以此法获得的牌交给任意角色各一张", + position: "he", + animate: false, + filterCard(card, player) { + if (!get.event("cards").includes(card)) return false; + return !get.event("list").some(list => list[1] == card); + }, + filterTarget(card, player, target) { + return !get.event("list").some(list => list[0] == target); + }, + ai1(card) { + if (card.name == "sha") return 2.5; + return 1 + Math.random(); + }, + ai2(target) { + return get.attitude(get.event("player"), target); + }, + }) + .set("forced", !list.length) + .set("list", list) + .set("cards", cards) + .forResult(); + if (result.bool) { + list.push([result.targets[0], result.cards[0]]); + player.addGaintag(result.cards, "olsujian_given"); + } else break; + } + if (_status.connectMode) { + game.broadcastAll(() => { + delete _status.noclearcountdown; + game.stopCountChoose(); + }); + } + if (list.length) { + const targets = list.slice().map(list => list[0]); + await game + .loseAsync({ + gain_list: list, + player: player, + cards: list.slice().map(list => list[1]), + giver: player, + animate: "giveAuto", + }) + .setContent("gaincardMultiple"); + for (const target of targets) { + await target + .chooseToUse(function (card, player, event) { + if (get.name(card) != "sha") return false; + return lib.filter.cardEnabled.apply(this, arguments); + }) + .set("openskilldialog", "筏铸:是否使用一张【杀】(无距离限制)?") + .set("norestore", true) + .set("custom", { + add: {}, + replace: { window: function () {} }, + }) + .set("targetRequired", true) + .set("complexSelect", true) + .set("filterTarget", function (card, player, target) { + return lib.filter.targetEnabled.apply(this, arguments); + }) + .set("addCount", false); + } + } + }, + ai: { + effect: { + target(card, player, target) { + if (!card || get.type(card) != "delay") return; + if (!get.tag(card, "damage") && target.canRecast(card)) return "zeroplayertarget"; + }, + }, + }, + }, + //一将2023 + //孙礼 + kangli: { + audio: 2, + trigger: { + player: "damageEnd", + source: "damageSource", + }, + forced: true, + locked: false, + content: function () { + player.draw(2).gaintag = ["kangli"]; + player.when({ source: "damageBegin1" }).then(() => { + var cards = player.getCards("h", card => card.hasGaintag("kangli") && lib.filter.cardDiscardable(card, player, "kangli")); + if (cards.length) player.discard(cards); + }); + }, + ai: { + maixie: true, + }, + }, + //夏侯楙 + tongwei: { + audio: 2, + enable: "phaseUse", + usable: 1, + filter: function (event, player) { + return player.countCards("he", card => lib.skill.tongwei.filterCard(card, player)) > 1 && game.hasPlayer(i => i != player); + }, + filterTarget: lib.filter.notMe, + filterCard: lib.filter.cardRecastable, + selectCard: 2, + position: "he", + discard: false, + lose: false, + delay: false, + popname: true, + check: function (card) { + var num = 6.5; + if (ui.selected.cards.length) { + var cardx = ui.selected.cards[0]; + num = get.number(cardx); + } + var del = Math.abs(get.number(card) - num); + return 5 + del / 5 - get.value(card); + }, + content: function () { + "step 0"; + player.recast(cards); + "step 1"; + var numbers = cards.map(c => get.number(c, player)).sort((a, b) => a - b); + target.when("useCard1").then(() => { + trigger._tongwei_checked = true; + }); + target + .when("useCardAfter") + .assign({ + numbers: numbers, + playerx: player, + mod: { + aiOrder: function (player, card, num) { + var number = get.number(card); + if (typeof number != "number" || number <= numbers[0] || number >= numbers[1]) return num + 10; + }, + }, + }) + .filter((event, player) => { + return event._tongwei_checked; + }) + .then(() => { + var number = get.number(trigger.card); + var numbers = get.info(event.name).numbers; + event.playerx = get.info(event.name).playerx; + if (typeof number != "number" || number <= numbers[0] || number >= numbers[1]) event.finish(); + }) + .then(() => { + var playerx = event.playerx; + var names = ["sha", "guohe"].filter(name => playerx.canUse({ name: name, isCard: true }, player, false)); + if (!names.length) event.finish(); + else if (names.length == 1) event._result = { links: [[null, null, names[0]]] }; + else + playerx + .chooseButton([`请选择要视为对${get.translation(player)}使用的牌`, [names, "vcard"]], true) + .set("ai", button => { + return button.link[0][2] == _status.event.choice; + }) + .set( + "choice", + (function () { + var list = names + .map(name => { + return [name, get.effect(player, { name: name, isCard: true }, playerx, playerx)]; + }) + .sort((a, b) => { + return b[1] - a[1]; + }); + return list[0][0]; + })() + ); + }) + .then(() => { + var name = result.links[0][2]; + var card = { name: name, isCard: true }, + playerx = event.playerx; + if (playerx.canUse(card, player, false)) playerx.useCard(card, player, "tongwei"); + }); + }, + ai: { + expose: 0.2, + order: 7, + threaten: 2.2, + result: { + target: -1, + }, + }, + }, + cuguo: { + audio: 2, + trigger: { player: ["shaMiss", "eventNeutralized"] }, + filter: function (event, player) { + if (event.type != "card" && event.name != "_wuxie") return false; + if ( + !event.target || + !event.target.isIn() || + !player.canUse( + { + name: event.card.name, + nature: event.card.nature, + isCard: true, + }, + event.target, + false + ) + ) + return false; + if (!player.hasCard(card => lib.filter.cardDiscardable(card, player), "he")) return false; + var history = game.getGlobalHistory("everything"); + for (var evt of history) { + if (evt._neutralized || (evt.responded && (!evt.result || !evt.result.bool))) { + var evtx = evt.getParent(); + return evtx.name == "useCard" && evtx.player == player && evt == event; + } + } + return false; + }, + forced: true, + direct: true, + content: function () { + "step 0"; + var card = { + name: trigger.card.name, + nature: trigger.card.nature, + isCard: true, + storage: { cuguo: true }, + }; + event.card = card; + player.chooseToDiscard("蹙国:请弃置一张牌", `视为你对${get.translation(trigger.target)}使用一张${get.translation(card.nature || "")}【${get.translation(card.name)}】`, "he", true).set("logSkill", ["cuguo", trigger.target]); + "step 1"; + if (player.canUse(card, trigger.target, false)) { + player.useCard(card, trigger.target); + player + .when("useCardAfter") + .filter(event => { + return event.card.storage && event.card.storage.cuguo; + }) + .then(() => { + if ( + game.hasGlobalHistory("everything", evt => { + if (evt._neutralized || (evt.responded && (!evt.result || !evt.result.bool))) { + if (evt.getParent() == trigger) return true; + } + return false; + }) + ) { + player.loseHp(); + } + }); + } + }, + }, + //陈式 + qingbei: { + audio: 2, + trigger: { global: "roundStart" }, + direct: true, + content: function () { + "step 0"; + var next = player.chooseButton(['###擎北:是否选择任意种花色?###
    你不能于本轮能使用这些花色,且使用牌后摸等同于选择花色数的牌
    ', [lib.suit.map(i => ["", "", "lukai_" + i]), "vcard"]], [1, 4]); + next.set("ai", button => { + var player = _status.event.player; + var suit = button.link[2].slice(6); + var val = player + .getCards("hs", { suit: suit }) + .map(card => { + return get.value(card) + player.getUseValue(card) / 3; + }) + .reduce((p, c) => { + return p + c; + }, 0); + if (val > 10 && ui.selected.buttons.length > 0) return -1; + if (val > 6 && ui.selected.buttons.length == 2) return -1; + if (ui.selected.buttons.length == 3) return -1; + return 1 + 1 / val; + }); + "step 1"; + if (result.bool) { + var suits = result.links.map(i => i[2].slice(6)); + player.logSkill("qingbei"); + player.addTempSkill("qingbei_effect", "roundStart"); + player.setStorage("qingbei_effect", suits); + player.markSkill("qingbei_effect"); + } + }, + ai: { + threaten: 2.3, + }, + subSkill: { + effect: { + audio: "qingbei", + trigger: { player: "useCardAfter" }, + charlotte: true, + onremove: true, + forced: true, + filter: function (event, player) { + if (!lib.suit.includes(get.suit(event.card))) return false; + return player.getStorage("qingbei_effect").length; + }, + content: function () { + player.draw(player.getStorage("qingbei_effect").length); + }, + mark: true, + intro: { + content: storage => `本轮内不能使用${get.translation(storage)}花色的牌,且使用一张有花色的牌后摸${get.cnNumber(storage.length)}张牌`, + }, + mod: { + cardEnabled: function (card, player) { + if (player.getStorage("qingbei_effect").includes(get.suit(card))) return false; + }, + cardSavable: function (card, player) { + if (player.getStorage("qingbei_effect").includes(get.suit(card))) return false; + }, + }, + }, + }, + }, + //费曜 + zhenfeng: { + audio: 2, + trigger: { global: "useCard" }, + usable: 1, + filter: function (event, player) { + return event.player != player && event.player == _status.currentPhase && event.player.countCards("h") <= event.player.getHp(); + }, + check: function (event, player) { + var type = get.type2(event.card, event.player); + if (type == "equip" && event.player.hasCard(card => event.player.hasValueTarget(card))) return false; + if (get.attitude(player, event.player) > 0 && event.player.getHp() + event.player.countCards("hs", ["shan", "caochuan"]) <= 3) return false; + return true; + }, + onremove: true, + logTarget: "player", + content: function () { + "step 0"; + var choices = Array.from({ length: trigger.player.countCards("h") + 1 }).map((_, i) => get.cnNumber(i, true)); + var type = get.type2(trigger.card, trigger.player); + player + .chooseControl(choices) + .set("prompt", "镇锋:猜测其手牌中的" + get.translation(type) + "牌数") + .set("ai", () => { + return _status.event.choice; + }) + .set( + "choice", + (function () { + var num = trigger.player.countCards("h", card => get.type2(card) == type); + var knownNum = trigger.player.countKnownCards(_status.event.player, card => get.type2(card) == type); + if (trigger.player.isAllCardsKnown(_status.event.player)) { + return knownNum; + } + var restNum = num - knownNum; + var numx; + if (type == "basic") numx = num + Math.floor(Math.random() * restNum + 1); + else if (type == "trick") { + if (num > 2) numx = 2; + else numx = 1; + if (Math.random() < 0.5) { + numx += Math.random() > 0.5 ? 1 : -1; + } + } else { + numx = [0, 1].randomGet(); + } + if (numx < knownNum) numx = knownNum; + else if (numx >= choices.length) numx = choices.length - 1; + return numx; + })() + ); + "step 1"; + var guessedNum = result.index; + player.chat("我猜" + get.cnNumber(guessedNum) + "张"); + game.log(player, "猜测", trigger.player, "有", get.cnNumber(guessedNum) + "张" + get.translation(type) + "牌"); + event.guessedNum = guessedNum; + game.delay(); + "step 2"; + var type = get.type2(trigger.card, trigger.player); + var count = trigger.player.countCards("h", card => get.type2(card) == type); + var guessedNum = event.guessedNum; + if (count == guessedNum) { + player.popup("洗具"); + game.log(player, "猜测", "#g正确"); + if (player.countMark("zhenfeng") < 5) player.addMark("zhenfeng", 1, false); + player.draw(player.countMark("zhenfeng")); + if (player.canUse("sha", trigger.player, false)) player.useCard({ name: "sha", isCard: true }, trigger.player); + } else { + player.popup("杯具"); + game.log(player, "猜测", "#y错误"); + player.clearMark("zhenfeng"); + if (Math.abs(count - guessedNum) > 1 && trigger.player.canUse("sha", player, false)) { + trigger.player.useCard({ name: "sha", isCard: true }, player, false, "noai"); + } + } + }, + intro: { + content: "已连续猜对#次", + }, + }, + //新杀小加强 李严 + dcduliang: { + enable: "phaseUse", + usable: 1, + filterTarget: function (card, player, target) { + return player != target && target.countCards("he") > 0; + }, + audio: "duliang", + content: function () { + "step 0"; + player.gainPlayerCard(target, "he", true); + "step 1"; + var name = get.translation(target); + player + .chooseControl(function () { + return Math.random() < 0.5 ? "选项一" : "选项二"; + }) + .set("prompt", "督粮:请选择一项") + .set("choiceList", ["你观看牌堆顶的两张牌,然后令" + name + "获得其中的一或两张基本牌", "令" + name + "于下回合的摸牌阶段额外摸一张牌"]); + "step 2"; + if (result.control == "选项一") { + var cards = get.cards(2), + bool = false; + event.cards = cards; + game.cardsGotoOrdering(cards); + for (var card of cards) { + if (get.type(card) == "basic") { + bool = true; + break; + } + } + player + .chooseButton(["督粮:选择令" + get.translation(target) + "获得的牌", cards], [1, 2], bool) + .set("filterButton", button => { + return get.type(button.link) == "basic"; + }) + .set("ai", button => { + return _status.event.sgn * get.value(button.link); + }) + .set("sgn", get.sgnAttitude(player, target) > 0); + } else { + target.addTempSkill("dcduliang2", { player: "phaseAfter" }); + target.addMark("dcduliang2", 1, false); + event.finish(); + } + "step 3"; + if (result.bool) { + var cardsx = result.links; + target.gain(cardsx, "draw"); + game.log(target, "获得了" + get.cnNumber(cardsx.length) + "张牌"); + cards.removeArray(cardsx); + cards.reverse(); + } + for (var i = 0; i < cards.length; i++) { + ui.cardPile.insertBefore(cards[i], ui.cardPile.firstChild); + } + game.updateRoundNumber(); + }, + ai: { + order: 4, + result: { + target: -1, + player: 0.1, + }, + }, + }, + dcduliang2: { + trigger: { player: "phaseDrawBegin" }, + forced: true, + mark: true, + audio: false, + onremove: true, + charlotte: true, + intro: { + content: "下回合的摸牌阶段额外摸#张牌", + }, + content: function () { + trigger.num += player.countMark("dcduliang2"); + }, + }, + //苏飞 + shuojian: { + audio: 2, + enable: "phaseUse", + usable: 3, + filterTarget: lib.filter.notMe, + filterCard: true, + position: "he", + discard: false, + lose: false, + delay: false, + check: function (card, player) { + return 6 - get.value(card); + }, + content: function () { + "step 0"; + player.give(cards, target); + "step 1"; + var num = 3 - get.skillCount("shuojian") + 1; + event.num = num; + event.num2 = num; + if (event.num == 0) event.finish(); + "step 2"; + var forced = num != event.num2; + var prompt = "###" + get.translation(player) + "对你发动了【数谏】###视为使用" + get.cnNumber(num) + "张【过河拆桥】" + (forced ? "" : "且" + get.translation(player) + "此技能本回合失效,或点击“取消”令其摸" + get.cnNumber(num) + "张牌"); + if (!target.hasUseTarget({ name: "guohe" })) event._result = { bool: false }; + else + target + .chooseUseTarget(prompt, "guohe", forced) + .set("ai", function () { + var evt = _status.event; + if (evt.name == "chooseTarget") evt = evt.getParent(); + if (!evt.goon) return 0; + return get.effect_use.apply(this, arguments); + }) + .set("goon", target.getUseValue({ name: "guohe" }) > (get.sgnAttitude(target, player) * player.getUseValue({ name: "wuzhong" })) / (2 - num * 0.4)); + "step 3"; + if (!result.bool) { + player.draw(num); + if (num > 1) player.chooseToDiscard("he", num - 1, true); + event.finish(); + } + "step 4"; + if (--event.num2 > 0) { + event.goto(2); + } else player.tempBanSkill("shuojian"); + }, + ai: { + expose: 0.15, + order: 8, + result: { target: 1 }, + }, + }, + //谯周 + shiming: { + audio: 2, + trigger: { global: "phaseDrawBegin1" }, + filter: function (event, player) { + return !player.hasSkill("shiming_round"); + }, + check: function (event, player) { + return true; //get.attitude(player,event.player)<0||get.damageEffect(event.player,event.player,player)>0; + }, + logTarget: "player", + content: function () { + "step 0"; + player.addTempSkill("shiming_round", "roundStart"); + var cards = get.cards(3); + player + .chooseButton(["识命:是否将其中一张置于牌堆底?", cards.slice(0)]) + .set("ai", button => { + var att = _status.event.att, + damage = _status.event.damage, + val = get.value(button.link, _status.event.player); + if ((att > 0 && damage < 0) || (att <= 0 && damage > 0)) return 6 - val; + return val - 5.99; + }) + .set("att", get.attitude(player, trigger.player)) + .set("damage", get.damageEffect(trigger.player, trigger.player, player) > 0 && trigger.player.hp <= 3 ? 1 : -1); + while (cards.length) ui.cardPile.insertBefore(cards.pop(), ui.cardPile.firstChild); + "step 1"; + if (result.bool) { + var card = result.links[0]; + card.fix(); + ui.cardPile.appendChild(card); + player.popup("一下", "wood"); + game.log(player, "将一张牌置于了牌堆底"); + } + "step 2"; + trigger.player + .chooseBool("是否跳过摸牌阶段并对自己造成1点伤害,然后从牌堆底摸三张牌?") + .set("ai", () => _status.event.bool) + .set("bool", get.damageEffect(trigger.player, trigger.player) >= -6 || trigger.player.hp > 3); + "step 3"; + if (result.bool) { + trigger.cancel(); + trigger.player.damage(trigger.player); + } else event.finish(); + "step 4"; + trigger.player.draw(3, "bottom"); + }, + subSkill: { + round: { + mark: true, + intro: { content: "本轮已发动〖识命〗" }, + }, + }, + }, + jiangxi: { + audio: 2, + trigger: { global: "phaseEnd" }, + filter: function (event, player) { + var zhu = game.findPlayer(i => i.getSeatNum() == 1); + return ( + (zhu && + player.hasSkill("shiming_round") && + (game.getGlobalHistory("changeHp", evt => { + return evt.player == zhu && evt._dyinged; + }).length > 0 || + zhu.getHistory("damage").length == 0)) || + !game.hasPlayer2(current => current.getHistory("damage").length > 0) + ); + }, + direct: true, + content: function () { + "step 0"; + var zhu = game.findPlayer(i => i.getSeatNum() == 1); + if (zhu && player.hasSkill("shiming_round")) { + if ( + game.getGlobalHistory("changeHp", evt => { + return evt.player == zhu && evt._dyinged; + }).length > 0 || + zhu.getHistory("damage").length == 0 + ) { + player.chooseBool(get.prompt("jiangxi"), "重置〖识命〗"); + } + } else event.goto(2); + "step 1"; + if (result.bool) { + player.logSkill("jiangxi"); + event.logged = true; + player.removeSkill("shiming_round"); + player.draw(); + } + "step 2"; + if (!game.hasPlayer2(current => current.getHistory("damage").length > 0)) { + player + .chooseBool(get.prompt("jiangxi"), "与" + get.translation(trigger.player) + "各摸一张牌") + .set("ai", () => _status.event.bool) + .set("bool", trigger.player.getUseValue({ name: "wuzhong" }) + player.getUseValue({ name: "wuzhong" }) > 0); + } else event.finish(); + "step 3"; + if (result.bool) { + if (!event.logged) player.logSkill("jiangxi"); + trigger.player.draw("nodelay"); + player.draw(); + } + }, + }, + //韩龙 + duwang: { + audio: 2, + trigger: { + global: "phaseBefore", + player: "enterGame", + }, + forced: true, + filter: function (event, player) { + return event.name != "phase" || game.phaseNumber == 0; + }, + content: function () { + var cards = []; + for (var i = 0; i < ui.cardPile.childNodes.length; i++) { + var card = ui.cardPile.childNodes[i]; + if (card.name != "sha") cards.push(card); + if (cards.length >= 5) break; + } + if (cards.length) player.addToExpansion(cards, "gain2").gaintag.add("duwang"); + }, + marktext: "刺", + intro: { + name: "刺", + name2: "刺", + content: "expansion", + markcount: "expansion", + }, + mod: { + globalFrom: function (from, to, distance) { + return distance + Math.min(1, from.getExpansions("duwang").filter(i => i.name != "sha").length); + }, + globalTo: function (from, to, distance) { + return distance + Math.min(1, to.getExpansions("duwang").filter(i => i.name != "sha").length); + }, + }, + }, + cibei: { + audio: 2, + trigger: { global: "cardsDiscardAfter" }, + filter: function (event, player) { + if (!player.getExpansions("duwang").filter(i => i.name != "sha").length) return false; + var evt = event.getParent(); + if (evt.name != "orderingDiscard") return false; + var evtx = evt.relatedEvent || evt.getParent(); + return ( + evtx.name == "useCard" && + evtx.card.name == "sha" && + event.cards.filterInD("d").length && + game.hasPlayer2(current => + current.hasHistory("sourceDamage", evtxx => { + return evtxx.card == evtx.card; + }) + ) + ); + }, + direct: true, + group: "cibei_fullyReady", + content: function () { + "step 0"; + player.chooseButton(["###" + get.prompt(event.name) + '###
    将一张“刺”置入弃牌堆,并将' + get.translation(trigger.cards.filterInD("d")) + "置入“刺”
    ", player.getExpansions("duwang")]).set("filterButton", button => { + return button.link.name != "sha"; + }); + "step 1"; + if (result.bool) { + player.logSkill(event.name); + player.loseToDiscardpile(result.links); + player.addToExpansion(trigger.cards.filterInD("d"), "gain2").gaintag.add("duwang"); + if (game.hasPlayer(current => current.countDiscardableCards(player, "hej") > 0)) + player + .chooseTarget("刺北:弃置一名角色区域内的一张牌", true, (card, player, target) => { + return target.countDiscardableCards(player, "hej") > 0; + }) + .set("ai", target => { + return get.effect(target, { name: "guohe" }, _status.event.player); + }); + } else event.finish(); + "step 2"; + if (result.bool) { + var target = result.targets[0]; + player.line(target); + player.discardPlayerCard(target, "hej", true); + player.addExpose(0.1); + } + }, + ai: { + combo: "duwang", + }, + subSkill: { + fullyReady: { + trigger: { global: "phaseEnd" }, + forced: true, + locked: false, + filter: function (event, player) { + var storage = player.getExpansions("duwang"); + return storage.length > 0 && storage.every(i => i.name == "sha"); + }, + content: function () { + player.gain(player.getExpansions("duwang"), "gain2").gaintag.add("cibei_mark"); + player.addSkill("cibei_mark"); + }, + }, + mark: { + trigger: { player: "useCard1" }, + onremove: true, + charlotte: true, + silent: true, + firstDo: true, + filter: function (event, player) { + return player.hasHistory("lose", evt => { + if (evt.getParent() != event) return false; + for (var i in evt.gaintag_map) { + if (evt.gaintag_map[i].includes("cibei_mark")) return true; + } + return false; + }); + }, + content: function () { + if (trigger.addCount !== false) { + trigger.addCount = false; + var stat = player.getStat().card, + name = trigger.card.name; + if (typeof stat[name] == "number") stat[name]--; + } + }, + mod: { + ignoredHandcard: function (card, player) { + if (card.hasGaintag("cibei_mark")) return true; + }, + cardDiscardable: function (card, player, name) { + if (card.hasGaintag("cibei_mark")) return false; + }, + canBeDiscarded: function (card) { + if (card.hasGaintag("cibei_mark")) return false; + }, + targetInRange: function (card, player, target) { + if (!card.cards) return; + for (var i of card.cards) { + if (i.hasGaintag("cibei_mark")) return true; + } + }, + cardUsable: function (card, player) { + if (!card.cards) return; + for (var i of card.cards) { + if (i.hasGaintag("cibei_mark")) return true; + } + }, + }, + }, + }, + }, + //武安国 + diezhang: { + audio: 2, + locked: false, + zhuanhuanji: function (player, skill) { + if (!player.storage.duanwan) player.storage[skill] = !player.storage[skill]; + }, + trigger: { global: ["eventNeutralized", "shaMiss"] }, + filter: function (event, player) { + if (player.hasSkill("diezhang_used")) return false; + if (event.type != "card") return false; + var evt = event._neutralize_event; + var user, responder; + if (event.name == "sha") { + user = event.player; + responder = event.target; + } else { + if (evt.type != "card") return false; + user = event.player; + responder = evt.player; + } + if (!player.storage.diezhang) { + if (user != player || responder == player) return false; + return player.countDiscardableCards(player, "he") > 0 && player.canUse("sha", responder, false); + } else { + if (user == player || responder != player) return false; + return player.canUse("sha", user, false); + } + }, + direct: true, + content: function () { + "step 0"; + var evt = trigger._neutralize_event; + var user, responder; + if (trigger.name == "sha") { + user = trigger.player; + responder = trigger.target; + } else { + user = trigger.player; + responder = evt.player; + } + var num = player.storage.duanwan ? 2 : 1; + event.num = num; + if (!player.storage.diezhang) { + var target = responder; + event.target = target; + var next = player + .chooseToDiscard(get.prompt("diezhang", target), "弃置一张牌,视为对其使用" + get.cnNumber(num) + "张【杀】", "he") + .set("ai", card => { + if (_status.event.goon) return 6 - get.value(card); + return 0; + }) + .set("logSkill", ["diezhang", target]); + } else { + var target = user; + event.target = target; + var next = player.chooseBool(get.prompt("diezhang", target), "摸" + get.cnNumber(num) + "张牌,视为对其使用一张【杀】").set("ai", () => _status.event.goon); + } + next.set("goon", get.effect(target, { name: "sha" }, player, player) > 0); + "step 1"; + if (result.bool) { + if (player.storage.duanwan) player.addTempSkill("diezhang_used"); + player.changeZhuanhuanji("diezhang"); + if (!result.cards || !result.cards.length) { + player.logSkill("diezhang", target); + player.draw(num, "nodelay"); + player.useCard({ name: "sha", isCard: true }, target, false); + } else while (num--) player.useCard({ name: "sha", isCard: true }, target, false); + } + }, + marktext: "☯", + mark: true, + intro: { + content: function (storage, player) { + var cnNum = get.cnNumber(player.storage.duanwan ? 2 : 1); + if (storage) return "当其他角色使用牌被你抵消后,你可以摸" + cnNum + "张牌,视为对其使用一张【杀】。"; + return "当你使用牌被其他角色抵消后,你可以弃置一张牌,视为对其使用" + cnNum + "张【杀】。"; + }, + }, + mod: { + cardUsable: function (card, player, num) { + if (!player.storage.duanwan && card.name == "sha") return num + 1; + }, + }, + subSkill: { used: { charlotte: true } }, + }, + duanwan: { + audio: 2, + enable: "chooseToUse", + skillAnimation: true, + animationColor: "soil", + limited: true, + filter: function (event, player) { + return event.type == "dying" && player == event.dying; + }, + content: function () { + player.changeZhuanhuanji("diezhang"); + player.awakenSkill("duanwan"); + var num = 2 - player.hp; + if (num > 0) player.recover(num); + }, + ai: { + save: true, + skillTagFilter: function (player, tag, target) { + return player == target; + }, + result: { player: 1 }, + }, + }, + //李婉 + liandui: { + audio: 2, + trigger: { global: "useCard" }, + filter: function (event, player) { + const history = game.getAllGlobalHistory("useCard"); + const index = history.indexOf(event); + if (index <= 0) return false; + const previous = history[index - 1].player; + if (event.player == player && previous != player && previous.isIn()) return true; + if (event.player != player && previous == player) return true; + return false; + }, + async cost(event, trigger, player) { + if (!trigger.player) return; + const history = game.getAllGlobalHistory("useCard"); + const index = history.indexOf(trigger); + const previous = history[index - 1].player; + const { result } = await trigger.player + .chooseBool("是否对" + get.translation(previous) + "发动【联对】?", "令" + get.translation(previous) + "摸两张牌") + .set("ai", () => _status.event.bool) + .set("bool", get.effect(previous, { name: "draw" }, trigger.player, trigger.player) > 0); + if (result.bool) event.result = { bool: true, cost_data: previous }; + }, + async content(event, trigger, player) { + const { cost_data: previous } = event; + previous.draw(2); + }, + }, + biejun: { + audio: 2, + global: "biejun_give", + trigger: { player: "damageBegin4" }, + filter: function (event, player) { + return ( + !player.hasSkill("biejun_used") && + player.countCards("h", card => { + return card.hasGaintag("biejun"); + }) == 0 + ); + }, + prompt2: "翻面并防止此伤害", + check: function (event, player) { + return player.isTurnedOver() || event.num >= player.hp || get.distance(_status.currentPhase, player, "absolute") >= 3; + }, + content: function () { + player.addTempSkill("biejun_used"); + player.turnOver(); + trigger.cancel(); + }, + ai: { + effect: { + target: function (card, player, target) { + if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; + if (get.tag(card, "damage")) { + if (player.getNext() == target && lib.skill.biejun.filter(null, target) && target.isTurnedOver()) return [0, 1]; + } + }, + }, + }, + subSkill: { + used: { charlotte: true }, + give: { + audio: 2, + enable: "phaseUse", + usable: 1, + filter: function (event, player) { + if (!player.countCards("h")) return false; + var targets = game.filterPlayer(function (current) { + return current != player && current.hasSkill("biejun"); + }); + if (!targets.length) return false; + return true; + }, + selectCard: 1, + filterCard: true, + filterTarget: function (card, player, target) { + return target.hasSkill("biejun"); + }, + selectTarget: function () { + var player = _status.event.player; + var targets = game.filterPlayer(function (current) { + return current != player && current.hasSkill("biejun"); + }); + return targets.length > 1 ? 1 : -1; + }, + complexSelect: true, + prompt: function () { + var player = _status.event.player; + var targets = game.filterPlayer(function (current) { + return current != player && current.hasSkill("biejun"); + }); + return "将一张手牌交给" + get.translation(targets) + (targets.length > 1 ? "中的一人" : ""); + }, + position: "h", + discard: false, + lose: false, + delay: false, + check: function (card) { + var player = _status.event.player; + if ( + game.hasPlayer(function (current) { + return lib.skill.biejun_give.filterTarget(null, player, current) && get.attitude(player, current) > 0; + }) + ) { + return 5 - get.value(card); + } + return -get.value(card); + }, + content: function () { + game.trySkillAudio("biejun", target); + player.give(cards, target).gaintag.add("biejun"); + target.addTempSkill("biejun_tag"); + }, + ai: { + order: 2, + result: { target: 1 }, + }, + }, + tag: { + charlotte: true, + forced: true, + onremove: function (player) { + player.removeGaintag("biejun"); + }, + }, + }, + }, + //诸葛尚 + sangu: { + audio: 2, + trigger: { player: "phaseJieshuBegin" }, + direct: true, + getEffect: function (player, target, event, list1, list2) { + let att = get.attitude(player, target); + if (att === 0) return 0; + let getv = function (name, player, arg) { + let v = event.getTempCache("sangu", player.playerid + name); + if (typeof v === "number") return v; + v = player.getUseValue({ name: name, storage: { sangu: true } }, arg); + event.putTempCache("sangu", player.playerid + name, v); + return v; + }; + if (att < 0) { + for (let i of list1) { + if (getv(i, target) <= 0 || getv(i, target) <= 0) return -att * Math.sqrt(get.threaten(target)) * 2; + } + return 0; + } else { + let list = list1.concat(player.hp > 1 ? list2 : []), + eff = 0; + list.sort(function (a, b) { + return getv(b, target) - getv(a, target); + }); + list = list.slice(3); + for (let i of list) { + let res = getv(i, target); + if (res <= 5) break; + else eff += res; + } + return Math.sqrt(eff / 1.5) * att; + } + }, + content: function () { + "step 0"; + event.list1 = []; + event.list2 = []; + event.used = []; + player.getHistory("useCard", function (evt) { + event.used.add(evt.card.name); + }); + for (let name of lib.inpile) { + let add = false, + type = get.type(name); + if (name === "sha") add = true; + else if (type === "trick") { + let info = lib.card[name]; + if (info && !info.singleCard && !info.notarget) add = true; + } + if (!add) continue; + if (event.used.includes(name)) event.list1.push(name); + else event.list2.push(name); + } + if (!event.list1.length && !event.list2.length) event.finish(); + else + player + .chooseTarget(get.prompt2("sangu"), lib.filter.notMe) + .set("ai", function (target) { + return lib.skill.sangu.getEffect(_status.event.player, target, _status.event.getTrigger(), _status.event.list1, _status.event.list2); + }) + .set("list1", event.list1) + .set("list2", event.list2); + "step 1"; + if (result.bool) { + var target = result.targets[0]; + player.logSkill("sangu", target); + event.target = target; + } else event.finish(); + "step 2"; + var dialog = ["为" + get.translation(target) + "选择至多三个牌名"]; + if (event.list1.length) { + dialog.push('
    本回合已使用过的牌
    '); + dialog.push([event.list1.map(i => [get.type(i), "", i]), "vcard"]); + } + if (event.list2.length) { + dialog.push('
    本回合未使用过的牌
    '); + dialog.push([event.list2.map(i => [get.type(i), "", i]), "vcard"]); + } + player + .chooseButton(dialog, true, [1, 3]) + .set("ai", function (button) { + let name = button.link[2], + list = _status.event.list, + player = _status.event.player, + target = _status.event.getParent().target, + trigger = _status.event.getTrigger(), + getv = (name, player) => { + let v = trigger.getTempCache("sangu", player.playerid + name); + if (typeof v === "number") return v; + v = player.getUseValue({ name: name, storage: { sangu: true } }); + trigger.putTempCache("sangu", player.playerid + name, v); + return v; + }; + if (get.attitude(player, target) < 0) { + if (!list.includes(name)) return 0; + return -getv(name, target); + } else { + if (player.hp < 2 && !list.includes(name)) return 0; + let val = getv(name, target), + base = 5; + val = Math.min(15, val - base); + if (name === "wuzhong" || name === "dongzhuxianji") val += 15; + else if (name === "shunshou") val += 6; + return val; + } + }) + .set("list", event.list1); + "step 3"; + if (result.bool) { + var names = result.links.map(i => i[2]); + if (!target.storage.sangu_effect) target.storage.sangu_effect = []; + target.storage.sangu_effect = target.storage.sangu_effect.concat(names); + game.log(player, "为", target, "选择了", "#y" + get.translation(names)); + target.addTempSkill("sangu_effect", { player: "phaseUseAfter" }); + target.markSkill("sangu_effect"); + var bool = true; + for (var i of names) { + if (!event.used.includes(i)) { + bool = false; + break; + } + } + if (bool) { + target.addTempSkill("sangu_prevent", { player: "phaseUseAfter" }); + target.markAuto("sangu_prevent", [player]); + } + } + }, + ai: { + effect: { + target: function (card, player, target, current) { + if (get.tag(card, "damage") && card.storage && card.storage.sangu) return "zeroplayertarget"; + }, + }, + }, + subSkill: { + effect: { + trigger: { player: "phaseUseBegin" }, + charlotte: true, + forced: true, + popup: false, + content: function () { + player.addTempSkill("sangu_viewas"); + }, + onremove: true, + intro: { + mark: function (dialog, storage, player) { + if (!storage || !storage.length) return "当前无可用牌"; + dialog.add([[storage[0]], "vcard"]); + if (storage.length > 1) dialog.addSmall([storage.slice(1), "vcard"]); + }, + content: "$", + }, + }, + viewas: { + mod: { + hiddenCard: function (player, name) { + var storage = player.getStorage("sangu_effect"); + if (storage.length) return name == storage[0]; + }, + cardname: function (card, player) { + if (_status.event.name != "chooseToUse" || _status.event.skill) return; + var storage = player.getStorage("sangu_effect"); + if (storage.length) return storage[0]; + }, + cardnature: function (card, player) { + if (_status.event.name != "chooseToUse" || _status.event.skill) return; + var storage = player.getStorage("sangu_effect"); + if (storage.length) return false; + }, + }, + trigger: { player: ["useCard", "respond"] }, + forced: true, + charlotte: true, + filter: function (event, player) { + return event.cards.length > 0 && player.getStorage("sangu_effect").length > 0; + }, + content: function () { + if (!trigger.card.storage) trigger.card.storage = {}; + trigger.card.storage.sangu = true; + player.unmarkAuto("sangu_effect", [player.getStorage("sangu_effect")[0]]); + }, + }, + prevent: { + trigger: { source: "damageBegin2" }, + forced: true, + charlotte: true, + onremove: true, + filter: function (event, player) { + return event.card && event.card.storage && event.card.storage.sangu && player.getStorage("sangu_prevent").includes(event.player); + }, + content: function () { + trigger.cancel(); + }, + }, + }, + }, + yizu: { + audio: 2, + trigger: { target: "useCardToTargeted" }, + forced: true, + usable: 1, + filter: function (event, player) { + return player.isDamaged() && player.hp <= event.player.hp && (event.card.name == "sha" || event.card.name == "juedou"); + }, + content: function () { + player.recover(); + }, + ai: { + effect: { + target_use(card, player, target, current) { + if (target.isHealthy() || (card.name != "sha" && card.name != "juedou")) return; + if (target.storage.counttrigger && target.storage.counttrigger.yizu && current < 0) return 5; + if (player.hp < target.hp) return; + if (current > 0) return 1.2; + if (get.attitude(player, target) >= 0) return; + var copy = get.effect(target, { name: "shacopy" }, player, player); + if ( + copy > 0 && + player.isPhaseUsing() && + Math.min( + player.getCardUsable("sha"), + player.countCards("hs", function (card) { + return get.name(card) == "sha" && player.canUse(card, target, null, true); + }) + ) >= 2 + ) + return; + return [0, 2]; + }, + }, + }, + }, + //轲比能 + kousheng: { + audio: 2, + trigger: { player: "phaseUseBegin" }, + direct: true, + filter: function (event, player) { + return player.countCards("h") > 0; + }, + content: function () { + "step 0"; + player + .chooseCard("h", [1, player.countCards("h")], get.prompt("kousheng"), "你可以选择任意张手牌,这些手牌于本回合内视为无次数限制的【杀】。但当有角色受到这些【杀】的伤害后,其可以用所有手牌交换剩余的牌。") + .set("standard", player.getUseValue({ name: "sha" }, null, true)) + .set("ai", function (card) { + var player = _status.event.player, + standard = _status.event.standard; + if (standard <= 0) return 0; + var eff = player.getUseValue(card, null, true); + if (eff <= standard) return standard - eff + 0.1; + return 0; + }); + "step 1"; + if (result.bool) { + player.logSkill("kousheng"); + player.addGaintag(result.cards, "kousheng"); + player.addTempSkill("kousheng_effect"); + game.delayx(); + } + }, + subSkill: { + effect: { + audio: "kousheng", + trigger: { player: "useCard1" }, + forced: true, + charlotte: true, + firstDo: true, + filter: function (event, player) { + if (event.card.name != "sha") return false; + return player.hasHistory("lose", function (evt) { + if (evt.getParent() != event) return false; + for (var i in evt.gaintag_map) { + if (evt.gaintag_map[i].includes("kousheng")) return true; + } + return false; + }); + }, + content: function () { + if (!trigger.card.storage) trigger.card.storage = {}; + trigger.card.storage.kousheng = true; + if (trigger.addCount !== false) { + trigger.addCount = false; + player.getStat("card").sha--; + } + }, + onremove: function (player) { + player.removeGaintag("kousheng"); + }, + mod: { + cardUsable: function (card, player, target) { + if (card.name != "sha" || !card.cards) return; + for (var i of card.cards) { + if (i.hasGaintag("kousheng")) return Infinity; + } + }, + cardname: function (card) { + if (get.itemtype(card) == "card" && card.hasGaintag("kousheng")) return "sha"; + }, + cardnature: function (card) { + if (get.itemtype(card) == "card" && card.hasGaintag("kousheng")) return false; + }, + }, + group: "kousheng_damage", + }, + damage: { + audio: "kousheng", + trigger: { source: "damageSource" }, + forced: true, + filter: function (event, player) { + if (!event.card || !event.card.storage || !event.card.storage.kousheng || event.getParent().type != "card") return false; + var target = event.player; + return ( + target.isIn() && + player.hasCard(function (card) { + return card.hasGaintag("kousheng"); + }, "h") + ); + }, + content: function () { + "step 0"; + var target = trigger.player; + event.target = target; + var cards = player.getCards("h", function (card) { + return card.hasGaintag("kousheng"); + }); + event.cards = cards; + var str = get.translation(player); + player.showCards(cards, str + "的【寇旌】牌"); + if (target.countCards("h") > 0) + target.chooseBool("是否交换“寇旌”牌?", "用你的所有手牌交换" + str + "的下列“寇旌”牌:" + get.translation(cards)).set("ai", function () { + var player = _status.event.player, + target = _status.event.getParent().player; + if (player.hasShan() || player.countCards("hs", { name: ["tao", "jiu"] }) > 0 || get.attitude(player, target) >= 0) return false; + var hs1 = player.getCards("h"), + hs2 = _status.event.getParent().cards; + if (hs2.length >= player.hp) return true; + if (get.value(hs1, player) >= get.value(hs2, target)) return false; + return true; + }); + else event.finish(); + "step 1"; + if (result.bool) { + player.swapHandcards(target, cards, target.getCards("h")); + } + }, + }, + }, + }, + //陆凯 + lkbushi: { + audio: 2, + getBushi: function (player) { + if (!player.storage.lkbushi) return ["spade", "heart", "club", "diamond"]; + return player.storage.lkbushi; + }, + onremove: true, + trigger: { player: "phaseZhunbeiBegin" }, + direct: true, + locked: false, + content: function () { + "step 0"; + var list = lib.skill.lkbushi.getBushi(player); + list = list.map(function (i) { + return ["", "", "lukai_" + i]; + }); + var next = player.chooseToMove("卜筮:是否调整〖卜筮〗的花色顺序?"); + next.set("list", [ + [ + "无次数限制/使用打出摸牌
    可弃牌无效/结束阶段获得", + [list, "vcard"], + function (list) { + var list2 = list.map(function (i) { + return get.translation(i[2].slice(6)); + }); + return "你使用" + list2[0] + "牌时无次数限制;使用或打出" + list2[1] + "时,摸一张牌;
    成为" + list2[2] + "牌目标后可弃一张牌无效;结束阶段获得一张" + list2[3] + "牌"; + }, + ], + ]); + next.set("processAI", function () { + var player = _status.event.player; + var list = lib.skill.lkbushi.getBushi(player); + var list2 = []; + var hs = player.getCards("hs", function (card) { + return player.hasValueTarget(card); + }); + list.sort(function (a, b) { + return hs.filter(i => get.suit(i) == b).length - hs.filter(i => get.suit(i) == a).length; + }); + list2.push(list.shift()); + hs = player.getCards("hs", "sha"); + list.sort(function (a, b) { + return hs.filter(i => get.suit(i) == b).length - hs.filter(i => get.suit(i) == a).length; + }); + list2.unshift(list.shift()); + list.randomSort(); + list2.addArray(list); + return [list2.map(i => ["", "", "lukai_" + i])]; + }); + "step 1"; + if (result.bool) { + var list = lib.skill.lkbushi.getBushi(player), + list2 = result.moved[0].map(function (i) { + return i[2].slice(6); + }); + for (var i = 0; i < 4; i++) { + if (list[i] != list2[i]) { + player.logSkill("lkbushi"); + player.storage.lkbushi = list2; + var str = "#g"; + for (var j = 0; j < 4; j++) { + str += get.translation(list2[j]); + if (j != 3) str += "/"; + } + game.log(player, "将", "#g【卜筮】", "的花色序列改为", str); + game.delayx(); + break; + } + } + } + }, + mark: true, + marktext: "筮", + intro: { + content: function (storage, player) { + var list = lib.skill.lkbushi.getBushi(player).map(i => get.translation(i)); + return "①你使用" + list[0] + "牌无次数限制。②当你使用或打出" + list[1] + "牌后,你摸一张牌。③当你成为" + list[2] + "牌的目标后,你可以弃置一张牌,令此牌对你无效。④结束阶段开始时,你从牌堆或弃牌堆获得一张" + list[3] + "牌。⑤准备阶段开始时,你可调整此技能中四种花色的对应顺序。"; + }, + }, + group: ["lkbushi_unlimit", "lkbushi_draw", "lkbushi_defend", "lkbushi_gain"], + subSkill: { + unlimit: { + mod: { + cardUsable: function (card, player) { + const list = lib.skill.lkbushi.getBushi(player), + suit = get.suit(card); + if (suit === "unsure" || list[0] === suit) return Infinity; + }, + }, + trigger: { player: "useCard1" }, + forced: true, + popup: false, + silent: true, + firstDo: true, + filter: function (event, player) { + if (event.addCount === false) return true; + var list = lib.skill.lkbushi.getBushi(player); + return list[0] == get.suit(event.card); + }, + content: function () { + trigger.addCount = false; + var stat = player.getStat().card, + name = trigger.card.name; + if (stat[name] && typeof stat[name] == "number") stat[name]--; + }, + }, + draw: { + audio: "lkbushi", + trigger: { player: ["useCard", "respond"] }, + forced: true, + locked: false, + filter: function (event, player) { + var list = lib.skill.lkbushi.getBushi(player); + return list[1] == get.suit(event.card); + }, + content: function () { + player.draw(); + }, + }, + defend: { + audio: "lkbushi", + trigger: { target: "useCardToTargeted" }, + direct: true, + filter: function (event, player) { + var list = lib.skill.lkbushi.getBushi(player); + return list[2] == get.suit(event.card) && !event.excluded.includes(player) && player.countCards("he") > 0; + }, + content: function () { + "step 0"; + player + .chooseToDiscard("he", get.prompt("lkbushi"), "弃置一张牌,令" + get.translation(trigger.card) + "对你无效") + .set("ai", function (card) { + if (_status.event.eff >= 0) return false; + return -_status.event.eff * 1.1 - get.value(card); + }) + .set("eff", get.effect(player, trigger.card, trigger.player, player)).logSkill = ["lkbushi_defend", trigger.player]; + "step 1"; + if (result.bool) { + trigger.excluded.add(player); + } + }, + }, + gain: { + audio: "lkbushi", + trigger: { player: "phaseJieshuBegin" }, + forced: true, + locked: false, + content: function () { + var list = lib.skill.lkbushi.getBushi(player); + var card = get.cardPile(function (card) { + return get.suit(card, false) == list[3]; + }); + if (card) player.gain(card, "gain2"); + }, + }, + }, + }, + lkzhongzhuang: { + audio: 2, + trigger: { source: ["damageBegin1", "damageBegin4"] }, + forced: true, + filter: function (event, player, name) { + if (!event.card || event.card.name != "sha" || event.getParent().type != "card") return false; + var range = player.getAttackRange(); + if (name == "damageBegin1") return range > 3; + return range < 3 && event.num > 1; + }, + content: function () { + if (event.triggername == "damageBegin1") trigger.num++; + else trigger.num = 1; + }, + global: "lkzhongzhuang_ai", + subSkill: { + ai: { + ai: { + filterDamage: true, + skillTagFilter: function (player, tag, arg) { + if (arg && arg.card && arg.card.name == "sha") { + if (arg.player && arg.player.hasSkill("lkzhongzhuang") && arg.player.getAttackRange() < 3) return true; + } + return false; + }, + }, + }, + }, + }, + //将星独具 + xinzhilve: { + enable: "phaseUse", + audio: "zhilve", + usable: 1, + chooseButton: { + dialog: function (event, player) { + var list = ["移动场上的一张牌", "摸一张牌并视为使用一张【杀】"]; + var choiceList = ui.create.dialog("知略:失去1点体力并...", "forcebutton", "hidden"); + choiceList.add([ + list.map((item, i) => { + return [i, item]; + }), + "textbutton", + ]); + return choiceList; + }, + filter: function (button, player) { + if (button.link == 0) return player.canMoveCard(); + return player.hasUseTarget({ name: "sha", isCard: true }, false); + }, + check: function (button) { + return button.link; + }, + backup: function (links) { + return lib.skill["xinzhilve_" + ["move", "use"][links[0]]]; + }, + prompt: function () { + return "请选择【杀】的目标"; + }, + }, + ai: { + order: function (item, player) { + return get.order({ name: "sha" }) + 0.1; + }, + result: { + player: function (player) { + if (player.hp > 2 && player.hasValueTarget({ name: "sha" })) return 1; + return 0; + }, + }, + }, + }, + xinzhilve_move: { + audio: "zhilve", + filterCard: function () { + return false; + }, + selectCard: -1, + delay: false, + content: function () { + "step 0"; + event.forceDie = true; + if (!player.canMoveCard(null, event.nojudge)) { + event.finish(); + return; + } + var next = player.chooseTarget(2, function (card, player, target) { + if (ui.selected.targets.length) { + var from = ui.selected.targets[0]; + var js = from.getCards("j"); + for (var i = 0; i < js.length; i++) { + if (_status.event.nojudge) break; + if (target.canAddJudge(js[i])) return true; + } + if (target.isMin()) return false; + var es = from.getCards("e"); + for (var i = 0; i < es.length; i++) { + if (target.canEquip(es[i])) return true; + } + return false; + } else { + var range = "ej"; + if (_status.event.nojudge) range = "e"; + return target.countCards(range) > 0; + } + }); + next.set("nojudge", event.nojudge || false); + next.set("ai", function (target) { + var player = _status.event.player; + var att = get.attitude(player, target); + var sgnatt = get.sgn(att); + if (ui.selected.targets.length == 0) { + if (att > 0) { + if ( + !_status.event.nojudge && + target.countCards("j", function (card) { + return game.hasPlayer(function (current) { + return current.canAddJudge(card) && get.attitude(player, current) < 0; + }); + }) + ) + return 14; + if ( + target.countCards("e", function (card) { + return ( + get.value(card, target) < 0 && + game.hasPlayer(function (current) { + return current != target && get.attitude(player, current) < 0 && current.canEquip(card); + }) + ); + }) > 0 + ) + return 9; + } else if (att < 0) { + if ( + game.hasPlayer(function (current) { + if (current != target && get.attitude(player, current) > 0) { + var es = target.getCards("e"); + for (var i = 0; i < es.length; i++) { + if (get.value(es[i], target) > 0 && current.canEquip(es[i]) && get.value(es[i], current) > 0) return true; + } + } + }) + ) { + return -att; + } + } + return 0; + } + var es = ui.selected.targets[0].getCards("e"); + var i; + var att2 = get.sgn(get.attitude(player, ui.selected.targets[0])); + for (i = 0; i < es.length; i++) { + if (sgnatt != 0 && att2 != 0 && get.sgn(get.value(es[i], ui.selected.targets[0])) == -att2 && get.sgn(get.value(es[i], target)) == sgnatt && target.canEquip(es[i])) { + return Math.abs(att); + } + } + if ( + i == es.length && + (_status.event.nojudge || + !ui.selected.targets[0].countCards("j", function (card) { + return target.canAddJudge(card); + })) + ) { + return 0; + } + return -att * get.attitude(player, ui.selected.targets[0]); + }); + next.set("multitarget", true); + next.set("targetprompt", _status.event.targetprompt || ["被移走", "移动目标"]); + next.set("prompt", event.prompt || "移动场上的一张牌"); + if (event.prompt2) next.set("prompt2", event.prompt2); + if (event.forced) next.set("forced", true); + "step 1"; + event.result = result; + if (result.bool) { + player.line2(result.targets, "green"); + event.targets = result.targets; + } else { + event.finish(); + } + "step 2"; + game.delay(); + "step 3"; + if (targets.length == 2) { + player + .choosePlayerCard( + "ej", + true, + function (button) { + var player = _status.event.player; + var targets0 = _status.event.targets0; + var targets1 = _status.event.targets1; + if (get.attitude(player, targets0) > 0 && get.attitude(player, targets1) < 0) { + if (get.position(button.link) == "j") return 12; + if (get.value(button.link, targets0) < 0) return 10; + return 0; + } else { + if (get.position(button.link) == "j") return -10; + return get.equipValue(button.link); + } + }, + targets[0] + ) + .set("nojudge", event.nojudge || false) + .set("targets0", targets[0]) + .set("targets1", targets[1]) + .set("filterButton", function (button) { + var targets1 = _status.event.targets1; + if (get.position(button.link) == "j") { + if (_status.event.nojudge) return false; + return targets1.canAddJudge(button.link); + } else { + return targets1.canEquip(button.link); + } + }); + } else { + event.finish(); + } + "step 4"; + if (result.bool && result.links.length) { + player.loseHp(); + } + "step 5"; + if (result.bool && result.links.length) { + var link = result.links[0]; + if (get.position(link) == "e") { + event.targets[1].equip(link); + } else if (link.viewAs) { + event.targets[1].addJudge({ name: link.viewAs }, [link]); + } else { + event.targets[1].addJudge(link); + } + event.targets[0].$give(link, event.targets[1]); + event.result.card = link; + event.result.position = get.position(link); + game.delay(); + player.addTempSkill("xinzhilve_mark"); + player.addMark("xinzhilve_mark", 1, false); + } + }, + }, + xinzhilve_use: { + audio: "zhilve", + filterCard: function () { + return false; + }, + selectCard: -1, + filterTarget: function (card, player, target) { + return player.canUse({ name: "sha", isCard: true }, target, false); + }, + content: function () { + player.loseHp(); + player.draw(); + player.useCard({ name: "sha", isCard: true }, false, target).forceDie = true; + player.addTempSkill("xinzhilve_mark"); + player.addMark("xinzhilve_mark", 1, false); + }, + ai: { + result: { + target: function (player, target) { + return get.effect(target, { name: "sha" }, player, target); + }, + }, + }, + }, + xinzhilve_mark: { + intro: { content: "本回合手牌上限+#" }, + onremove: true, + charlotte: true, + mod: { + maxHandcard: function (player, num) { + return num + player.countMark("xinzhilve_mark"); + }, + }, + }, + xinxhzhiyan: { + audio: "xhzhiyan", + enable: "phaseUse", + filter: function (event, player) { + return (!player.hasSkill("xinxhzhiyan_true") && player.countCards("h") > player.hp) || (!player.hasSkill("xinxhzhiyan_false") && player.countCards("h") < player.maxHp); + }, + filterCard: true, + selectCard: function () { + var player = _status.event.player; + if (player.hasSkill("xinxhzhiyan_true")) return 0; + var num = Math.max(0, player.countCards("h") - player.hp); + if (ui.selected.cards.length || player.hasSkill("xinxhzhiyan_false") || player.countCards("h") >= player.maxHp) return [num, num]; + return [0, num]; + }, + filterTarget: lib.filter.notMe, + selectTarget: function () { + if (ui.selected.cards.length) return [1, 1]; + return [0, 0]; + }, + check: function (card) { + var player = _status.event.player; + var checkx = function (card) { + if ( + player.getUseValue(card, null, true) <= 0 && + game.hasPlayer(function (current) { + return current != player && get.value(card, current) > 0 && get.attitude(player, current) > 0; + }) + ) + return 2; + return 1; + }; + if ( + player.countCards("h", function (card) { + return checkx(card) > 0; + }) < + player.countCards("h") - player.hp + ) + return 0; + return checkx(card); + }, + delay: false, + discard: false, + lose: false, + content: function () { + var bool = cards && cards.length > 0; + player.addTempSkill("xinxhzhiyan_" + bool, "phaseUseEnd"); + if (!bool) { + player.draw(player.maxHp - player.countCards("h")); + } else { + player.give(cards, target); + } + }, + ai: { + order: function (obj, player) { + if (player.countCards("h") > player.hp) return 10; + return 0.5; + }, + result: { + player: function (player, target) { + if (!ui.selected.cards.length && player.countCards("h") < player.maxHp) return 1; + return 0; + }, + target: 1, + }, + }, + }, + xinxhzhiyan_true: {}, + xinxhzhiyan_false: { + mod: { + playerEnabled: function (card, player, target) { + if (player != target && (!get.info(card) || !get.info(card).singleCard || !ui.selected.targets.length)) return false; + }, + }, + mark: true, + intro: { + content: "不能对其他角色使用牌", + }, + }, + weifeng: { + audio: 2, + trigger: { player: "useCardAfter" }, + forced: true, + filter: function (event, player) { + if ( + !event.targets || + !event.targets.filter(function (target) { + return target != player && !target.storage.weifeng2; + }).length + ) + return false; + var evt = event.getParent("phaseUse"); + if (!evt || evt.player != player) return false; + if (!get.tag(event.card, "damage")) return false; + if (!["basic", "trick"].includes(get.type(event.card))) return false; + return ( + player + .getHistory("useCard", function (ev) { + return ev.getParent("phaseUse") == evt && get.tag(ev.card, "damage") && ["basic", "trick"].includes(get.type(ev.card)); + }) + .indexOf(event) == 0 && + game.hasPlayer(function (current) { + return current != player && !current.storage.weifeng2 && event.targets.includes(current); + }) + ); + }, + content: function () { + "step 0"; + player + .chooseTarget(true, "威风:请选择一个目标,令其获得一个【惧(" + get.translation(trigger.card.name) + ")】标记", function (card, player, target) { + return player != target && !target.storage.weifeng2 && _status.event.getTrigger().targets.includes(target); + }) + .set("ai", function (target) { + return -get.attitude(_status.event.player, target); + }); + "step 1"; + if (result.bool) { + var target = result.targets[0]; + target.storage.weifeng2 = trigger.card.name; + player.line(target, "green"); + game.log(target, "获得了一个", "#g【惧(" + get.translation(trigger.card.name) + ")】", "标记"); + target.markSkill("weifeng2"); + player.addSkill("weifeng3"); + } + }, + }, + weifeng2: { + intro: { + content: "当前“惧”标记名称:$", + onunmark: function (storage, player) { + if (player.storage.weifeng2) { + game.log(player, "移去了一个", "#g【惧(" + get.translation(player.storage.weifeng2) + ")】", "标记"); + delete player.storage.weifeng2; + } + }, + }, + marktext: "惧", + }, + weifeng3: { + trigger: { + global: "damageBegin3", + player: ["phaseZhunbeiBegin", "dieBegin"], + }, + forced: true, + popup: false, + filter: function (event, player) { + if (event.name != "damage") return true; + return event.player != player && typeof event.player.storage.weifeng2 == "string"; + }, + content: function () { + if (trigger.name == "damage") { + player.logSkill("weifeng", trigger.player); + if (trigger.card && trigger.card.name == trigger.player.storage.weifeng2) trigger.num++; + else if (trigger.player.countGainableCards(player, "he") > 0) player.gainPlayerCard(trigger.player, "he", true); + trigger.player.unmarkSkill("weifeng2"); + } else { + game.countPlayer(function (current) { + if (current.storage.weifeng2) current.unmarkSkill("weifeng2"); + }); + player.removeSkill("weifeng3"); + } + }, + }, + gnjinfan: { + trigger: { player: "phaseDiscardBegin" }, + direct: true, + locked: false, + audio: 2, + filter: function (event, player) { + var list = []; + player.getCards("s", function (card) { + if (card.hasGaintag("gnjinfan")) list.add(get.suit(card)); + }); + if (list.length >= lib.suit.length) return false; + return ( + player.countCards("h", function (card) { + return _status.connectMode || !list.includes(get.suit(card)); + }) > 0 + ); + }, + content: function () { + "step 0"; + player + .chooseCard( + "h", + get.prompt("gnjinfan"), + "将任意张手牌当做“铃”置于武将牌上", + [ + 1, + (function () { + var list = []; + var list2 = []; + player.getCards("s", function (card) { + if (card.hasGaintag("gnjinfan")) list.add(get.suit(card)); + }); + player.getCards("h", function (card) { + list2.add(get.suit(card)); + }); + list2.removeArray(list); + return Math.max(1, list2.length); + })(), + ], + function (card, player) { + return ( + !player.countCards("s", function (cardx) { + return cardx.hasGaintag("gnjinfan") && get.suit(cardx, false) == get.suit(card, player); + }) && + !ui.selected.cards.filter(function (cardx) { + return get.suit(cardx, player) == get.suit(card, player); + }).length + ); + } + ) + .set("ai", function (card) { + var player = _status.event.player; + if (player.hasUseTarget(card) && !player.hasValueTarget(card)) return 0; + if (["sha", "shan", "wuxie", "caochuan"].includes(card.name)) return 2 + Math.random(); + return 1 + Math.random(); + }) + .set("complexCard", true); + "step 1"; + if (result.bool) { + player.logSkill("gnjinfan"); + game.log(player, "将", result.cards, "放到了武将牌上"); + player.loseToSpecial(result.cards, "gnjinfan").visible = true; + } else event.finish(); + "step 2"; + player.markSkill("gnjinfan"); + }, + group: ["gnjinfan_gain"], + marktext: "铃", + intro: { + mark: function (dialog, storage, player) { + dialog.addAuto( + player.getCards("s", function (card) { + return card.hasGaintag("gnjinfan"); + }) + ); + }, + markcount: function (storage, player) { + return player.getCards("s", function (card) { + return card.hasGaintag("gnjinfan"); + }).length; + }, + onunmark: function (storage, player) { + var cards = player.getCards("s", function (card) { + return card.hasGaintag("gnjinfan"); + }); + if (cards.length) { + player.lose(cards, ui.discardPile); + player.$throw(cards, 1000); + game.log(cards, "进入了弃牌堆"); + } + }, + }, + mod: { + aiOrder: function (player, card, num) { + if (get.itemtype(card) == "card" && card.hasGaintag("gnjinfan")) return num + 0.5; + }, + }, + }, + gnjinfan_gain: { + audio: "gnjinfan", + trigger: { player: "loseAfter" }, + forced: true, + filter: function (event, player) { + if (!event.ss || !event.ss.length) return false; + for (var i in event.gaintag_map) { + if (event.gaintag_map[i].includes("gnjinfan")) return true; + return false; + } + }, + content: function () { + "step 0"; + var cards = []; + for (var i of trigger.ss) { + if (!trigger.gaintag_map[i.cardid] || !trigger.gaintag_map[i.cardid].includes("gnjinfan")) continue; + var suit = get.suit(i, false); + var card = get.cardPile2(function (card) { + return !cards.includes(card) && get.suit(card, false) == suit; + }); + if (card) cards.push(card); + } + if (cards.length) player.gain(cards, "gain2"); + var num = player.getCards("s", function (card) { + return card.hasGaintag("gnjinfan"); + }).length; + if (num) player.markSkill("gnjinfan"); + else player.unmarkSkill("gnjinfan"); + "step 1"; + game.updateRoundNumber(); + }, + }, + gnsheque: { + audio: 2, + trigger: { global: "phaseZhunbeiBegin" }, + direct: true, + filter: function (event, player) { + return event.player.isIn() && event.player.countCards("e") > 0 && lib.filter.targetEnabled({ name: "sha" }, player, event.player) && (player.hasSha() || (_status.connectMode && player.countCards("h") > 0)); + }, + content: function () { + player + .chooseToUse( + function (card, player, event) { + if (get.name(card) != "sha") return false; + return lib.filter.filterCard.apply(this, arguments); + }, + "射却:是否对" + get.translation(trigger.player) + "使用一张杀?" + ) + .set("logSkill", "gnsheque") + .set("complexSelect", true) + .set("filterTarget", function (card, player, target) { + if (target != _status.event.sourcex && !ui.selected.targets.includes(_status.event.sourcex)) return false; + return lib.filter.targetEnabled.apply(this, arguments); + }) + .set("sourcex", trigger.player) + .set("oncard", function (card) { + try { + card.gnsheque_tag = true; + } catch (e) { + alert("发生了一个导致【射却】无法正常触发无视防具效果的错误。请关闭十周年UI/手杀ui等扩展以解决"); + } + }); + }, + ai: { + unequip: true, + unequip_ai: true, + skillTagFilter: function (player, tag, arg) { + if (tag == "unequip_ai") { + if (_status.event.getParent().name != "gnsheque") return false; + } else if (!arg || !arg.card || !arg.card.gnsheque_tag) return false; + }, + }, + }, + //猩黄忠 + spshidi: { + audio: 2, + trigger: { player: ["phaseZhunbeiBegin", "phaseJieshuBegin"] }, + zhuanhuanji: "number", + filter: function (event, player) { + return player.countMark("spshidi") % 2 == ["phaseJieshu", "phaseZhunbei"].indexOf(event.name); + }, + logAudio(event, player) { + return "spshidi" + (2 - player.countMark("spshidi") % 2) +".mp3"; + }, + forced: true, + content: function () { + player.changeZhuanhuanji("spshidi"); + }, + mod: { + globalFrom: function (from, to, distance) { + if (from.countMark("spshidi") % 2 == 0) return distance - 1; + }, + globalTo: function (from, to, distance) { + if (to.countMark("spshidi") % 2 == 1) return distance + 1; + }, + aiOrder: function (player, card, num) { + if (player.countMark("spshidi") % 2 == 0 && card.name == "sha" && get.color(card) == "black") return num + 0.1; + }, + }, + mark: true, + marktext: "☯", + intro: { + content: function (storage, player) { + return "已转换过" + (storage || 0) + "次"; + }, + }, + ai: { + directHit_ai: true, + skillTagFilter: function (player, tag, arg) { + if (!arg || !arg.card || !arg.target || arg.card.name != "sha") return false; + return player.countMark("spshidi") % 2 == 0 && get.color(arg.card) == "black"; + }, + }, + group: ["spshidi_use", "spshidi_beused"], + subSkill: { + use: { + audio: "spshidi1.mp3", + trigger: { player: "useCard" }, + forced: true, + filter: function (event, player) { + return event.card.name == "sha" && player.countMark("spshidi") % 2 == 0 && get.color(event.card, false) == "black"; + }, + content: function () { + trigger.directHit.addArray(game.players); + }, + }, + beused: { + audio: "spshidi2.mp3", + trigger: { target: "useCardToTargeted" }, + forced: true, + filter: function (event, player) { + return event.card.name == "sha" && player.countMark("spshidi") % 2 == 1 && get.color(event.card, false) == "red"; + }, + content: function () { + trigger.directHit.add(player); + }, + }, + }, + }, + spyishi: { + audio: 2, + trigger: { source: "damageBegin2" }, + filter: function (event, player) { + return player != event.player && event.player.countCards("e") > 0; + }, + check: function (event, player) { + return ( + get.damageEffect(event.player, player, player) <= 0 || + (get.attitude(player, event.player) <= 0 && + !event.player.hasSkillTag("noe") && + event.player.hasCard(function (card) { + return get.value(card) > 9 - event.player.hp; + }, "e")) + ); + }, + logTarget: "player", + content: function () { + trigger.num--; + player.gainPlayerCard(trigger.player, "e", true); + }, + }, + spqishe: { + enable: "chooseToUse", + viewAs: { name: "jiu" }, + filterCard: { type: "equip" }, + position: "hes", + viewAsFilter: function (player) { + return player.hasCard({ type: "equip" }, "ehs"); + }, + check: function (card) { + if (_status.event.type == "dying") return 1 / (get.value(card) || 0.5); + return 5 - get.value(card); + }, + locked: false, + mod: { + maxHandcard: function (player, num) { + return num + player.countCards("e"); + }, + }, + }, + //☆胃炎 + mbguli: { + audio: 2, + enable: "phaseUse", + filterCard: true, + selectCard: -1, + position: "h", + filter: function (event, player) { + if (player.hasSkill("mbguli_used")) return false; + var hs = player.getCards("h"); + if (!hs.length) return false; + for (var card of hs) { + var mod2 = game.checkMod(card, player, "unchanged", "cardEnabled2", player); + if (mod2 === false) return false; + } + return event.filterCard(get.autoViewAs({ name: "sha" }, hs)); + }, + viewAs: { + name: "sha", + storage: { mbguli: true }, + }, + onuse: function (links, player) { + player.addTempSkill("mbguli_used", "phaseUseAfter"); + }, + ai: { + order: 1, + threaten: 1.14514, + unequip_ai: true, + skillTagFilter: function (player, tag, arg) { + if (arg && arg.name == "sha" && arg.card && arg.card.storage && arg.card.storage.mbguli) return true; + return false; + }, + }, + subSkill: { + used: { + audio: "mbguli", + trigger: { global: "useCardAfter" }, + charlotte: true, + prompt2: "失去1点体力,然后将手牌摸至体力上限", + check: function (event, player) { + var num = player.maxHp - player.countCards("h"); + return (num >= 3 && player.hp >= 2) || (num >= 2 && player.hp >= 3); + }, + filter: function (event, player) { + return ( + event.card.storage && + event.card.storage.mbguli && + game.hasPlayer2(current => { + return current.hasHistory("sourceDamage", evt => evt.card == event.card); + }) + ); + }, + content: function () { + "step 0"; + player.loseHp(); + "step 1"; + player.drawTo(player.maxHp); + }, + group: "mbguli_unequip", + }, + unequip: { + trigger: { + player: "useCardToPlayered", + }, + filter: function ({ card }) { + return card.name == "sha" && card.storage && card.storage.mbguli; + }, + forced: true, + popup: false, + logTarget: "target", + content: function () { + trigger.target.addTempSkill("qinggang2"); + trigger.target.storage.qinggang2.add(trigger.card); + trigger.target.markSkill("qinggang2"); + }, + }, + }, + }, + mbaosi: { + audio: 2, + trigger: { source: "damageSource" }, + forced: true, + filter: function (event, player) { + return player.inRange(event.player) && player.isPhaseUsing() && event.player.isIn() && !player.getStorage("mbaosi_inf").includes(event.player); + }, + logTarget: "player", + content: function () { + player.addTempSkill("mbaosi_inf", "phaseUseAfter"); + player.markAuto("mbaosi_inf", [trigger.player]); + }, + subSkill: { + inf: { + charlotte: true, + onremove: true, + forced: true, + intro: { content: "对$使用牌无次数限制" }, + mod: { + cardUsableTarget: function (card, player, target) { + if (player.getStorage("mbaosi_inf").includes(target)) return true; + }, + }, + }, + }, + }, + //☆周不疑 + mbhuiyao: { + audio: 2, + enable: "phaseUse", + usable: 1, + // filterTarget:lib.filter.notMe, + content: function () { + "step 0"; + player.damage("nosource"); + "step 1"; + if (game.countPlayer() < 2) event.finish(); + if (game.countPlayer() == 2) + event._result = { + bool: true, + targets: [game.findPlayer(i => i != player), player], + }; + else + player + .chooseTarget( + `慧夭:请选择两名角色`, + `令不为你的第一名角色视为对第二名角色造成过1点伤害。`, + (card, player, target) => { + if (!ui.selected.targets.length) return player != target; + return true; + }, + 2, + true + ) + .set("multitarget", true) + .set("targetprompt", ["伤害来源", "受伤角色"]) + .set("ai", target => { + return target == get.event("aiTargets")[ui.selected.targets.length] ? 10 : 0; + }) + .set("aiTargets", lib.skill.mbhuiyao.getUnrealDamageTargets(player, [game.filterPlayer(i => i != player), game.filterPlayer()], true)); + "step 2"; + if (result.bool) { + var targets = result.targets; + player.line2(targets, "green"); + game.delaye(); + targets[1].damage(targets[0], "unreal"); + } + }, + getUnrealDamageTargets: (player, lists, forced) => { + const targets = [null, null]; + let sourceList, targetList; + if (lists.length == 2 && lists.every(l => Array.isArray(l))) { + sourceList = lists[0]; + targetList = lists[1]; + } else { + sourceList = lists.slice(); + targetList = lists.slice(); + } + const list = targetList + .map(current => { + const _hp = current.hp, + _maxhp = current.maxHp; + current.hp = 100; + current.maxHp = 100; + const att = -get.sgnAttitude(player, current); + let val = get.damageEffect(current, player, current) * att; + current.getSkills(null, false, false).forEach(skill => { + const info = get.info(skill); + if (info && info.ai && (info.ai.maixie || info.ai.maixie_hp || info.ai.maixie_defend)) val = Math[val > 0 ? "max" : "min"](val > 0 ? 0.1 : -0.1, val + 2 * att); + }); + const eff = 100 / val + 15; + current.hp = _hp; + current.maxHp = _maxhp; + return [current, eff]; + }) + .sort((a, b) => b[1] - a[1])[0]; + if (list[1] < 0 && !forced) return targets; + const targetx = list[0]; + targets[1] = targetx; + const list2 = sourceList + .filter(i => i != targetx) + .map(current => { + const _hp = targetx.hp, + _maxhp = targetx.maxHp; + targetx.hp = 100; + targetx.maxHp = 100; + const att = -get.sgnAttitude(player, current); + const eff = get.damageEffect(targetx, current, current) * att; + targetx.hp = _hp; + targetx.maxHp = _maxhp; + return [current, eff]; + }) + .sort((a, b) => b[1] - a[1])[0]; + if (!list2) return targets; + targets[0] = list2[0]; + return targets; + }, + ai: { + order: 6, + result: { + player: function (player) { + if (player.getHp() + player.countCards("hs", card => player.canSaveCard(card, player)) <= 1) return 0; + var limit = 25; + var quesong = player.hasSkill("mbquesong") && !player.getStat().damaged; + if (quesong) { + limit -= 7.5; + } + if ( + quesong && + game.hasPlayer(target => { + var att = get.attitude(player, target); + if (att < 0) return false; + return ( + att * + Math.sqrt( + Math.max( + 1, + [1, 2, 3, 4].reduce((p, c) => p + target.countEmptySlot(c), 0) + ) + ) >= + 10 || target.getHp() <= 2 + ); + }) + ) + return 1; + if ( + !quesong && + game.hasPlayer(target => { + if (target == player) return false; + var _hp = target.hp, + _maxhp = target.maxHp; + target.hp = 100; + target.maxHp = 100; + var att = -get.sgnAttitude(player, target); + var val = get.damageEffect(target, player, target) * att; + target.getSkills(null, false, false).forEach(skill => { + var info = get.info(skill); + if (info && info.ai && (info.ai.maixie || info.ai.maixie_hp || info.ai.maixie_defend)) val = Math[val > 0 ? "max" : "min"](val > 0 ? 0.1 : -0.1, val + 2 * att); + }); + var eff = 100 / val; + target.hp = _hp; + target.maxHp = _maxhp; + if (eff < limit) return false; + return true; + }) + ) + return 1; + return 0; + }, + }, + }, + }, + mbquesong: { + audio: 2, + trigger: { global: "phaseJieshuBegin" }, + filter: function (event, player) { + return player.getHistory("damage").length; + }, + direct: true, + content: function () { + "step 0"; + player.chooseTarget(get.prompt2("mbquesong")).set("ai", target => { + var player = _status.event.player; + if (get.attitude(player, target) <= 0) return 0; + var len = lib.skill.mbquesong.getNum(target), + hp = target.getHp(); + return len + target.isTurnedOver() * 2 + (1.5 * Math.min(4, target.getDamagedHp())) / (hp + 1); + }); + "step 1"; + if (result.bool) { + var target = result.targets[0]; + event.target = target; + player.logSkill("mbquesong", target); + var len = lib.skill.mbquesong.getNum(target); + if (target.isHealthy()) event._result = { index: 0 }; + else { + target + .chooseControl() + .set("choiceList", ["摸" + get.cnNumber(len) + "张牌并复原武将牌", "回复1点体力"]) + .set("prompt", "雀颂:请选择一项") + .set("ai", () => { + var player = _status.event.player; + var len = _status.event.len; + return get.effect(player, { name: "draw" }, player, player) * len >= get.recoverEffect(player, player, player) ? 0 : 1; + }) + .set("len", len); + } + } else event.finish(); + "step 2"; + if (result.index == 1) { + target.recover(); + event.finish(); + } else target.draw(lib.skill.mbquesong.getNum(target)); + "step 3"; + target.link(false); + "step 4"; + target.turnOver(false); + }, + getNum: function (player) { + return player.countCards("e", card => get.subtype(card) != "equip5") >= 3 ? 2 : 3; + }, + ai: { + expose: 0.2, + maixie: true, + skillTagFilter: function (player, tag) { + if (player.getStat().damaged) return false; + }, + }, + }, + //王戎 + mpjianlin: { + audio: 2, + trigger: { + global: "phaseAfter", + }, + getCards(player) { + const cards = []; + game.checkGlobalHistory("cardMove", evt => { + if (evt.name == "lose") { + if (evt.position !== ui.discardPile) return false; + } else if (evt.name !== "cardsDiscard") return false; + if (get.info("mpjianlin").isUseOrRespond(evt, player)) { + cards.addArray( + evt.cards.filter(card => { + return get.type(card) == "basic" && get.position(card) === "d"; + }) + ); + } + }); + player.checkHistory("lose", evt => { + if (evt.type == "discard") { + cards.addArray( + evt.cards2.filter(card => { + return get.type(card) == "basic" && get.position(card) === "d"; + }) + ); + } + }); + return cards; + }, + isUseOrRespond(event, player) { + if (event.name !== "cardsDiscard") return false; + const evtx = event.getParent(); + if (evtx.name !== "orderingDiscard") return false; + const evt2 = evtx.relatedEvent || evtx.getParent(); + return ["useCard", "respond"].includes(evt2.name) && evt2.player == player; + }, + filter(event, player) { + return get.info("mpjianlin").getCards(player).length; + }, + async cost(event, trigger, player) { + const cards = get.info("mpjianlin").getCards(player); + const { + result: { bool, links }, + } = await player.chooseButton(["俭吝:你可以获得其中一张牌", cards]).set("ai", get.buttonValue); + event.result = { + bool: bool, + cost_data: links, + }; + }, + async content(event, trigger, player) { + player.gain(event.cost_data, "gain2"); + }, + }, + mpsixiao: { + audio: 2, + trigger: { + global: "phaseBefore", + player: "enterGame", + }, + locked: true, + filter(event, player) { + return (event.name != "phase" || game.phaseNumber == 0) && game.hasPlayer(current => current != player); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(true, lib.filter.notMe, "死孝:请选择一名角色当其孝子", "当该角色需要使用或打出除【无懈可击】外的牌时,其可以观看你的手牌并可以使用或打出其中一张牌,然后你摸一张牌") + .set("ai", target => { + return get.attitude(get.player(), target); + }) + .forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + game.log(player, "成为了", target, "的孝子"); + target.storage.mpsixiao_use = player; + target.addSkill("mpsixiao_use"); + }, + subSkill: { + use: { + charlotte: true, + mark: "character", + intro: { + content: "当你需要使用或打出除【无懈可击】外的牌时,你可以观看$的手牌并可以使用或打出其中一张牌,然后$摸一张牌", + }, + hiddenCard(player, name) { + if (name == "wuxie" || !lib.inpile.includes(name) || player.hasSkill("mpsixiao_used", null, null, false)) return false; + const target = player.storage.mpsixiao_use; + const cards = target.getCards("h"); + for (var i of cards) { + if (get.name(i, target) == name) return true; + } + return false; + }, + enable: ["chooseToUse", "chooseToRespond"], + filter(event, player) { + const target = player.storage.mpsixiao_use; + const cards = target.getCards("h"); + if (player.hasSkill("mpsixiao_used", null, null, false)) return false; + return cards.some(i => + event.filterCard( + { + name: get.name(i, target), + nature: get.nature(i, target), + isCard: true, + }, + player, + event + ) + ); + }, + chooseButton: { + dialog(event, player) { + const target = player.storage.mpsixiao_use; + const cards = target.getCards("h"); + return ui.create.dialog("死孝", cards); + }, + filter(button, player) { + const evt = _status.event.getParent(); + const target = player.storage.mpsixiao_use; + return evt.filterCard( + { + name: get.name(button.link, target), + nature: get.nature(button.link, target), + isCard: true, + }, + player, + evt + ); + }, + check(button) { + const player = get.player(); + const evt = _status.event.getParent(); + if (evt.dying) return get.attitude(player, evt.dying); + if (_status.event.getParent().type != "phase") return 1; + return player.getUseValue(get.autoViewAs(button.link), null, true); + }, + backup(links, player) { + const target = player.storage.mpsixiao_use; + return { + viewAs: { + name: get.name(links[0], target), + nature: get.nature(links[0], target), + isCard: true, + }, + card: links[0], + filterCard: () => false, + selectCard: -1, + log: false, + async precontent(event, trigger, player) { + const card = lib.skill.mpsixiao_use_backup.card, + target = player.storage.mpsixiao_use; + event.result.card = card; + event.result.cards = [card]; + player.addTempSkill("mpsixiao_used"); + target + .when({ global: ["useCard", "respond"] }) + .filter(evt => evt.player == player && evt.skill == "mpsixiao_use_backup") + .then(() => { + player.draw(); + }); + }, + }; + }, + ai: { + hasSha: true, + hasShan: true, + skillTagFilter(player, tag) { + const name = "s" + tag.slice(4); + return lib.skill.mpsixiao_use.hiddenCard(player, name); + }, + }, + }, + ai: { + order: 8, + result: { + player: 1, + }, + }, + }, + used: {}, + }, + }, + //小程序刘伶 + mpjiusong: { + audio: 2, + enable: "chooseToUse", + trigger: { global: "useCard" }, + filterCard: function (card) { + return get.type2(card) == "trick"; + }, + viewAs: { name: "jiu" }, + position: "hs", + viewAsFilter: function (player) { + return player.hasCard(card => get.type2(card) == "trick", "hs"); + }, + check: function (card) { + if (get.itemtype(card) !== "card") return true; + if (get.event().type == "dying") return 1 / Math.max(0.1, get.value(card)); + return 4 - get.value(card); + }, + prompt: "将一张锦囊牌当【酒】使用", + filter: function (event, player) { + if (event.name == "chooseToUse") return player.hasCard(card => get.type2(card) == "trick", "hs"); + return event.card.name == "jiu" && player.countMark("mpjiusong") < 3; + }, + forced: true, + locked: false, + content: function () { + player.addMark("mpjiusong"); + }, + marktext: "醉", + intro: { + name: "醉(酒颂/酕醄)", + name2: "醉", + content: "mark", + }, + }, + mpmaotao: { + audio: 2, + trigger: { global: "useCardToPlayer" }, + filter: function (event, player) { + if (event.targets.length != 1 || !event.isFirstTarget) return false; + if (!["basic", "trick"].includes(get.type(event.card))) return false; + return event.player != player && player.countMark("mpjiusong"); + }, + prompt2: function (event, player) { + let list; + if (get.type(event.card) != "delay") + list = game.filterPlayer(current => { + return lib.filter.targetEnabled2(event.card, event.player, current); + }); + else list = game.filterPlayer(current => current.canAddJudge(event.card)); + const gainText = `${list.length > 1 && !player.storage.mpmaotao_gained ? `若新目标与原目标相同,你` : ""}${!player.storage.mpmaotao_gained ? "获得牌堆中的一张锦囊牌。" : ""}`; + return `移去1枚“醉”${list.length > 1 ? `,令${get.translation(event.card)}目标改为${get.translation(list)}中的一名随机角色` : ""}。${gainText}`; + }, + check: function (event, player) { + const eff = get.effect(event.target, event.card, player, player); + let list; + if (get.type(event.card) != "delay") + list = game.filterPlayer(current => { + return lib.filter.targetEnabled2(event.card, event.player, current); + }); + else list = game.filterPlayer(current => current.canAddJudge(event.card)); + let list2 = list.filter(current => get.effect(current, event.card, player, player) > eff); + let list3 = list.filter(current => get.effect(current, event.card, player, player) > 0); + return list2.length >= list.length / 2 || (player.countMark("mpjiusong") >= 2 && list3.length >= list.length / 2); + }, + content: function () { + player.removeMark("mpjiusong", 1); + var list, + oriTarget = trigger.target; + trigger.targets.remove(oriTarget); + trigger.getParent().triggeredTargets1.remove(oriTarget); + trigger.untrigger(); + game.delayx(); + if (get.type(trigger.card) != "delay") + list = game.filterPlayer(current => { + return lib.filter.targetEnabled2(trigger.card, trigger.player, current); + }); + else list = game.filterPlayer(current => current.canAddJudge(trigger.card)); + if (list.length) target = list.randomGet(); + trigger.targets.push(target); + trigger.player.line(target, "thunder"); + game.log(trigger.card, "的目标被改为", target); + if (target == oriTarget && !player.storage.mpmaotao_gained) { + var card = get.cardPile2(card => get.type2(card) == "trick"); + if (card) { + if (!player.storage.mpmaotao_gained) { + player.when({ global: "phaseAfter" }).then(() => { + delete player.storage.mpmaotao_gained; + }); + player.storage.mpmaotao_gained = true; + } + player.gain(card, "gain2"); + } else { + // player.chat('没酒了!'); + // game.log('但是牌堆中已经没有','#y酒','了!'); + player.chat("没牌了!"); + game.log("但是牌堆中已经没有", "#y锦囊牌", "了!"); + } + } + }, + ai: { + combo: "mpjiusong", + }, + }, + mpbishi: { + audio: 2, + forced: true, + trigger: { global: "useCard1" }, + filter: function (event, player) { + if (get.type2(event.card) != "trick" || !get.tag(event.card, "damage")) return false; + if (!lib.skill.xunshi.isXunshi(event.card)) return false; + const targets = event.targets.slice(); + targets.remove(event.player); + return targets.length == game.countPlayer() - 2; + }, + content: function* () {}, + mod: { + targetEnabled: function (card) { + if (get.type2(card) == "trick" && get.tag(card, "damage") > 0) return false; + }, + }, + }, +}; + +export default skills; diff --git a/character/newjiang/sort.js b/character/newjiang/sort.js new file mode 100644 index 0000000000..9f130877e5 --- /dev/null +++ b/character/newjiang/sort.js @@ -0,0 +1,15 @@ +const characterSort = { + yijiang_2020: ["yj_zhanghe", "yj_zhangliao", "yj_xuhuang", "yj_ganning"], + yijiang_2022: ["yj_huangzhong", "lukai", "kebineng", "zhugeshang", "liwan", "wuanguo", "hanlong", "yj_sufei", "yj_qiaozhou"], + yijiang_2023: ["mp_liuling", "yj_weiyan", "xiahoumao", "chenshi", "sunli", "feiyao"], + yijiang_2024: ["mp_wangrong", "yj_zhoubuyi", "linghuyu", "yj_simafu", "yj_xuangongzhu", "xukun", "yj_majun", "xunyuxunyou", "yj_sb_guojia"], +}; + +const characterSortTranslate = { + yijiang_2020: "一将成名2020", + yijiang_2022: "一将成名2022", + yijiang_2023: "一将成名2023", + yijiang_2024: "一将成名2024", +}; + +export { characterSort, characterSortTranslate }; diff --git a/character/newjiang/translate.js b/character/newjiang/translate.js new file mode 100644 index 0000000000..9daac685c0 --- /dev/null +++ b/character/newjiang/translate.js @@ -0,0 +1,157 @@ +const translates = { + yj_zhanghe: "☆张郃", + yj_zhanghe_prefix: "☆", + yj_zhangliao: "☆张辽", + yj_zhangliao_prefix: "☆", + yj_xuhuang: "☆徐晃", + yj_xuhuang_prefix: "☆", + yj_ganning: "☆甘宁", + yj_ganning_prefix: "☆", + xhzhiyan: "治严", + xhzhiyan_info: "出牌阶段,若你的手牌数不等于体力上限,则你可以将手牌摸至/弃至手牌上限,然后本回合不能对其他角色使用牌/可以将弃置的一张牌交给一名其他角色。", + zhilve: "知略", + zhilve_info: "锁定技,准备阶段,你选择一项:1.移动场上装备区的一张牌并失去1点体力。2.移动场上判定区的一张牌并令本回合手牌上限-1。3.本回合摸牌阶段多摸一张牌且使用的第一张【杀】无距离限制且不计入次数限制。", + xinzhilve: "知略", + xinzhilve_backup: "知略", + xinzhilve_mark: "知略", + xinzhilve_info: "出牌阶段限一次,你可以失去1点体力并选择一项:1.移动场上的一张牌;2.视为使用一张无距离限制且不计入次数限制的【杀】并摸一张牌。然后你本回合的手牌上限+1。", + xinxhzhiyan: "治严", + xinxhzhiyan_false: "治严", + xinxhzhiyan_info: "出牌阶段每项各限一次,若你的手牌数:大于体力值,则你可以将X张手牌交给一名其他角色(X为你的手牌数与体力值之差);小于体力上限,则你可以摸X张牌且本阶段内不能再对其他角色使用牌。(X为你的手牌数与体力上限之差)", + weifeng: "威风", + weifeng2: "威风", + weifeng3: "威风", + weifeng_info: "锁定技,当你于出牌阶段内使用第一张伤害性基本牌或普通锦囊牌后,你令此牌的一名没有“惧”的其他目标角色获得一枚名称为此牌牌名的“惧”。有“惧”的角色受到伤害时,其移去“惧”,然后若造成伤害的牌名称和“惧”:相同,此伤害+1;不同,你获得该角色的一张牌。准备阶段开始时或你死亡时,你移去场上的所有“惧”。", + gnjinfan: "锦帆", + gnjinfan_gain: "锦帆", + gnjinfan_info: "弃牌阶段开始时,你可将任意张手牌置于武将牌上,称为“铃”(每种花色的“铃”限一张)。你可以如手牌般使用或打出“铃”。当有“铃”移动到处理区后,你从牌堆中获得与“铃”花色相同的一张牌。", + gnsheque: "射却", + gnsheque_info: "一名其他角色的准备阶段开始时,若其装备区内有牌,则你可以对其使用一张【杀】(无距离关系的限制且无视防具)。", + yj_huangzhong: "☆黄忠", + yj_huangzhong_prefix: "☆", + spshidi: "势敌", + spshidi_info: "转换技,锁定技。①准备阶段/结束阶段开始时,若你发动此分支的累计次数为奇数/偶数,则你获得一个“☯”。②若你的“☯”数为偶数,则你至其他角色的距离-1,且你使用的黑色【杀】不可被响应。③若你的“☯”数为奇数,则其他角色至你的距离+1,且你不可响应红色【杀】。", + spyishi: "义释", + spyishi_info: "当你对装备区有牌的其他角色造成伤害时,你可令此伤害-1,然后获得其装备区内的一张牌。", + spqishe: "骑射", + spqishe_info: "你可以将一张装备牌当做【酒】使用。你的手牌上限+X(X为你装备区内的牌数)。", + yj_weiyan: "☆魏延", + yj_weiyan_prefix: "☆", + mbguli: "孤厉", + mbguli_info: "出牌阶段限一次。你可以将所有手牌当做一张无视防具的【杀】使用。此牌结算结束后,若此牌造成过伤害,你可以失去1点体力并将手牌摸至X张(X为你的体力上限)。", + mbaosi: "骜肆", + mbaosi_info: "锁定技。当你于出牌阶段对一名攻击范围内的角色造成伤害后,你于此阶段对其使用牌无次数限制。", + yj_zhoubuyi: "☆周不疑", + yj_zhoubuyi_prefix: "☆", + mbhuiyao: "慧夭", + mbhuiyao_info: "出牌阶段限一次。你可以受到1点无来源伤害,然后你选择一名其他角色,令其视为对另一名角色造成过1点伤害。", + mbquesong: "雀颂", + mbquesong_info: "一名角色的结束阶段,若你于本回合受到过伤害,你可以令一名角色选择一项:1.摸X张牌并复原武将牌(X为3,若其装备区非宝物牌牌数不小于三张则X为2);2.回复1点体力。", + lukai: "陆凯", + lukai_spade: "♠", + lukai_spade_bg: "♠️", + lukai_heart: "♥", + lukai_heart_bg: "♥️", + lukai_club: "♣", + lukai_club_bg: "♣", + lukai_diamond: "♦", + lukai_diamond_bg: "♦️️", + lkbushi: "卜筮", + lkbushi_info: "①你使用♠牌无次数限制。②当你使用或打出♥牌后,你摸一张牌。③当你成为♣牌的目标后,你可以弃置一张牌,令此牌对你无效。④结束阶段开始时,你从牌堆或弃牌堆获得一张♦牌。⑤准备阶段开始时,你可调整此技能中四种花色的对应顺序。", + lkzhongzhuang: "忠壮", + lkzhongzhuang_info: "锁定技。①当你因执行【杀】的效果而造成伤害时,若你的攻击范围大于3,则此伤害+1。②当一名角色受到你因执行【杀】的效果而造成的伤害时,若你的攻击范围小于3,则此伤害改为1。", + kebineng: "轲比能", + kousheng: "寇旌", + kousheng_info: "①出牌阶段开始时,你可以选择任意张手牌,这些牌称为“寇旌”直到回合结束。②你的“寇旌”均视为【杀】且无次数限制。③当你因执行对应实体牌包含“寇旌”的【杀】的效果而造成伤害后,你展示所有“寇旌”牌,然后目标角色可以用所有手牌交换这些牌。", + zhugeshang: "诸葛尚", + sangu: "三顾", + sangu_info: "结束阶段,你可以选择至多三个{【杀】或不为notarget或singleCard的普通锦囊牌}中的牌名,然后令一名其他角色记录这些牌名。该角色的下个出牌阶段开始时,其的手牌于其需要使用牌时均视为其记录中的第一张牌直到此阶段结束,且当其使用或打出有对应实体牌的牌时,移除这些牌中的第一张牌。若你以此法选择过的牌名均为你本回合内使用过的牌名,则防止你因其以此法使用牌造成的伤害。", + yizu: "轶祖", + yizu_info: "锁定技。每回合限一次,当你成为【杀】或【决斗】的目标后,若你的体力值不大于使用者的体力值,则你回复1点体力。", + liwan: "李婉", + liandui: "联对", + liandui_info: "①当你使用牌时,若本局游戏内上一张被使用的牌的使用者不为你,你可以令其摸两张牌。②其他角色使用牌时,若本局游戏内上一张被使用的牌的使用者为你,其可以令你摸两张牌。", + biejun: "别君", + biejun_info: "①其他角色的出牌阶段限一次。其可以将一张手牌交给你。②每回合限一次。当你受到伤害时,若你手牌中没有本回合因〖别君①〗得到的牌,你可以翻面并防止此伤害。", + yj_sufei: "苏飞", + shuojian: "数谏", + shuojian_info: "出牌阶段限三次。你可以交给一名其他角色一张牌,其选择一项:1.令你摸X张牌并弃置X-1张牌;2.视为使用X张【过河拆桥】,然后此技能本回合失效(X为此技能本阶段剩余发动次数+1)。", + yj_qiaozhou: "谯周", + shiming: "识命", + shiming_info: "每轮限一次。一名角色的摸牌阶段,你可以观看牌堆顶的三张牌,并可以将其中一张置于牌堆底。然后该角色可以改为对自己造成1点伤害,然后从牌堆底摸三张牌。", + jiangxi: "将息", + jiangxi_info: "一名角色的回合结束时,若一号位于此回合内进入过濒死状态或未受到过伤害,你可以重置〖识命〗并摸一张牌;若所有角色均未受到过伤害,你可以与当前回合角色各摸一张牌。", + hanlong: "韩龙", + duwang: "独往", + duwang_info: "锁定技。①游戏开始时,你从牌堆顶将五张不为【杀】的牌置于武将牌上,称为“刺”。②若你有牌名不为【杀】“刺”,你至其他角色或其他角色至你的距离+1。", + cibei: "刺北", + cibei_info: "①当一名角色使用【杀】造成伤害且此牌对应的实体牌进入弃牌堆后,你可以将一张不为【杀】的“刺”置入弃牌堆,并将这些牌置入“刺”,然后弃置一名角色区域里的一张牌。②一名角色的回合结束时,若你的“刺”均为【杀】,你获得所有“刺”,且这些牌不能被弃置,不计入手牌上限,且当你使用对应实体牌包含这些牌的牌时无次数和距离限制。", + wuanguo: "武安国", + diezhang: "叠嶂", + diezhang_info: "转换技。①出牌阶段,你使用【杀】的次数上限+1。②阴:当你使用牌被其他角色抵消后,你可以弃置一张牌,视为对其使用X张【杀】;阳:当其他角色使用牌被你抵消后,你可以摸X张牌,视为对其使用一张【杀】(X为1)。", + duanwan: "断腕", + duanwan_info: "限定技。当你处于濒死状态时,你可以将体力回复至2点,然后删除〖叠嶂①〗和当前转换技状态的〖叠嶂②〗分支,并将〖叠嶂〗修改为“每回合限一次”且将X修改为2。", + dcduliang: "督粮", + dcduliang2: "督粮", + dcduliang_info: "出牌阶段限一次。你可以获得一名其他角色的一张牌,然后选择一项:1.你观看牌堆顶的两张牌,然后令其获得其中的一或两张基本牌;2.令其于下回合的摸牌阶段额外摸一张牌。", + sunli: "孙礼", + kangli: "伉厉", + kangli_info: "当你造成或受到伤害后,你摸两张牌。然后你下次造成伤害时弃置这些牌。", + xiahoumao: "夏侯楙", + tongwei: "统围", + tongwei_info: "出牌阶段限一次。你可以重铸两张牌并指定一名其他角色,当其使用的下一张牌结算结束后,若此牌点数在你上次以此法重铸的牌的点数之间,你视为对其使用一张【杀】或【过河拆桥】。", + cuguo: "蹙国", + cuguo_info: "锁定技。当你于一回合使用牌首次被抵消后,你弃置一张牌,视为对此牌的目标角色使用一张该被抵消的牌。此牌结算结束后,若此牌被抵消,你失去1点体力。", + chenshi: "陈式", + qingbei: "擎北", + qingbei_info: "一轮游戏开始时,你可以选择任意种花色,你不能于本轮内使用这些花色的牌。然后当你于本轮使用一张有花色的牌结算结束后,你摸等同于你上一次〖擎北〗选择过的花色数的牌。", + feiyao: "费曜", + zhenfeng: "镇锋", + zhenfeng_info: "每回合限一次。当其他角色于其回合内使用牌时,若其手牌数不大于其体力值,你可以猜测其手牌中与此牌类别相同的牌数。若你猜对,你摸X张牌并视为对其使用一张【杀】(X为你连续猜对的次数且至多为5);若你猜错且差值大于1,其视为对你使用一张【杀】。", + linghuyu: "令狐愚", + yj_simafu: "司马孚", + yj_xuangongzhu: "宣公主", + xukun: "徐琨", + xvzhi: "蓄志", + xvzhi_info: "出牌阶段限一次,你可令两名角色各选择任意张手牌并交换这些牌,然后获得牌数较少的角色视为使用无视距离的【杀】;若获得牌数相等,你摸两张牌且可以对此阶段未以此法选择过的角色再发动一次〖蓄志〗。", + beiyu: "备预", + beiyu_info: "出牌阶段限一次,你可将手牌摸至体力上限,然后你将一种花色的所有手牌置于牌堆底。", + duchi: "督持", + duchi_info: "每回合限一次,当你成为其他角色使用牌的目标后,你可从牌堆底摸一张牌并展示所有手牌,若颜色均相同,则此牌对你无效。", + yjqimei: "齐眉", + yjqimei_info: "出牌阶段限一次,你可以选择一名其他角色,你与其各摸两张牌并弃置两张牌,然后你根据你与其弃置牌的花色总数执行以下效果:1、你依次使用这些弃置的牌中可以使用的牌;2、你与其复原武将牌;3、你与其横置武将牌;4、你与其各摸一张牌,然后你修改〖齐眉〗为“出牌阶段限两次”直到回合结束。", + yjzhuiji: "追姬", + yjzhuiji_info: "当你死亡时,你可以令一名角色从牌堆和弃牌堆中的随机使用任意装备牌直至其没有空置的装备栏。若如此做,当其失去以此法使用的装备牌后,其废除对应的装备栏。", + fazhu: "筏铸", + fazhu_info: "准备阶段,你可以重铸你的区域内任意张非伤害牌,然后将以此法获得的牌交给至多等量名角色各一张,这些角色可以依次使用一张无距离限制的【杀】。", + xunyuxunyou: "荀彧荀攸", + zhinang: "智囊", + zhinang_info: "当你使用锦囊牌后,你可以获得一个技能台词包含“谋”的技能;当你使用装备牌后,你可以获得一个技能名包含“谋”的技能。", + gouzhu: "苟渚", + gouzhu_info: "你发动技能后,若此技能为:锁定技,回复1点体力;觉醒技,获得一张基本牌;限定技,对随机一名其他角色造成1点伤害;转换技,手牌上限+1;主公技,增加1点体力上限。", + yj_sb_guojia: "谋郭嘉", + yj_sb_guojia_prefix: "谋", + xianmou: "先谋", + xianmou_info: "转换技。①游戏开始时,你可以转换此技能状态;②你失去过牌的回合结束时,你可以:阳,观看牌堆顶五张牌并获得至多X张牌,若未获得X张牌则获得〖遗计〗直到再发动此技能;阴,观看一名角色手牌并弃置其中至多X张牌,若弃置X张牌则你进行一次【闪电】判定。(X为你本回合失去牌数)", + lunshi: "论势", + lunshi_info: "一名角色对其以外的角色使用普通锦囊牌的结算中,若你手牌中两种颜色的牌数量相同,你可将一张手牌当作不可被响应的【无懈可击】使用。", + mp_liuling: "刘伶", + mpjiusong: "酒颂", + mpjiusong_info: "①你可以将一张锦囊牌当【酒】使用。②当一名角色使用【酒】时,你获得1枚“醉”标记(“醉”数至多为3)。", + mpmaotao: "酕醄", + mpmaotao_info: "当其他角色使用基本牌或普通锦囊牌指定唯一目标时,你可以移去1枚“醉”,令此牌的目标改为随机一名合法角色(无距离限制)。若目标角色与原目标相同且你本回合未以此法获得过牌,你从牌堆中随机获得一张锦囊牌。", + mpbishi: "避世", + mpbishi_info: "锁定技。你不能成为伤害类锦囊牌的目标。", + mp_wangrong: "王戎", + mpjianlin: "俭吝", + mpjianlin_info: "每回合结束后,若本回合你有基本牌因使用、打出或弃置而进入弃牌堆,则你可以选择其中一张牌获得之。", + mpsixiao: "死孝", + mpsixiao_info: "锁定技,游戏开始时,你选择一名其他角色。每回合限一次,当该角色需要使用或打出除【无懈可击】外的牌时,其可以观看你的手牌并可以使用或打出其中一张牌,然后你摸一张牌。", + yj_majun: "马钧", + yjgongqiao: "工巧", + yjgongqiao_info: "①出牌阶段限一次。你可以将一张手牌置于你的任意装备栏内(可替换原装备牌)。②若你装备区内的实体牌有:⒈基本牌,当你使用基本牌时,你令此牌的牌面数值+1;⒉锦囊牌,当你于一回合内首次使用一种类型的牌后,你摸一张牌;⒊装备牌,你的手牌上限+3。", + yjjingyi: "精益", + yjjingyi_info: "锁定技。当有实体牌进入你的装备区后,你摸X张牌,然后弃置两张牌(X为你装备区内实体牌的数量)。", +}; + +export default translates; diff --git a/character/newjiang/voices.js b/character/newjiang/voices.js new file mode 100644 index 0000000000..73f36c19ac --- /dev/null +++ b/character/newjiang/voices.js @@ -0,0 +1,88 @@ +export default { + "#zhenfeng1": "河西诸贼作乱,吾当驱万里之远。", + "#zhenfeng2": "可折诸葛之锋而御者,独我其谁。", + "#feiyao:die": "姜维,你果然是蜀军内应!", + // 击、逆、泰、每,懂? + "#fazhu1": "击风雨于共济,逆流亦溯千帆。", + "#fazhu2": "泰山轻于大义,每思志士、何惧临渊。", + "#fazhu3": "大江潮起,伐苇成舟,载江南春风。", + "#xukun:die": "何处射来的流矢?", + "#kangli1": "地界纷争皋陶难断,然图藏天府,坐上可明。", + "#kangli2": "正至歉岁,难征百姓于役,望陛下明鉴。", + "#sunli:die": "国无矩不立,何谓之方圆?", + "#tongwei1": "集关西诸路大军,必雪当年长坂坡之耻。", + "#tongwei2": "手织天网十万尺,欲擒飞龙落彀中。", + "#cuguo1": "身担父命,怎可蜷于宫阙。", + "#cuguo2": "体承国运,岂能缩居朝堂。", + "#xiahoumao:die": "一将无能,徒累死三军……", + "#qingbei1": "待追上那司马懿,定教他没好果子吃!", + "#qingbei2": "身若不周,吾一人可作擎北之柱。", + "#chenshi:die": "丞相、丞相!是魏延指使我的!", + "#diezhang1": "某家这大锤,舞起来那叫一个万夫莫敌。", + "#diezhang2": "贼吕布何在?某家来取汝性命了!", + "#duanwan1": "好你个吕奉先,竟敢卸我膀子!", + "#duanwan2": "汝这匹夫,为何往手腕上招呼?", + "#wuanguo:die": "吕奉先,你给某家等着!", + "#duwang1": "此去,欲诛敌莽、杀单于。", + "#duwang2": "风萧萧兮易水寒,壮士一去兮不复还!", + "#cibei1": "匹夫一怒,流血二人,天下缟素。", + "#cibei2": "我欲效专诸、聂政之旧事,逐天狼于西北。", + "#hanlong:die": "杀轲比能者,韩龙也!", + "#shiming1": "今天命在北,我等已尽人事。", + "#shiming2": "益州国疲民敝,非人力可续之。", + "#jiangxi1": "典午忽兮,月酉没兮。", + "#jiangxi2": "周慕孔子遗风,可与刘、扬同轨。", + "#yj_qiaozhou:die": "炎汉百年之业,吾一言毁之……", + "#shuojian1": "我数荐卿而祖不用,其之失也。", + "#shuojian2": "兴霸乃当世豪杰,何患无爵。", + "#yj_sufei:die": "兴霸何在?吾命休矣……", + "#liandui1": "以句相联,抒离散之苦。", + "#liandui2": "以诗相对,颂哀怨之情。", + "#biejun1": "彼岸荼蘼远,落寞北风凉。", + "#biejun2": "此去经年,不知何时能归?", + "#liwan:die": "生不能同寝,死亦难同穴……", + "#sangu1": "思报君恩,尽父子之忠。", + "#sangu2": "欲酬三顾,竭三代之力。", + "#yizu1": "仿祖父行事,可阻敌袭。", + "#yizu2": "习先人故智,可御寇侵。", + "#zhugeshang:die": "父子荷国重恩,当尽忠以报!", + "#kousheng1": "驰马掠野,塞外称雄。", + "#kousheng2": "控弦十万,纵横漠南。", + "#kebineng:die": "草原雄鹰,折翼于此……", + "#lkbushi1": "论演玄意,以筮辄验。", + "#lkbushi2": "手不释书,好研经卷。", + "#lkzhongzhuang1": "秽尘天听,卿有不测之祸!", + "#lkzhongzhuang2": "倾乱国政,安得寿终正寝?", + "#lukai:die": "不听忠言,国将亡矣……", + "#mbhuiyao1": "幸有仓舒为伴,吾不至居高寡寒。", + "#mbhuiyao2": "通悟而无笃学之念,则必盈天下之叹也。", + "#mbquesong1": "承白雀之瑞,显周公之德。", + "#mbquesong2": "挽汉室于危亡,继光武之中兴。", + "#yj_zhoubuyi:die": "慧童亡,天下伤……", + "#mbguli1": "今若弑此昏聩主,纵蒙恶名又如何?", + "#mbguli2": "韩玄少谋多忌,吾今当诛之!", + "#mbaosi1": "凶慢骜肆,天生狂骨!", + "#mbaosi2": "暴戾恣睢,傲视诸雄!", + "#yj_weiyan:die": "使君为何弃我而去……呃啊!", + "#spshidi1": "诈败以射之,其必死矣!", + "#spshidi2": "呃啊,中其拖刀计矣!", + "#spyishi1": "昨日释忠之恩,今吾虚射以报。", + "#spyishi2": "君刀不砍头颅,吾箭只射盔缨。", + "#spqishe1": "诱敌之计已成,吾且拈弓搭箭!", + "#spqishe2": "关羽即至吊桥,既已控弦,如何是好?", + "#yj_huangzhong:die": "关云长义释黄某,吾又安忍射之……", + "#weifeng1": "广散惧义,尽泄敌之斗志。", + "#weifeng2": "哼哼,若尔等惧我,自当卷甲以降!", + "#yj_zhangliao:die": "惑于女子而尽失战机,庸主误我啊……", + "#zhilve1": "将者,上不治天,下不治地,中不治人。", + "#zhilve2": "料敌之计,明敌之意,因况反制。", + "#yj_zhanghe:die": "若非小人作梗,何至官渡之败……", + "#xhzhiyan1": "治军严谨,方得精锐之师。", + "#xhzhiyan2": "精兵当严于律己,束身自修。", + "#yj_xuhuang:die": "唉,明主未遇,大功未成……", + "#gnjinfan1": "扬锦帆,劫四方,快意逍遥!", + "#gnjinfan2": "铃声所至之处,再无安宁!", + "#gnsheque1": "看我此箭,取那轻舟冒进之人性命!", + "#gnsheque2": "纵有劲甲良盾,也难挡我神射之威!", + "#yj_ganning:die": "铜铃声……怕是听不到了……", +}; diff --git a/character/offline/card.js b/character/offline/card.js index d41c2e9c19..cded72ea9d 100644 --- a/character/offline/card.js +++ b/character/offline/card.js @@ -16,5 +16,220 @@ const cards = { }, }, }, + jingxiangshengshi: { + audio: true, + fullskin: true, + derivation: "jx_shen_liubiao", + type: "trick", + enable: true, + filterTarget: lib.filter.notMe, + selectTarget() { + return game.countGroup(); + }, + complexTarget: true, + contentBefore() { + if (!targets.length) { + event.finish(); + return; + } + var num = game.countPlayer(), cards = get.cards(num); + game.cardsGotoOrdering(cards).relatedEvent = event.getParent(); + var dialog = ui.create.dialog("荆襄盛世", cards, true); + _status.dieClose.push(dialog); + dialog.videoId = lib.status.videoId++; + game.addVideo("cardDialog", null, ["荆襄盛世", get.cardsInfo(cards), dialog.videoId]); + event.getParent().preResult = dialog.videoId; + game.broadcast( + function (cards, id) { + var dialog = ui.create.dialog("荆襄盛世", cards, true); + _status.dieClose.push(dialog); + dialog.videoId = id; + }, + cards, + dialog.videoId + ); + game.log(event.card, "亮出了", cards); + }, + content() { + "step 0"; + for (var i = 0; i < ui.dialogs.length; i++) { + if (ui.dialogs[i].videoId == event.preResult) { + event.dialog = ui.dialogs[i]; + break; + } + } + if (!event.dialog || event.dialog.buttons.length == 0) { + event.finish(); + return; + } + if (event.dialog.buttons.length > 1) { + var next = target.chooseButton(true); + next.set("ai", button => { + let player = _status.event.player, card = button.link, val = get.value(card, player); + if (get.tag(card, "recover")) { + val += game.countPlayer(target => { + return target.hp < 2 && get.attitude(player, target) > 0 && lib.filter.cardSavable(card, player, target); + }); + if (player.hp <= 2 && game.checkMod(card, player, "unchanged", "cardEnabled2", player)) val *= 2; + } + return val; + }); + next.set("dialog", event.preResult); + next.set("closeDialog", false); + next.set("dialogdisplay", true); + } else { + event.directButton = event.dialog.buttons[0]; + } + "step 1"; + var dialog = event.dialog; + var card; + if (event.directButton) { + card = event.directButton.link; + } else { + for (var i of dialog.buttons) { + if (i.link == result.links[0]) { + card = i.link; + break; + } + } + if (!card) card = event.dialog.buttons[0].link; + } + var button; + for (var i = 0; i < dialog.buttons.length; i++) { + if (dialog.buttons[i].link == card) { + button = dialog.buttons[i]; + button.querySelector(".info").innerHTML = (function (target) { + if (target._tempTranslate) return target._tempTranslate; + var name = target.name; + if (lib.translate[name + "_ab"]) return lib.translate[name + "_ab"]; + return get.translation(name); + })(target); + dialog.buttons.remove(button); + break; + } + } + var capt = get.translation(target) + "选择了" + get.translation(button.link); + if (card) { + target.gain(card, "visible"); + target.$gain2(card); + game.broadcast( + function (card, id, name, capt) { + var dialog = get.idDialog(id); + if (dialog) { + dialog.content.firstChild.innerHTML = capt; + for (var i = 0; i < dialog.buttons.length; i++) { + if (dialog.buttons[i].link == card) { + dialog.buttons[i].querySelector(".info").innerHTML = name; + dialog.buttons.splice(i--, 1); + break; + } + } + } + }, + card, + dialog.videoId, + (function (target) { + if (target._tempTranslate) return target._tempTranslate; + var name = target.name; + if (lib.translate[name + "_ab"]) return lib.translate[name + "_ab"]; + return get.translation(name); + })(target), + capt + ); + } + dialog.content.firstChild.innerHTML = capt; + game.addVideo("dialogCapt", null, [dialog.videoId, dialog.content.firstChild.innerHTML]); + game.log(target, "选择了", button.link); + game.delay(); + }, + contentAfter() { + "step 0" + event.remained = []; + for (var i = 0; i < ui.dialogs.length; i++) { + if (ui.dialogs[i].videoId == event.preResult) { + var dialog = ui.dialogs[i]; + dialog.close(); + _status.dieClose.remove(dialog); + if (dialog.buttons.length) { + for (var i = 0; i < dialog.buttons.length; i++) { + event.remained.push(dialog.buttons[i].link); + } + } + break; + } + } + game.broadcast(function (id) { + var dialog = get.idDialog(id); + if (dialog) { + dialog.close(); + _status.dieClose.remove(dialog); + } + }, event.preResult); + game.addVideo("cardDialog", null, event.preResult); + "step 1" + if (event.remained.length) player.gain(event.remained, "gain2"); + }, + //ai简略,待补充 + ai: { + wuxie() { + if (Math.random() < 0.5) return 0; + }, + basic: { + order: 3, + useful: 0.5, + }, + result: { + player(player, target) { + return game.countPlayer() / game.countGroup() - 1; + }, + target(player, target) { + return 1.8 / Math.sqrt(1 + get.distance(player, target, "absolute")); + }, + }, + tag: { + draw: 1, + multitarget: 1, + }, + }, + }, + xingbian: { + audio: true, + fullskin: true, + derivation: "yj_tianchuan", + type: "equip", + skills: ["xingbian_skill"], + async content(event, trigger, player) { + if (!event.card.subtypes) { + const choices = []; + for (let i = 0; i <= 5; i++) { + if (player.hasEquipableSlot(i)) choices.push(`equip${i}`); + } + if (!choices.length) return; + const result = await player.chooseControl(choices) + .set("prompt", "请选择置入【刑鞭】的装备栏") + .set("ai", () => _status.event.controls.randomGet()) + .forResult(); + event.card.subtypes = [result.control]; + } + if ( + !event.card?.cards.some(card => { + return get.position(card, true) !== "o"; + }) + ) { + await event.target.equip(event.card); + } + }, + ai: { + equipValue(card, player) { + if (get.nameList(player).includes("yj_tianchuan")) { + return 5; + } + return 0; + }, + basic: { + equipValue: 5, + }, + }, + }, }; export default cards; diff --git a/character/offline/character.js b/character/offline/character.js index c95751774d..d85b662593 100644 --- a/character/offline/character.js +++ b/character/offline/character.js @@ -1,4 +1,67 @@ const characters = { + ty_anyingx: ["male", "qun", 4, ["tyzhuiling", "tyxihun", "tyxianqi", "tyfansheng"]], + ty_anying: ["male", "qun", 4 , ["tyliupo", "tyzhuiling", "tyxihun", "tyxianqi"]], + ty_wuque: ["male", "qun", 4 , ["tyansha", "tycangshen", "tyxiongren"]], + ty_yanque: ["male", "qun", 4 , ["tysiji", "tycangshen"]], + ty_wangque: ["male", "qun", 3 , ["tydaifa", "tycangshen"]], + ty_fanjiang: ["male", "wu", 4, ["tybianta", "tybenxiang", "tyxiezhan"]], + ty_zhangda: ["male", "wu", 4, ["tyxingsha", "tyxianshou", "tyxiezhan"]], + ty_liue: ["male", "wu", 5, ["tyxiyu"]], + ty_tanxiong: ["male", "wu", 4, ["tylengjian", "tysheju"]], + ty_buzhi: ["male", "wu", 3, ["tyhongde", "tydingpan"]], + ty_ganning: ["male", "wu", 4, ["tyqixi", "tyfenwei"]], + ty_luxun: ["male", "wu", 3, ["tyqianshou", "tytanlong", "tyxibei"]], + ty_shen_liubei: ["male", "shen", 6, ["tylongnu", "nzry_jieying", "tytaoyuan"], ["shu"]], + ty_shen_zhangfei: ["male", "shen", 4, ["tyshencai", "tyxunshi"], ["shu"]], + ty_shen_guanyu: ["male", "shen", 5, ["tywushen", "tywuhun"], ["shu"]], + ty_guanyinping: ["female", "shu", 3, ["xueji", "huxiao", "tywuji"]], + ty_shamoke: ["male", "shu", 4, ["gzjili", "tymanyong"]], + ty_guanxing: ["male", "shu", 4, ["tyconglong", "tyzhaowu"]], + ty_shicong: ["male", "shu", 4, ["tyjinzhong"]], + ty_wuban: ["male", "shu", 4, ["tyyoujun", "tyjicheng"], ["character:wuban", "clan:陈留吴氏"]], + ty_huangzhong: ["male", "shu", 4, ["xinliegong", "tyyizhuang"]], + ty_liaohua: ["male", "shu", 4, ["tydangxian", "tyfuli"]], + ty_fengxí: ["male", "shu", 4, ["tyqingkou"], ["character:tw_fengxí"]], + ty_zhangnan: ["male", "shu", 4 ,["tyfenwu"], ["character:tw_zhangnan"]], + ty_zhaorong: ["male", "shu", 4, ["tyyuantao"]], + ty_chengjix: ["male", "shu", 3, ["tyzhongen", "tyliebao"]], + ty_chenshi: ["male", "shu", 4, ["tyzhuan"]], + ty_liubei: ["male", "shu", 4, ["tyqingshi", "tyyilin", "tychengming"]], + ty_sunquan: ["male", "shu", 3, ["tyfuhan", "tychende", "tywansu"]], + ty_guanyu: ["male", "shu", 5, ["tywusheng", "tychengshi", "tyfuwei"]], + jd_sb_xuhuang: ["male", "wei", 4, ["jdsbduanliang", "sbshipo"], ["character:sb_xuhuang", "die:sb_xuhuang"]], + jd_jin_wangyuanji: ["female", "jin", 3, ["jdshiren", "jdyanxi"], ["hiddenSkill", "character:jin_wangyuanji", "die:jin_wangyuanji"]], + jd_ol_huaxin: ["male", "wei", 3, ["jdcaozhao", "olxibing"], ["character:ol_huaxin", "die:ol_huaxin"]], + jd_sp_yangwan: ["female", "qun", 3, ["jdmingxuan", "spxianchou"], ["character:sp_yangwan", "die:sp_yangwan"]], + jd_sb_huangyueying: ["female", "shu", 3, ["jdjizhi", "jdqicai"], ["character:sb_huangyueying", "die:sb_huangyueying"]], + jd_sb_zhaoyun: ["male", "shu", 4, ["jdlongdan", "sbjizhu"], ["character:sb_zhaoyun", "die:sb_zhaoyun"]], + jd_sb_ganning: ["male", "wu", 4, ["jdqixi", "jdfenwei"], ["character:sb_ganning", "die:sb_ganning"]], + jd_sb_pangtong: ["male", "shu", 3, ["jdlianhuan", "oldniepan"], ["tempname:sb_pangtong", "character:sb_pangtong", "die:sb_pangtong"]], + jd_hanlong: ["male", "wei", 4, ["duwang", "jdcibei"], ["character:hanlong", "die:hanlong"]], + jd_jin_xiahouhui: ["female", "jin", 3, ["jdbaoqie", "jyishi", "shiduo"], ["hiddenSkill", "character:jin_xiahouhui", "die:jin_xiahouhui", "name:夏侯|徽"]], + jd_jin_simazhao: ["male", "jin", 3, ["tuishi", "choufa", "zhaoran", "chengwu"], ["zhu", "hiddenSkill", "character:jin_simazhao", "die:jin_simazhao", "name:司马|昭"]], + jd_sb_caocao: ["male", "wei", 4, ["jdjianxiong", "sbqingzheng", "sbhujia"], ["zhu", "character:sb_caocao", "die:sb_caocao"]], + jd_sb_sp_zhugeliang: ["male", "shu", 3, ["jdhuoji", "jdkanpo"], ["character:sb_sp_zhugeliang", "die:sb_sp_zhugeliang", "name:诸葛|亮"]], + jd_jin_simashi: ["male", "jin", "3/4", ["taoyin", "yimie", "jdtairan", "ruilve"], ["zhu", "hiddenSkill", "character:jin_simashi", "die:jin_simashi", "name:司马|师"]], + jd_sb_menghuo: ["male", "shu", 4, ["jdsbhuoshou", "jdsbzaiqi"], ["character:sb_menghuo", "die:sb_menghuo"]], + jd_sb_yuanshao: ["male", "qun", 4, ["jdsbluanji", "jdsbxueyi"], ["zhu", "character:sb_yuanshao", "die:sb_yuanshao"]], + jd_sb_yujin: ["male", "wei", 4, ["sbxiayuan", "jdsbjieyue"], ["character:sb_yujin", "die:sb_yujin"]], + jd_sb_sunshangxiang: ["female", "shu", 4, ["jdsbjieyin", "jdsbliangzhu", "sbxiaoji"], ["character:sb_sunshangxiang", "die:sb_sunshangxiang", "border:wu"]], + jd_sb_liubei: ["male", "shu", 4, ["sbrende", "jdsbzhangwu", "sbjijiang"], ["zhu", "character:sb_liubei", "die:sb_liubei"]], + jd_sb_fazheng: ["male", "shu", 3, ["jdsbxuanhuo", "jdsbenyuan"], ["character:sb_fazheng", "die:sb_fazheng"]], + jd_sb_zhangfei: ["male", "shu", 4, ["jdsbpaoxiao", "sbxieji"], ["character:sb_zhangfei", "die:sb_zhangfei"]], + jd_sb_sunquan: ["male", "wu", 4, ["jdsbzhiheng", "jdsbtongye", "jdsbjiuyuan"], ["zhu", "character:sb_sunquan", "die:sb_sunquan"]], + jd_sb_xiaoqiao: ["female", "wu", 3, ["jdsbtianxiang", "jdsbhongyan"], ["character:sb_xiaoqiao", "die:sb_xiaoqiao"]], + jd_sb_guanyu: ["male", "shu", 4, ["jdsbwusheng", "jdsbyijue"], ["character:sb_guanyu", "die:sb_guanyu"]], + jd_sb_jiangwei: ["male", "shu", 4, ["jdsbtiaoxin", "jdsbzhiji"], ["character:sb_jiangwei", "die:sb_jiangwei"]], + jd_sb_daqiao: ["female", "wu", 3, ["jdsbguose", "jdsbliuli"], ["character:sb_daqiao", "die:sb_daqiao"]], + jd_simayan: ["male", "jin", 3, ["jdjuqi", "jdfengtu", "jdtaishi"], ["zhu"]], + jx_sunjian: ["male", "wu", "4/5", ["gzyinghun", "wulie", "twpolu"]], + jx_zhouyu: ["male", "wu", 4, ["jxxiongzi", "jxzhanyan"]], + jx_guanyu: ["male", "shu", 4, ["jxwusheng", "jsrgguanjue", "nuzhan"]], + jx_shen_caoren: ["male", "shen", 4, ["jxjushou"], ["wei"]], + jx_shen_liubiao: ["male", "shen", 2, ["jxxiongju", "jxfujing", "jxyongrong"], ["qun"]], + yj_tianchuan: ["female", "qun", 3 ,["pshuying", "psqianjing", "psbianchi"]], yj_zhonghui: ["male", "wei", 4, ["psmouchuan", "pszizhong", "psjizun", "psqingsuan"], ["zhu"]], yj_ehuan: ["male", "qun", 5, ["psdiwan", "pssuiluan", "psconghan"], ["doublegroup:shu:qun"]], yj_zhouji: ["female", "wu", 3, ["psyanmou", "pszhanyan", "psyuhuo"], ["name:周|null"]], diff --git a/character/offline/characterReplace.js b/character/offline/characterReplace.js index 2092d9297b..8ba20b41a5 100644 --- a/character/offline/characterReplace.js +++ b/character/offline/characterReplace.js @@ -1,3 +1,9 @@ -const characterReplaces = {}; +const characterReplaces = { + ty_guanxing: ["ty_guanxing", "std_guanxing"], + ty_fengxí: ["ty_fengxí", "tw_fengxí"], + ty_zhangnan: ["ty_zhangnan", "tw_zhangnan"], + ty_chenshi: ["ty_chenshi", "chenshi"], + ty_anying: ["ty_anying", "ty_anyingx"], +}; export default characterReplaces; diff --git a/character/offline/dynamicTranslate.js b/character/offline/dynamicTranslate.js index cdee02b0ae..2892ab66f4 100644 --- a/character/offline/dynamicTranslate.js +++ b/character/offline/dynamicTranslate.js @@ -1,4 +1,40 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; -const dynamicTranslates = {}; +const dynamicTranslates = { + jdjuqi(player) { + if (player.storage.jdjuqi) return '转换技。阴:准备阶段,你摸三张牌;其他角色的准备阶段,其可以展示并交给你一张黑色手牌。阳:准备阶段,你令你本回合使用牌无次数限制且造成的伤害+1;其他角色的准备阶段,其可以展示并交给你一张红色手牌。'; + return '转换技。阴:准备阶段,你摸三张牌;其他角色的准备阶段,其可以展示并交给你一张黑色手牌。阳:准备阶段,你令你本回合使用牌无次数限制且造成的伤害+1;其他角色的准备阶段,其可以展示并交给你一张红色手牌。'; + }, + jdlongdan(player) { + return lib.translate["jdlongdan" + (player.hasSkill("sblongdan_mark", null, null, false) ? "x" : "") + "_info"]; + }, + tylongnu(player) { + let str="转换技,游戏开始时,你可以改变此转换技的状态。出牌阶段开始时,你可以摸一张牌并:"; + let yin="阴:失去1点体力,然后此阶段内你可以将红色手牌当无距离限制的火【杀】使用或打出;"; + if(player.hasSkill("tylongnu_yin")) yin=""+yin+""; + else if(!player.storage.tylongnu&&!player.hasSkill("tylongnu_yang")) yin=""+yin+""; + str+=yin; + let yang="阳:减少1点体力上限,然后此阶段内你可以将锦囊牌当无次数限制的雷【杀】使用或打出。"; + if(player.hasSkill("tylongnu_yang")) yang=""+yang+""; + else if(player.storage.tylongnu&&!player.hasSkill("tylongnu_yin")) yang=""+yang+""; + str+=yang; + return str; + }, + tyqianshou(player){ + let str="转换技,其他角色的回合开始时,若其体力值大于你,或其未处于横置状态,", + yin="阴:你可展示并交给其一张红色牌,本回合你不能使用手牌且你与其不能成为牌的目标;", + yang="阳:你可令其展示并交给你一张牌,若此牌不为黑色,你失去一点体力。"; + if(player.storage.tyqianshou) yang=""+yang+""; + else yin=""+yin+""; + return str+yin+yang; + }, + tyliupo(player){ + let str="转换技,回合开始时,你令本轮:", + yin="阴:所有角色不能使用【桃】;", + yang="阳:所有即将造成的伤害均视为体力流失。"; + if(player.storage.tyliupo) yang=""+yang+""; + else yin=""+yin+""; + return str+yin+yang; + }, +}; export default dynamicTranslates; diff --git a/character/offline/index.js b/character/offline/index.js index c32c9ea9fb..0dfa4186cb 100644 --- a/character/offline/index.js +++ b/character/offline/index.js @@ -15,7 +15,7 @@ game.import("character", function () { return { name: "offline", connect: true, - connectBanned: ["zhangliang"], + connectBanned: ["zhangliang", "yj_tianchuan"], character: { ...characters }, characterSort: { offline: characterSort, @@ -45,6 +45,9 @@ game.import("character", function () { ps_caozhi: "S2081", ps_shen_machao: "SX015", }, + characterSubstitute: { + jd_sb_sp_zhugeliang: [["sb_zhugeliang", []]], + }, dynamicTranslate: { ...dynamicTranslates }, characterIntro: { ...characterIntros }, characterReplace: { ...characterReplaces }, diff --git a/character/offline/intro.js b/character/offline/intro.js index b754e5e778..70d70698b1 100644 --- a/character/offline/intro.js +++ b/character/offline/intro.js @@ -1,4 +1,5 @@ const characterIntro = { + simayan: "晋武帝司马炎(236年—290年5月16日),字安世,河内郡温县(今河南省温县)人。中国西晋开国皇帝(266年2月8日—290年5月16日在位),晋宣帝司马懿之孙,晋文帝司马昭嫡长子,母为文明皇后王元姬。司马炎出身河内司马氏。曹魏末年,其祖司马懿、伯父司马师、父司马昭相继控制朝政。咸熙元年(264年),司马炎被立为晋王世子,翌年司马昭去世,他继任为相国,袭封晋王。同年十二月(266年2月),逼迫魏元帝曹奂禅让,即位为帝,建立西晋,改元泰始。即位之初,鉴于曹魏宗室屏藩无力以致孤立而亡,大封同姓诸王,又委任几位宗王统领重兵,出镇要地;重视法律的修订,其颁行的《晋律》是中国古代重要的法典。咸宁五年(279年),发兵南下,次年灭亡吴国,实现全国统一。其间颁行占田制、户调式,促进人口增长,使得经济社会呈现繁荣景象,史称“太康之治”。但随着天下安定,司马炎逐渐“怠于政术,耽于游宴”,使统治阶层中奢侈荒淫之风广泛蔓延。他执意立智力低下的司马衷为继承人,又在统一前后命诸王就国、废除州郡武备,为西晋短暂统治的覆亡埋下了深刻隐患。太熙元年(290年),司马炎在洛阳含章殿病逝,时年五十五岁,谥号武皇帝,庙号世祖,安葬于峻阳陵。司马炎在父祖开创的政治基础上,建立晋朝,渡江灭吴,完成了三国统一的历史伟业。由他制定的有晋一代的政治、经济、律法制度,还深刻影响了后世王朝的政治体制。", ehuan: "鄂焕,古典文学名著《三国演义》人物,为蜀将高定部将,身长九尺,面目狰狞,使一只方天戟,有万夫不当之勇。于孔明征朱褒、雍闿时粉墨登场,与魏延大战不分胜负,后中计被魏延、王平、张翼联手擒获,孔明以礼相待,成功离间高定与朱、雍二人。后高定派鄂焕斩朱褒、平雍闿,二人一起归蜀,鄂焕遂因其功而被封为牙门将。", zhouji: "三国杀集换式卡牌游戏《阵面对决》中的权倾系列卡牌。游卡桌游官方的三国时期女性角色,原型是周妃(又名周彻)。周瑜之女。", lvchang: "吕常(161—221年),荆州南阳博望(今河南省南阳市方城县博望镇)人,汉末至三国时期曹魏将领。吕常曾担任曹魏横海将军、章陵太守,为武猛都尉厉节中郎将裨将军,封关内侯。常以中勇,显名州司,试守雉长,执戈秉戎,慎守易,兵不顿于敌国,坠不侵于四邻,拜武猛都尉厉节中郎将裨将军,封关内侯。王师南征,与充军从,奄有江汉,舍爵册勋,封阴德亭侯,领郡。鸠集荒散,为民统纪,三考有成,转拜平狄将军,改封卢亭侯,莅国赋政,十有三年。会蜀将关羽猖獗为寇,常御之,羽不能克。文帝加其庸,转拜横海将军,徙封西鄂都乡侯,食邑并七百户。年六十一,黄初二年正月卒。", @@ -11,6 +12,20 @@ const characterIntro = { xiaotao: "2021年「虚拟天团」Vtuber企划中推出的虚拟偶像之一,该企划原定培养12位虚拟偶像,然而企划由于各方面原因暴死,现虚拟偶像仅存在于各武将的皮肤中。
    设定上为小杀的亲妹妹,陪姐姐去拍摄代言宣传照的时候,被导演看中,觉得三国美貌姐妹花是非常好的噱头,于是一并签下。正所谓“三国姐妹花,永远不分家!”。
    小桃对应B站账号已销号。", xiaole: "2021年「虚拟天团」Vtuber企划中推出的虚拟偶像之一,该企划原定培养12位虚拟偶像,然而企划由于各方面原因暴死,现虚拟偶像仅存在于各武将的皮肤中。
    设定上小乐家与小桃小杀家是世交,三人从小就认识。和小闪是同班同学,小乐很喜欢安静的小闪。和小酒是小杀介绍认识的,大家都是打三国杀的网友,在打游戏时候比较依赖小酒——躺赢人躺赢魂,躺赢都是人上人。
    小乐对应B站账号已销号。", xiaojiu: "2021年「虚拟天团」Vtuber企划中推出的虚拟偶像之一,该企划原定培养12位虚拟偶像,然而企划由于各方面原因暴死,现虚拟偶像仅存在于各武将的皮肤中。
    设定上为非人类,是一只年龄成迷的神兽,真身是白泽。是小杀网上玩游戏认识的网友,爱好是喝酒,和小杀也有好酒友的关系。
    小酒对应B站账号已销号。", + tianchuan: "田钏是《阵面对决》中的角色,原型为一个出现在江东的神秘女刺客,她犹如一只狡猾的狐狸,穿梭于人群之中,执行着不为人知的猎杀任务。她能潜伏在目标身边数月,只为了逐渐消磨目标的意志,慢慢折磨他直到死亡。她不知道自己的生父是谁,只知道自己名叫田钏,出生名门,却从来没见过自己的父母。她来自暗影,遁于暗影,在她的手中,再具有权势的人,也终将成为亡魂。在之后的故事里,吕蒙病逝被怀疑就是田钏所为。", + chengjix: "程畿(?~222年),巴西阆中(今四川省阆中市)人 。三国时期蜀汉官员。刘璋割据益州时,程畿为汉昌长。后来,巴西太守庞羲因刘璋猜疑而怀有叛离之心,命令程畿的儿子征召士兵自保,程畿不仅制止儿子的行为,还说服了庞羲,因此受到刘璋的赏识,被刘璋任命为江阳太守。后来刘备取代刘璋担任益州牧,程畿担任从事祭酒。蜀汉建国后,程畿随刘备伐吴,刘备兵败夷陵,程畿不肯撤退,最终奋力战死。", + zhaorong: "赵融(生卒年不详),三国时期蜀汉将领,曾随刘备参加夷陵之战,为帐下别督。", + shicong: "是个侍从,大概。", + tanxiong: "谭雄,小说《三国演义》中的虚构人物,不见于正史记载。东吴将领,在夷陵之战时随孙桓迎战蜀军,曾暗放冷箭射倒张苞的坐骑;后为关兴所擒,被张苞斩杀祭马。", + liue: "刘阿(生卒年不详)三国时期孙吴将领。章武元年(221)七月,刘备因关关羽被杀准备东征孙吴,孙权请求和解遭拒绝后,令陆议、李异、刘阿等人屯兵于巫县和秭归。后被吴班、冯习打败了,刘备军进驻秭归。黄初七年(226年),魏明帝曹叡即位,派张郃与司马懿伐吴,击败吴将刘阿。", + zhangda: "张达,请查看「范疆张达」的武将介绍。", + fanjiang: "范疆,请查看「范疆张达」的武将介绍。", + ty_anyingx: "刘备率蜀汉雄狮伐吴,途经诸乡。沿途黎庶咸感其仁德之召,箪食壶浆,夹道以迎。刘备屯军修整之际,亦不缀微服私访,察民情、恤疾苦,每以温语慰问,布施恩泽于四方。一日夜阑人静,玄德公自外回营,行至幽深之处,忽逢数名刺客,皆头戴乌鹊之冠,身披轻捷之裳。骤然暴起,意图行刺。虽侍卫忠勇奋激,终因寡不敌众,难以抵挡。玄德公亦年岁已高,此刻难以匹敌。", + ty_anying: "刘备率蜀汉雄狮伐吴,途经诸乡。沿途黎庶咸感其仁德之召,箪食壶浆,夹道以迎。刘备屯军修整之际,亦不缀微服私访,察民情、恤疾苦,每以温语慰问,布施恩泽于四方。一日夜阑人静,玄德公自外回营,行至幽深之处,忽逢数名刺客,皆头戴乌鹊之冠,身披轻捷之裳。骤然暴起,意图行刺。虽侍卫忠勇奋激,终因寡不敌众,难以抵挡。玄德公亦年岁已高,此刻难以匹敌。", + ty_wuque: "刘备率蜀汉雄狮伐吴,途经诸乡。沿途黎庶咸感其仁德之召,箪食壶浆,夹道以迎。刘备屯军修整之际,亦不缀微服私访,察民情、恤疾苦,每以温语慰问,布施恩泽于四方。一日夜阑人静,玄德公自外回营,行至幽深之处,忽逢数名刺客,皆头戴乌鹊之冠,身披轻捷之裳。骤然暴起,意图行刺。虽侍卫忠勇奋激,终因寡不敌众,难以抵挡。玄德公亦年岁已高,此刻难以匹敌。", + ty_yanque: "刘备率蜀汉雄狮伐吴,途经诸乡。沿途黎庶咸感其仁德之召,箪食壶浆,夹道以迎。刘备屯军修整之际,亦不缀微服私访,察民情、恤疾苦,每以温语慰问,布施恩泽于四方。一日夜阑人静,玄德公自外回营,行至幽深之处,忽逢数名刺客,皆头戴乌鹊之冠,身披轻捷之裳。骤然暴起,意图行刺。虽侍卫忠勇奋激,终因寡不敌众,难以抵挡。玄德公亦年岁已高,此刻难以匹敌。", + ty_wangque: "刘备率蜀汉雄狮伐吴,途经诸乡。沿途黎庶咸感其仁德之召,箪食壶浆,夹道以迎。刘备屯军修整之际,亦不缀微服私访,察民情、恤疾苦,每以温语慰问,布施恩泽于四方。一日夜阑人静,玄德公自外回营,行至幽深之处,忽逢数名刺客,皆头戴乌鹊之冠,身披轻捷之裳。骤然暴起,意图行刺。虽侍卫忠勇奋激,终因寡不敌众,难以抵挡。玄德公亦年岁已高,此刻难以匹敌。", + ty_sunquan: "公元二百二十四年,先主挟夷陵之余威,挥师东进,直捣吴都建邺,吴主孙权并大都督陆逊,见事不可为,率群臣出降。江东膏腴之地,自此尽入炎汉彀中。先主既克建邺,颁诏大赦,广开言路,招揽贤才。更约法三章,施以宽政,留其旧制,以安民心。
    先主此举,旨在抚慰江南,彰大汉仁德。吴地上下,无不感激涕零。自此六郡归心,昔日之敌,融为一炉。上下一心,共图国泰民安,传为一时佳话。", + ty_guanyu: "危难之间,一神秘将军挺身而出,与刘备协力御敌,其人面目刚毅,铁甲覆身,临危不惧。二人同进共退,配合无间,见久攻不下,刺客突施冷箭,直指刘备要害。神秘将军惊觉异常,以及身为盾,挡下夺命之矢。箭铁透甲入骨,其而持人巍然不动,手持青龙刀:“吾兄,大汉之未来,望汝承载矣!”继而持刀冲阵,化为清风。", }; - export default characterIntro; diff --git a/character/offline/skill.js b/character/offline/skill.js index 3e7cd35494..c108887404 100644 --- a/character/offline/skill.js +++ b/character/offline/skill.js @@ -2,8 +2,5439 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { + //桃园挽歌 + //铠甲合体 + _taoyuanwange: { + trigger: { + global: "phaseBefore", + player: "enterGame", + }, + filter(event, player) { + if (event.name == "phase" && game.phaseNumber != 0) return false; + return Object.keys(lib.skill._taoyuanwange.getEquip).some(name => { + return get.nameList(player).includes(name); + }); + }, + direct: true, + getEquip: { + ty_liubei: ["dilu", "ty_feilongduofeng"], + ty_luxun: ["shangfangbaojian"], + ty_sunquan: ["qingmingjian"], + }, + getAudio:{ + ty_liubei: "jizhao2", + ty_luxun: "nzry_cuike2", + ty_sunquan: "sbzhiheng2", + }, + async content(event, trigger, player) { + let list = get.nameList(player), + info=lib.skill._taoyuanwange, + names = Object.keys(info.getEquip); + for (const name of names) { + if (list.includes(name)) { + let equips = []; + for (let card of info.getEquip[name]) { + let cardx = get.cardPile(cardx => cardx.name == card && player.canEquip(cardx)); + if (cardx) equips.push(cardx); + } + if (equips.length) { + game.broadcastAll(function (audio) { + if (lib.config.background_speak) { + game.playAudio("skill", audio); + } + },info.getAudio[name]); + player.$gain2(equips); + await player.equip(equips); + } + } + } + }, + }, + //刺客×4 孩子,我们分身 + tyliupo: { + mark: true, + zhuanhuanji: true, + marktext: "☯", + intro: { + content(storage, player, skill) { + if (storage) return "回合开始时,你可令本轮所有所有即将造成的伤害均视为体力流失"; + return "回合开始时,你可令所有角色不能使用【桃】"; + }, + }, + trigger: { + player: "phaseBegin", + }, + logTarget: () => game.players, + async content(event, trigger, player) { + player.changeZhuanhuanji(event.name); + let skill = event.name + "_" + (player.storage[event.name] ? "wansha" : "jueqing"); + for (let i of game.players) i.addTempSkill(skill, "roundStart"); + }, + subSkill: { + wansha: { + charlotte: true, + mod: { + cardSavable(card, player) { + if (card.name == "tao") return false; + }, + cardEnabled(card, player) { + if (card.name == "tao") return false; + }, + }, + mark: true, + marktext: '', + intro: { + content: "不能使用桃", + }, + }, + jueqing: { + trigger: { player: "damageBefore" }, + forced: true, + charlotte: true, + content: function () { + trigger.cancel(); + trigger.player.loseHp(trigger.num); + }, + ai: { + jueqing: true, + }, + mark: true, + marktext: '', + intro: { + content: "造成伤害改为失去体力", + }, + }, + }, + }, + tyzhuiling: { + trigger: { + global: "loseHpEnd", + }, + filter(event, player) { + return player.countMark("tyzhuiling") < 3 && event.num > 0; + }, + forced: true, + logTarget: "player", + async content(event, trigger, player) { + let num = Math.min(3 - player.countMark(event.name), trigger.num); + player.addMark(event.name, num); + }, + marktext: "魂", + intro: { + name: "魂", + content: "mark", + }, + mod: { + cardUsableTarget(card, player, target) { + if (!target.countCards("h")) return Infinity; + }, + targetInRange(card, player, target) { + if (!target.countCards("h")) return true; + }, + }, + }, + tyxihun: { + trigger: { global: "roundStart" }, + forced: true, + filter(event, player) { + const curLen = player.actionHistory.length; + if (curLen <= 2) return false; + return true; + }, + async content(event, trigger, player) { + for (const target of game.players) { + if (target == player) continue; + const result = await target + .chooseToDiscard(2, "h", "弃置两张手牌,或点取消失去1点体力") + .set("ai", card => { + let player = get.player(); + if (get.effect(player, { name: "losehp" }, player, player) > 0) return 0; + return 6 - get.value(card); + }) + .forResult(); + if (!result.bool) await target.loseHp(); + } + if (!player.hasMark("tyzhuiling")) return; + let list = []; + for (let i = 1; i <= player.countMark("tyzhuiling"); i++) { + list.push(get.cnNumber(i, true)); + } + const result = await player + .chooseControl(list) + .set("prompt", "吸魂:选择要移去的“魂”数") + .set("ai", () => { + const player = get.player(); + return get.cnNumber(Math.max(1, Math.min(player.countMark("tyzhuiling"), player.getDamagedHp())), true); + }) + .forResult(); + let num = result.index + 1; + player.removeMark("tyzhuiling", num); + if (player.isDamaged()) await player.recover(num); + }, + }, + tyxianqi: { + global: "tyxianqi_damage", + subSkill: { + damage: { + enable: "phaseUse", + usable: 1, + prompt: "弃置两张牌或对自身造成1点伤害,然后令有【献气】的其他角色受到1点伤害", + filterCard: true, + position: "he", + selectCard: [0, 2], + filter(event, player) { + return game.hasPlayer(current => current.hasSkill("tyxianqi") && current != player); + }, + filterTarget(card, player, target) { + if (ui.selected.cards?.length == 1) return false; + return target.hasSkill("tyxianqi") && target != player; + }, + selectTarget() { + if (ui.selected.cards?.length == 1) return 114514; + return -1; + }, + check(card) { + let player = get.player(); + if (get.damageEffect(player, player, player) > 0) return 0; + return 8 - get.value(card); + }, + complexTarget: true, + async contentBefore(event, trigger, player) { + if (!event.cards || !event.cards.length) await player.damage(); + }, + async content(event, trigger, player) { + await event.target.damage(); + }, + ai: { + order: 6, + result: { + player(player, target) { + if (ui.selected.cards.length) return 0; + if (player.hp >= target.hp) return -0.9; + if (player.hp <= 2) return -10; + return -2; + }, + target(player, target) { + if (!ui.selected.cards.length) { + if (player.hp < 2) return 0; + if (player.hp == 2 && target.hp >= 2) return 0; + if (target.hp > player.hp) return 0; + } + return get.damageEffect(target, player); + }, + }, + }, + }, + }, + }, + tyfansheng: { + trigger: { + player: "dying", + }, + filter(event, player) { + return game.getAllGlobalHistory("everything", evt => { + return evt.name == "dying" && evt.player == player; + }).indexOf(event) == 0; + }, + forced: true, + skillAnimation: true, + animationColor: "metal", + async content(event, trigger, player) { + await player.recoverTo(1); + for (const target of game.players) { + if (target == player) continue; + const list = []; + if (target.countCards("h")) list.push("手牌区"); + if (target.countCards("e")) list.push("装备区"); + if (list.length == 0) continue; + let result; + if (list.length == 1) result = { control: list[0] }; + else { + result = await target + .chooseControl(list) + .set("prompt", "返生:弃置一个区域的所有牌") + .set("ai", () => [0, 1].randomGet()) + .forResult(); + } + let pos = result.control == "手牌区" ? "h" : "e"; + let cards = target.getCards(pos); + if (cards.length) await target.discard(cards); + } + }, + }, + tyansha: { + inherit: "tysiji", + filter: function (event, player) { + return ( + player.countCards("hes") && + player.canUse( + { + name: "sha", + nature: "stab", + }, + event.player, + ) + ); + }, + group: "tyansha_range", + subSkill: { + range: { + trigger: { + player: "useCardAfter", + }, + filter(event, player) { + return event.skill == "tyansha" && event.targets?.some(i => { + return i.isIn() && !player.getStorage("tyansha_range").includes(i); + }); + }, + direct: true, + content() { + if (!player.getStorage("tyansha_range").length) { + player.when({ global: "roundStart" }).then(() => { + player.unmarkAuto("tyansha_range", player.getStorage("tyansha_range")); + }); + } + let targets = trigger.targets.filter(i => { + return i.isIn() && !player.getStorage("tyansha_range").includes(i); + }); + player.markAuto("tyansha_range", targets); + }, + intro: { + content: "$本轮计算与你的距离视为1", + }, + firstDo: true, + onremove: true, + locked: false, + mod: { + globalTo(from, to, num) { + if (to.getStorage("tyansha_range").includes(from)) { + return -Infinity; + } + }, + }, + }, + backup: { + filterCard: function (card) { + return get.itemtype(card) == "card"; + }, + viewAs: { + name: "sha", + nature: "stab", + }, + selectCard: 1, + position: "hes", + filterTarget(card, player, target) { + if (target != _status.event.useTarget && !ui.selected.targets.includes(_status.event.useTarget)) return false; + return lib.filter.targetEnabled.apply(this, arguments); + }, + precontent() { + event.result.skill = event.getParent(2).name; + }, + ai1(card) { + return 7 - get.value(card); + }, + }, + }, + }, + tycangshen: { + forced: true, + trigger: { + player: "useCardAfter", + }, + filter(event, player) { + return event.card.name == "sha"; + }, + async content(event, trigger, player) { + player.tempBanSkill("tycangshen", "roundStart"); + }, + mod: { + globalTo(from, to, num) { + if (!to.isTempBanned("tycangshen")) return num + 1; + }, + }, + }, + tyxiongren: { + trigger: { + source: "damageBegin1", + }, + filter(event, player) { + if (get.distance(event.player, player) <= 1) return false; + return event.card?.name == "sha"; + }, + forced: true, + async content(event, trigger, player) { + trigger.num++; + }, + mod: { + cardUsableTarget(card, player, target) { + if (get.distance(target, player) <= 1) return Infinity; + }, + targetInRange(card, player, target) { + if (get.distance(target, player) <= 1) return true; + }, + }, + }, + tysiji: { + trigger: { global: "phaseJieshuBegin" }, + filter: function (event, player) { + if (!event.player.hasHistory("lose", evt => { + return !["useCard", "respond"].includes(evt.getParent().name); + })) return false; + return ( + player.countCards("hes") && + player.canUse( + { + name: "sha", + nature: "stab", + }, + event.player, + false + ) + ); + }, + direct: true, + async content(event, trigger, player) { + var next = player.chooseToUse(); + next.set("useTarget", trigger.player); + next.set("openskilldialog", `###${get.prompt(event.name, trigger.player)}###${lib.translate[event.name + "_info"]}`); + next.set("norestore", true); + next.set("_backupevent", "tyansha_backup"); + next.set("addCount", false); + next.set("custom", { + add: {}, + replace: { window: function () { } }, + }); + next.backup("tyansha_backup"); + }, + }, + tydaifa: { + inherit: "tysiji", + filter: function (event, player) { + if (!game.hasPlayer2(current => { + if (current == event.player) return false; + if (current.hasHistory("lose", evt => { + if (evt.type != "gain") return false; + var evtx = evt.getParent(); + if (evtx.giver || evtx.getParent().name == "gift") return false; + var cards = evtx.getg(event.player); + if (!cards.length) return false; + var cards2 = evtx.getl(current).cards2; + for (var card of cards2) { + if (cards.includes(card)) return true; + } + return false; + })) return true; + })) return false + return ( + player.countCards("hes") && + player.canUse( + { + name: "sha", + nature: "stab", + }, + event.player, + false + ) + ); + }, + }, + //桃神关羽 + tywushen: { + audio: "wushen", + enable: ["chooseToRespond", "chooseToUse"], + filterCard(card, player) { + return get.suit(card) == "heart"; + }, + position: "hes", + viewAs: { + name: "sha", + storage: { + tywushen: true, + }, + }, + viewAsFilter(player) { + if (!player.countCards("hes", { suit: "heart" })) return false; + }, + prompt: "将一张红桃牌当杀使用或打出", + check(card) { + const val = get.value(card); + if (_status.event.name == "chooseToRespond") return 1 / Math.max(0.1, val); + return 5 - val; + }, + ai: { + skillTagFilter(player) { + if (!player.countCards("hes", { suit: "heart" })) return false; + }, + respondSha: true, + }, + locked: false, + mod: { + cardUsable(card, player) { + if (card?.storage?.tywushen) return Infinity; + }, + targetInRange(card, player) { + if (card?.storage?.tywushen) return true; + }, + }, + group: "tywushen_respond", + subSkill: { + respond: { + trigger: { player: "useCard" }, + direct: true, + forced: true, + filter(event, player) { + return event.card?.storage?.tywushen; + }, + content() { + trigger.directHit.addArray(game.players); + if (trigger.addCount !== false) { + trigger.addCount = false; + if (player.stat[player.stat.length - 1].card.sha > 0) { + player.stat[player.stat.length - 1].card.sha--; + } + } + }, + }, + }, + }, + tywuhun: { + audio: "wuhun2", + trigger: { player: "damageEnd" }, + filter(event, player) { + return event.source && event.source.isIn(); + }, + forced: true, + logTarget: "source", + content() { + trigger.source.addMark("tywuhun", trigger.num); + }, + group: "tywuhun_die", + ai: { + notemp: true, + effect: { + target: (card, player, target) => { + if (!target.hasFriend()) return; + let rec = get.tag(card, "recover"), + damage = get.tag(card, "damage"); + if (!rec && !damage) return; + if (damage && player.hasSkillTag("jueqing", false, target)) return 1.7; + let die = [null, 1], + temp; + game.filterPlayer(i => { + temp = i.countMark("new_wuhun"); + if (i === player && target.hp + target.hujia > 1) temp++; + if (temp > die[1]) die = [i, temp]; + else if (temp === die[1]) { + if (!die[0]) die = [i, temp]; + else if (get.attitude(target, i) < get.attitude(target, die[0])) die = [i, temp]; + } + }); + if (die[0]) { + if (damage) return [1, 0, 1, (-6 * get.sgnAttitude(player, die[0])) / Math.max(1, target.hp)]; + return [1, (6 * get.sgnAttitude(player, die[0])) / Math.max(1, target.hp)]; + } + }, + }, + }, + marktext: "魇", + intro: { + name: "梦魇", + content: "mark", + onunmark: true, + }, + subSkill: { + die: { + audio: "wuhun2", + trigger: { player: "die" }, + filter(event, player) { + return event.source || game.hasPlayer(function (current) { + return current != player && current.hasMark("tywuhun"); + }); + }, + forced: true, + direct: true, + forceDie: true, + skillAnimation: true, + animationColor: "soil", + content() { + "step 0"; + var num = 0; + for (var i = 0; i < game.players.length; i++) { + var current = game.players[i]; + if (current != player && current.countMark("tywuhun") > num) { + num = current.countMark("tywuhun"); + } + } + player + .chooseTarget(true, "请选择【武魂】的目标", "令其进行判定,若判定结果不为【桃】,则其死亡", function (card, player, target) { + return target != player && (target == _status.event.getTrigger().source || target.countMark("tywuhun") == _status.event.num); + }) + .set("ai", function (target) { + return -get.attitude(_status.event.player, target); + }) + .set("forceDie", true) + .set("num", num); + "step 1"; + if (result.bool) { + var target = result.targets[0]; + event.target = target; + player.logSkill("tywuhun_die", target); + player.line(target, { color: [255, 255, 0] }); + game.delay(2); + } + "step 2"; + target.judge(function (card) { + if (["tao"].includes(card.name)) return 10; + return -10; + }).judge2 = function (result) { + return result.bool == false ? true : false; + }; + "step 3"; + if (!result.bool) target.die(); + }, + }, + }, + }, + //桃神张飞 + tyshencai: { + audio: "shencai", + enable: "phaseUse", + usable: 5, + filter(event, player) { + var count = player.getStat("skill").tyshencai; + if (count && count > player.countMark("shencai")) return false; + return true; + }, + filterTarget: lib.filter.notMe, + onremove: true, + prompt: "选择一名其他角色进行地狱审判", + content() { + var next = target.judge(); + next.callback = lib.skill.shencai.contentx; + }, + ai: { + order: 8, + result: { target: -1 }, + }, + group: "tyshencai_wusheng", + subSkill: { + wusheng: { + audio: "shencai", + enable: ["chooseToRespond", "chooseToUse"], + filterCard(card, player) { + return get.suit(card) == "none"; + }, + position: "hes", + viewAs: { + name: "sha", + color: "none", + suit: "none", + }, + viewAsFilter(player) { + if (!player.countCards("hes", { suit: "none" })) return false; + }, + prompt: "将一张无色牌当杀使用或打出", + check(card) { + const val = get.value(card); + if (_status.event.name == "chooseToRespond") return 1 / Math.max(0.1, val); + return 5 - val; + }, + ai: { + skillTagFilter(player) { + if (!player.countCards("hes", { color: "none" })) return false; + }, + respondSha: true, + }, + }, + }, + }, + tyxunshi: { + audio: "xunshi", + mod: { + suit(card) { + if (lib.skill.xunshi.isXunshi(card)) return "none"; + }, + targetInRange(card) { + const suit = get.color(card); + if (suit == "none" || suit == "unsure") return true; + }, + cardUsable(card) { + const suit = get.color(card); + if (suit == "none" || suit == "unsure") return Infinity; + }, + }, + init(player, skill) { + player.addSkill("tyxunshi_mark"); + }, + onremove(player, skill) { + player.removeSkill("tyxunshi_mark"); + }, + trigger: { player: "useCard2" }, + forced: true, + filter(event, player) { + return get.color(event.card) == "none"; + }, + content() { + "step 0"; + if (player.countMark("shencai") < 4 && player.hasSkill("tyshencai", null, null, false)) player.addMark("shencai", 1, false); + if (trigger.addCount !== false) { + trigger.addCount = false; + var stat = player.getStat().card, + name = trigger.card.name; + if (typeof stat[name] == "number") stat[name]--; + } + var info = get.info(trigger.card); + if (info.allowMultiple == false) event.finish(); + else if (trigger.targets && !info.multitarget) { + if ( + !game.hasPlayer(function (current) { + return !trigger.targets.includes(current) && lib.filter.targetEnabled2(trigger.card, player, current); + }) + ) + event.finish(); + } else event.finish(); + "step 1"; + var prompt2 = "为" + get.translation(trigger.card) + "增加任意个目标"; + player + .chooseTarget( + get.prompt("xunshi"), + function (card, player, target) { + var player = _status.event.player; + return !_status.event.targets.includes(target) && lib.filter.targetEnabled2(_status.event.card, player, target); + }, + [1, Infinity] + ) + .set("prompt2", prompt2) + .set("ai", function (target) { + var trigger = _status.event.getTrigger(); + var player = _status.event.player; + return get.effect(target, trigger.card, player, player); + }) + .set("card", trigger.card) + .set("targets", trigger.targets); + "step 2"; + if (result.bool) { + if (!event.isMine() && !event.isOnline()) game.delayx(); + event.targets = result.targets; + } else { + event.finish(); + } + "step 3"; + if (event.targets) { + player.line(event.targets, "fire"); + trigger.targets.addArray(event.targets); + } + }, + subSkill: { + mark: { + charlotte: true, + trigger: { + player: "gainAfter", + global: "loseAsyncAfter", + }, + filter(event, player, name) { + return event.getg(player).length && player.countCards("h"); + }, + direct: true, + firstDo: true, + content() { + let cards1 = [], cards2 = []; + player.getCards("h").forEach(card => { + let bool1 = lib.skill.xunshi.isXunshi(card), bool2 = card.hasGaintag("tyxunshi_tag"); + if (bool1 && !bool2) cards1.add(card); + if (!bool1 && bool2) cards2.add(card); + }); + if (cards1.length) player.addGaintag(cards1, "tyxunshi_tag"); + if (cards2.length) cards2.forEach(card => card.removeGaintag("tyxunshi_tag")); + }, + }, + }, + }, + //范强张达 + tybianta: { + trigger: { + target: "useCardToTargeted", + }, + usable: 1, + filter(event, player) { + return get.tag(event.card, "damage") && event.cards?.length; + }, + marktext: "怨", + intro: { + name: "怨", + content: "expansion", + markcount: "expansion", + }, + init(player, skill) { + if (player.getExpansions("tyxingsha").length) { + for (let card of player.getExpansions("tyxingsha")) { + card.gaintag.remove("tyxingsha"); + card.gaintag.add(skill); + } + player.markSkill(skill); + } + }, + onremove(player, skill) { + if (!_status.event.getParent("tyxiezhan", true)) { + let cards = player.getExpansions(skill); + if (cards.length) player.loseToDiscardpile(skill); + } + }, + async content(event, trigger, player) { + const next = player.addToExpansion(trigger.cards, "gain2"); + next.gaintag.add("tybianta"); + await next; + }, + group: "tybianta_jieshu", + subSkill: { + jieshu: { + trigger: { + player: "phaseJieshuBegin", + }, + filter(event, player) { + return player.getExpansions("tybianta").length; + }, + prompt2: "依次使用或打出你所有的“怨”", + async content(event, trigger, player) { + player.addTempSkill("tybianta_use"); + while (player.getExpansions("tybianta").length) { + const card = player.getExpansions("tybianta")[0]; + if (player.hasUseTarget(card)) { + const result = await player.chooseUseTarget(card).forResult(); + if (!result.bool) break; + } + else break; + } + player.removeTempSkill("tybianta_use"); + }, + }, + use: { + enable: ["chooseToUse", "chooseToRespond"], + filter(event, player) { + if (!event.tybianta) return false; + let card = event.tybianta; + return event.filterCard(card, player, event); + }, + onChooseToUse(event) { + if (game.online) return; + var player = event.player; + if (!player.getExpansions("tybianta").length) event.set("tybianta", false); + else event.set("tybianta", player.getExpansions("tybianta")[0]); + }, + onChooseToRespond(event) { + if (game.online) return; + var player = event.player; + if (!player.getExpansions("tybianta").length) event.set("tybianta", false); + else event.set("tybianta", player.getExpansions("tybianta")[0]); + }, + filterCard(card, player) { + return card == _status.event.tybianta; + }, + selectCard: -1, + position: "x", + viewAs(cards, player) { + let card = _status.event.tybianta; + if (card) return card; + return null; + }, + prompt(event, player) { + let card = _status.event.tybianta; + return `是否使用${get.translation(card)}?`; + }, + precontent() { + event.result.card = event.result.cards[0]; + }, + hiddenCard(player, name) { + if (!player.getExpansions("tybianta").length) return false; + return get.name(player.getExpansions("tybianta")[0], false) == name; + }, + ai: { + respondSha: true, + respondShan: true, + skillTagFilter(player, target, arg) { + let name = tag.slice(7); + if (!player.getExpansions("tybianta").length) return false; + return get.name(player.getExpansions("tybianta")[0], false) == name; + } + }, + }, + }, + }, + tybenxiang: { + trigger: { + source: "die", + }, + locked: true, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2(event.name.slice(0, -5)), lib.filter.notMe, true) + .set("ai", target => { + return get.effect(target, { name: "draw" }, get.player(), get.player()); + }) + .forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + await target.draw(3); + }, + }, + tyxiezhan: { + audio: "juesheng", + trigger: { + player: ["phaseUseBegin", "enterGame"], + global: "phaseBefore", + }, + filter(event, player) { + return event.name != "phase" || game.phaseNumber == 0; + }, + locked: true, + async cost(event, trigger, player) { + let list = get.nameList(player), bool = trigger.name == "phaseUse"; + if (bool) { + if (list.includes("ty_fanjiang")) { + event.result = { + bool: true, + cost_data: "ty_zhangda", + }; + } + else if (list.includes("ty_zhangda")) { + event.result = { + bool: true, + cost_data: "ty_fanjiang", + }; + } + else bool = false; + } + if (!bool) { + const result = await player + .chooseControl("范疆", "张达") + .set("prompt", "协战:请变身") + .set("ai", () => [0, 1].randomGet()) + .forResult(); + event.result = { + bool: true, + cost_data: result.control == "范疆" ? "ty_fanjiang" : "ty_zhangda", + }; + } + }, + async content(event, trigger, player) { + let prename = player.name1; + if (player.name2 && get.character(player.name2, 3).includes("tyxiezhan")) prename = player.name2; + await player.reinitCharacter(prename, event.cost_data); + await game.delay(); + }, + }, + tyxingsha: { + marktext: "怨", + intro: { + name: "怨", + content: "expansion", + markcount: "expansion", + }, + init(player, skill) { + if (player.getExpansions("tybianta").length) { + for (let card of player.getExpansions("tybianta")) { + card.gaintag.remove("tybianta"); + card.gaintag.add(skill); + } + player.markSkill(skill); + } + }, + onremove(player, skill) { + if (!_status.event.getParent("tyxiezhan", true)) { + let cards = player.getExpansions(skill); + if (cards.length) player.loseToDiscardpile(skill); + } + }, + enable: "phaseUse", + filter(event, player) { + return player.countCards("he") && !player.hasSkill("tyxingsha_used"); + }, + filterCard: true, + selectCard: [1, 2], + lose: false, + discard: false, + async content(event, trigger, player) { + player.addTempSkill("tyxingsha_used"); + const next = player.addToExpansion(event.cards, player, "give"); + next.gaintag.add("tyxingsha"); + await next; + }, + group: "tyxingsha_use", + subSkill: { + used: { + charlotte: true, + }, + use: { + trigger: { + player: "phaseJieshuBegin", + }, + filter(event, player) { + if (!player.hasUseTarget(get.autoViewAs({ name: "sha" }, "unsure"), false)) return false; + return player.getExpansions("tyxingsha").length; + }, + async cost(event, trigger, player) { + const result = await player + .chooseButton(["刑杀:是否将两张“怨”当作杀使用?", player.getExpansions("tyxingsha")], 2) + .set("ai", button => { + let player = get.player(), + eff = player.getUseValue(get.autoViewAs({ name: "sha" }, "unsure"), false); + if (eff <= 0) return 0; + return player.getHp() - player.getUseValue(button.link); + }) + .forResult(); + event.result = { + bool: result.bool, + cards: result.links, + }; + }, + async content(event, trigger, player) { + let card = get.autoViewAs({ name: "sha" }, event.cards); + await player.chooseUseTarget(card, event.cards, false); + }, + }, + }, + }, + tyxianshou: { + trigger: { + source: "die", + }, + locked: true, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2(event.name.slice(0, -5)), lib.filter.notMe, true) + .set("ai", target => { + return get.effect(target, { name: "recover" }, get.player(), get.player()); + }) + .forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + if (target.isDamaged()) await target.recover(2); + }, + }, + //刘阿 + tyxiyu: { + audio: 2, + trigger: { + global: "useCardToPlayered", + }, + filter(event, player) { + return event.isFirstTarget && (get.is.convertedCard(event.card) || get.is.virtualCard(event.card)); + }, + frequent: true, + async content(event, trigger, player) { + await player.draw(); + }, + }, + //谭雄 + tylengjian: { + trigger: { + player: "useCardToTargeted", + }, + filter(event, player) { + if (event.card.name != "sha") return false; + return !player.getStorage("tylengjian").includes(event.target); + }, + intro: { + content: "本回合已对$使用过【杀】", + }, + forced: true, + logTarget: "target", + async content(event, trigger, player) { + const target = event.targets[0]; + if (!player.getStorage("tylengjian").length) { + player.when({ global: "phaseEnd" }).then(() => { + player.unmarkSkill("tylengjian"); + delete player.storage.tylengjian; + }); + } + player.markAuto("tylengjian", target); + if (player.inRange(target)) { + const id = target.playerid; + const map = trigger.getParent().customArgs; + if (!map[id]) map[id] = {}; + if (typeof map[id].extraDamage != "number") { + map[id].extraDamage = 0; + } + map[id].extraDamage++; + } + else trigger.getParent().directHit.push(target); + }, + mod: { + targetInRange(card, player, target) { + if (card.name == "sha" && !player.inRange(target)) { + if (!player.getStorage("tylengjian").includes(target)) return true; + } + }, + }, + }, + tysheju: { + trigger: { + player: "useCardAfter", + }, + filter(event, player) { + if (event.card.name != "sha") return false; + return event.targets?.some(current => current.isIn() && current.countCards("he")); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2("tysheju"), function (card, player, target) { + return _status.event.getTrigger().targets.includes(target) && target.countCards("he"); + }) + .set("ai", target => { + return get.effect(target, { name: "guohe_copy2" }, get.player(), get.player()); + }) + .forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + const result = await player.discardPlayerCard(target, "he", true).forResult(); + if (!result.bool || !result.links) return; + let subtype = get.subtype(result.links[0]); + if (subtype && ["equip3", "equip4", "equip6"].includes(subtype)) return; + target.addTempSkill("tysheju_range"); + target.addMark("tysheju_range", 1, false); + if (target.inRange(player)) { + await target + .chooseToUse(function (card, player, event) { + if (get.name(card) != "sha") return false; + return lib.filter.filterCard.apply(this, arguments); + }, "是否对" + get.translation(player) + "使用一张杀?") + .set("targetRequired", true) + .set("complexSelect", true) + .set("filterTarget", function (card, player, target) { + if (target != _status.event.sourcex && !ui.selected.targets.includes(_status.event.sourcex)) return false; + return lib.filter.targetEnabled.apply(this, arguments); + }) + .set("sourcex", player); + } + }, + subSkill: { + range: { + charlotte: true, + onremove: true, + mark: true, + intro: { + content: "本回合攻击范围+#", + }, + mod: { + attackFrom(from, to, distance) { + return distance - from.countMark("tysheju_range"); + }, + }, + }, + }, + }, + //buzhi + tyhongde: { + audio: "hongde", + trigger: { + player: ["loseAfter", "gainAfter"], + global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], + }, + filter(event, player) { + var num = event.getl(player).cards2.length; + if (event.getg) num = Math.max(num, event.getg(player).length); + return num > 1; + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2("tyhongde")) + .set("ai", function (target) { + let player = get.player(), name = get.attitude(player, target) > 0 ? "draw" : "guohe_copy2"; + return get.effect(target, { name: name }, player, player); + }) + .forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + const result = await player + .chooseControl("摸一张牌", "弃置一张牌") + .set("prompt", `令${get.translation(target)}执行一项`) + .set("target", target) + .set("ai", () => { + const player = get.player(), target = get.event("target"); + let eff1 = get.effect(target, { name: "guohe_copy2" }, player, player), + eff2 = get.effect(target, { name: "draw" }, player, player); + if (eff1 > eff2) return 1; + return 0; + }) + .forResult(); + if (result.index == 0) await target.draw(); + else if (target.countCards("he")) await target.chooseToDiscard("he", true); + }, + }, + tydingpan: { + audio: "dingpan", + enable: "phaseUse", + usable: 3, + filter(event, player) { + if (event.tydingpan && player.countMark("tydingpan") >= event.tydingpan.length) return false; + return game.hasPlayer(current => current.countCards("e")); + }, + filterTarget(event, player, target) { + return target.countCards("e"); + }, + onChooseToUse: function (event) { + if (event.type != "phase" || game.online) return; + var list = [], + player = event.player; + player.getHistory("useCard", function (evt) { + list.add(get.type2(evt.card)); + }); + event.set("tydingpan", list); + }, + async content(event, trigger, player) { + if (!player.countMark("tydingpan")) { + player.when({ global: ["phaseUseBegin", "phaseUseAfter"] }).then(() => { + player.removeMark("tydingpan", player.countMark("tydingpan"), false); + }); + } + player.addMark("tydingpan", 1, false); + const target = event.target; + await target.draw(); + let goon = get.damageEffect(target, player, target) >= 0; + if (!goon && target.hp >= 4 && get.attitude(player, target) < 0) { + var es = target.getCards("e"); + for (var i = 0; i < es.length; i++) { + if (get.equipValue(es[i], target) >= 8) { + goon = true; + break; + } + } + } + const result = await target + .chooseControl(function () { + if (_status.event.goon) return "选项二"; + return "选项一"; + }) + .set("goon", goon) + .set("prompt", "定叛") + .set("choiceList", [ + "令" + get.translation(player) + "弃置你两张牌", + "获得你装备区内的所有牌并受到1点伤害" + ]) + .forResult(); + if (result.index == 0) await player.discardPlayerCard(target, "he", Math.min(target.countCards("he"), 2), true); + else { + await target.gain(target.getCards("e"), "gain2"); + await target.damage(); + } + }, + ai: { + order: 7, + result: { + target(player, target) { + if (get.damageEffect(target, player, target) >= 0) return 2; + var att = get.attitude(player, target); + if (att == 0) return 0; + var es = target.getCards("e"); + if (att > 0 && (target.countCards("h") > 2 || target.needsToDiscard(1))) return 0; + if (es.length == 1 && att > 0) return 0; + for (var i = 0; i < es.length; i++) { + var val = get.equipValue(es[i], target); + if (val <= 4) { + if (att > 0) { + return 1; + } + } else if (val >= 7) { + if (att < 0) { + return -1; + } + } + } + return 0; + }, + }, + }, + }, + //甘宁 + tyqixi: { + audio: "qixi", + inherit: "qixi", + group: "tyqixi_nowuxie", + subSkill: { + nowuxie: { + trigger: { + player: "useCard", + }, + filter(event, player) { + if (event.card.name != "guohe" || !get.is.convertedCard(event.card)) return false; + return event.cards?.some(card => get.type(card) != "basic"); + }, + direct: true, + async content(event, trigger, player) { + trigger.directHit.addArray(game.players); + }, + }, + }, + }, + tyfenwei: { + skillAnimation: true, + animationColor: "wood", + audio: "fenwei", + trigger: { global: "useCardToPlayered" }, + filter(event, player) { + if (event.getParent().triggeredTargets3.length > 1) return false; + if (get.type(event.card) != "trick") return false; + if (get.info(event.card).multitarget) return false; + if (event.targets.length < 2) return false; + return true; + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt("tyfenwei"), [1, trigger.targets.length], function (card, player, target) { + return _status.event.targets.includes(target); + }) + .set("ai", function (target) { + var trigger = _status.event.getTrigger(); + if (game.phaseNumber > game.players.length * 2 && trigger.targets.length >= game.players.length - 1 && !trigger.excluded.includes(target)) { + return -get.effect(target, trigger.card, trigger.player, _status.event.player); + } + return -1; + }) + .set("targets", trigger.targets) + .forResult(); + }, + async content(event, trigger, player) { + trigger.getParent().excluded.addArray(event.targets); + let num = Math.max(1, player.getAllHistory("useSkill", evt => evt.skill == event.name).length - 1); + const result = await player + .chooseBool(`失去${num}点体力,或点取消失去【奋威】`) + .set("choice", player.hp > num) + .forResult(); + if (result.bool) await player.loseHp(num); + else await player.removeSkills(event.name); + }, + }, + //陆逊 + tyqianshou: { + mark: true, + zhuanhuanji: true, + marktext: "☯", + intro: { + content(storage) { + if (storage) return "其他角色的回合开始时,若其体力值大于你,或其未处于横置状态,你可令其展示并交给你一张牌,若此牌不为黑色,你失去一点体力。"; + return "其他角色的回合开始时,若其体力值大于你,或其未处于横置状态,你可展示并交给其一张红色牌,本回合你不能使用手牌且你与其不能成为牌的目标。"; + }, + }, + trigger: { + global: "phaseBegin", + }, + filter(event, player) { + if (event.player == player) return false; + if (event.player.hp <= player.hp && event.player.isLinked()) return false; + if (player.storage.tyqianshou) return event.player.countCards("he"); + return player.countCards("he", { color: "red" }); + }, + async cost(event, trigger, player) { + if (player.storage.tyqianshou) { + event.result = await player + .chooseBool(get.prompt2("tyqianshou", trigger.player)) + .set("choice", get.attitude(player, trigger.player) > 0 || player.hp > 1) + .forResult(); + } + else { + event.result = await player + .chooseCard(get.prompt2("tyqianshou", trigger.player), "he", function (card) { + return get.color(card) == "red"; + }) + .set("canGive", function () { + const att = get.attitude(player, trigger.player) > 0; + if (trigger.player.hp >= 3) return att; + if (trigger.player.countCards("h") < 4) return att; + return false; + }()) + .set("ai", card => { + if (get.event("canGive")) return 6 - get.value(card); + return 0; + }) + .forResult(); + } + event.result.targets = [trigger.player]; + }, + async content(event, trigger, player) { + player.changeZhuanhuanji(event.name); + if (player.storage[event.name]) { + await player.showCards(get.translation(player) + "发动了【谦守】", event.cards); + await player.give(event.cards, event.targets[0]); + player.addTempSkill("tyqianshou_use"); + for (let target of [player].concat(event.targets)) { + target.addTempSkill("tyqianshou_target"); + } + } + else { + const target = event.targets[0], result = await target + .chooseCard("he", true, `交给${get.translation(player)}一张牌,若不为黑色其失去1点体力`) + .set("att", get.attitude(target, player)) + .set("ai", card => { + let att = _status.event.att, val = 7 - get.value(card); + if (get.color(card) == "black") val += att; + return val; + }) + .forResult(); + await target.showCards(get.translation(player) + "发动了【谦守】", result.cards); + await target.give(result.cards, player); + if (!player.getHistory("gain", evt => { + return evt?.cards?.includes(result.cards[0]) && evt.getParent(event.name) == event; + }).length) return; + if (get.color(result.cards[0]) != "black") { + await player.loseHp(); + } + } + }, + subSkill: { + use: { + mark: true, + marktext: '', + mod: { + cardEnabled2(card) { + if (get.position(card) == "h") return false; + }, + }, + charlotte: true, + intro: { + content: "不能使用或打出手牌", + }, + }, + target: { + charlotte: true, + mark: true, + marktext: '', + intro: { content: "本回合无法成为牌的目标" }, + mod: { targetEnabled: () => false }, + }, + }, + }, + tytanlong: { + enable: "phaseUse", + usable: 221, + filter(event, player) { + if (player.countMark("tytanlong") > game.countPlayer(current => current.isLinked())) return false; + return game.hasPlayer(current => player.canCompare(current)) && player.countCards("h"); + }, + filterTarget(event, player, target) { + return player.canCompare(target); + }, + async content(event, trigger, player) { + if (!player.countMark("tytanlong")) { + player.when({ global: ["phaseUseBegin", "phaseUseAfter"] }).then(() => { + player.removeMark("tytanlong", player.countMark("tytanlong"), false); + }); + } + player.addMark("tytanlong", 1, false); + const target = event.target; + const next = player.chooseToCompare(target); + if (get.attitude(player, target) > 0) next.set("small", true); + const result = await next.forResult(); + if (result.tie) return; + let winner = result.bool ? player : target, card = result[result.bool ? "target" : "player"]; + if (winner?.isIn() && card && [card].filterInD("d")) { + let bool = get.attitude(winner, player) > 0; + if (winner.getUseValue(card) >= 4) bool = true; + const result2 = await winner + .chooseBool(`是否获得${get.translation(card)}并视为对自己使用一张【铁索连环】?`) + .set("choice", bool) + .forResult(); + if (!result2.bool) return; + await winner.gain(card, "gain2"); + let cardx = { name: "tiesuo", isCard: true }; + if (winner.canUse(cardx, winner)) await winner.useCard(cardx, winner); + } + }, + ai: { + order: 7, + result: { + target(player, target) { + return get.effect(target, { name: "tiesuo" }, target, target); + }, + }, + }, + }, + tyxibei: { + trigger: { + global: ["gainAfter", "loseAsyncAfter"], + }, + getIndex(event, player) { + if (!event.getg) return []; + return game.filterPlayer(current => { + if (current == player) return false; + if (event.name == "gain") return event.getg(current)?.length && event.notFromCardpile; + return event.getg(current)?.some(card => { + return card.original != "c"; + }); + }).sortBySeat(); + }, + logTarget(event, player, name, target) { + return target; + }, + frequent: true, + async content(event, trigger, player) { + await player.draw(); + if (!player.isPhaseUsing()) return; + const result = await player + .chooseCard("h", "是否展示一张锦囊牌,令此牌视为【火烧连营】?", card => { + return get.type2(card) == "trick"; + }) + .set("ai", card => { + let player = get.player(); + if (player.getUseValue("huogong") > 0) return 6 - get.value(card); + return 0; + }) + .forResult(); + if (!result.bool) return; + game.broadcastAll(function (cards) { + cards.forEach(card => card.addGaintag("tyxibei")); + }, result.cards); + player.addTempSkill("tyxibei_viewAs"); + }, + group: "tyxibei_record", + subSkill: { + record: { + trigger: { global: "gainBefore" }, + direct: true, + filter(event, player) { + if (player == event.player) return false; + if (event.cards.length) { + if (event.getParent().name == "draw") return false; + for (var i = 0; i < event.cards.length; i++) if (get.position(event.cards[i]) != "c" || (!get.position(event.cards[i]) && event.cards[i].original != "c")) return true; + } + return false; + }, + content() { + trigger.notFromCardpile = true; + }, + }, + viewAs: { + mod: { + cardname(card, player) { + if (card.hasGaintag("tyxibei")) return "lx_huoshaolianying"; + }, + }, + charlotte: true, + onremove(player) { + player.removeGaintag("tyxibei"); + }, + }, + }, + }, + //神刘 + tylongnu: { + mark: true, + zhuanhuanji: true, + marktext: "☯", + intro: { + content(storage) { + if (storage) return "出牌阶段开始时,你可以减少1点体力上限并摸一张牌,然后本阶段内你可以将锦囊牌当作无次数限制雷杀使用或打出"; + return "锁定技,出牌阶段开始时,你可以失去1点体力并摸一张牌,然后本阶段内你可以将红色手牌当作无距离限制的火杀使用或打出"; + }, + }, + audio: "nzry_longnu", + trigger: { + player: "phaseUseBegin", + }, + async content(event, trigger, player) { + player.changeZhuanhuanji("tylongnu"); + await player.draw(); + if (!player.storage.tylongnu) { + await player.loseMaxHp(); + player.addTempSkill("tylongnu_yang", "phaseUseAfter"); + } else { + await player.loseHp(); + player.addTempSkill("tylongnu_yin", "phaseUseAfter"); + } + }, + group: "tylongnu_change", + subSkill: { + change: { + audio: "nzry_longnu", + trigger: { + global: "phaseBefore", + player: "enterGame", + }, + filter(event, player) { + return event.name != "phase" || game.phaseNumber == 0; + }, + prompt2(event, player) { + return "切换【龙怒】为状态" + (player.storage.tylongnu ? "阴" : "阳"); + }, + check: () => Math.random() > 0.5, + content() { + player.changeZhuanhuanji("tylongnu"); + }, + }, + yang: { + mod: { + cardUsable(card, player) { + if (card?.storage?.tylongnu) return Infinity; + }, + }, + charlotte: true, + locked: false, + audio: "nzry_longnu", + enable: ["chooseToUse", "chooseToRespond"], + filterCard(card, player) { + return get.type2(card) == "trick"; + }, + position: "hes", + viewAs: { + name: "sha", + nature: "thunder", + storage: { + tylongnu: true, + }, + }, + viewAsFilter(player) { + if (!player.countCards("hes", card => get.type2(card) == "trick")) return false; + }, + prompt: "将一张锦囊牌当雷杀使用或打出", + check(card) { + var val = get.value(card); + return 5 - val; + }, + ai: { + effect: { + target(card, player, target, current) { + if (get.tag(card, "respondSha") && current < 0) return 0.6; + }, + }, + respondSha: true, + }, + }, + yin: { + mod: { + targetInRange(card) { + if (card?.storage?.tylongnu) return true; + }, + }, + charlotte: true, + locked: false, + audio: "nzry_longnu", + enable: ["chooseToUse", "chooseToRespond"], + filterCard(card, player) { + return get.color(card) == "red"; + }, + position: "hs", + viewAs: { + name: "sha", + nature: "fire", + storage: { + tylongnu: true, + }, + }, + viewAsFilter(player) { + if (!player.countCards("hs", { color: "red" })) return false; + }, + prompt: "将一张红色手牌当火杀使用或打出", + check(card) { + var val = get.value(card); + return 5 - val; + }, + ai: { + effect: { + target(card, player, target, current) { + if (get.tag(card, "respondSha") && current < 0) return 0.6; + }, + }, + respondSha: true, + }, + }, + }, + ai: { + fireAttack: true, + halfneg: true, + threaten: 1.05, + }, + }, + tytaoyuan: { + enable: "phaseUse", + usable: 1, + filterCard: true, + selectCard: 2, + position: "he", + filterTarget: true, + check(card){ + return 4-get.value(card); + }, + async content(event, trigger, player) { + const card = game.createCard("taoyuan", "heart", 1); + if (card) await event.target.gain(card, "gain2"); + }, + ai: { + order: 4, + result:{ + target(player, target) { + if (target.getUseValue("taoyuan") * get.sgnAttitude(player, target) >= player.getUseValue("wuzhong")) return 1; + return 0; + }, + }, + }, + }, + //关银屏 + tywuji: { + skillAnimation: true, + animationColor: "orange", + audio: "wuji", + trigger: { player: "phaseJieshuBegin" }, + forced: true, + juexingji: true, + filter(event, player) { + return player.getStat("damage") >= 3; + }, + async content(event, trigger, player) { + player.awakenSkill(event.name); + await player.gainMaxHp(); + await player.recover(); + await player.removeSkills("huxiao"); + const result = await player + .chooseControl("获得青龙刀", "摸两张牌") + .set("prompt", "武继:选择一项") + .set("ai", () => 1) + .forResult(); + if (result.index == 0) { + const card = game.createCard("qinglong", "spade", 5); + if (card) { + await player.gain(card, "gain2", "log"); + } + } + else await player.draw(2); + }, + }, + //沙和尚 + tymanyong: { + trigger: { + player: ["phaseZhunbeiBegin", "phaseJieshuBegin"], + }, + filter(event, player) { + let hasCard = player.getEquips("tiejili").length > 0; + if (event.name == "phaseZhunbei") return !hasCard; + return hasCard; + }, + async content(event, trigger, player) { + if (trigger.name == "phaseZhunbei") { + const card = game.createCard("tiejili", "spade", 5); + if (card) { + player.$gain2(card); + await player.equip(card); + } + } + else { + const cards = player.getEquips("tiejili"); + if (cards?.length) await player.discard(cards); + } + }, + }, + //关兴 + tyconglong: { + trigger: { + global: ["useCard", "damageBegin1", "phaseEnd"], + }, + filter(event, player) { + if (event.name == "phase") { + let num = 0; + player.getHistory("lose", evt => { + if (evt.type == "discard") num += evt.cards2.length; + }); + return num >= 2; + } + if (!event.card || event.card.name != "sha" || get.color(event.card) != "red") return false; + return player.countCards("he", card => get.type2(card) == (event.name == "damage" ? "equip" : "trick")); + }, + frequent: true, + async cost(event, trigger, player) { + if (trigger.name == "phase") { + event.result = await player + .chooseBool(get.prompt("tyconglong"), "摸一张牌") + .set("frequentSkill", "tyconglong") + .forResult(); + } + else { + const eff1 = get.damageEffect(trigger.player, trigger.source, player); + const eff2 = get.attitude(player, trigger.player); + event.result = await player + .chooseToDiscard("he", card => { + const type = _status.event.typex; + return get.type2(card) == type; + }) + .set("typex", trigger.name == "damage" ? "equip" : "trick") + .set("prompt", get.prompt("tyconglong")) + .set("prompt2", trigger.name == "damage" ? "令此伤害+1" : "令此牌不可响应") + .set("eff", trigger.name == "damage" ? eff1 : eff2) + .set("ai", card => { + if (get.event("eff") <= 0) return 0; + if (get.color(card) == "red") return 4 - get.value(card); + return 8 - get.value(card); + }) + .set("chooseonly", true) + .forResult(); + } + }, + async content(event, trigger, player) { + if (trigger.name == "phase") await player.draw(); + else { + await player.discard(event.cards); + if (trigger.name == "damage") trigger.num++; + else trigger.directHit.addArray(game.players); + } + }, + }, + tyzhaowu: { + trigger: { + player: "damageEnd", + }, + filter(event, player) { + if (!player.countCards("he")) return false; + return event.source && event.source != player; + }, + async cost(event, trigger, player) { + event.result = await player + .chooseToDiscard("he", get.prompt2("tyzhaowu", trigger.source)) + .set("ai", card => { + let player = get.player(), target = get.event().getTrigger().source; + if (get.attitude(player, target) >= 0 || player.getStorage("tyzhaowu").includes(target)) return 0; + return 7 - get.value(card); + }) + .set("chooseonly", true) + .forResult(); + event.result.targets = [trigger.source]; + }, + async content(event, trigger, player) { + await player.discard(event.cards); + player.addTempSkill("tyzhaowu_wusheng", "roundStart"); + player.markAuto("tyzhaowu_wusheng", event.targets); + }, + subSkill: { + wusheng: { + mark: true, + intro: { + content: "本轮可对$使用父亲的力量", + }, + charlotte: true, + onremove: true, + mod: { + targetInRange(card, player, target) { + if (player.getStorage("tyzhaowu_wusheng").includes(target)) return true; + }, + playerEnabled(card, player, target) { + if (player.getStorage("tyzhaowu_wusheng").includes(target)) return; + if (card.storage?.tyzhaowu) return false; + }, + }, + locked: false, + audio: "new_rewusheng", + enable: "chooseToUse", + filterCard(card, player) { + return get.color(card) == "red"; + }, + position: "hes", + viewAs: { + name: "sha", + storage: { + tyzhaowu: true, + }, + }, + viewAsFilter(player) { + if (!player.countCards("hes", { color: "red" })) return false; + }, + prompt: "将一张红色牌当杀使用或打出", + check(card) { + var val = get.value(card); + return 5 - val; + }, + ai: { + respondSha: true, + skillTagFilter: function (player) { + if (!player.countCards("hes", { color: "red" })) return false; + }, + }, + }, + }, + }, + //侍从 + tyjinzhong: { + trigger: { + player: ["phaseUseBegin", "damageEnd"], + }, + filter(event, player) { + if (game.hasPlayer(i => i.getSeatNum() == 1 || get.nameList(i).some(name => get.rawName(name) == "刘备"))) return true; + if (player.countCards("h")) return true; + return false; + }, + async cost(event, trigger, player) { + const result = await player + .chooseControl("选项一", "选项二", "cancel2") + .set("choiceList", [ + "失去一点体力,令一号位或“刘备”回复一点体力", + "交给一名角色至多两张手牌", + ]) + .set("prompt", get.prompt("tyjinzhong")) + .set("choice", function () { + let targets = game.filterPlayer(i => i.getSeatNum() == 1 || get.nameList(i).some(name => get.rawName(name) == "刘备")); + if (targets?.length && targets.some(i => get.attitude(player, i) > 0 && i.hp <= player.hp)) return "选项一"; + if (game.hasPlayer(i => get.attitude(player, i) > 0 && player.countCards("h") > Math.min(2, player.hp))) return "选项二"; + return "cancel2"; + }()) + .set("ai", () => get.event("choice")) + .forResult(); + if (result.control == "cancel2") { + event.result = { bool: false }; + return; + } + if (result.control == "选项一") { + event.result = await player + .chooseTarget("尽忠:是否失去一点体力并令一号位或“刘备”回复一点体力?", function (card, player, target) { + return target.getSeatNum() == 1 || get.nameList(target).some(name => get.rawName(name) == "刘备"); + }) + .set("ai", target => { + if (get.attitude(get.player(), target) <= 0) return 0; + return player.hp + 1 - target.hp; + }) + .forResult(); + } + else { + event.result = await player + .chooseCardTarget({ + filterCard: true, + selectCard: [1, 2], + position: "h", + filterTarget: lib.filter.notMe, + prompt: "尽忠:是否交给一名其他角色至多两张牌?", + ai1(card) { + return 8 - get.value(card); + }, + ai2(target) { + let player = _status.event.player, + card = ui.selected.cards[0], + att = get.attitude(player, target); + if (att <= 0) return 0; + return target.getUseValue(card) + 4; + }, + }) + .forResult(); + } + }, + async content(event, trigger, player) { + if (event.cards?.length > 0) { + await player.give(event.cards, event.targets[0]); + } + else { + await player.loseHp(); + await event.targets[0].recover(); + } + }, + }, + //吴班 + tyyoujun: { + audio: "dcyouzhan", + enable: "phaseUse", + usable: 1, + filterTarget(card, player, target) { + return target.countGainableCards(player, "he") && target != player; + }, + async content(event, trigger, player) { + const target = event.target; + await player.gainPlayerCard(target, "he", true); + const result = await target + .chooseBool("是否令你所有手牌视为杀,然后视为对" + get.translation(player) + "使用决斗?") + .set("choice", get.effect(player, { name: "juedou" }, target, target) > 0) + .forResult(); + if (result.bool) { + target.addTempSkill("tyyoujun_sha"); + const card = { name: "juedou", isCard: true }; + if (target.canUse(card, player)) await target.useCard(card, player); + } + }, + subSkill: { + sha: { + charlotte: true, + mod: { + cardname(card) { + return "sha"; + }, + }, + }, + }, + ai: { + order: 5, + result: { + target(player, target) { + if (player.hp == 1) return 0; + return get.effect(target, { name: "shunshou_copy2" }, player, target); + }, + }, + }, + }, + tyjicheng: { + skillAnimation: true, + animationColor: "fire", + limited: true, + trigger: { + player: "damageEnd", + }, + filter(event, player) { + if (player.hp > 2) return false; + return event.card && get.type(event.card) == "trick"; + }, + async content(event, trigger, player) { + player.awakenSkill(event.name); + await player.chooseDrawRecover(2, true); + }, + }, + //黄忠 + tyyizhuang: { + trigger: { player: "phaseZhunbeiBegin" }, + filter(event, player) { + return player.countCards("j"); + }, + check(event, player) { + return player.hp > 1 && player.countCards("j", card => card.viewAs || card.name != "jsrg_xumou"); + }, + async content(event, trigger, player) { + await player.damage(); + await player.discardPlayerCard(player, "j", true, player.countCards("j")); + }, + }, + //廖化 + tydangxian: { + trigger: { player: "phaseBegin" }, + forced: true, + audio: "dangxian", + async content(event, trigger, player) { + const cards = Array.from(ui.discardPile.childNodes).filter(card => card.name == "sha"); + if (cards.length) { + const result = await player.chooseButton(["获得一张杀", cards], true).forResult(); + if (result.bool) await player.gain(result.links, "gain2"); + } + game.updateRoundNumber(); + trigger.phaseList.splice(trigger.num, 0, "phaseUse|tydangxian"); + }, + }, + tyfuli: { + audio: "xinfuli", + skillAnimation: true, + animationColor: "soil", + unique: true, + limited: true, + enable: "chooseToUse", + mark: true, + filter(event, player) { + if (event.type != "dying") return false; + if (player != event.dying) return false; + return true; + }, + async content(event, trigger, player) { + player.awakenSkill(event.name); + await player.recoverTo(2); + await player.drawTo(2); + }, + ai: { + save: true, + skillTagFilter(player, arg, target) { + return player == target; + }, + result: { + player: 10, + }, + threaten: function (player, target) { + if (!target.storage.tyfuli) return 0.9; + }, + }, + intro: { + content: "limited", + }, + }, + //冯习 + tyqingkou: { + trigger: { + player: "phaseJieshuBegin", + }, + frequent: true, + async content(event, trigger, player) { + const result = await player.draw("bottom").forResult(); + await player.showCards(get.translation(player) + "发动了【轻寇】", result); + if (result?.length != 1) return; + let list = [], card = result[0]; + for (let name of lib.inpile) { + if (get.type(name) == "trick" && get.cardNameLength(name) == player.hp) { + list.push(["锦囊", "", name]); + } + } + list.push(["基本", "", "sha"]); + const result2 = await player + .chooseButton([`是否将${get.translation(result)}当作其中一张使用?`, [list, "vcard"]]) + .set("filterButton", button => { + let card = get.autoViewAs({ name: button.link[2], natrue: button.link[3] }, get.event("resultCard")); + return get.player().hasUseTarget(card); + }) + .set("resultCard", [card]) + .set("ai", button => { + let card = get.autoViewAs({ name: button.link[2], natrue: button.link[3] }, get.event("resultCard")); + return get.player().getUseValue(card); + }).forResult(); + if (result2.bool && player.getCards("h").includes(card)) { + const cardx = { name: result2.links[0][2], natrue: result2.links[0][3] }; + game.broadcastAll(function (card) { + lib.skill.tyqingkou_backup.viewAs = card; + lib.skill.tyqingkou_backup.prompt = `是否将此牌当作${get.translation(card)}使用?`; + }, cardx); + const next = player.chooseToUse(); + next.set("cards", result); + next.set("openskilldialog", `是否将此牌当作${get.translation(cardx)}使用?`); + next.set("norestore", true); + next.set("_backupevent", "tyqingkou_backup"); + next.set("custom", { + add: {}, + replace: { window: function () { } }, + }); + next.backup("tyqingkou_backup"); + await next; + } + }, + subSkill: { + backup: { + filterCard: function (card) { + return get.itemtype(card) == "card" && get.event("cards").includes(card); + }, + position: "h", + selectCard: 1, + check: card => 7 - get.value(card), + popname: true, + }, + }, + }, + //张南 + tyfenwu: { + trigger: { + player: "phaseZhunbeiBegin", + }, + frequent: true, + async content(event, trigger, player) { + const result = await player.draw().forResult(); + await player.showCards(get.translation(player) + "发动了【奋武】", result); + if (result?.length != 1) return; + let list = [], card = result[0]; + for (let name of lib.inpile) { + if (get.type(name) == "basic" && get.cardNameLength(name) == get.cardNameLength(card)) { + list.push(["基本", "", name]); + if (name == "sha") { + for (let nature of lib.inpile_nature) list.push(["基本", "", name, nature]); + } + } + } + list.push(["锦囊", "", "juedou"]); + const result2 = await player + .chooseButton([`是否将${get.translation(result)}当作其中一张使用?`, [list, "vcard"]]) + .set("filterButton", button => { + let card = get.autoViewAs({ name: button.link[2], natrue: button.link[3] }, get.event("resultCard")); + return get.player().hasUseTarget(card); + }) + .set("resultCard", [card]) + .set("ai", button => { + let card = get.autoViewAs({ name: button.link[2], natrue: button.link[3] }, get.event("resultCard")); + return get.player().getUseValue(card); + }).forResult(); + if (result2.bool && player.getCards("h").includes(card)) { + const cardx = { name: result2.links[0][2], natrue: result2.links[0][3] }; + game.broadcastAll(function (card) { + lib.skill.tyfenwu_backup.viewAs = card; + lib.skill.tyfenwu_backup.prompt = `是否将此牌当作${get.translation(card)}使用?`; + }, cardx); + const next = player.chooseToUse(); + next.set("cards", result); + next.set("openskilldialog", `是否将此牌当作${get.translation(cardx)}使用?`); + next.set("norestore", true); + next.set("_backupevent", "tyfenwu_backup"); + next.set("custom", { + add: {}, + replace: { window: function () { } }, + }); + next.backup("tyfenwu_backup"); + await next; + } + }, + subSkill: { + backup: { + filterCard: function (card) { + return get.itemtype(card) == "card" && get.event("cards").includes(card); + }, + position: "h", + selectCard: 1, + check: card => 7 - get.value(card), + popname: true, + }, + }, + }, + //赵融 + tyyuantao: { + trigger: { + global: "useCard", + }, + usable: 1, + filter(event, player) { + if (!event.targets.length) return false; + return get.type(event.card) == "basic"; + }, + check(event, player) { + return get.effect(event.targets[0], event.card, event.player, player) > 0 && player.hp > 2; + }, + async content(event, trigger, player) { + trigger.effectCount++; + player.when({ global: "phaseEnd" }).then(() => { + player.loseHp(); + }); + }, + }, + //程畿 + tyzhongen: { + audio: 2, + trigger: { + global: "phaseJieshuBegin", + }, + filter(event, player) { + return player.getHistory("gain").length + player.getHistory("lose", evt => evt.hs?.length).length; + }, + async cost(event, trigger, player) { + const target = trigger.player, + goon = player.hasCard(card => { + if (_status.connectMode) return true; + return get.name(card, player) == "sha" && game.checkMod(card, player, "unchanged", "cardEnabled2", player) !== false && lib.filter.targetEnabled2(get.autoViewAs({ name: "wuzhong" }, [card]), player, target); + }, "hs"); + let list = []; + if (goon) list.push("选项一"); + list.addArray(["选项二", "cancel2"]); + const { result } = await player + .chooseControl(list) + .set("choiceList", [`将一张【杀】当【无中生有】对${get.translation(target)}使用`, `使用一张无距离限制的【杀】`]) + .set("ai", () => { + const player = get.event("player"), + target = get.event().getTrigger().player; + return get.effect(target, { name: "wuzhong" }, player, player) > player.getUseValue({ name: "sha" }) ? 0 : 1; + }); + event.result = { + bool: result.control != "cancel2", + skill_popup: false, + cost_data: result.control, + }; + }, + async content(event, trigger, player) { + const index = event.cost_data, + target = trigger.player; + if (index == "选项一") { + const { + result: { bool, cards }, + } = await player + .chooseCard( + "hes", + true, + (card, player) => { + if (get.name(card, player) != "sha") return false; + if (!game.checkMod(card, player, "unchanged", "cardEnabled2", player)) return false; + return lib.filter.targetEnabled2(get.autoViewAs({ name: "wuzhong" }, [card]), player, get.event("target")); + }, + "将一张【杀】当作【无中生有】对" + get.translation(target) + "使用" + ) + .set("ai", card => { + const player = get.event("player"), + target = get.event("target"); + return get.effect(target, get.autoViewAs({ name: "wuzhong" }, [card]), player, player) / Math.max(1, get.value(card)); + }) + .set("target", target); + if (bool) { + player.logSkill(event.name, target); + await player.useCard({ name: "wuzhong" }, cards, target, false); + } + } else { + await player + .chooseToUse(function (card, player, event) { + if (get.name(card) != "sha") return false; + return lib.filter.filterCard.apply(this, arguments); + }, "忠恩:是否使用一张【杀】?") + .set("targetRequired", true) + .set("complexSelect", true) + .set("filterTarget", function (card, player, target) { + return lib.filter.targetEnabled.apply(this, arguments); + }) + .set("logSkill", event.name) + .set("addCount", false) + .forResult(); + } + }, + }, + tyliebao: { + trigger: { global: "useCardToTarget" }, + filter(event, player) { + if (event.card.name != "sha" || event.targets?.includes(player)) return false; + if (!event.target.isMinHandcard()) return false; + return lib.filter.targetEnabled(event.card, event.player, player); + }, + check(event, player) { + return get.attitude(player, event.target) > 0 && (player.hp > 2 || player.countCards("h", "shan")); + }, + logTarget: "target", + async content(event, trigger, player) { + const target = event.targets[0]; + const evt = trigger.getParent(); + evt.triggeredTargets2.remove(target); + evt.targets.remove(target); + evt.targets.push(player); + await player.draw(); + target.when({ global: "useCardAfter" }).filter(evt => evt.card == trigger.card).then(() => { + if (!skiller.hasHistory("damage", evt => evt.getParent("useCard") == evtx) && player.isDamaged()) player.recover(); + }).vars({ + skiller: player, + evtx: evt, + }); + }, + }, + //龙果子 + tyzhuan: { + audio: "qingbei", + enable: "phaseUse", + filterCard(card, player) { + return get.name(card, player) == "sha"; + }, + filterTarget(card, player, target) { + return target != player && target.countCards("ej", card => get.type(card, target) == "equip"); + }, + check(card) { + return 5 - get.value(card); + }, + filter(event, player) { + if (!player.countCards("he", card => lib.skill.tyzhuan.filterCard(card, player))) return false; + return game.hasPlayer(target => lib.skill.tyzhuan.filterTarget(event, player, target)); + }, + async content(event, trigger, player) { + const target = event.target; + if (!target.countCards("ej", card => get.type(card, target) == "equip")) return; + await player.gainPlayerCard("ej", target, true).set("filterButton", button => { + return get.type(button.link, get.owner(button.link)) == "equip"; + }); + }, + ai: { + order(item, player) { + if (!player.hasCard(card => player.hasValueTarget(card), "h")) return 9; + return 1; + }, + result: { + target: -1, + }, + }, + subfrequent: ["draw"], + group: "tyzhuan_draw", + subSkill: { + draw: { + audio: "qingbei", + trigger: { global: "useCardAfter" }, + filter(event, player) { + return get.type(event.card, null, false) == "equip"; + }, + frequent: true, + prompt2: "摸一张牌", + content() { + player.draw(); + }, + }, + }, + }, + //龙刘备 + tyqingshi: { + audio: 2, + trigger: { player: "phaseZhunbeiBegin" }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget([1, player.hp], get.prompt2("tyqingshi"), function (card, player, target) { + return target.countCards("h"); + }) + .set("ai", target => { + return Math.max(0.1, get.attitude(get.player(), target)); + }) + .forResult(); + }, + async content(event, trigger, player) { + await player.chooseToDebate(event.targets.sortBySeat()).set("callback", lib.skill.tyqingshi.callback); + }, + async callback(event, trigger, player) { + const result = event.debateResult; + if (result.bool && result.opinion) { + var opinion = result.opinion, + targets = result[opinion].map(i => i[0]); + if (opinion == "red") { + for (const target of targets) { + target.addTempSkill("tyqingshi_distance", "roundStart"); + target.addMark("tyqingshi_distance", 1, false); + } + } + else { + await player.draw(targets.length); + let gains = [], give_map = []; + while (true) { + const result = await player.chooseCardTarget({ + filterCard(card) { + return get.itemtype(card) == "card" && !card.hasGaintag("mbjiejian_tag"); + }, + filterTarget(card, player, target) { + return get.event("canGain")(target) && target != player; + }, + prompt: "倾师:是否分配手牌?", + prompt2: "请选择要分配的卡牌和目标", + ai1(card) { + return 8 - get.value(card); + }, + ai2(target) { + let player = _status.event.player, + card = ui.selected.cards[0], + att = get.attitude(player, target); + if (att <= 0) return 0; + return target.getUseValue(card) + 4; + }, + }).set("canGain", (target) => { + return targets.includes(target) && !gains.includes(target); + }).forResult(); + if (result.bool && result.targets?.length) { + give_map.add([result.targets[0], result.cards]); + player.addGaintag(result.cards, "mbjiejian_tag"); + gains.addArray(result.targets); + } + else break; + if (!game.hasPlayer(i => i != player && targets.includes(i) && !gains.includes(i))) break; + } + await game.loseAsync({ + gain_list: give_map, + player: player, + cards: give_map.map(i => i[1]).flat(), + giver: player, + animate: "giveAuto", + }).setContent("gaincardMultiple"); + } + } + }, + subSkill: { + distance: { + charlotte: true, + mod: { + globalFrom(from, to, distance) { + return distance + from.countMark("tyqingshi_distance"); + }, + globalTo(from, to, distance) { + return distance + to.countMark("tyqingshi_distance"); + }, + }, + onremove: true, + mark: true, + intro: { + content: "你与其他角色的相互距离+$", + }, + }, + }, + }, + tyyilin: { + audio: 2, + trigger: { + global: ["gainAfter", "loseAsyncAfter"], + }, + getIndex(event, player) { + if (event.name == "loseAsync" && event.type != "gain") return []; + if (!event.getl || !event.getg) return []; + let cardsx = event.getl(player).cards2, cardsy = event.getg(player); + return game.filterPlayer(current => { + if (current == player) return false; + if (player.getHistory("useSkill", evt => evt.skill == "tyyilin" && evt.targets?.includes(current)).length) return false; + if (cardsx.length) { + let cards = event.getg(current); + if (cards?.length && cards.some(card => cardsx.includes(card))) return true; + } + if (cardsy.length) { + let evt = event.getl(current); + if (evt?.cards2?.length && evt.cards2.some(card => cardsy.includes(card))) return true; + } + return false; + }).sortBySeat(); + }, + logTarget(event, player, name, target) { + return target; + }, + check(event, player, name, target) { + return get.attitude(player, target) > 0; + }, + async content(event, trigger, player) { + const target = event.targets[0]; + let cards1 = trigger.getl(player)?.cards2, cards2 = trigger.getg(player); + let cardsx = trigger.getl(target)?.cards2, cardsy = trigger.getg(target); + if (cards1?.some(card => cardsy.includes(card))) { + await target.chooseToUse({ + filterCard(card) { + if (get.itemtype(card) != "card" || !get.event("useCard").includes(card)) return false; + return lib.filter.filterCard.apply(this, arguments); + }, + prompt: "是否使用获得的一张牌?", + }).set("useCard", cards1); + } + if (cardsx?.some(card => cards2.includes(card))) { + await player.chooseToUse({ + filterCard(card) { + if (get.itemtype(card) != "card" || !get.event("useCard").includes(card)) return false; + return lib.filter.filterCard.apply(this, arguments); + }, + prompt: "是否使用获得的一张牌?", + }).set("useCard", cardsx); + } + }, + }, + tychengming: { + audio: 2, + skillAnimation: true, + animationColor: "fire", + trigger: { player: "dying" }, + zhuSkill: true, + filter: function (event, player) { + if (player.hp > 0) return false; + if (!player.hasZhuSkill("tychengming")) return false; + return game.hasPlayer(function (current) { + return current != player && current.group == "shu"; + }); + }, + mark: true, + unique: true, + limited: true, + async cost(event, trigger, player) { + event.result = await player.chooseTarget(get.prompt2("tychengming"), function (card, player, target) { + return target != player && target.group == "shu"; + }).set("ai", target => { + return Math.max(1, get.attitude(get.player(), target)); + }).forResult(); + }, + async content(event, trigger, player) { + player.awakenSkill(event.name); + let cards = player.getCards("hej"), target = event.targets[0]; + if (cards.length) await target.gain(cards, "give"); + await player.recoverTo(1); + let skills = target.getSkills(null, false, false).filter(skill => { + var info = get.info(skill); + if (!info || info.charlotte || !get.is.locked(skill) || get.skillInfoTranslation(skill, target).length == 0) return false; + return true; + }); + if (skills.length) await target.addSkills("rerende"); + }, + }, + //蜀孙权-孩子们,其实我早就是蜀国人了 + tyfuhan: { + audio: 2, + trigger: { + global: ["gainAfter", "loseAsyncAfter"], + }, + getIndex(event, player) { + if (event.name == "loseAsync" && event.type != "gain") return []; + if (!event.getl || !event.getg) return []; + let cardsx = event.getl(player).cards2, cardsy = event.getg(player); + return game.filterPlayer(current => { + if (current == player) return false; + if (cardsx.length) { + let cards = event.getg(current); + if (cards?.length && cards.some(card => cardsx.includes(card))) return true; + } + if (cardsy.length) { + let evt = event.getl(current); + if (evt?.cards2?.length && evt.cards2.some(card => cardsy.includes(card))) return true; + } + return false; + }).sortBySeat(); + }, + filter: function (event, player, name, target) { + if (!target.isIn()) return false; + return true; + }, + async cost(event, trigger, player) { + const target = event.indexedData; + let dialog = [get.prompt("tyfuhan", player, target)], list1 = [], list2 = [], bool = false; + for (let i = 1; i < 6; i++) { + if (player.hasEnabledSlot(i)) list1.push(i); + if (player.hasDisabledSlot(i)) list2.push(i); + } + if (list2.length && trigger.getl(player)?.cards2?.length && trigger.getg(target).some(card => trigger.getl(player).cards2.includes(card))) { + dialog.push("恢复其一个装备栏"); + dialog.push([list2.map(i => [[i, true], get.translation(`equip${i}`) + "栏"]), "tdnodes"]); + bool = true; + } + if (list1.length && trigger.getg(player) && trigger.getl(target)?.cards2.some(card => trigger.getg(player).includes(card))) { + dialog.push("废除其一个装备栏"); + dialog.push([list1.map(i => [[i, false], get.translation(`equip${i}`) + "栏"]), "tdnodes"]); + bool = true; + } + if (bool) { + const result = await target + .chooseButton(dialog) + .set("ai", button => { + const type = button.link[1]; + if (_status.event.att > 0) { + if (!_status.event.used || type) return 1 + Math.random(); + return 0; + } + return type ? 0 : (1 + Math.random()); + }) + .set("used", player.getHistory("useSkill", evt => evt.skill == "tyfuhan").length > 0) + .set("att", get.attitude(target, _status.currentPhase)) + .forResult(); + event.result = { + bool: result.bool, + targets: [target], + cost_data: result.links[0], + }; + } + else event.result = { bool: false }; + }, + async content(event, trigger, player) { + const cost = event.cost_data; + if (cost[1]) await player.enableEquip(cost[0]); + else await player.disableEquip(cost[0]); + }, + group: "tyfuhan_draw", + subSkill: { + draw: { + trigger: { + global: "phaseEnd", + }, + filter(event, player) { + if (!_status.currentPhase || _status.currentPhase.countCards("h") >= _status.currentPhase.maxHp) return false; + return player.getHistory("useSkill", evt => evt.skill == "tyfuhan").length; + }, + forced: true, + locked: true, + logTarget: () => _status.currentPhase, + async content(event, trigger, player) { + await event.targets[0].drawTo(event.targets[0].maxHp); + }, + }, + }, + }, + tychende: { + audio: 2, + enable: "phaseUse", + filterCard: true, + selectCard: [2, Infinity], + filter(event, player) { + return player.countCards("h") > 1; + }, + check(card) { + const player = get.player(); + if (ui.selected.cards.length >= 2) return 0; + if (player.getUseValue(card)) return 10 - get.value(card); + return 6 - get.value(card); + }, + position: "he", + lose: false, + delay: false, + discard: false, + filterTarget: lib.filter.notMe, + async content(event, trigger, player) { + const target = event.target, + cards = event.cards; + await player.showCards(get.translation(player) + "发动了【臣德】", cards); + await player.give(cards, target, true); + let list = []; + for (let card of cards) { + if (player.hasUseTarget(card, true, true) && ["trick", "basic"].includes(get.type(card))) list.push([get.type(card), "", get.name(card, false), get.nature(card, false)]); + } + if (!list.length) return; + const result = await player + .chooseButton(["臣德:是否视为使用其中一张?", [list, "vcard"]]) + .set("ai", button => { + return get.player().getUseValue(button.link[2]); + }) + .forResult(); + if (result.bool) await player.chooseUseTarget({ name: result.links[0][2], nature: result.links[0][3] }, true); + }, + ai: { + order: 6, + result: { + target: 1, + }, + }, + }, + tywansu: { + audio: 2, + trigger: { + global: ["useCard", "damageBefore"], + }, + filter(event, player) { + if (!event.card || !get.is.virtualCard(event.card)) return false; + if (event.name == "useCard") return game.players.some(target => target.hasDisabledSlot()); + return true; + }, + forced: true, + logTarget(event, player) { + if (event.name == "useCard") return game.players.filter(target => target.hasDisabledSlot()); + return event.player; + }, + async content(event, trigger, player) { + if (trigger.name == "useCard") trigger.directHit.addArray(event.targets); + else { + trigger.cancel(); + trigger.player.loseHp(trigger.num); + } + }, + ai: { + jueqing: true, + }, + }, + //神秘将军-孩子们,其实我没有死 + tywusheng: { + audio: 2, + enable: ["chooseToRespond", "chooseToUse"], + filterCard(card, player) { + return get.color(card) == "red"; + }, + position: "hes", + viewAs: { + name: "sha", + storage: { + tywusheng: true, + }, + }, + viewAsFilter(player) { + if (!player.countCards("hes", { color: "red" })) return false; + }, + precontent: function () { + var targets = event.result.targets; + for (var target of targets) { + target.addTempSkill("tywusheng_guanjue"); + } + }, + prompt: "将一张红色牌当杀使用或打出", + check(card) { + const val = get.value(card); + if (_status.event.name == "chooseToRespond") return 1 / Math.max(0.1, val); + return 5 - val; + }, + ai: { + skillTagFilter(player) { + if (!player.countCards("hes", { color: "red" })) return false; + }, + respondSha: true, + }, + subSkill: { + guanjue: { + mod: { + cardEnabled(card, player) { + let evt = _status.event; + if (evt.name != "chooseToUse") evt = evt.getParent("chooseToUse"); + if (!evt || !evt.respondTo) return; + const cardx = evt.respondTo[1]; + if (!cardx.storage?.tywusheng) return; + const suit = get.suit(card); + if (suit != "unsure" && suit != get.suit(cardx)) return false; + }, + }, + charlotte: true, + }, + }, + }, + tychengshi: { + audio: 2, + trigger: { + source: "damageSource", + }, + forced: true, + usable: 1, + filter(event, player) { + if (!_status.currentPhase) return false; + if (_status.currentPhase != player && !event.player.isIn()) return false; + return event.card?.name == "sha" && get.color(event.card) == "red"; + }, + async content(event, trigger, player) { + if (player == _status.currentPhase) { + let evt = trigger.getParent("useCard", true); + if (evt?.addCount !== false) { + evt.addCount = false; + evt.player.getStat().card.sha--; + } + } + else if (trigger.player.isIn()) { + trigger.player.addTempSkill("tychengshi_tiaoxin", { global: lib.phaseName.map(i => `${i}End`) }); + trigger.player.markAuto("tychengshi_tiaoxin", [player]); + } + }, + subSkill: { + tiaoxin: { + mark: true, + intro: { + content(storage, player) { + if (!storage || !storage.length) return "无记录"; + if (storage.length > 1) return "不能使用伤害类牌指定任何人"; + return `不能使用伤害类牌指定${get.translation(storage)}以外的角色`; + }, + }, + charlotte: true, + onremove: true, + mod: { + playerEnabled(card, player, target) { + if (!get.tag(card, "damage")) return; + let storage = player.getStorage("tychengshi_tiaoxin"); + if (!storage.length) return; + if (storage.length > 1 || !player.getStorage("tychengshi_tiaoxin").includes(target)) return false; + }, + }, + }, + }, + }, + tyfuwei: { + audio: 2, + trigger: { + global: "damageEnd", + }, + filter(event, player) { + if (!player.countCards("he") || !event.player.isIn() || event.player == player) return false; + if (event.player.getSeatNum() == 1) return true; + if (get.nameList(event.player).some(name => get.rawName(name) == "刘备")) return true; + }, + usable: 1, + async cost(event, trigger, player) { + event.result = await player.chooseCardTarget({ + prompt: get.prompt("tyfuwei", trigger.player), + prompt2: `交给其至多${trigger.num}张牌,然后可以对伤害来源使用至多${trigger.num}张杀`, + filterCard: true, + selectCard: [1, trigger.num], + position: "he", + filterTarget(card, player, target) { + return target == _status.event.getTrigger().player; + }, + ai1(card) { + return 4 - get.value(card); + }, + ai2(target) { + let att = get.attitude(_status.event.player, target); + return Math.max(0, att); + }, + }).forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0], cards = event.cards; + await player.give(cards, target); + if (!trigger.source || !trigger.source.isIn() || !player.canUse(get.autoViewAs({ name: "sha" }, "unsure"), trigger.source, false)) return; + let num = 0; + while (num < trigger.num) { + const { result } = await player + .chooseToUse(function (card, player, event) { + if (get.name(card) != "sha") return false; + return lib.filter.filterCard.apply(this, arguments); + }, `抚危:是否对${get.translation(trigger.source)}使用一张杀?(${num}/${trigger.num})`) + .set("targetRequired", true) + .set("complexSelect", true) + .set("filterTarget", function (card, player, target) { + if (target != _status.event.sourcex && !ui.selected.targets.includes(_status.event.sourcex)) return false; + return lib.filter.targetEnabled.apply(this, arguments); + }) + .set("sourcex", trigger.source); + if (result.bool == false) break; + else num++; + } + }, + }, + //九鼎-徐晃 + jdsbduanliang: { + audio: "sbduanliang", + inherit: "sbduanliang", + async content(event, trigger, player) { + const target = event.targets[0]; + const result = await player + .chooseToDuiben(target) + .set("title", "谋弈") + .set("namelist", ["固守城池", "突出重围", "围城断粮", "擂鼓进军"]) + .set("translationList", [`以防止${get.translation(player)}通过此技能对你使用【决斗】`, `以防止${get.translation(player)}通过此技能对你使用【兵粮寸断】`, `若成功,你摸一张牌,然后可以将一张黑色非锦囊牌当做【兵粮寸断】对${get.translation(target)}使用`, `若成功,视为对${get.translation(target)}使用【决斗】`]) + .set("ai", button => { + var source = _status.event.getParent().player, + target = _status.event.getParent().target; + if (get.effect(target, { name: "juedou" }, source, source) >= 10 && button.link[2] == "db_def2" && Math.random() < 0.5) return 10; + return 1 + Math.random(); + }) + .forResult(); + if (result.bool) { + if (result.player == "db_def1") { + await player.draw(); + if (target.hasJudge("bingliang") && target.countGainableCards(player, "he")) await player.gainPlayerCard(target, "he", true); + else { + const next = player.chooseToUse(); + next.set("openskilldialog", "断粮:是否将一张黑色非锦囊牌当作【兵粮寸断】对" + get.translation(target) + "使用?"); + next.set("norestore", true); + next.set("_backupevent", "jdsbduanliang_backup"); + next.set("custom", { + add: {}, + replace: { window: function () { } }, + }); + next.backup("jdsbduanliang_backup"); + next.set("targetRequired", true); + next.set("complexSelect", true); + next.set("filterTarget", function (card, player, target) { + if (target != _status.event.sourcex) return false; + return lib.filter.targetEnabled.apply(this, arguments); + }); + next.set("sourcex", target); + await next; + } + } else { + const card = { name: "juedou", isCard: true }; + if (player.canUse(card, target)) await player.useCard(card, target); + } + } + }, + subSkill: { + backup: { + viewAs: { + name: "bingliang", + }, + filterCard(card, player) { + return get.itemtype(card) == "card" && get.color(card, player) == "black" && get.type2(card) != "trick"; + }, + position: "hes", + selectCard: 1, + check(card) { + return 6 - get.value(card); + }, + }, + }, + }, + //九鼎--王元姬 + jdshiren: { + audio: "shiren", + trigger: { player: "showCharacterAfter" }, + filter(event, player) { + if (!event.toShow?.some(i => get.character(i).skills?.includes("jdshiren"))) return false; + const target = _status.currentPhase; + return target && target != player && target.isAlive() && target.countCards("h") > 0; + }, + logTarget: () => _status.currentPhase, + hiddenSkill: true, + content() { + const next = game.createEvent("jdyanxi", false); + next.player = player; + next.target = _status.currentPhase; + next.setContent(lib.skill["jdyanxi"].content); + }, + }, + jdyanxi: { + audio: "yanxi", + inherit: "yanxi", + async content(event, trigger, player) { + const target = event.target; + const [card] = await player.choosePlayerCard(target, "h", true).forResult("cards"); + if (card) { + const videoId = lib.status.videoId++; + game.addVideo("showCards", player, [`${get.translation(player)}对${get.translation(target)}发动了【宴戏】`, get.cardsInfo([card])]); + game.broadcastAll( + (card, id, player, target) => { + let dialog; + if (player === game.me) dialog = ui.create.dialog(`${get.translation(target)}手牌展示中...`); + else dialog = ui.create.dialog(`${get.translation(player)}对${get.translation(target)}发动了【宴戏】`, [card]); + dialog.forcebutton = true; + dialog.videoId = id; + }, + card, + videoId, + player, + target + ); + await game.delay(2); + game.broadcastAll("closeDialog", videoId); + let cards = [card].concat(get.cards(2)).randomSort(); + game.log(player, "展示了", cards); + const videoIdx = lib.status.videoId++; + const str = get.translation(player) + "对" + get.translation(target) + "发动了【宴戏】"; + game.broadcastAll( + (str, id, cards) => { + const dialog = ui.create.dialog(str, cards); + dialog.videoId = id; + }, + str, + videoIdx, + cards + ); + game.addVideo("showCards", player, [str, get.cardsInfo(cards)]); + const func = function (id, target) { + const dialog = get.idDialog(id); + if (dialog) dialog.content.firstChild.innerHTML = "猜猜哪张是" + get.translation(target) + "的手牌?"; + }; + if (player == game.me) func(videoIdx, target); + else if (player.isOnline()) player.send(func, videoIdx, target); + const next = player.chooseButton(true); + next.set("dialog", videoIdx); + next.set("ai", button => { + const evt = get.event(); + if (evt.answer) return button.link == evt.answer ? 1 : 0; + return get.value(button.link, evt.player); + }); + if (player.hasSkillTag("viewHandcard", null, target, true)) next.set("answer", card); + const result = await next.forResult(); + game.broadcastAll("closeDialog", videoIdx); + if (result.bool) { + const card2 = result.links[0]; + cards.remove(card2); + if (card2 == card) { + player.popup("洗具"); + player.$gain2(cards); + await player.gain(cards, "log"); + await player.gain(card, target, "bySelf", "give"); + } else { + player.popup("杯具"); + await player.gain(card2, "gain2"); + const { result } = await player + .chooseToMove("宴戏:将剩余的牌以任意顺序置于牌堆顶", true) + .set("list", [["牌堆顶", cards]]) + .set("reverse", _status.currentPhase && _status.currentPhase.next && get.attitude(player, _status.currentPhase.next) > 0) + .set("processAI", list => { + const cards = list[0][1].slice(0); + cards.sort((a, b) => { + return (_status.event.reverse ? 1 : -1) * (get.value(b) - get.value(a)); + }); + return [cards]; + }); + if (!result.bool) return; + cards = result.moved[0]; + cards.reverse(); + if (cards.includes(card)) { + target.$throw(1, 1000); + await target.lose([card], ui.special); + } + await game.cardsGotoPile(cards, "insert"); + game.log(player, "将", cards, "置于了牌堆顶"); + } + } + } + }, + }, + //九鼎-华歆 + jdcaozhao: { + audio: "caozhao", + trigger: { global: "phaseUseBegin" }, + filter(event, player) { + if ( + lib.inpile.every(i => { + return player.getStorage("jdcaozhao").includes(i); + }) + ) + return false; + return event.player.countCards("h") && event.player.getHp() <= player.getHp(); + }, + async cost(event, trigger, player) { + const target = trigger.player; + event.result = await player + .choosePlayerCard(target, "h", get.prompt2("jdcaozhao", target)) + .set("ai", () => { + const player = get.player(), + target = get.event().getTrigger().player; + if (lib.inpile.some(i => !player.getStorage("jdcaozhao").includes(i) && target.getUseValue(i) * get.attitude(player, target) > 0)) return 1 + Math.random(); + return 0; + }) + .forResult(); + }, + logTarget: "player", + round: 1, + async content(event, trigger, player) { + const target = trigger.player; + await player.showCards(event.cards, get.translation(player) + "对" + get.translation(target) + "发动了【草诏】"); + const result = await player + .chooseButton( + [ + "草诏:请选择一个基本牌或锦囊牌", + [ + lib.inpile.filter(i => { + return !player.getStorage("jdcaozhao").includes(i); + }), + "vcard", + ], + ], + true + ) + .set("ai", button => { + const player = get.player(), + target = get.event().getTrigger().player, + sgn = get.sgn(get.attitude(player, target)); + const cards = get.event().getParent().cards, + card = get.autoViewAs({ name: button.link[2] }, cards); + if (!target.hasUseTarget(card) || target.getUseValue(card) * sgn <= 0) Math.random(); + return 5 + target.getUseValue(card) * sgn; + }) + .forResult(); + if (result.bool) { + const name = result.links[0][2]; + player.markAuto("jdcaozhao", [name]); + player.popup(name, "thunder"); + game.log(player, "声明了", "#y" + get.translation(name)); + const card = get.autoViewAs({ name: name }, event.cards); + let resultx; + if (!target.hasUseTarget(card)) resultx = { bool: false }; + else + resultx = await target + .chooseUseTarget('###草诏###
    使用' + get.translation(card) + "(" + get.translation(event.cards) + "),或失去1点体力
    ", card, false) + .set("cards", event.cards) + .forResult(); + if (!resultx.bool) await target.loseHp(); + } + }, + }, + //九鼎-杨婉 + jdmingxuan: { + audio: "spmingxuan", + trigger: { player: "phaseUseBegin" }, + filter(event, player) { + const num = Math.min( + player + .getCards("h") + .slice() + .map(i => get.suit(i, player)) + .unique().length, + game.countPlayer(current => { + return current != player && !player.getStorage("jdmingxuan").includes(current); + }) + ); + return num > 0; + }, + forced: true, + async content(event, trigger, player) { + const num = Math.min( + player + .getCards("h") + .slice() + .map(i => get.suit(i, player)) + .unique().length, + game.countPlayer(current => { + return current != player && !player.getStorage("jdmingxuan").includes(current); + }) + ); + const result = await player + .chooseCard("h", true, [1, num], "瞑昡:请选择至多" + get.cnNumber(num) + "张花色各不相同的手牌", (card, player) => { + if (!ui.selected.cards.length) return true; + return !ui.selected.cards.some(i => get.suit(i, player) == get.suit(card)); + }) + .set("complexCard", true) + .set("ai", card => 6 - get.value(card)) + .forResult(); + if (result.bool && result.cards?.length > 0) { + let cards = result.cards.slice().randomSort(); + let targets = game.filterPlayer(current => current != player && !player.getStorage("jdmingxuan").includes(current)).sortBySeat(player); + const dialog = ui.create.dialog("瞑昡", cards, true); + _status.dieClose.push(dialog); + dialog.videoId = lib.status.videoId++; + event.dialogID = dialog.videoId; + game.addVideo("cardDialog", null, ["瞑昡", get.cardsInfo(cards), dialog.videoId]); + game.broadcast( + function (cards, id) { + var dialog = ui.create.dialog("瞑昡", cards, true); + _status.dieClose.push(dialog); + dialog.videoId = id; + }, + cards, + dialog.videoId + ); + while (cards.length && targets.length) { + await game.delayx(); + const target = targets.shift(); + const resultx = await target + .chooseButton(true, button => { + return get.value(button.link, _status.event.player); + }) + .set("dialog", event.dialogID) + .set("closeDialog", false) + .set("dialogdisplay", true) + .set("cardFilter", cards.slice()) + .set("filterButton", button => { + return _status.event.cardFilter.includes(button.link); + }) + .forResult(); + if (resultx.bool) { + const card = resultx.links[0]; + if (card) { + cards.remove(card); + const capt = get.translation(target) + "选择了" + get.translation(card); + game.broadcastAll( + (card, id, name, capt) => { + const dialog = get.idDialog(id); + if (dialog) { + dialog.content.firstChild.innerHTML = capt; + for (let i = 0; i < dialog.buttons.length; i++) { + if (dialog.buttons[i].link == card) { + dialog.buttons[i].querySelector(".info").innerHTML = name; + break; + } + } + game.addVideo("dialogCapt", null, [dialog.videoId, dialog.content.firstChild.innerHTML]); + } + }, + card, + event.dialogID, + (target => { + if (target._tempTranslate) return target._tempTranslate; + const name = target.name; + if (lib.translate[name + "_ab"]) return lib.translate[name + "_ab"]; + return get.translation(name); + })(target), + capt + ); + await target.gain(card, player, "give"); + } + const resulty = await target + .chooseToUse(function (card, player, event) { + if (get.name(card) != "sha") return false; + return lib.filter.filterCard.apply(this, arguments); + }, "对" + get.translation(player) + "使用一张杀,否则交给其一张牌且其摸一张牌") + .set("targetRequired", true) + .set("complexSelect", true) + .set("filterTarget", function (card, player, target) { + if (target != _status.event.sourcex && !ui.selected.targets.includes(_status.event.sourcex)) return false; + return lib.filter.filterTarget.apply(this, arguments); + }) + .set("sourcex", player) + .set("addCount", false) + .forResult(); + if (resulty.bool) player.markAuto("jdmingxuan", [target]); + else { + await target.chooseToGive("he", true, player, "交给" + get.translation(player) + "一张牌"); + await player.draw(); + } + } + } + for (let i = 0; i < ui.dialogs.length; i++) { + if (ui.dialogs[i].videoId == event.dialogID) { + const dialogx = ui.dialogs[i]; + dialogx.close(); + _status.dieClose.remove(dialogx); + break; + } + } + game.broadcast(id => { + const dialog = get.idDialog(id); + if (dialog) { + dialog.close(); + _status.dieClose.remove(dialog); + } + }, event.dialogID); + game.addVideo("cardDialog", null, event.dialogID); + } + }, + intro: { content: "已被$使用过杀" }, + }, + //九鼎-黄月英 + jdjizhi: { + audio: "sbjizhi", + trigger: { player: "useCard" }, + filter(event, player) { + return get.type(event.card) == "trick"; + }, + forced: true, + content() { + "step 0"; + player.draw(); + "step 1"; + player.addTempSkill("jdjizhi_mark"); + player.addMark("jdjizhi_mark", 1, false); + }, + subSkill: { + mark: { + charlotte: true, + onremove: true, + intro: { content: "手牌上限+#" }, + charlotte: true, + onremove: true, + mod: { + maxHandcard(player, num) { + return num + player.countMark("jdjizhi_mark"); + }, + }, + }, + }, + }, + jdqicai: { + audio: "sbqicai", + enable: "phaseUse", + filter(event, player) { + return player.countCards("he", { type: "equip" }); + }, + filterCard(card) { + return !ui.selected.cards.length && get.type(card) == "equip"; + }, + selectCard: [1, 2], + filterTarget: lib.filter.notMe, + position: "he", + check(card) { + return 8 - get.value(card); + }, + complexCard: true, + complexSelect: true, + lose: false, + discard: false, + delay: false, + usable: 1, + get prompt() { + return lib.translate.jdqicai_info.slice("①你使用锦囊牌无距离限制。②".length); + }, + async content(event, trigger, player) { + const target = event.target; + const str = get.translation(player); + await player.showCards(event.cards, get.translation(player) + "发动了【奇才】"); + await player.give(event.cards, target); + const result = await target + .chooseCard( + player, + 2, + "he", + card => { + return get.type(card) !== "equip"; + }, + "奇才:交给" + str + "两张非装备牌,或令" + str + "获得两张普通锦囊牌" + ) + .forResult(); + if (!result.bool) { + let gains = []; + while (gains.length < 2) { + const card = get.cardPile(i => get.type(i) == "trick" && !gains.includes(i)); + if (card) gains.push(card); + else break; + } + if (gains.length) await player.gain(gains, "gain2"); + else { + player.chat("无牌可得?!"); + game.log("但是牌堆和弃牌堆都没有普通锦囊牌了!"); + } + } else { + await target.showCards(result.cards); + await target.give(result.cards, player); + } + }, + ai: { + order: 7, + result: { + target(player, target) { + const att = get.attitude(player, target); + return get.sgn(att) * (2 + get.sgn(att)); + }, + }, + }, + mod: { + targetInRange(card) { + if (get.type2(card) == "trick") return true; + }, + }, + locked: false, + }, + //九鼎-赵云 + jdlongdan: { + audio: "sblongdan", + enable: ["chooseToUse", "chooseToRespond"], + filter(event, player) { + if (event.type == "wuxie") return false; + var marked = player.hasSkill("sblongdan_mark", null, null, false); + for (var name of lib.inpile) { + if (!marked && name != "sha" && name != "shan") continue; + if (get.type(name) != "basic") continue; + if (player.hasCard(lib.skill.jdlongdan.getFilter(name, player), "hs")) { + if (event.filterCard(get.autoViewAs({ name }, "unsure"), player, event)) return true; + if (marked && name == "sha") { + for (var nature of lib.inpile_nature) { + if (event.filterCard(get.autoViewAs({ name, nature }, "unsure"), player, event)) return true; + } + } + } + } + return false; + }, + chooseButton: { + dialog(event, player) { + var list = []; + var marked = player.hasSkill("sblongdan_mark", null, null, false); + for (var name of lib.inpile) { + if (!marked && name != "sha" && name != "shan") continue; + if (get.type(name) != "basic") continue; + if (player.hasCard(lib.skill.jdlongdan.getFilter(name, player), "hs")) { + if (event.filterCard(get.autoViewAs({ name }, "unsure"), player, event)) list.push(["基本", "", name]); + if (marked && name == "sha") { + for (var nature of lib.inpile_nature) { + if (event.filterCard(get.autoViewAs({ name, nature }, "unsure"), player, event)) list.push(["基本", "", name, nature]); + } + } + } + } + return ui.create.dialog("龙胆", [list, "vcard"], "hidden"); + }, + check(button) { + if (_status.event.getParent().type != "phase") return 1; + var player = _status.event.player, + card = { name: button.link[2], nature: button.link[3] }; + if (card.name == "jiu" && player.countCards("h", { type: "basic" }) < 2) return 0; + return player.getUseValue(card, null, true); + }, + backup(links, player) { + return { + viewAs: { + name: links[0][2], + nature: links[0][3], + }, + filterCard: lib.skill.jdlongdan.getFilter(links[0][2], player), + position: "he", + popname: true, + check(card) { + return 6 / Math.max(1, get.value(card)); + }, + precontent() { + player.addTempSkill("jdlongdan_draw"); + }, + }; + }, + prompt(links, player) { + var marked = player.hasSkill("sblongdan_mark", null, null, false); + var card = { + name: links[0][2], + nature: links[0][3], + isCard: true, + }; + if (marked) return "将一张基本牌当作【" + get.translation(card) + "】使用"; + return "将一张【" + (card.name == "sha" ? "闪" : "杀") + "】当作【" + get.translation(card) + "】使用"; + }, + }, + hiddenCard(player, name) { + if (get.type(name) != "basic") return false; + var marked = player.hasSkill("sblongdan_mark", null, null, false); + if (!marked && name != "sha" && name != "shan") return false; + return player.hasCard(lib.skill.jdlongdan.getFilter(name, player), "hs"); + }, + ai: { + respondSha: true, + respondShan: true, + skillTagFilter(player, tag) { + return lib.skill.jdlongdan.hiddenCard(player, tag == "respondSha" ? "sha" : "shan"); + }, + order: 9, + result: { + player(player) { + if (_status.event.dying) return get.attitude(player, _status.event.dying); + return 1; + }, + }, + }, + getFilter(name, player) { + if (!player.hasSkill("sblongdan_mark", null, null, false)) { + if (name == "sha") return { name: "shan" }; + if (name == "shan") return { name: "sha" }; + return () => false; + } + return { type: "basic" }; + }, + derivation: "jdlongdanx", + onremove(player) { + player.removeSkill("sblongdan_mark"); + }, + subSkill: { + backup: { audio: "sblongdan" }, + mark: { charlotte: true }, + draw: { + charlotte: true, + trigger: { player: ["useCardAfter", "respondAfter"] }, + filter(event, player) { + if (player.hasSkill("jdlongdan_mark")) return false; + return event.skill == "jdlongdan_backup"; + }, + forced: true, + popup: false, + *content(event, map) { + const player = map.player; + const result = yield player.draw(2); + if (Array.isArray(result) && result.length) player.addTempSkill("jdlongdan_mark", ["phaseChange", "phaseAfter"]); + }, + }, + }, + }, + //九鼎-甘宁 + jdqixi: { + audio: "sbqixi", + inherit: "sbqixi", + filterCard(card) { + return lib.suit.includes(get.suit(card)); + }, + check(card) { + return 7 - get.value(card); + }, + position: "h", + lose: false, + discard: false, + async content(event, trigger, player) { + const target = event.target; + let suits = lib.suit.slice().reverse(), + num = 0; + while (suits.length > 0) { + const control = await target + .chooseControl(suits) + .set("prompt", "奇袭:猜测" + get.translation(player) + "选择的牌的花色") + .set("ai", () => { + var player = _status.event.getParent().player, + controls = _status.event.controls; + if (player.countCards("h") <= 3 && controls.includes("diamond") && Math.random() < 0.3) return "diamond"; + return controls.randomGet(); + }) + .forResult("control"); + if (control) { + target.chat("我猜是" + get.translation(control) + "!"); + game.log(target, "猜测为", "#y" + control); + if (!event.isMine() && !event.isOnline()) await game.delayx(); + if (get.suit(event.cards[0]) !== control) { + player.chat("猜错了!"); + game.log(target, "猜测", "#y错误"); + suits.remove(control); + num++; + continue; + } else { + player.chat(num == 0 ? "这么准?" : "猜对了!"); + game.log(target, "猜测", "#g正确"); + const card = event.cards[0]; + if (get.owner(card) == player && get.position(card) == "h") { + await player.showCards([card], get.translation(player) + "选择的手牌"); + if (lib.filter.cardDiscardable(card, player)) await player.discard([card]); + } + if (num > 0 && target.countDiscardableCards(player, "hej")) { + player.line(target); + player.discardPlayerCard(target, num, true, "hej"); + } + break; + } + } else break; + } + }, + }, + jdfenwei: { + unique: true, + limited: true, + audio: "sbfenwei", + trigger: { global: "useCardToPlayered" }, + filter(event, player) { + if (!event.isFirstTarget || get.type(event.card) != "trick") return false; + return event.targets.length <= 2; + }, + direct: true, + skillAnimation: true, + animationColor: "wood", + content() { + "step 0"; + player + .chooseTarget(get.prompt("jdfenwei"), "令" + get.translation(trigger.card) + "对任意名角色无效", [1, trigger.targets.length], (card, player, target) => { + return _status.event.targets.includes(target); + }) + .set("ai", target => { + var trigger = _status.event.getTrigger(); + return -get.effect(target, trigger.card, trigger.player, _status.event.player); + }) + .set("targets", trigger.targets); + "step 1"; + if (result.bool) { + player.logSkill("jdfenwei", result.targets); + player.awakenSkill("jdfenwei"); + trigger.getParent().excluded.addArray(result.targets); + if (result.targets.includes(player)) player.addSkill("jdfenwei_qixi"); + } + }, + ai: { expose: 0.2 }, + subSkill: { + qixi: { + charlotte: true, + trigger: { global: "phaseEnd" }, + async cost(event, trigger, player) { + const result = await player + .chooseCardTarget({ + prompt: get.prompt2("jdqixi"), + prompt2: lib.translate.jdqixi_info.slice("出牌阶段限一次,你可以".length), + filterCard: lib.skill.jdqixi.filterCard, + filterTarget: lib.skill.jdqixi.filterTarget, + position: lib.skill.jdqixi.position, + ai1: lib.skill.jdqixi.check, + ai2: target => { + const player = get.player(); + return get.effect(target, "twyuanhu", player, player); + }, + }) + .forResult(); + event.result = result; + if (result.bool) event.result.cost_data = result; + }, + popup: false, + async content(event, trigger, player) { + const result = event.cost_data; + result.skill = "jdqixi"; + player.useResult(result, event); + }, + }, + }, + }, + //九鼎-庞统 + jdlianhuan: { + audio: "sblianhuan", + trigger: { player: "useCardToPlayered" }, + filter(event, player) { + return event.card.name == "tiesuo" && !event.target.isLinked() && event.target.countCards("he"); + }, + direct: true, + content() { + const target = trigger.target; + player.discardPlayerCard(target, "he", get.prompt("jdlianhuan", target)).logSkill = ["jdlianhuan", target]; + }, + group: "jdlianhuan_lianhuan", + subSkill: { + lianhuan: { + audio: "sblianhuan", + inherit: "lianhuan", + prompt: "将♣手牌当作【铁索连环】使用或重铸", + }, + }, + }, + //九鼎-韩龙 + jdcibei: { + audio: "cibei", + inherit: "cibei", + group: ["jdcibei_gain", "jdcibei_fullyReady"], + subSkill: { + fullyReady: { + audio: "cibei", + trigger: { global: "phaseEnd" }, + filter(event, player) { + var storage = player.getExpansions("duwang"); + return storage.length > 0 && storage.every(i => i.name == "sha"); + }, + forced: true, + locked: false, + *content(event, map) { + const player = map.player; + yield player.gain(player.getExpansions("duwang"), "gain2"); + player.addSkill("jdcibei_effect"); + }, + }, + effect: { + mod: { + cardUsable(card) { + if (card.name == "sha") return Infinity; + }, + targetInRange(card) { + if (card.name == "sha") return true; + }, + }, + charlotte: true, + mark: true, + marktext: "杀", + intro: { content: "准备完毕!本局游戏使用【杀】无距离和次数限制" }, + }, + gain: { + audio: "cibei", + trigger: { global: "phaseEnd" }, + filter(event, player) { + return player.hasHistory("lose", evt => evt.type == "discard" && evt.cards.filterInD("d").some(i => i.name == "sha")); + }, + forced: true, + locked: false, + content() { + player.gain( + player + .getHistory("lose", evt => { + return evt.type == "discard" && evt.cards.filterInD("d").filter(i => i.name == "sha"); + }) + .slice() + .map(evt => { + return evt.cards.filterInD("d").filter(i => i.name == "sha"); + }) + .flat(), + "gain2" + ); + }, + }, + }, + }, + //九鼎-夏侯徽 + jdbaoqie: { + audio: "baoqie", + trigger: { player: "showCharacterAfter" }, + forced: true, + hiddenSkill: true, + filter(event, player) { + return event.toShow?.some(i => get.character(i).skills?.includes("jdbaoqie")); + }, + content() { + "step 0"; + var card = get.cardPile(function (card) { + return get.subtype(card, false) == "equip2" && !get.cardtag(card, "gifts"); + }); + if (!card) { + event.finish(); + return; + } + event.card = card; + player.gain(card, "gain2"); + "step 1"; + if (player.getCards("h").includes(card) && get.subtype(card) == "equip2") player.chooseUseTarget(card).nopopup = true; + }, + }, + //九鼎-曹操 + jdjianxiong: { + audio: "sbjianxiong", + inherit: "sbjianxiong", + filter(event, player) { + return (get.itemtype(event.cards) == "cards" && event.cards.some(i => get.position(i, true) == "o")) || 2 - player.countMark("sbjianxiong") > 0; + }, + prompt2(event, player) { + var gain = get.itemtype(event.cards) == "cards" && event.cards.some(i => get.position(i, true) == "o"), + draw = 2 - player.countMark("sbjianxiong"); + var str = ""; + if (gain) str += "获得" + get.translation(event.cards); + if (gain && draw > 0) str += "并"; + if (draw > 0) str += "摸" + get.cnNumber(draw) + "张牌"; + if (player.countMark("sbjianxiong")) str += ",然后可以弃1枚“治世”"; + return str; + }, + content() { + "step 0"; + if (get.itemtype(trigger.cards) == "cards" && trigger.cards.some(i => get.position(i, true) == "o")) { + player.gain(trigger.cards, "gain2"); + } + var num = player.countMark("sbjianxiong"); + if (2 - num > 0) player.draw(2 - num, "nodelay"); + if (!num) event.finish(); + "step 1"; + player.chooseBool("是否弃1枚“治世”?").set("ai", () => { + var player = _status.event.player, + current = _status.currentPhase; + if (get.distance(current, player, "absolute") > 3 && player.hp <= 2) return true; + return false; + }); + "step 2"; + if (result.bool) player.removeMark("sbjianxiong", 1); + }, + ai: { + maixie: true, + maixie_hp: true, + effect: { + target(card, player, target) { + if (player.hasSkillTag("jueqing", false, target)) return [1, -1]; + if (get.tag(card, "damage") && player != target) { + var cards = card.cards, + evt = _status.event; + if (evt.player == target && card.name == "damage" && evt.getParent().type == "card") cards = evt.getParent().cards.filterInD(); + if (target.hp <= 1) return; + if (get.itemtype(cards) != "cards") return; + for (var i of cards) { + if (get.name(i, target) == "tao") return [1, 4.5]; + } + if (get.value(cards, target) >= 7 + target.getDamagedHp()) return [1, 2]; + return [1, 0.55 + 0.05 * Math.max(0, 2 - target.countMark("sbjianxiong"))]; + } + }, + }, + }, + group: "jdjianxiong_mark", + }, + //九鼎-诸葛亮 + jdhuoji: { + audio: "sbhuoji", + dutySkill: true, + derivation: ["jdguanxing", "sbkongcheng"], + group: ["jdhuoji_fire", "jdhuoji_achieve", "jdhuoji_fail", "jdhuoji_mark"], + subSkill: { + fire: { + audio: "sbhuoji1.mp3", + enable: "phaseUse", + filterTarget: lib.filter.notMe, + prompt: "选择一名其他角色,对其与其势力相同的所有其他角色各造成1点火属性伤害", + usable: 1, + line: "fire", + content: function () { + "step 0"; + target.damage("fire"); + "step 1"; + var targets = game.filterPlayer(current => { + if (current == player || current == target) return false; + return current.group == target.group; + }); + if (targets.length) { + game.delayx(); + player.line(targets, "fire"); + targets.forEach(i => i.damage("fire")); + } + }, + ai: { + order: 7, + fireAttack: true, + result: { + target: function (player, target) { + var att = get.attitude(player, target); + return ( + get.sgn(att) * + game + .filterPlayer(current => { + if (current == player) return false; + return current.group == target.group; + }) + .reduce((num, current) => num + get.damageEffect(current, player, player, "fire"), 0) + ); + }, + }, + }, + }, + achieve: { + audio: "jdhuoji2.mp3", + trigger: { player: "phaseZhunbeiBegin" }, + filter: function (event, player) { + return player.getAllHistory("sourceDamage", evt => evt.hasNature("fire") && evt.player != player).reduce((num, evt) => num + evt.num, 0) >= game.players.length + game.dead.length; + }, + forced: true, + locked: false, + skillAnimation: true, + animationColor: "fire", + async content(event, trigger, player) { + player.awakenSkill("jdhuoji"); + game.log(player, "成功完成使命"); + player.changeSkin("jdhuoji", "sb_zhugeliang"); + player.changeSkills(["jdguanxing", "sbkongcheng"], ["jdhuoji", "jdkanpo"]); + }, + }, + fail: { + audio: "jdhuoji3.mp3", + trigger: { player: "dying" }, + forced: true, + locked: false, + content: function () { + player.awakenSkill("jdhuoji"); + game.log(player, "使命失败"); + }, + }, + mark: { + charlotte: true, + trigger: { source: "damage" }, + filter: function (event, player) { + return event.hasNature("fire"); + }, + firstDo: true, + forced: true, + popup: false, + content: function () { + player.addTempSkill("jdhuoji_count", { + player: ["jdhuoji_achieveBegin", "jdhuoji_failBegin"], + }); + player.storage.jdhuoji_count = player.getAllHistory("sourceDamage", evt => evt.hasNature("fire") && evt.player != player).reduce((num, evt) => num + evt.num, 0); + player.markSkill("jdhuoji_count"); + }, + }, + count: { + charlotte: true, + intro: { content: "本局游戏已造成过#点火属性伤害" }, + }, + }, + }, + jdkanpo: { + audio: "sbkanpo", + trigger: { + global: ["phaseBefore", "useCard"], + player: "enterGame", + }, + filter(event, player) { + if (event.name == "useCard") + return player + .getExpansions("jdkanpo") + .slice() + .map(i => i.name) + .includes(event.card.name); + return event.name != "phase" || game.phaseNumber == 0; + }, + async cost(event, trigger, player) { + if (trigger.name == "useCard") { + event.result = await player + .chooseButton(["###" + get.prompt("jdkanpo") + "###弃置一张同名牌,令" + get.translation(trigger.card) + "无效", player.getExpansions("jdkanpo")]) + .set("filterButton", button => { + const name = get.event().getTrigger().card.name; + return button.link.name == name; + }) + .set("ai", () => { + const player = get.player(), + trigger = get.event().getTrigger(); + return lib.skill.sbkanpo.subSkill.kanpo.check(trigger, player) ? 1 : 0; + }) + .forResult(); + if (event.result.bool) { + event.result.cards = event.result.links; + event.result.targets = [trigger.player]; + } + } else event.result = { bool: true }; + }, + async content(event, trigger, player) { + if (trigger.name == "useCard") { + await player.loseToDiscardpile(event.cards); + trigger.targets.length = 0; + trigger.all_excluded = true; + game.log(trigger.card, "被无效了"); + await player.draw(); + } else { + await player.draw(3); + if (player.countCards("h")) { + const result = await player + .chooseCard("看破:是否将至多三张牌置于武将牌上?", [1, 3]) + .set("ai", card => { + switch (card.name) { + case "wuxie": + return 5 + Math.random(); + case "sha": + return 5 + Math.random(); + case "tao": + return 4 + Math.random(); + case "jiu": + return 3 + Math.random(); + case "lebu": + return 3 + Math.random(); + case "shan": + return 4.5 + Math.random(); + case "wuzhong": + return 4 + Math.random(); + case "shunshou": + return 2.7 + Math.random(); + case "nanman": + return 2 + Math.random(); + case "wanjian": + return 1.6 + Math.random(); + default: + return 0; + } + }) + .forResult(); + if (result.bool) await player.addToExpansion(result.cards, player, "give").set("gaintag", ["jdkanpo"]); + } + } + }, + marktext: "谋", + intro: { + content: "expansion", + markcount: "expansion", + }, + onremove(player, skill) { + const cards = player.getExpansions(skill); + if (cards.length) player.loseToDiscardpile(cards); + }, + }, + jdguanxing: { + audio: "sbguanxing", + inherit: "sbguanxing", + trigger: { player: "phaseZhunbeiBegin" }, + filter(event, player) { + const bool = player.hasCard(card => card.hasGaintag("sbguanxing"), "s"); + return bool || 7 - 3 * player.countMark("sbguanxingx") > 0; + }, + async content(event, trigger, player) { + player.addMark("sbguanxingx", 1, false); + const cards = player.getCards("s", card => card.hasGaintag("sbguanxing")); + if (cards.length) player.loseToDiscardpile(cards); + const num = Math.max(0, 7 - 3 * (player.countMark("sbguanxingx") - 1)); + if (num) { + const cards2 = get.cards(num); + player.$gain2(cards2, false); + game.log(player, "将", cards2, "置于了武将牌上"); + await player.loseToSpecial(cards2, "sbguanxing").set("visible", true); + player.markSkill("sbguanxing"); + } + }, + group: ["sbguanxing_unmark", "jdguanxing_put"], + subSkill: { + put: { + audio: "sbguanxing", + enable: "phaseUse", + filter(event, player) { + return player.hasCard(card => card.hasGaintag("sbguanxing"), "s"); + }, + filterCard(card) { + return card.hasGaintag("sbguanxing"); + }, + selectCard: [1, Infinity], + position: "s", + lose: false, + discard: false, + delay: 0, + prompt: "将任意张“星”置于牌堆顶", + content() { + player.loseToDiscardpile(cards, ui.cardPile, "insert").log = false; + game.log(player, "将", cards, "置于了牌堆顶"); + }, + }, + }, + }, + //九鼎-司马师 + jdtairan: { + audio: "tairan", + inherit: "tairan", + trigger: { + player: "phaseJieshuBegin", + }, + async content(event, trigger, player) { + const maxHp = player.maxHp; + const hp = maxHp - player.getHp(); + if (hp > 0) await player.recoverTo(maxHp); + const num = maxHp - player.countCards("h"); + if (num > 0) await player.drawTo(maxHp); + player + .when("phaseUseBegin") + .then(() => { + if (hp > 0) player.loseHp(hp); + }) + .then(() => { + if (player.countCards("h") && num > 0) player.chooseToDiscard("h", num, true); + }) + .vars({ hp: hp, num: num }); + }, + }, + //九鼎-张飞 + jdsbpaoxiao: { + audio: "sbpaoxiao", + inherit: "sbpaoxiao", + content() { + if (!trigger.card.storage) trigger.card.storage = {}; + trigger.card.storage.jdsbpaoxiao = true; + trigger.baseDamage++; + trigger.directHit.addArray(game.players); + player.addTempSkill(event.name + "_effect", "phaseUseAfter"); + }, + subSkill: { + effect: { + inherit: "sbpaoxiao_effect", + filter(event, player) { + return event.card.storage && event.card.storage.jdsbpaoxiao && event.target.isIn(); + }, + group: "jdsbpaoxiao_recoil", + }, + recoil: { + inherit: "sbpaoxiao_recoil", + filter(event, player) { + return event.card && event.card.storage && event.card.storage.jdsbpaoxiao && event.player.isIn(); + }, + async content(event, trigger, player) { + await player.loseHp(); + if (player.countDiscardableCards(trigger.player, "h")) await trigger.player.discardPlayerCard(player, "h", true); + }, + }, + }, + }, + //九鼎-法正 + jdsbxuanhuo: { + audio: "sbxuanhuo", + inherit: "sbxuanhuo", + group: "jdsbxuanhuo_rob", + filterTarget(card, player, target) { + return !target.hasMark("jdsbxuanhuo_mark") && player != target; + }, + onremove(player) { + delete player.storage.jdsbxuanhuo; + player.unmarkSkill("jdsbxuanhuo"); + }, + subSkill: { + mark: { + marktext: "眩", + intro: { + name: "眩惑", + name2: "眩", + markcount: () => 0, + content: "已获得“眩”标记", + }, + }, + rob: { + audio: "jdsbxuanhuo", + inherit: "sbxuanhuo_rob", + filter(event, player, name, target) { + const evt = event.getParent("phaseDraw"); + if (evt && evt.name == "phaseDraw") return false; + if (!event.getg(target).length || !target.hasMark("jdsbxuanhuo_mark")) return false; + if (evt && evt.player == target) return false; + if (lib.skill.sbxuanhuo.getNum(target, "jdsbxuanhuo_rob", "jdsbxuanhuo_mark") >= 5) return false; + return target.hasCard(card => lib.filter.canBeGained(card, target, player), "he"); + }, + getIndex(event, player) { + const evt = event.getParent("phaseDraw"); + if (evt && evt.name == "phaseDraw") return false; + return game + .filterPlayer(current => { + if (!event.getg(current).length || !current.hasMark("jdsbxuanhuo_mark")) return false; + if (evt && evt.player == current) return false; + if (lib.skill.sbxuanhuo.getNum(current, "jdsbxuanhuo_rob", "jdsbxuanhuo_mark") >= 5) return false; + return current.hasCard(card => lib.filter.canBeGained(card, current, player), "he"); + }) + .sortBySeat(); + }, + async content(event, trigger, player) { + const target = event.targets[0], + hs = target.getCards("h", card => lib.filter.canBeGained(card, target, player)); + if (hs.length) { + await player.gainPlayerCard(target, "h", true); + if (!player.storage.jdsbxuanhuo) player.storage.jdsbxuanhuo = {}; + player.storage.jdsbxuanhuo[target.playerid] = lib.skill.sbxuanhuo.getNum(target, "jdsbxuanhuo_rob", "jdsbxuanhuo_mark"); + player.markSkill("jdsbxuanhuo"); + } + }, + }, + }, + }, + jdsbenyuan: { + audio: "sbenyuan", + inherit: "sbenyuan", + filter(event, player, name, target) { + return target?.isIn() && target.hasMark("jdsbxuanhuo_mark"); + }, + getIndex(event, player) { + return game.filterPlayer(target => target.hasMark("jdsbxuanhuo_mark")).sortBySeat(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + target.clearMark("jdsbxuanhuo_mark"); + for (const current of game.players) { + const storage = current.storage.jdsbxuanhuo; + if (storage && storage[target.playerid]) delete storage[target.playerid]; + if (storage && get.is.empty(storage)) { + delete current.storage.jdsbxuanhuo; + current.unmarkSkill("jdsbxuanhuo"); + } + } + if (target.countCards("h") < player.countCards("h")) { + const num = Math.min(player.countCards("he"), 2); + if (num) await player.chooseToGive(target, `恩怨:交给${get.translation(target)}${get.cnNumber(num)}张牌`, true, num, "he"); + } else { + await target.loseHp(); + await player.recover(); + } + }, + ai: { + combo: "jdsbxuanhuo", + }, + }, + //九鼎-刘备 + jdsbzhangwu: { + audio: "sbzhangwu", + enable: "phaseUse", + filter(event, player) { + return player.countMark("sbrende"); + }, + limited: true, + chooseButton: { + dialog(event, player) { + return ui.create.dialog("###章武###" + get.translation("jdsbzhangwu_info")); + }, + chooseControl(event, player) { + return Array.from({ + length: player.countMark("sbrende"), + }) + .map((_, i) => get.cnNumber(i + 1, true)) + .concat(["cancel2"]); + }, + check(event, player) { + const choices = Array.from({ + length: player.countMark("sbrende"), + }).map((_, i) => get.cnNumber(i + 1, true)); + return choices.length - 1; + }, + backup(result, player) { + return { + num: result.index + 1, + audio: "sbzhangwu", + filterCard: () => false, + selectCard: -1, + skillAnimation: "epic", + animationColor: "orange", + async content(event, trigger, player) { + player.awakenSkill("jdsbzhangwu"); + const num = lib.skill.jdsbzhangwu_backup.num; + player.removeMark("sbrende", num); + await player.draw(num); + player.tempBanSkill("sbrende", { player: "dying" }); + player.addTempSkill("new_repaoxiao2"); + }, + }; + }, + prompt(result, player) { + return `移去${result.index + 1}枚“仁望”并摸等量张牌`; + }, + }, + ai: { + order: 9, + combo: "sbrende", + result: { + player(player, target) { + return player.countMark("sbrende") > 3 ? 1 : 0; + }, + }, + }, + subSkill: { + backup: {}, + }, + }, + //九鼎-孙尚香 + jdsbjieyin: { + audio: "sbjieyin", + trigger: { + player: "phaseUseBegin", + }, + filter(event, player) { + return game.hasPlayer(current => current.countCards("h") <= player.countCards("h")); + }, + locked: true, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget( + get.prompt2(event.name.slice(0, -5)), + (card, player, target) => { + return target.countCards("h") <= player.countCards("h"); + }, + true + ) + .set("ai", target => { + return get.attitude(get.player(), target) * (target.countCards("h") + 1); + }) + .forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + const num = Math.min(2, Math.max(1, target.countCards("h"))); + let bool; + if (player == target) bool = !target.countCards("h") ? false : await player.chooseBool(get.prompt(event.name), "是否获得1点护甲?").forResultBool(); + else + bool = await target + .chooseToGive(player, `交给${get.translation(player)}${get.cnNumber(num)}张手牌,然后获得1点护甲;或令其回复1点体力并获得所有“妆”,然后其减少1点体力上限,变更势力为吴`, num, "h") + .set("ai", card => { + if (_status.event.goon) return 100 - get.value(card); + return 0; + }) + .set("goon", get.attitude(target, player) > 1) + .forResultBool(); + if (bool) await target.changeHujia(1, null, true); + else { + await player.recover(); + if (player.getExpansions("jdsbliangzhu").length) await player.gain(player.getExpansions("jdsbliangzhu"), "gain2"); + await player.loseMaxHp(); + if (player.group != "wu") await player.changeGroup("wu"); + } + }, + }, + jdsbliangzhu: { + audio: "sbliangzhu", + inherit: "sbliangzhu", + async content(event, trigger, player) { + const target = event.targets[0]; + const cards = await player.choosePlayerCard(target, "e", true).forResultCards(); + if (!cards || !cards.length) return; + const next = player.addToExpansion(cards, target, "give"); + next.gaintag.add(event.name); + await next; + const targets = game.filterPlayer(current => current != player && current.isDamaged()); + if (!targets) return; + const list = + targets.length == 1 + ? targets + : await player + .chooseTarget(`选择一名其他角色,令其回复1点体力`, (card, player, target) => { + return target != player && target.isDamaged(); + }) + .set("ai", target => { + const player = get.player(); + return get.recoverEffect(target, player, player); + }) + .forResultTargets(); + if (list && list.length) await list[0].recover(); + }, + ai: { + order: 9, + result: { + player: 1, + target: -1, + }, + }, + }, + //九鼎-种地的 + jdsbjieyue: { + audio: "sbjieyue", + trigger: { + player: "phaseJieshuBegin", + }, + filter(event, player) { + return game.hasPlayer(current => current != player); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(lib.filter.notMe, get.prompt2(event.name.slice(0, -5))) + .set("ai", target => { + return get.attitude(get.player(), target) / Math.sqrt(Math.min(1, target.hp + target.hujia)); + }) + .forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + await target.draw(2); + await target.changeHujia(1, null, true); + if (target.countCards("he")) await target.chooseToGive(player, "he", Math.min(2, target.countCards("he")), true); + }, + }, + //九鼎-高贵名门 + jdsbluanji: { + audio: "sbluanji", + inherit: "sbluanji", + filter(event, player) { + if (event.name == "chooseToUse") return player.countCards("hs") > 1 && !player.hasSkill("jdsbluanji_used"); + const evt = event.getParent(2); + return evt.name == "wanjian" && evt.getParent().player == player && event.player != player && event.player.countCards("h") > player.countCards("h") && player.countCards("h") < player.getHp(); + }, + precontent() { + player.addTempSkill("jdsbluanji_used", "phaseUseAfter"); + }, + subSkill: { + used: { + charlotte: true, + }, + }, + }, + jdsbxueyi: { + audio: "sbxueyi", + trigger: { + global: ["useCardAfter", "respondAfter"], + }, + filter(event, player) { + if (!event.respondTo) return false; + if (player != event.respondTo[0]) return false; + return player.hasZhuSkill("jdsbxueyi") && event.player != player && event.player.group == "qun"; + }, + zhuSkill: true, + forced: true, + logTarget: "player", + async content(event, trigger, player) { + for (const name of lib.phaseName) { + const evt = _status.event.getParent(name); + if (!evt || evt.name != name) continue; + trigger.player.addTempSkill(event.name + "_ban", name + "After"); + break; + } + }, + mod: { + maxHandcard(player, num) { + if (player.hasZhuSkill("jdsbxueyi")) { + return num + 2 * game.countPlayer(current => player != current && current.group == "qun"); + } + }, + }, + subSkill: { + ban: { + charlotte: true, + mark: true, + mod: { + cardEnabled2(card) { + if (get.position(card) == "h") return false; + }, + }, + intro: { + content: "不能使用或打出手牌", + }, + }, + }, + }, + //九鼎-孟获 + jdsbhuoshou: { + audio: "sbhuoshou", + trigger: { + player: "phaseUseEnd", + }, + filter(event, player) { + return player.countCards("h"); + }, + async content(event, trigger, player) { + await player.discard(player.getCards("h")); + const nanman = get.autoViewAs({ name: "nanman", isCard: true }); + if (player.hasUseTarget(nanman)) await player.chooseUseTarget(nanman, true, false); + }, + forced: true, + group: ["sbhuoshou_cancel", "sbhuoshou_source"], + }, + jdsbzaiqi: { + audio: "sbzaiqi", + trigger: { + player: "phaseDiscardEnd", + }, + filter(event, player) { + return player.getHistory("lose", evt => evt.type == "discard").length; + }, + async cost(event, trigger, player) { + const num = player.getHistory("lose", evt => evt.type == "discard").reduce((num, evt) => num + evt.cards2.length, 0); + event.result = await player + .chooseTarget(get.prompt2(event.name.slice(0, -5)), [1, num]) + .set("ai", target => { + const player = get.player(); + const att = get.attitude(player, target); + return 3 - get.sgn(att) + Math.abs(att / 1000); + }) + .forResult(); + }, + async content(event, trigger, player) { + const targets = event.targets.sortBySeat(); + while (targets.length) { + const target = targets.shift(); + const bool = !target.countCards("he") + ? false + : await target + .chooseToDiscard(get.translation(player) + "对你发动了【再起】", "是否弃置一张牌令其回复1点体力?或者点击“取消”,令该角色摸一张牌。", "he") + .set("ai", card => { + const eff = _status.event.eff, + att = _status.event.att; + if ((eff > 0 && att > 0) || (eff <= 0 && att < 0)) return 5.5 - get.value(card); + return 0; + }) + .set("eff", get.recoverEffect(player, player, target)) + .set("att", get.attitude(target, player)) + .forResultBool(); + target.line(player); + await player[bool ? "recover" : "draw"](); + } + }, + }, + //九鼎-大乔 + jdsbguose: { + audio: "sbguose", + inherit: "sbguose", + usable: 1, + filterTarget(card, player, target) { + if (!ui.selected.cards.length) { + if (!target.hasJudge("lebu")) return false; + return game.hasPlayer(current => current != target && current.canAddJudge("lebu")); + } + if (player == target) return false; + return player.canUse(get.autoViewAs({ name: "lebu" }, ui.selected.cards), target); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + if (target.hasJudge("lebu")) { + await player + .moveCard(true, card => (card.viewAs || card.name) == "lebu") + .set("sourceTargets", [target]) + .set( + "aimTargets", + game.filterPlayer(current => current != target && current.canAddJudge("lebu")) + ) + .set("prompt", `移动${get.translation(target)}的一张【乐不思蜀】`); + } else { + const next = player.useCard({ name: "lebu" }, target, event.cards); + next.audio = false; + await next; + } + }, + }, + jdsbliuli: { + audio: "sbliuli", + inherit: "liuli", + group: "jdsbliuli_add", + subSkill: { + add: { + trigger: { player: "logSkill" }, + filter(event, player) { + if (event.skill != "jdsbliuli") return false; + return event.targets[0].isIn(); + }, + forced: true, + popup: false, + content() { + game.countPlayer(i => i.removeSkill("jdsbliuli_dangxian")); + trigger.targets[0].addSkill("jdsbliuli_dangxian"); + }, + }, + dangxian: { + trigger: { player: "phaseBegin" }, + forced: true, + charlotte: true, + mark: true, + marktext: "流", + intro: { content: "回合开始时,执行一个额外的出牌阶段" }, + content() { + player.removeSkill("jdsbliuli_dangxian"); + trigger.phaseList.splice(trigger.num, 0, "phaseUse|jdsbliuli_dangxian"); + }, + }, + }, + }, + //九鼎-姜维 + jdsbtiaoxin: { + audio: "sbtiaoxin", + enable: "phaseUse", + usable: 1, + filter(event, player) { + return game.hasPlayer(current => current != player); + }, + filterTarget: lib.filter.notMe, + selectTarget() { + return [1, get.player().getHp()]; + }, + multiline: true, + async content(event, trigger, player) { + const target = event.target; + const bool = await target + .chooseToUse(function (card, player, event) { + if (get.name(card) != "sha") return false; + return lib.filter.filterCard.apply(this, arguments); + }, "挑衅:对" + get.translation(player) + "使用一张杀,或令其获得你一张牌") + .set("targetRequired", true) + .set("complexSelect", true) + .set("filterTarget", function (card, player, target) { + if (target != _status.event.sourcex && !ui.selected.targets.includes(_status.event.sourcex)) return false; + return lib.filter.targetEnabled.apply(this, arguments); + }) + .set("sourcex", player) + .forResultBool(); + if (!target.countGainableCards(player, "he")) return; + if (!bool || (bool && !target.hasHistory("sourceDamage", evt => evt.getParent(4) == event))) await player.gainPlayerCard(target, "he", true); + }, + ai: { + threaten: 1.2, + order: 4, + expose: 0.2, + result: { + target(player, target) { + if (target.countGainableCards(player, "he") == 0) return 0; + return -1; + }, + player(player, target) { + if (!target.canUse("sha", player)) return 0; + if (target.countCards("h") == 0) return 0; + if (target.countCards("h") == 1) return -0.1; + if (player.hp <= 2) return -2; + if (player.countCards("h", "shan") == 0) return -1; + return -0.5; + }, + }, + }, + }, + jdsbzhiji: { + audio: "sbzhiji", + trigger: { + player: "dying", + }, + juexingji: true, + forced: true, + skillAnimation: true, + animationColor: "fire", + async content(event, trigger, player) { + player.awakenSkill(event.name); + await player.recoverTo(2); + await player.loseMaxHp(); + await player.addSkills("jdsbbeifa"); + if (player.isMinHandcard()) await player.draw(2); + }, + derivation: "jdsbbeifa", + }, + jdsbbeifa: { + audio: 2, + enable: "phaseUse", + filter(event, player) { + return game.hasPlayer(current => current != player); + }, + filterCard: true, + selectCard: [1, Infinity], + check(card) { + if (ui.selected.cards.length > 2) return 0; + const player = get.player(); + if (game.hasPlayer(current => current != player && get.attitude(player, current) > 0 && current.getCards("h").some(cardx => get.name(cardx) == get.name(card)))) return 1; + return 7.5 - get.value(card); + }, + async content(event, trigger, player) { + const cards = event.cards, + num = cards.length, + names = cards.map(card => get.name(card)).toUniqued(); + if (!game.hasPlayer(current => current != player && current.countCards("h"))) return; + const targets = await player + .chooseTarget(`北伐:令一名其他角色展示${num}张手牌`, true, (card, player, target) => { + return target != player && target.countCards("h"); + }) + .set("ai", target => { + const player = get.player(); + return get.attitude(player, target) * (1 + target.countCards("h")); + }) + .forResultTargets(); + if (!targets || !targets.length) return; + const target = targets[0]; + let showCards = await target + .chooseCard("h", Math.min(num, target.countCards("h")), true, `选择${get.translation(num)}张手牌展示`) + .set("ai", card => { + const player = get.player(), + goon = get.event("goon"), + names = get.event("names"); + if (goon) { + if (names.includes(get.name(card))) return 10; + return 7.5 - get.value(card); + } else { + if (names.includes(get.name(card))) return 0; + return 6 - get.value(card); + } + }) + .set("goon", get.attitude(target, player) > 0) + .set("names", names) + .forResultCards(); + if (!showCards || !showCards.length) return; + await target.showCards(showCards); + while (showCards.some(card => names.includes(get.name(card)) && player.hasUseTarget(get.autoViewAs({ name: "sha" }, [card]), false, false))) { + const links = await player + .chooseButton(["北伐:将其中一张牌当【杀】使用", showCards]) + .set("filterButton", button => { + const player = get.player(), + card = button.link; + if (!get.event("names").includes(get.name(card))) return false; + return player.hasUseTarget(get.autoViewAs({ name: "sha" }, [card]), false, false); + }) + .set("ai", button => { + return get.value(button.link); + }) + .set("names", names) + .forResultLinks(); + if (!links || !links.length) break; + showCards.removeArray(links); + const card = links[0], + cardx = { + name: "sha", + cards: [card], + }; + await player.chooseUseTarget(cardx, [card], true, false); + } + }, + ai: { + order: 10, + result: { + player(player, target) { + if (!game.hasPlayer(current => get.effect(current, { name: "sha" }, player, player) > 0)) return 0; + const names = player + .getCards("he") + .map(card => get.name(card)) + .toUniqued(); + if (game.hasPlayer(current => current != player && get.attitude(player, current) > 0 && current.getCards("h").some(card => names.includes(get.name(card))))) return 1; + return 0; + }, + }, + }, + }, + //九鼎-关羽 + jdsbwusheng: { + audio: "sbwusheng", + trigger: { + player: "phaseUseBegin", + }, + filter(event, player) { + return game.hasPlayer(target => target != player && target.countCards("h")); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt(event.name.slice(0, -5)), "令一名其他角色展示所有手牌,本阶段对其使用的前X张【杀】无距离和次数限制且结算后你摸一张牌(X为其以此法展示的红色手牌数)", (card, player, target) => { + return target != player && target.countCards("h"); + }) + .set("ai", target => { + const player = get.player(); + return get.effect(target, { name: "sha" }, player, player) * (1 + target.countCards("h", { color: "red" })); + }) + .forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + await target.showHandcards(); + if (get.mode() !== "identity" || player.identity !== "nei") player.addExpose(0.25); + const num = target.countCards("h", { color: "red" }); + if (num > 0) { + player.addTempSkill("jdsbwusheng_effect", { player: "phaseUseAfter" }); + player.storage.jdsbwusheng_effect[target.playerid] = num; + } + }, + group: "sbwusheng_wusheng", + subSkill: { + effect: { + charlotte: true, + onremove: true, + init(player, skill) { + if (!player.storage[skill]) player.storage[skill] = {}; + }, + mod: { + targetInRange(card, player, target) { + if (card.name !== "sha" || typeof player.storage.jdsbwusheng_effect[target.playerid] !== "number") return; + if (player.storage.jdsbwusheng_effect[target.playerid] > 0) return true; + }, + cardUsableTarget(card, player, target) { + if (card.name !== "sha" || typeof player.storage.jdsbwusheng_effect[target.playerid] !== "number") return; + if (player.storage.jdsbwusheng_effect[target.playerid] > 0) return true; + }, + }, + audio: "sbwusheng", + trigger: { + player: "useCardAfter", + }, + filter(event, player) { + if (event.card.name != "sha") return false; + return event.targets.some(target => typeof player.storage.jdsbwusheng_effect[target.playerid] == "number" && player.storage.jdsbwusheng_effect[target.playerid] > 0); + }, + forced: true, + async content(event, trigger, player) { + const targets = trigger.targets.filter(target => typeof player.storage.jdsbwusheng_effect[target.playerid] == "number" && player.storage.jdsbwusheng_effect[target.playerid] > 0); + player.line(targets); + await player.draw(targets.length); + for (const target of targets) player.storage.jdsbwusheng_effect[target.playerid]--; + }, + }, + }, + }, + jdsbyijue: { + audio: "sbyijue", + trigger: { + player: "phaseZhunbeiBegin", + }, + filter(event, player) { + return game.hasPlayer(current => current != player); + }, + forced: true, + logTarget(event, player) { + return game.filterPlayer(current => current != player).sortBySeat(); + }, + async content(event, trigger, player) { + const givers = []; + for (const target of event.targets) { + const bool = !target.countCards("he") + ? false + : await target + .chooseToGive(player, "he", `交给${get.translation(player)}一张牌,本回合当你首次受到其的【杀】的造成的伤害时,防止之`) + .set("ai", card => { + const player = get.event("player"), + target = get.event().getParent().player; + const att = get.attitude(player, target); + if (att >= 0) return 0; + if (player.getHp() > 1 || !target.canUse({ name: "sha" }, player, true, true)) return 0; + return 7.5 - get.value(card); + }) + .forResultBool(); + if (bool) givers.add(target); + } + if (givers.length) { + player.addTempSkill(event.name + "_effect"); + player.markAuto(event.name + "_effect", givers); + } + }, + subSkill: { + effect: { + charlotte: true, + onremove: true, + intro: { + content: "本回合$首次受到你的【杀】的造成的伤害时,你防止之", + }, + trigger: { + global: "damageBegin4", + }, + filter(event, player) { + if (!player.getStorage("jdsbyijue_effect").includes(event.player)) return false; + return event.card && event.card.name == "sha" && event.getParent().type == "card"; + }, + forced: true, + popup: false, + async content(event, trigger, player) { + trigger.cancel(); + player.unmarkAuto(event.name, [trigger.player]); + }, + }, + }, + }, + //九鼎-小乔 + jdsbtianxiang: { + audio: "sbtianxiang", + trigger: { + player: "damageBegin4", + }, + filter(event, player) { + return player.countCards("h") > 1 && event.num > 0; + }, + async cost(event, trigger, player) { + event.result = await player + .chooseCardTarget({ + filterCard: true, + selectCard: 2, + filterTarget: lib.filter.notMe, + position: "he", + ai1(card) { + return 10 - get.value(card); + }, + ai2(target) { + var att = get.attitude(_status.event.player, target); + var trigger = _status.event.getTrigger(); + var da = 0; + if (_status.event.player.hp == 1) { + da = 10; + } + var eff = get.damageEffect(target, trigger.source, target); + if (att == 0) return 0.1 + da; + if (eff >= 0 && att > 0) { + return att + da; + } + if (att > 0 && target.hp > 1) { + if (target.maxHp - target.hp >= 3) return att * 1.1 + da; + if (target.maxHp - target.hp >= 2) return att * 0.9 + da; + } + return -att + da; + }, + prompt: get.prompt("jdsbtianxiang"), + prompt2: lib.translate.jdsbtianxiang_info, + }) + .forResult(); + }, + async content(event, trigger, player) { + const cards = event.cards, + target = event.targets[0]; + await player.showCards(cards); + const links = await target + .chooseButton(["天香:获得其中一张牌", cards], true) + .set("ai", button => { + const player = get.player(), + card = button.link; + return get.value(card); + }) + .forResultLinks(); + if (!links || !links.length) return; + const suit = get.suit(links[0], player); + await target.gain(links, "gain2"); + if (suit == "heart") { + trigger.cancel(); + await target + .damage(trigger.source || "nosource", trigger.nature, trigger.num) + .set("card", trigger.card) + .set("cards", trigger.cards); + } else { + target.addTempSkill(event.name + "_effect"); + target.markAuto(event.name + "_effect", [get.type2(links[0])]); + } + }, + subSkill: { + effect: { + charlotte: true, + onremove: true, + mark: true, + intro: { + content: storage => `本回合不能使用${get.translation(storage)}牌`, + }, + mod: { + cardEnabled(card, player) { + const hs = player.getCards("h"), + cards = [card]; + if (Array.isArray(card.cards)) cards.addArray(card.cards); + if (cards.containsSome(...hs) && player.getStorage("jdsbtianxiang_effect").includes(get.type2(card))) return false; + }, + cardSavable(card, player) { + const hs = player.getCards("h"), + cards = [card]; + if (Array.isArray(card.cards)) cards.addArray(card.cards); + if (cards.containsSome(...hs) && player.getStorage("jdsbtianxiang_effect").includes(get.type2(card))) return false; + }, + }, + }, + }, + }, + jdsbhongyan: { + audio: "xinhongyan", + mod: { + suit(card, suit) { + if (suit == "spade") return "heart"; + }, + }, + trigger: { + player: "loseAfter", + global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], + }, + forced: true, + filter(event, player) { + if (player.hasHistory("gain", evt => evt.getParent().name == "draw" && evt.getParent(2).name == "jdsbhongyan")) return false; + const evt = event.getl(player); + return evt.cards2.some(i => get.suit(i, player) == "heart"); + }, + async content(event, trigger, player) { + if (!trigger.visible) { + const cards = trigger.getl(player).hs.filter(i => get.suit(i, player) == "heart"); + if (cards.length > 0) await player.showCards(cards, get.translation(player) + "发动了【红颜】"); + } + await player.draw(); + }, + }, + //九鼎-孙权 + jdsbzhiheng: { + audio: "sbzhiheng", + inherit: "sbzhiheng", + prompt() { + return "出牌阶段限一次。你可以弃置任意张牌并摸等量的牌,若你以此法弃置的牌包括你装备区的牌,则你多摸一张牌"; + }, + async content(event, trigger, player) { + const cards = event.cards; + const num = cards.some(card => player.getCards("e").includes(card)) ? 1 : 0; + await player.discard(cards); + await player.draw(cards.length + num); + }, + }, + jdsbtongye: { + init(player) { + if (game.shuffleNumber == 0) { + player.addAdditionalSkill("jdsbtongye", get.info("jdsbtongye").derivation); + lib.onwash.push(function () { + player.removeAdditionalSkill("jdsbtongye"); + }); + } + }, + onremove(player) { + player.removeAdditionalSkill("jdsbtongye"); + }, + derivation: ["sbyingzi", "olguzheng"], + locked: true, + }, + jdsbjiuyuan: { + audio: "sbjiuyuan", + enable: "phaseUse", + usable: 1, + zhuSkill: true, + filter(event, player) { + return game.hasPlayer(current => get.info("jdsbjiuyuan").filterTarget(null, player, current)); + }, + filterTarget(card, player, target) { + return target != player && target.group == "wu" && target.countGainableCards(player, "e") && player.hasZhuSkill("jdsbjiuyuan", target); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + await player.gain(target.getCards("e"), target, "giveAuto", "bySelf"); + await player.recover(); + }, + ai: { + order: 10, + result: { + target(player, target) { + return get.effect(target, { name: "shunshou_copy2" }, player, target) * target.countGainableCards(player, "e"); + }, + }, + }, + }, + //九鼎-司马炎 + jdfengtu: { + mode: ["identity", "guozhan", "doudizhu", "versus"], + available(mode) { + if (mode == "versus" && _status.mode == "three") return false; + }, + trigger: { global: "dieAfter" }, + filter(event, player) { + //if (game.players.includes(event.player)) return false; + return game.hasPlayer(target => { + return !game.getAllGlobalHistory("everything", evt => { + return evt.name == "loseMaxHp" && evt.getParent().name == "jdfengtu" && evt.player == target; + }).length; + }); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2("jdfengtu"), (card, player, target) => { + return get.event().targets.includes(target); + }) + .set("ai", target => { + const player = get.event("player"), + att = get.attitude(player, target); + if (target.maxHp <= 1) return 114514119810 * get.sgn(-att); + if (player.identity == "nei" && target != player) return 0; + return target.maxHp - 1; + }) + .set( + "targets", + game.filterPlayer(target => { + return !game.getAllGlobalHistory("everything", evt => { + return evt.name == "loseMaxHp" && evt.getParent().name == "jdfengtu" && evt.player == target; + }).length; + }) + ) + .forResult(); + }, + async content(event, trigger, player) { + if (!lib.onround.includes(lib.skill.jdfengtu.onRound)) { + lib.onround.push(lib.skill.jdfengtu.onRound); + } + const target = event.targets[0]; + await target.loseMaxHp(); + target.addSkill("jdfengtu_phase"); + target.markAuto("jdfengtu_phase", [trigger.player]); + }, + onRound(event) { + return (event.relatedEvent || event.getParent(2)).name != "jdfengtu_phase"; + }, + check(source, player) { + const players = game.players + .slice() + .concat(game.dead) + .filter(target => { + return target.isAlive() || [source, player].includes(target); + }) + .sort((a, b) => parseInt(a.dataset.position) - parseInt(b.dataset.position)); + const num = players.indexOf(source), + num2 = players.indexOf(player); + return num2 - num == 1 || (num == players.length - 1 && num2 == 0); + }, + subSkill: { + phase: { + charlotte: true, + trigger: { global: "phaseOver" }, + filter(event, player) { + return player.getStorage("jdfengtu_phase").some(target => { + return lib.skill.jdfengtu.check(event.player, target); + }); + }, + forced: true, + popup: false, + content() { + const next = player.insertPhase(); + delete next.skill; + }, + intro: { content: "获得$的额定回合" }, + }, + }, + }, + jdjuqi: { + trigger: { global: "phaseZhunbeiBegin" }, + filter(event, player) { + const storage = player.storage.jdjuqi; + return event.player == player || event.player.countCards("h", card => _status.connectMode || (get.color(card, event.player) == storage ? "red" : "black")); + }, + async cost(event, trigger, player) { + const target = trigger.player; + if (target == player) { + event.result = { bool: true }; + } else { + const color = player.storage.jdjuqi ? "red" : "black"; + event.result = await target + .chooseCard((card, player) => get.color(card, player) == color, `举棋:你可以交给${get.translation(player)}一张${get.translation(color)}手牌`) + .set("ai", card => { + const player = get.player(), + target = get.event("target"); + if (get.attitude(player, target) <= 0) return 0; + return 6 - get.value(card); + }) + .set("target", player) + .forResult(); + } + }, + async content(event, trigger, player) { + const target = trigger.player; + player.changeZhuanhuanji(event.name); + if (target == player) { + if (player.storage[event.name]) await player.draw(3); + else player.addTempSkill(event.name + "_effect"); + } else { + await target.showCards(event.cards); + await target.give(event.cards, player); + } + }, + mark: true, + zhuanhuanji: true, + marktext: "☯", + intro: { + content(storage) { + if (storage) return "
  • 准备阶段,你令你本回合使用牌无次数限制且造成的伤害+1
  • 其他角色的准备阶段,其可以展示并交给你一张红色手牌"; + return "
  • 准备阶段,你摸三张牌
  • 其他角色的准备阶段,其可以展示并交给你一张黑色手牌"; + }, + }, + subSkill: { + effect: { + charlotte: true, + mod: { cardUsable: () => Infinity }, + forced: true, + popup: false, + trigger: { source: "damageBegin1" }, + filter(event, player) { + return event.card && event.getParent().type == "card"; + }, + async content(event, trigger, player) { + trigger.num++; + }, + mark: true, + intro: { content: "本回合使用牌无次数限制且造成的伤害+1" }, + }, + }, + }, + jdtaishi: { + zhuSkill: true, + trigger: { global: "phaseBefore" }, + filter(event, player) { + return game.hasPlayer(current => current.isUnseen(2)); + }, + logTarget() { + return game.filterPlayer(current => current.isUnseen(2)).sortBySeat(); + }, + limited: true, + skillAnimation: true, + animationColor: "orange", + async content(event, trigger, player) { + player.awakenSkill(event.name); + for (const target of game.filterPlayer(current => current.isUnseen(2)).sortBySeat()) { + await target.showCharacter(2); + } + }, + }, + //荆襄风云 + jxxiongzi: { + audio: "reyingzi", + trigger: { + player: "phaseDrawBegin2", + }, + forced: true, + preHidden: true, + filter(event, player) { + return !event.numFixed; + }, + content() { + trigger.num += player.hp; + }, + ai: { + threaten: 1.5, + }, + mod: { + maxHandcard(player, num) { + return num + player.hp; + }, + }, + }, + jxzhanyan: { + enable: "phaseUse", + usable: 1, + audio: "dcsbronghuo", + filter(event, player) { + return player.countCards("h"); + }, + filterTarget: lib.filter.notMe, + async content(event, trigger, player) { + const target = event.targets[0]; + let list = Array.from(Array(player.countCards("h") + 1)).map((i, p) => p); + let dialog = [`猜测${get.translation(player)}拥有的红色手牌数量`]; + while (list.length) { + let nums = list.slice(0, Math.min(10, list.length)); + list.removeArray(nums); + dialog.push([nums, "tdnodes"]); + } + const result = await target + .chooseButton(dialog, true) + .set("ai", () => Math.random()) + .forResult(); + if (result.bool) { + target.chat(`我猜你有${result.links[0]}张红色牌!`); + game.log(target, "猜测", player, "有红色牌", "#g" + result.links[0] + "张"); + if (event.isMine() && !event.isOnline()) await game.delay(); + await player.showHandcards(player, "发动了【绽焰】"); + const num = Math.min(3, Math.abs(result.links[0] - player.countCards("h", card => get.color(card, player) == "red"))); + const redCards = player.getCards("he", card => get.color(card, player) == "red"); + if (redCards.length) await player.give(redCards, target); + if (num > 0) await target.damage("fire", num); + } + }, + ai: { + order: 3, + result: { + target(player, target) { + return get.damageEffect(target, player, target) + player.countCards("he", { color: "red" }); + }, + }, + }, + }, + jxwusheng: { + mod: { + targetInRange(card) { + if (get.suit(card) == "diamond" && card.name == "sha") return true; + }, + }, + locked: false, + audio: "wusheng", + enable: ["chooseToUse", "chooseToRespond"], + filter(event, player) { + return get + .inpileVCardList(info => { + const name = info[2]; + if (info[3]) return false; + if (name != "sha" && name != "jiu") return false; + return get.type(name) == "basic"; + }) + .some(card => player.hasCard(cardx => get.color(cardx, player) == "red" && event.filterCard({ name: card[2], nature: card[3], cards: [cardx] }, player, event), "hes")); + }, + chooseButton: { + dialog(event, player) { + const list = get + .inpileVCardList(info => { + const name = info[2]; + if (info[3]) return false; + if (name != "sha" && name != "jiu") return false; + return get.type(name) == "basic"; + }) + .filter(card => player.hasCard(cardx => get.color(cardx, player) == "red" && event.filterCard({ name: card[2], nature: card[3], cards: [cardx] }, player, event), "hes")); + return ui.create.dialog("武圣", [list, "vcard"]); + }, + filter(button, player) { + return _status.event.getParent().filterCard({ name: button.link[2], nature: button.link[3] }, player, _status.event.getParent()); + }, + check(button) { + if (_status.event.getParent().type != "phase") return 1; + const player = get.event("player"), + value = player.getUseValue({ name: button.link[2], nature: button.link[3] }); + return value; + }, + backup(links, player) { + return { + audio: "wusheng", + filterCard(card, player) { + return get.color(card, player) == "red"; + }, + popname: true, + check(card) { + return 6 - get.value(card); + }, + position: "hse", + viewAs: { name: links[0][2], nature: links[0][3] }, + }; + }, + prompt(links, player) { + return "将一张牌当作" + (get.translation(links[0][3]) || "") + "【" + get.translation(links[0][2]) + "】使用或打出"; + }, + }, + hiddenCard(player, name) { + if (name != "jiu") return false; + return player.countCards("hes", { color: "red" }); + }, + ai: { + skillTagFilter(player) { + if (!player.countCards("hes", { color: "red" })) return false; + }, + respondSha: true, + }, + }, + //神曹仁 + jxjushou: { + trigger: { + player: "phaseJieshuBegin", + }, + check(event, player) { + return event.player.hp + player.countCards("h") < 4; + }, + async content(event, trigger, player) { + await player.turnOver(); + await player.draw(game.countPlayer()); + let eff = 0; + for (const current of game.players) { + eff += get.sgnAttitude(player, current) * (current.countCards("e") + 3 + current.isTurnedOver() ? 5 : -5); + } + const result = await player + .chooseBool("是否令所有角色翻面并摸三张牌?") + .set("choice", eff > 0) + .forResult(); + if (result.bool) { + for (const current of game.players) { + await current.turnOver(); + await current.draw(3); + } + const lose_list = []; + for (const current of game.players) { + if (current.countCards("e")) lose_list.push([current, current.getCards("e")]); + } + if (lose_list.length) { + await game + .loseAsync({ + lose_list: lose_list, + discarder: player, + }) + .setContent("discardMultiple"); + } + await player.changeSkills(["jxtuwei"], ["jxjushou"]); + } + }, + ai: { + effect: { + target(card, player, target) { + if (card.name == "guiyoujie") return [0, 1]; + }, + }, + }, + derivation: ["jxtuwei"], + }, + jxtuwei: { + enable: "phaseUse", + intro: { + content: "已对$发动过【突围】", + }, + onremove: true, + onChooseToUse(event) { + if (!event.jxtuwei && !game.online) { + const player = get.player(); + const cards = Array.from(ui.discardPile.childNodes).filter(card => get.type(card) == "equip"); + event.set("jxtuwei", cards); + } + }, + filter(event, player) { + if (!game.hasPlayer(current => !player.getStorage("jxtuwei").includes(current))) return false; + return event.jxtuwei && event.jxtuwei.length; + }, + chooseButton: { + dialog(event, player) { + const list2 = event.jxtuwei; + var dialog = ui.create.dialog('###突围###
    请选择一张装备牌置入一名其他角色的装备区
    '); + if (list2.length) { + dialog.add(list2); + } + return dialog; + }, + check(button) { + var player = _status.event.player; + var num = get.value(button.link); + if (!game.hasPlayer(target => !player.getStorage("jxtuwei").includes(target) && get.attitude(player, target) > 0)) return num; + return 5 / num; + }, + backup(links, player) { + return { + card: links[0], + filterTarget(card, player, target) { + return !player.getStorage("jxtuwei").includes(target); + }, + check: () => 1, + async content(event, trigger, player) { + const cardx = lib.skill.jxtuwei_backup.card, + target = event.targets[0]; + target.$gain2(cardx); + await game.delayx(); + await target.equip(cardx); + player.markAuto("jxtuwei", target); + if (target != player) { + const result = await player + .chooseControl("令其摸一张牌", "对其造成1点伤害", "cancel2") + .set("ai", function () { + return _status.event.choice; + }) + .set( + "choice", + (function () { + if (get.damageEffect(target, player, player) > 0) return "对其造成1点伤害"; + if (get.effect(target, { name: "draw" }, player, player) > 0) return "令其摸一张牌"; + return "cancel2"; + })() + ) + .forResult(); + if (result.index == 0) await target.draw(); + if (result.index == 1) { + player.line(target, "green"); + await target.damage(); + } + } + }, + ai: { + result: { + target(player, target) { + var att = get.attitude(player, target); + if (att > 0) return 3; + if (att < 0) return -1; + return 0; + }, + }, + }, + }; + }, + prompt(links, player) { + return "请选择置入" + get.translation(links) + "的角色"; + }, + }, + subSkill: { + backup: {}, + }, + }, + //神刘表 + jxxiongju: { + trigger: { + global: "phaseBefore", + player: "enterGame", + }, + forced: true, + filter(event, player) { + return event.name != "phase" || game.phaseNumber == 0; + }, + async content(event, trigger, player) { + let cards = []; + while (cards.length < 2) { + const card = game.createCard2("jingxiangshengshi", "heart", 5); + cards.push(card); + } + if (cards.length) await player.gain(cards, "gain2"); + const num = game.countGroup(); + await player.draw(num); + await player.gainMaxHp(num); + await player.recover(num); + }, + mod: { + maxHandcard(player, num) { + return num + game.countGroup(); + }, + }, + }, + jxfujing: { + trigger: { + player: "phaseDrawBefore", + }, + forced: true, + async content(event, trigger, player) { + trigger.cancel(); + const card = { name: "jingxiangshengshi", isCard: true }; + if (game.countPlayer(current => player.canUse(card, current)) < game.countGroup()) return; + await player.chooseUseTarget(card, true); + for (const target of game.players) { + if (target.getHistory("gain", evt => evt.getParent(event.name) == event).length && target != player) { + target.addTempSkill("jxfujing_effect", "roundStart"); + target.markAuto("jxfujing_effect", player); + } + } + }, + subSkill: { + effect: { + mark: true, + intro: { + content: "本轮下一次对$使用牌时须弃置一张牌", + }, + onremove: true, + trigger: { + player: "useCardToPlayer", + }, + filter(event, player) { + return player.getStorage("jxfujing_effect").includes(event.target); + }, + forced: true, + charlotte: true, + async content(event, trigger, player) { + const target = trigger.target; + if (player.countCards("he")) await player.chooseToDiscard("he", true); + player.unmarkAuto("jxfujing_effect", [target]); + if (!player.getStorage("jxfujing_effect").length) player.removeSkill(event.name); + }, + }, + }, + }, + jxyongrong: { + trigger: { + source: "damageBegin1", + player: "damageBegin3", + }, + usable: 1, + filter(event, player, name) { + const target = name == "damageBegin1" ? event.player : event.source; + return target && target.isIn() && target.countCards("h") < player.countCards("h"); + }, + async cost(event, trigger, player) { + const target = event.triggername == "damageBegin1" ? trigger.player : trigger.source; + const prompt2 = `交给其一张牌并令此伤害${event.triggername == "damageBegin1" ? "+" : "-"}1`; + const result = await player + .chooseCard(get.prompt("jxyongrong", target), prompt2, "he") + .set("ai", function (card) { + const eff = _status.event.eff, + isPlayer = _status.event.isPlayer; + if ((isPlayer && eff < 0) || (!isPlayer && eff > 0)) return 6 - get.value(card); + return 0; + }) + .set("eff", get.damageEffect(trigger.player, trigger.source, player)) + .set("isPlayer", player == trigger.player) + .forResult(); + event.result = { + bool: result.bool, + cards: result.cards, + targets: [target], + }; + }, + async content(event, trigger, player) { + await player.give(event.cards, event.targets[0]); + if (event.triggername == "damageBegin1") trigger.num++; + else trigger.num--; + }, + }, //线下E系列 - //钟会 先放着 + //钟会 psmouchuan: { audio: 2, trigger: { @@ -59,12 +5490,19 @@ const skills = { }, }, trigger: { - player: "useCard", + player: ["useCard", "respond"], }, filter(event, player) { const num = get.info("jsrgjuxia").countSkill(player) - 2; - if (!num || get.type(event.card) == "equip") return false; - return player.getRoundHistory("useCard", evt => get.name(evt.card) == get.name(event.card)).indexOf(event) == 0; + if (num <= 0 || get.type(event.card) == "equip") return false; + return ( + !player.getRoundHistory("useCard", evt => { + get.name(evt.card) == get.name(event.card) && evt != event; + }).length && + !player.getRoundHistory("respond", evt => { + get.name(evt.card) == get.name(event.card) && evt != event; + }).length + ); }, forced: true, async content(event, trigger, player) { @@ -320,7 +5758,7 @@ const skills = { let cards = trigger.getg(player); await player.showCards(cards, get.translation(player) + "发动了【炎谋】"); cards = cards.filter(card => { - if (!player.hasUseTarget(card)) return false; + if (!player.hasUseTarget(card) || get.owner(card) !== player) return false; return get.name(card) == "huogong" || (get.name(card) == "sha" && game.hasNature(card, "fire")); }); if (cards.length) { @@ -348,17 +5786,19 @@ const skills = { return game.hasPlayer(target => player.inRange(target)); }, usable: 1, + filterTarget(card, player, target) { + return player.inRange(target); + }, + selectTarget: -1, + multitarget: true, + multiline: true, delay: 0, async content(event, trigger, player) { - const targets = game - .filterPlayer(target => { - return player.inRange(target); - }) - .sortBySeat(); + const targets = event.targets.sortBySeat(); let damages = 0, puts = 0; player.line(targets); - await game.asyncDelay(); + await game.delay(); for (const target of targets) { let dialog = ["绽焰:将手牌中或弃牌堆中的一张【火攻】或火【杀】置于牌堆顶,或受到1点火焰伤害"]; const Tcards = target.getCards("h", card => { @@ -398,11 +5838,12 @@ const skills = { else ui.discardPile.removeChild(card); ui.cardPile.insertBefore(card, ui.cardPile.firstChild); game.updateRoundNumber(); + game.log(target, "将" + get.translation(card) + "置于牌堆顶"); } else { damages++; await target.damage(1, "fire"); } - await game.asyncDelay(0.5); + await game.delay(0.5); } const num = Math.min(damages, puts); if (num) await player.draw(num); @@ -425,7 +5866,7 @@ const skills = { nofire: true, effect: { target(card, player, target, current) { - if (get.tag(card, "fireDamage")) return "zerotarget"; + if (get.tag(card, "fireDamage")) return "zeroplayertarget"; }, }, }, @@ -490,7 +5931,7 @@ const skills = { target = get.event().getParent().player; const att = get.attitude(player, target); if (att > 0) return 7.5 - get.value(card); - if (att == 0 && get.attitude(target, player) == 0) return 0; + if (att > -1) return 0; if ( att < 0 && get.attitude(target, player) < 0 && @@ -499,10 +5940,9 @@ const skills = { const info = get.info(skill); return info && info.ai && (info.ai.maixie || info.ai.maixie_hp || info.ai.maixie_defend); }) && - player.getHp() > 2 - ) - return 0; - return 7.5 - get.value(card); + player.getHp() <= 2 + ) return 7.5 - get.value(card); + return 0; }) .set("prompt", "超绝:交给" + get.translation(player) + "一张" + get.translation(suits) + "手牌,或本回合非锁定技失效"); if (!bool) target.addTempSkill("fengyin"); @@ -692,7 +6132,7 @@ const skills = { if (target != player) { player.$give(card, target, false); } - await game.asyncDelay(0.5); + await game.delay(0.5); await target.equip(card); } else break; } @@ -735,7 +6175,7 @@ const skills = { for (let j = 0; j < targets.length; j++) { await targets[j].draw("nodelay"); } - await game.asyncDelayx(); + await game.delayx(); } break; } @@ -748,7 +6188,7 @@ const skills = { for (const target of choices) { target.addTempSkill("draglizhong_effect", "roundStart"); } - await game.asyncDelayx(); + await game.delayx(); } }, subSkill: { @@ -894,16 +6334,16 @@ const skills = { if (player.skipList.includes("phaseUse")) return true; return ( player.countCards("h") + - event.num + - Math.min( - 5, - game.countPlayer(target => { - return target.inRange(player); - }) - ) - + event.num + + Math.min( + 5, game.countPlayer(target => { - return target != player && get.attitude(player, target) > 0; - }) <= + return target.inRange(player); + }) + ) - + game.countPlayer(target => { + return target != player && get.attitude(player, target) > 0; + }) <= player.getHandcardLimit() ); }, @@ -996,10 +6436,10 @@ const skills = { audio: 1, trigger: { global: "useCard" }, direct: true, - filter: function (event, player) { + filter(event, player) { return event.player != player && event.card.name == "sha" && player.countCards("he") > 0 && event.player.isPhaseUsing(); }, - content: function () { + content() { "step 0"; var go = false, d1 = false; @@ -1101,10 +6541,10 @@ const skills = { forced: true, charlotte: true, onremove: true, - filter: function (event, player) { + filter(event, player) { return event.card && event.card.name == "sha" && event.card.storage && event.card.storage.vtbguisha_targets && event.card.storage.vtbguisha_targets.includes(event.player); }, - content: function () { + content() { trigger.num++; }, }, @@ -1116,13 +6556,13 @@ const skills = { global: "damageSource", }, usable: 2, - filter: function (event, player) { + filter(event, player) { return event.source && event.source != player && event.card && event.card.name == "sha" && event.source.isIn(); }, - check: function (event, player) { + check(event, player) { return get.attitude(player, event.source) >= 0 || (get.attitude(player, event.source) >= -4 && get.distance(_status.currentPhase, player, "absolute") > get.distance(_status.currentPhase, event.source, "absolute")); }, - content: function () { + content() { "step 0"; var drawers = [trigger.source, player].sortBySeat(_status.currentPhase); game.asyncDraw(drawers); @@ -1134,7 +6574,7 @@ const skills = { trigger: { global: "useCardToTarget", }, - filter: function (event, player) { + filter(event, player) { return ( event.card.name == "sha" && event.target != player && @@ -1145,7 +6585,7 @@ const skills = { ); }, direct: true, - content: function () { + content() { "step 0"; player .chooseToDiscard(get.prompt("vtbshanwu"), "弃置一张【闪】,取消此【杀】对" + get.translation(trigger.targets) + "的目标", { name: "shan" }) @@ -1205,7 +6645,7 @@ const skills = { global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], }, usable: 2, - filter: function (event, player) { + filter(event, player) { if (!_status.currentPhase || !_status.currentPhase.isIn() || !_status.currentPhase.countGainableCards(player, "he")) return false; var evt = event.getl(player); return ( @@ -1216,14 +6656,14 @@ const skills = { }) ); }, - check: function (event, player) { + check(event, player) { return get.effect(_status.currentPhase, { name: "shunshou_copy2" }, player, player) > 0; }, - prompt2: function (event, player) { + prompt2(event, player) { return "获得" + get.translation(_status.currentPhase) + "的一张牌"; }, logTarget: () => _status.currentPhase, - content: function () { + content() { "step 0"; player.gainPlayerCard(_status.currentPhase, "he", true); }, @@ -1238,7 +6678,7 @@ const skills = { player: "phaseBegin", }, direct: true, - content: function () { + content() { "step 0"; if (!_status.vtbtaoyan_count) { _status.vtbtaoyan_count = 5; @@ -1283,14 +6723,14 @@ const skills = { popup: false, firstDo: true, forceDie: true, - filter: function (event, player) { + filter(event, player) { if (typeof _status.vtbtaoyan_count != "number") return false; var cards = event.getd(); return cards.some(card => { return _status.vtbtaoyan_cards.includes(card.cardid); }); }, - content: function () { + content() { var cards = trigger.getd(), remove = []; for (var card of cards) { @@ -1315,15 +6755,15 @@ const skills = { trigger: { global: "dying", }, - filter: function (event, player) { + filter(event, player) { if (player.hasSkill("vtbyanli_used")) return false; if (_status.currentPhase == player) return false; return event.player.hp <= 0; }, - check: function (event, player) { + check(event, player) { return get.recoverEffect(event.player, player, player) > 0; }, - content: function () { + content() { "step 0"; player.addTempSkill("vtbyanli_used", "roundStart"); trigger.player.recover(1 - trigger.player.hp); @@ -1342,10 +6782,10 @@ const skills = { global: "phaseBegin", }, direct: true, - filter: function (event, player) { + filter(event, player) { return player.countCards("he") >= 3; }, - content: function () { + content() { "step 0"; player .chooseToDiscard(get.prompt2("vtbleyu", trigger.player), 3, "he") @@ -1376,7 +6816,7 @@ const skills = { audio: 1, trigger: { global: ["phaseUseSkipped", "phaseUseCancelled"] }, direct: true, - content: function () { + content() { "step 0"; player.chooseTarget(get.prompt2("vtbyuanli"), lib.filter.notMe).set("ai", target => get.attitude(_status.event.player, target) + 1); "step 1"; @@ -1392,28 +6832,28 @@ const skills = { vtbmeiniang: { audio: 1, trigger: { global: "phaseUseBegin" }, - filter: function (event, player) { + filter(event, player) { return event.player != player; }, - check: function (event, player) { + check(event, player) { return get.attitude(player, event.player) > 0 && event.player.getUseValue("jiu") >= 0; }, logTarget: "player", - content: function () { + content() { trigger.player.chooseUseTarget("jiu", true, false); }, }, vtbyaoli: { audio: 1, trigger: { global: "useCardAfter" }, - filter: function (event, player) { + filter(event, player) { return event.card.name == "jiu" && event.player != player && event.player.isPhaseUsing(); }, logTarget: "player", - check: function (event, player) { + check(event, player) { return get.attitude(player, event.player) > 0; }, - content: function () { + content() { trigger.player.addTempSkill("vtbyaoli_effect"); trigger.player.addMark("vtbyaoli_effect", 1, false); }, @@ -1429,10 +6869,10 @@ const skills = { popup: false, onremove: true, nopop: true, - filter: function (event, player) { + filter(event, player) { return event.card.name == "sha" && player.countMark("vtbyaoli_effect") > 0; }, - content: function () { + content() { "step 0"; trigger.directHit.addArray(game.filterPlayer()); var num = player.countMark("vtbyaoli_effect"); @@ -1471,7 +6911,7 @@ const skills = { }, ai: { directHit_ai: true, - skillTagFilter: function (player, tag, arg) { + skillTagFilter(player, tag, arg) { return arg.card.name == "sha"; }, }, @@ -1482,10 +6922,10 @@ const skills = { psshouli: { audio: "shouli", enable: ["chooseToUse", "chooseToRespond"], - hiddenCard: function (player, name) { + hiddenCard(player, name) { if (player != _status.currentPhase && (name == "sha" || name == "shan")) return true; }, - filter: function (event, player) { + filter(event, player) { if (event.responded || event.psshouli || event.type == "wuxie") return false; if ( game.hasPlayer(function (current) { @@ -1525,7 +6965,7 @@ const skills = { }, delay: false, locked: true, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { var event = _status.event, evt = event; if (event._backup) evt = event._backup; @@ -1565,7 +7005,7 @@ const skills = { }); }, prompt: "将场上的一张坐骑牌当做【杀】或【闪】使用或打出", - content: function () { + content() { "step 0"; var evt = event.getParent(2); evt.set("psshouli", true); @@ -1661,7 +7101,7 @@ const skills = { evt.set("norestore", true); evt.set("custom", { add: {}, - replace: { window: function () {} }, + replace: { window() { } }, }); } else { delete evt.result.skill; @@ -1688,7 +7128,7 @@ const skills = { ai: { respondSha: true, respondShan: true, - skillTagFilter: function (player, tag) { + skillTagFilter(player, tag) { var func = get.is[tag == "respondSha" ? "attackingMount" : "defendingMount"]; return game.hasPlayer(function (current) { return current.hasCard(card => func(card, false), "e"); @@ -1696,7 +7136,7 @@ const skills = { }, order: 2, result: { - player: function (player, target) { + player(player, target) { var att = Math.max(8, get.attitude(player, target)); if (_status.event.type != "phase") return 9 - att; if (!player.hasValueTarget({ name: "sha" })) return 0; @@ -1711,7 +7151,7 @@ const skills = { trigger: { player: "damageBegin1" }, forced: true, mark: true, - content: function () { + content() { trigger.num++; game.setNature(trigger, "thunder"); }, @@ -1749,7 +7189,7 @@ const skills = { player: "enterGame", }, forced: true, - filter: function (event, player) { + filter(event, player) { return event.name != "phase" || game.phaseNumber == 0; }, logTarget: () => game.filterPlayer(), @@ -1763,7 +7203,7 @@ const skills = { ["heart", 13, "zhuahuang"], ["heart", 3, "jingfanma"], ], - content: function () { + content() { "step 0"; event.targets = game.filterPlayer().sortBySeat(_status.firstAct2 || game.zhong || game.zhu || _status.firstAct || player); event.target = event.targets.shift(); @@ -1810,12 +7250,12 @@ const skills = { popup: false, firstDo: true, forceDie: true, - filter: function (event, player) { + filter(event, player) { if (!_status.psshouli_equips || !_status.psshouli_equips.length) return false; var cards = event.getd(); return cards.filter(i => _status.psshouli_equips.includes(i.cardid)).length; }, - content: function () { + content() { var cards = trigger.getd(), remove = []; for (var card of cards) { @@ -1835,7 +7275,7 @@ const skills = { }, psshouli_backup: { sourceSkill: "psshouli", - precontent: function () { + precontent() { "step 0"; delete event.result.skill; event.result._apply_args = { throw: false }; @@ -1852,7 +7292,7 @@ const skills = { target.addTempSkill("psshouli_thunder"); player.addTempSkill("psshouli_thunder"); }, - filterCard: function () { + filterCard() { return false; }, prompt: "请选择【杀】的目标", @@ -1874,10 +7314,10 @@ const skills = { trigger: { player: ["useCard", "respond"] }, direct: true, locked: false, - filter: function (event, player) { + filter(event, player) { return game.hasPlayer(i => i.countCards("ej", cardx => get.type(cardx) == "equip" && get.suit(event.card) == get.suit(cardx))); }, - content: function () { + content() { "step 0"; var suit = get.suit(trigger.card), extra = game @@ -1911,10 +7351,10 @@ const skills = { var num = result.cards.length; player.draw( num + - game - .filterPlayer() - .map(i => i.countCards("ej", cardx => get.type(cardx) == "equip" && get.suit(trigger.card) == get.suit(cardx))) - .reduce((p, c) => p + c) + game + .filterPlayer() + .map(i => i.countCards("ej", cardx => get.type(cardx) == "equip" && get.suit(trigger.card) == get.suit(cardx))) + .reduce((p, c) => p + c) ); } }, @@ -1971,13 +7411,13 @@ const skills = { trigger: { global: "dying" }, forced: true, //priority:6.5, - check: function () { + check() { return false; }, - filter: function (event, player) { + filter(event, player) { return event.player != player && event.parent.name == "damage" && event.parent.source && event.parent.source.isFriendOf(player); }, - content: function () { + content() { player.draw(); }, ai: { @@ -1989,13 +7429,13 @@ const skills = { audio: "suishi", trigger: { global: "dieAfter" }, forced: true, - check: function () { + check() { return false; }, - filter: function (event, player) { + filter(event, player) { return event.player.isFriendOf(player); }, - content: function () { + content() { player.loseHp(); }, }, @@ -2005,17 +7445,17 @@ const skills = { forced: true, trigger: { target: "useCardToBefore" }, priority: 15, - filter: function (event, player) { + filter(event, player) { if (!player.hasEmptySlot(2)) return false; if (event.card.name != "sha") return false; return game.hasNature(event.card); }, - content: function () { + content() { trigger.cancel(); }, ai: { effect: { - target_use(card, player, target) { + target(card, player, target) { if (card.name === "sha" && game.hasNature(card) && target.hasEmptySlot(2)) return "zeroplayertarget"; if (get.subtype(card) == "equip2" && target.isEmpty(2)) return [0.6, -0.8]; }, @@ -2027,10 +7467,10 @@ const skills = { audio: "shangyi", enable: "phaseUse", usable: 1, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { return player != target; }, - content: function () { + content() { "step 0"; target.viewHandcards(player); "step 1"; @@ -2044,7 +7484,7 @@ const skills = { ai: { order: 11, result: { - target: function (player, target) { + target(player, target) { return -target.countCards("h"); }, }, @@ -2057,11 +7497,11 @@ const skills = { trigger: { global: "useCard" }, forced: true, preHidden: true, - filter: function (event, player) { + filter(event, player) { if (get.type(event.card) != "equip") return false; return player.countMark("pkwuku") < 3; }, - content: function () { + content() { player.addMark("pkwuku", 1); }, marktext: "库", @@ -2080,10 +7520,10 @@ const skills = { juexingji: true, skillAnimation: true, animationColor: "gray", - filter: function (event, player) { + filter(event, player) { return player.countMark("pkwuku") > 2; }, - content: function () { + content() { player.awakenSkill("pksanchen"); player.gainMaxHp(); player.recover(); @@ -2097,7 +7537,7 @@ const skills = { pkmiewu: { audio: "spmiewu", enable: ["chooseToUse", "chooseToRespond"], - filter: function (event, player) { + filter(event, player) { if (!player.countMark("pkwuku") || player.hasSkill("pkmiewu2")) return false; for (var i of lib.inpile) { var type = get.type(i); @@ -2106,7 +7546,7 @@ const skills = { return false; }, chooseButton: { - dialog: function (event, player) { + dialog(event, player) { var list = []; for (var i = 0; i < lib.inpile.length; i++) { var name = lib.inpile[i]; @@ -2124,7 +7564,7 @@ const skills = { //filter:function(button,player){ // return _status.event.getParent().filterCard({name:button.link[2]},player,_status.event.getParent()); //}, - check: function (button) { + check(button) { if (_status.event.getParent().type != "phase") return 1; var player = _status.event.player; if (["wugu", "zhulu_card", "yiyi", "lulitongxin", "lianjunshengyan", "diaohulishan"].includes(button.link[2])) return 0; @@ -2133,24 +7573,24 @@ const skills = { nature: button.link[3], }); }, - backup: function (links, player) { + backup(links, player) { return { audio: "spmiewu", filterCard: () => false, selectCard: -1, popname: true, viewAs: { name: links[0][2], nature: links[0][3] }, - precontent: function () { + precontent() { player.addTempSkill("pkmiewu2"); player.removeMark("pkwuku", 1); }, }; }, - prompt: function (links, player) { + prompt(links, player) { return "视为使用" + (get.translation(links[0][3]) || "") + get.translation(links[0][2]) + "并摸一张牌"; }, }, - hiddenCard: function (player, name) { + hiddenCard(player, name) { if (!lib.inpile.includes(name)) return false; var type = get.type(name); return (type == "basic" || type == "trick") && player.countMark("pkwuku") > 0 && !player.hasSkill("pkmiewu2"); @@ -2160,12 +7600,12 @@ const skills = { fireAttack: true, respondSha: true, respondShan: true, - skillTagFilter: function (player) { + skillTagFilter(player) { if (!player.countMark("pkwuku") || player.hasSkill("pkmiewu2")) return false; }, order: 1, result: { - player: function (player) { + player(player) { if (_status.event.dying) return get.attitude(player, _status.event.dying); return 1; }, @@ -2177,10 +7617,10 @@ const skills = { forced: true, charlotte: true, popup: false, - filter: function (event, player) { + filter(event, player) { return event.skill == "pkmiewu_backup"; }, - content: function () { + content() { player.draw(); }, }, @@ -2189,11 +7629,11 @@ const skills = { pszhonghun: { audio: "zhongyi", trigger: { player: ["useCard", "respond"] }, - filter: function (event, player) { + filter(event, player) { return get.color(event.card) == "red"; }, frequent: true, - content: function () { + content() { "step 0"; var card = game.cardsGotoOrdering(get.cards()).cards[0]; event.card = card; @@ -2207,11 +7647,11 @@ const skills = { psqizuo: { audio: 2, trigger: { global: ["damageBegin1", "damageBegin3"] }, - filter: function (event, player, name) { + filter(event, player, name) { return (name == "damageBegin1" && event.source && event.source.isIn() && player.inRange(event.source)) || (name == "damageBegin3" && event.player && event.player.isIn() && player.inRange(event.player)); }, direct: true, - content: function () { + content() { "step 0"; var name = event.triggername; var source = get.translation(trigger.source), @@ -2284,10 +7724,10 @@ const skills = { global: "useCardAfter", }, direct: true, - filter: function (event, player) { + filter(event, player) { return get.type2(event.card) == "trick" && event.player != player && event.targets && event.targets.includes(player) && event.cards.filterInD("odj").length && player.countCards("h"); }, - content: function () { + content() { "step 0"; player .chooseToDiscard(get.prompt("psquanmou"), "弃置一张" + get.translation(get.color(trigger.card)) + "手牌,获得" + get.translation(trigger.cards), "h", (card, player) => { @@ -2312,11 +7752,11 @@ const skills = { audio: 2, trigger: { player: ["shaMiss", "eventNeutralized"] }, direct: true, - filter: function (event, player) { + filter(event, player) { if (!event.card || event.card.name != "sha") return false; return event.target.isIn() && player.canUse("sha", event.target, false) && (player.hasSha() || (_status.connectMode && player.countCards("h"))); }, - content: function () { + content() { "step 0"; player .chooseToUse( @@ -2335,11 +7775,11 @@ const skills = { audio: 2, trigger: { source: "damageSource" }, usable: 1, - filter: function (event, player) { + filter(event, player) { return event.card && event.card.name == "sha" && event.getParent(2).player == player && event.notLink() && player.isPhaseUsing(); }, direct: true, - content: function () { + content() { "step 0"; player .chooseToUse( @@ -2360,10 +7800,10 @@ const skills = { psqijin: { audio: 2, trigger: { player: "phaseDrawBegin1" }, - filter: function (event, player) { + filter(event, player) { return !event.numFixed; }, - content: function () { + content() { "step 0"; trigger.changeToZero(); event.cards = get.cards(7); @@ -2419,10 +7859,10 @@ const skills = { psqichu: { audio: 2, enable: ["chooseToUse", "chooseToRespond"], - hiddenCard: function (player, name) { + hiddenCard(player, name) { if (player != _status.currentPhase && !player.hasSkill("psqichu_used") && get.type(name) == "basic" && lib.inpile.includes(name)) return true; }, - filter: function (event, player) { + filter(event, player) { if (event.responded || player == _status.currentPhase || player.hasSkill("psqichu_used")) return false; for (var i of lib.inpile) { if (get.type(i) == "basic" && event.filterCard({ name: i }, player, event)) return true; @@ -2430,7 +7870,7 @@ const skills = { return false; }, delay: false, - content: function () { + content() { "step 0"; player.addTempSkill("psqichu_used"); var evt = event.getParent(2); @@ -2531,7 +7971,7 @@ const skills = { }, ai: { effect: { - target: function (card, player, target, effect) { + target(card, player, target, effect) { if (target.hasSkill("psqichu_used")) return; if (get.tag(card, "respondShan")) return 0.7; if (get.tag(card, "respondSha")) return 0.7; @@ -2541,7 +7981,7 @@ const skills = { respondShan: true, respondSha: true, result: { - player: function (player) { + player(player) { if (_status.event.dying) return get.attitude(player, _status.event.dying); return 1; }, @@ -2549,14 +7989,14 @@ const skills = { }, subSkill: { backup: { - precontent: function () { + precontent() { delete event.result.skill; var name = event.result.card.name; event.result.cards = event.result.card.cards; event.result.card = get.autoViewAs(event.result.cards[0]); event.result.card.name = name; }, - filterCard: function () { + filterCard() { return false; }, selectCard: -1, @@ -2568,10 +8008,10 @@ const skills = { audio: 2, trigger: { player: "phaseJudgeBegin" }, direct: true, - filter: function (event, player) { + filter(event, player) { return player.countCards("j") && player.countCards("h"); }, - content: function () { + content() { "step 0"; player .chooseToDiscard(get.prompt2("pslongxin"), { type: "equip" }, "he") @@ -2601,11 +8041,11 @@ const skills = { global: "loseAsyncAfter", }, frequent: true, - filter: function (event, player) { + filter(event, player) { if (player != _status.currentPhase) return false; return event.getg(player).filter(i => get.owner(i) == player).length > 0; }, - content: function () { + content() { "step 0"; player.showCards( trigger.getg(player).filter(i => get.owner(i) == player), @@ -2626,7 +8066,7 @@ const skills = { charlotte: true, forced: true, onremove: ["psoldshiyin_effect", "psoldshiyin_damage"], - content: function () { + content() { var num = player.countMark("psoldshiyin_effect"); if (num >= 1) trigger.directHit.addArray(game.players); if (num >= 2 && get.tag(trigger.card, "damage")) trigger.baseDamage += player.countMark("psoldshiyin_damage"); @@ -2634,7 +8074,7 @@ const skills = { player.removeSkill("psoldshiyin_effect"); }, mod: { - aiOrder: function (player, card, num) { + aiOrder(player, card, num) { var numx = player.countMark("psoldshiyin_effect"); if (numx >= 2 && get.tag(card, "damage")) return num + 10; }, @@ -2653,10 +8093,10 @@ const skills = { locked: false, direct: true, group: "psshiyin_change", - filter: function (event, player) { + filter(event, player) { return event.name != "phase" || game.phaseNumber == 0; }, - content: function () { + content() { "step 0"; player.chooseCard(get.prompt("psshiyin"), "将一张手牌置于武将牌上,称为“杂音”牌").set("ai", card => 20 - get.value(card)); "step 1"; @@ -2676,10 +8116,10 @@ const skills = { change: { trigger: { player: "phaseUseBegin" }, direct: true, - filter: function (event, player) { + filter(event, player) { return player.getExpansions("psshiyin").length && player.countCards("h"); }, - content: function () { + content() { "step 0"; var card = player.getExpansions("psshiyin")[0]; player @@ -2711,24 +8151,24 @@ const skills = { }, }, ai: { - combo: "psliaozou" + combo: "psliaozou", }, }, psquwu: { audio: 2, forced: true, trigger: { target: "useCardToBefore" }, - filter: function (event, player) { + filter(event, player) { return player.getExpansions("psshiyin").length && get.suit(player.getExpansions("psshiyin")[0]) == get.suit(event.card); }, - content: function () { + content() { trigger.cancel(); }, ai: { threaten: 1.1, combo: "psshiyin", effect: { - target_use(card, player, target, current) { + target(card, player, target, current) { var list = target.getExpansions("psshiyin"); for (var cardx of list) { if (get.suit(cardx) == get.suit(card)) return "zeroplayertarget"; @@ -2737,19 +8177,19 @@ const skills = { }, }, mod: { - cardEnabled2: function (card, player) { + cardEnabled2(card, player) { var list = player.getExpansions("psshiyin"); for (var cardx of list) { if (get.suit(cardx) == get.suit(card)) return false; } }, - cardRespondable: function (card, player) { + cardRespondable(card, player) { var list = player.getExpansions("psshiyin"); for (var cardx of list) { if (get.suit(cardx) == get.suit(card)) return false; } }, - cardSavable: function (card, player) { + cardSavable(card, player) { var list = player.getExpansions("psshiyin"); for (var cardx of list) { if (get.suit(cardx) == get.suit(card)) return false; @@ -2761,10 +8201,10 @@ const skills = { audio: 2, enable: "phaseUse", locked: false, - filter: function (event, player) { + filter(event, player) { return !player.hasSkill("psliaozou_blocker", null, null, false) && player.getExpansions("psshiyin").length > 0; }, - content: function () { + content() { "step 0"; player.showHandcards(get.translation(player) + "发动了【聊奏】"); "step 1"; @@ -2787,11 +8227,11 @@ const skills = { blocker: { charlotte: true }, }, mod: { - aiValue: function (player, card, num) { + aiValue(player, card, num) { var suit = get.suit(card); if (player.isPhaseUsing() && player.getExpansions("psshiyin").some(i => get.suit(i) == suit)) return num / 5; }, - aiUseful: function () { + aiUseful() { return lib.skill.psliaozou.mod.aiValue.apply(this, arguments); }, }, @@ -2799,7 +8239,7 @@ const skills = { combo: "psshiyin", order: 9.9, result: { - player: function (player) { + player(player) { var cards = player.getExpansions("psshiyin"), bool = true; for (var card of cards) { @@ -2815,11 +8255,11 @@ const skills = { psquanyi: { enable: "phaseUse", usable: 1, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { return player.canCompare(target); }, group: "psquanyi_tianbian", - content: function () { + content() { "step 0"; player.chooseToCompare(target, function (card) { if (typeof card == "string" && lib.skill[card]) { @@ -2892,7 +8332,7 @@ const skills = { tianbian: { audio: "psquanyi", enable: "chooseCard", - check: function (event) { + check(event) { var player = _status.event.player; if (player.hasSkill("smyyingshi")) { var card = ui.cardPile.childNodes[0]; @@ -2905,10 +8345,10 @@ const skills = { ? 20 : 0; }, - filter: function (event) { + filter(event) { return event.type == "compare" && !event.directresult; }, - onCompare: function (player) { + onCompare(player) { return game.cardsGotoOrdering(get.cards()).cards; }, }, @@ -2919,11 +8359,11 @@ const skills = { audio: 2, trigger: { player: "phaseDrawBegin1" }, forced: true, - filter: function (event, player) { + filter(event, player) { return !event.numFixed; }, group: "psliushang_give", - content: function () { + content() { "step 0"; trigger.changeToZero(); player.draw(1 + Math.max(3, game.countPlayer())); @@ -2937,11 +8377,11 @@ const skills = { current: current, filterCard: true, forced: true, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { return target == _status.event.current; }, selectTarget: -1, - ai1: function (card) { + ai1(card) { var current = _status.event.current; return get.value(card, current) * get.attitude(_status.event.player, current); }, @@ -2961,12 +8401,12 @@ const skills = { subSkill: { give: { trigger: { global: "phaseZhunbeiBegin" }, - filter: function (event, player) { + filter(event, player) { return event.player != player && event.player.getExpansions("psliushang").length; }, forced: true, logTarget: "player", - content: function () { + content() { "step 0"; var cards = trigger.player.getExpansions("psliushang"), name = get.translation(cards); @@ -3005,19 +8445,19 @@ const skills = { }, prevent: { trigger: { source: "damageBegin2" }, - filter: function (event, player) { + filter(event, player) { return player.getStorage("psliushang_prevent").includes(event.player); }, forced: true, onremove: true, charlotte: true, logTarget: "player", - content: function () { + content() { trigger.cancel(); }, ai: { effect: { - target: function (card, player, target, current) { + target(card, player, target, current) { if (player.getStorage("psliushang_prevent").includes(target) && get.tag(card, "damage")) { return "zeroplayertarget"; } @@ -3029,13 +8469,13 @@ const skills = { }, psqibu: { trigger: { player: "dying" }, - filter: function (event, player) { + filter(event, player) { return player.hp <= 0; }, limited: true, skillAnimation: true, animationColor: "water", - content: function () { + content() { "step 0"; player.awakenSkill("psqibu"); var cards = game.cardsGotoOrdering(get.cards(7)).cards; @@ -3057,10 +8497,10 @@ const skills = { animationColor: "water", limited: true, direct: true, - filter: function (event, player) { + filter(event, player) { return player.hp >= 1; }, - content: function () { + content() { "step 0"; player.chooseTarget(get.prompt2("psjianwei"), lib.filter.notMe).set("ai", target => { var player = _status.event.player; @@ -3106,7 +8546,7 @@ const skills = { next.setContent(lib.skill.psjianwei.swapRegioncards); } }, - swapRegioncards: function () { + swapRegioncards() { "step 0"; player.$giveAuto(event.cards1, target); target.$giveAuto(event.cards2, player); @@ -3160,10 +8600,10 @@ const skills = { audio: 2, trigger: { global: "dieAfter" }, global: "pszhonghu_skip", - filter: function (event, player) { + filter(event, player) { return player != _status.currentPhase; }, - content: function () { + content() { "step 0"; var evt = trigger.getParent("phaseUse"); if (evt && evt.name == "phaseUse") { @@ -3184,11 +8624,11 @@ const skills = { priority: Infinity, popup: false, firstDo: true, - filter: function (event, player) { + filter(event, player) { if ((_status._pszhonghu && !_status._pszhonghu.isIn()) || event.player == _status._pszhonghu) delete _status._pszhonghu; return _status._pszhonghu && event.player != _status._pszhonghu; }, - content: function () { + content() { trigger.cancel(null, null, "notrigger"); }, }, @@ -3199,7 +8639,7 @@ const skills = { audio: 2, trigger: { player: "phaseBegin" }, frequent: true, - content: function () { + content() { "step 0"; player.judge(function (card) { if (get.type(card) == "basic" || get.type(card) == "trick") return 3; @@ -3222,21 +8662,21 @@ const skills = { enable: "chooseToUse", popname: true, position: "hs", - hiddenCard: function (player, name) { + hiddenCard(player, name) { return player.storage.pshuxiao_use.card.name == name; }, - filter: function (event, player) { + filter(event, player) { if (!player.storage.pshuxiao_use) return false; if (!player.countCards("h")) return false; return event.filterCard(player.storage.pshuxiao_use.card, player, event); }, - viewAs: function (cards, player) { + viewAs(cards, player) { return player.storage.pshuxiao_use.card; }, - filterCard: function (card, player) { + filterCard(card, player) { return get.number(card) == player.storage.pshuxiao_use.number || get.suit(card) == player.storage.pshuxiao_use.suit; }, - prompt: function (event) { + prompt(event) { var player = _status.event.player; return "将一张" + get.translation(player.storage.pshuxiao_use.suit) + "牌或点数为" + get.strNumber(player.storage.pshuxiao_use.number) + "的牌当作" + get.translation(player.storage.pshuxiao_use.card) + "使用"; }, @@ -3248,14 +8688,14 @@ const skills = { trigger: { player: "phaseZhunbeiBegin" }, frequent: true, preHidden: true, - content: function () { + content() { "step 0"; var num = 5; var cards = get.cards(num); game.cardsGotoOrdering(cards); var next = player.chooseToMove(); next.set("list", [["牌堆顶", cards], ["牌堆底"]]); - next.set("prompt", "观星:点击将牌移动到牌堆顶或牌堆底"); + next.set("prompt", "观星:点击或拖动将牌移动到牌堆顶或牌堆底"); next.processAI = function (list) { var cards = list[0][1], player = _status.event.player; @@ -3311,7 +8751,7 @@ const skills = { pslongyin: { audio: 2, enable: ["chooseToUse", "chooseToRespond"], - filter: function (event, player) { + filter(event, player) { if (!player.countCards("hse") || player.hasSkill("pslongyin_used")) return false; for (var i of lib.inpile) { var type = get.type(i); @@ -3320,7 +8760,7 @@ const skills = { return false; }, chooseButton: { - dialog: function (event, player) { + dialog(event, player) { var list = []; for (var i = 0; i < lib.inpile.length; i++) { var name = lib.inpile[i]; @@ -3334,10 +8774,10 @@ const skills = { } return ui.create.dialog("虎啸", [list, "vcard"]); }, - filter: function (button, player) { + filter(button, player) { return _status.event.getParent().filterCard({ name: button.link[2], nature: button.link[3] }, player, _status.event.getParent()); }, - check: function (button) { + check(button) { if (_status.event.getParent().type != "phase") return 1; var player = _status.event.player; if (["wugu", "zhulu_card", "yiyi", "lulitongxin", "lianjunshengyan", "diaohulishan"].includes(button.link[2])) return 0; @@ -3346,9 +8786,9 @@ const skills = { nature: button.link[3], }); }, - backup: function (links, player) { + backup(links, player) { return { - filterCard: function (card, player) { + filterCard(card, player) { var num = 0; for (var i = 0; i < ui.selected.cards.length; i++) { num += get.number(ui.selected.cards[i]); @@ -3356,7 +8796,7 @@ const skills = { return get.number(card) + num <= 13; }, selectCard: [1, Infinity], - filterOk: function () { + filterOk() { var num = 0; for (var i = 0; i < ui.selected.cards.length; i++) { num += get.number(ui.selected.cards[i]); @@ -3366,7 +8806,7 @@ const skills = { audio: "pslongyin", popname: true, complexCard: true, - check: function (card) { + check(card) { var num = 0; for (var i = 0; i < ui.selected.cards.length; i++) { num += get.number(ui.selected.cards[i]); @@ -3386,16 +8826,16 @@ const skills = { }, position: "hes", viewAs: { name: links[0][2], nature: links[0][3] }, - precontent: function () { + precontent() { player.addTempSkill("pslongyin_used"); }, }; }, - prompt: function (links, player) { + prompt(links, player) { return "将任意张点数和为13牌当做" + (get.translation(links[0][3]) || "") + get.translation(links[0][2]) + "使用"; }, }, - hiddenCard: function (player, name) { + hiddenCard(player, name) { if (!lib.inpile.includes(name)) return false; var type = get.type(name); return (type == "basic" || type == "trick") && player.countCards("she") > 0 && !player.hasSkill("pslongyin_used"); @@ -3404,12 +8844,12 @@ const skills = { fireAttack: true, respondSha: true, respondShan: true, - skillTagFilter: function (player) { + skillTagFilter(player) { if (!player.countCards("hse") || player.hasSkill("pslongyin_used")) return false; }, order: 1, result: { - player: function (player) { + player(player) { if (_status.event.dying) return get.attitude(player, _status.event.dying); return 1; }, @@ -3424,7 +8864,7 @@ const skills = { audio: 2, enable: "phaseUse", usable: 1, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { if (!ui.selected.targets.length) return true; return target.group != ui.selected.targets[0].group; }, @@ -3434,10 +8874,10 @@ const skills = { multiline: true, filterCard: true, selectCard: 2, - check: function (card) { + check(card) { return 6 - get.value(card); }, - content: function () { + content() { "step 0"; targets.sortBySeat(); if (targets[0].canUse("sha", targets[1], false)) targets[0].useCard({ name: "sha", isCard: true }, targets[1], false, "noai"); @@ -3448,7 +8888,7 @@ const skills = { order: 2.5, result: { player: 1, - target: function (player, target) { + target(player, target) { if (ui.selected.targets.length) { var targetx = ui.selected.targets[0]; if (get.effect(targetx, { name: "sha" }, target, player) + get.effect(target, { name: "sha" }, targetx, player) < 0) return 0; @@ -3464,10 +8904,10 @@ const skills = { enable: "phaseUse", filterCard: true, selectCard: 2, - check: function (card) { + check(card) { return 6 - get.value(card); }, - content: function () { + content() { "step 0"; var cards = game.cardsGotoOrdering(get.cards(5)).cards; event.cards = cards; @@ -3480,7 +8920,7 @@ const skills = { ai: { order: 9, result: { - player: function (player) { + player(player) { if (player.getUseValue({ name: "wanjian" }) < 0) return 0; return 1; }, @@ -3490,10 +8930,10 @@ const skills = { //官盗S马超 psweihou: { trigger: { player: "judgeBegin" }, - filter: function (event, player) { + filter(event, player) { return !event.directresult; }, - content: function () { + content() { "step 0"; var cards = get.cards(2); for (var i = cards.length - 1; i >= 0; i--) { @@ -3537,11 +8977,11 @@ const skills = { psqupo: { audio: 2, trigger: { global: "phaseBegin" }, - filter: function (event, player) { + filter(event, player) { return player.countCards("he"); }, direct: true, - content: function () { + content() { "step 0"; var cards = player.getCards("he"); var current = trigger.player; @@ -3581,13 +9021,13 @@ const skills = { filterCard: true, prompt: get.prompt2("psqupo"), current: trigger.player, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { return player != target && target != _status.event.current; }, - ai1: function (card) { + ai1(card) { return card == _status.event.cardx ? 1 : 0; }, - ai2: function (target) { + ai2(target) { return target == _status.event.targetx ? 1 : 0; }, }); @@ -3621,13 +9061,13 @@ const skills = { forced: true, charlotte: true, onremove: true, - filter: function (event, player) { + filter(event, player) { if (event.card.name != "sha") return false; var targets = player.getStorage("psqupo_black").slice(); targets.remove(event.target); return targets.length; }, - content: function () { + content() { var targets = player.getStorage("psqupo_black").slice(); targets.remove(trigger.target); player.loseHp(targets.length); @@ -3638,7 +9078,7 @@ const skills = { charlotte: true, forced: true, onremove: true, - content: function () { + content() { player.loseHp(player.countMark("psqupo_red")); player.removeSkill("psqupo_red"); }, @@ -3648,11 +9088,11 @@ const skills = { psbaoquan: { audio: 2, trigger: { player: "damageBegin4" }, - filter: function (event, player) { + filter(event, player) { return player.countCards("h", { type: ["trick", "delay"] }) || _status.connectMode; }, direct: true, - content: function () { + content() { "step 0"; player .chooseToDiscard(get.prompt2("psbaoquan"), { type: ["trick", "delay"] }) @@ -3676,7 +9116,7 @@ const skills = { selectCard: -1, position: "h", locked: false, - filter: function (event, player) { + filter(event, player) { if (player.hasSkill("pssheji_used")) return false; var hs = player.getCards("h"); if (!hs.length) return false; @@ -3690,7 +9130,7 @@ const skills = { name: "sha", storage: { pssheji: true }, }, - onuse: function (links, player) { + onuse(links, player) { player.addTempSkill("pssheji_used", "phaseUseAfter"); }, ai: { @@ -3698,7 +9138,7 @@ const skills = { threaten: 1.1, }, mod: { - targetInRange: function (card, player, target) { + targetInRange(card, player, target) { if (card.storage && card.storage.pssheji) return true; }, }, @@ -3710,7 +9150,7 @@ const skills = { forced: true, popup: false, logTarget: "player", - filter: function (event, player) { + filter(event, player) { return ( event.card.storage && event.card.storage.pssheji && @@ -3720,7 +9160,7 @@ const skills = { }, "e") ); }, - content: function () { + content() { var cards = trigger.player.getCards("e", card => { if (!lib.filter.canBeGained(card, player, trigger.player)) return false; return ["equip1", "equip3", "equip4", "equip6"].includes(get.subtype(card)); @@ -3739,13 +9179,13 @@ const skills = { source: "damageSource", }, frequent: true, - filter: function (event, player, name) { + filter(event, player, name) { if (name == "damageEnd") return true; var evt = event.getParent(); if (evt.player != player) return false; return evt.card && evt.type == "card" && evt.targets.length == 1; }, - content: function () { + content() { "step 0"; player.draw(); "step 1"; @@ -3764,13 +9204,13 @@ const skills = { content: "expansion", markcount: "expansion", }, - onremove: function (player, skill) { + onremove(player, skill) { var cards = player.getExpansions(skill); if (cards.length) player.loseToDiscardpile(cards); }, locked: false, mod: { - maxHandcard: function (player, num) { + maxHandcard(player, num) { return num + player.getExpansions("zyquanji").length; }, }, @@ -3779,18 +9219,18 @@ const skills = { audio: "gzpaiyi", enable: "phaseUse", usable: 1, - filter: function (event, player) { + filter(event, player) { return player.getExpansions("zyquanji").length > 0; }, chooseButton: { - dialog: function (event, player) { + dialog(event, player) { return ui.create.dialog("排异", player.getExpansions("zyquanji"), "hidden"); }, - backup: function (links, player) { + backup(links, player) { return { audio: "gzpaiyi", filterTarget: true, - filterCard: function () { + filterCard() { return false; }, selectCard: -1, @@ -3800,7 +9240,7 @@ const skills = { ai: { order: 10, result: { - target: function (player, target) { + target(player, target) { if (target != player) return 0; if (player.getExpansions("zyquanji").length <= 1 || (player.needsToDiscard() && !player.getEquip("zhuge") && !player.hasSkill("new_paoxiao"))) return 0; return 1; @@ -3809,11 +9249,11 @@ const skills = { }, }; }, - prompt: function () { + prompt() { return "请选择【排异】的目标"; }, }, - contentx: function () { + contentx() { "step 0"; var card = lib.skill.zypaiyi_backup.card; player.loseToDiscardpile(card); @@ -3826,7 +9266,7 @@ const skills = { } }, ai: { - order: function (item, player) { + order(item, player) { var num = player.getExpansions("zyquanji").length; if (num == 1) return 8; return 1; @@ -3842,11 +9282,11 @@ const skills = { audio: "gzshilu", preHidden: true, trigger: { global: "dieAfter" }, - prompt2: function (event, player) { + prompt2(event, player) { return "将其的所有武将牌" + (player == event.source ? "及武将牌库里的一张随机武将牌" : "") + "置于武将牌上作为“戮”"; }, logTarget: "player", - content: function () { + content() { var list = [], target = trigger.player; if (target.name1 && !target.isUnseen(0) && target.name1.indexOf("gz_shibing") != 0 && _status.characterlist.includes(target.name1)) list.push(target.name1); @@ -3878,13 +9318,13 @@ const skills = { marktext: "戮", intro: { content: "character", - onunmark: function (storage, player) { + onunmark(storage, player) { if (storage && storage.length) { _status.characterlist.addArray(storage); storage.length = 0; } }, - mark: function (dialog, storage, player) { + mark(dialog, storage, player) { if (storage && storage.length) { dialog.addSmall([storage, "character"]); } else { @@ -3900,11 +9340,11 @@ const skills = { zhiheng: { audio: "zyshilu", trigger: { player: "phaseZhunbeiBegin" }, - filter: function (event, player) { + filter(event, player) { return player.getStorage("zyshilu").length > 0 && player.countCards("he") > 0; }, direct: true, - content: function () { + content() { "step 0"; var num = Math.min(player.getStorage("zyshilu").length, player.countCards("he")); player.chooseToDiscard("he", get.prompt("zyshilu"), "弃置至多" + get.cnNumber(num) + "张牌并摸等量的牌", [1, num]).logSkill = "zyshilu_zhiheng"; @@ -3918,10 +9358,10 @@ const skills = { audio: "gzxiongnve", trigger: { player: "phaseUseBegin" }, direct: true, - filter: function (event, player) { + filter(event, player) { return player.getStorage("zyshilu").length > 0; }, - content: function () { + content() { "step 0"; player .chooseButton([get.prompt("zyxiongnve"), [player.storage.zyshilu, "character"]]) @@ -3961,7 +9401,7 @@ const skills = { game.log(player, "本回合", "#g" + lib.skill[skill].promptx); }, group: "zyxiongnve_end", - throwCharacter: function (player, list) { + throwCharacter(player, list) { player.unmarkAuto("zyshilu", list); _status.characterlist.addArray(list); game.log(player, "从", "#y“戮”", "中移去了", "#g" + get.translation(list)); @@ -3995,7 +9435,7 @@ const skills = { trigger: { source: "damageBegin1" }, forced: true, logTarget: "player", - content: function () { + content() { trigger.num++; }, }, @@ -4009,11 +9449,11 @@ const skills = { }, trigger: { source: "damageBegin1" }, forced: true, - filter: function (event, player) { + filter(event, player) { return player != event.player && event.player.countGainableCards(player, "he") > 0; }, logTarget: "player", - content: function () { + content() { player.gainPlayerCard(trigger.player, true, "he"); }, }, @@ -4037,15 +9477,15 @@ const skills = { }, trigger: { player: "damageBegin4" }, forced: true, - filter: function (event, player) { + filter(event, player) { return event.source != player && event.source && event.source.isIn(); }, - content: function () { + content() { trigger.num--; }, ai: { effect: { - target: function (card, player, target) { + target(card, player, target) { if (player.hasSkillTag("jueqing", false, target)) return; var num = get.tag(card, "damage"); if (num) { @@ -4059,10 +9499,10 @@ const skills = { end: { trigger: { player: "phaseUseEnd" }, direct: true, - filter: function (event, player) { + filter(event, player) { return player.getStorage("zyshilu").length > 1; }, - content: function () { + content() { "step 0"; player.chooseButton(["凶虐:是否移去两张“戮”获得减伤?", [player.storage.zyshilu, "character"]], 2).set("ai", function (button) { var player = _status.event.player; @@ -4088,15 +9528,15 @@ const skills = { qiuan: { audio: 2, trigger: { player: "damageBegin4" }, - filter: function (event, player) { + filter(event, player) { return event.cards && event.cards.filterInD().length > 0 && !player.getExpansions("qiuan").length; }, - check: function (event, player) { + check(event, player) { if (get.damageEffect(player, event.source || player, player, event.nature) >= 0) return false; return true; }, preHidden: true, - content: function () { + content() { var cards = trigger.cards.filterInD(); player.addToExpansion("gain2", cards).gaintag.add("qiuan"); trigger.cancel(); @@ -4114,10 +9554,10 @@ const skills = { audio: 2, trigger: { player: "phaseZhunbeiBegin" }, forced: true, - filter: function (event, player) { + filter(event, player) { return player.getExpansions("qiuan").length > 0; }, - content: function () { + content() { "step 0"; var cards = player.getExpansions("qiuan"); player.gain(cards, "gain2").gaintag.add("liangfan"); @@ -4133,7 +9573,7 @@ const skills = { audio: "liangfan", mark: true, mod: { - aiOrder: function (player, card, num) { + aiOrder(player, card, num) { if (get.itemtype(card) == "card" && card.hasGaintag("liangfan")) return num + 0.1; }, }, @@ -4141,11 +9581,11 @@ const skills = { trigger: { source: "damageEnd" }, logTarget: "player", charlotte: true, - onremove: function (player) { + onremove(player) { player.removeGaintag("liangfan"); }, prompt: event => "量反:是否获得" + get.translation(event.player) + "的一张牌?", - filter: function (event, player) { + filter(event, player) { var evt = event.getParent(2); if (evt.name != "useCard" || evt.card != event.card) return false; if (!event.player.countGainableCards(player, "he")) return false; @@ -4160,7 +9600,7 @@ const skills = { ); }, marktext: "反", - content: function () { + content() { player.gainPlayerCard(trigger.player, true, "he"); }, }, @@ -4169,7 +9609,7 @@ const skills = { audio: 2, enable: "phaseUse", usable: 1, - filter: function (event, player) { + filter(event, player) { return ( player.countCards("he") > 0 && game.hasPlayer(function (current) { @@ -4179,13 +9619,13 @@ const skills = { }, filterCard: true, position: "he", - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { return target != player && target.countCards("he") > 0; }, - check: function (card) { + check(card) { return 6 - get.value(card); }, - content: function () { + content() { "step 0"; target .chooseCard("he", "交给" + get.translation(player) + "一张装备牌,或令其获得你的一张牌", { type: "equip" }) @@ -4205,7 +9645,7 @@ const skills = { ai: { order: 6, result: { - player: function (player, target) { + player(player, target) { if ( target.countCards("e", function (card) { return get.suit(card) == "spade" && get.value(card) < 8; @@ -4215,7 +9655,7 @@ const skills = { return get.effect(player, { name: "sha" }, target, player); return 0; }, - target: function (player, target) { + target(player, target) { var es = target.getCards("e").sort(function (a, b) { return get.value(b, target) - get.value(a, target); }); @@ -4229,10 +9669,10 @@ const skills = { zybishi: { audio: 2, trigger: { target: "useCardToTargeted" }, - filter: function (event, player) { + filter(event, player) { return event.card.name == "sha" && event.player != player; }, - check: function (event, player) { + check(event, player) { var effect = 0; if (event.targets && event.targets.length) { for (var i = 0; i < event.targets.length; i++) { @@ -4249,7 +9689,7 @@ const skills = { } return false; }, - content: function () { + content() { player.line(trigger.player, "green"); trigger.player.draw(); var evt = trigger.getParent(); @@ -4262,10 +9702,10 @@ const skills = { audio: 2, trigger: { global: "damageBegin3" }, logTarget: "player", - filter: function (event, player) { + filter(event, player) { return event.player != player && event.player.isIn() && event.card && event.card.name == "sha" && event.player.countGainableCards(player, "he") > 0; }, - content: function () { + content() { "step 0"; player.gainPlayerCard(trigger.player, true, "he"); "step 1"; @@ -4281,11 +9721,11 @@ const skills = { zylianji: { audio: "wylianji", trigger: { player: "phaseUseEnd" }, - filter: function (event, player) { + filter(event, player) { return player.hasHistory("useCard", evt => evt.getParent("phaseUse") == event); }, direct: true, - content: function () { + content() { "step 0"; var types = []; player.getHistory("useCard", evt => { @@ -4356,27 +9796,27 @@ const skills = { trigger: { player: ["phaseZhunbeiBefore", "phaseJudgeBefore", "phaseDrawBefore", "phaseUseBefore", "phaseDiscardBefore", "phaseJieshuBefore"], }, - init: function (player) { + init(player) { if (!player.storage.zylianji_skip) player.storage.zylianji_skip = []; }, forced: true, charlotte: true, group: "zylianji_insert", onremove: true, - content: function () { + content() { trigger.cancel(); player.storage.zylianji_skip.push(trigger.name); }, }, insert: { trigger: { player: "phaseEnd" }, - filter: function (event, player) { + filter(event, player) { return player.storage.zylianji_skip && player.storage.zylianji_skip.length && player.storage.zylianji_insert && player.storage.zylianji_insert.isIn(); }, forced: true, charlotte: true, onremove: true, - getStr: function (str) { + getStr(str) { switch (str) { case "phaseDraw": return "player.phaseDraw();if(!player.noPhaseDelay){if(player==game.me){game.delay()}else{game.delayx()}}"; @@ -4386,7 +9826,7 @@ const skills = { return "player." + str + "();"; } }, - content: function () { + content() { "step 0"; var func = ""; for (var i = 0; i < player.storage.zylianji_skip.length; i++) { @@ -4406,7 +9846,7 @@ const skills = { viewAs: { name: "jiedao" }, filterCard: { color: "black" }, position: "he", - check: function (card) { + check(card) { return 4.5 - get.value(card); }, }, @@ -4415,7 +9855,7 @@ const skills = { audio: "luoshen", trigger: { player: "phaseZhunbeiBegin" }, frequent: true, - content: function () { + content() { "step 0"; event.cards = []; "step 1"; @@ -4469,7 +9909,7 @@ const skills = { yjzhenlve: { audio: "zhenlue", inherit: "zhenlue", - content: function () { + content() { trigger.directHit.addArray(game.players); }, }, @@ -4477,10 +9917,10 @@ const skills = { audio: "jianshu", enable: "phaseUse", usable: 1, - filter: function (event, player) { + filter(event, player) { return player.countCards("h") > 0; }, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { if (target == player) return false; if (ui.selected.targets.length) { return ui.selected.targets[0] != target && !ui.selected.targets[0].hasSkillTag("noCompareSource") && target.countCards("h") && !target.hasSkillTag("noCompareTarget"); @@ -4491,14 +9931,14 @@ const skills = { discard: false, lose: false, delay: false, - check: function (card) { + check(card) { if (_status.event.player.hp == 1) return 8 - get.value(card); return 6 - get.value(card); }, selectTarget: 2, targetprompt: ["发起者", "拼点对象"], multitarget: true, - content: function () { + content() { "step 0"; player.give(cards, targets[0], "give"); "step 1"; @@ -4518,7 +9958,7 @@ const skills = { expose: 0.4, order: 4, result: { - target: function (player, target) { + target(player, target) { if (ui.selected.targets.length) return -1; return -0.5; }, @@ -4538,12 +9978,9 @@ const skills = { }, async cost(event, trigger, player) { event.result = await player - .chooseTarget( - get.prompt2("yjyongdi"), - (card, player, target) => { - return target.hasSex("male") || target.name == "key_yuri"; - } - ) + .chooseTarget(get.prompt2("yjyongdi"), (card, player, target) => { + return target.hasSex("male") || target.name == "key_yuri"; + }) .set("ai", target => { if (!_status.event.goon) return 0; var player = _status.event.player; @@ -4551,11 +9988,14 @@ const skills = { if (att <= 1) return 0; var mode = get.mode(); if (mode == "identity" || (mode == "versus" && _status.mode == "four")) { - if (target.getStockSkills(true, true).some(i => { - if (target.hasSkill(i)) return false; - let info = get.info(i); - return info && info.zhuSkill; - })) return att * 2; + if ( + target.getStockSkills(true, true).some(i => { + if (target.hasSkill(i)) return false; + let info = get.info(i); + return info && info.zhuSkill; + }) + ) + return att * 2; } return att; }) @@ -4564,7 +10004,8 @@ const skills = { }, async content(event, trigger, player) { player.awakenSkill("yjyongdi"); - let target = event.targets[0], mode = get.mode(); + let target = event.targets[0], + mode = get.mode(); if (player !== target && (mode !== "identity" || player.identity !== "nei")) player.addExpose(0.3); target.gainMaxHp(true); target.recover(); @@ -4585,13 +10026,13 @@ const skills = { usable: 1, filterCard: true, position: "he", - prompt: function () { + prompt() { var str = "弃置一张牌,然后获得"; if (get.itemtype(_status.pileTop) == "card") str += get.translation(_status.pileTop); else str += "牌堆顶的一张牌"; return str; }, - check: function (card) { + check(card) { var player = _status.event.player; var cardx = _status.pileTop; if (get.itemtype(cardx) != "card") return 0; @@ -4601,7 +10042,7 @@ const skills = { return (val - val2) / Math.max(0.1, get.value(card)); }, group: ["yjshicai_mark"], - content: function () { + content() { var card = get.cards()[0]; player.gain(card, "gain2").gaintag.add("yjshicai_clear"); player.addTempSkill("yjshicai_clear", "phaseUseAfter"); @@ -4615,7 +10056,7 @@ const skills = { trigger: { player: "phaseBegin" }, silent: true, firstDo: true, - content: function () { + content() { player.addTempSkill("spshicai2"); }, }, @@ -4624,13 +10065,13 @@ const skills = { player: "loseAfter", global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], }, - onremove: function (player, skill) { + onremove(player, skill) { player.removeGaintag(skill); }, forced: true, charlotte: true, popup: false, - filter: function (event, player) { + filter(event, player) { if (event.name == "lose") { for (var i in event.gaintag_map) { if (event.gaintag_map[i].includes("yjshicai_clear")) return true; @@ -4644,7 +10085,7 @@ const skills = { } }); }, - content: function () { + content() { delete player.getStat("skill").yjshicai; }, }, @@ -4655,14 +10096,14 @@ const skills = { trigger: { global: "useCardToPlayered", }, - filter: function (event, player) { + filter(event, player) { return event.isFirstTarget && event.targets.length > 1 && event.player.isIn(); }, - check: function (event, player) { + check(event, player) { return get.attitude(player, event.player) > 0; }, logTarget: "player", - content: function () { + content() { trigger.player.draw(); }, ai: { expose: 0.2 }, @@ -4671,17 +10112,17 @@ const skills = { audio: "zezhu", enable: "phaseUse", usable: 1, - filter: function (event, player) { + filter(event, player) { var zhu = get.zhu(player) || game.filterPlayer(i => i.getSeatNum() == 1)[0]; if (!zhu) return false; return zhu.countGainableCards(player, zhu == player ? "ej" : "hej"); }, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { var zhu = get.zhu(player) || game.filterPlayer(i => i.getSeatNum() == 1)[0]; return target == zhu; }, selectTarget: 1, - content: function () { + content() { "step 0"; player.gainPlayerCard(target, player == target ? "ej" : "hej", true); "step 1"; @@ -4703,13 +10144,13 @@ const skills = { filterCard: () => false, selectCard: -1, log: false, - precontent: function () { + precontent() { player.logSkill("yjtuicheng"); player.loseHp(); }, ai: { effect: { - player: function (card, player) { + player(card, player) { if (get.name(card) != "tuixinzhifu" || _status.event.skill != "yjtuicheng") return; if (player.hp < 3) return "zeroplayertarget"; if (player.hasSkill("yjshicha") && !player.hasHistory("useSkill", evt => evt.skill == "yjtuicheng")) return [1, 2]; @@ -4724,7 +10165,7 @@ const skills = { player: "phaseUseEnd", }, direct: true, - content: function () { + content() { "step 0"; player .chooseTarget(get.prompt("yjyaoling"), "减1点体力上限,选择一名其他角色A和一名角色B,令A选择对B使用杀或被你弃牌", 2, (card, player, target) => { @@ -4739,12 +10180,16 @@ const skills = { if (!ui.selected.targets.length) return get.effect(target, { name: "guohe_copy2" }, player, player); var targetx = ui.selected.targets[0]; return get.effect(target, { name: "sha" }, targetx, player) + 5; - }).set("check", function(){ - if (player.maxHp < 2) return false; - if (player.hasSkill("yjshicha") && !player.hasHistory("useSkill", evt => evt.skill == "yjtuicheng")) return true; - if (player.maxHp > 2 && player.getDamagedHp() > 1) return true; - return false; - }()); + }) + .set( + "check", + (function () { + if (player.maxHp < 2) return false; + if (player.hasSkill("yjshicha") && !player.hasHistory("useSkill", evt => evt.skill == "yjtuicheng")) return true; + if (player.maxHp > 2 && player.getDamagedHp() > 1) return true; + return false; + })() + ); "step 1"; if (result.bool) { var targets = result.targets; @@ -4753,13 +10198,10 @@ const skills = { player.line2(targets); player.loseMaxHp(); targets[0] - .chooseToUse( - function (card, player, event) { - if (get.name(card) != "sha") return false; - return lib.filter.filterCard.apply(this, arguments); - }, - "耀令:对" + get.translation(targets[1]) + "使用一张杀,或令" + get.translation(player) + "弃置你的一张牌" - ) + .chooseToUse(function (card, player, event) { + if (get.name(card) != "sha") return false; + return lib.filter.filterCard.apply(this, arguments); + }, "耀令:对" + get.translation(targets[1]) + "使用一张杀,或令" + get.translation(player) + "弃置你的一张牌") .set("targetRequired", true) .set("filterTarget", function (card, player, target) { if (target != _status.event.sourcex && !ui.selected.targets.includes(_status.event.sourcex)) return false; @@ -4777,7 +10219,7 @@ const skills = { audio: 2, trigger: { player: "phaseDiscardBegin" }, forced: true, - filter: function (event, player) { + filter(event, player) { var tuicheng = false, yaoling = false; player.getHistory("useSkill", evt => { @@ -4786,7 +10228,7 @@ const skills = { }); return !(tuicheng && yaoling); }, - content: function () { + content() { player.addTempSkill("yjshicha_limit"); }, subSkill: { @@ -4807,7 +10249,7 @@ const skills = { audio: 2, trigger: { player: "phaseJieshuBegin" }, zhuSkill: true, - filter: function (event, player) { + filter(event, player) { return ( player.hasZhuSkill("yjyongquan") && game.hasPlayer(current => { @@ -4815,12 +10257,12 @@ const skills = { }) ); }, - logTarget: function (event, player) { + logTarget(event, player) { return game.filterPlayer(current => { return current != player && player.hasZhuSkill(current) && current.group == "qun"; }); }, - content: function () { + content() { "step 0"; var targets = lib.skill.yjyongquan.logTarget(trigger, player); event.targets = targets; @@ -4847,11 +10289,8 @@ const skills = { yjjielve: { audio: 2, enable: "phaseUse", - filter: function (event, player) { - return !player.hasSkill("yjjielve_ban"); - }, viewAs: { name: "chenghuodajie" }, - filterCard: function (card, player) { + filterCard(card, player) { if (ui.selected.cards.length) return get.color(card) == get.color(ui.selected.cards[0]); var cards = player.getCards("hes"); for (var cardx of cards) { @@ -4862,10 +10301,10 @@ const skills = { position: "hes", selectCard: 2, complexCard: true, - check: function (card) { + check(card) { return 5 - get.value(card); }, - onuse: function (links, player) { + onuse(links, player) { player.addTempSkill("yjjielve_check"); }, subSkill: { @@ -4874,14 +10313,13 @@ const skills = { forced: true, charlotte: true, popup: false, - filter: function (event, player) { + filter(event, player) { return event.card && event.card.name == "chenghuodajie" && event.getParent().skill == "yjjielve"; }, - content: function () { - player.addTempSkill("yjjielve_ban"); + content() { + player.tempBanSkill("yjjielve"); }, }, - ban: { charlotte: true }, }, }, //用间beta张飞 @@ -4893,7 +10331,7 @@ const skills = { global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], }, direct: true, - filter: function (event, player) { + filter(event, player) { if (player.hp < 1 || !player.countDiscardableCards(player, "h")) return false; if (["damage", "loseHp", "recover"].includes(event.name)) return true; var evt = event.getl(player); @@ -4901,16 +10339,16 @@ const skills = { if (!evt || !evt.es.length) return false; return game.hasPlayer(current => player.canUse("sha", current, false)); }, - content: function () { + content() { "step 0"; player.chooseCardTarget({ prompt: "莽击:弃置一张手牌,视为对一名其他角色使用一张【杀】", forced: true, filterCard: lib.filter.cardDiscardable, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { return player.canUse("sha", target, false); }, - ai2: function (target) { + ai2(target) { return get.effect(target, { name: "sha" }, _status.event.player); }, }); @@ -4930,13 +10368,13 @@ const skills = { enable: "phaseUse", usable: 1, locked: false, - filter: function (event, player) { + filter(event, player) { for (var card of ui.discardPile.childNodes) { if (get.type(card) == "equip") return true; } return false; }, - content: function () { + content() { "step 0"; var cards = Array.from(ui.discardPile.childNodes).filter(i => get.type(i) == "equip"); player.chooseButton(["厉锋:获得一张装备牌", cards], cards.length > 0).set("ai", get.buttonValue); @@ -4950,13 +10388,13 @@ const skills = { order: 10, result: { player: 1 }, effect: { - target: function (card, player, target) { + target(card, player, target) { if (card && get.type(card) == "equip" && _status.event.skill == "_gifting") return 0; }, }, }, mod: { - cardGiftable: function (card, player) { + cardGiftable(card, player) { return get.type(card) == "equip"; }, }, @@ -4966,10 +10404,10 @@ const skills = { audio: 2, forced: true, mod: { - cardname: function (card, player, name) { + cardname(card, player, name) { if (player == _status.currentPhase && card.name == "du") return "guohe"; }, - aiValue: function (player, card, num) { + aiValue(player, card, num) { if (card.name == "du") return get.value({ name: "guohe" }); }, }, @@ -4977,21 +10415,21 @@ const skills = { game.addGlobalSkill("yjdumou_du"); }, onremove: () => { - if (!game.hasPlayer(i => i.hasSkill("yjdumou"), true)) game.removeGlobalSkill("yjdumou_du"); + if (!game.hasPlayer(i => i.hasSkill("yjdumou", null, null, false), true)) game.removeGlobalSkill("yjdumou_du"); }, subSkill: { du: { mod: { - cardname: function (card, player, name) { + cardname(card, player, name) { if (_status.currentPhase && player != _status.currentPhase && _status.currentPhase.hasSkill("yjdumou") && get.color(card) == "black") return "du"; }, - aiValue: function (player, card, num) { + aiValue(player, card, num) { if (get.name(card) == "du" && card.name != "du") return get.value({ name: card.name }); }, }, trigger: { player: "dieAfter" }, filter: () => { - return !game.hasPlayer(i => i.hasSkill("yjdumou"), true); + return !game.hasPlayer(i => i.hasSkill("yjdumou", null, null, false), true); }, silent: true, forceDie: true, @@ -5010,7 +10448,7 @@ const skills = { filterTarget: true, limited: true, selectTarget: () => [1, game.roundNumber], - contentBefore: function () { + contentBefore() { "step 0"; player.awakenSkill("yjweiquan"); player.chooseTarget("威权:选择获得牌的角色", true).set("ai", target => { @@ -5023,7 +10461,7 @@ const skills = { "step 1"; event.getParent()._yjweiquan = result.targets[0]; }, - content: function () { + content() { "step 0"; var targetx = event.getParent()._yjweiquan; if (target == targetx || !target.countCards("h")) event.finish(); @@ -5034,7 +10472,7 @@ const skills = { target.give(result.cards, targetx); } }, - contentAfter: function () { + contentAfter() { var targetx = event.getParent()._yjweiquan; if (targetx.countCards("h") > targetx.hp) { var next = targetx.phase(); @@ -5059,7 +10497,7 @@ const skills = { ai: { order: 6, result: { - player: function (player) { + player(player) { var num = game.countPlayer(current => get.attitude(player, current) < 0 && current.countCards("h")); if ( (game.roundNumber < num && player.hp > 2) || @@ -5078,13 +10516,13 @@ const skills = { audio: 2, enable: "phaseUse", usable: 1, - filter: function (event, player) { + filter(event, player) { for (var card of ui.discardPile.childNodes) { if (get.color(card) == "black" && get.type(card) == "basic") return true; } return false; }, - content: function () { + content() { "step 0"; var cards = Array.from(ui.discardPile.childNodes).filter(i => get.color(i) == "black" && get.type(i) == "basic"); player.chooseButton(["人望:选择一张黑色基本牌", cards], cards.length > 0).set("ai", get.buttonValue); @@ -5114,14 +10552,14 @@ const skills = { locked: false, filter: (event, player) => event.target != player && event.target.isIn(), logTarget: "target", - content: function () { + content() { "step 0"; event.target = trigger.target; event.card = trigger.card; event.target.markAuto("yjxiandao_block", [get.suit(event.card, false)]); event.target.addTempSkill("yjxiandao_block"); "step 1"; - var type = get.type(card, false); + var type = get.type(card); if (type == "trick") player.draw(2); if (type == "equip") { if ( @@ -5143,13 +10581,13 @@ const skills = { charlotte: true, onremove: true, mod: { - cardEnabled: function (card, player) { + cardEnabled(card, player) { if (player.getStorage("yjxiandao_block").includes(get.suit(card))) return false; }, - cardRespondable: function (card, player) { + cardRespondable(card, player) { if (player.getStorage("yjxiandao_block").includes(get.suit(card))) return false; }, - cardSavable: function (card, player) { + cardSavable(card, player) { if (player.getStorage("yjxiandao_block").includes(get.suit(card))) return false; }, }, @@ -5161,10 +10599,10 @@ const skills = { yjsancai: { enable: "phaseUse", usable: 1, - filter: function (event, player) { + filter(event, player) { return player.countCards("h") > 0; }, - content: function () { + content() { "step 0"; player.showHandcards(); var hs = player.getCards("h"); @@ -5191,7 +10629,7 @@ const skills = { } }, ai: { - combo: "yixiandao" + combo: "yixiandao", }, }, yjyibing: { @@ -5200,7 +10638,7 @@ const skills = { global: "loseAsyncAfter", }, direct: true, - filter: function (event, player) { + filter(event, player) { if (event.getParent().name == "gift") return false; if (event.getParent("yjyibing").player == player) return false; var evt = event.getParent("phaseDraw"), @@ -5221,7 +10659,7 @@ const skills = { ) ); }, - content: function () { + content() { var cards = trigger.getg(player); player.chooseUseTarget(get.prompt("yjyibing"), "将" + get.translation(cards) + "当做【杀】使用", "sha", cards, false, "nodistance").logSkill = "yjyibing"; }, @@ -5229,7 +10667,7 @@ const skills = { //龙羽飞 longyi: { enable: ["chooseToUse", "chooseToRespond"], - filter: function (event, player) { + filter(event, player) { if (event.type == "wuxie") return false; var hs = player.getCards("h"); if (!hs.length) return false; @@ -5248,7 +10686,7 @@ const skills = { return false; }, chooseButton: { - dialog: function (event, player) { + dialog(event, player) { var vcards = [], hs = player.getCards("h"); for (var i of lib.inpile) { @@ -5261,14 +10699,14 @@ const skills = { } return ui.create.dialog("龙裔", [vcards, "vcard"]); }, - check: function (button, player) { + check(button, player) { if (_status.event.getParent().type != "phase") return 1; return _status.event.player.getUseValue({ name: button.link[2], nature: button.link[3], }); }, - backup: function (links, player) { + backup(links, player) { return { audio: "longyi", popname: true, @@ -5278,22 +10716,22 @@ const skills = { position: "h", }; }, - prompt: function (links, player) { + prompt(links, player) { return "将所有手牌当做" + (get.translation(links[0][3]) || "") + get.translation(links[0][2]) + "使用或打出"; }, }, - hiddenCard: function (player, name) { + hiddenCard(player, name) { return name != "du" && get.type(name) == "basic" && player.countCards("h") > 0; }, ai: { respondSha: true, respondShan: true, - skillTagFilter: function (player) { + skillTagFilter(player) { return player.countCards("h") > 0; }, order: 0.5, result: { - player: function (player) { + player(player) { if (_status.event.dying) { return get.attitude(player, _status.event.dying); } @@ -5303,7 +10741,7 @@ const skills = { max = 0; for (var i of hs) { val += get.value(i, player); - if (get.type(i, player) == "trick") max += 5; + if (get.type(i, null, player) == "trick") max += 5; } if (player.hasSkill("zhenjue")) max += 7; return val <= max ? 1 : 0; @@ -5317,7 +10755,7 @@ const skills = { forced: true, charlotte: true, popup: false, - filter: function (event, player) { + filter(event, player) { if (event.skill != "longyi_backup") return false; for (var i of event.cards) { var type = get.type2(i, player); @@ -5325,7 +10763,7 @@ const skills = { } return false; }, - content: function () { + content() { var map = {}; for (var i of trigger.cards) { map[get.type2(i, player)] = true; @@ -5339,11 +10777,11 @@ const skills = { }, zhenjue: { trigger: { global: "phaseJieshuBegin" }, - filter: function (event, player) { + filter(event, player) { return player.countCards("h") == 0; }, logTarget: "player", - content: function () { + content() { "step 0"; trigger.player .chooseToDiscard("he", "弃置一张牌,或令" + get.translation(player) + "摸一张牌") @@ -5365,11 +10803,11 @@ const skills = { discard: false, lose: false, delay: false, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { return player != target; }, onremove: true, - check: function (card) { + check(card) { if (ui.selected.cards.length && ui.selected.cards[0].name == "du") return 0; if (!ui.selected.cards.length && card.name == "du") return 20; var player = get.owner(card); @@ -5387,7 +10825,7 @@ const skills = { } return 10 - get.value(card); }, - content: function () { + content() { "step 0"; var evt = _status.event.getParent("phaseUse"); if (evt && evt.name == "phaseUse" && !evt.jsprende) { @@ -5491,14 +10929,14 @@ const skills = { }, ai: { fireAttack: true, - order: function (skill, player) { + order(skill, player) { if (player.hp < player.maxHp && player.storage.jsprende < 2 && player.countCards("h") > 1) { return 10; } return 4; }, result: { - target: function (player, target) { + target(player, target) { if (target.hasSkillTag("nogain")) return 0; if (ui.selected.cards.length && ui.selected.cards[0].name == "du") { if (target.hasSkillTag("nodu")) return 0; @@ -5514,7 +10952,7 @@ const skills = { }, }, effect: { - target: function (card, player, target) { + target_use(card, player, target) { if (player == target && get.type(card) == "equip") { if (player.countCards("e", { subtype: get.subtype(card) })) { if ( @@ -5535,10 +10973,10 @@ const skills = { nskuishe: { enable: "phaseUse", usable: 1, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { return target != player && target.countCards("he") > 0; }, - content: function () { + content() { "step 0"; player.choosePlayerCard(target, "he", true).set("ai", get.buttonValue); "step 1"; @@ -5571,13 +11009,10 @@ const skills = { } else event.finish(); "step 3"; target - .chooseToUse( - function (card, player, event) { - if (get.name(card) != "sha") return false; - return lib.filter.filterCard.apply(this, arguments); - }, - "是否对" + get.translation(player) + "使用一张杀?" - ) + .chooseToUse(function (card, player, event) { + if (get.name(card) != "sha") return false; + return lib.filter.filterCard.apply(this, arguments); + }, "是否对" + get.translation(player) + "使用一张杀?") .set("targetRequired", true) .set("complexSelect", true) .set("filterTarget", function (card, player, target) { @@ -5591,7 +11026,7 @@ const skills = { expose: 0.2, result: { target: -1.5, - player: function (player, target) { + player(player, target) { if (!target.canUse("sha", player)) return 0; if (target.countCards("h") == 1) return 0.1; if (player.hasShan()) return -0.5; @@ -5607,10 +11042,10 @@ const skills = { enable: "phaseUse", usable: 1, filterCard: { suit: "heart" }, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { return target != player && target.countCards("h") > player.countCards("h"); }, - filter: function (event, player) { + filter(event, player) { var info = lib.skill.nsyangwu; return ( player.countCards("h", info.filterCard) && @@ -5619,7 +11054,7 @@ const skills = { }) ); }, - check: function (card) { + check(card) { var num = 0; var player = _status.event.player; game.countPlayer(function (current) { @@ -5627,14 +11062,14 @@ const skills = { }); return Math.ceil((num + 1) / 2) * 2 + 4 - get.value(card); }, - content: function () { + content() { var num = Math.ceil((target.countCards("h") - player.countCards("h")) / 2); if (num) player.gainPlayerCard(target, true, "h", num, "visible"); }, ai: { order: 4, result: { - target: function (player, target) { + target(player, target) { return player.countCards("h") - target.countCards("h"); }, }, @@ -5643,12 +11078,12 @@ const skills = { nslulve: { enable: "phaseUse", usable: 1, - filter: function (event, player) { + filter(event, player) { return game.hasPlayer(function (current) { return current.countCards("e") > 0 && current.countCards("e") <= player.countCards("he"); }); }, - filterCard: function () { + filterCard() { if (ui.selected.targets.length) return false; return true; }, @@ -5656,10 +11091,10 @@ const skills = { selectCard: [1, Infinity], complexSelect: true, complexCard: true, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { return target != player && target.countCards("e") > 0 && ui.selected.cards.length == target.countCards("e"); }, - check: function (card) { + check(card) { var player = _status.event.player; if ( game.hasPlayer(function (current) { @@ -5678,14 +11113,14 @@ const skills = { return 0; } }, - content: function () { + content() { target.damage("nocard"); }, ai: { damage: true, order: 2, result: { - target: function (player, target) { + target(player, target) { return get.damageEffect(target, player); }, }, @@ -5695,7 +11130,7 @@ const skills = { nsfeixiong: { trigger: { player: "phaseUseBegin" }, direct: true, - filter: function (event, player) { + filter(event, player) { return ( player.countCards("h") > 0 && game.hasPlayer(function (current) { @@ -5703,7 +11138,7 @@ const skills = { }) ); }, - content: function () { + content() { "step 0"; player .chooseTarget(get.prompt2("nsfeixiong"), function (card, player, target) { @@ -5740,7 +11175,7 @@ const skills = { nscesuan: { trigger: { player: "damageBegin3" }, forced: true, - content: function () { + content() { "step 0"; trigger.cancel(); event.lose = player.loseMaxHp(); @@ -5750,7 +11185,7 @@ const skills = { ai: { neg: true, filterDamage: true, - skillTagFilter: function (player, tag, arg) { + skillTagFilter(player, tag, arg) { if (tag === "filterDamage" && arg && arg.player) { if (arg.player.hasSkillTag("jueqing", false, player)) return false; } @@ -5763,7 +11198,7 @@ const skills = { player: "loseAfter", global: ["cardsDiscardAfter", "loseAsyncAfter"], }, - filter: function (event, player) { + filter(event, player) { if (event.name != "cardsDiscard") { if (event.type != "discard") return false; var evt = event.getl(player); @@ -5775,7 +11210,7 @@ const skills = { } }, forced: true, - content: function () { + content() { "step 0"; var evt = trigger.getParent().relatedEvent; if ((trigger.name == "discard" && !trigger.delay) || (evt && evt.name == "respond")) game.delayx(); @@ -5842,7 +11277,7 @@ const skills = { target.damage("nocard"); } }, - onremove: function (player, skill) { + onremove(player, skill) { var cards = player.getExpansions(skill); if (cards.length) player.loseToDiscardpile(cards); }, @@ -5856,10 +11291,10 @@ const skills = { yjxuepin: { enable: "phaseUse", usable: 1, - filterTarget: function (event, player, target) { + filterTarget(event, player, target) { return player.inRange(target) && target.countDiscardableCards(player, "he") > 0; }, - content: function () { + content() { "step 0"; player.loseHp(); "step 1"; @@ -5871,13 +11306,13 @@ const skills = { ai: { order: 4, result: { - player: function (player, target) { + player(player, target) { if (player.hp == 1) return -8; if (target.countCards("e") > 1) return 0; if (player.hp > 2 || target.countCards("h") > 1) return -0.5; return -2; }, - target: function (player, target) { + target(player, target) { if (target.countDiscardableCards(player, "he") < 2) return 0; return -2; }, @@ -5886,14 +11321,14 @@ const skills = { }, nsjianglie: { trigger: { player: "useCardToPlayered" }, - filter: function (event, player) { + filter(event, player) { return event.card.name == "sha" && event.target.countCards("h") > 0; }, - check: function (event, player) { + check(event, player) { return get.attitude(player, event.target) < 0; }, logTarget: "target", - content: function () { + content() { "step 0"; trigger.target.showHandcards(); "step 1"; @@ -5922,7 +11357,7 @@ const skills = { spyinzhi: { trigger: { player: "damageEnd" }, frequent: true, - content: function () { + content() { "step 0"; event.count = trigger.num; "step 1"; @@ -5971,10 +11406,10 @@ const skills = { spmingjian: { trigger: { global: "phaseBegin" }, direct: true, - filter: function (event, player) { + filter(event, player) { return player.countCards("he") > 0; }, - content: function () { + content() { "step 0"; var next = player.chooseCard(get.prompt2("spmingjian", trigger.player), "he"); next.set("ai", function (card) { @@ -6025,11 +11460,11 @@ const skills = { silent: true, popup: false, charlotte: true, - content: function () { + content() { if (trigger.name == "phase") player.removeSkill(event.name); else trigger.noJudgeTrigger = true; }, - onremove: function (player, skill) { + onremove(player, skill) { var cards = player.getExpansions(skill); if (cards.length) player.loseToDiscardpile(cards); }, @@ -6043,37 +11478,37 @@ const skills = { spshude: { trigger: { player: "phaseJieshuBegin" }, frequent: true, - filter: function (event, player) { + filter(event, player) { return player.countCards("h") < player.maxHp; }, - content: function () { + content() { player.drawTo(player.maxHp); }, }, spfuluan: { enable: "phaseUse", usable: 1, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { return player.inRange(target); }, selectCard: 3, position: "he", - check: function (card) { + check(card) { return 5 - get.value(card); }, complexCard: true, - filterCard: function (card, player) { + filterCard(card, player) { if (!ui.selected.cards.length) return player.countCards("he", { suit: get.suit(card) }) > 2; return get.suit(card) == get.suit(ui.selected.cards[0]); }, - content: function () { + content() { target.turnOver(); player.addTempSkill("spfuluan2"); }, ai: { order: 1, result: { - target: function (player, target) { + target(player, target) { if (target.isTurnedOver()) return 2; return -1; }, @@ -6082,20 +11517,20 @@ const skills = { }, spfuluan2: { mod: { - cardEnabled: function (card) { + cardEnabled(card) { if (card.name == "sha") return false; }, }, }, spzhaoxin: { trigger: { player: "phaseDrawEnd" }, - check: function (event, player) { + check(event, player) { return player.getUseValue({ name: "sha", isCard: true }) > 0; }, - filter: function (event, player) { + filter(event, player) { return player.countCards("h") > 0; }, - content: function () { + content() { "step 0"; player.showHandcards(); "step 1"; @@ -6104,11 +11539,11 @@ const skills = { }, splanggu: { trigger: { player: "damageEnd" }, - filter: function (event, player) { + filter(event, player) { return get.itemtype(event.source) == "player"; }, logTarget: "source", - content: function () { + content() { "step 0"; player.judge(); "step 1"; @@ -6125,11 +11560,11 @@ const skills = { }, splanggu_rewrite: { trigger: { player: "judge" }, - filter: function (event, player) { + filter(event, player) { return player.countCards("hs") > 0 && event.getParent().name == "splanggu"; }, direct: true, - content: function () { + content() { "step 0"; player .chooseCard("狼顾的判定结果为" + get.translation(trigger.player.judging[0]) + ",是否打出一张手牌进行代替?", "hs", function (card) { @@ -6173,10 +11608,10 @@ const skills = { player: "loseEnd", }, frequent: true, - filter: function (event, player) { + filter(event, player) { return event.type == "discard" && event.getParent(3).name == "phaseDiscard" && event.cards.filterInD("d").length > 0; }, - content: function () { + content() { if (!player.storage.sphantong) player.storage.sphantong = []; var cards = trigger.cards.filterInD("d"); player.storage.sphantong.addArray(cards); @@ -6195,10 +11630,10 @@ const skills = { sphantong_gain: { trigger: { global: "phaseBegin" }, direct: true, - filter: function (event, player) { + filter(event, player) { return player.storage.sphantong && player.storage.sphantong.length > 0; }, - content: function () { + content() { "step 0"; player.chooseButton([get.prompt("sphantong"), player.storage.sphantong], function (button) { var player = _status.event.player; @@ -6295,7 +11730,7 @@ const skills = { }, sphuangen: { trigger: { global: "useCardToPlayered" }, - filter: function (event, player) { + filter(event, player) { if (!event.isFirstTarget) return false; if (get.type(event.card) != "trick") return false; if (get.info(event.card).multitarget) return false; @@ -6303,7 +11738,7 @@ const skills = { return player.hp > 0; }, direct: true, - content: function () { + content() { "step 0"; player .chooseTarget(get.prompt("sphuangen"), [1, Math.min(player.hp, trigger.targets.length)], function (card, player, target) { @@ -6320,15 +11755,46 @@ const skills = { player.draw(); } }, + ai: { threaten: 3.5 }, + global: "sphuangen_ai", + subSkill: { + ai: { + ai: { + effect: { + player_use(card, player) { + if ( + typeof card != "object" || + !game.hasPlayer(target => { + return target.hasSkill("sphuangen") && (get.attitude(player, target) < 0 || get.attitude(target, player) < 0); + }) || + game.countPlayer(target => { + return player.canUse(card, target); + }) < 2 + ) + return; + if (get.info(card)?.type != "trick") return; + const select = get.info(card).selectTarget; + let range; + if (select == undefined) range = [1, 1]; + else if (typeof select == "number") range = [select, select]; + else if (get.itemtype(select) == "select") range = select; + else if (typeof select == "function") range = select(card, player); + game.checkMod(card, player, range, "selectTarget", player); + if (range[1] == -1 || (range[1] > 1 && ui.selected.targets && ui.selected.targets.length)) return "zeroplayertarget"; + }, + }, + }, + }, + }, }, spyicong: { trigger: { player: "phaseDiscardEnd" }, direct: true, locked: false, - filter: function (event, player) { + filter(event, player) { return player.countCards("he") > 0; }, - content: function () { + content() { "step 0"; player.chooseCard("he", [1, player.countCards("he")], get.prompt2("spyicong")).set("ai", function (card) { if (card.name == "du") return 10; @@ -6342,18 +11808,18 @@ const skills = { } }, mod: { - globalTo: function (from, to, num) { + globalTo(from, to, num) { return num + to.getExpansions("spyicong").length; }, }, marktext: "扈", - onremove: function (player, skill) { + onremove(player, skill) { var cards = player.getExpansions(skill); if (cards.length) player.loseToDiscardpile(cards); }, intro: { name: "义从", - content: function (storage, player) { + content(storage, player) { return "共有" + get.cnNumber(player.getExpansions("spyicong").length) + "张“扈”"; }, markcount: "expansion", @@ -6363,10 +11829,10 @@ const skills = { trigger: { player: "phaseZhunbeiBegin" }, forced: true, locked: false, - filter: function (event, player) { + filter(event, player) { return player.getExpansions("spyicong").length > 0; }, - content: function () { + content() { var cards = player.getExpansions("spyicong"); var num = cards.length; player.addMark("sptuji2", num, false); @@ -6382,7 +11848,7 @@ const skills = { onremove: true, charlotte: true, mod: { - globalFrom: function (from, to, num) { + globalFrom(from, to, num) { return num - from.countMark("sptuji2"); }, }, @@ -6397,10 +11863,10 @@ const skills = { global: "phaseUseBegin", }, direct: true, - filter: function (event, player) { + filter(event, player) { return player.countCards("he") > 0; }, - content: function () { + content() { "step 0"; var next = player.chooseToDiscard(get.prompt("xinfu_yanyu"), get.translation("xinfu_yanyu_info"), "he").set("logSkill", "xinfu_yanyu"); if (player == trigger.player) { @@ -6473,10 +11939,10 @@ const skills = { }, }, xinfu_yanyu2: { - init: function (player, skill) { + init(player, skill) { player.storage[skill] = 0; }, - onremove: function (player, skill) { + onremove(player, skill) { delete player.storage.xinfu_yanyu; delete player.storage.xinfu_yanyu2; }, @@ -6484,7 +11950,7 @@ const skills = { global: ["loseAfter", "cardsDiscardAfter", "loseAsyncAfter", "equipAfter"], }, direct: true, - filter: function (event, player) { + filter(event, player) { if (player.storage.xinfu_yanyu2 >= 3) return false; var type = player.storage.xinfu_yanyu, cards = event.getd(); @@ -6493,7 +11959,7 @@ const skills = { } return false; }, - content: function () { + content() { "step 0"; event.logged = false; event.cards = []; @@ -6549,7 +12015,7 @@ const skills = { }, forced: true, popup: false, - content: function () { + content() { player.removeAdditionalSkill("xinfu_xiaode"); player.removeSkill("xinfu_xiaode_remove"); }, @@ -6559,10 +12025,10 @@ const skills = { global: "dieAfter", }, direct: true, - filter: function (skill, event) { + filter(skill, event) { return !event.hasSkill("xinfu_xiaode_remove"); }, - content: function () { + content() { "step 0"; var list = []; var listm = []; @@ -6601,7 +12067,7 @@ const skills = { chixin: { group: ["chixin1", "chixin2"], mod: { - cardUsableTarget: function (card, player, target) { + cardUsableTarget(card, player, target) { if (card.name == "sha" && !target.hasSkill("chixin3") && player.inRange(target)) return true; }, }, @@ -6609,7 +12075,7 @@ const skills = { silent: true, firstDo: true, locked: false, - content: function () { + content() { trigger.target.addTempSkill("chixin3"); }, }, @@ -6619,7 +12085,7 @@ const skills = { position: "hes", viewAs: { name: "sha" }, prompt: "将一张♦牌当杀使用或打出", - check: function (card) { + check(card) { return 5 - get.value(card); }, ai: { @@ -6632,13 +12098,13 @@ const skills = { viewAs: { name: "shan" }, position: "hes", prompt: "将一张♦牌当闪使用或打出", - check: function (card) { + check(card) { return 5 - get.value(card); }, ai: { respondShan: true, effect: { - target: function (card, player, target, current) { + target(card, player, target, current) { if (get.tag(card, "respondShan") && current < 0) return 0.8; }, }, @@ -6649,7 +12115,7 @@ const skills = { trigger: { player: "phaseZhunbeiBegin" }, skillAnimation: true, animationColor: "gray", - filter: function (event, player) { + filter(event, player) { return !player.storage.suiren; }, intro: { @@ -6659,7 +12125,7 @@ const skills = { direct: true, unique: true, limited: true, - content: function () { + content() { "step 0"; var check = player.hp == 1 || (player.hp == 2 && player.countCards("h") <= 1); player @@ -6688,7 +12154,7 @@ const skills = { player: "gainAfter", global: "loseAsyncAfter", }, - filter: function (event, player) { + filter(event, player) { var hs = player.getCards("h"); return ( event.type != "xinmanjuan" && @@ -6697,7 +12163,7 @@ const skills = { }).length > 0 ); }, - content: function () { + content() { "step 0"; var hs = player.getCards("h"), cards = trigger.getg(player).filter(function (card) { @@ -6730,7 +12196,7 @@ const skills = { ai: { threaten: 4.2, nogain: 1, - skillTagFilter: function (player) { + skillTagFilter(player) { return player != _status.currentPhase; }, }, @@ -6738,7 +12204,7 @@ const skills = { manjuan: { audio: true, trigger: { global: "loseAfter" }, - filter: function (event, player) { + filter(event, player) { if (event.type != "discard") return false; if (event.player == player) return false; if (!player.countCards("he")) return false; @@ -6752,7 +12218,7 @@ const skills = { direct: true, unique: true, gainable: true, - content: function () { + content() { "step 0"; if (trigger.delay == false) game.delay(); "step 1"; @@ -6798,7 +12264,7 @@ const skills = { unique: true, limited: true, trigger: { player: "phaseZhunbeiBegin" }, - content: function () { + content() { "step 0"; player.awakenSkill("zuixiang"); event.cards = player.showCards(get.cards(3)).cards; @@ -6811,7 +12277,7 @@ const skills = { player.addSkill("zuixiang2"); } }, - filterSame: function (c) { + filterSame(c) { for (var i = 0; i < c.length; i++) { for (var j = i + 1; j < c.length; j++) { if (get.number(c[i]) == get.number(c[j])) return true; @@ -6826,17 +12292,17 @@ const skills = { markcount: "expansion", }, mod: { - cardEnabled: function (card, player) { + cardEnabled(card, player) { var type = get.type2(card); var list = player.getExpansions("zuixiang2"); for (var i of list) { if (get.type2(i, false) == type) return false; } }, - cardRespondable: function () { + cardRespondable() { return lib.skill.zuixiang2.mod.cardEnabled.apply(this, arguments); }, - cardSavable: function () { + cardSavable() { return lib.skill.zuixiang2.mod.cardEnabled.apply(this, arguments); }, }, @@ -6846,7 +12312,7 @@ const skills = { }, forced: true, charlotte: true, - filter: function (event, player) { + filter(event, player) { if (event.name == "phaseZhunbei") return !event._zuixiang; var type = get.type2(event.card); var list = player.getExpansions("zuixiang2"); @@ -6855,7 +12321,7 @@ const skills = { } return false; }, - content: function () { + content() { "step 0"; if (event.triggername == "useCardToBefore") { trigger.cancel(); @@ -6874,7 +12340,7 @@ const skills = { }, ai: { effect: { - target_use(card, player, target) { + target(card, player, target) { var type = get.type2(card); var list = target.getExpansions("zuixiang2"); for (var i of list) { @@ -6888,21 +12354,21 @@ const skills = { audio: 2, enable: "phaseUse", filterCard: { suit: "diamond" }, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { return target.canAddJudge({ name: "yanxiao_card" }); }, - check: function (card) { + check(card) { return 7 - get.value(card); }, position: "he", - filter: function (event, player) { + filter(event, player) { return player.countCards("he", { suit: "diamond" }) > 0; }, discard: false, lose: false, delay: false, prepare: "give", - content: function () { + content() { "step 0"; game.addGlobalSkill("yanxiao_global"); target.addJudge({ name: "yanxiao_card" }, cards); @@ -6912,7 +12378,7 @@ const skills = { ai: { order: 8, result: { - target: function (player, target) { + target(player, target) { if ( target.countCards("j", function (card) { return ( @@ -6937,16 +12403,16 @@ const skills = { yanxiao_global: { trigger: { player: "phaseJudgeBegin" }, forced: true, - filter: function (event, player) { + filter(event, player) { return player.countCards("j") > 0 && player.hasJudge("yanxiao_card"); }, - content: function () { + content() { player.gain(player.getCards("j"), "gain2"); }, ai: { effect: { - target: function (card, player, target) { - if (get.type(card) == "delay" && target.hasJudge("yanxiao_card")) return [0, 0, 0, 0.1]; + target_use(card, player, target) { + if (get.type(card) == "delay" && target.hasJudge("yanxiao_card")) return [0, 0.1]; }, }, }, @@ -6958,14 +12424,14 @@ const skills = { source: { audio: "anxian", trigger: { source: "damageBegin2" }, - filter: function (event, player) { + filter(event, player) { return event.card && event.card.name == "sha"; }, - check: function (event, player) { + check(event, player) { if (get.damageEffect(event.player, player, player) <= 0) return true; return false; }, - content: function () { + content() { "step 0"; if (trigger.player.countCards("h")) { trigger.player.chooseToDiscard(true); @@ -6979,10 +12445,10 @@ const skills = { audio: "anxian", trigger: { target: "useCardToTargeted" }, direct: true, - filter: function (event, player) { + filter(event, player) { return event.card.name == "sha" && player.countCards("h"); }, - content: function () { + content() { "step 0"; var next = player.chooseToDiscard(get.prompt2("anxian")); next.set("ai", function (card) { @@ -7007,10 +12473,10 @@ const skills = { junwei: { trigger: { player: "phaseJieshuBegin" }, direct: true, - filter: function (event, player) { + filter(event, player) { return player.getExpansions("yinling").length >= 3; }, - content: function () { + content() { "step 0"; var cards = player.getExpansions("yinling"); if (cards.length > 3) { @@ -7114,14 +12580,14 @@ const skills = { content: "expansion", markcount: "expansion", }, - onremove: function (player, skill) { + onremove(player, skill) { var cards = player.getExpansions(skill); if (cards.length) player.loseToDiscardpile(cards); }, trigger: { player: "phaseJieshuBegin" }, forced: true, charlotte: true, - content: function () { + content() { "step 0"; var cards = player.getExpansions("junwei2").filter(function (card) { return player.canEquip(card, true); @@ -7145,20 +12611,20 @@ const skills = { content: "expansion", markcount: "expansion", }, - onremove: function (player, skill) { + onremove(player, skill) { var cards = player.getExpansions(skill); if (cards.length) player.loseToDiscardpile(cards); }, - filter: function (event, player) { + filter(event, player) { return player.countCards("he", { color: "black" }) > 0 && player.getExpansions("yinling").length < 4; }, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { return target.countCards("he") > 0 && target != player; }, - check: function (card) { + check(card) { return 6 - get.value(card); }, - content: function () { + content() { "step 0"; player.choosePlayerCard("hej", target, true); "step 1"; @@ -7170,7 +12636,7 @@ const skills = { order: 10.1, expose: 0.1, result: { - target: function (player, target) { + target(player, target) { if (target.hasSkill("tuntian")) return 0; var es = target.getCards("e"); var nh = target.countCards("h"); @@ -7197,7 +12663,7 @@ const skills = { fenyong: { audio: 2, trigger: { player: "damageEnd" }, - content: function () { + content() { player.addTempSkill("fenyong2"); }, }, @@ -7209,7 +12675,7 @@ const skills = { }, trigger: { player: "damageBegin3" }, forced: true, - content: function () { + content() { trigger.cancel(); }, ai: { @@ -7219,8 +12685,8 @@ const skills = { nothunder: true, nodamage: true, effect: { - target: function (card, player, target, current) { - if (get.tag(card, "damage")) return [0, 0]; + target(card, player, target, current) { + if (get.tag(card, "damage")) return "zeroplayertarget"; }, }, }, @@ -7230,10 +12696,10 @@ const skills = { trigger: { global: "phaseJieshuBegin" }, forced: true, locked: false, - filter: function (event, player) { + filter(event, player) { return player.hasSkill("fenyong2") && event.player.isIn(); }, - content: function () { + content() { "step 0"; player.removeSkill("fenyong2"); player @@ -7273,7 +12739,7 @@ const skills = { }, mouduan: { audio: 1, - init2: function (player) { + init2(player) { game.broadcastAll(function (player) { player._mouduan_mark = player.mark("武", { content: "拥有技能【激昂】、【谦逊】", @@ -7281,7 +12747,7 @@ const skills = { }, player); player.addAdditionalSkill("mouduan", ["jiang", "qianxun"]); }, - onremove: function (player) { + onremove(player) { game.broadcastAll(function (player) { if (player._mouduan_mark) { player._mouduan_mark.delete(); @@ -7293,10 +12759,10 @@ const skills = { trigger: { player: "loseEnd" }, forced: true, locked: false, - filter: function (event, player) { + filter(event, player) { return player._mouduan_mark && player._mouduan_mark.name == "武" && player.countCards("h") <= 2; }, - content: function () { + content() { game.broadcastAll(function (player) { if (!player._mouduan_mark) return; player._mouduan_mark.name = "文"; @@ -7312,11 +12778,11 @@ const skills = { audio: 1, trigger: { global: "phaseZhunbeiBegin" }, //priority:5, - filter: function (event, player) { + filter(event, player) { return player._mouduan_mark && player._mouduan_mark.name == "文" && player.countCards("h") > 2; }, direct: true, - content: function () { + content() { "step 0"; player.chooseToDiscard("he", "谋断:是否弃置一张牌将标记变为“武”?").ai = function () { return -1; @@ -7338,13 +12804,13 @@ const skills = { audio: 1, enable: "phaseUse", usable: 1, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { return player.canCompare(target); }, - filter: function (event, player) { + filter(event, player) { return player.countCards("h") > 0; }, - content: function () { + content() { "step 0"; player.chooseToCompare(target); "step 1"; @@ -7354,7 +12820,7 @@ const skills = { }, ai: { result: { - target: function (player, target) { + target(player, target) { var hs = player.getCards("h"); if (hs.length < 3) return 0; var bool = false; @@ -7380,10 +12846,10 @@ const skills = { }, tanhu3: { mod: { - globalFrom: function (from, to) { + globalFrom(from, to) { if (to.hasSkill("tanhu2")) return -Infinity; }, - wuxieRespondable: function (card, player, target) { + wuxieRespondable(card, player, target) { if (target && target.hasSkill("tanhu2")) return false; }, }, @@ -7391,11 +12857,11 @@ const skills = { jie: { audio: 1, trigger: { source: "damageBegin1" }, - filter: function (event) { + filter(event) { return event.card && event.card.name == "sha" && get.color(event.card) == "red" && event.notLink(); }, forced: true, - content: function () { + content() { trigger.num++; }, }, @@ -7403,13 +12869,13 @@ const skills = { audio: true, enable: "phaseUse", usable: 1, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { return player.canCompare(target); }, - filter: function (event, player) { + filter(event, player) { return player.countCards("h") > 0; }, - content: function () { + content() { "step 0"; player.chooseToCompare(target).set("preserve", "win"); "step 1"; @@ -7444,7 +12910,7 @@ const skills = { }, ai: { result: { - target: function (player, target) { + target(player, target) { var hs = player.getCards("h"); if (hs.length < 3) return 0; var bool = false; @@ -7470,13 +12936,13 @@ const skills = { content: "非红桃闪无效", }, mod: { - cardRespondable: function (card, player) { + cardRespondable(card, player) { if (card.name == "shan") { const suit = get.suit(card); if (suit != "heart" && suit != "unsure") return false; } }, - cardEnabled: function (card, player) { + cardEnabled(card, player) { if (card.name == "shan") { const suit = get.suit(card); if (suit != "heart" && suit != "unsure") return false; @@ -7494,33 +12960,33 @@ const skills = { trigger: { player: "phaseZhunbeiBegin" }, zhuSkill: true, direct: true, - filter: function (event, player) { + filter(event, player) { if (!player.hasZhuSkill("shichou")) return false; if (player.countCards("he") < 2) return false; return game.hasPlayer(function (current) { return current != player && current.group == "shu"; }); }, - init: function (player) { + init(player) { if (player.hasZhuSkill("shichou")) { player.markSkill("shichou"); player.storage.shichou = false; } }, - content: function () { + content() { "step 0"; player.chooseCardTarget({ prompt: get.prompt2("shichou"), selectCard: 2, - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { return target.group == "shu" && target != player; }, filterCard: true, position: "he", - ai1: function (card) { + ai1(card) { return 7 - get.value(card); }, - ai2: function (target) { + ai2(target) { var player = _status.event.player; if (player.hasUnknown()) return 0; var att = get.attitude(player, target); @@ -7554,7 +13020,7 @@ const skills = { trigger: { player: "damageBegin3" }, forced: true, popup: false, - content: function () { + content() { trigger.player = player.storage.shichou_target; trigger.shichou4 = true; trigger.player.addSkill("shichou4"); @@ -7563,7 +13029,7 @@ const skills = { }, ai: { effect: { - target: function (card, player, target, current) { + target(card, player, target, current) { if (get.tag(card, "damage")) { if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; if (get.attitude(player, target) > 0) return [0, 0]; @@ -7585,10 +13051,10 @@ const skills = { forced: true, popup: false, //priority:10, - filter: function (event, player) { + filter(event, player) { return event.player == player.storage.shichou_target; }, - content: function () { + content() { trigger.player.unmarkSkill("shichou"); delete player.storage.shichou_target; player.removeSkill("shichou2"); @@ -7599,7 +13065,7 @@ const skills = { forced: true, popup: false, audio: false, - content: function () { + content() { if (!trigger.shichou4) return; if (event.triggername == "damageAfter" && trigger.num) { player.draw(trigger.num); @@ -7610,10 +13076,10 @@ const skills = { zhaolie: { trigger: { player: "phaseDrawBegin2" }, direct: true, - filter: function (event, player) { + filter(event, player) { return !event.numFixed; }, - content: function () { + content() { "step 0"; player .chooseTarget(get.prompt2("zhaolie"), function (card, player, target) { @@ -7637,7 +13103,7 @@ const skills = { trigger: { player: "phaseDrawEnd" }, forced: true, popup: false, - content: function () { + content() { "step 0"; event.cards = get.cards(3); player.showCards(event.cards); @@ -7729,11 +13195,11 @@ const skills = { }, fulu: { trigger: { player: "useCard1" }, - filter: function (event, player) { + filter(event, player) { if (event.card.name == "sha" && !game.hasNature(event.card)) return true; }, audio: true, - check: function (event, player) { + check(event, player) { var eff = 0; for (var i = 0; i < event.targets.length; i++) { var target = event.targets[i]; @@ -7744,7 +13210,7 @@ const skills = { } return eff >= 0; }, - content: function () { + content() { game.setNature(trigger.card, "thunder"); if (get.itemtype(trigger.card) == "card") { var next = game.createEvent("fulu_clear"); @@ -7759,20 +13225,20 @@ const skills = { }, fuji: { trigger: { global: "damageBegin1" }, - filter: function (event) { + filter(event) { return event.source && event.source.isIn() && event.hasNature("thunder"); }, - check: function (event, player) { + check(event, player) { return get.attitude(player, event.source) > 0 && get.attitude(player, event.player) < 0; }, - prompt: function (event) { + prompt(event) { return get.translation(event.source) + "即将对" + get.translation(event.player) + "造成伤害," + get.prompt("fuji"); }, logTarget: "source", - content: function () { + content() { trigger.source.judge().callback = lib.skill.fuji.callback; }, - callback: function () { + callback() { var evt = event.getParent(2); if (event.judgeResult.color == "black") { //game.cardsDiscard(card); @@ -7782,6 +13248,359 @@ const skills = { } }, }, -}; + //田钏 + pshuying: { + trigger: { + global: ["phaseBefore", "dieAfter"], + player: "enterGame", + }, + forced: true, + filter(event, player) { + if (event.name == "die") return event.player != player; + return event.name != "phase" || game.phaseNumber == 0; + }, + async content(event, trigger, player) { + let cards = [], num = trigger.name == "die" ? 1 : 2; + while (cards.length < num) { + const card = game.createCard2("xingbian", "spade", 9); + cards.push(card); + } + if (cards.length) await player.gain(cards, "gain2"); + }, + mod: { + ignoredHandcard(card, player) { + if (card.name == "xingbian") { + return true; + } + }, + cardDiscardable(card, player, name) { + if (name == "phaseDiscard" && card.name == "xingbian") { + return false; + } + }, + globalTo(from, to, num) { + let count = 0; + game.filterPlayer(current => { + count += current.countCards("ej", card => card.name == "xingbian"); + }); + return num + count; + }, + }, + }, + psqianjing: { + trigger: { + player: "damageEnd", + source: "damageSource", + }, + filter(event, player) { + if (!player.countCards("h", card => card.name == "xingbian")) return false; + return game.hasPlayer(current => current.hasEnabledSlot()); + }, + async cost(event, trigger, player) { + event.result = await player.chooseCardTarget({ + filterCard(card) { + return card.name == "xingbian"; + }, + position: "h", + prompt: get.prompt("psqianjing"), + prompt2: "将手牌中的一张【刑鞭】置入一名角色装备区", + filterTarget(card, player, target) { + return target.hasEnabledSlot(); + }, + ai1(card) { + return 10 - get.value(card); + }, + ai2(target) { + const player = get.player(); + if (target == player) return 1; + if (get.attitude(player, target) < 0) return 3; + return 0; + }, + }).forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0], cardx = event.cards[0]; + const choices = []; + for (let i = 0; i <= 5; i++) { + if (target.hasEquipableSlot(i)) choices.push(`equip${i}`); + } + if (!choices.length) return; + const result = await player.chooseControl(choices) + .set("prompt", `请选择为${get.translation(target)}置入【刑鞭】的装备栏`) + .set("ai", () => _status.event.controls.randomGet()) + .forResult(); + const card = get.autoViewAs(cardx); + card.subtypes = [result.control]; + player.$give(card, target); + await target.equip(card); + if (target == player) await player.draw(); + }, + group: "psqianjing_use", + subSkill: { + use: { + enable: "chooseToUse", + filter(event, player) { + if (!event.filterCard(get.autoViewAs({ name: "sha" }, "unsure"), player, event)) return false; + if (player.countCards("h", card => card.name == "xingbian")) return true; + return game.hasPlayer(current => { + return current.countCards("ej", card => card.name == "xingbian"); + }); + }, + delay: false, + locked: false, + prompt: "将场上或你手牌中的一张【刑鞭】当作【杀】使用", + filterTarget(card, player, target) { + let event = _status.event, + evt = event; + if (event._backup) evt = event._backup; + const pos = target == player ? "hej" : "ej"; + return target.countCards(pos, card => { + if (card.name != "xingbian") return false; + let sha = get.autoViewAs({ name: "sha", storage: { qianjing: true } }, [card]); + if (evt.filterCard(sha, player, event)) { + return game.hasPlayer(function (current) { + return evt.filterTarget(sha, player, current); + }); + } + }); + }, + async content(event, trigger, player) { + var evt = event.getParent(2), target = event.targets[0]; + evt.set("xingbian", true); + const result = await player.choosePlayerCard(true, target, target == player ? "hej" : "ej").set("filterButton", function (button) { + var card = button.link; + return card.name == "xingbian"; + }).forResult(); + game.broadcastAll( + function (result, name) { + lib.skill.psqianjing_backup.viewAs = { + name: name, + cards: [result], + storage: { qianjing: true }, + }; + lib.skill.psqianjing_backup.prompt = "选择" + get.translation(name) + "(" + get.translation(result) + ")的目标"; + }, + result.links[0], + "sha" + ); + evt.set("_backupevent", "psqianjing_backup"); + evt.backup("psqianjing_backup"); + evt.set("openskilldialog", "选择杀(" + get.translation(result.links[0]) + ")的目标"); + evt.set("norestore", true); + evt.set("custom", { + add: {}, + replace: { window() { } }, + }); + evt.goto(0); + }, + ai: { + respondSha: true, + skillTagFilter(player, tag) { + var func = (card) => card.name == "xingbian"; + return game.hasPlayer(function (current) { + return current.countCards(current == player ? "hej" : "ej", func); + }); + }, + order: 1, + result: { + player(player, target) { + if (_status.event.type != "phase") return 1; + if (!player.hasValueTarget({ name: "sha" })) return 0; + return 0.1; + }, + }, + }, + }, + backup: { + precontent() { + "step 0"; + delete event.result.skill; + var cards = event.result.card.cards; + event.result.cards = cards; + var owner = get.owner(cards[0]); + event.target = owner; + owner.$give(cards[0], player, false); + player.popup(event.result.card.name, "metal"); + game.delayx(); + event.getParent().addCount = false; + }, + filterCard() { + return false; + }, + prompt: "请选择【杀】的目标", + selectCard: -1, + }, + }, + }, + psbianchi: { + trigger: { + player: "phaseJieshuEnd", + }, + limited: true, + skillAnimation: true, + animationColor: "metal", + logTarget(event, player) { + return game.filterPlayer(current => { + return current.countCards("ej", card => card.name == "xingbian"); + }); + }, + filter(event, player) { + const targets = lib.skill.psbianchi.logTarget(event, player); + return targets && targets.length; + }, + check(event, player) { + const targets = lib.skill.psbianchi.logTarget(event, player); + let eff = 0; + for (const target of targets) eff += get.sgnAttitude(player, target); + return eff < 0; + }, + async content(event, trigger, player) { + player.awakenSkill(event.name); + const lose_list = []; + for (const target of event.targets) { + lose_list.push([target, target.getCards("ej", card => card.name == "xingbian")]); + } + await game.loseAsync({ + lose_list: lose_list, + discarder: player, + }).setContent("discardMultiple"); + for (const target of event.targets) { + const result = await target.chooseControl() + .set("choiceList", [ + "令" + get.translation(player) + "操控你执行一个仅能使用两张牌的出牌阶段", + "失去2点体力", + ]) + .set("choice", function () { + if (get.attitude(target, player) > 0) return "选项一"; + if (get.effect(target, { name: "losehp" }, target, target) > 0 && target.hp > 2) return "选项二"; + return "选项一"; + }()) + .set("ai", () => { + return _status.event.choice; + }) + .forResult(); + if (result.control == '选项一') { + target.addTempSkill("psbianchi_control", { player: "phaseUseEnd" }); + const next = target.phaseUse(); + next.owner = ["psbianchi", player]; + await next; + } + else await target.loseHp(2); + } + }, + subSkill: { + control: { + forced: true, + charlotte: true, + direct: true, + trigger: { + player: "phaseUseBefore", + }, + filter(event, player) { + return !player._trueMe && event?.owner?.[1].isIn() && player != event.owner[1]; + }, + content() { + const owner = trigger.owner[1]; + player._trueMe = owner; + game.addGlobalSkill("autoswap"); + if (player == game.me) { + game.notMe = true; + if (!_status.auto) ui.click.auto(); + } + }, + mod: { + cardEnabled(card, player) { + let history = player.getHistory("useCard", evt => { + let phaseUse = evt.getParent("phaseUse", true); + return phaseUse?.player == player && phaseUse.owner?.[0] == "psbianchi"; + }); + if (history?.length >= 2) return false; + }, + cardUsable(card, player) { + return lib.skill.psbianchi_control.mod.cardEnabled.apply(this, arguments); + }, + cardSavable(card, player) { + return lib.skill.psbianchi_control.mod.cardEnabled.apply(this, arguments); + }, + }, + onremove(player) { + if (player._trueMe) { + if (player == game.me) { + if (!game.notMe) game.swapPlayerAuto(player._trueMe); + else delete game.notMe; + if (_status.auto) ui.click.auto(); + } + delete player._trueMe; + } + }, + }, + }, + }, + xingbian_skill: { + equipSkill: true, + mod: { + attackRange: function (player, distance) { + return ( + distance + player.countCards("e", card => card.name == "xingbian") + ); + }, + }, + trigger: { + player: "phaseUseBegin", + }, + forced: true, + intro: { + content(storage, player) { + let str = ""; + for (const arg of storage) { + str += `${get.translation(arg[0])}命你攻击${get.translation(arg[1])}
    `; + } + return str.slice(0, -4); + }, + }, + logTarget(event, player) { + return game.filterPlayer(current => get.nameList(current).includes("yj_tianchuan")); + }, + filter(event, player) { + const targets = lib.skill.xingbian_skill.logTarget(event, player); + return targets && targets.length; + }, + async content(event, trigger, player) { + for (const target of event.targets) { + const result = await target.chooseTarget(`刑鞭:为${get.translation(player)}指定塔塔开目标`, true, function (card, player, targetx) { + return targetx != _status.event.owner; + }) + .set("owner", player) + .set("ai", target => { + return get.distance(_status.event.owner, target) + 1; + }).forResult(); + if (result.bool) { + if (!player.getStorage("xingbian_skill").length) { + player.when("phaseJieshuBegin").then(() => { + const args = player.storage.xingbian_skill.shift(); + let damage = true; + if (player.getHistory("useCard", evt => evt.card.name == "sha" && evt.targets?.includes(args[1])).length) damage = false; + if (player.getHistory("sourceDamage", evt => evt.player == args[1]).length) damage = false; + if (damage === true) { + args[0].chat("该罚!"); + args[0].line(player, "green"); + player.damage(player); + } + if (player.storage.xingbian_skill.length) event.redo(); + else { + player.unmarkSkill("xingbian_skill"); + delete player.storage.xingbian_skill; + } + }); + player.storage.xingbian_skill = []; + } + target.line(result.targets[0], "green"); + player.storage.xingbian_skill.push([target, result.targets[0]]); + player.markSkill("xingbian_skill"); + } + } + }, + }, +} export default skills; diff --git a/character/offline/sort.js b/character/offline/sort.js index 91faa843d2..091b667870 100644 --- a/character/offline/sort.js +++ b/character/offline/sort.js @@ -5,11 +5,14 @@ const characterSort = { offline_luanwu: ["ns_lijue", "ns_zhangji", "ns_fanchou"], offline_yongjian: ["ns_chendao", "yj_caoang", "yj_caocao", "yj_liru", "yj_caohong", "yj_zhangfei", "yongjian_ganning", "yj_dongzhuo", "yj_xuyou", "yj_jiaxu", "yj_zhenji"], offline_piracyE_zy: ["shen_jiaxu", "pe_wangyun", "pe_zhonghui", "pe_sunchen", "pe_mengda", "pe_wenqin", "ns_caoanmin", "jiangqing", "kongrong", "jiling", "tianfeng", "mateng"], - offline_piracyE: ["yj_zhouji", "yj_ehuan", "yj_zhonghui"], + offline_piracyE: ["yj_zhouji", "yj_ehuan", "yj_tianchuan"], offline_piracyS: ["ns_jiaxu", "longyufei", "ps_guanyu", "ps1059_guojia", "ps2070_guojia", "ps2063_zhaoyun", "ps2067_zhaoyun", "ps1062_zhouyu", "ps2080_zhouyu", "ps_caozhi", "ps_jin_simayi", "ps_caopi", "ps_simayi", "ps2068_simayi", "ps_machao", "ps_zhugeliang", "ps2066_zhugeliang", "ps_jiaxu", "ps_lvbu", "ps_shen_machao", "jsp_liubei"], offline_piracyK: ["pk_sp_duyu"], offline_vtuber: ["vtb_xiaosha", "vtb_xiaoshan", "vtb_xiaotao", "vtb_xiaole", "vtb_xiaojiu"], offline_longyutao: ["drag_guanyu", "drag_caoren", "drag_lvchang"], + offline_jingxiang: ["jx_shen_caoren", "jx_shen_liubiao", "jx_sunjian", "jx_zhouyu", "jx_guanyu"], + offline_taoyuan: ["ty_guanyu", "ty_sunquan", "ty_liubei", "ty_chenshi", "ty_chengjix", "ty_zhaorong", "ty_zhangnan", "ty_fengxí", "ty_liaohua", "ty_huangzhong", "ty_wuban", "ty_shicong", "ty_guanxing", "ty_shamoke", "ty_guanyinping", "ty_shen_liubei", "ty_luxun", "ty_ganning", "ty_buzhi", "ty_tanxiong", "ty_liue", "ty_zhangda", "ty_fanjiang", "ty_shen_zhangfei", "ty_shen_guanyu", "ty_anying", "ty_anyingx", "ty_wuque", "ty_yanque", "ty_wangque"], + offline_jiudin: ["jd_jin_wangyuanji", "jd_ol_huaxin", "jd_sp_yangwan", "jd_sb_huangyueying", "jd_sb_zhaoyun", "jd_sb_ganning", "jd_sb_pangtong", "jd_hanlong", "jd_jin_xiahouhui", "jd_jin_simazhao", "jd_sb_caocao", "jd_sb_sp_zhugeliang", "jd_simayan", "yj_zhonghui", "jd_sb_sunquan", "jd_sb_xiaoqiao", "jd_sb_guanyu", "jd_sb_jiangwei", "jd_sb_daqiao", "jd_sb_menghuo", "jd_sb_yuanshao", "jd_sb_yujin", "jd_sb_sunshangxiang", "jd_sb_liubei", "jd_sb_fazheng", "jd_sb_zhangfei", "jd_jin_simashi", "jd_sb_xuhuang"], //offline_others:[""], }; @@ -28,6 +31,9 @@ const characterSortTranslate = { offline_piracyK: "官盗K系列", offline_others: "线下其他系列", offline_longyutao: "龙起襄樊", + offline_jingxiang: "荆襄风云", + offline_taoyuan: "桃园挽歌", + offline_jiudin: "九鼎系列", }; export { characterSort, characterSortTranslate }; diff --git a/character/offline/translate.js b/character/offline/translate.js index 70291de424..3f0072415d 100644 --- a/character/offline/translate.js +++ b/character/offline/translate.js @@ -1,4 +1,15 @@ const translates = { + yj_tianchuan: "田钏", + pshuying: "狐影", + pshuying_info: "锁定技,游戏开始时/其他角色死亡后,你从游戏外获得两/一张【刑鞭】;【刑鞭】不计入你的手牌上限,其他角色计算与你的距离+X(X为场上的【刑鞭】数)。", + psqianjing: "潜荆", + psqianjing_info: "当你造成或受到伤害后,你可以将手牌中的一张【刑鞭】置入一名角色的任意装备栏,若为你则摸一张牌。你可以将场上或你手牌中的一张【刑鞭】当作不计入次数限制的【杀】使用。", + psbianchi: "鞭笞", + psbianchi_info: "限定技,结束阶段,你可以弃置场上所有【刑鞭】,并令以此法失去牌的所有其他角色依次选择一项:1.令你操控其执行一个额外出牌阶段,此阶段至多使用两张牌;2.失去2点体力。", + xingbian: "刑鞭", + xingbian_info: "锁定技,你装备区每有一张【刑鞭】,你的攻击范围便+1;此牌可置入任意装备栏;你的出牌阶段开始时,若场上存在“田钏”,其为你指定一名其他角色,结束阶段若你本回合未对其使用【杀】或造成伤害,你对自己造成1点伤害。", + xingbian_skill: "刑鞭", + xingbian_skill_info: "锁定技,你的出牌阶段开始时,若场上存在“田钏”,其为你指定一名其他角色,结束阶段若你本回合未对其使用【杀】或造成伤害,你对自己造成1点伤害。", sp_gongsunzan: "SP公孙瓒", sp_gongsunzan_prefix: "SP", sp_simazhao: "SP司马昭", @@ -444,6 +455,343 @@ const translates = { psdaohe_info: "出牌阶段限一次,你可以令一名其他角色交给你至少一张手牌,然后你令其回复1点体力。", pszhiyi: "志异", pszhiyi_info: "出牌阶段限一次,你可以令一名角色摸一张牌并对其造成1点伤害。", + jx_shen_caoren: "荆神曹仁", + jx_shen_caoren_prefix: "荆神", + jx_shen_liubiao: "荆神刘表", + jx_shen_liubiao_prefix: "荆神", + jingxiangshengshi: "荆襄盛世", + jingxiangshengshi_info: "出牌阶段,对X名其他角色使用,亮出牌堆顶存活角色数张牌,令这些角色依次获得其中一张,然后你获得剩余的牌(X为全场势力数)。", + jxjushou: "据守", + jxjushou_info: "结束阶段,你可以翻面并摸X张牌(X为场上存活人数),然后你可令全场角色翻面并各摸三张牌,若如此做你弃置场上所有装备牌,失去〖据守〗并获得〖突围〗。", + jxtuwei: "突围", + jxtuwei_info: "出牌阶段,你可将弃牌堆的一张装备牌置入一名角色对应的装备栏内,然后若其不为你,你可以令其摸一张牌或对其造成1点伤害。(每名角色限一次)", + jxxiongju: "雄踞", + jxxiongju_info: "锁定技,游戏开始时,你从游戏外获得两张【荆襄盛世】并摸X张牌,然后增加X点体力上限并恢复等量体力;你的手牌上限+X(X为场上势力数)。", + jxfujing: "富荆", + jxfujing_info: "锁定技,摸牌阶段开始前,你跳过此阶段并视为使用一张【荆襄盛世】;以此法获得牌的其他角色本轮首次对你使用牌时需弃置一张牌。", + jxyongrong: "雍容", + jxyongrong_info: "每回合限一次,你造成/受到伤害时,若受伤角色/伤害来源的手牌数小于你,你可以交给其一张牌令此伤害+1/-1。", + jx_sunjian: "荆孙坚", + jx_sunjian_prefix: "荆", + jx_zhouyu: "荆周瑜", + jx_zhouyu_prefix: "荆", + jx_guanyu: "荆关羽", + jx_guanyu_prefix: "荆", + jxxiongzi: "雄姿", + jxxiongzi_info: "锁定技,摸牌阶段你额外摸X张牌,你的手牌上限+X(X为你的体力值)。", + jxzhanyan: "绽焰", + jxzhanyan_info: "出牌阶段限一次,你可以令一名其他角色猜测你的红色手牌数量,然后你展示手牌并将所有红色牌交给其,对其造成X点火焰伤害(X为其猜测值与红色手牌数之差,至多为3)。", + jxwusheng: "武圣", + jxwusheng_info: "你可以将一张红色牌当【杀】或【酒】使用或打出;你使用♦【杀】无距离限制。", + jd_simayan: "司马炎", + jdfengtu: "封土", + jdfengtu_info: "一名其他角色死亡后,你可以选择一名未因此法失去过体力上限的角色,令其减1点体力上限,然后其获得死亡角色座次数的额定回合。", + jdjuqi: "举棋", + jdjuqi_info: "转换技。阴:准备阶段,你摸三张牌;其他角色的准备阶段,其可以展示并交给你一张黑色手牌。阳:准备阶段,你令你本回合使用牌无次数限制且造成的伤害+1;其他角色的准备阶段,其可以展示并交给你一张红色手牌。", + jdtaishi: "泰始", + jdtaishi_info: "主公技,限定技。一名角色的回合开始前,你可以令场上所有隐匿角色依次登场。", + jdtaishi_info_guozhan: "主公技,限定技。一名角色的回合开始前,你可以令场上所有存在未明置武将牌的角色依次明置所有武将牌。", + jd_sb_sunquan: "鼎孙权", + jd_sb_sunquan_prefix: "鼎", + jdsbzhiheng: "制衡", + jdsbzhiheng_info: "出牌阶段限一次。你可以弃置任意张牌并摸等量的牌,若你以此法弃置的牌包括你装备区的牌,则你多摸一张牌", + jdsbtongye: "统业", + jdsbtongye_info: "锁定技,若牌堆未洗过牌,你视为拥有〖英姿〗和〖固政〗。", + jdsbjiuyuan: "救援", + jdsbjiuyuan_info: "出牌阶段限一次,你可以获得一名其他吴势力角色装备区的所有牌,然后你回复1点体力。", + jd_sb_xiaoqiao: "鼎小乔", + jd_sb_xiaoqiao_prefix: "鼎", + jdsbtianxiang: "天香", + jdsbtianxiang_info: "当你受到伤害时,你可以展示两张手牌,令一名其他角色选择并获得其中一张,若其以此法获得♥牌,你将此伤害转移给其;否则其本回合不能使用同类型的手牌。", + jdsbhongyan: "红颜", + jdsbhongyan_info: "锁定技。①你的♠牌和♠判定牌的花色视为♥。②当你失去牌后,若你本回合未以此法获得过牌,你展示这些牌中背面向上移动的牌,若这些牌中有花色为♥的牌,你摸一张牌。", + jd_sb_guanyu: "鼎关羽", + jd_sb_guanyu_prefix: "鼎", + jdsbwusheng: "武圣", + jdsbwusheng_info: "你可以将一张手牌当任意【杀】使用或打出。出牌阶段开始时,你可以令一名其他角色展示所有手牌,本阶段你对其使用的前X张【杀】无距离和次数限制且结算后你摸一张牌(X为其以此法展示的红色手牌数)。", + jdsbyijue: "义绝", + jdsbyijue_info: "锁定技,准备阶段,所有其他角色依次选择是否交给你一张牌,以此法交给你牌的角色本回合首次受到你的【杀】的造成的伤害时,你防止之。", + jd_sb_jiangwei: "鼎姜维", + jd_sb_jiangwei_prefix: "鼎", + jdsbtiaoxin: "挑衅", + jdsbtiaoxin_info: "出牌阶段限一次。你可以选择至多X名角色(X为你的体力值),令这些角色选择一项:1.对你使用一张无距离限制的【杀】,此【杀】结算结束后,若此【杀】未造成伤害,你获得其一张牌;2.你获得其一张牌。", + jdsbzhiji: "志继", + jdsbzhiji_info: "觉醒技,当你进入濒死状态时,你回复体力至2点,减少1点体力上限,获得〖北伐〗,然后若你的手牌数为全场最少,你摸两张牌。", + jdsbbeifa: "北伐", + jdsbbeifa_info: "出牌阶段,你可以弃置任意张手牌,然后令一名其他角色展示等量张手牌。若如此做,你可以将其展示牌中与你弃置牌中牌名相同的牌当无次数限制的【杀】使用,然后你可以重复此流程。", + jd_sb_daqiao: "鼎大乔", + jd_sb_daqiao_prefix: "鼎", + jdsbguose: "国色", + jdsbguose_info: "出牌阶段限一次,你可以将一张♦牌当【乐不思蜀】使用或移动场上一张【乐不思蜀】。", + jdsbliuli: "流离", + jdsbliuli_info: "当你成为【杀】的目标时,你可以弃置一张牌并选择你攻击范围内的一名不为此【杀】使用者的角色,将此【杀】转移给该角色。然后其获得“流离”标记,且移去场上所有其他的“流离”。有“流离”的角色回合开始时,其移去其“流离”并执行一个额外的出牌阶段。", + jd_sb_menghuo: "鼎孟获", + jd_sb_menghuo_prefix: "鼎", + jdsbhuoshou: "祸首", + jdsbhuoshou_info: "锁定技。①【南蛮入侵】对你无效。②其他角色使用【南蛮入侵】指定目标后,你代替其成为此牌的伤害来源。③出牌阶段结束时,你弃置所有手牌视为使用一张【南蛮入侵】。", + jdsbzaiqi: "再起", + jdsbzaiqi_info: "弃牌阶段结束时,你可以令至多X名角色各选择一项(X为你本回合弃置的牌数):1.你摸一张牌;2.弃置一张牌,然后你回复1点体力。", + jd_sb_yuanshao: "鼎袁绍", + jd_sb_yuanshao_prefix: "鼎", + jdsbluanji: "乱击", + jdsbluanji_info: "出牌阶段限一次,你可以将两张手牌当【万箭齐发】使用。手牌数大于你的其他角色打出【闪】响应你的【万箭齐发】后,若你的手牌数小于体力值,你摸一张牌。", + jdsbxueyi: "血裔", + jdsbxueyi_info: "主公技,锁定技,你的手牌上限+2X(X为其他群势力角色数)。当其他群势力角色使用或打出牌响应你使用的牌结算结束后,你令其此阶段不能使用或打出手牌。", + jd_sb_yujin: "鼎于禁", + jd_sb_yujin_prefix: "鼎", + jdsbjieyue: "节钺", + jdsbjieyue_info: "结束阶段,你可以令一名其他角色摸两张牌并获得1点护甲,然后其须交给你两张牌。", + jd_sb_sunshangxiang: "鼎孙尚香", + jd_sb_sunshangxiang_prefix: "鼎", + jdsbjieyin: "结姻", + jdsbjieyin_info: "锁定技,出牌阶段开始时,你令一名手牌数不大于你的角色选择一项:1.交给你X张手牌(X=min(2,其手牌数)且至少为1),然后获得1点护甲;2.你回复1点体力并获得所有“妆”,然后减少1点体力上限,变更势力为吴。", + jdsbliangzhu: "良助", + jdsbliangzhu_info: "蜀势力技。出牌阶段限一次,你可以将一名其他角色装备区的一张牌置于你的武将牌上,称为“妆”,然后令一名其他角色回复1点体力。", + jd_sb_liubei: "鼎刘备", + jd_sb_liubei_prefix: "鼎", + jdsbzhangwu: "章武", + jdsbzhangwu_info: "限定技,出牌阶段,你可以移去任意的“仁望”标记并摸等量张牌,若如此做,本回合你使用【杀】无距离限制且〖仁德〗失效直到你进入濒死状态。", + jd_sb_fazheng: "鼎法正", + jd_sb_fazheng_prefix: "鼎", + jdsbxuanhuo: "眩惑", + jdsbxuanhuo_info: "①出牌阶段限一次。你可以将一张牌交给一名没有“眩”标记的其他角色,然后令其获得“眩”标记。②当有“眩”的其他角色于摸牌阶段外得到牌后,若你以此法于其本次获得“眩”的期间内得到其的牌数小于5,你获得其一张手牌。", + jdsbenyuan: "恩怨", + jdsbenyuan_info: "锁定技。准备阶段,若场上存在有“眩”的角色,你移去该角色的“眩”,且若其手牌数小于你,你交给其两张牌;否则其失去1点体力,你回复1点体力。", + jd_sb_zhangfei: "鼎张飞", + jd_sb_zhangfei_prefix: "鼎", + jdsbpaoxiao: "咆哮", + jdsbpaoxiao_info: "锁定技。①你使用【杀】无次数限制。②若你的装备区内有武器牌,则你使用【杀】无距离限制。③当你于出牌阶段内使用第二张及以后【杀】时,你获得如下效果:{此【杀】不可被响应且伤害值基数+1;此【杀】指定目标后,目标角色的非锁定技于本回合内失效;此【杀】造成伤害后,若目标角色存活,则你失去1点体力且其弃置你一张手牌。}", + jd_jin_simashi: "鼎司马师", + jd_jin_simashi_prefix: "鼎", + jdtairan: "泰然", + jdtairan_info: "锁定技,结束阶段,你将体力回复至体力上限,并将手牌摸至体力上限。然后你的下一个出牌阶段开始时,你失去上一次以此法回复的体力值的体力,弃置X张手牌(X为你上次以此法获得的牌数)。", + jd_sb_sp_zhugeliang: "鼎诸葛亮", + jd_sb_sp_zhugeliang_prefix: "鼎", + jdhuoji: "火计", + jdhuoji_info: "使命技。①使命:出牌阶段限一次,你可以对一名其他角色造成1点火焰伤害,然后你对所有与其势力相同的不为其的其他角色各造成1点火焰伤害。②成功:准备阶段,若你本局游戏已对其他角色造成的火焰伤害不小于本局游戏总角色数,则你失去〖火计〗和〖看破〗,然后获得〖观星〗和〖空城〗。③失败:使命成功前进入濒死状态。", + jdkanpo: "看破", + jdkanpo_info: "①游戏开始时,你摸三张牌,然后将三张牌置于武将牌上。②一名角色使用牌时,你可以移去武将牌上的一张与此牌牌名相同的“看破”牌,然后取消之并摸一张牌。", + jdguanxing: "观星", + jdguanxing_info: "①准备阶段,你将所有“星”置入弃牌堆,然后将牌堆顶的X张牌置于你的武将牌上,称为“星”(X为7-此前发动〖观星①〗次数的3倍,且X至少为0)。②出牌阶段,你可以将任意张“星”置于牌堆顶。③你可以如手牌般使用或打出“星”。", + jd_sb_caocao: "鼎曹操", + jd_sb_caocao_prefix: "鼎", + jdjianxiong: "奸雄", + jdjianxiong_info: "①游戏开始时,你可获得至多2枚“治世”标记。②当你受到伤害后,你可获得伤害牌,摸2-X张牌(X为“治世”数),然后你可以移去1枚“治世”。", + jd_jin_simazhao: "鼎司马昭", + jd_jin_simazhao_prefix: "鼎", + jd_jin_xiahouhui: "鼎夏侯徽", + jd_jin_xiahouhui_prefix: "鼎", + jdbaoqie: "宝箧", + jdbaoqie_info: "隐匿技,锁定技。你登场后,从牌堆或弃牌堆中获得一张不为赠物的防具牌,然后你可以使用此牌。", + jd_hanlong: "鼎韩龙", + jd_hanlong_prefix: "鼎", + jdcibei: "刺北", + jdcibei_info: "①当一名角色使用【杀】造成伤害且此牌对应的实体牌进入弃牌堆后,你可以将一张不为【杀】的“刺”置入弃牌堆,并将这些牌置入“刺”,然后弃置一名角色区域里的一张牌。②一名角色的回合结束时,若你的“刺”均为【杀】,你获得所有“刺”,然后你本局游戏使用【杀】无距离和次数限制。③一名角色的回合结束时,你获得弃牌堆中你本回合弃置的所有【杀】。", + jd_sb_pangtong: "鼎庞统", + jd_sb_pangtong_prefix: "鼎", + jdlianhuan: "连环", + jdlianhuan_info: "①你可以将♣手牌当作【铁索连环】使用或重铸。②当你使用【铁索连环】指定一名未横置角色为目标后,你可以弃置其一张牌。", + jd_sb_ganning: "鼎甘宁", + jd_sb_ganning_prefix: "鼎", + jdqixi: "奇袭", + jdqixi_info: "出牌阶段限一次,你可以选择一张手牌,然后令一名其他角色声明一个此次未以此法声明过的花色,若此牌的花色与其声明的花色:不同,你令其重复此流程;相同,你展示并弃置选择的牌,然后弃置其区域内的X-1张牌(X为其于本次〖奇袭〗中选择花色的次数)。", + jdfenwei: "奋威", + jdfenwei_info: "限定技,当一名角色使用普通锦囊牌指定第一个目标后,若此牌目标数不大于2,则你可以令此牌对任意名角色无效,若你选择了自己,则你可以于本回合结束时发动〖奇袭〗。", + jd_sb_zhaoyun: "鼎赵云", + jd_sb_zhaoyun_prefix: "鼎", + jdlongdan: "龙胆", + jdlongdan_info: "你可以将【杀】/【闪】当作【闪】/【杀】使用或打出,然后若你本阶段未以此法获得过牌,则你摸两张牌。", + jdlongdanx: "龙胆·改", + jdlongdanx_info: "你可以将一张基本牌当作任意基本牌使用或打出,然后若你本阶段未以此法获得过牌,则你摸两张牌。", + jd_sb_huangyueying: "鼎黄月英", + jd_sb_huangyueying_prefix: "鼎", + jdjizhi: "集智", + jdjizhi_info: "锁定技,当你使用一张普通锦囊牌时,你摸一张牌,且你本回合手牌上限+1。", + jdqicai: "奇才", + jdqicai_info: "①你使用锦囊牌无距离限制。②出牌阶段限一次,你可以展示一张装备牌并交给一名其他角色,然后其选择一项:1.展示并交给你两张非装备牌;2.你从牌堆或弃牌堆随机获得两张普通锦囊牌。", + jd_sp_yangwan: "鼎杨婉", + jd_sp_yangwan_prefix: "鼎", + jdmingxuan: "瞑昡", + jdmingxuan_info: "锁定技。出牌阶段开始时,你须选择至多X张花色各不相同的手牌(X为未选择过选项一的角色)展示之。然后从你的下家开始,未选择过选项一的角色依次选择获得其中的一张牌,然后选择一项:⒈对你使用一张【杀】。⒉交给你一张牌,然后你摸一张牌。", + jd_ol_huaxin: "鼎华歆", + jd_ol_huaxin_prefix: "鼎", + jdcaozhao: "草诏", + jdcaozhao_info: "每轮限一次,体力值小于等于你的角色的出牌阶段开始时,你可以展示其一张手牌,选择一个你本局游戏未以此法声明过的基本牌或普通锦囊牌,然后令其选择一项:1.将此牌当作你声明的牌使用;2.失去1点体力。", + jd_jin_wangyuanji: "鼎王元姬", + jd_jin_wangyuanji_prefix: "鼎", + jdshiren: "识人", + jdshiren_info: "隐匿技,当你于其他角色的回合内登场时,若其有手牌,则你可对其发动〖宴戏〗。", + jdyanxi: "宴戏", + jdyanxi_info: "出牌阶段,你可以选择一名有手牌的其他角色,其将此牌给场上其他角色展示,然后你将此牌与牌堆顶的两张牌混合后展示,然后你选择其中一张。若你以此法选择的是该角色展示的手牌,则你获得这三张牌;否则你获得选择的牌,然后将剩余的牌以任意顺序置于牌堆顶。", + jd_sb_xuhuang: "鼎徐晃", + jd_sb_xuhuang_prefix: "鼎", + jdsbduanliang: "断粮", + jdsbduanliang_info: "出牌阶段限一次。你可以与一名其他角色进行谋弈。若你赢,且你选择的选项为:“围城断粮”,你摸一张牌,然后若其判定区没有【兵粮寸断】,你可以将一张黑色非锦囊牌当【兵粮寸断】对其使用,否则你获得其一张牌;“擂鼓进军”,你视为对其使用一张【决斗】。", + ty_guanyu: "神秘将军", + ty_guanyu_ab: "牢关羽", + ty_guanyu_prefix: "牢", + tywusheng: "武圣", + tywusheng_info: "你可以将一张红色牌当【杀】使用或打出。你以此法使用的【杀】仅能被与此牌花色相同的【闪】抵消。", + tychengshi: "乘势", + tychengshi_info: "锁定技,每回合限一次,当你于回合内/回合外使用红色【杀】造成伤害后,你令此牌不计入次数/令受伤角色此阶段不能使用伤害类牌指定除你以外的角色为目标。", + tyfuwei: "抚危", + tyfuwei_info: "每回合限一次,当一号位或「刘备」受到伤害后,你可以交给其至多X张牌,然后可以对伤害来源依次使用至多X张【杀】(X为受到伤害点数)。", + ty_sunquan: "桃孙权", + ty_sunquan_prefix: "桃", + tyfuhan: "辅汉", + tyfuhan_info: "当你获得其他角色的手牌后/其他角色获得你的手牌后,该角色可以废除/恢复你的一个装备栏。一名角色的回合结束时,若你本回合发动过【辅汉】,你令当前回合角色将手牌摸至体力上限。", + tychende: "臣德", + tychende_info: "出牌阶段,你可以展示并交给其他角色至少两张手牌,然后你可以视为使用其中一张基本牌或普通锦囊牌。", + tywansu: "完夙", + tywansu_info: "锁定技,有装备栏被废除的角色不能响应虚拟牌;一张虚拟牌即将造成的伤害视为体力流失。", + ty_liubei: "桃刘备", + ty_liubei_prefix: "桃", + tyqingshi: "倾师", + tyqingshi_info: "准备阶段,你可令至多你体力值名角色进行议事,若议事结果为:红色,本轮意见为红色的角色各与其以外的角色互相计算距离+1;黑色,你摸意见为黑色的角色数张牌,然后你可以交给任意名意见为黑色的角色各一张牌。", + tyyilin: "夷临", + tyyilin_info: "每回合每名角色限一次,当你获得其他角色的牌/其他角色获得你的牌后,你可令获得牌的角色选择是否使用其中一张牌。", + tychengming: "承命", + tychengming_info: "主公技,限定技,当你进入濒死时,你可令一名其他蜀势力角色获得你区域里的所有牌,然后你将体力值恢复至1点。若其拥有锁定技,其获得【仁德】。", + ty_chenshi: "桃陈式", + ty_chenshi_prefix: "桃", + tyzhuan: "驻岸", + tyzhuan_info: "出牌阶段,你可以弃置一张【杀】并获得一名其他角色场上的一张装备牌;一名角色使用装备牌后,你可以摸一张牌。", + ty_chengjix: "程畿", + tyzhongen: "忠恩", + tyzhongen_info: "一名角色的结束阶段,若你的手牌本回合发生过变化,你可以将一张【杀】当【无中生有】对其使用,或使用一张无距离限制的【杀】。", + tyliebao: "烈报", + tyliebao_info: "手牌数最少的角色成为【杀】的目标后,你可以摸一张牌并代替其成为目标,若你未因此【杀】受到伤害,其回复一点体力。", + ty_zhaorong: "赵融", + tyyuantao: "援讨", + tyyuantao_info: "每回合限一次,一名角色使用基本牌时,你可以令此牌额外使用一次,然后你于当前回合结束时失去一点体力。", + ty_zhangnan: "桃张南", + ty_zhangnan_prefix: "桃", + tyfenwu: "奋武", + tyfenwu_info: "准备阶段,你可以摸一张牌并展示之,然后你可以将此牌当牌名字数与之相同的基本牌或【决斗】使用。", + ty_fengxí: "桃冯习", + ty_fengxí_prefix: "桃", + tyqingkou: "轻寇", + tyqingkou_info: "结束阶段,你可以从牌堆底摸一张牌并展示之,然后你可以将此牌当牌名字数与你的体力值相同的普通锦囊牌或【杀】使用。", + ty_liaohua: "桃廖化", + ty_liaohua_prefix: "桃", + tydangxian: "当先", + tydangxian_info: "锁定技,回合开始时,你执行一个额外的出牌阶段并从弃牌堆中选择一张【杀】获得。", + tyfuli: "伏枥", + tyfuli_info: "限定技,当你处于濒死状态时,你可以回复体力至2点并将手牌模至两张。", + ty_huangzhong: "桃黄忠", + ty_huangzhong_prefix: "桃", + tyyizhuang: "益壮", + tyyizhuang_info: "准备阶段,若你的判定区里有牌,你可以对自己造成一点伤害,然后弃置判定区里的所有牌。", + ty_wuban: "桃吴班", + ty_wuban_prefix: "桃", + tyyoujun: "诱军", + tyyoujun_info: "出牌阶段限一次,你可以获得一名其他角色的一张牌。若如此做,其可以令其本回合所有手牌视为【杀】并视为对你使用一张【决斗】。", + tyjicheng: "计成", + tyjicheng_info: "限定技,当你受到普通锦囊牌的伤害后,若你的体力值不大于2,你可以选择回复一点体力或摸两张牌。", + ty_shicong: "侍从", + tyjinzhong: "尽忠", + tyjinzhong_info: "出牌阶段开始时或你受到伤害后,你可以选择一项:1:失去一点体力并令一号位或「刘备」回复一点体力;2:交给一名角色至多两张手牌。", + ty_guanxing: "桃关兴", + ty_guanxing_prefix: "桃", + tyconglong: "从龙", + tyconglong_info: "一名角色使用红色【杀】时,你可以弃置一张锦囊牌,令此【杀】不可被响应;一名角色受到红色【杀】造成的伤害时,你可以弃置一张装备牌,令此伤害+1;一名角色的回合结束时,若你本回合弃置过至少两张牌,你可以摸一张牌。", + tyzhaowu: "昭武", + tyzhaowu_info: "当你受到其他角色造成的伤害后,你可以弃置一张牌。若如此做,直到本轮结束,你可以将一张红色牌当【杀】对其使用,且你对其使用牌无距离限制。", + ty_shamoke: "桃沙摩柯", + ty_shamoke_prefix: "桃", + tymanyong: "蛮勇", + tymanyong_info: "回合开始时,若你的装备区里没有【铁蒺藜骨朵】,你可以从游戏外搜寻并使用之;回合结束时,你可以弃置装备区里的【铁蒺藜骨朵】。", + ty_guanyinping: "桃关银屏", + ty_guanyinping_prefix: "桃", + tywuji: "武继", + tywuji_info: "觉醒技,结束阶段,若你本回合造成了3点或更多伤害,你加1点体力上限并回复1点体力,失去【虎啸】,然后选择一项:1.从游戏外搜寻并获得【青龙偃月刀】;2.摸两张牌。", + ty_shen_liubei: "桃神刘备", + ty_shen_liubei_prefix: "桃神", + tylongnu: "龙怒", + tylongnu_info: "转换技,游戏开始时,你可以改变此转换技的状态。出牌阶段开始时,你可以摸一张牌并:阴:失去1点体力,然后此阶段内你可以将红色手牌当无距离限制的火【杀】使用或打出;阳:减少1点体力上限,然后此阶段内你可以将锦囊牌当无次数限制的雷【杀】使用或打出。", + tytaoyuan: "桃园", + tytaoyuan_info: "出牌阶段限一次,你可以弃置两张牌,然后令一名角色从游戏外获得一张【桃园结义】。", + ty_luxun: "桃陆逊", + ty_luxun_prefix: "桃", + tyqianshou: "谦守", + tyqianshou_info: "转换技,其他角色的回合开始时,若其体力值大于你,或其未处于横置状态,阴:你可展示并交给其一张红色牌,本回合你不能使用手牌且你与其不能成为牌的目标;阳:你可令其展示并交给你一张牌,若此牌不为黑色,你失去一点体力。", + tytanlong: "探龙", + tytanlong_info: "出牌阶段限x次,你可以与一名角色进行拼点。若如此做,拼点赢的角色可以获得另一名拼点角色的拼点牌,然后其视为对自己使用一张【铁索连环】(x为横置角色数+1)。", + tyxibei: "袭惫", + tyxibei_info: "当其他角色从牌堆外获得牌后,你可以摸一张牌;若此时为你的出牌阶段,你可展示一张锦囊牌并令此牌本回合视为【火烧连营】直到离开你的手牌区。", + ty_ganning: "桃甘宁", + ty_ganning_prefix: "桃", + tyqixi: "奇袭", + tyqixi_info: "你可以将一张黑色牌当【过河拆桥】使用:你使用非基本牌转化的【过河拆桥】不能被响应。", + tyfenwei: "奋威", + tyfenwei_info: "当一张锦囊牌指定两个或更多目标后,你可以失去X点体力或【奋威】,令此牌对其中任意名目标角色无效(X为“奋威”发动的次数且至少为1)。", + ty_buzhi: "桃步骘", + ty_buzhi_prefix: "桃", + tyhongde: "弘德", + tyhongde_info: "当你一次性获得或失去至少两张牌后,你可以令一名角色摸一张牌或弃一张牌。", + tydingpan: "定叛", + tydingpan_info: "出牌阶段限X次,你可以令一名装备区有牌的角色摸一张牌并选择一项:1.令你弃置其两张牌:2.获得其装备区里的所有牌,然后你对其造成1点伤害(X为你本回合使用过的牌的类型数)。", + ty_tanxiong: "谭雄", + tylengjian: "冷箭", + tylengjian_info: "锁定技,你对攻击范围内/外的角色每回合首次使用【杀】的伤害+1/无距离限制且不能被响应。", + tysheju: "射驹", + tysheju_info: "当你使用【杀】结算结束后,你可以弃置其中一名目标角色的一张牌,若此牌不为坐骑牌,其本回合攻击范围+1,然后若其攻击范围内含有你,其可以对你使用一张【杀】。", + ty_liue: "刘阿", + tyxiyu: "西御", + tyxiyu_info: "一名角色使用转化牌或虚拟牌指定目标后,你可以摸一张牌。", + ty_zhangda: "桃张达", + ty_zhangda_prefix: "桃", + ty_fanjiang: "桃范疆", + ty_fanjiang_prefix: "桃", + tybianta: "鞭挞", + tybianta_info: "每回合限一次,当你成为伤害类牌的目标后,你可以将此牌置于你的武将牌上,称为“怨”。结束阶段,你可以依次使用所有“怨”。", + tybenxiang: "奔降", + tybenxiang_info: "锁定技,你杀死一名角色后,你令一名其他角色摸三张牌。", + tyxiezhan: "协战", + tyxiezhan_info: "锁定技,①游戏开始时,你选择「范疆」或「张达」并变更武将牌。②出牌阶段开始时,你变更武将牌。", + tyxingsha: "刑杀", + tyxingsha_info: "每回合限一次,出牌阶段,你可以将至多两张牌置于你的武将牌上,称为“怨”。结束阶段,你可以将两张“怨”当做无距离限制的普通【杀】使用。", + tyxianshou: "献首", + tyxianshou_info: "锁定技,你杀死一名角色后,你令一名其他角色回复2点体力。", + ty_shen_zhangfei: "桃神张飞", + ty_shen_zhangfei_prefix: "桃神", + tyshencai: "神裁", + tyshencai_info: "①你可以将一张无色牌当作【杀】使用或打出。②出牌阶段限一次,你可以令一名其他角色进行判定。你获得此判定牌,然后若此判定牌:包含以下要素中的任意一个,则其失去已有的下列效果,并获得对应的效果:{⒈体力:当其受到伤害后,其失去等量的体力、⒉武器:其不能使用牌响应【杀】、⒊打出:当其失去手牌后,其再随机弃置一张手牌(不嵌套触发)、⒋距离:其的结束阶段开始时,其翻面};若均不包含,你获得其区域里的一张牌,其获得一枚“死”并获得如下效果:其的角色手牌上限-X、其的回合结束时,若X大于场上存活人数,则其死亡(X为其“死”标记数)。", + tyshencai_wusheng: "神裁·杀", + tyxunshi: "巡使", + tyxunshi_info: "锁定技。①你手牌中的的多目标锦囊牌花色视为none。②你使用颜色为none的牌无距离和次数限制。③当你使用无颜色的牌选择目标后,你令你的〖神裁〗的发动次数上限+1(至多为5),然后可以为此牌增加任意个目标。", + tyxunshi_tag: "无色牌", + ty_shen_guanyu: "桃神关羽", + ty_shen_guanyu_prefix: "桃神", + tywushen: "武神", + tywushen_info: "你可以将红桃牌当作无距离和次数限制且不可被响应的【杀】使用或打出。", + tywuhun: "武魂", + tywuhun_info: "锁定技,你受到1点伤害后,令伤害来源获得1枚“梦魇”标记;当你死亡时,你令杀人凶手或拥有“梦魇”标记最多的一名其他角色进行判定,若结果不为【桃】,其死亡。", + ty_anying: "暗影", + ty_anyingx: "暗影", + ty_wuque: "乌鹊", + ty_yanque: "阎鹊", + ty_wangque: "亡鹊", + tyliupo: "流魄", + tyliupo_info: "转换技,回合开始时,你令本轮:阴:所有角色不能使用【桃】;阳:所有即将造成的伤害均视为体力流失。", + tyzhuiling: "追灵", + tyzhuiling_info: "锁定技,当一名角色失去体力后,你获得等量的“魂”(你至多拥有3枚“魂”);你对没有手牌的角色使用牌无距离和次数限制。", + tyxihun: "吸魂", + tyxihun_info: "锁定技,每轮结束时,所有其他角色失去一点体力或弃置两张手牌。然后你弃置至多3枚“魂”并回复等量体力。", + tyxianqi: "献气", + tyxianqi_info: "其他角色的出牌阶段限一次,其可以对自身造成一点伤害或弃置两张手牌,若如此做,你受到一点伤害。", + tyfansheng: "返生", + tyfansheng_info: "锁定技,你首次进入濒死状态时,你回复体力至1点,然后令所有其他角色依次选择一项:1:弃置所有手牌;2:弃置装备区里的所有牌。", + tyansha: "暗杀", + tyansha_info: "其他角色的回合结束时,你可以将一张牌当刺【杀】对其使用,此牌结算后,其对你的距离视为1直到本轮结束。", + tycangshen: "藏身", + tycangshen_info: "锁定技,所有其他角色计算与你的距离+1;当你使用【杀】后,【藏身】失效直到本轮结束。", + tyxiongren: "凶刃", + tyxiongren_info: "锁定技,你对计算与你距离大于1/不大于1的角色使用【杀】造成的伤害+1/无距离和次数限制。", + tysiji: "伺机", + tysiji_info: "其他角色回合结束时,若其本回合不因使用或打出而失去过牌,你可以将一张牌当无距离限制的刺【杀】对其使用。", + tydaifa: "待发", + tydaifa_info: "其他角色回合结束时,若其本回合获得过除其外的角色的牌,你可以将一张牌当无距离限制的刺【杀】对其使用。", }; export default translates; diff --git a/character/old/character.js b/character/old/character.js index 149ddfda48..e67fdac800 100644 --- a/character/old/character.js +++ b/character/old/character.js @@ -1,7 +1,6 @@ const characters = { old_shixie: ["male", "qun", 3, ["biluan", "lixia"]], panfeng: ["male", "qun", 4, ["kuangfu"]], - old_shen_zhaoyun: ["male", "shen", 2, ["oldjuejing", "oldlonghun"], ["shu"]], old_guanyinping: ["female", "shu", 3, ["xueji_old", "oldhuxiao", "oldwuji"]], old_caocao: ["male", "shen", 3, ["junkguixin", "feiying"], ["die:caocao"]], old_chendao: ["male", "shu", 4, ["drlt_wanglie"]], diff --git a/character/old/skill.js b/character/old/skill.js index f0ebe675b4..0bd14c091a 100644 --- a/character/old/skill.js +++ b/character/old/skill.js @@ -2,84 +2,6 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { - //山包初版神赵 - oldjuejing: { - audio: "xinjuejing", - trigger: { player: "phaseDrawBegin2" }, - filter: function (event, player) { - return !event.numFixed && player.getHp() < player.maxHp; - }, - forced: true, - content: function () { - trigger.num += player.getDamagedHp(); - }, - mod: { - maxHandcard: (player, num) => num + 2, - }, - }, - oldlonghun: { - audio: "relonghun", - inherit: "xinlonghun", - prompt: () => `将${get.cnNumber(Math.max(1, get.player().getHp()))}张♦牌当做杀,♥牌当做桃,♣牌当做闪,♠牌当做无懈可击使用或打出`, - selectCard: () => Math.max(1, get.player().getHp()), - complexCard: true, - precontent: function () { - delete event.result.skill; - player.logSkill("oldlonghun"); - }, - ai: { - respondSha: true, - respondShan: true, - skillTagFilter: function (player, tag) { - var name; - switch (tag) { - case "respondSha": - name = "diamond"; - break; - case "respondShan": - name = "club"; - break; - case "save": - name = "heart"; - break; - } - if (!player.countCards("hes", { suit: name })) return false; - }, - order: function (item, player) { - if (player && _status.event.type == "phase") { - var max = 0; - var list = ["sha", "tao"]; - var map = { sha: "diamond", tao: "heart" }; - for (var i = 0; i < list.length; i++) { - var name = list[i]; - if ( - player.countCards("hes", function (card) { - return (name != "sha" || get.value(card) < 5) && get.suit(card, player) == map[name]; - }) >= Math.max(1, player.getHp()) && - player.getUseValue({ - name: name, - nature: name == "sha" ? "fire" : null, - }) > 0 - ) { - var temp = get.order({ - name: name, - nature: name == "sha" ? "fire" : null, - }); - if (temp > max) max = temp; - } - } - max /= 1.1; - return max; - } - return 2; - }, - }, - hiddenCard: function (player, name) { - if (name == "wuxie" && _status.connectMode && player.countCards("hes") > 0) return true; - if (name == "wuxie") return player.countCards("hes", { suit: "spade" }) >= Math.max(1, get.player().getHp()); - if (name == "tao") return player.countCards("hes", { suit: "heart" }) >= Math.max(1, get.player().getHp()); - }, - }, //魏武帝 junkguixin: { forbid: ["guozhan"], @@ -971,6 +893,7 @@ const skills = { ai: { expose: 0.2, }, + global: "faen_global", }, oldxuanfeng: { audio: "xuanfeng", diff --git a/character/old/sort.js b/character/old/sort.js index 9495390575..583a04e1ef 100644 --- a/character/old/sort.js +++ b/character/old/sort.js @@ -1,6 +1,6 @@ const characterSort = { old_standard: ["ol_yuanshu"], - old_shenhua: ["old_shen_zhaoyun", "old_caocao", "yuji", "zhangjiao", "old_zhugezhan", "old_guanqiujian", "xiahouyuan", "weiyan", "old_xiaoqiao", "pangde", "xuhuang", "junk_sunquan", "huangzhong", "new_caoren", "old_chendao"], + old_shenhua: ["old_caocao", "yuji", "zhangjiao", "old_zhugezhan", "old_guanqiujian", "xiahouyuan", "weiyan", "old_xiaoqiao", "pangde", "xuhuang", "junk_sunquan", "huangzhong", "new_caoren", "old_chendao"], old_refresh: ["old_zhangfei", "old_huatuo", "old_zhaoyun", "ol_huaxiong", "old_guanyu"], old_yijiang1: ["masu", "xushu", "xin_yujin", "old_xusheng", "old_lingtong", "fazheng", "old_gaoshun", "re_yujin"], old_yijiang2: ["old_zhonghui", "madai", "old_handang", "old_liubiao", "oldre_liubiao", "old_guanzhang", "old_wangyi"], diff --git a/character/old/translate.js b/character/old/translate.js index 93d55c57f8..d1a9254b35 100644 --- a/character/old/translate.js +++ b/character/old/translate.js @@ -131,12 +131,6 @@ const translates = { old_caochun_prefix: "旧", old_guanyinping: "旧关银屏", old_guanyinping_prefix: "旧", - old_shen_zhaoyun: "旧神赵云", - old_shen_zhaoyun_prefix: "旧神", - oldjuejing: "绝境", - oldjuejing_info: "锁定技。①摸牌阶段,你令额定摸牌数+X(X为你已损失的体力值)。②你的手牌上限+2。", - oldlonghun: "龙魂", - oldlonghun_info: "你可以将花色相同的Y张牌按下列规则使用或打出:♥当【桃】,♦当火【杀】,♣当【闪】,♠当普【无懈可击】(Y为你的体力值且至少为1)。", panfeng: "旧潘凤", panfeng_prefix: "旧", old_shixie: "旧士燮", diff --git a/character/onlyOL/character.js b/character/onlyOL/character.js index fd304778ea..4b2cadaf8d 100644 --- a/character/onlyOL/character.js +++ b/character/onlyOL/character.js @@ -1,4 +1,5 @@ const characters = { + ol_sb_sunjian: ["male", "wu", 4, ["olsbhulie", "olsbyipo"]], ol_sb_jiangwei: ["male", "shu", 4, ["olsbzhuri", "olsbranji"]], ol_caozhang: ["male", "wei", 4, ["oljiangchi"], ["die:xin_caozhang"]], ol_jianyong: ["male", "shu", 3, ["olqiaoshui", "jyzongshi"], ["tempname:re_jianyong", "die:re_jianyong"]], @@ -16,6 +17,9 @@ const characters = { ol_liru: ["male", "qun", 3, ["xinjuece", "olmieji", "dcfencheng"]], ol_liubiao: ["male", "qun", 3, ["olzishou", "olzongshi"]], ol_wuguotai: ["female", "wu", 3, ["olganlu", "olbuyi"], ["name:丁|null"]], + ol_sb_kongrong: ["male", "qun", 4, ["olsbliwen", "olsbzhengyi"]], + ol_zhangchunhua: ["female", "wei", 3, ["jueqing", "shangshi", "oljianmie"]], + ol_caochong: ["male", "wei", 3, ["olchengxiang", "olrenxin"]], }; export default characters; diff --git a/character/onlyOL/index.js b/character/onlyOL/index.js index 7c814dc6d5..fa610f5613 100644 --- a/character/onlyOL/index.js +++ b/character/onlyOL/index.js @@ -25,7 +25,9 @@ game.import("character", function () { characterIntro: { ...characterIntros }, characterReplace: { ...characterReplaces }, characterSubstitute: { - ol_sb_yuanshao: [], + ol_sb_yuanshao: [ + ["ol_sb_yuanshao_shadow", []], + ], }, card: { ...cards }, skill: { ...skills }, diff --git a/character/onlyOL/skill.js b/character/onlyOL/skill.js index 3ac972902c..91e5743f5f 100644 --- a/character/onlyOL/skill.js +++ b/character/onlyOL/skill.js @@ -2,14 +2,489 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { + //谋孙坚 + olsbhulie: { + audio: 2, + trigger: { + player: "useCardToPlayered", + }, + filter(event, player) { + if (event.targets.length != 1 || !["sha", "juedou"].includes(event.card.name)) return false; + var evtx = event.getParent(); + return !player.hasHistory( + "useCard", + evt => { + return evt != evtx && evt.card.name == event.card.name; + }, + evtx + ); + }, + check(event, player) { + return get.attitude(player, event.targets[0]) <= 0; + }, + logTarget: event => event.targets[0], + async content(event, trigger, player) { + const evt = trigger.getParent(); + if (typeof evt.baseDamage != "number") evt.baseDamage = 1; + evt.baseDamage++; + const target = trigger.targets[0], + sha = get.autoViewAs({ name: "sha", isCard: true }); + player + .when("useCardAfter") + .filter( + evt => + evt == trigger.getParent() && + target.canUse(sha, player, false) && + !game.hasPlayer2(current => { + return current.hasHistory("damage", evtx => evtx.card === evt.card); + }) + ) + .step(async (event, trigger, player) => { + const bool = await player + .chooseBool("虎烈", `是否令${get.translation(target)}视为对你使用一张杀?`) + .set("choice", get.effect(player, sha, target, player) > 0) + .forResultBool(); + if (bool) await target.useCard(sha, player, false); + }); + }, + }, + olsbyipo: { + audio: 2, + trigger: { + player: "changeHp", + }, + filter(event, player) { + const hp = player.getHp(); + if (hp <= 0) return false; + return !player + .getAllHistory("custom", evt => evt.olsbyipo_num) + .map(evt => evt.olsbyipo_num) + .includes(hp); + }, + async cost(event, trigger, player) { + player.getHistory("custom").push({ + olsbyipo_num: player.getHp(), + }); + event.result = await player + .chooseTarget(get.prompt2(event.name.slice(0, -5))) + .set("ai", target => { + const player = get.player(); + if (player.getDamagedHp() == 1 && target.countCards("he") == 0) { + return 0; + } + if (get.attitude(player, target) > 0) { + return 10 + get.attitude(player, target); + } + if (player.getDamagedHp() == 1) { + return -1; + } + return 1; + }) + .forResult(); + }, + async content(event, trigger, player) { + const num = Math.max(player.getDamagedHp(), 1); + const [target] = event.targets; + let directcontrol = num == 1; + if (!directcontrol) { + const str1 = "摸" + get.cnNumber(num, true) + "弃一"; + const str2 = "摸一弃" + get.cnNumber(num, true); + directcontrol = + str1 == + (await player + .chooseControl(str1, str2, function (event, player) { + return _status.event.choice; + }) + .set("choice", get.attitude(player, target) > 0 ? str1 : str2) + .set("prompt", "毅魄:请选择一项") + .forResultControl()); + } + if (directcontrol) { + await target.draw(num); + await target.chooseToDiscard(true, "he"); + } else { + await target.draw(); + await target.chooseToDiscard(num, true, "he"); + } + }, + }, + //OL界曹冲 + olchengxiang: { + audio: 2, + filter(event, player) { + return event.num > 0; + }, + getIndex(event, player) { + return event.num; + }, + trigger: { player: "damageEnd" }, + frequent: true, + intro: { + content: "下次发动【称象】多亮出$张牌", + }, + content: function () { + "step 0"; + let mark = player.countMark("olchengxiang"); + player.removeMark("olchengxiang", mark, false); + event.cards = get.cards(4 + mark); + game.cardsGotoOrdering(event.cards); + event.videoId = lib.status.videoId++; + game.broadcastAll( + function (player, id, cards, num) { + var str; + if (player == game.me && !_status.auto) { + str = "称象:选择任意张点数不大于" + num + "的牌"; + } else { + str = "称象"; + } + var dialog = ui.create.dialog(str, cards); + dialog.videoId = id; + }, + player, + event.videoId, + event.cards, + event.name == "oldchengxiang" ? 12 : 13 + ); + event.time = get.utc(); + game.addVideo("showCards", player, ["称象", get.cardsInfo(event.cards)]); + game.addVideo("delay", null, 2); + "step 1"; + var next = player.chooseButton([0, 4]); + next.set("dialog", event.videoId); + next.set("filterButton", function (button) { + var num = 0; + for (var i = 0; i < ui.selected.buttons.length; i++) { + num += get.number(ui.selected.buttons[i].link); + } + return num + get.number(button.link) <= _status.event.maxNum; + }); + next.set("maxNum", event.name == "oldchengxiang" ? 12 : 13); + next.set("ai", function (button) { + let player = _status.event.player, + name = get.name(button.link), + val = get.value(button.link, player); + if (name === "tao") return val + 2 * Math.min(3, 1 + player.getDamagedHp()); + if (name === "jiu" && player.hp < 3) return val + 2 * (2.8 - player.hp); + if (name === "wuxie" && player.countCards("j") && !player.hasWuxie()) return val + 5; + if (player.hp > 1 && player.hasSkill("renxin") && player.hasFriend() && get.type(button.link) === "equip") return val + 4; + return val; + }); + "step 2"; + if (result.bool && result.links) { + var cards2 = []; + for (var i = 0; i < result.links.length; i++) { + cards2.push(result.links[i]); + cards.remove(result.links[i]); + } + event.cards2 = cards2; + } else { + event.finish(); + } + var time = 1000 - (get.utc() - event.time); + if (time > 0) { + game.delay(0, time); + } + "step 3"; + game.broadcastAll("closeDialog", event.videoId); + var cards2 = event.cards2; + player.gain(cards2, "log", "gain2"); + let num = cards2.reduce((num, i) => { + return num + get.number(i, player); + }, 0); + if (num == 13) player.addMark("olchengxiang", 1, false); + }, + ai: { + maixie: true, + maixie_hp: true, + effect: { + target: function (card, player, target) { + if (get.tag(card, "damage")) { + if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; + if (!target.hasFriend()) return; + if (target.hp >= 4) return [1, 2]; + if (target.hp == 3) return [1, 1.5]; + if (target.hp == 2) return [1, 0.5]; + } + }, + }, + }, + }, + olrenxin: { + audio: 2, + trigger: { + global: "dying", + }, + filter(event, player) { + return event.player != player && player.countCards("he", { type: "equip" }) > 0; + }, + logTarget: "player", + async cost(event, trigger, player) { + event.result = await player + .chooseToDiscard(get.prompt(event.name.slice(0, -5), trigger.player), `弃置一张装备牌并将武将牌翻面,然后${get.translation(trigger.player)}回复至1点体力`, { type: "equip" }, "he") + .set("ai", card => { + const player = get.player(); + if (get.attitude(player, get.event().getTrigger().player) > 3) { + return 11 - get.value(card); + } + return -1; + }) + .forResult(); + }, + async content(event, trigger, player) { + await player.turnOver(); + await trigger.player.recoverTo(1); + }, + ai: { + expose: 0.5, + }, + }, + //OL张春华 + oljianmie: { + audio: 2, + enable: "phaseUse", + filterTarget: lib.filter.notMe, + usable: 1, + async content(event, trigger, player) { + const target = event.target; + let map = {}; + for (const current of [player, target]) { + let colors = ["red", "black"]; + if (current.getDiscardableCards(current, "h").some(card => get.color(card) == "none")) { + colors.push("none2"); + } + const str = get.translation(current == player ? target : player); + const result = await current + .chooseControl(colors) + .set("prompt", "翦灭:请选择一个颜色") + .set("prompt2", "弃置选择颜色的手牌,然后若你/" + str + "弃置的牌更多,则你/" + str + "视为对" + str + "/你使用【决斗】") + .set("ai", () => { + const player = get.event().player; + let controls = get.event().controls.slice(); + return controls.sort((a, b) => { + return ( + player + .getDiscardableCards(player, "h") + .filter(card => { + return get.color(card) == (a == "none2" ? "none" : a); + }) + .reduce((sum, card) => sum + get.value(card, player), 0) - + player + .getDiscardableCards(player, "h") + .filter(card => { + return get.color(card) == (b == "none2" ? "none" : b); + }) + .reduce((sum, card) => sum + get.value(card, player), 0) + ); + })[0]; + }) + .forResult(); + if (result.control) map[current.playerid] = result.control == "none2" ? "none" : result.control; + } + const cards_player = player.getDiscardableCards(player, "h").filter(card => get.color(card) == map[player.playerid]); + const cards_target = target.getDiscardableCards(target, "h").filter(card => get.color(card) == map[target.playerid]); + if (cards_player.length) await player.discard(cards_player); + else player.chat("无牌可弃"); + if (cards_target.length) await target.discard(cards_target); + else target.chat("无牌可弃"); + if (cards_player.length != cards_target.length) { + const user = cards_player.length > cards_target.length ? player : target; + const aim = user == player ? target : player; + const juedou = new lib.element.VCard({ name: "juedou" }); + if (user.canUse(juedou, aim, false)) await user.useCard(juedou, aim, false); + } + }, + ai: { + order: 1, + result: { + target(player, target) { + return get.effect(target, { name: "juedou" }, player, player) * get.sgn(get.attitude(player, target)); + }, + }, + }, + }, + //OL谋孔融 + olsbliwen: { + audio: 2, + trigger: { player: "phaseEnd" }, + filter(event, player) { + return player.hasMark("olsbliwen") && game.hasPlayer(t => t != player); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget( + get.prompt("olsbliwen"), + "移去任意枚“贤”标记并令任意其他角色各获得1枚“贤”标记", + (card, player, target) => { + return target.countMark("olsbliwen") < 5; + }, + [1, Infinity] + ) + .set("ai", target => get.attitude(get.event().player, target) * (target.countCards("h") + 1)) + .forResult(); + }, + async content(event, trigger, player) { + const ts = event.targets.sortBySeat(); + player.removeMark("olsbliwen", ts.length); + for (const t of ts) t.addMark("olsbliwen", 1); + const targets = game.filterPlayer(target => target.hasMark("olsbliwen")).sort((a, b) => b.countMark("olsbliwen") - a.countMark("olsbliwen")); + if (!targets.length) return; + player.line(targets); + for (const target of targets) { + const result = await target + .chooseToUse(function (card) { + const evt = _status.event; + if (!lib.filter.cardEnabled(card, evt.player, evt)) return false; + return get.position(card) == "h"; + }, '###立文###
    使用一张手牌,或移去所有“贤”标记并令' + get.translation(player) + "摸等量的牌
    ") + .set("addCount", false) + .forResult(); + if (!result.bool) { + const num = target.countMark("olsbliwen"); + target.clearMark("olsbliwen"); + await player.draw(num); + } + } + }, + intro: { + name2: "贤", + content: "mark", + }, + marktext: "贤", + group: "olsbliwen_gain", + subSkill: { + gain: { + audio: "olsbliwen", + trigger: { player: "useCard" }, + filter(event, player) { + if (player.countMark("olsbliwen") >= 5) return false; + let history = player.getAllHistory("useCard"); + if (history.length <= 1) return false; + const evt=history[history.length - 2]; + if (!evt || !evt.card) return false; + return get.suit(evt.card) == get.suit(event.card) || get.type2(evt.card) == get.type2(event.card); + }, + forced: true, + locked: false, + content() { + player.addMark("olsbliwen", 1); + }, + mod: { + aiOrder(player, card, num) { + if (typeof card == "object" && _status.currentPhase === player) { + const evt = player.getLastUsed(1); + if (evt && evt.card && ((get.suit(evt.card) && get.suit(evt.card) == get.suit(card)) || (evt.card.number && evt.card.number == get.number(card)))) { + return num + 10; + } + } + }, + }, + }, + }, + ai: { threaten: 3 }, + }, + olsbzhengyi: { + audio: 2, + trigger: { global: "damageBegin4" }, + filter(event, player) { + if (event.hasNature() || !event.player.hasMark("olsbliwen")) return false; + return game.hasPlayer(target => target != event.player && target.hasMark("olsbliwen")); + }, + logTarget(event, player) { + return game.filterPlayer(target => target != event.player && target.hasMark("olsbliwen")); + }, + forced: true, + locked: false, + async content(event, trigger, player) { + const targets = game.filterPlayer(target => target != trigger.player && target.hasMark("olsbliwen")); + let humans = targets.filter(current => current === game.me || current.isOnline()); + let locals = targets.slice(); + locals.removeArray(humans); + const eventId = get.id(); + const send = (current, eventId) => { + lib.skill.olsbzhengyi.chooseBool(current, trigger, eventId); + game.resume(); + }; + let choices = []; + event._global_waiting = true; + let time = 10000; + if (lib.configOL && lib.configOL.choose_timeout) time = parseInt(lib.configOL.choose_timeout) * 1000; + targets.forEach(current => current.showTimer(time)); + if (humans.length > 0) { + const solve = function (resolve, reject) { + return function (result, player) { + if (result && result.bool) { + choices.push(player); + resolve(); + } else reject(); + }; + }; + await Promise.any( + humans.map(current => { + return new Promise(async (resolve, reject) => { + if (current.isOnline()) { + current.send(send, current, eventId); + current.wait(solve(resolve, reject)); + } else { + const next = lib.skill.olsbzhengyi.chooseBool(current, trigger, eventId); + const solver = solve(resolve, reject); + if (_status.connectMode) game.me.wait(solver); + const result = await next.forResult(); + if (_status.connectMode) game.me.unwait(result, current); + else solver(result, current); + } + }); + }) + ).catch(() => {}); + game.broadcastAll("cancel", eventId); + } + if (locals.length > 0) { + for (const current of locals) { + const result = await lib.skill.olsbzhengyi.chooseBool(current, trigger).forResult(); + if (result && result.bool) choices.push(current); + } + } + delete event._global_waiting; + for (const i of targets) { + i.hideTimer(); + i.chat(choices.includes(i) ? "同意" : "拒绝"); + } + if (!choices.length) trigger.player.chat("杯具"); + else { + trigger.cancel(); + trigger.player.chat("洗具"); + game.log(choices, "响应了", trigger.player, "的号召"); + const max = Math.max(...targets.slice().map(i => i.getHp())); + for (const i of targets) { + if (choices.includes(i) && i.getHp() == max) await i.loseHp(trigger.num); + } + } + }, + chooseBool(player, trigger, eventId) { + return player + .chooseBool() + .set("prompt", "是否失去" + trigger.num + "点体力,为" + get.translation(trigger.player) + "取消此次伤害?") + .set( + "choice", + (function (player, trigger) { + const target = trigger.player; + let eff1 = get.damageEffect(target, trigger.source, player); + if (trigger.num > 1) eff1 = Math.min(-1, eff1) * trigger.num; + const eff2 = get.effect(player, { name: "losehp" }, player, player) * trigger.num; + return eff2 > eff1; + })(player, trigger) + ) + .set("id", eventId) + .set("_global_waiting", true); + }, + }, //OL界吴国太 olganlu: { inherit: "xinganlu", async content(event, trigger, player) { const num = Math.abs(event.targets[0].countCards("e") - event.targets[1].countCards("e")); await event.targets[0].swapEquip(event.targets[1]); - await game.asyncDelayx(); - if (player.getDamagedHp() < num && player.countCards("e")) await player.chooseToDiscard("he", num, true); + await game.delayx(); + if (player.getDamagedHp() < num) await player.chooseToDiscard("he", num, true); }, }, olbuyi: { @@ -112,7 +587,7 @@ const skills = { logTarget: "source", async content(event, trigger, player) { const target = trigger.source; - await trigger.cancel(); + trigger.cancel(); await target.draw(); player.addSkill("olzongshi_record"); player.markAuto("olzongshi_record", [target.group]); @@ -180,7 +655,7 @@ const skills = { if (result.bool) { const card = result.links[0]; player.$gain2(card, false); - await game.asyncDelayx(); + await game.delayx(); await player.chooseUseTarget(true, card, false); } } @@ -264,7 +739,7 @@ const skills = { .forResultCards(); const card = cards[0]; target.$give(card, player, false); - await game.asyncDelay(0.5); + await game.delay(0.5); await player.equip(card); } if (choices.includes("draw")) await player.draw(); @@ -301,7 +776,7 @@ const skills = { player.countCards("h", card => { return !current.hasUseTarget(card); }) >= - 2 + (player.getHp() > 1) + 2 + (player.getHp() > 1) ); }) ) @@ -382,6 +857,12 @@ const skills = { await current.damage("fire"); } } else { + const numbers = cards + .map(card => get.number(card, player)) + .toUniqued() + .sort((a, b) => a - b), + min = numbers[0], + max = numbers.at(-1); const [card] = links; cards.remove(card); const cardx = get.autoViewAs( @@ -426,12 +907,12 @@ const skills = { target.addSkill("olsbhongtu_limit"); if (!target.storage.olsbhongtu_limit) target.storage.olsbhongtu_limit = [0, 0]; target.storage.olsbhongtu_limit[0] += 2; - } else { + } else if (num != min && num != max) { skill = "qianxi"; } if (skill) { let skillName = `olsbhongtu_${player.playerid}`; - target.addAdditionalSkills(skillName, [skill]); + target.addAdditionalSkills(skillName, [skill], true); delete target.storage.olsbhongtu_phased; target.when({ player: "phaseBegin" }).then(() => { player.storage.olsbhongtu_phased = true; @@ -470,14 +951,14 @@ const skills = { }, }, trigger: { - player: "phaseEnd" + player: "phaseEnd", }, silent: true, lastDo: true, content() { player.storage.olsbhongtu_limit = [player.storage.olsbhongtu_limit[1], 0]; if (!player.storage.olsbhongtu_limit[0]) player.removeSkill("olsbhongtu_limit"); - } + }, }, }, }, @@ -687,7 +1168,7 @@ const skills = { return player.countMark("olzhenlie_effect"); }, forced: true, - inherit: "olmiji" + inherit: "olmiji", }, }, }, @@ -848,29 +1329,36 @@ const skills = { olchunlao: { audio: "chunlao", audioname: ["xin_chengpu"], - trigger: { - player: "loseAfter", - global: "loseAsyncAfter", - }, + trigger: { global: ["loseAfter", "loseAsyncAfter"] }, filter(event, player) { if (event.type != "discard" || event.getlx === false) return false; - const evt = event.getl(player); - return evt && evt.cards2 && evt.cards2.some(i => i.name == "sha" && get.position(i) == "d"); + return game.hasPlayer(target => { + if (![player.getPrevious(), player, player.getNext()].includes(target)) return false; + return event.getl(target)?.cards2?.some(i => i.name == "sha" && get.position(i) == "d"); + }); }, forced: true, locked: false, content() { - const evt = trigger.getl(player); player .addToExpansion( - evt.cards2.filter(i => i.name == "sha" && get.position(i) == "d"), + game + .filterPlayer(target => { + if (![player.getPrevious(), player, player.getNext()].includes(target)) return false; + return trigger.getl(target)?.cards2?.some(i => i.name == "sha" && get.position(i) == "d"); + }) + .map(target => { + return trigger.getl(target).cards2.filter(i => i.name == "sha" && get.position(i) == "d"); + }) + .flat() + .unique(), "gain2" ) .gaintag.add("olchunlao"); }, ai: { effect: { - player(card, player, target) { + player_use(card, player, target) { if (_status.currentPhase != player) return; if (card.name == "sha" && !player.getExpansions("olchunlao").length && target.hp > 1) { return "zeroplayertarget"; @@ -886,7 +1374,7 @@ const skills = { var cards = player.getExpansions(skill); if (cards.length) player.loseToDiscardpile(cards); }, - group: "olchunlao_save", + group: ["olchunlao_save", "olchunlao_gain"], subSkill: { save: { inherit: "chunlao2", @@ -914,6 +1402,28 @@ const skills = { result: { target: 1 }, }, }, + gain: { + audio: "chunlao", + audioname: ["xin_chengpu"], + trigger: { global: "loseHpEnd" }, + filter(event, player) { + return player.getExpansions("olchunlao").length; + }, + async cost(event, trigger, player) { + const cards = player.getExpansions("olchunlao"); + event.result = await player + .chooseButton(["###" + get.prompt("olchunlao") + "###获得至多两张“醇”?", cards], [1, 2]) + .set("ai", button => { + const player = get.event().player; + return player.hasSha() ? 0 : get.value(button.link); + }) + .forResult(); + if (event.result.bool) event.result.cards = event.result.links; + }, + async content(event, trigger, player) { + await player.gain(event.cards, player, "give"); + }, + }, }, }, //虞翻 @@ -928,8 +1438,8 @@ const skills = { if (event.getParent(3).name != "phaseDiscard") return false; const cards = get.info("olzongxuan").getCards(event, player); return game.hasPlayer(target => { - if (cards.some(i => get.type(i, target) == "equip") && (get.attitude(player, target) > 0 || get.recoverEffect(target, player, player) > 0)) return true; - if (cards.some(i => get.type(i, target) != "equip") && target.getHp() >= player.getHp() && get.effect(target, { name: "losehp" }, player, player) > 0) return true; + if (cards.some(i => get.type(i, null, target) == "equip") && (get.attitude(player, target) > 0 || get.recoverEffect(target, player, player) > 0)) return true; + if (cards.some(i => get.type(i, null, target) != "equip") && target.getHp() >= player.getHp() && get.effect(target, { name: "losehp" }, player, player) > 0) return true; return false; }); }, @@ -945,8 +1455,8 @@ const skills = { const cards = list[0][1].slice(), cards2 = cards.filter(card => { return game.hasPlayer(target => { - if (get.type(card, target) == "equip" && (get.attitude(player, target) > 0 || get.recoverEffect(target, player, player) > 0)) return true; - if (get.type(card, target) != "equip" && target.getHp() >= player.getHp() && get.effect(target, { name: "losehp" }, player, player) > 0) return true; + if (get.type(card, null, target) == "equip" && (get.attitude(player, target) > 0 || get.recoverEffect(target, player, player) > 0)) return true; + if (get.type(card, null, target) != "equip" && target.getHp() >= player.getHp() && get.effect(target, { name: "losehp" }, player, player) > 0) return true; return false; }); }), @@ -1000,9 +1510,9 @@ const skills = { if (!cards.length) return 0; const card = cards[0], att = get.attitude(player, target); - if (get.type(card, target) == "equip" && (get.attitude(player, target) > 0 || get.recoverEffect(target, player, player) > 0)) return get.recoverEffect(target, player, player) * 20 + att / 114514; - if (get.type(card, target) != "equip") { - if (target.getHp() >= player.getHp()) return get.effect(target, { name: "losehp" }, player, player) * 20 - att / 114514; + if (get.type(card, null, target) == "equip" && (get.attitude(player, target) > 0 || get.recoverEffect(target, player, player) > 0)) return get.recoverEffect(target, player, player) * 20 + att / 114514; + if (get.type(card, null, target) != "equip") { + if (target.getHp() !== player.getHp()) return get.effect(target, { name: "losehp" }, player, player) * 20 - att / 114514; return get.effect(target, { name: "draw" }, player, player); } return 0; @@ -1014,14 +1524,14 @@ const skills = { const { result } = await target.draw("visible"); if (result) { const card = result[0]; - if (get.type(card, target) == "equip") { + if (get.type(card, null, target) == "equip") { if (target.getCards("h").includes(card) && target.hasUseTarget(card)) { const { result: { bool }, } = await target.chooseUseTarget(card, true, "nopopup"); if (bool) await target.recover(); } - } else if (target.getHp() >= player.getHp()) await target.loseHp(); + } else if (target.getHp() !== player.getHp()) await target.loseHp(); } } }, @@ -1085,25 +1595,28 @@ const skills = { global: "olsbhetao_ai", subSkill: { ai: { - effect: { - player_use(card, player) { - if ( - !game.hasPlayer(target => { - return target.hasSkill("olsbhetao") && (get.attitude(player, target) < 0 || get.attitude(target, player) < 0); - }) || - game.countPlayer(target => { - return player.canUse(card, target); - }) < 2 - ) - return; - const select = get.copy(get.info(card).selectTarget); - let range; - if (select == undefined) range = [1, 1]; - else if (typeof select == "number") range = [select, select]; - else if (get.itemtype(select) == "select") range = select; - else if (typeof select == "function") range = select(card, player); - game.checkMod(card, player, range, "selectTarget", player); - if (range[1] == -1 || (range[1] > 1 && ui.selected.targets && ui.selected.targets.length)) return "zeroplayertarget"; + ai: { + effect: { + player_use(card, player) { + if ( + typeof card != "object" || + !game.hasPlayer(target => { + return target.hasSkill("olsbhetao") && (get.attitude(player, target) < 0 || get.attitude(target, player) < 0); + }) || + game.countPlayer(target => { + return player.canUse(card, target); + }) < 2 + ) + return; + const select = get.info(card).selectTarget; + let range; + if (select == undefined) range = [1, 1]; + else if (typeof select == "number") range = [select, select]; + else if (get.itemtype(select) == "select") range = select; + else if (typeof select == "function") range = select(card, player); + game.checkMod(card, player, range, "selectTarget", player); + if (range[1] == -1 || (range[1] > 1 && ui.selected.targets && ui.selected.targets.length)) return "zeroplayertarget"; + }, }, }, }, @@ -1223,7 +1736,7 @@ const skills = { if (get.owner(card)) get.owner(card).$give(card, player, false); else { player.$gain2(card, false); - game.delayx(); + await game.delayx(); } player.equip(card); }, @@ -1323,7 +1836,7 @@ const skills = { if (get.owner(card)) get.owner(card).$give(card, player, false); else { player.$gain2(card, false); - game.delayx(); + await game.delayx(); } player.equip(card); break; @@ -1831,7 +2344,6 @@ const skills = { player: ["phaseZhunbeiEnd", "phaseJudgeEnd", "phaseDrawEnd", "phaseUseEnd", "phaseDiscardEnd", "phaseJieshuEnd"], }, filter: function (event, player) { - if (player.hasSkill("olsbzhuri_block")) return false; if (!game.hasPlayer(target => player.canCompare(target))) return false; return player.getHistory("gain", evt => evt.getParent(event.name) == event).length + player.getHistory("lose", evt => evt.getParent(event.name) == event && evt.hs.length).length; }, @@ -1889,6 +2401,7 @@ const skills = { }) .set("list", list.slice(trigger.getParent().num, list.length)); player[result3.control == "失去体力" ? "loseHp" : "addTempSkill"](result3.control == "失去体力" ? 1 : "olsbzhuri_block"); + player.tempBanSkill("olsbzhuri"); } } }, @@ -2084,7 +2597,7 @@ const skills = { audio: "reqiaoshui", inherit: "reqiaoshui", filter(event, player) { - return player.countCards("h") > 0 && !player.hasSkill("olqiaoshui_used"); + return player.countCards("h") > 0; }, async content(event, trigger, player) { const target = event.target; @@ -2093,6 +2606,7 @@ const skills = { else { player.addTempSkill("qiaoshui2"); player.addTempSkill("olqiaoshui_used"); + player.tempBanSkill("olqiaoshui"); } }, subSkill: { diff --git a/character/onlyOL/sort.js b/character/onlyOL/sort.js index 731d42646f..5c1985bed8 100644 --- a/character/onlyOL/sort.js +++ b/character/onlyOL/sort.js @@ -1,9 +1,13 @@ const characterSort = { - onlyOL_yijiang1: ["ol_jianyong", "ol_lingtong", "ol_gaoshun", "ol_fazheng", "ol_wuguotai"], + onlyOL_yijiang1: ["ol_zhangchunhua", "ol_jianyong", "ol_lingtong", "ol_gaoshun", "ol_fazheng", "ol_wuguotai"], onlyOL_yijiang2: ["ol_caozhang", "ol_chengpu", "ol_wangyi", "ol_liubiao"], - onlyOL_yijiang3: ["ol_yufan", "ol_liru"], + onlyOL_yijiang3: ["ol_yufan", "ol_liru", "ol_caochong"], onlyOL_yijiang4: ["ol_caifuren"], - onlyOL_sb: ["ol_sb_jiangwei", "ol_sb_guanyu", "ol_sb_taishici", "ol_sb_yuanshao", "ol_sb_pangtong"], + onlyOL_sb_mouding: ["ol_sb_jiangwei", "ol_sb_pangtong"], + onlyOL_sb_wudong: ["ol_sb_guanyu"], + onlyOL_sb_fenwu: ["ol_sb_taishici", "ol_sb_yuanshao", "ol_sb_sunjian"], + onlyOL_sb_shiren: ["ol_sb_kongrong"], + onlyOL_waitingforsort: [], }; const characterSortTranslate = { @@ -11,7 +15,11 @@ const characterSortTranslate = { onlyOL_yijiang2: "OL专属·将2", onlyOL_yijiang3: "OL专属·将3", onlyOL_yijiang4: "OL专属·将4", - onlyOL_sb: "OL专属·上兵伐谋", + onlyOL_sb_mouding: "OL专属·谋定天下", + onlyOL_sb_wudong: "OL专属·武动乾坤", + onlyOL_sb_fenwu: "上兵伐谋·奋武扬威", + onlyOL_sb_shiren: "上兵伐谋·施仁布泽", + onlyOL_waitingforsort: "等待分包", }; export { characterSort, characterSortTranslate }; diff --git a/character/onlyOL/translate.js b/character/onlyOL/translate.js index bee307c804..9b1a3a5b8b 100644 --- a/character/onlyOL/translate.js +++ b/character/onlyOL/translate.js @@ -47,6 +47,7 @@ const translates = { olsbshenli_info: "出牌阶段限一次,当你使用【杀】指定目标后,你可以令所有可成为此牌目标的其他角色均成为此牌目标,此牌结算完毕后,若你因此牌造成的伤害值X:大于你的手牌数,你摸X张牌(至多摸五张);大于你的体力值,你再次对所有目标角色中可以成为此牌目标的角色使用此牌。", olsbyufeng: "玉锋", olsbyufeng_sizhaojian: "思召剑", + olsbyufeng_sizhaojian_info: "当你使用有点数的【杀】指定目标后,你令目标角色只能使用无点数或点数大于等于此【杀】的【闪】响应此牌。", olsbyufeng_block: "思召剑", olsbyufeng_info: "游戏开始时,你将【思召剑】置入装备区。", sizhaojian: "思召剑", @@ -59,13 +60,13 @@ const translates = { olzongxuan: "纵玄", olzongxuan_info: "当你弃置而失去牌后,或你的上家每回合因弃置首次失去牌后,你可以将位于弃牌堆的这些牌中的任意牌以任意顺序置于牌堆顶。", olzhiyan: "直言", - olzhiyan_info: "你或你的上家的结束阶段,你可以令一名角色正面朝上摸一张牌,然后若此牌:为装备牌,则其使用此牌并回复1点体力;不为装备牌且其体力值大于等于你,则其失去1点体力。", + olzhiyan_info: "你或你的上家的结束阶段,你可以令一名角色正面朝上摸一张牌,然后若此牌:为装备牌,则其使用此牌并回复1点体力;不为装备牌且其体力值不等于你,则其失去1点体力。", ol_chengpu: "OL界程普", ol_chengpu_prefix: "OL界", dclihuo: "疠火", dclihuo_info: "①你使用的非火【杀】可以改为火【杀】,若如此做,此牌结算完毕后,若此牌造成过伤害,则你弃置一张牌或失去1点体力。②你使用火【杀】可以额外指定一个目标。", olchunlao: "醇醪", - olchunlao_info: "①当你的【杀】因弃置进入弃牌堆后,你将位于弃牌堆的这些牌称为“醇”置于武将牌上。②一名角色处于濒死状态时,你可以将一张“醇”置入弃牌堆,然后令其视为使用一张【酒】。", + olchunlao_info: "①当你或你的上下家的【杀】因弃置进入弃牌堆后,你将位于弃牌堆的这些牌称为“醇”置于武将牌上。②一名角色处于濒死状态时,你可以将一张“醇”置入弃牌堆,然后令其视为使用一张【酒】。③当一名角色失去体力后,你可以获得至多两张“醇”。", ol_wangyi: "OL界王异", ol_wangyi_prefix: "OL界", olzhenlie: "贞烈", @@ -76,7 +77,7 @@ const translates = { ol_sb_pangtong: "OL谋庞统", ol_sb_pangtong_prefix: "OL谋", olsbhongtu: "鸿图", - olsbhongtu_info: "一名角色的阶段结束时,若你于此阶段得到过至少两张牌,你可以摸三张牌,展示三张手牌,令一名其他角色选择是否使用其中一张牌并令你随机弃置其中另一张牌。若使用牌的点数于三张牌中满足以下条件,其获得如下技能或效果直到其下一个回合的回合结束:唯一最大,其获得〖飞军〗;不为唯一最大且不为唯一最小,其获得〖潜袭〗;唯一最小,其手牌上限+2。若其未以此法使用牌,你对其与你各造成1点火焰伤害。", + olsbhongtu_info: "一名角色的阶段结束时,若你于此阶段得到过至少两张牌,你可以摸三张牌,展示三张手牌,令一名其他角色选择是否使用其中一张牌并令你随机弃置其中另一张牌。若使用牌的点数于三张牌中满足以下条件,其获得如下技能或效果直到其下一个回合的回合结束:唯一最大,其获得〖飞军〗;不为最大且不为最小,其获得〖潜袭〗;唯一最小,其手牌上限+2。若其未以此法使用牌,你对其与你各造成1点火焰伤害。", olsbqiwu: "栖梧", olsbqiwu_info: "当你每回合首次受到伤害时,若伤害来源为你或在你的攻击范围内,你可以弃置一张红色牌,防止此伤害。", ol_fazheng: "OL界法正", @@ -107,6 +108,28 @@ const translates = { olganlu_info: "出牌阶段限一次,你可以交换两名角色装备区内的牌,然后若你的已损失体力值小于X,你弃置X张牌(X为交换前两者装备区牌数之差)。", olbuyi: "补益", olbuyi_info: "一名角色进入濒死状态时,你可展示其区域内一张牌。若此牌不为基本牌,则其弃置此牌并回复1点体力。", + ol_sb_kongrong: "OL谋孔融", + ol_sb_kongrong_prefix: "OL谋", + olsbliwen: "立文", + olsbliwen_info: "①你使用牌时,若此牌与你使用的上一张牌的花色或类型相同,则你获得1枚“贤”标记(一名角色的“贤”标记上限为5)。②回合结束时,你可以失去任意枚“贤”标记并令等量其他角色各获得1枚“贤”标记,然后场上所有有“贤”标记的角色按照“贤”标记由大到小的顺序(“贤”标记数相同的角色按座次逆时针排序)依次选择是否使用一张手牌,若不选择使用,则其移去所有“贤”标记,然后你摸等量的牌。", + olsbzhengyi: "争义", + olsbzhengyi_info: "当一名有“贤”标记的角色受到伤害时,所有有“贤”标记同时选择是否取消此伤害,所有角色选择完毕后,若有角色选择是,则取消此伤害,然后选择是的角色中体力值最大的角色依次失去X点体力(X为伤害值)。", + ol_zhangchunhua: "OL界张春华", + ol_zhangchunhua_prefix: "OL界", + oljianmie: "翦灭", + oljianmie_info: "出牌阶段限一次,你可以选择一名其他角色,你与其依次选择一个颜色,然后依次弃置各自选择颜色的手牌,若你/其以此法弃置了更多手牌,则你/其视为对其/你使用一张【决斗】。", + ol_caochong: "OL界曹冲", + ol_caochong_prefix: "OL界", + olchengxiang: "称象", + olchengxiang_info: "当你受到1点伤害后,你可以亮出牌堆顶的四张牌,然后获得其中任意张点数之和不大于13的牌;若获得的牌点数之和刚好为13,下次发动【称象】额外亮出一张牌。", + olrenxin: "仁心", + olrenxin_info: "当一名其他角色进入濒死状态时,你可以翻面并弃置一张装备牌,然后令该角色回复体力至1点。", + ol_sb_sunjian: "OL谋孙坚", + ol_sb_sunjian_prefix: "OL谋", + olsbhulie: "虎烈", + olsbhulie_info: "每回合各限一次,当你使用【杀】或【决斗】指定唯一目标后,你可以令此牌伤害值基数+1。若此牌未造成伤害,你可以令目标角色视为对你使用一张【杀】。", + olsbyipo: "毅魄", + olsbyipo_info: "你的体力值变化后,若你体力值大于0且为你首次达到,你可以选择一名角色并选择一项:1.令其摸X张牌,然后弃置弃置一张牌;2.令其摸一张牌,然后其弃置X张牌(X为你已损失体力值且至少为1)。", }; export default translates; diff --git a/character/onlyOL/voices.js b/character/onlyOL/voices.js index dc732847a6..02c2e0a6a1 100644 --- a/character/onlyOL/voices.js +++ b/character/onlyOL/voices.js @@ -46,15 +46,26 @@ export default { "#olsbhetao1": "合诸侯之群力,扶大汉之将倾。", "#olsbhetao2": "猛虎啸于山野,群士执戈相待。", "#olsbhetao3": "合兵讨贼,其利断金!", + "#olsbhetao_ol_sb_yuanshao_shadow1": "众将一心,战无不胜!", + "#olsbhetao_ol_sb_yuanshao_shadow2": "秣马厉兵,今乃报国之时!", + "#olsbhetao_ol_sb_yuanshao_shadow3": "齐心协力,缔三造大汉之举!", "#olsbshenli1": "沧海之水难覆,将倾之厦难扶。", "#olsbshenli2": "诸君心怀苟且,安能并力西向?", "#olsbshenli3": "联军离心,各逐其利。", + "#olsbshenli_ol_sb_yuanshao_shadow1": "什么国恩大义,不过蔽履而已!", + "#olsbshenli_ol_sb_yuanshao_shadow2": "本盟主的话,你是听还是不听?", + "#olsbshenli_ol_sb_yuanshao_shadow3": "尔等皆为墙头草,随风而摆。", "#olsbyufeng1": "梦神人授剑,怀神兵济世。", "#olsbyufeng2": "哼!我剑也未尝不利!", + "#olsbyufeng_ol_sb_yuanshao_shadow1": "士者,怎可徒手而战!", "#olsbshishou1": "今执牛耳,当为天下之先。", "#olsbshishou2": "士者不徒手而战,况其首乎。", "#olsbshishou3": "吾居群士之首,可配剑履否?", + "#olsbshishou_ol_sb_yuanshao_shadow1": "剑来!", + "#olsbshishou_ol_sb_yuanshao_shadow2": "今秉七尺之躯,不负三尺之剑!", + "#olsbshishou_ol_sb_yuanshao_shadow3": "拔剑四顾,诸位识得我袁本初?", "#ol_sb_yuanshao:die": "众人合而无力,徒负大义也……", + "#ol_sb_yuanshao_shadow:die": "袁氏凋零,皆我一人之罪……", "#ol_yufan:die": "唉,主公不能容我啊!", "#ol_jianyong:die": "此景竟无言以对……", }; diff --git a/character/ow.js b/character/ow.js index ef0242ce93..3f066ac799 100644 --- a/character/ow.js +++ b/character/ow.js @@ -234,6 +234,7 @@ game.import("character", function () { return event.card.name == "sha"; }, mark: true, + marktext: "固", intro: { content: "其他角色对你使用杀时需要弃置一张基本牌,否则杀对你无效", }, @@ -266,7 +267,7 @@ game.import("character", function () { }, ai: { effect: { - target_use(card, player, target, current) { + target(card, player, target, current) { if (card.name == "sha") { if (_status.event.name == "qianggu2") return; if (get.attitude(player, target) > 0) return; @@ -1579,17 +1580,8 @@ game.import("character", function () { player.removeSkill("mianzhen2"); }, mod: { - cardEnabled: function () { - return false; - }, - cardUsable: function () { - return false; - }, - cardRespondable: function () { - return false; - }, - cardSavable: function () { - return false; + cardEnabled2: function (card) { + if (get.position(card) == "h") return false; }, }, ai: { @@ -1904,34 +1896,6 @@ game.import("character", function () { }, }, }, - zhuagou: { - enable: "phaseUse", - usable: 1, - changeSeat: true, - filterTarget: function (card, player, target) { - return player != target && player.next != target; - }, - filterCard: true, - check: function (card) { - return 4 - get.value(card); - }, - content: function () { - while (player.next != target) { - game.swapSeat(player, player.next); - } - }, - ai: { - order: 5, - result: { - player: function (player, target) { - var att = get.attitude(player, target); - if (target == player.previous && att > 0) return 1; - if (target == player.next.next && get.attitude(player, player.next) < 0) return 1; - return 0; - }, - }, - }, - }, bingqiang: { enable: "phaseUse", position: "he", @@ -2176,23 +2140,6 @@ game.import("character", function () { }, }, }, - shuangqiang: { - trigger: { source: "damageBegin" }, - check: function (event, player) { - var att = get.attitude(player, event.player); - if (event.player.hp == 1) return att > 0; - return att <= 0; - }, - logTarget: "player", - filter: function (event, player) { - return !event.player.isTurnedOver() && event.num > 0; - }, - content: function () { - trigger.num--; - trigger.player.draw(); - trigger.player.turnOver(); - }, - }, jidong: { trigger: { global: "phaseEnd" }, filter: function (event, player) { @@ -3585,11 +3532,6 @@ game.import("character", function () { }, ai: { expose: 0.1, - effect: { - target: function (card) { - if (card.name == "guiyoujie") return [0, 0]; - }, - }, }, }, shanxian2: { @@ -3674,8 +3616,6 @@ game.import("character", function () { qianggu_info: "出牌阶段限一次,你可以弃置两张牌并获得2点护甲,若如此做,直到你的下个回合开始,其他角色对你使用【杀】时需要弃置一张基本牌,否则此【杀】对你无效。", qianggu2: "强固", - qianggu2_bg: "固", - qianggu2_info: "其他角色对你使用【杀】时需要弃置一张基本牌,否则此【杀】对你无效。", pingzhang: "屏障", pingzhang_info: "每轮各限一次,当你受到伤害时,你可以弃置一张红桃牌令伤害-1;当一名其他角色受到伤害时,你可以弃置一张黑桃牌令伤害-1。", @@ -3776,14 +3716,10 @@ game.import("character", function () { duwen: "毒吻", duwen2: "毒吻", duwen_info: "锁定技,当你造成伤害时,若你的手牌数与受伤害角色相等,此伤害+1。", - zhuagou: "抓钩", - zhuagou_info: "出牌阶段限一次,你可以弃置一张手牌并将你的座位移到任意位置。", dulei: "诡雷", dulei2: "诡雷", dulei_info: "出牌阶段,若你武将牌上没有牌,你可以将一张牌背面朝上置于你的武将牌上,当一名角色使用与该牌花色相同的牌指定你为目标时,你展示并移去此牌,然后该角色失去1点体力并随机弃置一张牌。", - shuangqiang: "霜枪", - shuangqiang_info: "每当你对一名未翻面的角色造成伤害,你可以令伤害-1,然后令受伤害角色翻面。", baoxue: "暴雪", baoxue_info: "限定技,出牌阶段,若你未翻面,你可以展示并弃置你的所有黑色牌,然后令至多X名其他角色随机弃置一张牌并将武将牌翻至背面,X为你的弃牌数;结算后你将武将牌翻至背面。", diff --git a/character/rank.js b/character/rank.js index e1efae3861..ee1f2327c5 100644 --- a/character/rank.js +++ b/character/rank.js @@ -30,7 +30,7 @@ window.noname_character_rank = { "ns_zhangwei", "wanglang", "caojinyu", - "zhangmancheng", + "dc_zhangmancheng", "wu_zhugeliang", "sunlingluan", "wu_luxun", @@ -49,8 +49,10 @@ window.noname_character_rank = { "dc_zhouxuān", "key_iriya", "dc_zhaoyun", + "jd_simayan", ], ap: [ + "zhugejing", "xia_guanyu", "ol_sb_yuanshao", "gjqt_aruan", @@ -151,6 +153,8 @@ window.noname_character_rank = { "ol_feiyi", "ol_jiangwan", "bianyue", + "kongshu", + "mb_sp_zhenji", ], a: [ "star_caoren", @@ -398,6 +402,7 @@ window.noname_character_rank = { "star_sunshangxiang", "yj_xuangongzhu", "ol_sb_pangtong", + "ol_sb_kongrong", "dc_sb_zhugejin", "matie", "dc_sb_caoang", @@ -410,8 +415,15 @@ window.noname_character_rank = { "mb_wangjing", "zhangbu", "licuilianzhaoquanding", + "ol_sb_sunjian", ], am: [ + "dc_sb_chengyu", + "jx_shen_caoren", + "jx_shen_liubiao", + "jx_zhouyu", + "jx_guanyu", + "yj_majun", "tw_yanliang", "tw_wenchou", "tw_yuantan", @@ -642,6 +654,8 @@ window.noname_character_rank = { "re_dengzhi", "sp_jianggan", "tw_caozhao", + "xunyuxunyou", + "yj_sb_guojia", "tw_guohuai", "shen_jiangwei", "dc_luotong", @@ -658,6 +672,7 @@ window.noname_character_rank = { "zhangxuan", "tw_shenguanyu", "dc_sunru", + "ol_sunru", "dc_wangchang", "fengfang", "prp_zhugeliang", @@ -737,6 +752,38 @@ window.noname_character_rank = { "new_simayi", ], bp: [ + "ty_anying", + "ty_anyingx", + "ty_wuque", + "ty_yanque", + "ty_wangque", + "ty_shen_liubei", + "ty_shen_zhangfei", + "ty_shen_guanyu", + "ty_luxun", + "ty_fanjiang", + "ty_zhangda", + "ty_liue", + "ty_tanxiong", + "ty_buzhi", + "ty_ganning", + "ty_guanyinping", + "ty_shamoke", + "ty_guanxing", + "ty_shicong", + "ty_wuban", + "ty_huangzhong", + "ty_liaohua", + "ty_fengxí", + "ty_zhangnan", + "ty_zhaorong", + "ty_chengjix", + "ty_chenshi", + "ty_liubei", + "ty_sunquan", + "ty_guanyu", + "yj_tianchuan", + "jx_sunjian", "ol_peixiu", "caimao", "yj_ehuan", @@ -1034,6 +1081,7 @@ window.noname_character_rank = { "huzhao", "guanhai", "zhangfen", + "mb_zhangfen", "ol_dianwei", "wangyan", "chengui", @@ -1131,6 +1179,8 @@ window.noname_character_rank = { "jsrg_sunlubansunluyu", "jsrg_weiwenzhugezhi", "shen_xuzhu", + "std_pengyang", + "shen_huangzhong", "dc_jiangji", "dc_wangling", "yangfeng", @@ -1159,20 +1209,71 @@ window.noname_character_rank = { "std_chengyu", "std_fanyufeng", "std_feiyi", + "std_guanxing", + "std_fuhuanghou", + "std_liubiao", + "std_gongsunyuan", + "std_cenhun", + "std_simashi", + "std_huaxin", + "std_sunshao", + "std_jiangwan", + "std_maliang", + "std_xushu", + "std_xuezong", + "std_liuzhang", + "std_wangyuanji", + "std_wanglang", + "std_zhonghui", + "old_shen_zhaoyun", "tw_zhugejun", "mb_simafu", "huan_weiyan", "huan_simayi", "huan_zhaoyun", - "huan_guojia", + "huan_zhugeguo", "huan_jiangwei", "budugen", "jsrg_dongbai", "yj_zhonghui", "wuhujiang", "dc_noname", + "ol_caochong", + "ol_kebineng", + "ol_yuanji", + "dc_sb_jushou", + "jd_sb_sunquan", + "jd_sb_xiaoqiao", + "jd_sb_guanyu", + "jd_sb_jiangwei", + "jd_sb_daqiao", + "jd_sb_menghuo", + "jd_sb_yuanshao", + "jd_sb_yujin", + "jd_sb_sunshangxiang", + "jd_sb_liubei", + "jd_sb_fazheng", + "jd_sb_zhangfei", + "jd_jin_simashi", + "jd_sp_yangwan", + "jd_sb_huangyueying", + "jd_sb_zhaoyun", + "jd_sb_ganning", + "jd_sb_pangtong", + "jd_hanlong", + "jd_jin_xiahouhui", + "jd_jin_simazhao", + "jd_sb_caocao", + "jd_sb_sp_zhugeliang", + "jd_ol_huaxin", + "jd_jin_wangyuanji", + "jd_sb_xuhuang", + "mb_jiachong", + "sb_jiaxu", ], b: [ + "liuxiecaojie", + "liutan", "huan_zhugeliang", "huan_zhanghe", "star_zhangzhao", @@ -1232,6 +1333,7 @@ window.noname_character_rank = { "re_jsp_pangtong", "handang", "re_zhangchunhua", + "ol_zhangchunhua", "xunyou", "yufan", "re_chengong", @@ -1301,6 +1403,8 @@ window.noname_character_rank = { "re_jiangwei", "re_caiwenji", "ol_liushan", + "huan_liushan", + "huan_luxun", "re_zhangzhang", "re_masu", "old_madai", @@ -1817,6 +1921,7 @@ window.noname_character_rank = { ], rarity: { legend: [ + "zhugejing", "ol_feiyi", "dc_wuyi", "sp_sunce", @@ -1943,7 +2048,7 @@ window.noname_character_rank = { "shen_xunyu", "tw_gexuan", "fengfangnv", - "zhangmancheng", + "tw_zhangmancheng", "guanning", "shen_jiangwei", "ol_puyuan", @@ -2018,13 +2123,30 @@ window.noname_character_rank = { "guanyue", "key_mia", "jsrg_yuanshao", + "jd_simayan", ], epic: [ + "ty_anying", + "ty_anyingx", + "ty_shen_liubei", + "ty_shen_zhangfei", + "ty_shen_guanyu", + "ty_luxun", + "ty_chenshi", + "ty_liubei", + "ty_guanyu", + "jx_shen_caoren", + "jx_shen_liubiao", + "jx_zhouyu", + "jx_guanyu", + "yj_majun", + "xunyuxunyou", + "yj_sb_guojia", "wuhujiang", "yj_zhonghui", "bianyue", "budugen", - "huan_guojia", + "huan_zhugeguo", "huan_simayi", "dc_sb_zhangxiu", "ol_jiangwan", @@ -2228,7 +2350,9 @@ window.noname_character_rank = { "ol_xunyu", "ns_zhonglimu", "dc_sunru", + "ol_sunru", "zhangfen", + "mb_zhangfen", "xiahouxuan", "prp_zhugeliang", "zhangzhi", @@ -2322,6 +2446,7 @@ window.noname_character_rank = { "star_sunshangxiang", "jsrg_zhangjiao", "ol_sb_pangtong", + "ol_sb_kongrong", "dc_sb_zhugejin", "yue_miheng", "hansong", @@ -2331,8 +2456,40 @@ window.noname_character_rank = { "mb_wangjing", "zhangbu", "new_simayi", + "jd_sb_huangyueying", + "jd_sb_zhaoyun", + "jd_sb_caocao", + "jd_sb_sp_zhugeliang", + "jd_jin_wangyuanji", + "kongshu", + "mb_sp_zhenji", + "ol_sb_sunjian", ], rare: [ + "ty_wuque", + "ty_yanque", + "ty_wangque", + "ty_fanjiang", + "ty_zhangda", + "ty_liue", + "ty_tanxiong", + "ty_buzhi", + "ty_ganning", + "ty_guanyinping", + "ty_shamoke", + "ty_guanxing", + "ty_shicong", + "ty_wuban", + "ty_huangzhong", + "ty_liaohua", + "ty_fengxí", + "ty_zhangnan", + "ty_zhaorong", + "ty_chengjix", + "ty_sunquan", + "yj_tianchuan", + "jx_sunjian", + "liutan", "dc_noname", "ol_liubiao", "huan_weiyan", @@ -2355,6 +2512,23 @@ window.noname_character_rank = { "std_chengyu", "std_fanyufeng", "std_feiyi", + "std_guanxing", + "std_fuhuanghou", + "std_liubiao", + "std_gongsunyuan", + "std_cenhun", + "std_simashi", + "std_huaxin", + "std_sunshao", + "std_jiangwan", + "std_maliang", + "std_xushu", + "std_xuezong", + "std_liuzhang", + "std_wangyuanji", + "std_wanglang", + "std_zhonghui", + "old_shen_zhaoyun", "linghuyu", "yj_simafu", "yj_xuangongzhu", @@ -2593,6 +2767,8 @@ window.noname_character_rank = { "ol_dongzhuo", "re_jiangwei", "ol_liushan", + "huan_liushan", + "huan_luxun", "re_zhangzhang", "re_caiwenji", "re_caozhi", @@ -2655,6 +2831,7 @@ window.noname_character_rank = { "ol_lisu", "zhaozhong", "re_zhangchunhua", + "ol_zhangchunhua", "xin_handang", "sp_bianfuren", "tw_bianfuren", @@ -2875,8 +3052,38 @@ window.noname_character_rank = { "mp_liuling", "mp_wangrong", "licuilianzhaoquanding", + "ol_caochong", + "ol_kebineng", + "ol_yuanji", + "dc_sb_jushou", + "jd_sb_sunquan", + "jd_sb_xiaoqiao", + "jd_sb_guanyu", + "jd_sb_jiangwei", + "jd_sb_daqiao", + "jd_sb_menghuo", + "jd_sb_yuanshao", + "jd_sb_yujin", + "jd_sb_sunshangxiang", + "jd_sb_liubei", + "jd_sb_fazheng", + "jd_sb_zhangfei", + "jd_jin_simashi", + "jd_sp_yangwan", + "jd_sb_pangtong", + "jd_hanlong", + "jd_sb_ganning", + "jd_jin_xiahouhui", + "jd_jin_simazhao", + "jd_ol_huaxin", + "jd_sb_xuhuang", + "mb_jiachong", + "sb_jiaxu", ], junk: [ + "liuxiecaojie", + "std_pengyang", + "shen_huangzhong", "ol_peixiu", "ol_sb_guanyu", "junk_guanyu", diff --git a/character/refresh/character.js b/character/refresh/character.js index acce29a7ee..b3e37be2da 100644 --- a/character/refresh/character.js +++ b/character/refresh/character.js @@ -23,7 +23,7 @@ const characters = { re_xunyou: ["male", "wei", 3, ["reqice", "rezhiyu"], ["clan:颍川荀氏"]], dc_liru: ["male", "qun", 3, ["xinjuece", "dcmieji", "dcfencheng"]], re_zhuhuan: ["male", "wu", 4, ["refenli", "repingkou"]], - ol_dianwei: ["male", "wei", 4, ["olqiangxi", "olningwu"]], + ol_dianwei: ["male", "wei", 4, ["olqiangxi", "olninge"]], re_sp_taishici: ["male", "qun", 4, ["rejixu"], ["name:太史|慈"]], re_liufeng: ["male", "shu", 4, ["rexiansi"]], ol_xunyu: ["male", "wei", 3, ["quhu", "oljieming"], ["clan:颍川荀氏"]], diff --git a/character/refresh/dynamicTranslate.js b/character/refresh/dynamicTranslate.js index 54f855bdc2..5e8e8eca87 100644 --- a/character/refresh/dynamicTranslate.js +++ b/character/refresh/dynamicTranslate.js @@ -2,8 +2,8 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; const dynamicTranslates = { rejiushi(player) { - if (player.storage.chengzhang) return "当你需要使用【酒】时,若你的武将牌正面向上,你可以翻面,视为使用一张【酒】。当你受到伤害后,若你的武将牌背面向上,你可以翻面。当你翻面时,你获得牌堆中的一张随机锦囊。"; - return "当你需要使用【酒】时,若你的武将牌正面向上,你可以翻面,视为使用一张【酒】。当你受到伤害后,若你的武将牌背面向上,你可以翻面并获得牌堆中的一张随机锦囊。"; + if (player.storage.chengzhang) return "当你需要使用【酒】时,若你的武将牌正面向上,你可以翻面,视为使用一张【酒】。当你受到伤害后,若你的武将牌于受到伤害时背面向上,你可以翻面。当你翻面时,你获得牌堆中的一张随机锦囊牌。"; + return "当你需要使用【酒】时,若你的武将牌正面向上,你可以翻面,视为使用一张【酒】。当你受到伤害后,若你的武将牌于受到伤害时背面向上,你可以翻面并获得牌堆中的一张随机锦囊牌。"; }, rejiaozhao(player) { return ["出牌阶段限一次。你可以展示一张手牌,并令一名距离你最近的角色选择一种基本牌或普通锦囊牌的牌名。你可将此牌当做其声明的牌使用直到此阶段结束(你不是此牌的合法目标)。", "出牌阶段限一次。你可以将一张手牌当做一张基本牌或普通锦囊牌使用(你不是此牌的合法目标)。", "出牌阶段每种类型各限一次。你可以将一张手牌当做一张基本牌或普通锦囊牌使用。"][player.countMark("redanxin")]; diff --git a/character/refresh/skill.js b/character/refresh/skill.js index f36fa304ea..751c419936 100644 --- a/character/refresh/skill.js +++ b/character/refresh/skill.js @@ -570,7 +570,7 @@ const skills = { charlotte: true, forced: true, filter: function (event, player) { - return event.source && event.source.isIn() && event.source.hasSkill("mingjian2"); + return event.source && event.source.isIn() && event.source.hasSkill("remingjian_buff"); }, content: function () { player.restoreSkill("rexingshuai"); @@ -778,7 +778,7 @@ const skills = { if (result.bool) { var num = result.cards.length; for (var i of result.cards) { - if (get.type(i, false) == "equip") num++; + if (get.type(i) == "equip") num++; } event.cards = game.cardsGotoOrdering(get.cards(num)).cards; player.showCards(event.cards); @@ -840,7 +840,7 @@ const skills = { trigger: { player: "useCard" }, forced: true, filter: function (event, player) { - if (event.card.name != "sha" && get.type(event.card, false) != "trick") return false; + if (event.card.name != "sha" && get.type(event.card, null, false) != "trick") return false; for (var i = 2; i < 6; i++) { if (!player.hasEmptySlot(i)) return false; } @@ -853,7 +853,7 @@ const skills = { ai: { directHit_ai: true, skillTagFilter: function (player, tag, arg) { - if (!arg || !arg.card || !arg.target || (arg.card.name != "sha" && get.type(arg.card, false) != "trick")) return false; + if (!arg || !arg.card || !arg.target || (arg.card.name != "sha" && get.type(arg.card, null, false) != "trick")) return false; for (var i = 2; i < 6; i++) { if (!player.hasEmptySlot(i)) return false; } @@ -1270,7 +1270,7 @@ const skills = { player.addTempSkill("dcjiushi_sha", { player: "phaseEnd" }); player.addMark("dcjiushi_sha", 1, false); }, - group: ["dcjiushi_use", "dcjiushi_record", "dcjiushi_damage"], + group: ["dcjiushi_use", "dcjiushi_damage"], subSkill: { use: { audio: "dcjiushi", @@ -1348,7 +1348,6 @@ const skills = { }, effect: { target: function (card, player, target) { - if (card.name == "guiyoujie") return [0, 0.5]; if (target.isTurnedOver()) { if (get.tag(card, "damage")) { if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; @@ -1360,17 +1359,6 @@ const skills = { }, }, }, - record: { - trigger: { player: "damageBegin3" }, - silent: true, - firstDo: true, - filter: function (event, player) { - return player.isTurnedOver(); - }, - content: function () { - trigger.dcjiushi = true; - }, - }, damage: { audio: "dcjiushi", trigger: { player: "damageEnd" }, @@ -2442,7 +2430,7 @@ const skills = { threaten: 1.5, }, }, - olningwu: { + olninge: { audio: 2, trigger: { global: "damageEnd" }, filter: function (event, player) { @@ -2760,49 +2748,66 @@ const skills = { player.addTempSkill("rezhanjue_effect", "phaseUseEnd"); }, ai: { - order: 1, + order(item, player) { + if (player.countCards("h") > 1) return 0.8; + return 8; + }, tag: { respond: 2, respondSha: 2, damage: 1, }, result: { - target: -1.5, - player: function (player, target) { - if ( - player.hasSkillTag( - "directHit_ai", - true, - { - target: target, - card: { name: "juedou" }, - }, - true - ) - ) { - return 0; - } - if (get.damageEffect(target, player, target) > 0 && get.attitude(player, target) > 0 && get.attitude(target, player) > 0) { - return 0; - } - var hs1 = target.getCards("h", "sha"); - var hs2 = player.getCards("h", function (card) { - return card.hasGaintag("reqinwang") && get.name(card) == "sha"; - }); - if (hs1.length > hs2.length + 1) { - return -2; - } - var hsx = target.getCards("h"); - if (hsx.length > 2 && hs2.length == 0 && hsx[0].number < 6) { - return -2; - } - if (hsx.length > 3 && hs2.length == 0) { - return -2; - } - if (hs1.length > hs2.length && (!hs2.length || hs1[0].number > hs2[0].number)) { - return -2; - } - return -0.5; + player(player, target) { + let td = get.damageEffect(target, player, target); + if (!td) return 0; + let hs = player.getCards("h"), + val = hs.reduce((acc, i) => acc - get.value(i, player), 0) / 6 + 1; + if (td > 0) return val; + if (player.hasSkillTag( + "directHit_ai", + true, + { + target: target, + card: get.autoViewAs({ name: "juedou" }, hs), + } + )) return val; + let pd = get.damageEffect(player, target, player), + att = get.attitude(player, target); + if (att > 0 && get.damageEffect(target, player, player) > pd) return val; + let ts = target.mayHaveSha(player, "respond", null, "count"); + if (ts < 1 && ts * 8 < Math.pow(player.hp, 2)) return val; + let damage = pd / get.attitude(player, player), + ps = player.mayHaveSha(player, "respond", hs, "count"); + if (att > 0) { + if (ts < 1) return val; + return val + damage + 1; + } + if (pd >= 0) return val + damage + 1; + if (ts - ps + Math.exp(0.8 - player.hp) < 1) return val - ts; + return val + damage + 1 - ts; + }, + target(player, target) { + let td = get.damageEffect(target, player, target) / get.attitude(target, target); + if (!td) return 0; + let hs = player.getCards("h"); + if (td > 0 || player.hasSkillTag( + "directHit_ai", + true, + { + target: target, + card: get.autoViewAs({ name: "juedou" }, hs), + } + )) return td + 1; + let pd = get.damageEffect(player, target, player), + att = get.attitude(player, target); + if (att > 0) return td + 1; + let ts = target.mayHaveSha(player, "respond", null, "count"), + ps = player.mayHaveSha(player, "respond", hs, "count"); + if (ts < 1) return td + 1; + if (pd >= 0) return 0; + if (ts - ps < 1) return td + 1 - ts; + return -ts; }, }, nokeep: true, @@ -3308,20 +3313,14 @@ const skills = { } }, intro: { - markcount: function (card, player) { - var num = get.number(card, player); - var list = [1, 11, 12, 13]; - if (list.includes(num)) return ["A", "J", "Q", "K"][list.indexOf(num)]; - return parseFloat(num); + markcount(card, player) { + return get.strNumber(get.number(card, player)); }, content: function (card, player) { var suit = get.suit(card, player); var num = get.number(card, player); var str = "
  • 上一张牌的花色:" + get.translation(suit); - str += "
  • 上一张牌的点数:"; - var list = [1, 11, 12, 13]; - if (list.includes(num)) str += ["A(1)", "J(11)", "Q(12)", "K(13)"][list.indexOf(num)]; - else str += parseFloat(num); + str += "
  • 上一张牌的点数:" + get.strNumber(num); return str; }, }, @@ -4275,7 +4274,7 @@ const skills = { var card = result.cards[0], target = trigger.player; player.showCards(card, get.translation(player) + "对" + (player == target ? "自己" : get.translation(target)) + "发动了【补益】"); - if (get.type(card, target) != "basic") { + if (get.type(card, null, target) != "basic") { target.discard(card); target.recover(); if (target.countCards("h") == 1) target.draw(); @@ -4728,7 +4727,7 @@ const skills = { async content(event, trigger, player) { while (player.isIn() && trigger.player.isIn()) { await game.asyncDraw([trigger.player, player]); - await game.asyncDelayx(); + await game.delayx(); let getGainSuit = function (player) { let last = player.getHistory("gain", function (evt) { return evt.getParent(2) == event; @@ -5504,7 +5503,7 @@ const skills = { ai: { effect: { target: function (card, player, target) { - if (target == _status.currentPhase && get.tag(card, "damage")) return [0, 1]; + if (target == _status.currentPhase && get.tag(card, "damage")) return [0, 2, 0, 0]; }, }, }, @@ -5991,7 +5990,7 @@ const skills = { game.addGlobalSkill("relongyin_order"); }, onremove: player => { - if (!game.hasPlayer(current => current.hasSkill("relongyin"), true)) game.removeGlobalSkill("relongyin_order"); + if (!game.hasPlayer(current => current.hasSkill("relongyin", null, null, false), true)) game.removeGlobalSkill("relongyin_order"); }, trigger: { global: "useCard" }, direct: true, @@ -6075,7 +6074,7 @@ const skills = { }, trigger: { player: "dieAfter" }, filter: (event, player) => { - return !game.hasPlayer(current => current.hasSkill("relongyin"), true); + return !game.hasPlayer(current => current.hasSkill("relongyin", null, null, false), true); }, silent: true, forceDie: true, @@ -6315,6 +6314,7 @@ const skills = { }, }, reshizhi: { + audio: 2, mod: { cardname: function (card, player) { if (card.name == "shan" && player.hp == 1) return "sha"; @@ -6428,6 +6428,7 @@ const skills = { content: function () { trigger.player.draw(); }, + global: "faen_global", }, dcfaen: { audio: "refaen", @@ -6444,6 +6445,7 @@ const skills = { content: function () { trigger.player.draw(); }, + global: "faen_global", }, //界曹彰 xinjiangchi: { @@ -6744,20 +6746,18 @@ const skills = { forced: true, charlotte: true, filter: function (event, player) { - return ( - player.getHistory("sourceDamage", function (evxt) { - var evt = evxt.getParent(); - return evt && evt.name == "sha" && evt.skill == "changbiao" && evt.getParent("phaseUse") == event; - }).length > 0 - ); + return player.hasHistory("sourceDamage", function (evxt) { + var evt = evxt.getParent(); + return evt && evt.name == "sha" && evt.skill == "changbiao" && evt.getParent("phaseUse") == event; + }); }, content: function () { - var num = 0; + let cards = []; player.getHistory("sourceDamage", function (evxt) { var evt = evxt.getParent(); - if (evt && evt.name == "sha" && evt.skill == "changbiao" && evt.getParent("phaseUse") == trigger) num += evt.cards.length; + if (evt && evt.name == "sha" && evt.skill == "changbiao" && evt.getParent("phaseUse") == trigger) cards.addArray(evt.cards); }); - player.draw(num); + if (cards.length) player.draw(cards.length); }, }, }, @@ -7640,8 +7640,8 @@ const skills = { }, ai: { effect: { - target_use: function (card, player, target) { - if (target != _status.currentPhase && target.countCards("h") >= target.getHandcardLimit() && (get.type(card) == "delay" || get.color(card) == "none")) return "zerotarget"; + target: function (card, player, target) { + if (target != _status.currentPhase && target.countCards("h") >= target.getHandcardLimit() && (get.type(card) == "delay" || get.color(card) == "none")) return "zeroplayertarget"; }, }, }, @@ -8001,7 +8001,7 @@ const skills = { }, ai: { effect: { - player_use: function (card, player, target) { + player: function (card, player, target) { if ( player == target && get.type(card) == "equip" && @@ -9762,7 +9762,7 @@ const skills = { player.getAllHistory("damage", function (evt) { num += evt.num; }); - return num > 7; + return num >= 7; }, content: function () { player.markSkill("rejiushi_mark"); @@ -9778,7 +9778,7 @@ const skills = { rejiushi: { audio: 2, audioname: ["mb_caomao"], - group: ["rejiushi1", "rejiushi2", "rejiushi3", "rejiushi_gain"], + group: ["rejiushi1", "rejiushi3", "rejiushi_gain"], subfrequent: ["gain"], subSkill: { gain: { @@ -9868,7 +9868,6 @@ const skills = { }, effect: { target: function (card, player, target) { - if (card.name == "guiyoujie") return [0, 0.5]; if (target.isTurnedOver()) { if (get.tag(card, "damage")) { if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; @@ -9880,17 +9879,6 @@ const skills = { }, }, }, - rejiushi2: { - trigger: { player: "damageBegin3" }, - silent: true, - firstDo: true, - filter: function (event, player) { - return player.classList.contains("turnedover"); - }, - content: function () { - trigger.rejiushi = true; - }, - }, rejiushi3: { audio: "rejiushi", trigger: { player: "damageEnd" }, @@ -9924,7 +9912,7 @@ const skills = { mark: true, marktext: "改", intro: { - content: "当你需要使用【酒】时,若你的武将牌正面向上,你可以翻面,视为使用一张【酒】。当你受到伤害后,若你的武将牌背面向上,你可以翻面。当你翻面时,你获得牌堆中的一张随机锦囊。", + content: "当你需要使用【酒】时,若你的武将牌正面向上,你可以翻面,视为使用一张【酒】。当你受到伤害后,若你的武将牌于受到伤害时背面向上,你可以翻面。当你翻面时,你获得牌堆中的一张随机锦囊牌。", }, }, rehongyan: { @@ -11578,7 +11566,7 @@ const skills = { player.removeSkillBlocker(skill); }, skillBlocker: function (skill, player) { - return skill != "chanyuan" && skill != "rechanyuan" && !lib.skill[skill].charlotte && player.hp <= 1; + return skill != "chanyuan" && skill != "rechanyuan" && !lib.skill[skill].charlotte && !lib.skill[skill].persevereSkill && player.hp <= 1; }, mark: true, intro: { @@ -11644,7 +11632,7 @@ const skills = { ai: { useShan: true, effect: { - target: function (card, player, target, current) { + target_use: function (card, player, target, current) { let name; if (typeof card == "object") { if (card.viewAs) name = card.viewAs; @@ -11703,6 +11691,8 @@ const skills = { if (pos == "e") return [1, Math.min((Math.max(1, target.countCards("hs")) * (club + spade)) / 4, Math.max(club, spade))]; return [1, (club + spade) / 4]; } + }, + target(card, player, target) { if (name == "lebu" || name == "bingliang") return [target.hasSkillTag("rejudge") ? 0.4 : 1, 2, target.hasSkillTag("rejudge") ? 0.4 : 1, 0]; }, }, @@ -12400,9 +12390,9 @@ const skills = { if (target.hp <= 1) return; if (get.itemtype(cards) != "cards") return; for (var i of cards) { - if (get.name(i, target) == "tao") return [1, 5]; + if (get.name(i, target) == "tao") return [1, 4.5]; } - if (get.value(cards, target) >= 7 + target.getDamagedHp()) return [1, 3]; + if (get.value(cards, target) >= 7 + target.getDamagedHp()) return [1, 2.5]; return [1, 0.6]; } }, @@ -12458,7 +12448,9 @@ const skills = { dc_guansuo: "wusheng_guansuo", guanzhang: "wusheng_guanzhang", guansuo: "wusheng_guansuo", - gz_jun_liubei: "shouyue_wusheng" + gz_jun_liubei: "shouyue_wusheng", + std_guanxing: "wusheng_guanzhang", + ty_guanxing: "wusheng_guanzhang", }, enable: ["chooseToRespond", "chooseToUse"], filterCard: function (card, player) { @@ -12756,9 +12748,6 @@ const skills = { off: { sub: true, }, - off2: { - sub: true, - }, }, audio: 2, enable: "phaseUse", @@ -12775,16 +12764,13 @@ const skills = { return 3 - get.value(card); return 9 - get.value(card); }, - filter: function (event, player) { - return !player.hasSkill("new_reqingnang_off2"); - }, filterTarget: function (card, player, target) { if (target.hp >= target.maxHp || target.hasSkill("new_reqingnang_off")) return false; return true; }, content: function () { target.addTempSkill("new_reqingnang_off"); - if (get.color(cards[0]) == "black") player.addTempSkill("new_reqingnang_off2"); + if (get.color(cards[0]) == "black") player.tempBanSkill("new_reqingnang"); target.recover(); }, ai: { @@ -12868,7 +12854,7 @@ const skills = { game.cardsGotoOrdering(cards); var next = player.chooseToMove(); next.set("list", [["牌堆顶", cards], ["牌堆底"]]); - next.set("prompt", "观星:点击将牌移动到牌堆顶或牌堆底"); + next.set("prompt", "观星:点击或拖动将牌移动到牌堆顶或牌堆底"); next.processAI = function (list) { var cards = list[0][1], player = _status.event.player; @@ -13017,7 +13003,7 @@ const skills = { var subtype = get.subtype(card); if ( !game.hasPlayer(function (current) { - return current != player && current.hp != player.hp && get.attitude(player, current) > 0 && !current.countCards("e", { subtype: subtype }); + return current != player && get.attitude(player, current) > 0 && !current.countCards("e", { subtype: subtype }); }) ) { return 0; @@ -13074,29 +13060,23 @@ const skills = { return 2; }, result: { - target: function (player, target) { - var goon = function () { - var es = player.getCards("e"); - for (var i = 0; i < es.length; i++) { - if (player.countCards("h", { subtype: get.subtype(es[i]) })) return true; - } - return false; - }; - if (player.hp < target.hp) { - if (player.isHealthy()) { - if (!player.needsToDiscard(1) || goon()) return 0.1; - return 0; - } - return 1.5; + player(player, target) { + let card = ui.selected.cards[0], val = -get.value(card, player) / 6; + if (get.position(card) == "e") val += 2; + if (player.hp > target.hp) val++; + else if (player.hp < target.hp && player.isDamaged()) { + val += get.recoverEffect(player, player, player) / get.attitude(player, player); } - if (player.hp > target.hp) { - if (target.isHealthy()) { - if (!player.needsToDiscard(1) || goon()) return 0.1; - return 0; - } - return 1; + return val; + }, + target: function (player, target) { + let card = ui.selected.cards[0], + val = get.position(card) == "e" ? get.value(card, target) / 6 : 0; + if (target.hp > player.hp) val++; + else if (target.hp < player.hp && target.isDamaged()) { + val += get.recoverEffect(target, target, target) / get.attitude(target, target); } - return 0; + return val; }, }, }, @@ -13935,7 +13915,7 @@ const skills = { }, ai: { effect: { - target_use(card, player, target) { + target(card, player, target) { if (player == target || !target.hasFriend()) return; var type = get.type(card); var nh = Math.min( @@ -14001,8 +13981,11 @@ const skills = { ai: { threaten: 0.8, effect: { - target: function (card) { - if (card.name == "guohe" || card.name == "liuxinghuoyu") return 0.5; + player_use(card, player, target) { + if (player.countCards("h") === 1) return [1, 0.8]; + }, + target(card, player, target) { + if (get.tag(card, "loseCard") && target.countCards("h") === 1) return 0.5; }, }, noh: true, @@ -14162,6 +14145,7 @@ const skills = { rejianxiong: { audio: 2, audioname: ["shen_caopi"], + audioname2: { caoteng: "rejianxiong_caoteng" }, trigger: { player: "damageEnd" }, filter: function (event, player) { return get.itemtype(event.cards) == "cards" && get.position(event.cards[0], true) == "o"; @@ -14395,18 +14379,12 @@ const skills = { yijue2: { mark: true, mod: { - cardEnabled: function () { - return false; - }, - cardRespondable: function () { - return false; - }, - cardSavable: function () { - return false; + cardEnabled2: function (card) { + if (get.position(card) == "h") return false; }, }, intro: { - content: "不能使用或打出卡牌", + content: "不能使用或打出手牌", }, }, retieji: { @@ -14514,7 +14492,7 @@ const skills = { direct: true, filter: function (event, player) { if (event._notrigger.includes(event.player)) return false; - return event.card && event.card.name == "sha" && event.cards && get.color(event.cards) == "black" && event.player.countDiscardableCards(player, "hej"); + return event.card && event.card.name == "sha" && event.cards && get.color(event.cards) == "black" && event.player.countDiscardableCards(player, "e"); }, content: function () { "step 0"; @@ -15329,14 +15307,11 @@ const skills = { forced: true, filter: function (event, player) { if (event.name == "chooseToUse") return player.hasCard(card => get.suit(card) == "spade", "hs"); - return event.card && event.card.name == "sha" && event.getParent(2).jiu == true && !player.hasSkill("oljiuchi_air"); + return event.card && event.card.name == "sha" && event.getParent(2).jiu == true && !player.isTempBanned("benghuai"); }, content: function () { player.logSkill("oljiuchi"); - player.addTempSkill("oljiuchi_air"); - }, - subSkill: { - air: {}, + player.tempBanSkill("benghuai"); }, }, rezaiqi: { @@ -15401,6 +15376,18 @@ const skills = { if (targets.length) event.goto(2); }, }, + _dcjiushi_record: { + trigger: { player: "damageBegin3" }, + silent: true, + firstDo: true, + filter: function (event, player) { + return player.isTurnedOver(); + }, + content: function () { + trigger.dcjiushi = true; + trigger.rejiushi = true; + }, + }, }; export default skills; diff --git a/character/refresh/translate.js b/character/refresh/translate.js index cc798f44ea..6bb89f7dec 100644 --- a/character/refresh/translate.js +++ b/character/refresh/translate.js @@ -138,7 +138,7 @@ const translates = { new_rewusheng: "武圣", new_rewusheng_info: "你可以将一张红色牌当做【杀】使用或打出。你使用的方片【杀】没有距离限制。", new_yijue: "义绝", - new_yijue_info: "出牌阶段限一次,你可以弃置一张牌并令一名有手牌的其他角色展示一张手牌。若此牌为黑色,则该角色不能使用或打出牌,非锁定技失效且受到来自你的红桃【杀】的伤害+1直到回合结束。若此牌为红色,则你可以获得此牌,并可以令其回复1点体力。", + new_yijue_info: "出牌阶段限一次,你可以弃置一张牌并令一名有手牌的其他角色展示一张手牌。若此牌为黑色,则该角色不能使用或打出手牌,非锁定技失效且受到来自你的红桃【杀】的伤害+1直到回合结束。若此牌为红色,则你可以获得此牌,并可以令其回复1点体力。", new_yijue2: "义绝", new_yijue2_info: "", new_repaoxiao: "咆哮", @@ -321,11 +321,11 @@ const translates = { reluoying_judge: "落英", reluoying_info: "当其他角色的梅花牌因弃置或判定而进入弃牌堆后,你可以获得之。", rejiushi: "酒诗", - rejiushi_info: "当你需要使用【酒】时,若你的武将牌正面向上,你可以翻面,视为使用一张【酒】。当你受到伤害后,若你的武将牌背面向上,你可以翻面并获得牌堆中的一张随机锦囊。", + rejiushi_info: "当你需要使用【酒】时,若你的武将牌正面向上,你可以翻面,视为使用一张【酒】。当你受到伤害后,若你的武将牌于受到伤害时背面向上,你可以翻面并获得牌堆中的一张随机锦囊牌。", rejiushi1: "酒诗", rejiushi3: "酒诗", rejiushi_mark: "酒诗·改", - rejiushi_mark_info: "当你需要使用【酒】时,若你的武将牌正面向上,你可以翻面,视为使用一张【酒】。当你受到伤害后,若你的武将牌背面向上,你可以翻面。当你翻面时,你获得牌堆中的一张随机锦囊。", + rejiushi_mark_info: "当你需要使用【酒】时,若你的武将牌正面向上,你可以翻面,视为使用一张【酒】。当你受到伤害后,若你的武将牌于受到伤害时背面向上,你可以翻面。当你翻面时,你获得牌堆中的一张随机锦囊牌。", chengzhang: "成章", chengzhang_info: "觉醒技,准备阶段开始时,若你造成伤害与受到伤害值之和累计7点或以上,则你回复1点体力并摸一张牌,然后改写〖酒诗〗。", re_wuyi: "界吴懿", @@ -683,8 +683,8 @@ const translates = { ol_dianwei_prefix: "界", olqiangxi: "强袭", olqiangxi_info: "出牌阶段限两次。你可以弃置一张武器牌或受到1点无来源伤害,然后对一名本回合内未成为过〖强袭〗目标的其他角色造成1点伤害。", - olningwu: "狞恶", - olningwu_info: "锁定技。当一名角色A于一回合内第二次受到伤害后,若A或伤害来源为你,则你摸一张牌,然后弃置其装备区或判定区内的一张牌。", + olninge: "狞恶", + olninge_info: "锁定技。当一名角色A于一回合内第二次受到伤害后,若A或伤害来源为你,则你摸一张牌,然后弃置其装备区或判定区内的一张牌。", re_zhuhuan: "界朱桓", re_zhuhuan_prefix: "界", refenli: "奋励", diff --git a/character/refresh/voices.js b/character/refresh/voices.js index 71a08b34c0..73254ab4ef 100644 --- a/character/refresh/voices.js +++ b/character/refresh/voices.js @@ -91,8 +91,8 @@ export default { "#re_zhuhuan:die": "憾老死病榻,恨未马革裹尸……", "#qiangxi_ol_dianwei1": "典韦来也,谁敢一战。", "#qiangxi_ol_dianwei2": "双戟青罡,百死无生!", - "#olningwu1": "古之恶来,今之典韦!", - "#olningwu2": "宁为刀俎,不为鱼肉。", + "#olninge1": "古之恶来,今之典韦!", + "#olninge2": "宁为刀俎,不为鱼肉。", "#ol_dianwei:die": "为将者,怎可徒手而亡?", "#rejixu1": "辨坚识钝,可解充栋之牛!", "#rejixu2": "以锐欺虚,可击泰山之踵!", @@ -335,6 +335,8 @@ export default { "#ol_pangtong:die": "骥飞羽落,坡道归尘……", "#rewurong1": "策略以入算,果烈以立威!", "#rewurong2": "诈与和亲,不攻可得!", + "#reshizhi1": "护汉成勋业,矢志报国恩。", + "#reshizhi2": "怀精忠之志,坦赤诚之心。", "#re_zhangyi:die": "挥师未捷,杀身以报!", "#xinganlu1": "纳采问名,而后交换文定。", "#xinganlu2": "兵戈相向,何如化戈为帛?", @@ -449,7 +451,7 @@ export default { "#xiaoji_re_sunshangxiang2": "我会的武器,可多着呢。", "#rejieyin1": "得遇夫君,妾身福分。", "#rejieyin2": "随夫嫁娶,宜室宜家。", - "#re_sunshangxiang:die": "就这样……结束了吗?", + "#re_sunshangxiang:die": "哎呀,这次弓箭射歪了。", "#reluoshen1": "屏翳收风,川后静波。", "#reluoshen2": "冯夷鸣鼓,女娲清歌。", "#reqingguo1": "肩若削成,腰如约素。", diff --git a/character/sb/character.js b/character/sb/character.js index 0de564b318..4312647f62 100644 --- a/character/sb/character.js +++ b/character/sb/character.js @@ -1,4 +1,5 @@ const characters = { + sb_jiaxu: ["male", "qun", 3, ["sbwansha", "sbluanwu", "sbweimu"]], sb_handang: ["male", "wu", 4, ["sbgongqi", "sbjiefan"]], sb_gongsunzan: ["male", "qun", 4, ["sbyicong", "sbqiaomeng"], ["name:公孙|瓒"]], sb_gaoshun: ["male", "qun", 4, ["sbxianzhen", "sbjinjiu"]], diff --git a/character/sb/dynamicTranslate.js b/character/sb/dynamicTranslate.js index f9772861b5..db80476386 100644 --- a/character/sb/dynamicTranslate.js +++ b/character/sb/dynamicTranslate.js @@ -31,5 +31,20 @@ const dynamicTranslates = { if (storage) str += ""; return str; }, + sbwansha(player) { + const storage = player.storage.sbwansha; + var str = "①你的回合内,不处于濒死状态的其他角色不能使用【桃】。②一名角色进入濒死状态时,你可以观看其手牌并选择其"; + str += storage ? "区域内" : "中"; + str += "零至两张牌,然后其选择一项:1.你将这些牌分配给任意名不为其的角色;2.其弃置除这些牌以外的牌。"; + return str; + }, + sbweimu(player) { + const storage = player.storage.sbweimu; + var str = "锁定技。"; + str += storage ? "①" : ""; + str += "当你成为黑色锦囊牌的目标时,取消之。"; + if (storage) str += "②每轮开始时,若你上一轮成为其他角色使用牌的目标的次数不大于2,你从弃牌堆中随机获得一张黑色锦囊牌或防具牌。"; + return str; + }, }; export default dynamicTranslates; diff --git a/character/sb/index.js b/character/sb/index.js index fc8c58b7d7..135507f224 100644 --- a/character/sb/index.js +++ b/character/sb/index.js @@ -22,7 +22,7 @@ game.import("character", function () { characterFilter: { ...characterFilters }, characterTitle: {}, characterSubstitute: { - sb_sp_zhugeliang: [], + sb_sp_zhugeliang: [["sb_zhugeliang", []]], }, dynamicTranslate: { ...dynamicTranslates }, characterIntro: { ...characterIntros }, diff --git a/character/sb/skill.js b/character/sb/skill.js index a2cc4ed730..c04438a7e0 100644 --- a/character/sb/skill.js +++ b/character/sb/skill.js @@ -2,6 +2,203 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { + //贾诩 + sbwansha: { + audio: 2, + trigger: { + global: "dying", + }, + filter(event, player) { + const position = player.storage.sbwansha ? "hej" : "h"; + return event.player.countCards(position); + }, + check(event, player) { + return get.attitude(player, event.player) <= 0; + }, + logTarget: "player", + async content(event, trigger, player) { + const target = trigger.player, + position = player.storage.sbwansha ? "hej" : "h"; + let cards = await player.choosePlayerCard(target, position, [0, 2], true).set("visible", true).forResultCards(); + if (cards.length) { + let result; + if (target.getCards(position).some(card => !cards.includes(card))) + result = await target + .chooseControl() + .set("choiceList", [`${get.translation(player)}将${get.translation(cards)}分配给其他角色`, `弃置不为${get.translation(cards)}的牌`]) + .set("ai", () => { + return get.event("goon") ? 0 : 1; + }) + .set("goon", 2 * cards.length <= target.countCards(position) || get.attitude(target, player) > 0) + .forResult(); + else result = { index: 0 }; + if (result.index == 0) { + if (_status.connectMode) game.broadcastAll(() => (_status.noclearcountdown = true)); + let given_map = {}; + while (cards.length) { + let result; + if (cards.length == 1) result = { bool: true, links: cards.slice() }; + else { + result = await player + .chooseCardButton("完杀:请选择要分配的牌", cards, [1, cards.length], true) + .set("ai", button => { + if (!ui.selected.buttons.length) return get.buttonValue(button); + return 0; + }) + .forResult(); + } + const gives = result.links; + const result2 = await player + .chooseTarget("选择获得" + get.translation(gives) + "的角色", cards.length == 1, (card, player, target) => { + return target != get.event().getTrigger().player; + }) + .set("ai", target => { + return get.attitude(get.event("player"), target) * get.sgn(get.sgn(get.event("goon")) + 0.5); + }) + .set( + "goon", + gives.reduce((sum, card) => sum + get.value(card), 0) + ) + .forResult(); + if (result2.bool) { + cards.removeArray(gives); + const id = result2.targets[0].playerid; + if (!given_map[id]) given_map[id] = []; + given_map[id].addArray(gives); + } + } + if (_status.connectMode) game.broadcastAll(() => delete _status.noclearcountdown); + let list = []; + for (const i in given_map) { + const source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; + player.line(source, "green"); + game.log(source, "获得了", given_map[i]); + list.push([source, given_map[i]]); + } + await game + .loseAsync({ + gain_list: list, + giver: player, + animate: "gain2", + }) + .setContent("gaincardMultiple"); + } else await target.discard(target.getCards(position).removeArray(cards)); + } else { + await target.discard(target.getCards(position)); + } + }, + global: "sbwansha_global", + subSkill: { + global: { + mod: { + cardEnabled(card, player) { + var source = _status.currentPhase; + if (card.name == "tao" && source && source != player && source.hasSkill("sbwansha") && !player.isDying()) return false; + }, + cardSavable(card, player) { + var source = _status.currentPhase; + if (card.name == "tao" && source && source != player && source.hasSkill("sbwansha") && !player.isDying()) return false; + }, + }, + }, + }, + }, + sbluanwu: { + audio: "luanwu", + inherit: "luanwu", + contentBefore() { + player.addTempSkill("sbluanwu_add"); + }, + subSkill: { + jiaxu: { + audio: 4, + }, + add: { + trigger: { + global: "loseHpEnd", + }, + filter(event, player) { + if (event.getParent().name != "sbluanwu") return false; + return ["sbwansha", "sbweimu"].some(skill => player.hasSkill(skill, null, null, false) && !player.storage[skill]); + }, + async cost(event, trigger, player) { + const choices = [], + list = ["sbwansha", "sbweimu"]; + const choiceList = ["修改【完杀】", "修改【帷幕】"]; + for (let i = 0; i < 2; i++) { + if (!player.hasSkill(list[i], null, null, false) || player.storage[list[i]]) { + choiceList[i] = '' + choiceList[i] + ""; + } else choices.push(`选项${get.cnNumber(i + 1, true)}`); + } + const control = await player + .chooseControl(choices, "cancel2") + .set("choiceList", choiceList) + .set("prompt", get.prompt(event.name.slice(0, -5))) + .set("ai", () => { + const choices = get.event().controls.slice().remove("cancel2"); + return choices.randomGet(); + }) + .forResultControl(); + event.result = { + bool: control != "cancel2", + cost_data: control, + }; + }, + async content(event, trigger, player) { + const list = ["sbwansha", "sbweimu"], + index = ["选项一", "选项二"].indexOf(event.cost_data); + player.storage[list[index]] = true; + }, + }, + }, + derivation: ["sbwansha_rewrite", "sbweimu_rewrite"], + }, + sbweimu: { + audio: 4, + trigger: { + player: "addJudgeBefore", + target: "useCardToTarget", + global: "roundStart", + }, + filter(event, player) { + if (event.name == "useCardToTarget") return get.type(event.card, null, false) == "trick" && get.color(event.card) == "black"; + if (event.name == "addJudge") return get.color(event.card) == "black"; + if (!player.storage.sbweimu || game.roundNumber < 2) return false; + let num = 0; + game.countPlayer2(current => { + if (player == current) return false; + num += current.getRoundHistory("useCard", evt => evt.targets?.includes(player), 1).length; + }); + return num <= 2 && Array.from(ui.discardPile.childNodes).some(card => get.info("sbweimu").filterCardx(card)); + }, + filterCardx(card) { + return get.subtype(card) == "equip2" || (get.type(card) == "trick" && get.color(card) == "black"); + }, + forced: true, + async content(event, trigger, player) { + if (trigger.name == "useCardToTarget") { + trigger.targets.remove(player); + trigger.getParent().triggeredTargets2.remove(player); + trigger.untrigger(); + } else if (trigger.name == "addJudge") { + trigger.cancel(); + const owner = get.owner(trigger.card); + if (owner?.getCards("hej").includes(trigger.card)) await owner.lose(trigger.card, ui.discardPile); + else await game.cardsDiscard(trigger.card); + game.log(trigger.card, "进入了弃牌堆"); + } else { + const cards = Array.from(ui.discardPile.childNodes).filter(card => get.info("sbweimu").filterCardx(card)); + await player.gain(cards.randomGet(), "gain2"); + } + }, + ai: { + effect: { + target: function (card, player, target, current) { + if (get.type(card, "trick") == "trick" && get.color(card) == "black") return "zeroplayertarget"; + }, + }, + }, + }, //韩当 sbgongqi: { audio: 2, @@ -52,11 +249,11 @@ const skills = { async content(event, trigger, player) { const { cards } = event; await player.discard(cards); - await game.asyncDelayx(); + await game.delayx(); player.addTempSkill("sbgongqi_effect", "phaseChange"); player.markAuto("sbgongqi_effect", [get.color(cards[0], player)]); player.line(game.filterPlayer()); - await game.asyncDelayx(); + await game.delayx(); }, updateBlocker(player) { const list = [], @@ -245,7 +442,7 @@ const skills = { result = await player .chooseControl(numbers, "cancel2") .set("prompt", get.prompt("sbyicong")) - .set("prompt2", "你可以消耗任意点蓄力值并选择一项:⒈你于本轮内至其他角色的距离-X,令系统选择牌堆中的一张【杀】;⒉其他角色于本轮内至你的距离+X,令系统选择牌堆中的一张【闪】(X为你消耗的蓄力值)。然后若你的“扈”数小于4,你将系统选择的牌置于武将牌上,称为“扈”。") + .set("prompt2", "你可以消耗任意点蓄力值并选择一项:⒈你于本轮内至其他角色的距离-1,令系统选择牌堆中的X张【杀】;⒉其他角色于本轮内至你的距离+1,令系统选择牌堆中的X张【闪】(X为你消耗的蓄力值)。然后若你的“扈”数小于4,你将系统选择的牌置于武将牌上,称为“扈”。") .set("ai", () => { return get.event("choice"); }) @@ -275,19 +472,35 @@ const skills = { .chooseControl(["选项一", "选项二", "返回"]) .set("prompt", "义从:请选择一项") .set("choiceList", [ - `你于本轮内至其他角色的距离-${num}${ + `你于本轮内至其他角色的距离-1${ player.countCards("s", card => { return card.hasGaintag("sbyicong"); }) >= 4 ? "" - : ",将牌堆中的一张【杀】置于你的武将牌上,称为“扈”" + : `,将牌堆中的${get.cnNumber( + Math.min( + num, + 4 - + player.countCards("s", card => { + return card.hasGaintag("sbyicong"); + }) + ) + )}张【杀】置于你的武将牌上,称为“扈”` }`, - `其他角色于本轮内至你的距离+${num}${ + `其他角色于本轮内至你的距离+1${ player.countCards("s", card => { return card.hasGaintag("sbyicong"); }) >= 4 ? "" - : ",将牌堆中的一张【闪】置于你的武将牌上,称为“扈”" + : `,将牌堆中的${get.cnNumber( + Math.min( + num, + 4 - + player.countCards("s", card => { + return card.hasGaintag("sbyicong"); + }) + ) + )}张【闪】置于你的武将牌上,称为“扈”` }`, ]) .set("ai", () => { @@ -317,15 +530,19 @@ const skills = { const skill = choice === 0 ? "sbyicong_to" : "sbyicong_from"; player.removeMark("charge", num); player.addTempSkill(skill, "roundStart"); - player.addMark(skill, num, false); - if (player.countCards("s", card => card.hasGaintag("sbyicong")) < 4) { + player.addMark(skill, 1, false); + let cards = []; + while (cards.length < num && cards.length + player.countCards("s", card => card.hasGaintag("sbyicong")) < 4) { const name = choice === 0 ? "sha" : "shan"; - const card = get.cardPile2(name); - if (card) { - game.log(player, "将", card, "置于了武将牌上"); - await player.loseToSpecial([card], "sbyicong"); - player.markSkill("sbyicong"); - } + const card = get.cardPile2(card => card.name == name && !cards.includes(card)); + if (card) cards.push(card); + else break; + } + if (cards.length) { + player.$gain2(cards, false); + game.log(player, "将", cards, "置于了武将牌上"); + await player.loseToSpecial(cards, "sbyicong"); + player.markSkill("sbyicong"); } }, marktext: "扈", @@ -410,7 +627,7 @@ const skills = { }, async cost(event, trigger, player) { const list = ["蓄力", "cancel2"]; - const choiceList = [`弃置${get.translation(trigger.player)}区域里的一张牌,你摸一张牌`, `获得2点蓄力值`]; + const choiceList = [`弃置${get.translation(trigger.player)}区域里的一张牌,你摸一张牌`, `获得3点蓄力值`]; if (trigger.player.isIn() && trigger.player.countDiscardableCards(player, "hej")) { list.unshift("弃牌"); } else { @@ -449,7 +666,7 @@ const skills = { await player.discardPlayerCard(trigger.player, "hej", true); await player.draw(); } else { - const num = Math.min(2, 4 - player.countMark("charge")); + const num = Math.min(3, 4 - player.countMark("charge")); if (num > 0) player.addMark("charge", num); } }, @@ -534,7 +751,7 @@ const skills = { } if (player.storage.sbxianzhen_damaged <= 2) { await target.damage(); - await game.asyncDelayx(); + await game.delayx(); } } const toGain = []; @@ -682,24 +899,20 @@ const skills = { const chosen = player .getAllHistory("useSkill", evt => evt.skill === "sbganglie") .map(evt => { - return evt.targets; + return evt.targets[0]; }); let targets = player .getAllHistory("damage", evt => evt.source && evt.source.isIn()) .map(evt => evt.source) .unique(); - targets = [...targets, ...targets]; targets.removeArray(chosen); event.set("sbganglie_enabledTargets", targets); }, filterTarget(card, player, target) { return get.event("sbganglie_enabledTargets").includes(target); }, - selectTarget: [1, Infinity], - multitarget: true, - multiline: true, async content(event, trigger, player) { - for (const target of event.targets.sortBySeat()) await target.damage(2); + await event.targets[0].damage(2); }, ai: { order: 6, @@ -866,7 +1079,7 @@ const skills = { gaintag: ["sbquhu"], }) .setContent(lib.skill.sbquhu.addToExpansionMultiple); - await game.asyncDelay(1.5); + await game.delay(1.5); const isMin = minLength > myCards.length; const sortedList = lose_list .filter(list => list[0] != player) @@ -891,7 +1104,7 @@ const skills = { }); if (isMin) { await mostPlayer.gain(myCards, "give", player); - await game.asyncDelay(); + await game.delay(); const gain_list = lose_list.filter(list => list[0] != player); game.loseAsync({ gain_list, @@ -900,9 +1113,9 @@ const skills = { } else { mostPlayer.line(secondPlayer, "thunder"); await secondPlayer.damage(mostPlayer); - await game.asyncDelay(); + await game.delay(); await mostPlayer.gain(myCards, "give", player); - await game.asyncDelay(); + await game.delay(); await game .loseAsync({ lose_list: sortedList, @@ -918,7 +1131,7 @@ const skills = { next.set("getlx", false); } }); - await game.asyncDelayx(); + await game.delayx(); } }, addToExpansionMultiple() { @@ -1216,18 +1429,8 @@ const skills = { if (get.tag(card, "damage") && target.hp > 1) { if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; if (!target.hasFriend()) return; - let max = 0; - const num = Math.max(1, player.getDamagedHp()); - if (num > 2) return [1, -2]; - const players = game.filterPlayer(); - for (const current of players) { - if (get.attitude(target, current) > 0) { - max = Math.max(current.countCards("he"), max); - } - } - return [1, Math.max(1, 1 + Math.min(2, max / 3))]; + return [1, 0.6 * (4 - 0.9 * Math.max(1, player.getDamagedHp()))]; } - if ((card.name == "tao" || card.name == "caoyao") && target.hp > 1 && target.countCards("h") <= target.hp) return [0, 0]; }, }, }, @@ -1248,7 +1451,10 @@ const skills = { ai: { result: { target(player, target) { - return target.isLinked() + target.isTurnedOver(); + let res = 0; + if (target.isLinked()) res = 0.3; + if (target.isTurnedOver()) res += 3.5 * get.threaten(target, player); + return res; }, }, }, @@ -1264,7 +1470,7 @@ const skills = { ai: { result: { target(player, target) { - return get.effect(target, { name: "draw" }, player, player) * (target == player ? 3 : 1) * get.sgn(get.attitude(player, target)); + return Math.min(5, Math.max(2, game.dead.length)); }, }, }, @@ -1284,12 +1490,14 @@ const skills = { ai: { result: { target(player, target) { - return ( - 1 + - Array.from({ length: 13 }) - .map((_, i) => "equip" + parseFloat(i + 1)) - .some(i => target.hasDisabledSlot(i)) - ); + let res = 0.2; + if (target.isHealthy()) res += 0.4; + if ( + Array.from({ length: 5 }) + .map((_, i) => "equip" + parseFloat(i + 1)) + .some(i => target.hasDisabledSlot(i)) + ) res += 0.3; + return res + get.recoverEffect(target, target, target) / 16; }, }, }, @@ -1461,7 +1669,7 @@ const skills = { ai: { result: { target(player, target) { - return -target.countCards("hs") - 1; + return -(target.countCards("hs") + 2) / 3; }, }, }, @@ -1478,7 +1686,7 @@ const skills = { ai: { result: { target(player, target) { - return -target.countCards("hs") - 2; + return -(target.countCards("hs") + 2) / 2; }, }, }, @@ -1495,7 +1703,7 @@ const skills = { ai: { result: { target(player, target) { - return -target.countCards("hs") - 1; + return -target.countCards("hs") - 2; }, }, }, @@ -1511,7 +1719,7 @@ const skills = { ai: { result: { target(player, target) { - return -target.getSkills(null, false).filter(i => get.info(i) && !get.info(i).charlotte).length; + return -target.getSkills(null, false).filter(i => get.info(i) && !get.info(i).charlotte).length * get.threaten(target, player); }, }, }, @@ -1524,7 +1732,13 @@ const skills = { async content(player, target) { target.addTempSkill("sbfangzhu_kill", { player: "phaseEnd" }); }, - ai: {}, + ai: { + result: { + target(player, target) { + return -(target.countCards("hs") + 2) / target.hp; + } + } + }, }, { cost: 3, @@ -1537,7 +1751,7 @@ const skills = { ai: { result: { target(player, target) { - return target.isTurnedOver() ? 1 : -1; + return target.isTurnedOver() ? 3.5 : -3.5; }, }, }, @@ -1908,7 +2122,7 @@ const skills = { }, ai: { effect: { - player_use(card, player, target) { + player(card, player, target) { if (player.getStorage("sbyijue_effect").includes(target)) return "zeroplayertarget"; }, }, @@ -2470,7 +2684,7 @@ const skills = { player .chooseToMove() .set("list", [["你的“星”", cards], ["牌堆顶"]]) - .set("prompt", "观星:点击将牌移动到牌堆顶") + .set("prompt", "观星:点击或拖动将牌移动到牌堆顶") .set("processAI", function (list) { var cards = list[0][1].slice(), player = _status.event.player; @@ -2544,7 +2758,7 @@ const skills = { audio: 2, trigger: { player: ["damageBegin3", "damageBegin4"] }, filter: function (event, player, name) { - if (!player.hasSkill("sbguanxing")) return false; + if (!player.hasSkill("sbguanxing") && !player.hasSkill("jdguanxing")) return false; const num = player.countCards("s", card => card.hasGaintag("sbguanxing")); if (name == "damageBegin3" && !num) return true; if (name == "damageBegin4" && num) return true; @@ -3114,7 +3328,7 @@ const skills = { expose: 0.05, effect: { target: function (card) { - if (card.name == "nanman") return [0, 1]; + if (card.name == "nanman") return [0, 1, 0, 0]; }, }, }, @@ -3879,7 +4093,7 @@ const skills = { ai: { effect: { player_use(card, player, target) { - if (player != target && target && target.group == "qun" && card.name != "tao") return [1, 0.1]; + if (player != target && target && target.group == "qun" && player.hasZhuSkill("sbxueyi") && player.countSkill("sbxueyi") < 2) return [1, 0.6]; }, }, }, @@ -4104,7 +4318,7 @@ const skills = { enable: "phaseUse", usable: 1, group: "sbxuanhuo_rob", - filterTarget: function (card, player, target) { + filterTarget(card, player, target) { return !target.hasMark("sbxuanhuo_mark") && player != target; }, filterCard: true, @@ -4112,33 +4326,33 @@ const skills = { discard: false, lose: false, delay: false, - onremove: function (player) { + onremove(player) { delete player.storage.sbxuanhuo; player.unmarkSkill("sbxuanhuo"); }, - check: function (card) { + check(card) { return 6.5 - get.value(card); }, - content: function () { - "step 0"; - player.give(cards, target); - if (player.storage.sbxuanhuo && player.storage.sbxuanhuo[target.playerid]) delete player.storage.sbxuanhuo[target.playerid]; - "step 1"; - target.addMark("sbxuanhuo_mark"); + async content(event, trigger, player) { + const target = event.targets[0], + cards = event.cards; + await player.give(cards, target); + if (player.storage[event.name] && player.storage[event.name][target.playerid]) delete player.storage[event.name][target.playerid]; + target.addMark(event.name + "_mark"); var history = target.getAllHistory("lose"); if (history.length) { - history[history.length - 1].sbxuanhuo_mark = true; + history[history.length - 1][event.name + "_mark"] = true; } }, - getNum: function (current, skill) { + getNum(current, skill, mark) { var num = 0; var history = current.getAllHistory("lose"); if (history.length) { for (var i = history.length - 1; i >= 0; i--) { var evt = history[i]; - if (evt.sbxuanhuo_mark) break; + if (evt[mark]) break; if (typeof skill == "string") { - if (evt.getParent(2).name == skill) num += evt.cards2.length; + if (evt.getParent(2).name == skill || evt.getParent(3).name == skill) num += evt.cards2.length; } else { var evtx = evt.getParent(), player = skill; @@ -4159,14 +4373,14 @@ const skills = { ai: { order: 9, result: { - target: function (player, target) { + target(player, target) { return -Math.sqrt(Math.max(target.hp, 1)); }, }, }, marktext: "惑", intro: { - content: function (storage, player) { + content(storage, player) { if (!storage || get.is.empty(storage)) return "未得到过牌"; var map = _status.connectMode ? lib.playerOL : game.playerMap; var str = "已得到"; @@ -4191,84 +4405,76 @@ const skills = { trigger: { global: ["gainAfter", "loseAsyncAfter"], }, - forced: true, - locked: false, - direct: true, - filter: function (event, player) { - var evt = event.getParent("phaseDraw"); + filter(event, player, name, target) { + const evt = event.getParent("phaseDraw"); if (evt && evt.name == "phaseDraw") return false; - return game.hasPlayer(current => { - if (!event.getg(current).length || !current.hasMark("sbxuanhuo_mark")) return false; - if (evt && evt.player == current) return false; - if (lib.skill.sbxuanhuo.getNum(current, "sbxuanhuo_rob") >= 5) return false; - return current.hasCard(card => lib.filter.canBeGained(card, current, player), "he"); - }); + if (!event.getg(target).length || !target.hasMark("sbxuanhuo_mark")) return false; + if (evt && evt.player == target) return false; + if (lib.skill.sbxuanhuo.getNum(target, "sbxuanhuo_rob", "sbxuanhuo_mark") >= 5) return false; + return target.hasCard(card => lib.filter.canBeGained(card, target, player), "he"); }, - content: function () { - "step 0"; - var evt = trigger.getParent("phaseDraw"); - var targets = game.filterPlayer(current => { - if (!trigger.getg(current).length || !current.hasMark("sbxuanhuo_mark")) return false; - if (evt && evt.player == current) return false; - if (lib.skill.sbxuanhuo.getNum(current, "sbxuanhuo_rob") >= 5) return false; - return current.hasCard(card => lib.filter.canBeGained(card, current, player), "he"); - }); - event.targets = targets; - "step 1"; - var target = targets.shift(); - player.logSkill("sbxuanhuo", target); - var hs = target.getCards("h", card => lib.filter.canBeGained(card, target, player)); + getIndex(event, player) { + const evt = event.getParent("phaseDraw"); + if (evt && evt.name == "phaseDraw") return false; + return game + .filterPlayer(current => { + if (!event.getg(current).length || !current.hasMark("sbxuanhuo_mark")) return false; + if (evt && evt.player == current) return false; + if (lib.skill.sbxuanhuo.getNum(current, "sbxuanhuo_rob", "sbxuanhuo_mark") >= 5) return false; + return current.hasCard(card => lib.filter.canBeGained(card, current, player), "he"); + }) + .sortBySeat(); + }, + logTarget(event, player, triggername, target) { + return target; + }, + forced: true, + locked: false, + async content(event, trigger, player) { + const target = event.targets[0], + hs = target.getCards("h", card => lib.filter.canBeGained(card, target, player)); if (hs.length) { - player.gain(hs.randomGet(), target, "giveAuto"); + await player.gain(hs.randomGet(), target, "giveAuto"); if (!player.storage.sbxuanhuo) player.storage.sbxuanhuo = {}; - player.storage.sbxuanhuo[target.playerid] = lib.skill.sbxuanhuo.getNum(target, "sbxuanhuo_rob") + 1; + player.storage.sbxuanhuo[target.playerid] = lib.skill.sbxuanhuo.getNum(target, "sbxuanhuo_rob", "sbxuanhuo_mark"); player.markSkill("sbxuanhuo"); } - if (targets.length > 0) event.redo(); }, }, }, }, sbenyuan: { audio: 2, - forced: true, - direct: true, trigger: { player: "phaseZhunbeiBegin" }, - filter: function (event, player) { - return game.hasPlayer(current => current.hasMark("sbxuanhuo_mark")); + filter(event, player, name, target) { + return target?.isIn() && target.hasMark("sbxuanhuo_mark"); }, - content: function () { - "step 0"; - var targets = game.filterPlayer(current => current.hasMark("sbxuanhuo_mark")); - event.targets = targets; - "step 1"; - var target = targets.shift(); - event.target = target; - player.logSkill("sbenyuan", target); - target.removeMark("sbxuanhuo_mark", target.countMark("sbxuanhuo_mark")); - game.players.forEach(current => { - var storage = current.storage.sbxuanhuo; + getIndex(event, player) { + return game.filterPlayer(target => target.hasMark("sbxuanhuo_mark")).sortBySeat(); + }, + logTarget(event, player, triggername, target) { + return target; + }, + forced: true, + async content(event, trigger, player) { + const target = event.targets[0]; + target.clearMark("sbxuanhuo_mark"); + for (const current of game.players) { + const storage = current.storage.sbxuanhuo; if (storage && storage[target.playerid]) delete storage[target.playerid]; if (storage && get.is.empty(storage)) { delete current.storage.sbxuanhuo; current.unmarkSkill("sbxuanhuo"); } - }); - var num = lib.skill.sbxuanhuo.getNum(target, player); + } + const num = lib.skill.sbxuanhuo.getNum(target, player, "sbxuanhuo_mark"); if (num >= 3) { - var cards = player.getCards("he"); - if (!cards.length) event._result = { bool: false }; - else if (cards.length <= 3) event._result = { bool: true, cards: cards }; - else player.chooseCard("恩怨:交给" + get.translation(target) + "三张牌", true, 3, "he"); + const num = Math.min(player.countCards("he"), 3); + if (num) await player.chooseToGive(target, `恩怨:交给${get.translation(target)}${get.cnNumber(num)}张牌`, true, num, "he"); } else { - target.loseHp(); - player.recover(); - event.goto(3); + await target.loseHp(); + await player.recover(); } - "step 2"; - if (result.bool) player.give(result.cards, target); - "step 3"; - if (targets.length) event.goto(1); }, ai: { combo: "sbxuanhuo", @@ -4979,7 +5185,7 @@ const skills = { forced: true, logTarget: "player", filter: function (event, player) { - return player.checkCooperationStatus(event.player, "sbjizhu") && player.hasSkill("sblongdan", null, null, false); + return player.checkCooperationStatus(event.player, "sbjizhu") && ["sblongdan", "jdlongdan"].some(skill => player.hasSkill(skill, null, null, false)); }, content: function () { game.log(player, "和", trigger.player, "的协力成功"); @@ -5061,44 +5267,42 @@ const skills = { sbxieji: { audio: 3, trigger: { player: "phaseZhunbeiBegin" }, - direct: true, - content: function () { - "step 0"; - player.chooseTarget(lib.filter.notMe, get.prompt("sbxieji"), "和一名其他角色进行“协力”").set("ai", function (target) { + logAudio : () => 2, + async cost(event, trigger, player){ + event.result = await player.chooseTarget(lib.filter.notMe, get.prompt("sbxieji"), "和一名其他角色进行“协力”") + .set("ai", function (target) { return get.threaten(target) * Math.sqrt(1 + target.countCards("h")) * (target.isTurnedOver() || target.hasJudge("lebu") ? 0.1 : 1); + }) + .forResult(); + }, + async content(event, trigger, player){ + const target = event.targets[0]; + //保证技能cooperation被移除之后 失去该技能 + player.addAdditionalSkill("cooperation", "sbxieji_effect"); + //选择对方的协击条件 + await player.chooseCooperationFor(target, "sbxieji").set("ai", function (button) { + var base = 0; + switch (button.link) { + case "cooperation_damage": + base = 0.8; + break; + case "cooperation_draw": + base = 0.1; + break; + case "cooperation_discard": + base = 0.1; + break; + case "cooperation_use": + base = 0.1; + break; + } + return base + Math.random(); }); - "step 1"; - if (result.bool) { - var target = result.targets[0]; - player.logSkill("sbxieji", target); - //选择对方的协击条件 - player.chooseCooperationFor(target, "sbxieji").set("ai", function (button) { - var base = 0; - switch (button.link) { - case "cooperation_damage": - base = 0.8; - break; - case "cooperation_draw": - base = 0.1; - break; - case "cooperation_discard": - base = 0.1; - break; - case "cooperation_use": - base = 0.1; - break; - } - return base + Math.random(); - }); - //保证技能cooperation被移除之后 失去该技能 - player.addAdditionalSkill("cooperation", "sbxieji_effect"); - } else event.finish(); - "step 2"; - game.delayx(); + await game.delayx(); }, subSkill: { effect: { - audio: "sbxieji", + audio: "sbxieji3.mp3", charlotte: true, trigger: { global: "phaseJieshuBegin" }, direct: true, @@ -5148,9 +5352,10 @@ const skills = { }, //徐晃 sbduanliang: { - audio: 1, + audio: 4, enable: "phaseUse", usable: 1, + logAudio: () => 1, filterTarget: lib.filter.notMe, content: function () { "step 0"; @@ -5191,9 +5396,18 @@ const skills = { }, }, subSkill: { - true1: { audio: true }, - true2: { audio: true }, - false: { audio: true }, + true1: { + audio: "sbduanliang", + logAudio: () => "sbduanliang2.mp3", + }, + true2: { + audio: "sbduanliang", + logAudio: () => "sbduanliang3.mp3", + }, + false: { + audio: "sbduanliang", + logAudio: () => "sbduanliang4.mp3", + }, }, }, sbshipo: { @@ -5337,9 +5551,10 @@ const skills = { }, //马超 sbtieji: { - audio: 1, + audio: 4, trigger: { player: "useCardToPlayered" }, logTarget: "target", + logAudio: () => 1, filter: function (event, player) { return player != event.target && event.card.name == "sha" && event.target.isIn(); }, @@ -5383,9 +5598,18 @@ const skills = { directHit_ai: true, }, subSkill: { - true1: { audio: true }, - true2: { audio: true }, - false: { audio: true }, + true1: { + audio: "sbtieji", + logAudio: () => "sbtieji2.mp3", + }, + true2: { + audio: "sbtieji", + logAudio: () => "sbtieji3.mp3", + }, + false: { + audio: "sbtieji", + logAudio: () => "sbtieji4.mp3", + }, }, }, //甘宁 @@ -5694,9 +5918,9 @@ const skills = { if (target.hp <= 1) return; if (get.itemtype(cards) != "cards") return; for (var i of cards) { - if (get.name(i, target) == "tao") return [1, 5]; + if (get.name(i, target) == "tao") return [1, 4.5]; } - if (get.value(cards, target) >= 7 + target.getDamagedHp()) return [1, 3]; + if (get.value(cards, target) >= 7 + target.getDamagedHp()) return [1, 2]; return [1, 0.55 + 0.05 * Math.max(0, 1 - target.countMark("sbjianxiong"))]; } }, @@ -5972,7 +6196,7 @@ const skills = { group: "sbguidao_defend", filter: function (event, player) { if (player.countMark("sbguidao") >= 8) return false; - if (event.name == "damage") return event.hasNature() && !player.hasSkill("sbguidao_forbid"); + if (event.name == "damage") return event.hasNature(); return event.name != "phase" || game.phaseNumber == 0; }, content: function () { @@ -6002,11 +6226,10 @@ const skills = { trigger.cancel(); player.removeMark("sbguidao", 2); if (player != _status.currentPhase) { - player.addTempSkill("sbguidao_forbid", { player: "phaseBegin" }); + player.tempBanSkill("sbguidao", { player: "phaseBegin" }); } }, }, - forbid: { charlotte: true }, }, }, sbhuangtian: { @@ -6180,6 +6403,7 @@ const skills = { return 6.5 - get.value(card); }, position: "he", + logAudio: () => 1, group: ["sbjushou_damage", "sbjushou_draw"], content: function () { player.turnOver(); @@ -6193,7 +6417,7 @@ const skills = { }, subSkill: { damage: { - audio: "sbjushou", + audio: "sbjushou2.mp3", trigger: { player: "damageEnd", }, @@ -6216,7 +6440,7 @@ const skills = { event.finish(); return; } - player.logSkill("sbjushou"); + player.logSkill("sbjushou_damage"); if (result.control == "翻面") { player.turnOver(); } else { @@ -6236,14 +6460,14 @@ const skills = { card: card, }) ) - return "zerotarget"; + return 0.1; } }, }, }, }, draw: { - audio: "sbjushou", + audio: "sbjushou3.mp3", trigger: { player: "turnOverAfter" }, forced: true, locked: false, @@ -6322,9 +6546,6 @@ const skills = { audio: 2, enable: "phaseUse", usable: 5, - filter: function (event, player) { - return !player.hasSkill("sbfanjian_ban"); - }, chooseButton: { dialog: function () { return ui.create.dialog("###反间###" + get.translation("sbfanjian_info")); @@ -6401,7 +6622,7 @@ const skills = { target.loseHp(); } else { if (result.index != 2) game.log(target, "猜测", "#g正确"); - player.addTempSkill("sbfanjian_ban"); + player.tempBanSkill("sbfanjian"); } }, ai: { @@ -6424,7 +6645,6 @@ const skills = { }, subSkill: { guessed: { onremove: true, charlotte: true }, - ban: { charlotte: true }, backup: {}, }, ai: { @@ -6853,6 +7073,7 @@ const skills = { }, //孙尚香 sbjieyin: { + audio: 2, trigger: { player: "phaseUseBegin" }, forced: true, locked: false, @@ -6861,6 +7082,7 @@ const skills = { filter: function (event, player) { return game.hasPlayer(current => current.hasMark("sbjieyin_mark")); }, + logAudio: () => 1, content: function () { "step 0"; var targets = game.filterPlayer(current => current.hasMark("sbjieyin_mark")); @@ -6911,7 +7133,7 @@ const skills = { }, subSkill: { fail: { - audio: "sbjieyin", + audio: "sbjieyin2.mp3", trigger: { global: "dieAfter" }, dutySkill: true, forced: true, @@ -6943,7 +7165,7 @@ const skills = { }, marked: { charlotte: true }, init: { - audio: "sbjieyin", + audio: "sbjieyin1.mp3", trigger: { global: "phaseBefore", player: "enterGame", @@ -7289,11 +7511,9 @@ const skills = { sbyangwei: { audio: 3, enable: "phaseUse", - filter: function (event, player) { - return !player.hasSkill("sbyangwei_counter", null, null, false); - }, content: function () { player.draw(2); + player.tempBanSkill("sbyangwei", "forever"); player.addTempSkill("sbyangwei_effect"); player.addSkill("sbyangwei_counter"); }, @@ -7329,7 +7549,10 @@ const skills = { onremove: true, content: function () { if (!player.storage.sbyangwei_counter) player.storage.sbyangwei_counter = true; - else player.removeSkill("sbyangwei_counter"); + else { + player.removeSkill("sbyangwei_counter"); + delete player.storage[`temp_ban_sbyangwei`]; + } }, }, }, @@ -7647,7 +7870,7 @@ const skills = { .set("complexSelect", true) .set("filterTarget", function (card, player, target) { if (target != _status.event.sourcex && !ui.selected.targets.includes(_status.event.sourcex)) return false; - return lib.filter.targetEnabled.apply(this, arguments); + return lib.filter.filterTarget.apply(this, arguments); }) .set("sourcex", player) .set("addCount", false); diff --git a/character/sb/sort.js b/character/sb/sort.js index 4430fb3b53..f660d32d6f 100644 --- a/character/sb/sort.js +++ b/character/sb/sort.js @@ -1,6 +1,6 @@ const characterSort = { sb_zhi: ["sb_sunquan", "sb_zhouyu", "sb_zhangjiao", "sb_caocao", "sb_zhenji", "sb_liubei", "sb_daqiao", "sb_liubiao", "sb_sp_zhugeliang", "sb_xunyu"], - sb_shi: ["sb_xuhuang", "sb_machao", "sb_fazheng", "sb_chengong", "sb_diaochan", "sb_pangtong", "sb_zhanghe", "sb_caopi", "sb_ganning", "sb_handang"], + sb_shi: ["sb_xuhuang", "sb_machao", "sb_fazheng", "sb_chengong", "sb_diaochan", "sb_pangtong", "sb_zhanghe", "sb_caopi", "sb_ganning", "sb_handang", "sb_jiaxu"], sb_tong: ["liucheng", "sp_yangwan", "sb_xiahoushi", "sb_zhangfei", "sb_zhaoyun", "sb_sunce", "sb_zhurong", "sb_xiaoqiao", "sb_xiahoudun"], sb_yu: ["sb_yujin", "sb_lvmeng", "sb_huangzhong", "sb_huanggai", "sb_zhouyu", "sb_caoren", "sb_yl_luzhi", "sb_huangyueying", "sb_luxun"], sb_neng: ["sb_huaxiong", "sb_sunshangxiang", "sb_jiangwei", "sb_yuanshao", "sb_menghuo", "sb_guanyu", "sb_gaoshun", "sb_gongsunzan"], diff --git a/character/sb/translate.js b/character/sb/translate.js index d07d355724..20ae3a0a2a 100644 --- a/character/sb/translate.js +++ b/character/sb/translate.js @@ -263,7 +263,7 @@ const translates = { sb_xiahoudun: "谋夏侯惇", sb_xiahoudun_prefix: "谋", sbganglie: "刚烈", - sbganglie_info: "出牌阶段限一次。你可以选择任意名本局游戏对你造成过伤害且你以此法选择过其的次数小于2的角色,你对其造成2点伤害。", + sbganglie_info: "出牌阶段限一次。你可以选择一名本局游戏对你造成过伤害且你未以此法选择过的角色,你对其造成2点伤害。", sbqingjian: "清俭", sbqingjian_info: "①当有一张牌不因使用而进入弃牌堆后,若你的“清俭”数小于X,你将此牌置于你的武将牌上,称为“清俭”(X为你的体力值-1,且至少为1)。②出牌阶段结束时,你将所有“清俭”分配给任意角色。", sb_gaoshun: "谋高顺", @@ -282,14 +282,26 @@ const translates = { sb_gongsunzan: "谋公孙瓒", sb_gongsunzan_prefix: "谋", sbyicong: "义从", - sbyicong_info: "蓄力技(2/4)。①一轮游戏开始时,你可以消耗任意点蓄力值并选择一项:⒈你于本轮内至其他角色的距离-X,令系统选择牌堆中的一张【杀】;⒉其他角色于本轮内至你的距离+X,令系统选择牌堆中的一张【闪】(X为你消耗的蓄力值)。然后若你的“扈”数小于4,你将系统选择的牌置于武将牌上,称为“扈”。②你可以将“扈”如手牌般使用或打出。", + sbyicong_info: "蓄力技(2/4)。①一轮游戏开始时,你可以消耗任意点蓄力值并选择一项:⒈你于本轮内至其他角色的距离-1,令系统选择牌堆中的X张【杀】;⒉其他角色于本轮内至你的距离+1,令系统选择牌堆中的X张【闪】(X为你消耗的蓄力值)。然后若你的“扈”数小于4,你将系统选择的牌置于武将牌上,称为“扈”。②你可以将“扈”如手牌般使用或打出。", sbqiaomeng: "趫猛", - sbqiaomeng_info: "当你使用【杀】造成伤害后,若你有〖义从〗,你可以选择一项:⒈弃置受伤角色区域里的一张牌并摸一张牌;⒉获得2点蓄力值。", + sbqiaomeng_info: "当你使用【杀】造成伤害后,若你有〖义从〗,你可以选择一项:⒈弃置受伤角色区域里的一张牌并摸一张牌;⒉获得3点蓄力值。", sb_luxun: "谋陆逊", sbqianxun: "谦逊", sbqianxun_info: "当一张锦囊牌对你生效时,若此牌名未记录且你不是使用者,则你记录之,然后可将至多X张牌置于你的武将牌上,此回合结束时获得(X为“谦逊”记录的牌名数且至多为5)。出牌阶段开始时,你可以移去一个记录的牌名,若为普通锦囊牌则可以视为使用此牌。", sblianying: "连营", sblianying_info: "其他角色的回合结束时,你可以观看牌堆顶的X张牌,然后将这些牌交给任意角色(X为你本回合失去的牌数,至多为5)。", + sb_jiaxu: "谋贾诩", + sb_jiaxu_prefix: "谋", + sbwansha: "完杀", + sbwansha_info: "①你的回合内,不处于濒死状态的其他角色不能使用【桃】。②一名角色进入濒死状态时,你可以观看其手牌并选择其中零至两张牌,然后其选择一项:1.你将这些牌分配给任意名不为其的角色;2.其弃置除这些牌以外的牌。", + sbwansha_rewrite: "完杀·改", + sbwansha_rewrite_info: "①你的回合内,不处于濒死状态的其他角色不能使用【桃】。②一名角色进入濒死状态时,你可以观看其手牌并选择其区域内零至两张牌,然后其选择一项:1.你将这些牌分配给任意名不为其的角色;2.其弃置除这些牌以外的牌。", + sbluanwu: "乱武", + sbluanwu_info: "限定技,出牌阶段,你可令所有其他角色依次选择一项:①对距离最近(或之一)的角色使用一张【杀】;②失去1点体力。一名角色因此失去体力后,你可以修改〖完杀〗或者〖帷幕〗。", + sbweimu: "帷幕", + sbweimu_info: "锁定技。当你成为黑色锦囊牌的目标时,取消之。", + sbweimu_rewrite: "帷幕·改", + sbweimu_rewrite_info: "锁定技。①当你成为黑色锦囊牌的目标时,取消之。②每轮开始时,若你上一轮成为其他角色使用牌的目标的次数不大于2,你从弃牌堆中随机获得一张黑色锦囊牌或防具牌。", }; export default translates; diff --git a/character/sb/voices.js b/character/sb/voices.js index ee62dd2386..3a193ea1d2 100644 --- a/character/sb/voices.js +++ b/character/sb/voices.js @@ -1,4 +1,15 @@ export default { + "#sbwansha1": "世人皆行殊途,于死亦有同归!", + "#sbwansha2": "九幽泉下,是你最好的归宿。", + "#sbluanwu_jiaxu1": "降则任人鱼肉,竭战或可保生!", + "#sbluanwu_jiaxu2": "一将功成需万骨,何妨多添此一城!", + "#sbluanwu_jiaxu3": "人之道,损不足以奉有余!", + "#sbluanwu_jiaxu4": "寒烟起于朽木,白骨亦可生花!", + "#sbweimu1": "执棋之人,不可入局者共论!", + "#sbweimu2": "世有千万门法,与我均无纠葛。", + "#sbweimu3": "方圆之间,参透天地万物心!", + "#sbweimu4": "帐前独知形表,幕后可见人心!", + "#sb_jiaxu:die": "踽踽黄泉,与吾行世又有何异?", "#sbqianxun1": "虽有戈矛之刺,不如恭俭之利也。", "#sbqianxun2": "贤者任重而行恭,知者功大而辞顺。", "#sblianying1": "蜀营连绵百里,正待吾燎原一炬!", @@ -83,13 +94,13 @@ export default { "#sbxiaoji1": "吾之所通,何止十八般兵刃!", "#sbxiaoji2": "既如此,就让尔等见识一番!", "#sb_sunshangxiang:die": "此去一别,竟无再见之日……", - "#sbzhiheng1": "稳坐山河,但观世变。", - "#sbzhiheng2": "身处惊涛,尤可弄潮。", - "#sbtongye1": "上下一心,君臣同志。", - "#sbtongye2": "胸有天下者,必可得其国。", - "#sbjiuyuan1": "汝救护有功,吾必当厚赐。", - "#sbjiuyuan2": "诸位将军,快快拦住贼军!", - "#sb_sunquan:die": "风急举发,命不久矣……", + "#sbzhiheng1": "待孤熟虑一番,再行定夺吧。", + "#sbzhiheng2": "江东兴亡,尽在孤的此番考量之中。", + "#sbtongye1": "有众卿相佐,何忧曹贼万众!", + "#sbtongye2": "广纳贤才,不辱父兄基业!", + "#sbjiuyuan1": "有爱卿这等良将,孤有何所惧。", + "#sbjiuyuan2": "幸有爱卿相助啊。", + "#sb_sunquan:die": "仲谋竟然辜负了……父兄所托……", "#sbkurou1": "既不能破,不如依张子布之言,投降便罢!", "#sbkurou2": "周瑜小儿!破曹不得,便欺吾三世老臣乎?", "#sbzhaxiang1": "江东六郡之卒,怎敌丞相百万雄师!", @@ -136,8 +147,14 @@ export default { "#sbfenwei2": "袭军挫阵,奋江东之威!", "#sb_ganning:die": "蛮将休得猖狂!呃啊!", "#sbtieji1": "厉马秣兵,只待今日!", + "#sbtieji2": "敌军防备空虚,出击直取敌营!", + "#sbtieji3": "敌军早有防备,先行扰阵疲敌!", + "#sbtieji4": "全军速撤回营,以期再觅良机!", "#sb_machao:die": "父兄妻儿具丧,吾有何面目活于世间……", "#sbduanliang1": "常读兵法,终有良策也!", + "#sbduanliang2": "烧敌粮草,救主于危急!", + "#sbduanliang3": "敌现混乱之机,我军可长驱直入!", + "#sbduanliang4": "敌即识破吾计,则断不可行矣。", "#sbshipo1": "已向尔等陈明利害,奉劝尔等早日归降!", "#sbshipo2": "此时归降或可封赏,即至城破必斩无赦!", "#sb_xuhuang:die": "为主效劳,何畏生死……", diff --git a/character/shenhua/characterReplace.js b/character/shenhua/characterReplace.js index a7dd2561e3..b7f5801d7c 100644 --- a/character/shenhua/characterReplace.js +++ b/character/shenhua/characterReplace.js @@ -1,37 +1,37 @@ const characterReplaces = { caoren: ["caoren", "old_caoren", "sb_caoren", "new_caoren", "star_caoren"], - sp_caoren: ["sp_caoren", "jsp_caoren"], + sp_caoren: ["sp_caoren", "jsp_caoren", "drag_caoren"], xiahouyuan: ["re_xiahouyuan", "ol_xiahouyuan", "xiahouyuan"], - huangzhong: ["re_huangzhong", "ol_huangzhong", "sb_huangzhong", "huangzhong", "jsrg_huangzhong", "yj_huangzhong", "wuhujiang"], + huangzhong: ["re_huangzhong", "ol_huangzhong", "sb_huangzhong", "huangzhong", "jsrg_huangzhong", "yj_huangzhong", "wuhujiang", "ty_huangzhong"], weiyan: ["re_weiyan", "ol_weiyan", "weiyan", "huan_weiyan"], zhoutai: ["zhoutai", "xin_zhoutai", "old_zhoutai"], - xiaoqiao: ["xiaoqiao", "ol_xiaoqiao", "re_xiaoqiao", "sb_xiaoqiao", "old_xiaoqiao"], + xiaoqiao: ["xiaoqiao", "ol_xiaoqiao", "re_xiaoqiao", "sb_xiaoqiao", "old_xiaoqiao", "jd_sb_xiaoqiao", "yue_xiaoqiao"], yuji: ["xin_yuji", "re_yuji", "yuji"], zhangjiao: ["sp_zhangjiao", "re_zhangjiao", "sb_zhangjiao", "jsrg_zhangjiao", "zhangjiao"], dianwei: ["dianwei", "ol_dianwei", "re_dianwei", "dc_sb_dianwei"], xunyu: ["xunyu", "ol_xunyu", "re_xunyu", "sb_xunyu"], - sp_zhugeliang: ["sp_zhugeliang", "ol_sp_zhugeliang", "re_sp_zhugeliang", "sb_sp_zhugeliang"], - pangtong: ["pangtong", "ol_pangtong", "re_pangtong", "ol_sb_pangtong", "sb_pangtong"], + sp_zhugeliang: ["sp_zhugeliang", "ol_sp_zhugeliang", "re_sp_zhugeliang", "sb_sp_zhugeliang", "jd_sb_sp_zhugeliang"], + pangtong: ["pangtong", "ol_pangtong", "re_pangtong", "ol_sb_pangtong", "sb_pangtong", "jd_sb_pangtong"], re_jsp_pangtong: ["re_jsp_pangtong", "jsrg_pangtong", "sp_pangtong"], taishici: ["taishici", "re_taishici", "ol_sb_taishici"], - re_yuanshao: ["re_yuanshao", "ol_yuanshao", "xin_yuanshao", "ol_sb_yuanshao", "star_yuanshao", "sb_yuanshao"], + re_yuanshao: ["re_yuanshao", "ol_yuanshao", "xin_yuanshao", "ol_sb_yuanshao", "star_yuanshao", "sb_yuanshao", "jd_sb_yuanshao"], pangde: ["re_pangde", "ol_pangde", "pangde"], yanwen: ["yanwen", "ol_yanwen", "re_yanwen"], caopi: ["caopi", "re_caopi", "ps_caopi", "sb_caopi"], - xuhuang: ["re_xuhuang", "ol_xuhuang", "sb_xuhuang", "xuhuang"], - menghuo: ["menghuo", "re_menghuo", "sb_menghuo", "tw_menghuo", "sp_menghuo", "dc_sp_menghuo"], + xuhuang: ["re_xuhuang", "ol_xuhuang", "sb_xuhuang", "xuhuang", "jd_sb_xuhuang"], + menghuo: ["menghuo", "re_menghuo", "sb_menghuo", "tw_menghuo", "sp_menghuo", "dc_sp_menghuo", "jd_sb_menghuo"], zhurong: ["zhurong", "ol_zhurong", "re_zhurong", "sb_zhurong"], - sunjian: ["sunjian", "ol_sunjian", "re_sunjian", "tw_ol_sunjian", "star_sunjian"], - jiaxu: ["jiaxu", "re_jiaxu", "ns_jiaxu", "ps_jiaxu", "sp_jiaxu", "dc_sp_jiaxu", "dc_sb_jiaxu"], + sunjian: ["sunjian", "ol_sunjian", "re_sunjian", "tw_ol_sunjian", "star_sunjian", "jx_sunjian", "ol_sb_sunjian"], + jiaxu: ["jiaxu", "re_jiaxu", "ns_jiaxu", "ps_jiaxu", "dc_sb_jiaxu", "sb_jiaxu"], dongzhuo: ["dongzhuo", "ol_dongzhuo", "re_dongzhuo", "star_dongzhuo", "jsrg_dongzhuo", "sp_dongzhuo", "yj_dongzhuo"], dengai: ["dengai", "ol_dengai", "re_dengai"], sp_ol_zhanghe: ["sp_ol_zhanghe", "yj_zhanghe", "sp_zhanghe", "jsrg_zhanghe", "huan_zhanghe"], - jiangwei: ["jiangwei", "ol_jiangwei", "re_jiangwei", "ol_sb_jiangwei", "sb_jiangwei", "jsrg_jiangwei", "huan_jiangwei"], - liushan: ["liushan", "ol_liushan", "re_liushan"], + jiangwei: ["jiangwei", "ol_jiangwei", "re_jiangwei", "ol_sb_jiangwei", "sb_jiangwei", "jsrg_jiangwei", "huan_jiangwei", "jd_sb_jiangwei"], + liushan: ["liushan", "ol_liushan", "re_liushan", "huan_liushan"], sunce: ["sunce", "re_sunce", "re_sunben", "sb_sunce", "dc_sunce"], zhangzhang: ["zhangzhang", "ol_zhangzhang", "re_zhangzhang", "tw_zhangzhao", "tw_zhanghong", "star_zhangzhao"], zuoci: ["zuoci", "re_zuoci"], - caiwenji: ["caiwenji", "ol_caiwenji", "re_caiwenji"], + caiwenji: ["caiwenji", "ol_caiwenji", "re_caiwenji", "yue_caiwenji"], xuyou: ["xuyou", "sp_xuyou", "jsrg_xuyou", "yj_xuyou", "junk_xuyou"], guanqiujian: ["guanqiujian", "re_guanqiujian", "tw_guanqiujian", "mb_sp_guanqiujian", "old_guanqiujian"], chendao: ["chendao", "ns_chendao", "old_chendao"], @@ -40,6 +40,7 @@ const characterReplaces = { zhanghe: ["zhanghe", "re_zhanghe", "sb_zhanghe"], yl_luzhi: ["yl_luzhi", "jsrg_yl_luzhi", "sb_yl_luzhi", "tw_yl_luzhi"], sunliang: ["sunliang", "xin_sunliang"], + zhoufei: ["zhoufei", "yue_zhoufei"], }; export default characterReplaces; diff --git a/character/shenhua/skill.js b/character/shenhua/skill.js index 90f67bb63e..d386d95f2e 100644 --- a/character/shenhua/skill.js +++ b/character/shenhua/skill.js @@ -42,7 +42,7 @@ const skills = { use = false; const cardx = get.autoViewAs({ name: "tiesuo" }, [card]); if (event.type == "phase" && player.canRecast(card)) recast = true; - if (game.checkMod(card, player, "unchanged", "cardEnabled2", player) !== false) { + if (card && game.checkMod(card, player, "unchanged", "cardEnabled2", player) !== false) { if (backup.filterCard(cardx, player, event)) use = true; } if (!use) return [0, 0]; @@ -62,7 +62,7 @@ const skills = { use = false; const cardx = get.autoViewAs({ name: "tiesuo" }, [card]); if (event.type == "phase" && player.canRecast(card)) recast = true; - if (game.checkMod(card, player, "unchanged", "cardEnabled2", player) !== false) { + if (card && game.checkMod(card, player, "unchanged", "cardEnabled2", player) !== false) { if (backup.filterCard(cardx, player, event)) use = true; } if (recast && selected == 0) { @@ -231,7 +231,7 @@ const skills = { async content(event, trigger, player) { const target = event.targets[0]; await game.asyncDraw([player, target].sortBySeat()); - await game.asyncDelayx(); + await game.delayx(); let num = player.getExpansions("olkongsheng").length; let check = player => { if (!player.isIn() || player.isHealthy()) return false; @@ -332,7 +332,7 @@ const skills = { const target = event.targets[0]; await player.discard(event.cards); await target.chooseToDiscard("he", true); - await game.asyncDelayx(); + await game.delayx(); const num = player.getExpansions("olkongsheng").length; const check = player => { if (!player.isIn() || player.isHealthy()) return false; @@ -429,13 +429,13 @@ const skills = { filter(event, player) { return ( player.getExpansions("olkongsheng").filter(function (card) { - return get.type(card, false) != "equip"; + return get.type(card, null, false) != "equip"; }).length > 0 ); }, async content(event, trigger, player) { let cards = player.getExpansions("olkongsheng").filter(function (card) { - return get.type(card, false) != "equip"; + return get.type(card, null, false) != "equip"; }); if (cards.length) await player.gain(cards, "gain2"); cards = player.getExpansions("olkongsheng"); @@ -941,7 +941,7 @@ const skills = { }, ai: { effect: { - target_use(card, player, target) { + target(card, player, target) { let hs = player.getCards("h", i => i !== card && (!card.cards || !card.cards.includes(i))), num = player.getCardUsable("sha"); if ((card.name !== "sha" && card.name !== "juedou") || hs.length < target.countCards("h")) return 1; @@ -1150,7 +1150,7 @@ const skills = { discard: false, lose: false, delay: false, - prompt: "将一张装备牌置入弃牌堆并摸一张牌", + prompt: "重铸一张装备牌", ai: { order: 10, result: { @@ -1626,7 +1626,7 @@ const skills = { player.addTempSkill("kongsheng_ai", "kongsheng2After"); while (true) { const cards = player.getExpansions("kongsheng2").filter(function (i) { - return get.type(i, false) == "equip" && player.hasUseTarget(i); + return get.type(i, null, false) == "equip" && player.hasUseTarget(i); }); if (cards.length > 0) { let [card] = cards; @@ -1673,7 +1673,7 @@ const skills = { trigger.player.addTempSkill("nzry_juzhany"); player.changeZhuanhuanji("nzry_juzhan"); player.addTempSkill("nzry_juzhanx"); - await game.asyncDelayx(); + await game.delayx(); }, }, 2: { @@ -2045,7 +2045,7 @@ const skills = { ai: { effect: { player(card, player, target) { - if (get.tag(card, "damage") && !player.inRangeOf(target)) return "zerotarget"; + if (get.tag(card, "damage") && !player.inRangeOf(target)) return "zeroplayertarget"; }, }, }, @@ -2229,6 +2229,23 @@ const skills = { }, nzry_shicai: { audio: "nzry_shicai_2", + locked: false, + mod: { + aiOrder(player, card, num) { + if (num <= 0 || player.nzry_shicai_aiOrder || get.itemtype(card) !== "card" || player.hasSkillTag("abnormalDraw")) return num; + let type = get.type2(card, false); + if ( + player.hasHistory("useCard", evt => { + return get.type2(evt.card, false) == type; + }) + ) + return num; + player.nzry_shicai_aiOrder = true; + let val = player.getUseValue(card, true, true); + delete player.nzry_shicai_aiOrder; + return 20 * val; + }, + }, trigger: { player: ["useCardAfter", "useCardToTargeted"] }, prompt2(event, player) { const cards = event.cards.filterInD("oe"); @@ -2255,7 +2272,7 @@ const skills = { check(event, player) { if (get.type(event.card) == "equip") { if (get.subtype(event.card) == "equip6") return true; - if (get.equipResult(player, player, event.card.name) <= 0) return true; + if (get.equipResult(player, player, event.card) <= 0) return true; const eff1 = player.getUseValue(event.card); const subtype = get.subtype(event.card); return ( @@ -2323,6 +2340,12 @@ const skills = { async content(event, trigger, player) { trigger.bottom = true; }, + ai: { + abnormalDraw: true, + skillTagFilter: function (player, tag, arg) { + if (tag === "abnormalDraw") return !arg || arg === "bottom"; + }, + }, }, nzry_mingren: { audio: "nzry_mingren_1", @@ -2562,7 +2585,10 @@ const skills = { player.changeZhuanhuanji("nzry_shenshi"); await player.give(event.cards, target); await target.damage("nocard"); - if (target.isIn()) return; + if (!game.getGlobalHistory("everything", evt => { + if (evt.name != "die" || evt.player != target) return false; + return evt.reason?.getParent() == event; + }).length) return; const { result } = await player .chooseTarget("令一名角色将手牌摸至四张", function (card, player, target) { return target.countCards("h") < 4; @@ -2660,13 +2686,6 @@ const skills = { } } }, - ai: { - effect: { - target(card, player, target) { - if (card.name == "guiyoujie") return [0, 1]; - }, - }, - }, }, xinjiewei: { audio: 2, @@ -2811,7 +2830,7 @@ const skills = { let current = target; let num1 = 0; let num2 = 0; - await game.asyncDelay(); + await game.delay(); while (dialog.buttons.length) { let card; if (dialog.buttons.length > 1) { @@ -2870,7 +2889,7 @@ const skills = { num2++; current = target; } - await game.asyncDelay(2); + await game.delay(2); } if (!_status.connectMode) { game.log(targets[0], "获得了" + get.cnNumber(num1) + "张牌"); @@ -3142,7 +3161,7 @@ const skills = { audioname: ["re_weiyan", "ol_weiyan"], trigger: { source: "damageSource" }, filter(event, player) { - return event.kuangguCheck && event.num > 0; + return event.xinkuangguCheck && event.num > 0; }, getIndex(event, player, triggername) { return event.num; @@ -3172,7 +3191,18 @@ const skills = { event.result = { bool: true }; // 好像在content里面不能中断getIndex喵 }, async content(event, trigger, player) {}, - group: "kuanggu_check", + }, + _xinkuanggu_check: { + charlotte: true, + trigger: { source: "damage" }, + filter(event, player) { + return get.distance(player, event.player) <= 1; + }, + firstDo: true, + silent: true, + content() { + trigger.xinkuangguCheck = true; + }, }, xinliegong: { mod: { @@ -3241,13 +3271,10 @@ const skills = { async content(event, trigger, player) { const target = event.target; const { result } = await target - .chooseToUse( - function (card, player, event) { - if (get.name(card) != "sha") return false; - return lib.filter.filterCard.apply(this, arguments); - }, - "挑衅:对" + get.translation(player) + "使用一张杀,或令其弃置你的一张牌" - ) + .chooseToUse(function (card, player, event) { + if (get.name(card) != "sha") return false; + return lib.filter.filterCard.apply(this, arguments); + }, "挑衅:对" + get.translation(player) + "使用一张杀,或令其弃置你的一张牌") .set("targetRequired", true) .set("complexSelect", true) .set("filterTarget", function (card, player, target) { @@ -3324,7 +3351,7 @@ const skills = { }, ai: { effect: { - target_use(card, player, target, current) { + target(card, player, target, current) { if (card.name == "sha" && get.attitude(player, target) < 0) { if (_status.event.name == "xiangle") return; if (get.attitude(player, target) > 0 && current < 0) return "zerotarget"; @@ -3370,7 +3397,7 @@ const skills = { }); }) .set("fang", fang) - .setHiddenSkill(event.name) + .setHiddenSkill(event.name.slice(0,-5)) .forResult(); }, async content(event, trigger, player) { @@ -3534,7 +3561,7 @@ const skills = { player.line(result.targets, "green"); if (!result.targets.length) return; await player.gainMultiple(result.targets); - await game.asyncDelay(); + await game.delay(); } }, ai: { threaten: 3 }, @@ -4404,8 +4431,7 @@ const skills = { const { promise, resolve } = Promise.withResolvers(); event.player.send(chooseButton, event.player, cards, event.logged); event.player.wait(async result => { - if(result =="ai") - result = await switchToAuto(); + if (result == "ai") result = await switchToAuto(); resolve(result); }); // 不再 game.resume 防止 game.loop 被重复执行 @@ -4498,7 +4524,7 @@ const skills = { ai: { effect: { target(card, player, target) { - if (card.name == "nanman") return 0; + if (card.name == "nanman") return "zeroplayertarget"; }, }, }, @@ -4581,7 +4607,7 @@ const skills = { ai: { effect: { target(card) { - if (card.name == "nanman") return [0, 1]; + if (card.name == "nanman") return [0, 1, 0, 0]; }, }, }, @@ -4973,7 +4999,7 @@ const skills = { audioname2: { re_sunyi: "gzyinghun_re_sunyi", tw_ol_sunjian: "yinghun_ol_sunjian", - boss_sunce: "yinghun_sunce" + boss_sunce: "yinghun_sunce", }, mod: { aiOrder(player, card, num) { @@ -5004,7 +5030,7 @@ const skills = { } return 1; }) - .setHiddenSkill(event.name) + .setHiddenSkill(event.name.slice(0,-5)) .forResult(); }, async content(event, trigger, player) { @@ -5094,7 +5120,7 @@ const skills = { } return 1; }) - .setHiddenSkill(event.name) + .setHiddenSkill(event.name.slice(0,-5)) .forResult(); }, async content(event, trigger, player) { @@ -5210,7 +5236,7 @@ const skills = { return false; }, filter(event, player) { - return !player.isMinHp() && !player.hasSkill("rejiuchi_air") && !player.hasSkill("oljiuchi_air"); + return !player.isMinHp(); }, async content(event, trigger, player) { const control = await player @@ -5269,6 +5295,9 @@ const skills = { luanwu: { audio: 2, audioname: ["re_jiaxu"], + audioname2: { + "sb_jiaxu": "sbluanwu_jiaxu", + }, unique: true, enable: "phaseUse", limited: true, @@ -5281,7 +5310,7 @@ const skills = { multitarget: true, multiline: true, async content(event, trigger, player) { - player.awakenSkill("luanwu"); + player.awakenSkill(event.name); const currented = [player]; let current = player.next; do { @@ -5316,7 +5345,7 @@ const skills = { .forResultBool(); if (!bool) await current.loseHp(); current = current.next; - } while (!currented.includes(current) && !void (await game.asyncDelay(0.5))); + } while (!currented.includes(current) && !void (await game.delay(0.5))); }, ai: { order: 1, @@ -5387,7 +5416,7 @@ const skills = { if (get.color(event.card) != "black") return false; return (event.card.name == "nanman" && player != event.player) || (event.card.name == "wanjian" && player != event.player) || (event.card.name == "taoyuan" && player.hp < player.maxHp) || event.card.name == "wugu"; }, - async content() { }, + async content() {}, mod: { targetEnabled(card) { if ((get.type(card) == "trick" || get.type(card) == "delay") && get.color(card) == "black") return false; @@ -5505,6 +5534,7 @@ const skills = { niepan: { audio: 2, audioname: ["re_pangtong"], + audioname2: { sb_pangtong: "sbniepan" }, unique: true, enable: "chooseToUse", mark: true, @@ -5519,7 +5549,7 @@ const skills = { if (event.type == "dying") { if (player != event.dying) return false; return true; - } else if (event.parent.name == "phaseUse") { + } else if (event.getParent().name == "phaseUse") { return true; } return false; @@ -5558,6 +5588,7 @@ const skills = { }, oldniepan: { audio: "niepan", + audioname2: { sb_pangtong: "sbniepan" }, unique: true, enable: "chooseToUse", mark: true, @@ -5750,14 +5781,61 @@ const skills = { }, }, qiangxix: { - inherit: "reqiangxi", - audioname: ["boss_lvbu3"], audio: "qiangxi", + audioname: ["boss_lvbu3"], + mod: { + aiOrder(player, card, num) { + if (player.getEquips(1).length || get.subtype(card, player) !== "equip1" || !player.hasSkillTag("noe")) return num; + return 10; + }, + }, + enable: "phaseUse", usable: 2, - filterTarget(card, player, target) { - if (player == target) return false; - if (target.hasSkill("reqiangxi_off")) return false; - return true; + locked: false, + filter: function (event, player) { + if (player.hp < 1 && !player.hasCard(card => lib.skill.qiangxix.filterCard(card), "he")) return false; + return game.hasPlayer(current => lib.skill.qiangxix.filterTarget(null, player, current)); + }, + filterCard: function (card) { + return get.subtype(card) == "equip1"; + }, + position: "he", + filterTarget: function (card, player, target) { + if (target == player) return false; + var stat = player.getStat()._qiangxix; + return !stat || !stat.includes(target); + }, + selectCard: function () { + if (_status.event.player.hp < 1) return 1; + return [0, 1]; + }, + content: function () { + var stat = player.getStat(); + if (!stat._qiangxix) stat._qiangxix = []; + stat._qiangxix.push(target); + if (!cards.length) player.loseHp(); + target.damage("nocard"); + }, + ai: { + damage: true, + order: 8, + result: { + player: function (player, target) { + if (ui.selected.cards.length) return 0; + if (player.hp >= target.hp) return -0.9; + if (player.hp <= 2) return -10; + return get.effect(player, { name: "losehp" }, player, player); + }, + target: function (player, target) { + if (!ui.selected.cards.length) { + if (player.hp < 2) return 0; + if (player.hp == 2 && target.hp >= 2) return 0; + if (target.hp > player.hp) return 0; + } + return get.damageEffect(target, player, target); + }, + }, + threaten: 1.5, }, }, qiangxi: { @@ -6192,7 +6270,7 @@ const skills = { ai: { useShan: true, effect: { - target(card, player, target, current) { + target_use(card, player, target, current) { if ( get.tag(card, "respondShan") && !player.hasSkillTag( @@ -6379,13 +6457,6 @@ const skills = { await player.draw(3); await player.turnOver(); }, - ai: { - effect: { - target(card, player, target) { - if (card.name == "guiyoujie") return [0, 1]; - }, - }, - }, }, moon_jushou: { audio: "xinjushou", @@ -6397,13 +6468,6 @@ const skills = { await player.draw(); await player.turnOver(); }, - ai: { - effect: { - target(card, player, target) { - if (card.name == "guiyoujie") return [0, 1]; - }, - }, - }, }, liegong: { audio: 2, @@ -6448,20 +6512,17 @@ const skills = { async content(event, trigger, player) { await player.recover(trigger.num); }, - group: "kuanggu_check", - subSkill: { - check: { - charlotte: true, - trigger: { source: "damage" }, - filter(event, player) { - return get.distance(player, event.player) <= 1; - }, - firstDo: true, - silent: true, - content() { - trigger.kuangguCheck = true; - }, - }, + }, + _kuanggu_check: { + charlotte: true, + trigger: { source: "damage" }, + filter(event, player) { + return get.distance(player, event.player) <= 1; + }, + firstDo: true, + silent: true, + content() { + trigger.kuangguCheck = true; }, }, tianxiang: { @@ -6596,7 +6657,7 @@ const skills = { prompt: get.prompt("retianxiang"), prompt2: lib.translate.retianxiang_info, }) - .setHiddenSkill(event.name) + .setHiddenSkill(event.name.slice(0,-5)) .forResult(); }, async content(event, trigger, player) { @@ -7149,7 +7210,7 @@ const skills = { preHidden: true, line: "thunder", async cost(event, trigger, player) { - const next = player.chooseTarget(get.prompt2("leiji")).setHiddenSkill(event.name); + const next = player.chooseTarget(get.prompt2("leiji")).setHiddenSkill(event.name.slice(0,-5)); next.ai = function (target) { if (target.hasSkill("hongyan")) return 0; return get.damageEffect(target, _status.event.player, _status.event.player, "thunder"); @@ -7174,7 +7235,7 @@ const skills = { mingzhi: false, useShan: true, effect: { - target(card, player, target, current) { + target_use(card, player, target, current) { if ( get.tag(card, "respondShan") && !player.hasSkillTag( @@ -7258,7 +7319,7 @@ const skills = { trigger.player.judging[0] = event.cards[0]; trigger.orderingCards.addArray(event.cards); game.log(trigger.player, "的判定牌改为", event.cards[0]); - await game.asyncDelay(2); + await game.delay(2); }, ai: { rejudge: true, @@ -7630,12 +7691,12 @@ const skills = { target.popup("不质疑", "wood"); } } - await game.asyncDelayx(); + await game.delayx(); game.broadcastAll(function (onEnd) { _status.event.onEnd01 = onEnd; if (_status.guhuoNode) _status.guhuoNode.listenTransition(onEnd, 300); }, event.onEnd01); - await game.asyncDelay(2); + await game.delay(2); if (!event.betrayer) return; if (event.fake) { event.betrayer.popup("质疑正确", "wood"); @@ -7647,7 +7708,7 @@ const skills = { event.betrayer.popup("质疑错误", "fire"); await event.betrayer.addSkills("chanyuan"); } - await game.asyncDelay(2); + await game.delay(2); if (event.fake) game.broadcastAll(() => ui.clear()); // game.broadcastAll(ui.clear); 原来的代码抽象喵 }, }, @@ -7660,7 +7721,7 @@ const skills = { player.removeSkillBlocker(skill); }, skillBlocker(skill, player) { - return skill != "chanyuan" && skill != "rechanyuan" && !lib.skill[skill].charlotte && player.hp == 1; + return skill != "chanyuan" && skill != "rechanyuan" && !lib.skill[skill].charlotte && !lib.skill[skill].persevereSkill && player.hp == 1; }, mark: true, intro: { diff --git a/character/shiji/characterReplace.js b/character/shiji/characterReplace.js index 7467d7f293..fb0142273f 100644 --- a/character/shiji/characterReplace.js +++ b/character/shiji/characterReplace.js @@ -1,6 +1,6 @@ const characterReplaces = { wangcan: ["wangcan", "sp_wangcan", "tw_wangcan"], - sunshao: ["sunshao", "sp_sunshao"], + sunshao: ["sunshao", "sp_sunshao", "std_sunshao"], xunchen: ["xunchen", "re_xunchen", "sp_xunchen", "tw_xunchen", "clan_xunchen"], xinpi: ["xinpi", "sp_xinpi"], duyu: ["duyu", "dc_duyu", "sp_duyu", "pk_sp_duyu"], @@ -12,16 +12,16 @@ const characterReplaces = { cuiyan: ["cuiyan", "sp_cuiyan"], wujing: ["wujing", "tw_wujing"], zhouchu: ["jin_zhouchu", "zhouchu", "tw_zhouchu", "std_zhouchu"], - liuzhang: ["liuzhang", "tw_liuzhang"], - chenzhen: ["sp_chenzhen", "tw_chenzhen"], + liuzhang: ["liuzhang", "tw_liuzhang", "std_liuzhang"], + sp_chenzhen: ["sp_chenzhen", "tw_chenzhen"], feiyi: ["ol_feiyi", "feiyi", "tw_feiyi", "std_feiyi"], wangling: ["dc_wangling", "wangling", "tw_wangling", "clan_wangling"], qiaogong: ["qiaogong", "tw_qiaogong"], sp_chendong: ["sp_chendong", "tw_chendong", "chendong"], sp_jiangqing: ["sp_jiangqing", "tw_jiangqing", "jiangqing"], - kongrong: ["dc_kongrong", "sp_kongrong", "jsrg_kongrong", "kongrong"], + kongrong: ["ol_sb_kongrong", "dc_kongrong", "sp_kongrong", "jsrg_kongrong", "kongrong"], dc_mifuren: ["dc_mifuren", "sp_mifuren"], - sp_jiangwan: ["ol_jiangwan", "sp_jiangwan"], + sp_jiangwan: ["ol_jiangwan", "sp_jiangwan", "std_jiangwan"], }; export default characterReplaces; diff --git a/character/shiji/skill.js b/character/shiji/skill.js index b52c066809..1f8947851d 100644 --- a/character/shiji/skill.js +++ b/character/shiji/skill.js @@ -268,58 +268,55 @@ const skills = { }, houfeng: { audio: 3, - group: "houfeng_zhengsu", + trigger: { global: "phaseUseBegin" }, + filter: function (event, player) { + if (!["zhengsu_leijin", "zhengsu_bianzhen", "zhengsu_mingzhi"].some(i => !event.player.hasSkill(i))) return false; + return player.inRange(event.player); + }, + check: function (event, player) { + return get.attitude(player, event.player) > 0; + }, + round: 1, + logAudio: () => 1, + logTarget: "player", + content: function () { + "step 0"; + player.chooseButton(["选择" + get.translation(trigger.player) + "要进行的整肃类型", [["zhengsu_leijin", "zhengsu_bianzhen", "zhengsu_mingzhi"].filter(i => !trigger.player.hasSkill(i)), "vcard"]], true).set("ai", () => Math.random()); + "step 1"; + if (result.bool) { + var name = result.links[0][2], + target = trigger.player; + target.addTempSkill("houfeng_share", { + player: ["phaseDiscardAfter", "phaseAfter"], + }); + target.markAuto("houfeng_share", [player]); + target.addTempSkill(name, { player: ["phaseDiscardAfter", "phaseAfter"] }); + target.markAuto("houfeng", name); + target.popup(name, "thunder"); + game.delayx(); + } + }, subSkill: { - zhengsu: { - audio: "houfeng1", - trigger: { global: "phaseUseBegin" }, - filter: function (event, player) { - if (!["zhengsu_leijin", "zhengsu_bianzhen", "zhengsu_mingzhi"].some(i => !event.player.hasSkill(i))) return false; - return player.inRange(event.player); - }, - check: function (event, player) { - return get.attitude(player, event.player) > 0; - }, - prompt2: () => lib.translate.houfeng_info, - round: 1, - logTarget: "player", - content: function () { - "step 0"; - player.chooseButton(["选择" + get.translation(trigger.player) + "要进行的整肃类型", [["zhengsu_leijin", "zhengsu_bianzhen", "zhengsu_mingzhi"].filter(i => !trigger.player.hasSkill(i)), "vcard"]], true).set("ai", () => Math.random()); - "step 1"; - if (result.bool) { - var name = result.links[0][2], - target = trigger.player; - target.addTempSkill("houfeng_share", { - player: ["phaseDiscardAfter", "phaseAfter"], - }); - target.markAuto("houfeng_share", [player]); - target.addTempSkill(name, { player: ["phaseDiscardAfter", "phaseAfter"] }); - target.popup(name, "thunder"); - game.delayx(); - } - }, - }, share: { + audio: "houfeng", charlotte: true, onremove: true, trigger: { player: "phaseDiscardEnd" }, forced: true, - popup: false, + logAudio(event, player) { + if (!lib.skill.zhengsu.filterx("houfeng", player)) return "houfeng3.mp3"; + return "houfeng2.mp3"; + }, content: function () { "step 0"; - if (!lib.skill.zhengsu.filter(trigger, player)) { - game.broadcastAll(function () { - if (lib.config.background_speak) game.playAudio("skill", "houfeng3"); - }); + if (!lib.skill.zhengsu.filterx("houfeng", player)) { + delete player.storage.houfeng; player.popup("整肃失败", "fire"); game.log(player, "整肃失败"); event.finish(); return; } - game.broadcastAll(function () { - if (lib.config.background_speak) game.playAudio("skill", "houfeng2"); - }); + delete player.storage.houfeng; player.popup("整肃成功", "wood"); game.log(player, "整肃成功"); var list = player.getStorage("houfeng_share").filter(i => i.isIn()); @@ -356,50 +353,48 @@ const skills = { //手杀皇甫嵩 spzhengjun: { audio: 3, - group: "spzhengjun_zhengsu", + trigger: { player: "phaseUseBegin" }, + filter: function (event, player) { + return ["zhengsu_leijin", "zhengsu_bianzhen", "zhengsu_mingzhi"].some(i => !player.hasSkill(i)); + }, + async cost(event, trigger, player) { + const { result } = await player.chooseButton([get.prompt("spzhengjun"), [["zhengsu_leijin", "zhengsu_bianzhen", "zhengsu_mingzhi"].filter(i => !player.hasSkill(i)), "vcard"]]).set("ai", () => Math.random()); + event.result = { + bool: result.bool, + cost_data: result.links[0][2], + }; + }, + logAudio: () => 1, + async content(event, trigger, player) { + const name = event.cost_data; + player.addTempSkill("spzhengjun_share", { + player: ["phaseDiscardAfter", "phaseAfter"], + }); + player.addTempSkill(name, { player: ["phaseDiscardAfter", "phaseAfter"] }); + player.markAuto("spzhengjun", name); + player.popup(name, "thunder"); + await game.delayx(); + }, subSkill: { - zhengsu: { - audio: "spzhengjun1", - trigger: { player: "phaseUseBegin" }, - filter: function (event, player) { - return ["zhengsu_leijin", "zhengsu_bianzhen", "zhengsu_mingzhi"].some(i => !player.hasSkill(i)); - }, - direct: true, - content: function () { - "step 0"; - player.chooseButton([get.prompt("spzhengjun"), [["zhengsu_leijin", "zhengsu_bianzhen", "zhengsu_mingzhi"].filter(i => !player.hasSkill(i)), "vcard"]]).set("ai", () => Math.random()); - "step 1"; - if (result.bool) { - player.logSkill("spzhengjun_zhengsu", player); - var name = result.links[0][2]; - player.addTempSkill("spzhengjun_share", { - player: ["phaseDiscardAfter", "phaseAfter"], - }); - player.addTempSkill(name, { player: ["phaseDiscardAfter", "phaseAfter"] }); - player.popup(name, "thunder"); - game.delayx(); - } - }, - }, share: { + audio: "spzhengjun", charlotte: true, trigger: { player: "phaseDiscardEnd" }, forced: true, - popup: false, + logAudio(event, player) { + if (!lib.skill.zhengsu.filterx("spzhengjun", player)) return "spzhengjun3.mp3"; + return "spzhengjun2.mp3"; + }, content: function () { "step 0"; - if (!lib.skill.zhengsu.filter(trigger, player)) { - game.broadcastAll(function () { - if (lib.config.background_speak) game.playAudio("skill", "spzhengjun3"); - }); + if (!lib.skill.zhengsu.filterx("spzhengjun", player)) { + delete player.storage.spzhengjun; player.popup("整肃失败", "fire"); game.log(player, "整肃失败"); event.finish(); return; } - game.broadcastAll(function () { - if (lib.config.background_speak) game.playAudio("skill", "spzhengjun2"); - }); + delete player.storage.spzhengjun; player.popup("整肃成功", "wood"); game.log(player, "整肃成功"); player.chooseDrawRecover(2, "整肃奖励:摸两张牌或回复1点体力"); @@ -436,7 +431,6 @@ const skills = { }, }, }, - spzhengjun1: { audio: true }, spshiji: { audio: 2, trigger: { source: "damageBegin2" }, @@ -773,49 +767,47 @@ const skills = { }, spyanji: { audio: 3, - group: "spyanji_zhengsu", + trigger: { player: "phaseUseBegin" }, + filter: function (event, player) { + return ["zhengsu_leijin", "zhengsu_bianzhen", "zhengsu_mingzhi"].some(i => !player.hasSkill(i)); + }, + logAudio: () => 1, + async cost(event, trigger, player) { + const { result } = await player.chooseButton([get.prompt("spyanji"), [["zhengsu_leijin", "zhengsu_bianzhen", "zhengsu_mingzhi"].filter(i => !player.hasSkill(i)), "vcard"]]).set("ai", () => Math.random()); + event.result = { + bool: result.bool, + cost_data: result.links[0][2], + }; + }, + async content(event, trigger, player) { + const name = event.cost_data; + player.addTempSkill("spyanji_share", { + player: ["phaseDiscardAfter", "phaseAfter"], + }); + player.addTempSkill(name, { player: ["phaseDiscardAfter", "phaseAfter"] }); + player.markAuto("spyanji", name); + player.popup(name, "thunder"); + await game.delayx(); + }, subSkill: { - zhengsu: { - audio: "spyanji", - trigger: { player: "phaseUseBegin" }, - filter: function (event, player) { - return ["zhengsu_leijin", "zhengsu_bianzhen", "zhengsu_mingzhi"].some(i => !player.hasSkill(i)); - }, - direct: true, - content: function () { - "step 0"; - player.chooseButton([get.prompt("spyanji"), [["zhengsu_leijin", "zhengsu_bianzhen", "zhengsu_mingzhi"].filter(i => !player.hasSkill(i)), "vcard"]]).set("ai", () => Math.random()); - "step 1"; - if (result.bool) { - player.logSkill("spyanji_zhengsu", player); - var name = result.links[0][2]; - player.addTempSkill("spyanji_share", { - player: ["phaseDiscardAfter", "phaseAfter"], - }); - player.addTempSkill(name, { player: ["phaseDiscardAfter", "phaseAfter"] }); - player.popup(name, "thunder"); - game.delayx(); - } - }, - }, share: { + audio: "spyanji", charlotte: true, trigger: { player: "phaseDiscardEnd" }, forced: true, - popup: false, + logAudio(event, player) { + if (!lib.skill.zhengsu.filterx("spyanji", player)) return "spyanji3.mp3"; + return "spyanji2.mp3"; + }, content: function () { - if (!lib.skill.zhengsu.filter(trigger, player)) { - game.broadcastAll(function () { - if (lib.config.background_speak) game.playAudio("skill", "spyanji3"); - }); + if (!lib.skill.zhengsu.filterx("spyanji", player)) { + delete player.storage.spyanji; player.popup("整肃失败", "fire"); game.log(player, "整肃失败"); event.finish(); return; } - game.broadcastAll(function () { - if (lib.config.background_speak) game.playAudio("skill", "spyanji2"); - }); + delete player.storage.spyanji; player.popup("整肃成功", "wood"); game.log(player, "整肃成功"); player.chooseDrawRecover(2, "整肃奖励:摸两张牌或回复1点体力"); @@ -823,7 +815,6 @@ const skills = { }, }, }, - spyanji1: { audio: true }, //蒋钦 spjianyi: { audio: 2, @@ -893,7 +884,7 @@ const skills = { trigger: { global: "useCardToTarget" }, usable: 1, filter: function (event, player) { - return (event.card.name == "sha" || get.type(event.card, false) == "delay") && event.player != player && !event.targets.includes(player) && player.inRange(event.target); + return (event.card.name == "sha" || get.type(event.card, null, false) == "delay") && event.player != player && !event.targets.includes(player) && player.inRange(event.target); }, logTarget: "target", check: function (event, player) { @@ -1236,7 +1227,7 @@ const skills = { else target.moveCard(); }, ai: { - order: 8, + order: 10, result: { target: function (player, target) { if (target.canMoveCard(true)) return 3; @@ -1290,118 +1281,91 @@ const skills = { trigger: { player: "phaseJieshuBegin" }, forced: true, filter: function (event, player) { - return !player.hasSkill("spxizhan_spfangzong") && player.countCards("h") < Math.min(8, game.countPlayer()); + return player.countCards("h") < Math.min(8, game.countPlayer()); }, content: function () { player.drawTo(Math.min(8, game.countPlayer())); }, mod: { playerEnabled: function (card, player, target) { - if (player == _status.currentPhase && get.tag(card, "damage") > 0 && !player.hasSkill("spxizhan_spfangzong") && player.inRange(target)) return false; + if (player == _status.currentPhase && get.tag(card, "damage") > 0 && !player.isTempBanned("spfangzong") && player.inRange(target)) return false; }, targetEnabled: function (card, player, target) { - if (get.tag(card, "damage") > 0 && !target.hasSkill("spxizhan_spfangzong") && player.inRange(target)) return false; + if (get.tag(card, "damage") > 0 && !target.isTempBanned("spfangzong") && player.inRange(target)) return false; }, }, }, spxizhan: { audio: 5, - group: "spxizhan_effect", - locked: false, - subSkill: { - spfangzong: { charlotte: true }, - effect: { - trigger: { global: "phaseBegin" }, - filter: function (event, player) { - return player != event.player; - }, - forced: true, - logTarget: "player", - content: function () { - "step 0"; - player.chooseToDiscard("he", "嬉战:弃置一张牌或失去1点体力", "根据弃置的牌对" + get.translation(trigger.player) + "视为使用如下牌:
    ♠,其使用【酒】;♥,你使用【无中生有】
    ♣,对其使用【铁索连环】;♦:对其使用火【杀】").set("ai", function (card) { - var player = _status.event.player, - target = _status.event.getTrigger().player; - var suit = get.suit(card, player), - list; - switch (suit) { - case "spade": - list = [{ name: "jiu" }, target, target]; - break; - case "heart": - list = [{ name: "wuzhong" }, player, player]; - break; - case "club": - list = [{ name: "tiesuo" }, player, target]; - break; - case "diamond": - list = [{ name: "sha", nature: "fire" }, player, target]; - break; - } - list[0].isCard = true; - var eff = 0; - if (list[1].canUse(list[0], list[2], false)) eff = get.effect(list[2], list[0], list[1], player); - if (eff >= 0 || suit == "club") eff = Math.max(eff, 5); - return eff * 1.5 - get.value(card); - }); - "step 1"; - if (result.bool) { - player.addTempSkill("spxizhan_spfangzong"); - var target = trigger.player, - card = result.cards[0], - suit = get.suit(card, player); - if (!lib.suit.includes(suit) || ((!target || !target.isIn()) && suit != "heart")) return; - game.broadcastAll(function (suit) { - if (lib.config.background_speak) game.playAudio("skill", "spxizhan" + [null, "spade", null, "heart", "club", "diamond"].indexOf(suit)); - }, suit); - switch (suit) { - case "spade": - target.chooseUseTarget("jiu", true); - break; - case "heart": - player.chooseUseTarget("wuzhong", true); - break; - case "club": - if (player.canUse("tiesuo", target)) - player.useCard( - { - name: "tiesuo", - isCard: true, - }, - target - ); - break; - case "diamond": - if ( - player.canUse( - { - name: "sha", - isCard: true, - nature: "fire", - }, - target, - false - ) - ) - player.useCard( - { - name: "sha", - isCard: true, - nature: "fire", - }, - target, - false - ); - break; + trigger: { global: "phaseBegin" }, + filter: function (event, player) { + return player != event.player; + }, + logAudio(event, player, name, indexedData, costResult) { + if (!costResult.cards.length) return "spxizhan2.mp3"; + let suit = get.suit(costResult.cards[0]); + return "spxizhan" + [null, "spade", null, "heart", "club", "diamond"].indexOf(suit) + ".mp3"; + }, + async cost(event, trigger, player) { + const result = await player.chooseToDiscard("he", "嬉战:弃置一张牌或失去1点体力", "根据弃置的牌对" + get.translation(trigger.player) + "视为使用如下牌:
    ♠,其使用【酒】;♥,你使用【无中生有】
    ♣,对其使用【铁索连环】;♦:对其使用火【杀】").set("ai", function (card) { + var player = _status.event.player, + target = _status.event.getTrigger().player; + var suit = get.suit(card, player), + list; + switch (suit) { + case "spade": + list = [{ name: "jiu" }, target, target]; + break; + case "heart": + list = [{ name: "wuzhong" }, player, player]; + break; + case "club": + list = [{ name: "tiesuo" }, player, target]; + break; + case "diamond": + list = [{ name: "sha", nature: "fire" }, player, target]; + break; + } + list[0].isCard = true; + var eff = 0; + if (list[1].canUse(list[0], list[2], false)) eff = get.effect(list[2], list[0], list[1], player); + if (eff >= 0 || suit == "club") eff = Math.max(eff, 5); + return eff * 1.5 - get.value(card); + }).set("chooseonly", true).forResult(); + event.result = { + bool: true, + cards: result.cards || [], + targets: [trigger.player], + }; + }, + async content(event, trigger, player) { + if (event.cards && event.cards.length) { + await player.discard(event.cards); + player.tempBanSkill("spfangzong"); + var target = trigger.player, + card = event.cards[0], + suit = get.suit(card, player); + if (!lib.suit.includes(suit) || ((!target || !target.isIn()) && suit != "heart")) return; + switch (suit) { + case "spade": + await target.chooseUseTarget("jiu", true); + break; + case "heart": + await player.chooseUseTarget("wuzhong", true); + break; + case "club": + if (player.canUse("tiesuo", target)) await player.useCard({ name: "tiesuo", isCard: true }, target); + break; + case "diamond": + if (player.canUse({ name: "sha", isCard: true, nature: "fire" }, target, false)) { + await player.useCard({ name: "sha", isCard: true, nature: "fire", }, target, false); } - } else { - game.broadcastAll(function () { - if (lib.config.background_speak) game.playAudio("skill", "spxizhan2"); - }); - player.loseHp(); - } - }, - }, + break; + } + } + else { + await player.loseHp(); + } }, }, //高览 @@ -1409,7 +1373,7 @@ const skills = { enable: "phaseUse", filter: function (event, player) { var num = player.getStat("skill").spjungong || 0; - return (num < player.hp || num <= player.countCards("he")) && !player.hasSkill("spjungong_block"); + return (num < player.hp || num <= player.countCards("he")); }, filterTarget: function (card, player, target) { return target != player && player.canUse("sha", target, false); @@ -1443,7 +1407,7 @@ const skills = { return evtx.card == card && evtx.getParent() == event; }) ) - player.addTempSkill("spjungong_block"); + player.tempBanSkill("spjungong"); }, ai: { order: function (item, player) { @@ -1456,7 +1420,6 @@ const skills = { }, }, }, - subSkill: { block: { charlotte: true } }, }, spdengli: { trigger: { @@ -1638,7 +1601,7 @@ const skills = { } else event.finish(); } "step 1"; - if (player.getCards("h").includes(card) && get.type(card, player) == "equip" && player.hasUseTarget(card)) player.chooseUseTarget(card, true, "nopopup"); + if (player.getCards("h").includes(card) && get.type(card, null, player) == "equip" && player.hasUseTarget(card)) player.chooseUseTarget(card, true, "nopopup"); "step 2"; var hs = target.getCards("h", function (card) { return target.canUse(get.autoViewAs({ name: "sha" }, [card]), player, false); @@ -1711,7 +1674,7 @@ const skills = { }, ai: { effect: { - player_use(card, player, target) { + player(card, player, target) { if (get.name(card) == "shan") { let num = get.number(card); if (!num || num <= player.storage.shanxie_banned.num) return "zeroplayertarget"; @@ -2120,7 +2083,7 @@ const skills = { }, ai: { effect: { - target_use(card, player, target, current) { + target(card, player, target, current) { if (card.name == "sha" && player.hp > target.hp && get.attitude(player, target) < 0) { var num = get.number(card); if (typeof num != "number") return false; @@ -2315,7 +2278,8 @@ const skills = { derivation: "zhangming", subSkill: { chuhai: { - audio: ["chuhai", 2], + audio: "chuhai", + logAudio: () => "chuhai1.mp3", inherit: "chuhai", prompt: "与一名其他角色进行拼点", }, @@ -2333,7 +2297,7 @@ const skills = { }, }, achieve: { - audio: ["chuhai", 2], + audio: "chuhai2.mp3", trigger: { player: "equipAfter" }, forced: true, skillAnimation: true, @@ -2349,7 +2313,7 @@ const skills = { }, }, fail: { - audio: "chuhai3", + audio: "chuhai3.mp3", trigger: { player: "chooseToCompareAfter" }, forced: true, filter: function (event, player) { @@ -2362,7 +2326,6 @@ const skills = { }, }, }, - chuhai3: { audio: true }, zhangming: { audio: 2, trigger: { player: "useCard" }, @@ -2548,7 +2511,7 @@ const skills = { event.targets.length == 1 && (event.target.countGainableCards(player, "h") > 0 || player.hasCard(function (i) { - return _status.connectMode || (get.type(i, player) == "basic" && lib.filter.cardDiscardable(i, player, "dbquedi")); + return _status.connectMode || (get.type(i, null, player) == "basic" && lib.filter.cardDiscardable(i, player, "dbquedi")); }, "h")) ); }, @@ -2560,7 +2523,7 @@ const skills = { if (target.countGainableCards(player, "h") > 0) list.push("选项一"); if ( player.hasCard(function (i) { - return get.type(i, player) == "basic" && lib.filter.cardDiscardable(i, player, "dbquedi"); + return get.type(i, null, player) == "basic" && lib.filter.cardDiscardable(i, player, "dbquedi"); }, "h") ) list.push("选项二"); @@ -2579,7 +2542,7 @@ const skills = { var bool1 = target.countGainableCards(player, "h") > 0; var bool2 = player.hasCard(function (i) { - return get.type(i, player) == "basic" && lib.filter.cardDiscardable(i, player, "dbquedi") && get.value(card, player) < 5; + return get.type(i, null, player) == "basic" && lib.filter.cardDiscardable(i, player, "dbquedi") && get.value(card, player) < 5; }, "h") && !target.hasSkillTag("filterDamage", null, { player: player, @@ -2605,7 +2568,7 @@ const skills = { if ( (event.control == "选项二" || event.control == "背水!") && player.hasCard(function (i) { - return get.type(i, player) == "basic" && lib.filter.cardDiscardable(i, player, "dbquedi"); + return get.type(i, null, player) == "basic" && lib.filter.cardDiscardable(i, player, "dbquedi"); }, "h") ) { player.chooseToDiscard("h", "弃置一张基本牌", { type: "basic" }, true); @@ -2680,7 +2643,7 @@ const skills = { }, content: function () { trigger.cancel(); - player.getStat().skill.dbzhuifeng = 2; + player.tempBanSkill("dbzhuifeng", { player: "phaseUseEnd" }); }, }, }, @@ -2870,7 +2833,7 @@ const skills = { forced: true, locked: false, filter: function (event, player) { - return get.type(event.card, false) != "delay" && !player.getStorage("xingqi").includes(event.card.name); + return get.type(event.card, null, false) != "delay" && !player.getStorage("xingqi").includes(event.card.name); }, content: function () { player.markAuto("xingqi", [trigger.card.name]); @@ -2966,7 +2929,6 @@ const skills = { dutySkill: true, forced: true, locked: false, - direct: true, filter: function (event, player) { if (!player.storage.xingqi || !player.storage.xingqi.length) return false; var map = { basic: 0, trick: 0, equip: 0 }; @@ -2979,11 +2941,13 @@ const skills = { } return true; }, + logAudio: () => 1, + skillAnimation: true, + animationColor: "water", content: function () { "step 0"; - player.logSkill("twmibei_achieve"); - game.log(player, "成功完成使命"); player.awakenSkill("mibei"); + game.log(player, "成功完成使命"); var list = ["basic", "equip", "trick"], cards = []; for (var i of list) { @@ -3016,7 +2980,7 @@ const skills = { }, mark: { charlotte: true }, fail: { - audio: "mibei2", + audio: "mibei2.mp3", trigger: { player: "phaseJieshuBegin" }, filter: function (event, player) { return !player.getStorage("xingqi").length && player.hasSkill("mibei_mark"); @@ -3030,8 +2994,6 @@ const skills = { }, }, }, - mibei1: { audio: true }, - mibei2: { audio: true }, xinmouli: { audio: "mouli", enable: "phaseUse", @@ -3424,7 +3386,7 @@ const skills = { group: ["qingyu_achieve", "qingyu_fail", "qingyu_defend"], subSkill: { defend: { - audio: "qingyu1", + audio: "qingyu1.mp3", trigger: { player: "damageBegin2" }, filter: function (event, player) { return ( @@ -3440,7 +3402,7 @@ const skills = { }, }, achieve: { - audio: "qingyu3", + audio: "qingyu3.mp3", trigger: { player: "phaseZhunbeiBegin" }, forced: true, skillAnimation: true, @@ -3455,7 +3417,7 @@ const skills = { }, }, fail: { - audio: "qingyu2", + audio: "qingyu2.mp3", trigger: { player: "dying" }, forced: true, content: function () { @@ -3467,9 +3429,6 @@ const skills = { }, derivation: "xuancun", }, - qingyu1: { audio: true }, - qingyu2: { audio: true }, - qingyu3: { audio: true }, xuancun: { audio: 2, trigger: { global: "phaseEnd" }, @@ -4972,7 +4931,7 @@ const skills = { if (player.hasSkill("ejian") && !player.getStorage("ejian").includes(target)) { var dam = get.damageEffect(target, player, target); if (dam > 0) return dam; - var type = get.type(card, target), + var type = get.type(card, null, target), ts = target.getCards("he", function (card) { return get.type(card) == type; }); @@ -5313,7 +5272,7 @@ const skills = { event.finish(); } else player.gain(card, "gain2"); "step 3"; - if (player.isIn() && player.getCards("h").includes(card) && get.type(card, player) == "equip") player.chooseUseTarget(card, true, "nopopup"); + if (player.isIn() && player.getCards("h").includes(card) && get.type(card, null, player) == "equip") player.chooseUseTarget(card, true, "nopopup"); }, onremove: true, intro: { content: "已发动过#次" }, @@ -6509,7 +6468,7 @@ const skills = { game.addGlobalSkill("spshanxi_bj"); }, onremove: function (player) { - if (!game.hasPlayer(current => current.hasSkill("spshanxi"), true)) game.removeGlobalSkill("spshanxi_bj"); + if (!game.hasPlayer(current => current.hasSkill("spshanxi", null, null, false), true)) game.removeGlobalSkill("spshanxi_bj"); }, trigger: { player: "phaseUseBegin" }, direct: true, @@ -6578,7 +6537,7 @@ const skills = { trigger: { player: "dieAfter" }, filter: function (event, player) { for (let i of game.players) { - if (i.hasSkill("spshanxi_suoming")) return false; + if (i.hasSkill("spshanxi_suoming", null, null, false)) return false; } return true; }, diff --git a/character/shiji/voices.js b/character/shiji/voices.js index f150ab6f78..f733f0401b 100644 --- a/character/shiji/voices.js +++ b/character/shiji/voices.js @@ -20,14 +20,14 @@ export default { "#sptaoluan1": "敌军依草结营,正犯兵家大忌!", "#sptaoluan2": "兵法所云火攻之计,正合此时之势!", "#sp_huangfusong:die": "力有所能,臣必为也……", - "#spdiaodu1": "三军器用,攻守之具,皆有法也!", - "#spdiaodu2": "士各执其器,乃陷坚陈,败强敌!", - "#spdiancai1": "资财当为公,不可为私也!", - "#spdiancai2": "财用于公则政明,而后民附也!", - "#spyanji1": "范既典主财计,必律己以率之!", - "#spyanji2": "有财贵于善用,须置军资以崇国防!", - "#spyanji3": "公帑私用?待吾查清定要严惩!", - "#sp_lvfan:die": "此病来势汹汹,恕臣无力侍奉……", + "#spdiaodu1": "兵甲统一分配,不可私自易之!", + "#spdiaodu2": "兵器调度已定,忤者军法从事!", + "#spdiancai1": "国无九年之蓄,为政安敢奢靡!", + "#spdiancai2": "上下尚俭戒奢,以足天下之用!", + "#spyanji1": "料覆之日已到,帐簿速速呈来!", + "#spyanji2": "帐簿收支不符,何人敢做假账!", + "#spyanji3": "所记无有纰漏,余财尚可维持!", + "#sp_lvfan:die": "今日朝事,可有……", "#spjianyi1": "今虽富贵,亦不可浪费。", "#spjianyi2": "缩衣克俭,才是兴家之道。", "#spshangyi1": "国士,当以义为先!", diff --git a/character/xinghuoliaoyuan/card.js b/character/sixiang/card.js similarity index 100% rename from character/xinghuoliaoyuan/card.js rename to character/sixiang/card.js diff --git a/character/sixiang/character.js b/character/sixiang/character.js new file mode 100644 index 0000000000..d72e01f721 --- /dev/null +++ b/character/sixiang/character.js @@ -0,0 +1,39 @@ +const characters = { + std_sunhao: ["male", "wu", 5, ["stdcanshi", "chouhai", "guiming"], ["zhu"]], + std_mateng: ["male", "qun", 4, ["stdxiongyi", "mashu", "stdyouji"], ["zhu"]], + std_mayunlu: ["female", "shu", 4, ["stdfengpo", "mashu"]], + std_jianggan: ["male", "wei", 3, ["stddaoshu", "stddaizui"]], + std_zhouchu: ["male", "wu", 4, ["stdxiongxia"]], + std_lvlingqi: ["female", "qun", 4, ["stdhuizhan"]], + std_dc_yanghu: ["male", "wei", 4, ["stdmingfa"]], + std_dc_luotong: ["male", "wu", 3, ["stdjinjian", "stdrenzheng"]], + std_lijue: ["male", "qun", 5, ["stdxiongsuan"]], + std_chengpu: ["male", "wu", 4, ["stdchunlao"]], + std_db_wenyang: ["male", "wei", 4, ["stdquedi"]], + std_re_dengzhi: ["male", "shu", 3, ["stdzhiyinmeng", "stdhehe"]], + std_zhangyì: ["male", "shu", 4, ["stdzhiyi"]], + std_chengyu: ["male", "wei", 3, ["stdshefu", "stdyibing"]], + std_fanyufeng: ["female", "qun", 3, ["stdbazhan", "stdzhanying"]], + std_feiyi: ["male", "shu", 3, ["stdtiaohe", "stdqiansu"]], + + std_guanxing: ["male", "shu", 4, ["stdwuyou"]], + std_fuhuanghou: ["female", "qun", 3, ["stdqiuyuan", "stdzhuikong"]], + std_liubiao: ["male", "qun", 3, ["stdzishou", "zongshi", "stdjujin"], ["zhu"]], + std_gongsunyuan: ["male", "qun", 4, ["stdhuaiyi", "stdfengbai"], ["name:公孙|渊", "zhu"]], + std_cenhun: ["male", "wu", 3, ["stdjishe", "stdwudu"]], + std_simashi: ["male", "wei", 4, ["stdjinglve"], ["name:司马|师"]], + std_sunshao: ["male", "wu", 3, ["stddingyi", "stdzuici"]], + std_jiangwan: ["male", "shu", 3, ["stdruwu", "stdchengshi"]], + std_maliang: ["male", "shu", 3, ["stdxiemu", "stdnaman"]], + old_shen_zhaoyun: ["male", "shen", 2, ["oldjuejing", "oldlonghun"], ["shu"]], + std_pengyang: ["male", "shu", 3, ["stdxiaofan", "stdtuishi"], ["unseen"]],//不想你,diy牢彭羕 + std_xushu: ["male", "shu", 3, ["stdwuyan", "stdjujian"], ["border:wei"]], + std_xuezong: ["male", "wu", 3, ["stdfunan", "stdxunjie"]], + std_liuzhang: ["male", "qun", 3, ["stdyinge", "stdshiren", "stdjuyi"], ["zhu"]], + std_wangyuanji: ["female", "wei", 3, ["stdqianchong", "stdshangjian"]], + std_wanglang: ["male", "wei", 3, ["stdgushe", "stdjici"]], + std_zhonghui: ["male", "wei", 4, ["stdxingfa"], ["clan:颍川钟氏"]], + std_huaxin: ["male", "wei", 3, ["stdyuanqing", "stdshuchen"]], +}; + +export default characters; diff --git a/character/sixiang/characterFilter.js b/character/sixiang/characterFilter.js new file mode 100644 index 0000000000..6d63d130c7 --- /dev/null +++ b/character/sixiang/characterFilter.js @@ -0,0 +1,5 @@ +import { lib, game, ui, get, ai, _status } from "../../noname.js"; + +const characterFilters = {}; + +export default characterFilters; diff --git a/character/sixiang/characterReplace.js b/character/sixiang/characterReplace.js new file mode 100644 index 0000000000..f284cd4883 --- /dev/null +++ b/character/sixiang/characterReplace.js @@ -0,0 +1,8 @@ +const characterReplaces = { + sunhao: ["sunhao", "std_sunhao"], + lvlingqi: ["lvlingqi", "std_lvlingqi"], + chengyu: ["chengyu", "std_chengyu", "dc_sb_chengyu"], + fanyufeng: ["fanyufeng", "std_fanyufeng"], +}; + +export default characterReplaces; diff --git a/character/xinghuoliaoyuan/dynamicTranslate.js b/character/sixiang/dynamicTranslate.js similarity index 100% rename from character/xinghuoliaoyuan/dynamicTranslate.js rename to character/sixiang/dynamicTranslate.js diff --git a/character/xinghuoliaoyuan/index.js b/character/sixiang/index.js similarity index 94% rename from character/xinghuoliaoyuan/index.js rename to character/sixiang/index.js index 2561dca6ec..aff1b3daf9 100644 --- a/character/xinghuoliaoyuan/index.js +++ b/character/sixiang/index.js @@ -14,11 +14,11 @@ import { characterSort, characterSortTranslate } from "./sort.js"; game.import("character", function () { return { - name: "xinghuoliaoyuan", + name: "sixiang", connect: true, character: { ...characters }, characterSort: { - xinghuoliaoyuan: characterSort, + sixiang: characterSort, }, characterFilter: { ...characterFilters }, characterTitle: {}, diff --git a/character/sixiang/intro.js b/character/sixiang/intro.js new file mode 100644 index 0000000000..9e9db8b41d --- /dev/null +++ b/character/sixiang/intro.js @@ -0,0 +1,5 @@ +const characterIntro = { + guanxing: "关兴,名将关羽之子,继承了父亲汉寿亭侯的爵位。年少时即受诸葛亮器重,在蜀汉担任侍中、中监军之职,后在夷陵之战中报了杀父之仇。", +}; + +export default characterIntro; diff --git a/character/sixiang/perfectPairs.js b/character/sixiang/perfectPairs.js new file mode 100644 index 0000000000..ff8b4c5632 --- /dev/null +++ b/character/sixiang/perfectPairs.js @@ -0,0 +1 @@ +export default {}; diff --git a/character/sixiang/pinyin.js b/character/sixiang/pinyin.js new file mode 100644 index 0000000000..bc893d3fb5 --- /dev/null +++ b/character/sixiang/pinyin.js @@ -0,0 +1,2 @@ +const pinyins = {}; +export default pinyins; diff --git a/character/sixiang/skill.js b/character/sixiang/skill.js new file mode 100644 index 0000000000..ad11b30c48 --- /dev/null +++ b/character/sixiang/skill.js @@ -0,0 +1,2176 @@ +import { lib, game, ui, get, ai, _status } from "../../noname.js"; + +/** @type { importCharacterConfig['skill'] } */ +const skills = { + //四象封印·太阴 + //华歆 + stdyuanqing: { + audio: "yuanqing", + trigger: { + player: "phaseEnd", + }, + getCards(player) { + let cards = []; + player.getHistory("lose", evt => { + if (evt.cards2 && evt.cards2.some(i => get.position(i) == "d")) { + cards.addArray(evt.cards2.filter(i => get.position(i) == "d")); + } + }); + return cards; + }, + filter(event, player) { + let targets = lib.skill.stdyuanqing.logTarget(event, player); + return targets && targets.length; + }, + logTarget(event, player) { + return game.filterPlayer(current => { + let cards = lib.skill.stdyuanqing.getCards(current); + return cards && cards.length; + }); + }, + async content(event, trigger, player) { + for (const target of event.targets) { + let cards = lib.skill.stdyuanqing.getCards(target); + if (!cards.length) continue; + const result = await target.chooseButton(["获得其中一张牌", cards], true).forResult(); + if (result.bool) { + await target.gain(result.links, 'gain2'); + } + } + }, + }, + stdshuchen: { + audio: "shuchen", + enable: "chooseToUse", + viewAsFilter(player) { + return player != _status.currentPhase && player.countCards("h") > player.getHandcardLimit(); + }, + filterCard: true, + position: "h", + selectCard() { + const player = get.player(); + return player.countCards("h") - player.getHandcardLimit(); + }, + viewAs: { + name: "tao", + }, + prompt: "将超出手牌上限的手牌当桃使用", + check(card) { + return 15 - get.value(card); + }, + }, + //玩姬 + stdqianchong: { + mod: { + cardUsable: function (card, player) { + if (player.countCards("e") % 2 != 0) return Infinity; + }, + targetInRange: function (card, player) { + if (player.countCards("e") % 2 == 0) return true; + }, + }, + }, + stdshangjian: { + trigger: { + player: "phaseJieshuBegin", + }, + audio: "xinfu_shangjian", + filter: function (event, player) { + let num = 0, cards = []; + player.getHistory("lose", evt => { + if (evt.cards2) num += evt.cards2.length; + if (evt.cards2.some(i => get.position(i) == "d")) cards.addArray(evt.cards2.filter(i => get.position(i) == "d")) + }); + return cards.length && num > 0 && num <= player.hp; + }, + async cost(event, trigger, player) { + let cards = []; + player.getHistory("lose", evt => { + if (evt.cards2 && evt.cards2.some(i => get.position(i) == "d")) cards.addArray(evt.cards2.filter(i => get.position(i) == "d")); + }); + const result = await player.chooseButton(['尚俭:选择获得其中一张牌', cards]).set('ai', button => { + return get.value(button.link, get.event('player')); + }).forResult(); + event.result = { + bool: result.bool, + cost_data: result.links, + } + }, + async content(event, trigger, player) { + await player.gain(event.cost_data, 'gain2'); + }, + }, + //王司徒 + stdgushe: { + audio: "gushe", + enable: "phaseUse", + usable: 1, + filterTarget: function (card, player, target) { + return player.canCompare(target); + }, + filter: function (event, player) { + return player.countCards("h") > 0; + }, + async content(event, trigger, player) { + let num = 1, target = event.target; + while (num > 0 && player.canCompare(target)) { + num--; + let winner = [], failure = []; + let { result } = await player.chooseToCompare(target) + if (result.bool) { + failure.push(target); + target.chat(lib.skill.gushe.chat.randomGet()); + await player.draw(); + } + else if (result.tie) failure = [player, target]; + else { + failure.push(player); + target.chat(lib.skill.gushe.chat.randomGet()); + await target.draw(); + } + if (player.canCompare(target)) { + for (let loser of failure) { + let choice = loser.countCards("h", card => get.value(card) <= 6 && card.number > 10) > 0; + const { result: { bool } } = await loser.chooseBool('是否与其再次拼点?').set('choice', choice) + if (bool) num++; + } + } + } + }, + ai: { + order: 7, + result: { + target: function (player, target) { + let hs = player.getCards("h"); + if (hs.some(card => get.value(card) <= 6 && card.number > 10) || player.getHp() < 2 && player.getHp() + player.countCards('h', { name: ["tao", "jiu"] }) > 2 || player.getHp() > 1 && player.getHp() + player.countCards('h', { name: "tao" }) > 2) return -1; + return 0; + }, + }, + }, + }, + stdjici: { + audio: "jici", + trigger: { + player: "compare", + target: "compare", + }, + filter: function (event, player) { + if (event.player == player && event.iwhile) return false; + return true; + }, + check(event, player) { + return player.getHp() < 2 && player.getHp() + player.countCards('h', { name: ["tao", "jiu"] }) > 2 || player.getHp() > 1 && player.getHp() + player.countCards('h', { name: "tao" }) > 2 + }, + async content(event, trigger, player) { + await player.loseHp(); + if (player == trigger.player) trigger.num1 = 13 + else trigger.num2 = 13; + game.log(player, "的拼点牌点数为13"); + }, + }, + //钟会 + stdxingfa: { + audio: "gzpaiyi", + trigger: { + player: "phaseZhunbeiBegin", + }, + filter: function (event, player) { + return player.getHp() <= player.countCards("h") && game.hasPlayer(function (current) { + return current != player; + }); + }, + async cost(event, trigger, player) { + event.result = await player.chooseTarget(get.prompt("stdxingfa"), "对一名其他角色造成1点伤害", function (card, player, target) { + return target != player; + }) + .set("ai", function (target) { + var player = _status.event.player; + return get.damageEffect(target, player, player); + }).forResult(); + }, + async content(event, trigger, player) { + await event.targets[0].damage('nocard') + }, + ai: { + expose: 0.25, + threaten: 1.7, + }, + }, + //刘璋 + stdyinge: { + audio: "yinlang", + usable: 1, + enable: "phaseUse", + selectTarget: 2, + multitarget: true, + targetprompt: ["摸牌", "出杀目标"], + filterTarget: function (card, player, target) { + if (ui.selected.targets.length == 0) { + return player != target; + } + return player.inRange(target) && ui.selected.targets[0].canUse({ name: "sha", isCard: true }, target, false); + }, + delay: false, + async content(event, trigger, player) { + const target = event.targets[0], target2 = event.targets[1]; + await target.draw(2); + await target.useCard({ name: "sha", isCard: true }, target2, "noai"); + }, + ai: { + order: 8, + result: { + target(player, target) { + if (ui.selected.targets.length == 0) { + return 3; + } else { + return get.effect(target, { name: "sha" }, ui.selected.targets[0], target); + } + }, + }, + }, + }, + stdshiren: { + audio: "xiusheng", + trigger: { + target: "useCardToTargeted", + }, + filter(event, player) { + return event.card.name == "sha" && event.player != player; + }, + usable: 1, + logTarget: "player", + async content(event, trigger, player) { + await player.draw(2); + await player.chooseToGive(event.targets[0], "he", true); + }, + }, + stdjuyi: { + zhuSkill: true, + trigger: { + player: "damageBegin4", + }, + filter(event, player) { + if (!event.source || event.source == player || !player.countCards("he")) return false; + if (player.hasHistory("damage", evt => evt.source && evt.source == event.source)) return false; + return event.source.group == "qun" && !player.getStorage("stdjuyi").includes(event.source); + }, + async cost(event, trigger, player) { + const result = await trigger.source.choosePlayerCard(player, "he", get.prompt("stdjuyi", player), "据益:是否获得" + get.translation(player) + "一张牌并防止此次伤害?") + .set("ai", button => { + if (get.event("eff") > 0) return 0; + return get.value(button.link); + }) + .set("eff", get.damageEffect(player, trigger.source, trigger.source)) + .forResult(); + event.result = { + bool: result.bool, + cards: result.links, + targets: [trigger.source], + }; + }, + async content(event, trigger, player) { + const target = event.targets[0]; + await player.give(event.cards, target); + trigger.cancel(); + if (!player.getStorage("stdjuyi").length) { + player.when({ global: "phaseEnd" }).then(() => { + delete player.storage.stdjuyi; + }); + } + player.markAuto("stdjuyi", target); + }, + }, + //薛总 + stdfunan: { + audio: "funan", + trigger: { + target: "shaMiss", + global: "eventNeutralized", + }, + usable: 1, + filter(event, player, name) { + if (event.type != "card" || event.player == player) return false; + if (name != "shaMiss" && event._neutralize_event.player != player) return false; + return event.cards && event.cards.someInD(); + }, + async content(event, trigger, player) { + await player.gain(trigger.cards.filterInD(), "gain2"); + }, + }, + stdxunjie: { + audio: "jiexun", + trigger: { + player: "phaseJieshuBegin", + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2("stdxunjie"), function (card, player, target) { + return target.countCards("h"); + }) + .set("ai", function (target) { + const player = _status.event.player; + let eff = get.effect(target, { name: "guohe_copy2" }, player, player); + if (target == player) return player.countCards("h", { suit: "diamod" }) ? 2 : -2; + return eff * (target.countCards("h") > 4 ? -1 : 1); + }).forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + const result = await target.chooseToDiscard("h", 1, true).set("ai", card => { + if (get.suit(card) == "diamond") return 11 - get.value(card); + return 5 - get.value(card); + }).forResult(); + if (!result.bool) return; + if (get.suit(result.cards[0]) == "diamond") await target.draw(2); + }, + }, + //徐庶 + stdwuyan: { + audio: "wuyan", + trigger: { + player: "useCard", + }, + forced: true, + filter(event, player) { + if (!event.cards || event.cards.length != 1 || get.type2(event.cards[0]) != "trick") return false; + return event.card.name == "wuxie"; + }, + async content() { }, + mod: { + cardname(card, player) { + let info = lib.card[card.name]; + if (info && ["trick", "delay"].includes(info.type)) return "wuxie"; + }, + }, + }, + stdjujian: { + audio: "jujian", + trigger: { + player: "useCardAfter" + }, + usable: 1, + filter(event, player) { + return event.cards && event.cards.length && event.card.name == "wuxie"; + }, + async cost(event, trigger, player) { + event.result = await player.chooseTarget(get.prompt2("stdjujian"), lib.filter.notMe).set("ai", target => { + const player = get.player(); + return target.getUseValue(_status.event.getTrigger().cards[0]) * get.attitude(player, target); + }).forResult(); + event.result.cards = trigger.cards; + }, + async content(event, trigger, player) { + await event.targets[0].gain(event.cards, "gain2"); + }, + }, + //牢彭羕 + stdxiaofan: { + audio: "olxiaofan", + trigger: { + player: "useCardAfter", + }, + forced: true, + filter(event, player) { + const num = Math.min(3, lib.skill.olxiaofan.getNum(player)), + pos = "jeh".slice(0, num); + return num > 0 && player.countCards(pos); + }, + async content(event, trigger, player) { + const num = Math.min(3, lib.skill.olxiaofan.getNum(player)), + pos = "jeh".slice(0, num); + let index = 0; + while (index < num) { + const posi = pos[index]; + const hs = player.countCards(posi); + if (hs > 0) await player.chooseToDiscard(hs, posi, true); + index++; + } + }, + ai: { + effect: { + player_use(card, player) { + if (get.type(card) == "equip") { + return [0, -5]; + } + }, + }, + neg: true, + }, + }, + stdtuishi: { + audio: "oltuishi", + mod: { + wuxieJudgeEnabled: () => false, + wuxieEnabled: () => false, + cardEnabled: card => { + if (card.name == "wuxie") return false; + }, + aiValue: (player, card, val) => { + if (card.name == "wuxie") return 0; + var num = get.number(card); + if ([1, 11, 12, 13].includes(num)) return 0; + }, + aiUseful: (player, card, val) => { + if (card.name == "wuxie") return 0; + var num = get.number(card); + if ([1, 11, 12, 13].includes(num)) return 0; + }, + aiOrder: (player, card, order) => { + var num = get.number(card); + if ([1, 11, 12, 13].includes(num)) return 0; + return order; + }, + }, + trigger: { + player: "useCard", + }, + filter(event, player) { + return [1, 11, 12, 13].includes(get.number(event.card)); + }, + forced: true, + async content(event, trigger, player) { + trigger.targets.length = 0; + trigger.all_excluded = true; + game.log(trigger.card, "被无效了"); + }, + }, + //牢赵云 + oldjuejing: { + audio: "xinjuejing", + trigger: { player: "phaseDrawBegin2" }, + filter: function (event, player) { + return !event.numFixed && player.getHp() < player.maxHp; + }, + forced: true, + content: function () { + trigger.num += player.getDamagedHp(); + }, + mod: { + maxHandcard: (player, num) => num + 2, + }, + }, + oldlonghun: { + audio: "relonghun", + inherit: "xinlonghun", + prompt: () => `将${get.cnNumber(Math.max(1, get.player().getHp()))}张♦牌当做杀,♥牌当做桃,♣牌当做闪,♠牌当做无懈可击使用或打出`, + selectCard: () => Math.max(1, get.player().getHp()), + complexCard: true, + precontent: function () { + delete event.result.skill; + player.logSkill("oldlonghun"); + }, + ai: { + respondSha: true, + respondShan: true, + skillTagFilter: function (player, tag) { + var name; + switch (tag) { + case "respondSha": + name = "diamond"; + break; + case "respondShan": + name = "club"; + break; + case "save": + name = "heart"; + break; + } + if (!player.countCards("hes", { suit: name })) return false; + }, + order: function (item, player) { + if (player && _status.event.type == "phase") { + var max = 0; + var list = ["sha", "tao"]; + var map = { sha: "diamond", tao: "heart" }; + for (var i = 0; i < list.length; i++) { + var name = list[i]; + if ( + player.countCards("hes", function (card) { + return (name != "sha" || get.value(card) < 5) && get.suit(card, player) == map[name]; + }) >= Math.max(1, player.getHp()) && + player.getUseValue({ + name: name, + nature: name == "sha" ? "fire" : null, + }) > 0 + ) { + var temp = get.order({ + name: name, + nature: name == "sha" ? "fire" : null, + }); + if (temp > max) max = temp; + } + } + max /= 1.1; + return max; + } + return 2; + }, + }, + hiddenCard: function (player, name) { + if (name == "wuxie" && _status.connectMode && player.countCards("hes") > 0) return true; + if (name == "wuxie") return player.countCards("hes", { suit: "spade" }) >= Math.max(1, get.player().getHp()); + if (name == "tao") return player.countCards("hes", { suit: "heart" }) >= Math.max(1, get.player().getHp()); + }, + }, + //马良 + stdxiemu: { + audio: "xiemu", + global: "stdxiemu_global", + subSkill: { + global: { + audio: "xiemu", + enable: "phaseUse", + usable: 1, + filter(event, player) { + if (!player.countCards("he", card => get.type(card) == "basic")) return false; + return game.hasPlayer(current => current.hasSkill("stdxiemu") && current != player); + }, + filterTarget(card, player, target) { + return target.hasSkill("stdxiemu") && target != player; + }, + selectTarget() { + const num = game.countPlayer(current => current.hasSkill("stdxiemu") && current != get.player()); + return num > 1 ? 1 : -1; + }, + filterCard(card) { + return get.type(card) == "basic"; + }, + position: "he", + check(card) { + return 4 - get.value(card); + }, + prompt() { + const list = game.filterPlayer(current => { + return current.hasSkill("stdxiemu"); + }); + return `将一张牌交给${get.translation(list)}${list.length > 1 ? "中的一人" : ""},然后你本回合攻击范围+1。`; + }, + log: false, + discard: false, + lose: false, + async content(event, trigger, player) { + const card = event.cards[0], + target = event.target; + player.logSkill("stdxiemu", target); + await player.showCards(card, get.translation(player) + "发动了【协穆】"); + await player.give(card, target); + player.addTempSkill("stdxiemu_range"); + player.addMark("stdxiemu_range", 1, false); + }, + ai: { + order: 7, + result: { + target: 1, + }, + }, + }, + range: { + charlotte: true, + onremove: true, + mod: { + attackRange(player, num) { + return num + player.countMark("stdxiemu_range"); + }, + }, + intro: { + content: "本回合攻击范围+#", + }, + }, + }, + }, + stdnaman: { + audio: "naman", + enable: "phaseUse", + usable: 1, + viewAs: { + name: "nanman", + }, + viewAsFilter(player) { + if (!player.countCards("he", card => get.type(card) == "basic")) return false; + }, + filterCard(card) { + return get.type(card) == "basic"; + }, + position: "he", + selectCard: [1, Infinity], + selectTarget() { + return ui.selected.cards.length; + }, + complexSelect: true, + }, + //蒋琬 + stdruwu: { + audio: "olxvfa", + enable: "chooseToUse", + filter(event, player) { + if (!event.stdruwu || !event.stdruwu.length) return false; + if (event.filterCard(get.autoViewAs({ name: "juedou" }, "unsure"), player, event)) return true; + if (event.filterCard(get.autoViewAs({ name: "wuzhong" }, "unsure"), player, event)) return true; + return false; + }, + onChooseToUse(event) { + if (game.online || event.stdruwu) return; + var list = event.player.getCards("e"); + var history = game.getGlobalHistory("everything", evt => evt.player == event.player && evt.name == "equip"); + list = list.filter(card => { + return !history.some(evt => evt.cards && evt.cards.includes(card)); + }); + event.set("stdruwu", list); + }, + chooseButton: { + dialog(event, player) { + var list = []; + if (event.filterCard(get.autoViewAs({ name: "juedou" }, "unsure"), player, event)) list.push(["锦囊", "", "juedou"]); + if (event.filterCard(get.autoViewAs({ name: "wuzhong" }, "unsure"), player, event)) list.push(["锦囊", "", "wuzhong"]); + return ui.create.dialog("儒武", [list, "vcard"]); + }, + check(button) { + if (_status.event.getParent().type != "phase") return 1; + var player = _status.event.player; + return player.getUseValue({ + name: button.link[2], + nature: button.link[3], + }); + }, + backup(links, player) { + return { + filterCard(card) { + return _status.event.stdruwu.includes(card); + }, + position: "e", + audio: "olxvfa", + popname: true, + check(card) { + return 8 - get.value(card); + }, + viewAs: { name: links[0][2] }, + }; + }, + prompt(links, player) { + return "将装备区里的一张牌当做" + get.translation(links[0][2]) + "使用"; + }, + }, + hiddenCard(player, name) { + var list = player.getCards("e"); + var history = game.getGlobalHistory("everything", evt => evt.player == player && evt.name == "equip"); + list = list.filter(card => { + return !history.some(evt => evt.cards && evt.cards.includes(card)); + }); + if (!list.length) return false; + return ["juedou", "wuzhong"].includes(name); + }, + ai: { + order: 1, + result: { + player: function (player) { + if (_status.event.dying) return get.attitude(player, _status.event.dying); + return 1; + }, + }, + }, + }, + stdchengshi: { + audio: "spjincui", + trigger: { + global: "die", + }, + filter(event, player) { + return event.player != player; + }, + check(event, player) { + return event.player.countCards("e") > player.countCards("e"); + }, + logTarget: "player", + skillAnimation: true, + limited: true, + animationColor: "fire", + changeSeat: true, + async content(event, trigger, player) { + const target = event.targets[0]; + player.awakenSkill(event.name); + game.broadcastAll(function (target1, target2) { + game.swapSeat(target1, target2); + }, player, target); + await player.swapEquip(target); + }, + mark: true, + intro: { + content: "limited", + }, + init: (player, skill) => (player.storage[skill] = false), + }, + //孙邵 + stddingyi: { + audio: "mjdingyi", + trigger: { + global: "phaseJieshuBegin", + }, + filter(event, player) { + return !event.player.countCards("e"); + }, + async cost(event, trigger, player) { + event.result = await trigger.player.chooseBool(get.prompt("stddingyi"), "摸一张牌").forResult(); + event.result.targets = [trigger.player]; + }, + async content(event, trigger, player) { + await event.targets[0].draw(); + }, + }, + stdzuici: { + audio: "mjzuici", + trigger: { + player: "damageEnd", + }, + filter(event, player) { + if (!event.source) return false; + return player.canMoveCard(null, null, game.filterPlayer(current => current != event.source), event.source); + }, + direct: true, + async content(event, trigger, player) { + const next = player.moveCard(game.filterPlayer(current => current != trigger.source), trigger.source); + next.prompt = get.prompt("stdzuici", trigger.source); + next.prompt2 = "将场上一张牌移动到其区域内"; + next.logSkill = event.name; + await next; + }, + }, + //司马师 + stdjinglve: { + audio: "jinglve", + trigger: { + global: "phaseDiscardBegin", + }, + filter(event, player) { + return player.countCards("h") > 1 && event.player != player; + }, + async cost(event, trigger, player) { + event.result = await player.chooseCard(get.prompt2("stdjinglve"), 2).set("ai", card => { + if (_status.event.att <= 0) return 0; + return 5 - get.value(card); + }).set("att", get.attitude(player, trigger.player)).forResult(); + event.result.targets = [trigger.player]; + }, + async content(event, trigger, player) { + const cards = event.cards, target = event.targets[0]; + await player.showCards(cards, get.translation(player) + "发动了【景略】"); + const next = player.give(cards, target); + next.gaintag.add("stdjinglve"); + await next; + trigger.player.addTempSkill("stdjinglve_discard"); + player.when({ global: "phaseDiscardEnd" }).filter(evt => evt == trigger).then(() => { + trigger.player.removeSkill("stdjinglve_discard"); + const cards = []; + game.getGlobalHistory("cardMove", function (evt) { + if (evt.name == "cardsDiscard") { + if (evt.getParent("phaseDiscard") == trigger) { + const moves = evt.cards.filterInD("d"); + cards.addArray(moves); + } + } + if (evt.name == "lose") { + if (evt.type != "discard" || evt.position != ui.discardPile || evt.getParent("phaseDiscard") != trigger) return; + const moves = evt.cards.filterInD("d"); + cards.addArray(moves); + } + }); + player.chooseButton(["景略:是否获得本阶段弃置的一张牌?", cards]); + }).then(() => { + if (result.bool) player.gain(result.links, "gain2"); + }); + }, + subSkill: { + discard: { + charlotte: true, + mod: { + cardDiscardable(card, player, name) { + if (name == "phaseDiscard" && card.hasGaintag("stdjinglve")) { + return false; + } + }, + }, + onremove(player) { + player.removeGaintag("stdjinglve"); + }, + }, + }, + }, + //岑昏 + stdjishe: { + audio: "jishe", + enable: "phaseUse", + filter(event, player) { + return player.getHandcardLimit() > 0; + }, + locked: false, + async content(event, trigger, player) { + player.addTempSkill("stdjishe_limit"); + player.addMark("stdjishe_limit", 1, false); + player.draw(); + }, + subSkill: { + limit: { + mod: { + maxHandcard: function (player, num) { + return num - player.countMark("stdjishe_limit"); + }, + }, + onremove: true, + charlotte: true, + marktext: "奢", + intro: { + content: "手牌上限-#", + }, + }, + }, + ai: { + order: 10, + result: { + player: function (player) { + if (!player.needsToDiscard(1)) { + return 1; + } + return 0; + }, + }, + }, + }, + stdwudu: { + trigger: { + global: "damageBegin4", + }, + filter(event, player) { + return !event.player.countCards("h"); + }, + logTarget: "player", + check(event, player) { + return player.maxHp > 1 && get.damageEffect(event.player, event.source, player) < 0; + }, + async content(event, trigger, player) { + trigger.cancel(); + await player.loseMaxHp(); + }, + }, + //公孙渊 + stdhuaiyi: { + audio: "rehuaiyi", + trigger: { + player: "phaseZhunbeiBegin", + }, + filter(event, player) { + return player.countCards("h"); + }, + forced: true, + async content(event, trigger, player) { + const hs = player.getCards("h"); + await player.showCards(hs, get.translation(player) + "发动了【怀异】"); + const colors = []; + for (let card of hs) { + colors.add(get.color(card)); + } + if (colors.length < 2) return; + const result = await player.chooseControl(colors).set("ai", () => { + return _status.event.color; + }).set("color", function () { + return colors.sort((a, b) => { + return player.countCards("h", { color: a }) - player.countCards("h", { color: b }); + })[0]; + }()).forResult(); + const discards = player.getCards("h", { color: result.control }); + if (discards.length) { + await player.discard(discards); + if (game.hasPlayer(current => current != player && current.countCards("he"))) { + const result2 = await player.chooseTarget(`获得至多${discards.length}名其他角色各一张牌`, [1, discards.length], true, function (card, player, target) { + return target != player && target.countCards("he") > 0; + }).set("ai", function (target) { + const player = get.player(); + return get.effect(target, { name: "shunshou_copy2" }, player, player); + }).forResult(); + await player.gainMultiple(result2.targets.sortBySeat(), "he"); + if (result2.targets.length > 1) await player.loseHp(); + } + } + }, + }, + stdfengbai: { + trigger: { + player: "gainAfter", + global: "loseAsyncAfter", + }, + zhuSkill: true, + logTarget: (event, player, triggername, target) => target, + check(event, player) { + return get.effect(event.indexedData, { name: "draw" }, player, player) > 0; + }, + getIndex(event, player) { + if (!event.getg || !event.getl) return false; + const cards = event.getg(player); + return game.filterPlayer(current => { + if (current == player || current.group != "qun") return false; + const evt = event.getl(current); + if (!evt || !evt.es) return false; + game.log(evt.es); + return evt.es.some(card => cards.includes(card)); + }).sortBySeat(); + }, + async content(event, trigger, player) { + await event.targets[0].draw(); + }, + }, + //刘表 + stdzishou: { + audio: "zishou", + trigger: { + player: "phaseUseBefore", + }, + check: function (event, player) { + return player.countCards("h") + 2 <= player.getHandcardLimit(); + }, + async content(event, trigger, player) { + await player.draw(game.countGroup()); + trigger.cancel(); + }, + ai: { + threaten: 1.5, + }, + }, + stdjujin: { + trigger: { + player: "damageEnd", + }, + filter(event, player) { + if (!event.source || event.source.group != "qun") return false; + return player.countCards("he") > 1; + }, + zhuSkill: true, + async cost(event, trigger, player) { + event.result = await player.chooseToDiscard(get.prompt2("stdjujin"), 2, "he") + .set("ai", card => { + const player = get.player(); + if (get.recoverEffect(player, player, player) <= 0 || player.hp >= player.maxHp) return 0; + return 5 - get.value(card); + }) + .set("chooseonly", true).forResult(); + }, + async content(event, trigger, player) { + const cards = event.cards; + await player.discard(cards); + if (player.isDamaged()) await player.recover(); + }, + }, + //伏皇后 + stdqiuyuan: { + audio: "xinqiuyuan", + trigger: { + target: "useCardToTarget", + }, + filter(event, player) { + return ( + event.card.name == "sha" && + game.hasPlayer(function (current) { + return current != player && !event.targets.includes(current) && lib.filter.targetEnabled(event.card, event.player, current); + }) + ); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2("stdqiuyuan"), function (card, player, target) { + var evt = _status.event.getTrigger(); + return target != player && !evt.targets.includes(target) && lib.filter.targetEnabled(evt.card, evt.player, target); + }) + .set("ai", function (target) { + var trigger = _status.event.getTrigger(); + var player = _status.event.player; + return get.effect(target, trigger.card, trigger.player, player) + 0.1; + }) + .set("targets", trigger.targets) + .set("playerx", trigger.player).forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + const result = await target + .chooseCard("交给" + get.translation(player) + "一张牌,或成为此杀的额外目标") + .set("ai", function (card) { + return get.attitude(target, _status.event.sourcex) >= 0 ? 1 : -1; + }) + .set("sourcex", player).forResult(); + if (result.bool) { + await target.give(result.cards, player); + game.delay(); + } else { + trigger.getParent().targets.push(target); + trigger.getParent().triggeredTargets2.push(target); + game.log(target, "成为了额外目标"); + } + }, + ai: { + expose: 0.2, + effect: { + target_use(card, player, target) { + if (card.name != "sha") return; + var players = game.filterPlayer(); + if (get.attitude(player, target) <= 0) { + for (var i = 0; i < players.length; i++) { + var target2 = players[i]; + if (player != target2 && target != target2 && player.canUse(card, target2, false) && get.effect(target2, { name: "shacopy", nature: card.nature, suit: card.suit }, player, target) > 0 && get.effect(target2, { name: "shacopy", nature: card.nature, suit: card.suit }, player, player) < 0) { + if (target.hp == target.maxHp) return 0.3; + return 0.6; + } + } + } else { + for (var i = 0; i < players.length; i++) { + var target2 = players[i]; + if (player != target2 && target != target2 && player.canUse(card, target2, false) && get.effect(target2, { name: "shacopy", nature: card.nature, suit: card.suit }, player, player) > 0) { + if (player.canUse(card, target2)) return; + if (target.hp == target.maxHp) return [0, 1]; + return [0, 0]; + } + } + } + }, + }, + }, + }, + stdzhuikong: { + audio: "rezhuikong", + trigger: { + global: "phaseZhunbeiBegin", + }, + check: function (event, player) { + if (get.attitude(player, event.player) < -2) { + var cards = player.getCards("h"); + if (cards.length > player.hp) return true; + for (var i = 0; i < cards.length; i++) { + var useful = get.useful(cards[i]); + if (useful < 5) return true; + if (get.number(cards[i]) > 9 && useful < 7) return true; + } + } + return false; + }, + filter(event, player) { + if (!player.canCompare(event.player)) return false; + return _status.connectMode && player.countCards("h") || player.countCards("h", "sha"); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseCard(get.prompt("stdzhuikong", trigger.player), "使用一张【杀】与其拼点", { name: "sha" }) + .set("ai", card => { + if (_status.event.effect) return 6 - get.value(card); + return 0; + }) + .set("effect", lib.skill.stdzhuikong.check(trigger, player)).forResult(); + event.result.targets = [trigger.player]; + }, + async content(event, trigger, player) { + const target = event.targets[0]; + const next = player.chooseToCompare(target); + if (!next.fixedResult) next.fixedResult = {}; + next.fixedResult[player.playerid] = event.cards[0]; + const result = await next.forResult(); + if (result.winner) { + const card = result[result.winner == player ? "target" : "player"]; + if (!card || !result.winner.hasUseTarget(card)) return; + await result.winner.chooseUseTarget(card); + } + }, + }, + //关兴 + stdwuyou: { + audio: 2, + enable: "phaseUse", + usable: 1, + filter(event, player) { + return game.hasPlayer(current => player.canCompare(current)); + }, + filterTarget(card, player, target) { + return player.canCompare(target); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + const { result } = await player.chooseToCompare(target); + if (!result.bool) { + player.addTempSkill(event.name + "_effect"); + await player.addAdditionalSkills(event.name + "_effect", "new_rewusheng"); + } + const winner = result.winner; + if (!winner) return; + const loser = player == winner ? target : player; + const juedou = get.autoViewAs({ name: "juedou", isCard: true }); + if (winner.canUse(juedou, loser, false)) await winner.useCard(juedou, loser, false); + }, + ai: { + order: 9, + result: { + target(player, target) { + return get.effect(target, { name: "juedou" }, player, player) * get.attitude(player, target); + }, + }, + }, + derivation: "new_rewusheng", + subSkill: { + effect: { + charlotte: true, + mark: true, + marktext: "佑", + intro: { + content: "视为拥有〖武圣〗", + }, + }, + }, + }, + + //四象封印·少阴 + //孙皓 + stdcanshi: { + audio: "canshi", + inherit: "canshi", + forced: true, + async content(event, trigger, player) { + trigger.changeToZero(); + await player.draw( + Math.max( + 1, + game.countPlayer(target => { + if (player.hasSkill("guiming") && target != player && target.group == "wu") return true; + return target.isDamaged(); + }) + ) + ); + player.addTempSkill("stdcanshi_effect"); + }, + subSkill: { + effect: { + charlotte: true, + trigger: { player: "useCardToPlayered" }, + filter(event, player) { + if (event.card.name != "sha" && get.type(event.card) != "trick") return false; + return event.target.isDamaged() && player.countCards("he"); + }, + forced: true, + autodelay: true, + content() { + player.chooseToDiscard("he", true); + }, + }, + }, + }, + //马腾 + stdxiongyi: { + unique: true, + limited: true, + audio: "xiongyi", + enable: "phaseUse", + filterTarget: true, + selectTarget: [1, Infinity], + multitarget: true, + multiline: true, + skillAnimation: true, + animationColor: "thunder", + async content(event, trigger, player) { + player.awakenSkill("stdxiongyi"); + const targets = event.targets.sortBySeat(); + let keep = true; + while (true) { + let stop = false; + for (const target of targets) { + let next = target + .chooseToUse(function (card) { + const event = get.event(); + if (!lib.filter.cardEnabled(card, event.player, event)) return false; + return get.name(card) == "sha"; + }, "雄异:是否使用一张不可被响应的【杀】?") + .set("oncard", card => { + _status.event.directHit.addArray(game.players); + }); + if (!keep) next.set("prompt2", "若你不使用,则结束此流程"); + const result = await next.forResult(); + if (!result.bool && !keep) { + stop = true; + break; + } + } + if (keep) keep = false; + if (stop) break; + } + }, + ai: { + order: 10, + result: { + target(player, target) { + if (player.hasUnknown()) return 0; + return target.countCards("hs"); + }, + }, + }, + }, + stdyouji: { + audio: 2, + trigger: { player: "phaseZhunbeiBegin" }, + filter(event, player) { + return player.canMoveCard( + null, + true, + game.filterPlayer(i => { + return i.group == "qun"; + }), + card => { + return [3, 4, 6].includes(parseInt(get.subtype(card).slice("equip".length))); + }, + "nojudge" + ); + }, + direct: true, + zhuSkill: true, + content() { + player + .moveCard( + game.filterPlayer(i => { + return i.group == "qun"; + }), + card => { + return [3, 4, 6].includes(parseInt(get.subtype(card).slice("equip".length))); + } + ) + .set("prompt", get.prompt2("stdyouji")) + .set("nojudge", true) + .set("logSkill", "stdyouji"); + }, + }, + //马云禄 + stdfengpo: { + audio: "fengpo", + trigger: { source: "damageBegin1" }, + filter(event, player) { + return ( + event.card.name == "sha" && + [player, event.player].some(target => { + return target.isIn() && target.countCards("he"); + }) + ); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2("stdfengpo"), (card, player, target) => { + const event = get.event().getTrigger(); + return [player, event.player] + .filter(targetx => { + return targetx.isIn() && targetx.countCards("he"); + }) + .includes(target); + }) + .set("ai", target => { + const player = get.event("player"), + aim = get.event().getTrigger().player; + let eff = get.damageEffect(aim, player, player); + if (aim === player && player.getDiscardableCards(player, "he", card => get.suit(card) == "diamond")) eff /= 4; + return eff + get.effect(target, { name: "guohe" }, player, player); + }) + .forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + const result = await player + .discardPlayerCard(target, "he", true) + .set("ai", button => { + const suit = get.suit(button.link); + return get.event().att * (suit == "diamond" ? 5 : 1) * get.value(button.link, player); + }) + .set("prompt", "凤魄:弃置" + (target != player ? get.translation(target) : "") + "一张牌") + .set("prompt2", "若弃置了方片牌,则此伤害+1") + .set("att", get.sgnAttitude(player, target)) + .forResult(); + if (result.bool) { + if (result.cards && result.cards.some(i => get.suit(i, target) == "diamond")) { + player.popup("洗具"); + trigger.increase("num"); + } + } + }, + }, + //蒋干 + stddaoshu: { + audio: "daoshu", + trigger: { global: "phaseZhunbeiBegin" }, + filter(event, player) { + return game.hasPlayer(target => { + return target != event.player && target.countCards("h"); + }); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2("stddaoshu"), (card, player, target) => { + const event = get.event().getTrigger(); + return target != event.player && target.countCards("h"); + }) + .set("ai", target => { + const player = get.event("player"); + return -1 / target.countCards("h"); + }) + .forResult(); + }, + async content(event, trigger, player) { + player.tempBanSkill("stddaoshu", "roundStart", false); + const target = event.targets[0]; + const result = await player.choosePlayerCard(target, "h", true).forResult(); + if (result.bool) { + const cards = result.cards || []; + if (cards.length) { + await player.showCards(cards, get.translation(player) + "发动了【盗书】"); + await trigger.player.gain(cards, target, "give"); + const suits = cards.reduce((list, card) => { + return list.add(get.suit(card, target)); + }, []); + if (suits.length) { + for (const i of [player, trigger.player]) { + i.addTempSkill("stddaoshu_effect"); + i.markAuto("stddaoshu_effect", suits); + } + } + } + } + }, + subSkill: { + effect: { + charlotte: true, + onremove: true, + mod: { + cardEnabled(card, player) { + if (player.getStorage("stddaoshu_effect").includes(get.suit(card))) return false; + }, + cardSavable(card, player) { + if (player.getStorage("stddaoshu_effect").includes(get.suit(card))) return false; + }, + }, + intro: { content: "不能使用$花色的牌" }, + }, + }, + }, + stddaizui: { + audio: "spdaizui", + trigger: { player: "damageEnd" }, + filter(event, player) { + return player.isTempBanned("stddaoshu"); + }, + forced: true, + content() { + delete player.storage.temp_ban_stddaoshu; + player.popup("盗书"); + game.log(player, "重置了技能", "#g【盗书】"); + }, + ai: { + combo: "stddaoshu" + }, + }, + //周处 + stdxiongxia: { + audio: "xianghai", + enable: "chooseToUse", + filterCard: true, + selectCard: 2, + position: "hes", + viewAs: { name: "juedou" }, + selectTarget: 2, + viewAsFilter(player) { + if (player.countCards("hes") < 2) return false; + }, + check(card) { + if (get.name(card) == "sha") return 4 - get.value(card); + return 7.5 - get.value(card); + }, + onuse(links, player) { + player.addTempSkill("stdxiongxia_effect"); + }, + subSkill: { + effect: { + charlotte: true, + trigger: { player: "useCardAfter" }, + filter(event, player) { + return ( + event.skill == "stdxiongxia" && + (event.targets || []).every(target => { + return target.getHistory("damage", evt => { + return evt.card && evt.card == event.card; + }).length; + }) + ); + }, + forced: true, + popup: false, + content() { + player.tempBanSkill("stdxiongxia"); + }, + }, + }, + }, + //吕玲绮 + stdhuizhan: { + audio: "guowu", + trigger: { player: "useCard2" }, + filter(event, player) { + if (event.card.name != "sha") return false; + return game.hasPlayer(target => { + return !event.targets.includes(target) && lib.filter.targetEnabled2(event.card, player, target) && lib.filter.targetInRange(event.card, player, target); + }); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget( + get.prompt2("stdhuizhan"), + (card, player, target) => { + const event = get.event().getTrigger(); + return !event.targets.includes(target) && lib.filter.targetEnabled2(event.card, player, target) && lib.filter.targetInRange(event.card, player, target); + }, + [1, 2] + ) + .set("ai", target => { + const player = get.event("player"), + event = get.event().getTrigger(); + return get.effect(target, event.card, player); + }) + .forResult(); + }, + async content(event, trigger, player) { + trigger.targets.addArray(event.targets); + player.addTempSkill("stdhuizhan_effect"); + trigger.card.stdhuizhan = true; + }, + subSkill: { + effect: { + charlotte: true, + trigger: { global: "chooseToUseBegin" }, + filter(event, player) { + if (event._stdhuizhan_effect) return false; + const evt = event.getParent(2); + return evt.card && evt.card.stdhuizhan; + }, + forced: true, + popup: false, + forceDie: true, + async content(event, trigger, player) { + trigger._stdhuizhan_effect = true; + const targets = trigger + .getParent(2) + .targets.filter(i => { + return i != trigger.player; + }) + .sortBySeat(); + if (targets.length) { + for (const target of targets) { + if (!target.isIn()) continue; + const next = target.chooseToUse("挥战:是否替" + get.translation(trigger.player) + "使用一张【闪】?", { name: "shan" }); + next.set("ai", () => { + const event = _status.event; + return get.attitude(event.player, event.source) - 2; + }); + next.set("skillwarn", "替" + get.translation(player) + "打出一张闪"); + next.autochoose = lib.filter.autoRespondShan; + next.set("source", player); + const result = await next.forResult(); + if (result.bool) { + trigger.result = { bool: true, card: { name: "shan", isCard: true, cards: result.cards.slice() }, cards: result.cards.slice() }; + trigger.responded = true; + trigger.animate = false; + break; + } + } + } + }, + }, + }, + }, + //羊祜 + stdmingfa: { + audio: "dcmingfa", + enable: "phaseUse", + filter(event, player) { + return game.hasPlayer(target => target.getHp() > 1); + }, + filterTarget(card, player, target) { + return target.getHp() > 1; + }, + async content(event, trigger, player) { + const target = event.target; + await target.damage(); + if (target.isIn()) { + player.tempBanSkill("stdmingfa", "forever"); + player.addSkill("stdmingfa_used"); + player.markAuto("stdmingfa_used", [target]); + } + }, + subSkill: { + used: { + charlotte: true, + onremove: true, + trigger: { global: ["dieAfter", "recoverAfter"] }, + filter(event, player) { + return player.getStorage("stdmingfa_used").includes(event.player); + }, + forced: true, + popup: false, + content() { + delete player.storage[`temp_ban_stdmingfa`]; + player.popup("明伐"); + game.log(player, "恢复了技能", "#g【明伐】"); + player.removeSkill("stdmingfa_used"); + }, + }, + }, + ai: { + order: 10, + result: { + target(player, target) { + return get.sgn(get.attitude(player, target)) * get.damageEffect(target, player, player); + }, + }, + }, + }, + //骆统 + stdrenzheng: { + audio: "renzheng", + trigger: { global: ["damageCancelled", "damageZero"] }, + filter(event, player, name) { + if (!_status.currentPhase || !_status.currentPhase.isIn()) return false; + if (name == "damageCancelled") return true; + return event.change_history.some(i => i < 0); + }, + forced: true, + logTarget: () => _status.currentPhase, + content() { + _status.currentPhase.draw(); + }, + }, + stdjinjian: { + audio: "jinjian", + trigger: { source: "damageBegin1" }, + logTarget: "player", + filter: function (event, player) { + return !event.stdjinjian_source2 && !player.hasSkill("stdjinjian_source2"); + }, + prompt2: "令即将对其造成的伤害+1", + check: function (event, player) { + return ( + get.attitude(player, event.player) < 0 && + !event.player.hasSkillTag("filterDamage", null, { + player: player, + card: event.card, + }) + ); + }, + usable: 1, + content: function () { + trigger.stdjinjian_source = true; + trigger.num++; + player.addTempSkill("stdjinjian_source2"); + }, + group: "stdjinjian_player", + subSkill: { + player: { + audio: "jinjian", + trigger: { player: "damageBegin4" }, + filter: function (event, player) { + return !event.stdjinjian_player2 && !player.hasSkill("stdjinjian_player2"); + }, + prompt2: "令即将受到的伤害-1", + usable: 1, + content: function () { + trigger.stdjinjian_player = true; + trigger.num--; + player.addTempSkill("stdjinjian_player2"); + }, + }, + source2: { + trigger: { source: "damageBegin1" }, + forced: true, + charlotte: true, + filter: function (event, player) { + return !event.stdjinjian_source; + }, + content: function () { + trigger.num--; + trigger.stdjinjian_source2 = true; + player.removeSkill("stdjinjian_source2"); + }, + marktext: " -1 ", + intro: { + content: "下次造成的伤害-1", + }, + }, + player2: { + trigger: { player: "damageBegin3" }, + forced: true, + charlotte: true, + filter: function (event, player) { + return !event.stdjinjian_player; + }, + content: function () { + trigger.num++; + trigger.stdjinjian_player2 = true; + player.removeSkill("stdjinjian_player2"); + }, + marktext: " +1 ", + intro: { + content: "下次受到的伤害+1", + }, + }, + }, + ai: { + maixie_defend: true, + threaten: 0.9, + effect: { + target: function (card, player, target) { + if (player.hasSkillTag("jueqing", false, target)) return; + if (player._stdjinjian_tmp) return; + const count = player.storage.counttrigger; + if (count && count.stdjinjian_player && count.stdjinjian_player > 0) return; + if (_status.event.getParent("useCard", true) || _status.event.getParent("_wuxie", true)) return; + if (get.tag(card, "damage")) { + if (target.hasSkill("stdjinjian_player2")) { + return [1, -2]; + } else { + if (get.attitude(player, target) > 0) { + return [0, 0.2]; + } + if (get.attitude(player, target) < 0 && !player.hasSkillTag("damageBonus")) { + var sha = player.getCardUsable({ name: "sha" }); + player._stdjinjian_tmp = true; + var num = player.countCards("h", function (card) { + if (card.name == "sha") { + if (sha == 0) { + return false; + } else { + sha--; + } + } + return get.tag(card, "damage") && player.canUse(card, target) && get.effect(target, card, player, player) > 0; + }); + delete player._stdjinjian_tmp; + if (player.hasSkillTag("damage")) { + num++; + } + if (num < 2) { + return [0, 0.8]; + } + } + } + } + }, + }, + }, + }, + //李傕 + stdxiongsuan: { + audio: "xinfu_langxi", + trigger: { player: "phaseZhunbeiBegin" }, + filter(event, player) { + return player.isMaxHp(); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget( + "请选择【凶算】的目标", + lib.translate.stdxiongsuan_info, + (card, player, target) => { + return target.getHp() == player.getHp(); + }, + [1, Infinity], + true + ) + .set("ai", target => { + const player = get.event("player"); + return get.damageEffect(target, player, player); + }) + .forResult(); + }, + locked: true, + async content(event, trigger, player) { + for (const i of event.targets) { + await i.damage(); + } + }, + ai: { + effect: { + target(card, player, target) { + if ( + target.hp <= 1 || + !target.hasFriend() || + !_status.currentPhase || + !get.tag(card, "damage") + ) return; + let hp = target.hp - 1; + if (game.hasPlayer(cur => { + return cur.hp > hp; + })) return; + let ori = game.countPlayer(cur => { + return cur.hp === hp + 1 && get.attitude(target, cur) <= 0; + }), now = game.countPlayer(cur => { + return cur.hp === hp && get.attitude(target, cur) <= 0; + }), seat = 1, tar = _status.currentPhase.next; + while (tar !== target) { + if (get.attitude(target, tar) <= 0) seat++; + tar = tar.next; + } + return [1, 2 * (now - ori) / seat]; + } + } + } + }, + //程普 + stdchunlao: { + audio: "chunlao", + trigger: { player: "phaseDiscardEnd" }, + filter(event, player) { + return ( + (event.cards || []).length >= 2 && + game.hasPlayer(target => { + return target != player && target.countCards("h"); + }) + ); + }, + async cost(event, trigger, player) { + const cards = trigger.cards; + event.result = await player + .chooseTarget(get.prompt("stdchunlao"), "用" + get.translation(cards) + "交换一名其他角色的手牌", (card, player, target) => { + return target != player && target.countCards("h"); + }) + .set("ai", target => { + return get.event("cards").length - target.countCards("h") - 0.5; + }) + .set("cards", cards) + .forResult(); + }, + async content(event, trigger, player) { + const cards = trigger.cards, + target = event.targets[0]; + await target.loseToDiscardpile(target.getCards("h")); + await target.gain(cards, "gain2").set("giver", player); + if (player.isDamaged()) { + const bool = await target + .chooseBool("是否令" + get.translation(player) + "回复1点体力?") + .set("choice", get.recoverEffect(player, target, target) > 0) + .forResult("bool"); + if (bool) { + target.line(player); + await player.recover(); + } + } + }, + }, + //文鸯 + stdquedi: { + audio: "dbquedi", + enable: "chooseToUse", + filterCard: { name: "sha" }, + position: "hes", + viewAs: { name: "juedou" }, + viewAsFilter(player) { + if (!player.countCards("hes", { name: "sha" })) return false; + }, + check(card) { + return 6 - get.value(card); + }, + }, + //邓芝 + //只因盟 + stdzhiyinmeng: { + audio: "weimeng", + trigger: { player: "phaseZhunbeiBegin" }, + filter(event, player) { + return player.countCards("he"); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseCardTarget({ + prompt: get.prompt2("stdzhiyinmeng"), + filterTarget: lib.filter.notMe, + filterCard: true, + position: "he", + selectCard: [1, Infinity], + complexCard: true, + complexTarget: true, + complexSelect: true, + ai1(card) { + if (ui.selected.cards.length && card.name != "du") return 0; + if (card.name == "du") return 114514; + return 5 - get.value(card); + }, + ai2(target) { + if (!ui.selected.cards.length) return 0; + const player = get.event("player"), + att = get.attitude(player, target); + if (ui.selected.cards[0].name == "du") { + if (!target.hasSkillTag("nodu")) return -att; + return -0.00001 * att; + } + return att; + }, + }) + .forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + await player.give(event.cards, target); + await target.chooseToGive("he", [1, Infinity], player); + }, + }, + stdhehe: { + audio: "jianliang", + trigger: { player: "phaseDrawEnd" }, + filter(event, player) { + return game.hasPlayer(target => { + return target != player && target.countCards("h") == player.countCards("h"); + }); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget( + get.prompt2("stdhehe"), + (card, player, target) => { + return target != player && target.countCards("h") == player.countCards("h"); + }, + [1, 2] + ) + .set("ai", target => { + const player = get.event("player"); + return get.effect(target, { name: "draw" }, player, player); + }) + .forResult(); + }, + locked: true, + async content(event, trigger, player) { + await game.asyncDraw(event.targets); + await game.delayx(); + }, + }, + //张翼 + stdzhiyi: { + audio: "zhiyi", + trigger: { global: "phaseEnd" }, + filter(event, player) { + return player.getHistory("useCard", evt => { + return evt.card.name == "sha"; + }).length; + }, + forced: true, + async content(event, trigger, player) { + const result = await player.chooseUseTarget("执义:视为使用【杀】,或摸一张牌", { name: "sha" }, false).forResult(); + if (!result.bool) await player.draw(); + }, + }, + //大魏汉尼拔 + stdshefu: { + audio: "shefu", + trigger: { player: "phaseJieshuBegin" }, + filter(event, player) { + return player.countCards("h"); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseCard(get.prompt("stdshefu"), "将一张手牌置于武将牌上", "h") + .set("ai", card => { + return ( + (lib.card.list + .slice() + .map(list => list[2]) + .filter(name => { + return card.name == name; + }).length - + 1) / + (get.value(card) || 0.5) + ); + }) + .forResult(); + }, + content() { + player.addToExpansion(event.cards, player, "giveAuto").gaintag.add("stdshefu"); + }, + marktext: "伏", + intro: { + markcount: "expansion", + mark(dialog, _, player) { + const cards = player.getExpansions("stdshefu"); + if (player.isUnderControl(true) && cards.length) dialog.addAuto(cards); + else return "共有" + get.cnNumber(cards.length) + "张“伏兵”"; + }, + }, + onremove(player, skill) { + const cards = player.getExpansions(skill); + if (cards.length) player.loseToDiscardpile(cards); + }, + group: "stdshefu_effect", + subSkill: { + effect: { + audio: "shefu", + trigger: { global: "useCard" }, + filter(event, player) { + return player.getExpansions("stdshefu").some(card => card.name == event.card.name); + }, + async cost(event, trigger, player) { + let result = await player + .chooseButton(["###" + get.prompt("stdshefu") + "###弃置一张同名牌,令此牌无效", player.getExpansions("stdshefu")]) + .set("filterButton", button => { + return button.link.name == get.event().getTrigger().card.name; + }) + .set("ai", button => { + return get.event("goon") ? 1 : 0; + }) + .set("goon", lib.skill.sbkanpo.subSkill.kanpo.check(trigger, player)) + .forResult(); + if (result.bool && result.links) { + result.cards = result.links.slice(); + delete result.links; + } + event.result = result; + }, + async content(event, trigger, player) { + await player.loseToDiscardpile(event.cards); + trigger.targets.length = 0; + trigger.all_excluded = true; + }, + }, + }, + }, + stdyibing: { + audio: "benyu", + trigger: { global: "dying" }, + filter(event, player) { + return event.player != player && event.player.countCards("h"); + }, + direct: true, + content() { + const target = trigger.player; + player.gainPlayerCard(target, "h", true).set("prompt", get.prompt("stdyibing", target)).logSkill = ["stdyibing", target]; + }, + }, + //樊玉凤 + stdbazhan: { + audio: "bazhan", + enable: "phaseUse", + filter(event, player) { + return player.countCards("h") > 0; + }, + filterCard: true, + position: "h", + filterTarget(card, player, target) { + return target != player && target.hasSex("male"); + }, + discard: false, + lose: false, + delay: false, + usable: 1, + check(card) { + if (card.name == "du") return 114514; + return 5 - get.value(card); + }, + async content(event, trigger, player) { + const target = event.target; + await player.give(event.cards, target, "visible"); + await target + .chooseToGive( + player, + (card, player) => { + return get.type2(card) != get.type2(get.event("cards")[0]); + }, + "he" + ) + .set("cards", event.cards); + }, + ai: { + order: 10, + result: { + target(player, target) { + if (!ui.selected.cards.length) return 0; + const cardxx = ui.selected.cards[0]; + if (cardxx.name == "du") return -100; + if (!player.hasSkill("stdzhanying")) return 1; + if (target.countMark("stdzhanying_count") == target.countCards("h") + 1) { + const cards = player.getCards("hs", card => { + return card != cardxx && get.tag(card, "damage") && player.canUse(card, target) && get.effect(target, card, player, player) > 0; + }); + if (!cards.length) return 1; + let cardx = cards.filter(card => get.name(card) == "sha"); + cardx.sort((a, b) => get.effect(target, b, player, player) - get.effect(target, a, player, player)); + cardx = cardx.slice(Math.min(cardx.length, player.getCardUsable("sha")), cardx.length); + cards.removeArray(cardx); + return -cards.reduce((sum, card) => sum + get.effect(target, card, player, player), 0); + } + return 1; + }, + }, + }, + }, + stdzhanying: { + audio: "jiaoying", + trigger: { global: "damageBegin2" }, + filter(event, player) { + if (_status.currentPhase !== player) return false; + return event.player.countCards("h") > event.player.countMark("stdzhanying_count"); + }, + forced: true, + logTarget: "player", + content() { + trigger.increase("num"); + }, + global: "stdzhanying_mark", + subSkill: { + count: { + charlotte: true, + onremove: true, + intro: { + markcount: storage => (storage || 0).toString(), + content: "本回合开始时手牌数为#张", + }, + }, + mark: { + charlotte: true, + trigger: { global: "phaseBegin" }, + filter(event, player) { + return event.player.hasSkill("stdzhanying", null, null, false); + }, + forced: true, + popup: false, + firstDo: true, + content() { + player.addTempSkill("stdzhanying_count"); + player.addMark("stdzhanying_count", player.countCards("h"), false); + }, + mod: { + cardEnabled(card, player) { + if (!_status.currentPhase || !_status.currentPhase.hasSkill("stdzhanying")) return; + if (get.color(card) == "red" && player.countMark("stdzhanying_count") < player.countCards("h")) return false; + }, + cardSavable(card, player) { + if (!_status.currentPhase || !_status.currentPhase.hasSkill("stdzhanying")) return; + if (get.color(card) == "red" && player.countMark("stdzhanying_count") < player.countCards("h")) return false; + }, + }, + }, + }, + }, + //F1 + stdtiaohe: { + audio: "fyjianyu", + enable: "phaseUse", + usable: 1, + filter(event, player) { + return game.hasPlayer(tar1 => { + return tar1.countDiscardableCards(player, "e", i => get.subtype(i) == "equip2") && game.hasPlayer(tar2 => { + return tar1 !== tar2 && tar2.countDiscardableCards(player, "e"); + }); + }); + let e = 0, fj = false; + game.countPlayer(target => { + let es = target.getDiscardableCards(player, "e"), js = target.getDiscardableCards(player, "j", i => get.type(i) == "equip"); + if (es.length) e++; + e += js.length; + if (!fj && (es.some(card => get.subtype(card) == "equip2") || js.some(card => get.subtype(card) == "equip2"))) fj = true; + }); + return fj && e >= 2; + }, + filterTarget(card, player, target) { + if (!ui.selected.targets.length || ui.selected.targets[0].countDiscardableCards(player, "e", i => get.subtype(i) == "equip2")) { + return target.countDiscardableCards(player, "e"); + } + return target.countDiscardableCards(player, "e", i => get.subtype(i) == "equip2"); + let e = 0; + let es = target.getDiscardableCards(player, "e"), js = target.getDiscardableCards(player, "j", i => get.type(i) == "equip"); + if (es.length) e++; + e += js.length; + if (!e) return false; + if (!ui.selected.targets.length) return true; + if (!ui.selected.targets[0].countDiscardableCards(player, "ej", i => get.subtype(i) == "equip2")) { + return es.some(card => get.subtype(card) == "equip2") || js.some(card => get.subtype(card) == "equip2"); + } + return true; + }, + selectTarget: function () { + return 2; + if (!ui.selected.targets.length) return [1, 2]; + let e = 0, player = get.event("player"), target = ui.selected.targets[0]; + let es = target.getDiscardableCards(player, "e"), js = target.getDiscardableCards(player, "j", i => get.type(i) == "equip"); + if (es.length) e++; + e += js.length; + if (e >= 2 && (es.some(card => get.subtype(card) == "equip2") || js.some(card => get.subtype(card) == "equip2"))) return [1, 2]; + return 2; + }, + complexTarget: true, + multitarget: true, + multiline: true, + async content(event, trigger, player) { + const targets = event.targets.slice(); + if (targets.length == 1) { + await player.discardPlayerCard("ej", targets[0], true, 2).set("filterButton", button => { + let position = get.position(button.link), subtype = get.subtype(button.link); + if (!subtype || !subtype.startsWith("equip")) return false; + if (ui.selected.buttons.length) { + let pos = get.position(ui.selected.buttons[0].link), sub = get.subtype(ui.selected.buttons[0].link); + if (pos == "e" && position == "e") return false; + if (sub == "equip2") return true; + return subtype == "equip2"; + } + if (position == "e") { + if (!get.event("js").some(i => get.subtype(i) == "equip2")) return subtype == "equip2"; + return true; + } + if (!get.event("es").length) return subtype == "equip2"; + return true; + }).set("es", targets[0].getDiscardableCards(player, "e", i => get.subtype(i) == "equip2")).set("js", targets[0].getDiscardableCards(player, "j", i => get.type(i) == "equip")); + return; + } + let canfj = targets.filter(target => { + return target.countDiscardableCards(player, "e", i => get.subtype(i) == "equip2"); + }); + for (let i = 0; i < 2; i++) { + if (i && canfj.includes(targets[i]) && !targets[i].countDiscardableCards(player, "e", i => get.subtype(i) == "equip2")) break; + const result = await player + .discardPlayerCard("e", targets[i], true) + .set("filterButton", button => { + if (get.event("fj")) return get.subtype(button.link) == "equip2"; + return true; + return get.type(button.link) == "equip"; + }) + .set("fj", canfj.length === 1 && canfj.includes(targets[i])) + .forResult(); + if (result.bool && get.subtype(result.cards[0]) == "equip2") { + canfj = []; + } + } + }, + ai: { + order: 10, + result: { + target(player, target) { + let att = get.attitude(player, target), es = []; + target.countDiscardableCards(player, "e", i => { + es.push(get.value(i, target)); + }); + let min = Math.min(...es), max = Math.max(...es), ext = target.hasSkillTag("noe") ? 10 : 0; + if (att <= 0) return ext - max; + return ext - min; + } + }, + }, + }, + stdqiansu: { + audio: "shengxi_feiyi", + trigger: { target: "useCardToTargeted" }, + filter(event, player) { + return get.type2(event.card) == "trick" && !player.countCards("e"); + }, + frequent: true, + content() { + player.draw(); + }, + ai: { + noe: true, + effect: { + target(card, player, target) { + if (target.countCards("e")) return; + if (target == player && get.type(card) == "equip" && get.equipValue(card) < 5) return 0; + if (get.type2(card) == "trick") return [1, 0.6]; + }, + }, + }, + }, +}; + +export default skills; diff --git a/character/sixiang/sort.js b/character/sixiang/sort.js new file mode 100644 index 0000000000..bd7cd5f8fd --- /dev/null +++ b/character/sixiang/sort.js @@ -0,0 +1,13 @@ +const characterSort = { + sixiang_shaoyin: ["std_sunhao", "std_mateng", "std_mayunlu", "std_jianggan", "std_zhouchu", "std_lvlingqi", "std_dc_yanghu", "std_dc_luotong", "std_lijue", "std_chengpu", "std_db_wenyang", "std_re_dengzhi", "std_zhangyì", "std_chengyu", "std_fanyufeng", "std_feiyi"], + sixiang_taiyin: ["std_guanxing", "std_fuhuanghou", "std_liubiao", "std_gongsunyuan", "std_cenhun", "std_simashi", "std_sunshao", "std_jiangwan", "std_maliang", "std_xushu", "std_xuezong", "std_liuzhang", "std_wangyuanji", "std_wanglang", "std_zhonghui", "std_huaxin"], + sixiang_trashBin: ["old_shen_zhaoyun", "std_pengyang"], +}; + +const characterSortTranslate = { + sixiang_shaoyin: "四象封印·少阴", + sixiang_taiyin: "四象封印·太阴", + sixiang_trashBin: "四象封印·垃圾桶", +}; + +export { characterSort, characterSortTranslate }; diff --git a/character/sixiang/translate.js b/character/sixiang/translate.js new file mode 100644 index 0000000000..c3a78c41cb --- /dev/null +++ b/character/sixiang/translate.js @@ -0,0 +1,189 @@ +const translates = { + sixiang: "四象封印", + std_sunhao: "标孙皓", + std_sunhao_prefix: "标", + std_mateng: "标马腾", + std_mateng_prefix: "标", + std_mayunlu: "标马云騄", + std_mayunlu_prefix: "标", + std_jianggan: "标蒋干", + std_jianggan_prefix: "标", + std_zhouchu: "标周处", + std_zhouchu_prefix: "标", + std_lvlingqi: "标吕玲绮", + std_lvlingqi_prefix: "标", + std_dc_yanghu: "标羊祜", + std_dc_yanghu_prefix: "标", + std_dc_luotong: "标骆统", + std_dc_luotong_prefix: "标", + std_lijue: "标李傕", + std_lijue_prefix: "标", + std_chengpu: "标程普", + std_chengpu_prefix: "标", + std_db_wenyang: "标文鸯", + std_db_wenyang_prefix: "标", + std_re_dengzhi: "标邓芝", + std_re_dengzhi_prefix: "标", + std_zhangyì: "标张翼", + std_zhangyì_prefix: "标", + std_chengyu: "标程昱", + std_chengyu_prefix: "标", + std_fanyufeng: "标樊玉凤", + std_fanyufeng_prefix: "标", + std_feiyi: "标费祎", + std_feiyi_prefix: "标", + stdcanshi: "残蚀", + stdcanshi_info: "锁定技,摸牌阶段,你改为摸X张牌(X为场上的已受伤角色且X至少为1)。然后本回合你使用【杀】或普通锦囊牌指定目标后,若其已受伤,你弃置一张牌。", + stdxiongyi: "雄异", + stdxiongyi_info: "限定技,出牌阶段,你可以选择任意名角色,这些角色依次选择是否使用一张不可被响应的【杀】,然后这些角色重复此流程直至有角色不使用【杀】。", + stdyouji: "游骑", + stdyouji_info: "主公技,准备阶段,你可以移动一名群势力角色的一张坐骑牌。", + stdfengpo: "凤魄", + stdfengpo_info: "当你使用【杀】造成伤害时,你可以弃置你或其的一张牌,若以此法弃置了方片牌,则此伤害+1。", + stddaoshu: "盗书", + stddaoshu_info: "每轮限一次,一名角色的准备阶段,你可以展示除其外一名角色的一张牌,然后令其获得此牌,且你与其本回合不能使用与此牌花色相同的牌。", + stddaizui: "戴罪", + stddaizui_info: "锁定技,当你受到伤害后,你视为本轮未发动过〖盗书〗。", + stdxiongxia: "凶侠", + stdxiongxia_info: "你可以将两张牌当作【决斗】对两名其他角色使用。你以此法使用的【决斗】结算完毕后,若所有目标角色都受到了此牌造成的伤害,则〖凶侠〗于本回合失效。", + stdhuizhan: "挥戟", + stdhuizhan_info: "你使用【杀】可以额外指定至多两个目标。若如此做,目标角色响应此【杀】时,其他目标角色可以代替其使用【闪】。", + stdmingfa: "明伐", + stdmingfa_info: "出牌阶段,你可以对一名体力值大于1的角色造成1点伤害,然后此技能失效直至其死亡或回复体力。", + stdjinjian: "进谏", + stdjinjian_info: "每回合每项各限一次,当你造成/受到伤害时,你可令此伤害+1/-1,然后你本回合内下一次造成的伤害-1/+1且不能触发〖进谏〗。", + stdrenzheng: "仁政", + stdrenzheng_info: "锁定技,当有伤害被防止时,你令当前回合角色摸一张牌。", + stdxiongsuan: "凶算", + stdxiongsuan_info: "锁定技,准备阶段,若你的体力值为全场最多,则你须对至少一名体力值等于你的角色各造成1点伤害。", + stdchunlao: "醇醪", + stdchunlao_info: "弃牌阶段结束时,若你本阶段弃置了不少于两张牌,则你可以用这些牌交换一名其他角色的手牌,然后其可以令你回复1点体力。", + stdquedi: "却敌", + stdquedi_info: "你可以将【杀】当作【决斗】使用。", + stdzhiyinmeng: "急盟", + stdzhiyinmeng_info: "准备阶段,你可以交给一名其他角色任意张牌,然后其可以交给你任意张牌。", + stdhehe: "和合", + stdhehe_info: "摸牌阶段结束时,你可以令至多两名手牌数与你相同的其他角色各摸一张牌。", + stdzhiyi: "执义", + stdzhiyi_info: "锁定技,一名角色的回合结束时,若你本回合使用过【杀】,则你视为使用【杀】或摸一张牌。", + stdshefu: "设伏", + stdshefu_info: "①结束阶段,你可以将一张手牌称为“伏兵”扣置于武将牌上。②一名角色使用牌时,你可以移去武将牌上的一张与此牌同名的“伏兵”并令此牌无效。", + stdyibing: "益兵", + stdyibing_info: "一名角色进入濒死状态时,你可以获得其一张牌。", + stdbazhan: "把盏", + stdbazhan_info: "出牌阶段限一次,你可以交给一名男性角色一张手牌,然后其可以交给你一张与此牌类别不同的牌。", + stdzhanying: "醮影", + stdzhanying_info: "锁定技,你的回合内,手牌数比回合开始时多的角色不能使用红色牌且受到的伤害+1。", + stdtiaohe: "调和", + stdtiaohe_info: "出牌阶段限一次,你可以弃置场上的一张装备牌和一张防具牌(不能为同一名角色的牌)。", + stdqiansu: "谦素", + stdqiansu_info: "当你成为锦囊牌的目标后,若你的装备区没有牌,则你可以摸一张牌。", + + + old_shen_zhaoyun: "牢神赵云", + old_shen_zhaoyun_prefix: "牢神", + std_pengyang: "牢彭羕", + std_pengyang_prefix: "牢", + std_xushu: "标徐庶", + std_xushu_prefix: "标", + std_xuezong: "标薛综", + std_xuezong_prefix: "标", + std_liuzhang: "标刘璋", + std_liuzhang_prefix: "标", + std_wangyuanji: "标王元姬", + std_wangyuanji_prefix: "标", + std_wanglang: "标王朗", + std_wanglang_prefix: "标", + std_zhonghui: "标钟会", + std_zhonghui_prefix: "标", + std_fuhuanghou: "标伏寿", + std_fuhuanghou_prefix: "标", + std_liubiao: "标刘表", + std_liubiao_prefix: "标", + std_gongsunyuan: "标公孙渊", + std_gongsunyuan_prefix: "标", + std_cenhun: "标岑昏", + std_cenhun_prefix: "标", + std_sunshao_prefix: "标", + std_jiangwan: "标蒋琬", + std_jiangwan_prefix: "标", + std_maliang: "标马良", + std_maliang_prefix: "标", + std_simashi: "标司马师", + std_simashi_prefix: "标", + std_guanxing: "标关兴", + std_guanxing_prefix: "标", + std_huaxin: "标华歆", + std_huaxin_prefix: "标", + stdwuyou: "武佑", + stdwuyou_info: "出牌阶段限一次,你可以与一名角色进行拼点,若你没赢,你本回合视为拥有〖武圣〗。然后拼点没赢的角色视为没赢的角色使用一张【决斗】。", + stdqiuyuan: "求援", + stdqiuyuan_info: "当你成为一名角色使用【杀】的目标时,你可以令另一名其他角色选择一项:1.交给你一张牌;2.成为此【杀】的额外目标。", + stdzhuikong: "惴恐", + stdzhuikong_info: "其他角色的准备阶段,你可以用【杀】与其拼点,赢的角色可以使用对方的拼点牌。", + stdzishou: "自守", + stdzishou_info: "出牌阶段开始前,你可以摸场上势力数张牌,然后跳过此阶段。", + stdjujin: "据荆", + stdjujin_info: "主公技,当你受到其他群势力角色造成的伤害后,你可以弃置两张牌,然后回复1点体力。", + stdhuaiyi: "怀异", + stdhuaiyi_info: "锁定技,准备阶段,你展示所有手牌,若颜色不同,你弃置其中一种颜色的所有牌,然后获得至多等量名其他角色各一张牌,若选择角色数大于1,你失去1点体力。", + stdfengbai: "封拜", + stdfengbai_info: "主公技,当你获得一名群势力角色装备区内的牌后,你可以令其摸一张牌。", + stdjishe: "极奢", + stdjishe_info: "出牌阶段,若你的手牌上限大于0,你可以令本回合手牌上限-1,然后摸一张牌。", + stdwudu: "无度", + stdwudu_info: "一名没有手牌的角色受到伤害时,你可以减少1点体力上限,防止此伤害。", + stdjinglve: "景略", + stdjinglve_info: "其他角色的弃牌阶段开始时,你可以展示并交给其两张牌,令其本阶段不能弃置这些牌,然后你可以于本阶段结束时获得本阶段弃置的一张牌。", + std_sunshao: "标孙邵", + stddingyi: "定仪", + stddingyi_info: "一名角色的结束阶段,若其装备区内没有牌,其可以摸一张牌。", + stdzuici: "罪辞", + stdzuici_info: "当你受到伤害后,你可以将场上的一张牌移至伤害来源区域内。", + stdruwu: "儒武", + stdruwu_info: "你可以将装备区内一张不为本回合置入的装备牌当【无中生有】或【决斗】使用。", + stdchengshi: "承事", + stdchengshi_info: "限定技,当一名其他角色死亡时,你可以与其交换座次和装备区内的牌。", + stdxiemu: "协穆", + stdxiemu_info: "其他角色的出牌阶段限一次,其可以展示并交给你一张基本牌,然后其本回合攻击范围+1。", + stdnaman: "纳蛮", + stdnaman_info: "出牌阶段限一次,你可以将任意张基本牌当指定等量名目标的【南蛮入侵】使用。", + oldjuejing: "绝境", + oldjuejing_info: "锁定技。①摸牌阶段,你令额定摸牌数+X(X为你已损失的体力值)。②你的手牌上限+2。", + oldlonghun: "龙魂", + oldlonghun_info: "你可以将花色相同的Y张牌按下列规则使用或打出:♥当【桃】,♦当火【杀】,♣当【闪】,♠当【无懈可击】(Y为你的体力值且至少为1)。", + stdxiaofan: "嚣翻", + stdxiaofan_info: "锁定技,当你使用牌结算结束后,你弃置你前X个区域内的牌:1.判定区 2.装备区 3.手牌区(X为你本回合使用牌的类型数)。", + stdtuishi: "侻失", + stdtuishi_info: "锁定技,你不能使用【无懈可击】,你使用的字母牌无效。", + stdfunan: "复难", + stdfunan_info: "每回合限一次,其他角色使用的牌被你抵消时,你可以获得之。", + stdxunjie: "训诫", + stdxunjie_info: "结束阶段,你可以令一名角色弃置一张手牌,若此牌花色为♦️,其摸两张牌。", + stdwuyan: "无言", + stdwuyan_info: "锁定技,你的锦囊牌均视为【无懈可击】。", + stdjujian: "举荐", + stdjujian_info: "每回合限一次,你的【无懈可击】结算结束后可以交给一名其他角色。", + stdyinge: "引戈", + stdyinge_info: "出牌阶段限一次,你可以令一名其他角色摸两张牌,然后其视为对你攻击范围内的另一名角色使用一张【杀】。", + stdshiren: "施仁", + stdshiren_info: "每回合限一次,当你成为其他角色使用【杀】的目标后,你可以摸两张牌,然后交给该角色一张牌。", + stdjuyi: "据益", + stdjuyi_info: "主公技,其他群势力角色每回合首次对你造成伤害时,其可以防止此伤害,改为获得你的一张牌。", + stdqianchong: "谦冲", + stdqianchong_info: "锁定技,若你的装备区内牌的数量为奇数/偶数,你使用牌无次数/距离限制。", + stdshangjian: "尚俭", + stdshangjian_info: "结束阶段,若你本回合失去的牌数不大于你的体力值,你可以从弃牌堆中获得一张你本回合失去的牌。", + stdgushe: "鼓舌", + stdgushe_info: "出牌阶段限一次,你可以与一名角色拼点,拼点赢的角色摸一张牌,然后拼点输的角色可以与对方重复此流程。", + stdjici: "激词", + stdjici_info: "当你亮出拼点牌时,你可以失去1点体力,令此牌点数视为k。", + stdxingfa: "兴伐", + stdxingfa_info: "准备阶段,若你的手牌数不小于体力值,你可以对一名其他角色造成1点伤害。", + stdyuanqing: "渊清", + stdyuanqing_info: "回合结束时,你可以令所有角色依次选择并获得弃牌堆中其于此回合内失去的一张牌。", + stdshuchen: "疏陈", + stdshuchen_info: "你的回合外,你可以将超出手牌上限的手牌当【桃】使用。", +}; + +export default translates; diff --git a/character/sixiang/voices.js b/character/sixiang/voices.js new file mode 100644 index 0000000000..ff8b4c5632 --- /dev/null +++ b/character/sixiang/voices.js @@ -0,0 +1 @@ +export default {}; diff --git a/character/sp/card.js b/character/sp/card.js index 369ab5bda7..4c32db63c8 100644 --- a/character/sp/card.js +++ b/character/sp/card.js @@ -278,10 +278,12 @@ const cards = { forceDie: true, onLose: function () { if ((!event.getParent(2) || event.getParent(2).name != "swapEquip") && (event.getParent().type != "equip" || event.getParent().swapEquip)) { - card.fix(); - card.remove(); - card.destroyed = true; - game.log(card, "被销毁了"); + cards.forEach(card => { + card.fix(); + card.remove(); + card.destroyed = true; + game.log(card, "被销毁了"); + }); } }, equipDelay: false, @@ -304,10 +306,12 @@ const cards = { skills: ["zhuangshu_trick"], onLose: function () { if ((!event.getParent(2) || event.getParent(2).name != "swapEquip") && (event.getParent().type != "equip" || event.getParent().swapEquip)) { - card.fix(); - card.remove(); - card.destroyed = true; - game.log(card, "被销毁了"); + cards.forEach(card => { + card.fix(); + card.remove(); + card.destroyed = true; + game.log(card, "被销毁了"); + }); } }, equipDelay: false, @@ -325,10 +329,12 @@ const cards = { inherit: "zhuangshu_basic", onLose: function () { if ((!event.getParent(2) || event.getParent(2).name != "swapEquip") && (event.getParent().type != "equip" || event.getParent().swapEquip)) { - card.fix(); - card.remove(); - card.destroyed = true; - game.log(card, "被销毁了"); + cards.forEach(card => { + card.fix(); + card.remove(); + card.destroyed = true; + game.log(card, "被销毁了"); + }); } }, equipDelay: false, diff --git a/character/sp/character.js b/character/sp/character.js index aa4dba014d..557bb0932f 100644 --- a/character/sp/character.js +++ b/character/sp/character.js @@ -1,4 +1,8 @@ const characters = { + kongshu: ["female", "qun", 3, ["olleiluan", "olfuchao"]], + ol_kebineng: ["male", "qun", 4, ["olpingduan"], ["name:科比|罐头"]], + ol_yuanji: ["female", "wu", 3, ["oljieyan", "oljinghua", "olshuiyue"], ["name:袁|null"]], + ol_sunru: ["female", "wu", 3, ["olchishi", "olweimian"]], caoteng: ["male", "qun", 3, ["olyongzu", "olqingliu"]], budugen: ["male", "qun", 4, ["olkouchao"]], mawan: ["male", "qun", 4, ["mashu", "olhunjiang"]], @@ -179,6 +183,14 @@ const characters = { quyi: ["male", "qun", 4, ["fuqi", "jiaozi"]], luzhi: ["male", "wei", 3, ["qingzhong", "weijing"]], + + wangcan: ["male", "qun", 3, ["xinfu_sanwen", "xinfu_qiai", "xinfu_denglou"]], + re_jsp_pangtong: ["male", "wu", 3, ["xinfu_guolun", "xinfu_songsang"]], + lvqian: ["male", "wei", 4, ["xinfu_weilu", "xinfu_zengdao"]], + panjun: ["male", "wu", 3, ["xinfu_guanwei", "xinfu_gongqing"]], + zhoufang: ["male", "wu", 3, ["xinfu_duanfa", "xinfu_youdi"]], + yanjun: ["male", "wu", 3, ["xinfu_guanchao", "xinfu_xunxian"]], + liuyan: ["male", "qun", 3, ["xinfu_tushe", "xinfu_limu"]], }; export default characters; diff --git a/character/sp/characterReplace.js b/character/sp/characterReplace.js index 2776141efc..73338bf471 100644 --- a/character/sp/characterReplace.js +++ b/character/sp/characterReplace.js @@ -1,18 +1,19 @@ const characterReplaces = { - guanyinping: ["guanyinping", "old_guanyinping"], + shamoke: ["shamoke", "ty_shamoke"], + guanyinping: ["guanyinping", "old_guanyinping", "ty_guanyinping"], shixie: ["shixie", "dc_shixie", "old_shixie"], caoshuang: ["caoshuang", "dc_caoshuang", "ns_caoshuang"], caoang: ["caoang", "yj_caoang", "tw_caoang"], caohong: ["caohong", "tw_re_caohong", "tw_caohong", "yj_caohong"], xiahouba: ["xiahouba", "dc_xiahouba", "tw_xiahouba"], - maliang: ["maliang", "re_maliang", "tw_maliang", "ol_maliang", "old_maliang"], + maliang: ["maliang", "re_maliang", "tw_maliang", "ol_maliang", "old_maliang", "std_maliang"], dingfeng: ["dingfeng", "tw_dingfeng", "old_dingfeng"], zumao: ["zumao", "tw_zumao"], tw_beimihu: ["beimihu", "tw_beimihu"], panfeng: ["panfeng", "re_panfeng", "std_panfeng"], sunluyu: ["sunluyu", "re_sunluyu", "mb_sunluyu"], - jin_simazhao: ["jin_simazhao", "simazhao", "sp_simazhao"], - jin_wangyuanji: ["jin_wangyuanji", "wangyuanji", "sp_wangyuanji"], + jin_simazhao: ["jin_simazhao", "simazhao", "sp_simazhao", "jd_jin_simazhao"], + jin_wangyuanji: ["jin_wangyuanji", "wangyuanji", "sp_wangyuanji", "std_wangyuanji", "jd_jin_wangyuanji"], wangyun: ["clan_wangyun", "wangyun", "dc_wangyun", "re_wangyun", "jsrg_wangyun", "old_wangyun", "pe_wangyun"], zhangliang: ["xin_zhangliang", "re_zhangliang", "zhangliang"], lingju: ["lingju", "old_lingju"], @@ -20,7 +21,7 @@ const characterReplaces = { zhangxingcai: ["zhangxingcai", "old_zhangxingcai"], lisu: ["ol_lisu", "lisu"], fuwan: ["fuwan", "tw_fuwan", "sp_fuwan"], - huaxin: ["ol_huaxin", "huaxin", "sp_huaxin"], + huaxin: ["ol_huaxin", "huaxin", "sp_huaxin", "std_huaxin", "jd_ol_huaxin"], xujing: ["xujing", "dc_xujing", "sp_xujing", "tw_xujing"], zhaoxiang: ["zhaoxiang", "dc_zhaoxiang", "tw_zhaoxiang"], dengzhi: ["ol_dengzhi", "re_dengzhi", "dengzhi", "tw_dengzhi", "std_re_dengzhi"], @@ -42,8 +43,8 @@ const characterReplaces = { zhaoyǎn: ["zhaoyǎn", "dc_zhaoyǎn"], furong: ["ol_furong", "furong", "tw_furong"], daxiaoqiao: ["daxiaoqiao", "dc_daxiaoqiao", "tw_daxiaoqiao"], - zhugeguo: ["zhugeguo", "tw_zhugeguo", "yue_zhugeguo"], - wanglang: ["ol_wanglang", "wanglang", "old_wanglang"], + zhugeguo: ["zhugeguo", "tw_zhugeguo", "yue_zhugeguo", "huan_zhugeguo"], + wanglang: ["ol_wanglang", "wanglang", "old_wanglang", "std_wanglang"], tengfanglan: ["tengfanglan", "dc_tengfanglan"], zhangyì: ["ol_zhangyì", "zhangyì", "std_zhangyì"], yuantanyuanshang: ["yuantanyuanshang", "yuantanyuanxiyuanshang"], @@ -52,18 +53,25 @@ const characterReplaces = { ganfuren: ["ganfuren", "dc_ganfuren", "jsp_ganfuren"], zhouqun: ["ol_zhouqun", "zhouqun"], qianzhao: ["ol_qianzhao", "qianzhao"], - ol_pengyang: ["ol_pengyang", "sp_pengyang"], + ol_pengyang: ["ol_pengyang", "sp_pengyang", "std_pengyang"], ol_luyusheng: ["ol_luyusheng", "luyusheng"], fanjiangzhangda: ["fanjiangzhangda", "jsrg_fanjiangzhangda"], simalang: ["re_simalang", "simalang"], zhugedan: ["re_zhugedan", "zhugedan"], zhangren: ["jsrg_zhangren", "zhangren"], - wenqin: ["ol_wenqin", "pe_wenqin"], + ol_wenqin: ["ol_wenqin", "pe_wenqin", "mb_wenqin"], lukai: ["ol_lukai", "lukai"], liupi: ["ol_liupi", "liupi"], kanze: ["kanze", "re_kanze"], lvfan: ["lvfan", "sp_lvfan"], dongbai: ["dongbai", "re_dongbai", "jsrg_dongbai"], + sp_jiaxu: ["dc_sp_jiaxu", "yj_jiaxu", "sp_jiaxu"], + duji: ["duji", "re_duji", "ns_duji"], + sp_taishici: ["sp_taishici", "re_sp_taishici"], + mazhong: ["mazhong", "re_mazhong"], + wenpin: ["wenpin", "re_wenpin"], + liuyan: ["liuyan", "jsrg_liuyan", "junk_liuyan"], + buzhi: ["buzhi", "ty_buzhi"], }; export default characterReplaces; diff --git a/character/sp/dynamicTranslate.js b/character/sp/dynamicTranslate.js index 0fcb212836..7ee010c1de 100644 --- a/character/sp/dynamicTranslate.js +++ b/character/sp/dynamicTranslate.js @@ -96,5 +96,21 @@ const dynamicTranslates = { const str = nameList.map(i => "【" + get.translation(i) + "】").join("/"); return "每轮每项限一次,你可以将一张牌当作" + str + "使用。此牌结算完毕后,将此项改为本局游戏最后一张不因使用进入弃牌堆的基本牌或普通锦囊牌的牌名,然后若〖寇钞〗的所有项均为基本牌,则你修改〖寇钞〗的所有项为【顺手牵羊】。"; }, + oljinghua(player) { + const storage = player.storage.oljinghua; + var str = "当其他角色获得你的牌后,其"; + str += storage ? "失去" : "回复"; + str += "1点体力。"; + if (!storage) str += "当你失去最后的手牌后,你可以将此技能描述中的“回复”改为“失去”。"; + return str; + }, + olshuiyue(player) { + const storage = player.storage.olshuiyue; + var str = "当其他角色受到你造成的伤害后,其"; + str += storage ? "弃置" : "摸"; + str += "一张牌。"; + if (!storage) str += "当你令其他角色进入濒死状态后,你可以将此技能描述中的“摸”改为“弃置”。"; + return str; + }, }; export default dynamicTranslates; diff --git a/character/sp/intro.js b/character/sp/intro.js index 268869f651..5daebb6c94 100644 --- a/character/sp/intro.js +++ b/character/sp/intro.js @@ -1,4 +1,5 @@ const characterIntro = { + kongshu: "孔淑,孔融之女,孔融被诛时年七岁,因和其兄年幼得以保全,寄养到了别人家中。孔淑与其兄专心博弈,周围的人好奇为何他们对孔融被诛杀之事视若无睹。孔淑回答:“安有巢毁而卵不破乎?”寄养他们的主人给他们肉汁喝,其兄口渴就喝了。孔淑说:“今天这样的祸,难道能够久活,还要知道肉味吗?”哥哥听了大哭,然后不再喝一口。后来有人将其对话说给曹操听,曹操下令将兄妹杀掉。孔淑死前跟兄长说:“如果死者有知,得见父母,岂不是我们最大的愿望!”孔淑面不改色引颈就刑。", caoteng: "曹腾(生卒年不详),字季兴,沛国谯(今安徽亳县)人,曹节(曹萌)之子,东汉宦官。永宁元年(120年),顺帝做太子时,邓太后看到曹腾年纪轻,又谨慎厚道,派其侍奉皇太子读书,因此得到顺帝宠信。顺帝即位(126年)后,曹腾任小黄门,后升迁至中常侍。因策划迎立桓帝有功,迁大长秋,被封为费亭侯,加位特进。曹腾用事宫中三十多年,未有显著过失,并能推荐贤人,受到种暠弹劾,却称种暠为能吏,因此受到人们赞美。曹腾是曹魏王朝中六个拥有帝号的人物之一,在中国历史上,还是唯一一个被正式授予正统皇帝称号的宦官。", budugen: "步度根(?-约233年),檀石槐之孙,魁头之弟。中国三国时期鲜卑首领之一。步度根在其兄魁头死后,嗣为鲜卑一部之首领,据有云中、雁门、北地、代郡、太原等地之全部或一部分。建安(196年-220年)中,曾与轲比能等通过护乌桓校尉阎柔向曹操贡献。后遣使向魏文帝曹丕献马,被封为王。因兄扶罗韩被轲比能所杀,与之结怨,互相攻劫,其部众益少,力量益弱。被迫率众万余落退保太原、雁门,并联络扶罗韩子泄归泥附己,共拒轲比能。黄初五年(224年),亲诣魏廷贡献,受赏赐,与魏保持和好关系。魏明帝青龙元年(233年),受轲比能诱使,叛魏,扰掠并州,在魏将秦朗追击下,走漠北,后为轲比能所杀。", mawan: "马玩,东汉末年凉州军阀之一。建安十六年(公元211年),同韩遂、马超联合,起兵反抗曹操。同年九月,联军战败,马玩不知去向。", @@ -160,6 +161,16 @@ const characterIntro = { guansuo: "关羽的三子。自荆州失陷后,逃难在鲍家庄养病,伤势痊愈之后入蜀,逢丞相诸葛亮南征,拜之为前部先锋,一同南征。", wanglang: "字景兴,汉末三国经学家,曹魏初期重臣。曾任会稽太守举兵抵抗孙策,后为曹操所征,被拜为谏议大夫等职。曹丕建立魏国后任命为司空。小说《三国演义》中他在阵前与诸葛亮饶舌比拼,最终被诸葛亮言词所驳倒,一时气愤坠马身亡。", zhangliang: "东汉末年黄巾起义首领之一,张角的三弟。中平元年(184)随兄起义,号称“人公将军”。遭到朝廷所派左中郎将皇甫嵩进攻时,他率军在广宗(今河北威县)进行反击。后因警戒疏忽,遭到汉军夜袭,兵败身亡。", + wangcan: "王粲(177年-217年2月17日),字仲宣。山阳郡高平县(今山东微山两城镇)人。东汉末年文学家,“建安七子”之一,太尉王龚曾孙、司空王畅之孙。", + re_jsp_pangtong: "庞统,字士元,襄阳(治今湖北襄阳)人。三国时刘备帐下谋士,官拜军师中郎将。才智与诸葛亮齐名,人称“凤雏”。在进围雒县时,统率众攻城,不幸被流矢击中去世,时年三十六岁。追赐统为关内侯,谥曰靖侯。庞统死后,葬于落凤庞统墓坡。", + lvdai: "吕岱(161年-256年),字定公,广陵海陵(今江苏如皋)人。三国时期吴国重臣、将领。吕岱一生戮力奉公,为孙吴开疆拓土,功勋赫赫。太平元年(256年),吕岱去世,年九十六。", + lvqian: "吕虔(生卒年不详),字子恪。任城国(今山东济宁东南)人。汉末至三国曹魏时期将领。 吕虔有勇有谋,曹操在兖州时,任命他为从事,率领家丁驻守湖陆。后升任泰山太守,与夏侯渊共同镇压济南等地的黄巾军。被推举为秀才,加任骑都尉,仍管辖泰山郡。 曹丕继任魏王后,加吕虔为裨将军,封益寿亭侯。再升任徐州刺史,加任威虏将军。任用王祥为别驾,将民政事务都委托于他,为世人所称赞。曹叡继位后,改封万年亭侯。吕虔死后,其子吕翻世袭万年亭侯。", + panjun: "潘濬(一作潘浚)(?-239年),字承明。武陵郡汉寿县(今湖南汉寿)人。三国时期吴国重臣,蜀汉大司马蒋琬的表弟。 潘濬为人聪察,对问有机理,拜大儒宋忠为师,得到“建安七子”之一的王粲赏识。不到三十,即被荆州牧刘表任命为江夏从事,因按杀贪污的沙羡长而闻名。建安十六年(211年),被刘备任命为荆州治中从事,与守臣关羽不睦。建安二十四年(219年),孙权得荆州,拜潘濬为辅军中郎将。又迁奋威将军,封常迁亭侯。孙权称帝后,拜少府,进封刘阳侯,又改太常。黄龙三年(231年),授假节,与吕岱率军五万平五溪蛮夷叛乱,经三年而斩获数万,使得一方宁静。潘濬为人刚正不阿,在吕壹弄权时,屡请孙权将其诛杀。甚至想亲手击杀吕壹,使吕壹对他非常畏惧。 赤乌二年(239年),潘濬去世。", + duji: "杜畿(163年—224年),字伯侯,京兆杜陵(今陕西西安东南)人。东汉末及三国时曹魏官吏及将领。西汉御史大夫杜延年的后代。历官郡功曹、守郑县令,善于断案。荀彧将他举荐给曹操,曹操任命他为司空司直,调任护羌校尉,使持节领西平太守。 曹丕受禅登基后,封杜畿为丰乐亭侯。官至尚书仆射。后在陶河试航时遇上大风沉没,杜畿淹死,死时六十二岁,曹丕为之涕泣,追赠其为太仆,谥戴侯。", + zhoufang: "周鲂(生卒年不详),字子鱼。吴郡阳羡县(今江苏宜兴)人。三国时期吴国将领。周鲂年少时好学,被举为孝廉。历任宁国县长、怀安县长、钱塘侯相,一月之内,便斩杀作乱的彭式及其党羽,因而升任丹阳西部都尉。彭绮率数万人反叛时,周鲂被任命为鄱阳太守,与胡综共同将其生擒,因功加职昭义校尉。后诈降曹休,诱其率军接应,使曹休在石亭之战中一败涂地,战后因功被加职为裨将军,封关内侯。贼帅董嗣凭险骚扰豫章等郡,周鲂派间谍将其诱杀,不费兵卒即安定数郡。周鲂在鄱阳赏罚分明、恩威并施,于任职十三年后去世。", + yanjun: "严畯(生卒年不详),字曼才,彭城(治今江苏徐州)人,三国时期孙吴官员、学者。性情忠厚,待人以诚。少好学,精通《诗》、《书》、《三礼》,又好《说文》。避乱江东,与诸葛瑾、步骘是好朋友,被张昭推荐给孙权作骑都尉、从事中郎。建安二十二年(217年),横江将军鲁肃去世,孙权打算让严畯接替其位。严畯很有自知之明,知道自己没有能力对抗在荆州的关羽和北面的曹魏,便坚决不接受此任命。后来担任尚书令。严畯享年七十八岁。著有《孝经传》、《潮水论》。", + liuyao: "刘繇(一读yóu)(156年-197年),字正礼。东莱牟平(今山东牟平)人。东汉末年宗室、大臣,汉末群雄之一,齐悼惠王刘肥之后,太尉刘宠之侄。
    刘繇最初被推举为孝廉,授郎中。任下邑县长时,因拒郡守请托而弃官。后被征辟为司空掾属,除授侍御史,因战乱而不到任,避居淮浦。兴平元年(194年),被任命为扬州刺史。他先后与袁术、孙策交战,一度被朝廷加授为扬州牧、振武将军,但最终还是败归丹徒。此后,刘繇又击破反叛的笮融,旋即病逝,年四十二。", + liuyan: "刘焉(?-194年),字君郎(《华阳国志》又作君朗)。江夏郡竟陵县(今湖北省天门市)人。东汉末年宗室、军阀,汉末群雄之一,西汉鲁恭王刘余之后。
    刘焉初以汉朝宗室身份,拜为中郎,历任雒阳令、冀州刺史、南阳太守、宗正、太常等官。因益州刺史郄俭在益州大肆聚敛,贪婪成风,加上当时天下大乱。刘焉欲取得一安身立命之所,割据一方,于是向朝廷求为益州牧,封阳城侯,前往益州整饬吏治。郄俭为黄巾军所杀,刘焉进入益州,派张鲁盘踞汉中,张鲁截断交通,斩杀汉使,从此益州与中央道路不通。刘焉进一步对内打击地方豪强,巩固自身势力,益州因而处于半独立的状态。兴平元年(194年),刘焉因背疮迸发而逝世,其子刘璋继领益州牧。", }; export default characterIntro; diff --git a/character/sp/perfectPairs.js b/character/sp/perfectPairs.js index 5f9b48bb3f..a6298d9390 100644 --- a/character/sp/perfectPairs.js +++ b/character/sp/perfectPairs.js @@ -23,4 +23,11 @@ export default { dongbai: ["dongzhuo"], cuimao: ["caopi"], simazhao: ["wangyuanji"], + lijue: ["guosi", "jiaxu"], + zhangji: ["zhangxiu", "drlt_zhangxiu", "zoushi"], + xf_sufei: ["ganning"], + simahui: ["pangdegong"], + zhangqiying: ["zhanglu"], + pangtong: ["zhugejin"], + taishici: ["liuyao", "kongrong"], }; diff --git a/character/sp/skill.js b/character/sp/skill.js index f36af93d16..e8ed6f31c6 100644 --- a/character/sp/skill.js +++ b/character/sp/skill.js @@ -2,2818 +2,3522 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { - //曹腾 - olyongzu: { - audio: 2, - trigger: { player: "phaseZhunbeiBegin" }, - filter(event, player) { - return game.hasPlayer(t => t != player); + //孔淑 + olleiluan: { + audio: 2, + onChooseToUse(event) { + if (!game.online && !event.olleiluan) { + const player = event.player; + let basic = lib.inpile.filter(i => get.type(i) == "basic"); + player.getRoundHistory("useCard", evt => { + if (get.type(evt.card) == "basic") basic.remove(evt.card.name); + }); + event.set("olleiluan", [basic, lib.skill.olleiluan.getNum(player)]); + } }, - async cost(event, trigger, player) { - event.result = await player - .chooseTarget(get.prompt2("olyongzu"), lib.filter.notMe) - .set("ai", target => { - const player = get.event().player; - if (get.attitude(player, target) <= 0) return 0; - const list = get - .info("olyongzu") - .getList(player, target) - .map(listx => listx[0][1]) - .filter(effect => !effect.filter || effect.filter(player)); - return Math.max(...list.map(effect => effect.ai(player))) + Math.max(...list.map(effect => effect.ai(target))); + getNum(player) { + let i = 0, + num = 0, + keep = true; + while (i < game.roundNumber) { + if (player.getRoundHistory("useSkill", evt => evt.skill == "olleiluan_backup", i).length + player.getRoundHistory("useSkill", evt => evt.skill == "olleiluan_effect", i - 1).length > 0) { + keep = false; + num++; + } else if (!keep) break; + i++; + } + return Math.max(1, num); + }, + enable: "chooseToUse", + filter(event, player) { + if (!event.olleiluan || player.countCards("hes") < event.olleiluan[1] || event.type == "wuxie") return false; + return get + .inpileVCardList(info => { + const name = info[2], + type = get.type(name); + return type == "basic" && event.olleiluan[0].includes(name); }) - .forResult(); + .some(card => { + return event.filterCard({ name: card[2], nature: card[3] }, player, event); + }); }, - async content(event, trigger, player) { - const target = event.targets[0]; - let list = get.info("olyongzu").getList(player, target), - choosed; - for (const current of [player, target]) { - const result = await current - .chooseButton(["拥族:请选择一项执行", [list.filter(effect => choosed !== effect[0][0]), "textbutton"]], true) - .set("filterButton", button => { - const effect = button.link[1]; - return !effect.filter || effect.filter(current); - }) - .set("ai", button => { - const effect = button.link[1]; - return effect.ai(get.event().player); + usable: 1, + chooseButton: { + dialog(event, player) { + const list = get + .inpileVCardList(info => { + const name = info[2], + type = get.type(name); + return type == "basic" && event.olleiluan[0].includes(name); }) - .forResult(); - if (result.bool) { - if (!choosed) choosed = result.links[0][0]; - await result.links[0][1].content(current, player); - } - } - }, - getList(player, target) { - let list = [ - [ - "摸两张牌", - { - async content(player) { - await player.draw(2); - }, - ai(player) { - return get.effect(player, { name: "wuzhong" }, player, player); - }, - }, - ], - [ - "回复1点体力", - { - async content(player) { - await player.recover(); - }, - ai(player) { - return get.recoverEffect(player, player, player); - }, + .filter(card => { + return event.filterCard({ name: card[2], nature: card[3] }, player, event); + }); + return ui.create.dialog("累卵", [list, "vcard"]); + }, + check(button) { + if (get.event().getParent().type != "phase") return 1; + return get.player().getUseValue({ name: button.link[2], nature: button.link[3] }); + }, + backup(links, player) { + return { + audio: "olleiluan", + filterCard: true, + selectCard: () => get.event().olleiluan[1], + check(card) { + return 1 / (get.value(card) || 0.5); }, - ], - [ - "复原武将牌", - { - async content(player) { - if (player.isTurnedOver()) { - await player.turnOver(false); - } - if (player.isLinked()) { - await player.link(false); - } - }, - ai(player) { - return (player.isTurnedOver() ? 3 : 0) + player.isLinked(); - }, + viewAs: { + name: links[0][2], + nature: links[0][3], }, - ], - ]; - if (get.mode() == "guozhan" ? target.isFriendOf(player) : target.group == player.group) { - list.addArray([ - [ - "手牌上限+1", - { - async content(player) { - player.addSkill("olyongzu_hand"); - player.addMark("olyongzu_hand", 1, false); - }, - ai: () => 1, - }, - ], - [ - "若为魏/群势力,则获得【奸雄】/【天命】", - { - async content(player, source) { - source.addTempSkill("olyongzu_skill", { player: "phaseBegin" }); - source.markAuto("olyongzu_skill", [player]); - const group = player[get.mode() == "guozhan" ? "identity" : "group"]; - const skill = group == "wei" ? "rejianxiong" : "tianming"; - player.popup(skill); - await player.addAdditionalSkills("olyongzu_skill", skill, true); - }, - filter: player => ["wei", "qun"].includes(player[get.mode() == "guozhan" ? "identity" : "group"]), - ai(player) { - return player[get.mode() == "guozhan" ? "identity" : "group"] == "wei" ? 2 : 3; - }, - }, - ], - ]); - } - return list.map(listx => [listx, listx[0]]); + position: "hes", + popname: true, + }; + }, + prompt(links) { + return "将" + get.cnNumber(get.event().olleiluan[1]) + "张牌当作" + (get.translation(links[0][3]) || "") + "【" + get.translation(links[0][2]) + "】使用"; + }, }, - derivation: ["rejianxiong", "tianming"], - ai: { threaten: 3.5 }, + hiddenCard(player, name) { + if (player.getStat("skill").olleiluan) return false; + let basic = lib.inpile.filter(i => get.type(i) == "basic"); + player.getRoundHistory("useCard", evt => { + if (get.type(evt.card) == "basic") basic.remove(evt.card.name); + }); + const num = lib.skill.olleiluan.getNum(player); + return basic.includes(name) && player.countCards("he") >= num; + }, + ai: { + order(item, player) { + if (player && get.event().type == "phase") { + let list = get + .inpileVCardList(info => { + return get.info("olleiluan").hiddenCard(player, info[2]); + }) + .map(card => { + return { name: card[2], nature: card[3] }; + }) + .filter(card => player.getUseValue(card, true, true) > 0); + if (!list.length) return 0; + list.sort((a, b) => { + return player.getUseValue(b, true, true) - player.getUseValue(a, true, true); + }); + return get.order(list[0], player) * 1.01; + } + return 0.001; + }, + respondSha: true, + respondShan: true, + skillTagFilter(player, tag, arg) { + if (arg === "respond") return false; + const name = tag == "respondSha" ? "sha" : "shan"; + return get.info("olleiluan").hiddenCard(player, name); + }, + result: { player: 1 }, + }, + frequent: true, + subfrequent: ["effect"], + group: "olleiluan_effect", subSkill: { - skill: { - onremove(player, skill) { - const targets = player.getStorage(skill).sortBySeat(player); - delete player.storage[skill]; - if (targets.length) { - for (const i of targets) i.removeAdditionalSkills(skill); - } + backup: {}, + effect: { + trigger: { global: "roundStart" }, + filter(event, player) { + if (game.roundNumber <= 1) return false; + return ( + player.getRoundHistory( + "useCard", + evt => { + return get.type(evt.card) == "basic"; + }, + 1 + ).length >= lib.skill.olleiluan.getNum(player) + ); }, - }, - hand: { - charlotte: true, - markimage: "image/card/handcard.png", - intro: { content: "手牌上限+#" }, - mod: { - maxHandcard(player, num) { - return num + player.countMark("olyongzu_hand"); - }, + frequent: true, + prompt2(event, player) { + return "摸" + get.cnNumber(lib.skill.olleiluan.getNum(player)) + "张牌,然后视为使用一张上一轮进入弃牌堆的普通锦囊牌"; + }, + async content(event, trigger, player) { + await player.draw(lib.skill.olleiluan.getNum(player)); + let cards = []; + const historys = _status.globalHistory; + for (let i = historys.length - 2; i >= 0; i--) { + const history = historys[i].everything; + for (let j = history.length - 1; j >= 0; j--) { + const evt = history[j]; + if (evt.name == "cardsDiscard" || (evt.name == "lose" && evt.position == ui.discardPile)) { + cards.addArray(evt.cards.filterInD("d").reverse()); + } + } + if (historys[i].isRound) break; + } + cards.reverse(); + cards = cards.filter(card => get.type(card, false) == "trick" && player.hasUseTarget(card)); + if (cards.length) { + const result = await player + .chooseButton(["视为使用其中一张普通锦囊牌", cards], true) + .set("ai", button => { + const card = { + name: get.name(button.link, false), + nature: get.nature(button.link, false), + suit: get.suit(button.link, false), + number: get.number(button.link, false), + isCard: true, + }; + return get.player().getUseValue(card); + }) + .forResult(); + if (result.bool) { + const card = { + name: get.name(result.links[0], false), + nature: get.nature(result.links[0], false), + suit: get.suit(result.links[0], false), + number: get.number(result.links[0], false), + isCard: true, + }; + if (player.hasUseTarget(card)) await player.chooseUseTarget(card, false, true); + } + } }, }, }, }, - olqingliu: { + olfuchao: { audio: 2, - trigger: { - global: "phaseBefore", - player: ["enterGame", "dyingAfter"], - }, + trigger: { player: ["useCard", "respond"] }, filter(event, player) { - if (event.name == "dying") { - const group = player.storage.olqingliu; - if (!group || player.group == group) return false; - return ( - game - .getAllGlobalHistory("everything", evt => { - return ( - evt.name == "dying" && - !game.getAllGlobalHistory("everything", evtx => { - return evtx.name == "die" && evtx.getParent() == evt; - }).length - ); - }) - .indexOf(event) == 0 - ); - } - return event.name != "phase" || game.phaseNumber == 0; + return Array.isArray(event.respondTo) && event.respondTo[0] != player; }, forced: true, + logTarget: event => event.respondTo[0], async content(event, trigger, player) { - if (trigger.name == "dying") await player.changeGroup(player.storage.olqingliu); - else { - const result = await player - .chooseControl("wei", "qun") - .set("ai", () => { - return get.rand(0, 1); - }) - .set("prompt", "清流:请选择你的势力") + const evt = game.getGlobalHistory("everything", evt => { + return evt.name === "useCard" && evt.card == trigger.respondTo[1]; + })[0]; + let result; + if (!player.countCards("he") && !evt.player.countCards("he")) { + result = { index: 1 }; + } else { + result = await player + .chooseControl() + .set("choiceList", ["弃置你与" + get.translation(evt.player) + "的各一张牌,然后其他角色不可响应此牌", "令" + get.translation(evt.card) + "对其他角色无效,然后" + get.translation(evt.card) + "对你额外结算一次"]) + .set("prompt", "覆巢:请选择一项") + .set("ai", () => 0) //插眼,PZ157 .forResult(); - if (result.control) { - const group = result.control; - player.popup(group + "2"); - game.log(player, "选择了", "#y" + get.translation(group + "2")); - player.storage.olqingliu = group == "wei" ? "qun" : "wei"; - if (player.group != group) await player.changeGroup(group); + } + const targets = game.filterPlayer(i => i != player); + if (result.index == 0) { + await player.chooseToDiscard("he", true); + await player.discardPlayerCard(evt.player, "he", true); + if (targets.length) { + evt.directHit.addArray(targets); + game.log(targets, "不可响应", evt.card); + } + } else { + evt.effectCount++; + evt.excluded.addArray(targets); + if (targets.length) { + game.log(evt.card, "对", targets, "无效"); } } }, }, - //步度根 - //古希腊掌管扣工资的神(bushi - olkouchao: { + //OL袁姬 + oljieyan: { audio: 2, - init(player, skill) { - if (!player.storage[skill]) { - player.storage[skill] = ["sha", "huogong", "guohe"]; - } - }, - hiddenCard(player, name) { - const storage = player.getStorage("olkouchao"); - for (let i = 0; i < storage.length; i++) { - if (!player.getStorage("olkouchao_used").includes(i) && name == storage[i]) return true; - } - return false; + trigger: { + player: "phaseZhunbeiBegin", }, - enable: "chooseToUse", - filter(event, player) { - if (!player.countCards("hes")) return false; - const storage = player.getStorage("olkouchao"); - for (let i = 0; i < storage.length; i++) { - if (player.getStorage("olkouchao_used").includes(i)) continue; - if (event.filterCard(get.autoViewAs({ name: storage[i] }, "unsure"), player, event)) return true; - } - return false; + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2(event.name.slice(0, -5))) + .set("ai", target => { + const player = get.player(), + att = get.attitude(player, target), + goon = player.hasSkill("olshuiyue", null, null, false); + let eff = get.damageEffect(target, player, player); + if (goon) { + if (player.storage.olshuiyue) eff += get.effect(target, { name: "guohe_copy2" }, player, player) * Math.min(2, target.countCards("he")); + else eff += get.effect(target, { name: "draw" }, player, player); + } + if (goon && target.getHp() > 2 && att > 0 && target != player && !player.storage.olshuiyue) { + return 0.1 + (target.countCards("h") - target.getHp()); + } + return eff; + }) + .forResult(); }, - chooseButton: { - dialog(event, player) { - const storage = player.getStorage("olkouchao"); - let list = []; - for (let i = 0; i < storage.length; i++) { - const name = storage[i]; - list.push([get.translation(get.type(name)), "", name, undefined, i]); - } - return ui.create.dialog("寇钞", [list, "vcard"]); - }, - filter(button, player) { - const evt = get.event().getParent(); - return evt.filterCard(get.autoViewAs({ name: button.link[2] }, "unsure"), player, evt) && !player.getStorage("olkouchao_used").includes(button.link[4]); - }, - check(button) { - const evt = get.event().getParent(); - const player = get.event().player; - if (evt.type != "phase") return 1; - if (button.link[2] == "jiu") { - if (player.getUseValue({ name: "jiu" }) <= 0) return 0; - if (player.countCards("h", "sha")) return player.getUseValue({ name: "jiu" }); + async content(event, trigger, player) { + const target = event.targets[0]; + await target.damage(); + const { + result: { index }, + } = await target + .chooseControl() + .set("choiceList", ["跳过下个弃牌阶段", "回复1点体力,下个弃牌阶段手牌上限-2"]) + .set("ai", () => { + const player = get.event("player"), + target = get.event().getTrigger().player; + if ((get.recoverEffect(player, target, target) > 0 || get.attitude(player, target) > 0) && game.hasPlayer(current => current != player && get.attitude(player, current) > 0)) return 1; return 0; - } - return player.getUseValue({ name: button.link[2] }) / 4; - }, - backup(links, player) { - return { - filterCard: true, - position: "hes", - viewAs: { - name: links[0][2], - storage: { olkouchao: links[0][4] + 1 }, - }, - precontent() { - if (!player.storage.olkouchao_used) { - player.when({ global: "roundStart" }).then(() => delete player.storage.olkouchao_used); - } - player.markAuto("olkouchao_used", [lib.skill.olkouchao_backup.viewAs.storage.olkouchao - 1]); - player.addTempSkill("olkouchao_effect"); - }, - }; - }, - prompt(links, player) { - const name = links[0][2], - index = links[0][4] + 1; - return '###寇钞###
    将一张牌当作【' + get.translation(name) + "】使用,然后修改【寇钞】的第" + get.cnNumber(index, true) + "项
    "; - }, - }, - ai: { - order(_, player) { - if (!player || get.event().type != "phase") return 1; - let names = player.getStorage("olkouchao"); - for (let i = 0; i < names.length; i++) { - if (player.getStorage("olkouchao_used").includes(i)) names.splice(i--, 1); - } - names = names.map(name => { - return { name: name }; }); - names.sort((a, b) => { - return player.getUseValue(b, true, true) - player.getUseValue(a, true, true); + if (index == 0) { + target.skip("phaseDiscard"); + game.log(target, "跳过下个弃牌阶段"); + } else { + await target.recover(); + target.addTempSkill("oljieyan_effect", { player: "phaseDiscardAfter" }); + target.addMark("oljieyan_effect", 2, false); + target.when("phaseDiscardBefore").then(() => { + player.addTempSkill("oljieyan_hand", { player: "phaseDiscardAfter" }); }); - let max = get.order(names[0], player); - if (max > 0) max += 0.3; - return max; - }, - respondShan: true, - respondSha: true, - skillTagFilter(player, tag, arg) { - if (arg == "respond") return false; - if (!player.countCards("hes")) return false; - return player.getStorage("olkouchao").includes(tag == "respondSha" ? "sha" : "shan"); - }, - result: { - player(player) { - const dying = get.event().dying; - return dying ? get.attitude(player, dying) : 1; - }, - }, + player.addSkill("oljieyan_gain"); + player.markAuto("oljieyan_gain", [target]); + } }, subSkill: { - backup: {}, effect: { charlotte: true, - trigger: { player: "useCardAfter" }, + onremove: true, + mark: true, + marktext: "弃", + intro: { + content: "下个弃牌阶段手牌上限-#", + }, + mod: { + maxHandcard(player, num) { + if (player.hasSkill("oljieyan_hand")) return num - player.countMark("oljieyan_effect"); + }, + }, + }, + hand: { + charlotte: true, + }, + gain: { + charlotte: true, + onremove: true, + intro: { + content: "节言角色:$", + }, + trigger: { + global: "phaseDiscardAfter", + }, filter(event, player) { - return (event.card.storage || {}).olkouchao; + return player.getStorage("oljieyan_gain").includes(event.player); }, forced: true, popup: false, async content(event, trigger, player) { - const cards = game - .getAllGlobalHistory("everything", evt => { - if (!evt.cards || !evt.cards.someInD("d")) return false; - if (evt.name == "lose") return evt.position == ui.discardPile; - if (evt.name != "cardsDiscard") return false; - const evtx = evt.getParent(); - if (evtx.name != "orderingDiscard") return false; - const evt2 = evtx.relatedEvent || evtx.getParent(); - return evt2 && evt2.name != "useCard"; - }) - .map(evt => evt.cards.filterInD("d")) - .flat() - .reverse(); - const card = cards.find(card => ["basic", "trick"].includes(get.type(card))); - if (card) { - const index = (trigger.card.storage || {}).olkouchao; - player.storage.olkouchao[index - 1] = card.name; - game.log(player, "修改", "#g【寇钞】", "的", "#y第" + get.cnNumber(index, true) + "项", "为", "#g【" + get.translation(card.name) + "】"); - if (player.storage.olkouchao.every(name => get.type(name) == "basic")) { - player.storage.olkouchao = ["shunshou", "shunshou", "shunshou"]; - game.log(player, "修改", "#g【寇钞】", "的", "#y所有项", "为", "#g【顺手牵羊】"); - } + const target = trigger.player, + cards = []; + target.getHistory("lose", evt => { + if (evt.type == "discard" && evt.getParent("phaseDiscard") == trigger) cards.addArray(evt.cards2.filterInD("d")); + }); + player.unmarkAuto("oljieyan_gain", [target]); + if (cards.length && game.hasPlayer(current => current != target)) { + const targets = await player + .chooseTarget(get.prompt(event.name), `令一名不为${get.translation(target)}的角色获得${get.translation(cards)}`, (card, player, target) => { + return target != get.event().getTrigger().player; + }) + .set("ai", target => { + const player = get.player(); + let att = get.attitude(player, target); + if (att < 3) return 0; + if (target.hasSkillTag("nogain")) att /= 10; + return att; + }) + .forResultTargets(); + if (targets && targets.length) await targets[0].gain(cards, "gain2"); } + if (!player.getStorage("oljieyan_gain").length) player.removeSkill("oljieyan_gain"); }, }, }, }, - //马玩 - olhunjiang: { + oljinghua: { + audio: 2, + trigger: { + global: "gainAfter", + player: "loseAsyncAfter", + }, + filter(event, player, triggername, target) { + if (!target || !target.isIn() || target == player) return false; + if (event.name == "loseAsync") { + if (event.type != "gain") return false; + } + const cards = event.getl(player).cards2; + if (!cards.length) return false; + if (!player.storage.oljinghua && target.isHealthy()) return false; + const cardsx = event.getg(target); + return cards.some(card => cardsx.includes(card)); + }, + getIndex(event, player) { + const cards = event.getl(player).cards2; + return game + .filterPlayer(target => { + if (target == player) return false; + if (!player.storage.oljinghua && target.isHealthy()) return false; + const cardsx = event.getg(target); + return cards.some(card => cardsx.includes(card)); + }) + .sortBySeat(); + }, + logTarget(event, player, triggername, target) { + return target; + }, + check(event, player, triggername, target) { + return player.storage.oljinghua ? get.effect(target, { name: "losehp" }, player, player) > 0 : get.recoverEffect(target, player, player) > 0; + }, + locked: false, + forced: true, + async content(event, trigger, player) { + event.targets[0][player.storage.oljinghua ? "loseHp" : "recover"](); + }, + group: "oljinghua_change", + subSkill: { + change: { + audio: "oljinghua", + trigger: { + player: "loseAfter", + global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], + }, + filter(event, player) { + if (player.countCards("h") || player.storage.oljinghua) return false; + const evt = event.getl(player); + return evt && evt.hs && evt.hs.length; + }, + prompt2: "修改【镜花】为:当其他角色获得你的牌后,其失去1点体力。", + async content(event, trigger, player) { + player.storage.oljinghua = true; + }, + }, + }, + }, + olshuiyue: { + audio: 2, + trigger: { + global: "damageEnd", + }, + filter(event, player) { + const target = event.player, + source = event.source; + if (!target.isIn() || target == player || !source || source != player) return false; + if (player.storage.olshuiyue) return target.countCards("he"); + return true; + }, + locked: false, + forced: true, + logTarget: "player", + async content(event, trigger, player) { + const target = trigger.player; + if (player.storage.olshuiyue) await target.chooseToDiscard("he", true); + else await target.draw(); + }, + group: "olshuiyue_change", + subSkill: { + change: { + audio: "olshuiyue", + trigger: { + source: "dying", + }, + filter(event, player) { + return !player.storage.olshuiyue && event.player != player; + }, + prompt2: "修改【水月】为:当其他角色受到你造成的伤害后,其弃置一张牌。", + async content(event, trigger, player) { + player.storage.olshuiyue = true; + }, + }, + }, + }, + //OL轲比能 + olpingduan: { audio: 2, enable: "phaseUse", + usable: 1, + filterTarget: true, + async content(event, trigger, player) { + const target = event.targets[0], + str = player != target ? `${get.translation(player)}对你发动了【平端】,` : `【平端】:`; + const use = await target + .chooseToUse(function (card, player, event) { + return get.type(card) == "basic" && lib.filter.cardEnabled.apply(this, arguments); + }, str + `你可以使用一张基本牌,然后摸一张牌`) + .set("addCount", false) + .forResultBool(); + if (!use) return; + await target.draw(); + if (!target.countCards("he", card => get.type2(card) == "trick" && player.canRecast(card, player))) return; + const cards = await target + .chooseCard( + "he", + (card, player) => { + return get.type2(card) == "trick" && player.canRecast(card, player); + }, + str + `你可以重铸一张锦囊牌,然后摸一张牌` + ) + .set("ai", card => 11 - get.value(card)) + .forResultCards(); + if (!cards || !cards.length) return; + await target.recast(cards); + await target.draw(); + if (!target.countGainableCards(player, "e")) return; + const bool = await target + .chooseBool(str + `你可以令${get.translation(player)}获得你装备区的一张牌,然后摸一张牌`) + .set("choice", get.attitude(target, player) > 0) + .forResultBool(); + if (!bool) return; + await player.gainPlayerCard(target, "e", true); + await target.draw(); + }, + ai: { + order: 6, + result: { + target(player, target) { + return target.countCards("he") + 0.5; + }, + }, + }, + }, + //OL孙茹 + //持室神将 + olchishi: { + audio: 2, + trigger: { global: ["loseAfter", "equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"] }, filter(event, player) { - return game.hasPlayer(target => lib.skill.olhunjiang.filterTarget(null, player, target)); + const target = _status.currentPhase; + if (!target || !target.isIn()) return false; + const evt = event.getl(target); + return evt && ["h", "e", "j"].some(pos => (evt[pos + "s"] || []).length > 0 && !target.countCards(pos)); }, - filterTarget(card, player, target) { - return target != player && player.inRange(target); + check(event, player) { + return get.effect(_status.currentPhase, { name: "draw" }, player, player) > 0; }, usable: 1, - selectTarget: [1, Infinity], - multitarget: true, - multiline: true, + logTarget: () => _status.currentPhase, async content(event, trigger, player) { - const targets = event.targets.sortBySeat(); - let answer_result = [[], []]; - let humans = targets.filter(current => current === game.me || current.isOnline()); - let locals = targets.slice(0).randomSort(); - locals.removeArray(humans); - const eventId = get.id(); - const send = (question, current, eventId) => { - lib.skill.dclisao.chooseControl(question, current, eventId); - game.resume(); - }; - event._global_waiting = true; - let time = 10000; - if (lib.configOL && lib.configOL.choose_timeout) time = parseInt(lib.configOL.choose_timeout) * 1000; - targets.forEach(current => current.showTimer(time)); - if (humans.length > 0) { - const solve = function (resolve, reject) { - return function (result, player) { - if (result && typeof result.index == "number") { - resolve(); - answer_result[result.index].push(player); - } else reject(); - }; - }; - await Promise.any( - humans.map(current => { - return new Promise(async (resolve, reject) => { - if (current.isOnline()) { - current.send(send, question, current, eventId); - current.wait(solve(resolve, reject)); - } else { - const next = lib.skill.olhunjiang.chooseControl(current, player, eventId); - const solver = solve(resolve, reject); - if (_status.connectMode) game.me.wait(solver); - const result = await next.forResult(); - if (_status.connectMode) game.me.unwait(result, current); - else solver(result, current); - } - }); - }) - ).catch(() => {}); - game.broadcastAll("cancel", eventId); - } - if (locals.length > 0) { - for (const current of locals) { - const result = await lib.skill.olhunjiang.chooseControl(current, player).forResult(); - if (result && typeof result.index == "number") { - answer_result[result.index].push(current); - } - } - } - delete event._global_waiting; - for (const i of targets) { - i.hideTimer(); - i.addExpose(0.05); - i.popup(answer_result[0].includes(i) ? "成为目标" : "令其摸牌"); - game.log(i, "选择了", "#y" + (answer_result[0].includes(i) ? "成为目标" : "令其摸牌")); - } - await game.asyncDelay(); - if (answer_result[0].length) { - answer_result[0].sortBySeat(); - player.addTempSkill("olhunjiang_addTarget"); - player.markAuto("olhunjiang_addTarget", answer_result[0]); - if (!answer_result[1].length) { - await player.draw(answer_result[0].length); - } - } - if (answer_result[1].length) { - answer_result[1].sortBySeat(); - await player.draw(answer_result[1].length); - if (!answer_result[0].length) { - player.addTempSkill("olhunjiang_addTarget"); - player.markAuto("olhunjiang_addTarget", answer_result[1]); - } - } - }, - ai: { - order(_, player) { - return get.order({ name: "sha" }, player) + 1; - }, - result: { - target(player, target) { - return get.sgn(get.sgn(get.attitude(player, target)) + 0.5); - }, - }, - }, - chooseControl(player, source, eventId) { - const str = get.translation(source); - return player - .chooseControl("成为目标", "令其摸牌") - .set("prompt", "###" + str + "对你发动了【浑疆】,请选择一项" + '###
    若所有角色选择了同一项,则所有角色也执行另一项
    ') - .set("choiceList", ["令" + str + "本阶段使用【杀】可以额外指定你为目标", "令" + str + "摸一张牌"]) - .set("source", source) - .set("id", eventId) - .set("_global_waiting", true) - .set("ai", () => Math.max(0, get.sgn(get.attitude(get.event().player, get.event().source)))); + const target = _status.currentPhase; + await target.draw(2); + target.addTempSkill("olchishi_effect"); + target.addMark("olchishi_effect", 2, false); }, subSkill: { - addTarget: { + effect: { charlotte: true, onremove: true, - intro: { content: "本阶段使用【杀】可以额外指定$为目标" }, - trigger: { player: "useCard2" }, - filter(event, player) { - if (event.card.name != "sha") return false; - return game.hasPlayer(target => { - if (!player.getStorage("olhunjiang_addTarget").includes(target)) return false; - return !event.targets.includes(target) && lib.filter.targetEnabled2(event.card, player, target) && lib.filter.targetInRange(event.card, player, target); - }); - }, - async cost(event, trigger, player) { - event.result = await player - .chooseTarget( - get.prompt("olhunjiang_addTarget"), - "令任意名【浑疆】选择成为额外目标的角色成为" + get.translation(trigger.card) + "的目标", - (card, player, target) => { - if (!player.getStorage("olhunjiang_addTarget").includes(target)) return false; - const event = get.event().getTrigger(); - return !event.targets.includes(target) && lib.filter.targetEnabled2(event.card, player, target) && lib.filter.targetInRange(event.card, player, target); - }, - [1, Infinity] - ) - .set("ai", target => { - const player = get.event("player"), - event = get.event().getTrigger(); - return get.effect(target, event.card, player); - }) - .forResult(); - }, - async content(event, trigger, player) { - trigger.targets.addArray(event.targets); - game.log(event.targets, "成为了", trigger.card, "的额外目标"); + markimage: "image/card/handcard.png", + intro: { content: "手牌上限+#" }, + mod: { + maxHandcard(player, num) { + return num + player.countMark("olchishi_effect"); + }, }, }, }, }, - //蒋琬 - olziruo: { + olweimian: { audio: 2, - trigger: { player: "useCard" }, + enable: "phaseUse", filter(event, player) { - if (!event.olziruo || !event.olziruo[player.playerid]) return false; - return event.olziruo[player.playerid][Boolean(player.storage.olziruo) ? 1 : 0]; - }, - forced: true, - async content(event, trigger, player) { - player.changeZhuanhuanji("olziruo"); - await player.draw(); + return player.hasEnabledSlot(); }, - mark: true, - marktext: "☯", - zhuanhuanji: true, - intro: { content: storage => "当你使用最" + (storage ? "右" : "左") + "侧的卡牌时,你摸一张牌。你以此法摸牌后本回合不能整理手牌。" }, - global: "olziruo_mark", - mod: { - aiOrder(player, card, num) { - if (typeof card == "object") { - const cards = player.getCards("h"); - if (cards.indexOf(card) == (player.storage.olziruo ? cards.length - 1 : 0)) return num + 10; + usable: 1, + chooseButton: { + dialog(event, player) { + let dialog = ui.create.dialog("###" + get.translation("olweimian") + "###" + lib.translate.olweimian_info, "hidden"); + let equips = []; + for (let i = 1; i < 6; i++) { + if (!player.hasEnabledSlot(i)) continue; + for (let j = 1; j <= player.countEnabledSlot(i); j++) { + equips.push(["equip" + i, get.translation("equip" + i)]); + } } + if (equips.length > 0) dialog.add([equips, "tdnodes"]); + return dialog; }, - }, - group: ["olziruo_gain", "olziruo_sort"], - subSkill: { - mark: { - charlotte: true, - trigger: { player: "useCardBegin" }, - filter(event, player) { - const cards = player.getCards("h"); - if (!cards.length) return false; - return (event.cards || []).some(card => cards[0] == card || cards[cards.length - 1] == card); - }, - forced: true, - popup: false, - content() { - const cards = player.getCards("h"); - if (!trigger.olziruo) trigger.olziruo = {}; - trigger.olziruo[player.playerid] = [trigger.cards.some(card => cards[0] == card), trigger.cards.some(card => cards[cards.length - 1] == card)]; - }, - }, - gain: { - trigger: { - player: "gainAfter", - }, - filter(event, player) { - if (player.hasSkill("olziruo_ban", null, null, false)) return false; - return event.getParent().name == "draw" && event.getParent(2).name == "olziruo"; - }, - forced: true, - popup: false, - async content(event, trigger, player) { - player.addTempSkill("olziruo_ban"); - }, + check(button) { + const player = get.event().player; + if (player.countCards("e") <= 3 && _status.currentPhase === player && ((player.storage.counttrigger || {}).olchishi || 0) <= 0) { + if ( + player + .getCards("e") + .slice() + .map(i => get.subtype(i)) + .includes(button.link) + ) + return 10; + } + if ( + ui.selected.buttons.length >= + Math.max( + ...game.filterPlayer().map(target => { + let max = 0; + if (get.attitude(player, target) > 0 && (target == player || target.hasDisabledSlot())) max++; + if (get.recoverEffect(target, player, player) > 0) max++; + if ( + target.countCards("h") > 0 && + target + .getCards("h", card => { + return lib.filter.cardDiscardable(card, target); + }) + .reduce((sum, card) => { + return sum + get.value(card, target); + }, 0) <= + get.effect(target, { name: "draw" }, player, player) * 4 + ) + max++; + return max; + }) + ) + ) + return 0; + return [2, 1, 4, 3, 5].indexOf(parseInt(button.link.slice("equip".length))) + 1; }, - ban: { - charlotte: true, - mark: true, - intro: { - content: "本回合不能整理手牌", - }, - ai: { noSortCard: true }, + select: [1, 3], + backup(links, player) { + return { + audio: "olweimian", + types: links.slice().sort((a, b) => parseInt(a.slice("equip".length)) - parseInt(b.slice("equip".length))), + filterTarget(card, player, target) { + if (target == player) return true; + return target.hasDisabledSlot() || target.isDamaged() || target.countCards("h") > 0; + }, + async content(event, trigger, player) { + const target = event.target, + types = lib.skill.olweimian_backup.types; + for (const t of types) await player.disableEquip(t); + const num = Math.min(target.hasDisabledSlot() + target.isDamaged() + (target.countCards("h") > 0), types.length); + const result = await target + .chooseButton( + [ + "慰勉:请选择" + get.cnNumber(num) + "项执行", + [ + [ + ["equip", "恢复一个装备栏"], + ["recover", "回复1点体力"], + ["discard", "弃置所有手牌,然后摸四张牌"], + ], + "textbutton", + ], + ], + num + ) + .set("filterButton", button => { + const player = get.event().player; + switch (button.link) { + case "equip": + return player.hasDisabledSlot(); + case "recover": + return player.isDamaged(); + case "discard": + return player.countCards("h"); + } + }) + .set("ai", button => { + const player = get.event().player; + switch (button.link) { + case "equip": + return 1; + case "recover": + return get.recoverEffect(player, player, player); + case "discard": + return ( + get.effect(player, { name: "draw" }, player, player) * 4 - + player + .getCards("h", card => { + return lib.filter.cardDiscardable(card, player); + }) + .reduce((sum, card) => { + return sum + get.value(card, player); + }, 0) + ); + } + }) + .forResult(); + if (result.bool) { + if (result.links.includes("equip")) { + await target.chooseToEnable(); + } + if (result.links.includes("recover")) { + await target.recover(); + } + if (result.links.includes("discard")) { + const cards = target.getDiscardableCards(target, "h"); + if (cards.length) await target.discard(cards); + await target.draw(4); + } + } + }, + ai: { + result: { + target(player, target) { + let max = 0; + if (get.attitude(player, target) > 0 && (target == player || target.hasDisabledSlot())) max++; + if (get.recoverEffect(target, player, player) > 0) max++; + if ( + target.countCards("h") > 0 && + target + .getCards("h", card => { + return lib.filter.cardDiscardable(card, target); + }) + .reduce((sum, card) => { + return sum + get.value(card, target); + }, 0) <= + get.effect(target, { name: "draw" }, player, player) * 4 + ) + max++; + return max; + }, + }, + }, + }; }, - sort: { - enable: "chooseToUse", - filter(event, player) { - return player.countCards("h") > 1 && !player.hasSkillTag("noSortCard"); - }, - filterCard: true, - selectCard: 2, - position: "h", - direct: true, - lose: false, - discard: false, - delay: 0, - prompt: "选择两张手牌,更换这两张手牌的顺序", - content() { - let h = player.getCards("h"), - hs = h.slice(); - const list = [hs.indexOf(cards[0]), hs.indexOf(cards[1])]; - hs[list[0]] = cards[1]; - hs[list[1]] = cards[0]; - hs.reverse(); - game.addVideo("lose", player, [get.cardsInfo(hs), [], [], []]); - h.forEach(i => i.goto(ui.special)); - player.directgain(hs, false); - event.getParent(2).goto(0); - }, + prompt(links, player) { + const types = links.slice().sort((a, b) => parseInt(a.slice("equip".length)) - parseInt(b.slice("equip".length))); + return "废除" + types.map(i => get.translation(i) + "栏").join("、") + ",令一名角色选择执行等量项"; }, }, - }, - olxvfa: { - audio: 2, - enable: "phaseUse", - filter(event, player) { - return (!player.hasSkill("olxvfa_0") && player.countCards("h")) || (!player.hasSkill("olxvfa_1") && player.getExpansions("olxvfa").length); - }, - chooseButton: { - dialog(_, player) { - let dialog = ui.create.dialog("蓄发:请选择一项", "hidden"); - const list = [ - ["0", "将至少一半手牌称为“蓄发”置于武将牌上,然后可以将一张牌当作“蓄发”牌中的一张普通锦囊牌使用"], - ["1", "移去至少一半“蓄发”牌,然后可以将一张牌当作其中一张普通锦囊牌使用"], - ].filter(listx => { - if (listx[0] == "0") return !player.hasSkill("olxvfa_0") && player.countCards("h"); - return !player.hasSkill("olxvfa_1") && player.getExpansions("olxvfa").length; - }); - dialog.add([list, "textbutton"]); - if (list.length == 1) dialog.direct = true; - return dialog; - }, - filter(button, player) { - if (button.link == "0") return !player.hasSkill("olxvfa_0") && player.countCards("h"); - return !player.hasSkill("olxvfa_1") && player.getExpansions("olxvfa").length; - }, - check: () => 1 + Math.random(), - backup: links => get.copy(lib.skill["olxvfa_" + ["put", "remove"][parseInt(links[0])]]), - prompt(links) { - if (links[0] == "0") return "###蓄发###将至少一半手牌称为“蓄发”置于武将牌上,然后可以将一张牌当作“蓄发”牌中的一张普通锦囊牌使用"; - return "###蓄发###移去一半“蓄发”牌,然后可以将一张牌当作其中一张普通锦囊牌使用"; - }, - }, - intro: { - content: "expansion", - markcount: "expansion", - }, - onremove(player, skill) { - const cards = player.getExpansions(skill); - if (cards.length) player.loseToDiscardpile(cards); + ai: { + order: 7, + result: { player: 1 }, }, subSkill: { backup: {}, - 0: { charlotte: true }, - 1: { charlotte: true }, - put: { - audio: "olxvfa", - filterCard: true, - selectCard: () => [Math.ceil(get.event("player").countCards("h") / 2), Infinity], - position: "h", - check(card) { - const player = get.event("player"), - value = player.getUseValue(card, true); - if (value > 0) return get.type(card) == "trick" ? 20 + value : 0; - return 15 - get.value(card) - get.useful(card); - }, - lose: false, - discard: false, - delay: 0, - async content(event, trigger, player) { - player.addTempSkill("olxvfa_0", "phaseUseAfter"); - await player.addToExpansion(event.cards, player, "give").set("gaintag", ["olxvfa"]); - const cards = player.getExpansions("olxvfa"); - if (cards.some(card => get.type(card) == "trick" && player.hasCard(cardx => player.hasUseTarget(get.autoViewAs({ name: card.name }, [cardx]), true), "hes"))) { - const result = await player - .chooseButton(['###蓄发###
    是否将一张牌当作一张“蓄发”牌使用?
    ', cards]) - .set("filterButton", button => { - const player = get.event("player"), - card = button.link; - return get.type(card) == "trick" && player.hasCard(cardx => player.hasUseTarget(get.autoViewAs({ name: card.name }, [cardx]), true), "hes"); - }) - .set("ai", button => { - const player = get.event("player"), - card = button.link; - return player.getUseValue({ name: card.name, isCard: true }, true); - }) - .forResult(); - if (result.bool) { - const card = result.links[0]; - game.broadcastAll(function (card) { - lib.skill.olxvfa_backupx.viewAs = { name: card.name }; - }, card); - await player - .chooseToUse() - .set("openskilldialog", "###蓄发###将一张牌当作【" + get.translation(card.name) + "】使用") - .set("norestore", true) - .set("addCount", false) - .set("_backupevent", "olxvfa_backupx") - .set("custom", { - add: {}, - replace: { window: function () {} }, - }) - .backup("olxvfa_backupx"); - } - } - }, - }, - remove: { - audio: "olxvfa", - filterCard: () => false, - selectCard: -1, - delay: 0, - async content(event, trigger, player) { - player.addTempSkill("olxvfa_1", "phaseUseAfter"); - const cards = player.getExpansions("olxvfa"), - num = Math.ceil(cards.length / 2); - const result = await player - .chooseButton(['###蓄发###
    请移去至少' + get.cnNumber(num) + "张“蓄发”牌
    ", cards], [num, Infinity], true) - .set("ai", button => { - const player = get.event("player"), - value = player.getUseValue(button.link, true); - if (value > 0 && get.type(button.link) == "trick") { - if ( - !ui.selected.buttons.some(but => { - return get.type(but.link) == "trick" && player.getUseValue(but.link, true) > 0; - }) - ) - return 20 + value; - return 0; - } - return 1 / (get.useful(button.link) || 0.5); - }) - .forResult(); - if (result.bool) { - const cardx = result.links; - await player.loseToDiscardpile(cardx); - if (cardx.some(card => get.type(card) == "trick" && player.hasCard(cardxx => player.hasUseTarget(get.autoViewAs({ name: card.name }, [cardxx]), true), "hes"))) { - const result2 = await player - .chooseButton(['###蓄发###
    是否将一张牌当作一张移去的“蓄发”牌使用?
    ', cardx]) - .set("filterButton", button => { - const player = get.event("player"), - card = button.link; - return get.type(card) == "trick" && player.hasCard(cardx => player.hasUseTarget(get.autoViewAs({ name: card.name }, [cardx]), true), "hes"); - }) - .set("ai", button => { - const player = get.event("player"), - card = button.link; - return player.getUseValue({ name: card.name, isCard: true }, true); - }) - .forResult(); - if (result2.bool) { - const card = result2.links[0]; - game.broadcastAll(function (card) { - lib.skill.olxvfa_backupx.viewAs = { name: card.name }; - }, card); - await player - .chooseToUse() - .set("openskilldialog", "###蓄发###将一张牌当作【" + get.translation(card.name) + "】使用") - .set("norestore", true) - .set("addCount", false) - .set("_backupevent", "olxvfa_backupx") - .set("custom", { - add: {}, - replace: { window: function () {} }, - }) - .backup("olxvfa_backupx"); - } - } - } - }, - }, - backupx: { - filterCard(card) { - return get.itemtype(card) == "card"; - }, - position: "hes", - check(card) { - const player = get.event("player"); - if (player.hasValueTarget(card, true, true)) return 0; - if (player.hasSkill("olziruo")) { - const cards = player.getCards("h"); - if (cards.indexOf(card) == (player.storage.olziruo ? cards.length - 1 : 0)) { - return 15 - get.value(card); - } - } - return 5 - get.value(card); - }, - log: false, - precontent() { - delete event.result.skill; - }, - }, - }, - ai: { - order: 1, - result: { player: 1 }, }, }, - //蔡瑁 - olzuolian: { + //曹腾 + olyongzu: { audio: 2, - enable: "phaseUse", + trigger: { player: "phaseZhunbeiBegin" }, filter(event, player) { - return player.getHp() > 0 && game.hasPlayer(target => target.countCards("h")); - }, - filterTarget(card, player, target) { - return target.countCards("h"); + return game.hasPlayer(t => t != player); }, - selectTarget() { - return [1, get.event("player").getHp()]; + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2("olyongzu"), lib.filter.notMe) + .set("ai", target => { + const player = get.event().player; + if (get.attitude(player, target) <= 0) return 0; + const list = get + .info("olyongzu") + .getList(player, target) + .map(listx => listx[0][1]) + .filter(effect => !effect.filter || effect.filter(player)); + return Math.max(...list.map(effect => effect.ai(player))) + Math.max(...list.map(effect => effect.ai(target))); + }) + .forResult(); }, - usable: 1, - multitarget: true, - multiline: true, async content(event, trigger, player) { - const targets = event.targets.sortBySeat(); - const cards = targets.slice().map(i => i.getCards("h").randomGet()); - const videoId = lib.status.videoId++; - game.broadcastAll( - (targets, cards, id, player) => { - let dialog = ui.create.dialog(get.translation(player) + "发动了【佐练】", cards); - dialog.videoId = id; - const getName = target => { - if (target._tempTranslate) return target._tempTranslate; - var name = target.name; - if (lib.translate[name + "_ab"]) return lib.translate[name + "_ab"]; - return get.translation(name); - }; - for (let i = 0; i < targets.length; i++) { - dialog.buttons[i].querySelector(".info").innerHTML = getName(targets[i]); - } - }, - targets, - cards, - videoId, - player - ); - await game.asyncDelay(3); - game.broadcastAll("closeDialog", videoId); - const cards_cardPile = Array.from(ui.cardPile.childNodes).filter(i => i.name == "sha" && get.nature(i, false)); - const cards_discardPile = Array.from(ui.discardPile.childNodes).filter(i => i.name == "sha" && get.nature(i, false)); - if (!Boolean(cards_cardPile.length + cards_discardPile.length)) { - player.popup("杯具"); - player.chat("我属性【杀】呢?!"); - game.log("但牌堆和弃牌堆都没有属性【杀】!"); - return; - } - const result = await player - .chooseToMove("佐练:选择交换展示牌和牌堆或弃牌堆中的属性【杀】") - .set( - "list", - (function (cards, cardPile, discardPile) { - let list = [["展示手牌", cards, "olzuolian_tag"]]; - if (cardPile.length) { - list.push(["牌堆", cardPile]); - } - if (discardPile.length) { - list.push(["弃牌堆", discardPile]); - } - return list; - })(cards, cards_cardPile, cards_discardPile) - ) - .set("filterMove", (from, to, moved) => { - if (typeof to == "number") return false; - const cards = get.event("cards"); - if (cards.includes(from.link) == cards.includes(to.link)) return false; - for (const pl of [ - [from.link, to.link], - [to.link, from.link], - ]) { - if (cards.includes(pl[0]) && moved[0].includes(pl[1]) && cards.indexOf(pl[0]) != moved[0].indexOf(pl[1])) return false; - } - return true; - }) - .set("processAI", list => { - return list.map(i => i[1]); - }) - .set("cards", cards) - .forResult(); - if (result.bool) { - const cardsx = result.moved[0]; - for (let i = 0; i < cardsx.length; i++) { - const current = targets[i], - card = cardsx[i]; - if (!cards.includes(card)) { - if (cards_cardPile.includes(card)) { - current.$throw([cards[i]], 1000); - await current - .lose([cards[i]], ui.cardPile) - .set("insert_index", () => { - return ui.cardPile.childNodes[get.event("num")]; - }) - .set("num", cards_cardPile.indexOf(card)); - } else if (cards_discardPile.includes(card)) { - await current.loseToDiscardpile(cards[i]); - } - await current.gain(card, "gain2"); - } + const target = event.targets[0]; + let list = get.info("olyongzu").getList(player, target), + choosed; + for (const current of [player, target]) { + const result = await current + .chooseButton(["拥族:请选择一项执行", [list.filter(effect => choosed !== effect[0][0]), "textbutton"]], true) + .set("filterButton", button => { + const effect = button.link[1]; + return !effect.filter || effect.filter(current); + }) + .set("ai", button => { + const effect = button.link[1]; + return effect.ai(get.event().player); + }) + .forResult(); + if (result.bool) { + if (!choosed) choosed = result.links[0][0]; + await result.links[0][1].content(current, player); } } }, - ai: { - order: 10, - result: { - target(player, target) { - //插个眼,等PZ157拯救此AI - return 0.5 - Math.random(); + getList(player, target) { + let list = [ + [ + "摸两张牌", + { + async content(player) { + await player.draw(2); + }, + ai(player) { + return get.effect(player, { name: "wuzhong" }, player, player); + }, + }, + ], + [ + "回复1点体力", + { + async content(player) { + await player.recover(); + }, + ai(player) { + return get.recoverEffect(player, player, player); + }, + }, + ], + [ + "复原武将牌", + { + async content(player) { + if (player.isTurnedOver()) { + await player.turnOver(false); + } + if (player.isLinked()) { + await player.link(false); + } + }, + ai(player) { + return (player.isTurnedOver() ? 3 : 0) + player.isLinked(); + }, + }, + ], + ]; + if (get.mode() == "guozhan" ? target.isFriendOf(player) : target.group == player.group) { + list.addArray([ + [ + "手牌上限+1", + { + async content(player) { + player.addSkill("olyongzu_hand"); + player.addMark("olyongzu_hand", 1, false); + }, + ai: () => 1, + }, + ], + [ + "若为魏/群势力,则获得【奸雄】/【天命】直到你的下个回合开始", + { + async content(player, source) { + source.addTempSkill("olyongzu_skill", { player: "phaseBegin" }); + const group = player[get.mode() == "guozhan" ? "identity" : "group"]; + const skill = group == "wei" ? "rejianxiong" : "tianming"; + player.popup(skill); + await player.addAdditionalSkills("olyongzu_skill", skill, true); + }, + filter: player => ["wei", "qun"].includes(player[get.mode() == "guozhan" ? "identity" : "group"]), + ai(player) { + return player[get.mode() == "guozhan" ? "identity" : "group"] == "wei" ? 2 : 3; + }, + }, + ], + ]); + } + return list.map(listx => [listx, listx[0]]); + }, + derivation: ["rejianxiong", "tianming"], + ai: { threaten: 3.5 }, + subSkill: { + skill: { + charlotte: true, + }, + hand: { + charlotte: true, + markimage: "image/card/handcard.png", + intro: { content: "手牌上限+#" }, + mod: { + maxHandcard(player, num) { + return num + player.countMark("olyongzu_hand"); + }, }, }, }, }, - oljingzhou: { + olqingliu: { audio: 2, - trigger: { player: "damageBegin3" }, - filter(event, player) { - return player.getHp() > 0; + trigger: { + global: "phaseBefore", + player: ["enterGame", "dyingAfter"], }, - async cost(event, trigger, player) { - event.result = await player - .chooseTarget(get.prompt2("oljingzhou"), [1, player.getHp()]) - .set("ai", target => { - const player = get.event("player"), - trigger = get.event().getTrigger(); - if (trigger.hasNature() && target == player) { - return -get.effect(target, { name: "tiesuo" }, player, player); - } - return get.effect(target, { name: "tiesuo" }, player, player); - }) - .forResult(); + filter(event, player) { + if (event.name == "dying") { + const group = player.storage.olqingliu; + if (!group || player.group == group) return false; + return ( + game + .getAllGlobalHistory("everything", evt => { + return ( + evt.name == "dying" && + evt.player == player && + !game.getAllGlobalHistory("everything", evtx => { + return evtx.name == "die" && evtx.player == player && evtx.getParent().name == "dying"; + }).length + ); + }) + .indexOf(event) == 0 + ); + } + return event.name != "phase" || game.phaseNumber == 0; }, + forced: true, async content(event, trigger, player) { - for (const i of event.targets) { - await i.link(!i.isLinked()); + if (trigger.name == "dying") await player.changeGroup(player.storage.olqingliu); + else { + const result = await player + .chooseControl("wei", "qun") + .set("ai", () => { + return get.rand(0, 1); + }) + .set("prompt", "清流:请选择你的势力") + .forResult(); + if (result.control) { + const group = result.control; + player.popup(group + "2"); + game.log(player, "选择了", "#y" + get.translation(group + "2")); + player.storage.olqingliu = group == "wei" ? "qun" : "wei"; + if (player.group != group) await player.changeGroup(group); + } } }, }, - //裴秀 - //我们三国杀也有属于自己的爽文.jpg - olmaozhu: { + rejianxiong_caoteng: { audio: true }, + tianming_caoteng: { audio: true }, + //步度根 + //古希腊掌管扣工资的神(bushi + olkouchao: { audio: 2, - trigger: { source: "damageBegin1" }, - filter(event, player) { - const count = lib.skill.olmaozhu.countSkill; - if (!player.isPhaseUsing() || count(player) <= count(event.player)) return false; - const evtx = event.getParent("phaseUse"); - return !player.getHistory("sourceDamage", evt => { - return evt.getParent("phaseUse") == evtx && count(player) > count(evt.player); - }).length; - }, - forced: true, - logTarget: "player", - content() { - trigger.increase("num"); - }, - countSkill(player) { - //飞扬跋扈,OL你无敌了 - const list = [ - ["feiyang", "飞扬"], - ["bahu", "跋扈"], - ]; - return player.getSkills(null, false, false).filter(i => { - if (list.some(text => i.includes(text[0]) && get.translation(i) == text[1])) return true; - const info = get.info(i); - return !info || !info.charlotte; - }).length; + init(player, skill) { + if (!player.storage[skill]) { + player.storage[skill] = ["sha", "huogong", "guohe"]; + } }, - mod: { - cardUsable(card, player, num) { - if (card.name == "sha") return num + lib.skill.olmaozhu.countSkill(player); - }, - maxHandcard(player, num) { - return num + lib.skill.olmaozhu.countSkill(player); - }, + hiddenCard(player, name) { + const storage = player.getStorage("olkouchao"); + for (let i = 0; i < storage.length; i++) { + if (!player.getStorage("olkouchao_used").includes(i) && name == storage[i]) return true; + } + return false; }, - }, - oljinlan: { - audio: 2, - enable: "phaseUse", + enable: "chooseToUse", filter(event, player) { - const count = lib.skill.olmaozhu.countSkill; - return player.countCards("h") < Math.max(...game.filterPlayer().map(i => count(i))); - }, - filterCard: () => false, - selectCard: [0, 1], - prompt() { - const count = lib.skill.olmaozhu.countSkill; - return "将手牌数摸至" + get.cnNumber(Math.max(...game.filterPlayer().map(i => count(i)))) + "张"; + if (!player.countCards("hes")) return false; + const storage = player.getStorage("olkouchao"); + for (let i = 0; i < storage.length; i++) { + if (player.getStorage("olkouchao_used").includes(i)) continue; + if (event.filterCard(get.autoViewAs({ name: storage[i] }, "unsure"), player, event)) return true; + } + return false; }, - usable: 1, - content() { - const count = lib.skill.olmaozhu.countSkill; - player.drawTo(Math.max(...game.filterPlayer().map(i => count(i)))); + chooseButton: { + dialog(event, player) { + const storage = player.getStorage("olkouchao"); + let list = []; + for (let i = 0; i < storage.length; i++) { + const name = storage[i]; + list.push([get.translation(get.type(name)), "", name, undefined, i]); + } + return ui.create.dialog("寇钞", [list, "vcard"]); + }, + filter(button, player) { + const evt = get.event().getParent(); + return evt.filterCard(get.autoViewAs({ name: button.link[2] }, "unsure"), player, evt) && !player.getStorage("olkouchao_used").includes(button.link[4]); + }, + check(button) { + const evt = get.event().getParent(); + const player = get.event().player; + if (evt.type != "phase") return 1; + if (button.link[2] == "jiu") { + if (player.getUseValue({ name: "jiu" }) <= 0) return 0; + if (player.countCards("h", "sha")) return player.getUseValue({ name: "jiu" }); + return 0; + } + return player.getUseValue({ name: button.link[2] }) / 4; + }, + backup(links, player) { + return { + filterCard: true, + position: "hes", + viewAs: { + name: links[0][2], + storage: { olkouchao: links[0][4] + 1 }, + }, + precontent() { + if (!player.storage.olkouchao_used) { + player.when({ global: "roundStart" }).then(() => delete player.storage.olkouchao_used); + } + player.markAuto("olkouchao_used", [lib.skill.olkouchao_backup.viewAs.storage.olkouchao - 1]); + player.addTempSkill("olkouchao_effect"); + }, + }; + }, + prompt(links, player) { + const name = links[0][2], + index = links[0][4] + 1; + return '###寇钞###
    将一张牌当作【' + get.translation(name) + "】使用,然后修改【寇钞】的第" + get.cnNumber(index, true) + "项
    "; + }, }, ai: { - order: 0.000000114514191981, - result: { player: 1 }, + order(_, player) { + if (!player || get.event().type != "phase") return 1; + let names = player.getStorage("olkouchao"); + for (let i = 0; i < names.length; i++) { + if (player.getStorage("olkouchao_used").includes(i)) names.splice(i--, 1); + } + names = names.map(name => { + return { name: name }; + }); + names.sort((a, b) => { + return player.getUseValue(b, true, true) - player.getUseValue(a, true, true); + }); + let max = get.order(names[0], player); + if (max > 0) max += 0.3; + return max; + }, + respondShan: true, + respondSha: true, + skillTagFilter(player, tag, arg) { + if (arg == "respond") return false; + if (!player.countCards("hes")) return false; + return player.getStorage("olkouchao").includes(tag == "respondSha" ? "sha" : "shan"); + }, + result: { + player(player) { + const dying = get.event().dying; + return dying ? get.attitude(player, dying) : 1; + }, + }, + }, + subSkill: { + backup: {}, + effect: { + charlotte: true, + trigger: { player: "useCardAfter" }, + filter(event, player) { + return (event.card.storage || {}).olkouchao; + }, + forced: true, + popup: false, + async content(event, trigger, player) { + const cards = game + .getAllGlobalHistory("everything", evt => { + if (!evt.cards || !evt.cards.someInD("d")) return false; + if (evt.name == "lose") return evt.position == ui.discardPile; + if (evt.name != "cardsDiscard") return false; + const evtx = evt.getParent(); + if (evtx.name != "orderingDiscard") return false; + const evt2 = evtx.relatedEvent || evtx.getParent(); + return evt2 && evt2.name != "useCard"; + }) + .map(evt => evt.cards.filterInD("d")) + .flat() + .reverse(); + const card = cards.find(card => ["basic", "trick"].includes(get.type(card))); + if (card) { + const index = (trigger.card.storage || {}).olkouchao; + player.storage.olkouchao[index - 1] = card.name; + game.log(player, "修改", "#g【寇钞】", "的", "#y第" + get.cnNumber(index, true) + "项", "为", "#g【" + get.translation(card.name) + "】"); + if (player.storage.olkouchao.every(name => get.type(name) == "basic")) { + player.storage.olkouchao = ["shunshou", "shunshou", "shunshou"]; + game.log(player, "修改", "#g【寇钞】", "的", "#y所有项", "为", "#g【顺手牵羊】"); + } + } + }, + }, }, }, - //鸭蛋 - olqingya: { + //马玩 + olhunjiang: { audio: 2, - trigger: { - player: "useCardToPlayered", - }, + enable: "phaseUse", filter(event, player) { - if (event.targets.length != 1 || event.target == player || event.target.hasSkill("nodis")) return false; - if (event.card.name != "sha") return false; - const target = event.target; - let left = [], - right = [], - left2 = player, - right2 = player; - while (left2 != target && right2 != target) { - left2 = left2.getPrevious(); - right2 = right2.getNext(); - if (left2 != target) left.push(left2); - if (right2 != target) right.push(right2); - } - if (target == left2) { - for (const i of left) { - if (i.countDiscardableCards(player)) return true; - } - } - if (target == right2) { - for (const i of right) { - if (i.countDiscardableCards(player)) return true; - } - } - return false; + return game.hasPlayer(target => lib.skill.olhunjiang.filterTarget(null, player, target)); }, - aiJudge(player, target, bool) { - let left = [], - right = [], - left2 = player, - right2 = player, - left3 = false, - right3 = false; - let eff_left = 0, - eff_right = 0; - while (left2 != target && right2 != target) { - left2 = left2.getPrevious(); - right2 = right2.getNext(); - if (left2 != target) left.push(left2); - if (right2 != target) right.push(right2); + filterTarget(card, player, target) { + return target != player && player.inRange(target); + }, + usable: 1, + selectTarget: [1, Infinity], + multitarget: true, + multiline: true, + async content(event, trigger, player) { + const targets = event.targets.sortBySeat(); + let answer_result = [[], []]; + let humans = targets.filter(current => current === game.me || current.isOnline()); + let locals = targets.slice(0).randomSort(); + locals.removeArray(humans); + const eventId = get.id(); + const send = (question, current, eventId) => { + lib.skill.dclisao.chooseControl(question, current, eventId); + game.resume(); + }; + event._global_waiting = true; + let time = 10000; + if (lib.configOL && lib.configOL.choose_timeout) time = parseInt(lib.configOL.choose_timeout) * 1000; + targets.forEach(current => current.showTimer(time)); + if (humans.length > 0) { + const solve = function (resolve, reject) { + return function (result, player) { + if (result && typeof result.index == "number") { + resolve(); + answer_result[result.index].push(player); + } else reject(); + }; + }; + await Promise.any( + humans.map(current => { + return new Promise(async (resolve, reject) => { + if (current.isOnline()) { + current.send(send, question, current, eventId); + current.wait(solve(resolve, reject)); + } else { + const next = lib.skill.olhunjiang.chooseControl(current, player, eventId); + const solver = solve(resolve, reject); + if (_status.connectMode) game.me.wait(solver); + const result = await next.forResult(); + if (_status.connectMode) game.me.unwait(result, current); + else solver(result, current); + } + }); + }) + ).catch(() => {}); + game.broadcastAll("cancel", eventId); } - const card = { name: "guohe", position: "h" }; - if (target == left2) { - for (const i of left) { - if (i.countDiscardableCards(player)) { - left3 = true; - eff_left += get.effect(i, card, player, player); + if (locals.length > 0) { + for (const current of locals) { + const result = await lib.skill.olhunjiang.chooseControl(current, player).forResult(); + if (result && typeof result.index == "number") { + answer_result[result.index].push(current); } } } - if (target == right2) { - for (const i of right) { - if (i.countDiscardableCards(player)) { - right3 = true; - eff_right += get.effect(i, card, player, player); - } - } + delete event._global_waiting; + for (const i of targets) { + i.hideTimer(); + i.addExpose(0.05); + i.popup(answer_result[0].includes(i) ? "成为目标" : "令其摸牌"); + game.log(i, "选择了", "#y" + (answer_result[0].includes(i) ? "成为目标" : "令其摸牌")); } - if (left3 && right3) { - if (!bool) return Math.max(eff_left, eff_right); - if (eff_left > Math.max(0, eff_right)) return "↖顺时针"; - if (eff_right > Math.max(0, eff_left)) return "逆时针↗"; - return "cancel2"; - } else if (left3) { - if (bool) return eff_left > 0 ? "↖顺时针" : "cancel2"; - return eff_left; - } else if (right3) { - if (bool) return eff_right > 0 ? "逆时针↗" : "cancel2"; - return eff_right; - } else return bool ? "cancel2" : 0; - }, - async cost(event, trigger, player) { - const choices = []; - const target = trigger.target; - let left = [], - right = [], - left2 = player, - right2 = player; - while (left2 != target && right2 != target) { - left2 = left2.getPrevious(); - right2 = right2.getNext(); - if (left2 != target) left.push(left2); - if (right2 != target) right.push(right2); - } - if (target == left2) { - for (const i of left) { - if (lib.filter.targetEnabled2(trigger.card, player, i)) { - choices.push("↖顺时针"); - break; - } - } - } - if (target == right2) { - for (const i of right) { - if (lib.filter.targetEnabled2(trigger.card, player, i)) { - choices.push("逆时针↗"); - break; - } + await game.delay(); + if (answer_result[0].length) { + answer_result[0].sortBySeat(); + player.addTempSkill("olhunjiang_addTarget"); + player.markAuto("olhunjiang_addTarget", answer_result[0]); + if (!answer_result[1].length) { + await player.draw(answer_result[0].length); } } - choices.push("cancel2"); - const result = await player - .chooseControl(choices) - .set("prompt", get.prompt("olqingya")) - .set("prompt2", `弃置自己和${get.translation(trigger.target)}某个方向之间的所有角色(不包括你与其)各一张手牌`) - .set("choices", choices) - .set("ai", () => { - var evt = _status.event.getTrigger(); - return lib.skill.olqingya.aiJudge(evt.player, evt.target, true); - }) - .forResult(); - if (result.control !== "cancel2") { - event.result = { - bool: true, - cost_data: { - control: result.control, - }, - }; - } - }, - async content(event, trigger, player) { - const result = event.cost_data; - const targets = []; - game.log(player, "选择了", "#g" + result.control); - if (result.control == "↖顺时针") { - let current = player.getPrevious(); - while (current != trigger.target) { - if (current.countDiscardableCards(player)) targets.push(current); - current = current.getPrevious(); - } - } else { - let current = player.getNext(); - while (current != trigger.target) { - if (current.countDiscardableCards(player)) targets.push(current); - current = current.getNext(); + if (answer_result[1].length) { + answer_result[1].sortBySeat(); + await player.draw(answer_result[1].length); + if (!answer_result[0].length) { + player.addTempSkill("olhunjiang_addTarget"); + player.markAuto("olhunjiang_addTarget", answer_result[1]); } } - for (const current of targets) { - if (!current.countDiscardableCards(player)) continue; - player.line(current); - await player.discardPlayerCard(current, true); - } - await game.asyncDelayx(); - let evt = trigger; - while (true) { - if (!evt.name || lib.phaseName.includes(evt.name)) break; - evt = evt.getParent(); - } - if (player.getHistory("custom", evtx => evtx.olqingya === evt.name).length) return; - player.getHistory("custom").push({ olqingya: evt.name }); - player - .when({ - global: lib.phaseName.map(name => name + "End").concat("phaseAfter"), - }) - .filter(evt => { - if (evt.name === "phase") return true; - let evt2 = trigger; - while (true) { - if (!evt2.name || lib.phaseName.includes(evt2.name)) break; - evt2 = evt2.getParent(); - } - return evt2.name !== evt.name; - }) - .vars({ - curPhaseName: evt.name, - }) - .then(() => { - if (trigger.name === "phase") { - return event.finish(); - } - const history = player.getHistory("useSkill", evt => { - if (evt.skill !== "olqingya") return false; - const evtx = evt.event.getParent(curPhaseName); - if (!evtx || evtx.name !== curPhaseName) return false; - return true; - }), - cards = []; - history.forEach(evt => { - game.countPlayer2(current => { - current.checkHistory("lose", evtx => { - if (evtx.getParent(4) !== evt.event) return; - cards.addArray(evtx.cards.filterInD("d")); - }); - }, true); - }); - if (!cards.length) { - return event.finish(); - } - event.cards = cards; - player - .chooseButton(["倾轧:是否使用其中的一张牌?", event.cards]) - .set("filterButton", button => { - return get.player().hasUseTarget(button.link); - }) - .set("ai", button => { - return get.player().getUseValue(button.link); - }); - }) - .then(() => { - if (result.bool) { - const card = result.links[0]; - player.$gain2(card, false); - game.delayx(); - player.chooseUseTarget(card, true); - } - }); }, ai: { - effect: { - player_use(card, player, target) { - if (!target || player._olqingya_judging || ui.selected.targets.length || player == target || target.hasSkill("nodis")) return; - if (typeof card != "object" || card.name != "sha") return false; - player._olqingya_judging = true; - var effect = lib.skill.olqingya.aiJudge(player, target); - delete player._olqingya_judging; - if (effect > 0) return [1, effect / Math.max(0.01, get.attitude(player, player))]; + order(_, player) { + return get.order({ name: "sha" }, player) + 1; + }, + result: { + target(player, target) { + return get.sgn(get.sgn(get.attitude(player, target)) + 0.5); }, }, }, - }, - oltielun: { - audio: 2, - mod: { - globalFrom(from, to, distance) { - let usedCount = 0; - const stats = from.stat.slice(); - stats.reverse(); - for (const stat of stats) { - Object.values(stat.card).forEach(cnt => { - usedCount += cnt; + chooseControl(player, source, eventId) { + const str = get.translation(source); + return player + .chooseControl("成为目标", "令其摸牌") + .set("prompt", "###" + str + "对你发动了【浑疆】,请选择一项" + '###
    若所有角色选择了同一项,则所有角色也执行另一项
    ') + .set("choiceList", ["令" + str + "本阶段使用【杀】可以额外指定你为目标", "令" + str + "摸一张牌"]) + .set("source", source) + .set("id", eventId) + .set("_global_waiting", true) + .set("ai", () => get.event().idx) + .set( + "idx", + (function () { + let cha = get.effect(player, { name: "sha" }, source, player) * source.mayHaveSha(player, "use", null, "odds") - get.effect(player, { name: "draw" }, source, player); + if (Math.abs(cha) < player.hp * player.hp) return [0, 1].randomGet(); + if (cha > 0) return 0; + return 1; + })() + ); + }, + subSkill: { + addTarget: { + charlotte: true, + onremove: true, + intro: { content: "本阶段使用【杀】可以额外指定$为目标" }, + trigger: { player: "useCard2" }, + filter(event, player) { + if (event.card.name != "sha") return false; + return game.hasPlayer(target => { + if (!player.getStorage("olhunjiang_addTarget").includes(target)) return false; + return !event.targets.includes(target) && lib.filter.targetEnabled2(event.card, player, target) && lib.filter.targetInRange(event.card, player, target); }); - if (stat.isRound) break; - } - return distance - usedCount; + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget( + get.prompt("olhunjiang_addTarget"), + "令任意名【浑疆】选择成为额外目标的角色成为" + get.translation(trigger.card) + "的目标", + (card, player, target) => { + if (!player.getStorage("olhunjiang_addTarget").includes(target)) return false; + const event = get.event().getTrigger(); + return !event.targets.includes(target) && lib.filter.targetEnabled2(event.card, player, target) && lib.filter.targetInRange(event.card, player, target); + }, + [1, Infinity] + ) + .set("ai", target => { + const player = get.event("player"), + event = get.event().getTrigger(); + return get.effect(target, event.card, player); + }) + .forResult(); + }, + async content(event, trigger, player) { + trigger.targets.addArray(event.targets); + game.log(event.targets, "成为了", trigger.card, "的额外目标"); + }, }, }, }, - //SP孙策 - olliantao: { + //蒋琬 + olziruo: { audio: 2, - trigger: { player: "phaseUseBegin" }, + trigger: { player: "useCard" }, filter(event, player) { - return game.hasPlayer(target => target != player); - }, - async cost(event, trigger, player) { - event.result = await player - .chooseTarget(get.prompt2(event.name.slice(0, -"_cost".length)), lib.filter.notMe) - .set("ai", target => { - const player = get.event("player"), - att = get.attitude(player, target); - const colors = Object.keys(lib.color).filter(i => i != "none"); - if ( - !colors.some(color => - player.hasCard(card => { - const juedou = get.autoViewAs({ name: "juedou" }, [card]); - return player.canUse(juedou, target, false); - }, "h") - ) - ) - return 20 + (3 - get.sgn(att)) + Math.random(); - const effs = colors.reduce((list, color) => { - const cards = player.getCards("h", card => { - const juedou = get.autoViewAs({ name: "juedou" }, [card]); - return player.canUse(juedou, target, false); - }); - if (cards.length) { - list.push( - cards.reduce((sum, card) => { - const juedou = get.autoViewAs({ name: "juedou" }, [card]); - return sum + get.effect(target, juedou, player, player); - }, 0) - ); - } - return list; - }, []); - return Math[att > 0 ? "max" : "min"].apply(Math, effs); - }) - .forResult(); + if (!event.olziruo || !event.olziruo[player.playerid]) return false; + return event.olziruo[player.playerid][Boolean(player.storage.olziruo) ? 1 : 0]; }, + forced: true, async content(event, trigger, player) { - const target = event.targets[0]; - const colors = Object.keys(lib.color).filter(i => i != "none"); - if (colors.length && player.countCards("h")) { - const result = await target - .chooseControl(colors) - .set("prompt", "连讨:请选择一个颜色") - .set("ai", () => { - const player = get.event("player"), - source = get.event().getParent().player; - let controls = get.event("controls").slice(); - if (controls.length == 1) return controls[0]; - const getSum = function (color, player, source) { - return source - .getCards("h", card => { - if (get.color(card) != color) return false; - const juedou = get.autoViewAs({ name: "juedou" }, [card]); - return source.canUse(juedou, player, false); - }) - .reduce((num, card) => { - const juedou = get.autoViewAs({ name: "juedou" }, [card]); - return num + get.effect(player, juedou, source, player); - }, 0); - }; - return controls.sort((a, b) => getSum(b, player, source) - getSum(a, player, source))[0]; - }) - .set("prompt2", get.translation(player) + "将对你依次使用由其手牌中所有此颜色的牌转化的【决斗】") - .forResult(); - const color = result.control; - game.broadcastAll( - (color, target) => { - lib.skill.olliantao_backup.filterCardx = [color, target]; - lib.skill.olliantao_backup.filterCard = function (card, player) { - const list = lib.skill.olliantao_backup.filterCardx; - if (get.color(card) != list[0]) return false; - const juedou = get.autoViewAs({ name: "juedou" }, [card]); - return player.canUse(juedou, list[1], false); - }; - }, - color, - target - ); - while ( - target.isIn() && - player.hasCard(card => lib.skill.olliantao_backup.filterCard(card, player)) && - !game.getGlobalHistory("everything", evt => { - return evt.name == "dying" && [player, target].includes(evt.player) && evt.getParent("olliantao") == event; - }).length - ) { - await player - .chooseToUse() - .set("forced", true) - .set("openskilldialog", "连讨:将一张" + get.translation(color) + "手牌当作【决斗】对" + get.translation(target) + "使用") - .set("norestore", true) - .set("_backupevent", "olliantao_backup") - .set("custom", { - add: {}, - replace: { window: function () {} }, - }) - .backup("olliantao_backup") - .set("targetRequired", true) - .set("complexSelect", true) - .set("filterTarget", function (card, player, target) { - if (target != _status.event.sourcex && !ui.selected.targets.includes(_status.event.sourcex)) return false; - return lib.filter.targetEnabled.apply(this, arguments); - }) - .set("sourcex", target) - .set("addCount", false); + player.changeZhuanhuanji("olziruo"); + await player.draw(); + }, + mark: true, + marktext: "☯", + zhuanhuanji: true, + intro: { content: storage => "当你使用最" + (storage ? "右" : "左") + "侧的卡牌时,你摸一张牌。你以此法摸牌后本回合不能整理手牌。" }, + global: "olziruo_mark", + mod: { + aiOrder(player, card, num) { + if (typeof card == "object") { + const cards = player.getCards("h"); + if (cards.indexOf(card) == (player.storage.olziruo ? cards.length - 1 : 0)) return num + 10; } - } - const num = player - .getHistory("sourceDamage", evt => { - return evt.getParent(4) == event; - }) - .reduce((sum, evt) => sum + evt.num, 0); - if (num) await player.draw(num); - if ( - event.name == "olliantao" && - !game.hasPlayer2(current => { - return current.getHistory("damage", evt => { - return evt.getParent(4) == event; - }).length; - }) - ) { - await player.draw(3); - player.addTempSkill("olliantao_buff"); - player.addMark("olliantao_buff", 3, false); - } - if ( - event.name == "junkliantao" && - !target.getHistory("damage", evt => { - return evt.getParent(4) == event; - }).length - ) { - await player.draw(); - player.addTempSkill("olliantao_buff"); - player.addMark("olliantao_buff", 1, false); - } + }, }, + group: ["olziruo_gain", "olziruo_sort"], subSkill: { - backup: { - viewAs: { name: "juedou" }, - position: "h", - check: () => 1 + Math.random(), - precontent() { - delete event.result.skill; + mark: { + charlotte: true, + trigger: { player: "useCardBegin" }, + filter(event, player) { + const cards = player.getCards("h"); + if (!cards.length) return false; + return (event.cards || []).some(card => cards[0] == card || cards[cards.length - 1] == card); + }, + forced: true, + popup: false, + content() { + const cards = player.getCards("h"); + if (!trigger.olziruo) trigger.olziruo = {}; + trigger.olziruo[player.playerid] = [trigger.cards.some(card => cards[0] == card), trigger.cards.some(card => cards[cards.length - 1] == card)]; }, }, - buff: { + gain: { + trigger: { + player: "gainAfter", + }, + filter(event, player) { + if (player.hasSkill("olziruo_ban", null, null, false)) return false; + return event.getParent().name == "draw" && event.getParent(2).name == "olziruo"; + }, + forced: true, + popup: false, + async content(event, trigger, player) { + player.addTempSkill("olziruo_ban"); + }, + }, + ban: { charlotte: true, - onremove: true, - mod: { - maxHandcard(player, num) { - return num + player.countMark("olliantao_buff"); - }, - cardEnabled(card) { - if (card.name == "sha") return false; - }, + mark: true, + intro: { + content: "本回合不能整理手牌", + }, + ai: { noSortCard: true }, + }, + sort: { + enable: "chooseToUse", + filter(event, player) { + return player.countCards("h") > 1 && !player.hasSkillTag("noSortCard"); + }, + direct: true, + lose: false, + discard: false, + delay: 0, + prompt: "整理手牌顺序", + async content(event, trigger, player) { + event.getParent(2).goto(0); + if (_status.connectMode || !event.isMine()) { + player.tempBanSkill("olziruo_sort", { player: ["useCard1", "useSkillBegin", "chooseToUseEnd"] }); + } + const next = player.chooseToMove("自若:请整理手牌顺序", true); + next.set("list", [["手牌", player.getCards("h")]]); + next.set("processAI", list => { + let player = get.player(), + cards = list[0][1].slice(0); + cards.sort((a, b) => get.useful(b, player) - get.useful(a, player)); + if (player.storage.olziruo) cards.reverse(); + return [cards]; + }); + const result = await next.forResult(); + if (!result || !result.bool) return; + let hs = result.moved[0].reverse(); + game.addVideo("lose", player, [get.cardsInfo(hs), [], [], []]); + hs.forEach(i => i.goto(ui.special)); + player.directgain(hs, false); + }, + ai: { + order: 10, + result: { player: 1 }, }, - intro: { content: "手牌上限+#,不能使用【杀】" }, }, }, }, - //王战孙策,但是通渠 - junkliantao: { - audio: "olliantao", - inherit: "olliantao", - }, - //刘辟 - olyicheng: { + olxvfa: { audio: 2, enable: "phaseUse", - usable: 1, - async content(event, trigger, player) { - let num = player.maxHp, - cards = get.cards(num, true); - await player.showCards(cards, get.translation(player) + "发动了【易城】"); - if (player.countCards("h")) { - const sum = cards.reduce((num, card) => num + get.number(card), 0); - const { - result: { bool, moved }, - } = await player - .chooseToMove("易城:请选择你要交换的牌") - .set("filterMove", (from, to) => { - return typeof to !== "number"; - }) - .set("list", [ - [ - "牌堆顶", - cards, - list => { - const sum2 = list.reduce((num, card) => num + get.number(card, false), 0); - return "牌堆顶(现" + sum2 + { 0: "=", "-1": "<", 1: ">" }[get.sgn(sum2 - sum).toString()] + "原" + sum + ")"; - }, - ], - ["手牌", player.getCards("h")], - ]) - .set("filterOk", moved => moved[1].some(i => !get.owner(i))) - .set("processAI", list => { - const player = get.event("player"), - limit = Math.min(get.event("num"), player.countCards("h")); - let cards = list[0][1].slice(), - hs = player.getCards("h"); - if (cards.reduce((num, card) => num + get.value(card), 0) > player.getCards("h").reduce((num, card) => num + get.value(card), 0)) { - cards.sort((a, b) => get.number(a) - get.number(b)); - hs.sort((a, b) => get.number(b) - get.number(a)); - let cards2 = cards.slice(0, limit), - hs2 = hs.slice(0, limit); - if (hs2.reduce((num, card) => num + get.number(card), 0) > cards2.reduce((num, card) => num + get.number(card), 0)) { - cards.removeArray(cards2); - hs.removeArray(hs2); - return [cards.concat(hs2), hs.concat(cards2)]; - } - return [cards, hs]; - } else { - cards.sort((a, b) => get.value(b) - get.value(a)); - hs.sort((a, b) => get.value(a) - get.value(b)); - let cards2 = cards.slice(0, limit), - hs2 = hs.slice(0, limit), - list = [cards, hs]; - for (let i = 0; i < limit; i++) { - if (get.value(cards2[i]) > get.value(hs2[i])) { - const change = [cards2[i], hs2[i]]; - cards[i] = change[1]; - hs[i] = change[0]; - } else break; - } - return list; - } - }) - .set("num", num); - if (bool) { - const puts = player.getCards("h", i => moved[0].includes(i)); - const gains = cards.filter(i => moved[1].includes(i)); - if (puts.length && gains.length) { - player.$throw(puts, 1000); - await player.lose(puts, ui.special); - await player.gain(gains, "gain2"); - cards = moved[0].slice(); - if (cards.length) { - await game.cardsGotoOrdering(cards); - for (let i = cards.length - 1; i >= 0; i--) { - ui.cardPile.insertBefore(cards[i], ui.cardPile.firstChild); - } - game.log(cards, "被放回了牌堆顶"); - game.updateRoundNumber(); - } - await player.showCards(cards, get.translation(player) + "【易城】第一次交换后"); - if (cards.reduce((num, card) => num + get.number(card), 0) > sum && player.countCards("h")) { - const { - result: { bool }, - } = await player.chooseBool("易城:是否使用全部手牌交换" + get.translation(cards) + "?").set( - "choice", - (() => { - return cards.reduce((num, card) => num + get.value(card), 0) > player.getCards("h").reduce((num, card) => num + get.value(card), 0); - })() - ); - if (bool) { - const hs = player.getCards("h"); - player.$throw(hs, 1000); - await player.lose(hs, ui.special); - await player.gain(cards, "gain2"); - cards = hs.slice(); - if (cards.length) { - await game.cardsGotoOrdering(cards); - for (let i = cards.length - 1; i >= 0; i--) { - ui.cardPile.insertBefore(cards[i], ui.cardPile.firstChild); - } - game.log(cards, "被放回了牌堆顶"); - game.updateRoundNumber(); - } - await player.showCards(cards, get.translation(player) + "【易城】第二次交换后"); - } - } - } - } - } - }, - ai: { - order: 9, - result: { player: 1 }, - }, - }, - //陆凯 - olxuanzhu: { - mark: true, - marktext: "☯", - zhuanhuanji: true, - audio: 2, - enable: "chooseToUse", filter(event, player) { - if (!player.countCards("he") || event.type == "wuxie") return false; - return get - .inpileVCardList(info => { - const name = info[2], - type = get.type(name), - infox = get.info({ name: name }); - if (type != "basic" && type != "trick") return false; - if (type == "trick" && (!infox || !infox.filterTarget)) return false; - return (type != "basic") == (player.storage.olxuanzhu || false); - }) - .some(card => event.filterCard({ name: card[2], nature: card[3] }, player, event)); + return (!player.hasSkill("olxvfa_0") && player.countCards("h")) || (!player.hasSkill("olxvfa_1") && player.getExpansions("olxvfa").length); }, - usable: 1, chooseButton: { - dialog(event, player) { - const list = get - .inpileVCardList(info => { - const name = info[2], - type = get.type(name), - infox = get.info({ name: name }); - if (type != "basic" && type != "trick") return false; - if (type == "trick" && (!infox || !infox.filterTarget)) return false; - return (type != "basic") == (player.storage.olxuanzhu || false); - }) - .filter(card => event.filterCard({ name: card[2], nature: card[3] }, player, event)); - return ui.create.dialog("玄注", [list, "vcard"]); - }, - check(button) { - if (get.event().getParent().type != "phase") return 1; - return get.event("player").getUseValue({ name: button.link[2], nature: button.link[3] }); - }, - backup(links, player) { - let next = { - audio: "olxuanzhu", - filterCard: true, - popname: true, - check(card) { - return 1 / (get.value(card) || 0.5); - }, - position: "he", - ignoreMod: true, - precontent() { - const cards = event.result.cards.slice(); - player.addToExpansion(cards, player, "give").gaintag.add("olxuanzhu"); - const viewAs = { - name: event.result.card.name, - nature: event.result.card.nature, - }; - event.result.card = viewAs; - event.result.cards = []; - player - .when("useCardAfter") - .filter(evt => evt.skill == "olxuanzhu_backup") - .then(() => { - const card = cards[0]; - if (get.type(card) != "equip") player.chooseToDiscard("he", true); - else { - const cardx = player.getExpansions("olxuanzhu"); - if (cardx.length) { - player.loseToDiscardpile(cardx); - player.draw(cardx.length); - } - } - }) - .vars({ cards: cards }); - }, - onuse(result, player) { - player.changeZhuanhuanji("olxuanzhu"); - }, - }; - const viewAs = { - name: links[0][2], - nature: links[0][3], - suit: "none", - number: null, - isCard: true, - }; - next.viewAs = viewAs; - if (get.info("xunshi").isXunshi(viewAs)) { - next.filterTarget = function (card, player, target) { - const info = get.info(card); - if (info.changeTarget) { - let targets = [target]; - info.changeTarget(player, targets); - if (targets.length > 1) return false; - } - return lib.filter.filterTarget(card, player, target); - }; - next.selectTarget = 1; - } - return next; - }, - prompt(links, player) { - const viewAs = { - name: links[0][2], - nature: links[0][3], - suit: "none", - number: null, - isCard: true, - }; - const str = "将一张牌称为“玄”置于武将牌上,然后视为使用" + (get.translation(links[0][3]) || "") + "【" + get.translation(links[0][2]) + "】"; - return str + (get.info("xunshi").isXunshi(viewAs) ? "(仅能指定一个目标)" : ""); + dialog(_, player) { + let dialog = ui.create.dialog("蓄发:请选择一项", "hidden"); + const list = [ + ["0", "将至少一半手牌称为“蓄发”置于武将牌上,然后可以将一张牌当作“蓄发”牌中的一张普通锦囊牌使用"], + ["1", "移去至少一半“蓄发”牌,然后可以将一张牌当作其中一张普通锦囊牌使用"], + ].filter(listx => { + if (listx[0] == "0") return !player.hasSkill("olxvfa_0") && player.countCards("h"); + return !player.hasSkill("olxvfa_1") && player.getExpansions("olxvfa").length; + }); + dialog.add([list, "textbutton"]); + if (list.length == 1) dialog.direct = true; + return dialog; }, - }, - hiddenCard(player, name) { - if (!lib.inpile.includes(name) || player.getStat("skill").olxuanzhu || !player.countCards("he")) return false; - return get - .inpileVCardList(info => { - const name = info[2], - type = get.type(name), - infox = get.info({ name: name }); - if (type != "basic" && type != "trick") return false; - if (type == "trick" && (!infox || !infox.filterTarget)) return false; - return (type != "basic") == (player.storage.olxuanzhu || false); - }) - .map(card => card[2]) - .includes(name); - }, - ai: { - order(item, player) { - if (player && get.event().type == "phase") { - let list = get - .inpileVCardList(info => { - const name = info[2], - type = get.type(name), - infox = get.info({ name: name }); - if (type != "basic" && type != "trick") return false; - if (type == "trick" && (!infox || !infox.filterTarget)) return false; - return (type != "basic") == (player.storage.olxuanzhu || false); - }) - .map(card => { - return { name: card[2], nature: card[3] }; - }) - .filter(card => player.getUseValue(card, true, true) > 0); - if (!list.length) return 0; - list.sort((a, b) => { - const getNum = function (card) { - if (get.info("xunshi").isXunshi(card)) - return get.effect( - game - .filterPlayer(target => { - return player.canUse(card, target, true, true); - }) - .sort((a, b) => get.effect(b, card, player, player) - get.effect(a, card, player, player))[0], - card, - player, - player - ); - return player.getUseValue(card, true, true); - }; - return (getNum(b) || 0) - (getNum(a) || 0); - }); - return get.order(list[0], player) * 0.99; - } - return 0.001; + filter(button, player) { + if (button.link == "0") return !player.hasSkill("olxvfa_0") && player.countCards("h"); + return !player.hasSkill("olxvfa_1") && player.getExpansions("olxvfa").length; }, - respondSha: true, - respondShan: true, - skillTagFilter(player, tag, arg) { - if (arg == "respond") return false; - const name = tag == "respondSha" ? "sha" : "shan"; - return get.info("olxuanzhu").hiddenCard(player, name); + check: () => 1 + Math.random(), + backup: links => get.copy(lib.skill["olxvfa_" + ["put", "remove"][parseInt(links[0])]]), + prompt(links) { + if (links[0] == "0") return "###蓄发###将至少一半手牌称为“蓄发”置于武将牌上,然后可以将一张牌当作“蓄发”牌中的一张普通锦囊牌使用"; + return "###蓄发###移去一半“蓄发”牌,然后可以将一张牌当作其中一张普通锦囊牌使用"; }, - result: { player: 1 }, }, intro: { + content: "expansion", markcount: "expansion", - mark(dialog, storage, player) { - const cards = player.getExpansions("olxuanzhu"); - if (cards.length) dialog.addSmall(player.getExpansions("olxuanzhu")); - dialog.addText( - (() => { - if (storage) return "每回合限一次,你可以将一张牌称为“玄”置于武将牌上,然后视为使用任意普通锦囊牌(须指定目标且仅指定一个目标)。若此次置于武将牌上的“玄”:不为装备牌,你弃置一张牌;为装备牌,你将所有“玄”置入弃牌堆,然后摸等量的牌。"; - return "每回合限一次,你可以将一张牌称为“玄”置于武将牌上,然后视为使用任意基本牌。若此次置于武将牌上的“玄”:不为装备牌,你弃置一张牌;为装备牌,你将所有“玄”置入弃牌堆,然后摸等量的牌。"; - })(storage) - ); - }, }, onremove(player, skill) { const cards = player.getExpansions(skill); if (cards.length) player.loseToDiscardpile(cards); }, - subSkill: { backup: {} }, - }, - oljiane: { - audio: 2, - trigger: { player: ["shaDamage", "useCardToEnd"] }, - filter(event, player, name) { - if (event.type != "card" || !event.target || !event.target.isIn() || event.target == player) return false; - if (name == "shaDamage") return true; - return event.card.name != "sha" && !event.getParent()._neutralized; - }, - logTarget: "target", - forced: true, - async content(event, trigger, player) { - trigger.target.addTempSkill("oljiane_neutralized"); - }, - group: "oljiane_neutralize", - global: "oljiane_ai", subSkill: { - neutralize: { - audio: "oljiane", - trigger: { - target: "shaMiss", - global: "eventNeutralized", - }, - filter(event, player, name) { - if (event.type != "card") return false; - return name == "shaMiss" || event._neutralize_event.player == player; + backup: {}, + 0: { charlotte: true }, + 1: { charlotte: true }, + put: { + audio: "olxvfa", + filterCard: true, + selectCard: () => [Math.ceil(get.event("player").countCards("h") / 2), Infinity], + position: "h", + check(card) { + const player = get.event("player"), + value = player.getUseValue(card, true); + if (value > 0) return get.type(card) == "trick" ? 20 + value : 0; + return 15 - get.value(card) - get.useful(card); }, - forced: true, + lose: false, + discard: false, + delay: 0, async content(event, trigger, player) { - player.addTempSkill("oljiane_nouse"); + player.addTempSkill("olxvfa_0", "phaseUseAfter"); + await player.addToExpansion(event.cards, player, "give").set("gaintag", ["olxvfa"]); + const cards = player.getExpansions("olxvfa"); + if (cards.some(card => get.type(card) == "trick" && player.hasCard(cardx => player.hasUseTarget(get.autoViewAs({ name: card.name }, [cardx]), true), "hes"))) { + const result = await player + .chooseButton(['###蓄发###
    是否将一张牌当作一张“蓄发”牌使用?
    ', cards]) + .set("filterButton", button => { + const player = get.event("player"), + card = button.link; + return get.type(card) == "trick" && player.hasCard(cardx => player.hasUseTarget(get.autoViewAs({ name: card.name }, [cardx]), true), "hes"); + }) + .set("ai", button => { + const player = get.event("player"), + card = button.link; + return player.getUseValue({ name: card.name, isCard: true }, true); + }) + .forResult(); + if (result.bool) { + const card = result.links[0]; + game.broadcastAll(function (card) { + lib.skill.olxvfa_backupx.viewAs = { name: card.name }; + }, card); + await player + .chooseToUse() + .set("openskilldialog", "###蓄发###将一张牌当作【" + get.translation(card.name) + "】使用") + .set("norestore", true) + .set("addCount", false) + .set("_backupevent", "olxvfa_backupx") + .set("custom", { + add: {}, + replace: { window: function () {} }, + }) + .backup("olxvfa_backupx"); + } + } }, }, - ai: { - ai: { - directHit_ai: true, - skillTagFilter(player, tag, arg) { - if (!arg || !arg.target || !arg.target.hasSkill("oljiane_neutralized")) return false; - }, + remove: { + audio: "olxvfa", + filterCard: () => false, + selectCard: -1, + delay: 0, + async content(event, trigger, player) { + player.addTempSkill("olxvfa_1", "phaseUseAfter"); + const cards = player.getExpansions("olxvfa"), + num = Math.ceil(cards.length / 2); + const result = await player + .chooseButton(['###蓄发###
    请移去至少' + get.cnNumber(num) + "张“蓄发”牌
    ", cards], [num, Infinity], true) + .set("ai", button => { + const player = get.event("player"), + value = player.getUseValue(button.link, true); + if (value > 0 && get.type(button.link) == "trick") { + if ( + !ui.selected.buttons.some(but => { + return get.type(but.link) == "trick" && player.getUseValue(but.link, true) > 0; + }) + ) + return 20 + value; + return 0; + } + return 1 / (get.useful(button.link) || 0.5); + }) + .forResult(); + if (result.bool) { + const cardx = result.links; + await player.loseToDiscardpile(cardx); + if (cardx.some(card => get.type(card) == "trick" && player.hasCard(cardxx => player.hasUseTarget(get.autoViewAs({ name: card.name }, [cardxx]), true), "hes"))) { + const result2 = await player + .chooseButton(['###蓄发###
    是否将一张牌当作一张移去的“蓄发”牌使用?
    ', cardx]) + .set("filterButton", button => { + const player = get.event("player"), + card = button.link; + return get.type(card) == "trick" && player.hasCard(cardx => player.hasUseTarget(get.autoViewAs({ name: card.name }, [cardx]), true), "hes"); + }) + .set("ai", button => { + const player = get.event("player"), + card = button.link; + return player.getUseValue({ name: card.name, isCard: true }, true); + }) + .forResult(); + if (result2.bool) { + const card = result2.links[0]; + game.broadcastAll(function (card) { + lib.skill.olxvfa_backupx.viewAs = { name: card.name }; + }, card); + await player + .chooseToUse() + .set("openskilldialog", "###蓄发###将一张牌当作【" + get.translation(card.name) + "】使用") + .set("norestore", true) + .set("addCount", false) + .set("_backupevent", "olxvfa_backupx") + .set("custom", { + add: {}, + replace: { window: function () {} }, + }) + .backup("olxvfa_backupx"); + } + } + } }, }, - neutralized: { - charlotte: true, - mark: true, - marktext: "牌", - intro: { content: "本回合无法抵消牌" }, - trigger: { global: "useCard" }, - forced: true, - popup: false, - async content(event, trigger, player) { - const id = player.playerid; - const map = trigger.customArgs; - if (!map[id]) map[id] = {}; - map[id].directHit2 = true; + backupx: { + filterCard(card) { + return get.itemtype(card) == "card"; }, - mod: { - wuxieJudgeEnabled: () => false, - wuxieEnabled: () => false, + position: "hes", + check(card) { + const player = get.event("player"); + if (player.hasValueTarget(card, true, true)) return 0; + if (player.hasSkill("olziruo")) { + const cards = player.getCards("h"); + if (cards.indexOf(card) == (player.storage.olziruo ? cards.length - 1 : 0)) { + return 15 - get.value(card); + } + } + return 5 - get.value(card); + }, + log: false, + precontent() { + delete event.result.skill; }, }, - nouse: { - charlotte: true, - mark: true, - marktext: '', - intro: { content: "本回合无法成为牌的目标" }, - mod: { targetEnabled: () => false }, - }, + }, + ai: { + order: 1, + result: { player: 1 }, }, }, - //刘磐 - olpijing: { + //蔡瑁 + olzuolian: { audio: 2, - trigger: { player: "useCardToPlayered" }, + enable: "phaseUse", filter(event, player) { - return (event.card.name == "sha" || get.type(event.card) == "trick") && event.targets.length == 1; + return player.getHp() > 0 && game.hasPlayer(target => target.countCards("h")); + }, + filterTarget(card, player, target) { + return target.countCards("h"); + }, + selectTarget() { + return [1, get.event("player").getHp()]; }, usable: 1, - direct: true, - locked: false, + multitarget: true, + multiline: true, async content(event, trigger, player) { - const num = Math.max(1, player.getDamagedHp()); - const { - result: { bool, targets }, - } = await player - .chooseTarget(get.prompt("olpijing"), [1, num], (card, player, target) => { - const trigger = get.event().getTrigger(); - if (trigger.targets.includes(target)) return true; - return target != player && lib.filter.targetEnabled2(trigger.card, player, target) && lib.filter.targetInRange(trigger.card, player, target); - }) - .set("ai", target => { - const player = get.event("player"), - trigger = get.event().getTrigger(); - return (trigger.targets.includes(target) ? -1 : 1) * get.effect(target, trigger.card, player, player) * (target.getStorage("olpijing_effect").includes(player) ? 2 : 1) + get.effect(target, { name: "shunshou_copy2" }, player, player); - }) - .set("prompt2", "令至多" + get.cnNumber(num) + "名角色成为或取消成为" + get.translation(trigger.card) + "的目标并随机交给你一张牌"); - if (bool) { - player.logSkill("olpijing", targets); - for (const i of targets) { - trigger.targets[trigger.targets.includes(i) ? "add" : "remove"](i); - } - for (const target of targets) { - target.addSkill("olpijing_effect"); - target.markAuto("olpijing_effect", [player]); - const cards = target.getGainableCards(player, "he"); - if (cards.length) { - await target.give(cards.randomGets(1), player); + const targets = event.targets.sortBySeat(); + const cards = targets.slice().map(i => i.getCards("h").randomGet()); + const videoId = lib.status.videoId++; + game.broadcastAll( + (targets, cards, id, player) => { + let dialog = ui.create.dialog(get.translation(player) + "发动了【佐练】", cards); + dialog.videoId = id; + const getName = target => { + if (target._tempTranslate) return target._tempTranslate; + var name = target.name; + if (lib.translate[name + "_ab"]) return lib.translate[name + "_ab"]; + return get.translation(name); + }; + for (let i = 0; i < targets.length; i++) { + dialog.buttons[i].querySelector(".info").innerHTML = getName(targets[i]); } - } - } else player.storage.counttrigger.olpijing--; - }, - mod: { - aiOrder(player, card, num) { - if (!(card.name == "sha" || get.type(card) == "trick")) return; - const info = get.info(card); - if ( - info && - !info.notarget && - (info.toself || info.singleCard || !info.selectTarget || info.selectTarget == 1) && - game.countPlayer(target => { - if (get.effect(target, card, player, player) <= 0) return false; - return lib.filter.targetEnabled2(card, player, target) && lib.filter.targetInRange(card, player, target); - }) > 1 - ) - return num + 0.01; - }, - }, - subSkill: { - effect: { - charlotte: true, - onremove: true, - intro: { - content: "使用的下一张基本牌或普通锦囊牌指定唯一目标时,可指定$为额外目标或摸一张牌", - }, - trigger: { player: "useCardToPlayer" }, - filter(event, player) { - return (get.type(event.card) == "basic" || get.type(event.card) == "trick") && event.targets.length == 1; }, - forced: true, - popup: false, - async content(event, trigger, player) { - const storage = player.getStorage("olpijing_effect"); - player.removeSkill("olpijing_effect"); - const { - result: { bool, targets }, - } = await player - .chooseTarget("披荆:请选择此牌的额外目标", [1, storage.length], (card, player, target) => { - const trigger = get.event().getTrigger(); - return !trigger.targets.includes(target) && get.event("storage").includes(target) && lib.filter.targetEnabled2(trigger.card, player, target) && lib.filter.targetInRange(trigger.card, player, target); - }) - .set("prompt2", "不选择的角色视为你选择摸牌项") - .set("ai", target => { - const player = get.event("player"), - trigger = get.event().getTrigger(); - return get.effect(target, trigger.card, player, player) - get.effect(player, { name: "draw" }, player, player); - }) - .set("storage", storage); - if (bool) { - player.line(targets); - trigger.targets.addArray(targets); - if (storage.length - targets.length > 0) { - player.draw(storage.length - targets.length); + targets, + cards, + videoId, + player + ); + await game.delay(3); + game.broadcastAll("closeDialog", videoId); + const cards_cardPile = Array.from(ui.cardPile.childNodes).filter(i => i.name == "sha" && get.nature(i, false)); + const cards_discardPile = Array.from(ui.discardPile.childNodes).filter(i => i.name == "sha" && get.nature(i, false)); + if (!Boolean(cards_cardPile.length + cards_discardPile.length)) { + player.popup("杯具"); + player.chat("我属性【杀】呢?!"); + game.log("但牌堆和弃牌堆都没有属性【杀】!"); + return; + } + const result = await player + .chooseToMove("佐练:选择交换展示牌和牌堆或弃牌堆中的属性【杀】") + .set( + "list", + (function (cards, cardPile, discardPile) { + let list = [["展示手牌", cards, "olzuolian_tag"]]; + if (cardPile.length) { + list.push(["牌堆", cardPile]); } - } else player.draw(storage.length); - }, - }, - }, - }, - //郭图 - olqushi: { - audio: 2, - enable: "phaseUse", - usable: 1, - delay: false, - async content(event, trigger, player) { - await player.draw(); - if (player.countCards("h") && game.hasPlayer(target => target != player)) { - const { - result: { bool, targets, cards }, - } = await player.chooseCardTarget({ - forced: true, - prompt: "将一张手牌作为“趋”扣置于其他角色的武将牌上", - filterTarget: lib.filter.notMe, - filterCard: true, - position: "h", - ai1(card) { - if (get.type(card, false) == "equip") return 1 - get.value(card); - return 7 - get.value(card); - }, - ai2(target) { - const att = get.sgn(get.sgn(get.attitude(get.event("player"), target)) + 0.5); - return (target.countCards("h") + 1) * att; - }, - }); - if (bool) { - const target = targets[0]; - target.addSkill("olqushi_effect"); - target.markAuto("olqushi_effect", [player]); - game.log(player, "将一张牌扣置于", target, "的武将牌上"); - target.addToExpansion(cards, player, "giveAuto").gaintag.add("olqushi_effect"); + if (discardPile.length) { + list.push(["弃牌堆", discardPile]); + } + return list; + })(cards, cards_cardPile, cards_discardPile) + ) + .set("filterMove", (from, to, moved) => { + if (typeof to == "number") return false; + const cards = get.event("cards"); + if (cards.includes(from.link) == cards.includes(to.link)) return false; + for (const pl of [ + [from.link, to.link], + [to.link, from.link], + ]) { + if (cards.includes(pl[0]) && moved[0].includes(pl[1]) && cards.indexOf(pl[0]) != moved[0].indexOf(pl[1])) return false; + } + return true; + }) + .set("processAI", list => { + return list.map(i => i[1]); + }) + .set("cards", cards) + .forResult(); + if (result.bool) { + const cardsx = result.moved[0]; + for (let i = 0; i < cardsx.length; i++) { + const current = targets[i], + card = cardsx[i]; + if (!cards.includes(card)) { + if (cards_cardPile.includes(card)) { + current.$throw([cards[i]], 1000); + await current + .lose([cards[i]], ui.cardPile) + .set("insert_index", () => { + return ui.cardPile.childNodes[get.event("num")]; + }) + .set("num", cards_cardPile.indexOf(card)); + } else if (cards_discardPile.includes(card)) { + await current.loseToDiscardpile(cards[i]); + } + await current.gain(card, "gain2"); + } } } }, ai: { - order: 1, - result: { player: 1 }, - }, - subSkill: { - effect: { - charlotte: true, - onremove(player, skill) { - delete player.storage[skill]; - const cards = player.getExpansions(skill); - if (cards.length) player.loseToDiscardpile(cards); - }, - marktext: "趋", - intro: { - content: "expansion", - markcount: "expansion", - mark(dialog, storage, player) { - if (storage.some(source => source.isUnderControl(true))) dialog.add(player.getExpansions("olqushi_effect")); - else return "共扣置" + get.cnNumber(player.getExpansions("olqushi_effect").length) + "张“趋”"; - }, - }, - trigger: { player: "phaseJieshuBegin" }, - forced: true, - popup: false, - async content(event, trigger, player) { - const cards = player.getExpansions("olqushi_effect"); - if (cards.length) { - await player.loseToDiscardpile(cards); - const targets = player - .getStorage("olqushi_effect") - .filter(i => { - return i.isIn(); - }) - .sortBySeat(); - const num = Math.min( - player - .getHistory("useCard", evt => { - return evt.targets && evt.targets.length; - }) - .reduce((targets, evt) => { - targets.addArray(evt.targets); - return targets; - }, []).length, - 5 - ); - if ( - targets.length && - num > 0 && - player.getHistory("useCard", evt => { - return cards.some(card => get.type2(card) == get.type2(evt.card)); - }).length - ) { - for (const target of targets) await target.draw(num); - } - } - player.removeSkill("olqushi_effect"); + order: 10, + result: { + target(player, target) { + //插个眼,等PZ157拯救此AI + return 0.5 - Math.random(); }, }, }, }, - olweijie: { + oljingzhou: { audio: 2, - enable: ["chooseToUse", "chooseToRespond"], + trigger: { player: "damageBegin3" }, filter(event, player) { - if ( - !game.hasPlayer(target => { - return get.distance(player, target) == 1 && target.countCards("h"); - }) || - _status.currentPhase === player || - event.olweijie - ) - return false; - return get - .inpileVCardList(info => { - const name = info[2]; - return get.type(name) == "basic"; + return player.getHp() > 0; + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2("oljingzhou"), [1, player.getHp()]) + .set("ai", target => { + const player = get.event("player"), + trigger = get.event().getTrigger(); + if (trigger.hasNature() && target == player) { + return -get.effect(target, { name: "tiesuo" }, player, player); + } + return get.effect(target, { name: "tiesuo" }, player, player); }) - .some(card => event.filterCard({ name: card[2], nature: card[3], isCard: true }, player, event)); + .forResult(); }, - chooseButton: { - dialog(event, player) { - const list = get - .inpileVCardList(info => { - const name = info[2]; - return get.type(name) == "basic"; - }) - .filter(card => event.filterCard({ name: card[2], nature: card[3], isCard: true }, player, event)); - return ui.create.dialog("诿解", [list, "vcard"]); - }, - filter(button, player) { - return get.event().getParent().filterCard({ name: button.link[2], nature: button.link[3], isCard: true }, player, _status.event.getParent()); - }, - check(button) { - if (get.event().getParent().type != "phase") return 1; - return get.event("player").getUseValue({ name: button.link[2], nature: button.link[3], isCard: true }); - }, - backup(links, player) { - return { - viewAs: { - name: links[0][2], - nature: links[0][3], - isCard: true, - }, - filterCard: () => false, - selectCard: -1, - *precontent(event, map) { - delete event.result.skill; - const player = map.player; - let stop = false; - const result = yield player - .chooseTarget("请选择一名距离为1的角色", "弃置其一张手牌,若此牌牌名为【" + get.translation(event.result.card.name) + "】,则视为你使用/打出之", (card, player, target) => { - return get.distance(player, target) == 1 && target.countCards("h"); - }) - .set("ai", target => 1 - get.sgn(get.attitude(get.event("player"), target))); - if (result.bool) { - const target = result.targets[0]; - player.logSkill("olweijie", target); - player.tempBanSkill("olweijie", null, false); - const result2 = yield player - .discardPlayerCard(target, "h", true) - .set("prompt2", "若弃置的牌名为【" + get.translation(event.result.card.name) + "】,则视为你使用/打出之") - .set("ai", button => { - if (button.link.isKnownBy(get.event("player")) && button.link.name == get.event("namex")) return 114514; - return 1 + Math.random(); - }) - .set("namex", event.result.card.name); - if (result2.bool) { - const card = result2.cards[0]; - if (get.name(card, target) == event.result.card.name) { - player.popup("洗具"); - stop = true; - } else player.popup("杯具"); - } - } - if (!stop) { - const evt = event.getParent(); - evt.set("olweijie", true); - evt.goto(0); - delete evt.openskilldialog; - return; - } - }, - }; - }, - prompt(links, player) { - const nature = get.translation(links[0][3]) || ""; - const name = "【" + get.translation(links[0][2]) + "】"; - return "弃置距离为1的一名角色的一张手牌,若此牌牌名为" + name + ",则你视为使用" + nature + name; - }, - }, - ai: { - order: 10, - respondSha: true, - respondShan: true, - skillTagFilter(player, tag) { - const name = tag == "respondSha" ? "sha" : "shan"; - return lib.skill.olweijie.hiddenCard(player, name); - }, - result: { - player(player) { - if (_status.event.dying && get.attitude(player, _status.event.dying) <= 0) return 0; - return game.hasPlayer(target => { - if (get.attitude(player, target) > 0) return false; - return get.distance(player, target) == 1 && target.countCards("h"); - }) - ? 1 - : 0; - }, - }, - }, - hiddenCard(player, name) { - if (!lib.inpile.includes(name) || _status.currentPhase === player || player.isTempBanned("olweijie")) return false; - return ( - get.type(name) == "basic" && - game.hasPlayer(target => { - return get.distance(player, target) == 1 && target.countCards("h"); - }) - ); - }, - }, - //胡金定 - olqingyuan: { - audio: 2, - trigger: { - global: ["phaseBefore", "gainAfter", "loseAsyncAfter"], - player: ["enterGame", "damageEnd"], - }, - filter(event, player) { - const storage = player.getStorage("olqingyuan"); - if (event.name == "gain" || event.name == "loseAsync") { - if (player.hasSkill("olqingyuan_used")) return false; - return storage.some(target => event.getg(target).length) && storage.some(target => target.hasCard(card => lib.filter.canBeGained(card, target, player), "h")); - } - if (!game.hasPlayer(target => !storage.includes(target) && target != player)) return false; - if (event.name == "damage" && player.getAllHistory("damage").indexOf(event) != 0) return false; - return event.name != "phase" || game.phaseNumber == 0; - }, - forced: true, async content(event, trigger, player) { - if (trigger.name == "gain" || trigger.name == "loseAsync") { - const target = player - .getStorage("olqingyuan") - .filter(target => target.hasCard(card => lib.filter.canBeGained(card, target, player), "h")) - .randomGet(); - player.line(target); - player.addTempSkill("olqingyuan_used"); - player.gain( - target - .getCards("h", card => { - return lib.filter.canBeGained(card, target, player); - }) - .randomGet(), - target, - "giveAuto" - ); - } else { - const filterTarget = (card, player, target) => { - return target != player && !player.getStorage("olqingyuan").includes(target); - }, - targetsx = game.filterPlayer(current => filterTarget(null, player, current)); - let result; - if (targetsx.length == 1) result = { bool: true, targets: targetsx }; - else - result = await player - .chooseTarget(filterTarget, true) - .set("prompt2", "每回合限一次,当你以此法选择的角色获得牌后,你随机获得其中一名角色的一张手牌") - .set("prompt", "请选择【轻缘】的目标") - .set("ai", target => { - const player = get.event("player"); - return get.effect(target, new lib.element.VCard({ name: "shunshou_copy2" }), player, player); - }) - .forResult(); - if (result.bool) { - const target = result.targets[0]; - player.line(target); - game.log(player, "选择了", target); - player.markAuto("olqingyuan", [target]); - } + for (const i of event.targets) { + await i.link(!i.isLinked()); } }, - subSkill: { used: { charlotte: true } }, - intro: { content: "已选择$为目标" }, - ai: { - expose: 0.3, - }, }, - olchongshen: { + //裴秀 + //我们三国杀也有属于自己的爽文.jpg + olmaozhu: { audio: 2, - locked: false, - enable: "chooseToUse", - filterCard(card) { - return get.itemtype(card) == "card" && card.hasGaintag("olchongshen") && get.color(card) == "red"; - }, - position: "h", - viewAs: { name: "shan" }, - viewAsFilter(player) { - if (!player.countCards("h", card => card.hasGaintag("olchongshen") && get.color(card) == "red")) return false; + trigger: { source: "damageBegin1" }, + filter(event, player) { + const count = lib.skill.olmaozhu.countSkill; + if (!player.isPhaseUsing() || count(player) <= count(event.player)) return false; + const evtx = event.getParent("phaseUse"); + return !player.getHistory("sourceDamage", evt => { + return evt.getParent("phaseUse") == evtx && count(player) > count(evt.player); + }).length; }, - prompt: "将本轮得到的红色牌当作【闪】使用", - check(card) { - return 7 - get.value(card); + forced: true, + logTarget: "player", + content() { + trigger.increase("num"); }, - ai: { - order: 2, - respondShan: true, - skillTagFilter(player, tag, arg) { - if (arg == "respond" || !player.countCards("h", card => _status.connectMode || (card.hasGaintag("olchongshen") && get.color(card) == "red"))) return false; - }, - effect: { - target(card, player, target, current) { - if (get.tag(card, "respondShan") && current < 0) return 0.6; - }, - }, + countSkill(player) { + //飞扬跋扈,OL你无敌了 + const list = [ + ["feiyang", "飞扬"], + ["bahu", "跋扈"], + ]; + return player.getSkills(null, false, false).filter(i => { + if (list.some(text => i.includes(text[0]) && get.translation(i) == text[1])) return true; + const info = get.info(i); + return !info || !info.charlotte; + }).length; }, - group: "olchongshen_mark", mod: { - aiValue(player, card, num) { - if (get.name(card) != "shan" && get.itemtype(card) == "card" && (!card.hasGaintag("olchongshen") || get.color(card) != "red")) return; - let cards = player.getCards("hs", card => get.name(card) == "shan" || card.hasGaintag("olchongshen")); - cards.sort((a, b) => (get.name(b) == "shan" ? 1 : 2) - (get.name(a) == "shan" ? 1 : 2)); - const geti = () => { - if (cards.includes(card)) return cards.indexOf(card); - return cards.length; - }; - if (get.name(card) == "shan") return Math.min(num, [6, 4, 3][Math.min(geti(), 2)]) * 0.6; - return Math.max(num, [6.5, 4, 3][Math.min(geti(), 2)]); - }, - aiUseful() { - return lib.skill.olchongshen.mod.aiValue.apply(this, arguments); + cardUsable(card, player, num) { + if (card.name == "sha") return num + lib.skill.olmaozhu.countSkill(player); }, - // ignoredHandcard(card,player){ - // if(card.hasGaintag('olchongshen')) return true; - // }, - // cardDiscardable(card,player,name){ - // if(name=='phaseDiscard'&&card.hasGaintag('olchongshen')) return false; - // }, - }, - init(player) { - if (game.phaseNumber > 0) { - const hs = player.getCards("h"), - history = player.getAllHistory(); - let cards = []; - for (let i = history.length - 1; i >= 0; i--) { - for (const evt of history[i].gain) { - cards.addArray(evt.cards); - } - if (history[i].isRound) break; - } - cards = cards.filter(i => hs.includes(i)); - if (cards.length) player.addGaintag(cards, "olchongshen"); - } - }, - onremove(player) { - player.removeGaintag("olchongshen"); - }, - subSkill: { - mark: { - charlotte: true, - trigger: { player: "gainBegin", global: "roundStart" }, - filter(event, player) { - return event.name == "gain" || game.roundNumber > 1; - }, - forced: true, - popup: false, - content() { - if (trigger.name == "gain") trigger.gaintag.add("olchongshen"); - else player.removeGaintag("olchongshen"); - }, + maxHandcard(player, num) { + return num + lib.skill.olmaozhu.countSkill(player); }, }, }, - //田畴 - olshandao: { + oljinlan: { audio: 2, enable: "phaseUse", filter(event, player) { - return game.hasPlayer(target => lib.skill.olshandao.filterTarget(null, player, target)); - }, - filterTarget(card, player, target) { - return target.countCards("he"); + const count = lib.skill.olmaozhu.countSkill; + return player.countCards("h") < Math.max(...game.filterPlayer().map(i => count(i))); + }, + filterCard: () => false, + selectCard: [0, 1], + prompt() { + const count = lib.skill.olmaozhu.countSkill; + return "将手牌数摸至" + get.cnNumber(Math.max(...game.filterPlayer().map(i => count(i)))) + "张"; }, usable: 1, - selectTarget: [1, Infinity], - multitarget: true, - multiline: true, - async content(event, trigger, player) { - const wugu = new lib.element.VCard({ name: "wugu" }); - const wanjian = new lib.element.VCard({ name: "wanjian" }); - const targets = game.filterPlayer(target => { - if (target == player) return false; - return !event.targets.includes(target) && player.canUse(wanjian, target, false); - }), - targetx = event.targets.sortBySeat(); - let dialog = ["将这些角色的各一张牌置于牌堆顶,然后视为对这些角色使用【五谷丰登】"]; - for (const target of targetx) { - const name = target == player ? "你" : get.translation(target); - if (target.countCards("h")) { - dialog.add('
    ' + name + "的手牌区
    "); - if (player.hasSkillTag("viewHandcard", null, target, true) || player == target) dialog.push(target.getCards("h")); - else dialog.push([target.getCards("h"), "blank"]); - } - if (target.countCards("e")) dialog.addArray(['
    ' + name + "的装备区
    ", target.getCards("e")]); - } - const { - result: { bool, links }, - } = await player - .chooseButton(dialog, event.targets.length, true) - .set("filterButton", button => { - return !ui.selected.buttons.some(but => get.owner(but.link) == get.owner(button.link)); - }) - .set("ai", button => 1 / (get.value(button.link, get.owner(button.link)) || 0.5)); - if (bool) { - const cards = links.sort((a, b) => targetx.indexOf(get.owner(a)) - targetx.indexOf(get.owner(b))); - for (const card of cards) { - const target = get.owner(card); - target.$throw(1, 1000); - await target.lose([card], ui.cardPile, "insert"); - } - const targety = targetx.filter(target => player.canUse(wugu, target, false)); - if (targety.length) await player.useCard(wugu, targety, false); - if (targets.length) await player.useCard(wanjian, targets, false); - } + content() { + const count = lib.skill.olmaozhu.countSkill; + player.drawTo(Math.max(...game.filterPlayer().map(i => count(i)))); }, ai: { - order: 9, - result: { target: 1 }, + order: 0.000000114514191981, + result: { player: 1 }, }, }, - //李异 - olchanshuang: { + //鸭蛋 + olqingya: { audio: 2, - enable: "phaseUse", - filterTarget: lib.filter.notMe, - usable: 1, - content: function* (event, map) { - const player = map.player, - target = event.target; - const choiceList = ["重铸一张牌", "使用一张【杀】", "弃置两张牌"], - list = ["重铸", "出杀", "弃牌", "无法选择"]; - let result = []; - for (let current of [player, target]) { - let list1 = list.slice(), - choiceList1 = choiceList.slice(); - list1 = list1.filter(control => { - if (control == "无法选择") return false; - if (control == "重铸") return current.countCards("he", card => current.canRecast(card)); - if (control == "出杀") return current.countCards("he", card => card.name == "sha" && current.hasUseTarget(card)); - if (control == "弃牌") return current.countCards("he", card => lib.filter.cardDiscardable(card, current)) > 1; - }); - choiceList1 = choiceList.filter(control => { - if (choiceList.indexOf(control) == 0) return current.countCards("he", card => current.canRecast(card)); - if (choiceList.indexOf(control) == 1) return current.countCards("he", card => card.name == "sha" && current.hasUseTarget(card)); - if (choiceList.indexOf(control) == 2) return current.countCards("he", card => lib.filter.cardDiscardable(card, current)) > 1; - }); - if (list1.length) { - if (list1.length == 1) result.push(list.indexOf(list1[0])); - else { - let result1 = yield current - .chooseControl(list1) - .set("ai", () => { - const current = _status.event.player; - const controls = _status.event.controls.slice(); - if (controls.includes("出杀") && current.countCards("hs", card => card.name == "sha" && current.hasValueTarget(card))) return "出杀"; - if (controls.includes("重铸")) return "重铸"; - return "弃牌"; - }) - .set("choiceList", choiceList1); - if (result1.control) result.push(list.indexOf(result1.control)); + trigger: { + player: "useCardToPlayered", + }, + filter(event, player) { + if (event.targets.length != 1 || event.target == player || event.target.hasSkill("nodis")) return false; + if (event.card.name != "sha") return false; + const target = event.target; + let left = [], + right = [], + left2 = player, + right2 = player; + while (left2 != target && right2 != target) { + left2 = left2.getPrevious(); + right2 = right2.getNext(); + if (left2 != target) left.push(left2); + if (right2 != target) right.push(right2); + } + if (target == left2) { + for (const i of left) { + if (i.countDiscardableCards(player)) return true; + } + } + if (target == right2) { + for (const i of right) { + if (i.countDiscardableCards(player)) return true; + } + } + return false; + }, + aiJudge(player, target, bool) { + let left = [], + right = [], + left2 = player, + right2 = player, + left3 = false, + right3 = false; + let eff_left = 0, + eff_right = 0; + while (left2 != target && right2 != target) { + left2 = left2.getPrevious(); + right2 = right2.getNext(); + if (left2 != target) left.push(left2); + if (right2 != target) right.push(right2); + } + const card = { name: "guohe", position: "h" }; + if (target == left2) { + for (const i of left) { + if (i.countDiscardableCards(player)) { + left3 = true; + eff_left += get.effect(i, card, player, player); } - } else result.push(3); + } } - player.popup(list[result[0]]); - target.popup(list[result[1]]); - for (let current of [player, target]) { - switch (list[result[current == player ? 0 : 1]]) { - case "重铸": { - let result2 = yield current.chooseCard("he", "请重铸一张牌", (card, player) => player.canRecast(card), true); - if (result2.bool) current.recast(result2.cards); - break; + if (target == right2) { + for (const i of right) { + if (i.countDiscardableCards(player)) { + right3 = true; + eff_right += get.effect(i, card, player, player); } - case "出杀": { - current.chooseToUse({ - prompt: "请使用一张【杀】", - filterCard: function (card, player) { - if (card.name != "sha") return false; - return lib.filter.filterCard.apply(this, arguments); - }, - forced: true, - ai1: function (card) { - return _status.event.player.getUseValue(card); - }, - }); + } + } + if (left3 && right3) { + if (!bool) return Math.max(eff_left, eff_right); + if (eff_left > Math.max(0, eff_right)) return "↖顺时针"; + if (eff_right > Math.max(0, eff_left)) return "逆时针↗"; + return "cancel2"; + } else if (left3) { + if (bool) return eff_left > 0 ? "↖顺时针" : "cancel2"; + return eff_left; + } else if (right3) { + if (bool) return eff_right > 0 ? "逆时针↗" : "cancel2"; + return eff_right; + } else return bool ? "cancel2" : 0; + }, + async cost(event, trigger, player) { + const choices = []; + const target = trigger.target; + let left = [], + right = [], + left2 = player, + right2 = player; + while (left2 != target && right2 != target) { + left2 = left2.getPrevious(); + right2 = right2.getNext(); + if (left2 != target) left.push(left2); + if (right2 != target) right.push(right2); + } + if (target == left2) { + for (const i of left) { + if (lib.filter.targetEnabled2(trigger.card, player, i)) { + choices.push("↖顺时针"); break; } - case "弃牌": { - current.chooseToDiscard("he", 2, true); + } + } + if (target == right2) { + for (const i of right) { + if (lib.filter.targetEnabled2(trigger.card, player, i)) { + choices.push("逆时针↗"); break; } } } + choices.push("cancel2"); + const result = await player + .chooseControl(choices) + .set("prompt", get.prompt("olqingya")) + .set("prompt2", `弃置自己和${get.translation(trigger.target)}某个方向之间的所有角色(不包括你与其)各一张手牌`) + .set("choices", choices) + .set("ai", () => { + var evt = _status.event.getTrigger(); + return lib.skill.olqingya.aiJudge(evt.player, evt.target, true); + }) + .forResult(); + if (result.control !== "cancel2") { + event.result = { + bool: true, + cost_data: { + control: result.control, + }, + }; + } }, - ai: { - order: function (item, player) { - return get.order({ name: "sha" }, player) - 0.1; - }, - result: { - target: function (player, target) { - const att = get.attitude(player, target); - if ( - target.countCards("hs", card => { - return ( - card.name == "sha" && - game.hasPlayer(current => { - return target.canUse(card, current) && get.effect(current, card, target, target) > 0 && get.effect(current, card, target, player) > 0; - }) - ); - }) - ) - return 3; - if (att > 0) return 2; - if (!target.countCards("h")) return get.sgn(att) + (att == 0 ? 1 : 0); - return 0; - }, - }, - }, - group: "olchanshuang_end", - subSkill: { - end: { - audio: "olchanshuang", - trigger: { player: "phaseJieshuBegin" }, - filter: function (event, player) { - return ( - player.getHistory("lose", evt => { - if (evt.type == "discard") { - var evtx = evt.getl(player); - return evtx && evtx.cards2.length == 2; - } - return evt.getParent(2).name == "recast"; - }).length || player.getHistory("useCard", evt => evt.card.name == "sha").length - ); - }, - forced: true, - locked: false, - content: function* (event, map) { - let num = 0, - player = map.player; - if (player.getHistory("lose", evt => evt.getParent(2).name == "recast").length) num++; - if (player.getHistory("useCard", evt => evt.card.name == "sha").length) num++; - if ( - player.getHistory("lose", evt => { - if (evt.type == "discard") { - var evtx = evt.getl(player); - return evtx && evtx.cards2.length == 2; - } - }).length - ) - num++; - if (num && player.countCards("he", card => player.canRecast(card))) { - let result = yield player.chooseCard("he", "请重铸一张牌", (card, player) => player.canRecast(card), true); - if (result.bool) yield player.recast(result.cards); + async content(event, trigger, player) { + const result = event.cost_data; + const targets = []; + game.log(player, "选择了", "#g" + result.control); + if (result.control == "↖顺时针") { + let current = player.getPrevious(); + while (current != trigger.target) { + if (current.countDiscardableCards(player)) targets.push(current); + current = current.getPrevious(); + } + } else { + let current = player.getNext(); + while (current != trigger.target) { + if (current.countDiscardableCards(player)) targets.push(current); + current = current.getNext(); + } + } + for (const current of targets) { + if (!current.countDiscardableCards(player)) continue; + player.line(current); + await player.discardPlayerCard(current, true); + } + await game.delayx(); + let evt = trigger; + while (true) { + if (!evt.name || lib.phaseName.includes(evt.name)) break; + evt = evt.getParent(); + } + if (player.getHistory("custom", evtx => evtx.olqingya === evt.name).length) return; + player.getHistory("custom").push({ olqingya: evt.name }); + player + .when({ + global: lib.phaseName.map(name => name + "End").concat("phaseAfter"), + }) + .filter(evt => { + if (evt.name === "phase") return true; + let evt2 = trigger; + while (true) { + if (!evt2.name || lib.phaseName.includes(evt2.name)) break; + evt2 = evt2.getParent(); } - if (num > 1 && player.countCards("he", card => card.name == "sha" && player.hasUseTarget(card))) { - yield player.chooseToUse({ - prompt: "请使用一张【杀】", - filterCard: function (card, player) { - if (card.name != "sha") return false; - return lib.filter.filterCard.apply(this, arguments); - }, - forced: true, - ai1: function (card) { - return _status.event.player.getUseValue(card); - }, - }); + return evt2.name !== evt.name; + }) + .vars({ + curPhaseName: evt.name, + }) + .then(() => { + if (trigger.name === "phase") { + return event.finish(); } - if (num > 2 && player.countCards("he", card => lib.filter.cardDiscardable(card, player))) yield player.chooseToDiscard("he", 2, true); - }, - }, - }, - }, - olzhanjin: { - audio: 2, - locked: true, - group: "olzhanjin_guanshi", - subSkill: { - guanshi: { - audio: "olzhanjin", - nobracket: true, - equipSkill: true, - trigger: { player: ["shaMiss", "eventNeutralized"] }, - filter: function (event, player) { - if (!player.hasEmptySlot(1) || !lib.card.guanshi || player.hasSkillTag("unequip_equip1")) return false; - if (event.type != "card" || event.card.name != "sha" || !event.target.isIn()) return false; - return player.countCards("he") >= 2; - }, - direct: true, - locked: false, - content: function () { - "step 0"; + const history = player.getHistory("useSkill", evt => { + if (evt.skill !== "olqingya") return false; + const evtx = evt.event.getParent(curPhaseName); + if (!evtx || evtx.name !== curPhaseName) return false; + return true; + }), + cards = []; + history.forEach(evt => { + game.countPlayer2(current => { + current.checkHistory("lose", evtx => { + if (evtx.getParent(4) !== evt.event) return; + cards.addArray(evtx.cards.filterInD("d")); + }); + }, true); + }); + if (!cards.length) { + return event.finish(); + } + event.cards = cards; player - .chooseToDiscard(get.prompt("olzhanjin_guanshi"), "弃置两张牌,令" + get.translation(trigger.card) + "强制命中", 2, "he") - .set("ai", function (card) { - var evt = _status.event.getTrigger(); - if (get.attitude(evt.player, evt.target) < 0) { - if (player.needsToDiscard()) return 15 - get.value(card); - if (evt.baseDamage + evt.extraDamage >= Math.min(2, evt.target.hp)) return 8 - get.value(card); - return 5 - get.value(card); - } - return -1; + .chooseButton(["倾轧:是否使用其中的一张牌?", event.cards]) + .set("filterButton", button => { + return get.player().hasUseTarget(button.link); }) - .set("complexCard", true).logSkill = "olzhanjin_guanshi"; - "step 1"; + .set("ai", button => { + return get.player().getUseValue(button.link); + }); + }) + .then(() => { if (result.bool) { - if (event.triggername == "shaMiss") { - trigger.untrigger(); - trigger.trigger("shaHit"); - trigger._result.bool = false; - trigger._result.result = null; - } else trigger.unneutralize(); + const card = result.links[0]; + player.$gain2(card, false); + game.delayx(); + player.chooseUseTarget(card, true); } - }, - mod: { - attackRange: function (player, num) { - if (lib.card.guanshi && player.hasEmptySlot(1)) return num - lib.card.guanshi.distance.attackFrom; - }, - }, - ai: { - directHit_ai: true, - skillTagFilter: function (player, tag, arg) { - if (player._olzhanjin_guanshi_temp || !player.hasEmptySlot(1) || !lib.card.guanshi || player.hasSkillTag("unequip_equip1")) return; - player._olzhanjin_guanshi_temp = true; - var bool = - get.attitude(player, arg.target) < 0 && - arg.card && - arg.card.name == "sha" && - player.countCards("he", card => { - return card != arg.card && (!arg.card.cards || !arg.card.cards.includes(card)) && get.value(card) < 5; - }) > 1; - delete player._olzhanjin_guanshi_temp; - return bool; - }, - effect: { - target: function (card, player, target) { - if (player.hasSkillTag("unequip_equip1")) return; - if (player == target && get.subtype(card) == "equip1") { - if (get.equipValue(card) <= get.equipValue({ name: "guanshi" })) return 0; - } - }, - }, + }); + }, + ai: { + effect: { + player_use(card, player, target) { + if (!target || player._olqingya_judging || ui.selected.targets.length || player == target || target.hasSkill("nodis")) return; + if (typeof card != "object" || card.name != "sha") return false; + player._olqingya_judging = true; + var effect = lib.skill.olqingya.aiJudge(player, target); + delete player._olqingya_judging; + if (effect > 0) return [1, effect / Math.max(0.01, get.attitude(player, player))]; }, }, }, }, - //曹宇 - olgongjie: { + oltielun: { audio: 2, - trigger: { global: "phaseBegin" }, - filter(event, player) { - if (!player.countCards("he")) return false; - return !game.hasPlayer(current => { - var history = current.actionHistory; - for (var num = history.length - 1; num >= 0; num--) { - if (history[num].isRound) break; - if (history[num].isSkipped) continue; - return true; + mod: { + globalFrom(from, to, distance) { + let usedCount = 0; + const stats = from.stat.slice(); + stats.reverse(); + for (const stat of stats) { + Object.values(stat.card).forEach(cnt => { + usedCount += cnt; + }); + if (stat.isRound) break; } - return false; - }); - }, - direct: true, - async content(event, trigger, player) { - var num = player.countCards("he"), - draws = []; - var { - result: { bool, targets }, - } = await player.chooseTarget(get.prompt2("olgongjie"), [1, num], lib.filter.notMe).set("ai", target => get.attitude(_status.event.player, target)); - if (!bool) return; - targets = targets.sortBySeat(); - player.logSkill("olgongjie", targets); - for (var target of targets) { - var { - result: { bool, cards }, - } = await target.gainPlayerCard(player, true, "he"); - if (bool) draws.add(get.suit(cards[0], player)); - } - player.draw(draws.length); + return distance - usedCount; + }, }, }, - olxiangxv: { + //SP孙策 + olliantao: { audio: 2, - trigger: { - player: "loseAfter", - global: ["gainAfter", "equipAfter", "addJudgeAfter", "loseAsyncAfter", "addToExpansionAfter"], - }, - filter(event, player) { - if (!_status.currentPhase || !_status.currentPhase.isIn()) return false; - if (!player.isMinHandcard()) return false; - var evt = event.getl(player); - if (evt && evt.player == player && evt.hs && evt.hs.length > 0) return true; - if (event.getg) - return game.hasPlayer(current => { - var cards = event.getg(current); - if (!cards.length) return false; - return current.countCards("h") >= player.countCards("h") && current.countCards("h") - cards.length < player.countCards("h"); - }); - return false; - }, - check(event, player) { - var target = _status.currentPhase; - var cards = target.getCards("h"); - if (target.isPhaseUsing()) { - var cardx = cards.filter(card => get.name(card) == "sha"); - cardx.sort((a, b) => target.getUseValue(b) - target.getUseValue(a)); - cardx = cardx.slice(Math.min(cardx.length, target.getCardUsable("sha")), cardx.length); - cards.removeArray(cardx); - } - return cards.length - player.countCards("h") > 0; - }, - usable: 1, - logTarget: () => _status.currentPhase, - async content(event, trigger, player) { - player - .when({ global: "phaseEnd" }) - .then(() => { - if (target && target.isIn()) { - var num = target.countCards("h") - player.countCards("h"); - if (num) { - if (num > 0) { - if (player.countCards("h") < 5) player.draw(Math.min(5 - player.countCards("h"), num)); - event.finish(); - } else player.chooseToDiscard(-num, "h", true); - } else event.finish(); - } else event.finish(); - }) - .then(() => { - if (result.bool && result.cards.length > 1) { - if (player.isDamaged()) player.recover(); - } - }) - .vars({ target: _status.currentPhase }); - }, - }, - olxiangzuo: { - audio: 2, - trigger: { player: "dying" }, + trigger: { player: "phaseUseBegin" }, filter(event, player) { - return player.countCards("he") && game.hasPlayer(target => target != player); + return game.hasPlayer(target => target != player); }, async cost(event, trigger, player) { event.result = await player - .chooseCardTarget({ - prompt: get.prompt2("olxiangzuo"), - filterCard: true, - selectCard: [1, Infinity], - filterTarget: lib.filter.notMe, - complexCard: true, - complexTarget: true, - complexSelect: true, - ai1(card) { - const player = get.event("player"); - if (!ui.selected.targets.length) return 0; - const target = ui.selected.targets[0]; - if ( - player.hasAllHistory("useSkill", evt => { - return evt.skill == "olgongjie" && (evt.targets || [evt.target]).includes(target); - }) && - player.hasAllHistory("useSkill", evt => { - return evt.skill == "olxiangxv" && (evt.targets || [evt.target]).includes(target); - }) - ) { - if (get.attitude(player, target) > 0) return 1; - if (player.canSaveCard(card, player)) return 0; - if (ui.selected.cards.length + player.hp >= player.maxHp) return 0; - return 20 - get.value(card); + .chooseTarget(get.prompt2(event.name.slice(0, -"_cost".length)), lib.filter.notMe) + .set("ai", target => { + const player = get.event("player"), + att = get.attitude(player, target); + const colors = Object.keys(lib.color).filter(i => i != "none"); + if ( + !colors.some(color => + player.hasCard(card => { + const juedou = get.autoViewAs({ name: "juedou" }, [card]); + return player.canUse(juedou, target, false); + }, "h") + ) + ) + return 20 + (3 - get.sgn(att)) + Math.random(); + const effs = colors.reduce((list, color) => { + const cards = player.getCards("h", card => { + const juedou = get.autoViewAs({ name: "juedou" }, [card]); + return player.canUse(juedou, target, false); + }); + if (cards.length) { + list.push( + cards.reduce((sum, card) => { + const juedou = get.autoViewAs({ name: "juedou" }, [card]); + return sum + get.effect(target, juedou, player, player); + }, 0) + ); } - if (get.attitude(player, target) > 0 && !player.countCards("he", cardx => player.canSaveCard(cardx, player))) return 1; - return 0; - }, - ai2(target) { - const player = get.event("player"); - const goon = - player.hasAllHistory("useSkill", evt => { - return evt.skill == "olgongjie" && (evt.targets || [evt.target]).includes(target); - }) && - player.hasAllHistory("useSkill", evt => { - return evt.skill == "olxiangxv" && (evt.targets || [evt.target]).includes(target); - }), - att = get.attitude(player, target); - if (goon) return 5 * att; - if (player.countCards("he", cardx => player.canSaveCard(cardx, player)) > 0) return att; - return 0; - }, + return list; + }, []); + return Math[att > 0 ? "max" : "min"].apply(Math, effs); }) .forResult(); }, - limited: true, - skillAnimation: true, - animationColor: "water", async content(event, trigger, player) { - const target = event.targets[0], - cards = event.cards; - player.awakenSkill("olxiangzuo"); - await player.give(cards, target); + const target = event.targets[0]; + const colors = Object.keys(lib.color).filter(i => i != "none"); + if (colors.length && player.countCards("h")) { + const result = await target + .chooseControl(colors) + .set("prompt", "连讨:请选择一个颜色") + .set("ai", () => { + const player = get.event("player"), + source = get.event().getParent().player; + let controls = get.event("controls").slice(); + if (controls.length == 1) return controls[0]; + const getSum = function (color, player, source) { + return source + .getCards("h", card => { + if (get.color(card) != color) return false; + const juedou = get.autoViewAs({ name: "juedou" }, [card]); + return source.canUse(juedou, player, false); + }) + .reduce((num, card) => { + const juedou = get.autoViewAs({ name: "juedou" }, [card]); + return num + get.effect(player, juedou, source, player); + }, 0); + }; + return controls.sort((a, b) => getSum(b, player, source) - getSum(a, player, source))[0]; + }) + .set("prompt2", get.translation(player) + "将对你依次使用由其手牌中所有此颜色的牌转化的【决斗】") + .forResult(); + const color = result.control; + game.broadcastAll( + (color, target) => { + lib.skill.olliantao_backup.filterCardx = [color, target]; + lib.skill.olliantao_backup.filterCard = function (card, player) { + const list = lib.skill.olliantao_backup.filterCardx; + if (get.color(card) != list[0]) return false; + const juedou = get.autoViewAs({ name: "juedou" }, [card]); + return player.canUse(juedou, list[1], false); + }; + }, + color, + target + ); + while ( + target.isIn() && + player.hasCard(card => lib.skill.olliantao_backup.filterCard(card, player)) && + !game.getGlobalHistory("everything", evt => { + return evt.name == "dying" && [player, target].includes(evt.player) && evt.getParent("olliantao") == event; + }).length + ) { + await player + .chooseToUse() + .set("forced", true) + .set("openskilldialog", "连讨:将一张" + get.translation(color) + "手牌当作【决斗】对" + get.translation(target) + "使用") + .set("norestore", true) + .set("_backupevent", "olliantao_backup") + .set("custom", { + add: {}, + replace: { window: function () {} }, + }) + .backup("olliantao_backup") + .set("targetRequired", true) + .set("complexSelect", true) + .set("filterTarget", function (card, player, target) { + if (target != _status.event.sourcex && !ui.selected.targets.includes(_status.event.sourcex)) return false; + return lib.filter.targetEnabled.apply(this, arguments); + }) + .set("sourcex", target) + .set("addCount", false); + } + } + const num = player + .getHistory("sourceDamage", evt => { + return evt.getParent(4) == event; + }) + .reduce((sum, evt) => sum + evt.num, 0); + if (num) await player.draw(num); if ( - player.hasAllHistory("useSkill", evt => { - return evt.skill == "olgongjie" && evt.targets.includes(target); - }) && - player.hasAllHistory("useSkill", evt => { - return evt.skill == "olxiangxv" && evt.targets.includes(target); + event.name == "olliantao" && + !game.hasPlayer2(current => { + return current.getHistory("damage", evt => { + return evt.getParent(4) == event; + }).length; }) - ) - await player.recover(cards.length); + ) { + await player.draw(3); + player.addTempSkill("olliantao_buff"); + player.addMark("olliantao_buff", 3, false); + } + if ( + event.name == "junkliantao" && + !target.getHistory("damage", evt => { + return evt.getParent(4) == event; + }).length + ) { + await player.draw(); + player.addTempSkill("olliantao_buff"); + player.addMark("olliantao_buff", 1, false); + } }, - ai: { - combo: "olgongjie", + subSkill: { + backup: { + viewAs: { name: "juedou" }, + position: "h", + check: () => 1 + Math.random(), + precontent() { + delete event.result.skill; + }, + }, + buff: { + charlotte: true, + onremove: true, + mod: { + maxHandcard(player, num) { + return num + player.countMark("olliantao_buff"); + }, + cardEnabled(card) { + if (card.name == "sha") return false; + }, + }, + intro: { content: "手牌上限+#,不能使用【杀】" }, + }, }, }, - //OL飞扬 - olfeiyang: { - trigger: { player: "phaseZhunbeiBegin" }, - filter: function (event, player) { - return ( - player.countCards("he", card => { - if (_status.connectMode && get.position(card) == "h") return true; - return lib.filter.cardDiscardable(card, player); - }) >= 3 && player.countCards("j") - ); - }, - direct: true, - //limited:true, - //skillAnimation:true, - //animationColor:'orange', - content: function () { - "step 0"; - player - .chooseToDiscard(get.prompt2("olfeiyang"), "he", 3) - .set("ai", function (card) { - var player = _status.event.player; - if ( - player.hasCard(function (card) { - return ( - get.effect( - player, - { - name: card.viewAs || card.name, - cards: [card], - }, - player, - player - ) < 0 - ); - }, "j") - ) - return 6 - get.value(card); - return 0; - }) - .set("logSkill", "olfeiyang"); - "step 1"; - if (result.bool) { - //player.awakenSkill('olfeiyang'); - player.discardPlayerCard(player, "j", true); - } - }, + //王战孙策,但是通渠 + junkliantao: { + audio: "olliantao", + inherit: "olliantao", }, - //李婉 - ollianju: { + //刘辟 + olyicheng: { audio: 2, - trigger: { player: "phaseJieshuBegin" }, - filter: function (event, player) { - var history = player.getHistory("useCard"); - if (!history.length) return false; - var evt = history[history.length - 1]; - return evt.cards && evt.cards.filterInD("d").length; - }, - direct: true, - content: function () { - "step 0"; - var history = player.getHistory("useCard"); - var evt = history[history.length - 1]; - event.evt = evt; - player - .chooseTarget(get.prompt("ollianju"), "令一名角色获得" + get.translation(evt.cards.filterInD("d")) + "并记录" + get.translation(evt.card.name), lib.filter.notMe) - .set("ai", target => { - var player = _status.event.player, - att = get.attitude(player, target); - var cards = _status.event.cards; - if (cards.filter(card => get.name(card, false) == "du").length >= Math.ceil(cards.length / 2)) att *= -1; - if (target.skipList.includes("phaseUse") || target.hasJudge("lebu")) return att / 20; - return att; - }) - .set("cards", evt.cards.filterInD("d")); - "step 1"; - if (result.bool) { - var evt = event.evt; - var target = result.targets[0]; - player.logSkill("oliandui", target); - target.gain(evt.cards.filterInD("d"), "gain2"); - player.addSkill("ollianju_effect"); - player.storage.ollianju = evt.card.name; - player.markSkill("ollianju"); - if (!player.storage.ollianju_effect[target.playerid]) player.storage.ollianju_effect[target.playerid] = []; - player.storage.ollianju_effect[target.playerid].add(evt.card.name); - } - }, - onunmark: true, - intro: { - content: function (storage, player) { - var str = "当前最后一次记录牌名:" + get.translation(storage); - if (player.storage.ollianju_effect) { - for (var i in player.storage.ollianju_effect) { - var target = game.findPlayer(target => target.playerid == i); - if (!i) continue; - str += "
    "; - str += get.translation(target) + "的下个结束阶段,其可令你获得其本回合使用的最后一张牌对应的所有位于弃牌堆的实体牌"; - str += ",然后若此牌名为" + get.translation(player.storage.ollianju_effect[i]) + ",则你失去1点体力,否则你可以视为使用" + get.translation(player.storage.ollianju_effect[i]); + enable: "phaseUse", + usable: 1, + async content(event, trigger, player) { + let num = player.maxHp, + cards = get.cards(num, true); + await player.showCards(cards, get.translation(player) + "发动了【易城】"); + if (player.countCards("h")) { + const sum = cards.reduce((num, card) => num + get.number(card), 0); + const { + result: { bool, moved }, + } = await player + .chooseToMove("易城:请选择你要交换的牌") + .set("filterMove", (from, to) => { + return typeof to !== "number"; + }) + .set("list", [ + [ + "牌堆顶", + cards, + list => { + const sum2 = list.reduce((num, card) => num + get.number(card, false), 0); + return "牌堆顶(现" + sum2 + { 0: "=", "-1": "<", 1: ">" }[get.sgn(sum2 - sum).toString()] + "原" + sum + ")"; + }, + ], + ["手牌", player.getCards("h")], + ]) + .set("filterOk", moved => moved[1].some(i => !get.owner(i))) + .set("processAI", list => { + const player = get.event("player"), + limit = Math.min(get.event("num"), player.countCards("h")); + let cards = list[0][1].slice(), + hs = player.getCards("h"); + if (cards.reduce((num, card) => num + get.value(card), 0) > player.getCards("h").reduce((num, card) => num + get.value(card), 0)) { + cards.sort((a, b) => get.number(a) - get.number(b)); + hs.sort((a, b) => get.number(b) - get.number(a)); + let cards2 = cards.slice(0, limit), + hs2 = hs.slice(0, limit); + if (hs2.reduce((num, card) => num + get.number(card), 0) > cards2.reduce((num, card) => num + get.number(card), 0)) { + cards.removeArray(cards2); + hs.removeArray(hs2); + return [cards.concat(hs2), hs.concat(cards2)]; + } + return [cards, hs]; + } else { + cards.sort((a, b) => get.value(b) - get.value(a)); + hs.sort((a, b) => get.value(a) - get.value(b)); + let cards2 = cards.slice(0, limit), + hs2 = hs.slice(0, limit), + list = [cards, hs]; + for (let i = 0; i < limit; i++) { + if (get.value(cards2[i]) > get.value(hs2[i])) { + const change = [cards2[i], hs2[i]]; + cards[i] = change[1]; + hs[i] = change[0]; + } else break; + } + return list; + } + }) + .set("num", num); + if (bool) { + const puts = player.getCards("h", i => moved[0].includes(i)); + const gains = cards.filter(i => moved[1].includes(i)); + if (puts.length && gains.length) { + player.$throw(puts, 1000); + await player.lose(puts, ui.special); + await player.gain(gains, "gain2"); + //调整手牌顺序 + player.getCards("h").forEach(i => i.goto(ui.special)); + player.directgain(moved[1].reverse(), false); + + cards = moved[0].slice(); + if (cards.length) { + await game.cardsGotoOrdering(cards); + for (let i = cards.length - 1; i >= 0; i--) { + ui.cardPile.insertBefore(cards[i], ui.cardPile.firstChild); + } + game.log(cards, "被放回了牌堆顶"); + game.updateRoundNumber(); + } + await player.showCards(cards, get.translation(player) + "【易城】第一次交换后"); + if (cards.reduce((num, card) => num + get.number(card), 0) > sum && player.countCards("h")) { + const { + result: { bool }, + } = await player.chooseBool("易城:是否使用全部手牌交换" + get.translation(cards) + "?").set( + "choice", + (() => { + return cards.reduce((num, card) => num + get.value(card), 0) > player.getCards("h").reduce((num, card) => num + get.value(card), 0); + })() + ); + if (bool) { + const hs = player.getCards("h"); + player.$throw(hs, 1000); + await player.lose(hs, ui.special); + await player.gain(cards, "gain2"); + cards = hs.slice(); + if (cards.length) { + await game.cardsGotoOrdering(cards); + for (let i = cards.length - 1; i >= 0; i--) { + ui.cardPile.insertBefore(cards[i], ui.cardPile.firstChild); + } + game.log(cards, "被放回了牌堆顶"); + game.updateRoundNumber(); + } + await player.showCards(cards, get.translation(player) + "【易城】第二次交换后"); + } + } } } - return str; - }, + } }, - subSkill: { - effect: { - init: function (player) { - if (!player.storage.ollianju_effect) player.storage.ollianju_effect = {}; - }, - charlotte: true, - trigger: { global: ["phaseJieshuBegin", "die"] }, - filter: function (event, player) { - return player.storage.ollianju_effect[event.player.playerid]; - }, - direct: true, - content: function () { - "step 0"; - if (trigger.name == "phaseJieshu") event.list = player.storage.ollianju_effect[trigger.player.playerid]; - delete player.storage.ollianju_effect[trigger.player.playerid]; - var history = trigger.player.getHistory("useCard"); - var evt = history[history.length - 1]; - event.evt = evt; - if (trigger.name == "die" || !history.length || !evt.cards || !evt.cards.filterInD("d").length) event.finish(); - "step 1"; - var evt = event.evt; - trigger.player.chooseBool(get.prompt("ollianju", player), "令" + get.translation(player) + "获得" + get.translation(evt.cards.filterInD("d")) + (event.list.includes(evt.card.name) ? ",然后" + get.translation(player) + "失去1点体力" : "")).set("choice", get.attitude(trigger.player, player) > 0 && (!event.list.includes(evt.card.name) || player.getHp() > 1)); - "step 2"; - if (result.bool) { - var evt = event.evt, - cards = evt.cards.filterInD("d"); - trigger.player.line(player); - player.gain(cards, "gain2"); - if (event.list.includes(evt.card.name)) player.loseHp(); - else { - var card = { - name: evt.card.name, - isCard: true, - }; - if (player.hasUseTarget(card)) player.chooseUseTarget(card, false); - } - } - }, - }, + ai: { + order: 9, + result: { player: 1 }, }, }, - olsilv: { + //陆凯 + olxuanzhu: { + mark: true, + marktext: "☯", + zhuanhuanji: true, audio: 2, - trigger: { - player: ["loseAfter", "gainAfter"], - global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], - }, - filter: function (event, player) { - var name = player.storage.ollianju; - if (!name) return false; - if (event.getg) return event.getg(player).some(card => card.name == name) && !player.hasSkill("olsilv_gain"); - return event.getl(player).cards2.some(card => card.name == name) && !player.hasSkill("olsilv_lose"); + enable: "chooseToUse", + filter(event, player) { + if (!player.countCards("he") || event.type == "wuxie") return false; + return get + .inpileVCardList(info => { + const name = info[2], + type = get.type(name), + infox = get.info({ name: name }); + if (type != "basic" && type != "trick") return false; + if (type == "trick" && (!infox || !infox.filterTarget || get.info("xunshi").isXunshi({ name: name }))) return false; + return (type != "basic") == (player.storage.olxuanzhu || false); + }) + .some(card => event.filterCard({ name: card[2], nature: card[3] }, player, event)); + }, + usable: 1, + chooseButton: { + dialog(event, player) { + const list = get + .inpileVCardList(info => { + const name = info[2], + type = get.type(name), + infox = get.info({ name: name }); + if (type != "basic" && type != "trick") return false; + if (type == "trick" && (!infox || !infox.filterTarget || get.info("xunshi").isXunshi({ name: name }))) return false; + return (type != "basic") == (player.storage.olxuanzhu || false); + }) + .filter(card => event.filterCard({ name: card[2], nature: card[3] }, player, event)); + return ui.create.dialog("玄注", [list, "vcard"]); + }, + check(button) { + if (get.event().getParent().type != "phase") return 1; + return get.event("player").getUseValue({ name: button.link[2], nature: button.link[3] }); + }, + backup(links, player) { + let next = { + audio: "olxuanzhu", + filterCard: true, + popname: true, + check(card) { + return 1 / (get.value(card) || 0.5); + }, + position: "he", + ignoreMod: true, + precontent() { + const cards = event.result.cards.slice(); + player.addToExpansion(cards, player, "give").gaintag.add("olxuanzhu"); + const viewAs = { + name: event.result.card.name, + nature: event.result.card.nature, + }; + event.result.card = viewAs; + event.result.cards = []; + player + .when("useCardAfter") + .filter(evt => evt.skill == "olxuanzhu_backup") + .then(() => { + const card = cards[0]; + if (get.type(card) != "equip") player.chooseToDiscard("he", true); + else { + const cardx = player.getExpansions("olxuanzhu"); + if (cardx.length) { + player.loseToDiscardpile(cardx); + player.draw(cardx.length); + } + } + }) + .vars({ cards: cards }); + }, + onuse(result, player) { + player.changeZhuanhuanji("olxuanzhu"); + }, + }; + const viewAs = { + name: links[0][2], + nature: links[0][3], + suit: "none", + number: null, + isCard: true, + }; + next.viewAs = viewAs; + if (get.info("xunshi").isXunshi(viewAs)) { + next.filterTarget = function (card, player, target) { + const info = get.info(card); + if (info.changeTarget) { + let targets = [target]; + info.changeTarget(player, targets); + if (targets.length > 1) return false; + } + return lib.filter.filterTarget(card, player, target); + }; + next.selectTarget = 1; + } + return next; + }, + prompt(links, player) { + const viewAs = { + name: links[0][2], + nature: links[0][3], + suit: "none", + number: null, + isCard: true, + }; + const str = "将一张牌称为“玄”置于武将牌上,然后视为使用" + (get.translation(links[0][3]) || "") + "【" + get.translation(links[0][2]) + "】"; + return str + (get.info("xunshi").isXunshi(viewAs) ? "(仅能指定一个目标)" : ""); + }, + }, + hiddenCard(player, name) { + if (!lib.inpile.includes(name) || player.getStat("skill").olxuanzhu || !player.countCards("he")) return false; + return get + .inpileVCardList(info => { + const name = info[2], + type = get.type(name), + infox = get.info({ name: name }); + if (type != "basic" && type != "trick") return false; + if (type == "trick" && (!infox || !infox.filterTarget || get.info("xunshi").isXunshi({ name: name }))) return false; + return (type != "basic") == (player.storage.olxuanzhu || false); + }) + .map(card => card[2]) + .includes(name); + }, + ai: { + order(item, player) { + if (player && get.event().type == "phase") { + let list = get + .inpileVCardList(info => { + const name = info[2], + type = get.type(name), + infox = get.info({ name: name }); + if (type != "basic" && type != "trick") return false; + if (type == "trick" && (!infox || !infox.filterTarget || get.info("xunshi").isXunshi({ name: name }))) return false; + return (type != "basic") == (player.storage.olxuanzhu || false); + }) + .map(card => { + return { name: card[2], nature: card[3] }; + }) + .filter(card => player.getUseValue(card, true, true) > 0); + if (!list.length) return 0; + list.sort((a, b) => { + const getNum = function (card) { + if (get.info("xunshi").isXunshi(card)) + return get.effect( + game + .filterPlayer(target => { + return player.canUse(card, target, true, true); + }) + .sort((a, b) => get.effect(b, card, player, player) - get.effect(a, card, player, player))[0], + card, + player, + player + ); + return player.getUseValue(card, true, true); + }; + return (getNum(b) || 0) - (getNum(a) || 0); + }); + return get.order(list[0], player) * 0.99; + } + return 0.001; + }, + respondSha: true, + respondShan: true, + skillTagFilter(player, tag, arg) { + if (arg == "respond") return false; + const name = tag == "respondSha" ? "sha" : "shan"; + return get.info("olxuanzhu").hiddenCard(player, name); + }, + result: { player: 1 }, + }, + intro: { + markcount: "expansion", + mark(dialog, storage, player) { + const cards = player.getExpansions("olxuanzhu"); + if (cards.length) dialog.addSmall(player.getExpansions("olxuanzhu")); + dialog.addText( + (() => { + if (storage) return "每回合限一次,你可以将一张牌称为“玄”置于武将牌上,然后视为使用任意普通锦囊牌(须指定目标且仅指定一个目标)。若此次置于武将牌上的“玄”:不为装备牌,你弃置一张牌;为装备牌,你将所有“玄”置入弃牌堆,然后摸等量的牌。"; + return "每回合限一次,你可以将一张牌称为“玄”置于武将牌上,然后视为使用任意基本牌。若此次置于武将牌上的“玄”:不为装备牌,你弃置一张牌;为装备牌,你将所有“玄”置入弃牌堆,然后摸等量的牌。"; + })(storage) + ); + }, + }, + onremove(player, skill) { + const cards = player.getExpansions(skill); + if (cards.length) player.loseToDiscardpile(cards); + }, + subSkill: { backup: {} }, + }, + oljiane: { + audio: 2, + trigger: { player: ["shaDamage", "useCardToEnd"] }, + filter(event, player, name) { + if (event.type != "card" || !event.target || !event.target.isIn() || event.target == player) return false; + if (name == "shaDamage") return true; + return event.card.name != "sha" && !event.getParent()._neutralized; + }, + logTarget: "target", + forced: true, + async content(event, trigger, player) { + trigger.target.addTempSkill("oljiane_neutralized"); + }, + group: "oljiane_neutralize", + global: "oljiane_ai", + subSkill: { + neutralize: { + audio: "oljiane", + trigger: { + target: "shaMiss", + global: "eventNeutralized", + }, + filter(event, player, name) { + if (event.type != "card") return false; + return name == "shaMiss" || event._neutralize_event.player == player; + }, + forced: true, + async content(event, trigger, player) { + player.addTempSkill("oljiane_nouse"); + }, + }, + ai: { + ai: { + directHit_ai: true, + skillTagFilter(player, tag, arg) { + if (!arg || !arg.target || !arg.target.hasSkill("oljiane_neutralized")) return false; + }, + }, + }, + neutralized: { + charlotte: true, + mark: true, + marktext: "牌", + intro: { content: "本回合无法抵消牌" }, + trigger: { global: "useCard" }, + forced: true, + popup: false, + async content(event, trigger, player) { + const id = player.playerid; + const map = trigger.customArgs; + if (!map[id]) map[id] = {}; + map[id].directHit2 = true; + }, + mod: { + wuxieJudgeEnabled: () => false, + wuxieEnabled: () => false, + }, + }, + nouse: { + charlotte: true, + mark: true, + marktext: '', + intro: { content: "本回合无法成为牌的目标" }, + mod: { targetEnabled: () => false }, + }, + }, + }, + //刘磐 + olpijing: { + audio: 2, + trigger: { player: "useCardToPlayered" }, + filter(event, player) { + return (event.card.name == "sha" || get.type(event.card) == "trick") && event.targets.length == 1; + }, + usable: 1, + direct: true, + locked: false, + async content(event, trigger, player) { + const num = Math.max(1, player.getDamagedHp()); + const { + result: { bool, targets }, + } = await player + .chooseTarget(get.prompt("olpijing"), [1, num], (card, player, target) => { + const trigger = get.event().getTrigger(); + if (trigger.targets.includes(target)) return true; + return target != player && lib.filter.targetEnabled2(trigger.card, player, target) && lib.filter.targetInRange(trigger.card, player, target); + }) + .set("ai", target => { + const player = get.event("player"), + trigger = get.event().getTrigger(); + return (trigger.targets.includes(target) ? -1 : 1) * get.effect(target, trigger.card, player, player) * (target.getStorage("olpijing_effect").includes(player) ? 2 : 1) + get.effect(target, { name: "shunshou_copy2" }, player, player); + }) + .set("prompt2", "令至多" + get.cnNumber(num) + "名角色成为或取消成为" + get.translation(trigger.card) + "的目标并随机交给你一张牌"); + if (bool) { + player.logSkill("olpijing", targets); + for (const i of targets) { + trigger.targets[!trigger.targets.includes(i) ? "add" : "remove"](i); + } + for (const target of targets) { + target.addSkill("olpijing_effect"); + target.markAuto("olpijing_effect", [player]); + const cards = target.getGainableCards(player, "he"); + if (cards.length) { + await target.give(cards.randomGets(1), player); + } + } + } else player.storage.counttrigger.olpijing--; + }, + mod: { + aiOrder(player, card, num) { + if (!(card.name == "sha" || get.type(card) == "trick")) return; + const info = get.info(card); + if ( + info && + !info.notarget && + (info.toself || info.singleCard || !info.selectTarget || info.selectTarget == 1) && + game.countPlayer(target => { + if (get.effect(target, card, player, player) <= 0) return false; + return lib.filter.targetEnabled2(card, player, target) && lib.filter.targetInRange(card, player, target); + }) > 1 + ) + return num + 0.01; + }, + }, + subSkill: { + effect: { + charlotte: true, + onremove: true, + intro: { + content: "使用的下一张基本牌或普通锦囊牌指定唯一目标时,可指定$为额外目标或摸一张牌", + }, + trigger: { player: "useCardToPlayer" }, + filter(event, player) { + return (get.type(event.card) == "basic" || get.type(event.card) == "trick") && event.targets.length == 1; + }, + forced: true, + popup: false, + async content(event, trigger, player) { + const storage = player.getStorage("olpijing_effect"); + player.removeSkill("olpijing_effect"); + const { + result: { bool, targets }, + } = await player + .chooseTarget("披荆:请选择此牌的额外目标", [1, storage.length], (card, player, target) => { + const trigger = get.event().getTrigger(); + return !trigger.targets.includes(target) && get.event("storage").includes(target) && lib.filter.targetEnabled2(trigger.card, player, target) && lib.filter.targetInRange(trigger.card, player, target); + }) + .set("prompt2", "不选择的角色视为你选择摸牌项") + .set("ai", target => { + const player = get.event("player"), + trigger = get.event().getTrigger(); + return get.effect(target, trigger.card, player, player) - get.effect(player, { name: "draw" }, player, player); + }) + .set("storage", storage); + if (bool) { + player.line(targets); + trigger.targets.addArray(targets); + if (storage.length - targets.length > 0) { + player.draw(storage.length - targets.length); + } + } else player.draw(storage.length); + }, + }, + }, + }, + //郭图 + olqushi: { + audio: 2, + enable: "phaseUse", + usable: 1, + delay: false, + async content(event, trigger, player) { + await player.draw(); + if (player.countCards("h") && game.hasPlayer(target => target != player)) { + const { + result: { bool, targets, cards }, + } = await player.chooseCardTarget({ + forced: true, + prompt: "将一张手牌作为“趋”扣置于其他角色的武将牌上", + filterTarget: lib.filter.notMe, + filterCard: true, + position: "h", + ai1(card) { + if (get.type2(card, false) == "equip") return 1 - get.value(card); + return 7 - get.value(card); + }, + ai2(target) { + const att = get.sgn(get.sgn(get.attitude(get.event("player"), target)) + 0.5); + return (target.countCards("h") + 1) * att; + }, + }); + if (bool) { + const target = targets[0]; + target.addSkill("olqushi_effect"); + target.markAuto("olqushi_effect", [player]); + game.log(player, "将一张牌扣置于", target, "的武将牌上"); + target.addToExpansion(cards, player, "giveAuto").gaintag.add("olqushi_effect"); + } + } + }, + ai: { + order: 1, + result: { player: 1 }, + }, + subSkill: { + effect: { + charlotte: true, + onremove(player, skill) { + delete player.storage[skill]; + const cards = player.getExpansions(skill); + if (cards.length) player.loseToDiscardpile(cards); + }, + marktext: "趋", + intro: { + content: "expansion", + markcount: "expansion", + mark(dialog, storage, player) { + if (storage.some(source => source.isUnderControl(true))) dialog.add(player.getExpansions("olqushi_effect")); + else return "共扣置" + get.cnNumber(player.getExpansions("olqushi_effect").length) + "张“趋”"; + }, + }, + trigger: { player: "phaseJieshuBegin" }, + forced: true, + popup: false, + async content(event, trigger, player) { + const cards = player.getExpansions("olqushi_effect"); + if (cards.length) { + await player.loseToDiscardpile(cards); + const targets = player + .getStorage("olqushi_effect") + .filter(i => { + return i.isIn(); + }) + .sortBySeat(); + const num = Math.min( + player + .getHistory("useCard", evt => { + return evt.targets && evt.targets.length; + }) + .reduce((targets, evt) => { + targets.addArray(evt.targets); + return targets; + }, []).length, + 5 + ); + if ( + targets.length && + num > 0 && + player.getHistory("useCard", evt => { + return cards.some(card => get.type2(card) == get.type2(evt.card)); + }).length + ) { + for (const target of targets) await target.draw(num); + } + } + player.removeSkill("olqushi_effect"); + }, + }, + }, + }, + olweijie: { + audio: 2, + enable: ["chooseToUse", "chooseToRespond"], + filter(event, player) { + if ( + !game.hasPlayer(target => { + return get.distance(player, target) == 1 && target.countCards("h"); + }) || + _status.currentPhase === player || + event.olweijie + ) + return false; + return get + .inpileVCardList(info => { + const name = info[2]; + return get.type(name) == "basic"; + }) + .some(card => event.filterCard({ name: card[2], nature: card[3], isCard: true }, player, event)); + }, + chooseButton: { + dialog(event, player) { + const list = get + .inpileVCardList(info => { + const name = info[2]; + return get.type(name) == "basic"; + }) + .filter(card => event.filterCard({ name: card[2], nature: card[3], isCard: true }, player, event)); + return ui.create.dialog("诿解", [list, "vcard"]); + }, + filter(button, player) { + return get.event().getParent().filterCard({ name: button.link[2], nature: button.link[3], isCard: true }, player, _status.event.getParent()); + }, + check(button) { + if (get.event().getParent().type != "phase") return 1; + return get.event("player").getUseValue({ name: button.link[2], nature: button.link[3], isCard: true }); + }, + backup(links, player) { + return { + viewAs: { + name: links[0][2], + nature: links[0][3], + isCard: true, + }, + filterCard: () => false, + selectCard: -1, + *precontent(event, map) { + delete event.result.skill; + const player = map.player; + let stop = false; + const result = yield player + .chooseTarget("请选择一名距离为1的角色", "弃置其一张手牌,若此牌牌名为【" + get.translation(event.result.card.name) + "】,则视为你使用/打出之", (card, player, target) => { + return get.distance(player, target) == 1 && target.countCards("h"); + }) + .set("ai", target => 1 - get.sgn(get.attitude(get.event("player"), target))); + if (result.bool) { + const target = result.targets[0]; + player.logSkill("olweijie", target); + player.tempBanSkill("olweijie", null, false); + const result2 = yield player + .discardPlayerCard(target, "h", true) + .set("prompt2", "若弃置的牌名为【" + get.translation(event.result.card.name) + "】,则视为你使用/打出之") + .set("ai", button => { + if (button.link.isKnownBy(get.event("player")) && button.link.name == get.event("namex")) return 114514; + return 1 + Math.random(); + }) + .set("namex", event.result.card.name); + if (result2.bool) { + const card = result2.cards[0]; + if (get.name(card, target) == event.result.card.name) { + player.popup("洗具"); + stop = true; + } else player.popup("杯具"); + } + } + if (!stop) { + const evt = event.getParent(); + evt.set("olweijie", true); + evt.goto(0); + delete evt.openskilldialog; + return; + } + }, + }; + }, + prompt(links, player) { + const nature = get.translation(links[0][3]) || ""; + const name = "【" + get.translation(links[0][2]) + "】"; + return "弃置距离为1的一名角色的一张手牌,若此牌牌名为" + name + ",则你视为使用" + nature + name; + }, + }, + ai: { + order: 10, + respondSha: true, + respondShan: true, + skillTagFilter(player, tag) { + const name = tag == "respondSha" ? "sha" : "shan"; + return lib.skill.olweijie.hiddenCard(player, name); + }, + result: { + player(player) { + if (_status.event.dying && get.attitude(player, _status.event.dying) <= 0) return 0; + return game.hasPlayer(target => { + if (get.attitude(player, target) > 0) return false; + return get.distance(player, target) == 1 && target.countCards("h"); + }) + ? 1 + : 0; + }, + }, + }, + hiddenCard(player, name) { + if (!lib.inpile.includes(name) || _status.currentPhase === player || player.isTempBanned("olweijie")) return false; + return ( + get.type(name) == "basic" && + game.hasPlayer(target => { + return get.distance(player, target) == 1 && target.countCards("h"); + }) + ); + }, + }, + //胡金定 + olqingyuan: { + audio: 2, + trigger: { + global: ["phaseBefore", "gainAfter", "loseAsyncAfter"], + player: ["enterGame", "damageEnd"], + }, + filter(event, player) { + const storage = player.getStorage("olqingyuan"); + if (event.name == "gain" || event.name == "loseAsync") { + if (player.hasSkill("olqingyuan_used")) return false; + return storage.some(target => event.getg(target).length) && storage.some(target => target.hasCard(card => lib.filter.canBeGained(card, target, player), "h")); + } + if (!game.hasPlayer(target => !storage.includes(target) && target != player)) return false; + if (event.name == "damage" && player.getAllHistory("damage").indexOf(event) != 0) return false; + return event.name != "phase" || game.phaseNumber == 0; + }, + forced: true, + async content(event, trigger, player) { + if (trigger.name == "gain" || trigger.name == "loseAsync") { + const target = player + .getStorage("olqingyuan") + .filter(target => target.hasCard(card => lib.filter.canBeGained(card, target, player), "h")) + .randomGet(); + player.line(target); + player.addTempSkill("olqingyuan_used"); + player.gain( + target + .getCards("h", card => { + return lib.filter.canBeGained(card, target, player); + }) + .randomGet(), + target, + "giveAuto" + ); + } else { + const filterTarget = (card, player, target) => { + return target != player && !player.getStorage("olqingyuan").includes(target); + }, + targetsx = game.filterPlayer(current => filterTarget(null, player, current)); + let result; + if (targetsx.length == 1) result = { bool: true, targets: targetsx }; + else + result = await player + .chooseTarget(filterTarget, true) + .set("prompt2", "每回合限一次,当你以此法选择的角色获得牌后,你随机获得其中一名角色的一张手牌") + .set("prompt", "请选择【轻缘】的目标") + .set("ai", target => { + const player = get.event("player"); + return get.effect(target, new lib.element.VCard({ name: "shunshou_copy2" }), player, player); + }) + .forResult(); + if (result.bool) { + const target = result.targets[0]; + player.line(target); + game.log(player, "选择了", target); + player.markAuto("olqingyuan", [target]); + } + } + }, + subSkill: { used: { charlotte: true } }, + intro: { content: "已选择$为目标" }, + ai: { + expose: 0.3, + }, + }, + olchongshen: { + audio: 2, + locked: false, + enable: "chooseToUse", + filterCard(card) { + return get.itemtype(card) == "card" && card.hasGaintag("olchongshen") && get.color(card) == "red"; + }, + position: "h", + viewAs: { name: "shan" }, + viewAsFilter(player) { + if (!player.countCards("h", card => card.hasGaintag("olchongshen") && get.color(card) == "red")) return false; + }, + prompt: "将本轮得到的红色牌当作【闪】使用", + check(card) { + return 7 - get.value(card); + }, + ai: { + order: 2, + respondShan: true, + skillTagFilter(player, tag, arg) { + if (arg == "respond" || !player.countCards("h", card => _status.connectMode || (card.hasGaintag("olchongshen") && get.color(card) == "red"))) return false; + }, + effect: { + target(card, player, target, current) { + if (get.tag(card, "respondShan") && current < 0) return 0.6; + }, + }, + }, + group: "olchongshen_mark", + mod: { + aiValue(player, card, num) { + if (get.name(card) != "shan" && get.itemtype(card) == "card" && (!card.hasGaintag("olchongshen") || get.color(card) != "red")) return; + let cards = player.getCards("hs", card => get.name(card) == "shan" || card.hasGaintag("olchongshen")); + cards.sort((a, b) => (get.name(b) == "shan" ? 1 : 2) - (get.name(a) == "shan" ? 1 : 2)); + const geti = () => { + if (cards.includes(card)) return cards.indexOf(card); + return cards.length; + }; + if (get.name(card) == "shan") return Math.min(num, [6, 4, 3][Math.min(geti(), 2)]) * 0.6; + return Math.max(num, [6.5, 4, 3][Math.min(geti(), 2)]); + }, + aiUseful() { + return lib.skill.olchongshen.mod.aiValue.apply(this, arguments); + }, + // ignoredHandcard(card,player){ + // if(card.hasGaintag('olchongshen')) return true; + // }, + // cardDiscardable(card,player,name){ + // if(name=='phaseDiscard'&&card.hasGaintag('olchongshen')) return false; + // }, + }, + init(player) { + if (game.phaseNumber > 0) { + const hs = player.getCards("h"), + history = player.getAllHistory(); + let cards = []; + for (let i = history.length - 1; i >= 0; i--) { + for (const evt of history[i].gain) { + cards.addArray(evt.cards); + } + if (history[i].isRound) break; + } + cards = cards.filter(i => hs.includes(i)); + if (cards.length) player.addGaintag(cards, "olchongshen"); + } + }, + onremove(player) { + player.removeGaintag("olchongshen"); + }, + subSkill: { + mark: { + charlotte: true, + trigger: { player: "gainBegin", global: "roundStart" }, + filter(event, player) { + return event.name == "gain" || game.roundNumber > 1; + }, + forced: true, + popup: false, + content() { + if (trigger.name == "gain") trigger.gaintag.add("olchongshen"); + else player.removeGaintag("olchongshen"); + }, + }, + }, + }, + //田畴 + olshandao: { + audio: 2, + enable: "phaseUse", + filter(event, player) { + return game.hasPlayer(target => lib.skill.olshandao.filterTarget(null, player, target)); + }, + filterTarget(card, player, target) { + return target.countCards("he"); + }, + usable: 1, + selectTarget: [1, Infinity], + multitarget: true, + multiline: true, + async content(event, trigger, player) { + const wugu = new lib.element.VCard({ name: "wugu" }); + const wanjian = new lib.element.VCard({ name: "wanjian" }); + const targets = game.filterPlayer(target => { + if (target == player) return false; + return !event.targets.includes(target) && player.canUse(wanjian, target, false); + }), + targetx = event.targets.sortBySeat(); + let dialog = ["将这些角色的各一张牌置于牌堆顶,然后视为对这些角色使用【五谷丰登】"]; + for (const target of targetx) { + const name = target == player ? "你" : get.translation(target); + if (target.countCards("h")) { + dialog.add('
    ' + name + "的手牌区
    "); + if (player.hasSkillTag("viewHandcard", null, target, true) || player == target) dialog.push(target.getCards("h")); + else dialog.push([target.getCards("h"), "blank"]); + } + if (target.countCards("e")) dialog.addArray(['
    ' + name + "的装备区
    ", target.getCards("e")]); + } + const { + result: { bool, links }, + } = await player + .chooseButton(dialog, event.targets.length, true) + .set("filterButton", button => { + return !ui.selected.buttons.some(but => get.owner(but.link) == get.owner(button.link)); + }) + .set("ai", button => 1 / (get.value(button.link, get.owner(button.link)) || 0.5)); + if (bool) { + const cards = links.sort((a, b) => targetx.indexOf(get.owner(a)) - targetx.indexOf(get.owner(b))); + for (const card of cards) { + const target = get.owner(card); + target.$throw(1, 1000); + await target.lose([card], ui.cardPile, "insert"); + } + const targety = targetx.filter(target => player.canUse(wugu, target, false)); + if (targety.length) await player.useCard(wugu, targety, false); + if (targets.length) await player.useCard(wanjian, targets, false); + } + }, + ai: { + order: 9, + result: { target: 1 }, + }, + }, + //李异 + olchanshuang: { + audio: 2, + enable: "phaseUse", + filterTarget: lib.filter.notMe, + usable: 1, + content: function* (event, map) { + const player = map.player, + target = event.target; + const choiceList = ["重铸一张牌", "使用一张【杀】", "弃置两张牌"], + list = ["重铸", "出杀", "弃牌", "无法选择"]; + let result = []; + for (let current of [player, target]) { + let list1 = list.slice(), + choiceList1 = choiceList.slice(); + list1 = list1.filter(control => { + if (control == "无法选择") return false; + if (control == "重铸") return current.countCards("he", card => current.canRecast(card)); + if (control == "出杀") return current.countCards("he", card => card.name == "sha" && current.hasUseTarget(card)); + if (control == "弃牌") return current.countCards("he", card => lib.filter.cardDiscardable(card, current)) > 1; + }); + choiceList1 = choiceList.filter(control => { + if (choiceList.indexOf(control) == 0) return current.countCards("he", card => current.canRecast(card)); + if (choiceList.indexOf(control) == 1) return current.countCards("he", card => card.name == "sha" && current.hasUseTarget(card)); + if (choiceList.indexOf(control) == 2) return current.countCards("he", card => lib.filter.cardDiscardable(card, current)) > 1; + }); + if (list1.length) { + if (list1.length == 1) result.push(list.indexOf(list1[0])); + else { + let result1 = yield current + .chooseControl(list1) + .set("ai", () => { + const current = _status.event.player; + const controls = _status.event.controls.slice(); + if (controls.includes("出杀") && current.countCards("hs", card => card.name == "sha" && current.hasValueTarget(card))) return "出杀"; + if (controls.includes("重铸")) return "重铸"; + return "弃牌"; + }) + .set("choiceList", choiceList1); + if (result1.control) result.push(list.indexOf(result1.control)); + } + } else result.push(3); + } + player.popup(list[result[0]]); + target.popup(list[result[1]]); + for (let current of [player, target]) { + switch (list[result[current == player ? 0 : 1]]) { + case "重铸": { + let result2 = yield current.chooseCard("he", "请重铸一张牌", (card, player) => player.canRecast(card), true); + if (result2.bool) current.recast(result2.cards); + break; + } + case "出杀": { + current.chooseToUse({ + prompt: "请使用一张【杀】", + filterCard: function (card, player) { + if (card.name != "sha") return false; + return lib.filter.filterCard.apply(this, arguments); + }, + forced: true, + ai1: function (card) { + return _status.event.player.getUseValue(card); + }, + }); + break; + } + case "弃牌": { + current.chooseToDiscard("he", 2, true); + break; + } + } + } + }, + ai: { + order: function (item, player) { + return get.order({ name: "sha" }, player) - 0.1; + }, + result: { + target: function (player, target) { + const att = get.attitude(player, target); + if ( + target.countCards("hs", card => { + return ( + card.name == "sha" && + game.hasPlayer(current => { + return target.canUse(card, current) && get.effect(current, card, target, target) > 0 && get.effect(current, card, target, player) > 0; + }) + ); + }) + ) + return 3; + if (att > 0) return 2; + if (!target.countCards("h")) return get.sgn(att) + (att == 0 ? 1 : 0); + return 0; + }, + }, + }, + group: "olchanshuang_end", + subSkill: { + end: { + audio: "olchanshuang", + trigger: { player: "phaseJieshuBegin" }, + filter: function (event, player) { + return ( + player.getHistory("lose", evt => { + if (evt.type == "discard") { + var evtx = evt.getl(player); + return evtx && evtx.cards2.length == 2; + } + return evt.getParent(2).name == "recast"; + }).length || player.getHistory("useCard", evt => evt.card.name == "sha").length + ); + }, + forced: true, + locked: false, + content: function* (event, map) { + let num = 0, + player = map.player; + if (player.getHistory("lose", evt => evt.getParent(2).name == "recast").length) num++; + if (player.getHistory("useCard", evt => evt.card.name == "sha").length) num++; + if ( + player.getHistory("lose", evt => { + if (evt.type == "discard") { + var evtx = evt.getl(player); + return evtx && evtx.cards2.length == 2; + } + }).length + ) + num++; + if (num && player.countCards("he", card => player.canRecast(card))) { + let result = yield player.chooseCard("he", "请重铸一张牌", (card, player) => player.canRecast(card), true); + if (result.bool) yield player.recast(result.cards); + } + if (num > 1 && player.countCards("he", card => card.name == "sha" && player.hasUseTarget(card))) { + yield player.chooseToUse({ + prompt: "请使用一张【杀】", + filterCard: function (card, player) { + if (card.name != "sha") return false; + return lib.filter.filterCard.apply(this, arguments); + }, + forced: true, + ai1: function (card) { + return _status.event.player.getUseValue(card); + }, + }); + } + if (num > 2 && player.countCards("he", card => lib.filter.cardDiscardable(card, player))) yield player.chooseToDiscard("he", 2, true); + }, + }, + }, + }, + olzhanjin: { + audio: 2, + locked: true, + group: "olzhanjin_guanshi", + subSkill: { + guanshi: { + audio: "olzhanjin", + nobracket: true, + equipSkill: true, + trigger: { player: ["shaMiss", "eventNeutralized"] }, + filter: function (event, player) { + if (!player.hasEmptySlot(1) || !lib.card.guanshi || player.hasSkillTag("unequip_equip1")) return false; + if (event.type != "card" || event.card.name != "sha" || !event.target.isIn()) return false; + return player.countCards("he") >= 2; + }, + direct: true, + locked: false, + content: function () { + "step 0"; + player + .chooseToDiscard(get.prompt("olzhanjin_guanshi"), "弃置两张牌,令" + get.translation(trigger.card) + "强制命中", 2, "he") + .set("ai", function (card) { + var evt = _status.event.getTrigger(); + if (get.attitude(evt.player, evt.target) < 0) { + if (player.needsToDiscard()) return 15 - get.value(card); + if (evt.baseDamage + evt.extraDamage >= Math.min(2, evt.target.hp)) return 8 - get.value(card); + return 5 - get.value(card); + } + return -1; + }) + .set("complexCard", true).logSkill = "olzhanjin_guanshi"; + "step 1"; + if (result.bool) { + if (event.triggername == "shaMiss") { + trigger.untrigger(); + trigger.trigger("shaHit"); + trigger._result.bool = false; + trigger._result.result = null; + } else trigger.unneutralize(); + } + }, + mod: { + attackRange: function (player, num) { + if (lib.card.guanshi && player.hasEmptySlot(1)) return num - lib.card.guanshi.distance.attackFrom; + }, + }, + ai: { + directHit_ai: true, + skillTagFilter: function (player, tag, arg) { + if (player._olzhanjin_guanshi_temp || !player.hasEmptySlot(1) || !lib.card.guanshi || player.hasSkillTag("unequip_equip1")) return; + player._olzhanjin_guanshi_temp = true; + var bool = + get.attitude(player, arg.target) < 0 && + arg.card && + arg.card.name == "sha" && + player.countCards("he", card => { + return card != arg.card && (!arg.card.cards || !arg.card.cards.includes(card)) && get.value(card) < 5; + }) > 1; + delete player._olzhanjin_guanshi_temp; + return bool; + }, + effect: { + target: function (card, player, target) { + if (player.hasSkillTag("unequip_equip1")) return; + if (player == target && get.subtype(card) == "equip1") { + if (get.equipValue(card) <= get.equipValue({ name: "guanshi" })) return 0; + } + }, + }, + }, + }, + }, + }, + //曹宇 + olgongjie: { + audio: 2, + trigger: { global: "phaseBegin" }, + filter(event, player) { + if (!player.countCards("he")) return false; + return !game.hasPlayer(current => { + var history = current.actionHistory; + for (var num = history.length - 1; num >= 0; num--) { + if (history[num].isRound) break; + if (history[num].isSkipped) continue; + return true; + } + return false; + }); + }, + direct: true, + async content(event, trigger, player) { + var num = player.countCards("he"), + draws = []; + var { + result: { bool, targets }, + } = await player.chooseTarget(get.prompt2("olgongjie"), [1, num], lib.filter.notMe).set("ai", target => get.attitude(_status.event.player, target)); + if (!bool) return; + targets = targets.sortBySeat(); + player.logSkill("olgongjie", targets); + for (var target of targets) { + var { + result: { bool, cards }, + } = await target.gainPlayerCard(player, true, "he"); + if (bool) draws.add(get.suit(cards[0], player)); + } + player.draw(draws.length); + }, + }, + olxiangxv: { + audio: 2, + trigger: { global: "phaseEnd" }, + filter(event, player) { + const target = _status.currentPhase; + if (!target?.isIn() || !player.hasSkill("olxiangxv_in")) return false; + const num = target.countCards("h") - player.countCards("h"); + if (num == 0 || (num > 0 && player.countCards("h") >= 5)) return false; + return num > 0 || player.countDisabledSlot(player, "h"); + }, + check(event, player) { + const target = _status.currentPhase, + num = target.countCards("h") - player.countCards("h"); + return num > 0 || (num == -2 && player.isDamaged()); + }, + usable: 1, + logTarget: () => _status.currentPhase, + async content(event, trigger, player) { + const target = _status.currentPhase, + num = target.countCards("h") - player.countCards("h"); + if (num > 0) { + if (player.countCards("h") < 5) await player.draw(Math.min(5 - player.countCards("h"), num)); + } else { + const result = await player.chooseToDiscard(-num, "h", true).forResult(); + if (result.bool && result.cards.length > 1) { + if (player.isDamaged()) await player.recover(); + } + } + }, + group: "olxiangxv_mark", + subSkill: { + mark: { + charlotte: true, + trigger: { + player: "loseAfter", + global: ["gainAfter", "equipAfter", "addJudgeAfter", "loseAsyncAfter", "addToExpansionAfter"], + }, + filter(event, player) { + if (!_status.currentPhase || !_status.currentPhase.isIn()) return false; + if (!player.isMinHandcard()) return false; + const evt = event.getl(player); + return evt?.player == player && evt?.hs?.length > 0; + }, + firstDo: true, + forced: true, + popup: false, + content() { + player.addTempSkill("olxiangxv_in"); + }, + }, + in: { charlotte: true }, + }, + }, + olxiangzuo: { + audio: 2, + trigger: { player: "dying" }, + filter(event, player) { + return player.countCards("he") && game.hasPlayer(target => target != player); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseCardTarget({ + prompt: get.prompt2("olxiangzuo"), + filterCard: true, + selectCard: [1, Infinity], + filterTarget: lib.filter.notMe, + position: "he", + complexCard: true, + complexTarget: true, + complexSelect: true, + ai1(card) { + const player = get.event("player"); + if (!ui.selected.targets.length) return 0; + const target = ui.selected.targets[0]; + if ( + player.hasAllHistory("useSkill", evt => { + return evt.skill == "olgongjie" && (evt.targets || [evt.target]).includes(target); + }) && + player.hasAllHistory("useSkill", evt => { + return evt.skill == "olxiangxv" && (evt.targets || [evt.target]).includes(target); + }) + ) { + if (get.attitude(player, target) > 0) return 1; + if (player.canSaveCard(card, player)) return 0; + if (ui.selected.cards.length + player.hp >= player.maxHp) return 0; + return 20 - get.value(card); + } + if (get.attitude(player, target) > 0 && !player.countCards("he", cardx => player.canSaveCard(cardx, player))) return 1; + return 0; + }, + ai2(target) { + const player = get.event("player"); + const goon = + player.hasAllHistory("useSkill", evt => { + return evt.skill == "olgongjie" && (evt.targets || [evt.target]).includes(target); + }) && + player.hasAllHistory("useSkill", evt => { + return evt.skill == "olxiangxv" && (evt.targets || [evt.target]).includes(target); + }), + att = get.attitude(player, target); + if (goon) return 5 * att; + if (player.countCards("he", cardx => player.canSaveCard(cardx, player)) > 0) return att; + return 0; + }, + }) + .forResult(); + }, + limited: true, + skillAnimation: true, + animationColor: "water", + async content(event, trigger, player) { + const target = event.targets[0], + cards = event.cards; + player.awakenSkill("olxiangzuo"); + await player.give(cards, target); + if ( + player.hasAllHistory("useSkill", evt => { + return evt.skill == "olgongjie" && evt.targets.includes(target); + }) && + player.hasAllHistory("useSkill", evt => { + return evt.skill == "olxiangxv" && evt.targets.includes(target); + }) + ) + await player.recover(cards.length); + }, + ai: { + combo: "olgongjie", + }, + }, + //OL飞扬 + olfeiyang: { + trigger: { player: "phaseZhunbeiBegin" }, + filter: function (event, player) { + return ( + player.countCards("he", card => { + if (_status.connectMode && get.position(card) == "h") return true; + return lib.filter.cardDiscardable(card, player); + }) >= 3 && player.countCards("j") + ); + }, + direct: true, + //limited:true, + //skillAnimation:true, + //animationColor:'orange', + content: function () { + "step 0"; + player + .chooseToDiscard(get.prompt2("olfeiyang"), "he", 3) + .set("ai", function (card) { + var player = _status.event.player; + if ( + player.hasCard(function (card) { + return ( + get.effect( + player, + { + name: card.viewAs || card.name, + cards: [card], + }, + player, + player + ) < 0 + ); + }, "j") + ) + return 6 - get.value(card); + return 0; + }) + .set("logSkill", "olfeiyang"); + "step 1"; + if (result.bool) { + //player.awakenSkill('olfeiyang'); + player.discardPlayerCard(player, "j", true); + } + }, + }, + //李婉 + ollianju: { + audio: 2, + trigger: { player: "phaseJieshuBegin" }, + filter: function (event, player) { + var history = player.getHistory("useCard"); + if (!history.length) return false; + var evt = history[history.length - 1]; + return evt.cards && evt.cards.filterInD("d").length; + }, + direct: true, + content: function () { + "step 0"; + var history = player.getHistory("useCard"); + var evt = history[history.length - 1]; + event.evt = evt; + player + .chooseTarget(get.prompt("ollianju"), "令一名角色获得" + get.translation(evt.cards.filterInD("d")) + "并记录" + get.translation(evt.card.name), lib.filter.notMe) + .set("ai", target => { + var player = _status.event.player, + att = get.attitude(player, target); + var cards = _status.event.cards; + if (cards.filter(card => get.name(card, false) == "du").length >= Math.ceil(cards.length / 2)) att *= -1; + if (target.skipList.includes("phaseUse") || target.hasJudge("lebu")) return att / 20; + return att; + }) + .set("cards", evt.cards.filterInD("d")); + "step 1"; + if (result.bool) { + var evt = event.evt; + var target = result.targets[0]; + player.logSkill("oliandui", target); + target.gain(evt.cards.filterInD("d"), "gain2"); + player.addSkill("ollianju_effect"); + player.storage.ollianju = evt.card.name; + player.markSkill("ollianju"); + if (!player.storage.ollianju_effect[target.playerid]) player.storage.ollianju_effect[target.playerid] = []; + player.storage.ollianju_effect[target.playerid].add(evt.card.name); + } + }, + onunmark: true, + intro: { + content: function (storage, player) { + var str = "当前最后一次记录牌名:" + get.translation(storage); + if (player.storage.ollianju_effect) { + for (var i in player.storage.ollianju_effect) { + var target = game.findPlayer(target => target.playerid == i); + if (!i) continue; + str += "
    "; + str += get.translation(target) + "的下个结束阶段,其可令你获得其本回合使用的最后一张牌对应的所有位于弃牌堆的实体牌"; + str += ",然后若此牌名为" + get.translation(player.storage.ollianju_effect[i]) + ",则你失去1点体力,否则你可以视为使用" + get.translation(player.storage.ollianju_effect[i]); + } + } + return str; + }, + }, + subSkill: { + effect: { + init: function (player) { + if (!player.storage.ollianju_effect) player.storage.ollianju_effect = {}; + }, + charlotte: true, + trigger: { global: ["phaseJieshuBegin", "die"] }, + filter: function (event, player) { + return player.storage.ollianju_effect[event.player.playerid]; + }, + direct: true, + content: function () { + "step 0"; + if (trigger.name == "phaseJieshu") event.list = player.storage.ollianju_effect[trigger.player.playerid]; + delete player.storage.ollianju_effect[trigger.player.playerid]; + var history = trigger.player.getHistory("useCard"); + var evt = history[history.length - 1]; + event.evt = evt; + if (trigger.name == "die" || !history.length || !evt.cards || !evt.cards.filterInD("d").length) event.finish(); + "step 1"; + var evt = event.evt; + trigger.player.chooseBool(get.prompt("ollianju", player), "令" + get.translation(player) + "获得" + get.translation(evt.cards.filterInD("d")) + (event.list.includes(evt.card.name) ? ",然后" + get.translation(player) + "失去1点体力" : "")).set("choice", get.attitude(trigger.player, player) > 0 && (!event.list.includes(evt.card.name) || player.getHp() > 1)); + "step 2"; + if (result.bool) { + var evt = event.evt, + cards = evt.cards.filterInD("d"); + trigger.player.line(player); + player.gain(cards, "gain2"); + if (event.list.includes(evt.card.name)) player.loseHp(); + else { + var card = { + name: evt.card.name, + isCard: true, + }; + if (player.hasUseTarget(card)) player.chooseUseTarget(card, false); + } + } + }, + }, + }, + }, + olsilv: { + audio: 2, + trigger: { + player: ["loseAfter", "gainAfter"], + global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], + }, + filter: function (event, player) { + var name = player.storage.ollianju; + if (!name) return false; + if (event.getg) return event.getg(player).some(card => card.name == name) && !player.hasSkill("olsilv_gain"); + return event.getl(player).cards2.some(card => card.name == name) && !player.hasSkill("olsilv_lose"); }, forced: true, content: function () { @@ -3121,37 +3825,30 @@ const skills = { ); }, direct: true, - content: [ - (event, map) => { - var player = map.player, - trigger = map.trigger; - var next = player.chooseToUse(); - next.set("openskilldialog", `###${get.prompt("olsuji")}###将一张黑色牌当【杀】使用${player == trigger.player ? "" : `。若${get.translation(trigger.player)}受到了此【杀】的伤害,你获得其一张牌。`}`); - next.set("norestore", true); - next.set("_backupevent", "olsuji_backup"); - next.set("addCount", false); - next.set("logSkill", "olsuji"); - next.set("custom", { - add: {}, - replace: { window: function () {} }, - }); - next.backup("olsuji_backup"); - }, - (event, map) => { - if (map.result.bool) { - var player = map.player, - trigger = map.trigger; - if ( - trigger.player.isIn() && - trigger.player.hasHistory("damage", evt => { - return evt.card && evt.card.storage && evt.card.storage.olsuji; - }) && - trigger.player.countGainableCards(player, "he") - ) - player.gainPlayerCard(trigger.player, "he", true); - } - }, - ], + async content(event, trigger, player) { + const next = player.chooseToUse(); + next.set("openskilldialog", `###${get.prompt("olsuji")}###将一张黑色牌当【杀】使用${player == trigger.player ? "" : `。若${get.translation(trigger.player)}受到了此【杀】的伤害,你获得其一张牌。`}`); + next.set("norestore", true); + next.set("_backupevent", "olsuji_backup"); + next.set("addCount", false); + next.set("logSkill", "olsuji"); + next.set("custom", { + add: {}, + replace: { window: function () {} }, + }); + next.backup("olsuji_backup"); + const result = await next.forResult(); + if (result.bool) { + if ( + trigger.player.isIn() && + trigger.player.hasHistory("damage", evt => { + return evt.card && evt.card.storage && evt.card.storage.olsuji; + }) && + trigger.player.countGainableCards(player, "he") + ) + player.gainPlayerCard(trigger.player, "he", true); + } + }, subSkill: { backup: { filterCard: function (card) { @@ -3686,7 +4383,7 @@ const skills = { check: function (card) { var player = _status.event.player; if (player.hasSkill("hezhong") && !(player.hasSkill("hezhong_0") && player.hasSkill("hezhong_1"))) { - if (player.countCards("h") - ui.selected.cards.length > 2) return 1 / (get.value(card) || 0.5); + if (player.countCards("h") - ui.selected.cards.length > 1) return 1 / (get.value(card) || 0.5); return 0; } if (ui.selected.cards.length < player.countCards("h") / 2) return 5 - get.value(card); @@ -3750,7 +4447,7 @@ const skills = { frequent: true, content: function () { "step 0"; - player.showHandcards(get.translation(player) + "发动了【技能】"); + player.showHandcards(get.translation(player) + "发动了【和衷】"); event.num = get.number(player.getCards("h")[0], player); "step 1"; player.draw(); @@ -3787,10 +4484,8 @@ const skills = { marktext: ">", intro: { markcount: list => { - var list2 = [1, 11, 12, 13]; return list.reduce((str, num) => { - if (list2.includes(num)) return str + ["A", "J", "Q", "K"][list2.indexOf(num)]; - return str + parseFloat(num); + return str + get.strNumber(num); }, ""); }, content: "使用的下一张点数大于$的普通锦囊牌额外结算一次", @@ -3824,10 +4519,8 @@ const skills = { marktext: "<", intro: { markcount: list => { - var list2 = [1, 11, 12, 13]; return list.reduce((str, num) => { - if (list2.includes(num)) return str + ["A", "J", "Q", "K"][list2.indexOf(num)]; - return str + parseFloat(num); + return str + get.strNumber(num); }, ""); }, content: "使用的下一张点数小于$的普通锦囊牌额外结算一次", @@ -4276,33 +4969,52 @@ const skills = { .chooseControl("弃牌,+1", "摸牌,-1", "cancel2") .set("choiceList", ["令" + str + "弃置一张牌,且其本回合手牌上限+1", "令" + str + "摸一张牌,且其本回合手牌上限-1"]) .set("ai", function () { - var player = _status.event.player; - var trigger = _status.event.getTrigger(); - var target = trigger.player; - var num1 = target.countCards("h"), - num2 = target.getHandcardLimit(); - switch (get.sgn(get.attitude(player, target))) { - case 0: - return 2; - case 1: - if (num1 - 1 >= num2) return 0; - if (num1 + 1 <= num2) return 1; - return 2; - case -1: - if (num1 - 2 <= num2) return 0; - if (num1 + 3 >= num2) return 1; - return 2; - } + let player = _status.event.player, + target = _status.event.getTrigger().player, + att = get.sgn(get.attitude(player, target)); + if (!att) return 2; + let dis = target.needsToDiscard(0, null, true), + res = [ + -att * + (1 + + Math.max( + 0, + dis - + (target.hasCard(i => { + return get.value(i, target) <= 6; + }, "e") + ? 1 + : 2) + )), + att * (1 - Math.max(0, dis + 2)), + -att * dis, + ]; + return res.indexOf(Math.max(...res)); }) .set("prompt", get.prompt("olrunwei", trigger.player)); "step 1"; if (result.index != 2) { player.logSkill("olrunwei", trigger.player); if (result.index == 0) { - trigger.player.chooseToDiscard("he", true).set("ai", card => { - if (get.position(card) == "e") return -get.value(card); - return 1 / (get.value(card) || 0.5); - }); + trigger.player + .chooseToDiscard("he", true) + .set("ai", card => { + if (get.position(card) == "e") return get.event().e - get.value(card); + return 1 / (get.value(card) || 0.5); + }) + .set( + "e", + (function () { + if ( + !trigger.player.hasCard(i => { + return get.value(i, trigger.player) <= 6; + }, "e") + ) + return 0; + if (!trigger.player.needsToDiscard(-2)) return 0; + return 6.2; + })() + ); trigger.player.addTempSkill("olrunwei_+"); trigger.player.addMark("olrunwei_+", 1, false); } @@ -4545,7 +5257,7 @@ const skills = { content: function () { "step 0"; var evt = event.getParent(2); - evt.set("olxiaofan", true); + if (_status.connectMode || !event.isMine()) evt.set("olxiaofan", true); var cards = get.bottomCards(lib.skill.olxiaofan.getNum(player) + 1, true); var aozhan = player.hasSkill("aozhan"); player @@ -5035,15 +5747,15 @@ const skills = { }, ai: { effect: { - target: function (card, player, target) { - if (get.type(card) == "delay") return "zerotarget"; + target_use: function (card, player, target) { + if (get.type(card) == "delay") return 0.1; }, }, }, subSkill: { skip: { mark: true, - intro: { content: "跳过下个的判定阶段" }, + intro: { content: "跳过下个判定阶段" }, }, }, }, @@ -5717,7 +6429,7 @@ const skills = { diamond_ai: { ai: { effect: { - player_use(card, player, target) { + player(card, player, target) { if (get.name(card) == "sha" && !player.hasSkill("oltianhou_diamond") && target != player.getNext() && target != player.getPrevious()) { let num = get.number(card), max = _status.aiyh_MAXNUM || 13; @@ -6660,8 +7372,9 @@ const skills = { if (!_status.olzhuyan || !_status.olzhuyan[player.playerid]) return 0; var num = _status.olzhuyan[player.playerid][status ? 1 : 0]; if (status) { + let no = num > 5; num -= player.countCards("h"); - if (num + player.countCards("h") > 5) num = 5 - player.countCards("h"); + if (no) num = Math.min(0, num); } else { num -= player.hp; if (num + player.hp < 1) num = 1 - player.hp; @@ -6681,7 +7394,7 @@ const skills = { } event.map = map; player - .chooseTarget(get.prompt("olzhuyan"), "令一名角色将{体力值/手牌数}调整至与其上个准备阶段相同(“--”表示已对其发动过该分支)", (card, player, target) => { + .chooseTarget(get.prompt("olzhuyan"), "令一名角色将{体力值/手牌数}调整至与其上个结束阶段相同(“--”表示已对其发动过该分支)", (card, player, target) => { var list = _status.event.map[target.playerid]; return list && (list[0] || list[1]); }) @@ -6860,7 +7573,7 @@ const skills = { } }, ai: { - order: 1, + order: 10, result: { target(player, target) { let sgn = 0, @@ -7137,7 +7850,7 @@ const skills = { for (var cardx of cards2) { var type = get.type2(cardx, player); var card = get.discardPile(function (card) { - return get.type(card, false) == type && !cards2.includes(card) && !cards.includes(card); + return get.type2(card, false) == type && !cards2.includes(card) && !cards.includes(card); }); if (card) cards.push(card); } @@ -7380,6 +8093,7 @@ const skills = { return lib.filter.filterCard.apply(this, arguments); }, prompt: "是否使用一张展示牌,然后重铸所有手牌?", + addCount: false, }); } else if (event.index == 2) { target.chooseToUse({ @@ -7388,6 +8102,7 @@ const skills = { return lib.filter.filterCard.apply(this, arguments); }, prompt: "是否使用一张手牌,然后重铸展示牌?", + addCount: false, }); event.goto(4); } else event.goto(6); @@ -7447,7 +8162,7 @@ const skills = { audio: 2, enable: "chooseToUse", viewAsFilter: function (player) { - return !player.hasSkill("olmiuyan_blocker") && player.hasCard(card => get.color(card) == "black", "hes"); + return player.hasCard(card => get.color(card) == "black", "hes"); }, viewAs: { name: "huogong" }, filterCard: { color: "black" }, @@ -7570,11 +8285,9 @@ const skills = { ); }, content: function () { - player.addTempSkill("olmiuyan_blocker", "roundStart"); - game.log(player, "的", "#g【谬焰】", "失效了"); + player.tempBanSkill("olmiuyan", "roundStart"); }, }, - blocker: { charlotte: true }, }, }, olshilu: { @@ -7649,7 +8362,7 @@ const skills = { game.addGlobalSkill("olkangrui_ai"); }, onremove: () => { - if (!game.hasPlayer(i => i.hasSkill("olkangrui"), true)) game.removeGlobalSkill("olkangrui_ai"); + if (!game.hasPlayer(i => i.hasSkill("olkangrui", null, null, false), true)) game.removeGlobalSkill("olkangrui_ai"); }, trigger: { global: "damageEnd" }, filter: function (event, player) { @@ -7755,7 +8468,7 @@ const skills = { ai: { trigger: { player: "dieAfter" }, filter: () => { - return !game.hasPlayer(i => i.hasSkill("olkangrui"), true); + return !game.hasPlayer(i => i.hasSkill("olkangrui", null, null, false), true); }, silent: true, forceDie: true, @@ -8192,7 +8905,7 @@ const skills = { threaten: 0.8, neg: true, effect: { - player_use(card, player, target) { + player(card, player, target) { if ((!card.isCard || !card.cards) && get.itemtype(card) != "card") return; let cs = 0; if ( @@ -9487,6 +10200,9 @@ const skills = { return event.skill == "olbixin" && player.countMark("olbixin") < 3; }, forced: true, + logAudio(event, player) { + return "olximo" + (1 + player.countMark("olbixin")) + ".mp3"; + }, content: function () { player.addMark("olbixin", 1, false); game.log(player, "删除了", "#g【笔心】", "描述的前五个字符"); @@ -9894,7 +10610,7 @@ const skills = { }, ai: { effect: { - target: function (card, player, target, current) { + target_use: function (card, player, target, current) { if (card.name == "sha" && target.hp > 0 && current < 0 && target.countCards("he") > 0) return 0.7; }, }, @@ -9967,13 +10683,13 @@ const skills = { lose_list.push([current, result[i].cards]); cards.push(card); } + game.loseAsync({ + lose_list: lose_list, + }).setContent("discardMultiple"); var type = get.type2(cards[0]); for (var i = 1; i < cards.length; i++) { if (get.type2(cards[i]) != type) event.finish(); } - game.loseAsync({ - lose_list: lose_list, - }).setContent("discardMultiple"); "step 3"; event.goto(1); for (var target of event.list) { @@ -11021,7 +11737,6 @@ const skills = { trigger: { player: "damageEnd" }, filter: (event, player) => player != _status.currentPhase, forced: true, - locked: false, content: function () { if (!player.storage.shanduan) player.storage.shanduan = [1, 2, 3, 4]; var list = player.storage.shanduan; @@ -11051,7 +11766,6 @@ const skills = { audio: "shanduan", trigger: { player: "phaseDrawBegin" }, forced: true, - locked: false, filter: function (event, player) { var list = event.getParent()._shanduan; return !list || list.length > 0; @@ -11084,7 +11798,6 @@ const skills = { audio: "shanduan", trigger: { player: "phaseUseBegin" }, forced: true, - locked: false, filter: function (event, player) { var list = event.getParent()._shanduan; return !list || list.length > 0; @@ -11177,7 +11890,6 @@ const skills = { audio: "shanduan", trigger: { player: "phaseDiscardBegin" }, forced: true, - locked: false, filter: function (event, player) { var list = event.getParent()._shanduan; return !list || list.length > 0; @@ -11961,4075 +12673,4588 @@ const skills = { }, }, }, - olqisi: { - audio: 2, - trigger: { player: "phaseDrawBegin2" }, + olqisi: { + audio: 2, + trigger: { player: "phaseDrawBegin2" }, + filter: function (event, player) { + return !event.numFixed && event.num > 0; + }, + check: function (event, player) { + if (player.hasEmptySlot(2) || player.hasEmptySlot(5) || player.hasEmptySlot(1)) return true; + return false; + }, + prompt2: "摸牌阶段开始时,你可以少摸一张牌并声明一种装备牌的副类别,然后从牌堆或弃牌堆中获得一张该副类别的牌。", + content: function () { + "step 0"; + player + .chooseControl("equip1", "equip2", "equip6", "equip5") + .set("prompt", "选择获得一种副类别的装备牌") + .set("ai", function (card) { + if (player.hasEmptySlot(2)) return "equip2"; + if (player.hasEmptySlot(5)) return "equip5"; + if (player.hasEmptySlot(1)) return "equip1"; + return "equip6"; + }); + "step 1"; + var card = get.cardPile(function (card) { + var type = get.subtype(card); + if (result.control == "equip6") return type == "equip3" || type == "equip4"; + return type == result.control; + }); + if (card) { + trigger.num--; + player.gain(card, "gain2"); + } + }, + group: "olqisi_init", + subSkill: { + init: { + audio: "olqisi", + trigger: { + global: "phaseBefore", + player: "enterGame", + }, + forced: true, + locked: false, + filter: function (event, player) { + return event.name != "phase" || game.phaseNumber == 0; + }, + content: function () { + "step 0"; + var i = 0; + var list = []; + while (i++ < 2) { + var card = get.cardPile(function (card) { + if (get.type(card) != "equip") return false; + return list.length == 0 || get.subtype(card) != get.subtype(list[0]); + }); + if (card) list.push(card); + } + if (!list.length) { + event.finish(); + return; + } + event.list = list; + player.gain(event.list, "gain2"); + "step 1"; + game.delay(1); + var card = event.list.shift(); + if (player.getCards("h").includes(card)) { + player.$give(card, player, false); + player.equip(card); + } + if (event.list.length) event.redo(); + }, + }, + }, + }, + //蒲元衍生 + zhaogujing_skill: { + equipSkill: true, + trigger: { player: "phaseUseEnd" }, + direct: true, + filter: function (event, player) { + return player.hasCard(function (card) { + if (_status.connectMode) return true; + var type = get.type(card, null, player); + return type == "basic" || type == "trick"; + }, "h"); + }, + content: function () { + "step 0"; + player + .chooseCard("h", get.prompt("zhaogujing_skill"), "展示并视为使用一张基本牌或普通锦囊牌", function (card, player) { + var type = get.type(card, null, player); + return type == "basic" || type == "trick"; + }) + .set("ai", function (card) { + var player = _status.event.player, + name = get.name(card, player); + if (name == "jiu") return 0; + return player.getUseValue({ + name: name, + nature: get.nature(card, player), + isCard: true, + }); + }); + "step 1"; + if (result.bool) { + player.logSkill("zhaogujing_skill"); + player.showCards(result.cards, get.translation(player) + "发动了【照骨镜】"); + var card = { + name: get.name(result.cards[0], player), + nature: get.nature(result.cards[0], player), + isCard: true, + }; + player.chooseUseTarget(card, true, false); + } + }, + }, + sanlve_skill: { + equipSkill: true, + mod: { + maxHandcard: function (player, num) { + return num + 1; + }, + attackRange: function (player, num) { + return num + 1; + }, + cardUsable: function (card, player, num) { + if (card.name == "sha") return num + 1; + }, + }, + }, + xuwangzhimian: { + equipSkill: true, + trigger: { player: "phaseDrawBegin2" }, + forced: true, + filter: function (event, player) { + return !event.numFixed; + }, + content: function () { + trigger.num += 2; + }, + mod: { + maxHandcard: function (player, num) { + return num - 1; + }, + }, + }, + shufazijinguan_skill: { + equipSkill: true, + trigger: { + player: "phaseZhunbeiBegin", + }, + direct: true, + content: function () { + "step 0"; + player + .chooseTarget(get.prompt("shufazijinguan"), "对一名其他角色造成1点伤害", function (card, player, target) { + return player != target; + }) + .set("ai", function (target) { + return get.damageEffect(target, player, player); + }); + "step 1"; + if (result.bool) { + player.logSkill("shufazijinguan_skill", result.targets[0]); + result.targets[0].damage(); + } + }, + }, + qimenbagua: { + equipSkill: true, + trigger: { target: "useCardToBefore" }, + forced: true, + filter: function (event, player) { + if (event.card.name != "sha") return false; + if (player.hasSkillTag("unequip2")) return false; + if ( + event.player.hasSkillTag("unequip", false, { + name: event.card ? event.card.name : null, + target: player, + card: event.card, + }) + ) + return false; + return true; + }, + content: function () { + trigger.cancel(); + }, + ai: { + effect: { + target(card, player, target) { + if (card.name != "sha") return; + if ( + target.hasSkillTag("unequip2") || + player.hasSkillTag("unequip", false, { + name: card ? card.name : null, + target: player, + card: card, + }) || + player.hasSkillTag("unequip_ai", false, { + name: card ? card.name : null, + target: player, + card: card, + }) + ) + return; + return "zeroplayertarget"; + }, + }, + }, + }, + guofengyupao: { + equipSkill: true, + mod: { + targetEnabled: function (card, player, target) { + if (player == target || get.type(card) != "trick") return; + if (target.hasSkillTag("unequip2")) return; + if ( + player.hasSkillTag("unequip", false, { + name: card ? card.name : null, + target: player, + card: card, + }) + ) + return; + return false; + }, + }, + }, + hongmianbaihuapao_skill: { + equipSkill: true, + trigger: { + player: "damageBegin4", + }, + filter: function (event, player) { + if (!event.hasNature("linked")) return false; + if (player.hasSkillTag("unequip2")) return false; + if ( + event.source && + event.source.hasSkillTag("unequip", false, { + name: event.card ? event.card.name : null, + target: player, + card: event.card, + }) + ) + return false; + return true; + }, + forced: true, + content: function () { + trigger.cancel(); + }, + ai: { + nofire: true, + nothunder: true, + effect: { + target: function (card, player, target, current) { + if (!get.tag(card, "natureDamage")) return; + if ( + !target.hasSkillTag("unequip2") && + !player.hasSkillTag("unequip", false, { + name: card ? card.name : null, + target: player, + card: card, + }) && + !player.hasSkillTag("unequip_ai", false, { + name: card ? card.name : null, + target: player, + card: card, + }) + ) + return "zeroplayertarget"; + }, + }, + }, + }, + linglongshimandai_skill: { + equipSkill: true, + trigger: { + target: "useCardToTargeted", + }, filter: function (event, player) { - return !event.numFixed && event.num > 0; + if ((event.targets && event.targets.length > 1) || event.player == player) return false; + if (player.hasSkillTag("unequip2")) return false; + var evt = event.getParent(); + if ( + evt.player && + evt.player.hasSkillTag("unequip", false, { + name: evt.card ? evt.card.name : null, + target: player, + card: evt.card, + }) + ) + return false; + return true; }, + audio: true, check: function (event, player) { - if (player.hasEmptySlot(2) || player.hasEmptySlot(5) || player.hasEmptySlot(1)) return true; - return false; + return get.effect(player, event.card, event.player, player) <= 0; }, - prompt2: "摸牌阶段开始时,你可以少摸一张牌并声明一种装备牌的副类别,然后从牌堆或弃牌堆中获得一张该副类别的牌。", + prompt2: event => "进行一次判定。若结果为♥,则" + get.translation(event.card) + "对你无效", content: function () { "step 0"; - player - .chooseControl("equip1", "equip2", "equip6", "equip5") - .set("prompt", "选择获得一种副类别的装备牌") - .set("ai", function (card) { - if (player.hasEmptySlot(2)) return "equip2"; - if (player.hasEmptySlot(5)) return "equip5"; - if (player.hasEmptySlot(1)) return "equip1"; - return "equip6"; - }); + player.judge("linglongshimandai", function (card) { + return get.suit(card) == "heart" ? 1.5 : -0.5; + }).judge2 = function (result) { + return result.bool ? true : false; + }; "step 1"; - var card = get.cardPile(function (card) { - var type = get.subtype(card); - if (result.control == "equip6") return type == "equip3" || type == "equip4"; - return type == result.control; - }); - if (card) { - trigger.num--; - player.gain(card, "gain2"); + if (result.judge > 0) { + trigger.getParent().excluded.add(player); } }, - group: "olqisi_init", - subSkill: { - init: { - audio: "olqisi", - trigger: { - global: "phaseBefore", - player: "enterGame", - }, - forced: true, - locked: false, - filter: function (event, player) { - return event.name != "phase" || game.phaseNumber == 0; - }, - content: function () { - "step 0"; - var i = 0; - var list = []; - while (i++ < 2) { - var card = get.cardPile(function (card) { - if (get.type(card) != "equip") return false; - return list.length == 0 || get.subtype(card) != get.subtype(list[0]); - }); - if (card) list.push(card); - } - if (!list.length) { - event.finish(); + ai: { + effect: { + target_use(card, player, target, effect) { + if ( + effect > 0 || + player.hasSkillTag("unequip", false, { + name: card ? card.name : null, + target: player, + card: card, + }) || + player.hasSkillTag("unequip_ai", false, { + name: card ? card.name : null, + target: player, + card: card, + }) + ) return; - } - event.list = list; - player.gain(event.list, "gain2"); - "step 1"; - game.delay(1); - var card = event.list.shift(); - if (player.getCards("h").includes(card)) { - player.$give(card, player, false); - player.equip(card); - } - if (event.list.length) event.redo(); + return 0.75; }, }, }, }, - //蒲元衍生 - zhaogujing_skill: { - equipSkill: true, - trigger: { player: "phaseUseEnd" }, - direct: true, + bintieshuangji_skill: { + trigger: { player: "shaMiss" }, filter: function (event, player) { - return player.hasCard(function (card) { - if (_status.connectMode) return true; - var type = get.type(card, player); - return type == "basic" || type == "trick"; - }, "h"); + return player.hp > 0; + }, + prompt2: function (event, player) { + var prompt = "失去1点体力,然后"; + var cards = event.cards.filterInD(); + if (cards.length) prompt += "获得" + get.translation(cards) + "、"; + prompt += "摸一张牌、本回合使用【杀】的次数上限+1"; + return prompt; + }, + check: function (event, player) { + if (get.effect(player, { name: "losehp" }, player, player) > 0) return true; + return player.hp > event.target.hp && event.cards.filterInD().length > 0; }, content: function () { "step 0"; - player - .chooseCard("h", get.prompt("zhaogujing_skill"), "展示并视为使用一张基本牌或普通锦囊牌", function (card, player) { - var type = get.type(card, player); - return type == "basic" || type == "trick"; - }) - .set("ai", function (card) { - var player = _status.event.player, - name = get.name(card, player); - if (name == "jiu") return 0; - return player.getUseValue({ - name: name, - nature: get.nature(card, player), - isCard: true, - }); - }); + player.loseHp(); "step 1"; - if (result.bool) { - player.logSkill("zhaogujing_skill"); - player.showCards(result.cards, get.translation(player) + "发动了【照骨镜】"); - var card = { - name: get.name(result.cards[0], player), - nature: get.nature(result.cards[0], player), - isCard: true, - }; - player.chooseUseTarget(card, true, false); - } + var cards = trigger.cards.filterInD(); + if (cards.length) player.gain(cards, "gain2"); + player.draw(); + "step 2"; + player.addTempSkill("bintieshuangji_skill_effect"); + player.addMark("bintieshuangji_skill_effect", 1, false); + }, + subSkill: { + effect: { + charlotte: true, + intro: { content: "使用【杀】的次数上限+#" }, + onremove: true, + mod: { + cardUsable: function (card, player, num) { + if (card.name == "sha") return num + player.countMark("bintieshuangji_skill_effect"); + }, + }, + }, }, }, - sanlve_skill: { + chixueqingfeng: { equipSkill: true, - mod: { - maxHandcard: function (player, num) { - return num + 1; - }, - attackRange: function (player, num) { - return num + 1; + trigger: { player: "useCardToPlayered" }, + filter: function (event) { + return event.card.name == "sha"; + }, + logTarget: "target", + forced: true, + content: function () { + var target = trigger.target; + target.addTempSkill("chixueqingfeng2"); + target.markAuto("chixueqingfeng2", [trigger.card]); + }, + ai: { + unequip_ai: true, + directHit_ai: true, + skillTagFilter: function (player, tag, arg) { + if (arg && arg.card && arg.card.name == "sha") return true; + return false; }, - cardUsable: function (card, player, num) { - if (card.name == "sha") return num + 1; + }, + }, + chixueqingfeng2: { + equipSkill: true, + trigger: { global: "useCardAfter" }, + forced: true, + charlotte: true, + popup: false, + firstDo: true, + onremove: true, + filter: function (event, player) { + return player.storage.chixueqingfeng2 && player.storage.chixueqingfeng2.includes(event.card); + }, + content: function () { + player.storage.chixueqingfeng2.remove(trigger.card); + if (!player.storage.chixueqingfeng2.length) player.removeSkill("chixueqingfeng2"); + }, + mark: true, + marktext: "※", + intro: { + content: "防具技能无效,且不能使用或打出手牌", + }, + mod: { + cardEnabled2: function (card) { + if (get.position(card) == "h") return false; }, }, + ai: { + unequip2: true, + }, }, - xuwangzhimian: { + guilongzhanyuedao: { equipSkill: true, - trigger: { player: "phaseDrawBegin2" }, + trigger: { player: "useCard" }, forced: true, filter: function (event, player) { - return !event.numFixed; + return event.card && event.card.name == "sha" && get.color(event.card) == "red"; }, content: function () { - trigger.num += 2; + trigger.directHit.addArray(game.players); }, - mod: { - maxHandcard: function (player, num) { - return num - 1; + ai: { + unequip_ai: true, + directHit_ai: true, + skillTagFilter: function (player, tag, arg) { + if (arg && arg.card && arg.card.name == "sha" && get.color(arg.card) == "red") return true; + return false; }, }, }, - shufazijinguan_skill: { + wushuangfangtianji_skill: { equipSkill: true, trigger: { - player: "phaseZhunbeiBegin", + source: "damageSource", + }, + filter: function (event, player) { + return event.card && event.card.name == "sha" && event.getParent().type == "card"; }, direct: true, content: function () { "step 0"; + var target = trigger.player; + var choices = ["摸一张牌"]; + if ( + target.hasCard(function (card) { + return lib.filter.canBeDiscarded(card, player, target); + }, "he") + ) + choices.push("弃置" + get.translation(target) + "的一张牌"); player - .chooseTarget(get.prompt("shufazijinguan"), "对一名其他角色造成1点伤害", function (card, player, target) { - return player != target; - }) - .set("ai", function (target) { - return get.damageEffect(target, player, player); + .chooseControl("cancel2") + .set("choiceList", choices) + .set("prompt", get.prompt("wushuangfangtianji_skill")) + .set("ai", function () { + var player = _status.event.player, + target = _status.event.getTrigger().player; + if ( + target.hasCard(function (card) { + return lib.filter.canBeDiscarded(card, player, target); + }, "he") && + get.effect(target, { name: "guohe_copy2" }, player, player) > get.effect(player, { name: "draw" }, player, player) + ) + return 1; + return 0; }); "step 1"; - if (result.bool) { - player.logSkill("shufazijinguan_skill", result.targets[0]); - result.targets[0].damage(); + if (result.control == "cancel2") return; + if (result.index == 0) { + player.logSkill("wushuangfangtianji_skill"); + player.draw(); + } else { + var target = trigger.player; + player.logSkill("wushuangfangtianji_skill", target); + player.discardPlayerCard(target, "he", true); } }, }, - qimenbagua: { - equipSkill: true, - trigger: { target: "useCardToBefore" }, - forced: true, - filter: function (event, player) { - if (event.card.name != "sha") return false; - if (player.hasSkillTag("unequip2")) return false; - if ( - event.player.hasSkillTag("unequip", false, { - name: event.card ? event.card.name : null, - target: player, - card: event.card, - }) - ) - return false; + //芮姬 + qiaoli: { + onChooseToUse: function (event) { + if (event.type == "phase" && !game.online && !(event.qiaoli_equip1 && event.qiaoli_noequip1)) { + var player = event.player; + var evt = event.getParent("phaseUse"); + if ( + player.getHistory("useCard", function (evtx) { + return evtx.getParent("phaseUse") == evt && evtx.skill == "qiaoli" && get.subtype(evtx.cards[0]) == "equip1"; + }).length + ) + event.set("qiaoli_equip1", true); + if ( + player.getHistory("useCard", function (evtx) { + return evtx.getParent("phaseUse") == evt && evtx.skill == "qiaoli" && get.subtype(evtx.cards[0]) != "equip1"; + }).length + ) + event.set("qiaoli_noequip1", true); + } + }, + audio: 2, + enable: "phaseUse", + viewAs: { + name: "juedou", + qiaoli: true, + }, + filterCard: function (card, player) { + if (get.type(card) != "equip") return false; + var event = _status.event; + if (get.subtype(card) == "equip1" && event.qiaoli_equip1) return false; + if (get.subtype(card) != "equip1" && event.qiaoli_noequip1) return false; return true; }, - content: function () { - trigger.cancel(); + viewAsFilter: function (player) { + return ( + player.isPhaseUsing() && + player.hasCard(function (card) { + return lib.skill.qiaoli.filterCard(card, player); + }, "hes") + ); + }, + check: function (card) { + if (get.position(card) == "e") return 7.5 - get.value(card); + return 12 - _status.event.player.getUseValue(card); + }, + position: "hes", + precontent: function () { + player.addTempSkill("qiaoli_norespond"); + player.addTempSkill("qiaoli_effect"); }, ai: { - effect: { - target_use(card, player, target) { - if (card.name != "sha") return; - if ( - target.hasSkillTag("unequip2") || - player.hasSkillTag("unequip", false, { - name: card ? card.name : null, - target: player, - card: card, - }) || - player.hasSkillTag("unequip_ai", false, { - name: card ? card.name : null, - target: player, - card: card, - }) - ) - return; - return "zerotarget"; - }, + directHit_ai: true, + skillTagFilter: function (player, tag, arg) { + return arg && arg.card && arg.card.name == "juedou" && _status.event.skill == "qiaoli"; }, }, - }, - guofengyupao: { - equipSkill: true, - mod: { - targetEnabled: function (card, player, target) { - if (player == target || get.type(card) != "trick") return; - if (target.hasSkillTag("unequip2")) return; - if ( - player.hasSkillTag("unequip", false, { - name: card ? card.name : null, - target: player, - card: card, - }) - ) - return; - return false; + subSkill: { + norespond: { + charlotte: true, + trigger: { player: "useCard1" }, + filter: function (event, player) { + return event.card.qiaoli && get.subtype(event.cards[0]) != "equip1"; + }, + forced: true, + popup: false, + content: function () { + player.addTempSkill("qiaoli_gain"); + trigger.directHit.addArray(game.players); + game.log(trigger.card, "不可被响应"); + }, + }, + effect: { + charlotte: true, + trigger: { source: "damageSource" }, + filter: function (event, player) { + return event.card && event.cards && event.card.qiaoli && get.subtype(event.cards[0]) == "equip1"; + }, + forced: true, + popup: false, + content: function () { + "step 0"; + var card = trigger.cards[0]; + var num = 1; + var info = get.info(card, false); + if (info && info.distance && typeof info.distance.attackFrom == "number") num -= info.distance.attackFrom; + player.draw(num); + "step 1"; + var cards = result; + if (get.itemtype(cards) != "cards") { + event.finish(5); + return; + } + var hs = player.getCards("h"); + cards = cards.filter(function (card) { + return hs.includes(card); + }); + if (!cards.length) { + event.finish(5); + return; + } + event.cards = cards; + if (_status.connectMode) + game.broadcastAll(function () { + _status.noclearcountdown = true; + }); + event.given_map = {}; + "step 2"; + player.chooseCardTarget({ + filterCard: function (card) { + return _status.event.cards.includes(card) && !card.hasGaintag("qiaoli_given"); + }, + cards: cards, + filterTarget: lib.filter.notMe, + selectCard: [1, cards.length], + prompt: "是否将获得的牌分配给其他角色?", + ai1: function (card) { + return -1; + }, + ai2: function (target) { + return -1; + }, + }); + "step 3"; + if (result.bool) { + var res = result.cards, + target = result.targets[0].playerid; + player.addGaintag(res, "qiaoli_given"); + cards.removeArray(res); + if (!event.given_map[target]) event.given_map[target] = []; + event.given_map[target].addArray(res); + if (cards.length) event.goto(2); + } + "step 4"; + if (_status.connectMode) { + game.broadcastAll(function () { + delete _status.noclearcountdown; + }); + game.stopCountChoose(); + } + for (var i in event.given_map) { + var source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; + player.line(source, "green"); + source.gain(event.given_map[i], player, "giveAuto"); + } + event.next.sort(function (a, b) { + return lib.sort.seat(a.player, b.player); + }); + }, }, - }, - }, - hongmianbaihuapao_skill: { - equipSkill: true, - trigger: { - player: "damageBegin4", - }, - filter: function (event, player) { - if (!event.hasNature("linked")) return false; - if (player.hasSkillTag("unequip2")) return false; - if ( - event.source && - event.source.hasSkillTag("unequip", false, { - name: event.card ? event.card.name : null, - target: player, - card: event.card, - }) - ) - return false; - return true; - }, - forced: true, - content: function () { - trigger.cancel(); - }, - ai: { - nofire: true, - nothunder: true, - effect: { - target: function (card, player, target, current) { - if (!get.tag(card, "natureDamage")) return; - if ( - !target.hasSkillTag("unequip2") && - !player.hasSkillTag("unequip", false, { - name: card ? card.name : null, - target: player, - card: card, - }) && - !player.hasSkillTag("unequip_ai", false, { - name: card ? card.name : null, - target: player, - card: card, - }) - ) - return "zerotarget"; + gain: { + charlotte: true, + audio: "qiaoli", + trigger: { player: "phaseJieshuBegin" }, + forced: true, + content: function () { + var card = get.cardPile2(function (card) { + return get.type(card) == "equip"; + }); + if (card) player.gain(card, "gain2"); }, }, }, }, - linglongshimandai_skill: { - equipSkill: true, - trigger: { - target: "useCardToTargeted", - }, + qingliang: { + audio: 2, + trigger: { target: "useCardToTarget" }, filter: function (event, player) { - if ((event.targets && event.targets.length > 1) || event.player == player) return false; - if (player.hasSkillTag("unequip2")) return false; - var evt = event.getParent(); - if ( - evt.player && - evt.player.hasSkillTag("unequip", false, { - name: evt.card ? evt.card.name : null, - target: player, - card: evt.card, - }) - ) - return false; - return true; + if (event.targets.length != 1) return false; + var bool1 = event.card.name == "sha"; + var bool2 = get.type2(event.card) == "trick" && get.tag(event.card, "damage"); + if (!bool1 && !bool2) return false; + return player != event.player && player.countCards("h") > 0; }, - audio: true, + usable: 1, + logTarget: "player", check: function (event, player) { - return get.effect(player, event.card, event.player, player) <= 0; + if (get.attitude(player, event.player) > 0 || event.player.hasSkillTag("nogain")) return true; + var eff = get.effect(player, event.card, event.player, player); + if (eff >= 0) return false; + var suits = [], + banned = [], + hs = player.getCards("h"); + for (var i of hs) { + var suit = get.suit(i, player); + suits.add(suit); + if (!lib.filter.cardDiscardable(i, player, "qingliang")) banned.add(suit); + } + suits.removeArray(banned); + for (var i of suits) { + var cards = player.getCards("h", function (card) { + return get.suit(card, player) == i; + }); + if (-eff / 2 - get.value(cards, player) > 0) return true; + } + return false; }, - prompt2: event => "进行一次判定。若结果为♥,则" + get.translation(event.card) + "对你无效", content: function () { "step 0"; - player.judge("linglongshimandai", function (card) { - return get.suit(card) == "heart" ? 1.5 : -0.5; - }).judge2 = function (result) { - return result.bool ? true : false; - }; + player.showHandcards(get.translation(player) + "发动了【清靓】"); "step 1"; - if (result.judge > 0) { - trigger.getParent().excluded.add(player); + var suits = [], + banned = [], + hs = player.getCards("h"); + for (var i of hs) { + var suit = get.suit(i, player); + suits.add(suit); + if (!lib.filter.cardDiscardable(i, player, "qingliang")) banned.add(suit); } - }, - ai: { - effect: { - target_use(card, player, target, effect) { - if ( - effect > 0 || - player.hasSkillTag("unequip", false, { - name: card ? card.name : null, - target: player, - card: card, - }) || - player.hasSkillTag("unequip_ai", false, { - name: card ? card.name : null, - target: player, - card: card, - }) - ) - return; - return 0.75; - }, - }, + if (suits.length > banned.length) { + player + .chooseControl() + .set("choiceList", ["和" + get.translation(trigger.player) + "各摸一张牌", "弃置一种花色的所有手牌,令" + get.translation(trigger.card) + "对自己无效"]) + .set("ai", function () { + var player = _status.event.player, + event = _status.event.getTrigger(); + if (get.attitude(player, event.player) > 0 || event.player.hasSkillTag("nogain")) return 0; + return 1; + }); + event.suits = suits; + suits.removeArray(banned); + suits.sort(); + } else { + event._result = { index: 0 }; + } + "step 2"; + if (result.index == 0) { + var list = [player, trigger.player].sortBySeat(); + list[0].draw("nodelay"); + list[1].draw(); + event.finish(); + } else { + if (event.suits.length == 1) event._result = { control: event.suits[0] }; + else + player + .chooseControl(event.suits) + .set("prompt", "选择弃置一种花色的所有牌") + .set("ai", function () { + var player = _status.event.player, + list = _status.event.controls.slice(0); + var gett = function (suit) { + var cards = player.getCards("h", function (card) { + return get.suit(card, player) == suit; + }); + return get.value(cards); + }; + return list.sort(function (b, a) { + return gett(b) - gett(a); + })[0]; + }); + } + "step 3"; + var cards = player.getCards("h", function (card) { + return get.suit(card) == result.control; + }); + if (cards.length) player.discard(cards); + trigger.targets.remove(player); + trigger.getParent().triggeredTargets2.remove(player); + trigger.untrigger(); }, }, - bintieshuangji_skill: { - trigger: { player: "shaMiss" }, + //卫兹 + yuanzi: { + audio: 2, + trigger: { global: "phaseZhunbeiBegin" }, + logTarget: "player", filter: function (event, player) { - return player.hp > 0; - }, - prompt2: function (event, player) { - var prompt = "失去1点体力,然后"; - var cards = event.cards.filterInD(); - if (cards.length) prompt += "获得" + get.translation(cards) + "、"; - prompt += "摸一张牌、本回合使用【杀】的次数上限+1"; - return prompt; + return player != event.player && event.player.isIn() && player.countCards("h") > 0 && !player.hasSkill("yuanzi_round", null, null, false); }, check: function (event, player) { - if (get.effect(player, { name: "losehp" }, player, player) > 0) return true; - return player.hp > event.target.hp && event.cards.filterInD().length > 0; - }, - content: function () { - "step 0"; - player.loseHp(); - "step 1"; - var cards = trigger.cards.filterInD(); - if (cards.length) player.gain(cards, "gain2"); - player.draw(); - "step 2"; - player.addTempSkill("bintieshuangji_skill_effect"); - player.addMark("bintieshuangji_skill_effect", 1, false); - }, - subSkill: { - effect: { - charlotte: true, - intro: { content: "使用【杀】的次数上限+#" }, - onremove: true, - mod: { - cardUsable: function (card, player, num) { - if (card.name == "sha") return num + player.countMark("bintieshuangji_skill_effect"); - }, - }, - }, - }, - }, - chixueqingfeng: { - equipSkill: true, - trigger: { player: "useCardToPlayered" }, - filter: function (event) { - return event.card.name == "sha"; + if (event.player.hasJudge("lebu") || get.attitude(player, event.player) < 2) return false; + return game.hasPlayer(function (current) { + return current !== player && current !== event.player && event.player.inRange(current) && get.attitude(event.player, current) < 0; + }); }, - logTarget: "target", - forced: true, content: function () { - var target = trigger.target; - target.addTempSkill("chixueqingfeng2"); - target.markAuto("chixueqingfeng2", [trigger.card]); + var cards = player.getCards("h"); + player.give(cards, trigger.player); + player.addTempSkill("yuanzi_effect"); + player.addTempSkill("yuanzi_round", "roundStart"); }, - ai: { - unequip_ai: true, - directHit_ai: true, - skillTagFilter: function (player, tag, arg) { - if (arg && arg.card && arg.card.name == "sha") return true; - return false; + subSkill: { + effect: { + charlotte: true, + audio: "yuanzi", + trigger: { global: "damageSource" }, + forced: true, + filter: function (event, player) { + var source = event.source; + return source && source == _status.currentPhase && player.countCards("h") <= source.countCards("h"); + }, + content: function () { + player.draw(2); + }, }, + round: { charlotte: true }, }, }, - chixueqingfeng2: { - equipSkill: true, - trigger: { global: "useCardAfter" }, - forced: true, - charlotte: true, - popup: false, - firstDo: true, - onremove: true, + liejie: { + audio: 2, + trigger: { player: "damageEnd" }, + direct: true, filter: function (event, player) { - return player.storage.chixueqingfeng2 && player.storage.chixueqingfeng2.includes(event.card); + return player.countCards("he") > 0; }, content: function () { - player.storage.chixueqingfeng2.remove(trigger.card); - if (!player.storage.chixueqingfeng2.length) player.removeSkill("chixueqingfeng2"); - }, - mark: true, - marktext: "※", - intro: { - content: "防具技能无效,且不能使用或打出手牌", - }, - mod: { - cardEnabled2: function (card) { - if (get.position(card) == "h") return false; - }, - }, - ai: { - unequip2: true, + "step 0"; + var source = trigger.source; + var prompt2 = "弃置至多三张牌并摸等量的牌"; + if (source) prompt2 += ",若弃置的牌中有红色牌,则弃置" + get.translation(source) + "至多等量的牌"; + var next = player.chooseToDiscard("he", [1, 3], get.prompt("liejie"), prompt2); + next.set("ai", function (card) { + return 6 - get.value(card); + }); + if (source) next.logSkill = ["liejie", source]; + else next.logSkill = "liejie"; + "step 1"; + if (result.bool) { + var cards = result.cards; + player.draw(cards.length); + if (trigger.source) { + var num = cards.filter(function (i) { + return get.color(i, player) == "red"; + }).length; + if (num > 0) player.discardPlayerCard(trigger.source, "he", [1, num]).set("forceAuto", true); + } + } }, }, - guilongzhanyuedao: { - equipSkill: true, - trigger: { player: "useCard" }, - forced: true, + //滕芳兰 + luochong: { + audio: 2, + trigger: { player: ["phaseZhunbeiBegin", "damageEnd"] }, + direct: true, filter: function (event, player) { - return event.card && event.card.name == "sha" && get.color(event.card) == "red"; + if (event.name == "damage") { + var history = player.getHistory("damage"); + if (history.indexOf(event) != 0) return false; + } + var storage1 = player.storage.luochong_round, + storage2 = player.getStorage("luochong"); + if (!storage1) storage1 = [[], []]; + for (var i = 0; i < 4; i++) { + if ( + !storage1[0].includes(i) && + !storage2.includes(i) && + game.hasPlayer(function (current) { + return !storage1[1].includes(current) && lib.skill.luochong.filterx[i](current); + }) + ) + return true; + } + return false; }, + filterx: [target => target.isDamaged(), () => true, target => target.countCards("he") > 0, () => true], + onremove: true, content: function () { - trigger.directHit.addArray(game.players); + "step 0"; + var list = []; + var choiceList = ["令一名角色回复1点体力。", "令一名角色失去1点体力。", "令一名角色弃置两张牌。", "令一名角色摸两张牌。"]; + var storage1 = player.storage.luochong_round, + storage2 = player.getStorage("luochong"); + if (!storage1) storage1 = [[], []]; + for (var i = 0; i < 4; i++) { + if (storage2.includes(i)) { + choiceList[i] = '' + choiceList[i] + ""; + } else if ( + storage1[0].includes(i) || + !game.hasPlayer(function (current) { + return !storage1[1].includes(current) && lib.skill.luochong.filterx[i](current); + }) + ) { + choiceList[i] = '' + choiceList[i] + ""; + } else list.push("选项" + get.cnNumber(i + 1, true)); + } + list.push("cancel2"); + player + .chooseControl(list) + .set("prompt", get.prompt("luochong")) + .set("choiceList", choiceList) + .set("ai", function () { + var player = _status.event.player; + var list = _status.event.controls.slice(0); + var listx = (player.storage.luochong_round || [[], []])[1]; + var gett = function (choice) { + if (choice == "cancel2") return 0.1; + var max = 0, + func = { + 选项一: function (current) { + if (current.isDamaged()) max = Math.max(max, get.recoverEffect(current, player, player)); + }, + 选项二: function (target) { + max = Math.max(max, get.effect(target, { name: "losehp" }, player, player)); + }, + 选项三: function (target) { + var num = target.countDiscardableCards(player, "he"); + if (num > 0) max = Math.max(max, Math.sqrt(Math.min(2, num)) * get.effect(target, { name: "guohe_copy2" }, player, player)); + }, + 选项四: function (target) { + max = Math.max(max, 2 * get.effect(target, { name: "draw" }, player, player)); + }, + }[choice]; + game.countPlayer(function (current) { + if (!listx.includes(current)) func(current); + }); + return max; + }; + return list.sort(function (a, b) { + return gett(b) - gett(a); + })[0]; + }); + "step 1"; + if (result.control != "cancel2") { + var index = ["选项一", "选项二", "选项三", "选项四"].indexOf(result.control); + event.index = index; + var listx = (player.storage.luochong_round || [[], []])[1]; + var list = [ + [ + "选择一名角色,令其回复1点体力", + function (target) { + var player = _status.event.player; + return get.recoverEffect(target, player, player); + }, + ], + [ + "选择一名角色,令其失去1点体力", + function (target) { + return get.effect(target, { name: "losehp" }, player, player); + }, + ], + [ + "选择一名角色,令其弃置两张牌", + function (target) { + var player = _status.event.player; + return get.effect(target, { name: "guohe_copy2" }, player, player) * Math.sqrt(Math.min(2, target.countCards("he"))); + }, + ], + [ + "选择一名角色,令其摸两张牌", + function (target) { + var player = _status.event.player; + return 2 * get.effect(target, { name: "draw" }, player, player); + }, + ], + ][index]; + var targets = game.filterPlayer(function (current) { + return !listx.includes(current) && lib.skill.luochong.filterx[event.index](current); + }); + var next = player.chooseTarget(list[0], true, function (card, player, target) { + return _status.event.targets.includes(target); + }); + next.set("targets", targets); + next.set("ai", list[1]); + } else event.finish(); + "step 2"; + if (result.bool) { + var target = result.targets[0]; + player.logSkill("luochong", target); + if (player != target) player.addExpose(0.2); + player.addTempSkill("luochong_round", "roundStart"); + if (!player.storage.luochong_round) player.storage.luochong_round = [[], []]; + player.storage.luochong_round[0].push(event.index); + player.storage.luochong_round[1].push(target); + switch (event.index) { + case 0: + target.recover(); + break; + case 1: + target.loseHp(); + break; + case 2: + target.chooseToDiscard(true, "he", 2); + break; + case 3: + target.draw(2); + break; + } + } }, - ai: { - unequip_ai: true, - directHit_ai: true, - skillTagFilter: function (player, tag, arg) { - if (arg && arg.card && arg.card.name == "sha" && get.color(arg.card) == "red") return true; - return false; + subSkill: { + round: { + charlotte: true, + onremove: true, }, }, }, - wushuangfangtianji_skill: { - equipSkill: true, - trigger: { - source: "damageSource", - }, + aichen: { + audio: 2, + trigger: { player: "dying" }, + forced: true, filter: function (event, player) { - return event.card && event.card.name == "sha" && event.getParent().type == "card"; + return player.hasSkill("luochong", null, null, false) && player.getStorage("luochong").length < 3; }, - direct: true, - content: function () { - "step 0"; - var target = trigger.player; - var choices = ["摸一张牌"]; - if ( - target.hasCard(function (card) { - return lib.filter.canBeDiscarded(card, player, target); - }, "he") - ) - choices.push("弃置" + get.translation(target) + "的一张牌"); + content: function () { + "step 0"; + //var num=1-player.hp; + //if(num>0) player.recover(num); + var list = []; + var choiceList = ["令一名角色回复1点体力。", "令一名角色失去1点体力。", "令一名角色弃置两张牌。", "令一名角色摸两张牌。"]; + var storage2 = player.getStorage("luochong"); + for (var i = 0; i < 4; i++) { + if (storage2.includes(i)) { + choiceList[i] = '' + choiceList[i] + ""; + } else list.push("选项" + get.cnNumber(i + 1, true)); + } player - .chooseControl("cancel2") - .set("choiceList", choices) - .set("prompt", get.prompt("wushuangfangtianji_skill")) + .chooseControl(list) + .set("prompt", "哀尘:选择移去一个〖落宠〗的选项") + .set("choiceList", choiceList) .set("ai", function () { - var player = _status.event.player, - target = _status.event.getTrigger().player; - if ( - target.hasCard(function (card) { - return lib.filter.canBeDiscarded(card, player, target); - }, "he") && - get.effect(target, { name: "guohe_copy2" }, player, player) > get.effect(player, { name: "draw" }, player, player) - ) - return 1; + var controls = _status.event.controls.slice(0); + var list = ["选项三", "选项四", "选项二", "选项一"]; + for (var i of list) { + if (controls.includes(i)) return i; + } return 0; }); "step 1"; - if (result.control == "cancel2") return; - if (result.index == 0) { - player.logSkill("wushuangfangtianji_skill"); - player.draw(); - } else { - var target = trigger.player; - player.logSkill("wushuangfangtianji_skill", target); - player.discardPlayerCard(target, "he", true); - } + var index = ["选项一", "选项二", "选项三", "选项四"].indexOf(result.control); + player.markAuto("luochong", [index]); + game.log(player, "移去了", "#g【落宠】", "的", "#y" + ["令一名角色回复1点体力", "令一名角色失去1点体力", "令一名角色弃置两张牌", "令一名角色摸两张牌"][index], "的选项"); }, - }, - //芮姬 - qiaoli: { - onChooseToUse: function (event) { - if (event.type == "phase" && !game.online && !(event.qiaoli_equip1 && event.qiaoli_noequip1)) { - var player = event.player; - var evt = event.getParent("phaseUse"); - if ( - player.getHistory("useCard", function (evtx) { - return evtx.getParent("phaseUse") == evt && evtx.skill == "qiaoli" && get.subtype(evtx.cards[0]) == "equip1"; - }).length - ) - event.set("qiaoli_equip1", true); - if ( - player.getHistory("useCard", function (evtx) { - return evtx.getParent("phaseUse") == evt && evtx.skill == "qiaoli" && get.subtype(evtx.cards[0]) != "equip1"; - }).length - ) - event.set("qiaoli_noequip1", true); - } + ai: { + combo: "luochong", + neg: true, }, + }, + //SP孟获 + spmanwang: { audio: 2, enable: "phaseUse", - viewAs: { - name: "juedou", - qiaoli: true, - }, - filterCard: function (card, player) { - if (get.type(card) != "equip") return false; - var event = _status.event; - if (get.subtype(card) == "equip1" && event.qiaoli_equip1) return false; - if (get.subtype(card) != "equip1" && event.qiaoli_noequip1) return false; - return true; - }, - viewAsFilter: function (player) { - return ( - player.isPhaseUsing() && - player.hasCard(function (card) { - return lib.skill.qiaoli.filterCard(card, player); - }, "hes") - ); + filter: function (event, player) { + return player.countCards("he") > 0; }, + filterCard: true, + position: "he", + selectCard: [1, Infinity], check: function (card) { - if (get.position(card) == "e") return 7.5 - get.value(card); - return 12 - _status.event.player.getUseValue(card); + var player = _status.event.player; + var max = Math.min(player.isDamaged() ? 3 : 2, 4 - player.countMark("spmanwang")); + if (!max && !player.hasSkill("sppanqin")) return 0; + if (max == 0 && ui.selected.length > 0) return 0; + return 7 - ui.selected.cards.length - get.value(card); }, - position: "hes", - precontent: function () { - player.addTempSkill("qiaoli_norespond"); - player.addTempSkill("qiaoli_effect"); + content: function () { + var num = Math.min(cards.length, 4 - player.countMark("spmanwang")); + if (num >= 1) player.addSkills("sppanqin"); + if (num >= 2) player.draw(); + if (num >= 3) player.recover(); + if (num >= 4) { + player.draw(2); + player.removeSkills("sppanqin"); + } }, + intro: { content: "已经移去过#个选项" }, ai: { - directHit_ai: true, - skillTagFilter: function (player, tag, arg) { - return arg && arg.card && arg.card.name == "juedou" && _status.event.skill == "qiaoli"; - }, - }, - subSkill: { - norespond: { - charlotte: true, - trigger: { player: "useCard1" }, - filter: function (event, player) { - return event.card.qiaoli && get.subtype(event.cards[0]) != "equip1"; - }, - forced: true, - popup: false, - content: function () { - player.addTempSkill("qiaoli_gain"); - trigger.directHit.addArray(game.players); - game.log(trigger.card, "不可被响应"); + order: 2, + result: { + player: function (player, target) { + if (player.getUseValue({ name: "nanman" }) <= 0) return 0; + if (player.getStat("skill").spmanwang && player.hasSkill("sppanqin")) return 0; + return 1; }, }, - effect: { - charlotte: true, - trigger: { source: "damageSource" }, - filter: function (event, player) { - return event.card && event.cards && event.card.qiaoli && get.subtype(event.cards[0]) == "equip1"; - }, - forced: true, - popup: false, - content: function () { - "step 0"; - var card = trigger.cards[0]; - var num = 1; - var info = get.info(card, false); - if (info && info.distance && typeof info.distance.attackFrom == "number") num -= info.distance.attackFrom; - player.draw(num); - "step 1"; - var cards = result; - if (get.itemtype(cards) != "cards") { - event.finish(5); - return; - } - var hs = player.getCards("h"); - cards = cards.filter(function (card) { - return hs.includes(card); - }); - if (!cards.length) { - event.finish(5); - return; + }, + derivation: "sppanqin", + }, + sppanqin: { + audio: 2, + trigger: { player: ["phaseUseEnd", "phaseDiscardEnd"] }, + filter: function (event, player) { + var cards = [], + bool = true; + player.getHistory("lose", function (evt) { + if (!bool || evt.type != "discard" || evt.getParent(event.name) != event) return false; + for (var i of evt.cards2) { + if (get.position(i, true) == "d") { + cards.add(i); + if (!game.checkMod(i, player, "unchanged", "cardEnabled2", player)) bool = false; } - event.cards = cards; - if (_status.connectMode) - game.broadcastAll(function () { - _status.noclearcountdown = true; - }); - event.given_map = {}; - "step 2"; - player.chooseCardTarget({ - filterCard: function (card) { - return _status.event.cards.includes(card) && !card.hasGaintag("qiaoli_given"); - }, - cards: cards, - filterTarget: lib.filter.notMe, - selectCard: [1, cards.length], - prompt: "是否将获得的牌分配给其他角色?", - ai1: function (card) { - return -1; - }, - ai2: function (target) { - return -1; - }, - }); - "step 3"; - if (result.bool) { - var res = result.cards, - target = result.targets[0].playerid; - player.addGaintag(res, "qiaoli_given"); - cards.removeArray(res); - if (!event.given_map[target]) event.given_map[target] = []; - event.given_map[target].addArray(res); - if (cards.length) event.goto(2); + } + }); + if (!bool || !cards.length) return false; + return player.hasUseTarget(get.autoViewAs({ name: "nanman" }, cards)); + }, + prompt2: function (event, player) { + var cards = []; + player.getHistory("lose", function (evt) { + if (evt.type != "discard" || evt.getParent(event.name) != event) return false; + for (var i of evt.cards2) { + if (get.position(i, true) == "d") { + cards.add(i); } - "step 4"; - if (_status.connectMode) { - game.broadcastAll(function () { - delete _status.noclearcountdown; - }); - game.stopCountChoose(); + } + }); + return "将" + get.translation(cards) + "(共计" + get.cnNumber(cards.length) + "张牌)当做【南蛮入侵】使用"; + }, + check: function (event, player) { + var cards = [], + bool = true; + player.getHistory("lose", function (evt) { + if (!bool || evt.type != "discard" || evt.getParent(event.name) != event) return false; + for (var i of evt.cards2) { + if (get.position(i, true) == "d") { + cards.add(i); + if (!game.checkMod(i, player, "unchanged", "cardEnabled2", player)) bool = false; } - for (var i in event.given_map) { - var source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; - player.line(source, "green"); - source.gain(event.given_map[i], player, "giveAuto"); + } + }); + if (!bool || !cards.length) return false; + return player.hasValueTarget(get.autoViewAs({ name: "nanman" }, cards)); + }, + content: function () { + "step 0"; + var cards = []; + player.getHistory("lose", function (evt) { + if (evt.type != "discard" || evt.getParent(trigger.name) != trigger) return false; + for (var i of evt.cards2) { + if (get.position(i, true) == "d") { + cards.add(i); } - event.next.sort(function (a, b) { - return lib.sort.seat(a.player, b.player); - }); - }, - }, - gain: { + } + }); + player.chooseUseTarget(true, { name: "nanman" }, cards); + player.addTempSkill("sppanqin_eff"); + }, + subSkill: { + eff: { + trigger: { player: "useCard" }, charlotte: true, - audio: "qiaoli", - trigger: { player: "phaseJieshuBegin" }, forced: true, + popup: false, + filter: function (event, player) { + return event.card.name == "nanman" && event.getParent(2).name == "sppanqin" && player.countMark("spmanwang") < 4 && player.hasSkill("spmanwang", null, null, false) && event.cards.length <= event.targets.length; + }, content: function () { - var card = get.cardPile2(function (card) { - return get.type(card) == "equip"; - }); - if (card) player.gain(card, "gain2"); + player.addMark("spmanwang", 1, false); + switch (player.countMark("spmanwang")) { + case 1: + player.draw(2); + player.removeSkills("sppanqin"); + break; + case 2: + player.recover(); + break; + case 3: + player.draw(); + break; + case 4: + player.addSkills("sppanqin"); + break; + } }, }, }, }, - qingliang: { + //清河公主 + zengou: { audio: 2, - trigger: { target: "useCardToTarget" }, + trigger: { global: "useCard" }, filter: function (event, player) { - if (event.targets.length != 1) return false; - var bool1 = event.card.name == "sha"; - var bool2 = get.type2(event.card) == "trick" && get.tag(event.card, "damage"); - if (!bool1 && !bool2) return false; - return player != event.player && player.countCards("h") > 0; + return ( + event.card.name == "shan" && + player.inRange(event.player) && + (player.hp > 0 || + player.hasCard(function (card) { + return get.type(card) != "basic" && lib.filter.cardDiscardable(card, player, "zengou"); + }, "eh")) + ); }, - usable: 1, logTarget: "player", check: function (event, player) { - if (get.attitude(player, event.player) > 0 || event.player.hasSkillTag("nogain")) return true; - var eff = get.effect(player, event.card, event.player, player); - if (eff >= 0) return false; - var suits = [], - banned = [], - hs = player.getCards("h"); - for (var i of hs) { - var suit = get.suit(i, player); - suits.add(suit); - if (!lib.filter.cardDiscardable(i, player, "qingliang")) banned.add(suit); - } - suits.removeArray(banned); - for (var i of suits) { - var cards = player.getCards("h", function (card) { - return get.suit(card, player) == i; + if (get.attitude(player, event.player) >= 0) return false; + if (get.damageEffect(event.player, event.getParent(3).player, player, get.nature(event.card)) <= 0) return false; + if ( + player.hasCard(function (card) { + return get.type(card) != "basic" && get.value(card) < 7 && lib.filter.cardDiscardable(card, player, "zengou"); + }, "eh") + ) + return true; + return player.hp > Math.max(1, event.player.hp); + }, + content: function () { + "step 0"; + trigger.all_excluded = true; + var str = "弃置一张非基本牌"; + if (player.hp > 0) str += ",或点「取消」失去1点体力"; + var next = player + .chooseToDiscard( + str, + function (card) { + return get.type(card) != "basic"; + }, + "he" + ) + .set("ai", function (card) { + return 7 - get.value(card); }); - if (-eff / 2 - get.value(cards, player) > 0) return true; - } + if (player.hp <= 0) next.set("forced", true); + "step 1"; + if (!result.bool) player.loseHp(); + "step 2"; + var cards = trigger.cards.filterInD(); + if (cards.length) player.gain(cards, "gain2"); + }, + }, + qhzhangji: { + audio: 2, + trigger: { global: "phaseJieshuBegin" }, + direct: true, + filter: function (event, player) { + if (!event.player.isIn()) return false; + if (player.getHistory("sourceDamage").length > 0) return true; + if (player.getHistory("damage").length > 0) return event.player.countCards("he") > 0; return false; }, content: function () { "step 0"; - player.showHandcards(get.translation(player) + "发动了【清靓】"); + event.target = trigger.player; + if (player.getHistory("sourceDamage").length) + player + .chooseBool(get.prompt("qhzhangji", event.target), "令" + get.translation(event.target) + "摸两张牌") + .set("choice", get.attitude(player, event.target) > 0) + .set("ai", () => _status.event.choice); + else event.goto(2); "step 1"; - var suits = [], - banned = [], - hs = player.getCards("h"); - for (var i of hs) { - var suit = get.suit(i, player); - suits.add(suit); - if (!lib.filter.cardDiscardable(i, player, "qingliang")) banned.add(suit); + if (result.bool) { + player.logSkill("qhzhangji", target); + event.logged = true; + target.draw(2); } - if (suits.length > banned.length) { + "step 2"; + if (target.isIn() && target.countCards("he") > 0 && player.getHistory("damage").length > 0) player - .chooseControl() - .set("choiceList", ["和" + get.translation(trigger.player) + "各摸一张牌", "弃置一种花色的所有手牌,令" + get.translation(trigger.card) + "对自己无效"]) - .set("ai", function () { - var player = _status.event.player, - event = _status.event.getTrigger(); - if (get.attitude(player, event.player) > 0 || event.player.hasSkillTag("nogain")) return 0; - return 1; - }); - event.suits = suits; - suits.removeArray(banned); - suits.sort(); - } else { - event._result = { index: 0 }; + .chooseBool(get.prompt("qhzhangji", event.target), "令" + get.translation(event.target) + "弃置两张牌") + .set("choice", get.attitude(player, event.target) < 0) + .set("ai", () => _status.event.choice); + else event.finish(); + "step 3"; + if (result.bool) { + if (!event.logged) player.logSkill("qhzhangji", target); + target.chooseToDiscard("he", true, 2); } - "step 2"; - if (result.index == 0) { - var list = [player, trigger.player].sortBySeat(); - list[0].draw("nodelay"); - list[1].draw(); - event.finish(); - } else { - if (event.suits.length == 1) event._result = { control: event.suits[0] }; - else - player - .chooseControl(event.suits) - .set("prompt", "选择弃置一种花色的所有牌") - .set("ai", function () { - var player = _status.event.player, - list = _status.event.controls.slice(0); - var gett = function (suit) { - var cards = player.getCards("h", function (card) { - return get.suit(card, player) == suit; - }); - return get.value(cards); - }; - return list.sort(function (b, a) { - return gett(b) - gett(a); - })[0]; - }); + }, + }, + //十周年夏侯霸 + rebaobian: { + audio: 2, + trigger: { player: "damageEnd" }, + filter: function (event, player) { + for (var i of lib.skill.rebaobian.derivation) { + if (!player.hasSkill(i, null, null, false)) return true; } - "step 3"; - var cards = player.getCards("h", function (card) { - return get.suit(card) == result.control; - }); - if (cards.length) player.discard(cards); - trigger.targets.remove(player); - trigger.getParent().triggeredTargets2.remove(player); - trigger.untrigger(); + return false; + }, + forced: true, + content: function () { + for (var i of lib.skill.rebaobian.derivation) { + if (!player.hasSkill(i, null, null, false)) { + player.addSkills(i); + break; + } + } + }, + ai: { + maixie: true, + effect: { + target: function (card, player, target) { + if (get.tag(card, "damage") && !target.hasSkill("oltiaoxin", null, null, false)) { + if (!target.hasFriend()) return; + if (target.hp >= 4) return [0, 1]; + } + }, + }, + }, + derivation: ["tiaoxin", "new_repaoxiao", "xinshensu"], + }, + //范强张达 + yuanchou: { + audio: 2, + trigger: { + player: "useCardToPlayered", + target: "useCardToTargeted", + }, + filter: function (event) { + return event.card.name == "sha" && get.color(event.card) == "black"; + }, + forced: true, + logTarget: "target", + content: function () { + trigger.target.addTempSkill("qinggang2"); + trigger.target.storage.qinggang2.add(trigger.card); + }, + ai: { + unequip_ai: true, + skillTagFilter: function (player, tag, arg) { + if (arg && arg.name == "sha" && get.color(arg.card) == "black") return true; + return false; + }, + }, + global: "yuanchou_ai", + subSkill: { + ai: { + unequip_ai: true, + skillTagFilter: function (player, tag, arg) { + if (arg && arg.name == "sha" && get.color(arg.card) == "black" && arg.target && arg.target.hasSkill("yuanchou")) return true; + return false; + }, + }, }, }, - //卫兹 - yuanzi: { + juesheng: { audio: 2, - trigger: { global: "phaseZhunbeiBegin" }, - logTarget: "player", - filter: function (event, player) { - return player != event.player && event.player.isIn() && player.countCards("h") > 0 && !player.hasSkill("yuanzi_round", null, null, false); - }, - check: function (event, player) { - if (event.player.hasJudge("lebu") || get.attitude(player, event.player) < 2) return false; - return game.hasPlayer(function (current) { - return current !== player && current !== event.player && event.player.inRange(current) && get.attitude(event.player, current) < 0; - }); + enable: "phaseUse", + limited: true, + skillAnimation: true, + animationColor: "orange", + viewAs: { name: "juedou", isCard: true }, + filterCard: () => false, + selectCard: -1, + precontent: function () { + player.awakenSkill("juesheng"); + player.addTempSkill("juesheng_counter"); }, - content: function () { - var cards = player.getCards("h"); - player.give(cards, trigger.player); - player.addTempSkill("yuanzi_effect"); - player.addTempSkill("yuanzi_round", "roundStart"); + ai: { + result: { + player: function (player, target) { + return (target.getAllHistory("useCard", evt => evt.card.name == "sha").length + 1) * lib.card.juedou.ai.result.player.apply(this, arguments); + }, + target: function (player, target) { + var num = target.getAllHistory("useCard", evt => evt.card.name == "sha").length + 1; + if (num < target.hp) return 0; + return num * lib.card.juedou.ai.result.target; + }, + }, }, subSkill: { - effect: { - charlotte: true, - audio: "yuanzi", - trigger: { global: "damageSource" }, + counter: { + trigger: { global: "damageBegin1" }, forced: true, + charlotte: true, filter: function (event, player) { - var source = event.source; - return source && source == _status.currentPhase && player.countCards("h") <= source.countCards("h"); + var evt = event.getParent(); + return evt.skill == "juesheng" && evt.player == player; }, content: function () { - player.draw(2); + var target = trigger.getParent().target; + trigger.num = 1 + target.getAllHistory("useCard", evt => evt.card.name == "sha").length; + target.addTempSkills("juesheng", { player: "phaseAfter" }); }, }, - round: { charlotte: true }, }, }, - liejie: { + //田之间 + saodi: { audio: 2, - trigger: { player: "damageEnd" }, - direct: true, - filter: function (event, player) { - return player.countCards("he") > 0; - }, - content: function () { - "step 0"; - var source = trigger.source; - var prompt2 = "弃置至多三张牌并摸等量的牌"; - if (source) prompt2 += ",若弃置的牌中有红色牌,则弃置" + get.translation(source) + "至多等量的牌"; - var next = player.chooseToDiscard("he", [1, 3], get.prompt("liejie"), prompt2); - next.set("ai", function (card) { - return 6 - get.value(card); - }); - if (source) next.logSkill = ["liejie", source]; - else next.logSkill = "liejie"; - "step 1"; - if (result.bool) { - var cards = result.cards; - player.draw(cards.length); - if (trigger.source) { - var num = cards.filter(function (i) { - return get.color(i, player) == "red"; - }).length; - if (num > 0) player.discardPlayerCard(trigger.source, "he", [1, num]).set("forceAuto", true); - } - } + trigger: { + player: "useCardToPlayer", }, - }, - //滕芳兰 - luochong: { - audio: 2, - trigger: { player: ["phaseZhunbeiBegin", "damageEnd"] }, direct: true, filter: function (event, player) { - if (event.name == "damage") { - var history = player.getHistory("damage"); - if (history.indexOf(event) != 0) return false; + if (event.targets.length != 1 || event.target == player || event.target.hasSkill("nodis")) return false; + if (event.card.name != "sha" && get.type(event.card) != "trick") return false; + var target = event.target; + var left = [], + right = [], + left2 = player, + right2 = player; + while (left2 != target && right2 != target) { + left2 = left2.getPrevious(); + right2 = right2.getNext(); + if (left2 != target) left.push(left2); + if (right2 != target) right.push(right2); } - var storage1 = player.storage.luochong_round, - storage2 = player.getStorage("luochong"); - if (!storage1) storage1 = [[], []]; - for (var i = 0; i < 4; i++) { - if ( - !storage1[0].includes(i) && - !storage2.includes(i) && - game.hasPlayer(function (current) { - return !storage1[1].includes(current) && lib.skill.luochong.filterx[i](current); - }) - ) - return true; + if (target == left2) { + for (var i of left) { + if (lib.filter.targetEnabled2(event.card, player, i)) return true; + } + } + if (target == right2) { + for (var i of right) { + if (lib.filter.targetEnabled2(event.card, player, i)) return true; + } } return false; }, - filterx: [target => target.isDamaged(), () => true, target => target.countCards("he") > 0, () => true], - onremove: true, - content: function () { - "step 0"; - var list = []; - var choiceList = ["令一名角色回复1点体力。", "令一名角色失去1点体力。", "令一名角色弃置两张牌。", "令一名角色摸两张牌。"]; - var storage1 = player.storage.luochong_round, - storage2 = player.getStorage("luochong"); - if (!storage1) storage1 = [[], []]; - for (var i = 0; i < 4; i++) { - if (storage2.includes(i)) { - choiceList[i] = '' + choiceList[i] + ""; - } else if ( - storage1[0].includes(i) || - !game.hasPlayer(function (current) { - return !storage1[1].includes(current) && lib.skill.luochong.filterx[i](current); - }) - ) { - choiceList[i] = '' + choiceList[i] + ""; - } else list.push("选项" + get.cnNumber(i + 1, true)); - } - list.push("cancel2"); - player - .chooseControl(list) - .set("prompt", get.prompt("luochong")) - .set("choiceList", choiceList) - .set("ai", function () { - var player = _status.event.player; - var list = _status.event.controls.slice(0); - var listx = (player.storage.luochong_round || [[], []])[1]; - var gett = function (choice) { - if (choice == "cancel2") return 0.1; - var max = 0, - func = { - 选项一: function (current) { - if (current.isDamaged()) max = Math.max(max, get.recoverEffect(current, player, player)); - }, - 选项二: function (target) { - max = Math.max(max, get.effect(target, { name: "losehp" }, player, player)); - }, - 选项三: function (target) { - var num = target.countDiscardableCards(player, "he"); - if (num > 0) max = Math.max(max, Math.sqrt(Math.min(2, num)) * get.effect(target, { name: "guohe_copy2" }, player, player)); - }, - 选项四: function (target) { - max = Math.max(max, 2 * get.effect(target, { name: "draw" }, player, player)); - }, - }[choice]; - game.countPlayer(function (current) { - if (!listx.includes(current)) func(current); - }); - return max; - }; - return list.sort(function (a, b) { - return gett(b) - gett(a); - })[0]; - }); - "step 1"; - if (result.control != "cancel2") { - var index = ["选项一", "选项二", "选项三", "选项四"].indexOf(result.control); - event.index = index; - var listx = (player.storage.luochong_round || [[], []])[1]; - var list = [ - [ - "选择一名角色,令其回复1点体力", - function (target) { - var player = _status.event.player; - return get.recoverEffect(target, player, player); - }, - ], - [ - "选择一名角色,令其失去1点体力", - function (target) { - return get.effect(target, { name: "losehp" }, player, player); - }, - ], - [ - "选择一名角色,令其弃置两张牌", - function (target) { - var player = _status.event.player; - return get.effect(target, { name: "guohe_copy2" }, player, player) * Math.sqrt(Math.min(2, target.countCards("he"))); - }, - ], - [ - "选择一名角色,令其摸两张牌", - function (target) { - var player = _status.event.player; - return 2 * get.effect(target, { name: "draw" }, player, player); - }, - ], - ][index]; - var targets = game.filterPlayer(function (current) { - return !listx.includes(current) && lib.skill.luochong.filterx[event.index](current); - }); - var next = player.chooseTarget(list[0], true, function (card, player, target) { - return _status.event.targets.includes(target); - }); - next.set("targets", targets); - next.set("ai", list[1]); - } else event.finish(); - "step 2"; - if (result.bool) { - var target = result.targets[0]; - player.logSkill("luochong", target); - if (player != target) player.addExpose(0.2); - player.addTempSkill("luochong_round", "roundStart"); - if (!player.storage.luochong_round) player.storage.luochong_round = [[], []]; - player.storage.luochong_round[0].push(event.index); - player.storage.luochong_round[1].push(target); - switch (event.index) { - case 0: - target.recover(); - break; - case 1: - target.loseHp(); - break; - case 2: - target.chooseToDiscard(true, "he", 2); - break; - case 3: - target.draw(2); - break; + aiJudge: function (card, player, target, bool) { + var left = [], + right = [], + left2 = player, + right2 = player, + left3 = false, + right3 = false; + var eff_left = 0, + eff_right = 0; + while (left2 != target && right2 != target) { + left2 = left2.getPrevious(); + right2 = right2.getNext(); + if (left2 != target) left.push(left2); + if (right2 != target) right.push(right2); + } + if (target == left2) { + for (var i of left) { + if (lib.filter.targetEnabled2(card, player, i)) { + left3 = true; + eff_left += get.effect(i, card, player, player); + } } } - }, - subSkill: { - round: { - charlotte: true, - onremove: true, - }, - }, - }, - aichen: { - audio: 2, - trigger: { player: "dying" }, - forced: true, - filter: function (event, player) { - return player.hasSkill("luochong", null, null, false) && player.getStorage("luochong").length < 3; + if (target == right2) { + for (var i of right) { + if (lib.filter.targetEnabled2(card, player, i)) { + right3 = true; + eff_right += get.effect(i, card, player, player); + } + } + } + if (left3 && right3) { + if (!bool) return Math.max(eff_left, eff_right); + if (eff_left > Math.max(0, eff_right)) return "↖顺时针"; + if (eff_right > Math.max(0, eff_left)) return "逆时针↗"; + return "cancel2"; + } else if (left3) { + if (bool) return eff_left > 0 ? "↖顺时针" : "cancel2"; + return eff_left; + } else if (right3) { + if (bool) return eff_right > 0 ? "逆时针↗" : "cancel2"; + return eff_right; + } else return bool ? "cancel2" : 0; }, content: function () { "step 0"; - //var num=1-player.hp; - //if(num>0) player.recover(num); - var list = []; - var choiceList = ["令一名角色回复1点体力。", "令一名角色失去1点体力。", "令一名角色弃置两张牌。", "令一名角色摸两张牌。"]; - var storage2 = player.getStorage("luochong"); - for (var i = 0; i < 4; i++) { - if (storage2.includes(i)) { - choiceList[i] = '' + choiceList[i] + ""; - } else list.push("选项" + get.cnNumber(i + 1, true)); + var choices = []; + var target = trigger.target; + var left = [], + right = [], + left2 = player, + right2 = player; + while (left2 != target && right2 != target) { + left2 = left2.getPrevious(); + right2 = right2.getNext(); + if (left2 != target) left.push(left2); + if (right2 != target) right.push(right2); + } + if (target == left2) { + for (var i of left) { + if (lib.filter.targetEnabled2(trigger.card, player, i)) { + choices.push("↖顺时针"); + break; + } + } + } + if (target == right2) { + for (var i of right) { + if (lib.filter.targetEnabled2(trigger.card, player, i)) { + choices.push("逆时针↗"); + break; + } + } } + choices.push("cancel2"); player - .chooseControl(list) - .set("prompt", "哀尘:选择移去一个〖落宠〗的选项") - .set("choiceList", choiceList) + .chooseControl(choices) + .set("prompt", get.prompt("saodi")) + .set("prompt2", "令自己和" + get.translation(trigger.target) + "某个方向之间的所有角色均成为" + get.translation(trigger.card) + "的目标") + .set("choices", choices) .set("ai", function () { - var controls = _status.event.controls.slice(0); - var list = ["选项三", "选项四", "选项二", "选项一"]; - for (var i of list) { - if (controls.includes(i)) return i; - } - return 0; + var evt = _status.event.getTrigger(); + return lib.skill.saodi.aiJudge(evt.card, evt.player, evt.target, true); }); "step 1"; - var index = ["选项一", "选项二", "选项三", "选项四"].indexOf(result.control); - player.markAuto("luochong", [index]); - game.log(player, "移去了", "#g【落宠】", "的", "#y" + ["令一名角色回复1点体力", "令一名角色失去1点体力", "令一名角色弃置两张牌", "令一名角色摸两张牌"][index], "的选项"); + if (result.control != "cancel2") { + var targets = []; + if (result.control == "↖顺时针") { + var current = player.getPrevious(); + while (current != trigger.target) { + if (lib.filter.targetEnabled2(trigger.card, player, current)) targets.push(current); + current = current.getPrevious(); + } + } else { + var current = player.getNext(); + while (current != trigger.target) { + if (lib.filter.targetEnabled2(trigger.card, player, current)) targets.push(current); + current = current.getNext(); + } + } + event.targets = targets; + if (!event.isMine() && !event.isOnline()) game.delayx(); + } else event.finish(); + "step 2"; + player.logSkill("saodi", targets); + trigger.targets.addArray(targets); }, ai: { - combo: "luochong", - neg: true, + effect: { + player_use(card, player, target) { + if (!target || player._saodi_judging || ui.selected.targets.length || player == target || target.hasSkill("nodis")) return; + if (typeof card != "object" || (card.name != "sha" && get.type(card) != "trick")) return false; + player._saodi_judging = true; + var effect = lib.skill.saodi.aiJudge(card, player, target); + delete player._saodi_judging; + if (effect > 0) return [1, effect / Math.max(0.01, get.attitude(player, player))]; + }, + }, }, }, - //SP孟获 - spmanwang: { + zhuitao: { audio: 2, - enable: "phaseUse", + direct: true, + locked: false, + trigger: { player: "phaseZhunbeiBegin" }, filter: function (event, player) { - return player.countCards("he") > 0; - }, - filterCard: true, - position: "he", - selectCard: [1, Infinity], - check: function (card) { - var player = _status.event.player; - var max = Math.min(player.isDamaged() ? 3 : 2, 4 - player.countMark("spmanwang")); - if (!max && !player.hasSkill("sppanqin")) return 0; - if (max == 0 && ui.selected.length > 0) return 0; - return 7 - ui.selected.cards.length - get.value(card); + var storage = player.getStorage("zhuitao"); + return game.hasPlayer(function (current) { + return current != player && !storage.includes(current); + }); }, content: function () { - var num = Math.min(cards.length, 4 - player.countMark("spmanwang")); - if (num >= 1) player.addSkills("sppanqin"); - if (num >= 2) player.draw(); - if (num >= 3) player.recover(); - if (num >= 4) { - player.draw(2); - player.removeSkills("sppanqin"); + "step 0"; + player + .chooseTarget(get.prompt("zhuitao"), "令自己至一名其他角色的距离-1", function (card, player, target) { + return target != player && !player.getStorage("zhuitao").includes(target); + }) + .set("ai", function (target) { + var player = _status.event.player; + var att = get.attitude(player, target); + if (att < 0 && get.distance(player, target) == 2) return 100; + return get.distance(player, target) * (1 - get.sgn(att) / 3); + }); + "step 1"; + if (result.bool) { + player.logSkill("zhuitao", result.targets[0]); + player.markAuto("zhuitao", result.targets); + game.delayx(); } }, - intro: { content: "已经移去过#个选项" }, - ai: { - order: 2, - result: { - player: function (player, target) { - if (player.getUseValue({ name: "nanman" }) <= 0) return 0; - if (player.getStat("skill").spmanwang && player.hasSkill("sppanqin")) return 0; - return 1; - }, - }, - }, - derivation: "sppanqin", - }, - sppanqin: { - audio: 2, - trigger: { player: ["phaseUseEnd", "phaseDiscardEnd"] }, - filter: function (event, player) { - var cards = [], - bool = true; - player.getHistory("lose", function (evt) { - if (!bool || evt.type != "discard" || evt.getParent(event.name) != event) return false; - for (var i of evt.cards2) { - if (get.position(i, true) == "d") { - cards.add(i); - if (!game.checkMod(i, player, "unchanged", "cardEnabled2", player)) bool = false; - } - } - }); - if (!bool || !cards.length) return false; - return player.hasUseTarget(get.autoViewAs({ name: "nanman" }, cards)); + intro: { + content: "至$的距离-1", + onunmark: true, }, - prompt2: function (event, player) { - var cards = []; - player.getHistory("lose", function (evt) { - if (evt.type != "discard" || evt.getParent(event.name) != event) return false; - for (var i of evt.cards2) { - if (get.position(i, true) == "d") { - cards.add(i); - } - } - }); - return "将" + get.translation(cards) + "(共计" + get.cnNumber(cards.length) + "张牌)当做【南蛮入侵】使用"; + onremove: true, + mod: { + globalFrom: function (player, target, distance) { + if (player.getStorage("zhuitao").includes(target)) return distance - 1; + }, }, - check: function (event, player) { - var cards = [], - bool = true; - player.getHistory("lose", function (evt) { - if (!bool || evt.type != "discard" || evt.getParent(event.name) != event) return false; - for (var i of evt.cards2) { - if (get.position(i, true) == "d") { - cards.add(i); - if (!game.checkMod(i, player, "unchanged", "cardEnabled2", player)) bool = false; - } - } - }); - if (!bool || !cards.length) return false; - return player.hasValueTarget(get.autoViewAs({ name: "nanman" }, cards)); + group: "zhuitao_remove", + subSkill: { + remove: { + audio: "zhuitao", + trigger: { + source: "damageSource", + }, + forced: true, + filter: function (event, player) { + return player.getStorage("zhuitao").includes(event.player); + }, + logTarget: "player", + content: function () { + player.unmarkAuto("zhuitao", [trigger.player]); + }, + }, }, + }, + //生鱼片 + olfengji: { + audio: 2, + trigger: { global: "roundStart" }, + forced: true, + locked: false, content: function () { "step 0"; - var cards = []; - player.getHistory("lose", function (evt) { - if (evt.type != "discard" || evt.getParent(trigger.name) != trigger) return false; - for (var i of evt.cards2) { - if (get.position(i, true) == "d") { - cards.add(i); + player + .chooseTarget("丰积:请选择增加摸牌的目标", "令自己本轮摸牌阶段的额定摸牌数-1,且目标本轮摸牌阶段的额定摸牌数+2。或者点击「取消」,令自己本轮摸牌阶段的额定摸牌数+1", lib.filter.notMe) + .set("ai", function (target) { + var player = _status.event.player; + var att = get.attitude(player, target), + dist = get.distance(player, target, "absolute"); + if (att > 0) { + if (target.hasJudge("lebu") || target.hasJudge("bingliang")) return 0; + if (_status.event.goon) { + return att / dist; + } + if ( + game.countPlayer(function (current) { + return current != player && current != target && get.attitude(player, current) < 0 && get.distance(player, current, "absolute") < dist; + }) >= target.hp + ) + return 0; + return att / dist; + } + if (player.hasSkill("olxuanhui", null, null, false) && !player.isTempBanned("olxuanhui") && att < 0) { + const first = get.event().getTrigger().player, + list = ["draw", "sha"]; + if (first == player || get.distance(player, first, "absolute") > dist) { + const targets = [target.storage["olfengji_" + list[0]] || 0, target.storage["olfengji_" + list[1]] || 0]; + return 1 + targets.reduce((sum, num) => sum + num, 0); + } + } + return 0; + }) + .set("goon", player.skipList.includes("lebu")); + "step 1"; + if (!player.storage.olfengji_draw) player.storage.olfengji_draw = 0; + if (result.bool) { + var target = result.targets[0]; + player.line(target, "thunder"); + player.storage.olfengji_draw--; + if (!target.storage.olfengji_draw) target.storage.olfengji_draw = 0; + target.storage.olfengji_draw += 2; + target.addTempSkill("olfengji_draw", "roundStart"); + target.markSkill("olfengji_draw"); + } else { + player.storage.olfengji_draw++; + } + player.addTempSkill("olfengji_draw", "roundStart"); + player.markSkill("olfengji_draw"); + "step 2"; + player.chooseTarget("丰积:请选择增加使用杀次数的目标", "令自己本轮使用杀的次数上限-1,且目标本轮使用杀的次数上限+2。或者点击「取消」,令自己本轮使用杀的次数上限+1", lib.filter.notMe).set("ai", function (target) { + var player = _status.event.player; + if (target.countMark("olfengji_draw") > 0 && target.getCardUsable("sha") < 2 && get.attitude(player, target) > 0) return get.attitude(player, target); + if (player.hasSkill("olxuanhui", null, null, false) && !player.isTempBanned("olxuanhui") && get.attitude(player, target) < 0) { + const first = get.event().getTrigger().player, + list = ["draw", "sha"]; + if (first == player || get.distance(player, first, "absolute") > get.distance(player, target, "absolute")) { + const targets = [target.storage["olfengji_" + list[0]] || 0, target.storage["olfengji_" + list[1]] || 0]; + return 1 + targets.reduce((sum, num) => sum + num, 0); } } + return 0; }); - player.chooseUseTarget(true, { name: "nanman" }, cards); - player.addTempSkill("sppanqin_eff"); + "step 3"; + if (!player.storage.olfengji_sha) player.storage.olfengji_sha = 0; + if (result.bool) { + var target = result.targets[0]; + player.line(target, "fire"); + player.storage.olfengji_sha--; + if (!target.storage.olfengji_sha) target.storage.olfengji_sha = 0; + target.storage.olfengji_sha += 2; + target.addTempSkill("olfengji_sha", "roundStart"); + target.markSkill("olfengji_sha"); + } else { + player.storage.olfengji_sha++; + } + player.addTempSkill("olfengji_sha", "roundStart"); + player.markSkill("olfengji_sha"); }, subSkill: { - eff: { - trigger: { player: "useCard" }, + sha: { + charlotte: true, + onremove: true, + intro: { + content: function (storage) { + return "使用【杀】的次数上限" + (storage >= 0 ? "+" : "") + storage; + }, + }, + mod: { + cardUsable: function (card, player, num) { + if (card.name == "sha") return num + player.storage.olfengji_sha; + }, + }, + }, + draw: { charlotte: true, + onremove: true, + intro: { + content: function (storage) { + return "额定摸牌数" + (storage >= 0 ? "+" : "") + storage; + }, + }, + trigger: { player: "phaseDrawBegin2" }, forced: true, - popup: false, filter: function (event, player) { - return event.card.name == "nanman" && event.getParent(2).name == "sppanqin" && player.countMark("spmanwang") < 4 && player.hasSkill("spmanwang", null, null, false) && event.cards.length <= event.targets.length; + return !event.numFixed; }, content: function () { - player.addMark("spmanwang", 1, false); - switch (player.countMark("spmanwang")) { - case 1: - player.draw(2); - player.removeSkills("sppanqin"); - break; - case 2: - player.recover(); - break; - case 3: - player.draw(); - break; - case 4: - player.addSkills("sppanqin"); - break; - } + trigger.num += player.storage.olfengji_draw; }, }, }, }, - //清河公主 - zengou: { + olxuanhui: { audio: 2, - trigger: { global: "useCard" }, - filter: function (event, player) { - return ( - event.card.name == "shan" && - player.inRange(event.player) && - (player.hp > 0 || - player.hasCard(function (card) { - return get.type(card) != "basic" && lib.filter.cardDiscardable(card, player, "zengou"); - }, "eh")) - ); + trigger: { player: "phaseZhunbeiBegin" }, + filter(event, player) { + const targets = lib.skill.olxuanhui.logTarget(event, player); + return targets && targets.length; }, - logTarget: "player", - check: function (event, player) { - if (get.attitude(player, event.player) >= 0) return false; - if (get.damageEffect(event.player, event.getParent(3).player, player, get.nature(event.card)) <= 0) return false; - if ( - player.hasCard(function (card) { - return get.type(card) != "basic" && get.value(card) < 7 && lib.filter.cardDiscardable(card, player, "zengou"); - }, "eh") - ) - return true; - return player.hp > Math.max(1, event.player.hp); + logTarget(event, player) { + return game.filterPlayer(target => { + if (target == player) return false; + return (player.hasSkill("olfengji_sha") && target.hasSkill("olfengji_sha")) || (player.hasSkill("olfengji_draw") && target.hasSkill("olfengji_draw")); + }); + }, + check(event, player) { + const targets = lib.skill.olxuanhui.logTarget(event, player), + list = ["sha", "draw"]; + let sum = 0; + for (const target of targets) { + let eff = 0; + for (const skill of list) { + if (typeof player.storage["olfengji_" + skill] == "number") eff += player.storage["olfengji_" + skill]; + if (typeof target.storage["olfengji_" + skill] == "number") eff -= target.storage["olfengji_" + skill]; + } + if (get.attitude(player, target) <= 0 || target.getSeatNum() < player.getSeatNum()) eff *= -1; + sum += eff; + } + return sum > 0; + }, + async content(event, trigger, player) { + for (const target of event.targets) { + const list = ["draw", "sha"]; + for (const effect of list) { + const skill = `olfengji_${effect}`; + if (typeof player.storage[skill] != "number") continue; + if (typeof target.storage[skill] != "number") continue; + const num = player.storage[skill]; + player.storage[skill] = target.storage[skill]; + target.storage[skill] = num; + target.markSkill(skill); + player.markSkill(skill); + game.log(player, "与", target, "交换了", `#g【丰积·${effect == "draw" ? "摸牌" : "出杀"}】`, "的数值"); + } + } + player.tempBanSkill("olxuanhui", "dieAfter"); + }, + }, + //朱灵 + jixian: { + audio: 2, + trigger: { player: "phaseDrawAfter" }, + direct: true, + filter: function (event, player) { + return game.hasPlayer(function (current) { + return current != player && lib.skill.jixian.getNum(player, current) > 0 && player.canUse("sha", current, false); + }); }, content: function () { "step 0"; - trigger.all_excluded = true; - var str = "弃置一张非基本牌"; - if (player.hp > 0) str += ",或点「取消」失去1点体力"; - var next = player - .chooseToDiscard( - str, - function (card) { - return get.type(card) != "basic"; - }, - "he" - ) - .set("ai", function (card) { - return 7 - get.value(card); + player + .chooseTarget(get.prompt("jixian"), "视为对一名满足条件的角色使用一张【杀】", function (card, player, target) { + return target != player && lib.skill.jixian.getNum(player, target) > 0 && player.canUse("sha", target, false); + }) + .set("ai", function (target) { + var player = _status.event.player; + return get.effect(target, { name: "sha" }, player, player) * Math.sqrt(lib.skill.jixian.getNum(player, target)); }); - if (player.hp <= 0) next.set("forced", true); "step 1"; - if (!result.bool) player.loseHp(); + if (result.bool) { + var target = result.targets[0]; + player.logSkill("jixian", target); + var num = lib.skill.jixian.getNum(player, target); + player.useCard({ name: "sha", isCard: true }, target, false); + if (num > 0) player.draw(num); + } else event.finish(); "step 2"; - var cards = trigger.cards.filterInD(); - if (cards.length) player.gain(cards, "gain2"); + if ( + !player.hasHistory("sourceDamage", function (evt) { + var card = evt.card; + if (!card || card.name != "sha") return false; + var evtx = evt.getParent("useCard"); + return evtx.card == card && evtx.getParent() == event; + }) + ) + player.loseHp(); + }, + getNum: function (player, target) { + var num = 0; + if (target.isHealthy()) num++; + if (target.getEquips(2).length) num++; + var countSkill = function (player) { + return player.getSkills(null, false, false).filter(function (skill) { + var info = get.info(skill); + if (!info || info.charlotte) return false; + if (info.zhuSkill) return player.hasZhuSkill(skill); + return true; + }).length; + }; + if (countSkill(player) < countSkill(target)) num++; + return num; }, }, - qhzhangji: { + //吾彦 + lanjiang: { audio: 2, - trigger: { global: "phaseJieshuBegin" }, - direct: true, - filter: function (event, player) { - if (!event.player.isIn()) return false; - if (player.getHistory("sourceDamage").length > 0) return true; - if (player.getHistory("damage").length > 0) return event.player.countCards("he") > 0; - return false; - }, + audioname2: { heqi: "lanjiang_heqi" }, + trigger: { player: "phaseJieshuBegin" }, content: function () { "step 0"; - event.target = trigger.player; - if (player.getHistory("sourceDamage").length) - player - .chooseBool(get.prompt("qhzhangji", event.target), "令" + get.translation(event.target) + "摸两张牌") - .set("choice", get.attitude(player, event.target) > 0) - .set("ai", () => _status.event.choice); - else event.goto(2); + var ph = player.countCards("h"); + var targets = game.filterPlayer(current => current == player || current.countCards("h") >= ph).sortBySeat(); + player.line(targets, "green"); + event.targets = targets; + event.num = 0; "step 1"; - if (result.bool) { - player.logSkill("qhzhangji", target); - event.logged = true; - target.draw(2); + var target = targets[num]; + event.num++; + if (target.isIn()) { + event.target = target; + target.chooseBool("是否令" + (player == target ? "自己" : get.translation(player)) + "摸一张牌?").set("ai", () => get.attitude(_status.event.player, _status.event.getParent().player) > 0); + } else { + event.goto(event.num < targets.length ? 1 : 3); } "step 2"; - if (target.isIn() && target.countCards("he") > 0 && player.getHistory("damage").length > 0) - player - .chooseBool(get.prompt("qhzhangji", event.target), "令" + get.translation(event.target) + "弃置两张牌") - .set("choice", get.attitude(player, event.target) < 0) - .set("ai", () => _status.event.choice); - else event.finish(); + if (result.bool) { + target.line(player); + if (player !== target && (get.mode() !== "identity" || target.identity !== "nei")) target.addExpose(0.15); + player.draw(); + } + if (num < targets.length) event.goto(1); "step 3"; + player + .chooseTarget("是否对一名手牌数等于自己的目标角色造成1点伤害?", function (card, player, target) { + return _status.event.getParent().targets.includes(target) && target.countCards("h") == player.countCards("h"); + }) + .set("ai", function (target) { + var player = _status.event.player; + return get.damageEffect(target, player, player); + }); + "step 4"; if (result.bool) { - if (!event.logged) player.logSkill("qhzhangji", target); - target.chooseToDiscard("he", true, 2); + var target = result.targets[0]; + player.line(target, "green"); + if (get.mode() !== "identity" || player.identity !== "nei") player.addExpose(0.15); + target.damage(); + } else event.finish(); + "step 5"; + var ph = player.countCards("h"); + if (ph > 0 && targets.some(target => target.isIn() && target.countCards("h") < ph)) { + player + .chooseTarget( + "请选择一名手牌数小于自己的目标角色,令其摸一张牌", + function (card, player, target) { + return _status.event.getParent().targets.includes(target) && target.countCards("h") < player.countCards("h"); + }, + true + ) + .set("ai", function (target) { + var player = _status.event.player; + return get.attitude(player, target); + }); + } + "step 6"; + if (result.bool) { + var target = result.targets[0]; + player.line(target); + if (player !== target && (get.mode() !== "identity" || player.identity !== "nei")) player.addExpose(0.1); + target.draw(); } }, }, - //十周年夏侯霸 - rebaobian: { + //新SP张郃 + spolzhouxuan: { audio: 2, - trigger: { player: "damageEnd" }, + trigger: { player: "phaseDiscardBegin" }, filter: function (event, player) { - for (var i of lib.skill.rebaobian.derivation) { - if (!player.hasSkill(i, null, null, false)) return true; - } - return false; + return player.countCards("h") > 0 && player.getExpansions("spolzhouxuan").length < 5; }, - forced: true, + direct: true, content: function () { - for (var i of lib.skill.rebaobian.derivation) { - if (!player.hasSkill(i, null, null, false)) { - player.addSkills(i); - break; - } + "step 0"; + player.chooseCard("h", get.prompt("spolzhouxuan"), [1, 5 - player.getExpansions("spolzhouxuan").length], "将至多" + get.cnNumber(5 - player.getExpansions("spolzhouxuan").length) + "张手牌置于武将牌上").set("ai", function (card) { + if (ui.selected.cards.length >= player.needsToDiscard()) return 6 - get.value(card); + return 100 - get.useful(card); + }); + "step 1"; + if (result.bool) { + var cards = result.cards; + player.logSkill("spolzhouxuan"); + player.addToExpansion(cards, player, "give").gaintag.add("spolzhouxuan"); } }, - ai: { - maixie: true, - effect: { - target: function (card, player, target) { - if (get.tag(card, "damage") && !target.hasSkill("oltiaoxin", null, null, false)) { - if (!target.hasFriend()) return; - if (target.hp >= 4) return [0, 1]; - } + marktext: "旋", + intro: { + content: "expansion", + markcount: "expansion", + }, + onremove: function (player, skill) { + var cards = player.getExpansions(skill); + if (cards.length) player.loseToDiscardpile(cards); + }, + group: ["spolzhouxuan_use", "spolzhouxuan_discard"], + subSkill: { + use: { + audio: "spolzhouxuan", + trigger: { player: "useCard" }, + filter: function (event, player) { + return player.getExpansions("spolzhouxuan").length > 0; + }, + forced: true, + locked: false, + content: function () { + "step 0"; + player.loseToDiscardpile(player.getExpansions("spolzhouxuan").randomGet()); + "step 1"; + var num = 1; + if (!player.isMaxHandcard(true)) num += player.getExpansions("spolzhouxuan").length; + player.draw(num); + }, + }, + discard: { + audio: "spolzhouxuan", + trigger: { player: "phaseUseEnd" }, + filter: function (event, player) { + return player.getExpansions("spolzhouxuan").length > 0; + }, + forced: true, + locked: false, + content: function () { + player.loseToDiscardpile(player.getExpansions("spolzhouxuan")); }, }, }, - derivation: ["tiaoxin", "new_repaoxiao", "xinshensu"], }, - //范强张达 - yuanchou: { + //董昭 + olxianlve: { audio: 2, + mode: ["identity"], trigger: { - player: "useCardToPlayered", - target: "useCardToTargeted", + global: "phaseZhunbeiBegin", }, - filter: function (event) { - return event.card.name == "sha" && get.color(event.card) == "black"; + direct: true, + filter: function (event, player) { + return event.player == game.zhu && event.player.isZhu; }, - forced: true, - logTarget: "target", content: function () { - trigger.target.addTempSkill("qinggang2"); - trigger.target.storage.qinggang2.add(trigger.card); + "step 0"; + var list = lib.inpile + .filter(function (i) { + return get.type2(i) == "trick"; + }) + .map(function (i) { + return ["锦囊", "", i]; + }); + if (!list.length) event.finish(); + else + player.chooseButton([get.prompt("olxianlve"), [list, "vcard"]]).set("ai", function (button) { + switch (button.link[2]) { + case "wuxie": + return 0.6 + Math.random(); + case "wuzhong": + case "dongzhuxianji": + return 0.5 + Math.random(); + case "guohe": + case "zhujinqiyuan": + return 0.4 + Math.random(); + default: + return Math.random(); + } + }); + "step 1"; + if (result.bool) { + var name = result.links[0][2]; + player.logSkill("olxianlve"); + player.storage.olxianlve = name; + player.markSkill("olxianlve"); + } }, - ai: { - unequip_ai: true, - skillTagFilter: function (player, tag, arg) { - if (arg && arg.name == "sha" && get.color(arg.card) == "black") return true; - return false; + intro: { + content: function (name, player) { + return "已声明" + (player.isUnderControl(true) ? "【" + get.translation(name) + "】" : "一个牌名"); }, }, - global: "yuanchou_ai", + group: ["olxianlve_use", "olxianlve_count"], subSkill: { - ai: { - unequip_ai: true, - skillTagFilter: function (player, tag, arg) { - if (arg && arg.name == "sha" && get.color(arg.card) == "black" && arg.target && arg.target.hasSkill("yuanchou")) return true; - return false; - }, - }, - }, - }, - juesheng: { - audio: 2, - enable: "phaseUse", - limited: true, - skillAnimation: true, - animationColor: "orange", - viewAs: { name: "juedou", isCard: true }, - filterCard: () => false, - selectCard: -1, - precontent: function () { - player.awakenSkill("juesheng"); - player.addTempSkill("juesheng_counter"); - }, - ai: { - result: { - player: function (player, target) { - return (target.getAllHistory("useCard", evt => evt.card.name == "sha").length + 1) * lib.card.juedou.ai.result.player.apply(this, arguments); + count: { + trigger: { global: "useCard1" }, + silent: true, + forced: true, + popup: false, + firstDo: true, + filter: function (event, player) { + return event.player != player && event.card.name == player.storage.olxianlve; }, - target: function (player, target) { - var num = target.getAllHistory("useCard", evt => evt.card.name == "sha").length + 1; - if (num < target.hp) return 0; - return num * lib.card.juedou.ai.result.target; + content: function () { + if (!trigger.olxianlve_map) trigger.olxianlve_map = {}; + trigger.olxianlve_map[player.playerid] = true; }, }, - }, - subSkill: { - counter: { - trigger: { global: "damageBegin1" }, + use: { + audio: "olxianlve", + trigger: { global: "useCardAfter" }, forced: true, - charlotte: true, + locked: false, + usable: 1, filter: function (event, player) { - var evt = event.getParent(); - return evt.skill == "juesheng" && evt.player == player; + return event.player != player && event.olxianlve_map && event.olxianlve_map[player.playerid] && event.card.name == player.storage.olxianlve; }, content: function () { - var target = trigger.getParent().target; - trigger.num = (1 + target.getAllHistory("useCard", evt => evt.card.name == "sha").length); - target.addTempSkills("juesheng", { player: "phaseAfter" }); - }, - }, - }, - }, - //田之间 - saodi: { - audio: 2, - trigger: { - player: "useCardToPlayer", - }, - direct: true, - filter: function (event, player) { - if (event.targets.length != 1 || event.target == player || event.target.hasSkill("nodis")) return false; - if (event.card.name != "sha" && get.type(event.card) != "trick") return false; - var target = event.target; - var left = [], - right = [], - left2 = player, - right2 = player; - while (left2 != target && right2 != target) { - left2 = left2.getPrevious(); - right2 = right2.getNext(); - if (left2 != target) left.push(left2); - if (right2 != target) right.push(right2); - } - if (target == left2) { - for (var i of left) { - if (lib.filter.targetEnabled2(event.card, player, i)) return true; - } - } - if (target == right2) { - for (var i of right) { - if (lib.filter.targetEnabled2(event.card, player, i)) return true; - } - } - return false; - }, - aiJudge: function (card, player, target, bool) { - var left = [], - right = [], - left2 = player, - right2 = player, - left3 = false, - right3 = false; - var eff_left = 0, - eff_right = 0; - while (left2 != target && right2 != target) { - left2 = left2.getPrevious(); - right2 = right2.getNext(); - if (left2 != target) left.push(left2); - if (right2 != target) right.push(right2); - } - if (target == left2) { - for (var i of left) { - if (lib.filter.targetEnabled2(card, player, i)) { - left3 = true; - eff_left += get.effect(i, card, player, player); + "step 0"; + player.draw(2); + "step 1"; + var cards = result; + if (get.itemtype(cards) != "cards") { + event.goto(5); + return; } - } - } - if (target == right2) { - for (var i of right) { - if (lib.filter.targetEnabled2(card, player, i)) { - right3 = true; - eff_right += get.effect(i, card, player, player); + var hs = player.getCards("h"); + cards = cards.filter(function (card) { + return hs.includes(card); + }); + if (!cards.length) { + event.goto(5); + return; } - } - } - if (left3 && right3) { - if (!bool) return Math.max(eff_left, eff_right); - if (eff_left > Math.max(0, eff_right)) return "↖顺时针"; - if (eff_right > Math.max(0, eff_left)) return "逆时针↗"; - return "cancel2"; - } else if (left3) { - if (bool) return eff_left > 0 ? "↖顺时针" : "cancel2"; - return eff_left; - } else if (right3) { - if (bool) return eff_right > 0 ? "逆时针↗" : "cancel2"; - return eff_right; - } else return bool ? "cancel2" : 0; - }, - content: function () { - "step 0"; - var choices = []; - var target = trigger.target; - var left = [], - right = [], - left2 = player, - right2 = player; - while (left2 != target && right2 != target) { - left2 = left2.getPrevious(); - right2 = right2.getNext(); - if (left2 != target) left.push(left2); - if (right2 != target) right.push(right2); - } - if (target == left2) { - for (var i of left) { - if (lib.filter.targetEnabled2(trigger.card, player, i)) { - choices.push("↖顺时针"); - break; + event.cards = cards; + if (_status.connectMode) + game.broadcastAll(function () { + _status.noclearcountdown = true; + }); + event.given_map = {}; + event.ai_list = []; + "step 2"; + player.chooseCardTarget({ + filterCard: function (card) { + return _status.event.cards.includes(card) && !card.hasGaintag("olxianlve"); + }, + cards: cards, + filterTarget: lib.filter.notMe, + selectCard: [1, cards.length], + prompt: "是否将得到的牌分配给其他角色?", + ai1: function (card) { + if (!ui.selected.cards.length) return 1; + return 0; + }, + ai2: function (target) { + var player = _status.event.player, + card = ui.selected.cards[0]; + var val = target.getUseValue(card); + if (target.isPhaseUsing() && get.type2(card) == "trick") val *= 3; + if (val > 0) return val * get.attitude(player, target) * 2; + return get.value(card, target) * get.attitude(player, target); + }, + }); + "step 3"; + if (result.bool) { + var res = result.cards, + target = result.targets[0].playerid; + player.addGaintag(res, "olxianlve"); + cards.removeArray(res); + if (!event.given_map[target]) event.given_map[target] = []; + event.given_map[target].addArray(res); + if (result.targets[0].isPhaseUsing() && get.type2(res[0]) == "trick") event.ai_list.push(res[0].name); + if (cards.length) event.goto(2); } - } - } - if (target == right2) { - for (var i of right) { - if (lib.filter.targetEnabled2(trigger.card, player, i)) { - choices.push("逆时针↗"); - break; + "step 4"; + if (_status.connectMode) { + game.broadcastAll(function () { + delete _status.noclearcountdown; + game.stopCountChoose(); + }); } - } - } - choices.push("cancel2"); - player - .chooseControl(choices) - .set("prompt", get.prompt("saodi")) - .set("prompt2", "令自己和" + get.translation(trigger.target) + "某个方向之间的所有角色均成为" + get.translation(trigger.card) + "的目标") - .set("choices", choices) - .set("ai", function () { - var evt = _status.event.getTrigger(); - return lib.skill.saodi.aiJudge(evt.card, evt.player, evt.target, true); - }); - "step 1"; - if (result.control != "cancel2") { - var targets = []; - if (result.control == "↖顺时针") { - var current = player.getPrevious(); - while (current != trigger.target) { - if (lib.filter.targetEnabled2(trigger.card, player, current)) targets.push(current); - current = current.getPrevious(); + var map = [], + cards = []; + for (var i in event.given_map) { + var source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; + player.line(source, "green"); + map.push([source, event.given_map[i]]); + cards.addArray(event.given_map[i]); } - } else { - var current = player.getNext(); - while (current != trigger.target) { - if (lib.filter.targetEnabled2(trigger.card, player, current)) targets.push(current); - current = current.getNext(); + if (map.length) + game.loseAsync({ + gain_list: map, + player: player, + cards: cards, + giver: player, + animate: "giveAuto", + }).setContent("gaincardMultiple"); + "step 5"; + var list = lib.inpile + .filter(function (i) { + return get.type2(i) == "trick"; + }) + .map(function (i) { + return ["锦囊", "", i]; + }); + if (!list.length) event.finish(); + else + player + .chooseButton([get.prompt("olxianlve"), [list, "vcard"]]) + .set("list", event.ai_list) + .set("ai", function (button) { + if (_status.event.list.includes(button.link[2])) return 2 + Math.random(); + switch (button.link[2]) { + case "wuxie": + return 0.6 + Math.random(); + case "wuzhong": + case "dongzhuxianji": + return 0.5 + Math.random(); + case "guohe": + case "zhujinqiyuan": + return 0.4 + Math.random(); + default: + return Math.random(); + } + }); + "step 6"; + if (result.bool) { + var name = result.links[0][2]; + player.storage.olxianlve = name; + player.markSkill("olxianlve"); } - } - event.targets = targets; - if (!event.isMine() && !event.isOnline()) game.delayx(); - } else event.finish(); - "step 2"; - player.logSkill("saodi", targets); - trigger.targets.addArray(targets); + }, + }, + }, + }, + olzaowang: { + mode: ["identity"], + available: function (mode) { + if (mode == "identity" && _status.mode == "purple") return false; + }, + audio: 2, + enable: "phaseUse", + limited: true, + skillAnimation: true, + animationColor: "water", + filterTarget: true, + content: function () { + player.awakenSkill("olzaowang"); + target.gainMaxHp(); + target.recover(); + target.draw(3); + target.addSkills("olzaowang2"); }, ai: { - effect: { - player_use(card, player, target) { - if (!target || player._saodi_judging || ui.selected.targets.length || player == target || target.hasSkill("nodis")) return; - if (typeof card != "object" || (card.name != "sha" && get.type(card) != "trick")) return false; - player._saodi_judging = true; - var effect = lib.skill.saodi.aiJudge(card, player, target); - delete player._saodi_judging; - if (effect > 0) return [1, effect / Math.max(0.01, get.attitude(player, player))]; + order: 2, + result: { + target: function (player, target) { + if (player.hasUnknown(2)) return 0; + if (target.identity == "zhong") return 20; + if (target.identity == "zhu") return 10; + if (target.identity == "nei") return 5; + if (!target.hasFriend()) return 5; + return 0; }, }, }, }, - zhuitao: { - audio: 2, - direct: true, - locked: false, - trigger: { player: "phaseZhunbeiBegin" }, + olzaowang2: { + charlotte: true, + trigger: { global: "dieBegin" }, + forced: true, filter: function (event, player) { - var storage = player.getStorage("zhuitao"); - return game.hasPlayer(function (current) { - return current != player && !storage.includes(current); - }); + return event.player.identity == "zhu" && (player.identity == "zhong" || player.identity == "mingzhong"); }, + logTarget: "player", + skillAnimation: true, + animationColor: "orange", content: function () { - "step 0"; - player - .chooseTarget(get.prompt("zhuitao"), "令自己至一名其他角色的距离-1", function (card, player, target) { - return target != player && !player.getStorage("zhuitao").includes(target); - }) - .set("ai", function (target) { - var player = _status.event.player; - var att = get.attitude(player, target); - if (att < 0 && get.distance(player, target) == 2) return 100; - return get.distance(player, target) * (1 - get.sgn(att) / 3); - }); - "step 1"; - if (result.bool) { - player.logSkill("zhuitao", result.targets[0]); - player.markAuto("zhuitao", result.targets); - game.delayx(); - } - }, - intro: { - content: "至$的距离-1", - onunmark: true, - }, - onremove: true, - mod: { - globalFrom: function (player, target, distance) { - if (player.getStorage("zhuitao").includes(target)) return distance - 1; - }, + game.broadcastAll( + function (player, target) { + target.identity = player.identity; + if (player.identity == "mingzhong") game.zhong = target; + delete target.isZhu; + player.identity = "zhu"; + game.zhu = player; + player.showIdentity(); + target.showIdentity(); + }, + player, + trigger.player + ); + event.trigger("zhuUpdate"); }, - group: "zhuitao_remove", + mark: true, + marktext: "王", + intro: { content: "造了个王" }, + group: "olzaowang2_kill", subSkill: { - remove: { - audio: "zhuitao", - trigger: { - source: "damageSource", - }, + kill: { + trigger: { player: "die" }, forced: true, + forceDie: true, + skillAnimation: true, + animationColor: "wood", filter: function (event, player) { - return player.getStorage("zhuitao").includes(event.player); + return player.identity == "fan" && event.source && (event.source.identity == "zhu" || event.source.identity == "zhong" || event.source.identity == "mingzhong"); }, - logTarget: "player", content: function () { - player.unmarkAuto("zhuitao", [trigger.player]); + game.over(game.me.identity == "zhu" || game.me.identity == "zhong" || game.me.identity == "mingzhong"); }, }, }, }, - //生鱼片 - olfengji: { + //冯方女 + zhuangshu: { audio: 2, - trigger: { global: "roundStart" }, - forced: true, - locked: false, + trigger: { global: "phaseBegin" }, + direct: true, + filter: function (event, player) { + return event.player.isIn() && event.player.hasEmptySlot(5) && player.hasCard(lib.skill.zhuangshu.filterCard, "he"); + }, + filterCard: function (card) { + if (_status.connectMode) return true; + var type = get.type2(card); + return type == "basic" || type == "trick" || type == "equip"; + }, content: function () { "step 0"; player - .chooseTarget("丰积:请选择增加摸牌的目标", "令自己本轮摸牌阶段的额定摸牌数-1,且目标本轮摸牌阶段的额定摸牌数+2。或者点击「取消」,令自己本轮摸牌阶段的额定摸牌数+1", lib.filter.notMe) - .set("ai", function (target) { - var player = _status.event.player; - var att = get.attitude(player, target), - dist = get.distance(player, target, "absolute"); - if (att > 0) { - if (target.hasJudge("lebu") || target.hasJudge("bingliang")) return 0; - if (_status.event.goon) { - return att / dist; - } - if ( - game.countPlayer(function (current) { - return current != player && current != target && get.attitude(player, current) < 0 && get.distance(player, current, "absolute") < dist; - }) >= target.hp - ) - return 0; - return att / dist; - } - if (player.hasSkill("olxuanhui", null, null, false) && !player.isTempBanned("olxuanhui") && att < 0) { - const first = get.event().getTrigger().player, - list = ["draw", "sha"]; - if (first == player || get.distance(player, first, "absolute") > dist) { - const targets = [target.storage["olfengji_" + list[0]] || 0, target.storage["olfengji_" + list[1]] || 0]; - return 1 + targets.reduce((sum, num) => sum + num, 0); - } - } - return 0; + .chooseToDiscard("he", get.prompt("zhuangshu", trigger.player), "弃置一张牌,并根据此牌的类型,按如下关系将一张宝物牌置入该角色的装备区:{<基本牌,【琼梳】>,<锦囊牌,【犀梳】>,<装备牌,【金梳】>}。", function (card) { + var type = get.type2(card); + return type == "basic" || type == "trick" || type == "equip"; }) - .set("goon", player.skipList.includes("lebu")); + .set("ai", function (card) { + var player = _status.event.player; + if (get.attitude(player, _status.event.getTrigger().player) < 4) return 0; + var name = "zhuangshu_" + get.type2(card, player); + if ( + game.hasPlayer(function (current) { + return current.getEquip(name) && get.attitude(player, current) > 0; + }) + ) + return 0; + return 7 - get.value(card); + }).logSkill = ["zhuangshu", trigger.player]; "step 1"; - if (!player.storage.olfengji_draw) player.storage.olfengji_draw = 0; if (result.bool) { - var target = result.targets[0]; - player.line(target, "thunder"); - player.storage.olfengji_draw--; - if (!target.storage.olfengji_draw) target.storage.olfengji_draw = 0; - target.storage.olfengji_draw += 2; - target.addTempSkill("olfengji_draw", "roundStart"); - target.markSkill("olfengji_draw"); - } else { - player.storage.olfengji_draw++; - } - player.addTempSkill("olfengji_draw", "roundStart"); - player.markSkill("olfengji_draw"); - "step 2"; - player.chooseTarget("丰积:请选择增加使用杀次数的目标", "令自己本轮使用杀的次数上限-1,且目标本轮使用杀的次数上限+2。或者点击「取消」,令自己本轮使用杀的次数上限+1", lib.filter.notMe).set("ai", function (target) { - var player = _status.event.player; - if (target.countMark("olfengji_draw") > 0 && target.getCardUsable("sha") < 2 && get.attitude(player, target) > 0) return get.attitude(player, target); - if (player.hasSkill("olxuanhui", null, null, false) && !player.isTempBanned("olxuanhui") && get.attitude(player, target) < 0) { - const first = get.event().getTrigger().player, - list = ["draw", "sha"]; - if (first == player || get.distance(player, first, "absolute") > get.distance(player, target, "absolute")) { - const targets = [target.storage["olfengji_" + list[0]] || 0, target.storage["olfengji_" + list[1]] || 0]; - return 1 + targets.reduce((sum, num) => sum + num, 0); + var name = "zhuangshu_" + get.type2(result.cards[0], result.cards[0].original == "h" ? player : false); + if (lib.card[name] && trigger.player.isIn && trigger.player.hasEmptySlot(5)) { + var target = game.findPlayer(function (current) { + var equip = current.getEquip(name); + return equip && equip.name == name; + }); + if (target) { + var card = target.getEquip(name); + target.$give(card, trigger.player, false); + } else { + var card = game.createCard(name, lib.card[name].cardcolor, 12); + trigger.player.$gain2(card, false); } + game.delayx(); + trigger.player.equip(card); } - return 0; - }); - "step 3"; - if (!player.storage.olfengji_sha) player.storage.olfengji_sha = 0; - if (result.bool) { - var target = result.targets[0]; - player.line(target, "fire"); - player.storage.olfengji_sha--; - if (!target.storage.olfengji_sha) target.storage.olfengji_sha = 0; - target.storage.olfengji_sha += 2; - target.addTempSkill("olfengji_sha", "roundStart"); - target.markSkill("olfengji_sha"); - } else { - player.storage.olfengji_sha++; } - player.addTempSkill("olfengji_sha", "roundStart"); - player.markSkill("olfengji_sha"); }, + group: "zhuangshu_gameStart", subSkill: { - sha: { - charlotte: true, - onremove: true, - intro: { - content: function (storage) { - return "使用【杀】的次数上限" + (storage >= 0 ? "+" : "") + storage; - }, - }, - mod: { - cardUsable: function (card, player, num) { - if (card.name == "sha") return num + player.storage.olfengji_sha; - }, - }, - }, - draw: { - charlotte: true, - onremove: true, - intro: { - content: function (storage) { - return "额定摸牌数" + (storage >= 0 ? "+" : "") + storage; - }, - }, - trigger: { player: "phaseDrawBegin2" }, - forced: true, + gameStart: { + trigger: { global: "phaseBefore" }, + direct: true, filter: function (event, player) { - return !event.numFixed; + return game.phaseNumber == 0; }, content: function () { - trigger.num += player.storage.olfengji_draw; + "step 0"; + player.chooseButton([get.prompt("zhuangshu"), [["zhuangshu_basic", "zhuangshu_trick", "zhuangshu_equip"], "vcard"]]).set("filterButton", function (button) { + return !game.hasPlayer(function (current) { + return current.getEquip(button.link[2]); + }); + }); + "step 1"; + if (result.bool) { + player.logSkill("zhuangshu"); + var name = result.links[0][2], + card = game.createCard(name, lib.card[name].cardcolor, 12); + player.$gain2(card, false); + game.delayx(); + player.equip(card); + } }, }, }, }, - olxuanhui: { + chuiti: { audio: 2, - trigger: { player: "phaseZhunbeiBegin" }, - filter(event, player) { - if (!player.hasSkill("olfengji_sha") && !player.hasSkill("olfengji_draw")) return false; - return game.hasPlayer(target => { - if (target == player) return false; - return target.hasSkill("olfengji_sha") || target.hasSkill("olfengji_draw"); - }); + usable: 1, + trigger: { + global: ["loseAfter", "loseAsyncAfter"], }, - async cost(event, trigger, player) { - event.result = await player - .chooseTarget(get.prompt("olxuanhui"), "与一名其他角色交换〖丰积〗效果", (card, player, target) => { - if (target == player) return false; - return target.hasSkill("olfengji_sha") || target.hasSkill("olfengji_draw"); - }) - .set("ai", target => { - const player = get.event().player, - list = ["draw", "sha"]; - return ( - get.sgn(get.attitude(player, target)) * - (list.reduce((sum, skill) => { - if (typeof player.storage["olfengji_" + skill] == "number") sum += player.storage["olfengji_" + skill]; - return sum; - }, 0) - - list.reduce((sum, skill) => { - if (typeof target.storage["olfengji_" + skill] == "number") sum += target.storage["olfengji_" + skill]; - return sum; - }, 0)) - ); - }) - .forResult(); + direct: true, + filter: function (event, player) { + if (event.type != "discard" || event.getlx === false) return false; + return game.hasPlayer(function (current) { + if (player != current) { + var cards = current.getEquips(5); + if (!cards.some(card => card.name.indexOf("zhuangshu_") == 0)) return false; + } + var evt = event.getl(current); + if (!evt || !evt.cards2) return false; + for (var i of evt.cards2) { + if (get.position(i, true) == "d" && player.hasUseTarget(i)) return true; + } + return false; + }); }, - async content(event, trigger, player) { - const target = event.targets[0], - list = ["draw", "sha"]; - const players = [player.storage["olfengji_" + list[0]] || 0, player.storage["olfengji_" + list[1]] || 0]; - const targets = [target.storage["olfengji_" + list[0]] || 0, target.storage["olfengji_" + list[1]] || 0]; - for (let i = 0; i <= 1; i++) { - const skill = "olfengji_" + list[i]; - if (!players[i]) target.removeSkill(skill); - else { - target.addTempSkill(skill, "roundStart"); - target.storage[skill] = players[i]; - target.markSkill(skill); + content: function () { + "step 0"; + var cards = []; + game.countPlayer(function (current) { + if (player != current) { + var cards2 = current.getEquips(5); + if (!cards2.some(card => card.name.indexOf("zhuangshu_") == 0)) return false; } - if (!targets[i]) player.removeSkill(skill); - else { - player.addTempSkill(skill, "roundStart"); - player.storage[skill] = targets[i]; - player.markSkill(skill); + var evt = trigger.getl(current); + for (var i of evt.cards2) { + if (get.position(i, true) == "d" && player.hasUseTarget(i)) cards.push(i); } - } - game.log(player, "与", target, "交换了", "#g【丰积】", "的数值"); - player.tempBanSkill("olxuanhui", "dieAfter"); + return false; + }); + player.chooseButton(["垂涕:是否使用其中的一张牌?", cards]).set("ai", function (button) { + return _status.event.player.getUseValue(button.link); + }); + "step 1"; + if (result.bool) { + player.$gain2(result.links[0], false); + game.delayx(); + player.chooseUseTarget(true, result.links[0], false).logSkill = "chuiti"; + } else player.storage.counttrigger.chuiti--; }, }, - //朱灵 - jixian: { - audio: 2, - trigger: { player: "phaseDrawAfter" }, + zhuangshu_basic: { + equipSkill: true, + trigger: { player: "damageBegin2" }, direct: true, filter: function (event, player) { - return game.hasPlayer(function (current) { - return current != player && lib.skill.jixian.getNum(player, current) > 0 && player.canUse("sha", current, false); - }); + var equip = player.getEquip("zhuangshu_basic"); + return ( + event.num <= + player.countCards("he", function (card) { + return card != equip; + }) + ); }, content: function () { "step 0"; player - .chooseTarget(get.prompt("jixian"), "视为对一名满足条件的角色使用一张【杀】", function (card, player, target) { - return target != player && lib.skill.jixian.getNum(player, target) > 0 && player.canUse("sha", target, false); + .chooseToDiscard("he", trigger.num, get.prompt("zhuangshu_basic"), "弃置" + get.cnNumber(trigger.num) + "张牌并防止伤害", function (card, player) { + return card != player.getEquip("zhuangshu_basic"); }) - .set("ai", function (target) { + .set("ai", function (card) { var player = _status.event.player; - return get.effect(target, { name: "sha" }, player, player) * Math.sqrt(lib.skill.jixian.getNum(player, target)); + return 4 + player.getUseValue(card) - get.value(card, player); }); "step 1"; - if (result.bool) { - var target = result.targets[0]; - player.logSkill("jixian", target); - var num = lib.skill.jixian.getNum(player, target); - player.useCard({ name: "sha", isCard: true }, target, false); - if (num > 0) player.draw(num); - } else event.finish(); - "step 2"; - if ( - !player.hasHistory("sourceDamage", function (evt) { - var card = evt.card; - if (!card || card.name != "sha") return false; - var evtx = evt.getParent("useCard"); - return evtx.card == card && evtx.getParent() == event; - }) - ) - player.loseHp(); + if (result.bool) trigger.cancel(); }, - getNum: function (player, target) { - var num = 0; - if (target.isHealthy()) num++; - if (target.getEquips(2).length) num++; - var countSkill = function (player) { - return player.getSkills(null, false, false).filter(function (skill) { - var info = get.info(skill); - if (!info || info.charlotte) return false; - if (info.zhuSkill) return player.hasZhuSkill(skill); - return true; - }).length; - }; - if (countSkill(player) < countSkill(target)) num++; - return num; + /*usable:1, + trigger:{player:'useCard2'}, + direct:true, + filter:function(event,player){ + if(event.targets.length!=1) return false; + if(event.card.name!='sha'&&get.type(event.card)!='trick') return false; + var info=get.info(event.card); + if(info.allowMultiple==false) return false; + if(event.targets&&!info.multitarget){ + var target=event.targets[0],hp=target.hp,hs=target.countCards('h'),card=event.card; + return game.hasPlayer(function(current){ + return current!=target&¤t!=player&&(current.hp==hp||current.countCards('h')==hs)&&lib.filter.targetEnabled2(card,player,current); + }); + } + return false; }, + content:function(){ + 'step 0' + player.chooseTarget(get.prompt('zhuangshu_basic'),'为'+get.translation(trigger.card)+'增加一个满足条件的额外目标',function(card,player,current){ + var card=_status.event.getTrigger().card,target=_status.event.target,hp=target.hp,hs=target.countCards('h'); + return current!=target&¤t!=player&&(current.hp==hp||current.countCards('h')==hs)&&lib.filter.targetEnabled2(card,player,current); + }).set('target',trigger.targets[0]).set('ai',function(target){ + var card=_status.event.getTrigger().card,player=_status.event.player; + return get.effect(target,card,player,player); + }); + 'step 1' + if(result.bool){ + if(player!=event.player&&!player.isOnline()) game.delayx(); + } + else{ + player.storage.counttrigger.zhuangshu_basic--; + event.finish(); + } + 'step 2' + var targets=result.targets; + player.logSkill('zhuangshu_basic',targets); + trigger.targets.addArray(targets); + trigger.directHit.addArray(targets); + },*/ }, - //吾彦 - lanjiang: { - audio: 2, - audioname2: { heqi: "lanjiang_heqi" }, - trigger: { player: "phaseJieshuBegin" }, + zhuangshu_trick: { + trigger: { player: ["phaseJudgeBefore"] }, + equipSkill: true, + direct: true, content: function () { "step 0"; - var ph = player.countCards("h"); - var targets = game.filterPlayer(current => current == player || current.countCards("h") >= ph).sortBySeat(); - player.line(targets, "green"); - event.targets = targets; - event.num = 0; - "step 1"; - var target = targets[num]; - event.num++; - if (target.isIn()) { - event.target = target; - target.chooseBool("是否令" + (player == target ? "自己" : get.translation(player)) + "摸一张牌?").set("ai", () => get.attitude(_status.event.player, _status.event.getParent().player) > 0); - } else { - event.goto(event.num < targets.length ? 1 : 3); - } - "step 2"; - if (result.bool) { - target.line(player); - if (player !== target && (get.mode() !== "identity" || target.identity !== "nei")) target.addExpose(0.15); - player.draw(); - } - if (num < targets.length) event.goto(1); - "step 3"; player - .chooseTarget("是否对一名手牌数等于自己的目标角色造成1点伤害?", function (card, player, target) { - return _status.event.getParent().targets.includes(target) && target.countCards("h") == player.countCards("h"); - }) - .set("ai", function (target) { + .chooseControl("判定阶段", "弃牌阶段", "cancel2") + .set("prompt", get.prompt("zhuangshu_trick")) + .set("prompt2", "跳过本回合的判定阶段或弃牌阶段") + .set("ai", function () { var player = _status.event.player; - return get.damageEffect(target, player, player); - }); - "step 4"; - if (result.bool) { - var target = result.targets[0]; - player.line(target, "green"); - if (get.mode() !== "identity" || player.identity !== "nei") player.addExpose(0.15); - target.damage(); - } else event.finish(); - "step 5"; - var ph = player.countCards("h"); - if (ph > 0 && targets.some(target => target.isIn() && target.countCards("h") < ph)) { - player - .chooseTarget( - "请选择一名手牌数小于自己的目标角色,令其摸一张牌", - function (card, player, target) { - return _status.event.getParent().targets.includes(target) && target.countCards("h") < player.countCards("h"); - }, - true + if ( + player.hasCard(function (card) { + return ( + get.effect( + player, + { + name: card.viewAs || card.name, + cards: [card], + }, + player, + player + ) < 0 + ); + }, "j") ) - .set("ai", function (target) { - var player = _status.event.player; - return get.attitude(player, target); - }); - } - "step 6"; - if (result.bool) { - var target = result.targets[0]; - player.line(target); - if (player !== target && (get.mode() !== "identity" || player.identity !== "nei")) player.addExpose(0.1); - target.draw(); + return "判定阶段"; + return "弃牌阶段"; + }); + "step 1"; + if (result.control != "cancel2") { + player.logSkill("zhuangshu_trick"); + if (result.control == "判定阶段") { + trigger.cancel(); + game.log(player, "跳过了", "#y判定阶段"); + } else { + player.skip("phaseDiscard"); + game.log(player, "跳过了", "#g弃牌阶段"); + } } }, }, - //新SP张郃 - spolzhouxuan: { - audio: 2, - trigger: { player: "phaseDiscardBegin" }, + zhuangshu_equip: { + trigger: { player: "phaseUseEnd" }, + forced: true, + equipSkill: true, filter: function (event, player) { - return player.countCards("h") > 0 && player.getExpansions("spolzhouxuan").length < 5; + return player.countCards("h") < Math.min(5, player.getHandcardLimit()); + }, + content: function () { + player.drawTo(Math.min(5, player.getHandcardLimit())); }, + }, + //杨仪 + oljuanxia: { + trigger: { player: "phaseJieshuBegin" }, direct: true, content: function () { "step 0"; - player.chooseCard("h", get.prompt("spolzhouxuan"), [1, 5 - player.getExpansions("spolzhouxuan").length], "将至多" + get.cnNumber(5 - player.getExpansions("spolzhouxuan").length) + "张手牌置于武将牌上").set("ai", function (card) { - if (ui.selected.cards.length >= player.needsToDiscard()) return 6 - get.value(card); - return 100 - get.useful(card); + player.chooseTarget(get.prompt2("oljuanxia"), lib.filter.notMe).set("ai", function (target) { + var player = _status.event.player, + list = []; + for (var name of lib.inpile) { + var info = lib.card[name]; + if (!info || info.type != "trick" || info.notarget || (info.selectTarget && info.selectTarget != 1)) continue; + if (!player.canUse(name, target, false)) continue; + var eff = get.effect(target, { name: name }, player, player); + if (eff > 0) list.push(eff); + } + list.sort().reverse(); + if (!list.length) return 0; + return list[0] + (list[1] || 0) + (list[2] || 0); }); "step 1"; if (result.bool) { - var cards = result.cards; - player.logSkill("spolzhouxuan"); - player.addToExpansion(cards, player, "give").gaintag.add("spolzhouxuan"); + var target = result.targets[0]; + event.target = target; + player.logSkill("oljuanxia", target); + } else event.finish(); + "step 2"; + var list = []; + for (var name of lib.inpile) { + var info = lib.card[name]; + if (!info || info.type != "trick" || info.notarget || (info.selectTarget && info.selectTarget != 1)) continue; + list.push(name); } - }, - marktext: "旋", - intro: { - content: "expansion", - markcount: "expansion", - }, - onremove: function (player, skill) { - var cards = player.getExpansions(skill); - if (cards.length) player.loseToDiscardpile(cards); - }, - group: ["spolzhouxuan_use", "spolzhouxuan_discard"], - subSkill: { - use: { - audio: "spolzhouxuan", - trigger: { player: "useCard" }, - filter: function (event, player) { - return player.getExpansions("spolzhouxuan").length > 0; - }, - forced: true, - locked: false, - content: function () { - "step 0"; - player.loseToDiscardpile(player.getExpansions("spolzhouxuan").randomGet()); - "step 1"; - var num = 1; - if (!player.isMaxHandcard(true)) num += player.getExpansions("spolzhouxuan").length; - player.draw(num); - }, - }, - discard: { - audio: "spolzhouxuan", - trigger: { player: "phaseUseEnd" }, - filter: function (event, player) { - return player.getExpansions("spolzhouxuan").length > 0; - }, - forced: true, - locked: false, - content: function () { - player.loseToDiscardpile(player.getExpansions("spolzhouxuan")); - }, - }, - }, - }, - //董昭 - olxianlve: { - audio: 2, - mode: ["identity"], - trigger: { - global: "phaseZhunbeiBegin", - }, - direct: true, - filter: function (event, player) { - return event.player == game.zhu && event.player.isZhu; - }, - content: function () { - "step 0"; - var list = lib.inpile - .filter(function (i) { - return get.type2(i) == "trick"; - }) - .map(function (i) { - return ["锦囊", "", i]; - }); if (!list.length) event.finish(); - else - player.chooseButton([get.prompt("olxianlve"), [list, "vcard"]]).set("ai", function (button) { - switch (button.link[2]) { - case "wuxie": - return 0.6 + Math.random(); - case "wuzhong": - case "dongzhuxianji": - return 0.5 + Math.random(); - case "guohe": - case "zhujinqiyuan": - return 0.4 + Math.random(); - default: - return Math.random(); - } + else { + event.list = list; + event.count = 0; + } + "step 3"; + var list = event.list.filter(function (name) { + return player.canUse(name, target, false); + }); + if (list.length) { + var next = player.chooseButton(["视为对" + get.translation(target) + "使用一张牌", [list, "vcard"]]).set("ai", function (button) { + let evt = _status.event.getParent(), + eff = get.effect(evt.target, { name: button.link[2] }, evt.player, evt.player); + if (evt.target.hp < 2 || get.attitude(evt.player, evt.target) > 0 || (evt.target.hp < 3 && get.tag(button.link, "damage"))) return eff; + return eff + get.effect(evt.player, { name: "sha" }, evt.target, evt.player); }); - "step 1"; + if (event.count == 0) next.set("forced", true); + } else { + event.stopped = true; + event.goto(5); + } + "step 4"; if (result.bool) { + event.count++; var name = result.links[0][2]; - player.logSkill("olxianlve"); - player.storage.olxianlve = name; - player.markSkill("olxianlve"); + event.list.remove(name); + player.useCard({ name: name, isCard: true }, target, false); + } else event.stopped = true; + "step 5"; + if (target.isIn() && event.count > 0) { + if (event.count < 3 && !event.stopped && event.list.length > 0) event.goto(3); + else { + target.addTempSkill("oljuanxia_counter", { player: "phaseAfter" }); + if (!target.storage.oljuanxia_counter) target.storage.oljuanxia_counter = {}; + if (!target.storage.oljuanxia_counter[player.playerid]) target.storage.oljuanxia_counter[player.playerid] = 0; + target.storage.oljuanxia_counter[player.playerid] += event.count; + } } }, - intro: { - content: function (name, player) { - return "已声明" + (player.isUnderControl(true) ? "【" + get.translation(name) + "】" : "一个牌名"); - }, - }, - group: ["olxianlve_use", "olxianlve_count"], subSkill: { - count: { - trigger: { global: "useCard1" }, - silent: true, - forced: true, - popup: false, - firstDo: true, - filter: function (event, player) { - return event.player != player && event.card.name == player.storage.olxianlve; - }, - content: function () { - if (!trigger.olxianlve_map) trigger.olxianlve_map = {}; - trigger.olxianlve_map[player.playerid] = true; - }, - }, - use: { - audio: "olxianlve", - trigger: { global: "useCardAfter" }, - forced: true, - locked: false, - usable: 1, - filter: function (event, player) { - return event.player != player && event.olxianlve_map && event.olxianlve_map[player.playerid] && event.card.name == player.storage.olxianlve; - }, - content: function () { - "step 0"; - player.draw(2); - "step 1"; - var cards = result; - if (get.itemtype(cards) != "cards") { - event.goto(5); - return; - } - var hs = player.getCards("h"); - cards = cards.filter(function (card) { - return hs.includes(card); - }); - if (!cards.length) { - event.goto(5); - return; - } - event.cards = cards; - if (_status.connectMode) - game.broadcastAll(function () { - _status.noclearcountdown = true; - }); - event.given_map = {}; - event.ai_list = []; - "step 2"; - player.chooseCardTarget({ - filterCard: function (card) { - return _status.event.cards.includes(card) && !card.hasGaintag("olxianlve"); - }, - cards: cards, - filterTarget: lib.filter.notMe, - selectCard: [1, cards.length], - prompt: "是否将得到的牌分配给其他角色?", - ai1: function (card) { - if (!ui.selected.cards.length) return 1; - return 0; - }, - ai2: function (target) { - var player = _status.event.player, - card = ui.selected.cards[0]; - var val = target.getUseValue(card); - if (target.isPhaseUsing() && get.type2(card) == "trick") val *= 3; - if (val > 0) return val * get.attitude(player, target) * 2; - return get.value(card, target) * get.attitude(player, target); - }, - }); - "step 3"; - if (result.bool) { - var res = result.cards, - target = result.targets[0].playerid; - player.addGaintag(res, "olxianlve"); - cards.removeArray(res); - if (!event.given_map[target]) event.given_map[target] = []; - event.given_map[target].addArray(res); - if (result.targets[0].isPhaseUsing() && get.type2(res[0]) == "trick") event.ai_list.push(res[0].name); - if (cards.length) event.goto(2); + counter: { + trigger: { player: "phaseEnd" }, + forced: true, + charlotte: true, + onremove: true, + filter: function (event, player) { + var map1 = _status.connectMode ? lib.playerOL : game.playerMap, + map2 = player.storage.oljuanxia_counter; + if (!map2) return false; + for (var i in map2) { + if (map1[i] && map1[i].isIn() && player.canUse("sha", map1[i], false)) return true; } - "step 4"; - if (_status.connectMode) { - game.broadcastAll(function () { - delete _status.noclearcountdown; - game.stopCountChoose(); - }); + return false; + }, + logTarget: function (event, player) { + var list = []; + var map1 = _status.connectMode ? lib.playerOL : game.playerMap, + map2 = player.storage.oljuanxia_counter; + if (!map2) return false; + for (var i in map2) { + if (map1[i] && map1[i].isIn()) list.push(map1[i]); } - var map = [], - cards = []; - for (var i in event.given_map) { - var source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; - player.line(source, "green"); - map.push([source, event.given_map[i]]); - cards.addArray(event.given_map[i]); + return list; + }, + content: function () { + "step 0"; + var list = []; + var map1 = _status.connectMode ? lib.playerOL : game.playerMap, + map2 = player.storage.oljuanxia_counter; + if (!map2) return false; + for (var i in map2) { + if (map1[i] && map1[i].isIn()) list.push(map1[i]); } - if (map.length) - game.loseAsync({ - gain_list: map, - player: player, - cards: cards, - giver: player, - animate: "giveAuto", - }).setContent("gaincardMultiple"); - "step 5"; - var list = lib.inpile - .filter(function (i) { - return get.type2(i) == "trick"; - }) - .map(function (i) { - return ["锦囊", "", i]; - }); - if (!list.length) event.finish(); - else + list.sortBySeat(); + event.num = 0; + event.targets = list; + "step 1"; + var target = targets[num]; + event.target = target; + if (target.isIn() && player.canUse("sha", target, false)) player - .chooseButton([get.prompt("olxianlve"), [list, "vcard"]]) - .set("list", event.ai_list) - .set("ai", function (button) { - if (_status.event.list.includes(button.link[2])) return 2 + Math.random(); - switch (button.link[2]) { - case "wuxie": - return 0.6 + Math.random(); - case "wuzhong": - case "dongzhuxianji": - return 0.5 + Math.random(); - case "guohe": - case "zhujinqiyuan": - return 0.4 + Math.random(); - default: - return Math.random(); - } - }); - "step 6"; - if (result.bool) { - var name = result.links[0][2]; - player.storage.olxianlve = name; - player.markSkill("olxianlve"); - } + .chooseBool("狷狭:是否视为对" + get.translation(target) + "依次使用" + get.cnNumber(player.storage.oljuanxia_counter[target.playerid]) + "张【杀】?") + .set("goon", get.effect(target, { name: "sha" }, player, player) > 0) + .set("ai", () => _status.event.goon); + "step 2"; + event.num++; + if (result.bool) event.count = player.storage.oljuanxia_counter[target.playerid]; + else if (event.num < targets.length) event.goto(1); + else event.finish(); + "step 3"; + event.count--; + if (target.isIn() && player.canUse("sha", target, false)) player.useCard({ name: "sha", isCard: true }, target, false); + if (event.count > 0) event.redo(); + else if (event.num < targets.length) event.goto(1); }, }, }, }, - olzaowang: { - mode: ["identity"], - available: function (mode) { - if (mode == "identity" && _status.mode == "purple") return false; + oldingcuo: { + trigger: { + player: "damageEnd", + source: "damageSource", }, - audio: 2, - enable: "phaseUse", - limited: true, - skillAnimation: true, - animationColor: "water", - filterTarget: true, + usable: 1, content: function () { - player.awakenSkill("olzaowang"); - target.gainMaxHp(); - target.recover(); - target.draw(3); - target.addSkills("olzaowang2"); - }, - ai: { - order: 2, - result: { - target: function (player, target) { - if (player.hasUnknown(2)) return 0; - if (target.identity == "zhong") return 20; - if (target.identity == "zhu") return 10; - if (target.identity == "nei") return 5; - if (!target.hasFriend()) return 5; - return 0; - }, - }, + "step 0"; + player.draw(2); + "step 1"; + if (Array.isArray(result) && result.length > 1) { + var color = get.color(result[0], player); + for (var i = 1; i < result.length; i++) { + if (get.color(result[i], player) != color) { + if (player.countCards("h")) player.chooseToDiscard("h", true); + break; + } + } + } }, }, - olzaowang2: { - charlotte: true, - trigger: { global: "dieBegin" }, - forced: true, + //左棻 + zhaosong: { + trigger: { global: "phaseDrawAfter" }, + logTarget: "player", filter: function (event, player) { - return event.player.identity == "zhu" && (player.identity == "zhong" || player.identity == "mingzhong"); + if (player == event.player || !event.player.countCards("h")) return false; + var types = ["basic", "trick", "equip"]; + for (var i of types) { + if (event.player.hasMark("zhaosong_" + i)) return false; + } + return true; + }, + prompt2: "令其交给你一张手牌,并根据类型获得对应的标记", + check: function (event, player) { + return get.attitude(_status.event.player, event.player) > 0; }, - logTarget: "player", - skillAnimation: true, - animationColor: "orange", content: function () { - game.broadcastAll( - function (player, target) { - target.identity = player.identity; - if (player.identity == "mingzhong") game.zhong = target; - delete target.isZhu; - player.identity = "zhu"; - game.zhu = player; - player.showIdentity(); - target.showIdentity(); + "step 0"; + event.target = trigger.player; + event.target.chooseCard("h", true, get.translation(player) + "发动了【诏颂】;请交给其一张手牌"); + "step 1"; + if (result.bool) { + var card = result.cards[0]; + target.give(card, player, "give"); + var type = get.type2(card, target); + if (lib.skill["zhaosong_" + type]) { + target.addSkill("zhaosong_" + type); + target.addMark("zhaosong_" + type); + } + } + }, + subSkill: { + basic: { + marktext: "颂", + intro: { + name: "诏颂(颂)", + name2: "颂", + content: "当你使用【杀】选择唯一目标时,你可移去“颂”,并为此【杀】增加至多两个目标。", + }, + trigger: { player: "useCard2" }, + direct: true, + charlotte: true, + onremove: true, + filter: function (event, player) { + return ( + player.hasMark("zhaosong_basic") && + event.card.name == "sha" && + event.targets.length == 1 && + game.hasPlayer(function (current) { + return current != player && current != event.targets[0] && lib.filter.targetEnabled2(event.card, player, current); + }) + ); + }, + content: function () { + "step 0"; + player + .chooseTarget([1, 2], "是否弃置“颂”标记?", "为" + get.translation(trigger.card) + "增加至多两个目标", function (card, player, target) { + var evt = _status.event.getTrigger(); + return target != player && target != evt.targets[0] && lib.filter.targetEnabled2(evt.card, player, target); + }) + .set("ai", function (target) { + var evt = _status.event.getTrigger(); + return get.effect(target, evt.card, evt.player, evt.player); + }); + "step 1"; + if (result.bool) { + if (player != event.player && !player.isOnline()) game.delayx(); + //player.addTempSkill('zhaosong_shaloss'); + } else event.finish(); + "step 2"; + var targets = result.targets; + player.logSkill("zhaosong_basic", targets); + player.removeMark("zhaosong_basic", 1); + player.removeSkill("zhaosong_basic"); + trigger.targets.addArray(targets); + trigger.zhaosong_basic = true; + }, + } /* + shaloss:{ + trigger:{player:'useCardAfter'}, + forced:true, + charlotte:true, + filter:function(event,player){ + if(!event.zhaosong_basic) return false; + var num=0; + player.getHistory('sourceDamage',function(evt){ + if(evt.card==event.card) num+=evt.num; + }); + return num<2; + }, + content:function(){ + player.loseHp(); + }, + },*/, + trick: { + marktext: "诔", + intro: { + name: "诏颂(诔)", + name2: "诔", + content: "当你进入濒死状态时,你可移去“诔”,然后将体力回复至1点并摸一张牌。", }, - player, - trigger.player - ); - event.trigger("zhuUpdate"); - }, - mark: true, - marktext: "王", - intro: { content: "造了个王" }, - group: "olzaowang2_kill", - subSkill: { - kill: { - trigger: { player: "die" }, - forced: true, - forceDie: true, - skillAnimation: true, - animationColor: "wood", + trigger: { player: "dying" }, + prompt: "是否弃置“诔”标记?", + prompt2: "回复体力至1点并摸一张牌。", + charlotte: true, + onremove: true, filter: function (event, player) { - return player.identity == "fan" && event.source && (event.source.identity == "zhu" || event.source.identity == "zhong" || event.source.identity == "mingzhong"); + return player.hasMark("zhaosong_trick") && player.hp < 1; + }, + check: function (event, player) { + if ( + player.maxHp < 2 || + player.countCards("h", function (card) { + var mod2 = game.checkMod(card, player, "unchanged", "cardEnabled2", player); + if (mod2 != "unchanged") return mod2; + var mod = game.checkMod(card, player, event.player, "unchanged", "cardSavable", player); + if (mod != "unchanged") return mod; + var savable = get.info(card).savable; + if (typeof savable == "function") savable = savable(card, player, event.player); + return savable; + }) >= + 1 + event.num - event.player.hp + ) + return false; + return true; }, content: function () { - game.over(game.me.identity == "zhu" || game.me.identity == "zhong" || game.me.identity == "mingzhong"); + player.removeMark("zhaosong_trick", 1); + player.removeSkill("zhaosong_trick"); + //player.loseMaxHp(); + if (player.hp < 1) player.recover(1 - player.hp); + player.draw(); }, }, - }, - }, - //冯方女 - zhuangshu: { - audio: 2, - trigger: { global: "phaseBegin" }, - direct: true, - filter: function (event, player) { - return event.player.isIn() && event.player.hasEmptySlot(5) && player.hasCard(lib.skill.zhuangshu.filterCard, "he"); - }, - filterCard: function (card) { - if (_status.connectMode) return true; - var type = get.type2(card); - return type == "basic" || type == "trick" || type == "equip"; - }, - content: function () { - "step 0"; - player - .chooseToDiscard("he", get.prompt("zhuangshu", trigger.player), "弃置一张牌,并根据此牌的类型,按如下关系将一张宝物牌置入该角色的装备区:{<基本牌,【琼梳】>,<锦囊牌,【犀梳】>,<装备牌,【金梳】>}。", function (card) { - var type = get.type2(card); - return type == "basic" || type == "trick" || type == "equip"; - }) - .set("ai", function (card) { - var player = _status.event.player; - if (get.attitude(player, _status.event.getTrigger().player) < 4) return 0; - var name = "zhuangshu_" + get.type2(card, player); - if ( - game.hasPlayer(function (current) { - return current.getEquip(name) && get.attitude(player, current) > 0; - }) - ) - return 0; - return 7 - get.value(card); - }).logSkill = ["zhuangshu", trigger.player]; - "step 1"; - if (result.bool) { - var name = "zhuangshu_" + get.type2(result.cards[0], result.cards[0].original == "h" ? player : false); - if (lib.card[name] && trigger.player.isIn && trigger.player.hasEmptySlot(5)) { - var target = game.findPlayer(function (current) { - var equip = current.getEquip(name); - return equip && equip.name == name; - }); - if (target) { - var card = target.getEquip(name); - target.$give(card, trigger.player, false); - } else { - var card = game.createCard(name, lib.card[name].cardcolor, 12); - trigger.player.$gain2(card, false); - } - game.delayx(); - trigger.player.equip(card); - } - } - }, - group: "zhuangshu_gameStart", - subSkill: { - gameStart: { - trigger: { global: "phaseBefore" }, + equip: { + marktext: "赋", + intro: { + name: "诏颂(赋)", + name2: "赋", + content: "出牌阶段开始时,你可移去“赋”并弃置一名角色区域内的至多两张牌。", + }, + trigger: { player: "phaseUseBegin" }, direct: true, + charlotte: true, + onremove: true, filter: function (event, player) { - return game.phaseNumber == 0; + return ( + player.hasMark("zhaosong_equip") && + game.hasPlayer(function (current) { + return current.hasCard(function (card) { + return lib.filter.canBeDiscarded(card, player, current); + }, "hej"); + }) + ); }, content: function () { "step 0"; - player.chooseButton([get.prompt("zhuangshu"), [["zhuangshu_basic", "zhuangshu_trick", "zhuangshu_equip"], "vcard"]]).set("filterButton", function (button) { - return !game.hasPlayer(function (current) { - return current.getEquip(button.link[2]); + player + .chooseTarget("是否弃置“赋”标记?", "弃置一名角色区域内的至多两张牌", function (card, player, current) { + return current.hasCard(function (card) { + return lib.filter.canBeDiscarded(card, player, current); + }, "hej"); + }) + .set("ai", function (target) { + var player = _status.event.player, + att = get.attitude(player, target) > 0 ? 2 : 1; + return get.effect(target, { name: "guohe_copy" }, player, player) * att; }); - }); "step 1"; if (result.bool) { - player.logSkill("zhuangshu"); - var name = result.links[0][2], - card = game.createCard(name, lib.card[name].cardcolor, 12); - player.$gain2(card, false); - game.delayx(); - player.equip(card); + var target = result.targets[0]; + event.target = target; + player.logSkill("zhaosong_equip", target); + player.removeMark("zhaosong_equip", 1); + player.removeSkill("zhaosong_equip"); + player.discardPlayerCard(target, true, "hej", [1, 2]); } }, }, }, }, - chuiti: { + lisi: { audio: 2, - usable: 1, - trigger: { - global: ["loseAfter", "loseAsyncAfter"], - }, + trigger: { player: "useCardAfter" }, direct: true, filter: function (event, player) { - if (event.type != "discard" || event.getlx === false) return false; + if (player == _status.currentPhase || !event.cards.filterInD().length) return false; + var hs = player.countCards("h"); return game.hasPlayer(function (current) { - if (player != current) { - var cards = current.getEquips(5); - if (!cards.some(card => card.name.indexOf("zhuangshu_") == 0)) return false; - } - var evt = event.getl(current); - if (!evt || !evt.cards2) return false; - for (var i of evt.cards2) { - if (get.position(i, true) == "d" && player.hasUseTarget(i)) return true; - } - return false; + return current != player && current.countCards("h") <= hs; }); }, content: function () { "step 0"; - var cards = []; - game.countPlayer(function (current) { - if (player != current) { - var cards2 = current.getEquips(5); - if (!cards2.some(card => card.name.indexOf("zhuangshu_") == 0)) return false; - } - var evt = trigger.getl(current); - for (var i of evt.cards2) { - if (get.position(i, true) == "d" && player.hasUseTarget(i)) cards.push(i); - } - return false; - }); - player.chooseButton(["垂涕:是否使用其中的一张牌?", cards]).set("ai", function (button) { - return _status.event.player.getUseValue(button.link); + player.chooseTarget(get.prompt("lisi"), "将" + get.translation(trigger.cards.filterInD()) + "交给一名手牌数不大于你的其他角色", function (card, player, target) { + return target != player && target.countCards("h") <= player.countCards("h"); }); "step 1"; - if (result.bool) { - player.$gain2(result.links[0], false); - game.delayx(); - player.chooseUseTarget(true, result.links[0], false).logSkill = "chuiti"; - } else player.storage.counttrigger.chuiti--; - }, - }, - zhuangshu_basic: { - equipSkill: true, - trigger: { player: "damageBegin2" }, - direct: true, - filter: function (event, player) { - var equip = player.getEquip("zhuangshu_basic"); - return ( - event.num <= - player.countCards("he", function (card) { - return card != equip; - }) - ); - }, - content: function () { - "step 0"; - player - .chooseToDiscard("he", trigger.num, get.prompt("zhuangshu_basic"), "弃置" + get.cnNumber(trigger.num) + "张牌并防止伤害", function (card, player) { - return card != player.getEquip("zhuangshu_basic"); - }) - .set("ai", function (card) { - var player = _status.event.player; - return 4 + player.getUseValue(card) - get.value(card, player); - }); - "step 1"; - if (result.bool) trigger.cancel(); - }, - /*usable:1, - trigger:{player:'useCard2'}, - direct:true, - filter:function(event,player){ - if(event.targets.length!=1) return false; - if(event.card.name!='sha'&&get.type(event.card)!='trick') return false; - var info=get.info(event.card); - if(info.allowMultiple==false) return false; - if(event.targets&&!info.multitarget){ - var target=event.targets[0],hp=target.hp,hs=target.countCards('h'),card=event.card; - return game.hasPlayer(function(current){ - return current!=target&¤t!=player&&(current.hp==hp||current.countCards('h')==hs)&&lib.filter.targetEnabled2(card,player,current); - }); - } - return false; - }, - content:function(){ - 'step 0' - player.chooseTarget(get.prompt('zhuangshu_basic'),'为'+get.translation(trigger.card)+'增加一个满足条件的额外目标',function(card,player,current){ - var card=_status.event.getTrigger().card,target=_status.event.target,hp=target.hp,hs=target.countCards('h'); - return current!=target&¤t!=player&&(current.hp==hp||current.countCards('h')==hs)&&lib.filter.targetEnabled2(card,player,current); - }).set('target',trigger.targets[0]).set('ai',function(target){ - var card=_status.event.getTrigger().card,player=_status.event.player; - return get.effect(target,card,player,player); - }); - 'step 1' - if(result.bool){ - if(player!=event.player&&!player.isOnline()) game.delayx(); - } - else{ - player.storage.counttrigger.zhuangshu_basic--; - event.finish(); + if (result.bool) { + var target = result.targets[0]; + player.logSkill("lisi", target); + target.gain(trigger.cards.filterInD(), "gain2"); } - 'step 2' - var targets=result.targets; - player.logSkill('zhuangshu_basic',targets); - trigger.targets.addArray(targets); - trigger.directHit.addArray(targets); - },*/ + }, }, - zhuangshu_trick: { - trigger: { player: ["phaseJudgeBefore"] }, - equipSkill: true, + //王荣 + olfengzi: { + audio: 2, + trigger: { player: "useCard" }, direct: true, + usable: 1, + filter: function (event, player) { + if (event.olfengzi_buff || !event.targets.length || !player.isPhaseUsing() || player.hasSkill("olfengzi_buff")) return false; + var type = get.type(event.card, null, false); + if (type != "basic" && type != "trick") return false; + return player.hasCard(function (i) { + if (_status.connectMode) return true; + return get.type2(i, player) == type; + }, "h"); + }, content: function () { "step 0"; + if (player != game.me && !player.isUnderControl() && !player.isOnline()) game.delayx(); + var type = get.type(trigger.card, null, false); player - .chooseControl("判定阶段", "弃牌阶段", "cancel2") - .set("prompt", get.prompt("zhuangshu_trick")) - .set("prompt2", "跳过本回合的判定阶段或弃牌阶段") - .set("ai", function () { + .chooseToDiscard("h", get.prompt("olfengzi"), "弃置一张" + get.translation(type) + "牌,令" + get.translation(trigger.card) + "结算两次", function (card, player) { + return get.type2(card, player) == _status.event.type; + }) + .set("type", type) + .set("ai", function (card) { var player = _status.event.player; - if ( - player.hasCard(function (card) { - return ( - get.effect( - player, - { - name: card.viewAs || card.name, - cards: [card], - }, - player, - player - ) < 0 - ); - }, "j") - ) - return "判定阶段"; - return "弃牌阶段"; - }); + var trigger = _status.event.getTrigger(); + if (trigger.card.name == "tiesuo") return 0; + var num = 0; + for (var i of trigger.targets) num += get.effect(i, trigger.card, player, player); + if (num <= 0) return 0; + return 7 - get.value(card); + }).logSkill = "olfengzi"; "step 1"; - if (result.control != "cancel2") { - player.logSkill("zhuangshu_trick"); - if (result.control == "判定阶段") { - trigger.cancel(); - game.log(player, "跳过了", "#y判定阶段"); - } else { - player.skip("phaseDiscard"); - game.log(player, "跳过了", "#g弃牌阶段"); - } - } + if (result.bool) { + trigger.effectCount++; + } else player.storage.counttrigger.olfengzi--; }, + /*subSkill:{ + buff:{ + trigger:{global:'useCardToTargeted'}, + forced:true, + charlotte:true, + popup:false, + lastDo:true, + filter:function(event,player){ + return (event.parent.olfengzi_buff==player&&event.targets.length==event.parent.triggeredTargets4.length); + }, + content:function(){ + trigger.getParent().targets=trigger.getParent().targets.concat(trigger.targets); + trigger.getParent().triggeredTargets4=trigger.getParent().triggeredTargets4.concat(trigger.targets); + }, + onremove:function(player){ + delete player.storage.counttrigger.olfengji; + }, + }, + },*/ }, - zhuangshu_equip: { - trigger: { player: "phaseUseEnd" }, - forced: true, - equipSkill: true, + oljizhan: { + audio: 2, + trigger: { player: "phaseDrawBegin1" }, filter: function (event, player) { - return player.countCards("h") < Math.min(5, player.getHandcardLimit()); - }, - content: function () { - player.drawTo(Math.min(5, player.getHandcardLimit())); + return !event.numFixed; }, - }, - //杨仪 - oljuanxia: { - trigger: { player: "phaseJieshuBegin" }, - direct: true, content: function () { "step 0"; - player.chooseTarget(get.prompt2("oljuanxia"), lib.filter.notMe).set("ai", function (target) { - var player = _status.event.player, - list = []; - for (var name of lib.inpile) { - var info = lib.card[name]; - if (!info || info.type != "trick" || info.notarget || (info.selectTarget && info.selectTarget != 1)) continue; - if (!player.canUse(name, target, false)) continue; - var eff = get.effect(target, { name: name }, player, player); - if (eff > 0) list.push(eff); - } - list.sort().reverse(); - if (!list.length) return 0; - return list[0] + (list[1] || 0) + (list[2] || 0); - }); + trigger.changeToZero(); + var card = get.cards()[0]; + game.cardsGotoOrdering(card); + event.cards = [card]; + event.num = get.number(card, false); + player.showCards(card, get.translation(player) + "发动了【吉占】"); "step 1"; - if (result.bool) { - var target = result.targets[0]; - event.target = target; - player.logSkill("oljuanxia", target); - } else event.finish(); + var str = get.strNumber(num); + player + .chooseControl("大于" + str, "小于" + str, "cancel2") + .set("prompt", "吉占:猜测下一张牌的点数") + .set("choice", num < 7 ? 0 : 1) + .set("ai", () => _status.event.choice); "step 2"; - var list = []; - for (var name of lib.inpile) { - var info = lib.card[name]; - if (!info || info.type != "trick" || info.notarget || (info.selectTarget && info.selectTarget != 1)) continue; - list.push(name); - } - if (!list.length) event.finish(); - else { - event.list = list; - event.count = 0; + var card = get.cards()[0]; + game.cardsGotoOrdering(card); + event.cards.push(card); + var num = get.number(card, false); + if ((num > event.num && result.index == 0) || (num < event.num && result.index == 1)) { + event.num = num; + event.goto(1); } + player.showCards(card); "step 3"; - var list = event.list.filter(function (name) { - return player.canUse(name, target, false); - }); - if (list.length) { - var next = player.chooseButton(["视为对" + get.translation(target) + "使用一张牌", [list, "vcard"]]).set("ai", function (button) { - var evt = _status.event.getParent(); - return get.effect(evt.target, { name: button.link[2] }, evt.player, evt.player); - }); - if (event.count == 0) next.set("forced", true); - } else { - event.stopped = true; - event.goto(5); - } - "step 4"; - if (result.bool) { - event.count++; - var name = result.links[0][2]; - event.list.remove(name); - player.useCard({ name: name, isCard: true }, target, false); - } else event.stopped = true; - "step 5"; - if (target.isIn() && event.count > 0) { - if (event.count < 3 && !event.stopped && event.list.length > 0) event.goto(3); - else { - target.addTempSkill("oljuanxia_counter", { player: "phaseAfter" }); - if (!target.storage.oljuanxia_counter) target.storage.oljuanxia_counter = {}; - if (!target.storage.oljuanxia_counter[player.playerid]) target.storage.oljuanxia_counter[player.playerid] = 0; - target.storage.oljuanxia_counter[player.playerid] += event.count; - } - } - }, - subSkill: { - counter: { - trigger: { player: "phaseEnd" }, - forced: true, - charlotte: true, - onremove: true, - filter: function (event, player) { - var map1 = _status.connectMode ? lib.playerOL : game.playerMap, - map2 = player.storage.oljuanxia_counter; - if (!map2) return false; - for (var i in map2) { - if (map1[i] && map1[i].isIn() && player.canUse("sha", map1[i], false)) return true; - } - return false; - }, - logTarget: function (event, player) { - var list = []; - var map1 = _status.connectMode ? lib.playerOL : game.playerMap, - map2 = player.storage.oljuanxia_counter; - if (!map2) return false; - for (var i in map2) { - if (map1[i] && map1[i].isIn()) list.push(map1[i]); - } - return list; - }, - content: function () { - "step 0"; - var list = []; - var map1 = _status.connectMode ? lib.playerOL : game.playerMap, - map2 = player.storage.oljuanxia_counter; - if (!map2) return false; - for (var i in map2) { - if (map1[i] && map1[i].isIn()) list.push(map1[i]); - } - list.sortBySeat(); - event.num = 0; - event.targets = list; - "step 1"; - var target = targets[num]; - event.target = target; - if (target.isIn() && player.canUse("sha", target, false)) - player - .chooseBool("狷狭:是否视为对" + get.translation(target) + "依次使用" + get.cnNumber(player.storage.oljuanxia_counter[target.playerid]) + "张【杀】?") - .set("goon", get.effect(target, { name: "sha" }, player, player) > 0) - .set("ai", () => _status.event.goon); - "step 2"; - event.num++; - if (result.bool) event.count = player.storage.oljuanxia_counter[target.playerid]; - else if (event.num < targets.length) event.goto(1); - else event.finish(); - "step 3"; - event.count--; - if (target.isIn() && player.canUse("sha", target, false)) player.useCard({ name: "sha", isCard: true }, target, false); - if (event.count > 0) event.redo(); - else if (event.num < targets.length) event.goto(1); - }, - }, + player.gain(cards, "gain2"); }, }, - oldingcuo: { - trigger: { - player: "damageEnd", - source: "damageSource", + olfusong: { + audio: 2, + forceDie: true, + trigger: { player: "die" }, + skillAnimation: true, + animationColor: "gray", + direct: true, + filter: function (event, player) { + return game.hasPlayer(function (current) { + return current.maxHp > player.maxHp; + }); }, - usable: 1, content: function () { "step 0"; - player.draw(2); + player + .chooseTarget(get.prompt("olfusong"), "令一名体力上限大于你的其他角色获得〖丰姿〗或〖吉占〗", function (card, player, target) { + return target.maxHp > player.maxHp; + }) + .set("forceDie", true) + .set("ai", target => get.attitude(_status.event.player, target)); "step 1"; - if (Array.isArray(result) && result.length > 1) { - var color = get.color(result[0], player); - for (var i = 1; i < result.length; i++) { - if (get.color(result[i], player) != color) { - if (player.countCards("h")) player.chooseToDiscard("h", true); - break; - } - } - } + if (result.bool) { + var target = result.targets[0]; + event.target = target; + player.logSkill("olfusong", target); + target + .chooseControl("olfengzi", "oljizhan") + .set("prompt", "令" + get.translation(target) + "获得其中一个技能") + .set("ai", () => (Math.random() > 0.5 ? 0 : 1)); + } else event.finish(); + "step 2"; + target.addSkills(result.control); }, }, - //左棻 - zhaosong: { - trigger: { global: "phaseDrawAfter" }, - logTarget: "player", + //邓芝 + olxiuhao: { + audio: 2, + trigger: { global: "damageBegin4" }, + usable: 1, filter: function (event, player) { - if (player == event.player || !event.player.countCards("h")) return false; - var types = ["basic", "trick", "equip"]; - for (var i of types) { - if (event.player.hasMark("zhaosong_" + i)) return false; - } - return true; + return event.source && event.source.isIn() && [event.source, event.player].includes(player) && event.source != event.player; + }, + logTarget: function (event, player) { + return player == event.player ? event.source : event.player; }, - prompt2: "令其交给你一张手牌,并根据类型获得对应的标记", check: function (event, player) { - return get.attitude(_status.event.player, event.player) > 0; + _status.olxiuhao_judging = true; + var bool = false; + if (get.attitude(player, event.player) > 0) bool = true; + else if (2 * get.effect(event.source, { name: "draw" }, player, _status.event.player) + event.num * get.damageEffect(player, event.source, _status.event.player, event.nature) > 0) bool = true; + else if (event.source.hasSkillTag("nogain")) bool = true; + delete _status.olxiuhao_judging; + return bool; }, content: function () { - "step 0"; - event.target = trigger.player; - event.target.chooseCard("h", true, get.translation(player) + "发动了【诏颂】;请交给其一张手牌"); - "step 1"; - if (result.bool) { - var card = result.cards[0]; - target.give(card, player, "give"); - var type = get.type2(card, target); - if (lib.skill["zhaosong_" + type]) { - target.addSkill("zhaosong_" + type); - target.addMark("zhaosong_" + type); - } - } + trigger.cancel(); + trigger.source.draw(2); }, - subSkill: { - basic: { - marktext: "颂", - intro: { - name: "诏颂(颂)", - name2: "颂", - content: "当你使用【杀】选择唯一目标时,你可移去“颂”,并为此【杀】增加至多两个目标。", - }, - trigger: { player: "useCard2" }, - direct: true, - charlotte: true, - onremove: true, - filter: function (event, player) { - return ( - player.hasMark("zhaosong_basic") && - event.card.name == "sha" && - event.targets.length == 1 && - game.hasPlayer(function (current) { - return current != player && current != event.targets[0] && lib.filter.targetEnabled2(event.card, player, current); - }) - ); + ai: { + effect: { + target: function (card, player, target) { + if (!_status.olxiuhao_judging && get.tag(card, "damage") && get.attitude(target, player) > 0 && player != target && (!target.storage.counttrigger || !target.storage.counttrigger.olxiuhao)) return [0, 0.5, 0, 0.5]; }, - content: function () { - "step 0"; - player - .chooseTarget([1, 2], "是否弃置“颂”标记?", "为" + get.translation(trigger.card) + "增加至多两个目标", function (card, player, target) { - var evt = _status.event.getTrigger(); - return target != player && target != evt.targets[0] && lib.filter.targetEnabled2(evt.card, player, target); - }) - .set("ai", function (target) { - var evt = _status.event.getTrigger(); - return get.effect(target, evt.card, evt.player, evt.player); - }); - "step 1"; - if (result.bool) { - if (player != event.player && !player.isOnline()) game.delayx(); - //player.addTempSkill('zhaosong_shaloss'); - } else event.finish(); - "step 2"; - var targets = result.targets; - player.logSkill("zhaosong_basic", targets); - player.removeMark("zhaosong_basic", 1); - player.removeSkill("zhaosong_basic"); - trigger.targets.addArray(targets); - trigger.zhaosong_basic = true; + player: function (card, player, target) { + if (!_status.olxiuhao_judging && get.tag(card, "damage") && get.attitude(player, target) > 0 && player != target && (!player.storage.counttrigger || !player.storage.counttrigger.olxiuhao)) return [0, 0.5, 0, 0.5]; }, - } /* - shaloss:{ - trigger:{player:'useCardAfter'}, - forced:true, - charlotte:true, - filter:function(event,player){ - if(!event.zhaosong_basic) return false; - var num=0; - player.getHistory('sourceDamage',function(evt){ - if(evt.card==event.card) num+=evt.num; + }, + }, + }, + olsujian: { + trigger: { player: "phaseDiscardBefore" }, + forced: true, + content: function () { + trigger.setContent(lib.skill.olsujian.phaseDiscard); + }, + phaseDiscard: function () { + "step 0"; + game.log(player, "进入了弃牌阶段"); + game.broadcastAll(function (player) { + if (lib.config.show_phase_prompt) { + player.popup("弃牌阶段", null, false); + } + }, player); + event.trigger("phaseDiscard"); + "step 1"; + var cards = lib.skill.olsujian.update(player); + if (!cards.length) event.finish(); + else { + event.cards = cards; + var str = get.translation(cards); + player + .chooseControl() + .set("choiceList", ["将" + str + "分配给任意名其他角色", "弃置" + str + "并弃置一名其他角色至多等量的牌"]) + .set("ai", function () { + var cards = _status.event.getParent().cards, + player = _status.event.player; + if ( + !game.hasPlayer(function (current) { + return player !== current && get.attitude(player, current) > 0; + }) + ) + return 1; + if ( + game.hasPlayer(function (current) { + var att = get.attitude(player, current); + return ( + att && + current.countDiscardableCards(player, "he", function (i) { + if (att > 0) return get.value(i, current) < 0; + return get.value(i, current) >= 4; + }) >= cards.length && + get.effect(current, { name: "guohe_copy2" }, player, player) > 0 + ); + }) + ) + return 1; + return 0; }); - return num<2; - }, - content:function(){ - player.loseHp(); - }, - },*/, - trick: { - marktext: "诔", - intro: { - name: "诏颂(诔)", - name2: "诔", - content: "当你进入濒死状态时,你可移去“诔”,然后将体力回复至1点并摸一张牌。", - }, - trigger: { player: "dying" }, - prompt: "是否弃置“诔”标记?", - prompt2: "回复体力至1点并摸一张牌。", - charlotte: true, - onremove: true, - filter: function (event, player) { - return player.hasMark("zhaosong_trick") && player.hp < 1; - }, - check: function (event, player) { - if ( - player.maxHp < 2 || - player.countCards("h", function (card) { - var mod2 = game.checkMod(card, player, "unchanged", "cardEnabled2", player); - if (mod2 != "unchanged") return mod2; - var mod = game.checkMod(card, player, event.player, "unchanged", "cardSavable", player); - if (mod != "unchanged") return mod; - var savable = get.info(card).savable; - if (typeof savable == "function") savable = savable(card, player, event.player); - return savable; - }) >= - 1 + event.num - event.player.hp - ) - return false; - return true; + } + "step 2"; + if (result.index == 1) { + cards = event.cards.filter(function (i) { + return lib.filter.cardDiscardable(i, player, "olsujian"); + }); + if (cards.length) { + event.num = cards.length; + player.discard(cards); + event.cards = cards; + } else event.finish(); + } else event.goto(5); + "step 3"; + if ( + game.hasPlayer(function (current) { + return current != player && current.countDiscardableCards(player, "he") > 0; + }) + ) { + player + .chooseTarget(true, "弃置一名其他角色的至多" + get.cnNumber(num) + "张牌", function (card, player, current) { + return current != player && current.countDiscardableCards(player, "he") > 0; + }) + .set("ai", function (current) { + var att = get.attitude(player, current); + if ( + current.countDiscardableCards(player, "he", function (i) { + if (att > 0) return get.value(i, current) >= 4; + return get.value(i, current) <= 0; + }) >= num + ) + return 4 * get.effect(current, { name: "guohe_copy2" }, player, player); + return get.effect(current, { name: "guohe_copy2" }, player, player); + }); + } else event.finish(); + "step 4"; + if (result.bool) { + var target = result.targets[0]; + player.line(target, "green"); + player.discardPlayerCard(target, true, [1, num]); + } + event.finish(); + "step 5"; + if (_status.connectMode) + game.broadcastAll(function () { + _status.noclearcountdown = true; + }); + event.given_map = {}; + "step 6"; + player.chooseCardTarget({ + filterCard: function (card) { + return card.hasGaintag("olsujian"); }, - content: function () { - player.removeMark("zhaosong_trick", 1); - player.removeSkill("zhaosong_trick"); - //player.loseMaxHp(); - if (player.hp < 1) player.recover(1 - player.hp); - player.draw(); + filterTarget: lib.filter.notMe, + selectCard: [1, cards.length], + forced: true, + prompt: "请选择要分配的卡牌和目标", + ai1: function (card) { + if (!ui.selected.cards.length) return 1; + return 0; }, - }, - equip: { - marktext: "赋", - intro: { - name: "诏颂(赋)", - name2: "赋", - content: "出牌阶段开始时,你可移去“赋”并弃置一名角色区域内的至多两张牌。", + ai2: function (target) { + var player = _status.event.player, + card = ui.selected.cards[0]; + var val = target.getUseValue(card); + if (val > 0) return val * get.attitude(player, target) * 2; + return get.value(card, target) * get.attitude(player, target); }, - trigger: { player: "phaseUseBegin" }, - direct: true, - charlotte: true, - onremove: true, + }); + "step 7"; + if (result.bool) { + var res = result.cards, + target = result.targets[0].playerid; + player.removeGaintag("olsujian", res); + player.addGaintag(res, "olsujian_given"); + cards.removeArray(res); + if (!event.given_map[target]) event.given_map[target] = []; + event.given_map[target].addArray(res); + if (cards.length) event.goto(6); + } else event.finish(); + "step 8"; + if (_status.connectMode) { + game.broadcastAll(function () { + delete _status.noclearcountdown; + game.stopCountChoose(); + }); + } + var map = [], + cards = []; + for (var i in event.given_map) { + var source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; + player.line(source, "green"); + map.push([source, event.given_map[i]]); + cards.addArray(event.given_map[i]); + } + if (map.length) + game.loseAsync({ + gain_list: map, + player: player, + cards: cards, + giver: player, + animate: "giveAuto", + }).setContent("gaincardMultiple"); + "step 9"; + event.cards = []; + }, + update: function (player) { + player.removeGaintag("olsujian"); + var hs = player.getCards("h"); + player.getHistory("gain", function (evt) { + hs.removeArray(evt.cards); + }); + if (hs.length) player.addGaintag(hs, "olsujian"); + return hs; + }, + group: "olsujian_sync", + subSkill: { + sync: { + trigger: { player: ["phaseBeginStart", "gainBegin"] }, + forced: true, + popup: false, + firstDo: true, filter: function (event, player) { - return ( - player.hasMark("zhaosong_equip") && - game.hasPlayer(function (current) { - return current.hasCard(function (card) { - return lib.filter.canBeDiscarded(card, player, current); - }, "hej"); - }) - ); + if (event.name == "gain") return player == _status.currentPhase && event.getParent("olsujian").player != player; + return true; }, content: function () { - "step 0"; - player - .chooseTarget("是否弃置“赋”标记?", "弃置一名角色区域内的至多两张牌", function (card, player, current) { - return current.hasCard(function (card) { - return lib.filter.canBeDiscarded(card, player, current); - }, "hej"); - }) - .set("ai", function (target) { - var player = _status.event.player, - att = get.attitude(player, target) > 0 ? 2 : 1; - return get.effect(target, { name: "guohe_copy" }, player, player) * att; - }); - "step 1"; - if (result.bool) { - var target = result.targets[0]; - event.target = target; - player.logSkill("zhaosong_equip", target); - player.removeMark("zhaosong_equip", 1); - player.removeSkill("zhaosong_equip"); - player.discardPlayerCard(target, true, "hej", [1, 2]); - } + lib.skill.olsujian.update(player); }, }, }, }, - lisi: { - audio: 2, - trigger: { player: "useCardAfter" }, - direct: true, - filter: function (event, player) { - if (player == _status.currentPhase || !event.cards.filterInD().length) return false; - var hs = player.countCards("h"); - return game.hasPlayer(function (current) { - return current != player && current.countCards("h") <= hs; - }); + //卞夫人 + fuwei: { + audio: "wanwei", + trigger: { + player: "loseAfter", + global: "gainAfter", }, - content: function () { - "step 0"; - player.chooseTarget(get.prompt("lisi"), "将" + get.translation(trigger.cards.filterInD()) + "交给一名手牌数不大于你的其他角色", function (card, player, target) { - return target != player && target.countCards("h") <= player.countCards("h"); - }); - "step 1"; - if (result.bool) { - var target = result.targets[0]; - player.logSkill("lisi", target); - target.gain(trigger.cards.filterInD(), "gain2"); + filter: function (event, player) { + var evt = event; + if (event.name == "lose") { + if (event.type != "discard") return false; + evt = event.getParent(); } + if (evt[event.name == "gain" ? "bySelf" : "notBySelf"] != true) return false; + var evtx = event.getl(player); + return evtx && evtx.cards2 && evtx.cards2.length > 0; }, - }, - //王荣 - olfengzi: { - audio: 2, - trigger: { player: "useCard" }, - direct: true, - usable: 1, - filter: function (event, player) { - if (event.olfengzi_buff || !event.targets.length || !player.isPhaseUsing() || player.hasSkill("olfengzi_buff")) return false; - var type = get.type(event.card, false); - if (type != "basic" && type != "trick") return false; - return player.hasCard(function (i) { - if (_status.connectMode) return true; - return get.type2(i, player) == type; - }, "h"); + prompt2: function (event, player) { + var evt = event.getl(player), + origins = evt.cards2.map(function (i) { + return get.name(i, evt.hs.includes(i) ? player : false); + }); + return "从牌堆中获得" + get.translation(origins) + ";若没有则改为摸一张牌"; }, + usable: 1, content: function () { - "step 0"; - if (player != game.me && !player.isUnderControl() && !player.isOnline()) game.delayx(); - var type = get.type(trigger.card, false); - player - .chooseToDiscard("h", get.prompt("olfengzi"), "弃置一张" + get.translation(type) + "牌,令" + get.translation(trigger.card) + "结算两次", function (card, player) { - return get.type2(card, player) == _status.event.type; - }) - .set("type", type) - .set("ai", function (card) { - var player = _status.event.player; - var trigger = _status.event.getTrigger(); - if (trigger.card.name == "tiesuo") return 0; - var num = 0; - for (var i of trigger.targets) num += get.effect(i, trigger.card, player, player); - if (num <= 0) return 0; - return 7 - get.value(card); - }).logSkill = "olfengzi"; - "step 1"; - if (result.bool) { - trigger.effectCount++; - } else player.storage.counttrigger.olfengzi--; + var num = 0, + cards = [], + evt = trigger.getl(player), + origins = evt.cards2.map(function (i) { + return get.name(i, evt.hs.includes(i) ? player : false); + }); + for (var i of origins) { + var card = get.cardPile2(function (card) { + return card.name == i && !cards.includes(card); + }); + if (card) cards.push(card); + else num++; + } + if (cards.length) player.gain(cards, "gain2"); + if (num) player.draw(num); }, - /*subSkill:{ - buff:{ - trigger:{global:'useCardToTargeted'}, - forced:true, - charlotte:true, - popup:false, - lastDo:true, - filter:function(event,player){ - return (event.parent.olfengzi_buff==player&&event.targets.length==event.parent.triggeredTargets4.length); - }, - content:function(){ - trigger.getParent().targets=trigger.getParent().targets.concat(trigger.targets); - trigger.getParent().triggeredTargets4=trigger.getParent().triggeredTargets4.concat(trigger.targets); - }, - onremove:function(player){ - delete player.storage.counttrigger.olfengji; - }, - }, - },*/ }, - oljizhan: { + yuejian: { audio: 2, - trigger: { player: "phaseDrawBegin1" }, + usable: 2, + trigger: { global: "useCardAfter" }, filter: function (event, player) { - return !event.numFixed; + return player != event.player && event.targets && event.targets.includes(player) && player.countCards("h") > 0; + }, + prompt2: function (event, player) { + var suit = get.suit(event.card), + hs = player.getCards("h"), + cards = event.cards.filterInD(); + if (!lib.suit.includes(suit) || !cards.length) { + return "展示所有手牌,然后无事发生"; + } + for (var i of hs) { + if (get.suit(i) == suit) { + return "展示所有手牌,然后无事发生"; + } + } + return '展示所有手牌,然后获得' + get.translation(cards) + ""; + }, + check: function (event, player) { + var suit = get.suit(event.card), + hs = player.getCards("h"), + cards = event.cards.filterInD(); + if (!lib.suit.includes(suit) || !cards.length) { + return false; + } + for (var i of hs) { + if (get.suit(i) == suit) { + return false; + } + } + return true; }, content: function () { "step 0"; - trigger.changeToZero(); - var card = get.cards()[0]; - game.cardsGotoOrdering(card); - event.cards = [card]; - event.num = get.number(card, false); - player.showCards(card, get.translation(player) + "发动了【吉占】"); - "step 1"; - var str = get.strNumber(num); - player - .chooseControl("大于" + str, "小于" + str, "cancel2") - .set("prompt", "吉占:猜测下一张牌的点数") - .set("choice", num < 7 ? 0 : 1) - .set("ai", () => _status.event.choice); - "step 2"; - var card = get.cards()[0]; - game.cardsGotoOrdering(card); - event.cards.push(card); - var num = get.number(card, false); - if ((num > event.num && result.index == 0) || (num < event.num && result.index == 1)) { - event.num = num; - event.goto(1); + player.showHandcards(get.translation(player) + "发动了【约俭】"); + var suit = get.suit(trigger.card), + hs = player.getCards("h"); + if (!lib.suit.includes(suit)) { + event.finish(); + return; } - player.showCards(card); - "step 3"; - player.gain(cards, "gain2"); + for (var i of hs) { + if (get.suit(i) == suit) { + event.finish(); + return; + } + } + "step 1"; + var cards = trigger.cards.filterInD(); + if (cards.length) player.gain(cards, "gain2"); }, }, - olfusong: { + //杜袭 + quxi: { audio: 2, - forceDie: true, - trigger: { player: "die" }, - skillAnimation: true, - animationColor: "gray", + trigger: { player: "phaseUseEnd" }, direct: true, + limited: true, + skillAnimation: true, + animationColor: "water", filter: function (event, player) { - return game.hasPlayer(function (current) { - return current.maxHp > player.maxHp; - }); + if (player.isTurnedOver()) return false; + var list = game.filterPlayer(target => target != player && !target.hasMark("quxi_gain") && !target.hasMark("quxi_lose")); + if (list.length < 2) return false; + var nf = list[0].countCards("h"); + for (var i = 1; i < list.length; i++) { + if (list[i].countCards("h") != nf) return true; + } + return false; }, content: function () { "step 0"; player - .chooseTarget(get.prompt("olfusong"), "令一名体力上限大于你的其他角色获得〖丰姿〗或〖吉占〗", function (card, player, target) { - return target.maxHp > player.maxHp; + .chooseTarget(2, get.prompt("quxi"), "选择两名手牌数不同的其他角色。你将翻至背面,令这两名角色中手牌数较少的角色获得另一名角色的一张牌并获得一枚“丰”,另一名角色获得一枚“歉”。", function (card, player, target) { + if (player == target || target.hasMark("quxi_gain") || target.hasMark("quxi_lose")) return false; + if (!ui.selected.targets.length) return true; + return target.countCards("h") != ui.selected.targets[0].countCards("h"); }) - .set("forceDie", true) - .set("ai", target => get.attitude(_status.event.player, target)); + .set("complexTarget", true) + .set("ai", function (target) { + if (!ui.selected.targets.length) { + var player = _status.event.player, + hs = target.countCards("h"); + if ( + game.hasPlayer(function (current) { + return current != player && current != target && current.countCards("h") > hs && !current.hasMark("quxi_gain") && !current.hasMark("quxi_lose"); + }) + ) + return get.attitude(player, target) / Math.sqrt(1 + target.countCards("h")); + return 0; + } + if (target.countCards("h") > ui.selected.targets[0].countCards("h")) return -get.attitude(_status.event.player, target); + return 0; + }); "step 1"; if (result.bool) { - var target = result.targets[0]; - event.target = target; - player.logSkill("olfusong", target); - target - .chooseControl("olfengzi", "oljizhan") - .set("prompt", "令" + get.translation(target) + "获得其中一个技能") - .set("ai", () => (Math.random() > 0.5 ? 0 : 1)); + player.logSkill("quxi", result.targets); + player.awakenSkill("quxi"); + player.skip("phaseDiscard"); + if (result.targets[0].countCards("h") > result.targets[1].countCards("h")) result.targets.reverse(); + event.gainner = result.targets[0]; + event.giver = result.targets[1]; + player.turnOver(); } else event.finish(); "step 2"; - target.addSkills(result.control); + event.gainner.gainPlayerCard(event.giver, true, "he"); + "step 3"; + player.addSkill("quxi_effect"); + event.gainner.addMark("quxi_gain", 1); + event.giver.addMark("quxi_lose", 1); + }, + subSkill: { + effect: { + global: "quxi_gainlose", + trigger: { global: ["roundStart", "die"] }, + charlotte: true, + direct: true, + filter: function (event, player) { + if (event.name == "die") return event.player.countMark("quxi_gain") > 0 || event.player.countMark("quxi_lose") > 0; + return game.hasPlayer(function (target) { + return target != player && (target.countMark("quxi_gain") > 0 || target.countMark("quxi_lose") > 0); + }); + }, + content: function () { + "step 0"; + if (trigger.name == "die") { + var gain = trigger.player.countMark("quxi_gain"), + lose = trigger.player.countMark("quxi_lose"); + player + .chooseTarget("是否令一名角色获得" + get.translation(trigger.player) + "的“" + (gain && lose ? "丰”和“歉" : gain ? "丰" : "歉") + "”标记?", function (card, player, target) { + return !target.hasMark("quxi_gain") && !target.hasMark("quxi_lose"); + }) + .set("goon", gain - lose) + .set("ai", function (target) { + var evt = _status.event; + return evt.goon * get.attitude(evt.player, target); + }); + } else event.goto(2); + "step 1"; + if (result.bool) { + var targets = result.targets; + if (targets.length < 2) targets.unshift(trigger.player); + player.logSkill("quxi_effect", targets, false); + player.line2(targets); + var gain = targets[0].countMark("quxi_gain"), + lose = targets[0].countMark("quxi_lose"); + if (gain) { + targets[0].removeMark("quxi_gain", gain); + targets[1].addMark("quxi_gain", gain); + } + if (lose) { + targets[0].removeMark("quxi_lose", lose); + targets[1].addMark("quxi_lose", lose); + } + game.delayx(); + event.finish(); + } + "step 2"; + if ( + game.hasPlayer(function (target) { + return target.countMark("quxi_gain") > 0; + }) + ) + player + .chooseTarget(2, "是否转移“丰”标记?", function (card, player, target) { + if (ui.selected.targets.length) return !target.hasMark("quxi_gain") && !target.hasMark("quxi_lose"); + return target.countMark("quxi_gain") > 0; + }) + .set("complexTarget", true) + .set("complexSelect", true) + .set("targetprompt", ["移走标记", "获得标记"]) + .set("ai", function (target) { + var player = _status.event.player; + if (!ui.selected.targets.length) { + return -get.attitude(player, target); + } + return get.attitude(player, target); + }); + else event.goto(4); + "step 3"; + if (result.bool) { + var targets = result.targets; + player.logSkill("quxi_effect", targets, false); + player.line2(targets); + var gain = targets[0].countMark("quxi_gain"); + if (gain) { + targets[0].removeMark("quxi_gain", gain); + targets[1].addMark("quxi_gain", gain); + } + game.delayx(); + } + "step 4"; + if ( + game.hasPlayer(function (target) { + return target.countMark("quxi_lose") > 0; + }) + ) + player + .chooseTarget(2, "是否转移“歉”标记?", function (card, player, target) { + if (ui.selected.targets.length) return !target.hasMark("quxi_gain") && !target.hasMark("quxi_lose"); + return target.countMark("quxi_lose") > 0; + }) + .set("complexTarget", true) + .set("complexSelect", true) + .set("targetprompt", ["移走标记", "获得标记"]) + .set("ai", function (target) { + var player = _status.event.player; + if (!ui.selected.targets.length) { + return get.attitude(player, target); + } + return -get.attitude(player, target); + }); + else event.finish(); + "step 5"; + if (result.bool) { + var targets = result.targets; + player.logSkill("quxi_effect", targets, false); + player.line2(targets); + var gain = targets[0].countMark("quxi_lose"); + if (gain) { + targets[0].removeMark("quxi_lose", gain); + targets[1].addMark("quxi_lose", gain); + } + game.delayx(); + } + }, + }, + gainlose: { + trigger: { player: "phaseDrawBegin" }, + forced: true, + filter: function (event, player) { + if (event.numFixed) return false; + return player.countMark("quxi_gain") - player.countMark("quxi_lose") != 0; + }, + content: function () { + trigger.num += player.countMark("quxi_gain") - player.countMark("quxi_lose"); + }, + }, + gain: { + marktext: "丰", + intro: { + name: "驱徙(丰)", + name2: "丰", + content: "mark", + }, + }, + lose: { + marktext: "歉", + intro: { + name: "驱徙(歉)", + name2: "歉", + content: "mark", + }, + }, }, }, - //邓芝 - olxiuhao: { - audio: 2, - trigger: { global: "damageBegin4" }, - usable: 1, - filter: function (event, player) { - return event.source && event.source.isIn() && [event.source, event.player].includes(player) && event.source != event.player; - }, - logTarget: function (event, player) { - return player == event.player ? event.source : event.player; + bixiong: { + trigger: { + player: "loseAfter", + global: "loseAsyncAfter", }, - check: function (event, player) { - _status.olxiuhao_judging = true; - var bool = false; - if (get.attitude(player, event.player) > 0) bool = true; - else if (2 * get.effect(event.source, { name: "draw" }, player, _status.event.player) + event.num * get.damageEffect(player, event.source, _status.event.player, event.nature) > 0) bool = true; - else if (event.source.hasSkillTag("nogain")) bool = true; - delete _status.olxiuhao_judging; - return bool; + forced: true, + filter: function (event, player) { + if (event.type != "discard" || event.getlx === false || event.getParent("phaseDiscard").player != player) return false; + var evt = event.getl(player); + return evt && evt.hs && evt.hs.length > 0; }, content: function () { - trigger.cancel(); - trigger.source.draw(2); + var cards = [], + hs = trigger.getl(player).hs; + for (var i of hs) cards.add(get.suit(i, player)); + player.addTempSkill("bixiong2", { player: "phaseBegin" }); + player.markAuto("bixiong2", cards); }, - ai: { - effect: { - target: function (card, player, target) { - if (!_status.olxiuhao_judging && get.tag(card, "damage") && get.attitude(target, player) > 0 && player != target && (!target.storage.counttrigger || !target.storage.counttrigger.olxiuhao)) return [0, 0.5, 0, 0.5]; - }, - player: function (card, player, target) { - if (!_status.olxiuhao_judging && get.tag(card, "damage") && get.attitude(player, target) > 0 && player != target && (!player.storage.counttrigger || !player.storage.counttrigger.olxiuhao)) return [0, 0.5, 0, 0.5]; - }, + }, + bixiong2: { + onremove: true, + mod: { + targetEnabled: function (card, player, target) { + if (player !== target && target.getStorage("bixiong2").includes(get.suit(card))) return false; }, }, + intro: { content: "不能成为其他角色$牌的目标" }, }, - olsujian: { - trigger: { player: "phaseDiscardBefore" }, - forced: true, - content: function () { - trigger.setContent(lib.skill.olsujian.phaseDiscard); + //高干 + juguan: { + audio: 2, + enable: "phaseUse", + usable: 1, + filter: function (event, player) { + return ( + event.filterCard( + { + name: "sha", + }, + player, + event + ) || + event.filterCard( + { + name: "juedou", + }, + player, + event + ) + ); }, - phaseDiscard: function () { - "step 0"; - game.log(player, "进入了弃牌阶段"); - game.broadcastAll(function (player) { - if (lib.config.show_phase_prompt) { - player.popup("弃牌阶段", null, false); - } - }, player); - event.trigger("phaseDiscard"); - "step 1"; - var cards = lib.skill.olsujian.update(player); - if (!cards.length) event.finish(); - else { - event.cards = cards; - var str = get.translation(cards); - player - .chooseControl() - .set("choiceList", ["将" + str + "分配给任意名其他角色", "弃置" + str + "并弃置一名其他角色至多等量的牌"]) - .set("ai", function () { - var cards = _status.event.getParent().cards, - player = _status.event.player; - if ( - !game.hasPlayer(function (current) { - return player !== current && get.attitude(player, current) > 0; - }) - ) - return 1; - if ( - game.hasPlayer(function (current) { - var att = get.attitude(player, current); - return ( - att && - current.countDiscardableCards(player, "he", function (i) { - if (att > 0) return get.value(i, current) < 0; - return get.value(i, current) >= 4; - }) >= cards.length && - get.effect(current, { name: "guohe_copy2" }, player, player) > 0 - ); - }) - ) - return 1; - return 0; - }); - } - "step 2"; - if (result.index == 1) { - cards = event.cards.filter(function (i) { - return lib.filter.cardDiscardable(i, player, "olsujian"); - }); - if (cards.length) { - event.num = cards.length; - player.discard(cards); - event.cards = cards; - } else event.finish(); - } else event.goto(5); - "step 3"; - if ( - game.hasPlayer(function (current) { - return current != player && current.countDiscardableCards(player, "he") > 0; - }) - ) { - player - .chooseTarget(true, "弃置一名其他角色的至多" + get.cnNumber(num) + "张牌", function (card, player, current) { - return current != player && current.countDiscardableCards(player, "he") > 0; - }) - .set("ai", function (current) { - var att = get.attitude(player, current); - if ( - current.countDiscardableCards(player, "he", function (i) { - if (att > 0) return get.value(i, current) >= 4; - return get.value(i, current) <= 0; - }) >= num - ) - return 4 * get.effect(current, { name: "guohe_copy2" }, player, player); - return get.effect(current, { name: "guohe_copy2" }, player, player); - }); - } else event.finish(); - "step 4"; - if (result.bool) { - var target = result.targets[0]; - player.line(target, "green"); - player.discardPlayerCard(target, true, [1, num]); - } - event.finish(); - "step 5"; - if (_status.connectMode) - game.broadcastAll(function () { - _status.noclearcountdown = true; - }); - event.given_map = {}; - "step 6"; - player.chooseCardTarget({ - filterCard: function (card) { - return card.hasGaintag("olsujian"); - }, - filterTarget: lib.filter.notMe, - selectCard: [1, cards.length], - forced: true, - prompt: "请选择要分配的卡牌和目标", - ai1: function (card) { - if (!ui.selected.cards.length) return 1; - return 0; - }, - ai2: function (target) { - var player = _status.event.player, - card = ui.selected.cards[0]; - var val = target.getUseValue(card); - if (val > 0) return val * get.attitude(player, target) * 2; - return get.value(card, target) * get.attitude(player, target); - }, - }); - "step 7"; - if (result.bool) { - var res = result.cards, - target = result.targets[0].playerid; - player.removeGaintag("olsujian", res); - player.addGaintag(res, "olsujian_given"); - cards.removeArray(res); - if (!event.given_map[target]) event.given_map[target] = []; - event.given_map[target].addArray(res); - if (cards.length) event.goto(6); - } else event.finish(); - "step 8"; - if (_status.connectMode) { - game.broadcastAll(function () { - delete _status.noclearcountdown; - game.stopCountChoose(); - }); - } - var map = [], - cards = []; - for (var i in event.given_map) { - var source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; - player.line(source, "green"); - map.push([source, event.given_map[i]]); - cards.addArray(event.given_map[i]); - } - if (map.length) - game.loseAsync({ - gain_list: map, - player: player, - cards: cards, - giver: player, - animate: "giveAuto", - }).setContent("gaincardMultiple"); - "step 9"; - event.cards = []; + chooseButton: { + dialog: function () { + return ui.create.dialog("拒关", [["sha", "juedou"], "vcard"]); + }, + filter: function (button, player) { + var evt = _status.event.getParent(); + return evt.filterCard( + { + name: button.link[2], + }, + player, + evt + ); + }, + check: function (button) { + return ( + _status.event.player.getUseValue({ + name: button.link[2], + }) * (button.link[2] == "juedou" ? 3 : 1) + ); + }, + backup: function (links) { + return { + audio: "juguan", + viewAs: { name: links[0][2] }, + filterCard: true, + check: function (card) { + return 6 - get.value(card); + }, + position: "hs", + onuse: function (result, player) { + player.addTempSkill("juguan_effect"); + }, + }; + }, + prompt: function (links) { + return "将一张手牌当做" + get.translation(links[0][2]) + "使用"; + }, }, - update: function (player) { - player.removeGaintag("olsujian"); - var hs = player.getCards("h"); - player.getHistory("gain", function (evt) { - hs.removeArray(evt.cards); - }); - if (hs.length) player.addGaintag(hs, "olsujian"); - return hs; + ai: { + order: function (item, player) { + return Math.max(get.order({ name: "sha" }), get.order({ name: "juedou" })) + 0.2; + }, + result: { player: 1 }, }, - group: "olsujian_sync", subSkill: { - sync: { - trigger: { player: ["phaseBeginStart", "gainBegin"] }, + effect: { + trigger: { global: "damage" }, forced: true, + charlotte: true, + firstDo: true, + silent: true, popup: false, + filter: function (event, player) { + var evt = event.getParent("useCard"); + return event.card && evt && event.card == evt.card && evt.skill == "juguan_backup" && evt.player == player; + }, + content: function () { + player.addSkill("juguan_draw"); + player.markAuto("juguan_draw", [trigger.player]); + }, + }, + draw: { + audio: "juguan", + trigger: { player: "phaseDrawBegin" }, + forced: true, + charlotte: true, + onremove: true, + content: function () { + player.removeSkill("juguan_draw"); + if (!trigger.numFixed) trigger.num += 2; + }, + group: "juguan_clear", + intro: { + content: "若没有受到$的伤害,则下个摸牌阶段多摸两张牌", + }, + }, + clear: { + trigger: { player: "damage" }, + forced: true, + charlotte: true, firstDo: true, + silent: true, + popup: false, filter: function (event, player) { - if (event.name == "gain") return player == _status.currentPhase && event.getParent("olsujian").player != player; - return true; + return player.storage.juguan_draw && player.storage.juguan_draw.includes(event.source); }, content: function () { - lib.skill.olsujian.update(player); + player.unmarkAuto("juguan_draw", [trigger.source]); + if (!player.storage.juguan_draw || !player.storage.juguan_draw.length) player.removeSkill("juguan_draw"); }, }, }, }, - //卞夫人 - fuwei: { - audio: "wanwei", - trigger: { - player: "loseAfter", - global: "gainAfter", - }, + //OL鲍三娘 + olwuniang: { + audio: "xinfu_wuniang", + trigger: { player: "useCardAfter" }, + usable: 1, filter: function (event, player) { - var evt = event; - if (event.name == "lose") { - if (event.type != "discard") return false; - evt = event.getParent(); - } - if (evt[event.name == "gain" ? "bySelf" : "notBySelf"] != true) return false; - var evtx = event.getl(player); - return evtx && evtx.cards2 && evtx.cards2.length > 0; - }, - prompt2: function (event, player) { - var evt = event.getl(player), - origins = evt.cards2.map(function (i) { - return get.name(i, evt.hs.includes(i) ? player : false); - }); - return "从牌堆中获得" + get.translation(origins) + ";若没有则改为摸一张牌"; + return event.card.name == "sha" && event.targets.length == 1 && event.targets[0].isIn(); }, - usable: 1, + logTarget: "targets", content: function () { - var num = 0, - cards = [], - evt = trigger.getl(player), - origins = evt.cards2.map(function (i) { - return get.name(i, evt.hs.includes(i) ? player : false); - }); - for (var i of origins) { - var card = get.cardPile2(function (card) { - return card.name == i && !cards.includes(card); - }); - if (card) cards.push(card); - else num++; - } - if (cards.length) player.gain(cards, "gain2"); - if (num) player.draw(num); + "step 0"; + var target = trigger.targets[0]; + target + .chooseToUse(function (card, player, event) { + if (get.name(card) != "sha") return false; + return lib.filter.filterCard.apply(this, arguments); + }, "武娘:是否对" + get.translation(player) + "使用一张杀?") + .set("targetRequired", true) + .set("complexSelect", true) + .set("filterTarget", function (card, player, target) { + if (target != _status.event.sourcex && !ui.selected.targets.includes(_status.event.sourcex)) return false; + return lib.filter.filterTarget.apply(this, arguments); + }) + .set("sourcex", player); + "step 1"; + player.addTempSkill("olwuniang2"); + player.addMark("olwuniang2", 1, false); + player.draw(); }, }, - yuejian: { - audio: 2, - usable: 2, - trigger: { global: "useCardAfter" }, + olwuniang2: { + onremove: true, + charlotte: true, + mod: { + cardUsable: function (card, player, num) { + if (card.name == "sha") return num + player.countMark("olwuniang2"); + }, + }, + }, + olxushen: { + derivation: "olzhennan", + audio: "xinfu_xushen", + trigger: { player: "dying" }, + limited: true, + skillAnimation: true, + animationColor: "fire", filter: function (event, player) { - return player != event.player && event.targets && event.targets.includes(player) && player.countCards("h") > 0; + return player.hp < 1; }, - prompt2: function (event, player) { - var suit = get.suit(event.card), - hs = player.getCards("h"), - cards = event.cards.filterInD(); - if (!lib.suit.includes(suit) || !cards.length) { - return "展示所有手牌,然后无事发生"; - } - for (var i of hs) { - if (get.suit(i) == suit) { - return "展示所有手牌,然后无事发生"; - } + content: function () { + "step 0"; + player.awakenSkill("olxushen"); + player.addSkills("olzhennan"); + player.recover(1 - player.hp); + "step 1"; + if ( + !player.isDying() && + !game.hasPlayer(function (current) { + return current.name1 == "guansuo" || current.name2 == "guansuo"; + }) + ) { + player + .chooseTarget(function (card, player, current) { + return current != player && current.hasSex("male"); + }, "许身:是否令一名其他男性角色选择是否将其武将牌替换为“关索”?") + .set("ai", function (target) { + return get.attitude(_status.event.player, target) - 4; + }); + } else event.finish(); + "step 2"; + if (!result.bool) { + event.finish(); + return; } - return '展示所有手牌,然后获得' + get.translation(cards) + ""; + var target = result.targets[0]; + event.target = target; + player.line(target, "fire"); + target.chooseBool("许身:是否将自己的一张武将牌替换为“关索”?"); + "step 3"; + if (result.bool) { + if (target.name2 != undefined) { + target.chooseControl(target.name1, target.name2).set("prompt", "请选择要更换的武将牌"); + } else event._result = { control: target.name1 }; + } else event.finish(); + "step 4"; + target.reinitCharacter(result.control, "guansuo"); }, - check: function (event, player) { - var suit = get.suit(event.card), - hs = player.getCards("h"), - cards = event.cards.filterInD(); - if (!lib.suit.includes(suit) || !cards.length) { - return false; - } - for (var i of hs) { - if (get.suit(i) == suit) { - return false; - } - } - return true; + }, + olzhennan: { + audio: "xinfu_zhennan", + enable: "phaseUse", + usable: 1, + viewAs: { name: "nanman" }, + filterCard: true, + selectCard: function () { + if (ui.selected.targets.length) return [ui.selected.targets.length, Math.min(ui.selected.targets.length + 1, game.players.length - 1)]; + return [1, Infinity]; + }, + check: function (card) { + var player = _status.event.player; + if ( + game.countPlayer(function (current) { + return current != player && player.canUse("nanman", current) && get.effect(current, { name: "nanman" }, player, player) > 0; + }) <= ui.selected.cards.length + ) + return 0; + return 6 - get.value(card); + }, + selectTarget: function () { + return ui.selected.cards.length; + }, + ai: { + order: 2, + }, + group: "olzhennan2", + }, + olzhennan2: { + trigger: { target: "useCardToBefore" }, + forced: true, + locked: false, + audio: "olzhennan", + filter: function (event, player) { + return event.card.name == "nanman"; }, content: function () { - "step 0"; - player.showHandcards(get.translation(player) + "发动了【约俭】"); - var suit = get.suit(trigger.card), - hs = player.getCards("h"); - if (!lib.suit.includes(suit)) { - event.finish(); - return; - } - for (var i of hs) { - if (get.suit(i) == suit) { - event.finish(); - return; - } - } - "step 1"; - var cards = trigger.cards.filterInD(); - if (cards.length) player.gain(cards, "gain2"); + trigger.cancel(); }, }, - //杜袭 - quxi: { - audio: 2, - trigger: { player: "phaseUseEnd" }, - direct: true, - limited: true, - skillAnimation: true, - animationColor: "water", + //黄承彦 + guanxu: { + enable: "phaseUse", + usable: 1, filter: function (event, player) { - if (player.isTurnedOver()) return false; - var list = game.filterPlayer(target => target != player && !target.hasMark("quxi_gain") && !target.hasMark("quxi_lose")); - if (list.length < 2) return false; - var nf = list[0].countCards("h"); - for (var i = 1; i < list.length; i++) { - if (list[i].countCards("h") != nf) return true; - } - return false; + return game.hasPlayer(current => lib.skill.guanxu.filterTarget(null, player, current)); + }, + filterTarget: function (card, player, target) { + return target != player && target.countCards("h") > 0; }, content: function () { "step 0"; + var cards = get.cards(5); + for (var i = cards.length - 1; i >= 0; i--) { + ui.cardPile.insertBefore(cards[i], ui.cardPile.firstChild); + } + game.updateRoundNumber(); + var hs = target.getCards("h"); + var dialog = ["观虚:选择要操作的牌", '
    ' + get.translation(target) + "的手牌
    ", hs, '
    牌堆顶
    ', cards]; player - .chooseTarget(2, get.prompt("quxi"), "选择两名手牌数不同的其他角色。你将翻至背面,令这两名角色中手牌数较少的角色获得另一名角色的一张牌并获得一枚“丰”,另一名角色获得一枚“歉”。", function (card, player, target) { - if (player == target || target.hasMark("quxi_gain") || target.hasMark("quxi_lose")) return false; - if (!ui.selected.targets.length) return true; - return target.countCards("h") != ui.selected.targets[0].countCards("h"); + .chooseButton(dialog, 2) + .set("filterButton", function (button) { + if (ui.selected.buttons.length) return get.position(button.link) != get.position(ui.selected.buttons[0].link); + return true; }) - .set("complexTarget", true) - .set("ai", function (target) { - if (!ui.selected.targets.length) { - var player = _status.event.player, - hs = target.countCards("h"); - if ( - game.hasPlayer(function (current) { - return current != player && current != target && current.countCards("h") > hs && !current.hasMark("quxi_gain") && !current.hasMark("quxi_lose"); - }) - ) - return get.attitude(player, target) / Math.sqrt(1 + target.countCards("h")); - return 0; - } - if (target.countCards("h") > ui.selected.targets[0].countCards("h")) return -get.attitude(_status.event.player, target); - return 0; - }); - "step 1"; - if (result.bool) { - player.logSkill("quxi", result.targets); - player.awakenSkill("quxi"); - player.skip("phaseDiscard"); - if (result.targets[0].countCards("h") > result.targets[1].countCards("h")) result.targets.reverse(); - event.gainner = result.targets[0]; - event.giver = result.targets[1]; - player.turnOver(); - } else event.finish(); - "step 2"; - event.gainner.gainPlayerCard(event.giver, true, "he"); - "step 3"; - player.addSkill("quxi_effect"); - event.gainner.addMark("quxi_gain", 1); - event.giver.addMark("quxi_lose", 1); - }, - subSkill: { - effect: { - global: "quxi_gainlose", - trigger: { global: ["roundStart", "die"] }, - charlotte: true, - direct: true, - filter: function (event, player) { - if (event.name == "die") return event.player.countMark("quxi_gain") > 0 || event.player.countMark("quxi_lose") > 0; - return game.hasPlayer(function (target) { - return target != player && (target.countMark("quxi_gain") > 0 || target.countMark("quxi_lose") > 0); - }); - }, - content: function () { - "step 0"; - if (trigger.name == "die") { - var gain = trigger.player.countMark("quxi_gain"), - lose = trigger.player.countMark("quxi_lose"); - player - .chooseTarget("是否令一名角色获得" + get.translation(trigger.player) + "的“" + (gain && lose ? "丰”和“歉" : gain ? "丰" : "歉") + "”标记?", function (card, player, target) { - return !target.hasMark("quxi_gain") && !target.hasMark("quxi_lose"); - }) - .set("goon", gain - lose) - .set("ai", function (target) { - var evt = _status.event; - return evt.goon * get.attitude(evt.player, target); - }); - } else event.goto(2); - "step 1"; - if (result.bool) { - var targets = result.targets; - if (targets.length < 2) targets.unshift(trigger.player); - player.logSkill("quxi_effect", targets, false); - player.line2(targets); - var gain = targets[0].countMark("quxi_gain"), - lose = targets[0].countMark("quxi_lose"); - if (gain) { - targets[0].removeMark("quxi_gain", gain); - targets[1].addMark("quxi_gain", gain); - } - if (lose) { - targets[0].removeMark("quxi_lose", lose); - targets[1].addMark("quxi_lose", lose); - } - game.delayx(); - event.finish(); - } - "step 2"; - if ( - game.hasPlayer(function (target) { - return target.countMark("quxi_gain") > 0; - }) - ) - player - .chooseTarget(2, "是否转移“丰”标记?", function (card, player, target) { - if (ui.selected.targets.length) return !target.hasMark("quxi_gain") && !target.hasMark("quxi_lose"); - return target.countMark("quxi_gain") > 0; - }) - .set("complexTarget", true) - .set("complexSelect", true) - .set("targetprompt", ["移走标记", "获得标记"]) - .set("ai", function (target) { - var player = _status.event.player; - if (!ui.selected.targets.length) { - return -get.attitude(player, target); - } - return get.attitude(player, target); - }); - else event.goto(4); - "step 3"; - if (result.bool) { - var targets = result.targets; - player.logSkill("quxi_effect", targets, false); - player.line2(targets); - var gain = targets[0].countMark("quxi_gain"); - if (gain) { - targets[0].removeMark("quxi_gain", gain); - targets[1].addMark("quxi_gain", gain); - } - game.delayx(); - } - "step 4"; - if ( - game.hasPlayer(function (target) { - return target.countMark("quxi_lose") > 0; - }) - ) - player - .chooseTarget(2, "是否转移“歉”标记?", function (card, player, target) { - if (ui.selected.targets.length) return !target.hasMark("quxi_gain") && !target.hasMark("quxi_lose"); - return target.countMark("quxi_lose") > 0; - }) - .set("complexTarget", true) - .set("complexSelect", true) - .set("targetprompt", ["移走标记", "获得标记"]) - .set("ai", function (target) { - var player = _status.event.player; - if (!ui.selected.targets.length) { - return get.attitude(player, target); - } - return -get.attitude(player, target); - }); - else event.finish(); - "step 5"; - if (result.bool) { - var targets = result.targets; - player.logSkill("quxi_effect", targets, false); - player.line2(targets); - var gain = targets[0].countMark("quxi_lose"); - if (gain) { - targets[0].removeMark("quxi_lose", gain); - targets[1].addMark("quxi_lose", gain); + .set("cards1", hs) + .set("cards2", cards) + .set("ai", function (button) { + var card = button.link, + cards1 = _status.event.cards1.slice(0); + var cards2 = _status.event.cards2.slice(0), + target = _status.event.getParent().target; + if (!ui.selected.buttons.length) { + if (!cards1.includes(card)) return 0; + cards1.remove(card); + var suits = cards2.map(function (i) { + return get.suit(i, target); + }); + for (var i of lib.suit) { + var num = cards1.filter(function (c) { + return get.suit(c, target) == i; + }).length; + if (num > 2 || (num > 1 && suits.includes(i))) return 20 + get.value(card); } - game.delayx(); + return get.value(card); } - }, - }, - gainlose: { - trigger: { player: "phaseDrawBegin" }, - forced: true, - filter: function (event, player) { - if (event.numFixed) return false; - return player.countMark("quxi_gain") - player.countMark("quxi_lose") != 0; - }, - content: function () { - trigger.num += player.countMark("quxi_gain") - player.countMark("quxi_lose"); - }, - }, - gain: { - marktext: "丰", - intro: { - name: "驱徙(丰)", - name2: "丰", - content: "mark", - }, - }, - lose: { - marktext: "歉", - intro: { - name: "驱徙(歉)", - name2: "歉", - content: "mark", + cards1.remove(ui.selected.buttons[0].link); + cards1.push(card); + for (var i of lib.suit) { + if ( + cards1.filter(function (c) { + return get.suit(c, target) == i; + }).length > 2 + ) + return 20 - get.value(card); + return get.value(ui.selected.buttons[0].link) - get.value(card); + } + }); + "step 1"; + if (result.bool) { + var cards = result.links; + if (get.position(cards[0]) != "h") cards.reverse(); + var next = target.lose(cards[0], ui.cardPile); + next.insert_index_card = cards[1]; + next.insert_index = function (event) { + return event.insert_index_card; + }; + target.gain(cards[1], "draw"); + } else event.finish(); + "step 2"; + game.updateRoundNumber(); + var suits = [], + map = {}, + hs = target.getCards("h"); + if (hs.length) { + for (var i of hs) { + if (!lib.filter.canBeDiscarded(i, player, target, "guanxu")) continue; + var suit = get.suit(i, target); + if (!map[suit]) map[suit] = 1; + else map[suit]++; + if (map[suit] > 2) suits.add(suit); + } + var next = player.discardPlayerCard(target, 3, "visible", "h"); + next.set("suits", suits); + next.set("filterButton", function (button) { + var suit = get.suit(button.link); + if (!ui.selected.buttons.length) return _status.event.suits.includes(suit); + return suit == get.suit(ui.selected.buttons[0].link); + }); + if (suits.length) next.set("forced", true); + } + }, + ai: { + order: 9, + result: { + target: function (player, target) { + if (target.countCards("h") > 3) return -5; + if (target.countCards("h") == 3) return -3; + return -0.5; }, }, }, }, - bixiong: { - trigger: { - player: "loseAfter", - global: "loseAsyncAfter", + yashi: { + trigger: { player: "damageEnd" }, + direct: true, + filter: function (event, player) { + if (event.source && event.source.isIn()) return true; + return game.hasPlayer(current => lib.skill.guanxu.filterTarget(null, player, current)); + }, + content: function () { + "step 0"; + event.addIndex = 0; + var choiceList = []; + if (trigger.source && trigger.source.isIn()) { + choiceList.push("令" + get.translation(trigger.source) + "的所有非锁定技失效"); + } else event.addIndex++; + if (game.hasPlayer(current => lib.skill.guanxu.filterTarget(null, player, current))) choiceList.push("发动一次〖观虚〗"); + player + .chooseControl("cancel2") + .set("prompt", get.prompt("yashi")) + .set("choiceList", choiceList) + .set("ai", function () { + var player = _status.event.player, + source = _status.event.getTrigger().source, + index = _status.event.getParent().addIndex; + if ( + game.hasPlayer(function (current) { + return current != player && current.countCards("h") > 3 && get.attitude(player, current) < 0; + }) + ) + return 1 - index; + if (source && source.isIn() && get.attitude(player, source) < 0 && !source.hasSkill("fengyin")) return 0; + if ( + game.hasPlayer(function (current) { + return current != player && current.countCards("h") > 0 && get.attitude(player, current) < 0; + }) + ) + return 1 - index; + return "cancel2"; + }); + "step 1"; + if (result.control != "cancel2") { + if (result.index + event.addIndex == 0) { + var target = trigger.source; + player.logSkill("yashi", target); + //target.removeSkill('fengyin'); + target.addTempSkill("fengyin", { player: "phaseBegin" }); + event.finish(); + } else + player.chooseTarget(true, "请选择〖观虚〗的目标", lib.skill.guanxu.filterTarget).set("ai", function (target) { + var player = _status.event.player; + return get.effect(target, "guanxu", player, player); + }); + } else event.finish(); + "step 2"; + if (result.bool) { + var target = result.targets[0]; + player.logSkill("yashi", target); + var next = game.createEvent("yashi_guanxu"); + next.player = player; + next.target = target; + next.setContent(lib.skill.guanxu.content); + } }, + }, + //黄祖 + wangong: { + audio: 2, + trigger: { player: "useCard" }, forced: true, filter: function (event, player) { - if (event.type != "discard" || event.getlx === false || event.getParent("phaseDiscard").player != player) return false; - var evt = event.getl(player); - return evt && evt.hs && evt.hs.length > 0; + return get.type(event.card, null, false) == "basic"; }, content: function () { - var cards = [], - hs = trigger.getl(player).hs; - for (var i of hs) cards.add(get.suit(i, player)); - player.addTempSkill("bixiong2", { player: "phaseBegin" }); - player.markAuto("bixiong2", cards); + player.addSkill("wangong2"); }, }, - bixiong2: { - onremove: true, + wangong2: { + trigger: { player: "useCard1" }, + forced: true, + popup: false, + firstDo: true, + charlotte: true, + content: function () { + player.removeSkill("wangong2"); + if (trigger.card.name == "sha") trigger.baseDamage++; + }, mod: { - targetEnabled: function (card, player, target) { - if (player !== target && target.getStorage("bixiong2").includes(get.suit(card))) return false; + cardUsable: function (card) { + if (card.name == "sha") return Infinity; + }, + targetInRange: function (card) { + if (card.name == "sha") return true; }, }, - intro: { content: "不能成为其他角色$牌的目标" }, + mark: true, + intro: { + content: "使用【杀】无距离和次数限制且伤害+1", + }, }, - //高干 - juguan: { + //潘淑 + weiyi: { + trigger: { global: "damageEnd" }, + filter: function (event, player) { + if (player.getStorage("weiyi").includes(event.player) || !event.player.isIn()) return false; + return event.player.hp >= player.hp || event.player.isDamaged(); + }, + direct: true, + content: function () { + "step 0"; + var list = []; + if (trigger.player.hp >= player.hp) list.push("失去体力"); + if (trigger.player.hp <= player.hp && trigger.player.isDamaged()) list.push("回复体力"); + list.push("cancel2"); + player + .chooseControl(list) + .set("prompt", get.prompt2("weiyi", trigger.player)) + .set("ai", function () { + var player = _status.event.player, + target = _status.event.getTrigger().player; + var att = get.attitude(player, target), + eff = get.recoverEffect(target, player, player); + if (target.hp <= player.hp && target.isDamaged() && att > 2 && eff > 0) { + if (player == target) { + var storage = player.getStorage("weiyi"); + if ( + player.hp >= 2 && + game.hasPlayer(function (current) { + return current.hp == player.hp + 1 && !storage.includes(current) && get.attitude(player, current) < 0; + }) + ) + return "cancel2"; + } + return "回复体力"; + } + if (target.hp >= player.hp && att < -2 && eff < 0) return "失去体力"; + return "cancel2"; + }); + "step 1"; + if (result.control != "cancel2") { + var target = trigger.player; + player.logSkill("weiyi", target); + player.markAuto("weiyi", [target]); + target[result.control == "失去体力" ? "loseHp" : "recover"](); + } + }, + onremove: true, + intro: { + content: "已令$对汝威服", + }, + }, + jinzhi: { audio: 2, - enable: "phaseUse", - usable: 1, + enable: ["chooseToUse", "chooseToRespond"], + hiddenCard: function (player, name) { + if (get.type(name) == "basic" && lib.inpile.includes(name) && player.countMark("jinzhi2") < player.countCards("he")) return true; + }, filter: function (event, player) { - return ( - event.filterCard( - { - name: "sha", - }, - player, - event - ) || - event.filterCard( - { - name: "juedou", - }, - player, - event - ) - ); + if (event.responded || event.jinzhi || player.countMark("jinzhi2") >= player.countCards("he")) return false; + for (var i of lib.inpile) { + if (get.type(i) == "basic" && event.filterCard({ name: i, isCard: true }, player, event)) return true; + } + return false; }, chooseButton: { - dialog: function () { - return ui.create.dialog("拒关", [["sha", "juedou"], "vcard"]); - }, - filter: function (button, player) { - var evt = _status.event.getParent(); - return evt.filterCard( - { - name: button.link[2], - }, - player, - evt - ); + dialog: function (event, player) { + var list = []; + for (var i of lib.inpile) { + if (get.type(i) == "basic" && event.filterCard({ name: i, isCard: true }, player, event)) { + list.push(["基本", "", i]); + if (i == "sha") { + for (var j of lib.inpile_nature) list.push(["基本", "", "sha", j]); + } + } + } + return ui.create.dialog("锦织", [list, "vcard"], "hidden"); }, check: function (button) { - return ( - _status.event.player.getUseValue({ - name: button.link[2], - }) * (button.link[2] == "juedou" ? 3 : 1) - ); + if (_status.event.getParent().type != "phase") return 1; + if (button.link[2] == "shan") return 3; + var player = _status.event.player; + if (button.link[2] == "jiu") { + if (player.getUseValue({ name: "jiu" }) <= 0) return 0; + if (player.countCards("h", "sha")) return player.getUseValue({ name: "jiu" }); + } + return player.getUseValue({ name: button.link[2], nature: button.link[3] }) / 4; }, - backup: function (links) { + backup: function (links, player) { return { - audio: "juguan", - viewAs: { name: links[0][2] }, - filterCard: true, + selectCard: player.countMark("jinzhi2") + 1, + filterCard: function (card, player) { + if (ui.selected.cards.length) { + if (get.color(card) != get.color(ui.selected.cards[0])) return false; + } + return lib.filter.cardDiscardable.apply(this, arguments); + }, + complexCard: true, + viewAs: { + name: links[0][2], + nature: links[0][3], + suit: "none", + number: null, + isCard: true, + }, + position: "he", + ignoreMod: true, check: function (card) { - return 6 - get.value(card); + var player = _status.event.player, + color = get.color(card, player); + if (player.countCards("he", { color: color }) <= player.countMark("jinzhi2") || (ui.selected.cards.length && get.color(ui.selected.cards[0], player) != color)) return -1; + if ( + lib.skill.jinzhi_backup.viewAs.name == "jiu" && + !player.countCards("h", function (cardx) { + return card != cardx && !ui.selected.cards.includes(cardx) && get.name(cardx, player) == "sha"; + }) + ) + return 0; + return Math.min(0.01, 6 - get.value(card)); }, - position: "hs", - onuse: function (result, player) { - player.addTempSkill("juguan_effect"); + precontent: function () { + player.logSkill("jinzhi"); + player.addTempSkill("jinzhi2", "roundStart"); + player.addMark("jinzhi2", 1, false); + var cards = event.result.cards; + player.discard(cards); + player.draw(); + event.result.card = { + name: event.result.card.name, + nature: event.result.card.nature, + isCard: true, + }; + event.result.cards = []; + delete event.result.skill; + if (cards.length > 1) { + var color = get.color(cards[0], player); + for (var i = 1; i < cards.length; i++) { + if (get.color(cards[i], player) != color) { + var evt = event.getParent(); + evt.set("jinzhi", true); + evt.goto(0); + return; + } + } + } }, }; }, - prompt: function (links) { - return "将一张手牌当做" + get.translation(links[0][2]) + "使用"; + prompt: function (links, player) { + var name = links[0][2]; + var nature = links[0][3]; + return "弃置" + get.cnNumber(player.countMark("jinzhi2") + 1) + "张颜色相同的牌并摸一张牌,然后视为使用" + (get.translation(nature) || "") + get.translation(name); }, }, ai: { order: function (item, player) { - return Math.max(get.order({ name: "sha" }), get.order({ name: "juedou" })) + 0.2; - }, - result: { player: 1 }, - }, - subSkill: { - effect: { - trigger: { global: "damage" }, - forced: true, - charlotte: true, - firstDo: true, - silent: true, - popup: false, - filter: function (event, player) { - var evt = event.getParent("useCard"); - return event.card && evt && event.card == evt.card && evt.skill == "juguan_backup" && evt.player == player; - }, - content: function () { - player.addSkill("juguan_draw"); - player.markAuto("juguan_draw", [trigger.player]); - }, + if (_status.event.type == "phase" && !player.countMark("jinzhi2") && player.getUseValue({ name: "jiu" }, null, true) > 0 && player.countCards("h", "sha")) return get.order({ name: "jiu" }) + 1; + return 1; }, - draw: { - audio: "juguan", - trigger: { player: "phaseDrawBegin" }, - forced: true, - charlotte: true, - onremove: true, - content: function () { - player.removeSkill("juguan_draw"); - if (!trigger.numFixed) trigger.num += 2; - }, - group: "juguan_clear", - intro: { - content: "若没有受到$的伤害,则下个摸牌阶段多摸两张牌", - }, + respondShan: true, + respondSha: true, + skillTagFilter: function (player) { + if (player.countMark("jinzhi2") >= player.countCards("he")) return false; }, - clear: { - trigger: { player: "damage" }, - forced: true, - charlotte: true, - firstDo: true, - silent: true, - popup: false, - filter: function (event, player) { - return player.storage.juguan_draw && player.storage.juguan_draw.includes(event.source); - }, - content: function () { - player.unmarkAuto("juguan_draw", [trigger.source]); - if (!player.storage.juguan_draw || !player.storage.juguan_draw.length) player.removeSkill("juguan_draw"); + result: { + player: function (player) { + if (_status.event.dying) return get.attitude(player, _status.event.dying); + return 1; }, }, }, }, - //OL鲍三娘 - olwuniang: { - audio: "xinfu_wuniang", - trigger: { player: "useCardAfter" }, - usable: 1, - filter: function (event, player) { - return event.card.name == "sha" && event.targets.length == 1 && event.targets[0].isIn(); - }, - logTarget: "targets", - content: function () { - "step 0"; - var target = trigger.targets[0]; - target - .chooseToUse(function (card, player, event) { - if (get.name(card) != "sha") return false; - return lib.filter.filterCard.apply(this, arguments); - }, "武娘:是否对" + get.translation(player) + "使用一张杀?") - .set("targetRequired", true) - .set("complexSelect", true) - .set("filterTarget", function (card, player, target) { - if (target != _status.event.sourcex && !ui.selected.targets.includes(_status.event.sourcex)) return false; - return lib.filter.filterTarget.apply(this, arguments); - }) - .set("sourcex", player); - "step 1"; - player.addTempSkill("olwuniang2"); - player.addMark("olwuniang2", 1, false); - player.draw(); - }, - }, - olwuniang2: { + jinzhi2: { onremove: true, - charlotte: true, - mod: { - cardUsable: function (card, player, num) { - if (card.name == "sha") return num + player.countMark("olwuniang2"); - }, + intro: { + content: "本轮已发动过#次", }, }, - olxushen: { - derivation: "olzhennan", - audio: "xinfu_xushen", - trigger: { player: "dying" }, - limited: true, - skillAnimation: true, - animationColor: "fire", + //宗预 + zyqiao: { + audio: 2, + trigger: { target: "useCardToTargeted" }, + logTarget: "player", + usable: 2, + preHidden: true, filter: function (event, player) { - return player.hp < 1; + var source = event.player; + if (source == player) return false; + if (get.mode() == "guozhan" && source.isFriendOf(player)) return false; + return source.countDiscardableCards(player, "he") > 0; }, - content: function () { - "step 0"; - player.awakenSkill("olxushen"); - player.addSkills("olzhennan"); - player.recover(1 - player.hp); - "step 1"; + check: function (event, player) { + var target = event.player; + if (get.attitude(player, target) >= 0) return false; if ( - !player.isDying() && - !game.hasPlayer(function (current) { - return current.name1 == "guansuo" || current.name2 == "guansuo"; + !player.countCards("he", function (card) { + return lib.filter.cardDiscardable(card, player, "zyqiao"); }) - ) { - player - .chooseTarget(function (card, player, current) { - return current != player && current.hasSex("male"); - }, "许身:是否令一名其他男性角色选择是否将其武将牌替换为“关索”?") - .set("ai", function (target) { - return get.attitude(_status.event.player, target) - 4; - }); - } else event.finish(); - "step 2"; - if (!result.bool) { - event.finish(); - return; - } - var target = result.targets[0]; - event.target = target; - player.line(target, "fire"); - target.chooseBool("许身:是否将自己的一张武将牌替换为“关索”?"); - "step 3"; - if (result.bool) { - if (target.name2 != undefined) { - target.chooseControl(target.name1, target.name2).set("prompt", "请选择要更换的武将牌"); - } else event._result = { control: target.name1 }; - } else event.finish(); - "step 4"; - target.reinitCharacter(result.control, "guansuo"); - }, - }, - olzhennan: { - audio: "xinfu_zhennan", - enable: "phaseUse", - usable: 1, - viewAs: { name: "nanman" }, - filterCard: true, - selectCard: function () { - if (ui.selected.targets.length) return [ui.selected.targets.length, Math.min(ui.selected.targets.length + 1, game.players.length - 1)]; - return [1, Infinity]; + ) + return true; + if (player.countCards("he", card => get.value(card, player) < 5)) return true; + if (target.countCards("he", card => get.value(card, target) > 6) && player.countCards("he", card => get.value(card, player) < 7)) return true; + return false; }, - check: function (card) { - var player = _status.event.player; + content: function () { + "step 0"; + player.discardPlayerCard(trigger.player, true, "he"); + "step 1"; if ( - game.countPlayer(function (current) { - return current != player && player.canUse("nanman", current) && get.effect(current, { name: "nanman" }, player, player) > 0; - }) <= ui.selected.cards.length + player.countCards("he", function (card) { + return lib.filter.cardDiscardable(card, player, "zyqiao"); + }) ) - return 0; - return 6 - get.value(card); - }, - selectTarget: function () { - return ui.selected.cards.length; - }, - ai: { - order: 2, + player.chooseToDiscard("he", true); }, - group: "olzhennan2", }, - olzhennan2: { - trigger: { target: "useCardToBefore" }, - forced: true, - locked: false, - audio: "olzhennan", + chengshang: { + audio: 2, + trigger: { player: "useCardAfter" }, filter: function (event, player) { - return event.card.name == "nanman"; + if (!lib.suit.includes(get.suit(event.card, false)) || typeof get.number(event.card) != "number") return false; + if ( + player.getHistory("sourceDamage", function (evt) { + return evt.card == event.card; + }).length + ) + return false; + var phsu = event.getParent("phaseUse"); + if (!phsu || phsu.player != player) return false; + if ( + player.getHistory("gain", function (evt) { + return evt.getParent().name == "chengshang" && phsu === evt.getParent("phaseUse"); + }).length + ) + return false; + for (var i of event.targets) { + if (i != player && (get.mode() != "guozhan" || i.isEnemyOf(player))) return true; + } + return false; }, + preHidden: true, content: function () { - trigger.cancel(); + var suit = get.suit(trigger.card); + var number = get.number(trigger.card); + var cards = []; + for (var i = 0; i < ui.cardPile.childNodes.length; i++) { + var card = ui.cardPile.childNodes[i]; + if (card.suit == suit && card.number == number) cards.push(card); + } + if (cards.length) player.gain(cards, "gain2"); }, }, - //黄承彦 - guanxu: { - enable: "phaseUse", - usable: 1, + //新丁奉 + reduanbing: { + audio: "duanbing", + audioname2: { heqi: "duanbing_heqi" }, + trigger: { player: "useCard2" }, filter: function (event, player) { - return game.hasPlayer(current => lib.skill.guanxu.filterTarget(null, player, current)); - }, - filterTarget: function (card, player, target) { - return target != player && target.countCards("h") > 0; + if (event.card.name != "sha") return false; + return game.hasPlayer(function (current) { + return !event.targets.includes(current) && get.distance(player, current) <= 1 && player.canUse(event.card, current); + }); }, + direct: true, + preHidden: ["reduanbing_sha"], content: function () { "step 0"; - var cards = get.cards(5); - for (var i = cards.length - 1; i >= 0; i--) { - ui.cardPile.insertBefore(cards[i], ui.cardPile.firstChild); - } - game.updateRoundNumber(); - var hs = target.getCards("h"); - var dialog = ["观虚:选择要操作的牌", '
    ' + get.translation(target) + "的手牌
    ", hs, '
    牌堆顶
    ', cards]; player - .chooseButton(dialog, 2) - .set("filterButton", function (button) { - if (ui.selected.buttons.length) return get.position(button.link) != get.position(ui.selected.buttons[0].link); - return true; + .chooseTarget(get.prompt("reduanbing"), "为" + get.translation(trigger.card) + "增加一个目标", function (card, player, target) { + return !_status.event.sourcex.includes(target) && get.distance(player, target) <= 1 && player.canUse(_status.event.card, target); }) - .set("cards1", hs) - .set("cards2", cards) - .set("ai", function (button) { - var card = button.link, - cards1 = _status.event.cards1.slice(0); - var cards2 = _status.event.cards2.slice(0), - target = _status.event.getParent().target; - if (!ui.selected.buttons.length) { - if (!cards1.includes(card)) return 0; - cards1.remove(card); - var suits = cards2.map(function (i) { - return get.suit(i, target); - }); - for (var i of lib.suit) { - var num = cards1.filter(function (c) { - return get.suit(c, target) == i; - }).length; - if (num > 2 || (num > 1 && suits.includes(i))) return 20 + get.value(card); - } - return get.value(card); - } - cards1.remove(ui.selected.buttons[0].link); - cards1.push(card); - for (var i of lib.suit) { - if ( - cards1.filter(function (c) { - return get.suit(c, target) == i; - }).length > 2 - ) - return 20 - get.value(card); - return get.value(ui.selected.buttons[0].link) - get.value(card); - } - }); + .set("sourcex", trigger.targets) + .set("ai", function (target) { + var player = _status.event.player; + return get.effect(target, _status.event.card, player, player); + }) + .set("card", trigger.card) + .setHiddenSkill(event.name); "step 1"; if (result.bool) { - var cards = result.links; - if (get.position(cards[0]) != "h") cards.reverse(); - var next = target.lose(cards[0], ui.cardPile); - next.insert_index_card = cards[1]; - next.insert_index = function (event) { - return event.insert_index_card; - }; - target.gain(cards[1], "draw"); - } else event.finish(); - "step 2"; - game.updateRoundNumber(); - var suits = [], - map = {}, - hs = target.getCards("h"); - if (hs.length) { - for (var i of hs) { - if (!lib.filter.canBeDiscarded(i, player, target, "guanxu")) continue; - var suit = get.suit(i, target); - if (!map[suit]) map[suit] = 1; - else map[suit]++; - if (map[suit] > 2) suits.add(suit); - } - var next = player.discardPlayerCard(target, 3, "visible", "h"); - next.set("suits", suits); - next.set("filterButton", function (button) { - var suit = get.suit(button.link); - if (!ui.selected.buttons.length) return _status.event.suits.includes(suit); - return suit == get.suit(ui.selected.buttons[0].link); - }); - if (suits.length) next.set("forced", true); + if (!event.isMine() && !event.isOnline()) game.delayx(); + event.target = result.targets[0]; + } else { + event.finish(); } + "step 2"; + player.logSkill("reduanbing", event.target); + trigger.targets.push(event.target); }, ai: { - order: 9, + effect: { + player_use: function (card, player, target, current, isLink) { + if (!isLink && card.name == "sha") { + if (player._reduanbingtmp) return; + player._reduanbingtmp = true; + if (get.effect(target, card, player, player) <= 0) { + delete player._reduanbingtmp; + return; + } + if ( + game.hasPlayer(function (current) { + return current != target && get.distance(player, current) <= 1 && player.canUse(card, current) && get.effect(current, card, player, player) > 0; + }) + ) { + delete player._reduanbingtmp; + return [1, 1]; + } + delete player._reduanbingtmp; + } + }, + }, + }, + group: "reduanbing_sha", + subSkill: { + sha: { + audio: "duanbing", + audioname: ["heqi"], + trigger: { player: "useCardToPlayered" }, + forced: true, + filter: function (event, player) { + return event.card.name == "sha" && !event.getParent().directHit.includes(event.target) && get.distance(player, event.target) <= 1; + }, + logTarget: "target", + content: function () { + var id = trigger.target.playerid; + var map = trigger.getParent().customArgs; + if (!map[id]) map[id] = {}; + if (typeof map[id].shanRequired == "number") { + map[id].shanRequired++; + } else { + map[id].shanRequired = 2; + } + }, + ai: { + directHit_ai: true, + skillTagFilter: function (player, tag, arg) { + if (arg.card.name != "sha" || arg.target.countCards("h", "shan") > 1 || get.distance(player, arg.target) > 1) return false; + }, + }, + }, + }, + }, + refenxun: { + audio: "fenxun", + enable: "phaseUse", + usable: 1, + position: "he", + filterTarget: function (card, player, target) { + return target != player; + }, + content: function () { + player.markAuto("refenxun2", targets); + player.addTempSkill("refenxun2"); + }, + ai: { + order: 6.5, result: { - target: function (player, target) { - if (target.countCards("h") > 3) return -5; - if (target.countCards("h") == 3) return -3; - return -0.5; + player: function (player, target) { + if (get.distance(player, target) <= 1) return 0; + var hs = player.getCards("h", "shunshou"); + if (hs.length && player.canUse(hs[0], target, false)) { + return 1; + } + var geteff = function (current) { + return player.canUse("sha", current, false, true) && get.effect(current, { name: "sha" }, player, player) > 0; + }; + if (player.hasSha() && geteff(target)) { + var num = game.countPlayer(function (current) { + return current != player && get.distance(player, current) <= 1 && geteff(current); + }); + if (num == 0) { + if ( + game.hasPlayer(function (current) { + return player.canUse("sha", current) && geteff(current) && current != target; + }) + ) { + return 1; + } + } else if (num == 1) { + return 1; + } + } + return 0; }, }, }, }, - yashi: { - trigger: { player: "damageEnd" }, - direct: true, - filter: function (event, player) { - if (event.source && event.source.isIn()) return true; - return game.hasPlayer(current => lib.skill.guanxu.filterTarget(null, player, current)); - }, - content: function () { - "step 0"; - event.addIndex = 0; - var choiceList = []; - if (trigger.source && trigger.source.isIn()) { - choiceList.push("令" + get.translation(trigger.source) + "的所有非锁定技失效"); - } else event.addIndex++; - if (game.hasPlayer(current => lib.skill.guanxu.filterTarget(null, player, current))) choiceList.push("发动一次〖观虚〗"); - player - .chooseControl("cancel2") - .set("prompt", get.prompt("yashi")) - .set("choiceList", choiceList) - .set("ai", function () { - var player = _status.event.player, - source = _status.event.getTrigger().source, - index = _status.event.getParent().addIndex; - if ( - game.hasPlayer(function (current) { - return current != player && current.countCards("h") > 3 && get.attitude(player, current) < 0; - }) - ) - return 1 - index; - if (source && source.isIn() && get.attitude(player, source) < 0 && !source.hasSkill("fengyin")) return 0; - if ( - game.hasPlayer(function (current) { - return current != player && current.countCards("h") > 0 && get.attitude(player, current) < 0; - }) - ) - return 1 - index; - return "cancel2"; - }); - "step 1"; - if (result.control != "cancel2") { - if (result.index + event.addIndex == 0) { - var target = trigger.source; - player.logSkill("yashi", target); - //target.removeSkill('fengyin'); - target.addTempSkill("fengyin", { player: "phaseBegin" }); - event.finish(); - } else - player.chooseTarget(true, "请选择〖观虚〗的目标", lib.skill.guanxu.filterTarget).set("ai", function (target) { - var player = _status.event.player; - return get.effect(target, "guanxu", player, player); - }); - } else event.finish(); - "step 2"; - if (result.bool) { - var target = result.targets[0]; - player.logSkill("yashi", target); - var next = game.createEvent("yashi_guanxu"); - next.player = player; - next.target = target; - next.setContent(lib.skill.guanxu.content); - } + refenxun2: { + audio: "fenxun", + trigger: { + player: "phaseJieshuBegin", }, - }, - //黄祖 - wangong: { - audio: 2, - trigger: { player: "useCard" }, forced: true, + charlotte: true, filter: function (event, player) { - return get.type(event.card, false) == "basic"; + return ( + player.getHistory("sourceDamage", function (evt) { + return player.storage.refenxun2.includes(evt.player); + }).length == 0 && + player.countCards("he", function (card) { + return lib.filter.cardDiscardable(card, player, "refenxun2"); + }) > 0 + ); }, content: function () { - player.addSkill("wangong2"); + player.chooseToDiscard("he", true); }, - }, - wangong2: { - trigger: { player: "useCard1" }, - forced: true, - popup: false, - firstDo: true, - charlotte: true, - content: function () { - player.removeSkill("wangong2"); - if (trigger.card.name == "sha") trigger.baseDamage++; + onremove: true, + intro: { + content: "到$的距离视为1", }, mod: { - cardUsable: function (card) { - if (card.name == "sha") return Infinity; + globalFrom: function (from, to) { + if (from.storage.refenxun2.includes(to)) { + return -Infinity; + } }, - targetInRange: function (card) { - if (card.name == "sha") return true; + }, + }, + //蔡阳新技能 + zhuixi: { + mod: { + cardUsable: function (card, player, num) { + if (card.name == "sha") return num + 1; }, }, - mark: true, - intro: { - content: "使用【杀】无距离和次数限制且伤害+1", + }, + //新塌顿 + reluanzhan: { + audio: "luanzhan", + trigger: { + player: "damageEnd", + source: "damageSource", + }, + forced: true, + locked: false, + content: function () { + player.addMark("reluanzhan", 1, false); }, + intro: { content: "mark" }, + ai: { notemp: true }, + group: ["reluanzhan_add", "reluanzhan_remove"], }, - //潘淑 - weiyi: { - trigger: { global: "damageEnd" }, + reluanzhan_add: { + trigger: { player: "useCard2" }, + direct: true, filter: function (event, player) { - if (player.getStorage("weiyi").includes(event.player) || !event.player.isIn()) return false; - return event.player.hp >= player.hp || event.player.isDamaged(); + if ((event.card.name != "sha" && (get.color(event.card) != "black" || get.type(event.card) != "trick")) || !player.countMark("reluanzhan")) return false; + var info = get.info(event.card); + if (info.allowMultiple == false) return false; + if (event.targets && !info.multitarget) { + if ( + game.hasPlayer(function (current) { + return !event.targets.includes(current) && lib.filter.targetEnabled2(event.card, player, current) && lib.filter.targetInRange(event.card, player, current); + }) + ) { + return true; + } + } + return false; }, - direct: true, content: function () { "step 0"; - var list = []; - if (trigger.player.hp >= player.hp) list.push("失去体力"); - if (trigger.player.hp <= player.hp && trigger.player.isDamaged()) list.push("回复体力"); - list.push("cancel2"); + var num = player.countMark("reluanzhan"); + var prompt2 = "为" + get.translation(trigger.card) + "增加至多" + get.cnNumber(num) + "个目标"; player - .chooseControl(list) - .set("prompt", get.prompt2("weiyi", trigger.player)) - .set("ai", function () { - var player = _status.event.player, - target = _status.event.getTrigger().player; - var att = get.attitude(player, target), - eff = get.recoverEffect(target, player, player); - if (target.hp <= player.hp && target.isDamaged() && att > 2 && eff > 0) { - if (player == target) { - var storage = player.getStorage("weiyi"); - if ( - player.hp >= 2 && - game.hasPlayer(function (current) { - return current.hp == player.hp + 1 && !storage.includes(current) && get.attitude(player, current) < 0; - }) - ) - return "cancel2"; - } - return "回复体力"; - } - if (target.hp >= player.hp && att < -2 && eff < 0) return "失去体力"; - return "cancel2"; - }); + .chooseTarget( + get.prompt("reluanzhan"), + function (card, player, target) { + if (_status.event.targets.includes(target)) return false; + var player = _status.event.player; + return lib.filter.targetEnabled2(_status.event.card, player, target) && lib.filter.targetInRange(_status.event.card, player, target); + }, + [1, num] + ) + .set("prompt2", prompt2) + .set("ai", function (target) { + var trigger = _status.event.getTrigger(); + var player = _status.event.player; + return get.effect(target, trigger.card, player, player); + }) + .set("card", trigger.card) + .set("targets", trigger.targets); "step 1"; - if (result.control != "cancel2") { - var target = trigger.player; - player.logSkill("weiyi", target); - player.markAuto("weiyi", [target]); - target[result.control == "失去体力" ? "loseHp" : "recover"](); + if (result.bool) { + if (!event.isMine() && !event.isOnline()) game.delayx(); + event.targets = result.targets; + } else { + event.finish(); + } + "step 2"; + if (event.targets) { + player.logSkill("reluanzhan", event.targets); + trigger.targets.addArray(event.targets); } }, - onremove: true, - intro: { - content: "已令$对汝威服", + }, + reluanzhan_remove: { + audio: "luanzhan", + trigger: { player: "useCardToPlayered" }, + forced: true, + locked: false, + filter: function (event, player) { + if (!event.isFirstTarget || (event.card.name != "sha" && (get.color(event.card) != "black" || get.type(event.card) != "trick")) || !player.countMark("reluanzhan")) return false; + var info = get.info(event.card); + if (info.allowMultiple == false || info.multitarget) return false; + return event.targets.length < player.countMark("reluanzhan"); + }, + content: function () { + player.removeMark("reluanzhan", Math.ceil(player.countMark("reluanzhan") / 2)); }, }, - jinzhi: { + //卧龙凤雏双头祈福 + youlong: { + enable: "chooseToUse", audio: 2, - enable: ["chooseToUse", "chooseToRespond"], + audioname: ["key_sakuya"], + zhuanhuanji: true, + marktext: "☯", + mark: true, + intro: { + content: function (storage, player) { + return storage ? "每轮限一次,你可以废除你的一个装备栏,视为使用一张未以此法使用过的基本牌。" : "每轮限一次,你可以废除你的一个装备栏,视为使用一张未以此法使用过的普通锦囊牌。"; + }, + }, + init: function (player) { + player.storage.youlong = false; + if (!player.storage.youlong2) player.storage.youlong2 = []; + }, hiddenCard: function (player, name) { - if (get.type(name) == "basic" && lib.inpile.includes(name) && player.countMark("jinzhi2") < player.countCards("he")) return true; + if (player.storage.youlong2.includes(name) || !player.hasEnabledSlot()) return false; + if (player.hasSkill("youlong_" + (player.storage.youlong || false))) return false; + var type = get.type(name); + if (player.storage.youlong) return type == "basic"; + return type == "trick"; }, filter: function (event, player) { - if (event.responded || event.jinzhi || player.countMark("jinzhi2") >= player.countCards("he")) return false; - for (var i of lib.inpile) { - if (get.type(i) == "basic" && event.filterCard({ name: i, isCard: true }, player, event)) return true; + if (player.storage.youlong2.includes(name) || !player.hasEnabledSlot()) return false; + if (player.hasSkill("youlong_" + (player.storage.youlong || false))) return false; + var type = player.storage.youlong ? "basic" : "trick"; + for (var name of lib.inpile) { + if (player.storage.youlong2.includes(name)) continue; + if (get.type(name) != type) continue; + if (event.filterCard({ name: name, isCard: true }, player, event)) return true; } return false; }, chooseButton: { dialog: function (event, player) { + var dialog = ui.create.dialog("游龙", "hidden"); + const equips = []; + for (let i = 1; i < 6; i++) { + if (!player.hasEnabledSlot(i)) continue; + equips.push([i, get.translation("equip" + i)]); + } + if (equips.length > 0) dialog.add([equips, "tdnodes"]); + var type = player.storage.youlong ? "basic" : "trick"; var list = []; - for (var i of lib.inpile) { - if (get.type(i) == "basic" && event.filterCard({ name: i, isCard: true }, player, event)) { - list.push(["基本", "", i]); - if (i == "sha") { + for (var name of lib.inpile) { + if (player.storage.youlong2.includes(name)) continue; + if (get.type(name) != type) continue; + if (event.filterCard({ name: name, isCard: true }, player, event)) { + list.push([type, "", name]); + if (name == "sha") { for (var j of lib.inpile_nature) list.push(["基本", "", "sha", j]); } } } - return ui.create.dialog("锦织", [list, "vcard"], "hidden"); + dialog.add([list, "vcard"]); + return dialog; + }, + filter: function (button) { + if (ui.selected.buttons.length && typeof button.link == typeof ui.selected.buttons[0].link) return false; + return true; }, + select: 2, check: function (button) { - if (button.link[2] == "shan") return 3; var player = _status.event.player; - if (button.link[2] == "jiu") { - if (player.getUseValue({ name: "jiu" }) <= 0) return 0; - if (player.countCards("h", "sha")) return player.getUseValue({ name: "jiu" }); + if (typeof button.link == "number") { + var card = player.getEquip(button.link); + if (card) { + var val = get.value(card); + if (val > 0) return 0; + return 5 - val; + } + switch (button.link) { + case 3: + return 4.5; + case 4: + return 4.4; + case 5: + return 4.3; + case 2: + return (3 - player.hp) * 1.5; + case 1: { + if ( + game.hasPlayer(function (current) { + return (get.realAttitude || get.attitude)(player, current) < 0 && get.distance(player, current) > 1; + }) + ) + return 0; + return 3.2; + } + } } - return player.getUseValue({ name: button.link[2], nature: button.link[3] }) / 4; + var name = button.link[2]; + var evt = _status.event.getParent(); + if (evt.type == "phase") { + var card = { name: name, nature: button.link[3], isCard: true }; + if (name == "shan") return 2; + if (evt.type == "dying") { + if (get.attitude(player, evt.dying) < 2) return false; + if (name == "jiu") return 2.1; + return 1.9; + } + return player.getUseValue(card); + } + return 1; }, backup: function (links, player) { + if (typeof links[1] == "number") links.reverse(); + var equip = links[0]; + var name = links[1][2]; + var nature = links[1][3]; return { - selectCard: player.countMark("jinzhi2") + 1, - filterCard: function (card, player) { - if (ui.selected.cards.length) { - if (get.color(card) != get.color(ui.selected.cards[0])) return false; - } - return lib.filter.cardDiscardable.apply(this, arguments); + filterCard: function () { + return false; }, - complexCard: true, + selectCard: -1, + equip: equip, viewAs: { - name: links[0][2], - nature: links[0][3], - suit: "none", - number: null, + name: name, + nature: nature, isCard: true, }, - position: "he", - ignoreMod: true, - check: function (card) { - var player = _status.event.player, - color = get.color(card, player); - if (player.countCards("he", { color: color }) <= player.countMark("jinzhi2") || (ui.selected.cards.length && get.color(ui.selected.cards[0], player) != color)) return -1; - if ( - lib.skill.jinzhi_backup.viewAs.name == "jiu" && - !player.countCards("h", function (cardx) { - return card != cardx && !ui.selected.cards.includes(cardx) && get.name(cardx, player) == "sha"; - }) - ) - return 0; - return Math.min(0.01, 6 - get.value(card)); - }, + popname: true, precontent: function () { - player.logSkill("jinzhi"); - player.addTempSkill("jinzhi2", "roundStart"); - player.addMark("jinzhi2", 1, false); - var cards = event.result.cards; - player.discard(cards); - player.draw(); - event.result.card = { - name: event.result.card.name, - nature: event.result.card.nature, - isCard: true, - }; - event.result.cards = []; + player.logSkill("youlong"); + player.disableEquip(lib.skill.youlong_backup.equip); delete event.result.skill; - if (cards.length > 1) { - var color = get.color(cards[0], player); - for (var i = 1; i < cards.length; i++) { - if (get.color(cards[i], player) != color) { - var evt = event.getParent(); - evt.set("jinzhi", true); - evt.goto(0); - return; - } - } - } + player.addTempSkill("youlong_" + (player.storage.youlong || false), "roundStart"); + player.changeZhuanhuanji("youlong"); + player.storage.youlong2.add(event.result.card.name); }, }; }, prompt: function (links, player) { - var name = links[0][2]; - var nature = links[0][3]; - return "弃置" + get.cnNumber(player.countMark("jinzhi2") + 1) + "张颜色相同的牌并摸一张牌,然后视为使用" + (get.translation(nature) || "") + get.translation(name); + if (typeof links[1] == "number") links.reverse(); + var equip = "equip" + links[0]; + var name = links[1][2]; + var nature = links[1][3]; + return "废除自己的" + get.translation(equip) + "栏,视为使用" + (get.translation(nature) || "") + get.translation(name); }, }, ai: { + respondSha: true, + respondShan: true, + skillTagFilter: function (player, tag, arg) { + if (arg == "respond") return false; + if (!player.storage.youlong || player.hasSkill("youlong_true")) return false; + var name = tag == "respondSha" ? "sha" : "shan"; + return !player.storage.youlong2.includes(name); + }, order: function (item, player) { - if (_status.event.type == "phase" && !player.countMark("jinzhi2") && player.getUseValue({ name: "jiu" }, null, true) > 0 && player.countCards("h", "sha")) return get.order({ name: "jiu" }) + 1; + if (player && _status.event.type == "phase") { + var max = 0, + add = false; + var type = player.storage.youlong ? "basic" : "trick"; + var list = lib.inpile.filter(name => get.type(name) == type && !player.storage.youlong2.includes(name)); + if (list.includes("sha")) add = true; + list = list.map(namex => { + return { name: namex, isCard: true }; + }); + if (add) lib.inpile_nature.forEach(naturex => list.push({ name: "sha", nature: naturex, isCard: true })); + for (var card of list) { + if (player.getUseValue(card) > 0) { + var temp = get.order(card); + if (temp > max) max = temp; + } + } + if (max > 0) max += 0.3; + return max; + } return 1; }, - respondShan: true, - respondSha: true, - skillTagFilter: function (player) { - if (player.countMark("jinzhi2") >= player.countCards("he")) return false; - }, result: { player: function (player) { if (_status.event.dying) return get.attitude(player, _status.event.dying); @@ -16038,13529 +17263,14720 @@ const skills = { }, }, }, - jinzhi2: { - onremove: true, - intro: { - content: "本轮已发动过#次", - }, - }, - //宗预 - zyqiao: { + youlong_true: { charlotte: true }, + youlong_false: { charlotte: true }, + luanfeng: { audio: 2, - trigger: { target: "useCardToTargeted" }, - logTarget: "player", - usable: 2, - preHidden: true, + audioname: ["key_sakuya"], + trigger: { global: "dying" }, filter: function (event, player) { - var source = event.player; - if (source == player) return false; - if (get.mode() == "guozhan" && source.isFriendOf(player)) return false; - return source.countDiscardableCards(player, "he") > 0; + return event.player.maxHp >= player.maxHp && event.player.hp < 1; }, + limited: true, + skillAnimation: true, + animationColor: "soil", + logTarget: "player", check: function (event, player) { - var target = event.player; - if (get.attitude(player, target) >= 0) return false; - if ( - !player.countCards("he", function (card) { - return lib.filter.cardDiscardable(card, player, "zyqiao"); - }) - ) - return true; - if (player.countCards("he", card => get.value(card, player) < 5)) return true; - if (target.countCards("he", card => get.value(card, target) > 6) && player.countCards("he", card => get.value(card, player) < 7)) return true; - return false; - }, - content: function () { - "step 0"; - player.discardPlayerCard(trigger.player, true, "he"); - "step 1"; - if ( - player.countCards("he", function (card) { - return lib.filter.cardDiscardable(card, player, "zyqiao"); - }) - ) - player.chooseToDiscard("he", true); - }, - }, - chengshang: { - audio: 2, - trigger: { player: "useCardAfter" }, - filter: function (event, player) { - if (!lib.suit.includes(get.suit(event.card, false)) || typeof get.number(event.card) != "number") return false; - if ( - player.getHistory("sourceDamage", function (evt) { - return evt.card == event.card; - }).length - ) - return false; - var phsu = event.getParent("phaseUse"); - if (!phsu || phsu.player != player) return false; + if (get.attitude(player, event.player) < 4) return false; if ( - player.getHistory("gain", function (evt) { - return evt.getParent().name == "chengshang" && phsu === evt.getParent("phaseUse"); - }).length + player.countCards("h", function (card) { + var mod2 = game.checkMod(card, player, "unchanged", "cardEnabled2", player); + if (mod2 != "unchanged") return mod2; + var mod = game.checkMod(card, player, event.player, "unchanged", "cardSavable", player); + if (mod != "unchanged") return mod; + var savable = get.info(card).savable; + if (typeof savable == "function") savable = savable(card, player, event.player); + return savable; + }) >= + 1 - event.player.hp ) return false; - for (var i of event.targets) { - if (i != player && (get.mode() != "guozhan" || i.isEnemyOf(player))) return true; - } - return false; + if (event.player == player || event.player == get.zhu(player)) return true; + return !player.hasUnknown(); }, - preHidden: true, content: function () { - var suit = get.suit(trigger.card); - var number = get.number(trigger.card); - var cards = []; - for (var i = 0; i < ui.cardPile.childNodes.length; i++) { - var card = ui.cardPile.childNodes[i]; - if (card.suit == suit && card.number == number) cards.push(card); + "step 0"; + player.awakenSkill("luanfeng"); + trigger.player.recover(3 - trigger.player.hp); + "step 1"; + var list = [], + target = trigger.player; + for (var i = 1; i < 6; i++) { + for (var j = 0; j < target.countDisabledSlot(i); j++) { + list.push(i); + } } - if (cards.length) player.gain(cards, "gain2"); + if (list.length > 0) target.enableEquip(list); + if (list.length < 6) target.drawTo(6 - list.length); + if (target.storage.kotarou_rewrite) target.storage.kotarou_rewrite = []; + if (player == target) player.storage.youlong2 = []; }, }, - //新丁奉 - reduanbing: { - audio: "duanbing", - audioname2: { heqi: "duanbing_heqi" }, - trigger: { player: "useCard2" }, + //曹爽,韩遂,何进 + xiaoxi: { + audio: 2, + audioname: ["machao", "hansui", "pangde"], + trigger: { + player: "enterGame", + global: "phaseBefore", + }, filter: function (event, player) { - if (event.card.name != "sha") return false; - return game.hasPlayer(function (current) { - return !event.targets.includes(current) && get.distance(player, current) <= 1 && player.canUse(event.card, current); - }); + return event.name != "phase" || game.phaseNumber == 0; }, direct: true, - preHidden: ["reduanbing_sha"], + content: function () { + player.chooseUseTarget("sha", get.prompt("xiaoxi"), "视为使用一张【杀】").logSkill = "xiaoxi"; + }, + }, + spmouzhu: { + enable: "phaseUse", + audio: "mouzhu", + usable: 1, + filter: function (event, player) { + return game.hasPlayer(current => lib.skill.spmouzhu.filterTarget(null, player, current)); + }, + filterTarget: function (card, player, target) { + if (!target.countCards("h")) return false; + return player != target && (target.hp == player.hp || get.distance(player, target) == 1); + }, + selectTarget: [1, Infinity], content: function () { "step 0"; - player - .chooseTarget(get.prompt("reduanbing"), "为" + get.translation(trigger.card) + "增加一个目标", function (card, player, target) { - return !_status.event.sourcex.includes(target) && get.distance(player, target) <= 1 && player.canUse(_status.event.card, target); - }) - .set("sourcex", trigger.targets) - .set("ai", function (target) { - var player = _status.event.player; - return get.effect(target, _status.event.card, player, player); - }) - .set("card", trigger.card) - .setHiddenSkill(event.name); + target.chooseCard("h", "交给" + get.translation(player) + "一张牌", true); "step 1"; - if (result.bool) { - if (!event.isMine() && !event.isOnline()) game.delayx(); - event.target = result.targets[0]; - } else { + if (result.bool) target.give(result.cards, player); + "step 2"; + if (player.countCards("h") <= target.countCards("h")) { event.finish(); + return; } - "step 2"; - player.logSkill("reduanbing", event.target); - trigger.targets.push(event.target); + var list = []; + if (target.canUse("sha", player, false)) list.push("sha"); + if (target.canUse("juedou", player, false)) list.push("juedou"); + if (!list.length) event.finish(); + else if (list.length == 1) event._result = { control: list[0] }; + else + target.chooseControl(list).set("prompt", "对" + get.translation(player) + "使用一张【杀】或【决斗】。").ai = function () { + return get.effect(player, { name: "sha" }, target, target) >= get.effect(player, { name: "juedou" }, target, target) ? "sha" : "juedou"; + }; + "step 3"; + target.useCard({ name: result.control, isCard: true }, player, "noai"); }, ai: { - effect: { - player: function (card, player, target, current, isLink) { - if (!isLink && card.name == "sha") { - if (player._reduanbingtmp) return; - player._reduanbingtmp = true; - if (get.effect(target, card, player, player) <= 0) { - delete player._reduanbingtmp; - return; - } - if ( - game.hasPlayer(function (current) { - return current != target && get.distance(player, current) <= 1 && player.canUse(card, current) && get.effect(current, card, player, player) > 0; - }) - ) { - delete player._reduanbingtmp; - return [1, 1]; - } - delete player._reduanbingtmp; - } + order: 7, + result: { + target: -1.2, + player: function (player, target) { + if (ui.selected.targets.length) return 0; + if (target.countCards("h") - player.countCards("h") > 1) return 1; + if (get.damageEffect(target, player, player, player) > 0) return 1; + if (player.hp > 3 || (player.countCards("h", "sha") && player.countCards("h", "shan"))) return 0; + if (player.hp > 2) return -1.1; + return -2; }, }, }, - group: "reduanbing_sha", + }, + spyanhuo: { + audio: "yanhuo", + trigger: { player: "die" }, + forceDie: true, + skillAnimation: true, + animationColor: "soil", + content: function () { + player.line(game.players, "green"); + game.addGlobalSkill("spyanhuo_damage"); + game.broadcastAll(() => { + if (!_status.yanhuo) _status.yanhuo = 0; + _status.yanhuo++; + }); + }, subSkill: { - sha: { - audio: "duanbing", - audioname: ["heqi"], - trigger: { player: "useCardToPlayered" }, + damage: { + trigger: { player: "useCard" }, forced: true, filter: function (event, player) { - return event.card.name == "sha" && !event.getParent().directHit.includes(event.target) && get.distance(player, event.target) <= 1; + return event.card.name == "sha"; }, - logTarget: "target", content: function () { - var id = trigger.target.playerid; - var map = trigger.getParent().customArgs; - if (!map[id]) map[id] = {}; - if (typeof map[id].shanRequired == "number") { - map[id].shanRequired++; - } else { - map[id].shanRequired = 2; - } - }, - ai: { - directHit_ai: true, - skillTagFilter: function (player, tag, arg) { - if (arg.card.name != "sha" || arg.target.countCards("h", "shan") > 1 || get.distance(player, arg.target) > 1) return false; - }, + trigger.baseDamage += _status.yanhuo || 0; }, }, }, }, - refenxun: { - audio: "fenxun", + spniluan: { enable: "phaseUse", - usable: 1, - position: "he", - filterTarget: function (card, player, target) { - return target != player; - }, - content: function () { - player.markAuto("refenxun2", targets); - player.addTempSkill("refenxun2"); + audio: "niluan", + viewAs: { name: "sha" }, + check: function (card) { + return 5.1 - get.value(card); }, - ai: { - order: 6.5, - result: { - player: function (player, target) { - if (get.distance(player, target) <= 1) return 0; - var hs = player.getCards("h", "shunshou"); - if (hs.length && player.canUse(hs[0], target, false)) { - return 1; - } - var geteff = function (current) { - return player.canUse("sha", current, false, true) && get.effect(current, { name: "sha" }, player, player) > 0; - }; - if (player.hasSha() && geteff(target)) { - var num = game.countPlayer(function (current) { - return current != player && get.distance(player, current) <= 1 && geteff(current); - }); - if (num == 0) { - if ( - game.hasPlayer(function (current) { - return player.canUse("sha", current) && geteff(current) && current != target; - }) - ) { - return 1; - } - } else if (num == 1) { - return 1; - } - } - return 0; - }, - }, + filterCard: { color: "black" }, + position: "hes", + viewAsFilter: function (player) { + return player.countCards("hes", lib.skill.spniluan.filterCard) > 0; }, + group: "spniluan_clear", }, - refenxun2: { - audio: "fenxun", - trigger: { - player: "phaseJieshuBegin", - }, + spniluan_clear: { + trigger: { player: "useCardAfter" }, forced: true, + silent: true, charlotte: true, filter: function (event, player) { return ( - player.getHistory("sourceDamage", function (evt) { - return player.storage.refenxun2.includes(evt.player); - }).length == 0 && - player.countCards("he", function (card) { - return lib.filter.cardDiscardable(card, player, "refenxun2"); - }) > 0 + event.skill == "spniluan" && + event.addCount !== false && + player.getHistory("sourceDamage", function (card) { + return card.card == event.card; + }).length == 0 ); }, content: function () { - player.chooseToDiscard("he", true); - }, - onremove: true, - intro: { - content: "到$的距离视为1", - }, - mod: { - globalFrom: function (from, to) { - if (from.storage.refenxun2.includes(to)) { - return -Infinity; - } - }, + trigger.addCount = false; + if (player.stat[player.stat.length - 1].card.sha > 0) { + player.stat[player.stat.length - 1].card.sha--; + } }, }, - //蔡阳新技能 - zhuixi: { + spweiwu: { + audio: 2, + locked: false, + enable: "phaseUse", + usable: 1, + viewAs: { + name: "shunshou", + storage: { spweiwu: true }, + }, + filterCard: { color: "red" }, + position: "hes", + check: function (card) { + return 7 - get.value(card); + }, mod: { - cardUsable: function (card, player, num) { - if (card.name == "sha") return num + 1; + targetInRange: function (card) { + if (card.storage && card.storage.spweiwu) return true; }, }, }, - //新塌顿 - reluanzhan: { - audio: "luanzhan", - trigger: { - player: "damageEnd", - source: "damageSource", + tuogu: { + audio: 2, + trigger: { global: "die" }, + filter: function (event, player) { + return ( + event.player.getStockSkills("仲村由理", "天下第一").filter(function (skill) { + var info = get.info(skill); + return info && !info.juexingji && !info.hiddenSkill && !info.zhuSkill && !info.charlotte && !info.limited && !info.dutySkill; + }).length > 0 + ); }, - forced: true, - locked: false, + logTarget: "player", + skillAnimation: true, + limited: true, + animationColor: "thunder", content: function () { - player.addMark("reluanzhan", 1, false); + "step 0"; + player.awakenSkill("tuogu"); + var list = trigger.player.getStockSkills("仲村由理", "天下第一").filter(function (skill) { + var info = get.info(skill); + return info && !info.juexingji && !info.hiddenSkill && !info.zhuSkill && !info.charlotte && !info.limited && !info.dutySkill; + }); + if (list.length == 1) event._result = { control: list[0] }; + else + trigger.player + .chooseControl(list) + .set("prompt", "选择令" + get.translation(player) + "获得一个技能") + .set("forceDie", true) + .set("ai", function () { + return list.randomGet(); + }); + "step 1"; + player.addSkills(result.control); + game.broadcastAll(function (skill) { + var list = [skill]; + game.expandSkills(list); + for (var i of list) { + var info = lib.skill[i]; + if (!info) continue; + if (!info.audioname2) info.audioname2 = {}; + info.audioname2.caoshuang = "tuogu"; + } + }, result.control); }, - intro: { content: "mark" }, - ai: { notemp: true }, - group: ["reluanzhan_add", "reluanzhan_remove"], }, - reluanzhan_add: { - trigger: { player: "useCard2" }, - direct: true, + retuogu: { + audio: "tuogu", + trigger: { global: "die" }, filter: function (event, player) { - if ((event.card.name != "sha" && (get.color(event.card) != "black" || get.type(event.card) != "trick")) || !player.countMark("reluanzhan")) return false; - var info = get.info(event.card); - if (info.allowMultiple == false) return false; - if (event.targets && !info.multitarget) { - if ( - game.hasPlayer(function (current) { - return !event.targets.includes(current) && lib.filter.targetEnabled2(event.card, player, current) && lib.filter.targetInRange(event.card, player, current); - }) - ) { - return true; - } + return ( + event.player.getStockSkills("仲村由理", "天下第一").filter(function (skill) { + var info = get.info(skill); + return info && !info.juexingji && !info.hiddenSkill && !info.zhuSkill && !info.charlotte && !info.limited && !info.dutySkill; + }).length > 0 + ); + }, + logTarget: "player", + check: function (event, player) { + var list = event.player.getStockSkills("仲村由理", "天下第一").filter(function (skill) { + var info = get.info(skill); + return info && !info.juexingji && !info.hiddenSkill && !info.zhuSkill && !info.charlotte && !info.limited && !info.dutySkill; + }); + var negSkill = list.some(function (skill) { + return get.skillRank(skill, "inout") <= 0; + }); + var att = get.sgnAttitude(event.player, player); + if (!player.storage.retuogu) { + if (negSkill && att < 0) return false; + return true; } - return false; + list.sort(function (a, b) { + return att * (get.skillRank(b, "inout") - get.skillRank(a, "inout")); + })[0]; + return get.skillRank(list[0], "inout") >= get.skillRank(player.storage.retuogu, "inout"); }, content: function () { "step 0"; - var num = player.countMark("reluanzhan"); - var prompt2 = "为" + get.translation(trigger.card) + "增加至多" + get.cnNumber(num) + "个目标"; - player - .chooseTarget( - get.prompt("reluanzhan"), - function (card, player, target) { - if (_status.event.targets.includes(target)) return false; - var player = _status.event.player; - return lib.filter.targetEnabled2(_status.event.card, player, target) && lib.filter.targetInRange(_status.event.card, player, target); - }, - [1, num] - ) - .set("prompt2", prompt2) - .set("ai", function (target) { - var trigger = _status.event.getTrigger(); - var player = _status.event.player; - return get.effect(target, trigger.card, player, player); - }) - .set("card", trigger.card) - .set("targets", trigger.targets); + var list = trigger.player.getStockSkills("仲村由理", "天下第一").filter(function (skill) { + var info = get.info(skill); + return info && !info.juexingji && !info.hiddenSkill && !info.zhuSkill && !info.charlotte && !info.limited && !info.dutySkill; + }); + if (list.length == 1) event._result = { control: list[0] }; + else + trigger.player + .chooseControl(list) + .set("prompt", "选择令" + get.translation(player) + "获得一个技能") + .set("forceDie", true) + .set("ai", function () { + var att = get.sgnAttitude(_status.event.getTrigger().player, player); + if (att == 0) return list.randomGet(); + var listx = list + .map(function (skill) { + return [skill, get.skillRank(skill, "inout")]; + }) + .sort(function (a, b) { + return att * (b[1] - a[1]); + }) + .slice(0, 2); + var listx2 = [0]; + if (Math.abs(listx[0][1] - listx[1][1]) <= 0.5 && Math.sign(listx[0][1]) == Math.sign(listx[1][1])) listx2.push(1); + return listx[listx2.randomGet()][0]; + }); "step 1"; - if (result.bool) { - if (!event.isMine() && !event.isOnline()) game.delayx(); - event.targets = result.targets; - } else { - event.finish(); - } - "step 2"; - if (event.targets) { - player.logSkill("reluanzhan", event.targets); - trigger.targets.addArray(event.targets); - } + if (player.storage.retuogu) player.removeSkill(player.storage.retuogu); + player.storage.retuogu = result.control; + player.markSkill("retuogu"); + player.addSkills(result.control); + game.broadcastAll(function (skill) { + var list = [skill]; + game.expandSkills(list); + for (var i of list) { + var info = lib.skill[i]; + if (!info) continue; + if (!info.audioname2) info.audioname2 = {}; + info.audioname2.caoshuang = "tuogu"; + } + }, result.control); }, + mark: true, + intro: { content: "当前托孤技能:$" }, }, - reluanzhan_remove: { - audio: "luanzhan", - trigger: { player: "useCardToPlayered" }, - forced: true, - locked: false, + shanzhuan: { + trigger: { source: "damageSource" }, + audio: 2, + direct: true, filter: function (event, player) { - if (!event.isFirstTarget || (event.card.name != "sha" && (get.color(event.card) != "black" || get.type(event.card) != "trick")) || !player.countMark("reluanzhan")) return false; - var info = get.info(event.card); - if (info.allowMultiple == false || info.multitarget) return false; - return event.targets.length < player.countMark("reluanzhan"); + return player != event.player && !event.player.isDisabledJudge() && event.player.countCards("he") && !event.player.countCards("j", card => get.type(card.viewAs || card.name) == "delay"); }, content: function () { - player.removeMark("reluanzhan", Math.ceil(player.countMark("reluanzhan") / 2)); + "step 0"; + player.choosePlayerCard(trigger.player, "he", get.prompt("shanzhuan", trigger.player)).set("ai", function (card) { + if (get.attitude(_status.event.player, _status.event.target) >= 0) return 0; + return get.buttonValue(card); + }); + "step 1"; + if (result.bool) { + player.logSkill("shanzhuan", trigger.player); + var card = result.cards[0]; + trigger.player.$throw(card); + game.delayx(); + if (get.type(card, null, false) == "delay") trigger.player.addJudge(card); + else trigger.player.addJudge({ name: get.color(card, false) == "red" ? "lebu" : "bingliang" }, result.cards); + } }, - }, - //卧龙凤雏双头祈福 - youlong: { - enable: "chooseToUse", - audio: 2, - audioname: ["key_sakuya"], - zhuanhuanji: true, - marktext: "☯", - mark: true, - intro: { - content: function (storage, player) { - return storage ? "每轮限一次,你可以废除你的一个装备栏,视为使用一张未以此法使用过的基本牌。" : "每轮限一次,你可以废除你的一个装备栏,视为使用一张未以此法使用过的普通锦囊牌。"; + group: "shanzhuan_draw", + subfrequent: ["draw"], + subSkill: { + draw: { + audio: "shanzhuan", + trigger: { player: "phaseEnd" }, + frequent: true, + prompt: "是否发动【擅专】摸一张牌?", + filter: function (event, player) { + return !player.getHistory("sourceDamage").length; + }, + content: function () { + player.draw(); + }, }, }, - init: function (player) { - player.storage.youlong = false; - if (!player.storage.youlong2) player.storage.youlong2 = []; + }, + olxingshen: { + trigger: { player: "damageEnd" }, + frequent: true, + audio: "xingshen", + content: function () { + "step 0"; + var next = player.draw(); + if (get.isLuckyStar(player) || Math.random() < 0.5) next.num = 2; + var num = player.countMark("olxingshen"); + if (num < 6) player.addMark("olxingshen", Math.min(6 - num, player.getDamagedHp()), false); }, - hiddenCard: function (player, name) { - if (player.storage.youlong2.includes(name) || !player.hasEnabledSlot()) return false; - if (player.hasSkill("youlong_" + (player.storage.youlong || false))) return false; - var type = get.type(name); - if (player.storage.youlong) return type == "basic"; - return type == "trick"; + intro: { + content: "下一次发动〖严教〗时多展示X张牌", + }, + }, + //张道陵 + zlhuji: { + mod: { + globalFrom: function (player, target, distance) { + return distance - 1; + }, }, + trigger: { player: "damageEnd" }, + forced: true, filter: function (event, player) { - if (player.storage.youlong2.includes(name) || !player.hasEnabledSlot()) return false; - if (player.hasSkill("youlong_" + (player.storage.youlong || false))) return false; - var type = player.storage.youlong ? "basic" : "trick"; - for (var name of lib.inpile) { - if (player.storage.youlong2.includes(name)) continue; - if (get.type(name) != type) continue; - if (event.filterCard({ name: name, isCard: true }, player, event)) return true; + return player != _status.currentPhase; + }, + content: function () { + "step 0"; + var func = function (result) { + if (get.color(result) == "red") return 1; + return 0; + }; + if (get.itemtype(trigger.source) != "player" || !player.canUse("sha", trigger.source, false)) + func = function (result) { + return 0; + }; + else if (get.effect(trigger.source, { name: "sha" }, player, player) < 0) + func = function (result) { + if (get.color(result) == "red") return -1; + return 0; + }; + player.judge(func).judge2 = function (result) { + return result.color == "red" ? true : false; + }; + "step 1"; + if (result.color == "red" && get.itemtype(trigger.source) == "player" && player.canUse("sha", trigger.source, false)) { + player.useCard({ name: "sha", isCard: true }, trigger.source, false, "noai"); } - return false; }, - chooseButton: { - dialog: function (event, player) { - var dialog = ui.create.dialog("游龙", "hidden"); - const equips = []; - for (let i = 1; i < 6; i++) { - if (!player.hasEnabledSlot(i)) continue; - equips.push([i, get.translation("equip" + i)]); - } - if (equips.length > 0) dialog.add([equips, "tdnodes"]); - var type = player.storage.youlong ? "basic" : "trick"; - var list = []; - for (var name of lib.inpile) { - if (player.storage.youlong2.includes(name)) continue; - if (get.type(name) != type) continue; - if (event.filterCard({ name: name, isCard: true }, player, event)) { - list.push([type, "", name]); - if (name == "sha") { - for (var j of lib.inpile_nature) list.push(["基本", "", "sha", j]); - } - } - } - dialog.add([list, "vcard"]); - return dialog; - }, - filter: function (button) { - if (ui.selected.buttons.length && typeof button.link == typeof ui.selected.buttons[0].link) return false; - return true; - }, - select: 2, - check: function (button) { - var player = _status.event.player; - if (typeof button.link == "number") { - var card = player.getEquip(button.link); - if (card) { - var val = get.value(card); - if (val > 0) return 0; - return 5 - val; - } - switch (button.link) { - case 3: - return 4.5; - case 4: - return 4.4; - case 5: - return 4.3; - case 2: - return (3 - player.hp) * 1.5; - case 1: { - if ( - game.hasPlayer(function (current) { - return (get.realAttitude || get.attitude)(player, current) < 0 && get.distance(player, current) > 1; - }) - ) - return 0; - return 3.2; - } - } - } - var name = button.link[2]; - var evt = _status.event.getParent(); - if (evt.type == "phase") { - var card = { name: name, nature: button.link[3], isCard: true }; - if (name == "shan") return 2; - if (evt.type == "dying") { - if (get.attitude(player, evt.dying) < 2) return false; - if (name == "jiu") return 2.1; - return 1.9; - } - return player.getUseValue(card); - } - return 1; - }, - backup: function (links, player) { - if (typeof links[1] == "number") links.reverse(); - var equip = links[0]; - var name = links[1][2]; - var nature = links[1][3]; - return { - filterCard: function () { - return false; - }, - selectCard: -1, - equip: equip, - viewAs: { - name: name, - nature: nature, - isCard: true, + }, + zlshoufu: { + enable: "phaseUse", + usable: 1, + delay: false, + content: function () { + "step 0"; + player.draw(); + "step 1"; + var filterTarget = function (card, player, target) { + return target != player && !target.hasSkill("zlshoufu2"); + }; + if ( + !player.countCards("h") || + !game.hasPlayer(function (current) { + return filterTarget(null, player, current); + }) + ) + event.finish(); + else + player.chooseCardTarget({ + forced: true, + prompt: "将一张手牌作为“箓”置于其他角色的武将牌上", + filterTarget: filterTarget, + filterCard: true, + position: "h", + ai1: function (card) { + if (get.type2(card, false) == "equip") return 1 - get.value(card); + return 7 - get.value(card); }, - popname: true, - precontent: function () { - player.logSkill("youlong"); - player.disableEquip(lib.skill.youlong_backup.equip); - delete event.result.skill; - player.addTempSkill("youlong_" + (player.storage.youlong || false), "roundStart"); - player.changeZhuanhuanji("youlong"); - player.storage.youlong2.add(event.result.card.name); + ai2: function (target) { + var player = _status.event.player; + var att = get.attitude(player, target); + if (att > 0) return -att; + return -att / get.distance(player, target, "absolute"); }, - }; - }, - prompt: function (links, player) { - if (typeof links[1] == "number") links.reverse(); - var equip = "equip" + links[0]; - var name = links[1][2]; - var nature = links[1][3]; - return "废除自己的" + get.translation(equip) + "栏,视为使用" + (get.translation(nature) || "") + get.translation(name); - }, + }); + "step 2"; + var target = result.targets[0]; + var cards = result.cards; + target.addToExpansion(cards, player, "give").gaintag.add("zlshoufu2"); + player.line(target, "green"); + if (get.mode() !== "identity" || player.identity !== "nei") player.addExpose(0.12); + target.addSkill("zlshoufu2"); + "step 3"; + game.delayx(); }, ai: { - respondSha: true, - respondShan: true, - skillTagFilter: function (player, tag, arg) { - if (arg == "respond") return false; - if (!player.storage.youlong || player.hasSkill("youlong_true")) return false; - var name = tag == "respondSha" ? "sha" : "shan"; - return !player.storage.youlong2.includes(name); + notemp: true, + order: 1, + result: { + player: function (player) { + if ( + game.hasPlayer(function (target) { + return target != player && !target.hasSkill("zlshoufu2") && get.attitude(player, target) < 0; + }) || + !game.hasPlayer(function (target) { + return target != player && !target.hasSkill("zlshoufu2") && get.attitude(player, target) > 0; + }) + ) + return 1; + return 0; + }, }, - order: function (item, player) { - if (player && _status.event.type == "phase") { - var max = 0, - add = false; - var type = player.storage.youlong ? "basic" : "trick"; - var list = lib.inpile.filter(name => get.type(name) == type && !player.storage.youlong2.includes(name)); - if (list.includes("sha")) add = true; - list = list.map(namex => { - return { name: namex, isCard: true }; - }); - if (add) lib.inpile_nature.forEach(naturex => list.push({ name: "sha", nature: naturex, isCard: true })); - for (var card of list) { - if (player.getUseValue(card) > 0) { - var temp = get.order(card); - if (temp > max) max = temp; - } - } - if (max > 0) max += 0.3; - return max; - } - return 1; + }, + }, + zlshoufu2: { + marktext: "箓", + intro: { + content: "expansion", + markcount: "expansion", + }, + charlotte: true, + onremove: function (player, skill) { + var cards = player.getExpansions(skill); + if (cards.length) player.loseToDiscardpile(cards); + }, + mod: { + cardEnabled: function (card, player) { + if ( + player.getExpansions("zlshoufu2").filter(function (magic) { + return get.type2(magic) == get.type2(card); + }).length + ) + return false; + }, + cardRespondable: function (card, player) { + if ( + player.getExpansions("zlshoufu2").filter(function (magic) { + return get.type2(magic) == get.type2(card); + }).length + ) + return false; + }, + cardSavable: function (card, player) { + if ( + player.getExpansions("zlshoufu2").filter(function (magic) { + return get.type2(magic) == get.type2(card); + }).length + ) + return false; }, - result: { player: 1 }, }, - }, - youlong_true: { charlotte: true }, - youlong_false: { charlotte: true }, - luanfeng: { - audio: 2, - audioname: ["key_sakuya"], - trigger: { global: "dying" }, + trigger: { + player: ["damageEnd", "loseAfter"], + global: "loseAsyncAfter", + }, + forced: true, filter: function (event, player) { - return event.player.maxHp >= player.maxHp && event.player.hp < 1; + var storage = player.getExpansions("zlshoufu2"); + if (!storage.length) return false; + if (event.name == "damage") return true; + if (event.type != "discard" || event.getlx === false || event.getParent("phaseDiscard").player != player) return false; + var num = 0, + evt = event.getl(player); + if (!evt || !evt.cards2) return false; + for (var i of evt.cards2) { + if ( + storage.filter(function (magic) { + return get.type2(magic) == get.type2(i, event.hs.includes(i) ? player : false); + }).length + ) + num++; + } + return num > 1; }, - limited: true, - skillAnimation: true, - animationColor: "soil", - logTarget: "player", - check: function (event, player) { - if (get.attitude(player, event.player) < 4) return false; - if ( - player.countCards("h", function (card) { - var mod2 = game.checkMod(card, player, "unchanged", "cardEnabled2", player); - if (mod2 != "unchanged") return mod2; - var mod = game.checkMod(card, player, event.player, "unchanged", "cardSavable", player); - if (mod != "unchanged") return mod; - var savable = get.info(card).savable; - if (typeof savable == "function") savable = savable(card, player, event.player); - return savable; - }) >= - 1 - event.player.hp - ) - return false; - if (event.player == player || event.player == get.zhu(player)) return true; - return !player.hasUnknown(); + content: function () { + player.removeSkill("zlshoufu2"); + }, + }, + //蔡阳 + yinka: { + trigger: { player: ["drawBegin", "judgeBegin"] }, + direct: true, + filter: function () { + return ui.cardPile.childNodes.length > 0; }, content: function () { "step 0"; - player.awakenSkill("luanfeng"); - trigger.player.recover(3 - trigger.player.hp); + player.chooseButton(["印卡:请选择要置于牌堆" + (trigger.bottom ? "底" : "顶") + "的牌(先选择的在上)", Array.from(ui.cardPile.childNodes)], [1, trigger.num || 1]); "step 1"; - var list = [], - target = trigger.player; - for (var i = 1; i < 6; i++) { - for (var j = 0; j < target.countDisabledSlot(i); j++) { - list.push(i); + if (result.bool) { + while (result.links.length) { + if (trigger.bottom) { + var card = result.links.shift(); + ui.cardPile.removeChild(card); + ui.cardPile.appendChild(card); + } else { + var card = result.links.pop(); + ui.cardPile.removeChild(card); + ui.cardPile.insertBefore(card, ui.cardPile.firstChild); + } } } - if (list.length > 0) target.enableEquip(list); - if (list.length < 6) target.drawTo(6 - list.length); - if (target.storage.kotarou_rewrite) target.storage.kotarou_rewrite = []; - if (player == target) player.storage.youlong2 = []; - }, - }, - //曹爽,韩遂,何进 - xiaoxi: { - audio: 2, - audioname: ["machao", "hansui", "pangde"], - trigger: { - player: "enterGame", - global: "phaseBefore", - }, - filter: function (event, player) { - return event.name != "phase" || game.phaseNumber == 0; - }, - direct: true, - content: function () { - player.chooseUseTarget("sha", get.prompt("xiaoxi"), "视为使用一张【杀】").logSkill = "xiaoxi"; }, + ai: { isLuckyStar: true }, }, - spmouzhu: { + //新王允 + xinlianji: { enable: "phaseUse", - audio: "mouzhu", + audio: "wylianji", usable: 1, - filter: function (event, player) { - return game.hasPlayer(current => lib.skill.spmouzhu.filterTarget(null, player, current)); + check: function (card) { + return 5 - get.value(card); }, filterTarget: function (card, player, target) { - if (!target.countCards("h")) return false; - return player != target && (target.hp == player.hp || get.distance(player, target) == 1); + if (ui.selected.targets.length) return true; + return target != player; }, - selectTarget: [1, Infinity], + filterCard: true, + selectTarget: 2, + multitarget: true, + targetprompt: ["打人", "被打"], content: function () { "step 0"; - target.chooseCard("h", "交给" + get.translation(player) + "一张牌", true); + //player.addMark('xinlianji',1,false); + var card = get.cardPile2(function (card) { + return get.subtype(card) == "equip1" && targets[0].hasUseTarget(card); + }); + if (card) { + if (card.name == "qinggang" && !lib.inpile.includes("qibaodao")) { + card.remove(); + card = game.createCard("qibaodao", card.suit, card.number); + } + targets[0].chooseUseTarget(card, true, "nopopup", "nothrow"); + } else { + player.chat("没有装备牌了吗"); + game.log("但是牌堆里已经没有装备牌了!"); + } "step 1"; - if (result.bool) target.give(result.cards, player); + game.updateRoundNumber(); + targets[0] + .chooseToUse("对" + get.translation(targets[1]) + "使用一张杀,或将装备区里的武器牌交给一名其他角色", { name: "sha" }) + .set("targetRequired", true) + .set("complexSelect", true) + .set("filterTarget", function (card, player, target) { + if (target != _status.event.sourcex && !ui.selected.targets.includes(_status.event.sourcex)) return false; + return lib.filter.filterTarget.apply(this, arguments); + }) + .set("sourcex", targets[1]) + .set("addCount", false); "step 2"; - if (player.countCards("h") <= target.countCards("h")) { - event.finish(); - return; - } - var list = []; - if (target.canUse("sha", player, false)) list.push("sha"); - if (target.canUse("juedou", player, false)) list.push("juedou"); - if (!list.length) event.finish(); - else if (list.length == 1) event._result = { control: list[0] }; - else - target.chooseControl(list).set("prompt", "对" + get.translation(player) + "使用一张【杀】或【决斗】。").ai = function () { - return get.effect(player, { name: "sha" }, target, target) >= get.effect(player, { name: "juedou" }, target, target) ? "sha" : "juedou"; - }; + var cards = targets[0].getEquips(1); + if (!result.bool && cards.length) { + event.cards = cards; + player.chooseTarget(true, "将" + get.translation(cards) + "交给一名其他角色").set("ai", function (target) { + var card = _status.event.getParent().cards; + return (target.hasSkillTag("nogain") ? 0 : get.attitude(_status.event.player, target)) * Math.max(0.1, target.getUseValue(cards[0])); + }); + } else event.finish(); "step 3"; - target.useCard({ name: result.control, isCard: true }, player, "noai"); + result.targets[0].gain(cards, result.targets[0], "give").giver = player; }, ai: { - order: 7, + order: 4, result: { - target: -1.2, - player: function (player, target) { - if (ui.selected.targets.length) return 0; - if (target.countCards("h") - player.countCards("h") > 1) return 1; - if (get.damageEffect(target, player, player, player) > 0) return 1; - if (player.hp > 3 || (player.countCards("h", "sha") && player.countCards("h", "shan"))) return 0; - if (player.hp > 2) return -1.1; - return -2; - }, - }, - }, - }, - spyanhuo: { - audio: "yanhuo", - trigger: { player: "die" }, - forceDie: true, - skillAnimation: true, - animationColor: "soil", - content: function () { - player.line(game.players, "green"); - game.addGlobalSkill("spyanhuo_damage"); - if (!_status.yanhuo) _status.yanhuo = 0; - _status.yanhuo++; - }, - subSkill: { - damage: { - trigger: { player: "useCard" }, - forced: true, - filter: function (event, player) { - return event.card.name == "sha"; - }, - content: function () { - trigger.baseDamage += _status.yanhuo || 0; - }, - }, - }, - }, - spniluan: { - enable: "phaseUse", - audio: "niluan", - viewAs: { name: "sha" }, - check: function (card) { - return 5.1 - get.value(card); - }, - filterCard: { color: "black" }, - position: "hes", - viewAsFilter: function (player) { - return player.countCards("hes", lib.skill.spniluan.filterCard) > 0; + target: function (player, target) { + if (ui.selected.targets.length) { + var pretarget = ui.selected.targets[0]; + if (pretarget.hasSha() && pretarget.canUse({ name: "sha" }, target)) return get.effect(target, { name: "sha" }, pretarget, target); + return Math.random(); + } + if (!target.getEquip(1)) { + if ( + game.hasPlayer(function (current) { + return current != target && !current.hasSkillTag("nogain") && get.attitude(current, target) > 0; + }) + ) + return 3; + return -3; + } + if ( + !game.hasPlayer(function (current) { + return current != target && !current.hasSkillTag("nogain") && get.attitude(current, target) > 0; + }) + ) + return -6; + return 4 - get.value(target.getEquip(1)); + }, + }, }, - group: "spniluan_clear", }, - spniluan_clear: { - trigger: { player: "useCardAfter" }, + xinmoucheng: { + trigger: { player: "phaseZhunbeiBegin" }, + audio: "moucheng", forced: true, - silent: true, - charlotte: true, + juexingji: true, + skillAnimation: true, + animationColor: "gray", + derivation: "xinjingong", + unique: true, filter: function (event, player) { - return ( - event.skill == "spniluan" && - event.addCount !== false && - player.getHistory("sourceDamage", function (card) { - return card.card == event.card; - }).length == 0 - ); + return game.hasPlayer2(function (current) { + return ( + current.getAllHistory("sourceDamage", function (evt) { + if (!evt.card || evt.card.name != "sha" || evt.getParent().type != "card") return false; + var evt2 = evt.getParent(4); + return evt2 && evt2.name == "xinlianji" && evt2.player == player; + }).length > 0 + ); + }); }, content: function () { - trigger.addCount = false; - if (player.stat[player.stat.length - 1].card.sha > 0) { - player.stat[player.stat.length - 1].card.sha--; - } + player.awakenSkill("xinmoucheng"); + player.changeSkills(["xinjingong"], ["xinlianji"]); + }, + ai: { + combo: "xinlianji", }, }, - spweiwu: { - audio: 2, - locked: false, + xinjingong: { + audio: "jingong", enable: "phaseUse", usable: 1, - viewAs: { - name: "shunshou", - storage: { spweiwu: true }, + filter: function (event, player) { + return ( + event.xinjingong_list && + player.countCards("hes", function (card) { + return card.name == "sha" || get.type(card) == "equip"; + }) + ); }, - filterCard: { color: "red" }, - position: "hes", - check: function (card) { - return 7 - get.value(card); + onChooseToUse: function (event) { + if (!game.online) { + var evt = event.getParent(); + if (evt.name != "phaseUse") return; + if (!evt.xinjingong_list) { + var list = get.inpile("trick").randomGets(2); + if (Math.random() < 0.5) { + list.push("wy_meirenji"); + } else { + list.push("wy_xiaolicangdao"); + } + evt.xinjingong_list = list; + } + if (!event.xinjingong_list) event.set("xinjingong_list", evt.xinjingong_list); + } }, - mod: { - targetInRange: function (card) { - if (card.storage && card.storage.spweiwu) return true; + chooseButton: { + dialog: function (event, player) { + var list = []; + for (var i of event.xinjingong_list) list.push(["锦囊", "", i]); + return ui.create.dialog("矜功", [list, "vcard"]); + }, + filter: function (button, player) { + return lib.filter.filterCard({ name: button.link[2] }, player, _status.event.getParent()); + }, + check: function (button) { + return _status.event.player.getUseValue({ name: button.link[2] }); + }, + backup: function (links, player) { + return { + audio: "jingong", + popname: true, + position: "hes", + viewAs: { name: links[0][2] }, + check: function (card) { + return 6 - get.value(card); + }, + filterCard: function (card) { + return card.name == "sha" || get.type(card) == "equip"; + }, + }; + }, + prompt: function (links, player) { + return "将一张【杀】或装备牌当做" + get.translation(links[0][2]) + "使用"; + }, + }, + ai: { + order: 2, + result: { + player: 1, }, }, }, - tuogu: { + //孙邵 + bizheng: { + trigger: { player: "phaseDrawEnd" }, + direct: true, audio: 2, - trigger: { global: "die" }, - filter: function (event, player) { - return ( - event.player.getStockSkills("仲村由理", "天下第一").filter(function (skill) { - var info = get.info(skill); - return info && !info.juexingji && !info.hiddenSkill && !info.zhuSkill && !info.charlotte && !info.limited && !info.dutySkill; - }).length > 0 - ); - }, - logTarget: "player", - skillAnimation: true, - limited: true, - animationColor: "thunder", content: function () { "step 0"; - player.awakenSkill("tuogu"); - var list = trigger.player.getStockSkills("仲村由理", "天下第一").filter(function (skill) { - var info = get.info(skill); - return info && !info.juexingji && !info.hiddenSkill && !info.zhuSkill && !info.charlotte && !info.limited && !info.dutySkill; + player.chooseTarget(get.prompt2("bizheng"), lib.filter.notMe).set("ai", function (target) { + var player = _status.event.player; + if (player.countCards("h") > player.maxHp) return 0; + var att = get.attitude(player, target); + if (att <= 0 || target.hasSkillTag("nogain")) return 0; + if (target.maxHp - target.countCards("h") >= 2) return att; + return att / 2; }); - if (list.length == 1) event._result = { control: list[0] }; - else - trigger.player - .chooseControl(list) - .set("prompt", "选择令" + get.translation(player) + "获得一个技能") - .set("forceDie", true) - .set("ai", function () { - return list.randomGet(); - }); "step 1"; - player.addSkills(result.control); - game.broadcastAll(function (skill) { - var list = [skill]; - game.expandSkills(list); - for (var i of list) { - var info = lib.skill[i]; - if (!info) continue; - if (!info.audioname2) info.audioname2 = {}; - info.audioname2.caoshuang = "tuogu"; - } - }, result.control); + if (result.bool) { + var target = result.targets[0]; + event.target = target; + player.logSkill("bizheng", target); + target.draw(2); + } else event.finish(); + "step 2"; + if (player.countCards("h") > player.maxHp) player.chooseToDiscard(2, "he", true); + "step 3"; + if (target.countCards("h") > target.maxHp) target.chooseToDiscard(2, "he", true); + }, + ai: { + expose: 0.25, }, }, - retuogu: { - audio: "tuogu", - trigger: { global: "die" }, + yidian: { + trigger: { player: "useCard2" }, filter: function (event, player) { - return ( - event.player.getStockSkills("仲村由理", "天下第一").filter(function (skill) { - var info = get.info(skill); - return info && !info.juexingji && !info.hiddenSkill && !info.zhuSkill && !info.charlotte && !info.limited && !info.dutySkill; - }).length > 0 - ); - }, - logTarget: "player", - check: function (event, player) { - var list = event.player.getStockSkills("仲村由理", "天下第一").filter(function (skill) { - var info = get.info(skill); - return info && !info.juexingji && !info.hiddenSkill && !info.zhuSkill && !info.charlotte && !info.limited && !info.dutySkill; - }); - var negSkill = list.some(function (skill) { - return get.skillRank(skill, "inout") <= 0; - }); - var att = get.sgnAttitude(event.player, player); - if (!player.storage.retuogu) { - if (negSkill && att < 0) return false; - return true; - } - list.sort(function (a, b) { - return att * (get.skillRank(b, "inout") - get.skillRank(a, "inout")); - })[0]; - return get.skillRank(list[0], "inout") >= get.skillRank(player.storage.retuogu, "inout"); - }, - content: function () { - "step 0"; - var list = trigger.player.getStockSkills("仲村由理", "天下第一").filter(function (skill) { - var info = get.info(skill); - return info && !info.juexingji && !info.hiddenSkill && !info.zhuSkill && !info.charlotte && !info.limited && !info.dutySkill; - }); - if (list.length == 1) event._result = { control: list[0] }; - else - trigger.player - .chooseControl(list) - .set("prompt", "选择令" + get.translation(player) + "获得一个技能") - .set("forceDie", true) - .set("ai", function () { - var att = get.sgnAttitude(_status.event.getTrigger().player, player); - if (att == 0) return list.randomGet(); - var listx = list - .map(function (skill) { - return [skill, get.skillRank(skill, "inout")]; - }) - .sort(function (a, b) { - return att * (b[1] - a[1]); - }) - .slice(0, 2); - var listx2 = [0]; - if (Math.abs(listx[0][1] - listx[1][1]) <= 0.5 && Math.sign(listx[0][1]) == Math.sign(listx[1][1])) listx2.push(1); - return listx[listx2.randomGet()][0]; - }); - "step 1"; - if (player.storage.retuogu) player.removeSkill(player.storage.retuogu); - player.storage.retuogu = result.control; - player.markSkill("retuogu"); - player.addSkills(result.control); - game.broadcastAll(function (skill) { - var list = [skill]; - game.expandSkills(list); - for (var i of list) { - var info = lib.skill[i]; - if (!info) continue; - if (!info.audioname2) info.audioname2 = {}; - info.audioname2.caoshuang = "tuogu"; + var info = get.info(event.card); + if (info.allowMultiple == false) return false; + if (event.targets && !info.multitarget) { + for (var i = 0; i < ui.discardPile.childElementCount; i++) { + if (ui.discardPile.childNodes[i].name == event.card.name) return false; + } + if ( + game.hasPlayer(function (current) { + return lib.filter.targetEnabled2(event.card, player, current) && !event.targets.includes(current); + }) + ) { + return true; } - }, result.control); + } + return false; + }, + direct: true, + content: function () { + "step 0"; + var prompt2 = "为" + get.translation(trigger.card) + "增加一个目标"; + player + .chooseTarget(get.prompt("yidian"), function (card, player, target) { + var player = _status.event.player; + if (_status.event.targets.includes(target)) return false; + return lib.filter.targetEnabled2(_status.event.card, player, target); + }) + .set("prompt2", prompt2) + .set("ai", function (target) { + var trigger = _status.event.getTrigger(); + var player = _status.event.player; + return get.effect(target, trigger.card, player, player); + }) + .set("targets", trigger.targets) + .set("card", trigger.card); + "step 1"; + if (result.bool) { + if (!event.isMine() && !event.isOnline()) game.delayx(); + event.targets = result.targets; + } else { + event.finish(); + } + "step 2"; + if (event.targets) { + player.logSkill("yidian", event.targets); + trigger.targets.addArray(event.targets); + } + }, + ai: { + expose: 0.25, }, - mark: true, - intro: { content: "当前托孤技能:$" }, }, - shanzhuan: { - trigger: { source: "damageSource" }, + //二袁 + neifa: { audio: 2, + trigger: { player: "phaseUseBegin" }, direct: true, - filter: function (event, player) { - return player != event.player && !event.player.isDisabledJudge() && event.player.countCards("he") && !event.player.countCards("j", card => get.type(card.viewAs || card.name) == "delay"); - }, content: function () { "step 0"; - player.choosePlayerCard(trigger.player, "he", get.prompt("shanzhuan", trigger.player)).set("ai", function (card) { - if (get.attitude(_status.event.player, _status.event.target) >= 0) return 0; - return get.buttonValue(card); - }); + _status.noclearcountdown = true; + if ( + game.hasPlayer(function (current) { + return current.countGainableCards(player, "ej") > 0; + }) + ) { + player + .chooseControl("cancel2") + .set("choiceList", ["摸两张牌,然后弃置一张牌", "获得场上的一张牌,然后弃置一张牌"]) + .set("prompt", get.prompt("neifa")) + .set("ai", function () { + if ( + game.hasPlayer(function (current) { + var att = get.attitude(player, current); + if (att == 0) return false; + if (att < 0) + return ( + current.countCards("e", function (card) { + return get.value(card, current) > 5; + }) > 0 + ); + return ( + current.countCards("ej", function (card) { + return get.position(card) == "j" || get.value(card, current) <= 0; + }) > 0 + ); + }) + ) + return 1; + return 0; + }); + } else { + player.chooseControl("ok", "cancel2").set("prompt", get.prompt2("neifa")); + } "step 1"; + if (result.control == "cancel2") { + delete _status.noclearcountdown; + if (!_status.noclearcountdown) { + game.stopCountChoose(); + } + event.finish(); + return; + } else if (result.index == 1) { + player + .chooseTarget("请选择一名角色,获得其装备区或判定区内的一张牌", true, function (card, player, target) { + return target.countGainableCards(player, "ej") > 0; + }) + .set("ai", function (target) { + var player = _status.event.player; + var att = get.attitude(player, target); + if ( + att > 0 && + target.countCards("ej", function (card) { + return get.position(card) == "j" || get.value(card, target) <= 0; + }) + ) + return 2 * att; + else if ( + att < 0 && + target.countCards("e", function (card) { + return get.value(card, target) > 5; + }) + ) + return -att; + return -1; + }); + } else { + delete _status.noclearcountdown; + if (!_status.noclearcountdown) { + game.stopCountChoose(); + } + player.logSkill("neifa"); + player.draw(2); + event.goto(3); + } + "step 2"; + delete _status.noclearcountdown; + if (!_status.noclearcountdown) { + game.stopCountChoose(); + } if (result.bool) { - player.logSkill("shanzhuan", trigger.player); - var card = result.cards[0]; - trigger.player.$throw(card); - game.delayx(); - if (get.type(card, false) == "delay") trigger.player.addJudge(card); - else trigger.player.addJudge({ name: get.color(card, false) == "red" ? "lebu" : "bingliang" }, result.cards); + var target = result.targets[0]; + player.logSkill("neifa", target); + player.gainPlayerCard(target, "ej", true); + } + "step 3"; + player.chooseToDiscard(true, "he").set("ai", function (cardx) { + var player = _status.event.player; + var num = 0; + var hs = player.getCards("h"); + var muniu = player.getEquip("muniu"); + var subs = []; + if (muniu && muniu.cards) hs = hs.concat(muniu.cards); + if (get.type(cardx) == "basic") { + var shas = hs.filter(function (card) { + return card != cardx && get.name(card, player) == "sha" && player.hasValueTarget(card); + }); + var numx = player.countCards("h", function (card) { + return get.type2(card, player) != "basic"; + }); + num += Math.min(numx, Math.max(0, shas.length - player.getCardUsable("sha"))) * 0.7; + num += + Math.min( + player.getCardUsable("sha") + numx, + shas.filter(function (card) { + return ( + game.countPlayer(function (current) { + return player.canUse(card, current) && get.effect(current, card, player, player) > 0; + }) > 1 + ); + }).length + ) * 1.1; + var taos = Math.min( + player.maxHp - player.hp, + hs.filter(function (card) { + return cardx != card && get.name(card, player) == "tao"; + }).length + ); + num += taos * player.getDamagedHp() * 1.2; + } else { + var numx = Math.sqrt( + Math.min( + 5, + player.countCards("h", function (card) { + return get.type2(card, player) == "basic"; + }) + ) + ); + if (numx) + num += + (numx * + Math.min( + 2, + hs.filter(function (card) { + if (card == cardx || get.type(card) != "equip" || !player.hasUseTarget(card)) return false; + subs.add(get.subtype(card)); + return true; + }).length + ) * + (2.5 + player.countCards("e"))) / + 2.5; + num += + hs.filter(function (card) { + return card != cardx && get.type2(card) == "trick" && player.hasValueTarget(card); + }).length * 0.65; + } + if (get.position(cardx) == "e" && cardx.name != "muniu" && subs.includes(get.subtype(card))) num += 3; + return num * 1.5 - get.value(cardx); + }); + "step 4"; + if (result.bool && result.cards && result.cards.length) { + var name = get.type(result.cards[0]) == "basic" ? "neifa_basic" : "neifa_nobasic"; + player.addTempSkill(name); + var num = Math.min( + 5, + player.countCards("h", function (cardx) { + return (name == "neifa_basic") != (get.type2(cardx, player) == "basic"); + }) + ); + if (num > 0) player.addMark(name, num, false); + else player.storage[name] = 0; } }, - group: "shanzhuan_draw", - subfrequent: ["draw"], - subSkill: { - draw: { - audio: "shanzhuan", - trigger: { player: "phaseEnd" }, - frequent: true, - prompt: "是否发动【擅专】摸一张牌?", - filter: function (event, player) { - return !player.getHistory("sourceDamage").length; - }, - content: function () { - player.draw(); - }, + ai: { + threaten: 3, + }, + }, + neifa_basic: { + mark: true, + marktext: "伐", + onremove: true, + intro: { + name: "内伐 - 基本牌", + content: "本回合内不能使用锦囊牌和装备牌,使用【杀】选择目标时可以额外指定一个目标且使用【杀】的目标次数上限+#。", + }, + mod: { + cardEnabled: function (card, player) { + if (["trick", "equip"].includes(get.type(card, "trick"))) return false; + }, + cardSavable: function (card, player) { + if (["trick", "equip"].includes(get.type(card, "trick"))) return false; + }, + cardUsable: function (card, player, num) { + if (card.name == "sha") { + return num + player.countMark("neifa_basic"); + } }, }, - }, - olxingshen: { - trigger: { player: "damageEnd" }, - frequent: true, - audio: "xingshen", + trigger: { player: "useCard2" }, + filter: function (event, player) { + if (event.card.name != "sha") return false; + return game.hasPlayer(function (current) { + return !event.targets.includes(current) && player.canUse(event.card, current); + }); + }, + direct: true, content: function () { "step 0"; - var next = player.draw(); - if (get.isLuckyStar(player) || Math.random() < 0.5) next.num = 2; - var num = player.countMark("olxingshen"); - if (num < 6) player.addMark("olxingshen", Math.min(6 - num, player.getDamagedHp()), false); - }, - intro: { - content: "下一次发动〖严教〗时多展示X张牌", + player + .chooseTarget(get.prompt("neifa"), "为" + get.translation(trigger.card) + "额外指定一个目标", function (card, player, target) { + return !_status.event.sourcex.includes(target) && player.canUse(_status.event.card, target); + }) + .set("sourcex", trigger.targets) + .set("ai", function (target) { + var player = _status.event.player; + return get.effect(target, _status.event.card, player, player); + }) + .set("card", trigger.card); + "step 1"; + if (result.bool) { + if (!event.isMine() && !event.isOnline()) game.delayx(); + event.targets = result.targets; + } else { + event.finish(); + } + "step 2"; + player.logSkill("neifa", event.targets); + trigger.targets.addArray(event.targets); }, }, - //张道陵 - zlhuji: { + neifa_nobasic: { + trigger: { player: "useCard2" }, + direct: true, + mark: true, + marktext: "伐", + onremove: true, mod: { - globalFrom: function (player, target, distance) { - return distance - 1; + cardEnabled: function (card, player) { + if (get.type(card) == "basic") return false; + }, + cardSavable: function (card, player) { + if (get.type(card) == "basic") return false; }, }, - trigger: { player: "damageEnd" }, - forced: true, + intro: { + name: "内伐 - 非基本牌", + content: "本回合内不能使用基本牌,使用普通锦囊牌选择目标时可以增加或减少一个目标,且本回合的出牌阶段内前两次使用装备牌时摸#张牌。", + }, filter: function (event, player) { - return player != _status.currentPhase; + if (get.type(event.card) != "trick") return false; + if (event.targets && event.targets.length > 0) return true; + var info = get.info(event.card); + if (info.allowMultiple == false) return false; + if (event.targets && !info.multitarget) { + if ( + game.hasPlayer(function (current) { + return !event.targets.includes(current) && lib.filter.targetEnabled2(event.card, player, current) && lib.filter.targetInRange(event.card, player, current); + }) + ) { + return true; + } + } + return false; }, content: function () { "step 0"; - var func = function (result) { - if (get.color(result) == "red") return 1; - return 0; - }; - if (get.itemtype(trigger.source) != "player" || !player.canUse("sha", trigger.source, false)) - func = function (result) { - return 0; - }; - else if (get.effect(trigger.source, { name: "sha" }, player, player) < 0) - func = function (result) { - if (get.color(result) == "red") return -1; - return 0; - }; - player.judge(func).judge2 = function (result) { - return result.color == "red" ? true : false; - }; + var prompt2 = "为" + get.translation(trigger.card) + "增加或减少一个目标"; + player + .chooseTarget(get.prompt("neifa"), function (card, player, target) { + var player = _status.event.player; + if (_status.event.targets.includes(target)) return true; + return lib.filter.targetEnabled2(_status.event.card, player, target) && lib.filter.targetInRange(_status.event.card, player, target); + }) + .set("prompt2", prompt2) + .set("ai", function (target) { + var trigger = _status.event.getTrigger(); + var player = _status.event.player; + return get.effect(target, trigger.card, player, player) * (_status.event.targets.includes(target) ? -1 : 1); + }) + .set("targets", trigger.targets) + .set("card", trigger.card); "step 1"; - if (result.color == "red" && get.itemtype(trigger.source) == "player" && player.canUse("sha", trigger.source, false)) { - player.useCard({ name: "sha", isCard: true }, trigger.source, false, "noai"); + if (result.bool) { + if (!event.isMine() && !event.isOnline()) game.delayx(); + event.targets = result.targets; + } else { + event.finish(); + } + "step 2"; + if (event.targets) { + player.logSkill("neifa", event.targets); + if (trigger.targets.includes(event.targets[0])) trigger.targets.removeArray(event.targets); + else trigger.targets.addArray(event.targets); } }, + group: "neifa_use", }, - zlshoufu: { - enable: "phaseUse", - usable: 1, - delay: false, + neifa_use: { + audio: "neifa", + usable: 2, + trigger: { player: "useCard" }, + forced: true, + filter: function (event, player) { + return get.type(event.card) == "equip" && player.countMark("neifa_nobasic") > 0; + }, content: function () { - "step 0"; - player.draw(); - "step 1"; - var filterTarget = function (card, player, target) { - return target != player && !target.hasSkill("zlshoufu2"); - }; - if ( - !player.countCards("h") || - !game.hasPlayer(function (current) { - return filterTarget(null, player, current); - }) - ) - event.finish(); - else - player.chooseCardTarget({ - forced: true, - prompt: "将一张手牌作为“箓”置于其他角色的武将牌上", - filterTarget: filterTarget, - filterCard: true, - position: "h", - ai1: function (card) { - if (get.type(card, false) == "equip") return 1 - get.value(card); - return 7 - get.value(card); - }, - ai2: function (target) { - var player = _status.event.player; - var att = get.attitude(player, target); - if (att > 0) return -att; - return -att / get.distance(player, target, "absolute"); - }, - }); - "step 2"; - var target = result.targets[0]; - var cards = result.cards; - target.addToExpansion(cards, player, "give").gaintag.add("zlshoufu2"); - player.line(target, "green"); - if (get.mode() !== "identity" || player.identity !== "nei") player.addExpose(0.12); - target.addSkill("zlshoufu2"); - "step 3"; - game.delayx(); + player.draw(player.countMark("neifa_nobasic")); }, ai: { - notemp: true, - order: 1, - result: { - player: function (player) { - if ( - game.hasPlayer(function (target) { - return target != player && !target.hasSkill("zlshoufu2") && get.attitude(player, target) < 0; - }) || - !game.hasPlayer(function (target) { - return target != player && !target.hasSkill("zlshoufu2") && get.attitude(player, target) > 0; - }) - ) - return 1; - return 0; + reverseOrder: true, + skillTagFilter(player) { + if (player.storage.counttrigger && player.storage.counttrigger.neifa_use >= 2) return false; + }, + effect: { + player_use(card, player, target) { + if (player.countSkill("neifa_use") < 2 && get.type(card) == "equip") return [1, player.countMark("neifa_nobasic")]; }, }, }, }, - zlshoufu2: { - marktext: "箓", - intro: { - content: "expansion", - markcount: "expansion", - }, - charlotte: true, - onremove: function (player, skill) { - var cards = player.getExpansions(skill); - if (cards.length) player.loseToDiscardpile(cards); + //许靖 + yuxu: { + audio: 2, + trigger: { player: "useCardAfter" }, + filter: function (event, player) { + var evt = event.getParent("phaseUse"); + if (!evt || evt.player != player) return false; + return true; }, - mod: { - cardEnabled: function (card, player) { - if ( - player.getExpansions("zlshoufu2").filter(function (magic) { - return get.type2(magic) == get.type2(card); - }).length - ) - return false; - }, - cardRespondable: function (card, player) { - if ( - player.getExpansions("zlshoufu2").filter(function (magic) { - return get.type2(magic) == get.type2(card); - }).length - ) - return false; - }, - cardSavable: function (card, player) { - if ( - player.getExpansions("zlshoufu2").filter(function (magic) { - return get.type2(magic) == get.type2(card); - }).length - ) - return false; - }, + direct: true, + content: function () { + "step 0"; + var draw = !player.hasMark("yuxu_used"); + if (draw) player.chooseBool(get.prompt2("yuxu")).set("ai", () => 1); + else event.goto(2); + "step 1"; + if (result.bool) { + player.logSkill("yuxu"); + player.draw(); + player.addMark("yuxu_used", 1, false); + player.addTempSkill("yuxu_used", "phaseUseAfter"); + } + event.finish(); + "step 2"; + player.logSkill("yuxu"); + player.removeMark("yuxu_used", player.countMark("yuxu_used"), false); + player.chooseToDiscard("he", true); }, - trigger: { - player: ["damageEnd", "loseAfter"], - global: "loseAsyncAfter", + subSkill: { + used: { + charlotte: true, + onremove: true, + }, }, - forced: true, + }, + xjshijian: { + audio: 2, + trigger: { global: "useCardAfter" }, + direct: true, filter: function (event, player) { - var storage = player.getExpansions("zlshoufu2"); - if (!storage.length) return false; - if (event.name == "damage") return true; - if (event.type != "discard" || event.getlx === false || event.getParent("phaseDiscard").player != player) return false; - var num = 0, - evt = event.getl(player); - if (!evt || !evt.cards2) return false; - for (var i of evt.cards2) { - if ( - storage.filter(function (magic) { - return get.type2(magic) == get.type2(i, event.hs.includes(i) ? player : false); - }).length - ) - num++; - } - return num > 1; + if (event.player == player) return false; + var evt = event.getParent("phaseUse"); + if (!evt || evt.player != event.player) return false; + return ( + event.player + .getHistory("useCard", function (evtt) { + return evtt.getParent("phaseUse") == evt; + }) + .indexOf(event) == 1 && player.countCards("he") > 0 + ); }, content: function () { - player.removeSkill("zlshoufu2"); + "step 0"; + var next = player.chooseToDiscard("he", get.prompt("xjshijian", trigger.player), "弃置一张牌并令其获得技能〖誉虚〗至回合结束"); + next.set("logSkill", ["xjshijian", trigger.player]); + next.set("check", get.attitude(player, trigger.player) > 0 && trigger.player.countCards("h") > 2); + next.ai = function (card) { + if (_status.event.check) return 5 - get.value(card); + return -1; + }; + "step 1"; + if (result.bool) trigger.player.addTempSkills("yuxu"); + }, + ai: { + expose: 0.25, }, }, - //蔡阳 - yinka: { - trigger: { player: ["drawBegin", "judgeBegin"] }, - direct: true, - filter: function () { - return ui.cardPile.childNodes.length > 0; + //新1v1 + yanhuo: { + audio: 2, + trigger: { player: "die" }, + forceDie: true, + filter: function (event, player) { + return player.countCards("he") > 0; }, + direct: true, + skillAnimation: true, + animationColor: "thunder", content: function () { "step 0"; - player.chooseButton(["印卡:请选择要置于牌堆" + (trigger.bottom ? "底" : "顶") + "的牌(先选择的在上)", Array.from(ui.cardPile.childNodes)], [1, trigger.num || 1]); + player + .chooseTarget(get.prompt2("yanhuo"), function (card, player, target) { + return target != player && target.countDiscardableCards(player, "he") > 0; + }) + .set("forceDie", true).ai = function (target) { + return -target.countCards("he") * get.attitude(player, target); + }; "step 1"; if (result.bool) { - while (result.links.length) { - if (trigger.bottom) { - var card = result.links.shift(); - ui.cardPile.removeChild(card); - ui.cardPile.appendChild(card); - } else { - var card = result.links.pop(); - ui.cardPile.removeChild(card); - ui.cardPile.insertBefore(card, ui.cardPile.firstChild); - } - } + var target = result.targets[0]; + event.target = target; + player.logSkill("yanhuo", target); + event.count = player.countCards("he"); + } else event.finish(); + "step 2"; + if (target.countDiscardableCards(player, "he")) { + player.line(target); + player.discardPlayerCard(target, "he", true).set("forceDie", true); + event.count--; + if (event.count) event.redo(); } }, - ai: { isLuckyStar: true }, }, - //新王允 - xinlianji: { + mouzhu: { + audio: 2, enable: "phaseUse", - audio: "wylianji", usable: 1, - check: function (card) { - return 5 - get.value(card); - }, filterTarget: function (card, player, target) { - if (ui.selected.targets.length) return true; - return target != player; + return target != player && target.countCards("h") > 0; }, - filterCard: true, - selectTarget: 2, - multitarget: true, - targetprompt: ["打人", "被打"], content: function () { "step 0"; - //player.addMark('xinlianji',1,false); - var card = get.cardPile2(function (card) { - return get.subtype(card) == "equip1" && targets[0].hasUseTarget(card); - }); - if (card) { - if (card.name == "qinggang" && !lib.inpile.includes("qibaodao")) { - card.remove(); - card = game.createCard("qibaodao", card.suit, card.number); - } - targets[0].chooseUseTarget(card, true, "nopopup", "nothrow"); - } else { - player.chat("没有装备牌了吗"); - game.log("但是牌堆里已经没有装备牌了!"); - } + target.chooseCard("h", "交给" + get.translation(player) + "一张手牌", true); "step 1"; - game.updateRoundNumber(); - targets[0] - .chooseToUse("对" + get.translation(targets[1]) + "使用一张杀,或将装备区里的武器牌交给一名其他角色", { name: "sha" }) - .set("targetRequired", true) - .set("complexSelect", true) - .set("filterTarget", function (card, player, target) { - if (target != _status.event.sourcex && !ui.selected.targets.includes(_status.event.sourcex)) return false; - return lib.filter.filterTarget.apply(this, arguments); - }) - .set("sourcex", targets[1]) - .set("addCount", false); + if (result.bool) target.give(result.cards, player); "step 2"; - var cards = targets[0].getEquips(1); - if (!result.bool && cards.length) { - event.cards = cards; - player.chooseTarget(true, "将" + get.translation(cards) + "交给一名其他角色").set("ai", function (target) { - var card = _status.event.getParent().cards; - return (target.hasSkillTag("nogain") ? 0 : get.attitude(_status.event.player, target)) * Math.max(0.1, target.getUseValue(cards[0])); - }); - } else event.finish(); + if (player.countCards("h") <= target.countCards("h")) { + event.finish(); + return; + } + var list = []; + if (target.canUse("sha", player, false)) list.push("sha"); + if (target.canUse("juedou", player, false)) list.push("juedou"); + if (!list.length) event.finish(); + else if (list.length == 1) event._result = { control: list[0] }; + else + target.chooseControl(list).set("prompt", "对" + get.translation(player) + "使用一张【杀】或【决斗】。").ai = function () { + return get.effect(player, { name: "sha" }, target, target) >= get.effect(player, { name: "juedou" }, target, target) ? "sha" : "juedou"; + }; "step 3"; - result.targets[0].gain(cards, result.targets[0], "give").giver = player; + target.useCard({ name: result.control, isCard: true }, player, "noai"); }, ai: { - order: 4, + order: 7, result: { - target: function (player, target) { - if (ui.selected.targets.length) { - var pretarget = ui.selected.targets[0]; - if (pretarget.hasSha() && pretarget.canUse({ name: "sha" }, target)) return get.effect(target, { name: "sha" }, pretarget, target); - return Math.random(); - } - if (!target.getEquip(1)) { - if ( - game.hasPlayer(function (current) { - return current != target && !current.hasSkillTag("nogain") && get.attitude(current, target) > 0; - }) - ) - return 3; - return -3; - } - if ( - !game.hasPlayer(function (current) { - return current != target && !current.hasSkillTag("nogain") && get.attitude(current, target) > 0; - }) - ) - return -6; - return 4 - get.value(target.getEquip(1)); + target: -1.2, + player: function (player, target) { + if (target.countCards("h") - player.countCards("h") > 1) return 1; + if (get.damageEffect(target, player, player, player) > 0) return 1; + if (player.hp > 3 || (player.countCards("h", "sha") && player.countCards("h", "shan"))) return 0; + if (player.hp > 2) return -1.1; + return -2; + }, + }, + }, + }, + niluan: { + audio: 2, + trigger: { global: "phaseJieshuBegin" }, + filter: function (event, player) { + return ( + event.player != player && + (event.player.hp > player.hp || + event.player.getHistory("useCard", function (card) { + return card.card.name == "sha"; + }).length > 0) + ); + }, + direct: true, + content: function () { + var next = player.chooseToUse(); + next.logSkill = "niluan"; + next.set("openskilldialog", get.prompt2("niluan")); + next.set("norestore", true); + next.set("_backupevent", "niluanx"); + next.set("custom", { + add: {}, + replace: { window: function () {} }, + }); + next.backup("niluanx"); + }, + }, + niluanx: { + viewAs: { name: "sha" }, + filterCard: { color: "black" }, + position: "hes", + selectCard: 1, + check: function (card) { + return 5 - get.value(card); + }, + }, + cuorui: { + audio: 2, + trigger: { + global: "phaseBefore", + player: "enterGame", + }, + forced: true, + filter: function (event, player) { + return player.maxHp > 0 && !get.is.single() && (event.name != "phase" || game.phaseNumber == 0); + }, + content: function () { + player.draw(Math.min(5, player.maxHp), false); + }, + group: "cuorui_nojudge", + subSkill: { + nojudge: { + trigger: { + player: "phaseJudgeBefore", + }, + forced: true, + audio: "cuorui", + filter: function (event, player) { + return !player.storage.cuorui && (get.is.single() || player.countCards("j")); + }, + content: function () { + player.storage.cuorui = true; + trigger.cancel(); + game.log(player, "跳过了", "#g判定阶段"); }, }, }, }, - xinmoucheng: { - trigger: { player: "phaseZhunbeiBegin" }, - audio: "moucheng", - forced: true, - juexingji: true, - skillAnimation: true, - animationColor: "gray", - derivation: "xinjingong", - unique: true, - filter: function (event, player) { - return game.hasPlayer2(function (current) { - return ( - current.getAllHistory("sourceDamage", function (evt) { - if (!evt.card || evt.card.name != "sha" || evt.getParent().type != "card") return false; - var evt2 = evt.getParent(4); - return evt2 && evt2.name == "xinlianji" && evt2.player == player; - }).length > 0 - ); - }); - }, + liewei: { + audio: 2, + trigger: { source: "dieAfter" }, + frequent: true, content: function () { - player.awakenSkill("xinmoucheng"); - player.changeSkills(["xinjingong"], ["xinlianji"]); - }, - ai: { - combo: "xinlianji", + player.draw(3); }, }, - xinjingong: { - audio: "jingong", - enable: "phaseUse", - usable: 1, - filter: function (event, player) { - return ( - event.xinjingong_list && - player.countCards("hes", function (card) { - return card.name == "sha" || get.type(card) == "equip"; - }) - ); + //蒋干 + weicheng: { + audio: 2, + trigger: { + global: "gainAfter", + player: "loseAsyncAfter", }, - onChooseToUse: function (event) { - if (!game.online) { - var evt = event.getParent(); - if (evt.name != "phaseUse") return; - if (!evt.xinjingong_list) { - var list = get.inpile("trick").randomGets(2); - if (Math.random() < 0.5) { - list.push("wy_meirenji"); - } else { - list.push("wy_xiaolicangdao"); + //forced:true, + frequent: true, + filter: function (event, player) { + if (player.getHp() <= player.countCards("h")) return false; + if (event.name == "loseAsync") { + if (event.type != "gain") return false; + var cards = event.getl(player).hs; + return game.hasPlayer(function (current) { + if (current == player) return false; + var cardsx = event.getg(current); + for (var i of cardsx) { + if (cards.includes(i)) return true; } - evt.xinjingong_list = list; - } - if (!event.xinjingong_list) event.set("xinjingong_list", evt.xinjingong_list); + return false; + }); } + if (event.player == player) return false; + var evt = event.getl(player); + return evt && evt.hs && evt.hs.length > 0; }, - chooseButton: { - dialog: function (event, player) { - var list = []; - for (var i of event.xinjingong_list) list.push(["锦囊", "", i]); - return ui.create.dialog("矜功", [list, "vcard"]); - }, - filter: function (button, player) { - return lib.filter.filterCard({ name: button.link[2] }, player, _status.event.getParent()); - }, - check: function (button) { - return _status.event.player.getUseValue({ name: button.link[2] }); - }, - backup: function (links, player) { - return { - audio: "jingong", - popname: true, - position: "hes", - viewAs: { name: links[0][2] }, - check: function (card) { - return 6 - get.value(card); - }, - filterCard: function (card) { - return card.name == "sha" || get.type(card) == "equip"; - }, - }; - }, - prompt: function (links, player) { - return "将一张【杀】或装备牌当做" + get.translation(links[0][2]) + "使用"; - }, - }, - ai: { - order: 2, - result: { - player: 1, - }, + preHidden: true, + content: function () { + player.draw(); }, }, - //孙邵 - bizheng: { - trigger: { player: "phaseDrawEnd" }, - direct: true, + daoshu: { audio: 2, + enable: "phaseUse", + filterTarget: function (c, p, t) { + return t != p && t.countGainableCards(p, "h") > 0; + }, + filter: function (e, p) { + return !p.hasSkill("daoshu_used"); + }, content: function () { "step 0"; - player.chooseTarget(get.prompt2("bizheng"), lib.filter.notMe).set("ai", function (target) { - var player = _status.event.player; - if (player.countCards("h") > player.maxHp) return 0; - var att = get.attitude(player, target); - if (att <= 0 || target.hasSkillTag("nogain")) return 0; - if (target.maxHp - target.countCards("h") >= 2) return att; - return att / 2; - }); + player + .chooseControl(lib.suit) + .set("prompt", "请选择一个花色") + .set("ai", () => get.event().chosen) + .set( + "chosen", + (function () { + let suits = {}, + msuit, + mcount = 0; + target.getKnownCards(player).forEach(i => { + let suit = get.suit(i); + if (suits[suit]) suits[suit]++; + else suits[suit] = 1; + }); + for (let i in suits) { + if (suits[i] > mcount && lib.suit.includes(i)) { + msuit = i; + mcount = suits[i]; + } + } + if (msuit) return msuit; + return lib.suit.randomGet(); + })() + ); "step 1"; + event.suit = result.control; + player.popup(event.suit + 2); + game.log(player, "选择了", event.suit + 2); + player.gainPlayerCard(target, true, "h", "visibleMove"); + "step 2"; if (result.bool) { - var target = result.targets[0]; - event.target = target; - player.logSkill("bizheng", target); - target.draw(2); + var suit2 = get.suit(result.cards[0]); + if (suit2 == event.suit) { + target.damage(); + event.finish(); + } else { + player.addTempSkill("daoshu_used", "phaseUseEnd"); + if ( + player.countCards("h", function (card) { + return get.suit(card) != suit2; + }) == 0 + ) { + player.showHandcards(); + event.finish(); + } else + player + .chooseCard( + "h", + true, + function (card) { + return get.suit(card) != _status.event.suit2; + }, + "交给" + get.translation(target) + "一张不为" + get.translation(suit2) + "花色的牌" + ) + .set("suit2", suit2); + } } else event.finish(); - "step 2"; - if (player.countCards("h") > player.maxHp) player.chooseToDiscard(2, "he", true); "step 3"; - if (target.countCards("h") > target.maxHp) target.chooseToDiscard(2, "he", true); + player.give(result.cards, target, true); }, ai: { - expose: 0.25, + order: 1, + result: { + target: -1, + }, + }, + subSkill: { + used: { sub: true }, }, }, - yidian: { - trigger: { player: "useCard2" }, + //统率三军诸葛瑾和文聘 + zhenwei_three: { + global: "zhenwei_three_others", + subSkill: { + others: { + mod: { + globalTo: function (from, to, distance) { + if ( + from.side != to.side && + game.hasPlayer(function (current) { + return current != to && current.side == to.side && current.hasSkill("zhenwei_three"); + }) + ) + return distance + 1; + }, + }, + sub: true, + }, + }, + }, + huanshi_three: { + audio: "huanshi", + trigger: { + global: "judge", + }, filter: function (event, player) { - var info = get.info(event.card); - if (info.allowMultiple == false) return false; - if (event.targets && !info.multitarget) { - for (var i = 0; i < ui.discardPile.childElementCount; i++) { - if (ui.discardPile.childNodes[i].name == event.card.name) return false; - } - if ( - game.hasPlayer(function (current) { - return lib.filter.targetEnabled2(event.card, player, current) && !event.targets.includes(current); - }) - ) { - return true; - } - } - return false; + return player.countCards("hes") > 0 && player.side == event.player.side; }, direct: true, content: function () { "step 0"; - var prompt2 = "为" + get.translation(trigger.card) + "增加一个目标"; player - .chooseTarget(get.prompt("yidian"), function (card, player, target) { + .chooseCard(get.translation(trigger.player) + "的" + (trigger.judgestr || "") + "判定为" + get.translation(trigger.player.judging[0]) + "," + get.prompt("huanshi_three"), "hes", function (card) { var player = _status.event.player; - if (_status.event.targets.includes(target)) return false; - return lib.filter.targetEnabled2(_status.event.card, player, target); + var mod2 = game.checkMod(card, player, "unchanged", "cardEnabled2", player); + if (mod2 != "unchanged") return mod2; + var mod = game.checkMod(card, player, "unchanged", "cardRespondable", player); + if (mod != "unchanged") return mod; + return true; }) - .set("prompt2", prompt2) - .set("ai", function (target) { + .set("ai", function (card) { var trigger = _status.event.getTrigger(); var player = _status.event.player; - return get.effect(target, trigger.card, player, player); + var judging = _status.event.judging; + var result = trigger.judge(card) - trigger.judge(judging); + var attitude = get.attitude(player, trigger.player); + if (attitude == 0 || result == 0) return 0; + if (attitude > 0) { + return result - get.value(card) / 2; + } else { + return -result - get.value(card) / 2; + } }) - .set("targets", trigger.targets) - .set("card", trigger.card); + .set("judging", trigger.player.judging[0]); "step 1"; if (result.bool) { - if (!event.isMine() && !event.isOnline()) game.delayx(); - event.targets = result.targets; + player.respond(result.cards, "highlight", "huanshi_three", "noOrdering"); } else { event.finish(); } "step 2"; - if (event.targets) { - player.logSkill("yidian", event.targets); - trigger.targets.addArray(event.targets); + if (result.bool) { + if (trigger.player.judging[0].clone) { + trigger.player.judging[0].clone.classList.remove("thrownhighlight"); + game.broadcast(function (card) { + if (card.clone) { + card.clone.classList.remove("thrownhighlight"); + } + }, trigger.player.judging[0]); + game.addVideo("deletenode", player, get.cardsInfo([trigger.player.judging[0].clone])); + } + game.cardsDiscard(trigger.player.judging[0]); + trigger.player.judging[0] = result.cards[0]; + trigger.orderingCards.addArray(result.cards); + game.log(trigger.player, "的判定牌改为", result.cards[0]); + game.delay(2); } }, ai: { - expose: 0.25, + rejudge: true, + tag: { + rejudge: 1, + }, }, }, - //二袁 - neifa: { - audio: 2, - trigger: { player: "phaseUseBegin" }, + //变权移植 + wanwei: { + trigger: { target: ["rewriteGainResult", "rewriteDiscardResult"] }, direct: true, + preHidden: true, + filter: function (event, player) { + return event.player != player; + }, + audio: 2, content: function () { "step 0"; - _status.noclearcountdown = true; - if ( - game.hasPlayer(function (current) { - return current.countGainableCards(player, "ej") > 0; - }) - ) { - player - .chooseControl("cancel2") - .set("choiceList", ["摸两张牌,然后弃置一张牌", "获得场上的一张牌,然后弃置一张牌"]) - .set("prompt", get.prompt("neifa")) - .set("ai", function () { - if ( - game.hasPlayer(function (current) { - var att = get.attitude(player, current); - if (att == 0) return false; - if (att < 0) - return ( - current.countCards("e", function (card) { - return get.value(card, current) > 5; - }) > 0 - ); - return ( - current.countCards("ej", function (card) { - return get.position(card) == "j" || get.value(card, current) <= 0; - }) > 0 - ); - }) - ) - return 1; - return 0; - }); - } else { - player.chooseControl("ok", "cancel2").set("prompt", get.prompt2("neifa")); - } + var prompt = "即将失去" + get.translation(trigger.result.cards) + ",是否发动【挽危】?"; + var next = player.choosePlayerCard(player, prompt, trigger.position); + next.set("ai", function (button) { + return 20 - get.value(button.link); + }); + next.filterButton = trigger.filterButton; + next.selectButton = trigger.result.cards.length; + next.setHiddenSkill("wanwei"); "step 1"; - if (result.control == "cancel2") { - delete _status.noclearcountdown; - if (!_status.noclearcountdown) { - game.stopCountChoose(); + if (result.bool) { + player.logSkill("wanwei"); + trigger.result.cards = result.links.slice(0); + trigger.result.links = result.links.slice(0); + trigger.cards = result.links.slice(0); + trigger.untrigger(); + } + }, + }, + gzjili: { + mod: { + aiOrder: function (player, card, num) { + if (player.isPhaseUsing() && get.subtype(card) == "equip1" && !get.cardtag(card, "gifts")) { + var range0 = player.getAttackRange(); + var range = 0; + var info = get.info(card); + if (info && info.distance && info.distance.attackFrom) { + range -= info.distance.attackFrom; + } + if (player.getEquip(1)) { + var num = 0; + var info = get.info(player.getEquip(1)); + if (info && info.distance && info.distance.attackFrom) { + num -= info.distance.attackFrom; + } + range0 -= num; + } + range0 += range; + if ( + range0 == player.getHistory("useCard").length + player.getHistory("respond").length + 2 && + player.countCards("h", function (cardx) { + return get.subtype(cardx) != "equip1" && player.getUseValue(cardx) > 0; + }) + ) + return num + 10; } - event.finish(); - return; - } else if (result.index == 1) { - player - .chooseTarget("请选择一名角色,获得其装备区或判定区内的一张牌", true, function (card, player, target) { - return target.countGainableCards(player, "ej") > 0; - }) - .set("ai", function (target) { - var player = _status.event.player; - var att = get.attitude(player, target); - if ( - att > 0 && - target.countCards("ej", function (card) { - return get.position(card) == "j" || get.value(card, target) <= 0; - }) - ) - return 2 * att; - else if ( - att < 0 && - target.countCards("e", function (card) { - return get.value(card, target) > 5; - }) - ) - return -att; - return -1; - }); - } else { - delete _status.noclearcountdown; - if (!_status.noclearcountdown) { - game.stopCountChoose(); + }, + }, + trigger: { player: ["useCard", "respond"] }, + frequent: true, + locked: false, + preHidden: true, + filter: function (event, player) { + return player.getHistory("useCard").length + player.getHistory("respond").length == player.getAttackRange(); + }, + audio: 2, + content: function () { + player.draw(player.getHistory("useCard").length + player.getHistory("respond").length); + }, + ai: { + threaten: 1.8, + effect: { + target_use(card, player, target, current) { + let used = target.getHistory("useCard").length + target.getHistory("respond").length; + if (get.subtype(card) == "equip1" && !get.cardtag(card, "gifts")) { + if (player != target || !player.isPhaseUsing()) return; + let range0 = player.getAttackRange(); + let range = 0; + let info = get.info(card); + if (info && info.distance && info.distance.attackFrom) { + range -= info.distance.attackFrom; + } + if (player.getEquip(1)) { + let num = 0; + let info = get.info(player.getEquip(1)); + if (info && info.distance && info.distance.attackFrom) { + num -= info.distance.attackFrom; + } + range0 -= num; + } + range0 += range; + let delta = range0 - used; + if (delta < 0) return; + let num = player.countCards("h", function (card) { + return (get.cardtag(card, "gifts") || get.subtype(card) != "equip1") && player.getUseValue(card) > 0; + }); + if (delta == 2 && num > 0) return [1, 3]; + if (num >= delta) return "zeroplayertarget"; + } else if (get.tag(card, "respondShan") > 0) { + if (current < 0 && used == target.getAttackRange() - 1) { + if (card.name === "sha") { + if ( + !target.mayHaveShan( + player, + "use", + target.getCards("h", i => { + return i.hasGaintag("sha_notshan"); + }) + ) + ) + return; + } else if (!target.mayHaveShan(player)) return 0.9; + return [1, (used + 1) / 2]; + } + } else if (get.tag(card, "respondSha") > 0) { + if (current < 0 && used == target.getAttackRange() - 1 && target.mayHaveSha(player)) return [1, (used + 1) / 2]; + } + }, + }, + }, + }, + //新服曹笨 + xinshanjia: { + group: ["xinshanjia_count"], + locked: false, + mod: { + aiValue: function (player, card, num) { + if ((player.storage.xinshanjia || 0) < 3 && get.type(card) == "equip" && !get.cardtag(card, "gifts")) { + return num / player.hp; } - player.logSkill("neifa"); - player.draw(2); - event.goto(3); + }, + }, + audio: "shanjia", + trigger: { + player: "phaseUseBegin", + }, + intro: { + content: "本局游戏内已失去过#张装备牌", + }, + frequent: true, + sync: function (player) { + var history = player.actionHistory; + var num = 0; + for (var i = 0; i < history.length; i++) { + for (var j = 0; j < history[i].lose.length; j++) { + if (history[i].lose[j].parent.name == "useCard") continue; + num += history[i].lose[j].cards2.filter(function (card) { + return get.type(card) == "equip"; + }).length; + } + } + player.storage.xinshanjia = num; + if (num > 0) player.markSkill("xinshanjia"); + }, + content: function () { + "step 0"; + player.draw(3); + "step 1"; + lib.skill.xinshanjia.sync(player); + var num = 3 - player.storage.xinshanjia; + if (num > 0) { + player.chooseToDiscard("he", true, num).ai = get.disvalue; } "step 2"; - delete _status.noclearcountdown; - if (!_status.noclearcountdown) { - game.stopCountChoose(); - } - if (result.bool) { - var target = result.targets[0]; - player.logSkill("neifa", target); - player.gainPlayerCard(target, "ej", true); - } - "step 3"; - player.chooseToDiscard(true, "he").set("ai", function (cardx) { - var player = _status.event.player; - var num = 0; - var hs = player.getCards("h"); - var muniu = player.getEquip("muniu"); - var subs = []; - if (muniu && muniu.cards) hs = hs.concat(muniu.cards); - if (get.type(cardx) == "basic") { - var shas = hs.filter(function (card) { - return card != cardx && get.name(card, player) == "sha" && player.hasValueTarget(card); - }); - var numx = player.countCards("h", function (card) { - return get.type(card, player) != "basic"; - }); - num += Math.min(numx, Math.max(0, shas.length - player.getCardUsable("sha"))) * 0.7; - num += - Math.min( - player.getCardUsable("sha") + numx, - shas.filter(function (card) { - return ( - game.countPlayer(function (current) { - return player.canUse(card, current) && get.effect(current, card, player, player) > 0; - }) > 1 - ); - }).length - ) * 1.1; - var taos = Math.min( - player.maxHp - player.hp, - hs.filter(function (card) { - return cardx != card && get.name(card, player) == "tao"; - }).length - ); - num += taos * player.getDamagedHp() * 1.2; - } else { - var numx = Math.sqrt( - Math.min( - 5, - player.countCards("h", function (card) { - return get.type(card, player) == "basic"; - }) - ) - ); - if (numx) - num += - (numx * - Math.min( - 2, - hs.filter(function (card) { - if (card == cardx || get.type(card) != "equip" || !player.hasUseTarget(card)) return false; - subs.add(get.subtype(card)); - return true; - }).length - ) * - (2.5 + player.countCards("e"))) / - 2.5; - num += - hs.filter(function (card) { - return card != cardx && get.type2(card) == "trick" && player.hasValueTarget(card); - }).length * 0.65; + var bool1 = true, + bool2 = true; + if (result.cards) { + var cards = result.cards; + for (var i = 0; i < result.cards.length; i++) { + var type = get.type(result.cards[i], "trick", result.cards[i].original == "h" ? player : false); + if (type == "basic") bool1 = false; + if (type == "trick") bool2 = false; } - if (get.position(cardx) == "e" && cardx.name != "muniu" && subs.includes(get.subtype(card))) num += 3; - return num * 1.5 - get.value(cardx); - }); - "step 4"; - if (result.bool && result.cards && result.cards.length) { - var name = get.type(result.cards[0]) == "basic" ? "neifa_basic" : "neifa_nobasic"; - player.addTempSkill(name); - var num = Math.min( - 5, - player.countCards("h", function (cardx) { - return (name == "neifa_basic") != (get.type(cardx, player) == "basic"); - }) - ); - if (num > 0) player.addMark(name, num, false); - else player.storage[name] = 0; + } + if (bool1) player.addTempSkill("xinshanjia_sha", "phaseUseAfter"); + if (bool2) player.addTempSkill("xinshanjia_nodis", "phaseUseAfter"); + if (bool1 && bool2) { + player.chooseUseTarget({ name: "sha" }, "是否视为使用一张【杀】?", false); } }, ai: { threaten: 3, + noe: true, + reverseOrder: true, + skillTagFilter: function (player) { + if (player.storage.xinshanjia > 2) return false; + }, + effect: { + target: function (card, player, target) { + if (player.storage.xinshanjia < 3 && get.type(card) == "equip" && !get.cardtag(card, "gifts")) return [1, 3]; + }, + }, }, - }, - neifa_basic: { - mark: true, - marktext: "伐", - onremove: true, - intro: { - name: "内伐 - 基本牌", - content: "本回合内不能使用锦囊牌和装备牌,使用【杀】选择目标时可以额外指定一个目标且使用【杀】的目标次数上限+#。", - }, - mod: { - cardEnabled: function (card, player) { - if (["trick", "equip"].includes(get.type(card, "trick"))) return false; + subSkill: { + count: { + forced: true, + silent: true, + popup: false, + trigger: { + player: "loseEnd", + }, + filter: function (event, player) { + return event.cards2 && event.cards2.length > 0; + }, + content: function () { + lib.skill.xinshanjia.sync(player); + }, }, - cardSavable: function (card, player) { - if (["trick", "equip"].includes(get.type(card, "trick"))) return false; + sha: { + mark: true, + charlotte: true, + intro: { content: "使用【杀】的次数上限+1" }, + mod: { + cardUsable: function (card, player, num) { + if (card.name == "sha") return num + 1; + }, + }, }, - cardUsable: function (card, player, num) { - if (card.name == "sha") { - return num + player.countMark("neifa_basic"); - } + nodis: { + mark: true, + charlotte: true, + intro: { content: "使用牌无距离限制" }, + mod: { + targetInRange: () => true, + }, }, }, + }, + //OL马超 + ol_shichou: { + audio: 2, trigger: { player: "useCard2" }, filter: function (event, player) { - if (event.card.name != "sha") return false; - return game.hasPlayer(function (current) { - return !event.targets.includes(current) && player.canUse(event.card, current); - }); + return event.card && event.card.name == "sha"; }, direct: true, content: function () { "step 0"; + var num = player.getDamagedHp() + 1; player - .chooseTarget(get.prompt("neifa"), "为" + get.translation(trigger.card) + "额外指定一个目标", function (card, player, target) { - return !_status.event.sourcex.includes(target) && player.canUse(_status.event.card, target); + .chooseTarget("是否发动【誓仇】?", "为" + get.translation(trigger.card) + "添加至多" + get.cnNumber(num) + "个目标", [1, num], function (card, player, target) { + var evt = _status.event.getTrigger(); + return target != player && !evt.targets.includes(target) && lib.filter.targetEnabled2(evt.card, player, target) && lib.filter.targetInRange(evt.card, player, target); }) - .set("sourcex", trigger.targets) .set("ai", function (target) { - var player = _status.event.player; - return get.effect(target, _status.event.card, player, player); - }) - .set("card", trigger.card); + return get.effect(target, _status.event.getTrigger().card, _status.event.player); + }); "step 1"; - if (result.bool) { - if (!event.isMine() && !event.isOnline()) game.delayx(); - event.targets = result.targets; - } else { - event.finish(); + if (result.bool && result.targets && result.targets.length) { + var targets = result.targets; + player.logSkill("ol_shichou", targets); + player.line(targets, trigger.card.nature); + trigger.targets.addArray(targets); } - "step 2"; - player.logSkill("neifa", event.targets); - trigger.targets.addArray(event.targets); }, }, - neifa_nobasic: { + dc_olshichou: { + audio: "ol_shichou", trigger: { player: "useCard2" }, + filter: function (event, player) { + return ( + event.card && + event.card.name == "sha" && + player.isDamaged() && + game.hasPlayer(function (current) { + return !event.targets.includes(current) && lib.filter.filterTarget(event.card, player, current); + }) + ); + }, + direct: true, + content: function () { + "step 0"; + var num = Math.min( + player.getDamagedHp(), + game.countPlayer(function (current) { + return !trigger.targets.includes(current) && lib.filter.filterTarget(trigger.card, player, current); + }) + ); + player.chooseTarget("是否发动【誓仇】,令至多" + get.cnNumber(num) + "名其他角色也成为此【杀】的目标?", [1, num], function (card, player, target) { + var evt = _status.event.getTrigger(); + return target != player && !evt.targets.includes(target) && lib.filter.targetEnabled2(evt.card, player, target) && lib.filter.targetInRange(evt.card, player, target); + }).ai = function (target) { + return get.effect(target, { name: "sha" }, _status.event.player); + }; + "step 1"; + if (result.bool && result.targets && result.targets.length) { + var targets = result.targets; + player.logSkill("dc_olshichou", targets); + player.line(targets, trigger.card.nature); + trigger.targets.addArray(targets); + trigger.ol_shichou = true; + player.addTempSkill("ol_shichou2"); + } + }, + }, + ol_shichou2: { + charlotte: true, + trigger: { player: "useCardAfter" }, + filter: function (event, player) { + return ( + event.ol_shichou && + !player.getHistory("sourceDamage", function (evt) { + return evt.card == event.card; + }).length && + event.cards.filterInD().length > 0 + ); + }, + forced: true, + popup: false, + content: function () { + player.gain(trigger.cards.filterInD(), "gain2"); + }, + }, + //新大小乔 + new_xingwu: { + audio: "xingwu", + trigger: { + player: "phaseDiscardBegin", + }, direct: true, - mark: true, - marktext: "伐", - onremove: true, - mod: { - cardEnabled: function (card, player) { - if (get.type(card) == "basic") return false; - }, - cardSavable: function (card, player) { - if (get.type(card) == "basic") return false; + intro: { + content: "expansion", + markcount: "expansion", + onunmark: function (storage, player) { + player.removeAdditionalSkill("new_luoyan"); }, }, - intro: { - name: "内伐 - 非基本牌", - content: "本回合内不能使用基本牌,使用普通锦囊牌选择目标时可以增加或减少一个目标,且本回合的出牌阶段内前两次使用装备牌时摸#张牌。", + onremove: function (player, skill) { + var cards = player.getExpansions(skill); + if (cards.length) player.loseToDiscardpile(cards); }, filter: function (event, player) { - if (get.type(event.card) != "trick") return false; - if (event.targets && event.targets.length > 0) return true; - var info = get.info(event.card); - if (info.allowMultiple == false) return false; - if (event.targets && !info.multitarget) { - if ( - game.hasPlayer(function (current) { - return !event.targets.includes(current) && lib.filter.targetEnabled2(event.card, player, current) && lib.filter.targetInRange(event.card, player, current); - }) - ) { - return true; - } - } - return false; + return player.countCards("he") > 0; }, content: function () { "step 0"; - var prompt2 = "为" + get.translation(trigger.card) + "增加或减少一个目标"; player - .chooseTarget(get.prompt("neifa"), function (card, player, target) { - var player = _status.event.player; - if (_status.event.targets.includes(target)) return true; - return lib.filter.targetEnabled2(_status.event.card, player, target) && lib.filter.targetInRange(_status.event.card, player, target); - }) - .set("prompt2", prompt2) - .set("ai", function (target) { - var trigger = _status.event.getTrigger(); - var player = _status.event.player; - return get.effect(target, trigger.card, player, player) * (_status.event.targets.includes(target) ? -1 : 1); + .chooseCard("he", get.prompt("new_xingwu"), "将一张牌置于武将牌上作为“舞”") + .set("ai", function (card) { + if (_status.event.goon) return 20 - get.value(card); + return 7 - get.value(card); }) - .set("targets", trigger.targets) - .set("card", trigger.card); + .set("goon", player.needsToDiscard() || player.getExpansions("new_xingwu").length > 1); "step 1"; if (result.bool) { - if (!event.isMine() && !event.isOnline()) game.delayx(); - event.targets = result.targets; - } else { - event.finish(); - } + player.logSkill("new_xingwu"); + var cards = result.cards; + player.addToExpansion(cards, player, "give").gaintag.add("new_xingwu"); + if (player.hasSkill("new_luoyan")) player.addAdditionalSkill("new_luoyan", ["oltianxiang", "liuli"]); + } else event.finish(); "step 2"; - if (event.targets) { - player.logSkill("neifa", event.targets); - if (trigger.targets.includes(event.targets[0])) trigger.targets.removeArray(event.targets); - else trigger.targets.addArray(event.targets); + game.delayx(); + var choices = []; + event.addIndex = 0; + if (player.getExpansions("new_xingwu").length > 2) { + choices.push("将三张“星舞”牌置入弃牌堆"); + } else event.addIndex++; + if ( + player.countCards("h", function (card) { + return lib.filter.cardDiscardable(card, player, "new_xingwu"); + }) > 1 + ) + choices.push("弃置两张手牌并将武将牌翻面"); + if (choices.length) { + player + .chooseControl("cancel2") + .set("prompt", "星舞:是否发射核弹?") + .set("choiceList", choices) + .set("ai", function () { + var player = _status.event.player; + if (player.getExpansions("new_xingwu").length > 2) return 0; + if (player.isTurnedOver() || player.identity == "fan" || player.getEnemies().length == 1) return 0; + return "cancel2"; + }); + } else event.finish(); + "step 3"; + if (result.control != "cancel2") { + var num = result.index + event.addIndex; + if (num == 1) { + event.goto(5); + return; + } + if (player.getExpansions("new_xingwu").length > 3) player.chooseButton(["请选择要移去的“星舞”牌", player.getExpansions("new_xingwu")], 3, true); + else + event._result = { + bool: true, + links: player.getExpansions("new_xingwu").slice(0), + }; + } else event.finish(); + "step 4"; + if (result.bool && result.links && result.links.length == 3) { + var cards = result.links; + player.loseToDiscardpile(cards); + event.goto(6); + } else event.finish(); + "step 5"; + player.chooseToDiscard(true, "h", 2); + player.turnOver(); + "step 6"; + player.chooseTarget("请选择【星舞】的目标", "弃置其装备区内的所有牌。然后对其造成2点伤害(目标为女性角色则改为1点)", true, lib.filter.notMe).set("ai", function (target) { + return ( + -get.attitude(_status.event.player, target) * + Math.sqrt( + 4 + + target.countCards("e", function (card) { + return get.value(card, target) > 0; + }) + ) * + (target.hasSex("female") ? 1 : 2) + ); + }); + "step 7"; + if (result.bool && result.targets && result.targets.length) { + var target = result.targets[0]; + player.line(target, "green"); + var num = target.countCards("e"); + if (num) player.discardPlayerCard(target, "e", num, true); + target.damage(target.hasSex("female") ? 1 : 2); } }, - group: "neifa_use", + ai: { + threaten: 1.5, + }, }, - neifa_use: { - audio: "neifa", - usable: 2, - trigger: { player: "useCard" }, - forced: true, - filter: function (event, player) { - return get.type(event.card) == "equip" && player.countMark("neifa_nobasic") > 0; + new_luoyan: { + init: function (player) { + if (player.getExpansions("new_xingwu").length) player.addAdditionalSkill("new_luoyan", ["oltianxiang", "liuli"]); }, - content: function () { - player.draw(player.countMark("neifa_nobasic")); + onremove: function (player) { + player.removeAdditionalSkill("new_luoyan"); }, + derivation: ["oltianxiang", "liuli"], + locked: true, ai: { - reverseOrder: true, - skillTagFilter(player) { - if (player.storage.counttrigger && player.storage.counttrigger.neifa_use >= 2) return false; - }, - effect: { - player_use(card, player, target) { - if (player.countSkill("neifa_use") < 2 && get.type(card) == "equip") return [1, player.countMark("neifa_nobasic")]; - }, - }, + combo: "new_xingwu", }, }, - //许靖 - yuxu: { - audio: 2, - trigger: { player: "useCardAfter" }, + //新孙鲁育 + new_meibu: { + audio: "meibu", + trigger: { + global: "phaseUseBegin", + }, filter: function (event, player) { - var evt = event.getParent("phaseUse"); - if (!evt || evt.player != player) return false; - return true; + return event.player != player && event.player.isIn() && player.countCards("he") > 0 && event.player.inRange(player); }, direct: true, - content: function () { - "step 0"; - var draw = !player.hasMark("yuxu_used"); - if (draw) player.chooseBool(get.prompt2("yuxu")).set("ai", () => 1); - else event.goto(2); - "step 1"; - if (result.bool) { - player.logSkill("yuxu"); - player.draw(); - player.addMark("yuxu_used", 1, false); - player.addTempSkill("yuxu_used", "phaseUseAfter"); + derivation: ["new_zhixi"], + checkx: function (event, player) { + if (get.attitude(player, event.player) >= 0) return false; + var e2 = player.getEquip(2); + if (e2) { + if (e2.name == "tengjia" || e2.name == "rewrite_tengjia") return true; + if (e2.name == "bagua" || e2.name == "rewrite_bagua") return true; } - event.finish(); - "step 2"; - player.logSkill("yuxu"); - player.removeMark("yuxu_used", player.countMark("yuxu_used"), false); - player.chooseToDiscard("he", true); - }, - subSkill: { - used: { - charlotte: true, - onremove: true, - }, - }, - }, - xjshijian: { - audio: 2, - trigger: { global: "useCardAfter" }, - direct: true, - filter: function (event, player) { - if (event.player == player) return false; - var evt = event.getParent("phaseUse"); - if (!evt || evt.player != event.player) return false; - return ( - event.player - .getHistory("useCard", function (evtt) { - return evtt.getParent("phaseUse") == evt; - }) - .indexOf(event) == 1 && player.countCards("he") > 0 - ); + return event.player.countCards("h") > event.player.hp; }, content: function () { "step 0"; - var next = player.chooseToDiscard("he", get.prompt("xjshijian", trigger.player), "弃置一张牌并令其获得技能〖誉虚〗至回合结束"); - next.set("logSkill", ["xjshijian", trigger.player]); - next.set("check", get.attitude(player, trigger.player) > 0 && trigger.player.countCards("h") > 2); - next.ai = function (card) { - if (_status.event.check) return 5 - get.value(card); - return -1; - }; + var check = lib.skill.new_meibu.checkx(trigger, player); + player + .chooseToDiscard(get.prompt2("new_meibu", trigger.player), "he") + .set("ai", function (card) { + if (_status.event.check) return 6 - get.value(card); + return 0; + }) + .set("check", check) + .set("logSkill", ["new_meibu", trigger.player]); "step 1"; - if (result.bool) trigger.player.addTempSkills("yuxu"); + if (result.bool) { + var target = trigger.player; + var card = result.cards[0]; + player.line(target, "green"); + target.addTempSkills("new_zhixi", "phaseUseAfter"); + if (card.name != "sha" && get.type(card) != "trick" && get.color(card) != "black") { + target.addTempSkill("new_meibu_range", "phaseUseAfter"); + target.markAuto("new_meibu_range", player); + } + target.markSkillCharacter("new_meibu", player, "魅步", "锁定技,出牌阶段,你至多可使用X张牌,你使用了锦囊牌后不能再使用牌(X为你的体力值)。"); + } }, ai: { - expose: 0.25, + expose: 0.2, + }, + subSkill: { + range: { + onremove: true, + charlotte: true, + mod: { + globalFrom: function (from, to, num) { + if (from.getStorage("new_meibu_range").includes(to)) { + return -Infinity; + } + }, + }, + sub: true, + }, }, }, - //新1v1 - yanhuo: { - audio: 2, - trigger: { player: "die" }, - forceDie: true, + new_mumu: { + audio: "mumu", + trigger: { + player: "phaseUseBegin", + }, filter: function (event, player) { - return player.countCards("he") > 0; + return game.hasPlayer(current => { + if (current == player) return current.getEquips(2).length > 0; + return current.countCards("e") > 0; + }); }, direct: true, - skillAnimation: true, - animationColor: "thunder", content: function () { "step 0"; player - .chooseTarget(get.prompt2("yanhuo"), function (card, player, target) { - return target != player && target.countDiscardableCards(player, "he") > 0; + .chooseTarget(get.prompt("new_mumu"), "弃置一名其他角色装备区内的一张牌,或者获得一名角色装备区内的防具牌", function (card, player, target) { + if (target == player) return target.getEquips(2).length > 0; + return target.countCards("e") > 0; }) - .set("forceDie", true).ai = function (target) { - return -target.countCards("he") * get.attitude(player, target); - }; + .set("ai", function (target) { + var player = _status.event.player; + var att = get.attitude(player, target); + if (target.getEquip(2) && player.hasEmptySlot(2)) { + return -2 * att; + } + return -att; + }); "step 1"; - if (result.bool) { - var target = result.targets[0]; - event.target = target; - player.logSkill("yanhuo", target); - event.count = player.countCards("he"); + if (result.bool && result.targets && result.targets.length) { + event.target = result.targets[0]; + player.logSkill("new_mumu", event.target); + player.line(event.target, "green"); + var e = event.target.getEquips(2); + event.e = e; + if (target == player) event.choice = "获得一张防具牌"; + else if (e.length > 0) { + player.chooseControl("弃置一张装备牌", "获得一张防具牌").set("ai", function () { + if (_status.event.player.getEquips(2).length > 0) { + return "弃置一张装备牌"; + } + return "获得一张防具牌"; + }); + } else { + event.choice = "弃置一张装备牌"; + } } else event.finish(); "step 2"; - if (target.countDiscardableCards(player, "he")) { - player.line(target); - player.discardPlayerCard(target, "he", true).set("forceDie", true); - event.count--; - if (event.count) event.redo(); - } - }, - }, - mouzhu: { - audio: 2, - enable: "phaseUse", - usable: 1, - filterTarget: function (card, player, target) { - return target != player && target.countCards("h") > 0; - }, - content: function () { - "step 0"; - target.chooseCard("h", "交给" + get.translation(player) + "一张手牌", true); - "step 1"; - if (result.bool) target.give(result.cards, player); - "step 2"; - if (player.countCards("h") <= target.countCards("h")) { - event.finish(); - return; + var choice = event.choice || result.control; + if (choice == "弃置一张装备牌") { + player.discardPlayerCard(event.target, "e", true); + } else { + if (event.e) { + player.gain(event.e, event.target, "give", "bySelf"); + player.addTempSkill("new_mumu_notsha"); + } } - var list = []; - if (target.canUse("sha", player, false)) list.push("sha"); - if (target.canUse("juedou", player, false)) list.push("juedou"); - if (!list.length) event.finish(); - else if (list.length == 1) event._result = { control: list[0] }; - else - target.chooseControl(list).set("prompt", "对" + get.translation(player) + "使用一张【杀】或【决斗】。").ai = function () { - return get.effect(player, { name: "sha" }, target, target) >= get.effect(player, { name: "juedou" }, target, target) ? "sha" : "juedou"; - }; - "step 3"; - target.useCard({ name: result.control, isCard: true }, player, "noai"); }, - ai: { - order: 7, - result: { - target: -1.2, - player: function (player, target) { - if (target.countCards("h") - player.countCards("h") > 1) return 1; - if (get.damageEffect(target, player, player, player) > 0) return 1; - if (player.hp > 3 || (player.countCards("h", "sha") && player.countCards("h", "shan"))) return 0; - if (player.hp > 2) return -1.1; - return -2; + subSkill: { + notsha: { + mark: true, + intro: { + content: "不能使用【杀】", + }, + charlotte: true, + mod: { + cardEnabled: function (card) { + if (card.name == "sha") return false; + }, }, }, }, }, - niluan: { - audio: 2, - trigger: { global: "phaseJieshuBegin" }, - filter: function (event, player) { - return ( - event.player != player && - (event.player.hp > player.hp || - event.player.getHistory("useCard", function (card) { - return card.card.name == "sha"; - }).length > 0) - ); + new_zhixi: { + mod: { + cardEnabled: function (card, player) { + if (player.storage.new_zhixi2 || player.countMark("new_zhixi") >= player.hp) return false; + }, + cardUsable: function (card, player) { + if (player.storage.new_zhixi2 || player.countMark("new_zhixi") >= player.hp) return false; + }, + cardSavable: function (card, player) { + if (player.storage.new_zhixi2 || player.countMark("new_zhixi") >= player.hp) return false; + }, + }, + trigger: { + player: "useCard1", + }, + forced: true, + popup: false, + firstDo: true, + init: function (player, skill) { + player.storage[skill] = 0; + var evt = _status.event.getParent("phaseUse"); + if (evt && evt.player == player) { + player.getHistory("useCard", function (evtx) { + if (evtx.getParent("phaseUse") == evt) { + player.storage[skill]++; + if (get.type2(evtx.card) == "trick") player.storage.new_zhixi2 = true; + } + }); + } + }, + onremove: function (player) { + player.unmarkSkill("new_meibu"); + delete player.storage.new_zhixi; + delete player.storage.new_zhixi2; }, - direct: true, content: function () { - var next = player.chooseToUse(); - next.logSkill = "niluan"; - next.set("openskilldialog", get.prompt2("niluan")); - next.set("norestore", true); - next.set("_backupevent", "niluanx"); - next.set("custom", { - add: {}, - replace: { window: function () {} }, - }); - next.backup("niluanx"); + player.addMark("new_zhixi", 1, false); + if (get.type2(trigger.card) == "trick") player.storage.new_zhixi2 = true; }, - }, - niluanx: { - viewAs: { name: "sha" }, - filterCard: { color: "black" }, - position: "hes", - selectCard: 1, - check: function (card) { - return 5 - get.value(card); + ai: { + presha: true, + pretao: true, + neg: true, + nokeep: true, }, }, - cuorui: { + qingzhong: { audio: 2, - trigger: { - global: "phaseBefore", - player: "enterGame", - }, - forced: true, - filter: function (event, player) { - return player.maxHp > 0 && !get.is.single() && (event.name != "phase" || game.phaseNumber == 0); + trigger: { player: "phaseUseBegin" }, + check: function (event, player) { + if ( + game.hasPlayer(function (current) { + return current != player && current.isMinHandcard() && get.attitude(player, current) > 0; + }) + ) { + return true; + } + if (player.countCards("h") <= 2) return true; + // if(player.countCards('h')<=3&&!player.countCards('h','shan')) return true; + //if(player.countCards('h',{type:'basic'})<=1) return true; + return false; }, content: function () { - player.draw(Math.min(5, player.maxHp), false); + player.draw(2); + player.addTempSkill("qingzhong_give"); }, - group: "cuorui_nojudge", subSkill: { - nojudge: { - trigger: { - player: "phaseJudgeBefore", - }, - forced: true, - audio: "cuorui", + give: { + audio: "qingzhong", + trigger: { player: "phaseUseEnd" }, filter: function (event, player) { - return !player.storage.cuorui && (get.is.single() || player.countCards("j")); + return !player.isMinHandcard(true); }, + forced: true, content: function () { - player.storage.cuorui = true; - trigger.cancel(); - game.log(player, "跳过了", "#g判定阶段"); + "step 0"; + var list = game.filterPlayer(function (current) { + return current.isMinHandcard(); + }); + if (list.length == 1) { + if (list[0] != player) { + player.line(list[0], "green"); + player.swapHandcards(list[0]); + } + event.finish(); + } else { + player + .chooseTarget(true, "清忠:选择一名手牌最少的角色与其交换手牌", function (card, player, target) { + return target.isMinHandcard(); + }) + .set("ai", function (target) { + return get.attitude(_status.event.player, target); + }); + } + "step 1"; + if (result.bool) { + var target = result.targets[0]; + if (target != player) { + player.line(target, "green"); + player.swapHandcards(target); + } + } }, }, }, }, - liewei: { - audio: 2, - trigger: { source: "dieAfter" }, - frequent: true, - content: function () { - player.draw(3); - }, - }, - //蒋干 - weicheng: { + weijing: { audio: 2, - trigger: { - global: "gainAfter", - player: "loseAsyncAfter", - }, - //forced:true, - frequent: true, + enable: "chooseToUse", filter: function (event, player) { - if (player.getHp() <= player.countCards("h")) return false; - if (event.name == "loseAsync") { - if (event.type != "gain") return false; - var cards = event.getl(player).hs; - return game.hasPlayer(function (current) { - if (current == player) return false; - var cardsx = event.getg(current); - for (var i of cardsx) { - if (cards.includes(i)) return true; - } - return false; - }); + if (event.type == "wuxie" || player.hasSkill("weijing_used")) return false; + for (var name of ["sha", "shan"]) { + if (event.filterCard({ name: name, isCard: true }, player, event)) return true; } - if (event.player == player) return false; - var evt = event.getl(player); - return evt && evt.hs && evt.hs.length > 0; - }, - preHidden: true, - content: function () { - player.draw(); - }, - }, - daoshu: { - audio: 2, - enable: "phaseUse", - filterTarget: function (c, p, t) { - return t != p && t.countGainableCards(p, "h") > 0; + return false; }, - filter: function (e, p) { - return !p.hasSkill("daoshu_used"); + chooseButton: { + dialog: function (event, player) { + var vcards = []; + for (var name of ["sha", "shan"]) { + var card = { name: name, isCard: true }; + if (event.filterCard(card, player, event)) vcards.push(["基本", "", name]); + } + var dialog = ui.create.dialog("卫境", [vcards, "vcard"], "hidden"); + dialog.direct = true; + return dialog; + }, + backup: function (links, player) { + return { + filterCard: () => false, + selectCard: -1, + viewAs: { + name: links[0][2], + isCard: true, + }, + popname: true, + precontent: function () { + player.logSkill("weijing"); + player.addTempSkill("weijing_used", "roundStart"); + }, + }; + }, + prompt: function (links, player) { + return "卫境:视为使用一张【" + get.translation(links[0][2]) + "】"; + }, }, - content: function () { - "step 0"; - player.chooseControl(lib.suit).set("prompt", "请选择一个花色").ai = function () { - return lib.suit.randomGet(); - }; - "step 1"; - event.suit = result.control; - player.popup(event.suit + 2); - game.log(player, "选择了", event.suit + 2); - player.gainPlayerCard(target, true, "h", "visibleMove"); - "step 2"; - if (result.bool) { - var suit2 = get.suit(result.cards[0]); - if (suit2 == event.suit) { - target.damage(); - event.finish(); - } else { - player.addTempSkill("daoshu_used", "phaseUseEnd"); + ai: { + order: function (item, player) { + var player = _status.event.player; + var event = _status.event; + if (event.filterCard({ name: "sha" }, player, event)) { if ( - player.countCards("h", function (card) { - return get.suit(card) != suit2; - }) == 0 + !player.hasShan() && + !game.hasPlayer(function (current) { + return player.canUse("sha", current) && current.hp == 1 && get.effect(current, { name: "sha" }, player, player) > 0; + }) ) { - player.showHandcards(); - event.finish(); - } else - player - .chooseCard( - "h", - true, - function (card) { - return get.suit(card) != _status.event.suit2; - }, - "交给" + get.translation(target) + "一张不为" + get.translation(suit2) + "花色的牌" - ) - .set("suit2", suit2); + return 0; + } + return 2.95; + } else { + var player = _status.event.player; + if (player.hasSkill("qingzhong_give")) return 2.95; + return 3.15; } - } else event.finish(); - "step 3"; - player.give(result.cards, target, true); - }, - ai: { - order: 1, + }, + respondSha: true, + respondShan: true, + skillTagFilter: function (player, tag, arg) { + if (player.hasSkill("weijing_used")) return false; + if (arg != "use") return false; + }, result: { - target: -1, + player: 1, }, }, subSkill: { - used: { sub: true }, + used: { + mark: true, + intro: { + content: "本轮已发动", + }, + }, }, }, - //统率三军诸葛瑾和文聘 - zhenwei_three: { - global: "zhenwei_three_others", + zishu: { + audio: 2, + locked: true, subSkill: { - others: { - mod: { - globalTo: function (from, to, distance) { - if ( - from.side != to.side && - game.hasPlayer(function (current) { - return current != to && current.side == to.side && current.hasSkill("zhenwei_three"); - }) - ) - return distance + 1; - }, + discard: { + trigger: { global: "phaseEnd" }, + audio: "zishu", + forced: true, + filter: function (event, player) { + if (_status.currentPhase != player) { + var he = player.getCards("h"); + var bool = false; + player.getHistory("gain", function (evt) { + if (!bool && evt && evt.cards) { + for (var i = 0; i < evt.cards.length; i++) { + if (he.includes(evt.cards[i])) bool = true; + break; + } + } + }); + return bool; + } + return false; + }, + content: function () { + var he = player.getCards("h"); + var list = []; + player.getHistory("gain", function (evt) { + if (evt && evt.cards) { + for (var i = 0; i < evt.cards.length; i++) { + if (he.includes(evt.cards[i])) list.add(evt.cards[i]); + } + } + }); + player.$throw(list, 1000); + player.lose(list, ui.discardPile, "visible"); + game.log(player, "将", list, "置入弃牌堆"); + }, + }, + mark: { + trigger: { + player: "gainBegin", + global: "phaseBeginStart", + }, + silent: true, + filter: function (event, player) { + return event.name != "gain" || player != _status.currentPhase; + }, + content: function () { + if (trigger.name == "gain") trigger.gaintag.add("zishu"); + else player.removeGaintag("zishu"); + }, + }, + draw: { + trigger: { + player: "gainAfter", + global: "loseAsyncAfter", + }, + audio: "zishu", + forced: true, + filter: function (event, player) { + if (_status.currentPhase != player || event.getg(player).length == 0) return false; + return event.getParent(2).name != "zishu_draw"; + }, + content: function () { + player.draw("nodelay"); }, - sub: true, }, }, - }, - huanshi_three: { - audio: "huanshi", - trigger: { - global: "judge", + ai: { + threaten: 1.2, + nogain: 1, + skillTagFilter: function (player) { + return player != _status.currentPhase; + }, + }, + group: ["zishu_draw", "zishu_discard", "zishu_mark"], + }, + xinyingyuan: { + audio: "yingyuan", + trigger: { player: "useCardAfter" }, + direct: true, + filter: function (event, player) { + if (_status.currentPhase != player) return false; + var type = get.type(event.card, "trick"); + return ( + player.getHistory("custom", function (evt) { + return evt.xinyingyuan_name == type; + }).length == 0 + ); + }, + content: function () { + "step 0"; + event.type = get.type(trigger.card, "trick"); + player + .chooseTarget(get.prompt("xinyingyuan"), "令一名其他角色从牌堆中获得一张" + get.translation(event.type) + "牌", function (card, player, target) { + return target != player; + }) + .set("ai", function (target) { + var att = get.attitude(_status.event.player, target); + if (att < 3) return 0; + if (target.hasJudge("lebu")) att /= 2; + if (target.hasSkillTag("nogain")) att /= 10; + return att / (1 + get.distance(player, target, "absolute")); + }); + "step 1"; + if (result.bool) { + player.logSkill("xinyingyuan", result.targets[0]); + var card = get.cardPile2(function (cardx) { + return get.type(cardx, "trick") == event.type; + }); + if (card) result.targets[0].gain(card, "log", "gain2"); + player.getHistory("custom").push({ xinyingyuan_name: event.type }); + } }, + }, + yingyuan: { + audio: 2, + trigger: { player: "useCardAfter" }, + direct: true, filter: function (event, player) { - return player.countCards("hes") > 0 && player.side == event.player.side; + if (_status.currentPhase != player) return false; + if ( + player.getHistory("custom", function (evt) { + return evt.yingyuan_name == event.card.name; + }).length > 0 + ) + return false; + return event.cards.filterInD().length > 0; }, - direct: true, content: function () { "step 0"; player - .chooseCard(get.translation(trigger.player) + "的" + (trigger.judgestr || "") + "判定为" + get.translation(trigger.player.judging[0]) + "," + get.prompt("huanshi_three"), "hes", function (card) { - var player = _status.event.player; - var mod2 = game.checkMod(card, player, "unchanged", "cardEnabled2", player); - if (mod2 != "unchanged") return mod2; - var mod = game.checkMod(card, player, "unchanged", "cardRespondable", player); - if (mod != "unchanged") return mod; - return true; + .chooseTarget(get.prompt("yingyuan"), "将" + get.translation(trigger.cards) + "交给一名其他角色", function (card, player, target) { + return target != player; }) - .set("ai", function (card) { - var trigger = _status.event.getTrigger(); - var player = _status.event.player; - var judging = _status.event.judging; - var result = trigger.judge(card) - trigger.judge(judging); - var attitude = get.attitude(player, trigger.player); - if (attitude == 0 || result == 0) return 0; - if (attitude > 0) { - return result - get.value(card) / 2; - } else { - return -result - get.value(card) / 2; - } + .set("ai", function (target) { + if (target.hasJudge("lebu")) return 0; + let att = get.attitude(_status.event.player, target), + name = _status.event.cards[0].name; + if (att < 3) return 0; + if (target.hasSkillTag("nogain")) att /= 10; + if (name === "sha" && target.hasSha()) att /= 5; + if (name === "wuxie" && target.needsToDiscard(_status.event.cards)) att /= 5; + return att / (1 + get.distance(player, target, "absolute")); }) - .set("judging", trigger.player.judging[0]); + .set("cards", trigger.cards); "step 1"; if (result.bool) { - player.respond(result.cards, "highlight", "huanshi_three", "noOrdering"); - } else { - event.finish(); - } - "step 2"; - if (result.bool) { - if (trigger.player.judging[0].clone) { - trigger.player.judging[0].clone.classList.remove("thrownhighlight"); - game.broadcast(function (card) { - if (card.clone) { - card.clone.classList.remove("thrownhighlight"); - } - }, trigger.player.judging[0]); - game.addVideo("deletenode", player, get.cardsInfo([trigger.player.judging[0].clone])); - } - game.cardsDiscard(trigger.player.judging[0]); - trigger.player.judging[0] = result.cards[0]; - trigger.orderingCards.addArray(result.cards); - game.log(trigger.player, "的判定牌改为", result.cards[0]); - game.delay(2); + player.logSkill("yingyuan", result.targets[0]); + result.targets[0].gain(trigger.cards.filterInD(), "gain2"); + player.getHistory("custom").push({ yingyuan_name: trigger.card.name }); } }, - ai: { - rejudge: true, - tag: { - rejudge: 1, - }, - }, }, - //变权移植 - wanwei: { - trigger: { target: ["rewriteGainResult", "rewriteDiscardResult"] }, + shuimeng: { + audio: 2, + trigger: { player: "phaseUseAfter" }, direct: true, - preHidden: true, filter: function (event, player) { - return event.player != player; + return player.countCards("h"); }, - audio: 2, content: function () { "step 0"; - var prompt = "即将失去" + get.translation(trigger.result.cards) + ",是否发动【挽危】?"; - var next = player.choosePlayerCard(player, prompt, trigger.position); - next.set("ai", function (button) { - return 20 - get.value(button.link); - }); - next.filterButton = trigger.filterButton; - next.selectButton = trigger.result.cards.length; - next.setHiddenSkill("wanwei"); + player + .chooseTarget(get.prompt2("shuimeng"), function (card, player, target) { + return player.canCompare(target); + }) + .set("ai", function (target) { + if (!_status.event.goon) return 0; + return -get.attitude(_status.event.player, target); + }) + .set( + "goon", + player.needsToDiscard() || + player.hasCard(function (card) { + var val = get.value(card); + if (val < 0) return true; + if (val <= 5) { + return card.number >= 11; + } + if (val <= 6) { + return card.number >= 12; + } + return false; + }) + ); "step 1"; if (result.bool) { - player.logSkill("wanwei"); - trigger.result.cards = result.links.slice(0); - trigger.result.links = result.links.slice(0); - trigger.cards = result.links.slice(0); - trigger.untrigger(); + player.logSkill("shuimeng", result.targets); + event.target = result.targets[0]; + player.chooseToCompare(event.target); + } else { + event.finish(); + } + "step 2"; + if (result.bool) { + player.chooseUseTarget({ name: "wuzhong", isCard: true }, true); + } else { + event.target.useCard({ name: "guohe", isCard: true }, player); } }, }, - gzjili: { - mod: { - aiOrder: function (player, card, num) { - if (player.isPhaseUsing() && get.subtype(card) == "equip1" && !get.cardtag(card, "gifts")) { - var range0 = player.getAttackRange(); - var range = 0; - var info = get.info(card); - if (info && info.distance && info.distance.attackFrom) { - range -= info.distance.attackFrom; - } - if (player.getEquip(1)) { - var num = 0; - var info = get.info(player.getEquip(1)); - if (info && info.distance && info.distance.attackFrom) { - num -= info.distance.attackFrom; - } - range0 -= num; - } - range0 += range; - if ( - range0 == player.getHistory("useCard").length + player.getHistory("respond").length + 2 && - player.countCards("h", function (cardx) { - return get.subtype(cardx) != "equip1" && player.getUseValue(cardx) > 0; - }) - ) - return num + 10; - } - }, - }, - trigger: { player: ["useCard", "respond"] }, - frequent: true, - locked: false, - preHidden: true, - filter: function (event, player) { - return player.getHistory("useCard").length + player.getHistory("respond").length == player.getAttackRange(); - }, + qianya: { audio: 2, - content: function () { - player.draw(player.getHistory("useCard").length + player.getHistory("respond").length); + trigger: { target: "useCardToTargeted" }, + filter: function (event, player) { + return get.type(event.card, "trick") == "trick" && player.countCards("h"); }, - ai: { - threaten: 1.8, - effect: { - target_use(card, player, target, current) { - let used = target.getHistory("useCard").length + target.getHistory("respond").length; - if (get.subtype(card) == "equip1" && !get.cardtag(card, "gifts")) { - if (player != target || !player.isPhaseUsing()) return; - let range0 = player.getAttackRange(); - let range = 0; - let info = get.info(card); - if (info && info.distance && info.distance.attackFrom) { - range -= info.distance.attackFrom; - } - if (player.getEquip(1)) { - let num = 0; - let info = get.info(player.getEquip(1)); - if (info && info.distance && info.distance.attackFrom) { - num -= info.distance.attackFrom; - } - range0 -= num; - } - range0 += range; - let delta = range0 - used; - if (delta < 0) return; - let num = player.countCards("h", function (card) { - return (get.cardtag(card, "gifts") || get.subtype(card) != "equip1") && player.getUseValue(card) > 0; - }); - if (delta == 2 && num > 0) return [1, 3]; - if (num >= delta) return "zeroplayertarget"; - } else if (get.tag(card, "respondShan") > 0) { - if (current < 0 && used == target.getAttackRange() - 1) { - if (card.name === "sha") { + async cost(event, trigger, player) { + let nh = player.countCards("h"); + event.result = await player + .chooseCardTarget({ + filterCard: true, + filterTarget: function (card, player, target) { + return target != player; + }, + selectCard: [1, nh], + ai1: function (card) { + var player = _status.event.player; + var cardname = _status.event.cardname; + if (_status.event.du) return -get.value(card, player, "raw"); + else if (_status.event.shuimeng) { + if (cardname == "wuzhong") { if ( - !target.mayHaveShan( - player, - "use", - target.getCards("h", i => { - return i.hasGaintag("sha_notshan"); - }) - ) + player.needsToDiscard(2, (i, player) => { + return !ui.selected.cards.includes(i) && !player.canIgnoreHandcard(i); + }) ) - return; - } else if (!target.mayHaveShan(player)) return 0.9; - return [1, (used + 1) / 2]; + return 10 - get.value(card, player, "raw"); + } else if (cardname == "guohe") { + if ( + player.needsToDiscard(-1, (i, player) => { + return !ui.selected.cards.includes(i) && !player.canIgnoreHandcard(i); + }) + ) + return 10 - get.value(card, player, "raw"); + } + return 0; + } else if (cardname == "lebu") { + if ( + player.needsToDiscard(1, (i, player) => { + return !ui.selected.cards.includes(i) && !player.canIgnoreHandcard(i); + }) + ) { + return 8 - get.value(card, player, "raw"); + } else { + if (!ui.selected.cards.length) { + return 6 - get.value(card, player, "raw"); + } + return 0; + } + } else if (cardname == "shunshou") { + if (_status.event.nh <= 2) return get.value(card, player, "raw"); + } else if (cardname == "huogong") { + if (player.hp == 1) return get.value(card, player, "raw"); } - } else if (get.tag(card, "respondSha") > 0) { - if (current < 0 && used == target.getAttackRange() - 1 && target.mayHaveSha(player)) return [1, (used + 1) / 2]; - } - }, - }, + if (ui.selected.cards.length) return 0; + return 7 - get.value(card, player, "raw"); + }, + ai2: function (target) { + var att = get.attitude(_status.event.player, target); + var nh2 = target.countCards("h"); + var num = Math.sqrt(1 + nh2); + var cardname = _status.event.cardname; + if (_status.event.du) return 0.5 - att; + else if (_status.event.shuimeng) { + return att / num; + } else if (cardname == "lebu") { + return att / num; + } else if (cardname == "shunshou") { + if (_status.event.nh <= 2) return att / num; + } else if (cardname == "huogong") { + if (_status.event.player.hp == 1) return att / num; + } + if (_status.event.nh > nh2 + 1) { + return att / num; + } + return 0; + }, + du: player.hasCard(function (card) { + return get.value(card, player, "raw") < 0; + }), + shuimeng: (function () { + if (trigger.card.name == "guohe") return trigger.getParent(2).name == "shuimeng"; + if (trigger.card.name == "wuzhong") return trigger.getParent(3).name == "shuimeng"; + })(), + nh: nh, + cardname: trigger.card.name, + prompt: get.prompt2("qianya"), + }) + .forResult(); }, - }, - //新服曹笨 - xinshanjia: { - group: ["xinshanjia_count"], - locked: false, - mod: { - aiValue: function (player, card, num) { - if ((player.storage.xinshanjia || 0) < 3 && get.type(card) == "equip" && !get.cardtag(card, "gifts")) { - return num / player.hp; - } - }, + async content(event, trigger, player) { + player.give(event.cards, event.targets[0]); }, - audio: "shanjia", + }, + xianfu: { trigger: { - player: "phaseUseBegin", + global: "phaseBefore", + player: "enterGame", + }, + locked: true, + filter: function (event, player) { + return game.hasPlayer(current => current != player) && (event.name != "phase" || game.phaseNumber == 0); + }, + audio: 6, + async cost(event, trigger, player) { + const result = await player + .chooseTarget("请选择【先辅】的目标", lib.translate.xianfu_info, true, function (card, player, target) { + return target != player && (!player.storage.xianfu2 || !player.storage.xianfu2.includes(target)); + }) + .set("ai", function (target) { + let att = get.attitude(_status.event.player, target); + if (att > 0) return att + 1; + if (att == 0) return Math.random(); + return att; + }) + .set("animate", false) + .forResult(); + event.result = { + bool: true, + cost_data: result.targets[0], + }; }, + logAudio: () => 2, + async content(event, trigger, player) { + let target = event.cost_data; + if (!player.storage.xianfu2) player.storage.xianfu2 = []; + player.storage.xianfu2.push(target); + player.addSkill("xianfu2"); + }, + }, + xianfu_mark: { + marktext: "辅", intro: { - content: "本局游戏内已失去过#张装备牌", + name: "先辅", + content: "当你受到伤害后,$受到等量的伤害,当你回复体力后,$回复等量的体力", }, - frequent: true, - sync: function (player) { - var history = player.actionHistory; - var num = 0; - for (var i = 0; i < history.length; i++) { - for (var j = 0; j < history[i].lose.length; j++) { - if (history[i].lose[j].parent.name == "useCard") continue; - num += history[i].lose[j].cards2.filter(function (card) { - return get.type(card, false) == "equip"; - }).length; + }, + xianfu2: { + audio: "xianfu", + charlotte: true, + trigger: { global: ["damageEnd", "recoverEnd"] }, + forced: true, + filter: function (event, player) { + if (event.player.isDead() || !player.storage.xianfu2 || !player.storage.xianfu2.includes(event.player) || event.num <= 0) return false; + if (event.name == "damage") return true; + return player.isDamaged(); + }, + logAudio(event, player) { + if (event.name == "damage") return ["xianfu5.mp3", "xianfu6.mp3"]; + return ["xianfu3.mp3", "xianfu4.mp3"]; + }, + logTarget: "player", + content: function () { + "step 0"; + var target = trigger.player; + if (!target.storage.xianfu_mark) target.storage.xianfu_mark = []; + target.storage.xianfu_mark.add(player); + target.storage.xianfu_mark.sortBySeat(); + target.markSkill("xianfu_mark"); + game.delayx(); + "step 1"; + player[trigger.name](trigger.num, "nosource"); + }, + onremove: function (player) { + if (!player.storage.xianfu2) return; + game.countPlayer(function (current) { + if (player.storage.xianfu2.includes(current) && current.storage.xianfu_mark) { + current.storage.xianfu_mark.remove(player); + if (!current.storage.xianfu_mark.length) current.unmarkSkill("xianfu_mark"); + else current.markSkill("xianfu_mark"); } - } - player.storage.xinshanjia = num; - if (num > 0) player.markSkill("xinshanjia"); + }); + delete player.storage.xianfu2; + }, + group: "xianfu3", + }, + xianfu3: { + trigger: { global: "dieBegin" }, + silent: true, + filter: function (event, player) { + return event.player == player || (player.storage.xianfu2 && player.storage.xianfu2.includes(player)); + }, + content: function () { + if (player == trigger.player) lib.skill.xianfu2.onremove(player); + else player.storage.xianfu2.remove(event.player); }, + }, + chouce: { + trigger: { player: "damageEnd" }, content: function () { "step 0"; - player.draw(3); + event.num = trigger.num; "step 1"; - lib.skill.xinshanjia.sync(player); - var num = 3 - player.storage.xinshanjia; - if (num > 0) { - player.chooseToDiscard("he", true, num).ai = get.disvalue; - } + player.judge(); "step 2"; - var bool1 = true, - bool2 = true; - if (result.cards) { - var cards = result.cards; - for (var i = 0; i < result.cards.length; i++) { - var type = get.type(result.cards[i], "trick", result.cards[i].original == "h" ? player : false); - if (type == "basic") bool1 = false; - if (type == "trick") bool2 = false; + event.color = result.color; + if (event.color == "black") { + if ( + game.hasPlayer(function (current) { + return current.countDiscardableCards(player, "hej") > 0; + }) + ) + player + .chooseTarget( + "弃置一名角色区域内的一张牌", + function (card, player, target) { + return target.countDiscardableCards(player, "hej"); + }, + true + ) + .set("ai", function (target) { + var player = _status.event.player; + var att = get.attitude(player, target); + if (att < 0) { + att = -Math.sqrt(-att); + } else { + att = Math.sqrt(att); + } + return att * lib.card.guohe.ai.result.target(player, target); + }); + else event.finish(); + } else { + var next = player.chooseTarget("令一名角色摸一张牌"); + if (player.storage.xianfu2 && player.storage.xianfu2.length) { + next.set("prompt2", "(若目标为" + get.translation(player.storage.xianfu2) + "则改为摸两张牌)"); } + next.set("ai", function (target) { + var player = _status.event.player; + var att = get.attitude(player, target) / Math.sqrt(1 + target.countCards("h")); + if (target.hasSkillTag("nogain")) att /= 10; + if (player.storage.xianfu2 && player.storage.xianfu2.includes(target)) return att * 2; + return att; + }); } - if (bool1) player.addTempSkill("xinshanjia_sha", "phaseUseAfter"); - if (bool2) player.addTempSkill("xinshanjia_nodis", "phaseUseAfter"); - if (bool1 && bool2) { - player.chooseUseTarget({ name: "sha" }, "是否视为使用一张【杀】?", false); + "step 3"; + if (result.bool) { + var target = result.targets[0]; + player.line(target, "green"); + if (event.color == "black") { + player.discardPlayerCard(target, "hej", true); + } else { + if (player.storage.xianfu2 && player.storage.xianfu2.includes(target)) { + if (!target.storage.xianfu_mark) target.storage.xianfu_mark = []; + target.storage.xianfu_mark.add(player); + target.storage.xianfu_mark.sortBySeat(); + target.markSkill("xianfu_mark"); + target.draw(2); + } else { + target.draw(); + } + } } - }, - ai: { - threaten: 3, - noe: true, - reverseOrder: true, - skillTagFilter: function (player) { - if (player.storage.xinshanjia > 2) return false; - }, - effect: { - target: function (card, player, target) { - if (player.storage.xinshanjia < 3 && get.type(card) == "equip" && !get.cardtag(card, "gifts")) return [1, 3]; - }, - }, - }, - subSkill: { - count: { - forced: true, - silent: true, - popup: false, - trigger: { - player: "loseEnd", - }, - filter: function (event, player) { - return event.cards2 && event.cards2.length > 0; - }, - content: function () { - lib.skill.xinshanjia.sync(player); - }, - }, - sha: { - mark: true, - charlotte: true, - intro: { content: "使用【杀】的次数上限+1" }, - mod: { - cardUsable: function (card, player, num) { - if (card.name == "sha") return num + 1; - }, - }, - }, - nodis: { - mark: true, - charlotte: true, - intro: { content: "使用牌无距离限制" }, - mod: { - targetInRange: () => true, + "step 4"; + if (--event.num > 0 && player.hasSkill("chouce")) { + player.chooseBool(get.prompt2("chouce")); + } else { + event.finish(); + } + "step 5"; + if (result.bool) { + player.logSkill("chouce"); + event.goto(1); + } + }, + ai: { + maixie: true, + maixie_hp: true, + effect: { + target: function (card, player, target) { + if (get.tag(card, "damage")) { + if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; + if (!target.hasFriend()) return; + if (target.hp >= 4) return [1, get.tag(card, "damage") * 1.5]; + if (target.hp == 3) return [1, get.tag(card, "damage") * 1]; + if (target.hp == 2) return [1, get.tag(card, "damage") * 0.5]; + } }, }, }, }, - //OL马超 - ol_shichou: { + fuqi: { audio: 2, - trigger: { player: "useCard2" }, + forced: true, + trigger: { + player: "useCard", + }, filter: function (event, player) { - return event.card && event.card.name == "sha"; + return ( + event.card && + (get.type(event.card) == "trick" || (get.type(event.card) == "basic" && !["shan", "tao", "jiu", "du"].includes(event.card.name))) && + game.hasPlayer(function (current) { + return current != player && get.distance(current, player) <= 1; + }) + ); }, - direct: true, content: function () { - "step 0"; - var num = player.getDamagedHp() + 1; - player - .chooseTarget("是否发动【誓仇】?", "为" + get.translation(trigger.card) + "添加至多" + get.cnNumber(num) + "个目标", [1, num], function (card, player, target) { - var evt = _status.event.getTrigger(); - return target != player && !evt.targets.includes(target) && lib.filter.targetEnabled2(evt.card, player, target) && lib.filter.targetInRange(evt.card, player, target); + trigger.directHit.addArray( + game.filterPlayer(function (current) { + return current != player && get.distance(current, player) <= 1; }) - .set("ai", function (target) { - return get.effect(target, _status.event.getTrigger().card, _status.event.player); - }); - "step 1"; - if (result.bool && result.targets && result.targets.length) { - var targets = result.targets; - player.logSkill("ol_shichou", targets); - player.line(targets, trigger.card.nature); - trigger.targets.addArray(targets); - } + ); + }, + ai: { + directHit_ai: true, + skillTagFilter: function (player, tag, arg) { + return get.distance(arg.target, player) <= 1; + }, }, }, - dc_olshichou: { - audio: "ol_shichou", - trigger: { player: "useCard2" }, + wylianji: { + enable: "phaseUse", + audio: 2, + usable: 1, filter: function (event, player) { + return player.hasCard(lib.skill.wylianji.filterCard); + }, + check: function (card) { + if (card.name == "sha") return 1; + else { + if (get.tag(card, "damage")) { + if (get.tag(card, "multineg")) return 5; + return 2; + } + } + return 0; + }, + filterCard: function (card) { + return get.name(card) == "sha" || (get.type(card, "trick") == "trick" && get.color(card) == "black" && !get.info(card).multitarget && get.info(card).enable); + }, + filterTarget: function (card, player, target) { return ( - event.card && - event.card.name == "sha" && - player.isDamaged() && - game.hasPlayer(function (current) { - return !event.targets.includes(current) && lib.filter.filterTarget(event.card, player, current); - }) + target != player && + !target.isMin() && + (player.canUse(card, target, false) || + game.hasPlayer(function (current) { + return current != player && target.canUse(card, current); + })) ); }, - direct: true, + discard: false, + lose: true, + delay: false, content: function () { "step 0"; - var num = Math.min( - player.getDamagedHp(), - game.countPlayer(function (current) { - return !trigger.targets.includes(current) && lib.filter.filterTarget(trigger.card, player, current); - }) - ); - player.chooseTarget("是否发动【誓仇】,令至多" + get.cnNumber(num) + "名其他角色也成为此【杀】的目标?", [1, num], function (card, player, target) { - var evt = _status.event.getTrigger(); - return target != player && !evt.targets.includes(target) && lib.filter.targetEnabled2(evt.card, player, target) && lib.filter.targetInRange(evt.card, player, target); - }).ai = function (target) { - return get.effect(target, { name: "sha" }, _status.event.player); - }; + player.showCards(get.translation(player) + "对" + get.translation(target) + "发动了【连计】", cards); "step 1"; - if (result.bool && result.targets && result.targets.length) { - var targets = result.targets; - player.logSkill("dc_olshichou", targets); - player.line(targets, trigger.card.nature); - trigger.targets.addArray(targets); - trigger.ol_shichou = true; - player.addTempSkill("ol_shichou2"); + var equip1 = get.cardPile2(function (card) { + return get.subtype(card) == "equip1"; + }); + if (!equip1) { + player.popup("杯具"); + game.log("牌堆中无装备"); + event.finish(); + return; + } + if (equip1.name == "qinggang" && !lib.inpile.includes("qibaodao")) { + equip1.remove(); + equip1 = game.createCard2("qibaodao", equip1.suit, equip1.number); + } + target.$draw(equip1); + target.chooseUseTarget(true, equip1, "nothrow", "nopopup"); + game.delay(); + "step 2"; + game.updateRoundNumber(); + var card = cards[0]; + var bool1 = game.hasPlayer(function (current) { + return current != player && target.canUse(card, current); + }); + var bool2 = player.canUse(card, target, false); + if (bool1 && bool2) { + target + .chooseControl(function () { + return 0; + }) + .set("choiceList", ["对除" + get.translation(player) + "以外的角色使用" + get.translation(cards) + ",并将装备区里的武器牌交给该牌的一个目标角色", "视为" + get.translation(player) + "对你使用" + get.translation(cards) + ",并将装备区内的武器牌交给" + get.translation(player)]); + } else if (bool1) { + event.directindex = 0; + } else if (bool2) { + event.directindex = 1; + } else { + event.finish(); + } + "step 3"; + var card = cards[0]; + if (result && typeof event.directindex != "number") { + event.directindex = result.index; + } + if (event.directindex == 1) { + event.insert(lib.skill.wylianji.content_use, { + player: player, + target: target, + card: card, + }); + } else { + event.insert(lib.skill.wylianji.content_give, { + player: target, + card: card, + targets: game.filterPlayer(function (current) { + return current != player; + }), + }); + } + }, + content_use: function () { + "step 0"; + player.useCard(card, target); + "step 1"; + if (!get.owner(card)) { + target.gain(card, "gain2"); + } + "step 2"; + var equip1 = target.getEquips(1); + if (equip1.length) { + game.delay(); + target.give(equip1, player); + target.line(player); + } + }, + content_give: function () { + "step 0"; + var select = get.select(get.info(card).selectTarget); + if (select[1] == -1) { + for (var i = 0; i < targets.length; i++) { + if (!player.canUse(card, targets[i])) { + targets.splice(i--, 1); + } + } + if (targets.length) { + player.useCard(card, targets); + } + event.list = targets.slice(0); + event.goto(2); + } else { + player + .chooseTarget(select, "选择" + get.translation(card) + "的目标", true, function (cardx, player, target) { + var card = _status.event.card; + return _status.event.targets.includes(target) && player.canUse(card, target); + }) + .set("ai", function (target) { + var card = _status.event.card; + var player = _status.event.player; + return get.effect(target, card, player, player); + }) + .set("targets", targets) + .set("card", card); + } + "step 1"; + if (result.bool) { + player.useCard(card, result.targets); + event.list = result.targets.slice(0); + } + "step 2"; + var equip1 = player.getEquips(1); + if (equip1.length) { + for (var i = 0; i < event.list.length; i++) { + if (event.list[i].isDead()) event.list.splice(i--, 1); + } + if (event.list.length > 1) { + player + .chooseTarget(true, "将" + get.translation(equip1) + "交给一名角色", function (card, player, target) { + return _status.event.list.includes(target); + }) + .set("ai", function (target) { + return get.attitude(player, target); + }) + .set("list", _status.event.list); + event.equip1 = equip1; + } else { + if (event.list.length == 1) { + player.give(equip1, event.list[0]); + player.line(event.list); + } + event.finish(); + } + } else { + event.finish(); + } + "step 3"; + if (result.bool && result.targets.length && event.equip1) { + player.give(event.equip1, result.targets[0]); + player.line(result.targets); } }, - }, - ol_shichou2: { - charlotte: true, - trigger: { player: "useCardAfter" }, - filter: function (event, player) { - return ( - event.ol_shichou && - !player.getHistory("sourceDamage", function (evt) { - return evt.card == event.card; - }).length && - event.cards.filterInD().length > 0 - ); + ai: { + order: 7, + result: { + target: function (player, target) { + if (ui.selected.cards.length) { + var card = ui.selected.cards[0]; + var bool = card.name != "sha"; + if ( + game.hasPlayer(function (current) { + return target.canUse(card, current, bool) && get.effect(current, card, target, player) > 0; + }) + ) { + var num = 1; + if (target.getEquip(1)) { + num = 0.6; + } + if (target.hasSkillTag("noe")) num *= 2; + return num; + } + } + return 0; + }, + }, }, + }, + moucheng: { + audio: 2, + derivation: ["jingong", "wy_meirenji", "wy_xiaolicangdao"], + trigger: { global: "damageEnd" }, forced: true, popup: false, - content: function () { - player.gain(trigger.cards.filterInD(), "gain2"); + filter: function (event, player) { + return event.source != player && event.getParent(2).name == "useCard" && event.getParent(3).name == "wylianjiInserted"; }, - }, - //新大小乔 - new_xingwu: { - audio: "xingwu", - trigger: { - player: "phaseDiscardBegin", + init: function (player) { + player.storage.moucheng = 0; }, - direct: true, intro: { - content: "expansion", - markcount: "expansion", - onunmark: function (storage, player) { - player.removeAdditionalSkill("new_luoyan"); - }, - }, - onremove: function (player, skill) { - var cards = player.getExpansions(skill); - if (cards.length) player.loseToDiscardpile(cards); - }, - filter: function (event, player) { - return player.countCards("he") > 0; + content: "已造成#点伤害", }, + unique: true, + juexingji: true, content: function () { - "step 0"; - player - .chooseCard("he", get.prompt("new_xingwu"), "将一张牌置于武将牌上作为“舞”") - .set("ai", function (card) { - if (_status.event.goon) return 20 - get.value(card); - return 7 - get.value(card); - }) - .set("goon", player.needsToDiscard() || player.getExpansions("new_xingwu").length > 1); - "step 1"; - if (result.bool) { - player.logSkill("new_xingwu"); - var cards = result.cards; - player.addToExpansion(cards, player, "give").gaintag.add("new_xingwu"); - if (player.hasSkill("new_luoyan")) player.addAdditionalSkill("new_luoyan", ["oltianxiang", "liuli"]); - } else event.finish(); - "step 2"; - game.delayx(); - var choices = []; - event.addIndex = 0; - if (player.getExpansions("new_xingwu").length > 2) { - choices.push("将三张“星舞”牌置入弃牌堆"); - } else event.addIndex++; - if ( - player.countCards("h", function (card) { - return lib.filter.cardDiscardable(card, player, "new_xingwu"); - }) > 1 - ) - choices.push("弃置两张手牌并将武将牌翻面"); - if (choices.length) { - player - .chooseControl("cancel2") - .set("prompt", "星舞:是否发射核弹?") - .set("choiceList", choices) - .set("ai", function () { - var player = _status.event.player; - if (player.getExpansions("new_xingwu").length > 2) return 0; - if (player.isTurnedOver() || player.identity == "fan" || player.getEnemies().length == 1) return 0; - return "cancel2"; - }); - } else event.finish(); - "step 3"; - if (result.control != "cancel2") { - var num = result.index + event.addIndex; - if (num == 1) { - event.goto(5); - return; - } - if (player.getExpansions("new_xingwu").length > 3) player.chooseButton(["请选择要移去的“星舞”牌", player.getExpansions("new_xingwu")], 3, true); - else - event._result = { - bool: true, - links: player.getExpansions("new_xingwu").slice(0), - }; - } else event.finish(); - "step 4"; - if (result.bool && result.links && result.links.length == 3) { - var cards = result.links; - player.loseToDiscardpile(cards); - event.goto(6); - } else event.finish(); - "step 5"; - player.chooseToDiscard(true, "h", 2); - player.turnOver(); - "step 6"; - player.chooseTarget("请选择【星舞】的目标", "弃置其装备区内的所有牌。然后对其造成2点伤害(目标为女性角色则改为1点)", true, lib.filter.notMe).set("ai", function (target) { - return ( - -get.attitude(_status.event.player, target) * - Math.sqrt( - 4 + - target.countCards("e", function (card) { - return get.value(card, target) > 0; - }) - ) * - (target.hasSex("female") ? 1 : 2) - ); - }); - "step 7"; - if (result.bool && result.targets && result.targets.length) { - var target = result.targets[0]; - player.line(target, "green"); - var num = target.countCards("e"); - if (num) player.discardPlayerCard(target, "e", num, true); - target.damage(target.hasSex("female") ? 1 : 2); + player.storage.moucheng += trigger.num; + if (player.hasSkill("moucheng")) { + player.markSkill("moucheng"); + player.syncStorage("moucheng"); + } + if (player.storage.moucheng >= 3) { + event.trigger("mouchengAwaken"); } }, + group: "moucheng_awaken", + subSkill: { + awaken: { + trigger: { player: "mouchengAwaken" }, + forced: true, + skillAnimation: true, + animationColor: "gray", + content: function () { + player.awakenSkill("moucheng"); + game.log(player, "失去了技能", "#g【连计】"); + player.changeSkills(["jingong"], ["wylianji"]); + }, + }, + }, ai: { - threaten: 1.5, + combo: "wylianji", }, }, - new_luoyan: { - init: function (player) { - if (player.getExpansions("new_xingwu").length) player.addAdditionalSkill("new_luoyan", ["oltianxiang", "liuli"]); + jingong: { + audio: 2, + enable: "phaseUse", + usable: 1, + filter: function (event, player) { + return ( + event.xinjingong_list && + player.countCards("hes", function (card) { + return card.name == "sha" || get.type(card) == "equip"; + }) + ); }, - onremove: function (player) { - player.removeAdditionalSkill("new_luoyan"); + onChooseToUse: function (event) { + if (!game.online) { + var evt = event.getParent(); + if (evt.name != "phaseUse") return; + if (!evt.xinjingong_list) { + var list = get.inpile("trick").randomGets(2); + if (Math.random() < 0.5) { + list.push("wy_meirenji"); + } else { + list.push("wy_xiaolicangdao"); + } + evt.xinjingong_list = list; + } + if (!event.xinjingong_list) event.set("xinjingong_list", evt.xinjingong_list); + } }, - derivation: ["oltianxiang", "liuli"], - locked: true, - ai: { - combo: "new_xingwu", + chooseButton: { + dialog: function (event, player) { + var list = []; + for (var i of event.xinjingong_list) list.push(["锦囊", "", i]); + return ui.create.dialog("矜功", [list, "vcard"]); + }, + filter: function (button, player) { + return lib.filter.filterCard({ name: button.link[2] }, player, _status.event.getParent()); + }, + check: function (button) { + return _status.event.player.getUseValue({ name: button.link[2] }); + }, + backup: function (links, player) { + return { + audio: "jingong", + popname: true, + position: "hes", + viewAs: { name: links[0][2] }, + check: function (card) { + return 6 - get.value(card); + }, + filterCard: function (card) { + return card.name == "sha" || get.type(card) == "equip"; + }, + precontent: function () { + player.addTempSkill("jingong2"); + }, + }; + }, + prompt: function (links, player) { + return "将一张【杀】或装备牌当做" + get.translation(links[0][2]) + "使用"; + }, }, - }, - //新孙鲁育 - new_meibu: { - audio: "meibu", - trigger: { - global: "phaseUseBegin", + ai: { + order: 2, + result: { + player: function (player) { + if ((player.hp <= 2 || player.needsToDiscard()) && !player.getStat("damage")) return 0; + return 1; + }, + }, }, + }, + jingong2: { + trigger: { player: "phaseJieshuBegin" }, + forced: true, filter: function (event, player) { - return event.player != player && event.player.isIn() && player.countCards("he") > 0 && event.player.inRange(player); + return !player.getStat("damage"); }, - direct: true, - derivation: ["new_zhixi"], - checkx: function (event, player) { - if (get.attitude(player, event.player) >= 0) return false; - var e2 = player.getEquip(2); - if (e2) { - if (e2.name == "tengjia" || e2.name == "rewrite_tengjia") return true; - if (e2.name == "bagua" || e2.name == "rewrite_bagua") return true; - } - return event.player.countCards("h") > event.player.hp; + content: function () { + player.loseHp(); + }, + }, + jingong3: { charlotte: true }, + weikui: { + audio: 2, + enable: "phaseUse", + usable: 1, + filterTarget: function (card, player, target) { + return target != player && target.countCards("h"); }, content: function () { "step 0"; - var check = lib.skill.new_meibu.checkx(trigger, player); - player - .chooseToDiscard(get.prompt2("new_meibu", trigger.player), "he") - .set("ai", function (card) { - if (_status.event.check) return 6 - get.value(card); - return 0; - }) - .set("check", check) - .set("logSkill", ["new_meibu", trigger.player]); + player.loseHp(); "step 1"; - if (result.bool) { - var target = trigger.player; - var card = result.cards[0]; - player.line(target, "green"); - target.addTempSkills("new_zhixi", "phaseUseAfter"); - if (card.name != "sha" && get.type(card) != "trick" && get.color(card) != "black") { - target.addTempSkill("new_meibu_range", "phaseUseAfter"); - target.markAuto("new_meibu_range", player); - } - target.markSkillCharacter("new_meibu", player, "魅步", "锁定技,出牌阶段,你至多可使用X张牌,你使用了锦囊牌后不能再使用牌(X为你的体力值)。"); + if (target.countCards("h", "shan")) { + player.viewHandcards(target); + if (player.canUse({ name: "sha", isCard: true }, target, false)) player.useCard({ name: "sha", isCard: true }, target, false); + player.storage.weikui2 = target; + player.addTempSkill("weikui2"); + } else { + player.discardPlayerCard(target, "visible", true, "h").set("ai", function (button) { + return get.value(button.link, _status.event.target); + }); } }, ai: { - expose: 0.2, - }, - subSkill: { - range: { - onremove: true, - charlotte: true, - mod: { - globalFrom: function (from, to, num) { - if (from.getStorage("new_meibu_range").includes(to)) { - return -Infinity; - } - }, + order: 8, + result: { + target: function (player, target) { + if (player.hp <= 2) return 0; + if (player.hp == 3) return target.hp <= 2 ? -1 : 0; + return -1; }, - sub: true, }, }, }, - new_mumu: { - audio: "mumu", - trigger: { - player: "phaseUseBegin", + weikui2: { + onremove: true, + mod: { + globalFrom: function (from, to) { + if (to == from.storage.weikui2) return -Infinity; + }, }, - filter: function (event, player) { - return game.hasPlayer(current => { - if (current == player) return current.getEquips(2).length > 0; - return current.countCards("e") > 0; - }); + mark: "character", + intro: { + content: "与$的距离视为1直到回合结束", }, + }, + lizhan: { + audio: 2, + trigger: { player: "phaseJieshuBegin" }, direct: true, + filter: function (event, player) { + for (var i = 0; i < game.players.length; i++) { + if (game.players[i].isDamaged()) { + return true; + } + } + return false; + }, content: function () { "step 0"; player - .chooseTarget(get.prompt("new_mumu"), "弃置一名其他角色装备区内的一张牌,或者获得一名角色装备区内的防具牌", function (card, player, target) { - if (target == player) return target.getEquips(2).length > 0; - return target.countCards("e") > 0; + .chooseTarget(get.prompt("lizhan"), "令任意名已受伤的角色各摸一张牌", [1, Infinity], function (card, player, target) { + return target.isDamaged(); }) .set("ai", function (target) { - var player = _status.event.player; - var att = get.attitude(player, target); - if (target.getEquip(2) && player.hasEmptySlot(2)) { - return -2 * att; - } - return -att; + return get.attitude(player, target); }); "step 1"; - if (result.bool && result.targets && result.targets.length) { - event.target = result.targets[0]; - player.logSkill("new_mumu", event.target); - player.line(event.target, "green"); - var e = event.target.getEquips(2); - event.e = e; - if (target == player) event.choice = "获得一张防具牌"; - else if (e.length > 0) { - player.chooseControl("弃置一张装备牌", "获得一张防具牌").set("ai", function () { - if (_status.event.player.getEquips(2).length > 0) { - return "弃置一张装备牌"; - } - return "获得一张防具牌"; - }); - } else { - event.choice = "弃置一张装备牌"; - } - } else event.finish(); - "step 2"; - var choice = event.choice || result.control; - if (choice == "弃置一张装备牌") { - player.discardPlayerCard(event.target, "e", true); - } else { - if (event.e) { - player.gain(event.e, event.target, "give", "bySelf"); - player.addTempSkill("new_mumu2"); - } - } - }, - }, - new_zhixi: { - mod: { - cardEnabled: function (card, player) { - if (player.storage.new_zhixi2 || player.countMark("new_zhixi") >= player.hp) return false; - }, - cardUsable: function (card, player) { - if (player.storage.new_zhixi2 || player.countMark("new_zhixi") >= player.hp) return false; - }, - cardSavable: function (card, player) { - if (player.storage.new_zhixi2 || player.countMark("new_zhixi") >= player.hp) return false; - }, - }, - trigger: { - player: "useCard1", - }, - forced: true, - popup: false, - firstDo: true, - init: function (player, skill) { - player.storage[skill] = 0; - var evt = _status.event.getParent("phaseUse"); - if (evt && evt.player == player) { - player.getHistory("useCard", function (evtx) { - if (evtx.getParent("phaseUse") == evt) { - player.storage[skill]++; - if (get.type2(evtx.card) == "trick") player.storage.new_zhixi2 = true; - } - }); + if (result.bool) { + player.logSkill("lizhan", result.targets); + game.asyncDraw(result.targets); } }, - onremove: function (player) { - player.unmarkSkill("new_meibu"); - delete player.storage.new_zhixi; - delete player.storage.new_zhixi2; - }, - content: function () { - player.addMark("new_zhixi", 1, false); - if (get.type2(trigger.card) == "trick") player.storage.new_zhixi2 = true; - }, ai: { - presha: true, - pretao: true, - neg: true, - nokeep: true, - }, - }, - new_mumu2: { - charlotte: true, - mod: { - cardEnabled: function (card) { - if (card.name == "sha") return false; - }, + expose: 0.3, + threaten: 1.3, }, }, - qingzhong: { - audio: 2, - trigger: { player: "phaseUseBegin" }, - check: function (event, player) { - if ( - game.hasPlayer(function (current) { - return current != player && current.isMinHandcard() && get.attitude(player, current) > 0; - }) - ) { - return true; - } - if (player.countCards("h") <= 2) return true; - // if(player.countCards('h')<=3&&!player.countCards('h','shan')) return true; - //if(player.countCards('h',{type:'basic'})<=1) return true; - return false; - }, - content: function () { - player.draw(2); - player.addTempSkill("qingzhong_give"); - }, - subSkill: { - give: { - audio: "qingzhong", - trigger: { player: "phaseUseEnd" }, - filter: function (event, player) { - return !player.isMinHandcard(true); - }, - forced: true, - content: function () { - "step 0"; - var list = game.filterPlayer(function (current) { - return current.isMinHandcard(); - }); - if (list.length == 1) { - if (list[0] != player) { - player.line(list[0], "green"); - player.swapHandcards(list[0]); - } - event.finish(); - } else { - player - .chooseTarget(true, "清忠:选择一名手牌最少的角色与其交换手牌", function (card, player, target) { - return target.isMinHandcard(); - }) - .set("ai", function (target) { - return get.attitude(_status.event.player, target); - }); - } - "step 1"; - if (result.bool) { - var target = result.targets[0]; - if (target != player) { - player.line(target, "green"); - player.swapHandcards(target); - } + xinfenyue: { + enable: "phaseUse", + audio: "fenyue", + filter: function (event, player) { + var num = game.players.length - player.getFriends(true).length; + if ((player.getStat().skill.xinfenyue || 0) >= num) return false; + return player.countCards("h") > 0; + }, + filterTarget: function (event, player, target) { + return player.canCompare(target); + }, + content: function () { + "step 0"; + player.chooseToCompare(target); + "step 1"; + if (!result.bool) event.finish(); + event.num = result.num1; + "step 2"; + if (num <= 5 && target.countGainableCards(player, "he") > 0) player.gainPlayerCard(target, "he", true); + "step 3"; + if (num <= 9) { + var card = get.cardPile2(function (x) { + return x.name == "sha"; + }); + if (card) player.gain(card, "gain2"); + } + "step 4"; + if (num <= 13) { + var card = { name: "sha", nature: "thunder" }; + if (player.canUse(card, target, false)) player.useCard(card, target, false); + } + }, + ai: { + order: 4, + result: { + target: function (player, target) { + var sort = function (a, b) { + return b.number - a.number; + }; + var ps = player.getCards("h").sort(sort); + var ts = target.getCards("h").sort(sort); + if (ps[0].number > ts[0].number) { + var effect = get.effect(target, { name: "sha", nature: "thunder" }, player, player); + if (ps[0].number < 6 && target.countCards("he") > 1) effect -= 2; + if (ps[0].number < 10) effect -= 1; + return effect; } + return ps.length >= ts.length ? -0.5 : 0; }, }, }, }, - weijing: { + fenyue: { audio: 2, - enable: "chooseToUse", + enable: "phaseUse", filter: function (event, player) { - if (event.type == "wuxie" || player.hasSkill("weijing_used")) return false; - for (var name of ["sha", "shan"]) { - if (event.filterCard({ name: name, isCard: true }, player, event)) return true; + if (!player.countCards("h")) return false; + var num; + if (get.mode() == "identity") { + num = game.countPlayer(function (current) { + return current.identity == "zhong" || current.identity == "mingzhong"; + }); + } else { + num = 1; } - return false; + if (player.getStat().skill.fenyue >= num) return false; + return true; }, - chooseButton: { - dialog: function (event, player) { - var vcards = []; - for (var name of ["sha", "shan"]) { - var card = { name: name, isCard: true }; - if (event.filterCard(card, player, event)) vcards.push(["基本", "", name]); - } - var dialog = ui.create.dialog("卫境", [vcards, "vcard"], "hidden"); - dialog.direct = true; - return dialog; - }, - backup: function (links, player) { - return { - filterCard: () => false, - selectCard: -1, - viewAs: { - name: links[0][2], - isCard: true, - }, - popname: true, - precontent: function () { - player.logSkill("weijing"); - player.addTempSkill("weijing_used", "roundStart"); - }, - }; - }, - prompt: function (links, player) { - return "卫境:视为使用一张【" + get.translation(links[0][2]) + "】"; - }, + filterTarget: function (card, player, target) { + return player.canCompare(target); }, ai: { - order: function (item, player) { - var player = _status.event.player; - var event = _status.event; - if (event.filterCard({ name: "sha" }, player, event)) { + order: 2.8, + result: { + target: function (player, target) { if ( - !player.hasShan() && - !game.hasPlayer(function (current) { - return player.canUse("sha", current) && current.hp == 1 && get.effect(current, { name: "sha" }, player, player) > 0; + get.attitude(player, target) < 0 && + player.hasCard(function (card) { + return (card.number >= 9 && get.value(card) <= 5) || get.value(card) <= 3; }) ) { + return get.effect(target, { name: "sha" }, player, target); + } else { return 0; } - return 2.95; - } else { - var player = _status.event.player; - if (player.hasSkill("qingzhong_give")) return 2.95; - return 3.15; - } - }, - respondSha: true, - respondShan: true, - skillTagFilter: function (player, tag, arg) { - if (player.hasSkill("weijing_used")) return false; - if (arg != "use") return false; - }, - result: { - player: 1, - }, - }, - subSkill: { - used: { - mark: true, - intro: { - content: "本轮已发动", - }, - }, - }, - }, - zishu: { - audio: 2, - locked: true, - subSkill: { - discard: { - trigger: { global: "phaseEnd" }, - audio: "zishu", - forced: true, - filter: function (event, player) { - if (_status.currentPhase != player) { - var he = player.getCards("h"); - var bool = false; - player.getHistory("gain", function (evt) { - if (!bool && evt && evt.cards) { - for (var i = 0; i < evt.cards.length; i++) { - if (he.includes(evt.cards[i])) bool = true; - break; - } - } - }); - return bool; - } - return false; - }, - content: function () { - var he = player.getCards("h"); - var list = []; - player.getHistory("gain", function (evt) { - if (evt && evt.cards) { - for (var i = 0; i < evt.cards.length; i++) { - if (he.includes(evt.cards[i])) list.add(evt.cards[i]); - } - } - }); - player.$throw(list, 1000); - player.lose(list, ui.discardPile, "visible"); - game.log(player, "将", list, "置入弃牌堆"); - }, - }, - mark: { - trigger: { - player: "gainBegin", - global: "phaseBeginStart", - }, - silent: true, - filter: function (event, player) { - return event.name != "gain" || player != _status.currentPhase; - }, - content: function () { - if (trigger.name == "gain") trigger.gaintag.add("zishu"); - else player.removeGaintag("zishu"); - }, - }, - draw: { - trigger: { - player: "gainAfter", - global: "loseAsyncAfter", }, - audio: "zishu", - forced: true, - filter: function (event, player) { - if (_status.currentPhase != player || event.getg(player).length == 0) return false; - return event.getParent(2).name != "zishu_draw"; - }, - content: function () { - player.draw("nodelay"); - }, - }, - }, - ai: { - threaten: 1.2, - nogain: 1, - skillTagFilter: function (player) { - return player != _status.currentPhase; }, }, - group: ["zishu_draw", "zishu_discard", "zishu_mark"], - }, - xinyingyuan: { - audio: "yingyuan", - trigger: { player: "useCardAfter" }, - direct: true, - filter: function (event, player) { - if (_status.currentPhase != player) return false; - var type = get.type(event.card, "trick"); - return ( - player.getHistory("custom", function (evt) { - return evt.xinyingyuan_name == type; - }).length == 0 - ); - }, content: function () { "step 0"; - event.type = get.type(trigger.card, "trick"); - player - .chooseTarget(get.prompt("xinyingyuan"), "令一名其他角色从牌堆中获得一张" + get.translation(event.type) + "牌", function (card, player, target) { - return target != player; - }) - .set("ai", function (target) { - var att = get.attitude(_status.event.player, target); - if (att < 3) return 0; - if (target.hasJudge("lebu")) att /= 2; - if (target.hasSkillTag("nogain")) att /= 10; - return att / (1 + get.distance(player, target, "absolute")); - }); + player.chooseToCompare(target); "step 1"; if (result.bool) { - player.logSkill("xinyingyuan", result.targets[0]); - var card = get.cardPile2(function (cardx) { - return get.type(cardx, "trick") == event.type; - }); - if (card) result.targets[0].gain(card, "log", "gain2"); - player.getHistory("custom").push({ xinyingyuan_name: event.type }); + player + .chooseControl(function () { + return 1; + }) + .set("choiceList", ["令" + get.translation(target) + "不能使用或打出手牌直到回合结束", "视为对" + get.translation(target) + "使用一张杀(不计入次数限制)"]); + } else { + var evt = _status.event.getParent("phaseUse"); + if (evt && evt.name == "phaseUse") { + evt.skipped = true; + } + event.finish(); + } + "step 2"; + if (result.control == "选项一") { + target.addTempSkill("fenyue2"); + } else { + player.useCard({ name: "sha", isCard: true }, target, false); } }, }, - yingyuan: { + fenyue2: { + mark: true, + mod: { + cardEnabled2: function (card) { + if (get.position(card) == "h") return false; + }, + }, + intro: { + content: "不能使用或打出手牌", + }, + }, + + zfengshi: { audio: 2, - trigger: { player: "useCardAfter" }, - direct: true, + trigger: { player: "useCardToPlayered" }, filter: function (event, player) { - if (_status.currentPhase != player) return false; - if ( - player.getHistory("custom", function (evt) { - return evt.yingyuan_name == event.card.name; - }).length > 0 - ) - return false; - return event.cards.filterInD().length > 0; + return event.card.name == "sha" && event.target.countCards("e"); + }, + logTarget: "target", + check: function (event, player) { + if (event.target.hasSkillTag("noe")) return false; + return get.attitude(player, event.target) < 0; }, content: function () { - "step 0"; - player - .chooseTarget(get.prompt("yingyuan"), "将" + get.translation(trigger.cards) + "交给一名其他角色", function (card, player, target) { - return target != player; - }) - .set("ai", function (target) { - if (target.hasJudge("lebu")) return 0; - let att = get.attitude(_status.event.player, target), - name = _status.event.cards[0].name; - if (att < 3) return 0; - if (target.hasSkillTag("nogain")) att /= 10; - if (name === "sha" && target.hasSha()) att /= 5; - if (name === "wuxie" && target.needsToDiscard(_status.event.cards)) att /= 5; - return att / (1 + get.distance(player, target, "absolute")); - }) - .set("cards", trigger.cards); - "step 1"; - if (result.bool) { - player.logSkill("yingyuan", result.targets[0]); - result.targets[0].gain(trigger.cards.filterInD(), "gain2"); - player.getHistory("custom").push({ yingyuan_name: trigger.card.name }); - } + trigger.target.chooseToDiscard("e", true); }, }, - shuimeng: { + chuanxin: { audio: 2, - trigger: { player: "phaseUseAfter" }, - direct: true, + trigger: { source: "damageBegin2" }, + preHidden: true, filter: function (event, player) { - return player.countCards("h"); + if (_status.currentPhase != player) return false; + if (!_status.event.getParent("phaseUse")) return false; + if (event.card && (event.card.name == "sha" || event.card.name == "juedou") && event.getParent().name == event.card.name) { + if (get.mode() == "guozhan") { + return (event.player.identity != "qun" || player.identity == "ye") && !event.player.isUnseen() && event.player.hasViceCharacter(); + } else { + var info = lib.character[event.player.name]; + if (!info) return false; + var skills = event.player.getSkills(); + for (var i = 0; i < info[3].length; i++) { + if (lib.skill[info[3][i]].fixed) continue; + if (skills.includes(info[3][i])) return true; + } + } + } + return false; + }, + logTarget: "player", + check: function (event, player) { + if (get.mode() == "guozhan") { + if (!event.player.isUnseen(1) && get.guozhanRank(event.player.name2, event.player) < 4) return false; + } + if (event.player.hasSkill("subplayer")) return false; + if (get.attitude(player, event.player) < 0) { + if (event.player.hp == 1 && event.player.countCards("e") < 2 && event.player.name2 != "gz_pangtong") return false; + return true; + } + return false; }, content: function () { "step 0"; - player - .chooseTarget(get.prompt2("shuimeng"), function (card, player, target) { - return player.canCompare(target); - }) - .set("ai", function (target) { - if (!_status.event.goon) return 0; - return -get.attitude(_status.event.player, target); - }) - .set( - "goon", - player.needsToDiscard() || - player.hasCard(function (card) { - var val = get.value(card); - if (val < 0) return true; - if (val <= 5) { - return card.number >= 11; - } - if (val <= 6) { - return card.number >= 12; - } - return false; - }) - ); - "step 1"; - if (result.bool) { - player.logSkill("shuimeng", result.targets); - event.target = result.targets[0]; - player.chooseToCompare(event.target); + trigger.cancel(); + if (trigger.player.countCards("e")) { + trigger.player + .chooseControl(function (event, player) { + if (get.mode() == "guozhan" && get.guozhanRank(player.name2, player) < 4) return 1; + if (player.hp == 1) return 1; + if (player.hp == 2 && player.countCards("e") >= 2) return 1; + return 0; + }) + .set("choiceList", ["弃置装备区内的所有牌并失去1点体力", get.mode() == "guozhan" ? "移除副将牌" : "随机移除武将牌上的一个技能"]); } else { - event.finish(); + event._result = { index: 1 }; } - "step 2"; - if (result.bool) { - player.chooseUseTarget({ name: "wuzhong", isCard: true }, true); + "step 1"; + if (result.index == 1) { + if (get.mode() != "guozhan") { + var info = lib.character[trigger.player.name]; + var skills = trigger.player.getSkills(); + var list = []; + for (var i = 0; i < info[3].length; i++) { + if (lib.skill[info[3][i]].fixed) continue; + if (skills.includes(info[3][i])) { + list.push(info[3][i]); + } + } + if (list.length) { + var skill = list.randomGet(); + trigger.player.removeSkills(skill); + } + } else { + trigger.player.removeCharacter(1); + } } else { - event.target.useCard({ name: "guohe", isCard: true }, player); + trigger.player.discard(trigger.player.getCards("e")); + trigger.player.loseHp(); } }, }, - qianya: { + hengjiang: { audio: 2, - trigger: { target: "useCardToTargeted" }, - direct: true, + trigger: { player: "damageEnd" }, + preHidden: true, + check: function (event, player) { + return get.attitude(player, _status.currentPhase) < 0 || !_status.currentPhase.needsToDiscard(2); + }, + filter: function (event) { + return _status.currentPhase && _status.currentPhase.isIn() && event.num > 0; + }, + logTarget: function () { + return _status.currentPhase; + }, + content: function () { + var source = _status.currentPhase; + if (source.hasSkill("hengjiang2")) { + source.storage.hengjiang2 += trigger.num; + source.storage.hengjiang3.add(player); + source.updateMarks(); + } else { + source.storage.hengjiang3 = [player]; + source.storage.hengjiang2 = trigger.num; + source.addTempSkill("hengjiang2"); + } + }, + ai: { + maixie_defend: true, + }, + }, + hengjiang2: { + mark: true, + charlotte: true, + intro: { + content: "手牌上限-#", + }, + mod: { + maxHandcard: function (player, num) { + return num - player.storage.hengjiang2; + }, + }, + onremove: function (player) { + delete player.storage.hengjiang2; + delete player.storage.hengjiang3; + }, + trigger: { player: "phaseDiscardEnd" }, filter: function (event, player) { - return get.type(event.card, "trick") == "trick" && player.countCards("h"); + if (event.cards && event.cards.length) return false; + var players = player.storage.hengjiang3; + for (var i = 0; i < players.length; i++) { + if (players[i].isIn()) return true; + } + return false; }, + forced: true, + popup: false, content: function () { - "step 0"; - var nh = player.countCards("h"); - player.chooseCardTarget({ - filterCard: true, - filterTarget: function (card, player, target) { - return target != player; - }, - selectCard: [1, nh], - ai1: function (card) { - var player = _status.event.player; - var cardname = _status.event.cardname; - if (_status.event.du) return -get.value(card, player, "raw"); - else if (_status.event.shuimeng) { - if (cardname == "wuzhong") { - if ( - player.needsToDiscard(2, (i, player) => { - return !ui.selected.cards.includes(i) && !player.canIgnoreHandcard(i); - }) - ) - return 10 - get.value(card, player, "raw"); - } else if (cardname == "guohe") { - if ( - player.needsToDiscard(-1, (i, player) => { - return !ui.selected.cards.includes(i) && !player.canIgnoreHandcard(i); - }) - ) - return 10 - get.value(card, player, "raw"); - } - return 0; - } else if (cardname == "lebu") { - if ( - player.needsToDiscard(1, (i, player) => { - return !ui.selected.cards.includes(i) && !player.canIgnoreHandcard(i); - }) - ) { - return 8 - get.value(card, player, "raw"); - } else { - if (!ui.selected.cards.length) { - return 6 - get.value(card, player, "raw"); - } - return 0; - } - } else if (cardname == "shunshou") { - if (_status.event.nh <= 2) return get.value(card, player, "raw"); - } else if (cardname == "huogong") { - if (player.hp == 1) return get.value(card, player, "raw"); - } - if (ui.selected.cards.length) return 0; - return 7 - get.value(card, player, "raw"); - }, - ai2: function (target) { - var att = get.attitude(_status.event.player, target); - var nh2 = target.countCards("h"); - var num = Math.sqrt(1 + nh2); - var cardname = _status.event.cardname; - if (_status.event.du) return 0.5 - att; - else if (_status.event.shuimeng) { - return att / num; - } else if (cardname == "lebu") { - return att / num; - } else if (cardname == "shunshou") { - if (_status.event.nh <= 2) return att / num; - } else if (cardname == "huogong") { - if (_status.event.player.hp == 1) return att / num; - } - if (_status.event.nh > nh2 + 1) { - return att / num; - } - return 0; - }, - du: player.hasCard(function (card) { - return get.value(card, player, "raw") < 0; - }), - shuimeng: trigger.getParent(2).name == "shuimeng", - nh: nh, - cardname: trigger.card.name, - prompt: get.prompt2("qianya"), - }); - "step 1"; - if (result.bool) { - player.logSkill("qianya", result.targets); - player.give(result.cards, result.targets[0]); + var players = player.storage.hengjiang3; + for (var i = 0; i < players.length; i++) { + if (players[i].isIn()) { + players[i].logSkill("hengjiang"); + players[i].line(player, "green"); + } } + game.asyncDraw(player.storage.hengjiang3); }, }, - xianfu: { - trigger: { - global: "phaseBefore", - player: "enterGame", + rehengjiang: { + audio: "hengjiang", + trigger: { player: "damageEnd" }, + check: function (event, player) { + return get.attitude(player, _status.currentPhase) < 0 || !_status.currentPhase.needsToDiscard(2); }, - forced: true, - filter: function (event, player) { - return game.hasPlayer(current => current != player) && (event.name != "phase" || game.phaseNumber == 0); + filter: function (event) { + return _status.currentPhase && _status.currentPhase.isIn() && event.num > 0; }, - audio: 6, + logTarget: function () { + return _status.currentPhase; + }, + preHidden: true, content: function () { "step 0"; - player - .chooseTarget("请选择【先辅】的目标", lib.translate.xianfu_info, true, function (card, player, target) { - return target != player && (!player.storage.xianfu2 || !player.storage.xianfu2.includes(target)); - }) - .set("ai", function (target) { - var att = get.attitude(_status.event.player, target); - if (att > 0) return att + 1; - if (att == 0) return Math.random(); - return att; - }).animate = false; + event.count = trigger.num; "step 1"; + event.count--; + var source = _status.currentPhase; + source.addTempSkill("rehengjiang2"); + source.addMark("rehengjiang2", 1, false); + player.addTempSkill("rehengjiang3"); + "step 2"; + if (event.count && player.hasSkill("rehengjiang")) { + player.chooseBool(get.prompt2("rehengjiang", _status.currentPhase)).set("ai", function () { + return lib.skill.rehengjiang.check(_status.event.getTrigger(), _status.event.player); + }); + } else event.finish(); + "step 3"; if (result.bool) { - var target = result.targets[0]; - if (!player.storage.xianfu2) player.storage.xianfu2 = []; - player.storage.xianfu2.push(target); - player.addSkill("xianfu2"); + player.logSkill("rehengjiang", _status.currentPhase); + event.goto(1); } }, + ai: { + maixie_defend: true, + notemp: true, + }, }, - xianfu_mark: { - marktext: "辅", + rehengjiang2: { + mark: true, + charlotte: true, + onremove: true, intro: { - name: "先辅", - content: "当你受到伤害后,$受到等量的伤害,当你回复体力后,$回复等量的体力", + content: "手牌上限-#", + }, + mod: { + maxHandcard: function (player, num) { + return num - player.storage.rehengjiang2; + }, }, }, - xianfu2: { - audio: "xianfu", - charlotte: true, - trigger: { global: ["damageEnd", "recoverEnd"] }, + rehengjiang3: { + audio: "hengjiang", + trigger: { global: "phaseEnd" }, forced: true, - filter: function (event, player) { - if (event.player.isDead() || !player.storage.xianfu2 || !player.storage.xianfu2.includes(event.player) || event.num <= 0) return false; - if (event.name == "damage") return true; - return player.isDamaged(); + charlotte: true, + filterx: function (event, player) { + if (!event.player.countMark("rehengjiang2")) return false; + if ( + event.player.hasHistory("lose", function (evt) { + return evt.type == "discard" && evt.cards2.length > 0 && evt.getParent("phaseDiscard").player == event.player; + }) + ) + return false; + return true; }, logTarget: "player", content: function () { - "step 0"; - var target = trigger.player; - if (!target.storage.xianfu_mark) target.storage.xianfu_mark = []; - target.storage.xianfu_mark.add(player); - target.storage.xianfu_mark.sortBySeat(); - target.markSkill("xianfu_mark"); - game.delayx(); - "step 1"; - player[trigger.name](trigger.num, "nosource"); - }, - onremove: function (player) { - if (!player.storage.xianfu2) return; - game.countPlayer(function (current) { - if (player.storage.xianfu2.includes(current) && current.storage.xianfu_mark) { - current.storage.xianfu_mark.remove(player); - if (!current.storage.xianfu_mark.length) current.unmarkSkill("xianfu_mark"); - else current.markSkill("xianfu_mark"); - } - }); - delete player.storage.xianfu2; + if (lib.skill.rehengjiang3.filterx(trigger, player)) { + var num = player.getHistory("useSkill", function (evt) { + return evt.skill == "rehengjiang" && evt.targets.includes(trigger.player); + }).length; + if (num > 0) player.draw(num); + } else player.draw(); }, - group: "xianfu3", }, - xianfu3: { - trigger: { global: "dieBegin" }, - silent: true, + shuangren: { + trigger: { player: "phaseUseBegin" }, + direct: true, + preHidden: true, filter: function (event, player) { - return event.player == player || (player.storage.xianfu2 && player.storage.xianfu2.includes(player)); - }, - content: function () { - if (player == trigger.player) lib.skill.xianfu2.onremove(player); - else player.storage.xianfu2.remove(event.player); + return ( + player.countCards("h") > 0 && + game.hasPlayer(function (current) { + return current != player && player.canCompare(current); + }) + ); }, - }, - chouce: { - trigger: { player: "damageEnd" }, content: function () { "step 0"; - event.num = trigger.num; + var goon; + if (player.needsToDiscard() > 1) { + goon = player.hasCard(function (card) { + return card.number > 10 && get.value(card) <= 5; + }); + } else { + goon = player.hasCard(function (card) { + return (card.number >= 9 && get.value(card) <= 5) || get.value(card) <= 3; + }); + } + player + .chooseTarget(get.prompt2("shuangren"), function (card, player, target) { + return player.canCompare(target); + }) + .set("ai", function (target) { + var player = _status.event.player; + if (_status.event.goon && get.attitude(player, target) < 0) { + return get.effect(target, { name: "sha" }, player, player); + } + return 0; + }) + .set("goon", goon) + .setHiddenSkill(event.name); "step 1"; - player.judge(); + if (result.bool) { + var target = result.targets[0]; + event.target = target; + player.logSkill("shuangren", target); + player.chooseToCompare(target); + } else { + event.finish(); + } "step 2"; - event.color = result.color; - if (event.color == "black") { + if (result.bool) { + var target = event.target; if ( game.hasPlayer(function (current) { - return current.countDiscardableCards(player, "hej") > 0; + if (target == current) return false; + if (!player.canUse("sha", current, false)) return false; + return target.isFriendOf(current); }) - ) + ) { + var str = "对一名与" + get.translation(target) + "势力相同的"; player - .chooseTarget( - "弃置一名角色区域内的一张牌", - function (card, player, target) { - return target.countDiscardableCards(player, "hej"); - }, - true - ) + .chooseTarget(str + "角色使用一张杀", true, function (card, player, target) { + if (!player.canUse("sha", target, false)) return false; + if (get.mode() == "guozhan") { + return target.isFriendOf(_status.event.identity); + } + return true; + }) .set("ai", function (target) { var player = _status.event.player; - var att = get.attitude(player, target); - if (att < 0) { - att = -Math.sqrt(-att); - } else { - att = Math.sqrt(att); - } - return att * lib.card.guohe.ai.result.target(player, target); - }); - else event.finish(); - } else { - var next = player.chooseTarget("令一名角色摸一张牌"); - if (player.storage.xianfu2 && player.storage.xianfu2.length) { - next.set("prompt2", "(若目标为" + get.translation(player.storage.xianfu2) + "则改为摸两张牌)"); - } - next.set("ai", function (target) { - var player = _status.event.player; - var att = get.attitude(player, target) / Math.sqrt(1 + target.countCards("h")); - if (target.hasSkillTag("nogain")) att /= 10; - if (player.storage.xianfu2 && player.storage.xianfu2.includes(target)) return att * 2; - return att; - }); - } - "step 3"; - if (result.bool) { - var target = result.targets[0]; - player.line(target, "green"); - if (event.color == "black") { - player.discardPlayerCard(target, "hej", true); + return get.effect(target, { name: "sha" }, player, player); + }) + .set("identity", target); } else { - if (player.storage.xianfu2 && player.storage.xianfu2.includes(target)) { - if (!target.storage.xianfu_mark) target.storage.xianfu_mark = []; - target.storage.xianfu_mark.add(player); - target.storage.xianfu_mark.sortBySeat(); - target.markSkill("xianfu_mark"); - target.draw(2); - } else { - target.draw(); - } + player.useCard({ name: "sha", isCard: true }, target, false); + event.finish(); } - } - "step 4"; - if (--event.num > 0 && player.hasSkill("chouce")) { - player.chooseBool(get.prompt2("chouce")); } else { + player.addTempSkill("zishou2"); event.finish(); } - "step 5"; + "step 3"; + if (result.bool && result.targets && result.targets.length) { + player.useCard({ name: "sha", isCard: true }, result.targets[0], false); + } + }, + }, + kuanshi: { + audio: 2, + trigger: { player: "phaseJieshuBegin" }, + direct: true, + content: function () { + "step 0"; + player.chooseTarget(get.prompt2("kuanshi")).set("ai", function (target) { + if (get.attitude(_status.event.player, target) > 0) { + return 1 / Math.sqrt(target.hp + 1); + } + return 0; + }).animate = false; + "step 1"; if (result.bool) { - player.logSkill("chouce"); - event.goto(1); + var target = result.targets[0]; + player.logSkill("kuanshi"); + target.storage.kuanshi2 = player; + target.addSkill("kuanshi2"); } }, - ai: { - maixie: true, - maixie_hp: true, - effect: { - target: function (card, player, target) { - if (get.tag(card, "damage")) { - if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; - if (!target.hasFriend()) return; - if (target.hp >= 4) return [1, get.tag(card, "damage") * 1.5]; - if (target.hp == 3) return [1, get.tag(card, "damage") * 1]; - if (target.hp == 2) return [1, get.tag(card, "damage") * 0.5]; - } - }, - }, - }, }, - fuqi: { - audio: 2, + kuanshi2: { + /*mark:'character', + intro:{ + content:'下一次受到超过1点的伤害时,防止此伤害,然后$跳过下个回合的摸牌阶段' + },*/ + trigger: { player: "damageBegin4" }, forced: true, - trigger: { - player: "useCard", - }, filter: function (event, player) { - return ( - event.card && - (get.type(event.card) == "trick" || (get.type(event.card) == "basic" && !["shan", "tao", "jiu", "du"].includes(event.card.name))) && - game.hasPlayer(function (current) { - return current != player && get.distance(current, player) <= 1; - }) - ); + return event.num > 1; }, + //priority:-11, content: function () { - trigger.directHit.addArray( - game.filterPlayer(function (current) { - return current != player && get.distance(current, player) <= 1; - }) - ); + trigger.cancel(); + player.storage.kuanshi2.skip("phaseDraw"); + player.removeSkill("kuanshi2"); }, - ai: { - directHit_ai: true, - skillTagFilter: function (player, tag, arg) { - return get.distance(arg.target, player) <= 1; + group: "kuanshi2_remove", + onremove: true, + subSkill: { + remove: { + trigger: { global: ["phaseZhunbeiBegin", "dieAfter"] }, + forced: true, + popup: false, + filter: function (event, player) { + return event.player == player.storage.kuanshi2; + }, + content: function () { + player.removeSkill("kuanshi2"); + }, }, }, }, - wylianji: { - enable: "phaseUse", + xiashu: { audio: 2, - usable: 1, + trigger: { player: "phaseUseBegin" }, + direct: true, filter: function (event, player) { - return player.hasCard(lib.skill.wylianji.filterCard); - }, - check: function (card) { - if (card.name == "sha") return 1; - else { - if (get.tag(card, "damage")) { - if (get.tag(card, "multineg")) return 5; - return 2; - } - } - return 0; - }, - filterCard: function (card) { - return get.name(card) == "sha" || (get.type(card, "trick") == "trick" && get.color(card) == "black" && !get.info(card).multitarget && get.info(card).enable); - }, - filterTarget: function (card, player, target) { - return ( - target != player && - !target.isMin() && - (player.canUse(card, target, false) || - game.hasPlayer(function (current) { - return current != player && target.canUse(card, current); - })) - ); + return player.countCards("h") > 0; }, - discard: false, - lose: true, - delay: false, content: function () { "step 0"; - player.showCards(get.translation(player) + "对" + get.translation(target) + "发动了【连计】", cards); + var maxval = 0; + var hs = player.getCards("h"); + for (var i = 0; i < hs.length; i++) { + maxval = Math.max(maxval, get.value(hs[i])); + } + player + .chooseTarget(get.prompt2("xiashu"), lib.filter.notMe) + .set("ai", function (target) { + var player = _status.event.player; + var maxval = _status.event.maxval; + var dh = target.countCards("h") - player.countCards("h"); + var att = get.attitude(player, target); + if (target.hasSkill("qingjian")) return false; + if (dh <= 0) return 0; + if (att > 0) return 0.1; + if (maxval >= 8) return 0; + if (att == 0) return 0.2; + if (dh >= 3) return dh; + if (dh == 2) { + if (maxval <= 7) return dh; + } + if (maxval <= 6) return dh; + return 0; + }) + .set("maxval", maxval); "step 1"; - var equip1 = get.cardPile2(function (card) { - return get.subtype(card) == "equip1"; - }); - if (!equip1) { - player.popup("杯具"); - game.log("牌堆中无装备"); + if (result.bool) { + player.logSkill("xiashu", result.targets); + event.target = result.targets[0]; + var hs = player.getCards("h"); + player.give(hs, event.target); + } else { event.finish(); - return; - } - if (equip1.name == "qinggang" && !lib.inpile.includes("qibaodao")) { - equip1.remove(); - equip1 = game.createCard2("qibaodao", equip1.suit, equip1.number); } - target.$draw(equip1); - target.chooseUseTarget(true, equip1, "nothrow", "nopopup"); - game.delay(); "step 2"; - game.updateRoundNumber(); - var card = cards[0]; - var bool1 = game.hasPlayer(function (current) { - return current != player && target.canUse(card, current); - }); - var bool2 = player.canUse(card, target, false); - if (bool1 && bool2) { - target - .chooseControl(function () { - return 0; - }) - .set("choiceList", ["对除" + get.translation(player) + "以外的角色使用" + get.translation(cards) + ",并将装备区里的武器牌交给该牌的一个目标角色", "视为" + get.translation(player) + "对你使用" + get.translation(cards) + ",并将装备区内的武器牌交给" + get.translation(player)]); - } else if (bool1) { - event.directindex = 0; - } else if (bool2) { - event.directindex = 1; - } else { + var hs = event.target.getCards("h"); + if (!hs.length) { event.finish(); + return; } + hs.sort(function (a, b) { + return get.value(b, player, "raw") - get.value(a, player, "raw"); + }); + event.target + .chooseCard([1, hs.length], "展示至少一张手牌", true) + .set("ai", function (card) { + var rand = _status.event.rand; + var list = _status.event.list; + if (_status.event.att) { + if (ui.selected.cards.length >= Math.ceil(list.length / 2)) return 0; + var value = get.value(card); + if (_status.event.getParent().player.isHealthy()) { + value += (get.tag(card, "damage") ? 1.5 : 0) + (get.tag(card, "draw") ? 2 : 0); + } + return value; + } + if (ui.selected.cards.length >= Math.floor(list.length / 2)) return 0; + return list.indexOf(card) % 2 == rand ? 1 : 0; + }) + .set("rand", Math.random() < 0.6 ? 1 : 0) + .set("list", hs) + .set("att", get.attitude(event.target, player) > 0); "step 3"; - var card = cards[0]; - if (result && typeof event.directindex != "number") { - event.directindex = result.index; + event.target.showCards(result.cards); + event.cards1 = result.cards; + event.cards2 = event.target.getCards("h", function (card) { + return !event.cards1.includes(card); + }); + "step 4"; + var choice; + var num1 = event.cards1.length; + var num2 = event.cards2.length; + if (get.attitude(event.target, player) > 0 && num1 >= num2) { + choice = 0; + } else if (num1 == num2) { + choice = Math.random() < 0.45 ? 0 : 1; + } else if (num1 > num2) { + if (num1 - num2 == 1) { + choice = Math.random() < 0.6 ? 0 : 1; + } else { + choice = 0; + } + } else { + if (num2 - num1 == 1) { + choice = Math.random() < 0.6 ? 1 : 0; + } else { + choice = 1; + } } - if (event.directindex == 1) { - event.insert(lib.skill.wylianji.content_use, { - player: player, - target: target, - card: card, - }); + player + .chooseControl(function (event, player) { + return _status.event.choice; + }) + .set("choiceList", ["获得" + get.translation(event.target) + "展示的牌", "获得" + get.translation(event.target) + "未展示的牌"]) + .set("choice", choice); + "step 5"; + if (result.index == 0) { + player.gain(event.cards1, target, "give", "bySelf"); } else { - event.insert(lib.skill.wylianji.content_give, { - player: target, - card: card, - targets: game.filterPlayer(function (current) { - return current != player; - }), - }); + player.gain(event.cards2, target, "giveAuto", "bySelf"); } }, - content_use: function () { + ai: { + expose: 0.1, + }, + }, + sheyan: { + audio: 2, + trigger: { target: "useCardToTarget" }, + filter: function (event, player) { + if (!event.targets || !event.targets.includes(player)) return false; + var info = get.info(event.card); + if (info.type != "trick") return false; + if (info.multitarget) return false; + if (event.targets.length > 1) return true; + return game.hasPlayer(function (current) { + return !event.targets.includes(current) && lib.filter.targetEnabled2(event.card, event.player, current); + }); + }, + direct: true, + content: function () { "step 0"; - player.useCard(card, target); + var bool1 = trigger.targets.length > 1; + var bool2 = game.hasPlayer(function (current) { + return !trigger.targets.includes(current) && lib.filter.targetEnabled2(trigger.card, trigger.player, current); + }); + if (bool1 && bool2) { + player + .chooseControlList(get.prompt("sheyan"), ["为" + get.translation(trigger.card) + "增加一个目标", "为" + get.translation(trigger.card) + "减少一个目标"], function (event, player) { + if (_status.event.add) return 0; + return 1; + }) + .set("add", get.effect(player, trigger.card, trigger.player, player) >= 0); + } else if (bool2) { + event.type = "add"; + event.goto(2); + event.unchosen = true; + } else { + event.type = "remove"; + event.goto(2); + event.unchosen = true; + } "step 1"; - if (!get.owner(card)) { - target.gain(card, "gain2"); + if (result.control == "cancel2") { + event.finish(); + } else if (result.index == 1) { + event.type = "remove"; + } else { + event.type = "add"; } "step 2"; - var equip1 = target.getEquips(1); - if (equip1.length) { - game.delay(); - target.give(equip1, player); - target.line(player); - } - }, - content_give: function () { - "step 0"; - var select = get.select(get.info(card).selectTarget); - if (select[1] == -1) { - for (var i = 0; i < targets.length; i++) { - if (!player.canUse(card, targets[i])) { - targets.splice(i--, 1); - } - } - if (targets.length) { - player.useCard(card, targets); - } - event.list = targets.slice(0); - event.goto(2); + if (event.type == "add") { + player + .chooseTarget(event.unchosen ? get.prompt("sheyan") : null, "为" + get.translation(trigger.card) + "增加一个目标", function (card, player, target) { + var trigger = _status.event.getTrigger(); + return !trigger.targets.includes(target) && lib.filter.targetEnabled2(trigger.card, trigger.player, target); + }) + .set("ai", function (target) { + var trigger = _status.event.getTrigger(); + return get.effect(target, trigger.card, trigger.player, _status.event.player); + }); } else { player - .chooseTarget(select, "选择" + get.translation(card) + "的目标", true, function (cardx, player, target) { - var card = _status.event.card; - return _status.event.targets.includes(target) && player.canUse(card, target); + .chooseTarget(event.unchosen ? get.prompt("sheyan") : null, "为" + get.translation(trigger.card) + "减少一个目标", function (card, player, target) { + return _status.event.targets.includes(target); }) .set("ai", function (target) { - var card = _status.event.card; - var player = _status.event.player; - return get.effect(target, card, player, player); + var trigger = _status.event.getTrigger(); + return -get.effect(target, trigger.card, trigger.player, _status.event.player); }) - .set("targets", targets) - .set("card", card); + .set("targets", trigger.targets); } - "step 1"; + "step 3"; if (result.bool) { - player.useCard(card, result.targets); - event.list = result.targets.slice(0); - } - "step 2"; - var equip1 = player.getEquips(1); - if (equip1.length) { - for (var i = 0; i < event.list.length; i++) { - if (event.list[i].isDead()) event.list.splice(i--, 1); - } - if (event.list.length > 1) { - player - .chooseTarget(true, "将" + get.translation(equip1) + "交给一名角色", function (card, player, target) { - return _status.event.list.includes(target); - }) - .set("ai", function (target) { - return get.attitude(player, target); - }) - .set("list", _status.event.list); - event.equip1 = equip1; - } else { - if (event.list.length == 1) { - player.give(equip1, event.list[0]); - player.line(event.list); - } - event.finish(); - } + if (!event.isMine() && !event.isOnline()) game.delayx(); + event.target = result.targets[0]; } else { event.finish(); } - "step 3"; - if (result.bool && result.targets.length && event.equip1) { - player.give(event.equip1, result.targets[0]); - player.line(result.targets); + "step 4"; + player.logSkill("sheyan", event.target); + if (event.type == "add") { + trigger.targets.push(event.target); + } else { + trigger.getParent().excluded.add(event.target); } }, ai: { - order: 7, - result: { - target: function (player, target) { - if (ui.selected.cards.length) { - var card = ui.selected.cards[0]; - var bool = card.name != "sha"; - if ( - game.hasPlayer(function (current) { - return target.canUse(card, current, bool) && get.effect(current, card, target, player) > 0; - }) - ) { - var num = 1; - if (target.getEquip(1)) { - num = 0.6; - } - if (target.hasSkillTag("noe")) 2 * num; - return num; - } - } - return 0; - }, - }, + expose: 0.2, }, }, - moucheng: { + bingzheng: { audio: 2, - derivation: ["jingong", "wy_meirenji", "wy_xiaolicangdao"], - trigger: { global: "damageEnd" }, - forced: true, - popup: false, - filter: function (event, player) { - return event.source != player && event.getParent(2).name == "useCard" && event.getParent(3).name == "wylianjiInserted"; - }, - init: function (player) { - player.storage.moucheng = 0; - }, - intro: { - content: "已造成#点伤害", - }, - unique: true, - juexingji: true, + trigger: { player: "phaseUseEnd" }, + direct: true, content: function () { - player.storage.moucheng += trigger.num; - if (player.hasSkill("moucheng")) { - player.markSkill("moucheng"); - player.syncStorage("moucheng"); - } - if (player.storage.moucheng >= 3) { - event.trigger("mouchengAwaken"); - } - }, - group: "moucheng_awaken", - subSkill: { - awaken: { - trigger: { player: "mouchengAwaken" }, - forced: true, - skillAnimation: true, - animationColor: "gray", - content: function () { - player.awakenSkill("moucheng"); - game.log(player, "失去了技能", "#g【连计】"); - player.changeSkills(["jingong"], ["wylianji"]); - }, - }, - }, - ai: { - combo: "wylianji", - }, - }, - jingong: { - audio: 2, - enable: "phaseUse", - usable: 1, - filter: function (event, player) { - return ( - event.xinjingong_list && - player.countCards("hes", function (card) { - return card.name == "sha" || get.type(card) == "equip"; + "step 0"; + player + .chooseTarget(get.prompt2("bingzheng"), function (card, player, target) { + return target.countCards("h") != target.hp; }) - ); - }, - onChooseToUse: function (event) { - if (!game.online) { - var evt = event.getParent(); - if (evt.name != "phaseUse") return; - if (!evt.xinjingong_list) { - var list = get.inpile("trick").randomGets(2); - if (Math.random() < 0.5) { - list.push("wy_meirenji"); + .set("ai", function (target) { + var player = _status.event.player; + var att = get.attitude(player, target); + var nh = target.countCards("h"); + if (att > 0) { + if (nh == target.hp - 1) { + if (player == target) return att + 1; + return att + 2; + } + if (player == target && player.needsToDiscard()) return att / 3; + return att; } else { - list.push("wy_xiaolicangdao"); + if (nh == target.hp + 1) return -att; + if (nh == 0) return 0; + return -att / 2; + } + }); + "step 1"; + if (result.bool) { + player.logSkill("bingzheng", result.targets); + event.target = result.targets[0]; + if (event.target.countCards("h")) { + player + .chooseControl(function (event, player) { + var target = event.target; + if (get.attitude(player, target) < 0) return 1; + return 0; + }) + .set("choiceList", ["令" + get.translation(event.target) + "摸一张牌", "令" + get.translation(event.target) + "弃置一张手牌"]); + } else { + event.directfalse = true; + } + } else { + event.finish(); + } + "step 2"; + if (event.directfalse || result.index == 0) { + event.target.draw(); + } else { + event.target.chooseToDiscard("h", true); + } + "step 3"; + if (event.target.countCards("h") == event.target.hp) { + player.draw(); + if (event.target == player) { + event.finish(); + return; + } + var next = player.chooseCard("是否交给" + get.translation(event.target) + "一张牌?", "he"); + next.set("ai", function (card) { + if (get.position(card) != "h") return 0; + if (_status.event.shan && card.name == "shan") { + return 11; } - evt.xinjingong_list = list; + if (_status.event.goon) { + return 10 - get.value(card); + } + return -get.value(card, _status.event.player, "raw"); + }); + if (get.attitude(player, event.target) > 1 && player.countCards("h", "shan") > 1 && player.countCards("h") > event.target.countCards("h")) { + next.set("shan", true); } - if (!event.xinjingong_list) event.set("xinjingong_list", evt.xinjingong_list); + if (get.attitude(player, event.target) > 0 && player.needsToDiscard()) { + next.set("goon", true); + } + } else { + event.finish(); + } + "step 4"; + if (result.bool) { + player.give(result.cards, target); } - }, - chooseButton: { - dialog: function (event, player) { - var list = []; - for (var i of event.xinjingong_list) list.push(["锦囊", "", i]); - return ui.create.dialog("矜功", [list, "vcard"]); - }, - filter: function (button, player) { - return lib.filter.filterCard({ name: button.link[2] }, player, _status.event.getParent()); - }, - check: function (button) { - return _status.event.player.getUseValue({ name: button.link[2] }); - }, - backup: function (links, player) { - return { - audio: "jingong", - popname: true, - position: "hes", - viewAs: { name: links[0][2] }, - check: function (card) { - return 6 - get.value(card); - }, - filterCard: function (card) { - return card.name == "sha" || get.type(card) == "equip"; - }, - precontent: function () { - player.addTempSkill("jingong2"); - }, - }; - }, - prompt: function (links, player) { - return "将一张【杀】或装备牌当做" + get.translation(links[0][2]) + "使用"; - }, }, ai: { - order: 2, - result: { - player: function (player) { - if ((player.hp <= 2 || player.needsToDiscard()) && !player.getStat("damage")) return 0; - return 1; - }, - }, - }, - }, - jingong2: { - trigger: { player: "phaseJieshuBegin" }, - forced: true, - filter: function (event, player) { - return !player.getStat("damage"); - }, - content: function () { - player.loseHp(); + expose: 0.2, + threaten: 1.4, }, }, - jingong3: { charlotte: true }, - weikui: { + fuman: { audio: 2, enable: "phaseUse", - usable: 1, filterTarget: function (card, player, target) { - return target != player && target.countCards("h"); + if (target == player) return false; + var stat = player.getStat("skill").fuman_targets; + return !stat || !stat.includes(target); + }, + filter: function (event, player) { + return player.countCards("h") > 0 && game.hasPlayer(current => lib.skill.fuman.filterTarget(null, player, current)); }, + discard: false, + lose: false, + delay: false, + filterCard: true, content: function () { - "step 0"; - player.loseHp(); - "step 1"; - if (target.countCards("h", "shan")) { - player.viewHandcards(target); - if (player.canUse({ name: "sha", isCard: true }, target, false)) player.useCard({ name: "sha", isCard: true }, target, false); - player.storage.weikui2 = target; - player.addTempSkill("weikui2"); - } else { - player.discardPlayerCard(target, "visible", true, "h").set("ai", function (button) { - return get.value(button.link, _status.event.target); - }); - } + player.give(cards, target).gaintag.add("fuman"); + target.addSkill("fuman2"); + player.addSkill("fuman_draw"); + var stat = player.getStat("skill"); + if (!stat.fuman_targets) stat.fuman_targets = []; + stat.fuman_targets.push(target); + }, + check: function (card) { + return 6 - get.value(card); }, ai: { - order: 8, + order: 2, result: { target: function (player, target) { - if (player.hp <= 2) return 0; - if (player.hp == 3) return target.hp <= 2 ? -1 : 0; - return -1; + if (!target.hasSha()) return 1.2; + return 1; + }, + }, + }, + subSkill: { + draw: { + trigger: { global: "useCardAfter" }, + forced: true, + charlotte: true, + filter: function (event, player) { + return event.player.hasHistory("lose", function (evt) { + if (evt.getParent() != event) return false; + for (var i in evt.gaintag_map) { + if (evt.gaintag_map[i].includes("fuman")) return true; + } + return false; + }); + }, + logTarget: "player", + content: function () { + player.draw( + trigger.player.hasHistory("sourceDamage", function (evt) { + return evt.card == trigger.card; + }) + ? 2 + : 1 + ); }, }, }, }, - weikui2: { - onremove: true, + fuman2: { mod: { - globalFrom: function (from, to) { - if (to == from.storage.weikui2) return -Infinity; + aiOrder: function (player, card, num) { + if (get.itemtype(card) == "card" && card.hasGaintag("fuman")) return num + 1; + }, + cardname: function (card, player) { + if (get.itemtype(card) == "card" && card.hasGaintag("fuman")) return "sha"; }, - }, - mark: "character", - intro: { - content: "与$的距离视为1直到回合结束", }, }, - lizhan: { - audio: 2, - trigger: { player: "phaseJieshuBegin" }, - direct: true, + qizhou: { + trigger: { player: ["phaseBefore", "equipEnd", "loseEnd"] }, + forced: true, + popup: false, + derivation: ["mashu", "reyingzi", "reduanbing", "fenwei"], filter: function (event, player) { - for (var i = 0; i < game.players.length; i++) { - if (game.players[i].isDamaged()) { - return true; - } + if (player.equiping) return false; + var suits = []; + var es = player.getCards("e"); + for (var i = 0; i < es.length; i++) { + suits.add(get.suit(es[i])); + } + if (player.additionalSkills.qizhou) { + return player.additionalSkills.qizhou.length != suits.length; + } else { + return suits.length > 0; } - return false; }, content: function () { - "step 0"; - player - .chooseTarget(get.prompt("lizhan"), "令任意名已受伤的角色各摸一张牌", [1, Infinity], function (card, player, target) { - return target.isDamaged(); - }) - .set("ai", function (target) { - return get.attitude(player, target); - }); - "step 1"; - if (result.bool) { - player.logSkill("lizhan", result.targets); - game.asyncDraw(result.targets); + var suits = []; + var es = player.getCards("e"); + for (var i = 0; i < es.length; i++) { + suits.add(get.suit(es[i])); + } + player.removeAdditionalSkill("qizhou"); + switch (suits.length) { + case 1: + player.addAdditionalSkill("qizhou", ["mashu"]); + break; + case 2: + player.addAdditionalSkill("qizhou", ["mashu", "reyingzi"]); + break; + case 3: + player.addAdditionalSkill("qizhou", ["mashu", "reyingzi", "reduanbing"]); + break; + case 4: + player.addAdditionalSkill("qizhou", ["mashu", "reyingzi", "reduanbing", "fenwei"]); + break; } }, ai: { - expose: 0.3, - threaten: 1.3, + threaten: 1.2, }, }, - xinfenyue: { + shanxi: { + audio: 2, enable: "phaseUse", - audio: "fenyue", - filter: function (event, player) { - var num = game.players.length - player.getFriends(true).length; - if ((player.getStat().skill.xinfenyue || 0) >= num) return false; - return player.countCards("h") > 0; + usable: 1, + filterCard: { color: "red", type: "basic" }, + filterTarget: function (card, player, target) { + return target != player && target.countCards("he") && player.inRange(target); }, - filterTarget: function (event, player, target) { - return player.canCompare(target); + check: function (card) { + return 6 - get.value(card); }, content: function () { "step 0"; - player.chooseToCompare(target); + player.discardPlayerCard(target, true); "step 1"; - if (!result.bool) event.finish(); - event.num = result.num1; - "step 2"; - if (num <= 5 && target.countGainableCards(player, "he") > 0) player.gainPlayerCard(target, "he", true); - "step 3"; - if (num <= 9) { - var card = get.cardPile2(function (x) { - return x.name == "sha"; - }); - if (card) player.gain(card, "gain2"); - } - "step 4"; - if (num <= 13) { - var card = { name: "sha", nature: "thunder" }; - if (player.canUse(card, target, false)) player.useCard(card, target, false); + if (result.bool) { + if (get.name(result.cards[0], result.cards[0].original == "h" ? player : false) == "shan") { + player.viewHandcards(target); + } else { + target.viewHandcards(player); + } } }, ai: { - order: 4, + order: 8, result: { - target: function (player, target) { - var sort = function (a, b) { - return b.number - a.number; - }; - var ps = player.getCards("h").sort(sort); - var ts = target.getCards("h").sort(sort); - if (ps[0].number > ts[0].number) { - var effect = get.effect(target, { name: "sha", nature: "thunder" }, player, player); - if (ps[0].number < 6 && target.countCards("he") > 1) effect -= 2; - if (ps[0].number < 10) effect -= 1; - return effect; - } - return ps.length >= ts.length ? -0.5 : 0; - }, + target: -1, }, }, }, - fenyue: { - audio: 2, + fenxun: { enable: "phaseUse", - filter: function (event, player) { - if (!player.countCards("h")) return false; - var num; - if (get.mode() == "identity") { - num = game.countPlayer(function (current) { - return current.identity == "zhong" || current.identity == "mingzhong"; - }); - } else { - num = 1; - } - if (player.getStat().skill.fenyue >= num) return false; - return true; - }, + usable: 1, + position: "he", filterTarget: function (card, player, target) { - return player.canCompare(target); + return target != player; + }, + content: function () { + player.markAuto("fenxun2", [target]); + player.addTempSkill("fenxun2"); + }, + check: function (card) { + if (card.name == "sha" && _status.event.player.countCards("h", "sha") <= 1) return 0; + return 6 - get.value(card); }, + filterCard: true, ai: { - order: 2.8, + order: 4, result: { - target: function (player, target) { - if ( - get.attitude(player, target) < 0 && - player.hasCard(function (card) { - return (card.number >= 9 && get.value(card) <= 5) || get.value(card) <= 3; - }) - ) { - return get.effect(target, { name: "sha" }, player, target); - } else { - return 0; + player: function (player, target) { + if (get.distance(player, target) <= 1) return 0; + var hs = player.getCards("h", "shunshou"); + if (hs.length && player.canUse(hs[0], target, false)) { + return 1; + } + var geteff = function (current) { + return player.canUse("sha", current, false, true) && get.effect(current, { name: "sha" }, player, player) > 0; + }; + if (player.hasSha() && geteff(target)) { + var num = game.countPlayer(function (current) { + return current != player && get.distance(player, current) <= 1 && geteff(current); + }); + if (num == 0) { + if ( + game.hasPlayer(function (current) { + return player.canUse("sha", current) && geteff(current) && current != target; + }) + ) { + return 1; + } + } else if (num == 1) { + return 1; + } } + return 0; }, }, }, - content: function () { - "step 0"; - player.chooseToCompare(target); - "step 1"; - if (result.bool) { - player - .chooseControl(function () { - return 1; - }) - .set("choiceList", ["令" + get.translation(target) + "不能使用或打出手牌直到回合结束", "视为对" + get.translation(target) + "使用一张杀(不计入次数限制)"]); - } else { - var evt = _status.event.getParent("phaseUse"); - if (evt && evt.name == "phaseUse") { - evt.skipped = true; - } - event.finish(); - } - "step 2"; - if (result.control == "选项一") { - target.addTempSkill("fenyue2"); - } else { - player.useCard({ name: "sha", isCard: true }, target, false); - } - }, }, - fenyue2: { - mark: true, - mod: { - cardEnabled2: function (card) { - if (get.position(card) == "h") return false; - }, - }, + fenxun2: { + mark: "character", + onremove: true, intro: { - content: "不能使用或打出手牌", - }, - }, - - zfengshi: { - audio: 2, - trigger: { player: "useCardToPlayered" }, - filter: function (event, player) { - return event.card.name == "sha" && event.target.countCards("e"); - }, - logTarget: "target", - check: function (event, player) { - if (event.target.hasSkillTag("noe")) return false; - return get.attitude(player, event.target) < 0; + content: "到$的距离视为1", }, - content: function () { - trigger.target.chooseToDiscard("e", true); + mod: { + globalFrom: function (from, to) { + if (from.getStorage("fenxun2").includes(to)) { + return -Infinity; + } + }, }, }, - chuanxin: { + duanbing: { audio: 2, - trigger: { source: "damageBegin2" }, - preHidden: true, + audioname2: { heqi: "duanbing_heqi" }, + trigger: { player: "useCard2" }, filter: function (event, player) { - if (_status.currentPhase != player) return false; - if (!_status.event.getParent("phaseUse")) return false; - if (event.card && (event.card.name == "sha" || event.card.name == "juedou") && event.getParent().name == event.card.name) { - if (get.mode() == "guozhan") { - return (event.player.identity != "qun" || player.identity == "ye") && !event.player.isUnseen() && event.player.hasViceCharacter(); - } else { - var info = lib.character[event.player.name]; - if (!info) return false; - var skills = event.player.getSkills(); - for (var i = 0; i < info[3].length; i++) { - if (lib.skill[info[3][i]].fixed) continue; - if (skills.includes(info[3][i])) return true; - } - } - } - return false; - }, - logTarget: "player", - check: function (event, player) { - if (get.mode() == "guozhan") { - if (!event.player.isUnseen(1) && get.guozhanRank(event.player.name2, event.player) < 4) return false; - } - if (event.player.hasSkill("subplayer")) return false; - if (get.attitude(player, event.player) < 0) { - if (event.player.hp == 1 && event.player.countCards("e") < 2 && event.player.name2 != "gz_pangtong") return false; - return true; - } - return false; + if (event.card.name != "sha") return false; + return game.hasPlayer(function (current) { + return !event.targets.includes(current) && get.distance(player, current) <= 1 && player.canUse(event.card, current); + }); }, + direct: true, content: function () { "step 0"; - trigger.cancel(); - if (trigger.player.countCards("e")) { - trigger.player - .chooseControl(function (event, player) { - if (get.mode() == "guozhan" && get.guozhanRank(player.name2, player) < 4) return 1; - if (player.hp == 1) return 1; - if (player.hp == 2 && player.countCards("e") >= 2) return 1; - return 0; - }) - .set("choiceList", ["弃置装备区内的所有牌并失去1点体力", get.mode() == "guozhan" ? "移除副将牌" : "随机移除武将牌上的一个技能"]); + player + .chooseTarget(get.prompt("duanbing"), "为" + get.translation(trigger.card) + "增加一个目标", function (card, player, target) { + return !_status.event.sourcex.includes(target) && get.distance(player, target) <= 1 && player.canUse(_status.event.card, target); + }) + .set("sourcex", trigger.targets) + .set("ai", function (target) { + var player = _status.event.player; + return get.effect(target, _status.event.card, player, player); + }) + .set("card", trigger.card); + "step 1"; + if (result.bool) { + if (!event.isMine() && !event.isOnline()) game.delayx(); + event.target = result.targets[0]; } else { - event._result = { index: 1 }; + event.finish(); } - "step 1"; - if (result.index == 1) { - if (get.mode() != "guozhan") { - var info = lib.character[trigger.player.name]; - var skills = trigger.player.getSkills(); - var list = []; - for (var i = 0; i < info[3].length; i++) { - if (lib.skill[info[3][i]].fixed) continue; - if (skills.includes(info[3][i])) { - list.push(info[3][i]); + "step 2"; + player.logSkill("duanbing", event.target); + trigger.targets.push(event.target); + }, + ai: { + effect: { + player_use: function (card, player, target, current, isLink) { + if (!isLink && card.name == "sha") { + if (player._duanbingtmp) return; + player._duanbingtmp = true; + if (get.effect(target, card, player, player) <= 0) { + delete player._duanbingtmp; + return; } + if ( + game.hasPlayer(function (current) { + return current != target && get.distance(player, current) <= 1 && player.canUse(card, current) && get.effect(current, card, player, player) > 0; + }) + ) { + delete player._duanbingtmp; + return [1, 1]; + } + delete player._duanbingtmp; } - if (list.length) { - var skill = list.randomGet(); - trigger.player.removeSkills(skill); - } - } else { - trigger.player.removeCharacter(1); - } - } else { - trigger.player.discard(trigger.player.getCards("e")); - trigger.player.loseHp(); - } + }, + }, }, }, - hengjiang: { + fuhan: { audio: 2, - trigger: { player: "damageEnd" }, - preHidden: true, - check: function (event, player) { - return get.attitude(player, _status.currentPhase) < 0 || !_status.currentPhase.needsToDiscard(2); + trigger: { player: "phaseBegin" }, + unique: true, + limited: true, + skillAnimation: true, + animationColor: "orange", + filter: function (event, player) { + return player.storage.fanghun2 > 0; }, - filter: function (event) { - return _status.currentPhase && _status.currentPhase.isIn() && event.num > 0; + prompt: function (event, player) { + var num = Math.max(2, player.storage.fanghun2 || 0); + num = Math.min(num, 8); + return get.prompt("fuhan") + "(体力上限:" + num + ")"; }, - logTarget: function () { - return _status.currentPhase; + check: function (event, player) { + var num = Math.max(2, player.storage.fanghun2 || 0); + if (num == 1) return false; + if (player.hp <= 1) return true; + if (num == 2) return false; + if (num == 3) return player.hp < 3 && player.isMinHp(); + return true; }, content: function () { - var source = _status.currentPhase; - if (source.hasSkill("hengjiang2")) { - source.storage.hengjiang2 += trigger.num; - source.storage.hengjiang3.add(player); - source.updateMarks(); + "step 0"; + if (player.storage.fanghun) player.draw(player.storage.fanghun); + player.removeMark("fanghun", player.storage.fanghun); + event.num = Math.max(2, player.storage.fanghun2 || 0); + var list; + if (_status.characterlist) { + list = []; + for (var i = 0; i < _status.characterlist.length; i++) { + var name = _status.characterlist[i]; + if (lib.character[name][1] == "shu") list.push(name); + } + } else if (_status.connectMode) { + list = get.charactersOL(function (i) { + return lib.character[i][1] != "shu"; + }); } else { - source.storage.hengjiang3 = [player]; - source.storage.hengjiang2 = trigger.num; - source.addTempSkill("hengjiang2"); + list = get.gainableCharacters(function (info) { + return info[1] == "shu"; + }); } - }, - ai: { - maixie_defend: true, - }, - }, - hengjiang2: { - mark: true, - charlotte: true, - intro: { - content: "手牌上限-#", - }, - mod: { - maxHandcard: function (player, num) { - return num - player.storage.hengjiang2; - }, - }, - onremove: function (player) { - delete player.storage.hengjiang2; - delete player.storage.hengjiang3; - }, - trigger: { player: "phaseDiscardEnd" }, - filter: function (event, player) { - if (event.cards && event.cards.length) return false; - var players = player.storage.hengjiang3; + var players = game.players.concat(game.dead); for (var i = 0; i < players.length; i++) { - if (players[i].isIn()) return true; + list.remove(players[i].name); + list.remove(players[i].name1); + list.remove(players[i].name2); } - return false; + list.remove("zhaoyun"); + list.remove("re_zhaoyun"); + list.remove("ol_zhaoyun"); + // var dialog=ui.create.dialog(); + // dialog.add([list.randomGets(5),'character']); + player + .chooseButton(true) + .set("ai", function (button) { + return get.rank(button.link, true) - lib.character[button.link][2]; + }) + .set("createDialog", ["将武将牌替换为一名角色", [list.randomGets(5), "character"]]); + player.awakenSkill("fuhan"); + "step 1"; + event.num = Math.min(event.num, 8); + player.reinitCharacter(get.character(player.name2, 3).includes("fuhan") ? player.name2 : player.name1, result.links[0]); + "step 2"; + var num = event.num - player.maxHp; + if (num > 0) player.gainMaxHp(num); + else player.loseMaxHp(-num); + player.recover(); }, - forced: true, - popup: false, - content: function () { - var players = player.storage.hengjiang3; - for (var i = 0; i < players.length; i++) { - if (players[i].isIn()) { - players[i].logSkill("hengjiang"); - players[i].line(player, "green"); - } - } - game.asyncDraw(player.storage.hengjiang3); + ai: { + combo: "fanghun", }, }, - rehengjiang: { - audio: "hengjiang", - trigger: { player: "damageEnd" }, - check: function (event, player) { - return get.attitude(player, _status.currentPhase) < 0 || !_status.currentPhase.needsToDiscard(2); - }, - filter: function (event) { - return _status.currentPhase && _status.currentPhase.isIn() && event.num > 0; - }, - logTarget: function () { - return _status.currentPhase; + refuhan: { + audio: "fuhan", + trigger: { player: "phaseZhunbeiBegin" }, + unique: true, + limited: true, + skillAnimation: true, + animationColor: "orange", + filter: function (event, player) { + return player.countMark("fanghun") > 0; }, - preHidden: true, content: function () { "step 0"; - event.count = trigger.num; + if (player.storage.fanghun) player.draw(player.storage.fanghun); + player.removeMark("fanghun", player.storage.fanghun); + player.awakenSkill("refuhan"); "step 1"; - event.count--; - var source = _status.currentPhase; - source.addTempSkill("rehengjiang2"); - source.addMark("rehengjiang2", 1, false); - player.addTempSkill("rehengjiang3"); + var list; + if (_status.characterlist) { + list = []; + for (var i = 0; i < _status.characterlist.length; i++) { + var name = _status.characterlist[i]; + if (lib.character[name][1] == "shu") list.push(name); + } + } else if (_status.connectMode) { + list = get.charactersOL(function (i) { + return lib.character[i][1] != "shu"; + }); + } else { + list = get.gainableCharacters(function (info) { + return info[1] == "shu"; + }); + } + var players = game.players.concat(game.dead); + for (var i = 0; i < players.length; i++) { + list.remove(players[i].name); + list.remove(players[i].name1); + list.remove(players[i].name2); + } + list.remove("zhaoyun"); + list.remove("re_zhaoyun"); + list.remove("ol_zhaoyun"); + list = list.randomGets(Math.max(4, game.countPlayer())); + var skills = []; + for (var i of list) { + skills.addArray( + (lib.character[i][3] || []).filter(function (skill) { + var info = get.info(skill); + return info && !info.zhuSkill && !info.limited && !info.juexingji && !info.hiddenSkill && !info.charlotte && !info.dutySkill; + }) + ); + } + if (!list.length || !skills.length) { + event.finish(); + return; + } + if (player.isUnderControl()) { + game.swapPlayerAuto(player); + } + var switchToAuto = function () { + _status.imchoosing = false; + event._result = { + bool: true, + skills: skills.randomGets(2), + }; + if (event.dialog) event.dialog.close(); + if (event.control) event.control.close(); + }; + var chooseButton = function (list, skills) { + var event = _status.event; + if (!event._result) event._result = {}; + event._result.skills = []; + var rSkill = event._result.skills; + var dialog = ui.create.dialog("请选择获得至多两个技能", [list, "character"], "hidden"); + event.dialog = dialog; + var table = document.createElement("div"); + table.classList.add("add-setting"); + table.style.margin = "0"; + table.style.width = "100%"; + table.style.position = "relative"; + for (var i = 0; i < skills.length; i++) { + var td = ui.create.div(".shadowed.reduce_radius.pointerdiv.tdnode"); + td.link = skills[i]; + table.appendChild(td); + td.innerHTML = "" + get.translation(skills[i]) + ""; + td.addEventListener(lib.config.touchscreen ? "touchend" : "click", function () { + if (_status.dragged) return; + if (_status.justdragged) return; + _status.tempNoButton = true; + setTimeout(function () { + _status.tempNoButton = false; + }, 500); + var link = this.link; + if (!this.classList.contains("bluebg")) { + if (rSkill.length >= 2) return; + rSkill.add(link); + this.classList.add("bluebg"); + } else { + this.classList.remove("bluebg"); + rSkill.remove(link); + } + }); + } + dialog.content.appendChild(table); + dialog.add("  "); + dialog.open(); + + event.switchToAuto = function () { + event.dialog.close(); + event.control.close(); + game.resume(); + _status.imchoosing = false; + }; + event.control = ui.create.control("ok", function (link) { + event.dialog.close(); + event.control.close(); + game.resume(); + _status.imchoosing = false; + }); + for (var i = 0; i < event.dialog.buttons.length; i++) { + event.dialog.buttons[i].classList.add("selectable"); + } + game.pause(); + game.countChoose(); + }; + if (event.isMine()) { + chooseButton(list, skills); + } else if (event.isOnline()) { + event.player.send(chooseButton, list, skills); + event.player.wait(); + game.pause(); + } else { + switchToAuto(); + } "step 2"; - if (event.count && player.hasSkill("rehengjiang")) { - player.chooseBool(get.prompt2("rehengjiang", _status.currentPhase)).set("ai", function () { - return lib.skill.rehengjiang.check(_status.event.getTrigger(), _status.event.player); - }); - } else event.finish(); - "step 3"; - if (result.bool) { - player.logSkill("rehengjiang", _status.currentPhase); - event.goto(1); + var map = event.result || result; + if (map && map.skills && map.skills.length) { + player.addSkills(map.skills); } + game.broadcastAll(function (list) { + game.expandSkills(list); + for (var i of list) { + var info = lib.skill[i]; + if (!info) continue; + if (!info.audioname2) info.audioname2 = {}; + info.audioname2.zhaoxiang = "fuhan"; + } + }, map.skills); + "step 3"; + if (player.isMinHp()) player.recover(); }, ai: { - maixie_defend: true, - notemp: true, + combo: "refanghun", }, }, - rehengjiang2: { - mark: true, - charlotte: true, - onremove: true, - intro: { - content: "手牌上限-#", - }, + refanghun: { mod: { - maxHandcard: function (player, num) { - return num - player.storage.rehengjiang2; + aiValue: function (player, card, num) { + if (card.name != "sha" && card.name != "shan") return; + var geti = function () { + var cards = player.getCards("hs", function (card) { + return card.name == "sha" || card.name == "shan"; + }); + if (cards.includes(card)) { + return cards.indexOf(card); + } + return cards.length; + }; + return Math.max(num, [7, 5, 5, 3][Math.min(geti(), 3)]); }, }, - }, - rehengjiang3: { - audio: "hengjiang", - trigger: { global: "phaseEnd" }, - forced: true, - charlotte: true, - filterx: function (event, player) { - if (!event.player.countMark("rehengjiang2")) return false; - if ( - event.player.hasHistory("lose", function (evt) { - return evt.type == "discard" && evt.cards2.length > 0 && evt.getParent("phaseDiscard").player == event.player; - }) - ) - return false; - return true; - }, - logTarget: "player", - content: function () { - if (lib.skill.rehengjiang3.filterx(trigger, player)) { - var num = player.getHistory("useSkill", function (evt) { - return evt.skill == "rehengjiang" && evt.targets.includes(trigger.player); - }).length; - if (num > 0) player.draw(num); - } else player.draw(); + locked: false, + audio: "fanghun", + inherit: "fanghun", + trigger: { + player: "useCard", + target: "useCardToTargeted", }, }, - shuangren: { - trigger: { player: "phaseUseBegin" }, - direct: true, - preHidden: true, - filter: function (event, player) { - return ( - player.countCards("h") > 0 && - game.hasPlayer(function (current) { - return current != player && player.canCompare(current); - }) - ); - }, - content: function () { - "step 0"; - var goon; - if (player.needsToDiscard() > 1) { - goon = player.hasCard(function (card) { - return card.number > 10 && get.value(card) <= 5; - }); - } else { - goon = player.hasCard(function (card) { - return (card.number >= 9 && get.value(card) <= 5) || get.value(card) <= 3; - }); - } - player - .chooseTarget(get.prompt2("shuangren"), function (card, player, target) { - return player.canCompare(target); - }) - .set("ai", function (target) { - var player = _status.event.player; - if (_status.event.goon && get.attitude(player, target) < 0) { - return get.effect(target, { name: "sha" }, player, player); - } - return 0; - }) - .set("goon", goon) - .setHiddenSkill(event.name); - "step 1"; - if (result.bool) { - var target = result.targets[0]; - event.target = target; - player.logSkill("shuangren", target); - player.chooseToCompare(target); - } else { - event.finish(); - } - "step 2"; - if (result.bool) { - var target = event.target; - if ( - game.hasPlayer(function (current) { - if (target == current) return false; - if (!player.canUse("sha", current, false)) return false; - return target.isFriendOf(current); - }) - ) { - var str = "对一名与" + get.translation(target) + "势力相同的"; - player - .chooseTarget(str + "角色使用一张杀", true, function (card, player, target) { - if (!player.canUse("sha", target, false)) return false; - if (get.mode() == "guozhan") { - return target.isFriendOf(_status.event.identity); - } - return true; - }) - .set("ai", function (target) { - var player = _status.event.player; - return get.effect(target, { name: "sha" }, player, player); - }) - .set("identity", target); - } else { - player.useCard({ name: "sha", isCard: true }, target, false); - event.finish(); - } - } else { - player.addTempSkill("zishou2"); - event.finish(); - } - "step 3"; - if (result.bool && result.targets && result.targets.length) { - player.useCard({ name: "sha", isCard: true }, result.targets[0], false); - } + fanghun: { + hiddenCard: function (player, name) { + if (!player.storage.fanghun || player.storage.fanghun <= 0) return false; + if (name == "tao") return player.countCards("hs", "jiu") > 0; + if (name == "jiu") return player.countCards("hs", "tao") > 0; + return false; }, - }, - kuanshi: { audio: 2, - trigger: { player: "phaseJieshuBegin" }, - direct: true, - content: function () { - "step 0"; - player.chooseTarget(get.prompt2("kuanshi")).set("ai", function (target) { - if (get.attitude(_status.event.player, target) > 0) { - return 1 / Math.sqrt(target.hp + 1); - } - return 0; - }).animate = false; - "step 1"; - if (result.bool) { - var target = result.targets[0]; - player.logSkill("kuanshi"); - target.storage.kuanshi2 = player; - target.addSkill("kuanshi2"); - } + marktext: "影", + intro: { + content: "mark", + name: "梅影", + }, + trigger: { + source: "damageSource", + player: "damageEnd", }, - }, - kuanshi2: { - /*mark:'character', - intro:{ - content:'下一次受到超过1点的伤害时,防止此伤害,然后$跳过下个回合的摸牌阶段' - },*/ - trigger: { player: "damageBegin4" }, forced: true, - filter: function (event, player) { - return event.num > 1; + locked: false, + filter: function (event) { + return event.card && event.card.name == "sha"; }, - //priority:-11, content: function () { - trigger.cancel(); - player.storage.kuanshi2.skip("phaseDraw"); - player.removeSkill("kuanshi2"); + player.addMark("fanghun", trigger.num || 1); + player.addMark("fanghun2", trigger.num || 1, false); }, - group: "kuanshi2_remove", - onremove: true, + group: ["fanghun_sha", "fanghun_draw"], subSkill: { - remove: { - trigger: { global: ["phaseZhunbeiBegin", "dieAfter"] }, + draw: { + trigger: { player: ["useCardAfter", "respondAfter"] }, forced: true, popup: false, - filter: function (event, player) { - return event.player == player.storage.kuanshi2; + filter: function (event) { + return event.skill == "fanghun_sha" || event.skill == "fanghun_shan"; }, content: function () { - player.removeSkill("kuanshi2"); + player.draw(); + }, + }, + sha: { + audio: "fanghun", + inherit: "ollongdan", + enable: ["chooseToUse", "chooseToRespond"], + prompt: "弃置一枚【梅影】标记,将杀当做闪,或将闪当做杀,或将桃当做酒,或将酒当做桃使用或打出", + filter: function (event, player) { + return player.hasMark("fanghun") && get.info("ollongdan").filter(event, player); + }, + onrespond: function () { + return this.onuse.apply(this, arguments); + }, + onuse: function (result, player) { + player.removeMark("fanghun", 1); + }, + ai: { + respondSha: true, + respondShan: true, + skillTagFilter: function (player, tag) { + if (!player.hasMark("fanghun")) return false; + return get.info("ollongdan").ai.skillTagFilter(player, tag); + }, + order: function (item, player) { + if (!player || !player.storage) { + player = _status.event.player; + if (!player || !player.storage) return 0; + if ( + Object.keys(player.storage).some(i => { + return typeof i == "string" && i.indexOf("fuhan") != -1; + }) + ) + return 4; + return 1; + } + const awakened = Object.keys(player.storage).some(i => typeof i == "string" && i.indexOf("fuhan") != -1); + if (_status.event.type == "phase") { + var max = 0; + var list = ["sha", "tao", "jiu"]; + var map = { sha: "shan", tao: "jiu", jiu: "tao" }; + for (var i = 0; i < list.length; i++) { + var name = list[i]; + if (player.countCards("hs", map[name]) > (name == "jiu" ? 1 : 0) && player.getUseValue({ name: name }) > 0) { + var temp = get.order({ name: name }); + if (temp > max) max = temp; + } + } + if (max > 0) max += awakened ? 0.3 : -0.3; + return max; + } + return awakened ? 4 : 1; + }, }, }, }, }, - xiashu: { - audio: 2, - trigger: { player: "phaseUseBegin" }, - direct: true, + yjixi: { + derivation: "rewangzun", + audio: "weidi", + trigger: { player: "phaseJieshuBegin" }, + forced: true, filter: function (event, player) { - return player.countCards("h") > 0; + if (player.phaseNumber < 3) return false; + var num = 0; + for (var i = player.actionHistory.length - 1; i >= 0; i--) { + if (!player.actionHistory[i].isMe) continue; + if (_status.globalHistory[i].changeHp.some(evt => evt.player == player && evt.getParent().name == "loseHp")) return false; + else { + num++; + if (num >= 3) break; + } + } + return true; }, + skillAnimation: true, + animationColor: "gray", + unique: true, + juexingji: true, content: function () { "step 0"; - var maxval = 0; - var hs = player.getCards("h"); - for (var i = 0; i < hs.length; i++) { - maxval = Math.max(maxval, get.value(hs[i])); - } - player - .chooseTarget(get.prompt2("xiashu"), lib.filter.notMe) - .set("ai", function (target) { - var player = _status.event.player; - var maxval = _status.event.maxval; - var dh = target.countCards("h") - player.countCards("h"); - var att = get.attitude(player, target); - if (target.hasSkill("qingjian")) return false; - if (dh <= 0) return 0; - if (att > 0) return 0.1; - if (maxval >= 8) return 0; - if (att == 0) return 0.2; - if (dh >= 3) return dh; - if (dh == 2) { - if (maxval <= 7) return dh; - } - if (maxval <= 6) return dh; - return 0; - }) - .set("maxval", maxval); + player.awakenSkill("yjixi"); + player.gainMaxHp(); + player.recover(); "step 1"; - if (result.bool) { - player.logSkill("xiashu", result.targets); - event.target = result.targets[0]; - var hs = player.getCards("h"); - player.give(hs, event.target); - } else { - event.finish(); - } - "step 2"; - var hs = event.target.getCards("h"); - if (!hs.length) { - event.finish(); - return; - } - hs.sort(function (a, b) { - return get.value(b, player, "raw") - get.value(a, player, "raw"); - }); - event.target - .chooseCard([1, hs.length], "展示至少一张手牌", true) - .set("ai", function (card) { - var rand = _status.event.rand; - var list = _status.event.list; - if (_status.event.att) { - if (ui.selected.cards.length >= Math.ceil(list.length / 2)) return 0; - var value = get.value(card); - if (_status.event.getParent().player.isHealthy()) { - value += (get.tag(card, "damage") ? 1.5 : 0) + (get.tag(card, "draw") ? 2 : 0); + var str = "摸两张牌"; + var mode = get.mode(); + var choice = "选项一"; + if (mode == "identity" || (mode == "versus" && _status.mode == "four")) { + var list = []; + var zhu = get.zhu(player); + if (zhu && zhu != player && zhu.skills) { + for (var i = 0; i < zhu.skills.length; i++) { + if (lib.skill[zhu.skills[i]] && lib.skill[zhu.skills[i]].zhuSkill) { + list.push(zhu.skills[i]); } - return value; } - if (ui.selected.cards.length >= Math.floor(list.length / 2)) return 0; - return list.indexOf(card) % 2 == rand ? 1 : 0; - }) - .set("rand", Math.random() < 0.6 ? 1 : 0) - .set("list", hs) - .set("att", get.attitude(event.target, player) > 0); - "step 3"; - event.target.showCards(result.cards); - event.cards1 = result.cards; - event.cards2 = event.target.getCards("h", function (card) { - return !event.cards1.includes(card); - }); - "step 4"; - var choice; - var num1 = event.cards1.length; - var num2 = event.cards2.length; - if (get.attitude(event.target, player) > 0 && num1 >= num2) { - choice = 0; - } else if (num1 == num2) { - choice = Math.random() < 0.45 ? 0 : 1; - } else if (num1 > num2) { - if (num1 - num2 == 1) { - choice = Math.random() < 0.6 ? 0 : 1; - } else { - choice = 0; } - } else { - if (num2 - num1 == 1) { - choice = Math.random() < 0.6 ? 1 : 0; - } else { - choice = 1; + if (list.length) { + str += "并获得技能" + get.translation(list); + event.list = list; + choice = "选项二"; } } player .chooseControl(function (event, player) { return _status.event.choice; }) - .set("choiceList", ["获得" + get.translation(event.target) + "展示的牌", "获得" + get.translation(event.target) + "未展示的牌"]) + .set("choiceList", ["获得技能〖妄尊〗", str]) .set("choice", choice); - "step 5"; - if (result.index == 0) { - player.gain(event.cards1, target, "give", "bySelf"); + "step 2"; + if (result.control == "选项一") { + player.addSkills("rewangzun"); } else { - player.gain(event.cards2, target, "giveAuto", "bySelf"); + player.draw(2); + if (event.list) { + player.addSkills(event.list); + game.broadcastAll(function (list) { + game.expandSkills(list); + for (var i of list) { + var info = lib.skill[i]; + if (!info) continue; + if (!info.audioname2) info.audioname2 = {}; + info.audioname2.old_yuanshu = "weidi"; + } + }, event.list); + } } }, - ai: { - expose: 0.1, - }, }, - sheyan: { - audio: 2, - trigger: { target: "useCardToTarget" }, + xinyongsi: { + audio: "yongsi", + group: ["xinyongsi1", "xinyongsi2"], + locked: true, + }, + xinyongsi1: { + audio: "yongsi1", + trigger: { player: "phaseDrawBegin1" }, + forced: true, filter: function (event, player) { - if (!event.targets || !event.targets.includes(player)) return false; - var info = get.info(event.card); - if (info.type != "trick") return false; - if (info.multitarget) return false; - if (event.targets.length > 1) return true; - return game.hasPlayer(function (current) { - return !event.targets.includes(current) && lib.filter.targetEnabled2(event.card, event.player, current); - }); + return !event.numFixed; + }, + content: function () { + player.draw(game.countGroup()); + trigger.changeToZero(); + }, + }, + xinyongsi2: { + audio: "yongsi2", + trigger: { player: "phaseDiscardBegin" }, + forced: true, + check: function () { + return false; }, - direct: true, content: function () { "step 0"; - var bool1 = trigger.targets.length > 1; - var bool2 = game.hasPlayer(function (current) { - return !trigger.targets.includes(current) && lib.filter.targetEnabled2(trigger.card, trigger.player, current); - }); - if (bool1 && bool2) { - player - .chooseControlList(get.prompt("sheyan"), ["为" + get.translation(trigger.card) + "增加一个目标", "为" + get.translation(trigger.card) + "减少一个目标"], function (event, player) { - if (_status.event.add) return 0; - return 1; - }) - .set("add", get.effect(player, trigger.card, trigger.player, player) >= 0); - } else if (bool2) { - event.type = "add"; - event.goto(2); - event.unchosen = true; - } else { - event.type = "remove"; - event.goto(2); - event.unchosen = true; - } + player.chooseToDiscard("he", "庸肆").set("prompt2", "弃置一张牌,或取消并失去1点体力").ai = function (card) { + return 8 - get.value(card); + }; "step 1"; - if (result.control == "cancel2") { - event.finish(); - } else if (result.index == 1) { - event.type = "remove"; - } else { - event.type = "add"; - } - "step 2"; - if (event.type == "add") { - player - .chooseTarget(event.unchosen ? get.prompt("sheyan") : null, "为" + get.translation(trigger.card) + "增加一个目标", function (card, player, target) { - var trigger = _status.event.getTrigger(); - return !trigger.targets.includes(target) && lib.filter.targetEnabled2(trigger.card, trigger.player, target); - }) - .set("ai", function (target) { - var trigger = _status.event.getTrigger(); - return get.effect(target, trigger.card, trigger.player, _status.event.player); - }); + if (!result.bool) player.loseHp(); + }, + }, + lianzhu: { + audio: 2, + enable: "phaseUse", + usable: 1, + filterCard: true, + position: "he", + filterTarget: function (card, player, target) { + return target != player; + }, + check: function (card) { + var num = get.value(card); + if (get.color(card) == "black") { + if (num >= 6) return 0; + return 20 - num; } else { - player - .chooseTarget(event.unchosen ? get.prompt("sheyan") : null, "为" + get.translation(trigger.card) + "减少一个目标", function (card, player, target) { - return _status.event.targets.includes(target); - }) - .set("ai", function (target) { - var trigger = _status.event.getTrigger(); - return -get.effect(target, trigger.card, trigger.player, _status.event.player); - }) - .set("targets", trigger.targets); + if (_status.event.player.needsToDiscard()) return 7 - num; } - "step 3"; - if (result.bool) { - if (!event.isMine() && !event.isOnline()) game.delayx(); - event.target = result.targets[0]; + return 0; + }, + discard: false, + lose: false, + delay: false, + content: function () { + "step 0"; + player.give(cards, target); + if (get.color(cards[0]) == "black") { + target + .chooseToDiscard(2, "he", "弃置两张牌,或令" + get.translation(player) + "摸两张牌") + .set("ai", function (card) { + if (_status.event.goon) return 7 - get.value(card); + return 0; + }) + .set("goon", get.attitude(target, player) < 0); } else { event.finish(); } - "step 4"; - player.logSkill("sheyan", event.target); - if (event.type == "add") { - trigger.targets.push(event.target); - } else { - trigger.getParent().excluded.add(event.target); + "step 1"; + if (!result.bool) { + player.draw(2); } }, ai: { + order: 8, expose: 0.2, + result: { + target: function (player, target) { + if (ui.selected.cards.length && get.color(ui.selected.cards[0]) == "red") { + if (target.countCards("h") < player.countCards("h")) return 1; + return 0.5; + } + return -1; + }, + }, }, }, - bingzheng: { + xiehui: { + mod: { + ignoredHandcard: function (card, player) { + if (get.color(card) == "black") { + return true; + } + }, + cardDiscardable: function (card, player, name) { + if (name == "phaseDiscard" && get.color(card) == "black") return false; + }, + }, + trigger: { + global: "gainAfter", + player: "loseAsyncAfter", + }, + forced: true, + popup: false, + filter: function (event, player) { + if (event.name == "loseAsync") { + if (event.type != "gain") return false; + return game.hasPlayer(function (current) { + if (current == player) return false; + var hs = current.getCards("h"), + cards = event.getl(player).cards2; + var cardsx = event.getg(current); + for (var i of cardsx) { + if (hs.includes(i) && cards.includes(i) && get.color(i, player) == "black") return true; + } + return false; + }); + } + if (event.player != player) { + var hs = event.player.getCards("h"); + var evt = event.getl(player); + return ( + evt && + evt.cards2 && + evt.cards2.filter(function (card) { + return hs.includes(card) && get.color(card, player) == "black"; + }).length > 0 + ); + } + return false; + }, + content: function () { + var cards = trigger.getl(player).cards2; + game.countPlayer(function (current) { + if (current == player) return; + var hs = current.getCards("h"), + cardsx = trigger.getg(current).filter(function (card) { + return hs.includes(card) && cards.includes(card) && get.color(card, player) == "black"; + }); + if (cardsx.length > 0) { + current.addSkill("xiehui2"); + current.addGaintag(cards, "xiehui"); + } + }); + }, + }, + xiehui2: { + mark: true, + intro: { + content: "不能使用、打出或弃置得到的黑色牌", + }, + mod: { + cardDiscardable: function (card, player) { + if (card.hasGaintag("xiehui")) return false; + }, + cardEnabled2: function (card, player) { + if (get.itemtype(card) == "card" && card.hasGaintag("xiehui")) return false; + }, + }, + trigger: { player: "changeHp" }, + forced: true, + popup: false, + charlotte: true, + filter: function (event) { + return event.num < 0; + }, + content: function () { + player.removeSkill("xiehui2"); + }, + onremove: function (player) { + player.removeGaintag("xiehui"); + }, + }, + shanjia: { + sync: function (player) { + if (game.online) return; + var history = player.actionHistory; + var num = 0; + for (var i = 0; i < history.length; i++) { + for (var j = 0; j < history[i].useCard.length; j++) { + if (get.type(history[i].useCard[j].card) == "equip") num++; + } + } + player.storage.shanjia = num; + if (num > 0) player.markSkill("shanjia"); + }, audio: 2, - trigger: { player: "phaseUseEnd" }, - direct: true, + intro: { + content: function (storage) { + if (storage == 0) return "未使用过装备牌"; + return "已使用过" + storage + "张装备牌"; + }, + }, + group: "shanjia2", + trigger: { player: "phaseUseBegin" }, + frequent: true, + filter: function (event, player) { + lib.skill.shanjia.sync(player); + return player.storage.shanjia > 0; + }, content: function () { "step 0"; - player - .chooseTarget(get.prompt2("bingzheng"), function (card, player, target) { - return target.countCards("h") != target.hp; - }) - .set("ai", function (target) { - var player = _status.event.player; - var att = get.attitude(player, target); - var nh = target.countCards("h"); - if (att > 0) { - if (nh == target.hp - 1) { - if (player == target) return att + 1; - return att + 2; - } - if (player == target && player.needsToDiscard()) return att / 3; - return att; - } else { - if (nh == target.hp + 1) return -att; - if (nh == 0) return 0; - return -att / 2; - } - }); + lib.skill.shanjia.sync(player); + player.draw(Math.min(7, player.storage.shanjia)); "step 1"; - if (result.bool) { - player.logSkill("bingzheng", result.targets); - event.target = result.targets[0]; - if (event.target.countCards("h")) { - player - .chooseControl(function (event, player) { - var target = event.target; - if (get.attitude(player, target) < 0) return 1; - return 0; - }) - .set("choiceList", ["令" + get.translation(event.target) + "摸一张牌", "令" + get.translation(event.target) + "弃置一张手牌"]); - } else { - event.directfalse = true; + player.chooseToDiscard("he", Math.min(7, player.storage.shanjia), true); + "step 2"; + var useCard = false; + if (result.bool && result.cards) { + for (var i = 0; i < result.cards.length; i++) { + if (result.cards[i].original == "e") { + useCard = true; + break; + } } - } else { - event.finish(); } - "step 2"; - if (event.directfalse || result.index == 0) { - event.target.draw(); - } else { - event.target.chooseToDiscard("h", true); + if (useCard) { + player.chooseUseTarget({ name: "sha" }, false, "是否视为使用一张【杀】?", "nodistance"); } - "step 3"; - if (event.target.countCards("h") == event.target.hp) { - player.draw(); - if (event.target == player) { - event.finish(); - return; - } - var next = player.chooseCard("是否交给" + get.translation(event.target) + "一张牌?", "he"); - next.set("ai", function (card) { - if (get.position(card) != "h") return 0; - if (_status.event.shan && card.name == "shan") { - return 11; - } - if (_status.event.goon) { - return 10 - get.value(card); - } - return -get.value(card, _status.event.player, "raw"); - }); - if (get.attitude(player, event.target) > 1 && player.countCards("h", "shan") > 1 && player.countCards("h") > event.target.countCards("h")) { - next.set("shan", true); + }, + ai: { + threaten: function (player, target) { + if (typeof target.storage.shanjia == "number") { + return Math.min(2, Math.sqrt(1 + target.storage.shanjia)); } - if (get.attitude(player, event.target) > 0 && player.needsToDiscard()) { - next.set("goon", true); + }, + }, + }, + shanjia2: { + trigger: { player: "useCard" }, + silent: true, + filter: function (event, player) { + return get.type(event.card) == "equip"; + }, + content: function () { + lib.skill.shanjia.sync(player); + }, + }, + zhanyi: { + enable: "phaseUse", + usable: 1, + audio: 2, + filterCard: true, + position: "he", + check: function (card) { + var player = _status.event.player; + if (player.hp < 3) return 0; + var type = get.type(card, "trick"); + if (type == "trick") { + return 6 - get.value(card); + } else if (type == "equip") { + if ( + player.hasSha() && + game.hasPlayer(function (current) { + return player.canUse("sha", current) && get.attitude(player, current) < 0 && get.effect(current, { name: "sha" }, player, player) > 0; + }) + ) { + return 6 - get.value(card); } - } else { - event.finish(); } - "step 4"; - if (result.bool) { - player.give(result.cards, target); + return 0; + }, + content: function () { + player.loseHp(); + switch (get.type(cards[0], "trick")) { + case "basic": + player.addTempSkill("zhanyi_basic"); + break; + case "equip": + player.addTempSkill("zhanyi_equip"); + break; + case "trick": + player.addTempSkill("zhanyi_trick"); + player.draw(2); + break; } }, ai: { - expose: 0.2, - threaten: 1.4, + order: 9.1, + result: { + player: 1, + }, }, }, - fuman: { - audio: 2, - enable: "phaseUse", - filterTarget: function (card, player, target) { - if (target == player) return false; - var stat = player.getStat("skill").fuman_targets; - return !stat || !stat.includes(target); + zhanyi_basic: { + group: ["zhanyi_basic_sha", "zhanyi_basic_jiu", "zhanyi_basic_tao"], + }, + zhanyi_basic_tao: { + enable: "chooseToUse", + filterCard: { type: "basic" }, + viewAs: { name: "tao" }, + viewAsFilter: function (player) { + if (!player.countCards("h", { type: "basic" })) return false; }, - filter: function (event, player) { - return player.countCards("h") > 0 && game.hasPlayer(current => lib.skill.fuman.filterTarget(null, player, current)); + prompt: "将一张基本牌当桃使用", + check: function (card) { + return 8 - get.value(card); }, - discard: false, - lose: false, - delay: false, - filterCard: true, - content: function () { - player.give(cards, target).gaintag.add("fuman"); - target.addSkill("fuman2"); - player.addSkill("fuman_draw"); - var stat = player.getStat("skill"); - if (!stat.fuman_targets) stat.fuman_targets = []; - stat.fuman_targets.push(target); + ai: { + skillTagFilter: function (player) { + if (!player.countCards("h", { type: "basic" })) return false; + }, + save: true, + }, + }, + zhanyi_basic_sha: { + enable: "chooseToUse", + filterCard: { type: "basic" }, + viewAs: { name: "sha" }, + viewAsFilter: function (player) { + if (!player.countCards("h", { type: "basic" })) return false; }, + prompt: "将一张基本牌当杀使用", check: function (card) { - return 6 - get.value(card); + return 4 - get.value(card); }, ai: { - order: 2, - result: { - target: function (player, target) { - if (!target.hasSha()) return 1.2; - return 1; - }, + skillTagFilter: function (player) { + if (!player.countCards("h", { type: "basic" })) return false; }, + respondSha: true, }, - subSkill: { - draw: { - trigger: { global: "useCardAfter" }, - forced: true, - charlotte: true, - filter: function (event, player) { - return event.player.hasHistory("lose", function (evt) { - if (evt.getParent() != event) return false; - for (var i in evt.gaintag_map) { - if (evt.gaintag_map[i].includes("fuman")) return true; - } - return false; - }); - }, - logTarget: "player", - content: function () { - player.draw( - trigger.player.hasHistory("sourceDamage", function (evt) { - return evt.card == trigger.card; - }) - ? 2 - : 1 - ); - }, + }, + zhanyi_basic_jiu: { + enable: "chooseToUse", + filterCard: { type: "basic" }, + viewAs: { name: "jiu" }, + viewAsFilter: function (player) { + if (!player.countCards("h", { type: "basic" })) return false; + }, + prompt: "将一张基本牌当酒使用", + check: function (card) { + if (_status.event.type == "dying") return 1; + return 4 - get.value(card); + }, + ai: { + skillTagFilter: function (player) { + return player.countCards("h", { type: "basic" }) > 0 && player.hp <= 0; }, + save: true, }, }, - fuman2: { + zhanyi_equip: { + trigger: { player: "shaBegin" }, + forced: true, + filter: function (event, player) { + return event.target.countCards("he") > 0; + }, + check: function (event, player) { + return get.attitude(player, event.target) < 0; + }, + content: function () { + trigger.target.chooseToDiscard("he", true, 2); + }, + }, + zhanyi_trick: { mod: { - aiOrder: function (player, card, num) { - if (get.itemtype(card) == "card" && card.hasGaintag("fuman")) return num + 1; - }, - cardname: function (card, player) { - if (get.itemtype(card) == "card" && card.hasGaintag("fuman")) return "sha"; + targetInRange: function () { + return true; }, }, }, - qizhou: { - trigger: { player: ["phaseBefore", "equipEnd", "loseEnd"] }, - forced: true, - popup: false, - derivation: ["mashu", "reyingzi", "reduanbing", "fenwei"], + dingpan: { + enable: "phaseUse", filter: function (event, player) { - if (player.equiping) return false; - var suits = []; - var es = player.getCards("e"); - for (var i = 0; i < es.length; i++) { - suits.add(get.suit(es[i])); - } - if (player.additionalSkills.qizhou) { - return player.additionalSkills.qizhou.length != suits.length; + var num; + var mode = get.mode(); + if (mode == "identity" || mode == "doudizhu") { + if (mode == "identity" && _status.mode == "purple") num = player.getEnemies().length; + else num = get.population("fan"); + } else if (mode == "versus") { + if (!_status.mode || _status.mode != "two") num = player.getEnemies().length; + else { + var target = game.findPlayer(x => { + var num = x.getFriends().length; + return !game.hasPlayer(y => { + return x != y && y.getFriends().length > num; + }); + }); + num = target ? target.getFriends(true).length : 1; + } } else { - return suits.length > 0; + num = 1; } + if ((player.getStat().skill.dingpan || 0) >= num) return false; + return true; + }, + filterTarget: function (card, player, target) { + return target.countCards("e") > 0; }, content: function () { - var suits = []; - var es = player.getCards("e"); - for (var i = 0; i < es.length; i++) { - suits.add(get.suit(es[i])); + "step 0"; + target.draw(); + "step 1"; + var goon = get.damageEffect(target, player, target) >= 0; + if (!goon && target.hp >= 4 && get.attitude(player, target) < 0) { + var es = target.getCards("e"); + for (var i = 0; i < es.length; i++) { + if (get.equipValue(es[i], target) >= 8) { + goon = true; + break; + } + } } - player.removeAdditionalSkill("qizhou"); - switch (suits.length) { - case 1: - player.addAdditionalSkill("qizhou", ["mashu"]); - break; - case 2: - player.addAdditionalSkill("qizhou", ["mashu", "reyingzi"]); - break; - case 3: - player.addAdditionalSkill("qizhou", ["mashu", "reyingzi", "reduanbing"]); - break; - case 4: - player.addAdditionalSkill("qizhou", ["mashu", "reyingzi", "reduanbing", "fenwei"]); - break; + target + .chooseControl(function () { + if (_status.event.goon) return "选项二"; + return "选项一"; + }) + .set("goon", goon) + .set("prompt", "定叛") + .set("choiceList", ["令" + get.translation(player) + "弃置你装备区里的一张牌", "获得你装备区内的所有牌并受到1点伤害"]); + "step 2"; + if (result.control == "选项一") { + player.discardPlayerCard(target, true, "e"); + event.finish(); + } else { + target.gain(target.getCards("e"), "gain2"); } + "step 3"; + game.delay(0.5); + target.damage(); }, ai: { - threaten: 1.2, + order: 7, + result: { + target: function (player, target) { + if (get.damageEffect(target, player, target) >= 0) return 2; + var att = get.attitude(player, target); + if (att == 0) return 0; + var es = target.getCards("e"); + if (att > 0 && (target.countCards("h") > 2 || target.needsToDiscard(1))) return 0; + if (es.length == 1 && att > 0) return 0; + for (var i = 0; i < es.length; i++) { + var val = get.equipValue(es[i], target); + if (val <= 4) { + if (att > 0) { + return 1; + } + } else if (val >= 7) { + if (att < 0) { + return -1; + } + } + } + return 0; + }, + }, }, }, - shanxi: { + hongde: { audio: 2, - enable: "phaseUse", - usable: 1, - filterCard: { color: "red", type: "basic" }, - filterTarget: function (card, player, target) { - return target != player && target.countCards("he") && player.inRange(target); + trigger: { + player: ["loseAfter", "gainAfter"], + global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], }, - check: function (card) { - return 6 - get.value(card); + direct: true, + filter: function (event, player) { + var num = event.getl(player).cards2.length; + if (event.getg) num = Math.max(num, event.getg(player).length); + return num > 1; }, content: function () { "step 0"; - player.discardPlayerCard(target, true); + player + .chooseTarget(get.prompt("hongde"), "令一名其他角色摸一张牌", function (card, player, target) { + return target != player; + }) + .set("ai", function (target) { + return get.attitude(get.player(), target); + }); "step 1"; if (result.bool) { - if (get.name(result.cards[0], result.cards[0].original == "h" ? player : false) == "shan") { - player.viewHandcards(target); - } else { - target.viewHandcards(player); - } + player.logSkill("hongde", result.targets); + result.targets[0].draw(); } }, - ai: { - order: 8, - result: { - target: -1, - }, - }, }, - fenxun: { + ziyuan: { + audio: 2, enable: "phaseUse", usable: 1, - position: "he", - filterTarget: function (card, player, target) { - return target != player; + filterCard: function (card) { + var num = 0; + for (var i = 0; i < ui.selected.cards.length; i++) { + num += get.number(ui.selected.cards[i]); + } + return get.number(card) + num <= 13; }, - content: function () { - player.markAuto("fenxun2", [target]); - player.addTempSkill("fenxun2"); + complexCard: true, + selectCard: function () { + var num = 0; + for (var i = 0; i < ui.selected.cards.length; i++) { + num += get.number(ui.selected.cards[i]); + } + if (num == 13) return ui.selected.cards.length; + return ui.selected.cards.length + 2; + }, + discard: false, + lose: false, + delay: false, + filterTarget: function (card, player, target) { + return player != target; }, check: function (card) { - if (card.name == "sha" && _status.event.player.countCards("h", "sha") <= 1) return 0; - return 6 - get.value(card); + var num = 0; + for (var i = 0; i < ui.selected.cards.length; i++) { + num += get.number(ui.selected.cards[i]); + } + if (num + get.number(card) == 13) return 9 - get.value(card); + if (ui.selected.cards.length == 0) { + var cards = _status.event.player.getCards("h"); + for (var i = 0; i < cards.length; i++) { + for (var j = i + 1; j < cards.length; j++) { + if (cards[i].number + cards[j].number == 13) { + if (cards[i] == card || cards[j] == card) return 8.5 - get.value(card); + } + } + } + } + return 0; + }, + content: function () { + player.give(cards, target, "give"); + target.recover(); }, - filterCard: true, ai: { - order: 4, + order: function (skill, player) { + if ( + game.hasPlayer(function (current) { + return current.hp < current.maxHp && current != player && get.recoverEffect(current, player, player) > 0; + }) + ) { + return 10; + } + return 1; + }, result: { player: function (player, target) { - if (get.distance(player, target) <= 1) return 0; - var hs = player.getCards("h", "shunshou"); - if (hs.length && player.canUse(hs[0], target, false)) { - return 1; - } - var geteff = function (current) { - return player.canUse("sha", current, false, true) && get.effect(current, { name: "sha" }, player, player) > 0; - }; - if (player.hasSha() && geteff(target)) { - var num = game.countPlayer(function (current) { - return current != player && get.distance(player, current) <= 1 && geteff(current); - }); - if (num == 0) { - if ( - game.hasPlayer(function (current) { - return player.canUse("sha", current) && geteff(current) && current != target; - }) - ) { - return 1; - } - } else if (num == 1) { - return 1; - } + if (get.attitude(player, target) < 0) return -1; + var eff = get.recoverEffect(target, player, player); + if (eff < 0) return 0; + if (eff > 0) { + if (target.hp == 1) return 3; + return 2; } + if (player.needsToDiscard()) return 1; return 0; }, }, + threaten: 1.3, }, }, - fenxun2: { - mark: "character", - onremove: true, - intro: { - content: "到$的距离视为1", - }, + jugu: { + audio: 2, mod: { - globalFrom: function (from, to) { - if (from.getStorage("fenxun2").includes(to)) { - return -Infinity; - } + maxHandcard: function (player, num) { + return num + player.maxHp; }, }, - }, - duanbing: { - audio: 2, - audioname2: { heqi: "duanbing_heqi" }, - trigger: { player: "useCard2" }, + trigger: { global: "phaseBefore", player: "enterGame" }, + forced: true, filter: function (event, player) { - if (event.card.name != "sha") return false; - return game.hasPlayer(function (current) { - return !event.targets.includes(current) && get.distance(player, current) <= 1 && player.canUse(event.card, current); - }); + return event.name != "phase" || game.phaseNumber == 0; }, - direct: true, content: function () { - "step 0"; - player - .chooseTarget(get.prompt("duanbing"), "为" + get.translation(trigger.card) + "增加一个目标", function (card, player, target) { - return !_status.event.sourcex.includes(target) && get.distance(player, target) <= 1 && player.canUse(_status.event.card, target); - }) - .set("sourcex", trigger.targets) - .set("ai", function (target) { - var player = _status.event.player; - return get.effect(target, _status.event.card, player, player); - }) - .set("card", trigger.card); - "step 1"; - if (result.bool) { - if (!event.isMine() && !event.isOnline()) game.delayx(); - event.target = result.targets[0]; - } else { - event.finish(); - } - "step 2"; - player.logSkill("duanbing", event.target); - trigger.targets.push(event.target); - }, - ai: { - effect: { - player: function (card, player, target, current, isLink) { - if (!isLink && card.name == "sha") { - if (player._duanbingtmp) return; - player._duanbingtmp = true; - if (get.effect(target, card, player, player) <= 0) { - delete player._duanbingtmp; - return; - } - if ( - game.hasPlayer(function (current) { - return current != target && get.distance(player, current) <= 1 && player.canUse(card, current) && get.effect(current, card, player, player) > 0; - }) - ) { - delete player._duanbingtmp; - return [1, 1]; - } - delete player._duanbingtmp; - } - }, - }, + player.draw(player.maxHp); }, }, - fuhan: { + tuifeng: { audio: 2, - trigger: { player: "phaseBegin" }, - unique: true, - limited: true, - skillAnimation: true, - animationColor: "orange", + trigger: { player: "damageEnd" }, + direct: true, + notemp: true, filter: function (event, player) { - return player.storage.fanghun2 > 0; - }, - prompt: function (event, player) { - var num = Math.max(2, player.storage.fanghun2 || 0); - num = Math.min(num, 8); - return get.prompt("fuhan") + "(体力上限:" + num + ")"; - }, - check: function (event, player) { - var num = Math.max(2, player.storage.fanghun2 || 0); - if (num == 1) return false; - if (player.hp <= 1) return true; - if (num == 2) return false; - if (num == 3) return player.hp < 3 && player.isMinHp(); - return true; + return player.countCards("he") > 0; }, content: function () { "step 0"; - if (player.storage.fanghun) player.draw(player.storage.fanghun); - player.removeMark("fanghun", player.storage.fanghun); - event.num = Math.max(2, player.storage.fanghun2 || 0); - var list; - if (_status.characterlist) { - list = []; - for (var i = 0; i < _status.characterlist.length; i++) { - var name = _status.characterlist[i]; - if (lib.character[name][1] == "shu") list.push(name); - } - } else if (_status.connectMode) { - list = get.charactersOL(function (i) { - return lib.character[i][1] != "shu"; - }); - } else { - list = get.gainableCharacters(function (info) { - return info[1] == "shu"; - }); - } - var players = game.players.concat(game.dead); - for (var i = 0; i < players.length; i++) { - list.remove(players[i].name); - list.remove(players[i].name1); - list.remove(players[i].name2); - } - list.remove("zhaoyun"); - list.remove("re_zhaoyun"); - list.remove("ol_zhaoyun"); - // var dialog=ui.create.dialog(); - // dialog.add([list.randomGets(5),'character']); - player - .chooseButton(true) - .set("ai", function (button) { - return get.rank(button.link, true) - lib.character[button.link][2]; - }) - .set("createDialog", ["将武将牌替换为一名角色", [list.randomGets(5), "character"]]); - player.awakenSkill("fuhan"); + player.chooseCard(get.prompt2("tuifeng"), "he", [1, trigger.num]).set("ai", function (card) { + if (card.name == "du") return 20; + return 7 - get.useful(card); + }); "step 1"; - event.num = Math.min(event.num, 8); - player.reinitCharacter(get.character(player.name2, 3).includes("fuhan") ? player.name2 : player.name1, result.links[0]); - "step 2"; - var num = event.num - player.maxHp; - if (num > 0) player.gainMaxHp(num); - else player.loseMaxHp(-num); - player.recover(); + if (result.bool) { + player.logSkill("tuifeng"); + player.addToExpansion(result.cards, player, "give").gaintag.add("tuifeng"); + } + }, + onremove: function (player, skill) { + var cards = player.getExpansions(skill); + if (cards.length) player.loseToDiscardpile(cards); }, + marktext: "锋", + intro: { + content: "expansion", + markcount: "expansion", + }, + group: "tuifeng2", ai: { - combo: "fanghun", + threaten: 0.8, + maixie: true, + maixie_hp: true, }, }, - refuhan: { - audio: "fuhan", + tuifeng2: { + audio: "tuifeng", trigger: { player: "phaseZhunbeiBegin" }, - unique: true, - limited: true, - skillAnimation: true, - animationColor: "orange", + forced: true, filter: function (event, player) { - return player.countMark("fanghun") > 0; + return player.getExpansions("tuifeng").length > 0; }, content: function () { - "step 0"; - if (player.storage.fanghun) player.draw(player.storage.fanghun); - player.removeMark("fanghun", player.storage.fanghun); - player.awakenSkill("refuhan"); - "step 1"; - var list; - if (_status.characterlist) { - list = []; - for (var i = 0; i < _status.characterlist.length; i++) { - var name = _status.characterlist[i]; - if (lib.character[name][1] == "shu") list.push(name); - } - } else if (_status.connectMode) { - list = get.charactersOL(function (i) { - return lib.character[i][1] != "shu"; - }); - } else { - list = get.gainableCharacters(function (info) { - return info[1] == "shu"; - }); - } - var players = game.players.concat(game.dead); - for (var i = 0; i < players.length; i++) { - list.remove(players[i].name); - list.remove(players[i].name1); - list.remove(players[i].name2); - } - list.remove("zhaoyun"); - list.remove("re_zhaoyun"); - list.remove("ol_zhaoyun"); - list = list.randomGets(Math.max(4, game.countPlayer())); - var skills = []; - for (var i of list) { - skills.addArray( - (lib.character[i][3] || []).filter(function (skill) { - var info = get.info(skill); - return info && !info.zhuSkill && !info.limited && !info.juexingji && !info.hiddenSkill && !info.charlotte && !info.dutySkill; - }) - ); - } - if (!list.length || !skills.length) { - event.finish(); - return; - } - if (player.isUnderControl()) { - game.swapPlayerAuto(player); - } - var switchToAuto = function () { - _status.imchoosing = false; - event._result = { - bool: true, - skills: skills.randomGets(2), - }; - if (event.dialog) event.dialog.close(); - if (event.control) event.control.close(); - }; - var chooseButton = function (list, skills) { - var event = _status.event; - if (!event._result) event._result = {}; - event._result.skills = []; - var rSkill = event._result.skills; - var dialog = ui.create.dialog("请选择获得至多两个技能", [list, "character"], "hidden"); - event.dialog = dialog; - var table = document.createElement("div"); - table.classList.add("add-setting"); - table.style.margin = "0"; - table.style.width = "100%"; - table.style.position = "relative"; - for (var i = 0; i < skills.length; i++) { - var td = ui.create.div(".shadowed.reduce_radius.pointerdiv.tdnode"); - td.link = skills[i]; - table.appendChild(td); - td.innerHTML = "" + get.translation(skills[i]) + ""; - td.addEventListener(lib.config.touchscreen ? "touchend" : "click", function () { - if (_status.dragged) return; - if (_status.justdragged) return; - _status.tempNoButton = true; - setTimeout(function () { - _status.tempNoButton = false; - }, 500); - var link = this.link; - if (!this.classList.contains("bluebg")) { - if (rSkill.length >= 2) return; - rSkill.add(link); - this.classList.add("bluebg"); - } else { - this.classList.remove("bluebg"); - rSkill.remove(link); - } - }); - } - dialog.content.appendChild(table); - dialog.add("  "); - dialog.open(); - - event.switchToAuto = function () { - event.dialog.close(); - event.control.close(); - game.resume(); - _status.imchoosing = false; - }; - event.control = ui.create.control("ok", function (link) { - event.dialog.close(); - event.control.close(); - game.resume(); - _status.imchoosing = false; - }); - for (var i = 0; i < event.dialog.buttons.length; i++) { - event.dialog.buttons[i].classList.add("selectable"); + var cards = player.getExpansions("tuifeng"); + player.draw(2 * cards.length); + player.addTempSkill("tuifeng3"); + player.addMark("tuifeng3", cards.length, false); + player.loseToDiscardpile(cards); + }, + }, + tuifeng3: { + mod: { + cardUsable: function (card, player, num) { + if (card.name == "sha") return num + player.countMark("tuifeng3"); + }, + }, + onremove: true, + charlotte: true, + }, + weidi: { + available(mode) { + return mode == "identity" || (mode == "versus" && _status.mode == "four"); + }, + init(player) { + const list = []; + const zhu = get.zhu(player); + if (zhu && zhu != player && zhu.skills) { + for (var i = 0; i < zhu.skills.length; i++) { + if (lib.skill[zhu.skills[i]] && lib.skill[zhu.skills[i]].zhuSkill) { + list.push(zhu.skills[i]); + } } - game.pause(); - game.countChoose(); - }; - if (event.isMine()) { - chooseButton(list, skills); - } else if (event.isOnline()) { - event.player.send(chooseButton, list, skills); - event.player.wait(); - game.pause(); - } else { - switchToAuto(); - } - "step 2"; - var map = event.result || result; - if (map && map.skills && map.skills.length) { - player.addSkills(map.skills); } + player.addAdditionalSkill("weidi", list); game.broadcastAll(function (list) { game.expandSkills(list); for (var i of list) { var info = lib.skill[i]; if (!info) continue; if (!info.audioname2) info.audioname2 = {}; - info.audioname2.zhaoxiang = "fuhan"; + info.audioname2.yuanshu = "weidi"; } - }, map.skills); - "step 3"; - if (player.isMinHp()) player.recover(); + }, list); + }, + trigger: { global: ["gameStart", "changeSkillsAfter"] }, + forced: true, + audio: 2, + filter: function (event, player) { + const mode = get.mode(); + if (mode != "identity" && (mode != "versus" || _status.mode != "four")) return false; + const zhu = get.zhu(player); + if (!zhu || zhu == player) return false; + if (event.name == "gameStart") return true; + return ( + event.player == zhu && + (event.addSkill.some(skill => { + return lib.skill[skill] && lib.skill[skill].zhuSkill; + }) || + event.addSkill.some(skill => { + return lib.skill[skill] && lib.skill[skill].zhuSkill; + })) + ); }, - ai: { - combo: "refanghun", + async content(event, trigger, player) { + lib.skill.weidi.init(player); }, }, - refanghun: { + zhenlue: { + audio: 2, + trigger: { player: "useCard" }, + forced: true, + filter: function (event) { + return get.type(event.card) == "trick"; + }, + content: function () { + trigger.nowuxie = true; + }, mod: { - aiValue: function (player, card, num) { - if (card.name != "sha" && card.name != "shan") return; - var geti = function () { - var cards = player.getCards("hs", function (card) { - return card.name == "sha" || card.name == "shan"; - }); - if (cards.includes(card)) { - return cards.indexOf(card); - } - return cards.length; - }; - return Math.max(num, [7, 5, 5, 3][Math.min(geti(), 3)]); + targetEnabled: function (card, player, target) { + if (get.type(card) == "delay") { + return false; + } }, }, - locked: false, - audio: "fanghun", - inherit: "fanghun", - trigger: { - player: "useCard", - target: "useCardToTargeted", - }, }, - fanghun: { - hiddenCard: function (player, name) { - if (!player.storage.fanghun || player.storage.fanghun <= 0) return false; - if (name == "tao") return player.countCards("hs", "jiu") > 0; - if (name == "jiu") return player.countCards("hs", "tao") > 0; - return false; - }, + jianshu: { audio: 2, - marktext: "影", - intro: { - content: "mark", - name: "梅影", + unique: true, + limited: true, + enable: "phaseUse", + animationColor: "thunder", + skillAnimation: "epic", + filter: function (event, player) { + return !player.storage.jianshu && player.countCards("h", { color: "black" }) > 0; }, - trigger: { - source: "damageSource", - player: "damageEnd", + init: function (player) { + player.storage.jianshu = false; }, - forced: true, - locked: false, - filter: function (event) { - return event.card && event.card.name == "sha"; + filterTarget: function (card, player, target) { + if (target == player) return false; + if (ui.selected.targets.length) { + return ui.selected.targets[0] != target && !ui.selected.targets[0].hasSkillTag("noCompareSource") && target.countCards("h") && !target.hasSkillTag("noCompareTarget"); + } + return true; + }, + filterCard: { color: "black" }, + mark: true, + discard: false, + lose: false, + delay: false, + check: function (card) { + if (_status.event.player.hp == 1) return 8 - get.value(card); + return 6 - get.value(card); }, + selectTarget: 2, + multitarget: true, content: function () { - player.addMark("fanghun", trigger.num || 1); - player.addMark("fanghun2", trigger.num || 1, false); + "step 0"; + player.awakenSkill("jianshu"); + player.storage.jianshu = true; + player.give(cards, targets[0], "give"); + "step 1"; + if (targets[0].canCompare(targets[1])) targets[0].chooseToCompare(targets[1]); + else event.finish(); + "step 2"; + if (result.bool) { + targets[0].chooseToDiscard("he", 2, true); + targets[1].loseHp(); + } else if (result.tie) { + targets[0].loseHp(); + targets[1].loseHp(); + } else { + targets[1].chooseToDiscard("he", 2, true); + targets[0].loseHp(); + } }, - group: ["fanghun_sha", "fanghun_draw"], - subSkill: { - draw: { - trigger: { player: ["useCardAfter", "respondAfter"] }, - forced: true, - popup: false, - filter: function (event) { - return event.skill == "fanghun_sha" || event.skill == "fanghun_shan"; - }, - content: function () { - player.draw(); + intro: { + content: "limited", + }, + ai: { + expose: 0.4, + order: 4, + result: { + target: function (player, target) { + if (player.hasUnknown()) return 0; + if (ui.selected.targets.length) return -1; + return -0.5; }, }, - sha: { - audio: "fanghun", - inherit: "ollongdan", - enable: ["chooseToUse", "chooseToRespond"], - prompt: "弃置一枚【梅影】标记,将杀当做闪,或将闪当做杀,或将桃当做酒,或将酒当做桃使用或打出", - filter: function (event, player) { - return player.hasMark("fanghun") && get.info("ollongdan").filter(event, player); - }, - onrespond: function () { - return this.onuse.apply(this, arguments); - }, - onuse: function (result, player) { - player.removeMark("fanghun", 1); - }, - ai: { - respondSha: true, - respondShan: true, - skillTagFilter: function (player, tag) { - if (!player.hasMark("fanghun")) return false; - return get.info("ollongdan").ai.skillTagFilter(player, tag); - }, - order: function (item, player) { - if (!player || !player.storage) { - player = _status.event.player; - if (!player || !player.storage) return 0; - if ( - Object.keys(player.storage).some(i => { - return typeof i == "string" && i.indexOf("fuhan") != -1; - }) - ) - return 4; - return 1; - } - const awakened = Object.keys(player.storage).some(i => typeof i == "string" && i.indexOf("fuhan") != -1); - if (_status.event.type == "phase") { - var max = 0; - var list = ["sha", "tao", "jiu"]; - var map = { sha: "shan", tao: "jiu", jiu: "tao" }; - for (var i = 0; i < list.length; i++) { - var name = list[i]; - if (player.countCards("hs", map[name]) > (name == "jiu" ? 1 : 0) && player.getUseValue({ name: name }) > 0) { - var temp = get.order({ name: name }); - if (temp > max) max = temp; - } + }, + }, + yongdi: { + audio: 2, + audioname: ["xinping"], + unique: true, + limited: true, + trigger: { player: "phaseZhunbeiBegin" }, + animationColor: "thunder", + skillAnimation: "legend", + mark: true, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2("yongdi"), (card, player, target) => { + if (player === target) return false; + return target.hasSex("male") || target.name == "key_yuri"; + }) + .set("ai", target => { + if (!_status.event.goon) return 0; + let player = _status.event.player; + let att = get.attitude(player, target); + if (att <= 1) return 0; + let mode = get.mode(); + if (mode == "identity" || (mode == "versus" && (_status.mode == "four" || _status.mode == "guandu"))) { + if ( + target.getStockSkills(true, true).some(i => { + if (target.hasSkill(i)) return false; + let info = get.info(i); + return info && info.zhuSkill; + }) + ) + return att * 2; + } + return att; + }) + .set("goon", !player.hasUnknown()) + .forResult(); + }, + async content(event, trigger, player) { + player.awakenSkill("yongdi"); + let target = event.targets[0], + mode = get.mode(); + if (mode !== "identity" || player.identity !== "nei") player.addExpose(0.25); + target.gainMaxHp(); + target.recover(); + let skills = target.getStockSkills(true, true).filter(skill => { + if (target.hasSkill(skill)) return false; + let info = get.info(skill); + return info && info.zhuSkill; + }); + if (skills.length) target.addSkills(skills); + }, + }, + regushe: { + audio: "gushe", + enable: "phaseUse", + filterTarget: function (card, player, target) { + return player.canCompare(target); + }, + selectTarget: [1, 3], + filter: function (event, player) { + return player.countMark("regushe") + player.countMark("regushe2") < 7 && player.countCards("h") > 0; + }, + multitarget: true, + multiline: true, + content: function () { + player.addTempSkill("regushe2"); + player.chooseToCompare(targets).callback = lib.skill.regushe.callback; + }, + intro: { + name: "饶舌", + content: "mark", + }, + callback: function () { + "step 0"; + if (event.winner !== player) { + target.chat(lib.skill.gushe.chat[player.countMark("regushe")]); + game.delay(); + player.addMark("regushe", 1); + if (player.countMark("regushe") >= 7) { + player.die(); + } + } else player.addMark("regushe2", 1, false); + "step 1"; + if (event.winner !== player) { + player.chooseToDiscard("he", "弃置一张牌,或摸一张牌").set("ai", function () { + return -1; + }); + } else event.goto(3); + "step 2"; + if (!result.bool) player.draw(); + "step 3"; + if (event.winner !== target) { + target + .chooseToDiscard("he", "弃置一张牌,或令" + get.translation(player) + "摸一张牌") + .set("ai", function (card) { + if (_status.event.goon) return 6 - get.value(card); + return 0; + }) + .set("goon", get.attitude(target, player) < 0); + } else event.finish(); + "step 4"; + if (!result.bool) player.draw(); + }, + ai: { + order: 7, + result: { + target: function (player, target) { + var num = ui.selected.targets.length + 1; + if (num + player.countMark("regushe") <= 6) return -1; + var hs = player.getCards("h"); + for (var i = 0; i < hs.length; i++) { + if (get.value(hs[i]) <= 6) { + switch (hs[i].number) { + case 13: + return -1; + case 12: + if (player.countMark("regushe") + num <= 8) return -1; + break; + case 11: + if (player.countMark("regushe") + num <= 7) return -1; + break; + default: + if (hs[i].number > 5 && player.countMark("regushe") + num <= 6) return -1; } - if (max > 0) max += awakened ? 0.3 : -0.3; - return max; } - return awakened ? 4 : 1; - }, + } + return 0; }, }, }, + marktext: "饶", }, - yjixi: { - derivation: "rewangzun", - audio: "weidi", - trigger: { player: "phaseJieshuBegin" }, + regushe2: { + charlotte: true, + onremove: true, + }, + rejici: { + audio: "jici", + trigger: { + player: "compare", + target: "compare", + }, forced: true, filter: function (event, player) { - if (player.phaseNumber < 3) return false; - var num = 0; - for (var i = player.actionHistory.length - 1; i >= 0; i--) { - if (!player.actionHistory[i].isMe) continue; - if (_status.globalHistory[i].changeHp.some(evt => evt.player == player && evt.getParent().name == "loseHp")) return false; - else { - num++; - if (num >= 3) break; - } + // if(player!=event.target&&event.iwhile) return false; + return (player == event.player ? event.num1 : event.num2) <= player.countMark("regushe"); + }, + content: function () { + if (player == trigger.target || !trigger.iwhile) { + trigger[player == trigger.player ? "num1" : "num2"] += player.countMark("regushe"); + game.log(player, "的拼点牌点数+" + player.countMark("regushe")); } - return true; + game.delayx(); + // var cards=[trigger.card1]; + // if(trigger.cardlist) cards.addArray(trigger.cardlist); + // else cards.push(trigger.card2); + // cards.sort(function(a,b){ + // return get.number(b)-get.number(a); + // }); + // var num=get.number(cards[0]); + // for(var i=1;i trigger.num2) cards.push(trigger.card1); + if (trigger.num1 < trigger.num2) cards.push(trigger.card2); + cards = cards.filterInD(); + if (cards.length) player.gain(cards, "gain2"); + }, + group: "rejici2", + ai: { + combo: "regushe", }, + }, + rejici2: { + audio: "jici", + trigger: { player: "die" }, + forced: true, + forceDie: true, skillAnimation: true, - animationColor: "gray", - unique: true, - juexingji: true, + animationColor: "water", + filter: function (event, player) { + return event.source && event.source.isIn(); + }, + logTarget: "source", + content: function () { + var num = 7 - player.countMark("regushe"); + if (num > 0) trigger.source.chooseToDiscard(num, true, "he"); + trigger.source.loseHp(); + }, + }, + gushe: { + audio: 2, + enable: "phaseUse", + usable: 1, + filterTarget: function (card, player, target) { + return player.canCompare(target); + }, + selectTarget: [1, 3], + filter: function (event, player) { + return player.countCards("h") > 0; + }, + multitarget: true, + multiline: true, content: function () { + player.chooseToCompare(targets).callback = lib.skill.gushe.callback; + }, + intro: { + name: "饶舌", + content: "mark", + }, + chat: ["粗鄙之语", "天地不容", "谄谀之臣", "皓首匹夫,苍髯老贼", "二臣贼子", "断脊之犬", "我从未见过有如此厚颜无耻之人!"], + callback: function () { "step 0"; - player.awakenSkill("yjixi"); - player.gainMaxHp(); - player.recover(); - "step 1"; - var str = "摸两张牌"; - var mode = get.mode(); - var choice = "选项一"; - if (mode == "identity" || (mode == "versus" && _status.mode == "four")) { - var list = []; - var zhu = get.zhu(player); - if (zhu && zhu != player && zhu.skills) { - for (var i = 0; i < zhu.skills.length; i++) { - if (lib.skill[zhu.skills[i]] && lib.skill[zhu.skills[i]].zhuSkill) { - list.push(zhu.skills[i]); - } - } - } - if (list.length) { - str += "并获得技能" + get.translation(list); - event.list = list; - choice = "选项二"; + if (event.winner !== player) { + target.chat(lib.skill.gushe.chat[player.countMark("gushe")]); + game.delay(); + player.addMark("gushe", 1); + if (player.countMark("gushe") >= 7) { + player.die(); } } - player - .chooseControl(function (event, player) { - return _status.event.choice; - }) - .set("choiceList", ["获得技能〖妄尊〗", str]) - .set("choice", choice); + "step 1"; + if (event.winner !== player) { + player.chooseToDiscard("he", "弃置一张牌,或摸一张牌").set("ai", function () { + return -1; + }); + } else event.goto(3); "step 2"; - if (result.control == "选项一") { - player.addSkills("rewangzun"); - } else { - player.draw(2); - if (event.list) { - player.addSkills(event.list); - game.broadcastAll(function (list) { - game.expandSkills(list); - for (var i of list) { - var info = lib.skill[i]; - if (!info) continue; - if (!info.audioname2) info.audioname2 = {}; - info.audioname2.old_yuanshu = "weidi"; - } - }, event.list); - } + if (!result.bool) { + player.draw(); } + "step 3"; + if (event.winner !== target) { + target + .chooseToDiscard("he", "弃置一张牌,或令" + get.translation(player) + "摸一张牌") + .set("ai", function (card) { + if (_status.event.goon) return 6 - get.value(card); + return 0; + }) + .set("goon", get.attitude(target, player) < 0); + } else event.finish(); + "step 4"; + if (!result.bool) player.draw(); + }, + ai: { + order: 7, + result: { + target: function (player, target) { + var num = ui.selected.targets.length + 1; + if (num > 3) num = 3; + var hs = player.getCards("h"); + for (var i = 0; i < hs.length; i++) { + if (get.value(hs[i]) <= 6) { + switch (hs[i].number) { + case 13: + return -1; + case 12: + if (player.countMark("gushe") + num <= 8) return -1; + break; + case 11: + if (player.countMark("gushe") + num <= 7) return -1; + break; + default: + if (hs[i].number > 5 && player.countMark("gushe") + num <= 6) return -1; + } + } + } + return 0; + }, + }, }, }, - xinyongsi: { - audio: "yongsi", - group: ["xinyongsi1", "xinyongsi2"], - locked: true, - }, - xinyongsi1: { - audio: "yongsi1", - trigger: { player: "phaseDrawBegin1" }, - forced: true, + jici: { + audio: 2, + trigger: { player: "compare" }, filter: function (event, player) { - return !event.numFixed; + return event.getParent().name == "gushe" && !event.iwhile && event.num1 <= player.countMark("gushe"); }, content: function () { - player.draw(game.countGroup()); - trigger.changeToZero(); - }, - }, - xinyongsi2: { - audio: "yongsi2", - trigger: { player: "phaseDiscardBegin" }, - forced: true, - check: function () { - return false; + if (trigger.num1 < player.countMark("gushe")) { + trigger.num1 += player.countMark("gushe"); + } else { + player.getStat().skill.gushe--; + } }, - content: function () { - "step 0"; - player.chooseToDiscard("he", "庸肆").set("prompt2", "弃置一张牌,或取消并失去1点体力").ai = function (card) { - return 8 - get.value(card); - }; - "step 1"; - if (!result.bool) player.loseHp(); + ai: { + combo: "gushe", }, }, - lianzhu: { + juesi: { audio: 2, enable: "phaseUse", - usable: 1, - filterCard: true, - position: "he", - filterTarget: function (card, player, target) { - return target != player; + filter: function (event, player) { + return player.countCards("h", "sha") > 0; }, - check: function (card) { - var num = get.value(card); - if (get.color(card) == "black") { - if (num >= 6) return 0; - return 20 - num; - } else { - if (_status.event.player.needsToDiscard()) return 7 - num; - } - return 0; + filterTarget: function (card, player, target) { + return target != player && target.countCards("he") > 0 && player.inRange(target); }, - discard: false, - lose: false, - delay: false, + filterCard: { name: "sha" }, content: function () { "step 0"; - player.give(cards, target); - if (get.color(cards[0]) == "black") { - target - .chooseToDiscard(2, "he", "弃置两张牌,或令" + get.translation(player) + "摸两张牌") - .set("ai", function (card) { - if (_status.event.goon) return 7 - get.value(card); - return 0; - }) - .set("goon", get.attitude(target, player) < 0); - } else { - event.finish(); - } + target.chooseToDiscard("he", true); "step 1"; - if (!result.bool) { - player.draw(2); + if (target.hp >= player.hp && result.bool && result.cards[0].name != "sha") { + player.useCard({ name: "juedou", isCard: true }, target); } }, ai: { - order: 8, - expose: 0.2, + order: 2, result: { target: function (player, target) { - if (ui.selected.cards.length && get.color(ui.selected.cards[0]) == "red") { - if (target.countCards("h") < player.countCards("h")) return 1; - return 0.5; + if (get.effect(target, { name: "juedou" }, player, player) <= 0) { + return 0; + } + if (target.hp < player.hp) { + if (player.countCards("h") > player.hp) return -0.1; + return 0; + } + var hs1 = target.getCards("h", "sha"); + var hs2 = player.getCards("h", "sha"); + if (hs1.length > hs2.length) { + return 0; + } + var hsx = target.getCards("h"); + if (hsx.length > 2 && hs2.length <= 1 && hsx[0].number < 6) { + return 0; + } + if (hsx.length > 3 && hs2.length <= 1) { + return 0; + } + if (hs1.length > hs2.length - 1 && hs1.length > 0 && (hs2.length <= 1 || hs1[0].number > hs2[0].number)) { + return 0; } return -1; }, }, }, }, - xiehui: { - mod: { - ignoredHandcard: function (card, player) { - if (get.color(card) == "black") { - return true; - } - }, - cardDiscardable: function (card, player, name) { - if (name == "phaseDiscard" && get.color(card) == "black") return false; - }, - }, - trigger: { - global: "gainAfter", - player: "loseAsyncAfter", + shefu: { + trigger: { player: "phaseJieshuBegin" }, + direct: true, + audio: 2, + init: function (player) { + if (!player.storage.shefu) player.storage.shefu = []; + if (!player.storage.shefu2) player.storage.shefu2 = []; }, - forced: true, - popup: false, filter: function (event, player) { - if (event.name == "loseAsync") { - if (event.type != "gain") return false; - return game.hasPlayer(function (current) { - if (current == player) return false; - var hs = current.getCards("h"), - cards = event.getl(player).cards2; - var cardsx = event.getg(current); - for (var i of cardsx) { - if (hs.includes(i) && cards.includes(i) && get.color(i, player) == "black") return true; - } - return false; - }); - } - if (event.player != player) { - var hs = event.player.getCards("h"); - var evt = event.getl(player); - return ( - evt && - evt.cards2 && - evt.cards2.filter(function (card) { - return hs.includes(card) && get.color(card, player) == "black"; - }).length > 0 - ); - } - return false; + return player.countCards("he") > 0; }, - content: function () { - var cards = trigger.getl(player).cards2; - game.countPlayer(function (current) { - if (current == player) return; - var hs = current.getCards("h"), - cardsx = trigger.getg(current).filter(function (card) { - return hs.includes(card) && cards.includes(card) && get.color(card, player) == "black"; - }); - if (cardsx.length > 0) { - current.addSkill("xiehui2"); - current.addGaintag(cards, "xiehui"); - } - }); + onremove: function (player, skill) { + var cards = player.getExpansions(skill); + if (cards.length) player.loseToDiscardpile(cards); }, - }, - xiehui2: { - mark: true, intro: { - content: "不能使用、打出或弃置得到的黑色牌", - }, - mod: { - cardDiscardable: function (card, player) { - if (card.hasGaintag("xiehui")) return false; + content: "cards", + onunmark: function (storage, player) { + player.storage.shefu = []; + player.storage.shefu2 = []; }, - cardEnabled2: function (card, player) { - if (get.itemtype(card) == "card" && card.hasGaintag("xiehui")) return false; + mark: function (dialog, content, player) { + if (content && content.length) { + dialog.addAuto(content); + if (player.isUnderControl(true)) { + var str = ""; + for (var i = 0; i < player.storage.shefu2.length; i++) { + str += get.translation(player.storage.shefu2[i]); + if (i < player.storage.shefu2.length - 1) { + str += "、"; + } + } + dialog.add('
    ' + str + "
    "); + } + } }, }, - trigger: { player: "changeHp" }, - forced: true, - popup: false, - charlotte: true, - filter: function (event) { - return event.num < 0; - }, content: function () { - player.removeSkill("xiehui2"); - }, - onremove: function (player) { - player.removeGaintag("xiehui"); - }, - }, - shanjia: { - sync: function (player) { - if (game.online) return; - var history = player.actionHistory; - var num = 0; - for (var i = 0; i < history.length; i++) { - for (var j = 0; j < history[i].useCard.length; j++) { - if (get.type(history[i].useCard[j].card) == "equip") num++; + "step 0"; + var list1 = [], + list2 = [], + list3 = []; + for (var i = 0; i < lib.inpile.length; i++) { + var type = get.type(lib.inpile[i]); + if (type == "basic") { + list1.push(["基本", "", lib.inpile[i]]); + } else if (type == "trick") { + list2.push(["锦囊", "", lib.inpile[i]]); + } else if (type == "delay") { + list3.push(["锦囊", "", lib.inpile[i]]); + } + } + player + .chooseButton([get.prompt("shefu"), [list1.concat(list2).concat(list3), "vcard"]]) + .set("filterButton", function (button) { + var player = _status.event.player; + if (player.storage.shefu2 && player.storage.shefu2.includes(button.link[2])) return false; + return true; + }) + .set("ai", function (button) { + var rand = _status.event.rand; + switch (button.link[2]) { + case "sha": + return 5 + rand[1]; + case "tao": + return 4 + rand[2]; + case "lebu": + return 3 + rand[3]; + case "shan": + return 4.5 + rand[4]; + case "wuzhong": + return 4 + rand[5]; + case "shunshou": + return 3 + rand[6]; + case "nanman": + return 2 + rand[7]; + case "wanjian": + return 2 + rand[8]; + default: + return rand[0]; + } + }) + .set("rand", [Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random()]); + "step 1"; + if (result.bool) { + event.cardname = result.links[0][2]; + player.logSkill("shefu"); + player.chooseCard("he", "选择一张牌作为“伏兵”", true); + } else { + event.finish(); + } + "step 2"; + if (result.bool) { + var card = result.cards[0]; + event.card = card; + player.addToExpansion(card, player, "give").gaintag.add("shefu"); + } + "step 3"; + if (player.getExpansions("shefu").includes(event.card)) { + player.storage.shefu.push(card); + player.storage.shefu2.push(event.cardname); + if (player.isOnline2()) { + player.send(function (storage) { + game.me.storage.shefu2 = storage; + }, player.storage.shefu2); } + player.syncStorage("shefu"); + player.markSkill("shefu"); } - player.storage.shanjia = num; - if (num > 0) player.markSkill("shanjia"); - }, - audio: 2, - intro: { - content: function (storage) { - if (storage == 0) return "未使用过装备牌"; - return "已使用过" + storage + "张装备牌"; - }, }, - group: "shanjia2", - trigger: { player: "phaseUseBegin" }, - frequent: true, + group: ["shefu2"], + }, + shefu2: { + trigger: { global: ["useCard"] }, + //priority:15, + audio: "shefu", filter: function (event, player) { - lib.skill.shanjia.sync(player); - return player.storage.shanjia > 0; + if (_status.currentPhase == player || event.player == player) return false; + return ( + player.storage.shefu2 && + player.storage.shefu2.includes(event.card.name) && + event.player.getHistory("lose", function (evt) { + return evt.getParent() == event && evt.hs && evt.hs.length == event.cards.length; + }).length + ); }, + direct: true, content: function () { "step 0"; - lib.skill.shanjia.sync(player); - player.draw(Math.min(7, player.storage.shanjia)); + var effect = 0; + if (trigger.card.name == "wuxie" || trigger.card.name == "shan") { + if (get.attitude(player, trigger.player) < -1) { + effect = -1; + } + } else if (trigger.targets && trigger.targets.length) { + for (var i = 0; i < trigger.targets.length; i++) { + effect += get.effect(trigger.targets[i], trigger.card, trigger.player, player); + } + } + var str = "设伏:是否令" + get.translation(trigger.player); + if (trigger.targets && trigger.targets.length) { + str += "对" + get.translation(trigger.targets); + } + str += "使用的" + get.translation(trigger.card) + "失效?"; + var next = player.chooseBool(str, function () { + var player = _status.event.player; + var trigger = _status.event.getTrigger(); + if (_status.event.effect < 0) { + if (trigger.card.name == "sha") { + var target = trigger.targets[0]; + if (target == player) { + return !player.countCards("h", "shan"); + } else { + return target.hp == 1 || (target.countCards("h") <= 2 && target.hp <= 2); + } + } else { + return true; + } + } + return false; + }); + next.set("effect", effect); "step 1"; - player.chooseToDiscard("he", Math.min(7, player.storage.shanjia), true); - "step 2"; - var useCard = false; - if (result.bool && result.cards) { - for (var i = 0; i < result.cards.length; i++) { - if (result.cards[i].original == "e") { - useCard = true; - break; + if (result.bool) { + player.logSkill("shefu", trigger.player); + var index = player.storage.shefu2.indexOf(trigger.card.name); + if (index != -1) { + var card = player.storage.shefu[index]; + player.loseToDiscardpile(card); + player.storage.shefu.splice(index, 1); + player.storage.shefu2.splice(index, 1); + if (player.storage.shefu.length == 0) { + player.unmarkSkill("shefu"); + } else { + player.syncStorage("shefu"); + player.markSkill("shefu"); + if (player.isOnline2()) { + player.send(function (storage) { + game.me.storage.shefu2 = storage; + }, player.storage.shefu2); + } } } - } - if (useCard) { - player.chooseUseTarget({ name: "sha" }, false, "是否视为使用一张【杀】?", "nodistance"); + trigger.targets.length = 0; + trigger.all_excluded = true; + if (trigger.player == _status.currentPhase) trigger.player.addTempSkill("baiban"); } }, ai: { - threaten: function (player, target) { - if (typeof target.storage.shanjia == "number") { - return Math.min(2, Math.sqrt(1 + target.storage.shanjia)); - } - }, + threaten: 1.8, + expose: 0.3, }, }, - shanjia2: { - trigger: { player: "useCard" }, - silent: true, + benyu: { + audio: 2, + trigger: { player: "damageEnd" }, filter: function (event, player) { - return get.type(event.card) == "equip"; + if (!event.source) return false; + var nh1 = player.countCards("h"); + var nh2 = event.source.countCards("h"); + var eh = player.countCards("e"); + if (nh1 + eh > nh2 && event.source.isIn()) return true; + if (nh1 < Math.min(5, nh2)) return true; }, + direct: true, content: function () { - lib.skill.shanjia.sync(player); + "step 0"; + var num1 = player.countCards("h"); + var num2 = trigger.source.countCards("h"); + var eh = player.countCards("he", function (card) { + return lib.filter.cardDiscardable(card, player, "benyu"); + }); + var bool1 = false, + bool2 = false; + if (num1 < Math.min(num2, 5)) bool1 = true; + if (eh > num2 && trigger.source.isIn()) bool2 = true; + if (bool1 && bool2) { + event.chosen = true; + player + .chooseControl("cancel2") + .set("prompt", get.prompt("benyu", trigger.source)) + .set("choiceList", ["将手牌摸至" + get.cnNumber(Math.min(num2, 5)) + "张", "弃置至少" + get.cnNumber(num2 + 1) + "张牌并对其造成1点伤害"]); + } else if (bool2) event.goto(3); + "step 1"; + if (event.chosen) { + if (result.control == "cancel2") event.finish(); + else if (result.index == 1) event.goto(3); + else event._result = { bool: true }; + } else player.chooseBool(get.prompt("benyu", trigger.source), "将手牌摸至" + get.cnNumber(Math.min(trigger.source.countCards("h"), 5)) + "张"); + "step 2"; + if (result.bool) { + player.logSkill("benyu", trigger.source); + player.drawTo(Math.min(trigger.source.countCards("h"), 5)); + } + event.finish(); + "step 3"; + var num = trigger.source.countCards("h") + 1; + var args = [[num, player.countCards("he")], "he"]; + if (event.chosen) { + player.logSkill("benyu", trigger.source); + args.push(true); + } else { + args.push(get.prompt("benyu", trigger.source)); + args.push("弃置" + get.cnNumber(num) + "张牌并对其造成1点伤害"); + } + var next = player.chooseToDiscard.apply(player, args); + if (!event.chosen) next.logSkill = ["benyu", trigger.source]; + next.set("ai", function (card) { + var trigger = _status.event.getTrigger(); + var player = _status.event.player; + if (ui.selected.cards.length >= _status.event.num) { + return -1; + } + if (get.damageEffect(trigger.source, player, player) > 0 && (get.value(card, player) < 0 || _status.event.num <= 2)) { + return 8 - get.value(card); + } + return -1; + }); + next.set("num", num); + "step 4"; + if (result.bool) trigger.source.damage(); }, }, - zhanyi: { - enable: "phaseUse", - usable: 1, + jili: { audio: 2, - filterCard: true, - position: "he", - check: function (card) { - var player = _status.event.player; - if (player.hp < 3) return 0; - var type = get.type(card, "trick"); - if (type == "trick") { - return 6 - get.value(card); - } else if (type == "equip") { - if ( - player.hasSha() && - game.hasPlayer(function (current) { - return player.canUse("sha", current) && get.attitude(player, current) < 0 && get.effect(current, { name: "sha" }, player, player) > 0; - }) - ) { - return 6 - get.value(card); + trigger: { + global: "useCardToTarget", + }, + forced: true, + check: function (event, player) { + return get.effect(player, event.card, event.player, player) > 0; + }, + filter: function (event, player) { + if (get.color(event.card) != "red") return false; + if (!event.targets) return false; + if (event.player == player) return false; + if (event.targets.includes(player)) return false; + if (get.info(event.card).multitarget) return false; + var type = get.type(event.card); + if (type != "basic" && type != "trick") return false; + if (lib.filter.targetEnabled2(event.card, event.player, player)) { + for (var i = 0; i < event.targets.length; i++) { + if (get.distance(event.targets[i], player) <= 1) return true; } } - return 0; + return false; }, + autodelay: true, content: function () { - player.loseHp(); - switch (get.type(cards[0], "trick")) { - case "basic": - player.addTempSkill("zhanyi_basic"); - break; - case "equip": - player.addTempSkill("zhanyi_equip"); - break; - case "trick": - player.addTempSkill("zhanyi_trick"); - player.draw(2); - break; - } - }, - ai: { - order: 9.1, - result: { - player: 1, - }, - }, - }, - zhanyi_basic: { - group: ["zhanyi_basic_sha", "zhanyi_basic_jiu", "zhanyi_basic_tao"], - }, - zhanyi_basic_tao: { - enable: "chooseToUse", - filterCard: { type: "basic" }, - viewAs: { name: "tao" }, - viewAsFilter: function (player) { - if (!player.countCards("h", { type: "basic" })) return false; - }, - prompt: "将一张基本牌当桃使用", - check: function (card) { - return 8 - get.value(card); + trigger.getParent().targets.add(player); + trigger.player.line(player, "green"); }, - ai: { - skillTagFilter: function (player) { - if (!player.countCards("h", { type: "basic" })) return false; + }, + zhidao: { + audio: 2, + mod: { + aiOrder: function (player, card, num) { + if (num > 0 && !player.hasSkill("zhidao2") && !get.tag(card, "damage") && (!lib.filter.targetEnabled(card, player, player) || get.effect(player, card, player) <= 0)) return num + 10; }, - save: true, }, - }, - zhanyi_basic_sha: { - enable: "chooseToUse", - filterCard: { type: "basic" }, - viewAs: { name: "sha" }, - viewAsFilter: function (player) { - if (!player.countCards("h", { type: "basic" })) return false; + trigger: { source: "damageSource" }, + filter: function (event, player) { + if (event._notrigger.includes(event.player)) return false; + return _status.currentPhase == player && event.player.isIn() && event.player.countCards("hej") > 0 && event.player != player && !player.hasSkill("zhidao2"); }, - prompt: "将一张基本牌当杀使用", - check: function (card) { - return 4 - get.value(card); + forced: true, + content: function () { + var num = 0; + if (trigger.player.countCards("h")) num++; + if (trigger.player.countCards("e")) num++; + if (trigger.player.countCards("j")) num++; + if (num) { + player.gainPlayerCard(trigger.player, num, "hej", true).set("filterButton", function (button) { + for (var i = 0; i < ui.selected.buttons.length; i++) { + if (get.position(button.link) == get.position(ui.selected.buttons[i].link)) return false; + } + return true; + }); + } + player.addTempSkill("zhidao2"); }, - ai: { - skillTagFilter: function (player) { - if (!player.countCards("h", { type: "basic" })) return false; + }, + zhidao2: { + mod: { + playerEnabled: function (card, player, target) { + if (player != target) return false; }, - respondSha: true, }, }, - zhanyi_basic_jiu: { - enable: "chooseToUse", - filterCard: { type: "basic" }, - viewAs: { name: "jiu" }, - viewAsFilter: function (player) { - if (!player.countCards("h", { type: "basic" })) return false; - }, - prompt: "将一张基本牌当酒使用", - check: function (card) { - if (_status.event.type == "dying") return 1; - return 4 - get.value(card); - }, - ai: { - skillTagFilter: function (player) { - return player.countCards("h", { type: "basic" }) > 0 && player.hp <= 0; + luanzhan: { + mod: { + selectTarget: function (card, player, range) { + if (!player.storage.luanzhan) return; + if (range[1] == -1) return; + if (card.name == "sha") range[1] += player.storage.luanzhan; + if (get.color(card) == "black" && get.type(card) == "trick") { + var info = get.info(card); + if (info.multitarget) return false; + range[1] += player.storage.luanzhan; + } }, - save: true, }, - }, - zhanyi_equip: { - trigger: { player: "shaBegin" }, + trigger: { source: "damageSource" }, + audio: 2, forced: true, - filter: function (event, player) { - return event.target.countCards("he") > 0; + mark: true, + intro: { + content: function (storage) { + return "可以额外指定" + storage + "个目标"; + }, }, - check: function (event, player) { - return get.attitude(player, event.target) < 0; + init: function (player) { + player.storage.luanzhan = 0; + }, + init2: function (player) { + player.markSkill("luanzhan"); }, content: function () { - trigger.target.chooseToDiscard("he", true, 2); + if (typeof player.storage.luanzhan == "number") { + player.storage.luanzhan += trigger.num; + } else { + player.storage.luanzhan = trigger.num; + } + if (player.hasSkill("luanzhan")) { + player.markSkill("luanzhan"); + } }, - }, - zhanyi_trick: { - mod: { - targetInRange: function () { - return true; + group: "luanzhan_cancel", + subSkill: { + cancel: { + audio: "luanzhan", + trigger: { player: "useCard" }, + forced: true, + filter: function (event, player) { + if (!player.storage.luanzhan) return false; + var check = false; + var card = event.card; + if (card.name == "sha") { + check = true; + } else if (get.color(card) == "black" && get.type(card) == "trick") { + var info = get.info(card); + if (!info.multitarget) { + check = true; + if (info.selectTarget == -1) { + check = false; + } else if (Array.isArray(info.selectTarget) && info.selectTarget[1] == -1) { + check = false; + } + } + } + if (check && event.targets && event.targets.length < player.storage.luanzhan) { + return true; + } + return false; + }, + content: function () { + player.storage.luanzhan = 0; + player.markSkill("luanzhan"); + }, }, }, }, - dingpan: { - enable: "phaseUse", + xinzhengnan: { + audio: "zhengnan", + trigger: { global: "dying" }, + frequent: true, filter: function (event, player) { - var num; - var mode = get.mode(); - if (mode == "identity" || mode == "doudizhu") { - if (mode == "identity" && _status.mode == "purple") num = player.getEnemies().length; - else num = get.population("fan"); - } else if (mode == "versus") { - if (!_status.mode || _status.mode != "two") num = player.getEnemies().length; - else { - var target = game.findPlayer(x => { - var num = x.getFriends().length; - return !game.hasPlayer(y => { - return x != y && y.getFriends().length > num; - }); - }); - num = target ? target.getFriends(true).length : 1; - } + return !player.storage.xinzhengnan || !player.storage.xinzhengnan.includes(event.player); + }, + content: function () { + "step 0"; + if (!player.storage.xinzhengnan) player.storage.xinzhengnan = []; + player.storage.xinzhengnan.add(trigger.player); + player.storage.xinzhengnan.sortBySeat(); + player.markSkill("xinzhengnan"); + player.recover(); + var list = []; + if (!player.hasSkill("new_rewusheng")) { + list.push("new_rewusheng"); + } + if (!player.hasSkill("xindangxian")) { + list.push("xindangxian"); + } + if (!player.hasSkill("rezhiman")) { + list.push("rezhiman"); + } + if (list.length) { + player.draw(); + event.list = list; } else { - num = 1; + player.draw(3); + event.finish(); } - if ((player.getStat().skill.dingpan || 0) >= num) return false; - return true; + "step 1"; + if (event.list.length == 1) event._result = { control: event.list[0] }; + else + player + .chooseControl(event.list) + .set("prompt", "征南:选择获得下列技能中的一个") + .set("ai", function () { + if (event.list.includes("xindangxian")) return "xindangxian"; + return 0; + }); + "step 2"; + if (result.control == "xindangxian") player.storage.xinfuli = true; + player.addSkills(result.control); }, - filterTarget: function (card, player, target) { - return target.countCards("e") > 0; + ai: { threaten: 2.5 }, + intro: { + content: "已因$发动过技能", }, + derivation: ["new_rewusheng", "xindangxian", "rezhiman"], + }, + zhengnan: { + derivation: ["new_rewusheng", "dangxian", "rezhiman"], + audio: 2, + trigger: { global: "dieAfter" }, + frequent: true, content: function () { "step 0"; - target.draw(); + player.draw(3); "step 1"; - var goon = get.damageEffect(target, player, target) >= 0; - if (!goon && target.hp >= 4 && get.attitude(player, target) < 0) { - var es = target.getCards("e"); - for (var i = 0; i < es.length; i++) { - if (get.equipValue(es[i], target) >= 8) { - goon = true; - break; - } - } - } - target - .chooseControl(function () { - if (_status.event.goon) return "选项二"; - return "选项一"; - }) - .set("goon", goon) - .set("prompt", "定叛") - .set("choiceList", ["令" + get.translation(player) + "弃置你装备区里的一张牌", "获得你装备区内的所有牌并受到1点伤害"]); + var list = lib.skill.zhengnan.derivation.filter(skill => !player.hasSkill(skill)); + if (list.length == 1) event._result = { control: list[0] }; + else if (list.length > 0) { + player + .chooseControl(list) + .set("prompt", "选择获得一项技能") + .set("ai", function () { + if (_status.event.controls.includes("dangxian")) return "dangxian"; + return _status.event.controls[0]; + }); + } else event.finish(); "step 2"; - if (result.control == "选项一") { - player.discardPlayerCard(target, true, "e"); - event.finish(); - } else { - target.gain(target.getCards("e"), "gain2"); - } - "step 3"; - game.delay(0.5); - target.damage(); + if (result.control) { + player.addSkills(result.control); + } }, - ai: { - order: 7, - result: { - target: function (player, target) { - if (get.damageEffect(target, player, target) >= 0) return 2; - var att = get.attitude(player, target); - if (att == 0) return 0; - var es = target.getCards("e"); - if (att > 0 && (target.countCards("h") > 2 || target.needsToDiscard(1))) return 0; - if (es.length == 1 && att > 0) return 0; - for (var i = 0; i < es.length; i++) { - var val = get.equipValue(es[i], target); - if (val <= 4) { - if (att > 0) { - return 1; - } - } else if (val >= 7) { - if (att < 0) { - return -1; - } - } - } - return 0; - }, + ai: { threaten: 2 }, + }, + wusheng_guansuo: { audio: 1 }, + dangxian_guansuo: { audio: 1 }, + zhiman_guansuo: { audio: 1 }, + xiefang: { + mod: { + globalFrom: function (from, to, distance) { + return ( + distance - + game.countPlayer(function (current) { + return current.hasSex("female"); + }) + ); }, }, }, - hongde: { + qizhi: { audio: 2, trigger: { - player: ["loseAfter", "gainAfter"], - global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], + player: "useCardToPlayered", }, direct: true, filter: function (event, player) { - var num = event.getl(player).cards2.length; - if (event.getg) num = Math.max(num, event.getg(player).length); - return num > 1; + if (!event.targets) return false; + if (!event.isFirstTarget) return false; + if (_status.currentPhase != player) return false; + var type = get.type(event.card, "trick"); + if (type != "basic" && type != "trick") return false; + if (event.noai) return false; + return game.hasPlayer(function (target) { + return !event.targets.includes(target) && target.countCards("he") > 0; + }); }, content: function () { "step 0"; player - .chooseTarget(get.prompt("hongde"), "令一名其他角色摸一张牌", function (card, player, target) { - return target != player; + .chooseTarget(get.prompt("qizhi"), "弃置一名角色的一张牌,然后其摸一张牌", function (card, player, target) { + return !_status.event.targets.includes(target) && target.countCards("he") > 0; }) .set("ai", function (target) { - return get.attitude(player, target); - }); + var player = _status.event.player; + if (target == player) return 2; + if (get.attitude(player, target) <= 0) { + return 1; + } + return 0.5; + }) + .set("targets", trigger.targets); "step 1"; if (result.bool) { - player.logSkill("hongde", result.targets); - result.targets[0].draw(); + player.getHistory("custom").push({ qizhi: true }); + player.logSkill("qizhi", result.targets); + player.discardPlayerCard(result.targets[0], true, "he"); + event.target = result.targets[0]; + } else { + event.finish(); } + "step 2"; + event.target.draw(); }, }, - ziyuan: { + jinqu: { audio: 2, - enable: "phaseUse", - usable: 1, - filterCard: function (card) { - var num = 0; - for (var i = 0; i < ui.selected.cards.length; i++) { - num += get.number(ui.selected.cards[i]); - } - return get.number(card) + num <= 13; + trigger: { player: "phaseJieshuBegin" }, + check: function (event, player) { + return ( + player.getHistory("custom", function (evt) { + return evt.qizhi == true; + }).length >= player.countCards("h") + ); }, - complexCard: true, - selectCard: function () { - var num = 0; - for (var i = 0; i < ui.selected.cards.length; i++) { - num += get.number(ui.selected.cards[i]); + prompt: function (event, player) { + var num = player.getHistory("custom", function (evt) { + return evt.qizhi == true; + }).length; + return "进趋:是否摸两张牌并将手牌弃置至" + get.cnNumber(num) + "张?"; + }, + content: function () { + "step 0"; + player.draw(2); + "step 1"; + var dh = + player.countCards("h") - + player.getHistory("custom", function (evt) { + return evt.qizhi == true; + }).length; + if (dh > 0) { + player.chooseToDiscard(dh, true); } - if (num == 13) return ui.selected.cards.length; - return ui.selected.cards.length + 2; }, - discard: false, - lose: false, - delay: false, - filterTarget: function (card, player, target) { - return player != target; + ai: { combo: "qizhi" }, + }, + jiaozi: { + audio: 2, + trigger: { player: "damageBegin3", source: "damageBegin1" }, + forced: true, + filter: function (event, player) { + return player.isMaxHandcard(true); }, - check: function (card) { - var num = 0; - for (var i = 0; i < ui.selected.cards.length; i++) { - num += get.number(ui.selected.cards[i]); + content: function () { + trigger.num++; + }, + ai: { presha: true }, + }, + jiqiao: { + audio: 2, + trigger: { player: "phaseUseBegin" }, + direct: true, + filter: function (event, player) { + return player.countCards("he", { type: "equip" }) > 0; + }, + content: function () { + "step 0"; + player + .chooseToDiscard(get.prompt2("jiqiao"), [1, player.countCards("he", { type: "equip" })], "he", function (card) { + return get.type(card) == "equip"; + }) + .set("ai", function (card) { + if (card.name == "bagua") return 10; + return 7 - get.value(card); + }).logSkill = "jiqiao"; + "step 1"; + if (result.bool) { + event.cards = get.cards(2 * result.cards.length); + player.showCards(event.cards); + } else { + event.finish(); } - if (num + get.number(card) == 13) return 9 - get.value(card); - if (ui.selected.cards.length == 0) { - var cards = _status.event.player.getCards("h"); - for (var i = 0; i < cards.length; i++) { - for (var j = i + 1; j < cards.length; j++) { - if (cards[i].number + cards[j].number == 13) { - if (cards[i] == card || cards[j] == card) return 8.5 - get.value(card); - } - } + "step 2"; + var gained = []; + var tothrow = []; + for (var i = 0; i < event.cards.length; i++) { + if (get.type(event.cards[i]) != "equip") { + gained.push(event.cards[i]); + } else { + tothrow.push(event.cards[i]); } } - return 0; + player.gain(gained, "gain2"); + game.cardsDiscard(tothrow); }, - content: function () { - player.give(cards, target, "give"); - target.recover(); + ai: { + threaten: 1.5, + }, + }, + linglong: { + audio: 2, + group: "linglong_bagua", + mod: { + cardUsable: function (card, player, num) { + if (card.name == "sha" && player.hasEmptySlot(1)) return num + 1; + }, + maxHandcard: function (player, num) { + if (!player.hasEmptySlot(3) || !player.hasEmptySlot(4)) return; + return num + 1; + }, + targetInRange: function (card, player, target, now) { + if (!player.hasEmptySlot(5)) return; + var type = get.type(card); + if (type == "trick" || type == "delay") return true; + }, + canBeDiscarded: function (card, source, player) { + if (!player.hasEmptySlot(5)) return; + if (get.position(card) == "e" && get.subtypes(card).some(slot => slot == "equip2" || slot == "equip5")) return false; + }, + /*cardDiscardable:function (card,player){ + if(player.getEquip(5)) return; + if(get.position(card)=='e') return false; + },*/ + }, + }, + linglong_bagua: { + audio: "linglong", + audioname2: { re_jsp_huangyueying: "relinglong" }, + inherit: "bagua_skill", + filter: function (event, player) { + if (!lib.skill.bagua_skill.filter(event, player)) return false; + if (!player.hasEmptySlot(2)) return false; + return true; }, ai: { - order: function (skill, player) { + respondShan: true, + freeShan: true, + skillTagFilter(player, tag, arg) { + if (tag !== "respondShan" && tag !== "freeShan") return; + if (!player.hasEmptySlot(2) || player.hasSkillTag("unequip2")) return false; + if (!arg || !arg.player) return true; if ( - game.hasPlayer(function (current) { - return current.hp < current.maxHp && current != player && get.recoverEffect(current, player, player) > 0; + arg.player.hasSkillTag("unequip", false, { + target: player, }) - ) { - return 10; - } - return 1; + ) + return false; + return true; }, - result: { - player: function (player, target) { - if (get.attitude(player, target) < 0) return -1; - var eff = get.recoverEffect(target, player, player); - if (eff < 0) return 0; - if (eff > 0) { - if (target.hp == 1) return 3; - return 2; + effect: { + target: function (card, player, target) { + if (player == target && get.subtype(card) == "equip2") { + if (get.equipValue(card) <= 7.5) return 0; } - if (player.needsToDiscard()) return 1; - return 0; + if (target.getEquip(2)) return; + return lib.skill.bagua_skill.ai.effect.target.apply(this, arguments); }, }, - threaten: 1.3, }, }, - jugu: { + zhenwei: { audio: 2, - mod: { - maxHandcard: function (player, num) { - return num + player.maxHp; - }, - }, - trigger: { global: "phaseBefore", player: "enterGame" }, - forced: true, - filter: function (event, player) { - return event.name != "phase" || game.phaseNumber == 0; - }, - content: function () { - player.draw(player.maxHp); + audioname: ["re_wenpin"], + trigger: { + global: "useCardToTarget", }, - }, - tuifeng: { - audio: 2, - trigger: { player: "damageEnd" }, direct: true, - notemp: true, filter: function (event, player) { - return player.countCards("he") > 0; + if (player == event.target || player == event.player) return false; + if (!player.countCards("he")) return false; + if (event.targets.length > 1) return false; + if (!event.target) return false; + if (event.target.hp >= player.hp) return false; + + var card = event.card; + if (card.name == "sha") return true; + if (get.color(card) == "black" && get.type(card, "trick") == "trick") return true; + return false; }, content: function () { "step 0"; - player.chooseCard(get.prompt2("tuifeng"), "he", [1, trigger.num]).set("ai", function (card) { - if (card.name == "du") return 20; - return 7 - get.useful(card); + var save = false; + if (get.attitude(player, trigger.target) > 2) { + if (trigger.card.name == "sha") { + if (player.countCards("h", "shan") || player.getEquip(2) || trigger.target.hp == 1 || player.hp > trigger.target.hp + 1) { + if (!trigger.target.countCards("h", "shan") || trigger.target.countCards("h") < player.countCards("h")) { + save = true; + } + } + } else if (trigger.card.name == "juedou" && trigger.target.hp == 1) { + save = true; + } else if (trigger.card.name == "shunshou" && get.attitude(player, trigger.player) < 0 && get.attitude(trigger.player, trigger.target) < 0) { + save = true; + } + } + var next = player.chooseToDiscard("he", get.prompt(event.name, trigger.target), "弃置一张牌,将" + get.translation(trigger.card) + "转移给自己,或令此牌对其无效"); + next.logSkill = [event.name, trigger.target]; + next.set("ai", function (card) { + if (_status.event.aisave) { + return 7 - get.value(card); + } + return 0; }); + next.set("aisave", save); "step 1"; if (result.bool) { - player.logSkill("tuifeng"); - player.addToExpansion(result.cards, player, "give").gaintag.add("tuifeng"); + player + .chooseControl("转移", "失效", function () { + var trigger = _status.event.getTrigger(); + var player = _status.event.player; + if (trigger.card.name == "sha") { + if (player.countCards("h", "shan")) return "转移"; + } else if (trigger.card.name == "juedou") { + if (player.countCards("h", "sha")) return "转移"; + } + return "失效"; + }) + .set("prompt", "将" + get.translation(trigger.card) + "转移给你,或令其失效"); + } else { + event.finish(); + } + "step 2"; + if (result.control == "转移") { + player.draw(); + trigger.getParent().targets.remove(trigger.target); + trigger.getParent().triggeredTargets2.remove(trigger.target); + trigger.getParent().targets.push(player); + trigger.untrigger(); + trigger.player.line(player); + game.delayx(); + } else { + var cards = trigger.cards.filterInD(); + if (cards.length > 0) { + trigger.player.addSkill("zhenwei2"); + trigger.player.addToExpansion(cards, "gain2").gaintag.add("zhenwei2"); + } + trigger.targets.length = 0; + trigger.getParent().triggeredTargets2.length = 0; } }, - onremove: function (player, skill) { - var cards = player.getExpansions(skill); - if (cards.length) player.loseToDiscardpile(cards); + ai: { + threaten: 1.1, }, - marktext: "锋", + }, + zhenwei2: { + audio: false, intro: { content: "expansion", markcount: "expansion", }, - group: "tuifeng2", - ai: { - threaten: 0.8, - maixie: true, - maixie_hp: true, + trigger: { global: "phaseEnd" }, + forced: true, + charlotte: true, + onremove: function (player, skill) { + var cards = player.getExpansions(skill); + if (cards.length) player.loseToDiscardpile(cards); + }, + content: function () { + "step 0"; + var cards = player.getExpansions("zhenwei2"); + if (cards.length) player.gain(cards, "gain2"); + "step 1"; + player.removeSkill("zhenwei2"); }, }, - tuifeng2: { - audio: "tuifeng", + xunzhi: { + audio: 2, trigger: { player: "phaseZhunbeiBegin" }, - forced: true, + locked: false, + init: function (player) { + player.storage.xunzhi = 0; + }, filter: function (event, player) { - return player.getExpansions("tuifeng").length > 0; + var previous = player.getPrevious(); + var next = player.getNext(); + if (previous && next) { + return player.hp != previous.hp && player.hp != next.hp; + } + return false; + }, + check: function (event, player) { + return player.hp >= 3 && player.countCards("h") > player.hp + 1 + player.storage.xunzhi; }, content: function () { - var cards = player.getExpansions("tuifeng"); - player.draw(2 * cards.length); - player.addTempSkill("tuifeng3"); - player.addMark("tuifeng3", cards.length, false); - player.loseToDiscardpile(cards); + player.loseHp(); + player.storage.xunzhi += 2; }, - }, - tuifeng3: { - mod: { - cardUsable: function (card, player, num) { - if (card.name == "sha") return num + player.countMark("tuifeng3"); + mark: true, + intro: { + content: function (storage, player) { + return "手牌上限+" + player.storage.xunzhi; }, }, - onremove: true, - charlotte: true, - }, - weidi: { - available(mode) { - return mode == "identity" || (mode == "versus" && _status.mode == "four"); - }, - init(player) { - const list = []; - const zhu = get.zhu(player); - if (zhu && zhu != player && zhu.skills) { - for (var i = 0; i < zhu.skills.length; i++) { - if (lib.skill[zhu.skills[i]] && lib.skill[zhu.skills[i]].zhuSkill) { - list.push(zhu.skills[i]); - } - } - } - player.addAdditionalSkill("weidi", list); - game.broadcastAll(function (list) { - game.expandSkills(list); - for (var i of list) { - var info = lib.skill[i]; - if (!info) continue; - if (!info.audioname2) info.audioname2 = {}; - info.audioname2.yuanshu = "weidi"; + mod: { + maxHandcard: function (player, num) { + if (typeof player.storage.xunzhi == "number") { + return num + player.storage.xunzhi; } - }, list); - }, - trigger: { global: ["gameStart", "changeSkillsAfter"] }, - forced: true, - audio: 2, - filter: function (event, player) { - const mode = get.mode(); - if (mode != "identity" && (mode != "versus" || _status.mode != "four")) return false; - const zhu = get.zhu(player); - if (!zhu || zhu == player) return false; - if (event.name == "gameStart") return true; - return ( - event.player == zhu && - (event.addSkill.some(skill => { - return lib.skill[skill] && lib.skill[skill].zhuSkill; - }) || - event.addSkill.some(skill => { - return lib.skill[skill] && lib.skill[skill].zhuSkill; - })) - ); - }, - async content(event, trigger, player) { - lib.skill.weidi.init(player); + }, }, }, - zhenlue: { + yawang: { audio: 2, - trigger: { player: "useCard" }, + trigger: { player: "phaseDrawBegin1" }, forced: true, - filter: function (event) { - return get.type(event.card) == "trick"; + filter: function (event, player) { + return !event.numFixed; + }, + check: function (event, player) { + var num = game.countPlayer(function (target) { + return target.hp == player.hp; + }); + if (!player.hasSkill("xunzhi2")) { + var nh = player.countCards("h"); + if (nh > 5) return false; + if (num == 3 && nh > 3) return false; + } + return num >= 3; }, content: function () { - trigger.nowuxie = true; + trigger.changeToZero(); + var num = game.countPlayer(function (target) { + return target.hp == player.hp; + }); + if (num) { + player.draw(num); + } + player.storage.yawang = num; + player.addTempSkill("yawang2"); + }, + ai: { + halfneg: true, }, + }, + yawang2: { mod: { - targetEnabled: function (card, player, target) { - if (get.type(card) == "delay") { - return false; - } + cardEnabled: function (card, player) { + if (_status.currentPhase != player) return; + if (player.countUsed() >= player.storage.yawang) return false; + }, + cardSavable: function (card, player) { + if (_status.currentPhase != player) return; + if (player.countUsed() >= player.storage.yawang) return false; }, }, }, - jianshu: { - audio: 2, - unique: true, - limited: true, - enable: "phaseUse", - animationColor: "thunder", - skillAnimation: "epic", + luoyan_tianxiang: { + inherit: "tianxiang", filter: function (event, player) { - return !player.storage.jianshu && player.countCards("h", { color: "black" }) > 0; + if (!player.storage.xingwu || !player.storage.xingwu.length) return false; + if (player.hasSkill("tianxiang")) return false; + return lib.skill.tianxiang.filter(event, player); }, - init: function (player) { - player.storage.jianshu = false; + }, + luoyan_liuli: { + inherit: "liuli", + filter: function (event, player) { + if (!player.storage.xingwu || !player.storage.xingwu.length) return false; + if (player.hasSkill("liuli")) return false; + return lib.skill.liuli.filter(event, player); }, - filterTarget: function (card, player, target) { - if (target == player) return false; - if (ui.selected.targets.length) { - return ui.selected.targets[0] != target && !ui.selected.targets[0].hasSkillTag("noCompareSource") && target.countCards("h") && !target.hasSkillTag("noCompareTarget"); - } - return true; + }, + luoyan: { + group: ["luoyan_tianxiang", "luoyan_liuli"], + derivation: ["tianxiang", "liuli"], + ai: { + combo: "xingwu", }, - filterCard: { color: "black" }, - mark: true, - discard: false, - lose: false, - delay: false, - check: function (card) { - if (_status.event.player.hp == 1) return 8 - get.value(card); - return 6 - get.value(card); + }, + xingwu: { + audio: 2, + group: ["xingwu_color", "xingwu_color2"], + subSkill: { + color: { + trigger: { player: "phaseZhunbeiBegin" }, + silent: true, + content: function () { + player.storage.xingwu_color = ["black", "red"]; + }, + }, + color2: { + trigger: { player: "useCard" }, + silent: true, + filter: function (event, player) { + return Array.isArray(player.storage.xingwu_color) && _status.currentPhase == player; + }, + content: function () { + player.storage.xingwu_color.remove(get.color(trigger.card)); + }, + }, }, - selectTarget: 2, - multitarget: true, - content: function () { - "step 0"; - player.awakenSkill("jianshu"); - player.storage.jianshu = true; - player.give(cards, targets[0], "give"); - "step 1"; - if (targets[0].canCompare(targets[1])) targets[0].chooseToCompare(targets[1]); - else event.finish(); - "step 2"; - if (result.bool) { - targets[0].chooseToDiscard("he", 2, true); - targets[1].loseHp(); - } else if (result.tie) { - targets[0].loseHp(); - targets[1].loseHp(); - } else { - targets[1].chooseToDiscard("he", 2, true); - targets[0].loseHp(); + trigger: { player: "phaseDiscardBegin" }, + direct: true, + filter: function (event, player) { + if (!player.storage.xingwu_color) return false; + var length = player.storage.xingwu_color.length; + if (length == 0) return false; + var hs = player.getCards("h"); + if (hs.length == 0) return false; + if (length == 2) return true; + var color = player.storage.xingwu_color[0]; + for (var i = 0; i < hs.length; i++) { + if (get.color(hs[i]) == color) return true; } + return false; }, intro: { - content: "limited", + content: "cards", }, - ai: { - expose: 0.4, - order: 4, - result: { - target: function (player, target) { - if (player.hasUnknown()) return 0; - if (ui.selected.targets.length) return -1; - return -0.5; - }, - }, + init: function (player) { + player.storage.xingwu = []; }, - }, - yongdi: { - audio: 2, - audioname: ["xinping"], - unique: true, - limited: true, - trigger: { player: "phaseZhunbeiBegin" }, - animationColor: "thunder", - skillAnimation: "legend", - mark: true, - async cost(event, trigger, player) { - event.result = await player - .chooseTarget(get.prompt2("yongdi"), (card, player, target) => { - if (player === target) return false; - return target.hasSex("male") || target.name == "key_yuri"; + content: function () { + "step 0"; + player + .chooseCard(get.prompt("xingwu"), function (card) { + return _status.event.player.storage.xingwu_color.includes(get.color(card)); }) - .set("ai", target => { - if (!_status.event.goon) return 0; - let player = _status.event.player; - let att = get.attitude(player, target); - if (att <= 1) return 0; - let mode = get.mode(); - if (mode == "identity" || (mode == "versus" && (_status.mode == "four" || _status.mode == "guandu"))) { + .set("ai", function (card) { + var player = _status.event.player; + if (player.storage.xingwu.length == 2) { if ( - target.getStockSkills(true, true).some(i => { - if (target.hasSkill(i)) return false; - let info = get.info(i); - return info && info.zhuSkill; + !game.hasPlayer(function (current) { + return current != player && current.hasSex("male") && get.damageEffect(current, player, player) > 0 && get.attitude(player, current) < 0; }) ) - return att * 2; + return 0; } - return att; - }) - .set("goon", !player.hasUnknown()) - .forResult(); - }, - async content(event, trigger, player) { - player.awakenSkill("yongdi"); - let target = event.targets[0], - mode = get.mode(); - if (mode !== "identity" || player.identity !== "nei") player.addExpose(0.25); - target.gainMaxHp(); - target.recover(); - let skills = target.getStockSkills(true, true).filter(skill => { - if (target.hasSkill(skill)) return false; - let info = get.info(skill); - return info && info.zhuSkill; - }); - if (skills.length) target.addSkills(skills); - }, - }, - regushe: { - audio: "gushe", - enable: "phaseUse", - filterTarget: function (card, player, target) { - return player.canCompare(target); - }, - selectTarget: [1, 3], - filter: function (event, player) { - return player.countMark("regushe") + player.countMark("regushe2") < 7 && player.countCards("h") > 0; - }, - multitarget: true, - multiline: true, - content: function () { - player.addTempSkill("regushe2"); - player.chooseToCompare(targets).callback = lib.skill.regushe.callback; - }, - intro: { - name: "饶舌", - content: "mark", - }, - callback: function () { - "step 0"; - if (event.num1 <= event.num2) { - target.chat(lib.skill.gushe.chat[player.countMark("regushe")]); - game.delay(); - player.addMark("regushe", 1); - if (player.countMark("regushe") >= 7) { - player.die(); - } - } else player.addMark("regushe2", 1, false); - "step 1"; - if (event.num1 <= event.num2) { - player.chooseToDiscard("he", "弃置一张牌,或摸一张牌").set("ai", function () { - return -1; + return 7 - get.value(card); }); - } else event.goto(3); + "step 1"; + if (result.bool) { + player.logSkill("xingwu"); + if (player.storage.xingwu.length < 2) { + player.$give(result.cards, player); + } + player.lose(result.cards, ui.special); + player.storage.xingwu = player.storage.xingwu.concat(result.cards); + player.markSkill("xingwu"); + player.syncStorage("xingwu"); + } else { + event.finish(); + } "step 2"; - if (!result.bool) { - player.draw(); + if (player.storage.xingwu.length == 3) { + player.$throw(player.storage.xingwu); + while (player.storage.xingwu.length) { + player.storage.xingwu.shift().discard(); + } + player.unmarkSkill("xingwu"); + player + .chooseTarget(function (card, player, target) { + return target != player && target.hasSex("male"); + }, "对一名男性角色造成2点伤害并弃置其装备区内的牌") + .set("ai", function (target) { + var player = _status.event.player; + if (get.attitude(player, target) > 0) return -1; + return get.damageEffect(target, player, player) + target.countCards("e") / 2; + }); + } else { + event.finish(); } "step 3"; - if (event.num1 >= event.num2) { - target - .chooseToDiscard("he", "弃置一张牌,或令" + get.translation(player) + "摸一张牌") - .set("ai", function (card) { - if (_status.event.goon) return 6 - get.value(card); - return 0; - }) - .set("goon", get.attitude(target, player) < 0); - } else event.finish(); + if (result.bool) { + var target = result.targets[0]; + target.damage(2); + event.target = target; + player.line(target, "green"); + } else { + event.finish(); + } "step 4"; - if (!result.bool) player.draw(); + if (event.target && event.target.isIn()) { + var es = event.target.getCards("e"); + if (es.length) { + event.target.discard(es); + } + } }, ai: { - order: 7, - result: { - target: function (player, target) { - var num = ui.selected.targets.length + 1; - if (num + player.countMark("regushe") <= 6) return -1; - var hs = player.getCards("h"); - for (var i = 0; i < hs.length; i++) { - if (get.value(hs[i]) <= 6) { - switch (hs[i].number) { - case 13: - return -1; - case 12: - if (player.countMark("regushe") + num <= 8) return -1; - break; - case 11: - if (player.countMark("regushe") + num <= 7) return -1; - break; - default: - if (hs[i].number > 5 && player.countMark("regushe") + num <= 6) return -1; - } - } - } - return 0; - }, - }, + threaten: 1.5, }, - marktext: "饶", - }, - regushe2: { - charlotte: true, - onremove: true, }, - rejici: { - audio: "jici", - trigger: { - player: "compare", - target: "compare", - }, - forced: true, + yinbing: { + trigger: { player: "phaseJieshuBegin" }, + direct: true, + audio: 2, + preHidden: true, filter: function (event, player) { - // if(player!=event.target&&event.iwhile) return false; - return (player == event.player ? event.num1 : event.num2) <= player.countMark("regushe"); + return player.countCards("he", { type: "basic" }) < player.countCards("he"); }, + marktext: "兵", content: function () { - if (player == trigger.target || !trigger.iwhile) { - trigger[player == trigger.player ? "num1" : "num2"] += player.countMark("regushe"); - game.log(player, "的拼点牌点数+" + player.countMark("regushe")); + "step 0"; + player + .chooseCard([1, player.countCards("he") - player.countCards("he", { type: "basic" })], "he", get.prompt("yinbing"), function (card) { + return get.type(card) != "basic"; + }) + .set("ai", function (card) { + return 6 - get.value(card); + }) + .setHiddenSkill("yinbing"); + "step 1"; + if (result.bool) { + player.logSkill("yinbing"); + player.addToExpansion(result.cards, player, "give").gaintag.add("yinbing"); } - game.delayx(); - // var cards=[trigger.card1]; - // if(trigger.cardlist) cards.addArray(trigger.cardlist); - // else cards.push(trigger.card2); - // cards.sort(function(a,b){ - // return get.number(b)-get.number(a); - // }); - // var num=get.number(cards[0]); - // for(var i=1;i trigger.num2) cards.push(trigger.card1); - if (trigger.num1 < trigger.num2) cards.push(trigger.card2); - cards = cards.filterInD(); - if (cards.length) player.gain(cards, "gain2"); }, - group: "rejici2", - ai: { - combo: "regushe", + onremove: function (player, skill) { + var cards = player.getExpansions(skill); + if (cards.length) player.loseToDiscardpile(cards); }, - }, - rejici2: { - audio: "jici", - trigger: { player: "die" }, - forced: true, - forceDie: true, - skillAnimation: true, - animationColor: "water", - filter: function (event, player) { - return event.source && event.source.isIn(); + intro: { + content: "expansion", + markcount: "expansion", }, - logTarget: "source", - content: function () { - var num = 7 - player.countMark("regushe"); - if (num > 0) trigger.source.chooseToDiscard(num, true, "he"); - trigger.source.loseHp(); + ai: { + effect: { + target: function (card, player, target, current) { + if (card.name == "sha" || card.name == "juedou") { + if (current < 0) return 1.2; + } + }, + }, + threaten: function (player, target) { + if (target.getExpansions("yinbing").length) return 2; + return 1; + }, + combo: "juedi", }, - }, - gushe: { - audio: 2, - enable: "phaseUse", - usable: 1, - filterTarget: function (card, player, target) { - return player.canCompare(target); + subSkill: { + discard: { + trigger: { player: "damageEnd" }, + forced: true, + filter: function (event, player) { + return event.card && player.getExpansions("yinbing").length > 0 && (event.card.name == "sha" || event.card.name == "juedou"); + }, + content: function () { + "step 0"; + player.chooseCardButton("移去一张引兵牌", true, player.getExpansions("yinbing")); + "step 1"; + if (result.bool) player.loseToDiscardpile(result.links); + }, + }, }, - selectTarget: [1, 3], + group: "yinbing_discard", + }, + juedi: { + trigger: { player: "phaseZhunbeiBegin" }, filter: function (event, player) { - return player.countCards("h") > 0; + return player.getExpansions("yinbing").length > 0; }, - multitarget: true, - multiline: true, + forced: true, + audio: 2, content: function () { - player.chooseToCompare(targets).callback = lib.skill.gushe.callback; - }, - intro: { - name: "饶舌", - content: "mark", - }, - chat: ["粗鄙之语", "天地不容", "谄谀之臣", "皓首匹夫,苍髯老贼", "二臣贼子", "断脊之犬", "我从未见过有如此厚颜无耻之人!"], - callback: function () { "step 0"; - if (event.num1 <= event.num2) { - target.chat(lib.skill.gushe.chat[player.countMark("gushe")]); - game.delay(); - player.addMark("gushe", 1); - if (player.countMark("gushe") >= 7) { - player.die(); - } - } + player + .chooseTarget(get.prompt2("juedi"), true, function (card, player, target) { + return player.hp >= target.hp; + }) + .set("ai", function (target) { + var player = _status.event.player; + var att = get.attitude(player, target); + if (att < 2) return att - 10; + var num = att / 10; + if (target == player) { + num += player.maxHp - player.countCards("h") + 0.5; + } else { + num += _status.event.n2 * 2; + if (target.isDamaged()) { + if (target.hp == 1) { + num += 3; + } else if (target.hp == 2) { + num += 2; + } else { + num += 0.5; + } + } + } + if (target.hasJudge("lebu")) { + num /= 2; + } + return num; + }) + .set("n2", player.getExpansions("yinbing").length); "step 1"; - if (event.num1 <= event.num2) { - player.chooseToDiscard("he", "弃置一张牌,或摸一张牌").set("ai", function () { - return -1; - }); - } else event.goto(3); - "step 2"; - if (!result.bool) { - player.draw(); + if (result.bool) { + player.line(result.targets[0], "green"); + var cards = player.getExpansions("yinbing"); + if (result.targets[0] == player) { + player.loseToDiscardpile(cards); + var num = player.maxHp - player.countCards("h"); + if (num > 0) player.draw(num); + } else { + var target = result.targets[0]; + target.recover(); + player.give(cards, target, "give"); + target.draw(cards.length); + } } - "step 3"; - if (event.num1 >= event.num2) { - target - .chooseToDiscard("he", "弃置一张牌,或令" + get.translation(player) + "摸一张牌") - .set("ai", function (card) { - if (_status.event.goon) return 6 - get.value(card); - return 0; - }) - .set("goon", get.attitude(target, player) < 0); - } else event.finish(); - "step 4"; - if (!result.bool) player.draw(); }, ai: { - order: 7, - result: { - target: function (player, target) { - var num = ui.selected.targets.length + 1; - if (num > 3) num = 3; - var hs = player.getCards("h"); - for (var i = 0; i < hs.length; i++) { - if (get.value(hs[i]) <= 6) { - switch (hs[i].number) { - case 13: - return -1; - case 12: - if (player.countMark("gushe") + num <= 8) return -1; - break; - case 11: - if (player.countMark("gushe") + num <= 7) return -1; - break; - default: - if (hs[i].number > 5 && player.countMark("gushe") + num <= 6) return -1; - } - } - } - return 0; - }, - }, + combo: "yinbing", }, }, - jici: { - audio: 2, - trigger: { player: "compare" }, + meibu: { + trigger: { global: "phaseUseBegin" }, filter: function (event, player) { - return event.getParent().name == "gushe" && !event.iwhile && event.num1 <= player.countMark("gushe"); + return event.player != player && get.distance(event.player, player, "attack") > 1; }, - content: function () { - if (trigger.num1 < player.countMark("gushe")) { - trigger.num1 += player.countMark("gushe"); - } else { - player.getStat().skill.gushe--; + logTarget: "player", + check: function (event, player) { + if (get.attitude(player, event.player) >= 0) return false; + var e2 = player.getEquip(2); + if (e2) { + if (e2.name == "tengjia" || e2.name == "rewrite_tengjia") return true; + if (e2.name == "bagua" || e2.name == "rewrite_bagua") return true; } + return player.countCards("h", "shan") > 0; + }, + content: function () { + var target = trigger.player; + target.addTempSkill("meibu_viewas"); + target.addTempSkill("meibu_range"); + target.storage.meibu = player; + target.markSkillCharacter("meibu", player, "魅步", "锦囊牌均视为杀且" + get.translation(player) + "视为在攻击范围内"); }, ai: { - combo: "gushe", + expose: 0.2, + }, + subSkill: { + range: { + mod: { + targetInRange: function (card, player, target) { + if (card.name == "sha" && target == player.storage.meibu) { + return true; + } + }, + }, + onremove: function (player) { + game.broadcast(function (player) { + if (player.marks.meibu) { + player.marks.meibu.delete(); + delete player.marks.meibu; + } + }, player); + if (player.marks.meibu) { + player.marks.meibu.delete(); + delete player.marks.meibu; + game.addVideo("unmark", player, "meibu"); + } + }, + trigger: { player: "useCard" }, + forced: true, + popup: false, + filter: function (event, player) { + return event.skill == "meibu_viewas"; + }, + content: function () { + player.removeSkill("meibu_viewas"); + game.broadcastAll(function (player) { + if (player.marks.meibu && player.marks.meibu.info) { + player.marks.meibu.info.content = player.marks.meibu.info.content.slice(8); + } + }, player); + }, + }, + viewas: { + mod: { + cardEnabled: function (card, player) { + if (card.name != "sha" && get.type(card, "trick") == "trick") return false; + }, + cardUsable: function (card, player) { + if (card.name != "sha" && get.type(card, "trick") == "trick") return false; + }, + cardRespondable: function (card, player) { + if (card.name != "sha" && get.type(card, "trick") == "trick") return false; + }, + cardSavable: function (card, player) { + if (card.name != "sha" && get.type(card, "trick") == "trick") return false; + }, + }, + enable: ["chooseToUse", "chooseToRespond"], + filterCard: function (card) { + return get.type(card, "trick") == "trick"; + }, + viewAs: { name: "sha" }, + check: function () { + return 1; + }, + ai: { + effect: { + target: function (card, player, target, current) { + if (get.tag(card, "respondSha") && current < 0) return 0.8; + }, + }, + respondSha: true, + order: 4, + useful: -1, + value: -1, + }, + }, }, }, - juesi: { - audio: 2, + mumu: { enable: "phaseUse", - filter: function (event, player) { - return player.countCards("h", "sha") > 0; + usable: 1, + filterCard: function (card, player, target) { + return card.name == "sha" || (get.type(card, "trick") == "trick" && get.color(card) == "black"); + }, + check: function (card) { + return 7 - get.value(card); }, filterTarget: function (card, player, target) { - return target != player && target.countCards("he") > 0 && player.inRange(target); + if (target == player) return false; + return target.getEquips(1).length > 0 || target.getEquips(2).length > 0; }, - filterCard: { name: "sha" }, content: function () { "step 0"; - target.chooseToDiscard("he", true); + var e1 = target.getEquips(1); + var e2 = target.getEquips(2); + event.e1 = e1; + event.e2 = e2; + if (e1.length && e2.length) { + player.chooseControl("武器牌", "防具牌").set("ai", function () { + if (_status.event.player.getEquip(2)) { + return "武器牌"; + } + return "防具牌"; + }); + } else if (e1.length) { + event.choice = "武器牌"; + } else { + event.choice = "防具牌"; + } "step 1"; - if (target.hp >= player.hp && result.bool && result.cards[0].name != "sha") { - player.useCard({ name: "juedou", isCard: true }, target); + var choice = event.choice || result.control; + if (choice == "武器牌") { + if (event.e1) { + target.discard(event.e1); + } + player.draw(); + } else { + if (event.e2) { + player.equip(event.e2); + target.$give(event.e2, player); + } } }, ai: { - order: 2, + order: 8, result: { target: function (player, target) { - if (get.effect(target, { name: "juedou" }, player, player) <= 0) { - return 0; - } - if (target.hp < player.hp) { - if (player.countCards("h") > player.hp) return -0.1; - return 0; - } - var hs1 = target.getCards("h", "sha"); - var hs2 = player.getCards("h", "sha"); - if (hs1.length > hs2.length) { - return 0; - } - var hsx = target.getCards("h"); - if (hsx.length > 2 && hs2.length <= 1 && hsx[0].number < 6) { - return 0; - } - if (hsx.length > 3 && hs2.length <= 1) { - return 0; - } - if (hs1.length > hs2.length - 1 && hs1.length > 0 && (hs2.length <= 1 || hs1[0].number > hs2[0].number)) { - return 0; + if (target.getEquip(2) && !player.getEquip(2)) { + return -2; } return -1; }, }, }, }, - shefu: { + fentian: { + audio: 2, trigger: { player: "phaseJieshuBegin" }, direct: true, - audio: 2, - init: function (player) { - if (!player.storage.shefu) player.storage.shefu = []; - if (!player.storage.shefu2) player.storage.shefu2 = []; - }, filter: function (event, player) { - return player.countCards("he") > 0; + if (player.countCards("h") >= player.hp) return false; + return game.hasPlayer(function (current) { + return player != current && player.inRange(current) && current.countCards("he"); + }); + }, + intro: { + content: "expansion", + markcount: "expansion", }, onremove: function (player, skill) { var cards = player.getExpansions(skill); if (cards.length) player.loseToDiscardpile(cards); }, - intro: { - content: "cards", - onunmark: function (storage, player) { - player.storage.shefu = []; - player.storage.shefu2 = []; - }, - mark: function (dialog, content, player) { - if (content && content.length) { - dialog.addAuto(content); - if (player.isUnderControl(true)) { - var str = ""; - for (var i = 0; i < player.storage.shefu2.length; i++) { - str += get.translation(player.storage.shefu2[i]); - if (i < player.storage.shefu2.length - 1) { - str += "、"; - } - } - dialog.add('
    ' + str + "
    "); - } - } - }, - }, - content: function () { - "step 0"; - var list1 = [], - list2 = [], - list3 = []; - for (var i = 0; i < lib.inpile.length; i++) { - var type = get.type(lib.inpile[i]); - if (type == "basic") { - list1.push(["基本", "", lib.inpile[i]]); - } else if (type == "trick") { - list2.push(["锦囊", "", lib.inpile[i]]); - } else if (type == "delay") { - list3.push(["锦囊", "", lib.inpile[i]]); - } - } - player - .chooseButton([get.prompt("shefu"), [list1.concat(list2).concat(list3), "vcard"]]) - .set("filterButton", function (button) { - var player = _status.event.player; - if (player.storage.shefu2 && player.storage.shefu2.includes(button.link[2])) return false; - return true; - }) - .set("ai", function (button) { - var rand = _status.event.rand; - switch (button.link[2]) { - case "sha": - return 5 + rand[1]; - case "tao": - return 4 + rand[2]; - case "lebu": - return 3 + rand[3]; - case "shan": - return 4.5 + rand[4]; - case "wuzhong": - return 4 + rand[5]; - case "shunshou": - return 3 + rand[6]; - case "nanman": - return 2 + rand[7]; - case "wanjian": - return 2 + rand[8]; - default: - return rand[0]; - } + content: function () { + "step 0"; + player + .chooseTarget("焚天:选择一名攻击范围内的角色,将其一张牌置于你的武将牌上", true, function (card, player, target) { + return player != target && player.inRange(target) && target.countCards("he") > 0; }) - .set("rand", [Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random()]); + .set("ai", function (target) { + return -get.attitude(_status.event.player, target); + }); "step 1"; if (result.bool) { - event.cardname = result.links[0][2]; - player.logSkill("shefu"); - player.chooseCard("he", "选择一张牌作为“伏兵”", true); + player.logSkill("fentian", result.targets); + event.target = result.targets[0]; + player.choosePlayerCard(result.targets[0], "he", true); } else { event.finish(); } "step 2"; if (result.bool) { - var card = result.cards[0]; - event.card = card; - player.addToExpansion(card, player, "give").gaintag.add("shefu"); - } - "step 3"; - if (player.getExpansions("shefu").includes(event.card)) { - player.storage.shefu.push(card); - player.storage.shefu2.push(event.cardname); - if (player.isOnline2()) { - player.send(function (storage) { - game.me.storage.shefu2 = storage; - }, player.storage.shefu2); - } - player.syncStorage("shefu"); - player.markSkill("shefu"); + player.addToExpansion(result.links, target, "give").gaintag.add("fentian"); } }, - group: ["shefu2"], + mod: { + attackRange: function (from, distance) { + return distance + from.getExpansions("fentian").length; + }, + }, }, - shefu2: { - trigger: { global: ["useCard"] }, - //priority:15, - audio: "shefu", + zhiri: { + trigger: { player: "phaseZhunbeiBegin" }, + forced: true, + unique: true, + juexingji: true, + audio: 2, + skillAnimation: true, + animationColor: "fire", + derivation: "xintan", filter: function (event, player) { - if (_status.currentPhase == player || event.player == player) return false; - return ( - player.storage.shefu2 && - player.storage.shefu2.includes(event.card.name) && - event.player.getHistory("lose", function (evt) { - return evt.getParent() == event && evt.hs && evt.hs.length == event.cards.length; - }).length - ); + return player.getExpansions("fentian").length >= 3; }, - direct: true, content: function () { - "step 0"; - var effect = 0; - if (trigger.card.name == "wuxie" || trigger.card.name == "shan") { - if (get.attitude(player, trigger.player) < -1) { - effect = -1; - } - } else if (trigger.targets && trigger.targets.length) { - for (var i = 0; i < trigger.targets.length; i++) { - effect += get.effect(trigger.targets[i], trigger.card, trigger.player, player); - } - } - var str = "设伏:是否令" + get.translation(trigger.player); - if (trigger.targets && trigger.targets.length) { - str += "对" + get.translation(trigger.targets); - } - str += "使用的" + get.translation(trigger.card) + "失效?"; - var next = player.chooseBool(str, function () { - var player = _status.event.player; - var trigger = _status.event.getTrigger(); - if (_status.event.effect < 0) { - if (trigger.card.name == "sha") { - var target = trigger.targets[0]; - if (target == player) { - return !player.countCards("h", "shan"); - } else { - return target.hp == 1 || (target.countCards("h") <= 2 && target.hp <= 2); - } - } else { - return true; - } - } - return false; - }); - next.set("effect", effect); - "step 1"; - if (result.bool) { - player.logSkill("shefu", trigger.player); - var index = player.storage.shefu2.indexOf(trigger.card.name); - if (index != -1) { - var card = player.storage.shefu[index]; - player.loseToDiscardpile(card); - player.storage.shefu.splice(index, 1); - player.storage.shefu2.splice(index, 1); - if (player.storage.shefu.length == 0) { - player.unmarkSkill("shefu"); - } else { - player.syncStorage("shefu"); - player.markSkill("shefu"); - if (player.isOnline2()) { - player.send(function (storage) { - game.me.storage.shefu2 = storage; - }, player.storage.shefu2); - } - } - } - trigger.targets.length = 0; - trigger.all_excluded = true; - if (trigger.player == _status.currentPhase) trigger.player.addTempSkill("baiban"); - } + player.awakenSkill("zhiri"); + player.loseMaxHp(); + player.storage.zhiri = true; + player.addSkills("xintan"); }, ai: { - threaten: 1.8, - expose: 0.3, + combo: "fentian", }, }, - benyu: { + xintan: { + enable: "phaseUse", + usable: 1, audio: 2, - trigger: { player: "damageEnd" }, + unique: true, filter: function (event, player) { - if (!event.source) return false; - var nh1 = player.countCards("h"); - var nh2 = event.source.countCards("h"); - var eh = player.countCards("e"); - if (nh1 + eh > nh2 && event.source.isIn()) return true; - if (nh1 < Math.min(5, nh2)) return true; + return player.getExpansions("fentian").length >= 2; }, - direct: true, + filterTarget: true, + prompt: "移去两张“焚”并令一名角色失去1点体力", content: function () { "step 0"; - var num1 = player.countCards("h"); - var num2 = trigger.source.countCards("h"); - var eh = player.countCards("he", function (card) { - return lib.filter.cardDiscardable(card, player, "benyu"); - }); - var bool1 = false, - bool2 = false; - if (num1 < Math.min(num2, 5)) bool1 = true; - if (eh > num2 && trigger.source.isIn()) bool2 = true; - if (bool1 && bool2) { - event.chosen = true; - player - .chooseControl("cancel2") - .set("prompt", get.prompt("benyu", trigger.source)) - .set("choiceList", ["将手牌摸至" + get.cnNumber(Math.min(num2, 5)) + "张", "弃置至少" + get.cnNumber(num2 + 1) + "张牌并对其造成1点伤害"]); - } else if (bool2) event.goto(3); + player.chooseCardButton(2, "移去两张“焚”并令" + get.translation(target) + "失去1点体力", player.getExpansions("fentian"), true); "step 1"; - if (event.chosen) { - if (result.control == "cancel2") event.finish(); - else if (result.index == 1) event.goto(3); - else event._result = { bool: true }; - } else player.chooseBool(get.prompt("benyu", trigger.source), "将手牌摸至" + get.cnNumber(Math.min(trigger.source.countCards("h"), 5)) + "张"); - "step 2"; if (result.bool) { - player.logSkill("benyu", trigger.source); - player.drawTo(Math.min(trigger.source.countCards("h"), 5)); - } - event.finish(); - "step 3"; - var num = trigger.source.countCards("h") + 1; - var args = [[num, player.countCards("he")], "he"]; - if (event.chosen) { - player.logSkill("benyu", trigger.source); - args.push(true); - } else { - args.push(get.prompt("benyu", trigger.source)); - args.push("弃置" + get.cnNumber(num) + "张牌并对其造成1点伤害"); + player.loseToDiscardpile(result.links); + target.loseHp(); } - var next = player.chooseToDiscard.apply(player, args); - if (!event.chosen) next.logSkill = ["benyu", trigger.source]; - next.set("ai", function (card) { - var trigger = _status.event.getTrigger(); - var player = _status.event.player; - if (ui.selected.cards.length >= _status.event.num) { - return -1; - } - if (get.damageEffect(trigger.source, player, player) > 0 && (get.value(card, player) < 0 || _status.event.num <= 2)) { - return 8 - get.value(card); - } - return -1; - }); - next.set("num", num); - "step 4"; - if (result.bool) trigger.source.damage(); }, - }, - jili: { - audio: 2, - trigger: { - global: "useCardToTarget", + ai: { + order: 8, + result: { + target: -1, + }, + combo: "fentian", }, + }, + danji: { + skillAnimation: true, + animationColor: "water", + trigger: { player: "phaseZhunbeiBegin" }, forced: true, - check: function (event, player) { - return get.effect(player, event.card, event.player, player) > 0; - }, + unique: true, + juexingji: true, + derivation: ["mashu", "nuzhan"], filter: function (event, player) { - if (get.color(event.card) != "red") return false; - if (!event.targets) return false; - if (event.player == player) return false; - if (event.targets.includes(player)) return false; - if (get.info(event.card).multitarget) return false; - var type = get.type(event.card); - if (type != "basic" && type != "trick") return false; - if (lib.filter.targetEnabled2(event.card, event.player, player)) { - for (var i = 0; i < event.targets.length; i++) { - if (get.distance(event.targets[i], player) <= 1) return true; + var zhu = get.zhu(player); + if (zhu && zhu.isZhu) { + var name = zhu.name; + while (name.indexOf("_") != -1) { + name = name.slice(name.indexOf("_") + 1); } + if (name.indexOf("liubei") == 0) return false; } - return false; + return !player.storage.danji && player.countCards("h") > player.hp; }, - autodelay: true, content: function () { - trigger.getParent().targets.add(player); - trigger.player.line(player, "green"); + player.awakenSkill("danji"); + player.loseMaxHp(); + player.addSkills(["mashu", "nuzhan"]); + }, + ai: { + maixie: true, + skillTagFilter: (player, tag, arg) => { + if (tag === "maixie") { + if (player.hp < 2 || player.storage.danji || player.hasSkill("nuzhan") || player.countCards("h") !== player.hp) return false; + let zhu = get.zhu(player); + if (zhu && zhu.isZhu) { + let name = zhu.name; + while (name.indexOf("_") !== -1) { + name = name.slice(name.indexOf("_") + 1); + } + if (name.indexOf("liubei") == 0) return false; + } + return true; + } + }, + effect: { + target: (card, player, target) => { + let hs = target.countCards("h"); + if (target.hp < 3 || target.storage.danji || target.hasSkill("nuzhan") || hs > target.hp + 1) return; + let zhu = get.zhu(target); + if (zhu && zhu.isZhu) { + let name = zhu.name; + while (name.indexOf("_") !== -1) { + name = name.slice(name.indexOf("_") + 1); + } + if (name.indexOf("liubei") == 0) return; + } + if (get.tag(card, "draw")) return 1.6; + if (get.tag(card, "lose") || get.tag(card, "discard")) return [1, -0.8]; + if (hs === target.hp && get.tag(card, "damage")) return [1, target.hp / 3]; + if (hs > target.hp && target.hp > 3 && (card.name === "shan" || card.name === "wuxie")) return "zeroplayertarget"; + }, + }, }, }, - zhidao: { + nuzhan: { audio: 2, - mod: { - aiOrder: function (player, card, num) { - if (num > 0 && !player.hasSkill("zhidao2") && !get.tag(card, "damage") && (!lib.filter.targetEnabled(card, player, player) || get.effect(player, card, player) <= 0)) return num + 10; - }, - }, - trigger: { source: "damageSource" }, + popup: false, + silent: true, + firstDo: true, + trigger: { player: "useCard1" }, filter: function (event, player) { - if (event._notrigger.includes(event.player)) return false; - return _status.currentPhase == player && event.player.isIn() && event.player.countCards("hej") > 0 && event.player != player && !player.hasSkill("zhidao2"); + return event.card && event.card.name == "sha" && event.addCount !== false && event.cards && event.cards.length == 1 && get.type(event.cards[0], "trick") == "trick"; }, forced: true, content: function () { - var num = 0; - if (trigger.player.countCards("h")) num++; - if (trigger.player.countCards("e")) num++; - if (trigger.player.countCards("j")) num++; - if (num) { - player.gainPlayerCard(trigger.player, num, "hej", true).set("filterButton", function (button) { - for (var i = 0; i < ui.selected.buttons.length; i++) { - if (get.position(button.link) == get.position(ui.selected.buttons[i].link)) return false; - } - return true; - }); + trigger.addCount = false; + if (player.stat[player.stat.length - 1].card.sha > 0) { + player.stat[player.stat.length - 1].card.sha--; } - player.addTempSkill("zhidao2"); }, - }, - zhidao2: { - mod: { - playerEnabled: function (card, player, target) { - if (player != target) return false; - }, + ai: { + combo: "wusheng", }, + group: "nuzhan2", }, - luanzhan: { - mod: { - selectTarget: function (card, player, range) { - if (!player.storage.luanzhan) return; - if (range[1] == -1) return; - if (card.name == "sha") range[1] += player.storage.luanzhan; - if (get.color(card) == "black" && get.type(card) == "trick") { - var info = get.info(card); - if (info.multitarget) return false; - range[1] += player.storage.luanzhan; - } - }, - }, - trigger: { source: "damageSource" }, - audio: 2, + nuzhan2: { + audio: "nuzhan", + trigger: { player: "useCard1" }, forced: true, - mark: true, - intro: { - content: function (storage) { - return "可以额外指定" + storage + "个目标"; - }, - }, - init: function (player) { - player.storage.luanzhan = 0; - }, - init2: function (player) { - player.markSkill("luanzhan"); + popup: false, + silent: true, + firstDo: true, + filter: function (event, player) { + return event.card && event.card.name == "sha" && event.cards && event.cards.length == 1 && get.type(event.cards[0]) == "equip"; }, content: function () { - if (typeof player.storage.luanzhan == "number") { - player.storage.luanzhan += trigger.num; - } else { - player.storage.luanzhan = trigger.num; - } - if (player.hasSkill("luanzhan")) { - player.markSkill("luanzhan"); - } + trigger.baseDamage++; }, - group: "luanzhan_cancel", + }, + jieyuan: { + audio: ["jieyuan_more.mp3", "jieyuan_less.mp3"], + group: ["jieyuan_more", "jieyuan_less"], subSkill: { - cancel: { - audio: "luanzhan", - trigger: { player: "useCard" }, - forced: true, + more: { + audio: true, + trigger: { source: "damageBegin1" }, + direct: true, filter: function (event, player) { - if (!player.storage.luanzhan) return false; - var check = false; - var card = event.card; - if (card.name == "sha") { - check = true; - } else if (get.color(card) == "black" && get.type(card) == "trick") { - var info = get.info(card); - if (!info.multitarget) { - check = true; - if (info.selectTarget == -1) { - check = false; - } else if (Array.isArray(info.selectTarget) && info.selectTarget[1] == -1) { - check = false; - } - } + if ( + !player.countCards(player.hasSkill("fenxin_nei") ? "he" : "h", function (card) { + if (player.hasSkill("fenxin_nei") || (_status.connectMode && get.position(card) == "h")) return true; + return get.color(card) == "black"; + }) + ) + return false; + return (event.player.hp >= player.hp || player.hasSkill("fenxin_fan")) && player != event.player; + }, + content: function () { + "step 0"; + var goon = get.attitude(player, trigger.player) < 0; + var next = player.chooseToDiscard(get.prompt("jieyuan", trigger.player), player.hasSkill("fenxin_nei") ? "he" : "h"); + if (!player.hasSkill("fenxin_nei")) { + next.set("filterCard", function (card) { + return get.color(card) == "black"; + }); + next.set("prompt2", "弃置一张黑色手牌令伤害+1"); + } else { + next.set("prompt2", "弃置一张手牌令伤害+1"); } - if (check && event.targets && event.targets.length < player.storage.luanzhan) { - return true; + next.set("ai", function (card) { + if (_status.event.goon) { + return 8 - get.value(card); + } + return 0; + }); + next.set("goon", goon); + next.logSkill = ["jieyuan_more", trigger.player]; + "step 1"; + if (result.bool) { + trigger.num++; } - return false; }, + }, + less: { + audio: true, + trigger: { player: "damageBegin2" }, + filter: function (event, player) { + if ( + !player.countCards(player.hasSkill("fenxin_nei") ? "he" : "h", function (card) { + if (player.hasSkill("fenxin_nei") || (_status.connectMode && get.position(card) == "h")) return true; + return get.color(card) == "red"; + }) + ) + return false; + return event.source && (event.source.hp >= player.hp || player.hasSkill("fenxin_zhong")) && player != event.source; + }, + direct: true, content: function () { - player.storage.luanzhan = 0; - player.markSkill("luanzhan"); + "step 0"; + var next = player.chooseToDiscard(get.prompt("jieyuan"), player.hasSkill("fenxin_nei") ? "he" : "h"); + if (!player.hasSkill("fenxin_nei")) { + next.set("filterCard", function (card) { + return get.color(card) == "red"; + }); + next.set("prompt2", "弃置一张红色手牌令伤害-1"); + } else { + next.set("prompt2", "弃置一张手牌令伤害-1"); + } + next.set("ai", function (card) { + var player = _status.event.player; + if (player.hp == 1 || _status.event.getTrigger().num > 1) { + return 9 - get.value(card); + } + if (player.hp == 2) { + return 8 - get.value(card); + } + return 7 - get.value(card); + }); + next.logSkill = "jieyuan_less"; + "step 1"; + if (result.bool) { + trigger.num--; + } }, }, }, - }, - xinzhengnan: { - audio: "zhengnan", - trigger: { global: "dying" }, - frequent: true, - filter: function (event, player) { - return !player.storage.xinzhengnan || !player.storage.xinzhengnan.includes(event.player); - }, - content: function () { - "step 0"; - if (!player.storage.xinzhengnan) player.storage.xinzhengnan = []; - player.storage.xinzhengnan.add(trigger.player); - player.storage.xinzhengnan.sortBySeat(); - player.markSkill("xinzhengnan"); - player.recover(); - var list = []; - if (!player.hasSkill("new_rewusheng")) { - list.push("new_rewusheng"); - } - if (!player.hasSkill("xindangxian")) { - list.push("xindangxian"); - } - if (!player.hasSkill("rezhiman")) { - list.push("rezhiman"); - } - if (list.length) { - player.draw(); - event.list = list; - } else { - player.draw(3); - event.finish(); - } - "step 1"; - if (event.list.length == 1) event._result = { control: event.list[0] }; - else - player - .chooseControl(event.list) - .set("prompt", "征南:选择获得下列技能中的一个") - .set("ai", function () { - if (event.list.includes("xindangxian")) return "xindangxian"; - return 0; - }); - "step 2"; - if (result.control == "xindangxian") player.storage.xinfuli = true; - player.addSkills(result.control); - }, - ai: { threaten: 2.5 }, - intro: { - content: "已因$发动过技能", + ai: { + expose: 0.2, + threaten: 1.5, }, - derivation: ["new_rewusheng", "xindangxian", "rezhiman"], }, - zhengnan: { - derivation: ["new_rewusheng", "dangxian", "rezhiman"], - audio: 2, - trigger: { global: "dieAfter" }, - frequent: true, + fenxin: { + mode: ["identity", "versus"], + available: function (mode) { + if (mode == "identity" && _status.mode == "purple") return false; + if (mode == "versus" && _status.mode != "two") return false; + }, + trigger: { global: ["dieAfter", "damageEnd"] }, + filter: function (event, player) { + var list = ["fan", "zhong", "nei"]; + if (get.mode() == "identity") return event.name == "die" && list.includes(event.player.identity) && !player.hasSkill("fenxin_" + event.player.identity); + return event.name == "damage" && event.player != player && list.some(identity => !player.hasSkill("fenxin_" + identity)) && event.player.getAllHistory("damage").indexOf(event) == 0; + }, + forced: true, + logTarget: "player", content: function () { "step 0"; - player.draw(3); - "step 1"; - var list = lib.skill.zhengnan.derivation.filter(skill => !player.hasSkill(skill)); - if (list.length == 1) event._result = { control: list[0] }; - else if (list.length > 0) { + if (get.mode() == "identity") { + event._result = { + bool: true, + links: ["fenxin_" + trigger.player.identity], + }; + } else { player - .chooseControl(list) - .set("prompt", "选择获得一项技能") - .set("ai", function () { - if (_status.event.controls.includes("dangxian")) return "dangxian"; - return _status.event.controls[0]; + .chooseButton( + [ + "焚心:请选择〖竭缘〗的升级方式", + [ + [ + ["fenxin_fan", "发动〖竭缘〗增加伤害无体力值限制"], + ["fenxin_zhong", "发动〖竭缘〗减少伤害无体力值限制"], + ["fenxin_nei", "将〖竭缘〗中的黑色手牌和红色手牌改为一张牌"], + ].filter(list => !player.hasSkill(list[0])), + "textbutton", + ], + ], + true + ) + .set("ai", function (button) { + return ["fenxin_fan", "fenxin_zhong", "fenxin_nei"].indexOf(button.link) + 1; }); - } else event.finish(); - "step 2"; - if (result.control) { - player.addSkills(result.control); + } + "step 1"; + if (result.bool) { + var identity = result.links[0]; + player.addSkill(identity); + player.markSkill("fenxin"); } }, - ai: { threaten: 2 }, + intro: { + mark: function (dialog, content, player) { + if (player.hasSkill("fenxin_zhong")) { + dialog.addText("你发动“竭缘”减少伤害无体力值限制"); + } + if (player.hasSkill("fenxin_fan")) { + dialog.addText("你发动“竭缘”增加伤害无体力值限制"); + } + if (player.hasSkill("fenxin_nei")) { + dialog.addText("将“竭缘”中的黑色手牌和红色手牌改为一张牌"); + } + }, + }, + subSkill: { + fan: { charlotte: true }, + zhong: { charlotte: true }, + nei: { charlotte: true }, + }, + ai: { combo: "jieyuan" }, }, - wusheng_guansuo: { audio: 1 }, - dangxian_guansuo: { audio: 1 }, - zhiman_guansuo: { audio: 1 }, - xiefang: { + xisheng: { + enable: "chooseToUse", + usable: 1, + viewAs: { name: "tao" }, + viewAsFilter: function (player) { + return player != _status.currentPhase && player.countCards("hes") > 1; + }, + selectCard: 2, + filterCard: true, + position: "hes", + }, + shulv: { + inherit: "zhiheng", + prompt: "弃置一张牌并摸一张牌", + selectCard: 1, + filter: function (event, player) { + return player.countCards("hs") > player.hp; + }, + }, + xiandeng: { mod: { - globalFrom: function (from, to, distance) { - return ( - distance - - game.countPlayer(function (current) { - return current.hasSex("female"); - }) - ); + cardUsable: function (card, player, num) { + if (card.name == "sha") return num + 1; + }, + targetInRange: function (card, player) { + if (card.name == "sha" && player.countUsed("sha", true) == 0) return true; }, }, }, - qizhi: { + qingyi: { audio: 2, - trigger: { - player: "useCardToPlayered", - }, + trigger: { player: "phaseJudgeBefore" }, direct: true, - filter: function (event, player) { - if (!event.targets) return false; - if (!event.isFirstTarget) return false; - if (_status.currentPhase != player) return false; - var type = get.type(event.card, "trick"); - if (type != "basic" && type != "trick") return false; - if (event.noai) return false; - return game.hasPlayer(function (target) { - return !event.targets.includes(target) && target.countCards("he") > 0; - }); - }, content: function () { "step 0"; + var check = player.countCards("h") > 2; player - .chooseTarget(get.prompt("qizhi"), "弃置一名角色的一张牌,然后其摸一张牌", function (card, player, target) { - return !_status.event.targets.includes(target) && target.countCards("he") > 0; + .chooseTarget(get.prompt("qingyi"), "跳过判定阶段和摸牌阶段,视为对一名其他角色使用一张【杀】", function (card, player, target) { + if (player == target) return false; + return player.canUse({ name: "sha" }, target, false); }) + .set("check", check) .set("ai", function (target) { - var player = _status.event.player; - if (target == player) return 2; - if (get.attitude(player, target) <= 0) { - return 1; - } - return 0.5; - }) - .set("targets", trigger.targets); + if (!_status.event.check) return 0; + return get.effect(target, { name: "sha" }, _status.event.player); + }); "step 1"; if (result.bool) { - player.getHistory("custom").push({ qizhi: true }); - player.logSkill("qizhi", result.targets); - player.discardPlayerCard(result.targets[0], true, "he"); - event.target = result.targets[0]; - } else { - event.finish(); + player.logSkill("qingyi", result.targets); + player.useCard({ name: "sha", isCard: true }, result.targets[0], false); + trigger.cancel(); + player.skip("phaseDraw"); } - "step 2"; - event.target.draw(); }, }, - jinqu: { - audio: 2, - trigger: { player: "phaseJieshuBegin" }, - check: function (event, player) { - return ( - player.getHistory("custom", function (evt) { - return evt.qizhi == true; - }).length >= player.countCards("h") - ); - }, - prompt: function (event, player) { - var num = player.getHistory("custom", function (evt) { - return evt.qizhi == true; - }).length; - return "进趋:是否摸两张牌并将手牌弃置至" + get.cnNumber(num) + "张?"; - }, + qingyi1: { + audio: true, + trigger: { player: "phaseZhunbeiBegin" }, + direct: true, content: function () { "step 0"; - player.draw(2); + player.addSkill("qingyi3"); + var check = player.countCards("h") > 2; + player.chooseTarget(get.prompt2("qingyi"), function (card, player, target) { + if (player == target) return false; + return player.canUse({ name: "sha" }, target); + }).ai = function (target) { + if (!check) return 0; + return get.effect(target, { name: "sha" }, _status.event.player); + }; "step 1"; - var dh = - player.countCards("h") - - player.getHistory("custom", function (evt) { - return evt.qizhi == true; - }).length; - if (dh > 0) { - player.chooseToDiscard(dh, true); + if (result.bool) { + player.logSkill("qingyi1", result.targets); + player.useCard({ name: "sha", isCard: true }, result.targets[0], false); + player.skip("phaseJudge"); + player.skip("phaseDraw"); } + player.removeSkill("qingyi3"); }, - ai: { combo: "qizhi" }, - }, - jiaozi: { - audio: 2, - trigger: { player: "damageBegin3", source: "damageBegin1" }, - forced: true, - filter: function (event, player) { - return player.isMaxHandcard(true); - }, - content: function () { - trigger.num++; - }, - ai: { presha: true }, }, - jiqiao: { - audio: 2, - trigger: { player: "phaseUseBegin" }, + qingyi2: { + audio: true, + trigger: { player: "phaseUseBefore" }, direct: true, filter: function (event, player) { return player.countCards("he", { type: "equip" }) > 0; }, content: function () { "step 0"; - player - .chooseToDiscard(get.prompt2("jiqiao"), [1, player.countCards("he", { type: "equip" })], "he", function (card) { - return get.type(card) == "equip"; - }) - .set("ai", function (card) { - if (card.name == "bagua") return 10; - return 7 - get.value(card); - }).logSkill = "jiqiao"; + player.addSkill("qingyi3"); + var check = player.countCards("h") <= player.hp; + player.chooseCardTarget({ + prompt: get.prompt2("qingyi"), + filterCard: function (card, player) { + return get.type(card) == "equip" && lib.filter.cardDiscardable(card, player); + }, + position: "he", + filterTarget: function (card, player, target) { + if (player == target) return false; + return player.canUse({ name: "sha" }, target); + }, + ai1: function (card) { + if (!_status.event.check) return 0; + return 6 - get.value(card); + }, + ai2: function (target) { + if (!_status.event.check) return 0; + return get.effect(target, { name: "sha" }, _status.event.player); + }, + check: check, + }); "step 1"; if (result.bool) { - event.cards = get.cards(2 * result.cards.length); - player.showCards(event.cards); - } else { - event.finish(); - } - "step 2"; - var gained = []; - var tothrow = []; - for (var i = 0; i < event.cards.length; i++) { - if (get.type(event.cards[i]) != "equip") { - gained.push(event.cards[i]); - } else { - tothrow.push(event.cards[i]); - } + player.logSkill("qingyi2", result.targets); + player.discard(result.cards[0]); + player.useCard({ name: "sha", isCard: true }, result.targets[0]); + trigger.cancel(); } - player.gain(gained, "gain2"); - game.cardsDiscard(tothrow); - }, - ai: { - threaten: 1.5, + player.removeSkill("qingyi3"); }, }, - linglong: { - audio: 2, - group: "linglong_bagua", + qingyi3: { mod: { - cardUsable: function (card, player, num) { - if (card.name == "sha" && player.hasEmptySlot(1)) return num + 1; - }, - maxHandcard: function (player, num) { - if (!player.hasEmptySlot(3) || !player.hasEmptySlot(4)) return; - return num + 1; - }, targetInRange: function (card, player, target, now) { - if (!player.hasEmptySlot(5)) return; - var type = get.type(card); - if (type == "trick" || type == "delay") return true; - }, - canBeDiscarded: function (card, source, player) { - if (!player.hasEmptySlot(5)) return; - if (get.position(card) == "e" && get.subtypes(card).some(slot => slot == "equip2" || slot == "equip5")) return false; + return true; }, - /*cardDiscardable:function (card,player){ - if(player.getEquip(5)) return; - if(get.position(card)=='e') return false; - },*/ }, }, - linglong_bagua: { - audio: "linglong", - audioname2: { re_jsp_huangyueying: "relinglong" }, - inherit: "bagua_skill", - filter: function (event, player) { - if (!lib.skill.bagua_skill.filter(event, player)) return false; - if (!player.hasEmptySlot(2)) return false; - return true; + qirang: { + audio: 2, + trigger: { player: "equipEnd" }, + frequent: true, + content: function () { + var card = get.cardPile(function (card) { + return get.type(card, "trick") == "trick"; + }); + if (card) { + var next = player.gain(card, "gain2"); + if (get.type(card) == "trick") next.gaintag.add("qirang"); + else { + player.addMark("qirang_mark", 1, false); + player.addTempSkill("qirang_mark", { player: "phaseBegin" }); + } + } }, ai: { - respondShan: true, - freeShan: true, - skillTagFilter(player, tag, arg) { - if (tag !== "respondShan" && tag !== "freeShan") return; - if (!player.hasEmptySlot(2) || player.hasSkillTag("unequip2")) return false; - if (!arg || !arg.player) return true; - if ( - arg.player.hasSkillTag("unequip", false, { - target: player, - }) - ) - return false; - return true; - }, effect: { - target: function (card, player, target) { - if (player == target && get.subtype(card) == "equip2") { - if (get.equipValue(card) <= 7.5) return 0; + target: function (card, player, target, current) { + if (get.type(card) == "equip" && !get.cardtag(card, "gifts")) return [1, 3]; + }, + }, + threaten: 1.3, + }, + group: "qirang_use", + subSkill: { + mark: { + charlotte: true, + onremove: function (player) { + var evt = _status.event; + if (evt.name != "phase") evt = evt.getParent("phase"); + if (evt && evt.player == player) { + if (!evt.qirang_num) evt.qirang_num = 0; + evt.qirang_num += player.storage.qirang_mark; + } + delete player.storage.qirang_mark; + }, + intro: { + content: "下回合发动〖羽化〗时卜算量+#", + }, + }, + use: { + audio: "qirang", + trigger: { player: "useCard2" }, + direct: true, + filter: function (event, player) { + if (get.type(event.card) != "trick") return false; + if (!event.targets || event.targets.length != 1) return false; + var info = get.info(event.card); + if (info.allowMultiple == false) return false; + if ( + !player.hasHistory("lose", function (evt) { + if (evt.getParent() != event) return false; + for (var i in evt.gaintag_map) { + if (evt.gaintag_map[i].includes("qirang")) return true; + } + return false; + }) + ) + return false; + if (!info.multitarget) { + if ( + game.hasPlayer(function (current) { + return !event.targets.includes(current) && lib.filter.targetEnabled2(event.card, player, current) && lib.filter.targetInRange(event.card, player, current); + }) + ) { + return true; + } + } + return false; + }, + content: function () { + "step 0"; + var prompt2 = "为" + get.translation(trigger.card) + "增加一个目标"; + player + .chooseTarget(get.prompt("qirang"), function (card, player, target) { + var player = _status.event.player; + if (_status.event.targets.includes(target)) return false; + return lib.filter.targetEnabled2(_status.event.card, player, target) && lib.filter.targetInRange(_status.event.card, player, target); + }) + .set("prompt2", prompt2) + .set("ai", function (target) { + var trigger = _status.event.getTrigger(); + var player = _status.event.player; + return get.effect(target, trigger.card, player, player) * (_status.event.targets.includes(target) ? -1 : 1); + }) + .set("targets", trigger.targets) + .set("card", trigger.card); + "step 1"; + if (result.bool) { + if (!event.isMine() && !event.isOnline()) game.delayx(); + event.targets = result.targets; + } else { + event.finish(); + } + "step 2"; + if (event.targets) { + player.logSkill("qirang_use", event.targets); + trigger.targets.addArray(event.targets); } - if (target.getEquip(2)) return; - return lib.skill.bagua_skill.ai.effect.target.apply(this, arguments); }, }, }, }, - zhenwei: { + yuhua: { + trigger: { player: ["phaseZhunbeiBegin", "phaseJieshuBegin"] }, + forced: true, audio: 2, - audioname: ["re_wenpin"], - trigger: { - global: "useCardToTarget", + content: function () { + "step 0"; + var num = 1, + evt = trigger.getParent(); + if (evt.qirang_num) num += evt.qirang_num; + var cards = get.cards(Math.min(5, num)); + game.cardsGotoOrdering(cards); + var next = player.chooseToMove(); + next.set("list", [["牌堆顶", cards], ["牌堆底"]]); + next.set("prompt", "羽化:点击或拖动将牌移动到牌堆顶或牌堆底"); + next.processAI = function (list) { + var cards = list[0][1], + player = _status.event.player; + var target = _status.event.getTrigger().name == "phaseZhunbei" ? player : player.next; + var att = get.sgn(get.attitude(player, target)); + var top = []; + var judges = target.getCards("j"); + var stopped = false; + if (player != target || !target.hasWuxie()) { + for (var i = 0; i < judges.length; i++) { + var judge = get.judge(judges[i]); + cards.sort(function (a, b) { + return (judge(b) - judge(a)) * att; + }); + if (judge(cards[0]) * att < 0) { + stopped = true; + break; + } else { + top.unshift(cards.shift()); + } + } + } + var bottom; + if (!stopped) { + cards.sort(function (a, b) { + return (get.value(b, player) - get.value(a, player)) * att; + }); + while (cards.length) { + if (get.value(cards[0], player) <= 5 == att > 0) break; + top.unshift(cards.shift()); + } + } + bottom = cards; + return [top, bottom]; + }; + "step 1"; + var top = result.moved[0]; + var bottom = result.moved[1]; + top.reverse(); + for (var i = 0; i < top.length; i++) { + ui.cardPile.insertBefore(top[i], ui.cardPile.firstChild); + } + for (i = 0; i < bottom.length; i++) { + ui.cardPile.appendChild(bottom[i]); + } + if (event.triggername == "phaseZhunbeiBegin" && top.length == 0) { + player.addTempSkill("reguanxing_on"); + } + player.popup(get.cnNumber(top.length) + "上" + get.cnNumber(bottom.length) + "下"); + game.log(player, "将" + get.cnNumber(top.length) + "张牌置于牌堆顶"); + game.updateRoundNumber(); + game.delayx(); }, - direct: true, + mod: { + ignoredHandcard: function (card, player) { + if (get.type(card) != "basic") { + return true; + } + }, + cardDiscardable: function (card, player, name) { + if (name == "phaseDiscard" && get.type(card) != "basic") return false; + }, + }, + }, + chenqing: { + audio: 2, + trigger: { global: "dying" }, + //priority:6, filter: function (event, player) { - if (player == event.target || player == event.player) return false; - if (!player.countCards("he")) return false; - if (event.targets.length > 1) return false; - if (!event.target) return false; - if (event.target.hp >= player.hp) return false; - - var card = event.card; - if (card.name == "sha") return true; - if (get.color(card) == "black" && get.type(card, "trick") == "trick") return true; - return false; + return event.player.hp <= 0 && !player.hasSkill("chenqing2"); }, + direct: true, content: function () { "step 0"; - var save = false; - if (get.attitude(player, trigger.target) > 2) { - if (trigger.card.name == "sha") { - if (player.countCards("h", "shan") || player.getEquip(2) || trigger.target.hp == 1 || player.hp > trigger.target.hp + 1) { - if (!trigger.target.countCards("h", "shan") || trigger.target.countCards("h") < player.countCards("h")) { - save = true; - } + player + .chooseTarget(get.prompt2("chenqing"), function (card, player, target) { + return target != player && target != _status.event.getTrigger().player; + }) + .set("ai", function (target) { + var player = _status.event.player; + var trigger = _status.event.getTrigger(); + if (get.attitude(player, trigger.player) > 0) { + var att1 = get.attitude(target, player); + var att2 = get.attitude(target, trigger.player); + var att3 = get.attitude(player, target); + if (att3 < 0) return 0; + return att1 / 2 + att2 + att3; + } else { + return 0; + // return get.attitude(player,target); } - } else if (trigger.card.name == "juedou" && trigger.target.hp == 1) { - save = true; - } else if (trigger.card.name == "shunshou" && get.attitude(player, trigger.player) < 0 && get.attitude(trigger.player, trigger.target) < 0) { - save = true; - } - } - var next = player.chooseToDiscard("he", get.prompt(event.name, trigger.target), "弃置一张牌,将" + get.translation(trigger.card) + "转移给自己,或令此牌对其无效"); - next.logSkill = [event.name, trigger.target]; - next.set("ai", function (card) { - if (_status.event.aisave) { - return 7 - get.value(card); - } - return 0; - }); - next.set("aisave", save); + }); "step 1"; if (result.bool) { - player - .chooseControl("转移", "失效", function () { - var trigger = _status.event.getTrigger(); - var player = _status.event.player; - if (trigger.card.name == "sha") { - if (player.countCards("h", "shan")) return "转移"; - } else if (trigger.card.name == "juedou") { - if (player.countCards("h", "sha")) return "转移"; - } - return "失效"; - }) - .set("prompt", "将" + get.translation(trigger.card) + "转移给你,或令其失效"); + player.addTempSkill("chenqing2", "roundStart"); + event.target = result.targets[0]; + event.target.draw(4); + player.logSkill("chenqing", event.target); } else { event.finish(); } "step 2"; - if (result.control == "转移") { - player.draw(); - trigger.getParent().targets.remove(trigger.target); - trigger.getParent().triggeredTargets2.remove(trigger.target); - trigger.getParent().targets.push(player); - trigger.untrigger(); - trigger.player.line(player); - game.delayx(); - } else { - var cards = trigger.cards.filterInD(); - if (cards.length > 0) { - trigger.player.addSkill("zhenwei2"); - trigger.player.addToExpansion(cards, "gain2").gaintag.add("zhenwei2"); + var target = event.target; + var tosave = trigger.player; + var att = get.attitude(target, tosave); + var hastao = target.countCards("h", "tao"); + target + .chooseToDiscard(4, true, "he") + .set("ai", function (card) { + var hastao = _status.event.hastao; + var att = _status.event.att; + if (!hastao && att > 0) { + var suit = get.suit(card); + for (var i = 0; i < ui.selected.cards.length; i++) { + if (get.suit(ui.selected.cards[i]) == suit) { + return -4 - get.value(card); + } + } + } + if (att < 0 && ui.selected.cards.length == 3) { + var suit = get.suit(card); + for (var i = 0; i < ui.selected.cards.length; i++) { + if (get.suit(ui.selected.cards[i]) == suit) { + return -get.value(card); + } + } + return -10 - get.value(card); + } + return -get.value(card); + }) + .set("hastao", hastao) + .set("att", att); + "step 3"; + if (result.cards && result.cards.length == 4) { + var suits = []; + for (var i = 0; i < result.cards.length; i++) { + suits.add(get.suit(result.cards[i])); + } + if (suits.length == 4 && game.checkMod({ name: "tao", isCard: true }, player, trigger.player, "unchanged", "cardSavable", player)) { + event.target.useCard({ name: "tao", isCard: true }, trigger.player); } - trigger.targets.length = 0; - trigger.getParent().triggeredTargets2.length = 0; } }, ai: { - threaten: 1.1, + expose: 0.2, + threaten: 1.5, }, }, - zhenwei2: { - audio: false, - intro: { - content: "expansion", - markcount: "expansion", - }, - trigger: { global: "phaseEnd" }, - forced: true, - charlotte: true, - onremove: function (player, skill) { - var cards = player.getExpansions(skill); - if (cards.length) player.loseToDiscardpile(cards); + mozhi: { + audio: 2, + trigger: { player: "phaseJieshuBegin" }, + direct: true, + filter: function (event, player) { + return ( + player.getHistory("useCard", function (evt) { + return evt.isPhaseUsing() && ["basic", "trick"].includes(get.type(evt.card)); + }).length > 0 && player.countCards("hs") > 0 + ); }, content: function () { "step 0"; - var cards = player.getExpansions("zhenwei2"); - if (cards.length) player.gain(cards, "gain2"); + event.count = 2; + event.history = player.getHistory("useCard", function (evt) { + return evt.isPhaseUsing() && ["basic", "trick"].includes(get.type(evt.card)); + }); "step 1"; - player.removeSkill("zhenwei2"); - }, - }, - xunzhi: { - audio: 2, - trigger: { player: "phaseZhunbeiBegin" }, - locked: false, - init: function (player) { - player.storage.xunzhi = 0; - }, - filter: function (event, player) { - var previous = player.getPrevious(); - var next = player.getNext(); - if (previous && next) { - return player.hp != previous.hp && player.hp != next.hp; + event._result = {}; + if (event.count && event.history.length && player.countCards("hs")) { + event.count--; + var card = event.history.shift().card; + card = { name: card.name, nature: card.nature }; + if (player.hasUseTarget(card, true, true)) { + if ( + game.hasPlayer(function (current) { + return player.canUse(card, current); + }) + ) { + lib.skill.mozhix.viewAs = card; + var next = player.chooseToUse(); + if (next.isOnline()) { + player.send(function (card) { + lib.skill.mozhix.viewAs = card; + }, card); + } + next.logSkill = "mozhi"; + next.set("openskilldialog", "默识:将一张手牌当" + get.translation(card) + "使用"); + next.set("norestore", true); + next.set("_backupevent", "mozhix"); + next.set("custom", { + add: {}, + replace: { window: function () {} }, + }); + next.backup("mozhix"); + } + } } - return false; - }, - check: function (event, player) { - return player.hp >= 3 && player.countCards("h") > player.hp + 1 + player.storage.xunzhi; - }, - content: function () { - player.loseHp(); - player.storage.xunzhi += 2; - }, - mark: true, - intro: { - content: function (storage, player) { - return "手牌上限+" + player.storage.xunzhi; - }, + "step 2"; + if (result && result.bool) event.goto(1); }, - mod: { - maxHandcard: function (player, num) { - if (typeof player.storage.xunzhi == "number") { - return num + player.storage.xunzhi; - } - }, + }, + mozhix: { + filterCard: function (card) { + return get.itemtype(card) == "card"; }, + selectCard: 1, + position: "hs", + popname: true, }, - yawang: { + chenqing2: { charlotte: true }, + ranshang: { audio: 2, - trigger: { player: "phaseDrawBegin1" }, - forced: true, + trigger: { player: "damageEnd" }, filter: function (event, player) { - return !event.numFixed; + return event.hasNature("fire"); }, - check: function (event, player) { - var num = game.countPlayer(function (target) { - return target.hp == player.hp; - }); - if (!player.hasSkill("xunzhi2")) { - var nh = player.countCards("h"); - if (nh > 5) return false; - if (num == 3 && nh > 3) return false; - } - return num >= 3; + forced: true, + check: function () { + return false; }, content: function () { - trigger.changeToZero(); - var num = game.countPlayer(function (target) { - return target.hp == player.hp; - }); - if (num) { - player.draw(num); - } - player.storage.yawang = num; - player.addTempSkill("yawang2"); + player.addMark("ranshang", trigger.num); }, - ai: { - halfneg: true, + intro: { + name2: "燃", + content: "mark", }, - }, - yawang2: { - mod: { - cardEnabled: function (card, player) { - if (_status.currentPhase != player) return; - if (player.countUsed() >= player.storage.yawang) return false; - }, - cardSavable: function (card, player) { - if (_status.currentPhase != player) return; - if (player.countUsed() >= player.storage.yawang) return false; + ai: { + neg: true, + effect: { + target: function (card, player, target, current) { + if (card.name == "sha") { + if (game.hasNature(card, "fire") || player.hasSkill("zhuque_skill")) return 2; + } + if (get.tag(card, "fireDamage") && current < 0) return 2; + }, }, }, + group: "ranshang2", }, - luoyan_tianxiang: { - inherit: "tianxiang", + ranshang2: { + audio: 2, + trigger: { player: "phaseJieshuBegin" }, + forced: true, filter: function (event, player) { - if (!player.storage.xingwu || !player.storage.xingwu.length) return false; - if (player.hasSkill("tianxiang")) return false; - return lib.skill.tianxiang.filter(event, player); + return player.countMark("ranshang") > 0; + }, + content: function () { + player.loseHp(player.countMark("ranshang")); + if (player.countMark("ranshang") > 2) { + player.loseMaxHp(2); + player.draw(2); + } }, }, - luoyan_liuli: { - inherit: "liuli", + hanyong: { + trigger: { player: "useCard" }, filter: function (event, player) { - if (!player.storage.xingwu || !player.storage.xingwu.length) return false; - if (player.hasSkill("liuli")) return false; - return lib.skill.liuli.filter(event, player); + return event.card && (event.card.name == "nanman" || event.card.name == "wanjian" || (event.card.name == "sha" && !game.hasNature(event.card) && get.suit(event.card) == "spade")) && player.isDamaged(); + }, + content: function () { + trigger.baseDamage++; + if (game.roundNumber <= player.hp) player.addMark("ranshang", 1); }, }, - luoyan: { - group: ["luoyan_tianxiang", "luoyan_liuli"], - ai: { - combo: "xingwu", + hanyong3: { + audio: false, + trigger: { source: "damageBegin1" }, + forced: true, + onremove: true, + filter: function (event, player) { + return event.card == player.storage.hanyong3; + }, + content: function () { + trigger.num++; }, }, - xingwu: { + yishe: { audio: 2, - group: ["xingwu_color", "xingwu_color2"], + trigger: { player: "phaseJieshuBegin" }, + filter: function (event, player) { + return !player.getExpansions("yishe").length; + }, + intro: { + content: "expansion", + markcount: "expansion", + }, + content: function () { + "step 0"; + player.draw(2); + "step 1"; + var cards = player.getCards("he"); + if (!cards.length) event.finish(); + else if (cards.length <= 2) event._result = { bool: true, cards: cards }; + else player.chooseCard(2, "he", true, "选择两张牌作为“米”"); + "step 2"; + if (result.bool) player.addToExpansion(result.cards, player, "give").gaintag.add("yishe"); + }, + group: "yishe_recover", + ai: { combo: "bushi" }, subSkill: { - color: { - trigger: { player: "phaseZhunbeiBegin" }, - silent: true, - content: function () { - player.storage.xingwu_color = ["black", "red"]; + recover: { + audio: "yishe", + trigger: { + player: ["loseAfter"], + global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], }, - }, - color2: { - trigger: { player: "useCard" }, - silent: true, filter: function (event, player) { - return Array.isArray(player.storage.xingwu_color) && _status.currentPhase == player; + if (player.isHealthy()) return false; + var evt = event.getl(player); + if (!evt || !evt.xs || !evt.xs.length || player.getExpansions("yishe").length > 0) return false; + if (event.name == "lose") { + for (var i in event.gaintag_map) { + if (event.gaintag_map[i].includes("yishe")) return true; + } + return false; + } + return player.hasHistory("lose", function (evt) { + if (event != evt.getParent()) return false; + for (var i in evt.gaintag_map) { + if (evt.gaintag_map[i].includes("yishe")) return true; + } + return false; + }); }, + forced: true, content: function () { - player.storage.xingwu_color.remove(get.color(trigger.card)); + player.recover(); }, }, }, - trigger: { player: "phaseDiscardBegin" }, - direct: true, + }, + bushi: { + audio: 2, + trigger: { player: "damageEnd", source: "damageEnd" }, filter: function (event, player) { - if (!player.storage.xingwu_color) return false; - var length = player.storage.xingwu_color.length; - if (length == 0) return false; - var hs = player.getCards("h"); - if (hs.length == 0) return false; - if (length == 2) return true; - var color = player.storage.xingwu_color[0]; - for (var i = 0; i < hs.length; i++) { - if (get.color(hs[i]) == color) return true; - } - return false; + if (event._notrigger.includes(event.player)) return false; + return event.player.isIn() && player.getExpansions("yishe").length > 0; }, - intro: { - content: "cards", + direct: true, + content: function () { + "step 0"; + event.count = trigger.num; + "step 1"; + trigger.player.chooseCardButton("选择获得一张“米”", player.getExpansions("yishe")); + "step 2"; + if (result.bool) { + event.count--; + player.logSkill("bushi", trigger.player); + trigger.player.gain(result.links[0], "give", player, "bySelf"); + } else event.finish(); + "step 3"; + if (event.count > 0 && player.getExpansions("yishe").length && player.hasSkill("bushi")) { + event.goto(1); + } }, - init: function (player) { - player.storage.xingwu = []; + ai: { combo: "yishe" }, + }, + midao: { + audio: 2, + trigger: { global: "judge" }, + direct: true, + filter: function (event, player) { + return player.getExpansions("yishe").length && event.player.isIn(); }, content: function () { "step 0"; + var list = player.getExpansions("yishe"); player - .chooseCard(get.prompt("xingwu"), function (card) { - return _status.event.player.storage.xingwu_color.includes(get.color(card)); + .chooseButton([get.translation(trigger.player) + "的" + (trigger.judgestr || "") + "判定为" + get.translation(trigger.player.judging[0]) + "," + get.prompt("midao"), list, "hidden"], function (button) { + var card = button.link; + var trigger = _status.event.getTrigger(); + var player = _status.event.player; + var judging = _status.event.judging; + var result = trigger.judge(card) - trigger.judge(judging); + var attitude = get.attitude(player, trigger.player); + return result * attitude; }) - .set("ai", function (card) { + .set("judging", trigger.player.judging[0]) + .set("filterButton", function (button) { var player = _status.event.player; - if (player.storage.xingwu.length == 2) { - if ( - !game.hasPlayer(function (current) { - return current != player && current.hasSex("male") && get.damageEffect(current, player, player) > 0 && get.attitude(player, current) < 0; - }) - ) - return 0; - } - return 7 - get.value(card); + var card = button.link; + var mod2 = game.checkMod(card, player, "unchanged", "cardEnabled2", player); + if (mod2 != "unchanged") return mod2; + var mod = game.checkMod(card, player, "unchanged", "cardRespondable", player); + if (mod != "unchanged") return mod; + return true; }); "step 1"; if (result.bool) { - player.logSkill("xingwu"); - if (player.storage.xingwu.length < 2) { - player.$give(result.cards, player); - } - player.lose(result.cards, ui.special); - player.storage.xingwu = player.storage.xingwu.concat(result.cards); - player.markSkill("xingwu"); - player.syncStorage("xingwu"); + event.forceDie = true; + player.respond(result.links, "midao", "highlight", "noOrdering"); + result.cards = result.links; + var card = result.cards[0]; + event.card = card; } else { event.finish(); } "step 2"; - if (player.storage.xingwu.length == 3) { - player.$throw(player.storage.xingwu); - while (player.storage.xingwu.length) { - player.storage.xingwu.shift().discard(); - } - player.unmarkSkill("xingwu"); - player - .chooseTarget(function (card, player, target) { - return target != player && target.hasSex("male"); - }, "对一名男性角色造成2点伤害并弃置其装备区内的牌") - .set("ai", function (target) { - var player = _status.event.player; - if (get.attitude(player, target) > 0) return -1; - return get.damageEffect(target, player, player) + target.countCards("e") / 2; - }); - } else { - event.finish(); - } - "step 3"; if (result.bool) { - var target = result.targets[0]; - target.damage(2); - event.target = target; - player.line(target, "green"); - } else { - event.finish(); - } - "step 4"; - if (event.target && event.target.isIn()) { - var es = event.target.getCards("e"); - if (es.length) { - event.target.discard(es); + if (trigger.player.judging[0].clone) { + trigger.player.judging[0].clone.classList.remove("thrownhighlight"); + game.broadcast(function (card) { + if (card.clone) { + card.clone.classList.remove("thrownhighlight"); + } + }, trigger.player.judging[0]); + game.addVideo("deletenode", player, get.cardsInfo([trigger.player.judging[0].clone])); } + game.cardsDiscard(trigger.player.judging[0]); + trigger.player.judging[0] = result.cards[0]; + trigger.orderingCards.addArray(result.cards); + game.log(trigger.player, "的判定牌改为", card); + game.delay(2); } }, ai: { - threaten: 1.5, + combo: "yishe", + rejudge: true, + tag: { + rejudge: 0.6, + }, }, }, - yinbing: { - trigger: { player: "phaseJieshuBegin" }, - direct: true, + fengpo: { audio: 2, - preHidden: true, + trigger: { + player: "useCardToPlayered", + }, filter: function (event, player) { - return player.countCards("he", { type: "basic" }) < player.countCards("he"); + if (event.targets.length != 1 || !["sha", "juedou"].includes(event.card.name)) return false; + var evtx = event.getParent(); + return !player.hasHistory( + "useCard", + function (evt) { + return evt != evtx && evt.card.name == event.card.name; + }, + evtx + ); }, - marktext: "兵", + direct: true, content: function () { "step 0"; + var str1 = get.translation(trigger.card), + str2 = get.translation(trigger.target); player - .chooseCard([1, player.countCards("he") - player.countCards("he", { type: "basic" })], "he", get.prompt("yinbing"), function (card) { - return get.type(card) != "basic"; - }) - .set("ai", function (card) { - return 6 - get.value(card); - }) - .setHiddenSkill("yinbing"); + .chooseControl("摸X加1伤", "摸1加X伤", "cancel2") + .set("prompt", get.prompt("fengpo", trigger.target)) + .set("prompt2", "你可以选择一项:1.摸X张牌,令" + str1 + "的伤害+1;2.摸一张牌,令" + str1 + "的伤害+X(X为" + str2 + "的♦牌的数量)。"); "step 1"; - if (result.bool) { - player.logSkill("yinbing"); - player.addToExpansion(result.cards, player, "give").gaintag.add("yinbing"); + if (result.control && result.control != "cancel2") { + player.logSkill("fengpo", trigger.target); + var nd = trigger.target.countCards("he", { suit: "diamond" }); + var draw = 1, + damage = 1; + if (result.control == "摸X加1伤") draw = nd; + else damage = nd; + player.draw(draw); + var trigger2 = trigger.getParent(); + if (typeof trigger2.baseDamage != "number") { + trigger2.baseDamage = 1; + } + trigger2.baseDamage += damage; } }, - onremove: function (player, skill) { - var cards = player.getExpansions(skill); - if (cards.length) player.loseToDiscardpile(cards); + }, + fengpo2: { + trigger: { source: "damageBegin1" }, + filter: function (event) { + return event.card && (event.card.name == "sha" || event.card.name == "juedou") && event.notLink(); }, - intro: { - content: "expansion", - markcount: "expansion", + forced: true, + audio: false, + content: function () { + if (typeof player.storage.fengpo == "number") { + trigger.num += player.storage.fengpo; + } }, - ai: { - effect: { - target: function (card, player, target, current) { - if (card.name == "sha" || card.name == "juedou") { - if (current < 0) return 1.2; + }, + fengpo3: { charlotte: true }, + //士燮 + biluan: { + audio: 2, + trigger: { player: "phaseDrawBegin1" }, + check: function (event, player) { + if (player.countCards("h") > player.hp) return true; + if (player.hasJudge("lebu")) return true; + var ng = []; + var players = game.filterPlayer(); + for (var i = 0; i < players.length; i++) { + if (players[i].group != "unknown") { + ng.add(players[i].group); + } + } + ng = ng.length; + if (ng < 2) return false; + var nai = 0; + for (var i = 0; i < players.length; i++) { + if (players[i] != player) { + var dist = get.distance(players[i], player, "attack"); + if (dist <= 1 && dist + ng > 1) { + nai++; } - }, - }, - threaten: function (player, target) { - if (target.getExpansions("yinbing").length) return 2; - return 1; - }, - combo: "juedi", + } + } + return nai >= 2; }, - subSkill: { - discard: { - trigger: { player: "damageEnd" }, - forced: true, - filter: function (event, player) { - return event.card && player.getExpansions("yinbing").length > 0 && (event.card.name == "sha" || event.card.name == "juedou"); - }, - content: function () { - "step 0"; - player.chooseCardButton("移去一张引兵牌", true, player.getExpansions("yinbing")); - "step 1"; - if (result.bool) player.loseToDiscardpile(result.links); - }, - }, + filter: function (event, player) { + return ( + !event.numFixed && + game.hasPlayer(function (current) { + return current != player && get.distance(current, player) <= 1; + }) + ); + }, + content: function () { + if (!player.hasSkill("rebiluan2")) player.addSkill("rebiluan2"); + var ng = []; + var players = game.filterPlayer(); + for (var i = 0; i < players.length; i++) { + if (players[i].group != "unknown") { + ng.add(players[i].group); + } + } + player.$damagepop(ng.length, "unknownx"); + player.storage.rebiluan2 += ng.length; + player.markSkill("rebiluan2"); + game.addVideo("storage", player, ["biluan", player.storage.rebiluan2]); + trigger.changeToZero(); }, - group: "yinbing_discard", }, - juedi: { - trigger: { player: "phaseZhunbeiBegin" }, + lixia: { + audio: 2, + trigger: { global: "phaseJieshuBegin" }, filter: function (event, player) { - return player.getExpansions("yinbing").length > 0; + return event.player.isIn() && event.player != player && !event.player.inRange(player); }, forced: true, - audio: 2, content: function () { "step 0"; player - .chooseTarget(get.prompt2("juedi"), true, function (card, player, target) { - return player.hp >= target.hp; - }) + .chooseTarget( + function (card, player, target) { + return target == player || target == _status.event.source; + }, + true, + "礼下:选择一个目标摸一张牌" + ) .set("ai", function (target) { - var player = _status.event.player; - var att = get.attitude(player, target); - if (att < 2) return att - 10; - var num = att / 10; - if (target == player) { - num += player.maxHp - player.countCards("h") + 0.5; - } else { - num += _status.event.n2 * 2; - if (target.isDamaged()) { - if (target.hp == 1) { - num += 3; - } else if (target.hp == 2) { - num += 2; - } else { - num += 0.5; - } - } - } - if (target.hasJudge("lebu")) { - num /= 2; - } - return num; + if (get.attitude(player, trigger.player) > 2) return 114514 - target.countCards(); + return player == target ? 1 : 0; }) - .set("n2", player.getExpansions("yinbing").length); + .set("source", trigger.player); "step 1"; - if (result.bool) { + if (result.targets.length) { + result.targets[0].draw(); player.line(result.targets[0], "green"); - var cards = player.getExpansions("yinbing"); - if (result.targets[0] == player) { - player.loseToDiscardpile(cards); - var num = player.maxHp - player.countCards("h"); - if (num > 0) player.draw(num); - } else { - var target = result.targets[0]; - target.recover(); - player.give(cards, target, "give"); - target.draw(cards.length); + } + if (!player.hasSkill("rebiluan2")) player.addSkill("rebiluan2"); + player.storage.rebiluan2--; + player.markSkill("rebiluan2"); + game.addVideo("storage", player, ["biluan", player.storage.rebiluan2]); + }, + ai: { + combo: "biluan", + }, + }, + olbiluan: { + audio: "biluan", + trigger: { player: "phaseJieshuBegin" }, + checkx: function (player) { + var ng = Math.min(4, game.countPlayer()); + var nai = 0; + for (var i = 0; i < game.players.length; i++) { + if (game.players[i] != player) { + var dist = get.distance(game.players[i], player, "attack"); + if (dist <= 1 && dist + ng > 1) nai++; } } + return nai >= 2; + }, + filter: function (event, player) { + return ( + player.countCards("he") && + game.hasPlayer(function (current) { + return current != player && get.distance(current, player) <= 1; + }) + ); + }, + direct: true, + content: function () { + "step 0"; + player + .chooseToDiscard("he", get.prompt2("olbiluan")) + .set("logSkill", "olbiluan") + .set("ai", function (card) { + if (_status.event.check) return 6 - get.value(card); + return 0; + }) + .set("check", lib.skill.olbiluan.checkx(player)); + "step 1"; + if (result.bool) { + player.addSkill("rebiluan2"); + var num = game.countGroup(); + player.$damagepop(num, "unknownx"); + player.storage.rebiluan2 += num; + player.markSkill("rebiluan2"); + game.addVideo("storage", player, ["rebiluan2", player.storage.rebiluan2]); + } }, - ai: { - combo: "yinbing", - }, }, - meibu: { - trigger: { global: "phaseUseBegin" }, + ollixia: { + audio: "lixia", + trigger: { global: "phaseJieshuBegin" }, filter: function (event, player) { - return event.player != player && get.distance(event.player, player, "attack") > 1; - }, - logTarget: "player", - check: function (event, player) { - if (get.attitude(player, event.player) >= 0) return false; - var e2 = player.getEquip(2); - if (e2) { - if (e2.name == "tengjia" || e2.name == "rewrite_tengjia") return true; - if (e2.name == "bagua" || e2.name == "rewrite_bagua") return true; - } - return player.countCards("h", "shan") > 0; + return event.player.isIn() && event.player != player && !event.player.inRange(player); }, + forced: true, content: function () { - var target = trigger.player; - target.addTempSkill("meibu_viewas"); - target.addTempSkill("meibu_range"); - target.storage.meibu = player; - target.markSkillCharacter("meibu", player, "魅步", "锦囊牌均视为杀且" + get.translation(player) + "视为在攻击范围内"); + "step 0"; + player + .chooseTarget( + function (card, player, target) { + return target == player || target == _status.event.source; + }, + true, + "礼下:请选择一个目标令其摸牌并减少你与其他角色的距离" + ) + .set("ai", function (target) { + return player == target ? 1 : 0; + }) + .set("source", trigger.player); + "step 1"; + if (result.targets.length) { + var num = result.targets[0] == player ? 1 : 2; + result.targets[0].draw(num); + player.line(result.targets[0], "green"); + } + if (!player.hasSkill("rebiluan2")) player.addSkill("rebiluan2"); + player.storage.rebiluan2--; + player.markSkill("rebiluan2"); + game.addVideo("storage", player, ["rebiluan2", player.storage.rebiluan]); }, ai: { - expose: 0.2, + combo: "rebiluan", }, - subSkill: { - range: { - mod: { - targetInRange: function (card, player, target) { - if (card.name == "sha" && target == player.storage.meibu) { - return true; - } - }, - }, - onremove: function (player) { - game.broadcast(function (player) { - if (player.marks.meibu) { - player.marks.meibu.delete(); - delete player.marks.meibu; - } - }, player); - if (player.marks.meibu) { - player.marks.meibu.delete(); - delete player.marks.meibu; - game.addVideo("unmark", player, "meibu"); - } - }, - trigger: { player: "useCard" }, - forced: true, - popup: false, - filter: function (event, player) { - return event.skill == "meibu_viewas"; - }, - content: function () { - player.removeSkill("meibu_viewas"); - game.broadcastAll(function (player) { - if (player.marks.meibu && player.marks.meibu.info) { - player.marks.meibu.info.content = player.marks.meibu.info.content.slice(8); - } - }, player); - }, + }, + rebiluan2: { + mark: true, + charlotte: true, + intro: { + content: function (storage) { + if (storage > 0) { + return "其他角色计算与你的距离时+" + storage; + } else if (storage < 0) { + return "其他角色计算与你的距离时" + storage; + } else { + return "无距离变化"; + } }, - viewas: { - mod: { - cardEnabled: function (card, player) { - if (card.name != "sha" && get.type(card, "trick") == "trick") return false; - }, - cardUsable: function (card, player) { - if (card.name != "sha" && get.type(card, "trick") == "trick") return false; - }, - cardRespondable: function (card, player) { - if (card.name != "sha" && get.type(card, "trick") == "trick") return false; - }, - cardSavable: function (card, player) { - if (card.name != "sha" && get.type(card, "trick") == "trick") return false; - }, - }, - enable: ["chooseToUse", "chooseToRespond"], - filterCard: function (card) { - return get.type(card, "trick") == "trick"; - }, - viewAs: { name: "sha" }, - check: function () { - return 1; - }, - ai: { - effect: { - target: function (card, player, target, current) { - if (get.tag(card, "respondSha") && current < 0) return 0.8; - }, - }, - respondSha: true, - order: 4, - useful: -1, - value: -1, - }, + }, + init: function (player) { + if (typeof player.storage.rebiluan2 != "number") player.storage.rebiluan2 = 0; + }, + mod: { + globalTo: function (from, to, distance) { + if (typeof to.storage.rebiluan2 == "number") { + return distance + to.storage.rebiluan2; + } }, }, }, - mumu: { - enable: "phaseUse", - usable: 1, - filterCard: function (card, player, target) { - return card.name == "sha" || (get.type(card, "trick") == "trick" && get.color(card) == "black"); - }, - check: function (card) { - return 7 - get.value(card); + rebiluan: { + audio: "biluan", + trigger: { player: "phaseJieshuBegin" }, + checkx: function (player) { + var ng = Math.min(4, game.countPlayer()); + var nai = 0; + for (var i = 0; i < game.players.length; i++) { + if (game.players[i] != player) { + var dist = get.distance(game.players[i], player, "attack"); + if (dist <= 1 && dist + ng > 1) { + nai++; + } + } + } + return nai >= 2; }, - filterTarget: function (card, player, target) { - if (target == player) return false; - return target.getEquips(1).length > 0 || target.getEquips(2).length > 0; + filter: function (event, player) { + return ( + player.countCards("he") && + game.hasPlayer(function (current) { + return current != player && get.distance(current, player) <= 1; + }) + ); }, + direct: true, content: function () { "step 0"; - var e1 = target.getEquips(1); - var e2 = target.getEquips(2); - event.e1 = e1; - event.e2 = e2; - if (e1.length && e2.length) { - player.chooseControl("武器牌", "防具牌").set("ai", function () { - if (_status.event.player.getEquip(2)) { - return "武器牌"; - } - return "防具牌"; + player + .chooseToDiscard("he", get.prompt2("rebiluan")) + .set("logSkill", "rebiluan") + .set("check", lib.skill.rebiluan.checkx(player)) + .set("ai", function (card) { + if (_status.event.check) return 6 - get.value(card); + return 0; }); - } else if (e1.length) { - event.choice = "武器牌"; - } else { - event.choice = "防具牌"; - } "step 1"; - var choice = event.choice || result.control; - if (choice == "武器牌") { - if (event.e1) { - target.discard(event.e1); - } - player.draw(); - } else { - if (event.e2) { - player.equip(event.e2); - target.$give(event.e2, player); + if (result.bool) { + player.addSkill("rebiluan2"); + var ng = Math.min(4, game.countPlayer()); + player.$damagepop(ng, "unknownx"); + player.storage.rebiluan2 += ng; + player.markSkill("rebiluan2"); + game.addVideo("storage", player, ["rebiluan2", player.storage.rebiluan2]); + } + }, + }, + relixia: { + audio: "lixia", + trigger: { global: "phaseJieshuBegin" }, + filter: function (event, player) { + return event.player.isIn() && event.player != player && !player.inRangeOf(event.player); + }, + forced: true, + content: function () { + "step 0"; + if (trigger.player.isDead()) { + event._result = { bool: true, links: [0] }; + return; + } + var list = ["令自己摸一张牌", "令XXX摸两张牌", "令XXX回复1点体力"]; + var card = get.translation(trigger.player); + var next = player.chooseButton( + [ + "【礼下】:请选择一至两项", + [ + list.map((item, index) => { + return [index, item.replace(/XXX/g, card)]; + }), + "textbutton", + ], + ], + true, + [1, 2] + ); + next.set("dialog", event.videoId); + next.set("filterButton", function (button) { + if (button.link == 2) { + return _status.event.bool1; } + return true; + }); + next.set("bool1", trigger.player.isDamaged()); + next.set("ai", function (button) { + var player = _status.event.player; + var event = _status.event.getTrigger(); + if (button.link && get.attitude(player, event.player) <= 0) return 0; + return button.link * Math.random(); + }); + "step 1"; + var map = [ + function (trigger, player, event) { + player.draw(); + }, + function (trigger, player, event) { + if (!result.links.includes(2)) player.line(trigger.player); + trigger.player.draw(2); + }, + function (trigger, player, event) { + player.line(trigger.player); + trigger.player.recover(); + }, + ]; + result.links.sort(); + for (var i = 0; i < result.links.length; i++) { + game.log(player, "选择了", "#g【礼下】", "的", "#y选项" + get.cnNumber(result.links[i] + 1, true)); + map[result.links[i]](trigger, player, event); } + player.addSkill("rebiluan2"); + player.storage.rebiluan2 -= result.links.length; + player.markSkill("rebiluan2"); + game.addVideo("storage", player, ["rebiluan2", player.storage.rebiluan2]); }, ai: { - order: 8, - result: { - target: function (player, target) { - if (target.getEquip(2) && !player.getEquip(2)) { - return -2; - } - return -1; - }, - }, + combo: "olbiluan", }, }, - fentian: { + guiming: { + unique: true, + zhuSkill: true, + locked: true, + ai: { + combo: "recanshi", + }, + }, + canshi: { audio: 2, - trigger: { player: "phaseJieshuBegin" }, - direct: true, - filter: function (event, player) { - if (player.countCards("h") >= player.hp) return false; - return game.hasPlayer(function (current) { - return player != current && player.inRange(current) && current.countCards("he"); + trigger: { player: "phaseDrawBegin1" }, + check: function (event, player) { + var num = game.countPlayer(function (current) { + if (player.hasZhuSkill("guiming") && current.group == "wu") return true; + return current.isDamaged(); }); + return num > 3; }, - intro: { - content: "expansion", - markcount: "expansion", + prompt: function (event, player) { + var num = game.countPlayer(function (current) { + if (player.hasZhuSkill("guiming") && current.group == "wu" && current != player) return true; + return current.isDamaged(); + }); + return "残蚀:是否改为摸" + get.cnNumber(num) + "张牌?"; }, - onremove: function (player, skill) { - var cards = player.getExpansions(skill); - if (cards.length) player.loseToDiscardpile(cards); + filter: function (event, player) { + return !event.numFixed; }, content: function () { - "step 0"; - player - .chooseTarget("焚天:选择一名攻击范围内的角色,将其一张牌置于你的武将牌上", true, function (card, player, target) { - return player != target && player.inRange(target) && target.countCards("he") > 0; - }) - .set("ai", function (target) { - return -get.attitude(_status.event.player, target); - }); - "step 1"; - if (result.bool) { - player.logSkill("fentian", result.targets); - event.target = result.targets[0]; - player.choosePlayerCard(result.targets[0], "he", true); - } else { - event.finish(); - } - "step 2"; - if (result.bool) { - player.addToExpansion(result.links, target, "give").gaintag.add("fentian"); + trigger.changeToZero(); + var num = game.countPlayer(function (current) { + if (player.hasZhuSkill("guiming") && current.group == "wu" && current != player) return true; + return current.isDamaged(); + }); + if (num > 0) { + player.draw(num); } - }, - mod: { - attackRange: function (from, distance) { - return distance + from.getExpansions("fentian").length; - }, + player.addTempSkill("canshi2"); }, }, - zhiri: { - trigger: { player: "phaseZhunbeiBegin" }, + canshi2: { + trigger: { player: "useCard" }, forced: true, - unique: true, - juexingji: true, - audio: 2, - skillAnimation: true, - animationColor: "fire", - derivation: "xintan", filter: function (event, player) { - return player.getExpansions("fentian").length >= 3; + if (player.countCards("he") == 0) return false; + var type = get.type(event.card, "trick"); + return type == "basic" || type == "trick"; }, + autodelay: true, content: function () { - player.awakenSkill("zhiri"); - player.loseMaxHp(); - player.storage.zhiri = true; - player.addSkills("xintan"); - }, - ai: { - combo: "fentian", + player.chooseToDiscard(true, "he"); }, }, - xintan: { - enable: "phaseUse", - usable: 1, + chouhai: { audio: 2, - unique: true, - filter: function (event, player) { - return player.getExpansions("fentian").length >= 2; - }, - filterTarget: true, - prompt: "移去两张“焚”并令一名角色失去1点体力", - content: function () { - "step 0"; - player.chooseCardButton(2, "移去两张“焚”并令" + get.translation(target) + "失去1点体力", player.getExpansions("fentian"), true); - "step 1"; - if (result.bool) { - player.loseToDiscardpile(result.links); - target.loseHp(); - } - }, - ai: { - order: 8, - result: { - target: -1, - }, - combo: "fentian", - }, - }, - danji: { - skillAnimation: true, - animationColor: "water", - trigger: { player: "phaseZhunbeiBegin" }, + trigger: { player: "damageBegin3" }, forced: true, - unique: true, - juexingji: true, - derivation: ["mashu", "nuzhan"], + check: function () { + return false; + }, filter: function (event, player) { - var zhu = get.zhu(player); - if (zhu && zhu.isZhu) { - var name = zhu.name; - while (name.indexOf("_") != -1) { - name = name.slice(name.indexOf("_") + 1); - } - if (name.indexOf("liubei") == 0) return false; - } - return !player.storage.danji && player.countCards("h") > player.hp; + return player.countCards("h") == 0; }, content: function () { - player.awakenSkill("danji"); - player.loseMaxHp(); - player.addSkills(["mashu", "nuzhan"]); + trigger.num++; }, ai: { - maixie: true, - skillTagFilter: (player, tag, arg) => { - if (tag === "maixie") { - if (player.hp < 2 || player.storage.danji || player.hasSkill("nuzhan") || player.countCards("h") !== player.hp) return false; - let zhu = get.zhu(player); - if (zhu && zhu.isZhu) { - let name = zhu.name; - while (name.indexOf("_") !== -1) { - name = name.slice(name.indexOf("_") + 1); - } - if (name.indexOf("liubei") == 0) return false; - } - return true; - } - }, + neg: true, effect: { - target: (card, player, target) => { - let hs = target.countCards("h"); - if (target.hp < 3 || target.storage.danji || target.hasSkill("nuzhan") || hs > target.hp + 1) return; - let zhu = get.zhu(target); - if (zhu && zhu.isZhu) { - let name = zhu.name; - while (name.indexOf("_") !== -1) { - name = name.slice(name.indexOf("_") + 1); - } - if (name.indexOf("liubei") == 0) return; - } - if (get.tag(card, "draw")) return 1.6; - if (get.tag(card, "lose") || get.tag(card, "discard")) return [1, -0.8]; - if (hs === target.hp && get.tag(card, "damage")) return [1, target.hp / 3]; - if (hs > target.hp && target.hp > 3 && (card.name === "shan" || card.name === "wuxie")) return "zeroplayertarget"; + target: function (card, player, target, current) { + if (get.tag(card, "damage") && target.countCards("h") == 0) return [1, -2]; }, }, }, }, - nuzhan: { - audio: 2, - popup: false, - silent: true, - firstDo: true, - trigger: { player: "useCard1" }, + recanshi: { + audio: "canshi", + trigger: { player: "phaseDrawBegin2" }, + check: function (event, player) { + if ( + player.skipList.includes("phaseUse") || + !player.countCards("h", function (card) { + return get.type(card, "trick") == "trick" && player.hasUseTarget(card); + }) + ) + return true; + var num = game.countPlayer(function (current) { + if (player.hasZhuSkill("guiming") && current.group == "wu") return true; + return current.isDamaged(); + }); + return num > 1; + }, + prompt: function (event, player) { + var num = game.countPlayer(function (current) { + if (player.hasZhuSkill("guiming") && current.group == "wu" && current != player) return true; + return current.isDamaged(); + }); + return "残蚀:是否多摸" + get.cnNumber(num) + "张牌?"; + }, filter: function (event, player) { - return event.card && event.card.name == "sha" && event.addCount !== false && event.cards && event.cards.length == 1 && get.type(event.cards[0], "trick") == "trick"; + return ( + !event.numFixed && + game.hasPlayer(function (current) { + if (player.hasZhuSkill("guiming") && current.group == "wu" && current != player) return true; + return current.isDamaged(); + }) + ); + }, + content: function () { + var num = game.countPlayer(function (current) { + if (player.hasZhuSkill("guiming") && current.group == "wu" && current != player) return true; + return current.isDamaged(); + }); + if (num > 0) { + trigger.num += num; + } + player.addTempSkill("recanshi2"); }, + }, + recanshi2: { + trigger: { player: "useCard" }, forced: true, - content: function () { - trigger.addCount = false; - if (player.stat[player.stat.length - 1].card.sha > 0) { - player.stat[player.stat.length - 1].card.sha--; - } + filter: function (event, player) { + if (player.countCards("he") == 0) return false; + if (event.card.name == "sha") return true; + return get.type(event.card) == "trick"; }, - ai: { - combo: "wusheng", + autodelay: true, + content: function () { + player.chooseToDiscard(true, "he"); }, - group: "nuzhan2", }, - nuzhan2: { - audio: "nuzhan", - trigger: { player: "useCard1" }, + rechouhai: { + audio: "chouhai", + trigger: { player: "damageBegin3" }, forced: true, - popup: false, - silent: true, - firstDo: true, + check: function () { + return false; + }, filter: function (event, player) { - return event.card && event.card.name == "sha" && event.cards && event.cards.length == 1 && get.type(event.cards[0]) == "equip"; + return event.card && event.card.name == "sha" && player.countCards("h") == 0; }, content: function () { - trigger.baseDamage++; + trigger.num++; }, - }, - jieyuan: { - group: ["jieyuan_more", "jieyuan_less"], - subSkill: { - more: { - audio: true, - trigger: { source: "damageBegin1" }, - direct: true, - filter: function (event, player) { - if ( - !player.countCards(player.hasSkill("fenxin_nei") ? "he" : "h", function (card) { - if (player.hasSkill("fenxin_nei") || (_status.connectMode && get.position(card) == "h")) return true; - return get.color(card) == "black"; - }) - ) - return false; - return (event.player.hp >= player.hp || player.hasSkill("fenxin_fan")) && player != event.player; - }, - content: function () { - "step 0"; - var goon = get.attitude(player, trigger.player) < 0; - var next = player.chooseToDiscard(get.prompt("jieyuan", trigger.player), player.hasSkill("fenxin_nei") ? "he" : "h"); - if (!player.hasSkill("fenxin_nei")) { - next.set("filterCard", function (card) { - return get.color(card) == "black"; - }); - next.set("prompt2", "弃置一张黑色手牌令伤害+1"); - } else { - next.set("prompt2", "弃置一张手牌令伤害+1"); - } - next.set("ai", function (card) { - if (_status.event.goon) { - return 8 - get.value(card); - } - return 0; - }); - next.set("goon", goon); - next.logSkill = ["jieyuan_more", trigger.player]; - "step 1"; - if (result.bool) { - trigger.num++; - } - }, - }, - less: { - audio: true, - trigger: { player: "damageBegin2" }, - filter: function (event, player) { - if ( - !player.countCards(player.hasSkill("fenxin_nei") ? "he" : "h", function (card) { - if (player.hasSkill("fenxin_nei") || (_status.connectMode && get.position(card) == "h")) return true; - return get.color(card) == "red"; - }) - ) - return false; - return event.source && (event.source.hp >= player.hp || player.hasSkill("fenxin_zhong")) && player != event.source; - }, - direct: true, - content: function () { - "step 0"; - var next = player.chooseToDiscard(get.prompt("jieyuan"), player.hasSkill("fenxin_nei") ? "he" : "h"); - if (!player.hasSkill("fenxin_nei")) { - next.set("filterCard", function (card) { - return get.color(card) == "red"; - }); - next.set("prompt2", "弃置一张红色手牌令伤害-1"); - } else { - next.set("prompt2", "弃置一张手牌令伤害-1"); - } - next.set("ai", function (card) { - var player = _status.event.player; - if (player.hp == 1 || _status.event.getTrigger().num > 1) { - return 9 - get.value(card); - } - if (player.hp == 2) { - return 8 - get.value(card); - } - return 7 - get.value(card); - }); - next.logSkill = "jieyuan_less"; - "step 1"; - if (result.bool) { - trigger.num--; - } + ai: { + neg: true, + effect: { + target: function (card, player, target, current) { + if (card.name == "sha" && target.countCards("h") == 0) return [1, -2]; }, }, }, - ai: { - expose: 0.2, - threaten: 1.5, - }, }, - fenxin: { - mode: ["identity", "versus"], - available: function (mode) { - if (mode == "identity" && _status.mode == "purple") return false; - if (mode == "versus" && _status.mode != "two") return false; + kunfen: { + audio: 2, + audioname2: { ol_sb_jiangwei: "kunfen_ol_sb_jiangwei" }, + trigger: { player: "phaseJieshuBegin" }, + locked: function (skill, player) { + if (!player || !player.storage.kunfen) return true; + return false; }, - trigger: { global: ["dieAfter", "damageEnd"] }, - filter: function (event, player) { - var list = ["fan", "zhong", "nei"]; - if (get.mode() == "identity") return event.name == "die" && list.includes(event.player.identity) && !player.hasSkill("fenxin_" + event.player.identity); - return event.name == "damage" && event.player != player && list.some(identity => !player.hasSkill("fenxin_" + identity)) && event.player.getHistory("damage").indexOf(event) == 0; + direct: true, + content: function () { + "step 0"; + if (player.storage.kunfen || (get.mode() == "guozhan" && player.hiddenSkills.includes("kunfen"))) { + if (!player.storage.kunfen) event.skillHidden = true; + player.chooseBool(get.prompt("kunfen"), "失去1点体力,然后摸两张牌").set("ai", function () { + var player = _status.event.player; + if (player.hp > 3) return true; + if (player.hp == 3 && player.countCards("h") < 3) return true; + if (player.hp == 2 && player.countCards("h") == 0) return true; + return false; + }); + } else event._result = { bool: true }; + "step 1"; + if (result.bool) { + player.logSkill("kunfen"); + player.loseHp(); + } else event.finish(); + "step 2"; + player.draw(2); }, + ai: { threaten: 1.5 }, + }, + fengliang: { + skillAnimation: true, + animationColor: "thunder", + unique: true, + juexingji: true, + audio: 2, + derivation: "oltiaoxin", + trigger: { player: "dying" }, + //priority:10, forced: true, - logTarget: "player", + filter: function (event, player) { + return !player.storage.kunfen; + }, content: function () { "step 0"; - if (get.mode() == "identity") { - event._result = { - bool: true, - links: ["fenxin_" + trigger.player.identity], - }; - } else { - player - .chooseButton( - [ - "焚心:请选择〖竭缘〗的升级方式", - [ - [ - ["fenxin_fan", "发动〖竭缘〗增加伤害无体力值限制"], - ["fenxin_zhong", "发动〖竭缘〗减少伤害无体力值限制"], - ["fenxin_nei", "将〖竭缘〗中的黑色手牌和红色手牌改为一张牌"], - ].filter(list => !player.hasSkill(list[0])), - "textbutton", - ], - ], - true - ) - .set("ai", function (button) { - return ["fenxin_fan", "fenxin_zhong", "fenxin_nei"].indexOf(button.link) + 1; - }); - } + player.awakenSkill("fengliang"); + player.loseMaxHp(); "step 1"; - if (result.bool) { - var identity = result.links[0]; - player.addSkill(identity); - player.markSkill("fenxin"); + if (player.hp < 2) { + player.recover(2 - player.hp); } + "step 2"; + player.storage.kunfen = true; + player.addSkills("oltiaoxin"); }, - intro: { - mark: function (dialog, content, player) { - if (player.hasSkill("fenxin_zhong")) { - dialog.addText("你发动“竭缘”减少伤害无体力值限制"); - } - if (player.hasSkill("fenxin_fan")) { - dialog.addText("你发动“竭缘”增加伤害无体力值限制"); - } - if (player.hasSkill("fenxin_nei")) { - dialog.addText("将“竭缘”中的黑色手牌和红色手牌改为一张牌"); - } + }, + zhuiji: { + mod: { + globalFrom: function (from, to) { + if (from.hp >= to.hp) return -Infinity; }, }, - subSkill: { - fan: { charlotte: true }, - zhong: { charlotte: true }, - nei: { charlotte: true }, + }, + oldcihuai: { + audio: "cihuai", + trigger: { player: "phaseUseBegin" }, + filter: function (event, player) { + return player.countCards("h") > 0; + }, + check: function (event, player) { + return !player.countCards("h", "sha"); + }, + content: function () { + player.showHandcards(); + if (!player.countCards("h", "sha")) player.addTempSkill("oldcihuai2"); + }, + }, + oldcihuai2: { + group: "oldcihuai3", + prompt: "视为使用一张杀", + enable: "chooseToUse", + viewAs: { name: "sha", isCard: true }, + filterCard: function () { + return false; + }, + selectCard: -1, + ai: { + presha: true, + respondSha: true, }, - ai: { combo: "jieyuan" }, }, - xisheng: { - enable: "chooseToUse", - usable: 1, - viewAs: { name: "tao" }, - viewAsFilter: function (player) { - return player != _status.currentPhase && player.countCards("hes") > 1; + oldcihuai3: { + trigger: { + player: ["loseAfter"], + global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter", "die"], }, - selectCard: 2, - filterCard: true, - position: "hes", - }, - shulv: { - inherit: "zhiheng", - prompt: "弃置一张牌并摸一张牌", - selectCard: 1, + silent: true, + firstDo: true, filter: function (event, player) { - return player.countCards("hs") > player.hp; + if (event.name == "die") return true; + var evt = event.getl(player); + return evt && evt.hs && evt.hs.length > 0; }, - }, - xiandeng: { - mod: { - cardUsable: function (card, player, num) { - if (card.name == "sha") return num + 1; - }, - targetInRange: function (card, player) { - if (card.name == "sha" && player.countUsed("sha", true) == 0) return true; - }, + content: function () { + player.removeSkill("oldcihuai2"); }, }, - qingyi: { - audio: 2, - trigger: { player: "phaseJudgeBefore" }, + cihuai: { + trigger: { player: "phaseUseBegin" }, direct: true, + filter: function (event, player) { + return player.countCards("h", "sha") == 0; + }, content: function () { "step 0"; - var check = player.countCards("h") > 2; player - .chooseTarget(get.prompt("qingyi"), "跳过判定阶段和摸牌阶段,视为对一名其他角色使用一张【杀】", function (card, player, target) { - if (player == target) return false; - return player.canUse({ name: "sha" }, target, false); + .chooseTarget(get.prompt2("cihuai"), function (card, player, target) { + return player.canUse({ name: "sha", isCard: true }, target); }) - .set("check", check) .set("ai", function (target) { - if (!_status.event.check) return 0; - return get.effect(target, { name: "sha" }, _status.event.player); + var player = _status.event.player; + return get.effect(target, { name: "sha", isCard: true }, player, player); }); "step 1"; if (result.bool) { - player.logSkill("qingyi", result.targets); - player.useCard({ name: "sha", isCard: true }, result.targets[0], false); - trigger.cancel(); - player.skip("phaseDraw"); + player.logSkill("cihuai"); + player.showHandcards(); + player.useCard({ name: "sha", isCard: true }, result.targets); } }, + ai: { + expose: 0.2, + }, }, - qingyi1: { - audio: true, - trigger: { player: "phaseZhunbeiBegin" }, + jilei: { + trigger: { player: "damageEnd" }, + audio: 2, direct: true, + filter: function (event) { + return event.source && event.source.isIn(); + }, content: function () { "step 0"; - player.addSkill("qingyi3"); - var check = player.countCards("h") > 2; - player.chooseTarget(get.prompt2("qingyi"), function (card, player, target) { - if (player == target) return false; - return player.canUse({ name: "sha" }, target); - }).ai = function (target) { - if (!check) return 0; - return get.effect(target, { name: "sha" }, _status.event.player); - }; + player + .chooseControl("basic", "trick", "equip", "cancel2", function () { + var source = _status.event.source; + if (get.attitude(_status.event.player, source) > 0) return "cancel2"; + var list = ["basic", "trick", "equip"].filter(function (name) { + return !source.storage.jilei2 || !source.storage.jilei2.includes(name); + }); + if (!list.length) return "cancel2"; + if ( + list.includes("trick") && + source.countCards("h", function (card) { + return get.type(card, null, source) == "trick" && source.hasValueTarget(card); + }) > 1 + ) + return "trick"; + return list[0]; + }) + .set("prompt", get.prompt2("jilei", trigger.source)) + .set("source", trigger.source); "step 1"; - if (result.bool) { - player.logSkill("qingyi1", result.targets); - player.useCard({ name: "sha", isCard: true }, result.targets[0], false); - player.skip("phaseJudge"); - player.skip("phaseDraw"); + if (result.control != "cancel2") { + player.logSkill("jilei", trigger.source); + player.popup(get.translation(result.control) + "牌"); + trigger.source.addTempSkill("jilei2", { player: "phaseBegin" }); + trigger.source.storage.jilei2.add(result.control); + trigger.source.updateMarks("jilei2"); } - player.removeSkill("qingyi3"); + }, + ai: { + maixie_defend: true, + threaten: 0.7, }, }, - qingyi2: { - audio: true, - trigger: { player: "phaseUseBefore" }, - direct: true, + jilei2: { + unique: true, + charlotte: true, + intro: { + content: function (storage) { + return "不能使用、打出或弃置" + get.translation(storage) + "牌"; + }, + }, + init: function (player, skill) { + if (!player.storage[skill]) player.storage[skill] = []; + }, + mark: true, + onremove: true, + mod: { + cardDiscardable: function (card, player) { + if (player.storage.jilei2.includes(get.type(card, "trick"))) return false; + }, + cardEnabled: function (card, player) { + if (player.storage.jilei2.includes(get.type(card, "trick"))) { + var hs = player.getCards("h"), + cards = [card]; + if (Array.isArray(card.cards)) cards.addArray(card.cards); + for (var i of cards) { + if (hs.includes(i)) return false; + } + } + }, + cardRespondable: function (card, player) { + if (player.storage.jilei2.includes(get.type(card, "trick"))) { + var hs = player.getCards("h"), + cards = [card]; + if (Array.isArray(card.cards)) cards.addArray(card.cards); + for (var i of cards) { + if (hs.includes(i)) return false; + } + } + }, + cardSavable: function (card, player) { + if (player.storage.jilei2.includes(get.type(card, "trick"))) { + var hs = player.getCards("h"), + cards = [card]; + if (Array.isArray(card.cards)) cards.addArray(card.cards); + for (var i of cards) { + if (hs.includes(i)) return false; + } + } + }, + }, + }, + danlao: { + audio: 2, filter: function (event, player) { - return player.countCards("he", { type: "equip" }) > 0; + return (event.card.name == "sha" || get.type(event.card) == "trick") && event.targets && event.targets.length > 1; + }, + check: function (event, player) { + return event.getParent().excluded.includes(player) || get.tag(event.card, "multineg") || get.effect(player, event.card, event.player, player) <= 0; }, + trigger: { target: "useCardToTargeted" }, content: function () { - "step 0"; - player.addSkill("qingyi3"); - var check = player.countCards("h") <= player.hp; - player.chooseCardTarget({ - prompt: get.prompt2("qingyi"), - filterCard: function (card, player) { - return get.type(card) == "equip" && lib.filter.cardDiscardable(card, player); - }, - position: "he", - filterTarget: function (card, player, target) { - if (player == target) return false; - return player.canUse({ name: "sha" }, target); - }, - ai1: function (card) { - if (!_status.event.check) return 0; - return 6 - get.value(card); - }, - ai2: function (target) { - if (!_status.event.check) return 0; - return get.effect(target, { name: "sha" }, _status.event.player); + trigger.getParent().excluded.add(player); + player.draw(); + }, + ai: { + effect: { + target(card) { + if (get.type(card) != "trick") return; + if (card.name == "tiesuo") return [0, 0]; + if (card.name == "yihuajiemu") return [0, 1]; + if (get.tag(card, "multineg")) return [0, 2]; }, - check: check, - }); + }, + }, + }, + taichen: { + enable: "phaseUse", + usable: 1, + filterTarget: function (card, player, target) { + return player.canUse("sha", target); + }, + content: function () { + "step 0"; + player.loseHp(); "step 1"; - if (result.bool) { - player.logSkill("qingyi2", result.targets); - player.discard(result.cards[0]); - player.useCard({ name: "sha", isCard: true }, result.targets[0]); - trigger.cancel(); + player.useCard({ name: "sha", isCard: true }, target, false); + }, + ai: { + order: 1, + result: { + target: function (player, target) { + if (player.hp > 2 && player.hp > target.hp && target.countCards("he") < 4) { + return get.effect(target, { name: "sha" }, player, target); + } + return 0; + }, + }, + }, + }, + naman: { + audio: 2, + trigger: { global: "respondAfter" }, + filter: function (event, player) { + if (event.card.name != "sha") return false; + if (event.player == player) return false; + if (event.cards) { + for (var i = 0; i < event.cards.length; i++) { + if (get.position(event.cards[i], true) == "o") return true; + } } - player.removeSkill("qingyi3"); + return false; }, - }, - qingyi3: { - mod: { - targetInRange: function (card, player, target, now) { - return true; - }, + frequent: true, + content: function () { + var cards = trigger.cards.slice(0); + for (var i = 0; i < cards.length; i++) { + if (get.position(cards[i], true) != "o") { + cards.splice(i--, 1); + } + } + game.delay(0.5); + player.gain(cards, "gain2"); }, }, - qirang: { + xiemu: { audio: 2, - trigger: { player: "equipEnd" }, - frequent: true, + enable: "phaseUse", + usable: 1, + filter: function (event, player) { + return player.countCards("h", "sha") > 0; + }, + filterCard: { name: "sha" }, + check: function (card) { + return 6 - get.value(card); + }, content: function () { - var card = get.cardPile(function (card) { - return get.type(card, "trick") == "trick"; + "step 0"; + var list = lib.group.filter(function (group) { + return ( + ["wei", "shu", "wu", "qun"].includes(group) || + game.hasPlayer(function (current) { + return current.group == group; + }) + ); }); - if (card) { - var next = player.gain(card, "gain2"); - if (get.type(card) == "trick") next.gaintag.add("qirang"); - else { - player.addMark("qirang_mark", 1, false); - player.addTempSkill("qirang_mark", { player: "phaseBegin" }); - } - } + if (player.storage.xiemu2) list.removeArray(player.storage.xiemu2); + var list2 = list.slice(0); + list2.sort(function (a, b) { + return lib.skill.xiemu.count(b) - lib.skill.xiemu.count(a); + }); + player + .chooseControl(list) + .set("prompt", "请选择一个势力") + .set("ai", function () { + return _status.event.group; + }) + .set("group", list2[0]); + "step 1"; + player.popup(result.control + 2, get.groupnature(result.control)); + game.log(player, "选择了", "#g" + get.translation(result.control + 2)); + player.addTempSkill("xiemu2", { player: "phaseBegin" }); + player.storage.xiemu2.add(result.control); + player.updateMarks("xiemu2"); }, ai: { - effect: { - target: function (card, player, target, current) { - if (get.type(card) == "equip" && !get.cardtag(card, "gifts")) return [1, 3]; - }, - }, - threaten: 1.3, + order: 1, + result: { player: 1 }, }, - group: "qirang_use", - subSkill: { - mark: { - charlotte: true, - onremove: function (player) { - var evt = _status.event; - if (evt.name != "phase") evt = evt.getParent("phase"); - if (evt && evt.player == player) { - if (!evt.qirang_num) evt.qirang_num = 0; - evt.qirang_num += player.storage.qirang_mark; - } - delete player.storage.qirang_mark; - }, - intro: { - content: "下回合发动〖羽化〗时卜算量+#", - }, - }, - use: { - audio: "qirang", - trigger: { player: "useCard2" }, - direct: true, - filter: function (event, player) { - if (get.type(event.card) != "trick") return false; - if (!event.targets || event.targets.length != 1) return false; - var info = get.info(event.card); - if (info.allowMultiple == false) return false; - if ( - !player.hasHistory("lose", function (evt) { - if (evt.getParent() != event) return false; - for (var i in evt.gaintag_map) { - if (evt.gaintag_map[i].includes("qirang")) return true; - } - return false; - }) - ) - return false; - if (!info.multitarget) { - if ( - game.hasPlayer(function (current) { - return !event.targets.includes(current) && lib.filter.targetEnabled2(event.card, player, current) && lib.filter.targetInRange(event.card, player, current); - }) - ) { - return true; - } - } - return false; - }, - content: function () { - "step 0"; - var prompt2 = "为" + get.translation(trigger.card) + "增加一个目标"; - player - .chooseTarget(get.prompt("qirang"), function (card, player, target) { - var player = _status.event.player; - if (_status.event.targets.includes(target)) return false; - return lib.filter.targetEnabled2(_status.event.card, player, target) && lib.filter.targetInRange(_status.event.card, player, target); - }) - .set("prompt2", prompt2) - .set("ai", function (target) { - var trigger = _status.event.getTrigger(); - var player = _status.event.player; - return get.effect(target, trigger.card, player, player) * (_status.event.targets.includes(target) ? -1 : 1); - }) - .set("targets", trigger.targets) - .set("card", trigger.card); - "step 1"; - if (result.bool) { - if (!event.isMine() && !event.isOnline()) game.delayx(); - event.targets = result.targets; - } else { - event.finish(); - } - "step 2"; - if (event.targets) { - player.logSkill("qirang_use", event.targets); - trigger.targets.addArray(event.targets); - } - }, - }, + count: function (group) { + var player = _status.event.player; + return game.countPlayer(function (current) { + return current != player && current.group == group && get.attitude(current, player) < 0; + }); }, }, - yuhua: { - trigger: { player: ["phaseZhunbeiBegin", "phaseJieshuBegin"] }, + xiemu2: { + onremove: true, + mark: true, forced: true, - audio: 2, + audio: "xiemu", + intro: { + content: function (storage) { + return "已指定" + get.translation(storage) + "势力"; + }, + }, + trigger: { + target: "useCardToTargeted", + }, + init: function (player) { + if (!player.storage.xiemu2) player.storage.xiemu2 = []; + }, + filter: function (event, player) { + if (!player.storage.xiemu2) return false; + if (get.color(event.card) != "black") return false; + if (!event.player) return false; + if (event.player == player || !player.storage.xiemu2.includes(event.player.group)) return false; + return true; + }, + content: function () { + player.draw(2); + }, + }, + oldxiemu: { + audio: "xiemu", + trigger: { target: "useCardToTargeted" }, + filter: function (event, player) { + if (get.color(event.card) != "black") return false; + if (!event.player) return false; + if (event.player == player) return false; + if (get.mode() != "guozhan") return false; + return player.countCards("h", "sha") > 0; + }, + direct: true, content: function () { "step 0"; - var num = 1, - evt = trigger.getParent(); - if (evt.qirang_num) num += evt.qirang_num; - var cards = get.cards(Math.min(5, num)); - game.cardsGotoOrdering(cards); - var next = player.chooseToMove(); - next.set("list", [["牌堆顶", cards], ["牌堆底"]]); - next.set("prompt", "羽化:点击将牌移动到牌堆顶或牌堆底"); - next.processAI = function (list) { - var cards = list[0][1], - player = _status.event.player; - var target = _status.event.getTrigger().name == "phaseZhunbei" ? player : player.next; - var att = get.sgn(get.attitude(player, target)); - var top = []; - var judges = target.getCards("j"); - var stopped = false; - if (player != target || !target.hasWuxie()) { - for (var i = 0; i < judges.length; i++) { - var judge = get.judge(judges[i]); - cards.sort(function (a, b) { - return (judge(b) - judge(a)) * att; - }); - if (judge(cards[0]) * att < 0) { - stopped = true; - break; - } else { - top.unshift(cards.shift()); - } - } - } - var bottom; - if (!stopped) { - cards.sort(function (a, b) { - return (get.value(b, player) - get.value(a, player)) * att; - }); - while (cards.length) { - if (get.value(cards[0], player) <= 5 == att > 0) break; - top.unshift(cards.shift()); - } - } - bottom = cards; - return [top, bottom]; - }; - "step 1"; - var top = result.moved[0]; - var bottom = result.moved[1]; - top.reverse(); - for (var i = 0; i < top.length; i++) { - ui.cardPile.insertBefore(top[i], ui.cardPile.firstChild); - } - for (i = 0; i < bottom.length; i++) { - ui.cardPile.appendChild(bottom[i]); - } - if (event.triggername == "phaseZhunbeiBegin" && top.length == 0) { - player.addTempSkill("reguanxing_on"); + var next = player.chooseToDiscard("协穆:是否弃置一张杀并摸两张牌?", { name: "sha" }); + next.set("ai", function (card) { + return 9 - get.value(card); + }); + next.logSkill = "xiemu"; + "step 1"; + if (result.bool) { + player.draw(2); } - player.popup(get.cnNumber(top.length) + "上" + get.cnNumber(bottom.length) + "下"); - game.log(player, "将" + get.cnNumber(top.length) + "张牌置于牌堆顶"); - game.updateRoundNumber(); - game.delayx(); }, - mod: { - ignoredHandcard: function (card, player) { - if (get.type(card) != "basic") { - return true; - } - }, - cardDiscardable: function (card, player, name) { - if (name == "phaseDiscard" && get.type(card) != "basic") return false; + ai: { + effect: { + target_use(card, player, target) { + if (get.color(card) == "black" && target.countCards("h") > 0) { + return [1, 0.5]; + } + }, }, }, }, - chenqing: { - audio: 2, - trigger: { global: "dying" }, - //priority:6, + spmengjin: { + trigger: { player: "shaBegin" }, filter: function (event, player) { - return event.player.hp <= 0 && !player.hasSkill("chenqing2"); + return event.target.countCards("he") > 0; }, direct: true, content: function () { "step 0"; - player - .chooseTarget(get.prompt2("chenqing"), function (card, player, target) { - return target != player && target != _status.event.getTrigger().player; - }) - .set("ai", function (target) { - var player = _status.event.player; - var trigger = _status.event.getTrigger(); - if (get.attitude(player, trigger.player) > 0) { - var att1 = get.attitude(target, player); - var att2 = get.attitude(target, trigger.player); - var att3 = get.attitude(player, target); - if (att3 < 0) return 0; - return att1 / 2 + att2 + att3; - } else { - return 0; - // return get.attitude(player,target); - } - }); + var att = get.attitude(player, trigger.target); + player.choosePlayerCard(get.prompt("spmengjin", trigger.target), "he", trigger.target).ai = function (button) { + var val = get.buttonValue(button); + if (att > 0) return -val; + return val; + }; "step 1"; if (result.bool) { - player.addTempSkill("chenqing2", "roundStart"); - event.target = result.targets[0]; - event.target.draw(4); - player.logSkill("chenqing", event.target); - } else { - event.finish(); - } - "step 2"; - var target = event.target; - var tosave = trigger.player; - var att = get.attitude(target, tosave); - var hastao = target.countCards("h", "tao"); - target - .chooseToDiscard(4, true, "he") - .set("ai", function (card) { - var hastao = _status.event.hastao; - var att = _status.event.att; - if (!hastao && att > 0) { - var suit = get.suit(card); - for (var i = 0; i < ui.selected.cards.length; i++) { - if (get.suit(ui.selected.cards[i]) == suit) { - return -4 - get.value(card); - } - } - } - if (att < 0 && ui.selected.cards.length == 3) { - var suit = get.suit(card); - for (var i = 0; i < ui.selected.cards.length; i++) { - if (get.suit(ui.selected.cards[i]) == suit) { - return -get.value(card); - } - } - return -10 - get.value(card); - } - return -get.value(card); - }) - .set("hastao", hastao) - .set("att", att); - "step 3"; - if (result.cards && result.cards.length == 4) { - var suits = []; - for (var i = 0; i < result.cards.length; i++) { - suits.add(get.suit(result.cards[i])); - } - if (suits.length == 4 && game.checkMod({ name: "tao", isCard: true }, player, trigger.player, "unchanged", "cardSavable", player)) { - event.target.useCard({ name: "tao", isCard: true }, trigger.player); - } + trigger.target.discard(result.links); + player.logSkill("spmengjin", trigger.target); + trigger.target.addTempSkill("mengjin2", "shaAfter"); } }, ai: { expose: 0.2, - threaten: 1.5, }, }, - mozhi: { + fenxun_old: { audio: 2, - trigger: { player: "phaseJieshuBegin" }, + trigger: { player: "shaBefore" }, direct: true, filter: function (event, player) { - return ( - player.getHistory("useCard", function (evt) { - return evt.isPhaseUsing() && ["basic", "trick"].includes(get.type(evt.card)); - }).length > 0 && player.countCards("hs") > 0 - ); + return event.targets.length == 1; }, + position: "he", content: function () { "step 0"; - event.count = 2; - event.history = player.getHistory("useCard", function (evt) { - return evt.isPhaseUsing() && ["basic", "trick"].includes(get.type(evt.card)); + player.chooseCardTarget({ + filterCard: lib.filter.cardDiscardable, + filterTarget: function (card, player, target) { + var trigger = _status.event.getTrigger(); + return lib.filter.targetEnabled(trigger.card, player, target) && target != trigger.targets[0]; + }, + ai1: function (card) { + return 6 - get.value(card); + }, + ai2: function (target) { + var trigger = _status.event.getTrigger(); + var player = _status.event.player; + return get.effect(target, trigger.card, player, player); + }, + prompt: get.prompt2("fenxun"), }); "step 1"; - event._result = {}; - if (event.count && event.history.length && player.countCards("hs")) { - event.count--; - var card = event.history.shift().card; - card = { name: card.name, nature: card.nature }; - if (player.hasUseTarget(card, true, true)) { - if ( - game.hasPlayer(function (current) { - return player.canUse(card, current); - }) - ) { - lib.skill.mozhix.viewAs = card; - var next = player.chooseToUse(); - if (next.isOnline()) { - player.send(function (card) { - lib.skill.mozhix.viewAs = card; - }, card); - } - next.logSkill = "mozhi"; - next.set("openskilldialog", "默识:将一张手牌当" + get.translation(card) + "使用"); - next.set("norestore", true); - next.set("_backupevent", "mozhix"); - next.set("custom", { - add: {}, - replace: { window: function () {} }, + if (result.bool) { + player.discard(result.cards); + trigger.targets.push(result.targets[0]); + player.logSkill("fenxun", result.targets); + } + }, + }, + rezhoufu: { + audio: "zhoufu", + enable: "phaseUse", + usable: 1, + filter: function (event, player) { + return player.countCards("he") > 0; + }, + filterCard: true, + filterTarget: function (card, player, target) { + return target != player && !target.getExpansions("rezhoufu_judge").length; + }, + check: function (card) { + return 6 - get.value(card); + }, + position: "he", + discard: false, + lose: false, + delay: false, + content: function () { + target.addToExpansion(cards, player, "give").gaintag.add("rezhoufu_judge"); + target.addSkill("rezhoufu_judge"); + }, + ai: { + order: 1, + result: { + target: -1, + }, + }, + group: ["rezhoufu_losehp"], + subSkill: { + judge: { + audio: "zhoufu", + init: player => { + player.storage.rezhoufu_judge_markcount = 0; + }, + onremove: player => { + delete player.storage.rezhoufu_judge_markcount; + let cards = player.getExpansions("rezhoufu_judge"); + if (cards.length) player.loseToDiscardpile(cards); + }, + intro: { + content: "expansion", + }, + trigger: { player: "judgeBefore" }, + forced: true, + charlotte: true, + filter: function (event, player) { + return !event.directresult && player.getExpansions("rezhoufu_judge").length; + }, + content: function () { + trigger.directresult = player.getExpansions("rezhoufu_judge")[0]; + player.storage.rezhoufu_judge_markcount = 0; + }, + }, + losehp: { + audio: "zhoufu", + trigger: { global: "phaseEnd" }, + forced: true, + filter: function (event, player) { + return game.hasPlayer(function (current) { + return current.hasHistory("lose", function (evt) { + if (!evt || !evt.xs || !evt.xs.length) return false; + for (var i in evt.gaintag_map) { + if (evt.gaintag_map[i].includes("rezhoufu_judge")) return true; + } + return false; }); - next.backup("mozhix"); + }); + }, + logTarget: function (current) { + return game + .filterPlayer(function (current) { + return current.hasHistory("lose", function (evt) { + if (!evt || !evt.xs || !evt.xs.length) return false; + for (var i in evt.gaintag_map) { + if (evt.gaintag_map[i].includes("rezhoufu_judge")) return true; + } + return false; + }); + }) + .sortBySeat(); + }, + content: function () { + var targets = game + .filterPlayer(function (current) { + return current.hasHistory("lose", function (evt) { + if (!evt || !evt.xs || !evt.xs.length) return false; + for (var i in evt.gaintag_map) { + if (evt.gaintag_map[i].includes("rezhoufu_judge")) return true; + } + return false; + }); + }) + .sortBySeat(); + while (targets.length) { + targets.shift().loseHp(); } - } - } - "step 2"; - if (result && result.bool) event.goto(1); - }, - }, - mozhix: { - filterCard: function (card) { - return get.itemtype(card) == "card"; + }, + }, }, - selectCard: 1, - position: "hs", - popname: true, }, - chenqing2: { charlotte: true }, - ranshang: { - audio: 2, - trigger: { player: "damageEnd" }, - filter: function (event, player) { - return event.hasNature("fire"); - }, + reyingbing: { + audio: "yingbin", + trigger: { global: "useCard" }, forced: true, - check: function () { - return false; + filter: function (event, player) { + var cards = event.player.getExpansions("rezhoufu_judge"); + return cards.length && get.color(cards[0]) == get.color(event.card); }, + logTarget: "player", content: function () { - player.addMark("ranshang", trigger.num); - }, - intro: { - name2: "燃", - content: "mark", + "step 0"; + player.draw(); + "step 1"; + trigger.player.storage.rezhoufu_judge_markcount++; + if (trigger.player.storage.rezhoufu_judge_markcount >= 2) { + var cards = trigger.player.getExpansions("rezhoufu_judge"); + player.gain(cards, trigger.player, "give", "bySelf"); + trigger.player.removeSkill("rezhoufu_judge"); + } else trigger.player.markSkill("rezhoufu_judge"); }, ai: { - neg: true, - effect: { - target: function (card, player, target, current) { - if (card.name == "sha") { - if (game.hasNature(card, "fire") || player.hasSkill("zhuque_skill")) return 2; - } - if (get.tag(card, "fireDamage") && current < 0) return 2; - }, - }, + combo: "rezhoufu", }, - group: "ranshang2", }, - ranshang2: { + zhoufu: { + audio: 2, + }, + yingbin: { + audio: 2, + }, + kuiwei: { audio: 2, trigger: { player: "phaseJieshuBegin" }, - forced: true, - filter: function (event, player) { - return player.countMark("ranshang") > 0; + check: function (event, player) { + if (player.isTurnedOver()) return true; + var num = game.countPlayer(function (current) { + return current.getEquip(1); + }); + return num > 1; }, content: function () { - player.loseHp(player.countMark("ranshang")); - if (player.countMark("ranshang") > 2) { - player.loseMaxHp(2); - player.draw(2); - } + "step 0"; + player.turnOver(); + "step 1"; + var num = game.countPlayer(function (current) { + return current.getEquips(1).length; + }); + player.draw(2 + num); + player.addSkill("kuiwei2"); }, }, - hanyong: { - trigger: { player: "useCard" }, - filter: function (event, player) { - return event.card && (event.card.name == "nanman" || event.card.name == "wanjian" || (event.card.name == "sha" && !game.hasNature(event.card) && get.suit(event.card) == "spade")) && player.isDamaged(); - }, + kuiwei2: { + trigger: { player: "phaseDrawBegin" }, + forced: true, + audio: false, content: function () { - trigger.baseDamage++; - if (game.roundNumber <= player.hp) player.addMark("ranshang", 1); + var num = game.countPlayer(function (current) { + return current.getEquips(1).length; + }); + if (num >= player.countCards("he")) { + player.discard(player.getCards("he")); + } else if (num) { + player.chooseToDiscard("he", num, true); + } + player.removeSkill("kuiwei2"); }, }, - hanyong3: { - audio: false, - trigger: { source: "damageBegin1" }, - forced: true, - onremove: true, + yanzheng: { + enable: "chooseToUse", + audio: 2, filter: function (event, player) { - return event.card == player.storage.hanyong3; + return player.hp < player.countCards("h") && player.countCards("e") > 0; }, - content: function () { - trigger.num++; + viewAsFilter: function (player) { + return player.hp < player.countCards("h") && player.countCards("e") > 0; + }, + filterCard: true, + position: "e", + viewAs: { name: "wuxie" }, + prompt: "将一张装备区内的牌当无懈可击使用", + check: function (card) { + return 8 - get.equipValue(card); }, + threaten: 1.2, }, - yishe: { + tongji: { + global: "tongji_disable", audio: 2, - trigger: { player: "phaseJieshuBegin" }, + trigger: { global: "useCard1" }, + forced: true, filter: function (event, player) { - return !player.getExpansions("yishe").length; - }, - intro: { - content: "expansion", - markcount: "expansion", + return event.targets.includes(player) && player != event.player && event.card.name == "sha" && player.hp < player.countCards("h"); }, - content: function () { - "step 0"; - player.draw(2); - "step 1"; - var cards = player.getCards("he"); - if (!cards.length) event.finish(); - else if (cards.length <= 2) event._result = { bool: true, cards: cards }; - else player.chooseCard(2, "he", true, "选择两张牌作为“米”"); - "step 2"; - if (result.bool) player.addToExpansion(result.cards, player, "give").gaintag.add("yishe"); + content: function () {}, + ai: { + neg: true, }, - group: "yishe_recover", - ai: { combo: "bushi" }, + unique: true, + gainable: true, subSkill: { - recover: { - audio: "yishe", - trigger: { - player: ["loseAfter"], - global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], - }, - filter: function (event, player) { - if (player.isHealthy()) return false; - var evt = event.getl(player); - if (!evt || !evt.xs || !evt.xs.length || player.getExpansions("yishe").length > 0) return false; - if (event.name == "lose") { - for (var i in event.gaintag_map) { - if (event.gaintag_map[i].includes("yishe")) return true; - } - return false; - } - return player.hasHistory("lose", function (evt) { - if (event != evt.getParent()) return false; - for (var i in evt.gaintag_map) { - if (evt.gaintag_map[i].includes("yishe")) return true; + disable: { + mod: { + targetEnabled: function (card, player, target) { + if (card.name == "sha") { + if (player.hasSkill("tongji")) return; + if (target.hasSkill("tongji")) return; + if ( + game.hasPlayer(function (current) { + return current.hasSkill("tongji") && current.hp < current.countCards("h") && player.inRange(current); + }) + ) { + return false; + } } - return false; - }); - }, - forced: true, - content: function () { - player.recover(); + }, }, }, }, }, - bushi: { + wangzun: { audio: 2, - trigger: { player: "damageEnd", source: "damageEnd" }, + audioname: ["old_yuanshu"], + trigger: { global: "phaseZhunbeiBegin" }, + check: function (event, player) { + var att = get.attitude(player, event.player); + return !game.hasPlayer(function (current) { + return get.attitude(player, current) < att; + }); + }, filter: function (event, player) { - if (event._notrigger.includes(event.player)) return false; - return event.player.isIn() && player.getExpansions("yishe").length > 0; + return event.player != player && !player.storage.wangzun; }, - direct: true, + logTarget: "player", content: function () { - "step 0"; - event.count = trigger.num; - "step 1"; - trigger.player.chooseCardButton("选择获得一张“米”", player.getExpansions("yishe")); - "step 2"; - if (result.bool) { - event.count--; - player.logSkill("bushi", trigger.player); - trigger.player.gain(result.links[0], "give", player, "bySelf"); - } else event.finish(); - "step 3"; - if (event.count > 0 && player.getExpansions("yishe").length && player.hasSkill("bushi")) { - event.goto(1); - } + player.draw(); + player.markSkill("wangzun"); + player.storage.wangzun = trigger.player; + trigger.player.addTempSkill("wangzun3"); + }, + ai: { + expose: 0.2, + }, + intro: { + content: "player", + }, + group: "wangzun2", + }, + wangzun2: { + trigger: { player: "phaseZhunbeiBegin" }, + silent: true, + content: function () { + player.unmarkSkill("wangzun"); + player.storage.wangzun = null; + }, + }, + wangzun3: { + mod: { + maxHandcard: function (player, num) { + return num - 1; + }, }, - ai: { combo: "yishe" }, }, - midao: { + kaikang: { audio: 2, - trigger: { global: "judge" }, - direct: true, + trigger: { global: "useCardToTargeted" }, filter: function (event, player) { - return player.getExpansions("yishe").length && event.player.isIn(); + return event.card.name == "sha" && get.distance(player, event.target) <= 1 && event.target.isIn(); + }, + check: function (event, player) { + return get.attitude(player, event.target) >= 0; }, + logTarget: "target", content: function () { "step 0"; - var list = player.getExpansions("yishe"); - player - .chooseButton([get.translation(trigger.player) + "的" + (trigger.judgestr || "") + "判定为" + get.translation(trigger.player.judging[0]) + "," + get.prompt("midao"), list, "hidden"], function (button) { - var card = button.link; - var trigger = _status.event.getTrigger(); - var player = _status.event.player; - var judging = _status.event.judging; - var result = trigger.judge(card) - trigger.judge(judging); - var attitude = get.attitude(player, trigger.player); - return result * attitude; - }) - .set("judging", trigger.player.judging[0]) - .set("filterButton", function (button) { - var player = _status.event.player; - var card = button.link; - var mod2 = game.checkMod(card, player, "unchanged", "cardEnabled2", player); - if (mod2 != "unchanged") return mod2; - var mod = game.checkMod(card, player, "unchanged", "cardRespondable", player); - if (mod != "unchanged") return mod; - return true; + player.draw(); + if (trigger.target != player) { + player.chooseCard(true, "he", "交给" + get.translation(trigger.target) + "一张牌").set("ai", function (card) { + if (get.position(card) == "e") return -1; + if (card.name == "shan") return 1; + if (get.type(card) == "equip") return 0.5; + return 0; }); - "step 1"; - if (result.bool) { - event.forceDie = true; - player.respond(result.links, "midao", "highlight", "noOrdering"); - result.cards = result.links; - var card = result.cards[0]; - event.card = card; } else { event.finish(); } + "step 1"; + player.give(result.cards, trigger.target, "give"); + game.delay(); + event.card = result.cards[0]; "step 2"; - if (result.bool) { - if (trigger.player.judging[0].clone) { - trigger.player.judging[0].clone.classList.remove("thrownhighlight"); - game.broadcast(function (card) { - if (card.clone) { - card.clone.classList.remove("thrownhighlight"); - } - }, trigger.player.judging[0]); - game.addVideo("deletenode", player, get.cardsInfo([trigger.player.judging[0].clone])); - } - game.cardsDiscard(trigger.player.judging[0]); - trigger.player.judging[0] = result.cards[0]; - trigger.orderingCards.addArray(result.cards); - game.log(trigger.player, "的判定牌改为", card); - game.delay(2); + if (trigger.target.getCards("h").includes(card) && get.type(card) == "equip") { + trigger.target.chooseUseTarget(card); } }, ai: { - combo: "yishe", - rejudge: true, - tag: { - rejudge: 0.6, - }, + threaten: 1.1, }, }, - fengpo: { + liangzhu: { audio: 2, - trigger: { - player: "useCardToPlayered", - }, + trigger: { global: "recoverAfter" }, + direct: true, filter: function (event, player) { - if (event.targets.length != 1 || !["sha", "juedou"].includes(event.card.name)) return false; - var evtx = event.getParent(); - return !player.hasHistory( - "useCard", - function (evt) { - return evt != evtx && evt.card.name == event.card.name; - }, - evtx - ); + return event.player.isPhaseUsing(); }, - direct: true, content: function () { "step 0"; - var str1 = get.translation(trigger.card), - str2 = get.translation(trigger.target); - player - .chooseControl("摸X加1伤", "摸1加X伤", "cancel2") - .set("prompt", get.prompt("fengpo", trigger.target)) - .set("prompt2", "你可以选择一项:1.摸X张牌,令" + str1 + "的伤害+1;2.摸一张牌,令" + str1 + "的伤害+X(X为" + str2 + "的♦牌的数量)。"); + if (player == trigger.player) { + player + .chooseControl("摸一张", "摸两张", "cancel2", function () { + return "摸两张"; + }) + .set("prompt", get.prompt2("liangzhu")); + event.single = true; + } else { + player + .chooseTarget(get.prompt2("liangzhu"), function (card, player, target) { + return target == _status.event.player || target == _status.event.target; + }) + .set("target", trigger.player) + .set("ai", function (target) { + var player = _status.event.player; + if (player == target) return 1; + return get.attitude(player, target) - 1.5; + }); + } "step 1"; - if (result.control && result.control != "cancel2") { - player.logSkill("fengpo", trigger.target); - var nd = trigger.target.countCards("he", { suit: "diamond" }); - var draw = 1, - damage = 1; - if (result.control == "摸X加1伤") draw = nd; - else damage = nd; - player.draw(draw); - var trigger2 = trigger.getParent(); - if (typeof trigger2.baseDamage != "number") { - trigger2.baseDamage = 1; + if (event.single) { + if (result.control != "cancel2") { + player.logSkill("liangzhu", player); + if (result.control == "摸一张") { + player.draw(); + } else { + player.draw(2); + if (!player.storage.liangzhu) player.storage.liangzhu = []; + player.storage.liangzhu.add(player); + } + } + } else if (result.bool) { + var target = result.targets[0]; + player.logSkill("liangzhu", target); + if (target == player) { + target.draw(); + } else { + target.draw(2); + if (target.storage.liangzhu) { + target.storage.liangzhu.add(player); + } else { + target.storage.liangzhu = [player]; + } } - trigger2.baseDamage += damage; } }, - }, - fengpo2: { - trigger: { source: "damageBegin1" }, - filter: function (event) { - return event.card && (event.card.name == "sha" || event.card.name == "juedou") && event.notLink(); - }, - forced: true, - audio: false, - content: function () { - if (typeof player.storage.fengpo == "number") { - trigger.num += player.storage.fengpo; - } + ai: { + expose: 0.1, }, }, - fengpo3: { charlotte: true }, - //士燮 - biluan: { + fanxiang: { + skillAnimation: true, + animationColor: "fire", audio: 2, - trigger: { player: "phaseDrawBegin1" }, - check: function (event, player) { - if (player.countCards("h") > player.hp) return true; - if (player.hasJudge("lebu")) return true; - var ng = []; - var players = game.filterPlayer(); - for (var i = 0; i < players.length; i++) { - if (players[i].group != "unknown") { - ng.add(players[i].group); - } - } - ng = ng.length; - if (ng < 2) return false; - var nai = 0; - for (var i = 0; i < players.length; i++) { - if (players[i] != player) { - var dist = get.distance(players[i], player, "attack"); - if (dist <= 1 && dist + ng > 1) { - nai++; - } - } - } - return nai >= 2; - }, + unique: true, + juexingji: true, + derivation: "xiaoji", + trigger: { player: "phaseZhunbeiBegin" }, filter: function (event, player) { - return ( - !event.numFixed && - game.hasPlayer(function (current) { - return current != player && get.distance(current, player) <= 1; - }) - ); + if (player.storage.fanxiang) return false; + return game.hasPlayer(function (current) { + return current.storage.liangzhu && current.storage.liangzhu.includes(player) && current.isDamaged(); + }); }, + forced: true, content: function () { - if (!player.hasSkill("rebiluan2")) player.addSkill("rebiluan2"); - var ng = []; - var players = game.filterPlayer(); - for (var i = 0; i < players.length; i++) { - if (players[i].group != "unknown") { - ng.add(players[i].group); - } - } - player.$damagepop(ng.length, "unknownx"); - player.storage.rebiluan2 += ng.length; - player.markSkill("rebiluan2"); - game.addVideo("storage", player, ["biluan", player.storage.rebiluan2]); - trigger.changeToZero(); + player.awakenSkill("fanxiang"); + player.gainMaxHp(); + player.recover(); + player.changeSkills(["xiaoji"], ["liangzhu"]); + }, + ai: { + combo: "liangzhu", }, }, - lixia: { + mingshi: { audio: 2, - trigger: { global: "phaseJieshuBegin" }, + trigger: { player: "damageBegin3" }, + direct: true, filter: function (event, player) { - return event.player.isIn() && event.player != player && get.distance(event.player, player, "attack") > 1; + return event.source && event.source.hp > player.hp; }, - forced: true, content: function () { "step 0"; - player - .chooseTarget( - function (card, player, target) { - return target == player || target == _status.event.source; - }, - true, - "礼下:选择一个目标摸一张牌" - ) - .set("ai", function (target) { - if (get.attitude(player, trigger.player) > 2) return 114514 - target.countCards(); - return player == target ? 1 : 0; - }) - .set("source", trigger.player); + var next = player.chooseToDiscard(get.prompt2("mingshi"), { color: "black" }); + next.set("ai", function (card) { + return 9 - get.value(card); + }); + next.set("logSkill", "mingshi"); "step 1"; - if (result.targets.length) { - result.targets[0].draw(); - player.line(result.targets[0], "green"); + if (result.bool) { + trigger.num--; } - if (!player.hasSkill("rebiluan2")) player.addSkill("rebiluan2"); - player.storage.rebiluan2--; - player.markSkill("rebiluan2"); - game.addVideo("storage", player, ["biluan", player.storage.rebiluan2]); }, ai: { - combo: "biluan", + threaten: 0.8, }, }, - olbiluan: { - audio: "biluan", - trigger: { player: "phaseJieshuBegin" }, - checkx: function (player) { - var ng = Math.min(4, game.countPlayer()); - var nai = 0; - for (var i = 0; i < game.players.length; i++) { - if (game.players[i] != player) { - var dist = get.distance(game.players[i], player, "attack"); - if (dist <= 1 && dist + ng > 1) nai++; - } - } - return nai >= 2; + lirang: { + audio: 2, + trigger: { + player: "loseAfter", + global: "loseAsyncAfter", }, filter: function (event, player) { - return ( - player.countCards("he") && - game.hasPlayer(function (current) { - return current != player && get.distance(current, player) <= 1; - }) - ); + if (!game.hasPlayer(current => current != player)) return false; + if (event.type != "discard" || event.getlx === false) return false; + var evt = event.getl(player); + if (!evt || !evt.cards2) return false; + for (var i = 0; i < evt.cards2.length; i++) { + if (get.position(evt.cards2[i]) == "d") { + return true; + } + } + return false; }, direct: true, + preHidden: true, content: function () { "step 0"; + if (trigger.delay == false) game.delay(); + event.cards = []; + var cards2 = trigger.getl(player).cards2; + for (var i = 0; i < cards2.length; i++) { + if (get.position(cards2[i], true) == "d") { + event.cards.push(cards2[i]); + } + } + if (_status.connectMode) + game.broadcastAll(function () { + _status.noclearcountdown = true; + }); + event.given_map = {}; + "step 1"; + var goon = false; + for (var i = 0; i < event.cards.length; i++) { + if (event.cards[i].name == "du") { + goon = true; + break; + } + } + if (!goon) { + goon = game.hasPlayer(function (current) { + return player != current && get.attitude(player, current) > 1; + }); + } player - .chooseToDiscard("he", get.prompt2("olbiluan")) - .set("logSkill", "olbiluan") - .set("ai", function (card) { - if (_status.event.check) return 6 - get.value(card); + .chooseButton(["礼让:是否分配本次弃置的牌?", event.cards], [1, event.cards.length]) + .set("ai", function (button) { + if (_status.event.goon && ui.selected.buttons.length == 0) return 1 + Math.abs(get.value(button.link)); return 0; }) - .set("check", lib.skill.olbiluan.checkx(player)); - "step 1"; + .set("goon", goon) + .setHiddenSkill("lirang"); + "step 2"; if (result.bool) { - player.addSkill("rebiluan2"); - var num = game.countGroup(); - player.$damagepop(num, "unknownx"); - player.storage.rebiluan2 += num; - player.markSkill("rebiluan2"); - game.addVideo("storage", player, ["rebiluan2", player.storage.rebiluan2]); + event.cards.removeArray(result.links); + event.togive = result.links.slice(0); + player + .chooseTarget("选择一名其他角色获得" + get.translation(result.links), true, lib.filter.notMe) + .set("ai", function (target) { + var att = get.attitude(_status.event.player, target); + if (_status.event.enemy) { + return -att; + } else if (att > 0) { + return att / (1 + target.countCards("h")); + } else { + return att / 100; + } + }) + .set("enemy", get.value(event.togive[0], player, "raw") < 0); + } else event.goto(4); + "step 3"; + if (result.targets.length) { + var id = result.targets[0].playerid, + map = event.given_map; + if (!map[id]) map[id] = []; + map[id].addArray(event.togive); + } + if (cards.length > 0) event.goto(1); + "step 4"; + if (_status.connectMode) { + game.broadcastAll(function () { + delete _status.noclearcountdown; + game.stopCountChoose(); + }); + } + var list = [], + targets = []; + for (var i in event.given_map) { + var source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; + list.push([source, event.given_map[i]]); + targets.push(source); + } + if (targets.length) { + player.logSkill("lirang", targets); + game.loseAsync({ + gain_list: list, + giver: player, + animate: "gain2", + }).setContent("gaincardMultiple"); } }, + ai: { + expose: 0.1, + effect: { + target: function (card, player, target, current) { + if (target.hasFriend() && get.tag(card, "discard")) { + if (current < 0) return 0; + return [1, 1]; + } + }, + }, + }, }, - ollixia: { - audio: "lixia", - trigger: { global: "phaseJieshuBegin" }, + moukui: { + audio: 2, + audioname: ["sp_mushun"], + trigger: { player: "useCardToPlayered" }, + direct: true, filter: function (event, player) { - return event.player.isIn() && event.player != player && get.distance(event.player, player, "attack") > 1; + return event.card.name == "sha"; }, - forced: true, content: function () { "step 0"; + var controls = ["draw_card"]; + if (trigger.target.countCards("he")) { + controls.push("discard_card"); + } + controls.push("cancel"); player - .chooseTarget( - function (card, player, target) { - return target == player || target == _status.event.source; - }, - true, - "礼下:请选择一个目标令其摸牌并减少你与其他角色的距离" - ) - .set("ai", function (target) { - return player == target ? 1 : 0; + .chooseControl(controls) + .set("ai", function () { + var trigger = _status.event.getTrigger(); + if (trigger.target.countCards("he") && get.attitude(_status.event.player, trigger.target) < 0) { + return "discard_card"; + } else { + return "draw_card"; + } }) - .set("source", trigger.player); + .set("prompt", get.prompt2("moukui")); "step 1"; - if (result.targets.length) { - var num = result.targets[0] == player ? 1 : 2; - result.targets[0].draw(num); - player.line(result.targets[0], "green"); - } - if (!player.hasSkill("rebiluan2")) player.addSkill("rebiluan2"); - player.storage.rebiluan2--; - player.markSkill("rebiluan2"); - game.addVideo("storage", player, ["rebiluan2", player.storage.rebiluan]); + if (result.control == "draw_card") { + player.draw(); + player.logSkill("moukui"); + } else if (result.control == "discard_card" && trigger.target.countCards("he")) { + player.discardPlayerCard(trigger.target, "he", true).logSkill = ["moukui", trigger.target]; + } else event.finish(); + "step 2"; + player.addTempSkill("moukui2", "shaEnd"); }, ai: { - combo: "rebiluan", + expose: 0.1, }, }, - rebiluan2: { - mark: true, - charlotte: true, - intro: { - content: function (storage) { - if (storage > 0) { - return "其他角色计算与你的距离时+" + storage; - } else if (storage < 0) { - return "其他角色计算与你的距离时" + storage; - } else { - return "无距离变化"; - } - }, - }, - init: function (player) { - if (typeof player.storage.rebiluan2 != "number") player.storage.rebiluan2 = 0; + moukui2: { + audio: false, + trigger: { player: "shaMiss" }, + forced: true, + filter: function (event, player) { + return player.countCards("he") > 0; }, - mod: { - globalTo: function (from, to, distance) { - if (typeof to.storage.rebiluan2 == "number") { - return distance + to.storage.rebiluan2; - } - }, + content: function () { + trigger.target.discardPlayerCard(player, true); }, }, - rebiluan: { - audio: "biluan", - trigger: { player: "phaseJieshuBegin" }, - checkx: function (player) { - var ng = Math.min(4, game.countPlayer()); - var nai = 0; - for (var i = 0; i < game.players.length; i++) { - if (game.players[i] != player) { - var dist = get.distance(game.players[i], player, "attack"); - if (dist <= 1 && dist + ng > 1) { - nai++; - } + shenxian: { + audio: 2, + trigger: { global: ["loseAfter", "loseAsyncAfter"] }, + filter: function (event, player) { + if (event.type != "discard" || _status.currentPhase == player || event.getlx === false) return false; + if (event.name == "lose" && event.player == player) return false; + if (player.hasSkill("shenxian2")) return false; + var cards = event.cards.slice(0); + var evt = event.getl(player); + if (evt && evt.cards) cards.removeArray(evt.cards); + for (var i = 0; i < cards.length; i++) { + if (get.type(cards[i], null, event.hs && event.hs.includes(cards[i]) ? event.player : false) == "basic" && cards[i].original != "j") { + return true; } } - return nai >= 2; - }, - filter: function (event, player) { - return ( - player.countCards("he") && - game.hasPlayer(function (current) { - return current != player && get.distance(current, player) <= 1; - }) - ); + return false; }, - direct: true, + frequent: true, content: function () { "step 0"; - player - .chooseToDiscard("he", get.prompt2("rebiluan")) - .set("logSkill", "rebiluan") - .set("check", lib.skill.rebiluan.checkx(player)) - .set("ai", function (card) { - if (_status.event.check) return 6 - get.value(card); - return 0; - }); + if (trigger.delay == false) game.delay(); "step 1"; - if (result.bool) { - player.addSkill("rebiluan2"); - var ng = Math.min(4, game.countPlayer()); - player.$damagepop(ng, "unknownx"); - player.storage.rebiluan2 += ng; - player.markSkill("rebiluan2"); - game.addVideo("storage", player, ["rebiluan2", player.storage.rebiluan2]); - } + player.draw(); + if (event.name == "shenxian") player.addTempSkill("shenxian2"); }, - }, - relixia: { - audio: "lixia", - trigger: { global: "phaseJieshuBegin" }, - filter: function (event, player) { - return event.player.isIn() && event.player != player && !player.inRangeOf(event.player); + ai: { + threaten: 1.5, }, - forced: true, + }, + shenxian2: { charlotte: true }, + qiangwu: { + audio: 2, + enable: "phaseUse", + usable: 1, content: function () { "step 0"; - if (trigger.player.isDead()) { - event._result = { bool: true, links: [0] }; - return; - } - var list = ["令自己摸一张牌", "令XXX摸两张牌", "令XXX回复1点体力"]; - var card = get.translation(trigger.player); - var next = player.chooseButton( - [ - "【礼下】:请选择一至两项", - [ - list.map((item, index) => { - return [index, item.replace(/XXX/g, card)]; - }), - "textbutton", - ], - ], - true, - [1, 2] - ); - next.set("dialog", event.videoId); - next.set("filterButton", function (button) { - if (button.link == 2) { - return _status.event.bool1; - } - return true; - }); - next.set("bool1", trigger.player.isDamaged()); - next.set("ai", function (button) { - var player = _status.event.player; - var event = _status.event.getTrigger(); - if (button.link && get.attitude(player, event.player) <= 0) return 0; - return button.link * Math.random(); + player.judge(card => { + if ( + game.hasPlayer(cur => { + return get.event("player").canUse("sha", cur); + }) + ) + return get.number(card); + return 1 / get.number(card); }); "step 1"; - var map = [ - function (trigger, player, event) { - player.draw(); - }, - function (trigger, player, event) { - if (!result.links.includes(2)) player.line(trigger.player); - trigger.player.draw(2); - }, - function (trigger, player, event) { - player.line(trigger.player); - trigger.player.recover(); - }, - ]; - result.links.sort(); - for (var i = 0; i < result.links.length; i++) { - game.log(player, "选择了", "#g【礼下】", "的", "#y选项" + get.cnNumber(result.links[i] + 1, true)); - map[result.links[i]](trigger, player, event); - } - player.addSkill("rebiluan2"); - player.storage.rebiluan2 -= result.links.length; - player.markSkill("rebiluan2"); - game.addVideo("storage", player, ["rebiluan2", player.storage.rebiluan2]); - }, - ai: { - combo: "olbiluan", + player.storage.qiangwu = result.number; + player.addTempSkill("qiangwu3", "phaseUseEnd"); }, - }, - guiming: { - unique: true, - zhuSkill: true, - locked: true, ai: { - combo: "recanshi", + result: { + player: 1, + }, + order: 11, }, }, - canshi: { - audio: 2, - trigger: { player: "phaseDrawBegin1" }, - check: function (event, player) { - var num = game.countPlayer(function (current) { - if (player.hasZhuSkill("guiming") && current.group == "wu") return true; - return current.isDamaged(); - }); - return num > 3; - }, - prompt: function (event, player) { - var num = game.countPlayer(function (current) { - if (player.hasZhuSkill("guiming") && current.group == "wu" && current != player) return true; - return current.isDamaged(); - }); - return "残蚀:是否改为摸" + get.cnNumber(num) + "张牌?"; + qiangwu3: { + mod: { + targetInRange: function (card, player) { + if (card.name == "sha") { + const num = get.number(card); + if (num == "unsure" || num < player.storage.qiangwu) return true; + } + }, + cardUsable: function (card, player) { + if (card.name == "sha") { + const num = get.number(card); + if (num == "unsure" || num > player.storage.qiangwu) return true; + } + }, }, + trigger: { player: "useCard1" }, filter: function (event, player) { - return !event.numFixed; - }, - content: function () { - trigger.changeToZero(); - var num = game.countPlayer(function (current) { - if (player.hasZhuSkill("guiming") && current.group == "wu" && current != player) return true; - return current.isDamaged(); - }); - if (num > 0) { - player.draw(num); - } - player.addTempSkill("canshi2"); + if (_status.currentPhase == player && event.card.name == "sha" && get.number(event.card) > player.storage.qiangwu && event.addCount !== false) return true; + return false; }, - }, - canshi2: { - trigger: { player: "useCard" }, forced: true, - filter: function (event, player) { - if (player.countCards("he") == 0) return false; - var type = get.type(event.card, "trick"); - return type == "basic" || type == "trick"; - }, - autodelay: true, + popup: false, + firstDo: true, content: function () { - player.chooseToDiscard(true, "he"); + trigger.addCount = false; + if (player.stat[player.stat.length - 1].card.sha > 0) { + player.stat[player.stat.length - 1].card.sha--; + } }, }, - chouhai: { + zhendu: { audio: 2, - trigger: { player: "damageBegin3" }, - forced: true, - check: function () { - return false; - }, + trigger: { global: "phaseUseBegin" }, filter: function (event, player) { - return player.countCards("h") == 0; + return /*(get.mode()!='guozhan'||event.player!=player)&&*/ event.player.isIn() && player.countCards("h") > 0 && event.player.hasUseTarget({ name: "jiu" }, null, true); }, + direct: true, + preHidden: true, content: function () { - trigger.num++; + "step 0"; + var nono = Math.abs(get.attitude(player, trigger.player)) < 3; + if (player == trigger.player || get.damageEffect(trigger.player, player, player) <= 0 || !trigger.player.hasUseTarget({ name: "jiu" }, null, true)) { + nono = true; + } else if (trigger.player.hp > 2) { + nono = true; + } else if (trigger.player.hp > 1 && player.countCards("h") < 3 && trigger.player.canUse("sha", player) && !player.countCards("h", "shan") && trigger.player.countCards("h") >= 3) { + nono = true; + } + var next = player.chooseToDiscard(get.prompt2("zhendu", trigger.player)); + next.set("ai", function (card) { + if (_status.event.nono) return -1; + return 7 - get.useful(card); + }); + next.set("logSkill", ["zhendu", trigger.player]); + next.set("nono", nono); + next.setHiddenSkill("zhendu"); + "step 1"; + if (result.bool) { + trigger.player.chooseUseTarget({ name: "jiu" }, true, "noTargetDelay", "nodelayx"); + } else { + event.finish(); + } + "step 2"; + if (result.bool && trigger.player != player) trigger.player.damage(); }, ai: { - neg: true, - effect: { - target: function (card, player, target, current) { - if (get.tag(card, "damage") && target.countCards("h") == 0) return [1, -2]; - }, - }, + threaten: 2, + expose: 0.3, }, }, - recanshi: { - audio: "canshi", - trigger: { player: "phaseDrawBegin2" }, - check: function (event, player) { - if ( - player.skipList.includes("phaseUse") || - !player.countCards("h", function (card) { - return get.type(card, "trick") == "trick" && player.hasUseTarget(card); - }) - ) - return true; - var num = game.countPlayer(function (current) { - if (player.hasZhuSkill("guiming") && current.group == "wu") return true; - return current.isDamaged(); + qiluan: { + audio: "qiluan2", + preHidden: true, + trigger: { global: "phaseEnd" }, + frequent: true, + filter: function (event, player) { + return game.hasPlayer2(function (current) { + return current.getStat("kill") > 0; }); - return num > 1; }, prompt: function (event, player) { - var num = game.countPlayer(function (current) { - if (player.hasZhuSkill("guiming") && current.group == "wu" && current != player) return true; - return current.isDamaged(); + var num = game.countPlayer2(function (current) { + return (current.getStat("kill") || 0) * (current == player ? 3 : 1); }); - return "残蚀:是否多摸" + get.cnNumber(num) + "张牌?"; + return get.prompt("qiluan") + "(可摸" + get.cnNumber(num) + "张牌)"; }, - filter: function (event, player) { - return ( - !event.numFixed && - game.hasPlayer(function (current) { - if (player.hasZhuSkill("guiming") && current.group == "wu" && current != player) return true; - return current.isDamaged(); + content: function () { + //if(get.mode()=='guozhan'){ + // player.draw(3); + //} + //else{ + player.draw( + game.countPlayer2(function (current) { + return (current.getStat("kill") || 0) * (current == player ? 3 : 1); }) ); + //} }, - content: function () { - var num = game.countPlayer(function (current) { - if (player.hasZhuSkill("guiming") && current.group == "wu" && current != player) return true; - return current.isDamaged(); - }); - if (num > 0) { - trigger.num += num; - } - player.addTempSkill("recanshi2"); + subSkill: { + draw: { + trigger: { global: "dieAfter" }, + frequent: true, + filter: function (event, player) { + return /*get.mode()!='guozhan'&&*/ player != event.source; + }, + content: function () { + player.draw(); + }, + }, }, }, - recanshi2: { - trigger: { player: "useCard" }, + qiluan2: { + audio: 2, + }, + zniaoxiang: { + audio: 2, + trigger: { player: "useCardToPlayered" }, forced: true, filter: function (event, player) { - if (player.countCards("he") == 0) return false; - if (event.card.name == "sha") return true; - return get.type(event.card) == "trick"; + return event.card.name == "sha" && !event.getParent().directHit.includes(event.target); }, - autodelay: true, + //priority:-1, + logTarget: "target", content: function () { - player.chooseToDiscard(true, "he"); + var id = trigger.target.playerid; + var map = trigger.getParent().customArgs; + if (!map[id]) map[id] = {}; + if (typeof map[id].shanRequired == "number") { + map[id].shanRequired++; + } else { + map[id].shanRequired = 2; + } }, }, - rechouhai: { - audio: "chouhai", - trigger: { player: "damageBegin3" }, - forced: true, - check: function () { - return false; - }, - filter: function (event, player) { - return event.card && event.card.name == "sha" && player.countCards("h") == 0; + shangyi: { + audio: 2, + enable: "phaseUse", + usable: 1, + filterTarget: function (card, player, target) { + return player != target && target.countCards("h"); }, content: function () { - trigger.num++; + "step 0"; + player.chooseCardButton(target, target.getCards("h")).set("filterButton", function (button) { + return get.color(button.link) == "black"; + }); + "step 1"; + if (result.bool) { + target.discard(result.links[0]); + } }, ai: { - neg: true, - effect: { - target: function (card, player, target, current) { - if (card.name == "sha" && target.countCards("h") == 0) return [1, -2]; + order: 11, + result: { + target: function (player, target) { + return -target.countCards("h"); }, }, + threaten: 1.1, }, }, - kunfen: { - audio: 2, - audioname2: { ol_sb_jiangwei: "kunfen_ol_sb_jiangwei" }, - trigger: { player: "phaseJieshuBegin" }, - locked: function (skill, player) { - if (!player || !player.storage.kunfen) return true; - return false; + shengxi: { + trigger: { player: "phaseDiscardBegin" }, + frequent: true, + filter: function (event, player) { + return !player.getStat("damage"); }, - direct: true, content: function () { - "step 0"; - if (player.storage.kunfen || (get.mode() == "guozhan" && player.hiddenSkills.includes("kunfen"))) { - if (!player.storage.kunfen) event.skillHidden = true; - player.chooseBool(get.prompt("kunfen"), "失去1点体力,然后摸两张牌").set("ai", function () { - var player = _status.event.player; - if (player.hp > 3) return true; - if (player.hp == 3 && player.countCards("h") < 3) return true; - if (player.hp == 2 && player.countCards("h") == 0) return true; - return false; - }); - } else event._result = { bool: true }; - "step 1"; - if (result.bool) { - player.logSkill("kunfen"); - player.loseHp(); - } else event.finish(); - "step 2"; player.draw(2); }, - ai: { threaten: 1.5 }, + audio: 2, + audioname: ["liushan"], }, - fengliang: { - skillAnimation: true, - animationColor: "thunder", - unique: true, - juexingji: true, + shoucheng: { + init(player) { + game.addGlobalSkill("shoucheng_draw", player); + }, + onremove: () => { + if (!game.hasPlayer(i => i.hasSkill("shoucheng", null, null, false), true)) game.removeGlobalSkill("shoucheng_draw"); + }, + trigger: { + global: ["equipAfter", "addJudgeAfter", "loseAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], + }, audio: 2, - derivation: "oltiaoxin", - trigger: { player: "dying" }, - //priority:10, - forced: true, + direct: true, filter: function (event, player) { - return !player.storage.kunfen; + return game.hasPlayer(function (current) { + if (current == _status.currentPhase) return false; + var evt = event.getl(current); + return evt && evt.hs && evt.hs.length && current.countCards("h") == 0; + }); }, content: function () { "step 0"; - player.awakenSkill("fengliang"); - player.loseMaxHp(); + event.list = game + .filterPlayer(function (current) { + if (current == _status.currentPhase) return false; + var evt = trigger.getl(current); + return evt && evt.hs && evt.hs.length; + }) + .sortBySeat(_status.currentPhase); "step 1"; - if (player.hp < 2) { - player.recover(2 - player.hp); - } + var target = event.list.shift(); + event.target = target; + if (target.isIn() && target.countCards("h") == 0) { + player.chooseBool(get.prompt2("shoucheng", target)).set("ai", function () { + return get.attitude(_status.event.player, _status.event.getParent().target) > 0; + }); + } else event.goto(3); "step 2"; - player.storage.kunfen = true; - player.addSkills("oltiaoxin"); + if (result.bool) { + player.logSkill(event.name, target); + if (player !== target && (get.mode() !== "identity" || player.identity !== "nei")) player.addExpose(0.15); + target.draw(); + } + "step 3"; + if (event.list.length) event.goto(1); }, - }, - zhuiji: { - mod: { - globalFrom: function (from, to) { - if (from.hp >= to.hp) return -Infinity; + ai: { + threaten: 1.3, + }, + subSkill: { + draw: { + trigger: { player: "dieAfter" }, + filter(event, player) { + return !game.hasPlayer(current => { + return current.hasSkill("shoucheng", null, null, false); + }, true); + }, + content() { + game.removeGlobalSkill("shoucheng_draw"); + }, + ai: { + noh: true, + skillTagFilter(player, tag, arg) { + if (player === _status.currentPhase || player.countCards("h") !== 1) return false; + return game.hasPlayer(current => { + return current.hasSkill("shoucheng") && player.isFriendOf(current); + }); + }, + }, }, }, }, - oldcihuai: { - audio: "cihuai", - trigger: { player: "phaseUseBegin" }, + hengzheng: { + audio: 2, + trigger: { player: "phaseDrawBegin1" }, + preHidden: true, filter: function (event, player) { - return player.countCards("h") > 0; + return !event.numFixed && (player.hp == 1 || player.countCards("h") == 0); }, check: function (event, player) { - return !player.countCards("h", "sha"); + var num = game.countPlayer(function (current) { + if (current.countCards("he") && current != player && get.attitude(player, current) <= 0) { + return true; + } + if (current.countCards("j") && current != player && get.attitude(player, current) > 0) { + return true; + } + }); + return num >= 2; }, content: function () { - player.showHandcards(); - if (!player.countCards("h", "sha")) player.addTempSkill("oldcihuai2"); - }, - }, - oldcihuai2: { - group: "oldcihuai3", - prompt: "视为使用一张杀", - enable: "chooseToUse", - viewAs: { name: "sha", isCard: true }, - filterCard: function () { - return false; + "step 0"; + var targets = game.filterPlayer(); + targets.remove(player); + targets.sort(lib.sort.seat); + event.targets = targets; + event.num = 0; + trigger.changeToZero(); + player.line(targets, "green"); + "step 1"; + if (num < event.targets.length) { + if (event.targets[num].countCards("hej")) { + player.gainPlayerCard(event.targets[num], "hej", true); + } + event.num++; + event.redo(); + } }, - selectCard: -1, ai: { - presha: true, - respondSha: true, + noh: true, + skillTagFilter: function (player, tag) { + if (tag == "noh") { + if (player.countCards("h") != 1) return false; + } + }, + threaten: function (player, target) { + if (target.hp == 1) return 2.5; + return 1; + }, }, }, - oldcihuai3: { - trigger: { - player: ["loseAfter"], - global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter", "die"], - }, - silent: true, - firstDo: true, + yongjue: { + audio: 2, + trigger: { global: "useCardAfter" }, + usable: 1, filter: function (event, player) { - if (event.name == "die") return true; - var evt = event.getl(player); - return evt && evt.hs && evt.hs.length > 0; + if (event.card.name != "sha") return false; + if (event.player == player) return false; + if (event.targets.includes(player)) return false; + if (event.cards) { + for (var i = 0; i < event.cards.length; i++) { + if (get.position(event.cards[i], true) == "o") return true; + } + } + return false; }, + frequent: true, content: function () { - player.removeSkill("oldcihuai2"); + var cards = trigger.cards.slice(0); + for (var i = 0; i < cards.length; i++) { + if (get.position(cards[i], true) != "o") { + cards.splice(i--, 1); + } + } + player.gain(cards, "gain2"); }, }, - cihuai: { - trigger: { player: "phaseUseBegin" }, - direct: true, + guixiu: { + audio: 2, + trigger: { target: "useCardToTargeted" }, + frequent: true, filter: function (event, player) { - return player.countCards("h", "sha") == 0; + return event.card.name == "sha" && player.countCards("h") < player.hp; }, content: function () { - "step 0"; - player - .chooseTarget(get.prompt2("cihuai"), function (card, player, target) { - return player.canUse({ name: "sha", isCard: true }, target); - }) - .set("ai", function (target) { - var player = _status.event.player; - return get.effect(target, { name: "sha", isCard: true }, player, player); - }); - "step 1"; - if (result.bool) { - player.logSkill("cihuai"); - player.showHandcards(); - player.useCard({ name: "sha", isCard: true }, result.targets); - } - }, - ai: { - expose: 0.2, + player.draw(); }, }, - jilei: { - trigger: { player: "damageEnd" }, + cunsi: { + skillAnimation: true, + animationColor: "orange", audio: 2, - direct: true, - filter: function (event) { - return event.source && event.source.isIn(); + unique: true, + enable: "phaseUse", + mark: true, + limited: true, + derivation: "yongjue", + filter: function (event, player) { + return !player.storage.cunsi && player.countCards("h") && !player.isTurnedOver(); + }, + init: function (player) { + player.storage.cunsi = false; + }, + filterTarget: function (card, player, target) { + return player != target && target.hasSex("male"); }, content: function () { "step 0"; - player - .chooseControl("basic", "trick", "equip", "cancel2", function () { - var source = _status.event.source; - if (get.attitude(_status.event.player, source) > 0) return "cancel2"; - var list = ["basic", "trick", "equip"].filter(function (name) { - return !source.storage.jilei2 || !source.storage.jilei2.includes(name); - }); - if (!list.length) return "cancel2"; - if ( - list.includes("trick") && - source.countCards("h", function (card) { - return get.type(card, source) == "trick" && source.hasValueTarget(card); - }) > 1 - ) - return "trick"; - return list[0]; - }) - .set("prompt", get.prompt2("jilei", trigger.source)) - .set("source", trigger.source); + player.awakenSkill("cunsi"); + var cards = player.getCards("h"); + player.give(cards, target); "step 1"; - if (result.control != "cancel2") { - player.logSkill("jilei", trigger.source); - player.popup(get.translation(result.control) + "牌"); - trigger.source.addTempSkill("jilei2", { player: "phaseBegin" }); - trigger.source.storage.jilei2.add(result.control); - trigger.source.updateMarks("jilei2"); - } - }, - ai: { - maixie_defend: true, - threaten: 0.7, + target.addSkills("yongjue"); + "step 2"; + target.markSkillCharacter("yongjue", player, "存嗣", '
    【勇决】
    每当其他角色于回合内使用一张杀,若目标不是你,你可以获得之,每回合限一次
    '); + player.turnOver(); }, - }, - jilei2: { - unique: true, - charlotte: true, intro: { - content: function (storage) { - return "不能使用、打出或弃置" + get.translation(storage) + "牌"; - }, - }, - init: function (player, skill) { - if (!player.storage[skill]) player.storage[skill] = []; + content: "limited", }, - mark: true, - onremove: true, - mod: { - cardDiscardable: function (card, player) { - if (player.storage.jilei2.includes(get.type(card, "trick"))) return false; - }, - cardEnabled: function (card, player) { - if (player.storage.jilei2.includes(get.type(card, "trick"))) { - var hs = player.getCards("h"), - cards = [card]; - if (Array.isArray(card.cards)) cards.addArray(card.cards); - for (var i of cards) { - if (hs.includes(i)) return false; - } - } - }, - cardRespondable: function (card, player) { - if (player.storage.jilei2.includes(get.type(card, "trick"))) { - var hs = player.getCards("h"), - cards = [card]; - if (Array.isArray(card.cards)) cards.addArray(card.cards); - for (var i of cards) { - if (hs.includes(i)) return false; - } - } - }, - cardSavable: function (card, player) { - if (player.storage.jilei2.includes(get.type(card, "trick"))) { - var hs = player.getCards("h"), - cards = [card]; - if (Array.isArray(card.cards)) cards.addArray(card.cards); - for (var i of cards) { - if (hs.includes(i)) return false; + ai: { + order: 4, + result: { + target: function (player, target) { + if (target.isMin()) return 0; + if (player.hp > 1) { + if (game.phaseNumber < game.players.length) return 0; + if (target.hp == 1 && target.maxHp > 2) return 0; + if (get.attitude(player, target) < 5) return 0; } - } + if (get.attitude(player, target) < 5) return 0; + if (target.hp == 1 && target.maxHp > 2) return 0.2; + if (target == game.me) return 1.2; + return 1; + }, }, + expose: 0.5, + threaten: 1.5, }, }, - danlao: { + fenming: { audio: 2, + trigger: { player: "phaseJieshuBegin" }, + check: function (event, player) { + var num = game.countPlayer(function (current) { + if (current.isLinked() && current.countCards("he")) { + return get.effect(current, { name: "guohe_copy2" }, player, player); + } + }); + return num < 0; + }, filter: function (event, player) { - return (event.card.name == "sha" || get.type(event.card) == "trick") && event.targets && event.targets.length > 1; + return player.isLinked(); }, - check: function (event, player) { - return event.getParent().excluded.includes(player) || get.tag(event.card, "multineg") || get.effect(player, event.card, event.player, player) <= 0; + preHidden: true, + prompt: "是否发动【奋命】?", + logTarget: function (event, player) { + return game.filterPlayer(function (current) { + if (current.isLinked() && current.countCards("he")) { + return true; + } + }); }, - trigger: { target: "useCardToTargeted" }, content: function () { - trigger.getParent().excluded.add(player); - player.draw(); - }, - ai: { - effect: { - target_use(card) { - if (get.type(card) != "trick") return; - if (card.name == "tiesuo") return [0, 0]; - if (card.name == "yihuajiemu") return [0, 1]; - if (get.tag(card, "multineg")) return [0, 2]; - }, - }, + "step 0"; + event.targets = game.filterPlayer(function (current) { + if (current.isLinked() && current.countCards("he")) { + return true; + } + }); + event.num = 0; + event.targets.sort(lib.sort.seat); + "step 1"; + if (event.num < event.targets.length) { + var target = event.targets[event.num]; + if (player == target) { + player.chooseToDiscard(true, "he"); + } else { + player.discardPlayerCard(true, "he", target); + } + event.num++; + event.redo(); + } }, }, - taichen: { + duanxie: { enable: "phaseUse", usable: 1, + audio: 2, + filter: function (event, player) { + return game.hasPlayer(function (current) { + return current != player && !current.isLinked(); + }); + }, filterTarget: function (card, player, target) { - return player.canUse("sha", target); + return player != target && !target.isLinked(); + }, + selectTarget: function () { + return [1, Math.max(1, _status.event.player.getDamagedHp())]; }, content: function () { - "step 0"; - player.loseHp(); - "step 1"; - player.useCard({ name: "sha", isCard: true }, target, false); + if (!target.isLinked()) target.link(); + }, + contentAfter: function () { + if (!player.isLinked()) player.link(); }, ai: { - order: 1, result: { - target: function (player, target) { - if (player.hp > 2 && player.hp > target.hp && target.countCards("he") < 4) { - return get.effect(target, { name: "sha" }, player, target); + player(player) { + return player.isLinked() ? 0 : -0.8; + }, + target(player, target) { + return get.effect(target, { name: "tiesuo" }, player, target) / get.attitude(target, target); + }, + }, + order: 2, + expose: 0.3, + effect: { + target: function (card) { + if (card.name == "tiesuo") { + return 0.5; } - return 0; }, }, }, }, - naman: { + xiaoguo: { audio: 2, - trigger: { global: "respondAfter" }, + trigger: { global: "phaseJieshuBegin" }, filter: function (event, player) { - if (event.card.name != "sha") return false; - if (event.player == player) return false; - if (event.cards) { - for (var i = 0; i < event.cards.length; i++) { - if (get.position(event.cards[i], true) == "o") return true; - } - } - return false; + return event.player.isIn() && event.player != player && player.countCards("h"); }, - frequent: true, + direct: true, content: function () { - var cards = trigger.cards.slice(0); - for (var i = 0; i < cards.length; i++) { - if (get.position(cards[i], true) != "o") { - cards.splice(i--, 1); - } + "step 0"; + var next = player.chooseToDiscard(get.prompt("xiaoguo", trigger.player)); + next.set("ai", function (card) { + return _status.event.eff - get.useful(card); + }); + next.set("logSkill", ["xiaoguo", trigger.player]); + next.set( + "eff", + (function () { + if (trigger.player.hasSkillTag("noe")) return get.attitude(_status.event.player, trigger.player); + return get.damageEffect(trigger.player, player, _status.event.player); + })() + ); + "step 1"; + if (result.bool) { + if (get.mode() !== "identity" || player.identity !== "nei") player.addExpose(0.15); + trigger.player + .chooseToDiscard("he", "弃置一张装备牌并令" + get.translation(player) + "摸一张牌,或受到1点伤害", { type: "equip" }) + .set("ai", function (card) { + if (_status.event.damage > 0) return 0; + if (_status.event.noe) return 12 - get.value(card); + return -_status.event.damage - get.value(card); + }) + .set("damage", get.damageEffect(trigger.player, player, trigger.player)) + .set("noe", trigger.player.hasSkillTag("noe")); + } else { + event.finish(); + } + "step 2"; + if (result.bool) { + player.draw(); + } else { + trigger.player.damage(); } - game.delay(0.5); - player.gain(cards, "gain2"); }, }, - xiemu: { + suishi: { audio: 2, - enable: "phaseUse", - usable: 1, - filter: function (event, player) { - return player.countCards("h", "sha") > 0; + trigger: { global: "dying" }, + forced: true, + popup: false, + //priority:12, + check: function () { + return false; }, - filterCard: { name: "sha" }, - check: function (card) { - return 6 - get.value(card); + filter: function (event, player) { + return event.player != player && event.parent.name == "damage" && event.parent.source && event.parent.source != event.player; }, content: function () { "step 0"; - var list = lib.group.filter(function (group) { - return ( - ["wei", "shu", "wu", "qun"].includes(group) || - game.hasPlayer(function (current) { - return current.group == group; - }) - ); - }); - if (player.storage.xiemu2) list.removeArray(player.storage.xiemu2); - var list2 = list.slice(0); - list2.sort(function (a, b) { - return lib.skill.xiemu.count(b) - lib.skill.xiemu.count(a); - }); - player - .chooseControl(list) - .set("prompt", "请选择一个势力") + var str; + if (trigger.parent.source == player) { + str = "随势:是否摸一张牌?"; + } else { + str = "随势:是否令" + get.translation(player) + "摸一张牌?"; + } + trigger.parent.source + .chooseBool(str) .set("ai", function () { - return _status.event.group; + return get.attitude(_status.event.player, _status.event.target) > 0; }) - .set("group", list2[0]); + .set("target", player); "step 1"; - player.popup(result.control + 2, get.groupnature(result.control)); - game.log(player, "选择了", "#g" + get.translation(result.control + 2)); - player.addTempSkill("xiemu2", { player: "phaseBegin" }); - player.storage.xiemu2.add(result.control); - player.updateMarks("xiemu2"); + if (result.bool) { + player.logSkill("suishi"); + trigger.parent.source.line(player, "green"); + player.draw(); + } }, ai: { - order: 1, - result: { player: 1 }, - }, - count: function (group) { - var player = _status.event.player; - return game.countPlayer(function (current) { - return current != player && current.group == group && get.attitude(current, player) < 0; - }); + halfneg: true, }, + group: "suishi2", }, - xiemu2: { - onremove: true, - mark: true, + suishi2: { + trigger: { global: "dieAfter" }, forced: true, - audio: "xiemu", - intro: { - content: function (storage) { - return "已指定" + get.translation(storage) + "势力"; - }, - }, - trigger: { - target: "useCardToTargeted", - }, - init: function (player) { - if (!player.storage.xiemu2) player.storage.xiemu2 = []; + popup: false, + check: function () { + return false; }, filter: function (event, player) { - if (!player.storage.xiemu2) return false; - if (get.color(event.card) != "black") return false; - if (!event.player) return false; - if (event.player == player || !player.storage.xiemu2.includes(event.player.group)) return false; - return true; + return event.player != player && event.source && event.source != player && event.source != event.player; }, content: function () { - player.draw(2); + "step 0"; + var str; + if (trigger.source == player) { + str = "随势:是否失去1点体力?"; + } else { + str = "随势:是否令" + get.translation(player) + "失去1点体力?"; + } + trigger.source + .chooseBool(str) + .set("ai", function () { + return get.attitude(_status.event.player, _status.event.target) < 0; + }) + .set("target", player); + "step 1"; + if (result.bool) { + player.logSkill("suishi"); + trigger.source.line(player, "green"); + player.loseHp(); + } }, }, - oldxiemu: { - audio: "xiemu", - trigger: { target: "useCardToTargeted" }, - filter: function (event, player) { - if (get.color(event.card) != "black") return false; - if (!event.player) return false; - if (event.player == player) return false; - if (get.mode() != "guozhan") return false; - return player.countCards("h", "sha") > 0; + sijian: { + trigger: { + player: "loseAfter", + global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], }, direct: true, + audio: 2, + preHidden: true, + filter: function (event, player) { + if (player.countCards("h")) return false; + if (event.name == "gain" && event.player == player) return false; + var evt = event.getl(player); + return evt && evt.hs && evt.hs.length > 0; + }, content: function () { "step 0"; - var next = player.chooseToDiscard("协穆:是否弃置一张杀并摸两张牌?", { name: "sha" }); - next.set("ai", function (card) { - return 9 - get.value(card); - }); - next.logSkill = "xiemu"; + player + .chooseTarget(get.prompt("sijian"), "弃置一名其他角色的一张牌", function (card, player, target) { + return player != target && target.countCards("he") > 0; + }) + .set("ai", function (target) { + return -get.attitude(_status.event.player, target); + }) + .setHiddenSkill(event.name); "step 1"; if (result.bool) { - player.draw(2); + player.logSkill("sijian", result.targets); + event.target = result.targets[0]; + player.discardPlayerCard(event.target, true); + } else { + event.finish(); } }, ai: { - effect: { - target_use(card, player, target) { - if (get.color(card) == "black" && target.countCards("h") > 0) { - return [1, 0.5]; - } - }, - }, + expose: 0.2, }, }, - spmengjin: { - trigger: { player: "shaBegin" }, + quji: { + audio: 2, + enable: "phaseUse", + usable: 1, + position: "he", + filterCard: true, + selectCard: function () { + var player = _status.event.player; + return player.getDamagedHp(); + }, + filterTarget: function (card, player, target) { + return target.hp < target.maxHp; + }, filter: function (event, player) { - return event.target.countCards("he") > 0; + return player.hp < player.maxHp; + }, + selectTarget: function () { + return [1, ui.selected.cards.length]; + }, + complexSelect: true, + check: function (card) { + if (get.color(card) == "black") return -1; + return 9 - get.value(card); }, - direct: true, content: function () { "step 0"; - var att = get.attitude(player, trigger.target); - player.choosePlayerCard(get.prompt("spmengjin", trigger.target), "he", trigger.target).ai = function (button) { - var val = get.buttonValue(button); - if (att > 0) return -val; - return val; - }; + target.recover(); "step 1"; - if (result.bool) { - trigger.target.discard(result.links); - player.logSkill("spmengjin", trigger.target); - trigger.target.addTempSkill("mengjin2", "shaAfter"); + if (target == targets[targets.length - 1]) { + for (var i = 0; i < cards.length; i++) { + if (get.color(cards[i], player) == "black") { + player.loseHp(); + break; + } + } } }, ai: { - expose: 0.2, + result: { + target: 1, + }, + order: 6, }, }, - fenxun_old: { + junbing: { audio: 2, - trigger: { player: "shaBefore" }, - direct: true, + trigger: { global: "phaseJieshuBegin" }, filter: function (event, player) { - return event.targets.length == 1; + return event.player.countCards("h") <= 1 && (player == event.player || player.hasSkill("junbing")); + }, + direct: true, + checkx: function (target, player) { + if (target) { + var num = target.countCards("h"); + var att = get.attitude(player, target); + if (num == 0) return true; + if (num == 1) return att > -1; + if (num == 2) return att > 0; + return att > 1; + } + return false; }, - position: "he", content: function () { "step 0"; - player.chooseCardTarget({ - filterCard: lib.filter.cardDiscardable, - filterTarget: function (card, player, target) { - var trigger = _status.event.getTrigger(); - return lib.filter.targetEnabled(trigger.card, player, target) && target != trigger.targets[0]; - }, - ai1: function (card) { - return 6 - get.value(card); - }, - ai2: function (target) { - var trigger = _status.event.getTrigger(); - var player = _status.event.player; - return get.effect(target, trigger.card, player, player); - }, - prompt: get.prompt2("fenxun"), - }); + event.target = player; + event.player = trigger.player; + var prompt; + if (player == event.player) prompt = "是否发动【郡兵】摸一张牌?"; + else prompt = "###是否对" + get.translation(event.target) + "发动【郡兵】?###" + (event.player == event.target ? "摸一张牌" : "摸一张牌,将所有手牌交给该角色,然后该角色交给你等量的手牌"); + event.player.chooseBool(prompt).set("choice", lib.skill.junbing.checkx(event.target, event.player)); "step 1"; - if (result.bool) { - player.discard(result.cards); - trigger.targets.push(result.targets[0]); - player.logSkill("fenxun", result.targets); + if (!result.bool) { + event.finish(); + return; } + target.logSkill("junbing", player); + if (player == target) event.finish(); + player.draw(); + "step 2"; + var cards = player.getCards("h"); + player.give(cards, target); + event.num = cards.length; + "step 3"; + var he = target.getCards("he"); + if (!he.length) event.finish(); + else if (he.length <= num) event._result = { cards: he }; + else target.chooseCard("选择还给" + get.translation(player) + "的牌", true, event.num, "he"); + "step 4"; + target.give(result.cards, player); }, }, - rezhoufu: { - audio: "zhoufu", + xiongyi: { + skillAnimation: true, + animationColor: "gray", + unique: true, enable: "phaseUse", - usable: 1, - filter: function (event, player) { - return player.countCards("he") > 0; - }, - filterCard: true, + audio: 2, + limited: true, filterTarget: function (card, player, target) { - return target != player && !target.getExpansions("rezhoufu_judge").length; + if (get.mode() == "guozhan") { + if (player == target) return true; + if (player.identity == "unknown") { + if (!player.wontYe("qun")) return false; + return target.identity == "qun"; + } + return target.isFriendOf(player); + } else { + return true; + } }, - check: function (card) { - return 6 - get.value(card); + multitarget: true, + multiline: true, + selectTarget: function () { + if (get.mode() == "guozhan") return -1; + return [1, Infinity]; }, - position: "he", - discard: false, - lose: false, - delay: false, content: function () { - target.addToExpansion(cards, player, "give").gaintag.add("rezhoufu_judge"); - target.addSkill("rezhoufu_judge"); + "step 0"; + player.awakenSkill("xiongyi"); + game.asyncDraw(targets, 3); + "step 1"; + if (player.isDamaged()) { + if (get.mode() == "guozhan") { + if (player.isMinor(true)) { + player.recover(); + } + } else if (player.isMinHp()) { + player.recover(); + } + } }, ai: { order: 1, result: { - target: -1, - }, - }, - group: ["rezhoufu_losehp"], - subSkill: { - judge: { - audio: "zhoufu", - init: (player) => { - player.storage.rezhoufu_judge_markcount = 0; - }, - onremove: (player) => { - delete player.storage.rezhoufu_judge_markcount; - let cards = player.getExpansions("rezhoufu_judge"); - if (cards.length) player.loseToDiscardpile(cards); - }, - intro: { - content: "expansion", - }, - trigger: { player: "judgeBefore" }, - forced: true, - charlotte: true, - filter: function (event, player) { - return !event.directresult && player.getExpansions("rezhoufu_judge").length; - }, - content: function () { - trigger.directresult = player.getExpansions("rezhoufu_judge")[0]; - player.storage.rezhoufu_judge_markcount = 0; - }, - }, - losehp: { - audio: "zhoufu", - trigger: { global: "phaseEnd" }, - forced: true, - filter: function (event, player) { - return game.hasPlayer(function (current) { - return current.hasHistory("lose", function (evt) { - if (!evt || !evt.xs || !evt.xs.length) return false; - for (var i in evt.gaintag_map) { - if (evt.gaintag_map[i].includes("rezhoufu_judge")) return true; - } - return false; - }); - }); - }, - logTarget: function (current) { - return game - .filterPlayer(function (current) { - return current.hasHistory("lose", function (evt) { - if (!evt || !evt.xs || !evt.xs.length) return false; - for (var i in evt.gaintag_map) { - if (evt.gaintag_map[i].includes("rezhoufu_judge")) return true; - } - return false; - }); - }) - .sortBySeat(); - }, - content: function () { - var targets = game - .filterPlayer(function (current) { - return current.hasHistory("lose", function (evt) { - if (!evt || !evt.xs || !evt.xs.length) return false; - for (var i in evt.gaintag_map) { - if (evt.gaintag_map[i].includes("rezhoufu_judge")) return true; - } - return false; - }); - }) - .sortBySeat(); - while (targets.length) { - targets.shift().loseHp(); - } + target: function (player) { + var num = player.countCards("h"); + if (player.hp == 1) return 1; + if (player.hp == 2 && num <= 2) return 1; + if (player.hp == 3 && num <= 1) return 1; + if (game.phaseNumber < game.players.length * 2) return 0; + if (player.hasUnknown()) return 0; + return 1; }, }, }, }, - reyingbing: { - audio: "yingbin", - trigger: { global: "useCard" }, - forced: true, + gzshushen: { + audio: "shushen", + trigger: { player: "recoverAfter" }, + direct: true, filter: function (event, player) { - var cards = event.player.getExpansions("rezhoufu_judge"); - return cards.length && get.color(cards[0]) == get.color(event.card); + return game.hasPlayer(function (current) { + return player != current && player.sameIdentityAs(current); + }); + }, + content: function () { + "step 0"; + event.num = trigger.num || 1; + "step 1"; + player + .chooseTarget(get.prompt2("gzshushen"), function (card, player, target) { + return target != player && player.sameIdentityAs(target); + }) + .set("ai", function (target) { + return get.attitude(_status.event.player, target); + }); + "step 2"; + if (result.bool) { + player.logSkill("gzshushen", result.targets); + result.targets[0].draw(); + if (event.num > 1) { + event.num--; + event.goto(1); + } + } }, - logTarget: "player", + ai: { + threaten: 0.8, + expose: 0.1, + }, + }, + shushen: { + audio: 2, + trigger: { player: "recoverAfter" }, + direct: true, content: function () { "step 0"; - player.draw(); + event.count = trigger.num; "step 1"; - trigger.player.storage.rezhoufu_judge_markcount++; - if (trigger.player.storage.rezhoufu_judge_markcount >= 2) { - var cards = trigger.player.getExpansions("rezhoufu_judge"); - player.gain(cards, trigger.player, "give", "bySelf"); - trigger.player.removeSkill("rezhoufu_judge"); - } else trigger.player.markSkill("rezhoufu_judge"); + player + .chooseTarget(get.prompt("shushen"), "令一名其他角色选择摸两张牌或回复1点体力", function (card, player, target) { + return target != player; + }) + .set("ai", function (target) { + return get.attitude(_status.event.player, target); + }); + "step 2"; + if (result.bool) { + event.count--; + player.logSkill("shushen", result.targets); + result.targets[0].chooseDrawRecover(2, true); + if (event.count) event.goto(1); + } }, ai: { - combo: "rezhoufu", + threaten: 0.8, + expose: 0.1, }, }, - zhoufu: { - audio: 2, - }, - yingbin: { + shenzhi: { audio: 2, + trigger: { player: "phaseZhunbeiBegin" }, + check: function (event, player) { + if (player.hp > 2) return false; + var cards = player.getCards("h"); + if (cards.length < player.hp) return false; + if (cards.length > 3) return false; + for (var i = 0; i < cards.length; i++) { + if (get.value(cards[i]) > 7 || get.tag(cards[i], "recover") >= 1) return false; + } + return true; + }, + filter: function (event, player) { + return player.countCards("h") > 0; + }, + preHidden: true, + content: function () { + "step 0"; + var cards = player.getCards("h"); + event.bool = cards.length >= player.hp; + player.discard(cards); + "step 1"; + if (event.bool) { + player.recover(); + } + }, }, - kuiwei: { + wuji: { + skillAnimation: true, + animationColor: "orange", audio: 2, trigger: { player: "phaseJieshuBegin" }, - check: function (event, player) { - if (player.isTurnedOver()) return true; - var num = game.countPlayer(function (current) { - return current.getEquip(1); - }); - return num > 1; + forced: true, + unique: true, + juexingji: true, + filter: function (event, player) { + return player.getStat("damage") >= 3 && !player.storage.wuji; }, content: function () { "step 0"; - player.turnOver(); + player.removeSkills("huxiao"); + player.gainMaxHp(); "step 1"; - var num = game.countPlayer(function (current) { - return current.getEquips(1).length; - }); - player.draw(2 + num); - player.addSkill("kuiwei2"); + player.recover(); + player.awakenSkill("wuji"); + player.storage.wuji = true; + + var card = get.cardPile("qinglong", "field"); + if (card) { + player.gain(card, "gain2", "log"); + } + }, + }, + xueji_old: { + audio: "xueji", + enable: "phaseUse", + usable: 1, + filter: function (event, player) { + return player.hp < player.maxHp && player.countCards("he", { color: "red" }) > 0; + }, + filterTarget: function (card, player, target) { + return player != target && get.distance(player, target, "attack") <= 1; + }, + selectTarget: function () { + return [1, _status.event.player.maxHp - _status.event.player.hp]; + }, + position: "he", + filterCard: function (card) { + return get.color(card) == "red"; + }, + check: function (card) { + return 8 - get.useful(card); + }, + content: function () { + "step 0"; + target.damage(); + "step 1"; + target.draw(); }, ai: { + order: 7, + result: { + target: function (player, target) { + return get.damageEffect(target, player); + }, + }, + threaten: function (player, target) { + if (target.hp == 1) return 2; + if (target.hp == 2) return 1.5; + return 0.5; + }, + maixie: true, effect: { - target: function (card) { - if (card.name == "guiyoujie") return [0, 2]; + target: function (card, player, target) { + if (get.tag(card, "damage")) { + if (target.hp == target.maxHp && target.hasFriend()) return [0, 1]; + } + if (get.tag(card, "recover") && player.hp >= player.maxHp - 1) return [0, 0]; }, }, }, }, - kuiwei2: { - trigger: { player: "phaseDrawBegin" }, + //FW关银屏 + oldhuxiao: { + audio: "huxiao", + trigger: { player: "shaMiss" }, forced: true, - audio: false, content: function () { - var num = game.countPlayer(function (current) { - return current.getEquips(1).length; - }); - if (num >= player.countCards("he")) { - player.discard(player.getCards("he")); - } else if (num) { - player.chooseToDiscard("he", num, true); + if (player.stat[player.stat.length - 1].card.sha > 0) { + player.stat[player.stat.length - 1].card.sha--; } - player.removeSkill("kuiwei2"); }, }, - yanzheng: { - enable: "chooseToUse", - audio: 2, + oldwuji: { + unique: true, + audio: "wuji", + trigger: { player: "phaseJieshuBegin" }, filter: function (event, player) { - return player.hp < player.countCards("h") && player.countCards("e") > 0; - }, - viewAsFilter: function (player) { - return player.hp < player.countCards("h") && player.countCards("e") > 0; + return player.getStat("damage") >= 3 && !player.storage.oldwuji; }, - filterCard: true, - position: "e", - viewAs: { name: "wuxie" }, - prompt: "将一张装备区内的牌当无懈可击使用", - check: function (card) { - return 8 - get.equipValue(card); + forced: true, + juexingji: true, + skillAnimation: true, + animationColor: "orange", + content: function () { + "step 0"; + player.removeSkills("oldhuxiao"); + player.gainMaxHp(); + "step 1"; + player.recover(); + player.awakenSkill("oldwuji"); }, - threaten: 1.2, }, - tongji: { - global: "tongji_disable", + xueji: { audio: 2, - trigger: { global: "useCard1" }, - forced: true, + enable: "phaseUse", + usable: 1, filter: function (event, player) { - return event.targets.includes(player) && player != event.player && event.card.name == "sha" && player.hp < player.countCards("h"); + return player.countCards("he", { color: "red" }) > 0; }, - content: function () {}, - ai: { - neg: true, + filterTarget: true, + selectTarget: function () { + var player = _status.event.player; + return [1, Math.max(1, player.getDamagedHp())]; }, - unique: true, - gainable: true, - subSkill: { - disable: { - mod: { - targetEnabled: function (card, player, target) { - if (card.name == "sha") { - if (player.hasSkill("tongji")) return; - if (target.hasSkill("tongji")) return; - if ( - game.hasPlayer(function (current) { - return current.hasSkill("tongji") && current.hp < current.countCards("h") && player.inRange(current); - }) - ) { - return false; - } - } - }, + position: "he", + filterCard: { color: "red" }, + check: function (card) { + return 8 - get.value(card); + }, + multitarget: true, + multiline: true, + line: "fire", + content: function () { + "step 0"; + event.delay = false; + for (var i = 0; i < targets.length; i++) { + if (!targets[i].isLinked()) { + targets[i].link(true); + event.delay = true; + } + } + "step 1"; + if (event.delay) { + game.delay(); + } + "step 2"; + targets[0].damage("fire", "nocard"); + }, + ai: { + damage: true, + fireAttack: true, + threaten: 1.5, + order: 7, + result: { + target: function (player, target) { + var eff = get.damageEffect(target, player, target, "fire"); + if (target.isLinked()) { + return eff / 10; + } else { + return eff; + } }, }, }, }, - wangzun: { - audio: 2, - audioname: ["old_yuanshu"], - trigger: { global: "phaseZhunbeiBegin" }, - check: function (event, player) { - var att = get.attitude(player, event.player); - return !game.hasPlayer(function (current) { - return get.attitude(player, current) < att; - }); - }, + huxiao: { + trigger: { source: "damageSource" }, + forced: true, filter: function (event, player) { - return event.player != player && !player.storage.wangzun; + if (event._notrigger.includes(event.player) || !event.player.isIn()) return false; + return event.hasNature("fire"); }, logTarget: "player", content: function () { - player.draw(); - player.markSkill("wangzun"); - player.storage.wangzun = trigger.player; - trigger.player.addTempSkill("wangzun3"); - }, - ai: { - expose: 0.2, - }, - intro: { - content: "player", + if (!player.storage.huxiao3) { + player.storage.huxiao3 = []; + } + player.storage.huxiao3.add(trigger.player); + trigger.player.draw(); + player.addTempSkill("huxiao3"); }, - group: "wangzun2", }, - wangzun2: { - trigger: { player: "phaseZhunbeiBegin" }, - silent: true, - content: function () { - player.unmarkSkill("wangzun"); - player.storage.wangzun = null; + huxiao3: { + onremove: true, + mark: true, + intro: { + content: "players", }, - }, - wangzun3: { mod: { - maxHandcard: function (player, num) { - return num - 1; + cardUsableTarget: function (card, player, target) { + if (player.storage.huxiao3 && player.storage.huxiao3.includes(target)) return true; }, }, }, - kaikang: { + aocai: { audio: 2, - trigger: { global: "useCardToTargeted" }, - filter: function (event, player) { - return event.card.name == "sha" && get.distance(player, event.target) <= 1 && event.target.isIn(); - }, - check: function (event, player) { - return get.attitude(player, event.target) >= 0; - }, - logTarget: "target", - content: function () { - "step 0"; - player.draw(); - if (trigger.target != player) { - player.chooseCard(true, "he", "交给" + get.translation(trigger.target) + "一张牌").set("ai", function (card) { - if (get.position(card) == "e") return -1; - if (card.name == "shan") return 1; - if (get.type(card) == "equip") return 0.5; - return 0; - }); - } else { - event.finish(); - } - "step 1"; - player.give(result.cards, trigger.target, "give"); - game.delay(); - event.card = result.cards[0]; - "step 2"; - if (trigger.target.getCards("h").includes(card) && get.type(card) == "equip") { - trigger.target.chooseUseTarget(card); - } - }, - ai: { - threaten: 1.1, + audioname: ["gz_zhugeke"], + enable: ["chooseToUse", "chooseToRespond"], + hiddenCard: function (player, name) { + if (player != _status.currentPhase && get.type(name) == "basic" && lib.inpile.includes(name)) return true; }, - }, - liangzhu: { - audio: 2, - trigger: { global: "recoverAfter" }, - direct: true, filter: function (event, player) { - return event.player.isPhaseUsing(); + if (event.responded || player == _status.currentPhase || event.aocai) return false; + for (var i of lib.inpile) { + if (get.type(i) == "basic" && event.filterCard(get.autoViewAs({ name: i }, "unsure"), player, event)) return true; + } + return false; }, + delay: false, content: function () { "step 0"; - if (player == trigger.player) { - player - .chooseControl("摸一张", "摸两张", "cancel2", function () { - return "摸两张"; - }) - .set("prompt", get.prompt2("liangzhu")); - event.single = true; - } else { - player - .chooseTarget(get.prompt2("liangzhu"), function (card, player, target) { - return target == _status.event.player || target == _status.event.target; - }) - .set("target", trigger.player) - .set("ai", function (target) { - var player = _status.event.player; - if (player == target) return 1; - return get.attitude(player, target) - 1.5; - }); + var evt = event.getParent(2); + evt.set("aocai", true); + var cards = get.cards(get.mode() != "guozhan" && player.countCards("h") == 0 ? 4 : 2); + for (var i = cards.length - 1; i >= 0; i--) { + ui.cardPile.insertBefore(cards[i].fix(), ui.cardPile.firstChild); } - "step 1"; - if (event.single) { - if (result.control != "cancel2") { - player.logSkill("liangzhu", player); - if (result.control == "摸一张") { - player.draw(); - } else { - player.draw(2); - if (!player.storage.liangzhu) player.storage.liangzhu = []; - player.storage.liangzhu.add(player); + var aozhan = player.hasSkill("aozhan"); + player + .chooseButton(["傲才:选择要" + (evt.name == "chooseToUse" ? "使用" : "打出") + "的牌", cards]) + .set("filterButton", function (button) { + return _status.event.cards.includes(button.link); + }) + .set( + "cards", + cards.filter(function (card) { + if (aozhan && card.name == "tao") { + return ( + evt.filterCard( + { + name: "sha", + isCard: true, + cards: [card], + }, + evt.player, + evt + ) || + evt.filterCard( + { + name: "shan", + isCard: true, + cards: [card], + }, + evt.player, + evt + ) + ); + } + return evt.filterCard(card, evt.player, evt); + }) + ) + .set("ai", function (button) { + var evt = _status.event.getParent(3); + if (evt && evt.ai) { + var tmp = _status.event; + _status.event = evt; + var result = (evt.ai || event.ai1)(button.link, _status.event.player, evt); + _status.event = tmp; + return result; } + return 1; + }); + "step 1"; + var evt = event.getParent(2); + if (result.bool && result.links && result.links.length) { + var card = result.links[0]; + var name = card.name, + aozhan = player.hasSkill("aozhan") && name == "tao"; + if (aozhan) { + name = evt.filterCard( + { + name: "sha", + isCard: true, + cards: [card], + }, + evt.player, + evt + ) + ? "sha" + : "shan"; } - } else if (result.bool) { - var target = result.targets[0]; - player.logSkill("liangzhu", target); - if (target == player) { - target.draw(); + if (evt.name == "chooseToUse") { + game.broadcastAll( + function (result, name) { + lib.skill.aocai_backup.viewAs = { + name: name, + cards: [result], + isCard: true, + }; + }, + card, + name + ); + evt.set("_backupevent", "aocai_backup"); + evt.set("openskilldialog", "请选择" + get.translation(card) + "的目标"); + evt.backup("aocai_backup"); } else { - target.draw(2); - if (target.storage.liangzhu) { - target.storage.liangzhu.add(player); - } else { - target.storage.liangzhu = [player]; - } + delete evt.result.skill; + delete evt.result.used; + evt.result.card = get.autoViewAs(result.links[0]); + if (aozhan) evt.result.card.name = name; + evt.result.cards = [result.links[0]]; + evt.redo(); + return; } } + evt.goto(0); }, ai: { - expose: 0.1, - }, - }, - fanxiang: { - skillAnimation: true, - animationColor: "fire", - audio: 2, - unique: true, - juexingji: true, - derivation: "xiaoji", - trigger: { player: "phaseZhunbeiBegin" }, - filter: function (event, player) { - if (player.storage.fanxiang) return false; - return game.hasPlayer(function (current) { - return current.storage.liangzhu && current.storage.liangzhu.includes(player) && current.isDamaged(); - }); + effect: { + target: function (card, player, target, effect) { + if (get.tag(card, "respondShan")) return 0.7; + if (get.tag(card, "respondSha")) return 0.7; + }, + }, + order: 11, + respondShan: true, + respondSha: true, + result: { + player: function (player) { + if (_status.event.dying) return get.attitude(player, _status.event.dying); + return 1; + }, + }, }, - forced: true, - content: function () { - player.awakenSkill("fanxiang"); - player.gainMaxHp(); - player.recover(); - player.changeSkills(["xiaoji"], ["liangzhu"]); + }, + aocai_backup: { + sourceSkill: "aocai", + precontent: function () { + delete event.result.skill; + var name = event.result.card.name, + cards = event.result.card.cards.slice(0); + event.result.cards = cards; + var rcard = cards[0], + card; + if (rcard.name == name) card = get.autoViewAs(rcard); + else card = get.autoViewAs({ name, isCard: true }); + event.result.card = card; }, - ai: { - combo: "liangzhu", + filterCard: function () { + return false; }, + selectCard: -1, }, - mingshi: { - audio: 2, - trigger: { player: "damageBegin3" }, + hongyuan: { + trigger: { player: "phaseDrawBegin2" }, direct: true, + audio: 2, filter: function (event, player) { - return event.source && event.source.hp > player.hp; + return !event.numFixed && event.num > 0; }, content: function () { "step 0"; - var next = player.chooseToDiscard(get.prompt2("mingshi"), { color: "black" }); - next.set("ai", function (card) { - return 9 - get.value(card); - }); - next.set("logSkill", "mingshi"); + var check; + if (player.countCards("h") == 0) { + check = false; + } else { + check = + game.countPlayer(function (current) { + return player != current && get.attitude(player, current) > 1; + }) >= 2; + } + if (get.is.versus()) { + event.versus = true; + player.chooseBool(get.prompt2("hongyuan")).ai = function () { + return ( + game.countPlayer(function (current) { + return player.side == current.side; + }) > 2 + ); + }; + } else { + player + .chooseTarget( + get.prompt2("hongyuan"), + [1, 2], + function (card, player, target) { + return player != target; + }, + function (target) { + if (!_status.event.check) return 0; + return get.attitude(_status.event.player, target); + } + ) + .set("check", check); + } "step 1"; if (result.bool) { + var targets; + if (event.versus) { + targets = game.filterPlayer(function (current) { + return current != player && current.side == player.side; + }); + } else { + targets = result.targets; + } + player.logSkill("hongyuan", targets); + game.asyncDraw(targets); trigger.num--; } }, - ai: { - threaten: 0.8, - }, }, - lirang: { + huanshi: { audio: 2, - trigger: { - player: "loseAfter", - global: "loseAsyncAfter", - }, + trigger: { global: "judge" }, filter: function (event, player) { - if (!game.hasPlayer(current => current != player)) return false; - if (event.type != "discard" || event.getlx === false) return false; - var evt = event.getl(player); - if (!evt || !evt.cards2) return false; - for (var i = 0; i < evt.cards2.length; i++) { - if (get.position(evt.cards2[i]) == "d") { - return true; - } + return player.countCards("he") > 0; + }, + logTarget: "player", + check: function (event, player) { + if (get.attitude(player, event.player) <= 0) return false; + var cards = player.getCards("he"); + var judge = event.judge(event.player.judging[0]); + for (var i = 0; i < cards.length; i++) { + var judge2 = event.judge(cards[i]); + if (judge2 > judge) return true; + if (_status.currentPhase != player && judge2 == judge && get.color(cards[i]) == "red" && get.useful(cards[i]) < 5) return true; } return false; }, - direct: true, - preHidden: true, content: function () { "step 0"; - if (trigger.delay == false) game.delay(); - event.cards = []; - var cards2 = trigger.getl(player).cards2; - for (var i = 0; i < cards2.length; i++) { - if (get.position(cards2[i], true) == "d") { - event.cards.push(cards2[i]); - } - } - if (_status.connectMode) - game.broadcastAll(function () { - _status.noclearcountdown = true; - }); - event.given_map = {}; - "step 1"; - var goon = false; - for (var i = 0; i < event.cards.length; i++) { - if (event.cards[i].name == "du") { - goon = true; - break; - } - } - if (!goon) { - goon = game.hasPlayer(function (current) { - return player != current && get.attitude(player, current) > 1; - }); - } - player - .chooseButton(["礼让:是否分配本次弃置的牌?", event.cards], [1, event.cards.length]) + var target = trigger.player; + var judge = trigger.judge(target.judging[0]); + var attitude = get.attitude(target, player); + target + .choosePlayerCard("请选择代替判定的牌", "he", "visible", true, player) .set("ai", function (button) { - if (_status.event.goon && ui.selected.buttons.length == 0) return 1 + Math.abs(get.value(button.link)); - return 0; - }) - .set("goon", goon) - .setHiddenSkill("lirang"); - "step 2"; - if (result.bool) { - event.cards.removeArray(result.links); - event.togive = result.links.slice(0); - player - .chooseTarget("选择一名其他角色获得" + get.translation(result.links), true, lib.filter.notMe) - .set("ai", function (target) { - var att = get.attitude(_status.event.player, target); - if (_status.event.enemy) { - return -att; - } else if (att > 0) { - return att / (1 + target.countCards("h")); + var card = button.link; + var judge = _status.event.judge; + var attitude = _status.event.attitude; + var result = trigger.judge(card) - judge; + var player = _status.event.player; + if (result > 0) { + return 20 + result; + } + if (result == 0) { + if (_status.currentPhase == player) return 0; + if (attitude >= 0) { + return get.color(card) == "red" ? 7 : 0 - get.value(card); } else { - return att / 100; + return get.color(card) == "black" ? 10 : 0 + get.value(card); } - }) - .set("enemy", get.value(event.togive[0], player, "raw") < 0); - } else event.goto(4); - "step 3"; - if (result.targets.length) { - var id = result.targets[0].playerid, - map = event.given_map; - if (!map[id]) map[id] = []; - map[id].addArray(event.togive); - } - if (cards.length > 0) event.goto(1); - "step 4"; - if (_status.connectMode) { - game.broadcastAll(function () { - delete _status.noclearcountdown; - game.stopCountChoose(); - }); - } - var list = [], - targets = []; - for (var i in event.given_map) { - var source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; - list.push([source, event.given_map[i]]); - targets.push(source); - } - if (targets.length) { - player.logSkill("lirang", targets); - game.loseAsync({ - gain_list: list, - giver: player, - animate: "gain2", - }).setContent("gaincardMultiple"); - } - }, - ai: { - expose: 0.1, - effect: { - target: function (card, player, target, current) { - if (target.hasFriend() && get.tag(card, "discard")) { - if (current < 0) return 0; - return [1, 1]; } - }, - }, - }, - }, - moukui: { - audio: 2, - audioname: ["sp_mushun"], - trigger: { player: "useCardToPlayered" }, - direct: true, - filter: function (event, player) { - return event.card.name == "sha"; - }, - content: function () { - "step 0"; - var controls = ["draw_card"]; - if (trigger.target.countCards("he")) { - controls.push("discard_card"); - } - controls.push("cancel"); - player - .chooseControl(controls) - .set("ai", function () { - var trigger = _status.event.getTrigger(); - if (trigger.target.countCards("he") && get.attitude(_status.event.player, trigger.target) < 0) { - return "discard_card"; + if (attitude >= 0) { + return get.color(card) == "red" ? 0 : -10 + result; } else { - return "draw_card"; + return get.color(card) == "black" ? 0 : -10 + result; } }) - .set("prompt", get.prompt2("moukui")); + .set("filterButton", function (button) { + var player = _status.event.target; + var card = button.link; + var mod2 = game.checkMod(card, player, "unchanged", "cardEnabled2", player); + if (mod2 != "unchanged") return mod2; + var mod = game.checkMod(card, player, "unchanged", "cardRespondable", player); + if (mod != "unchanged") return mod; + return true; + }) + .set("judge", judge) + .set("attitude", attitude); "step 1"; - if (result.control == "draw_card") { - player.draw(); - player.logSkill("moukui"); - } else if (result.control == "discard_card" && trigger.target.countCards("he")) { - player.discardPlayerCard(trigger.target, "he", true).logSkill = ["moukui", trigger.target]; - } else event.finish(); + if (result.bool) { + event.card = result.links[0]; + player.respond(event.card, "highlight", "noOrdering").nopopup = true; + } else { + event.finish(); + } "step 2"; - player.addTempSkill("moukui2", "shaEnd"); + if (result.bool) { + if (trigger.player.judging[0].clone) { + trigger.player.judging[0].clone.classList.remove("thrownhighlight"); + game.broadcast(function (card) { + if (card.clone) { + card.clone.classList.remove("thrownhighlight"); + } + }, trigger.player.judging[0]); + game.addVideo("deletenode", player, get.cardsInfo([trigger.player.judging[0].clone])); + } + game.cardsDiscard(trigger.player.judging[0]); + trigger.player.judging[0] = event.card; + trigger.orderingCards.add(event.card); + game.log(trigger.player, "的判定牌改为", event.card); + game.delay(2); + } }, ai: { - expose: 0.1, - }, - }, - moukui2: { - audio: false, - trigger: { player: "shaMiss" }, - forced: true, - filter: function (event, player) { - return player.countCards("he") > 0; - }, - content: function () { - trigger.target.discardPlayerCard(player, true); + rejudge: true, + tag: { + rejudge: 1, + }, }, }, - shenxian: { + mingzhe: { audio: 2, - trigger: { global: ["loseAfter", "loseAsyncAfter"] }, + trigger: { + player: ["useCard", "respond", "loseAfter"], + global: "loseAsyncAfter", + }, + frequent: true, filter: function (event, player) { - if (event.type != "discard" || _status.currentPhase == player || event.getlx === false) return false; - if (event.name == "lose" && event.player == player) return false; - if (player.hasSkill("shenxian2")) return false; - var cards = event.cards.slice(0); + if (player == _status.currentPhase) return false; + if (event.name.indexOf("lose") != 0) return get.color(event.card) == "red"; + if (event.type != "discard") return false; var evt = event.getl(player); - if (evt && evt.cards) cards.removeArray(evt.cards); - for (var i = 0; i < cards.length; i++) { - if (get.type(cards[i], null, event.hs && event.hs.includes(cards[i]) ? event.player : false) == "basic" && cards[i].original != "j") { - return true; + if (evt && evt.cards2) { + for (var i = 0; i < evt.cards2.length; i++) { + if (get.color(evt.cards2[i], player) == "red") return true; } } return false; }, - frequent: true, content: function () { "step 0"; - if (trigger.delay == false) game.delay(); + event.count = 1; + if (trigger.name.indexOf("lose") == 0) { + event.count = 0; + var evt = trigger.getl(player); + for (var i = 0; i < evt.cards2.length; i++) { + if (get.color(evt.cards2[i], player) == "red") event.count++; + } + } "step 1"; player.draw(); - if (event.name == "shenxian") player.addTempSkill("shenxian2"); + event.count--; + "step 2"; + if (event.count && player.hasSkill(event.name) && !get.is.blocked(event.name, player)) { + player.chooseBool(get.prompt2("mingzhe")).set("frequentSkill", event.name); + } else event.finish(); + "step 3"; + if (result.bool) { + player.logSkill("mingzhe"); + event.goto(1); + } }, ai: { - threaten: 1.5, + threaten: 0.7, }, }, - shenxian2: { charlotte: true }, - qiangwu: { + + duwu: { audio: 2, enable: "phaseUse", - usable: 1, - content: function () { - "step 0"; - player.judge(card => { - if ( - game.hasPlayer(cur => { - return get.event("player").canUse("sha", cur); - }) - ) - return get.number(card); - return 1 / get.number(card); + filter: function (event, player) { + return game.hasPlayer(function (current) { + return current.hp > 0 && current.hp <= player.countCards("he") && player.inRange(current); }); - "step 1"; - player.storage.qiangwu = result.number; - player.addTempSkill("qiangwu3", "phaseUseEnd"); - }, - ai: { - result: { - player: 1, - }, - order: 11, }, - }, - qiangwu3: { - mod: { - targetInRange: function (card, player) { - if (card.name == "sha") { - const num = get.number(card); - if (num == "unsure" || num < player.storage.qiangwu) return true; - } - }, - cardUsable: function (card, player) { - if (card.name == "sha") { - const num = get.number(card); - if (num == "unsure" || num > player.storage.qiangwu) return true; - } - }, + filterCard: function () { + if (ui.selected.targets.length) return false; + return true; }, - trigger: { player: "useCard1" }, - filter: function (event, player) { - if (_status.currentPhase == player && event.card.name == "sha" && get.number(event.card) > player.storage.qiangwu && event.addCount !== false) return true; - return false; + position: "he", + selectCard: [1, Infinity], + complexSelect: true, + complexCard: true, + filterTarget: function (card, player, target) { + return target != player && target.hp > 0 && player.inRange(target) && ui.selected.cards.length == target.hp; }, - forced: true, - popup: false, - firstDo: true, - content: function () { - trigger.addCount = false; - if (player.stat[player.stat.length - 1].card.sha > 0) { - player.stat[player.stat.length - 1].card.sha--; + check: function (card) { + var player = _status.event.player; + if ( + game.hasPlayer(function (current) { + return current != player && current.hp > 0 && player.inRange(current) && ui.selected.cards.length == current.hp && get.damageEffect(current, player, player) > 0; + }) + ) + return 0; + switch (ui.selected.cards.length) { + case 0: + return 8 - get.value(card); + case 1: + return 6 - get.value(card); + case 2: + return 3 - get.value(card); + default: + return 0; } }, - }, - zhendu: { - audio: 2, - trigger: { global: "phaseUseBegin" }, - filter: function (event, player) { - return /*(get.mode()!='guozhan'||event.player!=player)&&*/ event.player.isIn() && player.countCards("h") > 0 && event.player.hasUseTarget({ name: "jiu" }, null, true); - }, - direct: true, - preHidden: true, content: function () { - "step 0"; - var nono = Math.abs(get.attitude(player, trigger.player)) < 3; - if (player == trigger.player || get.damageEffect(trigger.player, player, player) <= 0 || !trigger.player.hasUseTarget({ name: "jiu" }, null, true)) { - nono = true; - } else if (trigger.player.hp > 2) { - nono = true; - } else if (trigger.player.hp > 1 && player.countCards("h") < 3 && trigger.player.canUse("sha", player) && !player.countCards("h", "shan") && trigger.player.countCards("h") >= 3) { - nono = true; - } - var next = player.chooseToDiscard(get.prompt2("zhendu", trigger.player)); - next.set("ai", function (card) { - if (_status.event.nono) return -1; - return 7 - get.useful(card); - }); - next.set("logSkill", ["zhendu", trigger.player]); - next.set("nono", nono); - next.setHiddenSkill("zhendu"); - "step 1"; - if (result.bool) { - trigger.player.chooseUseTarget({ name: "jiu" }, true, "noTargetDelay", "nodelayx"); - } else { - event.finish(); - } - "step 2"; - if (result.bool && trigger.player != player) trigger.player.damage(); + player.addTempSkill("duwu2"); + target.damage("nocard"); }, ai: { - threaten: 2, - expose: 0.3, - }, - }, - qiluan: { - audio: "qiluan2", - preHidden: true, - trigger: { global: "phaseEnd" }, - frequent: true, - filter: function (event, player) { - return game.hasPlayer2(function (current) { - return current.getStat("kill") > 0; - }); - }, - prompt: function (event, player) { - var num = game.countPlayer2(function (current) { - return (current.getStat("kill") || 0) * (current == player ? 3 : 1); - }); - return get.prompt("qiluan") + "(可摸" + get.cnNumber(num) + "张牌)"; - }, - content: function () { - //if(get.mode()=='guozhan'){ - // player.draw(3); - //} - //else{ - player.draw( - game.countPlayer2(function (current) { - return (current.getStat("kill") || 0) * (current == player ? 3 : 1); - }) - ); - //} - }, - subSkill: { - draw: { - trigger: { global: "dieAfter" }, - frequent: true, - filter: function (event, player) { - return /*get.mode()!='guozhan'&&*/ player != event.source; - }, - content: function () { - player.draw(); + damage: true, + order: 2, + result: { + target: function (player, target) { + return get.damageEffect(target, player); }, }, + threaten: 1.5, + expose: 0.3, }, }, - qiluan2: { - audio: 2, - }, - zniaoxiang: { - audio: 2, - trigger: { player: "useCardToPlayered" }, + duwu2: { + trigger: { global: "dyingAfter" }, forced: true, + popup: false, + charlotte: true, filter: function (event, player) { - return event.card.name == "sha" && !event.getParent().directHit.includes(event.target); + if (!event.player.isIn() || !event.reason) return false; + let evt = event.reason.getParent(); + return evt.name == "duwu" && evt.player == player; }, - //priority:-1, - logTarget: "target", content: function () { - var id = trigger.target.playerid; - var map = trigger.getParent().customArgs; - if (!map[id]) map[id] = {}; - if (typeof map[id].shanRequired == "number") { - map[id].shanRequired++; - } else { - map[id].shanRequired = 2; - } + player.loseHp(); + player.tempBanSkill("duwu"); }, }, - shangyi: { + yicong: { + trigger: { + player: ["changeHp"], + }, audio: 2, - enable: "phaseUse", - usable: 1, - filterTarget: function (card, player, target) { - return player != target && target.countCards("h"); + audioname: ["re_gongsunzan"], + forced: true, + filter: function (event, player) { + return get.sgn(player.hp - 2.5) != get.sgn(player.hp - 2.5 - event.num); }, - content: function () { - "step 0"; - player.chooseCardButton(target, target.getCards("h")).set("filterButton", function (button) { - return get.color(button.link) == "black"; - }); - "step 1"; - if (result.bool) { - target.discard(result.links[0]); - } + content: function () {}, + mod: { + globalFrom: function (from, to, current) { + if (from.hp > 2) return current - 1; + }, + globalTo: function (from, to, current) { + if (to.hp <= 2) return current + 1; + }, }, ai: { - order: 11, - result: { - target: function (player, target) { - return -target.countCards("h"); - }, - }, - threaten: 1.1, + threaten: 0.8, }, }, - shengxi: { - trigger: { player: "phaseDiscardBegin" }, - frequent: true, + yongsi: { + audio: 2, + group: ["yongsi1", "yongsi2"], + locked: true, + ai: { + threaten: 3.2, + }, + }, + yongsi1: { + audio: true, + trigger: { player: "phaseDrawBegin2" }, + forced: true, filter: function (event, player) { - return !player.getStat("damage"); + return !event.numFixed; }, content: function () { - player.draw(2); + trigger.num += game.countGroup(); }, - audio: 2, - audioname: ["liushan"], }, - shoucheng: { - init(player) { - game.addGlobalSkill("shoucheng_draw", player); - }, - trigger: { - global: ["equipAfter", "addJudgeAfter", "loseAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], + yongsi2: { + audio: true, + trigger: { player: "phaseDiscardBegin" }, + forced: true, + content: function () { + player.chooseToDiscard(game.countGroup(), "he", true); }, - audio: 2, + }, + bifa: { + trigger: { player: "phaseJieshuBegin" }, direct: true, + audio: 2, filter: function (event, player) { - return game.hasPlayer(function (current) { - if (current == _status.currentPhase) return false; - var evt = event.getl(current); - return evt && evt.hs && evt.hs.length && current.countCards("h") == 0; - }); + return player.countCards("h") > 0; }, content: function () { "step 0"; - event.list = game - .filterPlayer(function (current) { - if (current == _status.currentPhase) return false; - var evt = trigger.getl(current); - return evt && evt.hs && evt.hs.length; - }) - .sortBySeat(_status.currentPhase); + player.chooseCardTarget({ + filterCard: true, + filterTarget: function (card, player, target) { + return player != target && !target.getExpansions("bifa2").length; + }, + ai1: function (card) { + return 7 - get.value(card); + }, + ai2: function (target) { + var num = target.hasSkillTag("maixie") ? 2 : 0; + return -get.attitude(_status.event.player, target) - num; + }, + prompt: get.prompt2("bifa"), + }); "step 1"; - var target = event.list.shift(); - event.target = target; - if (target.isIn() && target.countCards("h") == 0) { - player.chooseBool(get.prompt2("shoucheng", target)).set("ai", function () { - return get.attitude(_status.event.player, _status.event.getParent().target) > 0; - }); - } else event.goto(3); - "step 2"; if (result.bool) { - player.logSkill(event.name, target); - if (player !== target && (get.mode() !== "identity" || player.identity !== "nei")) player.addExpose(0.15); - target.draw(); - } - "step 3"; - if (event.list.length) event.goto(1); + event.forceDie = true; + var target = result.targets[0]; + event.target = target; + player.logSkill("bifa", result.targets[0]); + event.card = result.cards[0]; + target.storage.bifa2 = [result.cards[0], player]; + if (!_status.connectMode && player.isUnderControl(true)) player.$giveAuto(result.cards[0], target, false); + else player.$give(1, target, false); + target.addToExpansion(result.cards[0]).gaintag.add("bifa2"); + } else event.finish(); + "step 2"; + if (target.getExpansions("bifa2").includes(card)) { + target.addSkill("bifa2"); + } else delete target.storage.bifa2; }, ai: { - threaten: 1.3, - }, - subSkill: { - draw: { - trigger: { player: "dieAfter" }, - filter(event, player) { - return !game.hasPlayer(current => { - return current.hasSkill("shoucheng"); - }, true); - }, - content() { - game.removeGlobalSkill("shoucheng_draw"); - }, - ai: { - noh: true, - skillTagFilter(player, tag, arg) { - if (player === _status.currentPhase || player.countCards("h") !== 1) return false; - return game.hasPlayer(current => { - return current.hasSkill("shoucheng") && player.isFriendOf(current); - }); - }, - }, - }, + threaten: 1.7, + expose: 0.3, }, }, - hengzheng: { - audio: 2, - trigger: { player: "phaseDrawBegin1" }, - preHidden: true, + bifa2: { + trigger: { player: "phaseZhunbeiBegin" }, + forced: true, + charlotte: true, + audio: false, filter: function (event, player) { - return !event.numFixed && (player.hp == 1 || player.countCards("h") == 0); - }, - check: function (event, player) { - var num = game.countPlayer(function (current) { - if (current.countCards("he") && current != player && get.attitude(player, current) <= 0) { - return true; - } - if (current.countCards("j") && current != player && get.attitude(player, current) > 0) { - return true; - } - }); - return num >= 2; + return player.storage.bifa2 && player.getExpansions("bifa2").includes(player.storage.bifa2[0]); }, content: function () { "step 0"; - var targets = game.filterPlayer(); - targets.remove(player); - targets.sort(lib.sort.seat); - event.targets = targets; - event.num = 0; - trigger.changeToZero(); - player.line(targets, "green"); + if (player.storage.bifa2[1].isIn() && player.countCards("h")) { + player + .chooseCard(get.translation(player.storage.bifa2[1]) + "的笔伐牌为:", function (card) { + return get.type(card, "trick") == _status.event.type; + }) + .set("ai", function (card) { + return 8 - get.value(card); + }) + .set("type", get.type(player.storage.bifa2[0], "trick")) + .set("promptx", [[player.storage.bifa2[0]], "请交给其一张与此牌类别相同的手牌,否则失去1点体力"]); + } else { + event.directfalse = true; + } "step 1"; - if (num < event.targets.length) { - if (event.targets[num].countCards("hej")) { - player.gainPlayerCard(event.targets[num], "hej", true); - } - event.num++; - event.redo(); + if (result.bool && !event.directfalse) { + player.give(result.cards, player.storage.bifa2[1]); + player.gain(player.storage.bifa2[0], "draw"); + } else { + player.loseHp(); } + "step 2"; + player.removeSkill("bifa2"); }, - ai: { - noh: true, - skillTagFilter: function (player, tag) { - if (tag == "noh") { - if (player.countCards("h") != 1) return false; - } - }, - threaten: function (player, target) { - if (target.hp == 1) return 2.5; - return 1; - }, + marktext: "檄", + intro: { + markcount: () => 1, + name: "笔伐", + content: "已成为〖笔伐〗的目标", + }, + onremove: function (player, skill) { + var cards = player.getExpansions(skill); + if (cards.length) player.loseToDiscardpile(cards); + delete player.storage[skill]; }, }, - yongjue: { + songci: { audio: 2, - trigger: { global: "useCardAfter" }, - usable: 1, + enable: "phaseUse", filter: function (event, player) { - if (event.card.name != "sha") return false; - if (event.player == player) return false; - if (event.targets.includes(player)) return false; - if (event.cards) { - for (var i = 0; i < event.cards.length; i++) { - if (get.position(event.cards[i], true) == "o") return true; - } - } - return false; + if (!player.storage.songci) return true; + return game.hasPlayer(function (current) { + return !player.getStorage("songci").includes(current); + }); }, - frequent: true, - content: function () { - var cards = trigger.cards.slice(0); - for (var i = 0; i < cards.length; i++) { - if (get.position(cards[i], true) != "o") { - cards.splice(i--, 1); - } + filterTarget: function (card, player, target) { + return !player.getStorage("songci").includes(target); + }, + logAudio(event, player) { + const target = event.targets[0], + goon = target.countCards("h") > target.hp; + return goon ? "songci2.mp3" : "songci1.mp3"; + }, + async content(event, trigger, player) { + const target = event.target, + goon = target.countCards("h") > target.hp; + player.markAuto("songci", [target]); + if (goon) { + await target.chooseToDiscard(2, "he", true); + } else { + await target.draw(2); } - player.gain(cards, "gain2"); }, + intro: { + content: "已对$发动过〖颂词〗", + }, + ai: { + order: 7, + threaten: 1.6, + expose: 0.2, + result: { + target: function (player, target) { + if (target.countCards("h") <= target.hp) { + return 1; + } else if (target.countCards("h") > target.hp) { + return -1; + } + }, + }, + }, + group: "songci_draw", }, - guixiu: { - audio: 2, - trigger: { target: "useCardToTargeted" }, - frequent: true, + songci_draw: { + audio: "songci", + trigger: { player: "phaseDiscardEnd" }, + forced: true, filter: function (event, player) { - return event.card.name == "sha" && player.countCards("h") < player.hp; + if (!player.storage.songci) return false; + return !game.hasPlayer(function (current) { + return !player.storage.songci.includes(current); + }); }, content: function () { player.draw(); }, }, - cunsi: { - skillAnimation: true, - animationColor: "orange", + baobian: { audio: 2, - unique: true, - enable: "phaseUse", - mark: true, - limited: true, - derivation: "yongjue", - filter: function (event, player) { - return !player.storage.cunsi && player.countCards("h") && !player.isTurnedOver(); - }, + trigger: { player: ["phaseBefore", "changeHp"] }, + forced: true, + popup: false, init: function (player) { - player.storage.cunsi = false; - }, - filterTarget: function (card, player, target) { - return player != target && target.hasSex("male"); + if (game.online) return; + player.removeAdditionalSkill("baobian"); + var list = []; + if (player.hp <= 3) { + //if(trigger.num!=undefined&&trigger.num<0&&player.hp-trigger.num>1) player.logSkill('baobian'); + list.push("oltiaoxin"); + } + if (player.hp <= 2) { + list.push("olpaoxiao"); + } + if (player.hp <= 1) { + list.push("xinshensu"); + } + if (list.length) { + player.addAdditionalSkill("baobian", list); + } }, + derivation: ["oltiaoxin", "olpaoxiao", "xinshensu"], content: function () { - "step 0"; - player.awakenSkill("cunsi"); - var cards = player.getCards("h"); - player.give(cards, target); - "step 1"; - target.addSkills("yongjue"); - "step 2"; - target.markSkillCharacter("yongjue", player, "存嗣", '
    【勇决】
    每当其他角色于回合内使用一张杀,若目标不是你,你可以获得之,每回合限一次
    '); - player.turnOver(); - }, - intro: { - content: "limited", + player.removeAdditionalSkill("baobian"); + var list = []; + if (player.hp <= 3) { + if (trigger.num != undefined && trigger.num < 0 && player.hp - trigger.num > 1) player.logSkill("baobian"); + list.push("oltiaoxin"); + } + if (player.hp <= 2) { + list.push("olpaoxiao"); + } + if (player.hp <= 1) { + list.push("xinshensu"); + } + if (list.length) { + player.addAdditionalSkill("baobian", list); + } }, ai: { - order: 4, - result: { - target: function (player, target) { - if (target.isMin()) return 0; - if (player.hp > 1) { - if (game.phaseNumber < game.players.length) return 0; - if (target.hp == 1 && target.maxHp > 2) return 0; - if (get.attitude(player, target) < 5) return 0; + maixie: true, + effect: { + target: function (card, player, target) { + if (get.tag(card, "damage")) { + if (!target.hasFriend()) return; + if (target.hp >= 4) return [0, 1]; } - if (get.attitude(player, target) < 5) return 0; - if (target.hp == 1 && target.maxHp > 2) return 0.2; - if (target == game.me) return 1.2; - return 1; + if (get.tag(card, "recover") && player.hp >= player.maxHp - 1) return [0, 0]; }, }, - expose: 0.5, - threaten: 1.5, }, }, - fenming: { + chongzhen: { audio: 2, - trigger: { player: "phaseJieshuBegin" }, - check: function (event, player) { - var num = game.countPlayer(function (current) { - if (current.isLinked() && current.countCards("he")) { - return get.effect(current, { name: "guohe_copy2" }, player, player); - } - }); - return num < 0; - }, + audioname: ["huan_zhaoyun"], + trigger: { player: ["useCard", "respond"] }, filter: function (event, player) { - return player.isLinked(); + if (event.card.name != "sha" && event.card.name != "shan") return false; + if (!event.skill || event.skill.indexOf("fanghun") + event.skill.indexOf("longdan") == -2) return false; + var target = lib.skill.chongzhen.logTarget(event, player); + return target && target.countGainableCards(player, "h") > 0; }, - preHidden: true, - prompt: "是否发动【奋命】?", logTarget: function (event, player) { - return game.filterPlayer(function (current) { - if (current.isLinked() && current.countCards("he")) { - return true; - } - }); + if (event.name == "respond") return event.source; + if (event.card.name == "sha") return event.targets[0]; + return event.respondTo[0]; + }, + prompt2: function (event, player) { + var target = lib.skill.chongzhen.logTarget(event, player); + return "获得" + get.translation(target) + "的一张手牌"; }, content: function () { - "step 0"; - event.targets = game.filterPlayer(function (current) { - if (current.isLinked() && current.countCards("he")) { - return true; - } - }); - event.num = 0; - event.targets.sort(lib.sort.seat); - "step 1"; - if (event.num < event.targets.length) { - var target = event.targets[event.num]; - if (player == target) { - player.chooseToDiscard(true, "he"); - } else { - player.discardPlayerCard(true, "he", target); - } - event.num++; - event.redo(); - } + var target = lib.skill.chongzhen.logTarget(trigger, player); + player.gainPlayerCard(target, "h", true); + }, + ai: { + combo: "ollongdan", + mingzhi: false, + effect: { + target: function (card, player, target, current) { + if (get.tag(card, "respondShan") || get.tag(card, "respondSha")) { + if (get.attitude(target, player) <= 0) { + if (current > 0) return; + if (target.countCards("h") == 0) return 1.6; + if (target.countCards("h") == 1) return 1.2; + if (target.countCards("h") == 2) return [0.8, 0.2, 0, -0.2]; + return [0.4, 0.7, 0, -0.7]; + } + } + }, + }, }, }, - duanxie: { + lihun: { + audio: 2, enable: "phaseUse", usable: 1, - audio: 2, - filter: function (event, player) { - return game.hasPlayer(function (current) { - return current != player && !current.isLinked(); - }); - }, filterTarget: function (card, player, target) { - return player != target && !target.isLinked(); - }, - selectTarget: function () { - return [1, Math.max(1, _status.event.player.getDamagedHp())]; + return player != target && target.hasSex("male"); }, + filterCard: true, + position: "he", content: function () { - if (!target.isLinked()) target.link(); + player.gainPlayerCard(target, true, "h", target.countCards("h")); + player.turnOver(); + player.addSkill("lihun2"); + player.storage.lihun = target; }, - contentAfter: function () { - if (!player.isLinked()) player.link(); + check: function (card) { + return 8 - get.value(card); }, ai: { + order: 10, result: { - target: -1, player: function (player) { - return player.isLinked() ? 0 : -0.8; - }, - }, - order: 2, - expose: 0.3, - effect: { - target: function (card) { - if (card.name == "tiesuo") { - return 0.5; - } + if (player.classList.contains("turnedover")) return 10; + return 0; + }, + target: function (player, target) { + if (target.countCards("h") > target.hp) return target.hp - target.countCards("h"); + return 0; }, }, + threaten: 1.5, }, }, - xiaoguo: { - audio: 2, - trigger: { global: "phaseJieshuBegin" }, - filter: function (event, player) { - return event.player.isIn() && event.player != player && player.countCards("h"); - }, - direct: true, + lihun2: { + trigger: { player: "phaseUseEnd" }, + forced: true, + popup: false, + audio: false, content: function () { "step 0"; - var next = player.chooseToDiscard(get.prompt("xiaoguo", trigger.player)); - next.set("ai", function (card) { - return _status.event.eff - get.useful(card); - }); - next.set("logSkill", ["xiaoguo", trigger.player]); - next.set( - "eff", - (function () { - if (trigger.player.hasSkillTag("noe")) return get.attitude(_status.event.player, trigger.player); - return get.damageEffect(trigger.player, player, _status.event.player); - })() - ); - "step 1"; - if (result.bool) { - if (get.mode() !== "identity" || player.identity !== "nei") player.addExpose(0.15); - trigger.player - .chooseToDiscard("he", "弃置一张装备牌并令" + get.translation(player) + "摸一张牌,或受到1点伤害", { type: "equip" }) - .set("ai", function (card) { - if (_status.event.damage > 0) return 0; - if (_status.event.noe) return 12 - get.value(card); - return -_status.event.damage - get.value(card); - }) - .set("damage", get.damageEffect(trigger.player, player, trigger.player)) - .set("noe", trigger.player.hasSkillTag("noe")); - } else { + var cards = player.getCards("he"); + player.removeSkill("lihun2"); + if (player.storage.lihun.classList.contains("dead") || player.storage.lihun.hp <= 0 || cards.length == 0) { event.finish(); - } - "step 2"; - if (result.bool) { - player.draw(); } else { - trigger.player.damage(); + if (cards.length < player.storage.lihun.hp) event._result = { bool: true, cards: cards }; + else player.chooseCard("he", true, player.storage.lihun.hp, "离魂:选择要交给" + get.translation(player.storage.lihun) + "的牌"); } + "step 1"; + player.give(result.cards, player.storage.lihun); }, }, - suishi: { - audio: 2, - trigger: { global: "dying" }, - forced: true, - popup: false, - //priority:12, - check: function () { - return false; - }, + yuanhu: { + audio: 3, + trigger: { player: "phaseJieshuBegin" }, filter: function (event, player) { - return event.player != player && event.parent.name == "damage" && event.parent.source && event.parent.source != event.player; + return player.countCards("he", { type: "equip" }) > 0; }, - content: function () { - "step 0"; - var str; - if (trigger.parent.source == player) { - str = "随势:是否摸一张牌?"; - } else { - str = "随势:是否令" + get.translation(player) + "摸一张牌?"; - } - trigger.parent.source - .chooseBool(str) - .set("ai", function () { - return get.attitude(_status.event.player, _status.event.target) > 0; + logAudio(_1, _2, _3, _4, result) { + return "yuanhu" + Math.max(get.equipNum(result.cards[0]), 3) + ".mp3"; + }, + async cost(event, trigger, player) { + event.result = await player + .chooseCardTarget({ + filterCard: function (card) { + return get.type(card) == "equip"; + }, + position: "he", + filterTarget: function (card, player, target) { + return target.canEquip(card); + }, + ai1: function (card) { + return 6 - get.value(card); + }, + ai2: function (target) { + return get.attitude(_status.event.player, target) - 3; + }, + prompt: get.prompt2("yuanhu"), }) - .set("target", player); - "step 1"; - if (result.bool) { - player.logSkill("suishi"); - trigger.parent.source.line(player, "green"); - player.draw(); - } + .forResult(); }, - ai: { - halfneg: true, + async content(event, trigger, player) { + const target = result.targets[0]; + const card = result.cards[0]; + target.equip(card); + if (target != player) { + player.$give(card, target, false); + } + switch (get.subtype(card)) { + case "equip1": { + if ( + !game.hasPlayer(function (current) { + return get.distance(target, current) <= 1; + }) + ) + return; + await game.delay(); + const { targets } = await player + .chooseTarget(true, function (card, player, target) { + return get.distance(_status.event.thisTarget, target) <= 1 && target.countCards("hej"); + }) + .set("ai", function (target) { + var attitude = get.attitude(_status.event.player, target); + if (attitude > 0 && target.countCards("j")) { + return attitude * 1.5; + } + return -attitude; + }) + .set("thisTarget", target) + .forResult(); + if (targets.length) await player.discardPlayerCard(true, targets[0], "hej"); + return; + } + case "equip2": + await target.draw(); + return; + case "equip5": + return; + default: + await target.recover(); + return; + } }, - group: "suishi2", }, - suishi2: { - trigger: { global: "dieAfter" }, - forced: true, - popup: false, - check: function () { - return false; + tianming: { + audio: 2, + audioname2: { caoteng: "tianming_caoteng" }, + trigger: { target: "useCardToTargeted" }, + check: function (event, player) { + var cards = player.getCards("h"); + if (cards.length <= 2) { + for (var i = 0; i < cards.length; i++) { + if (cards[i].name == "shan" || cards[i].name == "tao") return false; + } + } + return true; }, filter: function (event, player) { - return event.player != player && event.source && event.source != player && event.source != event.player; + return event.card.name == "sha"; }, content: function () { "step 0"; - var str; - if (trigger.source == player) { - str = "随势:是否失去1点体力?"; + player.chooseToDiscard(2, true, "he"); + player.draw(2); + var players = game.filterPlayer(); + players.sort(function (a, b) { + return b.hp - a.hp; + }); + if (players[0].hp > players[1].hp && players[0] != player) { + players[0].chooseBool(get.prompt2("tianming")); + event.player = players[0]; } else { - str = "随势:是否令" + get.translation(player) + "失去1点体力?"; + event.finish(); } - trigger.source - .chooseBool(str) - .set("ai", function () { - return get.attitude(_status.event.player, _status.event.target) < 0; - }) - .set("target", player); "step 1"; if (result.bool) { - player.logSkill("suishi"); - trigger.source.line(player, "green"); - player.loseHp(); + player.chooseToDiscard(2, true, "he"); + player.draw(2); } }, - }, - sijian: { - trigger: { - player: "loseAfter", - global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], + ai: { + effect: { + target_use(card, player, target, current) { + if (card.name == "sha") return [1, 0.5]; + }, + }, }, - direct: true, + }, + mizhao: { + enable: "phaseUse", + usable: 1, audio: 2, - preHidden: true, filter: function (event, player) { - if (player.countCards("h")) return false; - if (event.name == "gain" && event.player == player) return false; - var evt = event.getl(player); - return evt && evt.hs && evt.hs.length > 0; + return player.countCards("h") > 0; + }, + filterCard: true, + selectCard: -1, + filterTarget: function (card, player, target) { + return player != target; + }, + discard: false, + lose: false, + delay: false, + ai: { + order: 1, + result: { + player: 0, + target: function (player, target) { + if (target.hasSkillTag("nogain")) return 0; + if (player.countCards("h") > 1) { + return 1; + } + var players = game.filterPlayer(); + for (var i = 0; i < players.length; i++) { + if (players[i].countCards("h") && players[i] != target && players[i] != player && get.attitude(player, players[i]) < 0) { + break; + } + } + if (i == players.length) { + return 1; + } + return -2 / (target.countCards("h") + 1); + }, + }, }, content: function () { "step 0"; + event.target1 = targets[0]; + player.give(cards, targets[0], "giveAuto"); + "step 1"; + if (!targets[0].countCards("h")) { + event.finish(); + return; + } + var players = game.filterPlayer(); + for (var i = 0; i < players.length; i++) { + if (players[i] != event.target1 && players[i] != player && event.target1.canCompare(players[i])) { + break; + } + } + if (i == players.length) { + event.finish(); + } + "step 2"; player - .chooseTarget(get.prompt("sijian"), "弃置一名其他角色的一张牌", function (card, player, target) { - return player != target && target.countCards("he") > 0; + .chooseTarget(true, "选择拼点目标", function (card, player, target) { + return _status.event.target1.canCompare(target) && target != player; }) .set("ai", function (target) { - return -get.attitude(_status.event.player, target); + var player = _status.event.player; + var eff = get.effect(target, { name: "sha" }, _status.event.target1, player); + var att = get.attitude(player, target); + if (att > 0) { + return eff - 10; + } + return eff; }) - .setHiddenSkill(event.name); - "step 1"; - if (result.bool) { - player.logSkill("sijian", result.targets); - event.target = result.targets[0]; - player.discardPlayerCard(event.target, true); + .set("target1", event.target1) + .set("forceDie", true); + "step 3"; + if (result.targets.length) { + event.target2 = result.targets[0]; + event.target1.line(event.target2); + event.target1.chooseToCompare(event.target2); } else { event.finish(); } - }, - ai: { - expose: 0.2, + "step 4"; + if (!result.tie) { + if (result.bool) { + if (event.target1.canUse({ name: "sha", isCard: true }, event.target2, false)) event.target1.useCard({ name: "sha", isCard: true }, event.target2); + } else if (event.target2.canUse({ name: "sha", isCard: true }, event.target1, false)) { + event.target2.useCard({ name: "sha", isCard: true }, event.target1); + } + } }, }, - quji: { + gongao: { audio: 2, - enable: "phaseUse", - usable: 1, - position: "he", - filterCard: true, - selectCard: function () { - var player = _status.event.player; - return player.getDamagedHp(); + trigger: { global: "dieAfter" }, + forced: true, + content: function () { + player.gainMaxHp(); + player.recover(); }, - filterTarget: function (card, player, target) { - return target.hp < target.maxHp; + ai: { + threaten: 1.5, }, + }, + juyi: { + skillAnimation: true, + animationColor: "thunder", + audio: 1, + derivation: ["benghuai", "weizhong"], + trigger: { player: "phaseZhunbeiBegin" }, filter: function (event, player) { - return player.hp < player.maxHp; - }, - selectTarget: function () { - return [1, ui.selected.cards.length]; - }, - complexSelect: true, - check: function (card) { - if (get.color(card) == "black") return -1; - return 9 - get.value(card); + return player.maxHp > game.countPlayer() && !player.storage.juyi; }, + forced: true, + unique: true, + juexingji: true, content: function () { - "step 0"; - target.recover(); - "step 1"; - if (target == targets[targets.length - 1]) { - for (var i = 0; i < cards.length; i++) { - if (get.color(cards[i], player) == "black") { - player.loseHp(); - break; - } - } - } + player.awakenSkill("juyi"); + player.draw(player.maxHp); + player.addSkills(["benghuai", "weizhong"]); }, - ai: { - result: { - target: 1, - }, - order: 6, + }, + benghuai_zhugedan: { audio: 1 }, + weizhong: { + audio: 1, + trigger: { player: ["gainMaxHpEnd", "loseMaxHpEnd"] }, + forced: true, + content: function () { + player.draw(player.isMinHandcard() ? 2 : 1); }, }, - junbing: { + kuangfu: { + trigger: { source: "damageSource" }, audio: 2, - trigger: { global: "phaseJieshuBegin" }, - filter: function (event, player) { - return event.player.countCards("h") <= 1 && (player == event.player || player.hasSkill("junbing")); + filter: function (event) { + if (event._notrigger.includes(event.player)) return false; + return event.card && event.card.name == "sha" && event.player.countCards("e"); }, - direct: true, - checkx: function (target, player) { - if (target) { - var num = target.countCards("h"); - var att = get.attitude(player, target); - if (num == 0) return true; - if (num == 1) return att > -1; - if (num == 2) return att > 0; - return att > 1; - } - return false; + logTarget: "player", + preHidden: true, + check: function (event, player) { + return get.attitude(player, event.player) <= 0; }, content: function () { "step 0"; - event.target = player; - event.player = trigger.player; - var prompt; - if (player == event.player) prompt = "是否发动【郡兵】摸一张牌?"; - else prompt = "###是否对" + get.translation(event.target) + "发动【郡兵】?###" + (event.player == event.target ? "摸一张牌" : "摸一张牌,将所有手牌交给该角色,然后该角色交给你等量的手牌"); - event.player.chooseBool(prompt).set("choice", lib.skill.junbing.checkx(event.target, event.player)); + var neg = get.attitude(player, trigger.player) <= 0; + player + .choosePlayerCard("e", trigger.player) + .set("ai", function (button) { + if (_status.event.neg) { + return get.buttonValue(button); + } + return 0; + }) + .set("neg", neg); "step 1"; - if (!result.bool) { - event.finish(); - return; - } - target.logSkill("junbing", player); - if (player == target) event.finish(); - player.draw(); + if (result.bool) { + event.card = result.links[0]; + if (player.canEquip(event.card)) { + player.chooseBool("是否将" + get.translation(event.card) + "置入自己的装备区?").ai = function () { + return true; + }; + } else event._result = { bool: false }; + } else event.finish(); "step 2"; - var cards = player.getCards("h"); - player.give(cards, target); - event.num = cards.length; - "step 3"; - var he = target.getCards("he"); - if (!he.length) event.finish(); - else if (he.length <= num) event._result = { cards: he }; - else target.chooseCard("选择还给" + get.translation(player) + "的牌", true, event.num, "he"); - "step 4"; - target.give(result.cards, player); + if (result.bool) { + trigger.player.$give(event.card, player, false); + player.equip(event.card); + } else trigger.player.discard(event.card); }, }, - xiongyi: { - skillAnimation: true, - animationColor: "gray", - unique: true, - enable: "phaseUse", + xinfu_lingren: { audio: 2, - limited: true, - filterTarget: function (card, player, target) { - if (get.mode() == "guozhan") { - if (player == target) return true; - if (player.identity == "unknown") { - if (!player.wontYe("qun")) return false; - return target.identity == "qun"; - } - return target.isFriendOf(player); - } else { - return true; - } + trigger: { + player: "useCardToPlayered", }, - multitarget: true, - multiline: true, - selectTarget: function () { - if (get.mode() == "guozhan") return -1; - return [1, Infinity]; + filter: function (event, player) { + if (event.getParent().triggeredTargets3.length > 1) return false; + if (!["basic", "trick"].includes(get.type(event.card))) return false; + if (get.tag(event.card, "damage")) return true; + return false; }, + usable: 1, + direct: true, + derivation: ["lingren_jianxiong", "lingren_xingshang"], content: function () { "step 0"; - player.awakenSkill("xiongyi"); - game.asyncDraw(targets, 3); + player + .chooseTarget(get.prompt("xinfu_lingren"), "选择一名目标角色并猜测其手牌构成", function (card, player, target) { + return _status.event.targets.includes(target); + }) + .set("ai", function (target) { + return 2 - get.attitude(_status.event.player, target); + }) + .set("targets", trigger.targets); "step 1"; - if (player.isDamaged()) { - if (get.mode() == "guozhan") { - if (player.isMinor(true)) { - player.recover(); + if (result.bool) { + player.logSkill("xinfu_lingren", result.targets); + var target = result.targets[0]; + event.target = target; + event.choice = { + basic: false, + trick: false, + equip: false, + }; + player.chooseButton(["凌人:猜测其有哪些类别的手牌", [["basic", "trick", "equip"], "vcard"]], [0, 3], true).set("ai", function (button) { + switch (button.link[2]) { + case "basic": + var rand = 0.95; + if (!target.countCards("h", { type: ["basic"] })) rand = 0.05; + if (!target.countCards("h")) rand = 0; + return Math.random() < rand ? true : false; + case "trick": + var rand = 0.9; + if (!target.countCards("h", { type: ["trick", "delay"] })) rand = 0.1; + if (!target.countCards("h")) rand = 0; + return Math.random() < rand ? true : false; + case "equip": + var rand = 0.75; + if (!target.countCards("h", { type: ["equip"] })) rand = 0.25; + if (!target.countCards("h")) rand = 0; + return Math.random() < rand ? true : false; } - } else if (player.isMinHp()) { - player.recover(); - } + }); + } else { + player.storage.counttrigger.xinfu_lingren--; + event.finish(); + } + "step 2"; + if (result.bool) { + var choices = result.links.map(i => i[2]); + if (!event.isMine() && !event.isOnline()) game.delayx(); + var list = []; + event.num = 0; + ["basic", "trick", "equip"].forEach(type => { + if (choices.includes(type) == target.hasCard(card => get.type2(card, target) === type, "h")) event.num++; + }); + } + "step 3"; + player.popup("猜对" + get.cnNumber(event.num) + "项"); + game.log(player, "猜对了" + get.cnNumber(event.num) + "项"); + if (event.num > 0) { + target.addTempSkill("lingren_adddamage"); + target.storage.lingren = { + card: trigger.card, + //player:event.targett, + }; + } + if (event.num > 1) player.draw(2); + if (event.num > 2) { + player.addTempSkills(["lingren_jianxiong", "lingren_xingshang"], { + player: "phaseBegin", + }); } }, ai: { - order: 1, - result: { - target: function (player) { - var num = player.countCards("h"); - if (player.hp == 1) return 1; - if (player.hp == 2 && num <= 2) return 1; - if (player.hp == 3 && num <= 1) return 1; - if (game.phaseNumber < game.players.length * 2) return 0; - if (player.hasUnknown()) return 0; - return 1; - }, - }, + threaten: 2.4, }, }, - gzshushen: { - audio: "shushen", - trigger: { player: "recoverAfter" }, - direct: true, + lingren_adddamage: { + onremove: function (player) { + delete player.storage.lingren; + }, + trigger: { + player: "damageBegin3", + }, filter: function (event, player) { - return game.hasPlayer(function (current) { - return player != current && player.sameIdentityAs(current); - }); + var info = player.storage.lingren; + return event.card && event.card == info.card; }, + silent: true, + popup: false, + forced: true, + charlotte: true, content: function () { - "step 0"; - event.num = trigger.num || 1; - "step 1"; - player - .chooseTarget(get.prompt2("gzshushen"), function (card, player, target) { - return target != player && player.sameIdentityAs(target); - }) - .set("ai", function (target) { - return get.attitude(_status.event.player, target); - }); - "step 2"; - if (result.bool) { - player.logSkill("gzshushen", result.targets); - result.targets[0].draw(); - if (event.num > 1) { - event.num--; - event.goto(1); - } - } - }, - ai: { - threaten: 0.8, - expose: 0.1, + trigger.num++; }, }, - shushen: { - audio: 2, - trigger: { player: "recoverAfter" }, - direct: true, + lingren_jianxiong: { + audio: 1, + trigger: { + player: "damageEnd", + }, content: function () { "step 0"; - event.count = trigger.num; - "step 1"; - player - .chooseTarget(get.prompt("shushen"), "令一名其他角色选择摸两张牌或回复1点体力", function (card, player, target) { - return target != player; - }) - .set("ai", function (target) { - return get.attitude(_status.event.player, target); - }); - "step 2"; - if (result.bool) { - event.count--; - player.logSkill("shushen", result.targets); - result.targets[0].chooseDrawRecover(2, true); - if (event.count) event.goto(1); + if (get.itemtype(trigger.cards) == "cards" && get.position(trigger.cards[0], true) == "o") { + player.gain(trigger.cards, "gain2"); } + player.draw("nodelay"); }, ai: { - threaten: 0.8, - expose: 0.1, + maixie: true, + maixie_hp: true, + effect: { + target: function (card, player, target) { + if (player.hasSkillTag("jueqing", false, target)) return [1, -1]; + if (get.tag(card, "damage") && player != target) return [1, 0.6]; + }, + }, }, }, - shenzhi: { + lingren_xingshang: { + audio: 1, + inherit: "rexingshang", + }, + xinfu_fujian: { audio: 2, - trigger: { player: "phaseZhunbeiBegin" }, - check: function (event, player) { - if (player.hp > 2) return false; - var cards = player.getCards("h"); - if (cards.length < player.hp) return false; - if (cards.length > 3) return false; - for (var i = 0; i < cards.length; i++) { - if (get.value(cards[i]) > 7 || get.tag(cards[i], "recover") >= 1) return false; - } - return true; + trigger: { + player: "phaseJieshuBegin", }, filter: function (event, player) { - return player.countCards("h") > 0; + return !game.hasPlayer(function (current) { + return current.countCards("h") == 0; + }); }, - preHidden: true, + forced: true, content: function () { - "step 0"; - var cards = player.getCards("h"); - event.bool = cards.length >= player.hp; - player.discard(cards); - "step 1"; - if (event.bool) { - player.recover(); + event.num = 0; + var list = game.filterPlayer(function (target) { + if (target.isMinHandcard()) event.num = target.countCards("h"); + return player != target; + }); + if (event.num < 1) { + event.finish(); + } else { + var target = list.randomGet(); + var cards = target.getCards("h").randomGets(event.num); + player.line(target); + var content = [get.translation(target) + "的部分手牌", cards]; + game.log(player, "观看了", target, "的部分手牌"); + player.chooseControl("ok").set("dialog", content); } }, }, - wuji: { - skillAnimation: true, - animationColor: "orange", - audio: 2, - trigger: { player: "phaseJieshuBegin" }, - forced: true, - unique: true, - juexingji: true, - filter: function (event, player) { - return player.getStat("damage") >= 3 && !player.storage.wuji; + fujian: { + audio: "xinfu_fujian", + trigger: { player: ["phaseZhunbeiBegin", "phaseJieshuBegin"] }, + filter(event, player) { + return game.hasPlayer(target => target != player && target.countCards("h") && !target.isMaxHandcard()); }, - content: function () { - "step 0"; - player.removeSkills("huxiao"); - player.gainMaxHp(); - "step 1"; - player.recover(); - player.awakenSkill("wuji"); - player.storage.wuji = true; - - var card = get.cardPile("qinglong", "field"); - if (card) { - player.gain(card, "gain2", "log"); - } + forced: true, + async content(event, trigger, player) { + const target = game + .filterPlayer(target => { + return target != player && target.countCards("h") && !target.isMaxHandcard(); + }) + .randomGet(); + player.line(target); + game.log(player, "观看了", target, "的手牌"); + player.viewHandcards(target); }, }, - xueji_old: { - audio: "xueji", + xinfu_xionghuo: { + audio: 2, enable: "phaseUse", - usable: 1, filter: function (event, player) { - return player.hp < player.maxHp && player.countCards("he", { color: "red" }) > 0; + return player.countMark("xinfu_xionghuo") > 0; }, filterTarget: function (card, player, target) { - return player != target && get.distance(player, target, "attack") <= 1; - }, - selectTarget: function () { - return [1, _status.event.player.maxHp - _status.event.player.hp]; - }, - position: "he", - filterCard: function (card) { - return get.color(card) == "red"; - }, - check: function (card) { - return 8 - get.useful(card); + return player != target && !target.hasMark("xinfu_xionghuo"); }, content: function () { - "step 0"; - target.damage(); - "step 1"; - target.draw(); + player.removeMark("xinfu_xionghuo", 1); + target.addMark("xinfu_xionghuo", 1); }, ai: { - order: 7, + order: 11, result: { target: function (player, target) { - return get.damageEffect(target, player); + if ( + (player.countMark("xinfu_xionghuo") >= 2 || + !game.hasPlayer(function (current) { + return current != player && get.attitude(player, current) < 0 && current.hasMark("xinfu_xionghuo"); + })) && + player.countCards("h", function (card) { + return ( + get.tag(card, "damage") && + player.canUse(card, target, null, true) && + player.getUseValue(card) > 0 && + get.effect_use(target, card, player) > 0 && + target.hasSkillTag("filterDamage", null, { + player: player, + card: card, + }) + ); + }) + ) + return 3 / Math.max(1, target.hp); + if ( + (!player.hasUnknown() && + game.countPlayer(function (current) { + return get.attitude(player, current) < 0; + }) <= 1) || + player.countMark("xinfu_xionghuo") >= 2 + ) { + return -1; + } + return 0; + }, + }, + effect: { + player: function (card, player, target) { + if ( + player != target && + get.tag(card, "damage") && + target && + target.hasMark("xinfu_xionghuo") && + !target.hasSkillTag("filterDamage", null, { + player: player, + card: card, + }) + ) + return [1, 0, 1, -2]; + }, + }, + threaten: 1.6, + }, + marktext: "戾", + intro: { + name: "暴戾", + content: "mark", + }, + group: ["xinfu_xionghuo_init", "xinfu_xionghuo_damage", "xinfu_xionghuo_effect"], + subSkill: { + init: { + audio: "xinfu_xionghuo", + trigger: { + global: "phaseBefore", + player: "enterGame", + }, + filter: function (event, player) { + if (player.countMark("xinfu_xionghuo") >= 3) return false; + return event.name != "phase" || game.phaseNumber == 0; + }, + forced: true, + locked: false, + content: function () { + player.addMark("xinfu_xionghuo", 3 - player.countMark("xinfu_xionghuo")); }, }, - threaten: function (player, target) { - if (target.hp == 1) return 2; - if (target.hp == 2) return 1.5; - return 0.5; + damage: { + audio: "xinfu_xionghuo", + trigger: { source: "damageBegin1" }, + filter: function (event, player) { + return event.player.countMark("xinfu_xionghuo") > 0 && event.player != player; + }, + forced: true, + locked: false, + logTarget: "player", + content: function () { + trigger.num++; + }, }, - maixie: true, effect: { - target: function (card, player, target) { - if (get.tag(card, "damage")) { - if (target.hp == target.maxHp && target.hasFriend()) return [0, 1]; + audio: "xinfu_xionghuo", + trigger: { global: "phaseUseBegin" }, + filter: function (event, player) { + return event.player.countMark("xinfu_xionghuo") > 0 && event.player != player; + }, + line: false, + forced: true, + locked: false, + logTarget: "player", + content: function () { + "step 0"; + trigger.player.removeMark("xinfu_xionghuo", trigger.player.countMark("xinfu_xionghuo")); + "step 1"; + var num = get.rand(0, 2); + switch (num) { + case 0: { + player.line(trigger.player, "fire"); + trigger.player.damage("fire"); + trigger.player.addTempSkill("xinfu_xionghuo_disable"); + trigger.player.markAuto("xinfu_xionghuo_disable", [player]); + break; + } + case 1: { + player.line(trigger.player, "water"); + trigger.player.loseHp(); + trigger.player.addMark("xinfu_xionghuo_low", 1, false); + trigger.player.addTempSkill("xinfu_xionghuo_low"); + break; + } + case 2: { + player.line(trigger.player, "green"); + /* + var card1=trigger.player.getCards('h').randomGet(); + var card2=trigger.player.getCards('e').randomGet(); + var list=[]; + if(card1) list.push(card1); + if(card2) list.push(card2); + if(list.length) player.gain(list,trigger.player,'giveAuto','bySelf'); + */ + const cards = trigger.player.getGainableCards(player, "he"); + if (cards.length) player.gain(cards.randomGets(2), trigger.player, "giveAuto", "bySelf"); + break; + } } - if (get.tag(card, "recover") && player.hp >= player.maxHp - 1) return [0, 0]; + "step 2"; + game.delay(); + }, + }, + disable: { + mod: { + playerEnabled: function (card, player, target) { + if (card.name == "sha" && player.getStorage("xinfu_xionghuo_disable").includes(target)) return false; + }, + }, + charlotte: true, + onremove: true, + mark: true, + marktext: "禁", + intro: { content: "不能对$使用【杀】" }, + }, + low: { + mod: { + maxHandcard: function (player, num) { + return num - player.countMark("xinfu_xionghuo_low"); + }, }, + charlotte: true, + onremove: true, + mark: true, + marktext: "减", + intro: { content: "手牌上限-#" }, }, }, }, - //FW关银屏 - oldhuxiao: { - audio: "huxiao", - trigger: { player: "shaMiss" }, + xinfu_shajue: { + audio: 2, + trigger: { global: "dying" }, + filter: function (event, player) { + if (event.player == player) return false; + const bool1 = !player.hasSkill("xinfu_xionghuo") || player.countMark("xinfu_xionghuo") < 3; + const bool2 = event.player.hp < 0 && get.itemtype(event.parent.cards) == "cards" && event.parent.cards.some(card => get.position(card, true) == "o"); + return bool1 || bool2; + }, forced: true, content: function () { - if (player.stat[player.stat.length - 1].card.sha > 0) { - player.stat[player.stat.length - 1].card.sha--; + if (!player.hasSkill("xinfu_xionghuo") || player.countMark("xinfu_xionghuo") < 3) player.addMark("xinfu_xionghuo", 1); + if (trigger.player.hp < 0 && get.itemtype(trigger.parent.cards) == "cards" && trigger.parent.cards.some(card => get.position(card, true) == "o")) { + player.gain( + trigger.parent.cards.filter(card => get.position(card, true) == "o"), + "gain2" + ); } }, }, - oldwuji: { - unique: true, - audio: "wuji", - trigger: { player: "phaseJieshuBegin" }, - filter: function (event, player) { - return player.getStat("damage") >= 3 && !player.storage.oldwuji; + xinfu_jianjie: { audio: 3 }, + jianjie: { + group: ["jianjie_use", "jianjie_die"], + derivation: ["jianjie_huoji", "jianjie_lianhuan", "jianjie_yeyan"], + audio: "xinfu_jianjie", + trigger: { + player: "phaseZhunbeiBegin", }, forced: true, - juexingji: true, - skillAnimation: true, - animationColor: "orange", - content: function () { - "step 0"; - player.removeSkills("oldhuxiao"); - player.gainMaxHp(); - "step 1"; - player.recover(); - player.awakenSkill("oldwuji"); - }, - }, - xueji: { - audio: 2, - enable: "phaseUse", - usable: 1, + locked: false, filter: function (event, player) { - return player.countCards("he", { color: "red" }) > 0; - }, - filterTarget: true, - selectTarget: function () { - var player = _status.event.player; - return [1, Math.max(1, player.getDamagedHp())]; - }, - position: "he", - filterCard: { color: "red" }, - check: function (card) { - return 8 - get.value(card); + return player.phaseNumber <= 1 && game.hasPlayer(current => current != player); }, - multitarget: true, - multiline: true, - line: "fire", + logAudio: () => ["xinfu_jianjie1.mp3", "xinfu_jianjie2.mp3"], content: function () { "step 0"; - event.delay = false; - for (var i = 0; i < targets.length; i++) { - if (!targets[i].isLinked()) { - targets[i].link(true); - event.delay = true; - } - } + player.chooseTarget("荐杰:选择一名其他角色获得“龙印”", lib.filter.notMe, true).set("ai", target => { + return get.attitude(get.player(), target); + }); "step 1"; - if (event.delay) { - game.delay(); - } + if (result.bool) { + var target = result.targets[0]; + player.line(target, "fire"); + lib.skill.jianjie.addMark("huoji", player, target); + event.target = target; + game.delayx(); + } else event.finish(); "step 2"; - targets[0].damage("fire", "nocard"); - }, - ai: { - damage: true, - fireAttack: true, - threaten: 1.5, - order: 7, - result: { - target: function (player, target) { - var eff = get.damageEffect(target, player, target, "fire"); - if (target.isLinked()) { - return eff / 10; - } else { - return eff; - } - }, - }, - }, - }, - huxiao: { - trigger: { source: "damageSource" }, - forced: true, - filter: function (event, player) { - if (event._notrigger.includes(event.player) || !event.player.isIn()) return false; - return event.hasNature("fire"); - }, - logTarget: "player", - content: function () { - if (!player.storage.huxiao3) { - player.storage.huxiao3 = []; - } - player.storage.huxiao3.add(trigger.player); - trigger.player.draw(); - player.addTempSkill("huxiao3"); - }, - }, - huxiao3: { - onremove: true, - mark: true, - intro: { - content: "players", + if ( + game.hasPlayer(current => { + return current != player && current != target; + }) + ) { + player + .chooseTarget( + "荐杰:选择一名其他角色获得“凤印”", + function (card, player, target) { + return target != player && target != _status.event.getParent().target; + }, + true + ) + .set("ai", target => { + return get.attitude(get.player(), target); + }); + } else event.finish(); + "step 3"; + if (result.bool) { + var target = result.targets[0]; + player.line(target, "thunder"); + lib.skill.jianjie.addMark("lianhuan", player, target); + game.delayx(); + } }, - mod: { - cardUsableTarget: function (card, player, target) { - if (player.storage.huxiao3 && player.storage.huxiao3.includes(target)) return true; - }, + ai: { + threaten: 3, }, - }, - aocai: { - audio: 2, - audioname: ["gz_zhugeke"], - enable: ["chooseToUse", "chooseToRespond"], - hiddenCard: function (player, name) { - if (player != _status.currentPhase && get.type(name) == "basic" && lib.inpile.includes(name)) return true; + hasMark: (mark, player, target) => { + if (!target) return player.getStorage("jianjie_" + mark).length > 0; + return target.getStorage("jianjie_" + mark).includes(player); }, - filter: function (event, player) { - if (event.responded || player == _status.currentPhase || event.aocai) return false; - for (var i of lib.inpile) { - if (get.type(i) == "basic" && event.filterCard(get.autoViewAs({ name: i }, "unsure"), player, event)) return true; - } - return false; + addMark: (mark, player, target) => { + mark = "jianjie_" + mark; + target.addAdditionalSkill(`${mark}_${player.playerid}`, mark); + target.markAuto(mark, [player]); + game.log(player, "令", target, "获得了", `#g“${mark == "jianjie_huoji" ? "龙印" : "凤印"}”`); }, - delay: false, - content: function () { - "step 0"; - var evt = event.getParent(2); - evt.set("aocai", true); - var cards = get.cards(get.mode() != "guozhan" && player.countCards("h") == 0 ? 4 : 2); - for (var i = cards.length - 1; i >= 0; i--) { - ui.cardPile.insertBefore(cards[i].fix(), ui.cardPile.firstChild); + removeMark: (mark, player, target, log) => { + if (lib.skill.jianjie.hasMark(mark, player, target, log)) { + mark = "jianjie_" + mark; + target.removeAdditionalSkill(`${mark}_${player.playerid}`); + target.unmarkAuto(mark, [player]); + if (log) game.log(target, "移去了", player, "给予的", `#g“${mark == "jianjie_huoji" ? "龙印" : "凤印"}”`); + else game.log(player, "移去了", target, "的", `#g“${mark == "jianjie_huoji" ? "龙印" : "凤印"}”`); } - var aozhan = player.hasSkill("aozhan"); - player - .chooseButton(["傲才:选择要" + (evt.name == "chooseToUse" ? "使用" : "打出") + "的牌", cards]) - .set("filterButton", function (button) { - return _status.event.cards.includes(button.link); - }) - .set( - "cards", - cards.filter(function (card) { - if (aozhan && card.name == "tao") { - return ( - evt.filterCard( - { - name: "sha", - isCard: true, - cards: [card], - }, - evt.player, - evt - ) || - evt.filterCard( - { - name: "shan", - isCard: true, - cards: [card], - }, - evt.player, - evt - ) - ); - } - return evt.filterCard(card, evt.player, evt); - }) - ) - .set("ai", function (button) { - var evt = _status.event.getParent(3); - if (evt && evt.ai) { - var tmp = _status.event; - _status.event = evt; - var result = (evt.ai || event.ai1)(button.link, _status.event.player, evt); - _status.event = tmp; - return result; + }, + subSkill: { + use: { + audio: "xinfu_jianjie", + enable: "phaseUse", + usable: 1, + filter: function (event, player) { + if (player.phaseNumber <= 1) return false; + const skill = lib.skill.jianjie; + return game.hasPlayer(function (current) { + return skill.hasMark("huoji", player, current) || skill.hasMark("lianhuan", player, current); + }); + }, + filterTarget: function (card, player, target) { + if (ui.selected.targets.length == 0) { + const skill = lib.skill.jianjie; + return skill.hasMark("huoji", player, target) || skill.hasMark("lianhuan", player, target); } - return 1; - }); - "step 1"; - var evt = event.getParent(2); - if (result.bool && result.links && result.links.length) { - var card = result.links[0]; - var name = card.name, - aozhan = player.hasSkill("aozhan") && name == "tao"; - if (aozhan) { - name = evt.filterCard( - { - name: "sha", - isCard: true, - cards: [card], + return true; + }, + logAudio: () => ["xinfu_jianjie1.mp3", "xinfu_jianjie2.mp3"], + selectTarget: 2, + complexSelect: true, + complexTarget: true, + multitarget: true, + prompt: "移动场上的“龙印”或“凤印”", + targetprompt: ["失去印", "获得印"], + content: function () { + "step 0"; + var skill = lib.skill.jianjie; + var bool1 = skill.hasMark("huoji", player, targets[0]), + bool2 = skill.hasMark("lianhuan", player, targets[0]); + if (bool1 && bool2) { + player.chooseControl("龙印", "凤印").set("prompt", "选择要移动的“印”"); + } else { + event._result = { control: bool1 ? "龙印" : "凤印" }; + } + "step 1"; + var skill = lib.skill.jianjie, + mark = result.control == "龙印" ? "huoji" : "lianhuan"; + skill.removeMark(mark, player, targets[0]); + skill.addMark(mark, player, targets[1]); + if (skill.hasMark("huoji", player, targets[1]) && skill.hasMark("lianhuan", player, targets[1])) { + game.broadcastAll(function () { + if (lib.config.background_speak) game.playAudio("skill", "xinfu_jianjie3"); + }); + } + game.delayx(); + }, + ai: { + order: 8, + result: { + target: function (player, target) { + if (ui.selected.targets.length == 0) { + return get.attitude(player, target) < 0 ? -999 : -3; + } else { + return target.countCards("h") + 1; + } }, - evt.player, - evt + }, + expose: 0.4, + }, + }, + die: { + audio: "xinfu_jianjie", + trigger: { global: "die" }, + filter: function (event, player) { + const skill = lib.skill.jianjie; + return skill.hasMark("huoji", player, event.player) || skill.hasMark("lianhuan", player, event.player); + }, + forced: true, + logTarget: "player", + content: function () { + "step 0"; + if (lib.skill.jianjie.hasMark("huoji", player, trigger.player)) { + player.chooseTarget("荐杰:选择一名角色获得“龙印”", true).set("ai", target => { + return get.attitude(get.player(), target); + }); + } else event.goto(2); + "step 1"; + if (result.bool) { + var target = result.targets[0]; + player.line(target, "fire"); + lib.skill.jianjie.addMark("huoji", player, target); + if (lib.skill.jianjie.hasMark("huoji", player, target) && lib.skill.jianjie.hasMark("lianhuan", player, target)) { + game.broadcastAll(function () { + if (lib.config.background_speak) game.playAudio("skill", "xinfu_jianjie3"); + }); + } + game.delayx(); + } else event.finish(); + "step 2"; + if (lib.skill.jianjie.hasMark("lianhuan", player, trigger.player)) { + player.chooseTarget("荐杰:选择一名角色获得“凤印”", true).set("ai", target => { + return get.attitude(get.player(), target); + }); + } else event.finish(); + "step 3"; + if (result.bool) { + var target = result.targets[0]; + player.line(target, "thunder"); + lib.skill.jianjie.addMark("lianhuan", player, target); + if (lib.skill.jianjie.hasMark("huoji", player, target) && lib.skill.jianjie.hasMark("lianhuan", player, target)) { + game.broadcastAll(function () { + if (lib.config.background_speak) game.playAudio("skill", "xinfu_jianjie3"); + }); + } + game.delayx(); + } + }, + }, + huoji: { + marktext: "龙", + intro: { + name: "龙印", + content: "
  • 出牌阶段限三次。你可以将一张红色牌当作【火攻】使用,且你以此法使用【火攻】的作用效果改为“目标角色随机展示一张手牌A,然后你可以弃置一张与A颜色相同的牌,对目标造成1点火属性伤害”。
  • 若你同时拥有“凤印”,则你视为拥有技能〖业炎〗。(发动〖业炎〗时,弃置所有“龙印”和“凤印”)", + }, + inherit: "rehuoji", + usable: 3, + charlotte: true, + viewAsFilter: function (player) { + const storage = player.getStorage("jianjie_huoji"); + if ( + !storage.some(source => { + return source.isIn() && source.hasSkill("jianjie"); + }) ) - ? "sha" - : "shan"; - } - if (evt.name == "chooseToUse") { - game.broadcastAll( - function (result, name) { - lib.skill.aocai_backup.viewAs = { - name: name, - cards: [result], - isCard: true, - }; - }, - card, - name - ); - evt.set("_backupevent", "aocai_backup"); - evt.set("openskilldialog", "请选择" + get.translation(card) + "的目标"); - evt.backup("aocai_backup"); - } else { - delete evt.result.skill; - delete evt.result.used; - evt.result.card = get.autoViewAs(result.links[0]); - if (aozhan) evt.result.card.name = name; - evt.result.cards = [result.links[0]]; - evt.redo(); - return; - } - } - evt.goto(0); - }, - ai: { - effect: { - target: function (card, player, target, effect) { - if (get.tag(card, "respondShan")) return 0.7; - if (get.tag(card, "respondSha")) return 0.7; + return false; + return player.hasCard(card => get.color(card) == "red", "she"); }, + group: ["jianjie_yeyan", "jianjie_huoji_effect"], }, - order: 11, - respondShan: true, - respondSha: true, - result: { - player: function (player) { - if (_status.event.dying) return get.attitude(player, _status.event.dying); - return 1; + huoji_effect: { + trigger: { player: "huogongBegin" }, + forced: true, + popup: false, + charlotte: true, + filter: function (event, player) { + return event.skill == "jianjie_huoji"; + }, + content: function () { + trigger.setContent(lib.skill.olhuoji.huogongContent); }, }, - }, - }, - aocai_backup: { - sourceSkill: "aocai", - precontent: function () { - delete event.result.skill; - var name = event.result.card.name, - cards = event.result.card.cards.slice(0); - event.result.cards = cards; - var rcard = cards[0], - card; - if (rcard.name == name) card = get.autoViewAs(rcard); - else card = get.autoViewAs({ name, isCard: true }); - event.result.card = card; - }, - filterCard: function () { - return false; - }, - selectCard: -1, - }, - hongyuan: { - trigger: { player: "phaseDrawBegin2" }, - direct: true, - audio: 2, - filter: function (event, player) { - return !event.numFixed && event.num > 0; - }, - content: function () { - "step 0"; - var check; - if (player.countCards("h") == 0) { - check = false; - } else { - check = - game.countPlayer(function (current) { - return player != current && get.attitude(player, current) > 1; - }) >= 2; - } - if (get.is.versus()) { - event.versus = true; - player.chooseBool(get.prompt2("hongyuan")).ai = function () { - return ( - game.countPlayer(function (current) { - return player.side == current.side; - }) > 2 - ); - }; - } else { - player - .chooseTarget( - get.prompt2("hongyuan"), - [1, 2], - function (card, player, target) { - return player != target; - }, - function (target) { - if (!_status.event.check) return 0; - return get.attitude(_status.event.player, target); - } + lianhuan: { + marktext: "凤", + intro: { + name: "凤印", + content: "
  • 出牌阶段限三次。你可以将一张♣牌当作【铁索连环】使用或重铸,且你以此法使用【铁索连环】的目标数上限+1。
  • 若你同时拥有“龙印”,则你视为拥有技能〖业炎〗。(发动〖业炎〗时,弃置所有“龙印”和“凤印”)", + }, + charlotte: true, + usable: 3, + filter: function (event, player) { + const storage = player.getStorage("jianjie_lianhuan"); + if ( + !storage.some(source => { + return source.isIn() && source.hasSkill("jianjie"); + }) ) - .set("check", check); - } - "step 1"; - if (result.bool) { - var targets; - if (event.versus) { - targets = game.filterPlayer(function (current) { - return current != player && current.side == player.side; - }); - } else { - targets = result.targets; - } - player.logSkill("hongyuan", targets); - game.asyncDraw(targets); - trigger.num--; - } - }, - }, - huanshi: { - audio: 2, - trigger: { global: "judge" }, - filter: function (event, player) { - return player.countCards("he") > 0; - }, - logTarget: "player", - check: function (event, player) { - if (get.attitude(player, event.player) <= 0) return false; - var cards = player.getCards("he"); - var judge = event.judge(event.player.judging[0]); - for (var i = 0; i < cards.length; i++) { - var judge2 = event.judge(cards[i]); - if (judge2 > judge) return true; - if (_status.currentPhase != player && judge2 == judge && get.color(cards[i]) == "red" && get.useful(cards[i]) < 5) return true; - } - return false; - }, - content: function () { - "step 0"; - var target = trigger.player; - var judge = trigger.judge(target.judging[0]); - var attitude = get.attitude(target, player); - target - .choosePlayerCard("请选择代替判定的牌", "he", "visible", true, player) - .set("ai", function (button) { - var card = button.link; - var judge = _status.event.judge; - var attitude = _status.event.attitude; - var result = trigger.judge(card) - judge; - var player = _status.event.player; - if (result > 0) { - return 20 + result; - } - if (result == 0) { - if (_status.currentPhase == player) return 0; - if (attitude >= 0) { - return get.color(card) == "red" ? 7 : 0 - get.value(card); - } else { - return get.color(card) == "black" ? 10 : 0 + get.value(card); - } + return false; + if (!player.hasCard(card => get.suit(card) == "club", "she")) return false; + return event.type == "phase" || event.filterCard({ name: "tiesuo" }, player, event); + }, + inherit: "ollianhuan", + group: ["jianjie_yeyan", "jianjie_lianhuan_effect"], + }, + lianhuan_effect: { + trigger: { player: "useCard2" }, + filter: function (event, player) { + if (event.skill != "jianjie_lianhuan") return false; + var info = get.info(event.card); + if (info.allowMultiple == false) return false; + if (event.targets && !info.multitarget) { + if ( + game.hasPlayer(current => { + return !event.targets.includes(current) && lib.filter.targetEnabled2(event.card, player, current); + }) + ) + return true; } - if (attitude >= 0) { - return get.color(card) == "red" ? 0 : -10 + result; - } else { - return get.color(card) == "black" ? 0 : -10 + result; + return false; + }, + charlotte: true, + forced: true, + popup: false, + content: function () { + "step 0"; + player + .chooseTarget("是否为" + get.translation(trigger.card) + "额外指定一个目标?", (card, player, target) => { + return !_status.event.sourcex.includes(target) && lib.filter.targetEnabled2(_status.event.card, player, target); + }) + .set("sourcex", trigger.targets) + .set("ai", function (target) { + var player = _status.event.player; + return get.effect(target, _status.event.card, player, player); + }) + .set("card", trigger.card); + "step 1"; + if (result.bool) { + if (!event.isMine() && !event.isOnline()) game.delayex(); + } else event.finish(); + "step 2"; + if (result.bool) { + var targets = result.targets; + player.line(targets, "thunder"); + trigger.targets.addArray(targets); + game.log(targets, "也成为了", trigger.card, "的目标"); } - }) - .set("filterButton", function (button) { - var player = _status.event.target; - var card = button.link; - var mod2 = game.checkMod(card, player, "unchanged", "cardEnabled2", player); - if (mod2 != "unchanged") return mod2; - var mod = game.checkMod(card, player, "unchanged", "cardRespondable", player); - if (mod != "unchanged") return mod; - return true; - }) - .set("judge", judge) - .set("attitude", attitude); - "step 1"; - if (result.bool) { - event.card = result.links[0]; - player.respond(event.card, "highlight", "noOrdering").nopopup = true; - } else { - event.finish(); - } - "step 2"; - if (result.bool) { - if (trigger.player.judging[0].clone) { - trigger.player.judging[0].clone.classList.remove("thrownhighlight"); - game.broadcast(function (card) { - if (card.clone) { - card.clone.classList.remove("thrownhighlight"); - } - }, trigger.player.judging[0]); - game.addVideo("deletenode", player, get.cardsInfo([trigger.player.judging[0].clone])); - } - game.cardsDiscard(trigger.player.judging[0]); - trigger.player.judging[0] = event.card; - trigger.orderingCards.add(event.card); - game.log(trigger.player, "的判定牌改为", event.card); - game.delay(2); - } + }, + }, + yeyan: { + inherit: "yeyan", + filter: function (event, player) { + const huoji = player.getStorage("jianjie_huoji"), + lianhuan = player.getStorage("jianjie_lianhuan"); + return ( + huoji.length > 0 && + lianhuan.some(source => { + return huoji.includes(source) && source.isIn() && source.hasSkill("jianjie"); + }) + ); + }, + contentBefore: function () { + player.awakenSkill("jianjie_yeyan"); + var skill = lib.skill.jianjie; + var huoji = player.getStorage("jianjie_huoji").slice(0), + lianhuan = player.getStorage("jianjie_lianhuan").slice(0); + huoji.forEach(source => { + skill.removeMark("huoji", source, player, true); + }); + lianhuan.forEach(source => { + skill.removeMark("lianhuan", source, player, true); + }); + }, + }, + }, + }, + xinfu_yinshi: { + audio: 2, + trigger: { player: "damageBegin4" }, + forced: true, + filter: function (event, player) { + const skill = lib.skill.jianjie; + if (skill.hasMark("huoji", player) || skill.hasMark("lianhuan", player)) return false; + if (!player.hasEmptySlot(2)) return false; + if (event.hasNature()) return true; + return get.type(event.card, "trick") == "trick"; + }, + content: function () { + trigger.cancel(); }, ai: { - rejudge: true, - tag: { - rejudge: 1, + notrick: true, + nofire: true, + nothunder: true, + effect: { + target: function (card, player, target, current) { + const skill = lib.skill.jianjie; + if (skill.hasMark("huoji", target) || skill.hasMark("lianhuan", target)) return false; + if (player == target && get.subtype(card) == "equip2") { + if (get.equipValue(card) <= 8) return 0; + } + if (!target.hasEmptySlot(2)) return; + if (get.tag(card, "natureDamage")) return "zeroplayertarget"; + if (get.type(card) == "trick" && get.tag(card, "damage")) { + return "zeroplayertarget"; + } + }, }, }, }, - mingzhe: { + xinfu_chenghao: { audio: 2, trigger: { - player: ["useCard", "respond", "loseAfter"], - global: "loseAsyncAfter", + global: "damageEnd", }, - frequent: true, filter: function (event, player) { - if (player == _status.currentPhase) return false; - if (event.name.indexOf("lose") != 0) return get.color(event.card) == "red"; - if (event.type != "discard") return false; - var evt = event.getl(player); - if (evt && evt.cards2) { - for (var i = 0; i < evt.cards2.length; i++) { - if (get.color(evt.cards2[i], player) == "red") return true; - } - } - return false; + return event.lianhuanable == true && event.player.isIn(); }, + frequent: true, content: function () { "step 0"; - event.count = 1; - if (trigger.name.indexOf("lose") == 0) { - event.count = 0; - var evt = trigger.getl(player); - for (var i = 0; i < evt.cards2.length; i++) { - if (get.color(evt.cards2[i], player) == "red") event.count++; - } - } + event.cards = game.cardsGotoOrdering( + get.cards( + game.countPlayer(function (current) { + return current.isLinked(); + }) + 1 + ) + ).cards; + if (_status.connectMode) + game.broadcastAll(function () { + _status.noclearcountdown = true; + }); + event.given_map = {}; "step 1"; - player.draw(); - event.count--; + if (event.cards.length > 1) { + player.chooseCardButton("称好:请选择要分配的牌", true, event.cards, [1, event.cards.length]).set("ai", function (button) { + if (ui.selected.buttons.length == 0) return 1; + return 0; + }); + } else if (event.cards.length == 1) { + event._result = { links: event.cards.slice(0), bool: true }; + } else { + event.finish(); + } "step 2"; - if (event.count && player.hasSkill(event.name) && !get.is.blocked(event.name, player)) { - player.chooseBool(get.prompt2("mingzhe")).set("frequentSkill", event.name); - } else event.finish(); - "step 3"; if (result.bool) { - player.logSkill("mingzhe"); - event.goto(1); + event.cards.removeArray(result.links); + event.togive = result.links.slice(0); + player + .chooseTarget("选择一名角色获得" + get.translation(result.links), true) + .set("ai", function (target) { + var att = get.attitude(_status.event.player, target); + if (_status.event.enemy) { + return -att; + } else if (att > 0) { + return att / (1 + target.countCards("h")); + } else { + return att / 100; + } + }) + .set("enemy", get.value(event.togive[0], player, "raw") < 0); } - }, - ai: { - threaten: 0.7, - }, - }, - - duwu: { - audio: 2, - enable: "phaseUse", - filter: function (event, player) { - return ( - player.hasSkill("duwu2") == false && - game.hasPlayer(function (current) { - return current.hp > 0 && current.hp <= player.countCards("he") && player.inRange(current); - }) - ); - }, - filterCard: function () { - if (ui.selected.targets.length) return false; - return true; - }, - position: "he", - selectCard: [1, Infinity], - complexSelect: true, - complexCard: true, - filterTarget: function (card, player, target) { - return target != player && target.hp > 0 && player.inRange(target) && ui.selected.cards.length == target.hp; - }, - check: function (card) { - var player = _status.event.player; - if ( - game.hasPlayer(function (current) { - return current != player && current.hp > 0 && player.inRange(current) && ui.selected.cards.length == current.hp && get.damageEffect(current, player, player) > 0; - }) - ) - return 0; - switch (ui.selected.cards.length) { - case 0: - return 8 - get.value(card); - case 1: - return 6 - get.value(card); - case 2: - return 3 - get.value(card); - default: - return 0; + "step 3"; + if (result.targets.length) { + var id = result.targets[0].playerid, + map = event.given_map; + if (!map[id]) map[id] = []; + map[id].addArray(event.togive); } - }, - content: function () { - player.addTempSkill("duwu3"); - target.damage("nocard"); - }, - ai: { - damage: true, - order: 2, - result: { - target: function (player, target) { - return get.damageEffect(target, player); - }, - }, - threaten: 1.5, - expose: 0.3, - }, - }, - duwu2: { charlotte: true }, - duwu3: { - trigger: { global: "dyingAfter" }, - forced: true, - popup: false, - charlotte: true, - filter: function (event, player) { - return event.player.isIn() && event.reason && event.reason.getParent().name == "duwu"; - }, - content: function () { - player.loseHp(); - player.addTempSkill("duwu2"); + if (cards.length > 0) event.goto(1); + "step 4"; + if (_status.connectMode) { + game.broadcastAll(function () { + delete _status.noclearcountdown; + game.stopCountChoose(); + }); + } + var list = []; + for (var i in event.given_map) { + var source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; + player.line(source, "green"); + list.push([source, event.given_map[i]]); + } + game.loseAsync({ + gain_list: list, + giver: player, + animate: "draw", + }).setContent("gaincardMultiple"); }, }, - yicong: { + xinfu_wuniang: { trigger: { - player: ["changeHp"], + player: ["useCard", "respond"], }, audio: 2, - audioname: ["re_gongsunzan"], - forced: true, + direct: true, filter: function (event, player) { - return get.sgn(player.hp - 2.5) != get.sgn(player.hp - 2.5 - event.num); - }, - content: function () {}, - mod: { - globalFrom: function (from, to, current) { - if (from.hp > 2) return current - 1; - }, - globalTo: function (from, to, current) { - if (to.hp <= 2) return current + 1; - }, - }, - ai: { - threaten: 0.8, + return event.card.name == "sha"; }, - }, - yongsi: { - audio: 2, - group: ["yongsi1", "yongsi2"], - locked: true, - ai: { - threaten: 3.2, + content: function () { + "step 0"; + player + .chooseTarget(get.prompt("xinfu_wuniang"), "获得一名其他角色的一张牌,然后其和场上所有的“关索”摸一张牌。", function (card, player, target) { + if (player == target) return false; + return target.countGainableCards(player, "he") > 0; + }) + .set("ai", function (target) { + return 10 - get.attitude(_status.event.player, target); + }); + "step 1"; + if (result.bool) { + var target = result.targets[0]; + player.logSkill("xinfu_wuniang", target); + player.line(target, "fire"); + event.draws = game.filterPlayer(function (current) { + if (current == target) return true; + return current.name == "guansuo" || current.name2 == "guansuo"; + }); + player.gainPlayerCard(target, "he", true); + } else event.finish(); + "step 2"; + game.asyncDraw(event.draws, 1); + game.delay(); }, }, - yongsi1: { - audio: true, - trigger: { player: "phaseDrawBegin2" }, - forced: true, - filter: function (event, player) { - return !event.numFixed; + xinfu_xushen: { + derivation: ["xinfu_zhennan"], + audio: 2, + subSkill: { + count: { + trigger: { + player: "recoverBegin", + }, + forced: true, + silent: true, + popup: false, + filter: function (event, player) { + if (!event.card || event.card.name != "tao") return false; + if (!event.source || !event.source.hasSex("male")) return false; + if (!player.isDying()) return false; + if ( + game.hasPlayer(function (current) { + return current.name == "guansuo" || current.name2 == "guansuo"; + }) + ) + return false; + return true; + }, + content: function () { + trigger.xinfu_xushen = true; + }, + sub: true, + }, }, - content: function () { - trigger.num += game.countGroup(); + group: ["xinfu_xushen_count"], + trigger: { + player: "recoverAfter", }, - }, - yongsi2: { - audio: true, - trigger: { player: "phaseDiscardBegin" }, - forced: true, - content: function () { - player.chooseToDiscard(game.countGroup(), "he", true); + limited: true, + init: function (player) { + player.storage.xinfu_xushen = false; }, - }, - bifa: { - trigger: { player: "phaseJieshuBegin" }, - direct: true, - audio: 2, filter: function (event, player) { - return player.countCards("h") > 0; + if (player.storage.xinfu_xushen) return false; + if (player.isDying()) return false; + return event.xinfu_xushen == true; }, + direct: true, + skillAnimation: true, + animationColor: "fire", content: function () { "step 0"; - player.chooseCardTarget({ - filterCard: true, - filterTarget: function (card, player, target) { - return player != target && !target.getExpansions("bifa2").length; - }, - ai1: function (card) { - return 7 - get.value(card); - }, - ai2: function (target) { - var num = target.hasSkillTag("maixie") ? 2 : 0; - return -get.attitude(_status.event.player, target) - num; - }, - prompt: get.prompt2("bifa"), + trigger.source.chooseBool("【许身】:是否将自己的一张武将牌替换为“关索”?").set("ai", function () { + return false; }); "step 1"; if (result.bool) { - event.forceDie = true; - var target = result.targets[0]; - event.target = target; - player.logSkill("bifa", result.targets[0]); - event.card = result.cards[0]; - target.storage.bifa2 = [result.cards[0], player]; - if (!_status.connectMode && player.isUnderControl(true)) player.$giveAuto(result.cards[0], target, false); - else player.$give(1, target, false); - target.addToExpansion(result.cards[0]).gaintag.add("bifa2"); + player.awakenSkill("xinfu_xushen"); + player.logSkill("xinfu_xushen", trigger.source); + if (trigger.source.name2 != undefined) { + trigger.source.chooseControl(trigger.source.name1, trigger.source.name2).set("prompt", "请选择要更换的武将牌"); + } else event._result = { control: trigger.source.name1 }; } else event.finish(); "step 2"; - if (target.getExpansions("bifa2").includes(card)) { - target.addSkill("bifa2"); - } else delete target.storage.bifa2; + trigger.source.reinitCharacter(result.control, "guansuo"); + player.recover(); + player.addSkills("xinfu_zhennan"); }, - ai: { - threaten: 1.7, - expose: 0.3, + mark: true, + intro: { + content: "limited", }, }, - bifa2: { - trigger: { player: "phaseZhunbeiBegin" }, + xinfu_falu: { + subSkill: { + spade: { + marktext: "♠︎️", + intro: { + name: "紫薇", + content: "mark", + }, + }, + heart: { + marktext: "♥︎️", + intro: { + name: "玉清", + content: "mark", + }, + }, + club: { + marktext: "♣︎️", + intro: { + name: "后土", + content: "mark", + }, + }, + diamond: { + marktext: "♦︎", + intro: { + name: "勾陈", + content: "mark", + }, + }, + }, forced: true, - charlotte: true, - audio: false, + audio: 2, + trigger: { + player: ["loseAfter", "enterGame"], + global: ["loseAsyncAfter", "phaseBefore"], + }, filter: function (event, player) { - return player.storage.bifa2 && player.getExpansions("bifa2").includes(player.storage.bifa2[0]); + if (event.name.indexOf("lose") != 0) return event.name != "phase" || game.phaseNumber == 0; + if (event.type != "discard" || event.getlx === false) return false; + var evt = event.getl(player); + for (var i = 0; i < evt.cards2.length; i++) { + if (!player.hasMark("xinfu_falu_" + get.suit(evt.cards2[i]))) return true; + } + return false; + }, + content: function () { + if (trigger.name.indexOf("lose") !== 0) { + for (var i = 0; i < lib.suit.length; i++) { + if (!player.hasMark("xinfu_falu_" + lib.suit[i])) player.addMark("xinfu_falu_" + lib.suit[i]); + } + return; + } + var evt = trigger.getl(player); + for (var i = 0; i < evt.cards2.length; i++) { + var suit = get.suit(evt.cards2[i]); + if (!player.hasMark("xinfu_falu_" + suit)) player.addMark("xinfu_falu_" + suit); + } + }, + ai: { + threaten: 1.4, + combo: "xinfu_zhenyi", + }, + }, + xinfu_dianhua: { + trigger: { + player: ["phaseZhunbeiBegin", "phaseJieshuBegin"], + }, + frequent: true, + audio: 2, + filter: function (event, player) { + for (var i = 0; i < lib.suit.length; i++) { + if (player.hasMark("xinfu_falu_" + lib.suit[i])) return true; + } + return false; }, content: function () { "step 0"; - if (player.storage.bifa2[1].isIn() && player.countCards("h")) { - player - .chooseCard(get.translation(player.storage.bifa2[1]) + "的笔伐牌为:", function (card) { - return get.type(card, "trick") == _status.event.type; - }) - .set("ai", function (card) { - return 8 - get.value(card); - }) - .set("type", get.type(player.storage.bifa2[0], "trick")) - .set("promptx", [[player.storage.bifa2[0]], "请交给其一张与此牌类别相同的手牌,否则失去1点体力"]); - } else { - event.directfalse = true; + var num = 0; + for (var i = 0; i < lib.suit.length; i++) { + if (player.hasMark("xinfu_falu_" + lib.suit[i])) num++; } + var cards = get.cards(num); + game.cardsGotoOrdering(cards); + var next = player.chooseToMove(); + next.set("list", [["牌堆顶", cards], ["牌堆底"]]); + next.set("prompt", "点化:点击或拖动将牌移动到牌堆顶或牌堆底"); + next.processAI = function (list) { + var cards = list[0][1], + player = _status.event.player; + var target = _status.event.getTrigger().name == "phaseZhunbei" ? player : player.next; + var att = get.sgn(get.attitude(player, target)); + var top = []; + var judges = target.getCards("j"); + var stopped = false; + if (player != target || !target.hasWuxie()) { + for (var i = 0; i < judges.length; i++) { + var judge = get.judge(judges[i]); + cards.sort(function (a, b) { + return (judge(b) - judge(a)) * att; + }); + if (judge(cards[0]) * att < 0) { + stopped = true; + break; + } else { + top.unshift(cards.shift()); + } + } + } + var bottom; + if (!stopped) { + cards.sort(function (a, b) { + return (get.value(b, player) - get.value(a, player)) * att; + }); + while (cards.length) { + if (get.value(cards[0], player) <= 5 == att > 0) break; + top.unshift(cards.shift()); + } + } + bottom = cards; + return [top, bottom]; + }; "step 1"; - if (result.bool && !event.directfalse) { - player.give(result.cards, player.storage.bifa2[1]); - player.gain(player.storage.bifa2[0], "draw"); - } else { - player.loseHp(); + var top = result.moved[0]; + var bottom = result.moved[1]; + top.reverse(); + for (var i = 0; i < top.length; i++) { + ui.cardPile.insertBefore(top[i], ui.cardPile.firstChild); } - "step 2"; - player.removeSkill("bifa2"); - }, - marktext: "檄", - intro: { - markcount: () => 1, - name: "笔伐", - content: "已成为〖笔伐〗的目标", + for (i = 0; i < bottom.length; i++) { + ui.cardPile.appendChild(bottom[i]); + } + player.popup(get.cnNumber(top.length) + "上" + get.cnNumber(bottom.length) + "下"); + game.log(player, "将" + get.cnNumber(top.length) + "张牌置于牌堆顶"); + game.updateRoundNumber(); + game.delayx(); }, - onremove: function (player, skill) { - var cards = player.getExpansions(skill); - if (cards.length) player.loseToDiscardpile(cards); - delete player.storage[skill]; + ai: { + combo: "xinfu_falu", + threaten: 2.2, }, }, - songci: { + xinfu_zhenyi: { + group: ["zhenyi_spade", "zhenyi_club", "zhenyi_heart"], + trigger: { + player: "damageEnd", + }, audio: 2, - enable: "phaseUse", filter: function (event, player) { - if (!player.storage.songci) return true; - return game.hasPlayer(function (current) { - return !player.storage.songci.includes(current); - }); - }, - init: function (player) { - if (!player.storage.songci) player.storage.songci = []; - }, - filterTarget: function (card, player, target) { - return !player.storage.songci || !player.storage.songci.includes(target); + //if(!event.hasNature()) return false; + return player.hasMark("xinfu_falu_diamond"); }, + prompt2: "弃置「勾陈♦」标记,从牌堆中获得每种类型的牌各一张。", content: function () { - if (target.countCards("h") > target.hp) { - target.chooseToDiscard(2, "he", true); - } else { - target.draw(2); + "step 0"; + player.removeMark("xinfu_falu_diamond"); + event.num = 0; + event.togain = []; + "step 1"; + var card = get.cardPile(function (card) { + for (var i = 0; i < event.togain.length; i++) { + if (get.type(card, "trick") == get.type(event.togain[i], "trick")) return false; + } + return true; + }); + if (card) { + event.togain.push(card); + event.num++; + if (event.num < 3) event.redo(); + } + "step 2"; + if (event.togain.length) { + player.gain(event.togain, "gain2"); } - if (!player.storage.songci) player.storage.songci = []; - player.storage.songci.push(target); - player.storage.songci.sortBySeat(); - player.markSkill("songci"); - }, - intro: { - content: "已对$发动过〖颂词〗", }, ai: { - order: 7, - threaten: 1.6, - expose: 0.2, - result: { - target: function (player, target) { - if (target.countCards("h") <= target.hp) { - return 1; - } else if (target.countCards("h") > target.hp) { - return -1; - } - }, - }, + combo: "xinfu_falu", }, - group: "songci_draw", }, - songci_draw: { - audio: "songci", - trigger: { player: "phaseDiscardEnd" }, - forced: true, - filter: function (event, player) { - if (!player.storage.songci) return false; - return !game.hasPlayer(function (current) { - return !player.storage.songci.includes(current); - }); - }, - content: function () { - player.draw(); + zhenyi_spade: { + trigger: { + global: "judge", }, - }, - baobian: { - audio: 2, - trigger: { player: ["phaseBefore", "changeHp"] }, - forced: true, - popup: false, - init: function (player) { - if (game.online) return; - player.removeAdditionalSkill("baobian"); - var list = []; - if (player.hp <= 3) { - //if(trigger.num!=undefined&&trigger.num<0&&player.hp-trigger.num>1) player.logSkill('baobian'); - list.push("oltiaoxin"); - } - if (player.hp <= 2) { - list.push("olpaoxiao"); - } - if (player.hp <= 1) { - list.push("xinshensu"); - } - if (list.length) { - player.addAdditionalSkill("baobian", list); - } + direct: true, + filter: function (event, player) { + return player.hasMark("xinfu_falu_spade"); }, - derivation: ["oltiaoxin", "olpaoxiao", "xinshensu"], content: function () { - player.removeAdditionalSkill("baobian"); - var list = []; - if (player.hp <= 3) { - if (trigger.num != undefined && trigger.num < 0 && player.hp - trigger.num > 1) player.logSkill("baobian"); - list.push("oltiaoxin"); - } - if (player.hp <= 2) { - list.push("olpaoxiao"); - } - if (player.hp <= 1) { - list.push("xinshensu"); - } - if (list.length) { - player.addAdditionalSkill("baobian", list); + "step 0"; + var str = get.translation(trigger.player) + "的" + (trigger.judgestr || "") + "判定为" + get.translation(trigger.player.judging[0]) + ",是否发动【真仪】,弃置「紫薇♠」标记并修改判定结果?"; + player + .chooseControl("spade", "heart", "diamond", "club", "cancel2") + .set("prompt", str) + .set("ai", function () { + //return '取消'; + var judging = _status.event.judging; + var trigger = _status.event.getTrigger(); + var res1 = trigger.judge(judging); + var list = lib.suit.slice(0); + var attitude = get.attitude(player, trigger.player); + if (attitude == 0) return 0; + var getj = function (suit) { + return trigger.judge({ + name: get.name(judging), + nature: get.nature(judging), + suit: suit, + number: 5, + }); + }; + list.sort(function (a, b) { + return (getj(b) - getj(a)) * get.sgn(attitude); + }); + if ((getj(list[0]) - res1) * attitude > 0) return list[0]; + return "cancel2"; + }) + .set("judging", trigger.player.judging[0]); + "step 1"; + if (result.control != "cancel2") { + player.addExpose(0.25); + player.removeMark("xinfu_falu_spade"); + player.logSkill("xinfu_zhenyi", trigger.player); + //player.line(trigger.player); + player.popup(result.control); + game.log(player, "将判定结果改为了", "#y" + get.translation(result.control + 2) + 5); + trigger.fixedResult = { + suit: result.control, + color: get.color({ suit: result.control }), + number: 5, + }; } }, ai: { - maixie: true, - effect: { - target: function (card, player, target) { - if (get.tag(card, "damage")) { - if (!target.hasFriend()) return; - if (target.hp >= 4) return [0, 1]; - } - if (get.tag(card, "recover") && player.hp >= player.maxHp - 1) return [0, 0]; - }, + rejudge: true, + tag: { + rejudge: 1, }, + expose: 0.5, }, }, - chongzhen: { - audio: 2, - audioname: ["huan_zhaoyun"], - trigger: { player: ["useCard", "respond"] }, - filter: function (event, player) { - if (event.card.name != "sha" && event.card.name != "shan") return false; - if (!event.skill || event.skill.indexOf("fanghun") + event.skill.indexOf("longdan") == -2) return false; - var target = lib.skill.chongzhen.logTarget(event, player); - return target && target.countGainableCards(player, "h") > 0; - }, - logTarget: function (event, player) { - if (event.name == "respond") return event.source; - if (event.card.name == "sha") return event.targets[0]; - return event.respondTo[0]; + zhenyi_club: { + audio: "xinfu_zhenyi", + enable: "chooseToUse", + viewAsFilter: function (player) { + if (player == _status.currentPhase) return false; + return player.hasMark("xinfu_falu_club") && player.countCards("hs") > 0; }, - prompt2: function (event, player) { - var target = lib.skill.chongzhen.logTarget(event, player); - return "获得" + get.translation(target) + "的一张手牌"; + filterCard: true, + position: "hs", + viewAs: { + name: "tao", }, - content: function () { - var target = lib.skill.chongzhen.logTarget(trigger, player); - player.gainPlayerCard(target, "h", true); + prompt: "弃置「后土♣」标记,将一张手牌当桃使用", + check: function (card) { + return 15 - get.value(card); }, - ai: { - combo: "ollongdan", - mingzhi: false, - effect: { - target: function (card, player, target, current) { - if (get.tag(card, "respondShan") || get.tag(card, "respondSha")) { - if (get.attitude(target, player) <= 0) { - if (current > 0) return; - if (target.countCards("h") == 0) return 1.6; - if (target.countCards("h") == 1) return 1.2; - if (target.countCards("h") == 2) return [0.8, 0.2, 0, -0.2]; - return [0.4, 0.7, 0, -0.7]; - } - } - }, - }, + precontent: function () { + player.removeMark("xinfu_falu_club"); }, }, - lihun: { - audio: 2, - enable: "phaseUse", - usable: 1, - filterTarget: function (card, player, target) { - return player != target && target.hasSex("male"); + zhenyi_heart: { + trigger: { + source: "damageBegin1", + }, + audio: "xinfu_zhenyi", + filter: function (event, player) { + return player.hasMark("xinfu_falu_heart"); + }, + check: function (event, player) { + if (get.attitude(player, event.player) >= 0) return false; + if ( + event.player.hasSkillTag("filterDamage", null, { + player: player, + card: event.card, + }) + ) + return false; + return true; + //return player.hasMark('xinfu_falu_spade')||get.color(ui.cardPile.firstChild)=='black'; + }, + prompt2: function (event) { + return "弃置「玉清♥」标记,令对" + get.translation(event.player) + "即将造成的伤害+1。"; }, - filterCard: true, - position: "he", + logTarget: "player", content: function () { - player.gainPlayerCard(target, true, "h", target.countCards("h")); - player.turnOver(); - player.addSkill("lihun2"); - player.storage.lihun = target; + player.removeMark("xinfu_falu_heart"); + trigger.num++; }, - check: function (card) { - return 8 - get.value(card); + }, + xinfu_zhennan: { + audio: 2, + trigger: { + target: "useCardToTargeted", }, - ai: { - order: 10, - result: { - player: function (player) { - if (player.classList.contains("turnedover")) return 10; - return 0; - }, - target: function (player, target) { - if (target.countCards("h") > target.hp) return target.hp - target.countCards("h"); - return 0; - }, - }, - threaten: 1.5, - effect: { - target: function (card) { - if (card.name == "guiyoujie") return [0, 2]; - }, - }, + filter: function (event, player) { + return event.card.name == "nanman"; }, - }, - lihun2: { - trigger: { player: "phaseUseEnd" }, - forced: true, - popup: false, - audio: false, + direct: true, content: function () { "step 0"; - var cards = player.getCards("he"); - player.removeSkill("lihun2"); - if (player.storage.lihun.classList.contains("dead") || player.storage.lihun.hp <= 0 || cards.length == 0) { - event.finish(); - } else { - if (cards.length < player.storage.lihun.hp) event._result = { bool: true, cards: cards }; - else player.chooseCard("he", true, player.storage.lihun.hp, "离魂:选择要交给" + get.translation(player.storage.lihun) + "的牌"); - } + player + .chooseTarget(get.prompt("xinfu_zhennan"), "对一名其他角色造成1-3点随机伤害", function (card, player, target) { + return target != player; + }) + .set("ai", function (target) { + var player = _status.event.player; + return get.damageEffect(target, player, player); + }); "step 1"; - player.give(result.cards, player.storage.lihun); + if (result.bool && result.targets && result.targets.length) { + game.delay(); + player.logSkill("xinfu_zhennan", result.targets); + var num = [1, 2, 3, 1, 1, 2].randomGet(); + if (get.isLuckyStar(player)) num = 3; + //player.line(result.targets[0],'fire'); + result.targets[0].damage(num); + } + }, + ai: { + expose: 0.25, }, }, - yuanhu: { - audio: 3, - trigger: { player: "phaseJieshuBegin" }, + xinyingshi: { + audio: "xinfu_yingshi", + trigger: { player: "phaseUseBegin" }, direct: true, filter: function (event, player) { - return player.countCards("he", { type: "equip" }) > 0; + return ( + player.countCards("he") > 0 && + !game.hasPlayer(function (current) { + return current.getExpansions("xinyingshi_cards").length > 0; + }) + ); }, content: function () { "step 0"; player.chooseCardTarget({ - filterCard: function (card) { - return get.type(card) == "equip"; - }, + filterCard: true, + filterTarget: lib.filter.notMe, + selectCard: [1, player.countCards("he")], position: "he", - filterTarget: function (card, player, target) { - return target.canEquip(card); - }, + prompt: get.prompt("xinyingshi"), + prompt2: "将任意张牌置于一名其他角色的武将牌上作为“酬”", ai1: function (card) { - return 6 - get.value(card); + return 1 - player.getUseValue(card); }, ai2: function (target) { - return get.attitude(_status.event.player, target) - 3; + var player = _status.event.player; + return ( + (1 + + game.countPlayer(function (current) { + return get.attitude(player, current) > 0 && current.inRange(target) && get.damageEffect(target, current, player) > 0; + })) * + -get.attitude(player, target) + ); }, - prompt: get.prompt2("yuanhu"), - }); - "step 1"; - if (result.bool) { - player.logSkill("yuanhu", result.targets); - var thisTarget = result.targets[0]; - var thisCard = result.cards[0]; - thisTarget.equip(thisCard); - event.target = thisTarget; - if (thisTarget != player) { - player.$give(thisCard, thisTarget, false); - } - switch (get.subtype(thisCard)) { - case "equip1": { - if ( - !game.hasPlayer(function (current) { - return get.distance(thisTarget, current) <= 1; - }) - ) { - event.finish(); - return; - } - game.delay(); - player - .chooseTarget(true, function (card, player, target) { - return get.distance(_status.event.thisTarget, target) <= 1 && target.countCards("hej"); - }) - .set("ai", function (target) { - var attitude = get.attitude(_status.event.player, target); - if (attitude > 0 && target.countCards("j")) { - return attitude * 1.5; - } - return -attitude; - }) - .set("thisTarget", thisTarget); - return; - } - case "equip2": { - thisTarget.draw(); - event.finish(); - return; - } - case "equip5": { - event.finish(); - return; - } - default: { - thisTarget.recover(); - event.finish(); - return; - } - } - } else { - event.finish(); - } - "step 2"; - if (result.targets.length) { - player.discardPlayerCard(true, result.targets[0], "hej"); - } - }, - }, - tianming: { - audio: 2, - trigger: { target: "useCardToTargeted" }, - check: function (event, player) { - var cards = player.getCards("h"); - if (cards.length <= 2) { - for (var i = 0; i < cards.length; i++) { - if (cards[i].name == "shan" || cards[i].name == "tao") return false; - } - } - return true; - }, - filter: function (event, player) { - return event.card.name == "sha"; - }, - content: function () { - "step 0"; - player.chooseToDiscard(2, true, "he"); - player.draw(2); - var players = game.filterPlayer(); - players.sort(function (a, b) { - return b.hp - a.hp; }); - if (players[0].hp > players[1].hp && players[0] != player) { - players[0].chooseBool(get.prompt2("tianming")); - event.player = players[0]; - } else { - event.finish(); - } "step 1"; if (result.bool) { - player.chooseToDiscard(2, true, "he"); - player.draw(2); + var target = result.targets[0], + cards = result.cards; + player.logSkill("xinyingshi", target); + target.addSkill("xinyingshi_cards"); + target.addToExpansion(player, "give", cards).gaintag.add("xinyingshi_cards"); + target.storage.xinyingshi_source = player; } }, - ai: { - effect: { - target_use(card, player, target, current) { - if (card.name == "sha") return [1, 0.5]; - }, - }, - }, - }, - mizhao: { - enable: "phaseUse", - usable: 1, - audio: 2, - filter: function (event, player) { - return player.countCards("h") > 0; - }, - filterCard: true, - selectCard: -1, - filterTarget: function (card, player, target) { - return player != target; - }, - discard: false, - lose: false, - delay: false, - ai: { - order: 1, - result: { - player: 0, - target: function (player, target) { - if (target.hasSkillTag("nogain")) return 0; - if (player.countCards("h") > 1) { - return 1; - } - var players = game.filterPlayer(); - for (var i = 0; i < players.length; i++) { - if (players[i].countCards("h") && players[i] != target && players[i] != player && get.attitude(player, players[i]) < 0) { - break; - } - } - if (i == players.length) { - return 1; - } - return -2 / (target.countCards("h") + 1); + subSkill: { + cards: { + trigger: { player: "damageSource" }, + forced: true, + charlotte: true, + filter: function (event, player) { + return event.source && event.source.isIn() && event.card && event.getParent().type == "card" && player.getExpansions("xinyingshi_cards").length; }, - }, - }, - content: function () { - "step 0"; - event.target1 = targets[0]; - player.give(cards, targets[0], "giveAuto"); - "step 1"; - if (!targets[0].countCards("h")) { - event.finish(); - return; - } - var players = game.filterPlayer(); - for (var i = 0; i < players.length; i++) { - if (players[i] != event.target1 && players[i] != player && event.target1.canCompare(players[i])) { - break; - } - } - if (i == players.length) { - event.finish(); - } - "step 2"; - player - .chooseTarget(true, "选择拼点目标", function (card, player, target) { - return _status.event.target1.canCompare(target) && target != player; - }) - .set("ai", function (target) { - var player = _status.event.player; - var eff = get.effect(target, { name: "sha" }, _status.event.target1, player); - var att = get.attitude(player, target); - if (att > 0) { - return eff - 10; - } - return eff; - }) - .set("target1", event.target1) - .set("forceDie", true); - "step 3"; - if (result.targets.length) { - event.target2 = result.targets[0]; - event.target1.line(event.target2); - event.target1.chooseToCompare(event.target2); - } else { - event.finish(); - } - "step 4"; - if (!result.tie) { - if (result.bool) { - if (event.target1.canUse({ name: "sha", isCard: true }, event.target2, false)) event.target1.useCard({ name: "sha", isCard: true }, event.target2); - } else if (event.target2.canUse({ name: "sha", isCard: true }, event.target1, false)) { - event.target2.useCard({ name: "sha", isCard: true }, event.target1); - } - } + logTarget: "source", + content: function () { + "step 0"; + event.target = trigger.source; + event.target.chooseButton(["应势:请选择你的赏金", player.getExpansions("xinyingshi_cards")]); + "step 1"; + if (result.bool) { + var cards = [result.links[0]]; + for (var i = 0; i < ui.cardPile.childNodes.length; i++) { + var card = ui.cardPile.childNodes[i]; + if (card.number == cards[0].number && card.suit == cards[0].suit) cards.push(card); + } + player.$give(cards[0], target); + if (cards.length > 1) { + setTimeout(function () { + target.$gain2(cards.slice(1)); + }, get.delayx(200, 200)); + game.log(target, "从牌堆获得了", cards.slice(1)); + } + game.delay(0, get.delayx(500, 500)); + target.gain(cards); + } + "step 2"; + if (!player.getExpansions("xinyingshi_cards").length) player.removeSkill("xinyingshi_cards"); + }, + marktext: "酬", + intro: { + content: "expansion", + markcount: "expansion", + }, + ai: { threaten: 3 }, + group: "xinyingshi_regain", + onremove: function (player, skill) { + var cards = player.getExpansions(skill); + if (cards.length) player.loseToDiscardpile(cards); + delete player.storage.xinyingshi_source; + }, + }, + regain: { + trigger: { player: "die" }, + forced: true, + charlotte: true, + forceDie: true, + filter: function (event, player) { + return player.storage.xinyingshi_source && player.storage.xinyingshi_source.isIn() && player.getExpansions("xinyingshi_cards").length > 0; + }, + content: function () { + player.storage.xinyingshi_source.gain(player.getExpansions("xinyingshi_cards"), player, "give", "bySelf"); + }, + }, }, }, - gongao: { + xinfu_guolun: { audio: 2, - trigger: { global: "dieAfter" }, - forced: true, + enable: "phaseUse", + usable: 1, + filter: function (event, player) { + return player.countCards("h") > 0; + }, + filterTarget: function (card, player, target) { + return target != player && target.countCards("h") > 0; + }, content: function () { - player.gainMaxHp(); - player.recover(); + "step 0"; + player.choosePlayerCard(target, true, "h"); + "step 1"; + event.cardt = result.cards[0]; + target.showCards(event.cardt); + player.chooseCard("he").set("ai", function (card) { + var event = _status.event.getParent(), + player = event.player; + var numt = get.number(event.cardt); + var att = get.attitude(player, target); + var value = get.value(event.cardt); + var num = get.number(card); + if (num < numt || att > 2) return value + 6 - get.value(card); + else if (num == numt) return value - get.value(card); + return -1; + }); + "step 2"; + if (!result.bool) event.finish(); + else { + player.showCards(result.cards); + event.cardp = result.cards[0]; + } + "step 3"; + player.swapHandcards(target, [event.cardp], [event.cardt]); + "step 4"; + var nump = get.number(event.cardp, player); + var numt = get.number(event.cardt, target); + if (nump < numt) { + player.draw(); + } else if (nump > numt) { + target.draw(); + } }, ai: { threaten: 1.5, + order: 8, + result: { + player: function (player, target) { + if (get.attitude(player, target) > 0) return 1.5; + return 0.5; + }, + }, }, }, - juyi: { - skillAnimation: true, - animationColor: "thunder", - audio: 1, - derivation: ["benghuai", "weizhong"], - trigger: { player: "phaseZhunbeiBegin" }, - filter: function (event, player) { - return player.maxHp > game.countPlayer() && !player.storage.juyi; + xinfu_zhanji: { + audio: 2, + trigger: { + player: "gainAfter", }, forced: true, - unique: true, - juexingji: true, - content: function () { - player.awakenSkill("juyi"); - player.draw(player.maxHp); - player.addSkills(["benghuai", "weizhong"]); + filter: function (event, player) { + if (!player.isPhaseUsing()) return false; + return event.getParent().name == "draw" && event.getParent(2).name != "xinfu_zhanji"; }, - }, - benghuai_zhugedan: { audio: 1 }, - weizhong: { - audio: 1, - trigger: { player: ["gainMaxHpEnd", "loseMaxHpEnd"] }, - forced: true, content: function () { - player.draw(player.isMinHandcard() ? 2 : 1); + player.draw("nodelay"); }, }, - kuangfu: { - trigger: { source: "damageSource" }, + xinfu_songsang: { + limited: true, + skillAnimation: true, + animationColor: "wood", audio: 2, - filter: function (event) { - if (event._notrigger.includes(event.player)) return false; - return event.card && event.card.name == "sha" && event.player.countCards("e"); - }, + derivation: "xinfu_zhanji", + trigger: { global: "dieAfter" }, logTarget: "player", - preHidden: true, - check: function (event, player) { - return get.attitude(player, event.player) <= 0; - }, - content: function () { - "step 0"; - var neg = get.attitude(player, trigger.player) <= 0; - player - .choosePlayerCard("e", trigger.player) - .set("ai", function (button) { - if (_status.event.neg) { - return get.buttonValue(button); - } - return 0; - }) - .set("neg", neg); - "step 1"; - if (result.bool) { - event.card = result.links[0]; - if (player.canEquip(event.card)) { - player.chooseBool("是否将" + get.translation(event.card) + "置入自己的装备区?").ai = function () { - return true; - }; - } else event._result = { bool: false }; - } else event.finish(); - "step 2"; - if (result.bool) { - trigger.player.$give(event.card, player, false); - player.equip(event.card); - } else trigger.player.discard(event.card); + async content(e, t, player) { + player.awakenSkill("xinfu_songsang"); + if (player.isDamaged()) { + player.recover(); + } else player.gainMaxHp(); + player.addSkills("xinfu_zhanji"); }, }, - xinfu_lingren: { + xinfu_jixu: { audio: 2, - trigger: { - player: "useCardToPlayered", - }, + enable: "phaseUse", + usable: 1, filter: function (event, player) { - if (event.getParent().triggeredTargets3.length > 1) return false; - if (!["basic", "trick"].includes(get.type(event.card))) return false; - if (get.tag(event.card, "damage")) return true; - return false; + return player.countCards("h") > 0; }, - usable: 1, - direct: true, - derivation: ["lingren_jianxiong", "lingren_xingshang"], + filterTarget: function (card, player, target) { + if (player == target) return false; + if (ui.selected.targets.length) { + return target.hp == ui.selected.targets[0].hp; + } + return true; + }, + selectTarget: [1, Infinity], + multitarget: true, + multiline: true, content: function () { "step 0"; - player - .chooseTarget(get.prompt("xinfu_lingren"), "选择一名目标角色并猜测其手牌构成", function (card, player, target) { - return _status.event.targets.includes(target); - }) - .set("ai", function (target) { - return 2 - get.attitude(_status.event.player, target); - }) - .set("targets", trigger.targets); + targets.sort(lib.sort.seat); "step 1"; - if (result.bool) { - player.logSkill("xinfu_lingren", result.targets); - var target = result.targets[0]; - event.target = target; - event.choice = { - basic: false, - trick: false, - equip: false, - }; - player.chooseButton(["凌人:猜测其有哪些类别的手牌", [["basic", "trick", "equip"], "vcard"]], [0, 3], true).set("ai", function (button) { - switch (button.link[2]) { - case "basic": - var rand = 0.95; - if (!target.countCards("h", { type: ["basic"] })) rand = 0.05; - if (!target.countCards("h")) rand = 0; - return Math.random() < rand ? true : false; - case "trick": - var rand = 0.9; - if (!target.countCards("h", { type: ["trick", "delay"] })) rand = 0.1; - if (!target.countCards("h")) rand = 0; - return Math.random() < rand ? true : false; - case "equip": - var rand = 0.75; - if (!target.countCards("h", { type: ["equip"] })) rand = 0.25; - if (!target.countCards("h")) rand = 0; - return Math.random() < rand ? true : false; - } - }); - } else { - player.storage.counttrigger.xinfu_lingren--; - event.finish(); - } + if (!event.num) event.num = 0; + if (!event.caicuolist) event.caicuolist = []; + targets[event.num].chooseBool("是否押杀?").ai = function (event, player) { + var evt = _status.event.getParent(); + if (get.attitude(targets[event.num], evt.player) > 0) return evt.player.countCards("h", "sha") ? false : true; + return Math.random() < 0.5; + }; "step 2"; if (result.bool) { - var choices = result.links.map(i => i[2]); - if (!event.isMine() && !event.isOnline()) game.delayx(); - var list = []; - event.num = 0; - ["basic", "trick", "equip"].forEach(type => { - if (choices.includes(type) == target.hasCard({ type: type }, "h")) event.num++; - }); + targets[event.num].chat("有杀"); + game.log(targets[event.num], "认为", player, "#g有杀"); + if (!player.countCards("h", "sha")) event.caicuolist.add(targets[event.num]); + } else { + targets[event.num].chat("没杀"); + game.log(targets[event.num], "认为", player, "#y没有杀"); + if (player.countCards("h", "sha")) event.caicuolist.add(targets[event.num]); } + event.num++; + game.delay(); + if (event.num < targets.length) event.goto(1); "step 3"; - player.popup("猜对" + get.cnNumber(event.num) + "项"); - game.log(player, "猜对了" + get.cnNumber(event.num) + "项"); - if (event.num > 0) { - target.addTempSkill("lingren_adddamage"); - target.storage.lingren = { - card: trigger.card, - //player:event.targett, - }; + player.popup(player.countCards("h", "sha") ? "有杀" : "没杀"); + game.log(player, player.countCards("h", "sha") ? "有杀" : "没杀"); + if (event.caicuolist.length == 0) { + var evt = _status.event.getParent("phaseUse"); + if (evt && evt.name == "phaseUse") { + evt.skipped = true; + event.finish(); + } + } else { + player.draw(event.caicuolist.length); + if (player.countCards("h", "sha")) { + player.addTempSkill("jixu_sha"); + player.storage.jixu_sha = event.caicuolist; + event.finish(); + } else event.num = 0; } - if (event.num > 1) player.draw(2); - if (event.num > 2) { - player.addTempSkills(["lingren_jianxiong", "lingren_xingshang"], { - player: "phaseBegin", - }); + "step 4"; + if (event.num < event.caicuolist.length) { + var target = event.caicuolist[event.num]; + player.discardPlayerCard(true, "he", target); + event.num++; + event.redo(); } }, ai: { - threaten: 2.4, + order: function () { + return get.order({ name: "sha" }) + 0.1; + }, + result: { + target: function (player, target) { + var raweffect = function (player, target) { + if (player.countCards("h", "sha")) { + return get.effect(target, { name: "sha" }, player, target); + } else { + var att = get.attitude(player, target); + var nh = target.countCards("h"); + if (att > 0) { + if (target.getEquip("baiyin") && target.isDamaged() && get.recoverEffect(target, player, player) > 0) { + if (target.hp == 1 && !target.hujia) return 1.6; + if (target.hp == 2) return 0.01; + return 0; + } + } + var es = target.getCards("e"); + var noe = es.length == 0 || target.hasSkillTag("noe"); + var noe2 = es.length == 1 && es[0].name == "baiyin" && target.isDamaged(); + var noh = nh == 0 || target.hasSkillTag("noh"); + if (noh && (noe || noe2)) return 0; + if (att <= 0 && !target.countCards("he")) return 1.5; + return -1.5; + } + }; + var num = game.countPlayer(function (current) { + return current != player && current.hp == target.hp && raweffect(player, current) * get.attitude(player, current) > 0; + }); + return raweffect(player, target) * Math.max(0, num - 1); + }, + }, + expose: 0.4, }, }, - lingren_adddamage: { - onremove: function (player) { - delete player.storage.lingren; - }, + jixu_sha: { + audio: "xinfu_jixu", trigger: { - player: "damageBegin3", + player: "useCard", + }, + onremove: function (player) { + delete player.storage.jixu_sha; }, filter: function (event, player) { - var info = player.storage.lingren; - return event.card && event.card == info.card; + if (event.card.name == "sha") { + return game.hasPlayer(function (current) { + return current != player && player.storage.jixu_sha.includes(current) && !event.targets.includes(current); + }); + } + return false; }, + forced: true, silent: true, popup: false, - forced: true, - charlotte: true, content: function () { - trigger.num++; + player.logSkill("xinfu_jixu"); + for (var i = 0; i < player.storage.jixu_sha.length; i++) { + if (!trigger.targets.includes(player.storage.jixu_sha[i]) && player.canUse("sha", player.storage.jixu_sha[i], false)) { + player.line(player.storage.jixu_sha[i], trigger.card.nature); + trigger.targets.push(player.storage.jixu_sha[i]); + } + } }, }, - lingren_jianxiong: { - audio: 1, + xinfu_sanwen: { + audio: 2, + usable: 1, trigger: { - player: "damageEnd", + player: "gainAfter", + global: "loseAsyncAfter", + }, + filter: function (event, player) { + var cards = event.getg(player); + if (!cards || !cards.length) return false; + var namelist = []; + var namedlist = []; + for (var i = 0; i < cards.length; i++) { + namelist.add(get.name(cards[i])); + } + var hs = player.getCards("h"); + for (var j = 0; j < hs.length; j++) { + if (namelist.includes(get.name(hs[j])) && !cards.includes(hs[j])) return true; + } + return false; }, content: function () { "step 0"; - if (get.itemtype(trigger.cards) == "cards" && get.position(trigger.cards[0], true) == "o") { - player.gain(trigger.cards, "gain2"); + var namelist = []; + var namedlist = []; + var nameddlist = []; + var namedddlist = []; + var cards = trigger.getg(player); + for (var i = 0; i < cards.length; i++) { + namelist.add(get.name(cards[i])); } - player.draw("nodelay"); - }, - ai: { - maixie: true, - maixie_hp: true, - effect: { - target: function (card, player, target) { - if (player.hasSkillTag("jueqing", false, target)) return [1, -1]; - if (get.tag(card, "damage") && player != target) return [1, 0.6]; - }, - }, + var hs = player.getCards("h"); + for (var j = 0; j < hs.length; j++) { + if (namelist.includes(get.name(hs[j])) && !cards.includes(hs[j])) { + namedlist.push(hs[j]); + namedddlist.add(get.name(hs[j])); + } + } + for (var k = 0; k < cards.length; k++) { + if (namedddlist.includes(get.name(cards[k]))) nameddlist.push(cards[k]); + } + var showlist = namedlist.concat(nameddlist); + player.showCards(showlist); + player.discard(nameddlist); + player.draw(2 * nameddlist.length); }, }, - lingren_xingshang: { - audio: 1, - inherit: "rexingshang", + xinfu_qiai: { + skillAnimation: true, + animationColor: "gray", + trigger: { player: "dying" }, + limited: true, + audio: 2, + content: function () { + "step 0"; + player.awakenSkill("xinfu_qiai"); + event.targets = game + .filterPlayer(function (current) { + return current != player; + }) + .sortBySeat(); + if (!event.targets.length) event.finish(); + "step 1"; + event.current = event.targets.shift(); + if (!event.current.countCards("he")) event.goto(3); + else + event.current.chooseCard("交给" + get.translation(player) + "一张牌", "he", true).set("ai", function (card) { + var evt = _status.event.getParent(); + if (get.attitude(_status.event.player, evt.player) > 2) { + if (card.name == "jiu") return 120; + if (card.name == "tao") return 110; + } + return 100 - get.value(card); + }); + "step 2"; + if (result.bool && result.cards && result.cards.length) { + event.current.give(result.cards, player); + } + "step 3"; + if (event.targets.length > 0) event.goto(1); + }, }, - xinfu_fujian: { + xinfu_denglou: { audio: 2, trigger: { player: "phaseJieshuBegin", }, + limited: true, filter: function (event, player) { - return !game.hasPlayer(function (current) { - return current.countCards("h") == 0; - }); + return player.countCards("h") == 0; }, - forced: true, + skillAnimation: true, + animationColor: "gray", content: function () { - event.num = 0; - var list = game.filterPlayer(function (target) { - if (target.isMinHandcard()) event.num = target.countCards("h"); - return player != target; - }); - if (event.num < 1) { - event.finish(); + "step 0"; + player.awakenSkill("xinfu_denglou"); + event.cards = get.cards(4); + event.gains = []; + event.discards = []; + var content = ["牌堆顶的四张牌", event.cards]; + game.log(player, "观看了", "#y牌堆顶的四张牌"); + player.chooseControl("ok").set("dialog", content); + "step 1"; + if (get.type(event.cards[0]) != "basic") { + event.gains.push(event.cards[0]); + event.cards.remove(event.cards[0]); } else { - var target = list.randomGet(); - var cards = target.getCards("h").randomGets(event.num); - player.line(target); - var content = [get.translation(target) + "的部分手牌", cards]; - game.log(player, "观看了", target, "的部分手牌"); - player.chooseControl("ok").set("dialog", content); + var bool = game.hasPlayer(function (current) { + return player.canUse(event.cards[0], current); + }); + if (bool) { + player.chooseUseTarget(event.cards[0], true, false); + } else event.discards.push(event.cards[0]); + event.cards.remove(event.cards[0]); + } + "step 2"; + if (event.cards.length) event.goto(1); + else { + if (event.gains.length) player.gain(event.gains, "gain2"); + if (event.discards.length) { + player.$throw(event.discards); + game.cardsDiscard(event.discards); + } } }, }, - fujian: { - audio: "xinfu_fujian", - trigger: { player: ["phaseZhunbeiBegin", "phaseJieshuBegin"] }, - filter(event, player) { - return game.hasPlayer(target => target != player && target.countCards("h") && !target.isMaxHandcard()); - }, - forced: true, - async content(event, trigger, player) { - const target = game - .filterPlayer(target => { - return target != player && target.countCards("h") && !target.isMaxHandcard(); - }) - .randomGet(); - player.line(target); - game.log(player, "观看了", target, "的手牌"); - player.viewHandcards(target); - }, - }, - xinfu_xionghuo: { - audio: 2, - enable: "phaseUse", - filter: function (event, player) { - return player.countMark("xinfu_xionghuo") > 0; - }, - filterTarget: function (card, player, target) { - return player != target && !target.hasMark("xinfu_xionghuo"); - }, - content: function () { - player.removeMark("xinfu_xionghuo", 1); - target.addMark("xinfu_xionghuo", 1); - }, - ai: { - order: 11, - result: { - target: function (player, target) { - if ( - (player.countMark("xinfu_xionghuo") >= 2 || - !game.hasPlayer(function (current) { - return current != player && get.attitude(player, current) < 0 && current.hasMark("xinfu_xionghuo"); - })) && - player.countCards("h", function (card) { - return ( - get.tag(card, "damage") && - player.canUse(card, target, null, true) && - player.getUseValue(card) > 0 && - get.effect_use(target, card, player) > 0 && - target.hasSkillTag("filterDamage", null, { - player: player, - card: card, - }) - ); - }) - ) - return 3 / Math.max(1, target.hp); - if ( - (!player.hasUnknown() && - game.countPlayer(function (current) { - return get.attitude(player, current) < 0; - }) <= 1) || - player.countMark("xinfu_xionghuo") >= 2 - ) { - return -1; - } - return 0; - }, - }, - effect: { - player: function (card, player, target) { - if ( - player != target && - get.tag(card, "damage") && - target && - target.hasMark("xinfu_xionghuo") && - !target.hasSkillTag("filterDamage", null, { - player: player, - card: card, - }) - ) - return [1, 0, 1, -2]; - }, - }, - threaten: 1.6, - }, - marktext: "戾", - intro: { - name: "暴戾", - content: "mark", - }, - group: ["xinfu_xionghuo_init", "xinfu_xionghuo_damage", "xinfu_xionghuo_effect"], - subSkill: { - init: { - audio: "xinfu_xionghuo", - trigger: { - global: "phaseBefore", - player: "enterGame", - }, - filter: function (event, player) { - if (player.countMark("xinfu_xionghuo") >= 3) return false; - return event.name != "phase" || game.phaseNumber == 0; - }, - forced: true, - locked: false, - content: function () { - player.addMark("xinfu_xionghuo", 3 - player.countMark("xinfu_xionghuo")); - }, - }, - damage: { - audio: "xinfu_xionghuo", - trigger: { source: "damageBegin1" }, - filter: function (event, player) { - return event.player.countMark("xinfu_xionghuo") > 0 && event.player != player; - }, - forced: true, - locked: false, - logTarget: "player", - content: function () { - trigger.num++; - }, - }, - effect: { - audio: "xinfu_xionghuo", - trigger: { global: "phaseUseBegin" }, - filter: function (event, player) { - return event.player.countMark("xinfu_xionghuo") > 0 && event.player != player; - }, - line: false, - forced: true, - locked: false, - logTarget: "player", - content: function () { - "step 0"; - trigger.player.removeMark("xinfu_xionghuo", trigger.player.countMark("xinfu_xionghuo")); - "step 1"; - var num = get.rand(0, 2); - switch (num) { - case 0: { - player.line(trigger.player, "fire"); - trigger.player.damage("fire"); - trigger.player.addTempSkill("xinfu_xionghuo_disable"); - trigger.player.markAuto("xinfu_xionghuo_disable", [player]); - break; - } - case 1: { - player.line(trigger.player, "water"); - trigger.player.loseHp(); - trigger.player.addMark("xinfu_xionghuo_low", 1, false); - trigger.player.addTempSkill("xinfu_xionghuo_low"); - break; - } - case 2: { - player.line(trigger.player, "green"); - /* - var card1=trigger.player.getCards('h').randomGet(); - var card2=trigger.player.getCards('e').randomGet(); - var list=[]; - if(card1) list.push(card1); - if(card2) list.push(card2); - if(list.length) player.gain(list,trigger.player,'giveAuto','bySelf'); - */ - const cards = trigger.player.getGainableCards(player, "he"); - if (cards.length) player.gain(cards.randomGets(2), trigger.player, "giveAuto", "bySelf"); - break; - } - } - "step 2"; - game.delay(); + qinguo_use: { audio: 2 }, + xinfu_qinguo: { + group: "xinfu_qinguo_recover", + audio: "qinguo_use", + subfrequent: ["recover"], + trigger: { + player: "useCardEnd", + }, + filter: function (event, player) { + return get.type(event.card) == "equip"; + }, + direct: true, + content: function () { + player.chooseUseTarget({ name: "sha" }, get.prompt("xinfu_qinguo"), "视为使用一张【杀】", false).logSkill = "xinfu_qinguo"; + }, + subSkill: { + recover: { + audio: "qinguo_use", + trigger: { + player: "loseAfter", + global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], }, - }, - disable: { - mod: { - playerEnabled: function (card, player, target) { - if (card.name == "sha" && player.getStorage("xinfu_xionghuo_disable").includes(target)) return false; - }, + prompt: "是否发动【勤国】回复1点体力?", + filter: function (event, player) { + if (player.isHealthy() || player.countCards("e") != player.hp) return false; + var evt = event.getl(player); + if (event.name == "equip" && event.player == player) return evt.cards.length != (evt.es?.length ?? 0); + return evt && evt.es.length; + }, + frequent: true, + content: function () { + player.recover(); }, - charlotte: true, - onremove: true, - mark: true, - marktext: "禁", - intro: { content: "不能对$使用【杀】" }, }, - low: { - mod: { - maxHandcard: function (player, num) { - return num - player.countMark("xinfu_xionghuo_low"); - }, + }, + ai: { + effect: { + target: function (card, player, target, current) { + if ( + get.type(card) == "equip" && + !get.cardtag(card, "gifts") && + game.hasPlayer(function (current) { + return target.canUse("sha", current); + }) + ) + return [1, 1.5]; }, - charlotte: true, - onremove: true, - mark: true, - marktext: "减", - intro: { content: "手牌上限-#" }, + }, + noe: true, + reverseEquip: true, + skillTagFilter: function (player, tag, arg) { + if (tag == "noe") return player.countCards("e") == player.hp + 1; + return game.hasPlayer(function (current) { + return player.canUse("sha", current); + }); }, }, }, - xinfu_shajue: { + xinfu_jijun: { + ai: { + reverseEquip: true, + effect: { + target_use: function (card, player, target, current) { + if (get.type(card) == "equip" && player == target && player == _status.currentPhase && get.subtype(card) == "equip1") return [1, 3]; + }, + }, + combo: "xinfu_fangtong", + }, audio: 2, - trigger: { global: "dying" }, + trigger: { + player: "useCardToPlayered", + }, + frequent: true, filter: function (event, player) { - if (event.player == player) return false; - const bool1 = !player.hasSkill("xinfu_xionghuo") || player.countMark("xinfu_xionghuo") < 3; - const bool2 = event.player.hp < 0 && get.itemtype(event.parent.cards) == "cards" && event.parent.cards.some(card => get.position(card, true) == "o"); - return bool1 || bool2; + if (player != _status.currentPhase) return false; + if (event.getParent().triggeredTargets3.length > 1) return false; + if (get.type(event.card) == "equip" && get.subtype(event.card) != "equip1") return false; + if (event.targets.includes(player)) return true; + return false; + }, + callback: function () { + player.addToExpansion(card, "gain2").gaintag.add("xinfu_jijun"); }, - forced: true, content: function () { - if (!player.hasSkill("xinfu_xionghuo") || player.countMark("xinfu_xionghuo") < 3) player.addMark("xinfu_xionghuo", 1); - if (trigger.player.hp < 0 && get.itemtype(trigger.parent.cards) == "cards" && trigger.parent.cards.some(card => get.position(card, true) == "o")) { - player.gain( - trigger.parent.cards.filter(card => get.position(card, true) == "o"), - "gain2" - ); - } + player.judge(function (card) { + return 1; + }).callback = lib.skill.xinfu_jijun.callback; + }, + onremove: function (player, skill) { + var cards = player.getExpansions(skill); + if (cards.length) player.loseToDiscardpile(cards); + }, + intro: { + content: "expansion", + markcount: "expansion", + mark: function (dialog, content, player) { + var content = player.getExpansions("xinfu_jijun"); + if (content && content.length) { + dialog.addAuto(content); + if (player == game.me || player.isUnderControl()) { + var list = lib.skill.xinfu_fangtong.getAuto(player); + if (list.length > 0) { + dialog.addText("
  • 推荐方案:" + get.translation(list[0]) + "+ " + get.translation(list.slice(1))); + } + } + } + }, }, + marktext: "方", }, - xinfu_jianjie: { audio: 3 }, - jianjie: { - group: ["jianjie_use", "jianjie_die"], - derivation: ["jianjie_huoji", "jianjie_lianhuan", "jianjie_yeyan"], - audio: "xinfu_jianjie", + xinfu_fangtong: { + getAuto: function (player) { + var hs = player.getCards("he"); + var ss = player.getExpansions("xinfu_jijun"); + var bool = false, + max = Math.pow(2, ss.length), + index, + i; + for (i = 0; i < hs.length; i++) { + for (var j = 1; j < max; j++) { + var num = get.number(hs[i]); + index = j.toString(2); + while (index.length < ss.length) { + index = "0" + index; + } + for (var k = 0; k < ss.length; k++) { + if (index[k] == "1") num += get.number(ss[k]); + } + if (num == 36) { + bool = true; + break; + } + } + if (bool) break; + } + if (!bool) return []; + var list = [hs[i]]; + for (var k = 0; k < ss.length; k++) { + if (index[k] == "1") list.push(ss[k]); + } + return list; + }, + audio: 2, trigger: { - player: "phaseZhunbeiBegin", + player: "phaseJieshuBegin", }, - forced: true, - locked: false, filter: function (event, player) { - return player.phaseNumber <= 1 && game.hasPlayer(current => current != player); + return player.countCards("he") > 0 && player.getExpansions("xinfu_jijun").length > 0; }, + direct: true, + skillAnimation: true, + animationColor: "metal", content: function () { "step 0"; - player.chooseTarget("荐杰:选择一名其他角色获得“龙印”", lib.filter.notMe, true).set("ai", target => { - return get.attitude(get.player(), target); + var info = ["是否发动【方统】?"]; + info.push('
    ' + get.translation(player) + "的“方”
    "); + info.push(player.getExpansions("xinfu_jijun")); + if (player.countCards("h")) { + info.push('
    ' + get.translation(player) + "的手牌区
    "); + info.push(player.getCards("h")); + } + if (player.countCards("e")) { + info.push('
    ' + get.translation(player) + "的装备区
    "); + info.push(player.getCards("e")); + } + var next = player.chooseButton(); + next.set("createDialog", info); + next.set("selectButton", function () { + var num = 0; + for (var i = 0; i < ui.selected.buttons.length; i++) { + num += get.number(ui.selected.buttons[i]); + } + if (num == 36) return ui.selected.buttons.length; + return ui.selected.buttons.length + 2; + }); + next.set("filterButton", function (button) { + var player = _status.event.player, + cards = player.getExpansions("xinfu_jijun"); + if (ui.selected.buttons.length) { + if (!cards.includes(button.link)) return false; + } else if (cards.includes(button.link)) return false; + var num = 0; + for (var i = 0; i < ui.selected.buttons.length; i++) { + num += get.number(ui.selected.buttons[i]); + } + return get.number(button.link) + num <= 36; + }); + next.set("autolist", lib.skill.xinfu_fangtong.getAuto(player)); + next.set("processAI", function () { + if (_status.event.autolist && _status.event.autolist.length > 0) { + return { + bool: true, + links: _status.event.autolist, + }; + } + return { bool: false }; }); + next.set("complexSelect", true); "step 1"; if (result.bool) { - var target = result.targets[0]; - player.line(target, "fire"); - lib.skill.jianjie.addMark("huoji", player, target); - event.target = target; - game.delayx(); - } else event.finish(); - "step 2"; - if ( - game.hasPlayer(current => { - return current != player && current != target; - }) - ) { + player.logSkill("xinfu_fangtong"); + var tothrow = []; + var cards = result.links.slice(0); + for (var i = 0; i < cards.length; i++) { + if (get.position(cards[i]) == "x") { + tothrow.push(cards[i]); + } else { + player.discard(cards[i]).delay = false; + } + } + player.loseToDiscardpile(tothrow); player - .chooseTarget( - "荐杰:选择一名其他角色获得“凤印”", - function (card, player, target) { - return target != player && target != _status.event.getParent().target; - }, - true - ) - .set("ai", target => { - return get.attitude(get.player(), target); + .chooseTarget("选择一个目标并对其造成3点雷电伤害", true, function (card, player, target) { + return target != player; + }) + .set("ai", function (target) { + return get.damageEffect(target, _status.event.player, _status.event.player, "thunder"); }); - } else event.finish(); - "step 3"; - if (result.bool) { - var target = result.targets[0]; - player.line(target, "thunder"); - lib.skill.jianjie.addMark("lianhuan", player, target); - game.delayx(); + } else { + event.finish(); } + "step 2"; + var target = result.targets[0]; + player.line(target, "thunder"); + target.damage(3, "thunder"); }, ai: { - threaten: 3, + combo: "xinfu_jijun", }, - hasMark: (mark, player, target) => { - if (!target) return player.getStorage("jianjie_" + mark).length > 0; - return target.getStorage("jianjie_" + mark).includes(player); + }, + xinfu_weilu: { + audio: 2, + trigger: { + player: "damageEnd", }, - addMark: (mark, player, target) => { - mark = "jianjie_" + mark; - target.addAdditionalSkill(`${mark}_${player.playerid}`, mark); - target.markAuto(mark, [player]); - game.log(player, "令", target, "获得了", `#g“${mark == "jianjie_huoji" ? "龙印" : "凤印"}”`); + filter: function (event, player) { + return event.source && event.source.isIn() && !player.getStorage("xinfu_weilu_effect").includes(event.source); }, - removeMark: (mark, player, target, log) => { - if (lib.skill.jianjie.hasMark(mark, player, target, log)) { - mark = "jianjie_" + mark; - target.removeAdditionalSkill(`${mark}_${player.playerid}`); - target.unmarkAuto(mark, [player]); - if (log) game.log(target, "移去了", player, "给予的", `#g“${mark == "jianjie_huoji" ? "龙印" : "凤印"}”`); - else game.log(player, "移去了", target, "的", `#g“${mark == "jianjie_huoji" ? "龙印" : "凤印"}”`); - } + check: function (event, player) { + return get.effect(event.source, { name: "losehp" }, player, player) >= 0; }, - subSkill: { - use: { - audio: "xinfu_jianjie", - enable: "phaseUse", - usable: 1, - filter: function (event, player) { - if (player.phaseNumber <= 1) return false; - const skill = lib.skill.jianjie; - return game.hasPlayer(function (current) { - return skill.hasMark("huoji", player, current) || skill.hasMark("lianhuan", player, current); - }); - }, - filterTarget: function (card, player, target) { - if (ui.selected.targets.length == 0) { - const skill = lib.skill.jianjie; - return skill.hasMark("huoji", player, target) || skill.hasMark("lianhuan", player, target); - } - return true; - }, - selectTarget: 2, - complexSelect: true, - complexTarget: true, - multitarget: true, - prompt: "移动场上的“龙印”或“凤印”", - targetprompt: ["失去印", "获得印"], - content: function () { - "step 0"; - var skill = lib.skill.jianjie; - var bool1 = skill.hasMark("huoji", player, targets[0]), - bool2 = skill.hasMark("lianhuan", player, targets[0]); - if (bool1 && bool2) { - player.chooseControl("龙印", "凤印").set("prompt", "选择要移动的“印”"); - } else { - event._result = { control: bool1 ? "龙印" : "凤印" }; - } - "step 1"; - var skill = lib.skill.jianjie, - mark = result.control == "龙印" ? "huoji" : "lianhuan"; - skill.removeMark(mark, player, targets[0]); - skill.addMark(mark, player, targets[1]); - game.delayx(); - }, - ai: { - order: 8, - result: { - target: function (player, target) { - if (ui.selected.targets.length == 0) { - return get.attitude(player, target) < 0 ? -999 : -3; - } else { - return target.countCards("h") + 1; - } - }, - }, - expose: 0.4, + forced: true, + logTarget: "source", + content: function () { + player.addTempSkill("xinfu_weilu_effect", { player: "die" }); + player.markAuto("xinfu_weilu_effect", [trigger.source]); + game.delayx(); + }, + ai: { + maixie_defend: true, + threaten: 0.85, + effect: { + target: function (card, player, target) { + if (player.hasSkillTag("jueqing", false, target)) return; + return 0.9; }, }, - die: { - audio: "xinfu_jianjie", - trigger: { global: "die" }, - filter: function (event, player) { - const skill = lib.skill.jianjie; - return skill.hasMark("huoji", player, event.player) || skill.hasMark("lianhuan", player, event.player); - }, + }, + subSkill: { + effect: { + audio: "xinfu_weilu", + trigger: { player: "phaseUseBegin" }, + charlotte: true, forced: true, - logTarget: "player", + logTarget: function (event, player) { + return player.getStorage("xinfu_weilu_effect").filter(function (current) { + return current.isIn() && current.hp > 1; + }); + }, content: function () { "step 0"; - if (lib.skill.jianjie.hasMark("huoji", player, trigger.player)) { - player.chooseTarget("荐杰:选择一名角色获得“龙印”", true).set("ai", target => { - return get.attitude(get.player(), target); - }); - } else event.goto(2); + var targets = player.getStorage("xinfu_weilu_effect"); + player.removeSkill("xinfu_weilu_effect"); + event.targets = targets.sortBySeat(); "step 1"; - if (result.bool) { - var target = result.targets[0]; - player.line(target, "fire"); - lib.skill.jianjie.addMark("huoji", player, target); - event.target = target; - game.delayx(); - } else event.finish(); + var target = targets.shift(); + if (target.isIn() && target.hp > 1) { + event._delay = true; + var num = target.hp - 1; + player.markAuto("xinfu_weilu_recover", [[target, num]]); + target.loseHp(num); + } + if (targets.length > 0) event.redo(); + else if (!event._delay) event.finish(); "step 2"; - if (lib.skill.jianjie.hasMark("lianhuan", player, trigger.player)) { - player.chooseTarget("荐杰:选择一名角色获得“凤印”", true).set("ai", target => { - return get.attitude(get.player(), target); - }); - } else event.finish(); - "step 3"; - if (result.bool) { - var target = result.targets[0]; - player.line(target, "thunder"); - lib.skill.jianjie.addMark("lianhuan", player, target); - game.delayx(); - } + player.addTempSkill("xinfu_weilu_recover", { + player: ["phaseUseAfter", "phaseAfter"], + }); + game.delayx(); }, + onremove: true, + intro: { content: "已将$列入“威虏”战略打击目标" }, }, - huoji: { - marktext: "龙", - intro: { - name: "龙印", - content: "
  • 出牌阶段限三次。你可以将一张红色牌当作【火攻】使用,且你以此法使用【火攻】的作用效果改为“目标角色随机展示一张手牌A,然后你可以弃置一张与A颜色相同的牌,对目标造成1点火属性伤害”。
  • 若你同时拥有“凤印”,则你视为拥有技能〖业炎〗。(发动〖业炎〗时,弃置所有“龙印”和“凤印”)", - }, - inherit: "rehuoji", - usable: 3, + recover: { + audio: "xinfu_weilu", charlotte: true, - viewAsFilter: function (player) { - const storage = player.getStorage("jianjie_huoji"); - if ( - !storage.some(source => { - return source.isIn() && source.hasSkill("jianjie"); - }) - ) - return false; - return player.hasCard(card => get.color(card) == "red", "she"); - }, - group: ["jianjie_yeyan", "jianjie_huoji_effect"], - }, - huoji_effect: { - trigger: { player: "huogongBegin" }, + trigger: { player: "phaseUseEnd" }, forced: true, - popup: false, - charlotte: true, - filter: function (event, player) { - return event.skill == "jianjie_huoji"; - }, - content: function () { - trigger.setContent(lib.skill.olhuoji.huogongContent); - }, - }, - lianhuan: { - marktext: "凤", - intro: { - name: "凤印", - content: "
  • 出牌阶段限三次。你可以将一张♣牌当作【铁索连环】使用或重铸,且你以此法使用【铁索连环】的目标数上限+1。
  • 若你同时拥有“龙印”,则你视为拥有技能〖业炎〗。(发动〖业炎〗时,弃置所有“龙印”和“凤印”)", - }, - charlotte: true, - usable: 3, - filter: function (event, player) { - const storage = player.getStorage("jianjie_lianhuan"); - if ( - !storage.some(source => { - return source.isIn() && source.hasSkill("jianjie"); - }) - ) - return false; - if (!player.hasCard(card => get.suit(card) == "club", "she")) return false; - return event.type == "phase" || event.filterCard({ name: "tiesuo" }, player, event); - }, - inherit: "ollianhuan", - group: ["jianjie_yeyan", "jianjie_lianhuan_effect"], - }, - lianhuan_effect: { - trigger: { player: "useCard2" }, filter: function (event, player) { - if (event.skill != "jianjie_lianhuan") return false; - var info = get.info(event.card); - if (info.allowMultiple == false) return false; - if (event.targets && !info.multitarget) { - if ( - game.hasPlayer(current => { - return !event.targets.includes(current) && lib.filter.targetEnabled2(event.card, player, current); - }) - ) - return true; + var targets = player.getStorage("xinfu_weilu_recover"); + for (var i of targets) { + if (i[0].isIn() && i[0].isDamaged()) return true; } return false; }, - charlotte: true, - forced: true, - popup: false, + onremove: true, + logTarget: function (event, player) { + var logs = [], + targets = player.getStorage("xinfu_weilu_recover"); + for (var i of targets) { + if (i[0].isIn() && i[0].isDamaged()) logs.add(i[0]); + } + return logs; + }, content: function () { "step 0"; - player - .chooseTarget("是否为" + get.translation(trigger.card) + "额外指定一个目标?", (card, player, target) => { - return !_status.event.sourcex.includes(target) && lib.filter.targetEnabled2(_status.event.card, player, target); - }) - .set("sourcex", trigger.targets) - .set("ai", function (target) { - var player = _status.event.player; - return get.effect(target, _status.event.card, player, player); - }) - .set("card", trigger.card); + event.list = player.getStorage("xinfu_weilu_recover").slice(0); + event.list.sort(function (a, b) { + return lib.sort.seat(a[0], b[0]); + }); "step 1"; - if (result.bool) { - if (!event.isMine() && !event.isOnline()) game.delayex(); - } else event.finish(); - "step 2"; - if (result.bool) { - var targets = result.targets; - player.line(targets, "thunder"); - trigger.targets.addArray(targets); - game.log(targets, "也成为了", trigger.card, "的目标"); + var group = event.list.shift(); + if (group[0].isIn() && group[0].isDamaged()) { + group[0].recover(group[1]); + event._delay = true; } + if (event.list.length > 0) event.redo(); + else if (!event._delay) event.finish(); + "step 2"; + game.delayx(); }, }, - yeyan: { - inherit: "yeyan", - filter: function (event, player) { - const huoji = player.getStorage("jianjie_huoji"), - lianhuan = player.getStorage("jianjie_lianhuan"); - return ( - huoji.length > 0 && - lianhuan.some(source => { - return huoji.includes(source) && source.isIn() && source.hasSkill("jianjie"); - }) - ); + }, + }, + xinfu_zengdao: { + audio: 2, + limited: true, + enable: "phaseUse", + filter: function (event, player) { + return player.countCards("e") > 0; + }, + filterTarget: lib.filter.notMe, + skillAnimation: true, + animationColor: "thunder", + position: "e", + filterCard: true, + selectCard: [1, Infinity], + discard: false, + lose: false, + content: function () { + player.awakenSkill("xinfu_zengdao"); + target.addToExpansion(cards, player, "give").gaintag.add("xinfu_zengdao2"); + target.addSkill("xinfu_zengdao2"); + }, + ai: { + order: function () { + var player = _status.event.player, + num = 0; + if (player.hasCard(card => get.value(card, player) < 0, "e")) return 9; + for (var i = 1; i < 6; i++) { + num += player.countEquipableSlot(i); + } + if (num <= 2) return 9; + var targets = player.getStorage("xinfu_weilu_recover"), + num = 0; + if ( + player.hp <= 2 || + !game.hasPlayer(current => { + if (player == current || get.attitude(player, current) < 0 || current.hp <= 1) return false; + for (var arr of targets) { + if (current == arr[0]) break; + } + return current.hp > 2 || current.countCards("hs") > 2; + }) + ) + return 1; + return 0; + }, + result: { + target: function (player, target) { + if (target.hasValueTarget({ name: "sha", isCard: true })) return ui.selected.cards.length; + return 0; }, - contentBefore: function () { - player.awakenSkill("jianjie_yeyan"); - var skill = lib.skill.jianjie; - var huoji = player.getStorage("jianjie_huoji").slice(0), - lianhuan = player.getStorage("jianjie_lianhuan").slice(0); - huoji.forEach(source => { - skill.removeMark("huoji", source, player, true); - }); - lianhuan.forEach(source => { - skill.removeMark("lianhuan", source, player, true); - }); + }, + }, + }, + xinfu_zengdao2: { + trigger: { source: "damageBegin1" }, + forced: true, + charlotte: true, + filter: function (event, player) { + return player.getExpansions("xinfu_zengdao2").length > 0; + }, + content: function () { + "step 0"; + player.chooseCardButton("将一张“刀”置入弃牌堆", player.getExpansions("xinfu_zengdao2"), true); + "step 1"; + if (result.bool) { + trigger.num++; + player.loseToDiscardpile(result.links); + } + }, + marktext: "刀", + intro: { + content: "expansion", + markcount: "expansion", + onunmark: function (storage, player) { + player.removeSkill("xinfu_zengdao2"); + }, + }, + }, + xinfu_guanwei: { + audio: 2, + usable: 1, + init: () => { + game.addGlobalSkill("xinfu_guanwei_ai"); + }, + onremove: () => { + if (!game.hasPlayer(i => i.hasSkill("xinfu_guanwei", null, null, false), true)) game.removeGlobalSkill("xinfu_guanwei_ai"); + }, + trigger: { + global: "phaseUseEnd", + }, + filter: function (event, player) { + var history = event.player.getHistory("useCard"); + var num = 0; + var suit = false; + for (var i = 0; i < history.length; i++) { + var suit2 = get.suit(history[i].card); + if (!lib.suit.includes(suit2)) return false; + if (suit && suit != suit2) return false; + suit = suit2; + num++; + } + return num > 1; + }, + direct: true, + content: function () { + "step 0"; + var target = trigger.player; + player + .chooseToDiscard("he", get.prompt("xinfu_guanwei", trigger.player), "弃置一张牌,令其摸两张牌并进行一个额外的出牌阶段。") + .set("ai", function (card) { + if (get.attitude(_status.event.player, _status.event.targetx) < 1) return 0; + return 9 - get.value(card); + }) + .set("logSkill", ["xinfu_guanwei", target]) + .set("targetx", target); + "step 1"; + if (result.bool) { + player.line(trigger.player, "green"); + trigger.player.draw(2); + } else { + player.storage.counttrigger.xinfu_guanwei--; + event.finish(); + } + "step 2"; + var evt = trigger.getParent("phase", true); + if (evt) evt.phaseList.splice(evt.num, 0, "phaseUse|xinfu_guanwei"); + }, + ai: { + expose: 0.5, + }, + subSkill: { + ai: { + trigger: { player: "dieAfter" }, + filter: () => { + return !game.hasPlayer(i => i.hasSkill("xinfu_guanwei", null, null, false), true); + }, + silent: true, + forceDie: true, + content: () => { + game.removeGlobalSkill("xinfu_guanwei_ai"); + }, + ai: { + effect: { + player_use(card, player, target) { + if (typeof card != "object" || !player.isPhaseUsing()) return; + var hasPanjun = game.hasPlayer(function (current) { + return ( + current.hasSkill("xinfu_guanwei") && + (!current.storage.counttrigger || !current.storage.counttrigger.xinfu_guanwei) && + get.attitude(current, player) >= 1 && + current.hasCard(function (card) { + return get.value(card) < 7 || (current != game.me && !current.isUnderControl() && !current.isOnline() && get.value(card) < 9); + }, "he") + ); + }); + if (!hasPanjun) return; + var suitx = get.suit(card); + var history = player.getHistory("useCard"); + if (!history.length) { + var val = 0; + if ( + player.hasCard(function (cardx) { + return get.suit(cardx) == suitx && card != cardx && (!card.cards || !card.cards.includes(cardx)) && player.hasValueTarget(cardx); + }, "hs") + ) + val = [2, 0.1]; + if (val) return val; + return; + } + var num = 0; + var suit = false; + for (var i = 0; i < history.length; i++) { + var suit2 = get.suit(history[i].card); + if (!lib.suit.includes(suit2)) return; + if (suit && suit != suit2) return; + suit = suit2; + num++; + } + if (suitx == suit && num == 1) return [1, 0.1]; + if ( + suitx != suit && + (num > 1 || + (num <= 1 && + player.hasCard(function (cardx) { + return get.suit(cardx) == suit && player.hasValueTarget(cardx); + }, "hs"))) + ) + return "zeroplayertarget"; + }, + }, }, }, }, }, - xinfu_yinshi: { + xinfu_gongqing_gz_panjun: { audio: 2 }, + xinfu_gongqing: { audio: 2, - trigger: { player: "damageBegin4" }, + audioname2: { gz_panjun: "xinfu_gongqing_gz_panjun" }, + trigger: { + player: ["damageBegin3", "damageBegin4"], + }, forced: true, - filter: function (event, player) { - const skill = lib.skill.jianjie; - if (skill.hasMark("huoji", player) || skill.hasMark("lianhuan", player)) return false; - if (!player.hasEmptySlot(2)) return false; - if (event.hasNature()) return true; - return get.type(event.card, "trick") == "trick"; + filter: function (event, player, name) { + if (!event.source) return false; + var range = event.source.getAttackRange(); + if (name == "damageBegin3") return range > 3; + return event.num > 1 && range < 3; }, + preHidden: true, content: function () { - trigger.cancel(); + trigger.num = event.triggername == "damageBegin4" ? 1 : trigger.num + 1; }, ai: { - notrick: true, - nofire: true, - nothunder: true, - effect: { - target: function (card, player, target, current) { - const skill = lib.skill.jianjie; - if (skill.hasMark("huoji", target) || skill.hasMark("lianhuan", target)) return false; - if (player == target && get.subtype(card) == "equip2") { - if (get.equipValue(card) <= 8) return 0; - } - if (!target.hasEmptySlot(2)) return; - if (get.tag(card, "natureDamage")) return "zerotarget"; - if (get.type(card) == "trick" && get.tag(card, "damage")) { - return "zeroplayertarget"; - } - }, + filterDamage: true, + skillTagFilter: function (player, tag, arg) { + if (arg && arg.player) { + if (arg.player.hasSkillTag("jueqing", false, player)) return false; + if (arg.player.getAttackRange() < 3) return true; + } + return false; }, }, }, - xinfu_chenghao: { + xinfu_andong: { + subSkill: { + add: { + sub: true, + mod: { + ignoredHandcard: function (card, player) { + if (get.suit(card) == "heart") { + return true; + } + }, + cardDiscardable: function (card, player, name) { + if (name == "phaseDiscard" && get.suit(card) == "heart") return false; + }, + }, + }, + }, audio: 2, trigger: { - global: "damageEnd", + player: "damageBegin4", }, filter: function (event, player) { - return event.lianhuanable == true && event.player.isIn(); + return get.itemtype(event.source) == "player"; }, - frequent: true, + logTarget: "source", content: function () { "step 0"; - event.cards = game.cardsGotoOrdering( - get.cards( - game.countPlayer(function (current) { - return current.isLinked(); - }) + 1 - ) - ).cards; - if (_status.connectMode) - game.broadcastAll(function () { - _status.noclearcountdown = true; - }); - event.given_map = {}; - "step 1"; - if (event.cards.length > 1) { - player.chooseCardButton("称好:请选择要分配的牌", true, event.cards, [1, event.cards.length]).set("ai", function (button) { - if (ui.selected.buttons.length == 0) return 1; + if (!trigger.source.countCards("h")) event._result = { index: 1 }; + else + trigger.source.chooseControlList(["令" + get.translation(player) + "观看你的手牌,并获得其中所有的红桃牌。", "防止即将对" + get.translation(player) + "造成的伤害,并使自己本回合内的红桃手牌不计入手牌上限。"], true).set("ai", function (event, player) { + var target = _status.event.getParent().player; + var player = _status.event.player; + if (get.attitude(player, target) > 0) return 1; return 0; }); - } else if (event.cards.length == 1) { - event._result = { links: event.cards.slice(0), bool: true }; - } else { + "step 1"; + if (result.index == 1) { + trigger.cancel(); + trigger.source.addTempSkill("xinfu_andong_add"); event.finish(); + } else { + player.viewHandcards(trigger.source); } "step 2"; - if (result.bool) { - event.cards.removeArray(result.links); - event.togive = result.links.slice(0); - player - .chooseTarget("选择一名角色获得" + get.translation(result.links), true) - .set("ai", function (target) { - var att = get.attitude(_status.event.player, target); - if (_status.event.enemy) { - return -att; - } else if (att > 0) { - return att / (1 + target.countCards("h")); - } else { - return att / 100; - } - }) - .set("enemy", get.value(event.togive[0], player, "raw") < 0); - } - "step 3"; - if (result.targets.length) { - var id = result.targets[0].playerid, - map = event.given_map; - if (!map[id]) map[id] = []; - map[id].addArray(event.togive); - } - if (cards.length > 0) event.goto(1); - "step 4"; - if (_status.connectMode) { - game.broadcastAll(function () { - delete _status.noclearcountdown; - game.stopCountChoose(); - }); - } - var list = []; - for (var i in event.given_map) { - var source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; - player.line(source, "green"); - list.push([source, event.given_map[i]]); + var cards = trigger.source.getCards("h"); + var togain = []; + for (var i = 0; i < cards.length; i++) { + if (get.suit(cards[i]) == "heart") togain.push(cards[i]); } - game.loseAsync({ - gain_list: list, - giver: player, - animate: "draw", - }).setContent("gaincardMultiple"); + if (togain.length) player.gain(togain, trigger.source, "giveAuto", "bySelf"); }, }, - xinfu_wuniang: { + xinfu_yingshi: { + audio: 2, + group: ["yingshi_die"], trigger: { - player: ["useCard", "respond"], + player: "phaseUseBegin", }, - audio: 2, direct: true, filter: function (event, player) { - return event.card.name == "sha"; + return ( + player.countCards("he", { suit: "heart" }) > 0 && + !game.hasPlayer(function (current) { + return current.hasSkill("yingshi_heart"); + }) + ); }, content: function () { "step 0"; player - .chooseTarget(get.prompt("xinfu_wuniang"), "获得一名其他角色的一张牌,然后其和场上所有的“关索”摸一张牌。", function (card, player, target) { - if (player == target) return false; - return target.countGainableCards(player, "he") > 0; + .chooseTarget(get.prompt2("xinfu_yingshi"), function (card, player, target) { + return target != player; }) - .set("ai", function (target) { - return 10 - get.attitude(_status.event.player, target); + .set("ai", function () { + return -1; }); "step 1"; if (result.bool) { + var cards = player.getCards("he", { suit: "heart" }); var target = result.targets[0]; - player.logSkill("xinfu_wuniang", target); - player.line(target, "fire"); - event.draws = game.filterPlayer(function (current) { - if (current == target) return true; - return current.name == "guansuo" || current.name2 == "guansuo"; - }); - player.gainPlayerCard(target, "he", true); - } else event.finish(); - "step 2"; - game.asyncDraw(event.draws, 1); - game.delay(); + player.logSkill("xinfu_yingshi", target); + target.addSkill("yingshi_heart"); + target.addToExpansion(cards, player, "give").gaintag.add("xinfu_yingshi"); + } }, - }, - xinfu_xushen: { - derivation: ["xinfu_zhennan"], - audio: 2, - subSkill: { - count: { - trigger: { - player: "recoverBegin", - }, - forced: true, - silent: true, - popup: false, - filter: function (event, player) { - if (!event.card || event.card.name != "tao") return false; - if (!event.source || !event.source.hasSex("male")) return false; - if (!player.isDying()) return false; - if ( - game.hasPlayer(function (current) { - return current.name == "guansuo" || current.name2 == "guansuo"; - }) - ) - return false; - return true; - }, - content: function () { - trigger.xinfu_xushen = true; - }, - sub: true, + marktext: "酬", + intro: { + markcount: "expansion", + content: "expansion", + onunmark: function (storage, player) { + player.removeSkill("yingshi_heart"); }, }, - group: ["xinfu_xushen_count"], - trigger: { - player: "recoverAfter", - }, - limited: true, - init: function (player) { - player.storage.xinfu_xushen = false; - }, + }, + yingshi_heart: { + charlotte: true, + trigger: { player: "damageEnd" }, filter: function (event, player) { - if (player.storage.xinfu_xushen) return false; - if (player.isDying()) return false; - return event.xinfu_xushen == true; + return event.source && event.source.isIn() && event.card && event.card.name == "sha" && player.getExpansions("xinfu_yingshi").length > 0; }, - direct: true, - skillAnimation: true, - animationColor: "fire", + forced: true, + logTarget: "source", content: function () { "step 0"; - trigger.source.chooseBool("【许身】:是否将自己的一张武将牌替换为“关索”?").set("ai", function () { - return false; - }); + trigger.source.chooseCardButton("应势:选择获得一张“酬”", player.getExpansions("xinfu_yingshi"), true); "step 1"; if (result.bool) { - player.awakenSkill("xinfu_xushen"); - player.logSkill("xinfu_xushen", trigger.source); - if (trigger.source.name2 != undefined) { - trigger.source.chooseControl(trigger.source.name1, trigger.source.name2).set("prompt", "请选择要更换的武将牌"); - } else event._result = { control: trigger.source.name1 }; - } else event.finish(); - "step 2"; - trigger.source.reinitCharacter(result.control, "guansuo"); - player.recover(); - player.addSkills("xinfu_zhennan"); + trigger.source.gain(result.links, player, "give"); + } }, - mark: true, - intro: { - content: "limited", + }, + yingshi_die: { + audio: "xinfu_yingshi", + forced: true, + trigger: { global: "die" }, + logTarget: "player", + filter: function (event, player) { + return event.player.getExpansions("xinfu_yingshi").length > 0; + }, + content: function () { + var target = trigger.player; + player.gain(target.getExpansions("xinfu_yingshi"), target, "give", "bySelf"); + }, + }, + xinfu_duanfa: { + init: function (player) { + player.storage.xinfu_duanfa = 0; + }, + audio: 2, + enable: "phaseUse", + position: "he", + filter: function (card, player) { + return player.storage.xinfu_duanfa < player.maxHp; + }, + filterCard: function (card) { + return get.color(card) == "black"; + }, + selectCard: function () { + var player = _status.event.player; + return [1, player.maxHp - player.storage.xinfu_duanfa]; + }, + check: function (card) { + return 6 - get.value(card); + }, + delay: false, + content: function () { + player.draw(cards.length); + player.storage.xinfu_duanfa += cards.length; }, - }, - xinfu_falu: { + group: "xinfu_duanfa_clear", subSkill: { - spade: { - marktext: "♠︎️", - intro: { - name: "紫薇", - content: "mark", - }, - }, - heart: { - marktext: "♥︎️", - intro: { - name: "玉清", - content: "mark", + clear: { + trigger: { + player: "phaseBefore", }, - }, - club: { - marktext: "♣︎️", - intro: { - name: "后土", - content: "mark", + forced: true, + silent: true, + popup: false, + content: function () { + player.storage.xinfu_duanfa = 0; }, + sub: true, }, - diamond: { - marktext: "♦︎", - intro: { - name: "勾陈", - content: "mark", - }, + }, + ai: { + order: 1, + result: { + player: 1, }, }, - forced: true, + }, + xinfu_youdi: { audio: 2, trigger: { - player: ["loseAfter", "enterGame"], - global: ["loseAsyncAfter", "phaseBefore"], + player: "phaseJieshuBegin", }, + direct: true, filter: function (event, player) { - if (event.name.indexOf("lose") != 0) return event.name != "phase" || game.phaseNumber == 0; - if (event.type != "discard" || event.getlx === false) return false; - var evt = event.getl(player); - for (var i = 0; i < evt.cards2.length; i++) { - if (!player.hasMark("xinfu_falu_" + get.suit(evt.cards2[i]))) return true; - } - return false; + return player.countCards("h") > 0; }, content: function () { - if (trigger.name.indexOf("lose") !== 0) { - for (var i = 0; i < lib.suit.length; i++) { - if (!player.hasMark("xinfu_falu_" + lib.suit[i])) player.addMark("xinfu_falu_" + lib.suit[i]); - } - return; + "step 0"; + player + .chooseTarget(get.prompt2("xinfu_youdi"), function (card, player, target) { + return player != target; + }) + .set("ai", function (target) { + var player = _status.event.player; + if (player.countCards("h", "sha") > player.countCards("h") / 3 && player.countCards("h", { color: "red" }) > player.countCards("h") / 2) return 0; + if (target.countCards("he") == 0) return 0.1; + return -get.attitude(_status.event.player, target); + }); + "step 1"; + if (result.bool) { + game.delay(); + player.logSkill("xinfu_youdi", result.targets); + event.target = result.targets[0]; + event.target.discardPlayerCard(player, "h", true); + } else { + event.finish(); } - var evt = trigger.getl(player); - for (var i = 0; i < evt.cards2.length; i++) { - var suit = get.suit(evt.cards2[i]); - if (!player.hasMark("xinfu_falu_" + suit)) player.addMark("xinfu_falu_" + suit); + "step 2"; + if (get.color(result.links[0]) != "black") player.draw("nodelay"); + if (result.links[0].name != "sha" && event.target.countCards("he")) { + player.gainPlayerCard("he", event.target, true); } }, ai: { + expose: 0.3, threaten: 1.4, - combo: "xinfu_zhenyi", }, }, - xinfu_dianhua: { - trigger: { - player: ["phaseZhunbeiBegin", "phaseJieshuBegin"], + xinfu_guanchao: { + subSkill: { + dizeng: { + mark: true, + marktext: "增", + intro: { + content: "单调递增", + }, + trigger: { + player: "useCard", + }, + audio: "xinfu_guanchao", + forced: true, + mod: { + aiOrder: function (player, card, num) { + if (typeof card.number != "number") return; + var history = player.getHistory("useCard", function (evt) { + return evt.isPhaseUsing() && evt.getParent("phaseUse") === _status.event.getParent("phaseUse"); + }); + if (history.length == 0) return num + 10 * (14 - card.number); + var num = get.number(history[0].card); + if (!num) return; + for (var i = 1; i < history.length; i++) { + var num2 = get.number(history[i].card); + if (!num2 || num2 <= num) return; + num = num2; + } + if (card.number > num) return num + 10 * (14 - card.number); + }, + }, + filter: function (event, player) { + var history = player.getHistory("useCard", function (evt) { + return evt.isPhaseUsing() && evt.getParent("phaseUse") === event.getParent("phaseUse"); + }); + if (history.length < 2) return false; + var num = get.number(history[0].card); + if (!num) return false; + for (var i = 1; i < history.length; i++) { + var num2 = get.number(history[i].card); + if (!num2 || num2 <= num) return false; + num = num2; + } + return true; + }, + content: function () { + player.draw(); + }, + sub: true, + }, + dijian: { + mark: true, + marktext: "减", + intro: { + content: "单调递减", + }, + init: function (player) { + player.storage.guanchao = 0; + }, + onremove: function (player) { + delete player.storage.guanchao; + }, + trigger: { + player: "useCard", + }, + audio: "xinfu_guanchao", + forced: true, + mod: { + aiOrder: function (player, card, num) { + if (typeof card.number != "number") return; + var history = player.getHistory("useCard", function (evt) { + return evt.isPhaseUsing() && evt.getParent("phaseUse") === _status.event.getParent("phaseUse"); + }); + if (history.length == 0) return num + 10 * card.number; + var num = get.number(history[0].card); + if (!num) return; + for (var i = 1; i < history.length; i++) { + var num2 = get.number(history[i].card); + if (!num2 || num2 >= num) return; + num = num2; + } + if (card.number < num) return num + 10 * card.number; + }, + }, + filter: function (event, player) { + var history = player.getHistory("useCard", function (evt) { + return evt.isPhaseUsing() && evt.getParent("phaseUse") === event.getParent("phaseUse"); + }); + if (history.length < 2) return false; + var num = get.number(history[0].card); + if (!num) return false; + for (var i = 1; i < history.length; i++) { + var num2 = get.number(history[i].card); + if (!num2 || num2 >= num) return false; + num = num2; + } + return true; + }, + content: function () { + player.draw(); + }, + sub: true, + }, }, - frequent: true, audio: 2, - filter: function (event, player) { - for (var i = 0; i < lib.suit.length; i++) { - if (player.hasMark("xinfu_falu_" + lib.suit[i])) return true; - } - return false; + trigger: { + player: "phaseUseBegin", }, + direct: true, content: function () { "step 0"; - var num = 0; - for (var i = 0; i < lib.suit.length; i++) { - if (player.hasMark("xinfu_falu_" + lib.suit[i])) num++; - } - var cards = get.cards(num); - game.cardsGotoOrdering(cards); - var next = player.chooseToMove(); - next.set("list", [["牌堆顶", cards], ["牌堆底"]]); - next.set("prompt", "点化:点击将牌移动到牌堆顶或牌堆底"); - next.processAI = function (list) { - var cards = list[0][1], - player = _status.event.player; - var target = _status.event.getTrigger().name == "phaseZhunbei" ? player : player.next; - var att = get.sgn(get.attitude(player, target)); - var top = []; - var judges = target.getCards("j"); - var stopped = false; - if (player != target || !target.hasWuxie()) { - for (var i = 0; i < judges.length; i++) { - var judge = get.judge(judges[i]); - cards.sort(function (a, b) { - return (judge(b) - judge(a)) * att; - }); - if (judge(cards[0]) * att < 0) { - stopped = true; - break; - } else { - top.unshift(cards.shift()); - } - } + var list = ["递增", "递减", "取消"]; + player + .chooseControl(list) + .set("prompt", get.prompt2("xinfu_guanchao")) + .set("ai", function () { + return [0, 1].randomGet(); + }); + "step 1"; + switch (result.control) { + case "递增": { + player.logSkill("xinfu_guanchao"); + player.addTempSkill("xinfu_guanchao_dizeng", "phaseUseEnd"); + break; } - var bottom; - if (!stopped) { - cards.sort(function (a, b) { - return (get.value(b, player) - get.value(a, player)) * att; - }); - while (cards.length) { - if (get.value(cards[0], player) <= 5 == att > 0) break; - top.unshift(cards.shift()); - } + case "递减": { + player.logSkill("xinfu_guanchao"); + player.addTempSkill("xinfu_guanchao_dijian", "phaseUseEnd"); + break; + } + case "取消": { + break; } - bottom = cards; - return [top, bottom]; - }; - "step 1"; - var top = result.moved[0]; - var bottom = result.moved[1]; - top.reverse(); - for (var i = 0; i < top.length; i++) { - ui.cardPile.insertBefore(top[i], ui.cardPile.firstChild); - } - for (i = 0; i < bottom.length; i++) { - ui.cardPile.appendChild(bottom[i]); } - player.popup(get.cnNumber(top.length) + "上" + get.cnNumber(bottom.length) + "下"); - game.log(player, "将" + get.cnNumber(top.length) + "张牌置于牌堆顶"); - game.updateRoundNumber(); - game.delayx(); - }, - ai: { - combo: "xinfu_falu", - threaten: 2.2, }, }, - xinfu_zhenyi: { - group: ["zhenyi_spade", "zhenyi_club", "zhenyi_heart"], + xinfu_xunxian: { + usable: 1, + audio: 2, trigger: { - player: "damageEnd", + player: ["useCardAfter", "respond"], }, - audio: 2, filter: function (event, player) { - //if(!event.hasNature()) return false; - return player.hasMark("xinfu_falu_diamond"); - }, - prompt2: "弃置「勾陈♦」标记,从牌堆中获得每种类型的牌各一张。", - content: function () { - "step 0"; - player.removeMark("xinfu_falu_diamond"); - event.num = 0; - event.togain = []; - "step 1"; - var card = get.cardPile(function (card) { - for (var i = 0; i < event.togain.length; i++) { - if (get.type(card, "trick") == get.type(event.togain[i], "trick")) return false; + if ( + get.itemtype(event.cards) !== "cards" || + !game.hasPlayer(current => { + if (current === player) return false; + return current.getHp() > player.getHp() || current.countCards("h") > player.countCards("h"); + }) + ) + return false; + for (var i = 0; i < event.cards.length; i++) { + if (event.cards[i].isInPile()) { + return true; } - return true; - }); - if (card) { - event.togain.push(card); - event.num++; - if (event.num < 3) event.redo(); - } - "step 2"; - if (event.togain.length) { - player.gain(event.togain, "gain2"); } + return false; + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2("xinfu_xunxian"), (card, player, target) => { + if (target === player) return false; + return target.getHp() > player.getHp() || target.countCards("h") > player.countCards("h"); + }) + .set("ai", target => { + let att = get.attitude(_status.event.player, target), + name = _status.event.cards[0].name; + if (att < 3) return 0; + if (target.hasJudge("lebu")) att /= 5; + if (name === "sha" && target.hasSha()) att /= 5; + if (name === "wuxie" && target.needsToDiscard(_status.event.cards)) att /= 5; + return att / (1 + get.distance(player, target, "absolute")); + }) + .set("cards", trigger.cards) + .forResult(); }, - ai: { - combo: "xinfu_falu", + async content(event, trigger, player) { + let list = []; + for (let i = 0; i < trigger.cards.length; i++) { + if (trigger.cards[i].isInPile()) { + list.push(trigger.cards[i]); + } + } + if (get.mode() !== "identity" || player.identity !== "nei") player.addExpose(0.2); + event.targets[0].gain(list, "gain2").giver = player; }, }, - zhenyi_spade: { - trigger: { - global: "judge", + xinfu_kannan: { + audio: 2, + subSkill: { + phase: { + sub: true, + }, }, - direct: true, + enable: "phaseUse", filter: function (event, player) { - return player.hasMark("xinfu_falu_spade"); + if (player.getStat().skill.xinfu_kannan >= player.hp) return false; + return player.countCards("h") > 0; + }, + filterTarget: function (card, player, target) { + if (target.hasSkill("xinfu_kannan_phase")) return false; + return player.canCompare(target); + }, + ai: { + order: function () { + return get.order({ name: "sha" }) + 0.4; + }, + result: { + target: function (player, target) { + if ( + player.hasCard(function (card) { + if (get.position(card) != "h") return false; + var val = get.value(card); + if (val < 0) return true; + if (val <= 5) { + return card.number >= 12; + } + if (val <= 6) { + return card.number >= 13; + } + return false; + }) + ) + return -1; + return 0; + }, + }, }, content: function () { "step 0"; - var str = get.translation(trigger.player) + "的" + (trigger.judgestr || "") + "判定为" + get.translation(trigger.player.judging[0]) + ",是否发动【真仪】,弃置「紫薇♠」标记并修改判定结果?"; - player - .chooseControl("spade", "heart", "diamond", "club", "cancel2") - .set("prompt", str) - .set("ai", function () { - //return '取消'; - var judging = _status.event.judging; - var trigger = _status.event.getTrigger(); - var res1 = trigger.judge(judging); - var list = lib.suit.slice(0); - var attitude = get.attitude(player, trigger.player); - if (attitude == 0) return 0; - var getj = function (suit) { - return trigger.judge({ - name: get.name(judging), - nature: get.nature(judging), - suit: suit, - number: 5, - }); - }; - list.sort(function (a, b) { - return (getj(b) - getj(a)) * get.sgn(attitude); - }); - if ((getj(list[0]) - res1) * attitude > 0) return list[0]; - return "cancel2"; - }) - .set("judging", trigger.player.judging[0]); + player.chooseToCompare(target); "step 1"; - if (result.control != "cancel2") { - player.addExpose(0.25); - player.removeMark("xinfu_falu_spade"); - player.logSkill("xinfu_zhenyi", trigger.player); - //player.line(trigger.player); - player.popup(result.control); - game.log(player, "将判定结果改为了", "#y" + get.translation(result.control + 2) + 5); - trigger.fixedResult = { - suit: result.control, - color: get.color({ suit: result.control }), - number: 5, - }; + if (result.bool) { + player.tempBanSkill("xinfu_kannan"); + if (!player.hasSkill("kannan_eff")) { + player.addSkill("kannan_eff"); + } else { + if (!player.storage.kannan_eff) player.storage.kannan_eff = 0; + } + player.storage.kannan_eff++; + player.markSkill("kannan_eff"); + } else { + target.addTempSkill("xinfu_kannan_phase"); + if (!target.hasSkill("kannan_eff")) { + target.addSkill("kannan_eff"); + } else { + if (!target.storage.kannan_eff) player.storage.kannan_eff = 0; + //target.storage.kannan_eff++; + //target.markSkill('kannan_eff'); + } + target.storage.kannan_eff++; + target.markSkill("kannan_eff"); } }, - ai: { - rejudge: true, - tag: { - rejudge: 1, - }, - expose: 0.5, - }, }, - zhenyi_club: { - audio: "xinfu_zhenyi", - enable: "chooseToUse", - viewAsFilter: function (player) { - if (player == _status.currentPhase) return false; - return player.hasMark("xinfu_falu_club") && player.countCards("hs") > 0; + kannan_eff: { + mark: true, + intro: { + content: "下一张杀的伤害基数+#", }, - filterCard: true, - position: "hs", - viewAs: { - name: "tao", + trigger: { + player: "useCard", }, - prompt: "弃置「后土♣」标记,将一张手牌当桃使用", - check: function (card) { - return 15 - get.value(card); + filter: function (event) { + return event.card && event.card.name == "sha"; }, - precontent: function () { - player.removeMark("xinfu_falu_club"); + forced: true, + content: function () { + if (!trigger.baseDamage) trigger.baseDamage = 1; + trigger.baseDamage += player.storage.kannan_eff; + player.removeSkill("kannan_eff"); + }, + init: function (player) { + player.storage.kannan_eff = 0; + }, + onremove: function (player) { + delete player.storage.kannan_eff; + }, + ai: { + damageBonus: true, }, }, - zhenyi_heart: { + xinfu_tushe: { + audio: 2, + mod: { + aiOrder(player, card, num) { + if (get.tag(card, "multitarget")) { + if (player.countCards("h", { type: "basic" })) return num / 10; + return num * 10; + } + if (get.type(card) === "basic") return num + 10; + }, + aiValue(player, card, num) { + if (card.name === "zhangba") { + let fact = n => { + if (n > 1) return n * fact(n - 1); + return 1; + }, + basic = 0; + return fact( + Math.min( + player.countCards("hs", i => { + if (get.tag(i, "multitarget")) return 2; + if (!["shan", "tao", "jiu"].includes(card.name)) return 1; + basic++; + }) / + (1 + basic), + player.getCardUsable("sha") + ) + ); + } + if (["shan", "tao", "jiu"].includes(card.name)) { + if (player.getEquip("zhangba") && player.countCards("hs") > 1) return 0.01; + return num / 2; + } + if (get.tag(card, "multitarget")) return num + game.players.length; + }, + aiUseful(player, card, num) { + if (get.name(card, player) === "shan") { + if ( + player.countCards("hs", i => { + if (card === i || (card.cards && card.cards.includes(i))) return false; + return get.name(i, player) === "shan"; + }) + ) + return -1; + return num / Math.pow(Math.max(1, player.hp), 2); + } + }, + }, trigger: { - source: "damageBegin1", + player: "useCardToPlayered", }, - audio: "xinfu_zhenyi", + locked: false, + frequent: true, filter: function (event, player) { - return player.hasMark("xinfu_falu_heart"); - }, - check: function (event, player) { - if (get.attitude(player, event.player) >= 0) return false; - if ( - event.player.hasSkillTag("filterDamage", null, { - player: player, - card: event.card, - }) - ) - return false; - return true; - //return player.hasMark('xinfu_falu_spade')||get.color(ui.cardPile.firstChild)=='black'; - }, - prompt2: function (event) { - return "弃置「玉清♥」标记,令对" + get.translation(event.player) + "即将造成的伤害+1。"; + if (get.type(event.card) == "equip") return false; + if (event.getParent().triggeredTargets3.length > 1) return false; + return event.targets.length > 0 && !player.countCards("h", { type: "basic" }); }, - logTarget: "player", content: function () { - player.removeMark("xinfu_falu_heart"); - trigger.num++; + player.draw(trigger.targets.length); + }, + ai: { + presha: true, + pretao: true, + threaten: 1.8, + effect: { + player_use(card, player, target) { + if ( + typeof card === "object" && + card.name !== "shan" && + get.type(card) !== "equip" && + !player.countCards("h", i => { + if (card === i || (card.cards && card.cards.includes(i))) return false; + return get.type(i) === "basic"; + }) + ) { + let targets = [], + evt = _status.event.getParent("useCard"); + targets.addArray(ui.selected.targets); + if (evt && evt.card == card) targets.addArray(evt.targets); + if (targets.length) return [1, targets.length]; + if (get.tag(card, "multitarget")) return [1, game.players.length - 1]; + return [1, 1]; + } + }, + }, }, }, - xinfu_zhennan: { - audio: 2, - trigger: { - target: "useCardToTargeted", + xinfu_limu: { + mod: { + targetInRange: function (card, player, target) { + if (player.countCards("j") && player.inRange(target)) { + return true; + } + }, + cardUsableTarget: function (card, player, target) { + if (player.countCards("j") && player.inRange(target)) return true; + }, + aiOrder(player, card, num) { + if (get.type(card, null, player) == "trick" && player.canUse(card, player) && player.canAddJudge(card)) return 15; + }, }, + locked: false, + audio: 2, + enable: "phaseUse", + discard: false, filter: function (event, player) { - return event.card.name == "nanman"; + if (player.hasJudge("lebu")) return false; + return player.countCards("hes", { suit: "diamond" }) > 0; }, - direct: true, - content: function () { - "step 0"; - player - .chooseTarget(get.prompt("xinfu_zhennan"), "对一名其他角色造成1-3点随机伤害", function (card, player, target) { - return target != player; - }) - .set("ai", function (target) { - var player = _status.event.player; - return get.damageEffect(target, player, player); - }); - "step 1"; - if (result.bool && result.targets && result.targets.length) { - game.delay(); - player.logSkill("xinfu_zhennan", result.targets); - var num = [1, 2, 3, 1, 1, 2].randomGet(); - if (get.isLuckyStar(player)) num = 3; - //player.line(result.targets[0],'fire'); - result.targets[0].damage(num); + viewAs: { name: "lebu" }, + //prepare:"throw", + position: "hes", + filterCard: function (card, player, event) { + return get.suit(card) == "diamond" && player.canAddJudge({ name: "lebu", cards: [card] }); + }, + selectTarget: -1, + filterTarget: function (card, player, target) { + return player == target; + }, + check(card) { + var player = _status.event.player; + if (!player.getEquip("zhangba")) { + let damaged = player.maxHp - player.hp - 1; + if ( + player.countCards("h", function (cardx) { + if (cardx == card) return false; + if (cardx.name == "tao") { + if (damaged < 1) return true; + damaged--; + } + return ["shan", "jiu"].includes(cardx.name); + }) > 0 + ) + return 0; } + if (card.name == "shan") return 15; + if (card.name == "tao" || card.name == "jiu") return 10; + return 9 - get.value(card); + }, + onuse: function (links, player) { + var next = game.createEvent("limu_recover", false, _status.event.getParent()); + next.player = player; + next.setContent(function () { + player.recover(); + }); }, ai: { - expose: 0.25, + result: { + target(player, target) { + let res = lib.card.lebu.ai.result.target(player, target); + if (target.isDamaged()) return res + 2 * Math.abs(get.recoverEffect(target, player, target)); + return res; + }, + ignoreStatus: true, + }, + order(item, player) { + if (player.hp > 1 && player.countCards("j")) return 0; + return 12; + }, + effect: { + target(card, player, target) { + if (target.isPhaseUsing() && typeof card === "object" && get.type(card, null, target) === "delay" && !target.countCards("j")) { + let shas = + target.getCards("hs", i => { + if (card === i || (card.cards && card.cards.includes(i))) return false; + return get.name(i, target) === "sha" && target.getUseValue(i) > 0; + }) - target.getCardUsable("sha"); + if (shas > 0) return [1, 1.5 * shas]; + } + }, + }, }, }, }; diff --git a/character/sp/sort.js b/character/sp/sort.js index c5fd7b0588..90f93f5476 100644 --- a/character/sp/sort.js +++ b/character/sp/sort.js @@ -1,18 +1,18 @@ const characterSort = { - sp_tianji: ["sunhao", "liuxie", "caoang", "hetaihou", "sunluyu", "ol_wangrong", "zuofen", "ol_bianfuren", "qinghegongzhu", "tengfanglan", "ruiji", "caoxiancaohua", "caoyu"], - sp_sibi: ["ol_lukai", "yangxiu", "guotu", "chenlin", "chengyu", "shixie", "fuwan", "wangyun", "zhugejin", "simalang", "maliang", "buzhi", "dongyun", "kanze", "sunqian", "xizhicai", "sunshao", "duxi", "jianggan", "ol_dengzhi", "ol_yangyi", "ol_dongzhao", "ol_chendeng", "jin_yanghu", "wangyan", "xiahouxuan", "quhuang", "zhanghua", "wangguan", "sunhong", "caoxi", "tianchou"], - sp_tianzhu: ["ol_liupi", "yadan", "liyi", "zhangyan", "niujin", "hejin", "hansui", "wutugu", "yanbaihu", "shamoke", "zhugedan", "huangzu", "gaogan", "tadun", "fanjiangzhangda", "ahuinan", "dongtuna", "ol_wenqin"], - sp_nvshi: ["ol_dingshangwan", "lingju", "guanyinping", "zhangxingcai", "mayunlu", "dongbai", "zhaoxiang", "ol_zhangchangpu", "daxiaoqiao", "jin_guohuai", "ol_hujinding", "ol_luyusheng", "ol_liwan"], + sp_tianji: ["liuyan", "caoteng", "sunhao", "liuxie", "caoang", "hetaihou", "sunluyu", "ol_wangrong", "zuofen", "ol_bianfuren", "qinghegongzhu", "tengfanglan", "ruiji", "caoxiancaohua", "caoyu"], + sp_sibi: ["liuyan", "yanjun", "panjun", "lvqian", "wangcan", "ol_lukai", "yangxiu", "guotu", "chenlin", "chengyu", "shixie", "fuwan", "wangyun", "zhugejin", "simalang", "maliang", "buzhi", "dongyun", "kanze", "sunqian", "xizhicai", "sunshao", "duxi", "jianggan", "ol_dengzhi", "ol_yangyi", "ol_dongzhao", "ol_chendeng", "jin_yanghu", "wangyan", "xiahouxuan", "quhuang", "zhanghua", "wangguan", "sunhong", "caoxi", "tianchou"], + sp_tianzhu: ["ol_liupi", "budugen", "ol_kebineng", "yadan", "liyi", "zhangyan", "niujin", "hejin", "hansui", "wutugu", "yanbaihu", "shamoke", "zhugedan", "huangzu", "gaogan", "tadun", "fanjiangzhangda", "ahuinan", "dongtuna", "ol_wenqin"], + sp_nvshi: ["ol_sunru", "ol_yuanji", "ol_dingshangwan", "lingju", "guanyinping", "zhangxingcai", "mayunlu", "dongbai", "zhaoxiang", "ol_zhangchangpu", "daxiaoqiao", "jin_guohuai", "ol_hujinding", "ol_luyusheng", "ol_liwan"], sp_shaowei: ["ol_pengyang", "simahui", "zhangbao", "zhanglu", "zhugeguo", "xujing", "zhangling", "huangchengyan", "zhangzhi", "lushi"], - sp_huben: ["duanjiong", "liupan", "ol_mengda", "caohong", "xiahouba", "zhugeke", "zumao", "wenpin", "litong", "mazhong", "heqi", "quyi", "luzhi", "yuejin", "dingfeng", "wuyan", "ol_zhuling", "tianyu", "huojun", "zhaoyǎn", "dengzhong", "ol_furong", "macheng", "ol_zhangyì", "ol_zhujun", "maxiumatie", "luoxian", "ol_huban", "haopu", "ol_qianzhao", "caimao"], + sp_huben: ["zhoufang", "duanjiong", "liupan", "ol_mengda", "caohong", "xiahouba", "zhugeke", "zumao", "wenpin", "litong", "mazhong", "heqi", "quyi", "luzhi", "yuejin", "dingfeng", "wuyan", "ol_zhuling", "tianyu", "huojun", "zhaoyǎn", "dengzhong", "ol_furong", "macheng", "ol_zhangyì", "ol_zhujun", "maxiumatie", "luoxian", "ol_huban", "haopu", "ol_qianzhao", "caimao"], sp_liesi: ["lvboshe", "mizhu", "weizi", "ol_liuba", "zhangshiping"], - sp_default: ["sp_diaochan", "sp_zhaoyun", "sp_sunshangxiang", "sp_caoren", "sp_jiangwei", "sp_machao", "sp_caiwenji", "jsp_guanyu", "jsp_huangyueying", "sp_pangde", "sp_jiaxu", "yuanshu", "sp_zhangliao", "sp_ol_zhanghe", "sp_menghuo", "sp_sunce"], + sp_default: ["re_jsp_pangtong", "sp_diaochan", "sp_zhaoyun", "sp_sunshangxiang", "sp_caoren", "sp_jiangwei", "sp_machao", "sp_caiwenji", "jsp_guanyu", "jsp_huangyueying", "sp_pangde", "sp_jiaxu", "yuanshu", "sp_zhangliao", "sp_ol_zhanghe", "sp_menghuo", "sp_sunce"], sp_qifu: ["ol_jiangwan", "ol_feiyi", "caoying", "panshu", "caochun", "yuantanyuanshang", "caoshuang", "wolongfengchu", "guansuo", "baosanniang", "fengfangnv", "jin_zhouchu"], sp_wanglang: ["ol_wanglang", "ol_puyuan", "ol_zhouqun"], sp_zhongdan: ["cuiyan", "huangfusong"], sp_guozhan2: ["sp_dongzhuo", "zhangren"], sp_others: ["hanba", "caiyang", "ol_peixiu"], - sp_waitforsort: ["ol_tw_zhangji", "mawan", "budugen", "caoteng"], + sp_waitforsort: ["kongshu", "ol_tw_zhangji", "mawan"], }; const characterSortTranslate = { diff --git a/character/sp/translate.js b/character/sp/translate.js index c54f434bf3..c650ad8b08 100644 --- a/character/sp/translate.js +++ b/character/sp/translate.js @@ -158,7 +158,8 @@ const translates = { caoying: "曹婴", simahui: "司马徽", baosanniang: "鲍三娘", - majun: "马钧", + majun: "手杀马钧", + majun_prefix: "手杀", simazhao: "司马昭", wangyuanji: "王元姬", @@ -205,8 +206,6 @@ const translates = { new_mumu_info: "出牌阶段开始时,你可以选择一项:1.弃置一名其他角色装备区里的一张牌;2.获得一名角色装备区里的一张防具牌,若如此做,你本回合不能使用【杀】。", new_zhixi: "止息", new_zhixi_info: "锁定技。出牌阶段内,若你使用过锦囊牌或使用过的牌数不小于X,则你不能使用牌(X为你的体力值)。", - new_mumu2: "穆穆", - new_mumu2_info: "锁定技,你不能使用【杀】。", new_xingwu: "星舞", new_xingwu_info: "弃牌阶段开始时,你可以将一张牌置于武将牌上,称为“舞”。然后你可以选择一项:①将三张“舞”置入弃牌堆;②弃置两张手牌并将武将牌翻面。若如此做,你选择一名角色,该角色弃置其装备区的所有牌并受到2点伤害(若为女性,则改为1点)。", new_luoyan: "落雁", @@ -317,7 +316,7 @@ const translates = { xiashu_info: "出牌阶段开始时,你可以将所有手牌交给一名其他角色,然后该角色亮出任意数量的手牌(至少一张)。你选择一项:1.获得其亮出的手牌;2.获得其未亮出的手牌。", kuanshi: "宽释", kuanshi2: "宽释", - kuanshi_info: "结束阶段,你可以选择一名角色。直到你的下回合开始,该角色第一次受到大于1的伤害时,防止此伤害,然后你跳过下个回合的摸牌阶段。", + kuanshi_info: "结束阶段,你可以选择一名角色(其他角色不可见)。直到你的下回合开始,该角色第一次受到大于1的伤害时,防止此伤害,然后你跳过下个回合的摸牌阶段。", bingzheng: "秉正", bingzheng_info: "出牌阶段结束时,你可以令手牌数不等于体力值的一名角色弃置一张手牌或摸一张牌。然后若其手牌数等于体力值,你摸一张牌,且可以交给该角色一张牌。", sheyan: "舍宴", @@ -516,7 +515,7 @@ const translates = { tianming: "天命", mizhao: "密诏", duwu: "黩武", - duwu3: "黩武", + duwu2: "黩武", mingzhe: "明哲", huanshi: "缓释", hongyuan: "弘援", @@ -861,7 +860,7 @@ const translates = { olfengji: "丰积", olfengji_info: "一轮游戏开始时,你选择:⒈本轮摸牌阶段的额定摸牌数-1,且令一名其他角色本轮摸牌阶段的额定摸牌数+2;⒉本轮摸牌阶段的额定摸牌数+1。然后你选择:⒈本轮使用【杀】的次数上限-1,且令一名其他角色本轮使用【杀】的次数上限+2;⒉本轮使用【杀】的次数上限+1。", olxuanhui: "旋回", - olxuanhui_info: "准备阶段,若你有〖丰积〗效果,你可以选择一名拥有〖丰积〗效果的其他角色。若如此做,你与其交换〖丰积〗效果,且〖旋回〗失效直到有角色死亡。", + olxuanhui_info: "准备阶段,若你有〖丰积〗效果,你可以与所有拥有〖丰积〗效果的其他角色与你交换对应的〖丰积〗效果,且〖旋回〗失效直到有角色死亡。", tianyu: "田豫", saodi: "扫狄", saodi_info: "当你使用【杀】或普通锦囊牌指定唯一其他角色为目标时,你可从逆时针方向和顺时针方向中选择一个你与其之间角色最少的方向。你令该方向下你与其之间的所有能成为此牌额外目标的角色均成为此牌的目标。", @@ -1077,7 +1076,7 @@ const translates = { olxinggu_info: "①游戏开始时,你将牌堆中的三张坐骑牌扣置于武将牌上。②结束阶段,你可以将一张〖行贾①〗牌置于一名其他角色的装备区,然后你从牌堆获得一张♦牌。", lushi: "卢氏", olzhuyan: "驻颜", - olzhuyan_info: "每名角色每项各限一次。弃牌阶段结束时,你可以令一名角色将以下一项调整至与其上一个结束阶段结束后相同:1.体力值;2.手牌数(体力值至多失去至1,手牌数至多摸至5;若其未执行过准备阶段则改为游戏开始时)。", + olzhuyan_info: "每名角色每项各限一次。弃牌阶段结束时,你可以令一名角色将以下一项调整至与其上一个结束阶段结束后相同:1.体力值;2.手牌数(体力值至多失去至1,摸牌时至多摸至5;若其未执行过结束阶段则改为游戏开始时)。", olleijie: "雷劫", olleijie_info: "准备阶段,你可以令一名角色判定,若结果为♠2~9,其受到2点雷电伤害,否则其摸两张牌。", releijie: "雷劫", @@ -1203,7 +1202,7 @@ const translates = { olgongjie: "恭节", olgongjie_info: "每轮的首个回合开始时,你可以令任意名角色获得你的一张牌,然后你摸X张牌(X为你本次失去的花色数)。", olxiangxv: "相胥", - olxiangxv_info: "当你的手牌数变为全场最少时,你可以获得以下效果:本回合结束时,将手牌数调整至与当前回合角色手牌数相同(至多摸至五张),然后若你以此法弃置了至少两张手牌,则你回复1点体力。", + olxiangxv_info: "一名角色的回合结束时,若你本回合的手牌数因失去手牌变为过全场最少,则你可以将手牌数调整至与当前回合角色手牌数相同(至多摸至五张),然后若你以此法弃置了至少两张手牌,则你回复1点体力。", olxiangzuo: "襄胙", olxiangzuo_info: "限定技,当你进入濒死状态时,你可以交给一名其他角色任意张牌,然后若你已对其发动过〖恭节〗和〖相胥〗,你回复等量的体力。", liyi: "李异", @@ -1272,9 +1271,112 @@ const translates = { olkouchao_info: "每轮每项限一次,你可以将一张牌当作【杀】/【火攻】/【过河拆桥】使用。此牌结算完毕后,将此项改为本局游戏最后一张不因使用进入弃牌堆的基本牌或普通锦囊牌的牌名,然后若〖寇钞〗的所有项均为基本牌,则你修改〖寇钞〗的所有项为【顺手牵羊】。", caoteng: "曹腾", olyongzu: "拥族", - olyongzu_info: "准备阶段,你可以选择一名其他角色。你与其依次选择不同的一项执行:①摸两张牌;②回复1点体力;③复原武将牌。若你与其势力相同,则额外添加两项:④手牌上限+1;⑤若势力为魏/群,则获得技能〖奸雄〗/〖天命〗。", + olyongzu_info: "准备阶段,你可以选择一名其他角色。你与其依次选择不同的一项执行:①摸两张牌;②回复1点体力;③复原武将牌。若你与其势力相同,则额外添加两项:④手牌上限+1;⑤若势力为魏/群,则获得技能〖奸雄〗/〖天命〗直到执行此选项者的下回合开始。", olqingliu: "清流", olqingliu_info: "锁定技。①游戏开始时,你选择魏国和群雄中的一个,将势力变更至此势力。②当你首次脱离濒死状态后,你将势力变更至〖清流①〗未选择的势力。", + ol_sunru: "OL孙茹", + ol_sunru_prefix: "OL", + olchishi: "持室", + olchishi_info: "每回合限一次,当前回合角色失去其一个区域内的最后一张牌后,你可以令其摸两张牌且本回合手牌上限+2。", + olweimian: "慰勉", + olweimian_info: "出牌阶段限一次,你可以废除至多三个装备栏,然后令一名角色选择等量项:①恢复一个已废除的装备栏;②回复1点体力;③弃置所有手牌,然后摸四张牌。", + ol_kebineng: "OL轲比能", + ol_kebineng_prefix: "OL", + olpingduan: "平端", + olpingduan_info: "出牌阶段限一次,你可以令一名角色依次执行:1.使用一张基本牌;2.重铸一张锦囊牌;3.可令你获得其装备区内一张牌。其每以此法执行一项便摸一张牌。", + ol_yuanji: "OL袁姬", + ol_yuanji_prefix: "OL", + oljieyan: "节言", + oljieyan_info: "准备阶段,你可以对一名角色造成1点伤害,然后其选择一项:1.跳过下个弃牌阶段;2.回复1点体力,其下个弃牌阶段手牌上限-2且你可以将其此阶段弃置的牌交给另一名角色。", + oljinghua: "镜花", + oljinghua_info: "当其他角色获得你的牌后,其回复1点体力。当你失去最后的手牌后,你可以将此技能描述中的“回复”改为“失去”。", + olshuiyue: "水月", + olshuiyue_info: "当其他角色受到你造成的伤害后,其摸一张牌。当你令其他角色进入濒死状态后,你可以将此技能描述中的“摸”改为“弃置”。", + kongshu: "孔淑", + olleiluan: "累卵", + olleiluan_info: "①每回合限一次,你可以将X张牌当作本轮未使用过的基本牌使用。②一轮游戏开始时,若你上一轮使用基本牌的次数大于等于X,则你可以摸X张牌,然后视为使用上一轮进入弃牌堆的一张普通锦囊牌。(X为你此前连续发动〖累卵〗的轮数且X至少为1,且〖累卵②〗视为发动轮次的上一轮发动)", + olfuchao: "覆巢", + olfuchao_info: "锁定技,当你响应其他角色使用的牌时,你选择一项:①弃置你与使用者的各一张牌,其他角色无法响应此牌;②令此牌对其他角色无效,且此牌对你额外结算一次。", + sp_taishici: "SP太史慈", + sp_taishici_prefix: "SP", + wangcan: "王粲", + re_jsp_pangtong: "SP庞统", + re_jsp_pangtong_prefix: "SP", + lvdai: "吕岱", + re_zhangliang: "张梁", + lvqian: "吕虔", + panjun: "潘濬", + duji: "杜畿", + zhoufang: "周鲂", + yanjun: "严畯", + liuyao: "刘繇", + liuyan: "刘焉", + xinfu_guolun: "过论", + xinfu_guolun_info: "出牌阶段限一次,你可以展示一名其他角色的手牌,然后展示你的一张牌。你与其交换这两张牌,然后展示的牌点数较小的角色摸一张牌。", + xinfu_zhanji: "展骥", + xinfu_zhanji_info: "锁定技。你的出牌阶段内,当你因摸牌且不是因为此技能效果而得到牌后,你摸一张牌。", + xinfu_songsang: "送丧", + xinfu_songsang_info: "限定技,其他角色死亡时,你可以回复1点体力(若你未受伤,则改为加1点体力上限);然后获得技能〖展骥〗。", + xinfu_jixu: "击虚", + xinfu_jixu_info: "出牌阶段限一次,若你有手牌,你可以令任意名体力值相等的其他角色猜测你的手牌中是否有【杀】。然后,你摸X张牌(X为猜错的角色数)。若你有【杀】,则你本回合内使用【杀】时,所有这些角色均成为【杀】的目标;若你没有【杀】,则你弃置所有这些角色的各一张牌。若X为零,你结束出牌阶段。", + jixu_sha: "击虚", + jixu_sha_info: "", + xinfu_sanwen: "散文", + xinfu_sanwen_info: "每回合限一次。当你得到牌后,若你的原手牌中有与这些牌名称相同的牌,则你可以展示这些牌,弃置新得到的同名牌并摸两倍的牌。", + xinfu_qiai: "七哀", + xinfu_qiai_info: "限定技,当你进入濒死状态时,你可以令所有其他角色依次交给你一张牌。", + xinfu_denglou: "登楼", + xinfu_denglou_info: "限定技,结束阶段,若你没有手牌,则你可以观看牌堆顶的四张牌,依次使用其中的所有基本牌(不能使用则弃置),然后获得其余的牌。", + qinguo_use: "勤国", + qinguo_use_info: "", + xinfu_qinguo: "勤国", + xinfu_qinguo_info: "当你使用的装备牌结算完成时,你可以视为使用一张【杀】;当你因使用或失去装备牌导致装备区内牌的数量发生变化后,若你装备区内牌的数量等于你的体力值,则你回复1点体力。", + qinguo_lose: "勤国", + qinguo_lose_info: "", + xinfu_jijun: "集军", + xinfu_jijun_info: "当你于回合内使用非装备牌或武器牌指定目标后,若你是此牌的目标,你可以进行一次判定。然后,你将判定牌置于自己的武将牌上,称之为「方」。", + xinfu_fangtong: "方统", + xinfu_fangtong_info: "结束阶段,你可以弃置总点数之和为36的一张牌与任意张「方」,并对一名其他角色造成3点雷电伤害。", + xinfu_weilu: "威虏", + xinfu_weilu_info: "锁定技,当你受到伤害后,伤害来源获得一枚「虏」。你的下个出牌阶段开始时,所有有「虏」的角色将体力失去至1点。此阶段结束后,这些角色回复以此法失去的体力。", + weilu_effect: "威虏", + weilu_effect_info: "", + weilu_effect2: "威虏", + weilu_effect2_info: "", + xinfu_zengdao: "赠刀", + xinfu_zengdao_info: "限定技,出牌阶段,你可以将装备区内的任意张牌置于一名其他角色的武将牌旁,称之为“刀”。该角色造成伤害时,其须移去一张“刀”,然后此伤害+1。", + xinfu_zengdao2: "赠刀", + xinfu_zengdao2_info: "", + xinfu_guanwei: "观微", + xinfu_guanwei_info: "每回合限一次。一名角色的出牌阶段结束时,若其本回合使用过两张以上的牌且这些牌均有花色且花色均相同,则你可以弃置一张牌,令其摸两张牌并进行一个额外的出牌阶段。", + xinfu_gongqing: "公清", + xinfu_gongqing_info: "锁定技。当你受到伤害时,若伤害来源的攻击范围:<3,则你令此伤害的数值减为1。>3,你令此伤害+1。", + xinfu_andong: "安东", + xinfu_andong_info: "当你受到伤害时,你可以令伤害来源选择一项:1.令你观看其的手牌并获得其中的所有红桃牌;2.防止此伤害,然后其本回合内的红桃手牌不计入手牌上限。", + xinfu_yingshi: "应势", + xinfu_yingshi_info: "出牌阶段开始时,若场上的所有角色均没有「酬」,则你可以将所有的红桃牌置于一名其他角色的武将牌旁,称之为「酬」。有「酬」的角色受到【杀】的伤害后/死亡时,伤害来源/你获得其中的一张/所有的「酬」。", + yingshi_heart: "应势", + yingshi_heart_info: "", + yingshi_die: "应势", + yingshi_die_info: "", + xinfu_duanfa: "断发", + xinfu_duanfa_info: "出牌阶段,你可以弃置任意张黑色牌,然后摸等量的牌。(每回合内限X张,X为你的体力上限)", + xinfu_youdi: "诱敌", + xinfu_youdi_info: "结束阶段开始时,你可以令一名其他角色弃置你的一张手牌,若此牌:不为黑色,你摸一张牌。不为【杀】,你获得该角色的一张牌。", + xinfu_guanchao: "观潮", + xinfu_guanchao_info: "出牌阶段开始时,你可以选择获得一项效果直到回合结束:1.当你使用牌时,若你此阶段使用过的所有牌的点数为递增,你摸一张牌;2.当你使用牌时,若你此阶段使用过的所有牌的点数为递减,你摸一张牌。", + xinfu_xunxian: "逊贤", + xinfu_xunxian_info: "每回合限一次。当你使用或打出的牌结算完成后,你可以将其对应的所有实体牌交给一名手牌数或体力值大于你的角色。", + xinfu_kannan: "戡难", + xinfu_kannan_info: "出牌阶段限X次,你可以与一名本回合内未成为过〖戡难〗目标的角色拼点。若你赢,你使用的下一张【杀】的伤害值基数+1,且你本回合内不能再发动〖戡难〗。若你没赢,其使用的下一张【杀】的伤害值基数+1。(X为你的体力值)。", + kannan_eff: "戡难", + kannan_eff_info: "", + xinfu_tushe: "图射", + xinfu_tushe_info: "当你使用非装备牌指定目标后,若你没有基本牌,则你可以摸X张牌。(X为此牌指定的目标数)", + xinfu_limu: "立牧", + xinfu_limu_info: "出牌阶段,你可以将一张♦牌当做【乐不思蜀】对自己使用,然后回复1点体力。只要你的判定区内有牌,你对攻击范围内的其他角色使用牌便没有次数和距离限制。", + xinyingshi: "应势", + xinyingshi_info: "出牌阶段开始时,若场上所有角色的武将牌上均没有“酬”,则你可以将任意张牌置于一名角色的武将牌上,称为“酬”。若如此做:当有角色使用牌对有“酬”的角色造成伤害后,其可以获得一张“酬”,并获得牌堆中所有与“酬”花色点数均相同的牌;有“酬”的角色死亡时,你获得其所有“酬”。", }; export default translates; diff --git a/character/sp/voices.js b/character/sp/voices.js index 64ebddbb32..22ade926d1 100644 --- a/character/sp/voices.js +++ b/character/sp/voices.js @@ -1,4 +1,16 @@ export default { + "#olchishi1": "柴米油盐之细,不逊兵家之谋。", + "#olchishi2": "治大家如烹小鲜,须面面俱到。", + "#olweimian1": "不过二三小事,夫君何须烦恼。", + "#olweimian2": "宦海疾风大浪,家为避风之塘。", + "#ol_sunru:die": "从来无情者,皆出帝王家。", + "#olyongzu1": "既拜我为父,咱家当视汝为骨肉。", + "#olyongzu2": "天地君亲师,此五者最须尊崇。", + "#rejianxiong_caoteng": "躬行禁闱,不敢争一时之气。", + "#tianming_caoteng": "天命在彼,事莫强为。", + "#olqingliu1": "谁说这宦官,皆是大奸大恶之人?", + "#olqingliu2": "咱家要让这天下人知道,宦亦有贤。", + "#caoteng:die": "种暠害我,望陛下明鉴……", "#olziruo1": "泰山虽崩于前,我亦风清云淡。", "#olziruo2": "诸君勿忧,一切尽在掌握。", "#olxvfa1": "常言道,积善之家必有余庆。", @@ -288,6 +300,8 @@ export default { "#tianyu:die": "命数之沙,已尽矣……", "#olfengji1": "取舍有道,待机而赢。", "#olfengji2": "此退彼进,月亏待盈。", + "#olxuanhui1": "今日,怕是要辜负温侯美意了。", + "#olxuanhui2": "前盖以惑敌,今图穷而匕现。", "#ol_chendeng:die": "可无命,不可无脍……", "#jixian1": "全军出击,速攻敌城。", "#jixian2": "勿以我为念,攻城!", @@ -687,11 +701,11 @@ export default { "#tiandu_xizhicai1": "既是如此。", "#tiandu_xizhicai2": "天意,不可逆。", "#xianfu1": "辅佐明君,从一而终。", - "#xianfu2": "愿为主公,尽我所能。", + "#xianfu2": "吾于此生,竭尽所能。", "#xianfu3": "赠人玫瑰,手有余香。", - "#xianfu4": "吾于此生,竭尽所能。", + "#xianfu4": "主公之幸,我之幸也。", "#xianfu5": "春蚕至死,蜡炬成灰!", - "#xianfu6": "主公之幸,我之幸也。", + "#xianfu6": "愿为主公,尽我所能。", "#chouce1": "一筹一划,一策一略。", "#chouce2": "主公之忧,吾之所思也。", "#xizhicai:die": "为何……不再给我……一点点时间……", @@ -781,4 +795,62 @@ export default { "#olqingya1": "罡风从虎,威震四方!", "#olqingya2": "铁车过处,寸草不生!", "#yadan:die": "多谢丞相不杀之恩……", + "#xinfu_sanwen1": "文若春华,思若泉涌。", + "#xinfu_sanwen2": "独步汉南,散文天下。", + "#xinfu_qiai1": "未知身死处,何能两相完?", + "#xinfu_qiai2": "悟彼下泉人,喟然伤心肝。", + "#xinfu_denglou1": "登兹楼以四望兮,聊暇日以销忧。", + "#xinfu_denglou2": "惟日月之逾迈兮,俟河清其未极。", + "#wangcan:die": "一作驴鸣悲,万古送葬别……", + "#xinfu_jixu1": "击虚箭射,懈敌戒备。", + "#xinfu_jixu2": "虚实难辨,方迷敌方之心!", + "#sp_taishici:die": "刘繇之见,短浅也……", + "#xinfu_guolun1": "品过是非,讨评好坏。", + "#xinfu_guolun2": "若有天下太平时,必讨四海之内才。", + "#xinfu_songsang1": "送丧至东吴,使命已完。", + "#xinfu_songsang2": "送丧虽至,吾与孝则得相交。", + "#re_jsp_pangtong:die": "我终究……不得东吴赏识……", + "#qinguo_use1": "为国勤事,体素精勤。", + "#qinguo_use2": "忠勤为国,通达治体。", + "#lvdai:die": "再也不能,为吴国奉身了……", + "#xinfu_jijun1": "集万千义军,定天下大局!", + "#xinfu_jijun2": "集民力万千,亦可为军!", + "#xinfu_fangtong1": "统领方队,为民意所举!", + "#xinfu_fangtong2": "三十六方,必为大统!", + "#re_zhangliang:die": "人公也难逃被人所杀……", + "#xinfu_weilu1": "贼人势大,需从长计议。", + "#xinfu_weilu2": "时机未到,先行撤退。", + "#xinfu_zengdao1": "有功赏之,有过罚之。", + "#xinfu_zengdao2": "治军之道,功过分明。", + "#lvqian:die": "我自泰山郡以来,百姓获安,镇军伐贼,此生已无憾!", + "#xinfu_guanwei1": "今日宴请诸位,有要事相商。", + "#xinfu_guanwei2": "天下未定,请主公以大局为重。", + "#xinfu_gongqing1": "尔辈何故与降虏交善。", + "#xinfu_gongqing2": "豪将在外,增兵必成祸患啊!", + "#panjun:die": "耻失荆州,耻失荆州啊!", + "#xinfu_andong1": "勇足以当大难,智涌以安万变。", + "#xinfu_andong2": "宽猛克济,方安河东之民。", + "#xinfu_yingshi1": "应民之声,势民之根。", + "#xinfu_yingshi2": "应势而谋,顺民而为。", + "#duji:die": "试船而溺之,虽亡而忠至……", + "#xinfu_duanfa1": "身体发肤,受之父母。", + "#xinfu_duanfa2": "今断发以明志,尚不可证吾之心意?", + "#xinfu_youdi1": "东吴已容不下我,愿降以保周全。", + "#xinfu_youdi2": "笺书七条,足以表我归降之心。", + "#zhoufang:die": "功亏一篑,功亏一篑啊……", + "#xinfu_guanchao1": "朝夕之间,可知所进退。", + "#xinfu_guanchao2": "月盈,潮起晨暮也;月亏,潮起日半也。", + "#xinfu_xunxian1": "督军之才,子明强于我甚多。", + "#xinfu_xunxian2": "此间重任,公卿可担之。", + "#yanjun:die": "著作,还……没完成……", + "#xinfu_kannan1": "俊才之杰,材匪戡难。", + "#xinfu_kannan2": "戡,克也,难,攻之。", + "#liuyao:die": "伯符小儿,还我子义!", + "#xinfu_tushe1": "非英杰不图?吾既谋之且射毕!", + "#xinfu_tushe2": "汉室衰微,朝纲祸乱,必图后福。", + "#xinfu_limu1": "米贼作乱,吾必为益州自保。", + "#xinfu_limu2": "废史立牧,可得一方安定。", + "#liuyan:die": "背疮难治,世子难继……", + "#xinfu_zhanji1": "公瑾安全至吴,心安之。", + "#xinfu_zhanji2": "功曹之恩,吾必有展骥之机。", }; diff --git a/character/sp2/character.js b/character/sp2/character.js index 2c46de53eb..a1360fa3a0 100644 --- a/character/sp2/character.js +++ b/character/sp2/character.js @@ -1,5 +1,4 @@ const characters = { - mp_wangrong: ["male", "wei", 3, ["mpjianlin", "mpsixiao"]], matie: ["male", "qun", 4, ["dczhuiwang", "dcquxian"]], hansong: ["male", "qun", 3, ["dcyinbi", "dcshuaiyan"]], chezhou: ["male", "wei", 4, ["dcshefu", "dcpigua"]], @@ -12,7 +11,6 @@ const characters = { star_yuanshu: ["male", "qun", 4, ["starcanxi", "starpizhi", "starzhonggu"], ["zhu"]], star_caoren: ["male", "wei", 4, ["starsujun", "starlifeng"]], star_sunshangxiang: ["female", "wu", 3, ["starsaying", "starjiaohao"]], - mp_liuling: ["male", "jin", 3, ["mpjiusong", "mpmaotao", "mpbishi"], ["doublegroup:wei:qun:jin"]], dc_jikang: ["male", "wei", 3, ["new_qingxian", "dcjuexiang"]], dc_jsp_guanyu: ["male", "wei", 4, ["new_rewusheng", "dcdanji"]], dc_mengda: ["male", "wei", 4, ["dclibang", "dcwujie"]], @@ -95,8 +93,14 @@ const characters = { xunchen: ["male", "qun", 3, ["fenglve", "mouzhi"], ["clan:颍川荀氏"]], sp_zhanghe: ["male", "qun", 4, ["yuanlve"]], sp_xuyou: ["male", "qun", 3, ["spshicai", "spfushi"]], - chunyuqiong: ["male", "qun", 5, ["cangchu", "sushou", "liangying"]], + chunyuqiong: ["male", "qun", 5, ["cangchu", "sushou", "liangying"], ["name:淳于|琼"]], lvkuanglvxiang: ["male", "qun", 4, ["liehou", "qigong"], ["name:吕|旷-吕|翔"]], + + duji: ["male", "wei", 3, ["xinfu_andong", "xinfu_yingshi"]], + liuyao: ["male", "qun", 4, ["xinfu_kannan", "twniju"], ["zhu"]], + lvdai: ["male", "wu", 4, ["xinfu_qinguo"]], + sp_taishici: ["male", "qun", 4, ["xinfu_jixu"], ["name:太史|慈"]], + re_zhangliang: ["male", "qun", 4, ["xinfu_jijun", "xinfu_fangtong"]], }; export default characters; diff --git a/character/sp2/characterReplace.js b/character/sp2/characterReplace.js index 8a8538a256..d625ef2c49 100644 --- a/character/sp2/characterReplace.js +++ b/character/sp2/characterReplace.js @@ -7,7 +7,7 @@ const characterReplaces = { dingyuan: ["ol_dingyuan", "dingyuan"], quyi: ["quyi", "re_quyi"], hansui: ["hansui", "re_hansui", "xin_hansui", "jsrg_hansui"], - jin_simashi: ["dc_simashi", "jin_simashi", "simashi"], + jin_simashi: ["dc_simashi", "jin_simashi", "simashi", "std_simashi", "jd_jin_simashi"], jin_yanghuiyu: ["jin_yanghuiyu", "yanghuiyu"], taoqian: ["re_taoqian", "taoqian"], jsp_liubei: ["jsrg_liubei", "jsp_liubei"], @@ -26,15 +26,16 @@ const characterReplaces = { caoanmin: ["caoanmin", "ns_caoanmin"], duanwei: ["duanwei", "junk_duanwei"], xushao: ["xushao", "jsrg_xushao"], - huban: ["ol_huban", "dc_huban", "mb_huban"], - mengda: ["ol_mengda", "dc_mengda", "pe_mengda"], + ol_huban: ["ol_huban", "dc_huban", "mb_huban"], + ol_mengda: ["ol_mengda", "dc_mengda", "pe_mengda"], jsp_guanyu: ["jsp_guanyu", "dc_jsp_guanyu", "jsrg_guanyu"], mushun: ["mushun", "sp_mushun"], wangjun: ["dc_wangjun", "wangjun"], re_zoushi: ["yue_zoushi", "re_zoushi", "jsrg_zoushi"], - zhangmancheng: ["dc_zhangmancheng", "tw_zhangmancheng"], + dc_zhangmancheng: ["dc_zhangmancheng", "tw_zhangmancheng"], xf_huangquan: ["xf_huangquan", "dc_huangquan"], re_zoushi: ["re_zoushi", "jsrg_zoushi", "yue_zoushi"], + lvkuanglvxiang: ["lvkuanglvxiang", "dc_lvkuanglvxiang"], }; export default characterReplaces; diff --git a/character/sp2/intro.js b/character/sp2/intro.js index b3022764b0..92de375136 100644 --- a/character/sp2/intro.js +++ b/character/sp2/intro.js @@ -64,11 +64,9 @@ const characterIntro = { guānning: "关宁,《三国演义》的虚构人物,为关定之子,关平的哥哥,学文。关羽前往冀州寻找刘备时曾居于关定庄,关定命关宁、关平二子出拜。后关羽同刘备回到关定庄时,关羽向刘备介绍关宁、关平二人,关定即提出让关平拜关羽为义父。", mushun: "穆顺,小说《三国演义》中的人物,男,东汉末宦官。献帝欲修书与国舅伏完,共谋图曹公。因顺为宦官中之忠义可托者,乃命顺往送书。顺藏书于发中,潜出禁宫,径至完宅,将书呈上。及完回书付顺,顺乃藏于头髻内,辞完回宫。然公闻信,先于宫门等候,顺回遇公,公喝左右,遍搜身上,并无夹带,放行。忽然风吹落其帽。公又唤回,取帽视之,遍观无物,还帽令戴。顺双手倒戴其帽。公心疑,令左右搜其头发中,搜出伏完书来。公见书大怒,执下顺于密室问之,顺不肯招。当晚将顺、完等宗族二百余口,皆斩于市。", jsp_guanyu: "关羽,字云长。曾水淹七军、擒于禁、斩庞德、威震华夏,吓得曹操差点迁都躲避,但是东吴偷袭荆州,关羽兵败被害。后传说吕蒙因关羽之魂索命而死。", - liuling: "刘伶(约221年-约300年),字伯伦,西晋沛国(治今安徽濉溪县西北)人,竹林七贤之一,中国魏晋时期作家,名士。
    刘伶自幼便失去了父爱,因其父亲身材矮小,及至长大成人后,刘伶身高也不过六尺。魏齐王曹芳正始之末(249年),刘伶已成为当世名重一时的名士,并且常与嵇康、阮籍、阮咸集会于山阳竹林之下,饮酒赋诗,弹琴作歌。晋武帝司马炎泰始初年(265年)前后,曾做过一段时间的建威参军,不久朝廷下诏,入宫中策问。他大谈老庄,强调无为而治,非但没有得到重用,反而连参军之职也被罢免了,从此再无仕进。晋惠帝司马衷永康元年(300年)前后,以寿而终。
    刘伶有“品酒第一人”的美称,也被酒行业传颂至今,后人以古瀑河边上的井水酿酒,还取刘伶墓地的黄土垒成窖池酿酒,为了纪念刘伶,当地百姓也将“润泉涌”更名为“刘伶醉”。其传世作品仅有《酒德颂》《北芒客舍》两篇,其中《酒德颂》所表现出的藐视一切存在的气概,敌视礼教之士的反抗精神,既高扬了人格的力量,批判了当时的黑暗政治,同时也抒发了压抑的愤世之情,充满了浪漫色彩,气魄豪迈,用辞又骈偶间行,有无意追求而自至的特点,对后代影响极大。", chezhou: "车胄(?-199年至200年),东汉末年武将,为曹操所置徐州刺史。建安四年,左将军刘备率军出征,前往下邳,于同年或次年杀死车胄。", hansong: "韩嵩(生卒年不详),字德高,南阳人。少好学,贫不改操。不应三公辟命,与同好数人隐居郦西山中。后担任刘表手下的别驾,转为从事中郎。出使许都,被拜为侍中,迁零陵太守。建安十三年(208年),韩嵩与蒯越、傅巽劝刘琮降曹。曹操平定荆州后,拜韩嵩为大鸿胪。", matie: "马铁(?-212年),扶风茂陵(今陕西兴平)人。马腾之子,马超之弟。马腾遭韩遂进攻,乃携马铁等入京受职。马铁被封为骑都尉。后在邺城居住。因其兄马超反曹而被曹操夷灭。", - mp_wangrong: "王戎(234年-305年7月11日),字濬冲。琅玡郡临沂县(今山东省临沂市白沙埠镇诸葛村)人。祖父为三国魏幽州刺史王雄,曹魏凉州刺史王浑的儿子。三国至西晋时期名士、官员,“竹林七贤”之一。
    王戎出身琅玡王氏。自少神采秀美,长于清谈,以精辟的品评与识鉴而著称,以聪颖知名,为父辈好友、名士阮籍器重,后人视之为玄学名士。初袭父爵贞陵亭侯,被大将军司马昭辟为掾属。累官豫州刺史、建威将军,参与晋灭吴之战。战后以功进封安丰县侯,故人称“王安丰”。治理荆州时,他拉拢士人,颇有成效。后历任侍中、光禄勋、吏部尚书、太子太傅、中书令、尚书左仆射等职。元康七年(296年),升任司徒,位列三公。王戎认为天下将乱,于是不理世事,以山水游玩为乐。赵王司马伦发动政变时,王戎被牵连免官。之后被起用为尚书令,再迁司徒。右将军张方劫持晋惠帝入长安后,王戎逃奔郏县。
    永兴二年(305年),王戎去世,时年七十二,谥号为“元”。", }; export default characterIntro; diff --git a/character/sp2/skill.js b/character/sp2/skill.js index b85f022760..4106d270a7 100644 --- a/character/sp2/skill.js +++ b/character/sp2/skill.js @@ -2,190 +2,6 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { - //王戎 - mpjianlin: { - audio: 2, - trigger: { - global: "phaseAfter", - }, - getCards(player) { - const cards = []; - game.checkGlobalHistory("cardMove", evt => { - if (evt.name == "lose") { - if (evt.position !== ui.discardPile) return false; - } else if (evt.name !== "cardsDiscard") return false; - if (get.info("mpjianlin").isUseOrRespond(evt, player)) { - cards.addArray( - evt.cards.filter(card => { - return get.type(card) == "basic" && get.position(card) === "d"; - }) - ); - } - }); - player.checkHistory("lose", evt => { - if (evt.type == "discard") { - cards.addArray( - evt.cards2.filter(card => { - return get.type(card) == "basic" && get.position(card) === "d"; - }) - ); - } - }); - return cards; - }, - isUseOrRespond(event, player) { - if (event.name !== "cardsDiscard") return false; - const evtx = event.getParent(); - if (evtx.name !== "orderingDiscard") return false; - const evt2 = evtx.relatedEvent || evtx.getParent(); - return ["useCard", "respond"].includes(evt2.name) && evt2.player == player; - }, - filter(event, player) { - return get.info("mpjianlin").getCards(player).length; - }, - async cost(event, trigger, player) { - const cards = get.info("mpjianlin").getCards(player); - const { - result: { bool, links }, - } = await player.chooseButton(["悭吝:你可以获得其中一张牌", cards]).set("ai", get.buttonValue); - event.result = { - bool: bool, - cost_data: links, - }; - }, - async content(event, trigger, player) { - player.gain(event.cost_data, "gain2"); - }, - }, - mpsixiao: { - audio: 2, - trigger: { - global: "phaseBefore", - player: "enterGame", - }, - locked: true, - filter(event, player) { - return (event.name != "phase" || game.phaseNumber == 0) && game.hasPlayer(current => current != player); - }, - async cost(event, trigger, player) { - event.result = await player - .chooseTarget(true, lib.filter.notMe, "死孝:请选择一名角色当其孝子", "当该角色需要使用或打出除【无懈可击】外的牌时,其可以观看你的手牌并可以使用或打出其中一张牌,然后你摸一张牌") - .set("ai", target => { - return get.attitude(get.player(), target); - }) - .forResult(); - }, - async content(event, trigger, player) { - const target = event.targets[0]; - game.log(player, "成为了", target, "的孝子"); - target.storage.mpsixiao_use = player; - target.addSkill("mpsixiao_use"); - }, - subSkill: { - use: { - charlotte: true, - mark: "character", - intro: { - content: "当你需要使用或打出除【无懈可击】外的牌时,你可以观看$的手牌并可以使用或打出其中一张牌,然后$摸一张牌", - }, - hiddenCard(player, name) { - if (name == "wuxie" || !lib.inpile.includes(name) || player.hasSkill("mpsixiao_used", null, null, false)) return false; - const target = player.storage.mpsixiao_use; - const cards = target.getCards("h"); - for (var i of cards) { - if (get.name(i, target) == name) return true; - } - return false; - }, - enable: ["chooseToUse", "chooseToRespond"], - filter(event, player) { - const target = player.storage.mpsixiao_use; - const cards = target.getCards("h"); - if (player.hasSkill("mpsixiao_used", null, null, false)) return false; - return cards.some(i => - event.filterCard( - { - name: get.name(i, target), - nature: get.nature(i, target), - isCard: true, - }, - player, - event - ) - ); - }, - chooseButton: { - dialog(event, player) { - const target = player.storage.mpsixiao_use; - const cards = target.getCards("h"); - return ui.create.dialog("死孝", cards); - }, - filter(button, player) { - const evt = _status.event.getParent(); - const target = player.storage.mpsixiao_use; - return evt.filterCard( - { - name: get.name(button.link, target), - nature: get.nature(button.link, target), - isCard: true, - }, - player, - evt - ); - }, - check(button) { - const player = get.player(); - const evt = _status.event.getParent(); - if (evt.dying) return get.attitude(player, evt.dying); - if (_status.event.getParent().type != "phase") return 1; - return player.getUseValue(get.autoViewAs(button.link), null, true); - }, - backup(links, player) { - const target = player.storage.mpsixiao_use; - return { - viewAs: { - name: get.name(links[0], target), - nature: get.nature(links[0], target), - isCard: true, - }, - card: links[0], - filterCard: () => false, - selectCard: -1, - log: false, - async precontent(event, trigger, player) { - const card = lib.skill.mpsixiao_use_backup.card, - target = player.storage.mpsixiao_use; - event.result.card = card; - event.result.cards = [card]; - player.addTempSkill("mpsixiao_used"); - target - .when({ global: ["useCard", "respond"] }) - .filter(evt => evt.player == player && evt.skill == "mpsixiao_use_backup") - .then(() => { - player.draw(); - }); - }, - }; - }, - ai: { - hasSha: true, - hasShan: true, - skillTagFilter(player, tag) { - const name = "s" + tag.slice(4); - return lib.skill.mpsixiao_use.hiddenCard(player, name); - }, - }, - }, - ai: { - order: 8, - result: { - player: 1, - }, - }, - }, - used: {}, - }, - }, //马铁 dczhuiwang: { mod: { @@ -308,7 +124,7 @@ const skills = { source: "damageBegin1", }, filter(event, player) { - if (!event.source || event.source == event.player) return false; + if (!event.source || event.source == event.player || !event.cards || !event.cards.length) return false; const evt = event.getParent(2); return evt && evt.name == "useCard"; }, @@ -557,7 +373,7 @@ const skills = { }) ) return false; - return (event.targets || []).some(target => target !== player && target.isIn()); + return event.isFirstTarget && (event.targets || []).some(target => target !== player && target.isIn()); }, locked: false, async cost(event, trigger, player) { @@ -839,7 +655,7 @@ const skills = { if (!logged) next.set("logSkill", "starminghui"); const result = await next.forResult(); if (!result.bool) return; - if (!player.isUnderControl(true) && !player.isOnline()) await game.asyncDelayx(); + if (!player.isUnderControl(true) && !player.isOnline()) await game.delayx(); const [bool, targets] = await player .chooseTarget("令一名角色回复1点体力") .set("ai", target => get.recoverEffect(target, get.player(), get.player())) @@ -899,7 +715,7 @@ const skills = { enable: "phaseUse", filter(event, player) { const cards = player.getCards("h", card => { - const type = get.type(card, player); + const type = get.type(card, null, player); if (type != "basic" && type != "trick") return false; return ( lib.filter.cardUsable(card, player) && @@ -917,7 +733,7 @@ const skills = { filterCard(card, player) { if (ui.selected.cards.length) return false; const cards = player.getCards("h", card => { - const type = get.type(card, player); + const type = get.type(card, null, player); if (type != "basic" && type != "trick") return false; return ( lib.filter.cardUsable(card, player) && @@ -1438,7 +1254,7 @@ const skills = { }, ai: { effect: { - player_use(card, player, target) { + player(card, player, target) { var targets = game.filterPlayer(targetx => targetx != player && targetx.getStorage("starcanxi_xiangsi").includes(player.group)); if (!targets.length) return; if (get.tag(card, "recover") && target == player && target.hp > 2) return 0; @@ -1749,8 +1565,9 @@ const skills = { if (!game.hasPlayer(current => { return result.winner.canUse({ name: 'sha' }, current, false) && get.effect(current, { name: 'sha' }, result.winner, result.winner) > 0; })) return '选项一'; - const eff1 = result.winner.getUseValue({ name: 'sha' }); - const eff2 = (get.value(cards[0], result.winner) + get.value(cards[1], result.winner)); + let eff1 = result.winner.getUseValue({ name: 'sha' }), eff2 = 0; + if (cards[0]) eff2 = get.value(cards[0], result.winner); + if (cards[1]) eff2 += get.value(cards[1], result.winner); if (eff1 > eff2 * 2.5) return '选项二'; return '选项一'; }()).forResult(); @@ -1787,128 +1604,6 @@ const skills = { }, }, }, - //小程序刘伶 - mpjiusong: { - audio: 2, - enable: "chooseToUse", - trigger: { global: "useCard" }, - filterCard: function (card) { - return get.type2(card) == "trick"; - }, - viewAs: { name: "jiu" }, - position: "hs", - viewAsFilter: function (player) { - return player.hasCard(card => get.type2(card) == "trick", "hs"); - }, - check: function (card) { - if (get.itemtype(card) !== "card") return true; - if (get.event().type == "dying") return 1 / Math.max(0.1, get.value(card)); - return 4 - get.value(card); - }, - prompt: "将一张锦囊牌当【酒】使用", - filter: function (event, player) { - if (event.name == "chooseToUse") return player.hasCard(card => get.type2(card) == "trick", "hs"); - return event.card.name == "jiu" && player.countMark("mpjiusong") < 3; - }, - forced: true, - locked: false, - content: function () { - player.addMark("mpjiusong"); - }, - marktext: "醉", - intro: { - name: "醉(酒颂/酕醄)", - name2: "醉", - content: "mark", - }, - }, - mpmaotao: { - audio: 2, - trigger: { global: "useCardToPlayer" }, - filter: function (event, player) { - if (event.targets.length != 1 || !event.isFirstTarget) return false; - if (!["basic", "trick"].includes(get.type(event.card))) return false; - return event.player != player && player.countMark("mpjiusong"); - }, - prompt2: function (event, player) { - let list; - if (get.type(event.card) != "delay") - list = game.filterPlayer(current => { - return lib.filter.targetEnabled2(event.card, event.player, current); - }); - else list = game.filterPlayer(current => current.canAddJudge(event.card)); - const gainText = `${list.length > 1 && !player.storage.mpmaotao_gained ? `若新目标与原目标相同,你` : ""}${!player.storage.mpmaotao_gained ? "获得牌堆中的一张锦囊牌。" : ""}`; - return `移去1枚“醉”${list.length > 1 ? `,令${get.translation(event.card)}目标改为${get.translation(list)}中的一名随机角色` : ""}。${gainText}`; - }, - check: function (event, player) { - const eff = get.effect(event.target, event.card, player, player); - let list; - if (get.type(event.card) != "delay") - list = game.filterPlayer(current => { - return lib.filter.targetEnabled2(event.card, event.player, current); - }); - else list = game.filterPlayer(current => current.canAddJudge(event.card)); - let list2 = list.filter(current => get.effect(current, event.card, player, player) > eff); - let list3 = list.filter(current => get.effect(current, event.card, player, player) > 0); - return list2.length >= list.length / 2 || (player.countMark("mpjiusong") >= 2 && list3.length >= list.length / 2); - }, - content: function () { - player.removeMark("mpjiusong", 1); - var list, - oriTarget = trigger.target; - trigger.targets.remove(oriTarget); - trigger.getParent().triggeredTargets1.remove(oriTarget); - trigger.untrigger(); - game.delayx(); - if (get.type(trigger.card) != "delay") - list = game.filterPlayer(current => { - return lib.filter.targetEnabled2(trigger.card, trigger.player, current); - }); - else list = game.filterPlayer(current => current.canAddJudge(trigger.card)); - if (list.length) target = list.randomGet(); - trigger.targets.push(target); - trigger.player.line(target, "thunder"); - game.log(trigger.card, "的目标被改为", target); - if (target == oriTarget && !player.storage.mpmaotao_gained) { - var card = get.cardPile2(card => get.type2(card) == "trick"); - if (card) { - if (!player.storage.mpmaotao_gained) { - player.when({ global: "phaseAfter" }).then(() => { - delete player.storage.mpmaotao_gained; - }); - player.storage.mpmaotao_gained = true; - } - player.gain(card, "gain2"); - } else { - // player.chat('没酒了!'); - // game.log('但是牌堆中已经没有','#y酒','了!'); - player.chat("没牌了!"); - game.log("但是牌堆中已经没有", "#y锦囊牌", "了!"); - } - } - }, - ai: { - combo: "mpjiusong", - }, - }, - mpbishi: { - audio: 2, - forced: true, - trigger: { global: "useCard1" }, - filter: function (event, player) { - if (get.type2(event.card) != "trick" || !get.tag(event.card, "damage")) return false; - if (!lib.skill.xunshi.isXunshi(event.card)) return false; - const targets = event.targets.slice(); - targets.remove(event.player); - return targets.length == game.countPlayer() - 2; - }, - content: function* () {}, - mod: { - targetEnabled: function (card) { - if (get.type2(card) == "trick" && get.tag(card, "damage") > 0) return false; - }, - }, - }, //十周年嵇康 dcjuexiang: { derivation: "dccanyun", @@ -2682,20 +2377,54 @@ const skills = { }, "he"); }); }, + getSkills(skills, len) { + skills = skills.filter(skill => { + let str = get.skillInfoTranslation(skill, get.event().player); + if (str.indexOf("当你于出牌阶段") != -1) return true; + let ss = game.expandSkills([skill]); + if (ss.some(skillx => { + let info = get.info(skillx); + if (!info || !info.enable) return false; + if ( + info.enable != "phaseUse" && + info.enable != "chooseToUse" && + ( + !Array.isArray(info.enable) || + !info.enable.includes("phaseUse") && + !info.enable.includes("chooseToUse") + ) + ) return false; + if (info.juexingji || info.hiddenSkill || info.charlotte || info.limited || info.dutySkill) return false; + if (info.ai && info.ai.notemp) return false; + return true; + })) return true; + return false; + }); + if (len && !skills.length) { + if (!_status.characterlist) lib.skill.pingjian.initList(); + let allList = _status.characterlist.slice(0); + allList.randomSort(); + for (const name of allList) { + const curSkills = lib.character[name][3]; + const filteredSkills = lib.skill.longsong.getSkills(curSkills); + if (filteredSkills.length > 0) return filteredSkills.randomGets(1); + } + } + return skills; + }, async cost(event, trigger, player) { event.result = await player .chooseCardTarget({ prompt: get.prompt2("longsong"), filterTarget(card, player, target) { if (target === player) return false; - const skills = lib.skill.dclongsong.getSkills(target).map(skill => get.translation(skill)); + const skills = lib.skill.longsong.getSkills(target.getSkills(null, false)).map(skill => get.translation(skill)); if (skills.length) { target.prompt(skills.join("
    ")); } return ( ui.selected.cards.length || target.hasCard(card => { - if (get.position(card) == "h") return true; return get.color(card) == "red" && lib.filter.canBeGained(card, player, target); }, "he") ); @@ -2718,7 +2447,7 @@ const skills = { const player = get.event("player"), att = get.attitude(player, target); if (att > 0 && !target.getGainableCards(player, "he").some(card => get.color(card) == "red")) return 0; - return lib.skill.dclongsong.getSkills(target).length + (att > 0 ? 0 : Math.max(0, get.effect(target, { name: "shunshou_copy2" }, player, player))); + return lib.skill.longsong.getSkills(target.getSkills(null, false)).length + (att > 0 ? 0 : Math.max(0, get.effect(target, { name: "shunshou_copy2" }, player, player))); }, }) .forResult(); @@ -2758,43 +2487,28 @@ const skills = { game.log("但是", target, "没有红色牌可被" + get.translation(player) + "获得!"); } } - let skills = lib.skill.dclongsong.getSkills(target), - fromTarget = true; - if (!skills.length) { - if (!_status.characterlist) { - lib.skill.pingjian.initList(); - } - const allList = _status.characterlist.slice(0); - allList.randomSort(); - for (const name of allList) { - const curSkills = lib.character[name][3]; - const filteredSkills = lib.skill.dclongsong.getSkills(null, curSkills); - if (filteredSkills.length > 0) { - skills = filteredSkills.randomGets(1); - fromTarget = false; - break; - } - } - } + let skills = lib.skill.longsong.getSkills(target.getSkills(null, false), true); + if (!event.isMine() && !event.isOnline()) await game.delayx(); if (!skills.length) return; - if (!event.isMine() && !event.isOnline()) await game.asyncDelayx(); - skills.forEach(skill => { - player.popup(skill, "thunder"); - }); - if (fromTarget) { - target.disableSkill("dclongsong_back", skills); - target.markAuto("dclongsong_back", skills); - target.addTempSkill("dclongsong_back", ["phaseUseAfter", "phaseAfter"]); - let str = ""; - for (let i = 0; i < skills.length; i++) { - str += "【" + get.translation(skills[i]) + "】"; - if (i != skills.length - 1) str += "、"; - } - game.log(target, "的技能", "#g" + str, "失效了"); - } + let skill; + if (skills.length == 1) skill = skills[0]; + else skill = await player.chooseControl(skill) + .set('choiceList', skills.map(i => { + return '
    ' + (lib.translate[i + '_ab'] || lib.translate[i]) + '
    ' + get.skillInfoTranslation(i, player) + '
    '; + })) + .set("displayIndex", false) + .set("prompt", "龙诵:请选择你要获得的技能") + .set("ai", () => { + var list = _status.event.controls.slice(); + return list.sort((a, b) => { + return get.skillRank(b, "in") - get.skillRank(a, "in"); + })[0]; + }) + .forResultControl(); + player.popup(skill, "thunder"); player.addTempSkill("dclongsong_remove", ["phaseUseAfter", "phaseAfter"]); - player.markAuto("dclongsong_remove", skills); - await player.addTempSkills(skills, ["phaseUseAfter", "phaseAfter"]); + player.markAuto("dclongsong_remove", [skill]); + await player.addTempSkills(skill, ["phaseUseAfter", "phaseAfter"]); }, }, //伏完 @@ -3380,7 +3094,7 @@ const skills = { }, ai: { effect: { - player: function (card, player, target) { + player_use: function (card, player, target) { if (card.name != "juedou") return; if ( player.hasSkillTag( @@ -3847,7 +3561,7 @@ const skills = { game.addGlobalSkill("dcchongyi_ai"); }, onremove: () => { - if (!game.hasPlayer(i => i.hasSkill("dcchongyi"), true)) game.removeGlobalSkill("dcchongyi_ai"); + if (!game.hasPlayer(i => i.hasSkill("dcchongyi", null, null, false), true)) game.removeGlobalSkill("dcchongyi_ai"); }, trigger: { global: "useCard" }, logTarget: "player", @@ -3897,7 +3611,7 @@ const skills = { }, trigger: { player: "dieAfter" }, filter: () => { - return !game.hasPlayer(i => i.hasSkill("dcchongyi"), true); + return !game.hasPlayer(i => i.hasSkill("dcchongyi", null, null, false), true); }, silent: true, forceDie: true, @@ -3941,7 +3655,7 @@ const skills = { const evt = history.lastItem, cards = evt.cards.filterInD("d"); if (cards.length) await player.gain(cards, "gain2"); - else await game.asyncDelayx(); + else await game.delayx(); }, }, sha: { @@ -4368,9 +4082,6 @@ const skills = { trigger: { player: "useCard" }, forced: true, zhuanhuanji: true, - filter: function (event, player) { - return !player.hasSkill("piaoping_blocker", null, null, false); - }, content: function () { player.changeZhuanhuanji("piaoping"); var num = Math.min( @@ -4398,7 +4109,6 @@ const skills = { return "转换技,锁定技。当你使用一张牌时,你摸X张牌。(X为你本阶段内发动过〖漂萍〗的次数且至多等于你的体力值)"; }, }, - subSkill: { blocker: { charlotte: true } }, }, tuoxian: { audio: 2, @@ -4457,7 +4167,7 @@ const skills = { if (result.index == 0) { if (target.countCards("j") > 0) target.discardPlayerCard(target, cards.length, true, "hej"); else target.chooseToDiscard("he", true, cards.length); - } else player.addTempSkill("piaoping_blocker"); + } else player.tempBanSkill("piaoping"); }, init(player) { player.addMark("tuoxian", 1, false); @@ -4471,19 +4181,18 @@ const skills = { filter: function (event, player) { if (player == event.player || get.color(event.card) != "black") return false; if (!player.hasSkill("piaoping", null, null, false)) return false; - return player.storage.piaoping == true || !player.hasSkill("chuaili_blocker", null, null, false); + return player.storage.piaoping == true; }, content: function () { if (player.storage.piaoping == true) { player.changeZhuanhuanji("piaoping"); } else { player.addMark("tuoxian", 1, false); - if (player.countCards("tuoxian") > 3) player.addTempSkill("chuaili_blocker"); + if (player.countCards("tuoxian") > 3) player.tempBanSkill("chuaili"); } game.delayx(); }, ai: { combo: "piaoping" }, - subSkill: { blocker: { charlotte: true } }, }, //闫柔 choutao: { @@ -4730,7 +4439,7 @@ const skills = { trigger: { source: ["damageBegin1", "recoverBegin"] }, filter: function (event, player) { var evt = event.getParent(); - return evt.type == "card" && get.type(evt.card, false) == "basic"; + return evt.type == "card" && get.type(evt.card, null, false) == "basic"; }, forced: true, logTarget: "player", @@ -4856,7 +4565,7 @@ const skills = { if (typeof numz == "number") num2 += numz; }); if (num > num2) { - var hs = target.getCards("he", function (card) { + var hs = target.getCards("h", function (card) { return lib.filter.cardDiscardable(card, target, "yijiao_effect"); }); if (hs.length) target.discard(hs.randomGets(get.rand(1, 3))); @@ -4921,6 +4630,7 @@ const skills = { content: function () { "step 0"; player.give(cards, target); + player.addTempSkill("channi_effect"); "step 1"; if (target.countCards("h") > 0) { game.broadcastAll(function (num) { @@ -4933,37 +4643,39 @@ const skills = { next.set("_backupevent", "channi_backup"); next.set("custom", { add: {}, - replace: { window: function () {} }, + replace: { window: function () { } }, }); next.backup("channi_backup"); - } else event.finish(); + } "step 2"; - if (result.bool) { - var evts = target.getHistory("useCard", function (evt) { - return evt.card.name == "juedou" && evt.getParent(2) == event; - }); - if (!evts.length) { - event.finish(); - return; - } - var num = evts[0].cards.length; - if ( - target.hasHistory("sourceDamage", function (evt) { - return evt.card && evt.card.name == "juedou" && evt.getParent(4) == event; - }) - ) - target.draw(num); - } else event.finish(); - "step 3"; - if ( - player.countCards("h") > 0 && - target.hasHistory("damage", function (evt) { - return evt.card && evt.card.name == "juedou" && evt.getParent(4) == event; - }) - ) - player.chooseToDiscard("h", true, player.countCards("h")); + player.removeSkill("channi_effect"); }, subSkill: { + effect: { + trigger: { + global: ["damageSource", "damageEnd"], + }, + filter(event, player, name) { + if (!event.card || event.card.name != "juedou") return false; + let evt = event.getParent(2); + if (!evt || evt.name != "useCard" || evt.card.name != "juedou") return false; + let user = evt.player; + let evtx = event.getParent("channi", true); + if (!evtx || evtx.player != player) return false; + if (name == "damageSource") return event.source == user && evt.cards.length; + return event.player == user && player.countCards("h"); + }, + forced: true, + charlotte: true, + logTarget(event, player, name) { + return event[name == "damageSource" ? "source" : "player"]; + }, + content() { + let evt = trigger.getParent(2); + if (event.triggername == "damageSource") evt.player.draw(evt.cards.length); + else player.chooseToDiscard("h", true, player.countCards("h")); + }, + }, backup: { filterCard: function (card) { return get.itemtype(card) == "card"; @@ -5067,21 +4779,31 @@ const skills = { }, subSkill: { effect: { - trigger: { player: "useCardAfter" }, - forced: true, charlotte: true, + trigger: { player: "useCardAfter" }, filter: function (event, player) { - return ( - player.maxHp > 1 && - event.skill == "xiongmang" && - !player.hasHistory("sourceDamage", function (evt) { - return evt.card == event.card; - }) - ); + return event.skill == "xiongmang"; }, + forced: true, + popup: false, content: function () { - player.loseMaxHp(); + if (!game.getGlobalHistory("changeHp", evt => evt.getParent().name == 'damage' && evt.getParent().card && evt.getParent().card == trigger.card).length) { + player.loseMaxHp(); + } else { + player.addTempSkill("xiongmang_more", ["phaseChange", "phaseAfter"]); + player.addMark("xiongmang_more", 1, false); + } + }, + }, + more: { + charlotte: true, + onremove: true, + mod: { + cardUsable(card, player, num) { + if (card.name == "sha") return num + player.countMark("xiongmang_more"); + }, }, + intro: { content: "使用【杀】的额定次数+#" }, }, }, }, @@ -5468,60 +5190,61 @@ const skills = { } return false; }, - usable: 1, - check: function (event, player) { - var hs = player.getCards("h"), - cards = event.cards.filter(function (i) { - return hs.includes(i) && get.color(i, player) == "red" && lib.filter.cardDiscardable(i, player, "difa"); - }); - var value = get.value(hs, player); - return Array.from(ui.cardPile.childNodes).some(function (card) { - return get.type2(card, false) == "trick" && get.value(card, player) > value; - }); - }, - content: function () { - "step 0"; - var hs = player.getCards("h"), + async cost(event, trigger, player) { + let hs = player.getCards("h"), cards = trigger.cards.filter(function (i) { return hs.includes(i) && get.color(i, player) == "red" && lib.filter.cardDiscardable(i, player, "difa"); - }); - if (!cards.length) event.finish(); - else { - event.cards = cards; - player.discard(cards); - } - "step 1"; - var list = lib.inpile.filter(function (i) { + }), + tricks = []; + for(let i = 0; i < ui.cardPile.childNodes.length; i++){ + let card = ui.cardPile.childNodes[i], type = get.type2(card, false); + if (type != "trick" || tricks.includes(type)) continue; + tricks.push([card.name, get.event().player.getUseValue(card)]); + } + for(let i = 0; i < ui.discardPile.childNodes.length; i++){ + let card = ui.discardPile.childNodes[i], type = get.type2(card, false); + if (type != "trick" || tricks.includes(type)) continue; + tricks.push([card.name, get.event().player.getUseValue(card)]); + } + tricks.sort((a, b) => b[1] - a[1]); + let result = await player.chooseToDiscard(get.prompt2("difa"), card => { + return get.event().cards.includes(card); + }).set("ai", card => { + let val = get.event().val; + if (typeof val !== "number") return 0; + return val - get.value(card); + }).set("val", function () { + if (!tricks.length) return false; + return 3 * tricks[0][1]; + }()).set("cards", cards).forResult(); + event.result = { + bool: result.bool, + cost_data: tricks + }; + }, + usable: 1, + async content(event, trigger, player) { + let list = lib.inpile.filter(function (i) { return get.type2(i, false) == "trick"; }); - if (!list.length) event.finish(); - else - player - .chooseButton(["选择获得一种锦囊牌", [list.map(i => ["锦囊", "", i]), "vcard"]], true) - .set("ai", function (button) { - var card = { name: button.link[2] }; - if (!_status.event.list.includes(card.name)) return 0; - return _status.event.player.getUseValue(card); - }) - .set( - "list", - Array.from(ui.cardPile.childNodes) - .filter(function (card) { - return get.type2(card, false) == "trick"; - }) - .map(function (card) { - return card.name; - }) - .reduce(function (list, name) { - if (!list.includes(name)) list.add(name); - return list; - }, []) - ); - "step 2"; - var card = get.cardPile(function (i) { - return i.name == result.links[0][2] && !event.cards.includes(i); - }); - if (card) player.gain(card, "gain2"); + if (!list.length) return; + const result = await player + .chooseButton(["选择获得一种锦囊牌", [list.map(i => ["锦囊", "", i]), "vcard"]], true) + .set("ai", function (button) { + var name = button.link[2]; + for (let i of get.event().list) { + if (i[0] == name) return i[1]; + } + return 0; + }) + .set("list", event.cost_data) + .forResult(); + if (result.bool) { + let card = get.cardPile(i => { + return i.name == result.links[0][2]; + }); + if (card) await player.gain(card, "gain2"); + } }, }, //童渊 @@ -5607,6 +5330,17 @@ const skills = { player.addSkills(lib.skill.chuanshu.derivation); }, derivation: ["ollongdan", "drlt_congjian", "chuanyun"], + ai: { + maixie_hp: true, + effect: { + target(card, player, target) { + if (get.tag(card, "damage")) { + if (target.isHealthy()) return [1, 3]; + } + else if (get.tag(card, "recover") && target.getDamagedHp() == 1) return [0, 0]; + } + } + } }, longdan_tongyuan: { audio: true }, ocongjian_tongyuan: { audio: true }, @@ -6555,7 +6289,7 @@ const skills = { animationColor: "gray", filter: function (event, player) { return player.countCards("h", function (card) { - var type = get.type(card, player); + var type = get.type(card, null, player); return (type == "basic" || type == "trick") && get.tag(card, "damage") > 0; }); }, @@ -6577,7 +6311,7 @@ const skills = { .set( "aiCards", player.getCards("h", function (card) { - var type = get.type(card, player); + var type = get.type(card, null, player); return (type == "basic" || type == "trick") && get.tag(card, "damage") > 0; }) ); @@ -6587,7 +6321,7 @@ const skills = { player.logSkill("qljsuiren", target); player.give( player.getCards("h", function (card) { - var type = get.type(card, player); + var type = get.type(card, null, player); return (type == "basic" || type == "trick") && get.tag(card, "damage") > 0; }), target, @@ -6992,7 +6726,7 @@ const skills = { while (result.cards.length) { const card = result.cards.shift(); target.$give(card, player); - await game.asyncDelay(); + await game.delay(); const name = card.viewAs || card.name; if (card.name != name) { await player.addJudge(name, card); @@ -7621,7 +7355,7 @@ const skills = { card: card, }) ) - return "zerotarget"; + return "zeroplayertarget"; return [0.5, 0, 0.5, 0]; } if (num === 1 && get.color(card) == "black") return "zeroplayertarget"; @@ -7661,7 +7395,7 @@ const skills = { forced: true, filter: function (event, player) { if (player == _status.currentPhase || player.countCards("h")) return false; - return event.card.name == "sha" || get.type(event.card, false) == "trick"; + return event.card.name == "sha" || get.type(event.card, null, false) == "trick"; }, content: function () { player.draw(2); @@ -7786,7 +7520,7 @@ const skills = { trigger: { target: "useCardToTargeted" }, forced: true, filter: function (event, player) { - return player != event.player && !player.hasSkill("weipo3") && player.countCards("h") < Math.min(5, player.maxHp) && (event.card.name == "sha" || get.type(event.card) == "trick"); + return player != event.player && player.countCards("h") < Math.min(5, player.maxHp) && (event.card.name == "sha" || get.type(event.card) == "trick"); }, content: function () { "step 0"; @@ -7808,7 +7542,7 @@ const skills = { }, content: function () { "step 0"; - player.addTempSkill("weipo3", { player: "phaseBegin" }); + player.tempBanSkill("weipo", { player: "phaseBegin" }); if (player.countCards("h") && trigger.player.isIn()) { player.chooseCard("h", true, "将一张手牌交给" + get.translation(trigger.player)); } else event.finish(); @@ -7818,7 +7552,6 @@ const skills = { } }, }, - weipo3: { charlotte: true }, refuqi: { audio: "fuqi", forced: true, @@ -8809,22 +8542,7 @@ const skills = { var td = ui.create.div(".shadowed.reduce_radius.pointerdiv.tdnode"); td.link = numbers[i]; table2.appendChild(td); - var num = numbers[i]; - switch (num) { - case 1: - num = "A"; - break; - case 11: - num = "J"; - break; - case 12: - num = "Q"; - break; - case 13: - num = "K"; - break; - } - td.innerHTML = "" + num + ""; + td.innerHTML = "" + get.strNumber(numbers[i]) + ""; td.addEventListener(lib.config.touchscreen ? "touchend" : "click", function () { if (_status.dragged) return; if (_status.justdragged) return; @@ -9380,7 +9098,7 @@ const skills = { }, content: function () { var card = get.cardPile2(function (card) { - var type = get.type(card, false); + var type = get.type(card, null, false); if (type != "basic" && type != "trick") return false; return get.tag(card, "damage") > 0; }); @@ -9422,14 +9140,14 @@ const skills = { init(player) { game.addGlobalSkill("gangzhi_jueqing"); }, - onremove(player) { - game.removeGlobalSkill("gangzhi_jueqing"); + onremove() { + if (!game.hasPlayer(cur => cur.hasSkill("gangzhi", null, null, false), true)) game.removeGlobalSkill("gangzhi_jueqing"); }, subSkill: { jueqing: { trigger: {player: "dieAfter"}, filter(event, player) { - return !game.hasPlayer(cur => cur.hasSkill("gangzhi")); + return !game.hasPlayer(cur => cur.hasSkill("gangzhi", null, null, false)); }, silent: true, forceDie: true, @@ -10791,7 +10509,7 @@ const skills = { audio: 2, enable: "phaseUse", filter: function (event, player) { - return !player.hasSkill("songshu_reflectionblue", null, null, false) && player.countCards("h") > 0; + return player.countCards("h") > 0; }, filterTarget: function (card, player, target) { return target != player && player.canCompare(target); @@ -10803,7 +10521,7 @@ const skills = { if (!result.bool) { player.draw(2, "nodelay"); target.draw(2); - player.addTempSkill("songshu_reflectionblue", "phaseUseAfter"); + player.tempBanSkill("songshu", "phaseUseAfter"); } else { target.addTempSkill("songshu_ai"); } @@ -10835,7 +10553,6 @@ const skills = { }, }, songshu_ai: { charlotte: true }, - songshu_reflectionblue: { charlotte: true }, sibian: { audio: 2, trigger: { player: "phaseDrawBegin1" }, @@ -11118,12 +10835,14 @@ const skills = { }, ai: { effect: { - player: function (card, player, target) { + player_use: function (card, player, target) { if (target != player.storage.yinju2) return; if (card.name == "lebu") return; - if (card.name !== "huogong" && get.tag(card, "damage") && target.isDamaged()) [1, 0.6, 0, 2.4]; return [1, 0.6, 1, 0.6]; }, + player(card, player, target) { + if (card.name !== "huogong" && get.tag(card, "damage") && target.isDamaged()) [1, 0, 0, 2]; + } }, }, }, @@ -11665,11 +11384,15 @@ const skills = { ai: { order: 9, result: { - target: function (player, target) { + player(player, target) { + if (target.countCards("hej")) return 0.92; + return 0; + }, + target(player, target) { var numj = target.countCards("j"); var numhe = target.countCards("he"); - if (numhe == 0) return numj > 0 ? 6 : -6; - return -6 - (numj + 1) / numhe; + if (numhe + numj > 0) return (1.6 * numj - numhe) / (numj + numhe) - 0.3; + return -0.3; }, }, threaten: 1.1, @@ -12596,10 +12319,10 @@ const skills = { ); }) .set("ai", target => { - const player = get.event("player"); - const card = get.event().getTrigger().card; - if (!get.info("dcmffengshi").check({ card: card, target: target })) return 0; - return get.effect(target, { name: "guohe_copy2" }, player, player); + let trigger = get.event().getTrigger(), player = trigger.player; + let eff = get.effect(player, { name: "guohe" }, player, get.event().player) + get.effect(target, { name: "guohe" }, player, get.event().player); + if (get.tag(trigger.card, "damage")) eff += get.damageEffect(target, trigger.card, trigger.player, get.event().player); + return eff; }); if (bool) { const target = targets[0]; @@ -12670,22 +12393,12 @@ const skills = { return "弃置你与" + get.translation(target) + "的各一张牌,然后令" + get.translation(event.card) + "的伤害+1"; }, check: function (event, player) { - var viewer = player, - player = event.player, - target = event.target; - if (viewer == player) { - if (get.attitude(viewer, target) >= 0) return false; - if (player.countCards("he", card => get.value(card, player) < 5)) return true; - var card = get.event().getTrigger().card; - if ((get.tag(card, "damage") || target.countCards("he", card => get.value(card, target) > 6)) && player.countCards("he", card => get.value(card, player) < 7)) return true; - return false; - } else { - if (get.attitude(viewer, player) >= 0) return false; - if (!get.tag(card, "damage")) return false; - if (viewer.countCards("he") > player.countCards("he")) return true; - if (viewer.countCards("he", card => get.value(card, target) > 6)) return false; - return true; - } + let viewer = get.event().player, + user = event.player, + target = event.target, + eff = get.effect(user, { name: "guohe" }, user, viewer) + get.effect(target, { name: "guohe" }, user, viewer); + if (get.tag(event.card, "damage")) eff += get.damageEffect(target, event.card, player, viewer); + return eff > 0; }, content: function () { if (get.tag(trigger.card, "damage")) trigger.getParent().baseDamage++; @@ -12715,24 +12428,13 @@ const skills = { var str; if (player == trigger.player) str = "弃置自己的和该角色"; else str = "令其弃置其与你的"; - var next = trigger.player.chooseBool("是否对" + get.translation(trigger.target) + "发动【锋势】?", str + "的各一张牌,然后令" + get.translation(trigger.card) + "的伤害+1").set("ai", function () { - var player = _status.event.getParent().player; - var target = _status.event.getParent().target; - var viewer = _status.event.player; - if (viewer == player) { - if (get.attitude(viewer, target) >= 0) return false; - if (player.countCards("he", card => get.value(card, player) < 5)) return true; - var card = _status.event.getTrigger().card; - if ((get.tag(card, "damage") || target.countCards("he", card => get.value(card, target) > 6)) && player.countCards("he", card => get.value(card, player) < 7)) return true; - return false; - } else { - if (get.attitude(viewer, player) >= 0) return false; - if (!get.tag(card, "damage")) return false; - if (viewer.countCards("he") > player.countCards("he")) return true; - if (viewer.countCards("he", card => get.value(card, target) > 6)) return false; - return true; - } - }); + var next = trigger.player.chooseBool("是否对" + get.translation(trigger.target) + "发动【锋势】?", str + "的各一张牌,然后令" + get.translation(trigger.card) + "的伤害+1") + .set("ai", () => get.event().bool) + .set("bool", function () { + let eff = get.effect(trigger.player, { name: "guohe" }, player, trigger.player) + get.effect(trigger.target, { name: "guohe" }, player, trigger.player); + if (get.tag(trigger.card, "damage")) eff += get.damageEffect(trigger.target, trigger.card, trigger.player, trigger.player); + return eff > 0; + }()); if (player == next.player) next.setHiddenSkill("mffengshi"); "step 1"; if (result.bool) { diff --git a/character/sp2/sort.js b/character/sp2/sort.js index f141343c0f..3ecbae1052 100644 --- a/character/sp2/sort.js +++ b/character/sp2/sort.js @@ -1,4 +1,5 @@ const characterSort = { + sp_xhly: ["duji", "lvdai", "liuyao", "sp_taishici", "re_zhangliang"], sp_whlw: ["xurong", "lijue", "zhangji", "fanchou", "guosi", "duanwei", "liangxing", "zhangheng", "tangji", "niufu", "dongxie", "liqueguosi"], sp_zlzy: ["zhangqiying", "lvkai", "zhanggong", "weiwenzhugezhi", "beimihu"], sp_longzhou: ["xf_tangzi", "xf_huangquan", "xf_sufei", "sp_liuqi"], @@ -16,11 +17,11 @@ const characterSort = { sp_xiaohu: ["haomeng", "yanfuren", "yanrou", "dc_zhuling"], sp_qunxiong: ["chezhou", "hansong", "matie"], sp_star: ["star_caoren", "star_yuanshu", "star_dongzhuo", "star_yuanshao", "star_zhangchunhua", "star_sunjian", "star_zhangzhao", "star_sunshangxiang"], - mini_qixian: ["mp_liuling", "mp_wangrong"], sp2_waitforsort: ["caobuxing", "re_maliang", "dc_jikang"], }; const characterSortTranslate = { + sp_xhly: "星火燎原", sp_whlw: "文和乱武", sp_zlzy: "逐鹿中原", sp_longzhou: "同舟共济", @@ -39,7 +40,6 @@ const characterSortTranslate = { sp_fenghuo: "烽火连天", sp_danqi: "千里单骑", sp_star: "将星系列", - mini_qixian: "小程序·竹林七贤", sp2_waitforsort: "等待分包", }; diff --git a/character/sp2/translate.js b/character/sp2/translate.js index fd268954d1..58dc213170 100644 --- a/character/sp2/translate.js +++ b/character/sp2/translate.js @@ -371,7 +371,7 @@ const translates = { nhlundao: "论道", nhlundao_info: "当你受到伤害后,若伤害来源比你手牌多,你可以弃置其一张牌;若伤害来源比你手牌少,你摸一张牌。", nhguanyue: "观月", - nhguanyue_info: "结束阶段,你可以观看牌堆顶两张牌,然后获得其中—张,另一张放回牌堆顶。", + nhguanyue_info: "结束阶段,你可以观看牌堆顶两张牌,然后获得其中一张,另一张放回牌堆顶。", nhyanzheng: "言政", nhyanzheng_info: "准备阶段,若你的手牌数大于1,你可以保留一张手牌并弃置其余的牌,然后选择至多等于弃牌数量的角色,对这些角色各造成1点伤害。", sp_mifangfushiren: "糜芳傅士仁", @@ -392,7 +392,7 @@ const translates = { tianze: "天则", tianze_info: "①其他角色于其出牌阶段内使用的第一张黑色手牌结算结束后,你可以弃置一张黑色牌,并对其造成1点伤害。②其他角色的判定生效后,若结果为黑色,则你摸一张牌。", difa: "地法", - difa_info: "每回合限一次。当你于回合内得到红色牌时,你可以弃置之。然后你选择一个锦囊牌的牌名,并从牌堆中获得一张此牌名的牌。", + difa_info: "每回合限一次。当你于回合内得到红色牌后,你可以弃置其中一张。然后你选择一个锦囊牌的牌名,并从牌堆/弃牌堆中获得一张此牌名的牌。", xinping: "辛评", fuyuan: "辅袁", fuyuan_info: "当你于回合外使用或打出牌时,若当前回合角色的手牌数:不小于你,你可摸一张牌;小于你,你可令其摸一张牌。", @@ -410,10 +410,10 @@ const translates = { yinyi_info: "锁定技。每回合限一次,当你受到非属性伤害时,若你的手牌数和体力值与伤害来源均不相同,则你防止此伤害。", haomeng: "郝萌", xiongmang: "雄莽", - xiongmang_info: "你可将任意张花色各不相同的手牌当做目标数上限为X的【杀】使用(X为此【杀】对应的实体牌数)。此【杀】使用结算结束后,若你未造成过渠道为此牌的伤害且体力上限大于1,则你减1点体力上限。", + xiongmang_info: "你可将任意张花色各不相同的手牌当做目标数上限为X的【杀】使用(X为此【杀】对应的实体牌数)。此【杀】使用结算结束后,若此牌造成过/未造成过伤害,则你本阶段使用【杀】的额定次数+1/减1点体力上限。", yanfuren: "严夫人", channi: "谗逆", - channi_info: "出牌阶段限一次。你可将任意张手牌交给一名其他角色,然后其可以将至多等量的手牌当做【决斗】使用。若其因此【决斗】造成了伤害,则其摸X张牌(X为此【决斗】对应的实体牌数)。若其因此【决斗】受到过伤害,则你弃置所有手牌。", + channi_info: "出牌阶段限一次。你可将任意张手牌交给一名其他角色,然后其可以将至多等量的手牌当做【决斗】使用。当其因此【决斗】:造成伤害后,其摸X张牌(X为此【决斗】对应的实体牌数);受到伤害后,你弃置所有手牌。", nifu: "匿伏", nifu_info: "锁定技。一名角色的回合结束时,你将手牌摸至或弃置至三张。", licaiwei: "李采薇", @@ -504,7 +504,7 @@ const translates = { dclongsong: "龙诵", dclongsong_info: "出牌阶段开始时,你可以将一张红色牌交给一名其他角色。然后其须选择其所有的发动时机包含“出牌阶段”的技能,其于此阶段这些技能失效,你获得这些技能且至多可以发动一次。", longsong: "龙诵", - longsong_info: "出牌阶段开始时,你可以将一张红色牌交给一名其他角色或获得一名其他角色的一张红色牌,然后你本阶段获得其所有的发动时机包含“出牌阶段”的技能且至多可以发动一次,若其没有符合条件的技能,则改为随机获得一个满足条件的技能。", + longsong_info: "出牌阶段开始时,你可以交给或获得一名其他角色一张红色牌,然后你本阶段获得其发动时机包含“出牌阶段”的一项技能且至多可以发动一次。若其没有符合条件的技能,则改为随机获得一个满足条件的技能。", dc_mengda: "孟达", dclibang: "利傍", dclibang_info: "出牌阶段限一次。你可以弃置一张牌,正面向上获得两名其他角色的各一张牌。然后你判定,若结果与这两张牌的颜色均不同,你交给其中一名角色两张牌或失去1点体力,否则你获得判定牌并视为对其中一名角色使用一张【杀】。", @@ -522,13 +522,6 @@ const translates = { dcjuexiang_info: "当你死亡时,杀死你的角色弃置其装备区内的所有牌并失去1点体力,然后你可以令一名其他角色获得〖残韵〗。", dccanyun: "残韵", dccanyun_info: "每名角色限一次。出牌阶段,你可以弃置一张牌并选择一名其他角色,然后若其装备区里的牌数:小于你,其回复1点体力;大于你,其失去1点体力;等于你,其摸一张牌。若你的体力值为1,你摸一张牌。", - mp_liuling: "刘伶", - mpjiusong: "酒颂", - mpjiusong_info: "①你可以将一张锦囊牌当【酒】使用。②当一名角色使用【酒】时,你获得1枚“醉”标记(“醉”数至多为3)。", - mpmaotao: "酕醄", - mpmaotao_info: "当其他角色使用基本牌或普通锦囊牌指定唯一目标时,你可以移去1枚“醉”,令此牌的目标改为随机一名合法角色(无距离限制)。若目标角色与原目标相同且你本回合未以此法获得过牌,你从牌堆中随机获得一张锦囊牌。", - mpbishi: "避世", - mpbishi_info: "锁定技。你不能成为伤害类锦囊牌的目标。", star_caoren: "星曹仁", star_caoren_prefix: "星", starsujun: "肃军", @@ -607,11 +600,6 @@ const translates = { dczhuiwang_info: "锁定技,你计算体力值小于等于你的角色的距离视为1。", dcquxian: "驱险", dcquxian_info: "出牌阶段开始时,你可以选择一名角色,攻击范围内包含其的其他角色可以依次对其使用一张【杀】。若其未以此法受到伤害,这些角色中未使用【杀】的角色失去X点体力(X为这些角色中使用【杀】的角色数)。", - mp_wangrong: "王戎", - mpjianlin: "俭吝", - mpjianlin_info: "每回合结束后,若本回合你有基本牌因使用、打出或弃置而进入弃牌堆,则你可以选择其中一张牌获得之。", - mpsixiao: "死孝", - mpsixiao_info: "锁定技,游戏开始时,你选择一名其他角色。每回合限一次,当该角色需要使用或打出除【无懈可击】外的牌时,其可以观看你的手牌并可以使用或打出其中一张牌,然后你摸一张牌。", }; export default translates; diff --git a/character/sp2/voices.js b/character/sp2/voices.js index e1337fef1c..15828904e5 100644 --- a/character/sp2/voices.js +++ b/character/sp2/voices.js @@ -126,11 +126,11 @@ export default { "#dczhanyi1": "以役兴国,战意磅礴!", "#dczhanyi2": "此命不已,此战不休!", "#dc_zhuling:die": "吾,错付曹公……", - "#yijiao1": "不能居下者,终为异教。", - "#yijiao2": "异教兴,而大义危。", - "#qibie1": "今与君别,恍如昨日,不经幽泣。", - "#qibie2": "相逢为君饮,相别为君泣。", - "#licaiwei:die": "我心孔疚,我行不来!", + "#yijiao1": "公呼异教,思汉也已。", + "#yijiao2": "非我同盟,其心必异。", + "#qibie1": "忽闻君别,泣下沾襟。", + "#qibie2": "相与泣别,承其遗志。", + "#licaiwei:die": "随君而去……", "#channi1": "此人心怀叵测,将军当拔剑诛之!", "#channi2": "请夫君听妾身之言,勿为小人所误!", "#nifu1": "当为贤妻宜室,莫做妒妇祸家。", diff --git a/character/standard/character.js b/character/standard/character.js index d6c36e4ad4..f719e3b598 100644 --- a/character/standard/character.js +++ b/character/standard/character.js @@ -33,22 +33,6 @@ const characters = { xf_yiji: ["male", "shu", 3, ["xinfu_jijie", "xinfu_jiyuan"], []], re_yuanshu: ["male", "qun", 4, ["rewangzun", "retongji"]], - std_sunhao: ["male", "wu", 5, ["stdcanshi", "chouhai", "guiming"], ["zhu"]], - std_mateng: ["male", "qun", 4, ["stdxiongyi", "mashu", "stdyouji"], ["zhu"]], - std_mayunlu: ["female", "shu", 4, ["stdfengpo", "mashu"]], - std_jianggan: ["male", "wei", 3, ["stddaoshu", "stddaizui"]], - std_zhouchu: ["male", "wu", 4, ["stdxiongxia"]], - std_lvlingqi: ["female", "qun", 4, ["stdhuizhan"]], - std_dc_yanghu: ["male", "wei", 4, ["stdmingfa"]], - std_dc_luotong: ["male", "wu", 3, ["stdjinjian", "stdrenzheng"]], - std_lijue: ["male", "qun", 5, ["stdxiongsuan"]], - std_chengpu: ["male", "wu", 4, ["stdchunlao"]], - std_db_wenyang: ["male", "wei", 4, ["stdquedi"]], - std_re_dengzhi: ["male", "shu", 3, ["stdzhiyinmeng", "stdhehe"]], - std_zhangyì: ["male", "shu", 4, ["stdzhiyi"]], - std_chengyu: ["male", "wei", 3, ["stdshefu", "stdyibing"]], - std_fanyufeng: ["female", "qun", 3, ["stdbazhan", "stdzhanying"]], - std_feiyi: ["male", "shu", 3, ["stdtiaohe", "stdqiansu"]], }; export default characters; diff --git a/character/standard/characterReplace.js b/character/standard/characterReplace.js index ff8238062f..77ee92a0e3 100644 --- a/character/standard/characterReplace.js +++ b/character/standard/characterReplace.js @@ -1,30 +1,30 @@ const characterReplaces = { - caocao: ["caocao", "re_caocao", "sb_caocao", "dc_caocao"], - guojia: ["guojia", "re_guojia", "ps1059_guojia", "ps2070_guojia", "huan_guojia"], - simayi: ["simayi", "re_simayi", "jsrg_simayi", "ps_simayi", "ps2068_simayi", "huan_simayi"], + caocao: ["caocao", "re_caocao", "sb_caocao", "dc_caocao", "jd_sb_caocao"], + guojia: ["guojia", "re_guojia", "sb_guojia", "ps1059_guojia", "ps2070_guojia"], + simayi: ["simayi", "re_simayi", "dc_sb_simayi", "jsrg_simayi", "ps_simayi", "ps2068_simayi", "huan_simayi"], jin_simayi: ["jin_simayi", "junk_simayi", "ps_jin_simayi"], zhenji: ["zhenji", "re_zhenji", "sb_zhenji", "yj_zhenji"], xuzhu: ["xuzhu", "re_xuzhu"], zhangliao: ["zhangliao", "re_zhangliao"], sp_zhangliao: ["sp_zhangliao", "yj_zhangliao", "jsrg_zhangliao"], xiahoudun: ["xiahoudun", "re_xiahoudun", "xin_xiahoudun", "sb_xiahoudun"], - liubei: ["liubei", "re_liubei", "sb_liubei", "dc_liubei", "junk_liubei"], - guanyu: ["guanyu", "re_guanyu", "ol_sb_guanyu", "sb_guanyu", "ps_guanyu", "old_guanyu", "junk_guanyu", "wuhujiang"], - zhangfei: ["zhangfei", "re_zhangfei", "old_zhangfei", "xin_zhangfei", "sb_zhangfei", "tw_zhangfei", "jsrg_zhangfei", "yj_zhangfei", "wuhujiang"], - zhaoyun: ["zhaoyun", "re_zhaoyun", "old_zhaoyun", "sb_zhaoyun", "jsrg_zhaoyun", "ps2063_zhaoyun", "ps2067_zhaoyun", "huan_zhaoyun", "wuhujiang"], + liubei: ["liubei", "re_liubei", "sb_liubei", "dc_liubei", "junk_liubei", "jd_sb_liubei", "ty_liubei"], + guanyu: ["guanyu", "re_guanyu", "ol_sb_guanyu", "sb_guanyu", "ps_guanyu", "old_guanyu", "junk_guanyu", "wuhujiang", "jx_guanyu", "jd_sb_guanyu", "ty_guanyu"], + zhangfei: ["zhangfei", "re_zhangfei", "old_zhangfei", "xin_zhangfei", "sb_zhangfei", "tw_zhangfei", "jsrg_zhangfei", "yj_zhangfei", "wuhujiang", "jd_sb_zhangfei"], + zhaoyun: ["zhaoyun", "re_zhaoyun", "old_zhaoyun", "sb_zhaoyun", "jsrg_zhaoyun", "ps2063_zhaoyun", "ps2067_zhaoyun", "huan_zhaoyun", "wuhujiang", "jd_sb_zhaoyun"], sp_zhaoyun: ["sp_zhaoyun", "jsp_zhaoyun"], machao: ["machao", "re_machao", "sb_machao", "ps_machao", "wuhujiang"], sp_machao: ["sp_machao", "dc_sp_machao", "jsrg_machao", "old_machao"], - zhugeliang: ["zhugeliang", "re_zhugeliang", "sb_zhugeliang", "ps2066_zhugeliang", "ps_zhugeliang", "huan_zhugeliang"], - huangyueying: ["huangyueying", "re_huangyueying", "junk_huangyueying", "sb_huangyueying"], - sunquan: ["sunquan", "re_sunquan", "sb_sunquan", "dc_sunquan", "xin_sunquan"], - zhouyu: ["zhouyu", "re_zhouyu", "dc_sb_zhouyu", "sb_zhouyu", "ps1062_zhouyu", "ps2080_zhouyu"], - luxun: ["luxun", "re_luxun", "jsrg_luxun", "sb_luxun"], + zhugeliang: ["zhugeliang", "re_zhugeliang", "ps2066_zhugeliang", "ps_zhugeliang", "huan_zhugeliang"], + huangyueying: ["huangyueying", "re_huangyueying", "junk_huangyueying", "sb_huangyueying", "jd_sb_huangyueying"], + sunquan: ["sunquan", "re_sunquan", "sb_sunquan", "dc_sunquan", "xin_sunquan", "jd_sb_sunquan", "ty_sunquan"], + zhouyu: ["zhouyu", "re_zhouyu", "dc_sb_zhouyu", "sb_zhouyu", "ps1062_zhouyu", "ps2080_zhouyu", "jx_zhouyu"], + luxun: ["luxun", "re_luxun", "jsrg_luxun", "sb_luxun", "ty_luxun", "huan_luxun"], lvmeng: ["lvmeng", "re_lvmeng", "sb_lvmeng"], huanggai: ["huanggai", "re_huanggai", "sb_huanggai"], - daqiao: ["daqiao", "re_daqiao", "sb_daqiao"], - sunshangxiang: ["sunshangxiang", "re_sunshangxiang", "sb_sunshangxiang", "jsrg_sunshangxiang", "star_sunshangxiang"], - ganning: ["ganning", "re_ganning", "sb_ganning", "yongjian_ganning"], + daqiao: ["daqiao", "re_daqiao", "sb_daqiao", "jd_sb_daqiao", "yue_daqiao"], + sunshangxiang: ["sunshangxiang", "re_sunshangxiang", "sb_sunshangxiang", "jsrg_sunshangxiang", "star_sunshangxiang", "jd_sb_sunshangxiang"], + ganning: ["ganning", "re_ganning", "sb_ganning", "yongjian_ganning", "jd_sb_ganning", "ty_ganning"], yj_ganning: ["yj_ganning", "sp_ganning"], lvbu: ["lvbu", "re_lvbu", "jsrg_lvbu", "ps_lvbu"], diaochan: ["diaochan", "re_diaochan", "sb_diaochan"], @@ -33,10 +33,6 @@ const characterReplaces = { yuanshu: ["yuanshu", "re_yuanshu", "yl_yuanshu", "old_yuanshu", "ol_yuanshu", "star_yuanshu"], gongsunzan: ["gongsunzan", "re_gongsunzan", "dc_gongsunzan", "xin_gongsunzan", "sb_gongsunzan"], re_lidian: ["re_lidian", "old_re_lidian", "junk_lidian"], - sunhao: ["sunhao", "std_sunhao"], - lvlingqi: ["lvlingqi", "std_lvlingqi"], - chengyu: ["chengyu", "std_chengyu"], - fanyufeng: ["fanyufeng", "std_fanyufeng"], }; export default characterReplaces; diff --git a/character/standard/skill.js b/character/standard/skill.js index c025d81541..0d26eb733d 100644 --- a/character/standard/skill.js +++ b/character/standard/skill.js @@ -2,1057 +2,6 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { - //四象封印·少阴 - //孙皓 - stdcanshi: { - audio: "canshi", - inherit: "canshi", - forced: true, - async content(event, trigger, player) { - trigger.changeToZero(); - await player.draw( - Math.max( - 1, - game.countPlayer(target => { - if (player.hasSkill("guiming") && target != player && target.group == "wu") return true; - return target.isDamaged(); - }) - ) - ); - player.addTempSkill("stdcanshi_effect"); - }, - subSkill: { - effect: { - charlotte: true, - trigger: { player: "useCardToPlayered" }, - filter(event, player) { - if (event.card.name != "sha" && get.type(event.card) != "trick") return false; - return event.target.isDamaged() && player.countCards("he"); - }, - forced: true, - autodelay: true, - content() { - player.chooseToDiscard("he", true); - }, - }, - }, - }, - //马腾 - stdxiongyi: { - unique: true, - limited: true, - audio: "xiongyi", - enable: "phaseUse", - filterTarget: true, - selectTarget: [1, Infinity], - multitarget: true, - multiline: true, - skillAnimation: true, - animationColor: "thunder", - async content(event, trigger, player) { - player.awakenSkill("stdxiongyi"); - const targets = event.targets.sortBySeat(); - let keep = true; - while (true) { - let stop = false; - for (const target of targets) { - let next = target - .chooseToUse(function (card) { - const event = get.event(); - if (!lib.filter.cardEnabled(card, event.player, event)) return false; - return get.name(card) == "sha"; - }, "雄异:是否使用一张不可被响应的【杀】?") - .set("oncard", card => { - _status.event.directHit.addArray(game.players); - }); - if (!keep) next.set("prompt2", "若你不使用,则结束此流程"); - const result = await next.forResult(); - if (!result.bool && !keep) { - stop = true; - break; - } - } - if (keep) keep = false; - if (stop) break; - } - }, - ai: { - order: 10, - result: { - target(player, target) { - if (player.hasUnknown()) return 0; - return target.countCards("hs"); - }, - }, - }, - }, - stdyouji: { - audio: 2, - trigger: { player: "phaseZhunbeiBegin" }, - filter(event, player) { - return player.canMoveCard( - null, - true, - game.filterPlayer(i => { - return i.group == "qun"; - }), - card => { - return [3, 4, 6].includes(parseInt(get.subtype(card).slice("equip".length))); - }, - "nojudge" - ); - }, - direct: true, - zhuSkill: true, - content() { - player - .moveCard( - game.filterPlayer(i => { - return i.group == "qun"; - }), - card => { - return [3, 4, 6].includes(parseInt(get.subtype(card).slice("equip".length))); - } - ) - .set("prompt", get.prompt2("stdyouji")) - .set("nojudge", true) - .set("logSkill", "stdyouji"); - }, - }, - //马云禄 - stdfengpo: { - audio: "fengpo", - trigger: { source: "damageBegin1" }, - filter(event, player) { - return ( - event.card.name == "sha" && - [player, event.player].some(target => { - return target.isIn() && target.countCards("he"); - }) - ); - }, - async cost(event, trigger, player) { - event.result = await player - .chooseTarget(get.prompt2("stdfengpo"), (card, player, target) => { - const event = get.event().getTrigger(); - return [player, event.player] - .filter(targetx => { - return targetx.isIn() && targetx.countCards("he"); - }) - .includes(target); - }) - .set("ai", target => { - const player = get.event("player"), - aim = get.event().getTrigger().player; - if (get.attitude(player, aim) > 0 || get.damageEffect(aim, player, player) < 0) return 0; - if (aim.countCards("he")) return -5; - if (player.getDiscardableCards(player, "he").some(card => get.suit(card) == "diamond")) return 1; - return 0; - }) - .forResult(); - }, - async content(event, trigger, player) { - const target = event.targets[0]; - const result = await player - .discardPlayerCard(target, "he", true) - .set("ai", button => { - const suit = get.suit(button.link); - return (suit == "diamond" ? 5 : 1) * get.value(button.link); - }) - .set("prompt", "凤魄:弃置" + (target != player ? get.translation(target) : "") + "一张牌") - .set("prompt2", "若弃置了方片牌,则此伤害+1") - .forResult(); - if (result.bool) { - if (result.cards && result.cards.some(i => get.suit(i, target) == "diamond")) { - player.popup("洗具"); - trigger.increase("num"); - } - } - }, - }, - //蒋干 - stddaoshu: { - audio: "daoshu", - trigger: { global: "phaseZhunbeiBegin" }, - filter(event, player) { - return game.hasPlayer(target => { - return target != event.player && target.countCards("h"); - }); - }, - async cost(event, trigger, player) { - event.result = await player - .chooseTarget(get.prompt2("stddaoshu"), (card, player, target) => { - const event = get.event().getTrigger(); - return target != event.player && target.countCards("h"); - }) - .set("ai", target => { - const player = get.event("player"); - return -1 / target.countCards("h"); - }) - .forResult(); - }, - async content(event, trigger, player) { - player.tempBanSkill("stddaoshu", "roundStart", false); - const target = event.targets[0]; - const result = await player.choosePlayerCard(target, "h", true).forResult(); - if (result.bool) { - const cards = result.cards || []; - if (cards.length) { - await player.showCards(cards, get.translation(player) + "发动了【盗书】"); - await trigger.player.gain(cards, target, "give"); - const suits = cards.reduce((list, card) => { - return list.add(get.suit(card, target)); - }, []); - if (suits.length) { - for (const i of [player, trigger.player]) { - i.addTempSkill("stddaoshu_effect"); - i.markAuto("stddaoshu_effect", suits); - } - } - } - } - }, - subSkill: { - effect: { - charlotte: true, - onremove: true, - mod: { - cardEnabled(card, player) { - if (player.getStorage("stddaoshu_effect").includes(get.suit(card))) return false; - }, - cardSavable(card, player) { - if (player.getStorage("stddaoshu_effect").includes(get.suit(card))) return false; - }, - }, - intro: { content: "不能使用$花色的牌" }, - }, - }, - }, - stddaizui: { - audio: "spdaizui", - trigger: { player: "damageEnd" }, - filter(event, player) { - return player.isTempBanned("stddaoshu"); - }, - forced: true, - content() { - delete player.storage.temp_ban_stddaoshu; - player.popup("盗书"); - game.log(player, "重置了技能", "#g【盗书】"); - }, - ai: { - combo: "stddaoshu" - }, - }, - //周处 - stdxiongxia: { - audio: "xianghai", - enable: "chooseToUse", - filterCard: true, - selectCard: 2, - position: "hes", - viewAs: { name: "juedou" }, - selectTarget: 2, - viewAsFilter(player) { - if (player.countCards("hes") < 2) return false; - }, - check(card) { - if (get.name(card) == "sha") return 4 - get.value(card); - return 7.5 - get.value(card); - }, - onuse(links, player) { - player.addTempSkill("stdxiongxia_effect"); - }, - subSkill: { - effect: { - charlotte: true, - trigger: { player: "useCardAfter" }, - filter(event, player) { - return ( - event.skill == "stdxiongxia" && - (event.targets || []).every(target => { - return target.getHistory("damage", evt => { - return evt.card && evt.card == event.card; - }).length; - }) - ); - }, - forced: true, - popup: false, - content() { - player.tempBanSkill("stdxiongxia"); - }, - }, - }, - }, - //吕玲绮 - stdhuizhan: { - audio: "guowu", - trigger: { player: "useCard2" }, - filter(event, player) { - if (event.card.name != "sha") return false; - return game.hasPlayer(target => { - return !event.targets.includes(target) && lib.filter.targetEnabled2(event.card, player, target) && lib.filter.targetInRange(event.card, player, target); - }); - }, - async cost(event, trigger, player) { - event.result = await player - .chooseTarget( - get.prompt2("stdhuizhan"), - (card, player, target) => { - const event = get.event().getTrigger(); - return !event.targets.includes(target) && lib.filter.targetEnabled2(event.card, player, target) && lib.filter.targetInRange(event.card, player, target); - }, - [1, 2] - ) - .set("ai", target => { - const player = get.event("player"), - event = get.event().getTrigger(); - return get.effect(target, event.card, player); - }) - .forResult(); - }, - async content(event, trigger, player) { - trigger.targets.addArray(event.targets); - player.addTempSkill("stdhuizhan_effect"); - trigger.card.stdhuizhan = true; - }, - subSkill: { - effect: { - charlotte: true, - trigger: { global: "chooseToUseBegin" }, - filter(event, player) { - if (event._stdhuizhan_effect) return false; - const evt = event.getParent(2); - return evt.card && evt.card.stdhuizhan; - }, - forced: true, - popup: false, - forceDie: true, - async content(event, trigger, player) { - trigger._stdhuizhan_effect = true; - const targets = trigger - .getParent(2) - .targets.filter(i => { - return i != trigger.player; - }) - .sortBySeat(); - if (targets.length) { - for (const target of targets) { - if (!target.isIn()) continue; - const next = target.chooseToUse("挥战:是否替" + get.translation(trigger.player) + "使用一张【闪】?", { name: "shan" }); - next.set("ai", () => { - const event = _status.event; - return get.attitude(event.player, event.source) - 2; - }); - next.set("skillwarn", "替" + get.translation(player) + "打出一张闪"); - next.autochoose = lib.filter.autoRespondShan; - next.set("source", player); - const result = await next.forResult(); - if (result.bool) { - trigger.result = { bool: true, card: { name: "shan", isCard: true, cards: result.cards.slice() }, cards: result.cards.slice() }; - trigger.responded = true; - trigger.animate = false; - break; - } - } - } - }, - }, - }, - }, - //羊祜 - stdmingfa: { - audio: "dcmingfa", - enable: "phaseUse", - filter(event, player) { - if (player.hasSkill("stdmingfa_used")) return false; - return game.hasPlayer(target => target.getHp() > 1); - }, - filterTarget(card, player, target) { - return target.getHp() > 1; - }, - async content(event, trigger, player) { - const target = event.target; - await target.damage(); - if (target.isIn()) { - player.addSkill("stdmingfa_used"); - player.markAuto("stdmingfa_used", [target]); - } - }, - subSkill: { - used: { - charlotte: true, - onremove: true, - trigger: { global: ["dieAfter", "recoverAfter"] }, - filter(event, player) { - return player.getStorage("stdmingfa_used").includes(event.player); - }, - forced: true, - popup: false, - content() { - player.popup("明伐"); - game.log(player, "恢复了技能", "#g【明伐】"); - player.removeSkill("stdmingfa_used"); - }, - }, - }, - ai: { - order: 10, - result: { - target(player, target) { - return get.sgn(get.attitude(player, target)) * get.damageEffect(target, player, player); - }, - }, - }, - }, - //骆统 - stdrenzheng: { - audio: "renzheng", - trigger: { global: ["damageCancelled", "damageZero"] }, - filter(event, player, name) { - if (!_status.currentPhase || !_status.currentPhase.isIn()) return false; - if (name == "damageCancelled") return true; - return event.change_history.some(i => i < 0); - }, - forced: true, - logTarget: () => _status.currentPhase, - content() { - _status.currentPhase.draw(); - }, - }, - stdjinjian: { - audio: "jinjian", - trigger: { source: "damageBegin1" }, - logTarget: "player", - filter: function (event, player) { - return !event.stdjinjian_source2 && !player.hasSkill("stdjinjian_source2"); - }, - prompt2: "令即将对其造成的伤害+1", - check: function (event, player) { - return ( - get.attitude(player, event.player) < 0 && - !event.player.hasSkillTag("filterDamage", null, { - player: player, - card: event.card, - }) - ); - }, - usable: 1, - content: function () { - trigger.stdjinjian_source = true; - trigger.num++; - player.addTempSkill("stdjinjian_source2"); - }, - group: "stdjinjian_player", - subSkill: { - player: { - audio: "jinjian", - trigger: { player: "damageBegin4" }, - filter: function (event, player) { - return !event.stdjinjian_player2 && !player.hasSkill("stdjinjian_player2"); - }, - prompt2: "令即将受到的伤害-1", - usable: 1, - content: function () { - trigger.stdjinjian_player = true; - trigger.num--; - player.addTempSkill("stdjinjian_player2"); - }, - }, - source2: { - trigger: { source: "damageBegin1" }, - forced: true, - charlotte: true, - filter: function (event, player) { - return !event.stdjinjian_source; - }, - content: function () { - trigger.num--; - trigger.stdjinjian_source2 = true; - player.removeSkill("stdjinjian_source2"); - }, - marktext: " -1 ", - intro: { - content: "下次造成的伤害-1", - }, - }, - player2: { - trigger: { player: "damageBegin3" }, - forced: true, - charlotte: true, - filter: function (event, player) { - return !event.stdjinjian_player; - }, - content: function () { - trigger.num++; - trigger.stdjinjian_player2 = true; - player.removeSkill("stdjinjian_player2"); - }, - marktext: " +1 ", - intro: { - content: "下次受到的伤害+1", - }, - }, - }, - ai: { - maixie_defend: true, - threaten: 0.9, - effect: { - target: function (card, player, target) { - if (player.hasSkillTag("jueqing", false, target)) return; - if (player._stdjinjian_tmp) return; - const count = player.storage.counttrigger; - if (count && count.stdjinjian_player && count.stdjinjian_player > 0) return; - if (_status.event.getParent("useCard", true) || _status.event.getParent("_wuxie", true)) return; - if (get.tag(card, "damage")) { - if (target.hasSkill("stdjinjian_player2")) { - return [1, -2]; - } else { - if (get.attitude(player, target) > 0) { - return [0, 0.2]; - } - if (get.attitude(player, target) < 0 && !player.hasSkillTag("damageBonus")) { - var sha = player.getCardUsable({ name: "sha" }); - player._stdjinjian_tmp = true; - var num = player.countCards("h", function (card) { - if (card.name == "sha") { - if (sha == 0) { - return false; - } else { - sha--; - } - } - return get.tag(card, "damage") && player.canUse(card, target) && get.effect(target, card, player, player) > 0; - }); - delete player._stdjinjian_tmp; - if (player.hasSkillTag("damage")) { - num++; - } - if (num < 2) { - return [0, 0.8]; - } - } - } - } - }, - }, - }, - }, - //李傕 - stdxiongsuan: { - audio: "xinfu_langxi", - trigger: { player: "phaseZhunbeiBegin" }, - filter(event, player) { - return player.isMaxHp(); - }, - async cost(event, trigger, player) { - event.result = await player - .chooseTarget( - "请选择【凶算】的目标", - lib.translate.stdxiongsuan_info, - (card, player, target) => { - return target.getHp() == player.getHp(); - }, - [1, Infinity], - true - ) - .set("ai", target => { - const player = get.event("player"); - return get.damageEffect(target, player, player); - }) - .forResult(); - }, - locked: true, - async content(event, trigger, player) { - for (const i of event.targets) { - await i.damage(); - } - }, - ai: { - effect: { - target(card, player, target) { - if ( - target.hp <= 1 || - !target.hasFriend() || - !_status.currentPhase || - !get.tag(card, "damage") - ) return; - let hp = target.hp - 1; - if (game.hasPlayer(cur => { - return cur.hp > hp; - })) return; - let ori = game.countPlayer(cur => { - return cur.hp === hp + 1 && get.attitude(target, cur) <= 0; - }), now = game.countPlayer(cur => { - return cur.hp === hp && get.attitude(target, cur) <= 0; - }), seat = 1, tar = _status.currentPhase.next; - while (tar !== target) { - if (get.attitude(target, tar) <= 0) seat++; - tar = tar.next; - } - return [1, 2 * (now - ori) / seat]; - } - } - } - }, - //程普 - stdchunlao: { - audio: "chunlao", - trigger: { player: "phaseDiscardEnd" }, - filter(event, player) { - return ( - (event.cards || []).length >= 2 && - game.hasPlayer(target => { - return target != player && target.countCards("h"); - }) - ); - }, - async cost(event, trigger, player) { - const cards = trigger.cards; - event.result = await player - .chooseTarget(get.prompt("stdchunlao"), "用" + get.translation(cards) + "交换一名其他角色的手牌", (card, player, target) => { - return target != player && target.countCards("h"); - }) - .set("ai", target => { - return get.event("cards").length - target.countCards("h") - 0.5; - }) - .set("cards", cards) - .forResult(); - }, - async content(event, trigger, player) { - const cards = trigger.cards, - target = event.targets[0]; - await target.loseToDiscardpile(target.getCards("h")); - await target.gain(cards, "gain2").set("giver", player); - if (player.isDamaged()) { - const bool = await target - .chooseBool("是否令" + get.translation(player) + "回复1点体力?") - .set("choice", get.recoverEffect(player, target, target) > 0) - .forResult("bool"); - if (bool) { - target.line(player); - await player.recover(); - } - } - }, - }, - //文鸯 - stdquedi: { - audio: "dbquedi", - enable: "chooseToUse", - filterCard: { name: "sha" }, - position: "hes", - viewAs: { name: "juedou" }, - viewAsFilter(player) { - if (!player.countCards("hes", { name: "sha" })) return false; - }, - check(card) { - return 6 - get.value(card); - }, - }, - //邓芝 - //只因盟 - stdzhiyinmeng: { - audio: "weimeng", - trigger: { player: "phaseZhunbeiBegin" }, - filter(event, player) { - return player.countCards("he"); - }, - async cost(event, trigger, player) { - event.result = await player - .chooseCardTarget({ - prompt: get.prompt2("stdzhiyinmeng"), - filterTarget: lib.filter.notMe, - filterCard: true, - position: "he", - selectCard: [1, Infinity], - complexCard: true, - complexTarget: true, - complexSelect: true, - ai1(card) { - if (ui.selected.cards.length && card.name != "du") return 0; - if (card.name == "du") return 114514; - return 5 - get.value(card); - }, - ai2(target) { - if (!ui.selected.cards.length) return 0; - const player = get.event("player"), - att = get.attitude(player, target); - if (ui.selected.cards[0].name == "du") { - if (!target.hasSkillTag("nodu")) return -att; - return -0.00001 * att; - } - return att; - }, - }) - .forResult(); - }, - async content(event, trigger, player) { - const target = event.targets[0]; - await player.give(event.cards, target); - await target.chooseToGive("he", [1, Infinity], player); - }, - }, - stdhehe: { - audio: "jianliang", - trigger: { player: "phaseDrawEnd" }, - filter(event, player) { - return game.hasPlayer(target => { - return target != player && target.countCards("h") == player.countCards("h"); - }); - }, - async cost(event, trigger, player) { - event.result = await player - .chooseTarget( - get.prompt2("stdhehe"), - (card, player, target) => { - return target != player && target.countCards("h") == player.countCards("h"); - }, - [1, 2] - ) - .set("ai", target => { - const player = get.event("player"); - return get.effect(target, { name: "draw" }, player, player); - }) - .forResult(); - }, - locked: true, - async content(event, trigger, player) { - await game.asyncDraw(event.targets); - await game.asyncDelayx(); - }, - }, - //张翼 - stdzhiyi: { - audio: "zhiyi", - trigger: { global: "phaseEnd" }, - filter(event, player) { - return player.getHistory("useCard", evt => { - return evt.card.name == "sha"; - }).length; - }, - forced: true, - async content(event, trigger, player) { - const result = await player.chooseUseTarget("执义:视为使用【杀】,或摸一张牌", { name: "sha" }, false).forResult(); - if (!result.bool) await player.draw(); - }, - }, - //大魏汉尼拔 - stdshefu: { - audio: "shefu", - trigger: { player: "phaseJieshuBegin" }, - filter(event, player) { - return player.countCards("h"); - }, - async cost(event, trigger, player) { - event.result = await player - .chooseCard(get.prompt("stdshefu"), "将一张手牌置于武将牌上", "h") - .set("ai", card => { - return ( - (lib.card.list - .slice() - .map(list => list[2]) - .filter(name => { - return card.name == name; - }).length - - 1) / - (get.value(card) || 0.5) - ); - }) - .forResult(); - }, - content() { - player.addToExpansion(event.cards, player, "giveAuto").gaintag.add("stdshefu"); - }, - marktext: "伏", - intro: { - markcount: "expansion", - mark(dialog, _, player) { - const cards = player.getExpansions("stdshefu"); - if (player.isUnderControl(true) && cards.length) dialog.addAuto(cards); - else return "共有" + get.cnNumber(cards.length) + "张“伏兵”"; - }, - }, - onremove(player, skill) { - const cards = player.getExpansions(skill); - if (cards.length) player.loseToDiscardpile(cards); - }, - group: "stdshefu_effect", - subSkill: { - effect: { - audio: "shefu", - trigger: { global: "useCard" }, - filter(event, player) { - return player.getExpansions("stdshefu").some(card => card.name == event.card.name); - }, - async cost(event, trigger, player) { - let result = await player - .chooseButton(["###" + get.prompt("stdshefu") + "###弃置一张同名牌,令此牌无效", player.getExpansions("stdshefu")]) - .set("filterButton", button => { - return button.link.name == get.event().getTrigger().card.name; - }) - .set("ai", button => { - return get.event("goon") ? 1 : 0; - }) - .set("goon", lib.skill.sbkanpo.subSkill.kanpo.check(trigger, player)) - .forResult(); - if (result.bool && result.links) { - result.cards = result.links.slice(); - delete result.links; - } - event.result = result; - }, - async content(event, trigger, player) { - await player.loseToDiscardpile(event.cards); - trigger.targets.length = 0; - trigger.all_excluded = true; - }, - }, - }, - }, - stdyibing: { - audio: "benyu", - trigger: { global: "dying" }, - filter(event, player) { - return event.player != player && event.player.countCards("h"); - }, - direct: true, - content() { - const target = trigger.player; - player.gainPlayerCard(target, "h", true).set("prompt", get.prompt("stdyibing", target)).logSkill = ["stdyibing", target]; - }, - }, - //樊玉凤 - stdbazhan: { - audio: "bazhan", - enable: "phaseUse", - filter(event, player) { - return player.countCards("h") > 0; - }, - filterCard: true, - position: "h", - filterTarget(card, player, target) { - return target != player && target.hasSex("male"); - }, - discard: false, - lose: false, - delay: false, - usable: 1, - check(card) { - if (card.name == "du") return 114514; - return 5 - get.value(card); - }, - async content(event, trigger, player) { - const target = event.target; - await player.give(event.cards, target, "visible"); - await target - .chooseToGive( - player, - (card, player) => { - return get.type2(card) != get.type2(get.event("cards")[0]); - }, - "he" - ) - .set("cards", event.cards); - }, - ai: { - order: 10, - result: { - target(player, target) { - if (!ui.selected.cards.length) return 0; - const cardxx = ui.selected.cards[0]; - if (cardxx.name == "du") return -100; - if (!player.hasSkill("stdzhanying")) return 1; - if (target.countMark("stdzhanying_count") == target.countCards("h") + 1) { - const cards = player.getCards("hs", card => { - return card != cardxx && get.tag(card, "damage") && player.canUse(card, target) && get.effect(target, card, player, player) > 0; - }); - if (!cards.length) return 1; - let cardx = cards.filter(card => get.name(card) == "sha"); - cardx.sort((a, b) => get.effect(target, b, player, player) - get.effect(target, a, player, player)); - cardx = cardx.slice(Math.min(cardx.length, player.getCardUsable("sha")), cardx.length); - cards.removeArray(cardx); - return -cards.reduce((sum, card) => sum + get.effect(target, card, player, player), 0); - } - return 1; - }, - }, - }, - }, - stdzhanying: { - audio: "jiaoying", - trigger: { global: "damageBegin2" }, - filter(event, player) { - if (_status.currentPhase !== player) return false; - return event.player.countCards("h") > event.player.countMark("stdzhanying_count"); - }, - forced: true, - logTarget: "player", - content() { - trigger.increase("num"); - }, - global: "stdzhanying_mark", - subSkill: { - count: { - charlotte: true, - onremove: true, - intro: { - markcount: storage => (storage || 0).toString(), - content: "本回合开始时手牌数为#张", - }, - }, - mark: { - charlotte: true, - trigger: { global: "phaseBegin" }, - filter(event, player) { - return event.player.hasSkill("stdzhanying", null, null, false); - }, - forced: true, - popup: false, - firstDo: true, - content() { - player.addTempSkill("stdzhanying_count"); - player.addMark("stdzhanying_count", player.countCards("h"), false); - }, - mod: { - cardEnabled(card, player) { - if (!_status.currentPhase || !_status.currentPhase.hasSkill("stdzhanying")) return; - if (get.color(card) == "red" && player.countMark("stdzhanying_count") < player.countCards("h")) return false; - }, - cardSavable(card, player) { - if (!_status.currentPhase || !_status.currentPhase.hasSkill("stdzhanying")) return; - if (get.color(card) == "red" && player.countMark("stdzhanying_count") < player.countCards("h")) return false; - }, - }, - }, - }, - }, - //F1 - stdtiaohe: { - audio: "fyjianyu", - enable: "phaseUse", - usable: 1, - filter(event, player) { - return game.hasPlayer(tar1 => { - return tar1.countDiscardableCards(player, "e", i => get.subtype(i) == "equip2") && game.hasPlayer(tar2 => { - return tar1 !== tar2 && tar2.countDiscardableCards(player, "e"); - }); - }); - let e = 0, fj = false; - game.countPlayer(target => { - let es = target.getDiscardableCards(player, "e"), js = target.getDiscardableCards(player, "j", i => get.type(i) == "equip"); - if (es.length) e++; - e += js.length; - if (!fj && (es.some(card => get.subtype(card) == "equip2") || js.some(card => get.subtype(card) == "equip2"))) fj = true; - }); - return fj && e >= 2; - }, - filterTarget(card, player, target) { - if (!ui.selected.targets.length || ui.selected.targets[0].countDiscardableCards(player, "e", i => get.subtype(i) == "equip2")) { - return target.countDiscardableCards(player, "e"); - } - return target.countDiscardableCards(player, "e", i => get.subtype(i) == "equip2"); - let e = 0; - let es = target.getDiscardableCards(player, "e"), js = target.getDiscardableCards(player, "j", i => get.type(i) == "equip"); - if (es.length) e++; - e += js.length; - if (!e) return false; - if (!ui.selected.targets.length) return true; - if (!ui.selected.targets[0].countDiscardableCards(player, "ej", i => get.subtype(i) == "equip2")) { - return es.some(card => get.subtype(card) == "equip2") || js.some(card => get.subtype(card) == "equip2"); - } - return true; - }, - selectTarget: function() { - return 2; - if (!ui.selected.targets.length) return [1, 2]; - let e = 0, player = get.event("player"), target = ui.selected.targets[0]; - let es = target.getDiscardableCards(player, "e"), js = target.getDiscardableCards(player, "j", i => get.type(i) == "equip"); - if (es.length) e++; - e += js.length; - if (e >= 2 && (es.some(card => get.subtype(card) == "equip2") || js.some(card => get.subtype(card) == "equip2"))) return [1, 2]; - return 2; - }, - complexTarget: true, - multitarget: true, - multiline: true, - async content(event, trigger, player) { - const targets = event.targets.slice(); - if (targets.length == 1) { - await player.discardPlayerCard("ej", targets[0], true, 2).set("filterButton", button => { - let position = get.position(button.link), subtype = get.subtype(button.link); - if (!subtype || !subtype.startsWith("equip")) return false; - if (ui.selected.buttons.length) { - let pos = get.position(ui.selected.buttons[0].link), sub = get.subtype(ui.selected.buttons[0].link); - if (pos == "e" && position == "e") return false; - if (sub == "equip2") return true; - return subtype == "equip2"; - } - if (position == "e") { - if (!get.event("js").some(i => get.subtype(i) == "equip2")) return subtype == "equip2"; - return true; - } - if (!get.event("es").length) return subtype == "equip2"; - return true; - }).set("es", targets[0].getDiscardableCards(player, "e", i => get.subtype(i) == "equip2")).set("js", targets[0].getDiscardableCards(player, "j", i => get.type(i) == "equip")); - return; - } - let canfj = targets.filter(target => { - return target.countDiscardableCards(player, "e", i => get.subtype(i) == "equip2"); - }); - for (let i = 0; i < 2; i++) { - if (i && canfj.includes(targets[i]) && !targets[i].countDiscardableCards(player, "e", i => get.subtype(i) == "equip2")) break; - const result = await player - .discardPlayerCard("e", targets[i], true) - .set("filterButton", button => { - if (get.event("fj")) return get.subtype(button.link) == "equip2"; - return true; - return get.type(button.link) == "equip"; - }) - .set("fj", canfj.length === 1 && canfj.includes(targets[i])) - .forResult(); - if (result.bool && get.subtype(result.cards[0]) == "equip2") { - canfj = []; - } - } - }, - ai: { - order: 10, - result: { - target(player, target) { - let att = get.attitude(player, target), es = []; - target.countDiscardableCards(player, "e").forEach(i => { - es.push(get.value(i, target)); - }); - let min = Math.min(...es), max = Math.max(...es), ext = target.hasSkillTag("noe") ? 10 : 0; - if (att <= 0) return ext - max; - return ext - min; - } - }, - }, - }, - stdqiansu: { - audio: "shengxi_feiyi", - trigger: { target: "useCardToTargeted" }, - filter(event, player) { - return get.type2(event.card) == "trick" && !player.countCards("e"); - }, - frequent: true, - content() { - player.draw(); - }, - ai: { - noe: true, - effect: { - target(card, player, target) { - if (target.countCards("e")) return; - if (target == player && get.type(card) == "equip" && get.equipValue(card) < 5) return 0; - if (get.type2(card) == "trick") return [1, 2]; - }, - }, - }, - }, //标准版甘夫人 stdshushen: { audio: "shushen", @@ -1219,7 +168,7 @@ const skills = { next.set("skillwarn", "替" + get.translation(player) + "打出一张闪"); next.autochoose = lib.filter.autoRespondShan; next.set("source", player); - bool = (await next).result.bool; + bool = await next.forResultBool(); } } player.storage.hujiaing = false; @@ -1347,7 +296,7 @@ const skills = { trigger.player.judging[0] = chooseCardResultCards[0]; trigger.orderingCards.addArray(chooseCardResultCards); game.log(trigger.player, "的判定牌改为", chooseCardResultCards[0]); - game.asyncDelay(2); + await game.delay(2); }, ai: { rejudge: true, @@ -1475,7 +424,7 @@ const skills = { async content(event, trigger, player) { player.gainMultiple(event.targets); trigger.changeToZero(); - game.asyncDelay(); + await game.delay(); }, ai: { threaten: 2, @@ -1652,7 +601,7 @@ const skills = { let bool; if (judge > 0) { event.cards.push(card); - bool = (await player.chooseBool("是否再次发动【洛神】?").set("frequentSkill", "luoshen")).result.bool; + bool = await player.chooseBool("是否再次发动【洛神】?").set("frequentSkill", "luoshen").forResultBool(); } else { for (let i = 0; i < event.cards.length; i++) { if (get.position(event.cards[i], true) != "o") { @@ -1693,7 +642,7 @@ const skills = { let bool; if (judge > 0) { event.cards.push(card); - bool = lib.config.autoskilllist.includes("luoshen") ? (await player.chooseBool("是否再次发动【洛神】?")).result.bool : true; + bool = lib.config.autoskilllist.includes("luoshen") ? await player.chooseBool("是否再次发动【洛神】?").forResultBool() : true; } else { for (let i = 0; i < event.cards.length; i++) { if (get.position(event.cards[i]) != "s") { @@ -1849,7 +798,7 @@ const skills = { }, }, effect: { - target(card, player, target) { + target_use(card, player, target) { if (player == target && get.type(card) == "equip") { if (player.countCards("e", { subtype: get.subtype(card) })) { const players = game.filterPlayer(); @@ -1928,7 +877,7 @@ const skills = { chooseToRespondEvent.set("skillwarn", "替" + get.translation(player) + "打出一张杀"); chooseToRespondEvent.noOrdering = true; chooseToRespondEvent.autochoose = lib.filter.autoRespondSha; - const { bool, card, cards } = (await chooseToRespondEvent).result; + const { bool, card, cards } = await chooseToRespondEvent.forResult(); if (bool) { trigger.card = card; trigger.cards = cards; @@ -2076,7 +1025,7 @@ const skills = { game.cardsGotoOrdering(cards); const next = player.chooseToMove(); next.set("list", [["牌堆顶", cards], ["牌堆底"]]); - next.set("prompt", "观星:点击将牌移动到牌堆顶或牌堆底"); + next.set("prompt", "观星:点击或拖动将牌移动到牌堆顶或牌堆底"); next.processAI = list => { const cards = list[0][1], player = _status.event.player; @@ -2118,7 +1067,7 @@ const skills = { }); player.popup(get.cnNumber(top.length) + "上" + get.cnNumber(bottom.length) + "下"); game.log(player, "将" + get.cnNumber(top.length) + "张牌置于牌堆顶"); - game.asyncDelayx(); + await game.delayx(); }, ai: { threaten: 1.2, @@ -2246,13 +1195,6 @@ const skills = { }, }, }, - mashu2: { - mod: { - globalFrom(from, to, distance) { - return distance - 1; - }, - }, - }, feiying: { mod: { globalTo(from, to, distance) { @@ -2372,7 +1314,7 @@ const skills = { }, delay: 0, async content(event, trigger, player) { - if (!player.hasSkill("xinzhiheng_delay")) game.asyncDelayx(); + if (!player.hasSkill("xinzhiheng_delay")) await game.delayx(); player.draw(event.cards.length); }, group: "xinzhiheng_draw", @@ -2700,12 +1642,11 @@ const skills = { source: trigger.player, card: trigger.card, }) - .setHiddenSkill(event.name) + .setHiddenSkill(event.name.slice(0, -5)) .forResult(); }, async content(event, trigger, player) { const target = event.targets[0]; - player.logSkill(event.name, target); player.discard(event.cards); const evt = trigger.getParent(); evt.triggeredTargets2.remove(player); @@ -2763,8 +1704,11 @@ const skills = { ai: { threaten: 0.8, effect: { - target(card) { - if (card.name == "guohe" || card.name == "liuxinghuoyu") return 0.5; + player_use(card, player, target) { + if (player.countCards("h") === 1) return [1, 0.8]; + }, + target(card, player, target) { + if (get.tag(card, "loseCard") && target.countCards("h") === 1) return 0.5; }, }, noh: true, @@ -3158,7 +2102,7 @@ const skills = { async content(event, trigger, player) { const useCardEvent = event.targets[1].useCard({ name: "juedou", isCard: true }, "nowuxie", event.targets[0], "noai"); useCardEvent.animate = false; - game.asyncDelay(0.5); + await game.delay(0.5); }, ai: { order: 8, diff --git a/character/standard/sort.js b/character/standard/sort.js index d79f4b84ae..149ca99df1 100644 --- a/character/standard/sort.js +++ b/character/standard/sort.js @@ -3,7 +3,6 @@ const characterSort = { standard_2013: ["old_re_lidian", "huaxiong", "re_yuanshu"], standard_2019: ["gongsunzan", "xf_yiji"], standard_2023: ["std_panfeng", "ganfuren"], - standard_shaoyin: ["std_sunhao", "std_mateng", "std_mayunlu", "std_jianggan", "std_zhouchu", "std_lvlingqi", "std_dc_yanghu", "std_dc_luotong", "std_lijue", "std_chengpu", "std_db_wenyang", "std_re_dengzhi", "std_zhangyì", "std_chengyu", "std_fanyufeng", "std_feiyi"], }; const characterSortTranslate = { @@ -11,7 +10,6 @@ const characterSortTranslate = { standard_2013: "2013版标准包", standard_2019: "2019版标准包", standard_2023: "2023版标准包", - standard_shaoyin: "四象封印·少阴", }; export { characterSort, characterSortTranslate }; diff --git a/character/standard/translate.js b/character/standard/translate.js index ec79c84bd1..d6320c4da6 100644 --- a/character/standard/translate.js +++ b/character/standard/translate.js @@ -62,7 +62,6 @@ const translates = { longdan1: "龙胆", longdan2: "龙胆", mashu: "马术", - mashu2: "马术", feiying: "飞影", tieji: "铁骑", jizhi: "集智", @@ -109,7 +108,6 @@ const translates = { kongcheng_info: "锁定技,当你没有手牌时,你不能成为【杀】或【决斗】的目标。", longdan_info: "你可以将【杀】当做【闪】,或将【闪】当做【杀】使用或打出。", mashu_info: "锁定技,你计算与其他角色的距离时-1。", - mashu2_info: "锁定技,你计算与其他角色的距离时-1。", feiying_info: "锁定技,其他角色计算与你的距离时+1。", tieji_info: "当你使用【杀】指定目标后,你可以进行判定。若结果为红色,则此【杀】不可被闪避。", jizhi_info: "当你使用非转化的普通锦囊牌时,你可以摸一张牌。", @@ -181,84 +179,6 @@ const translates = { stdshushen: "淑慎", stdshushen_info: "当你回复1点体力时,你可以令一名其他角色摸一张牌(若其没有手牌则改为摸两张牌)。", old_re_lidian: "李典", - std_sunhao: "标孙皓", - std_sunhao_prefix: "标", - std_mateng: "标马腾", - std_mateng_prefix: "标", - std_mayunlu: "标马云騄", - std_mayunlu_prefix: "标", - std_jianggan: "标蒋干", - std_jianggan_prefix: "标", - std_zhouchu: "标周处", - std_zhouchu_prefix: "标", - std_lvlingqi: "标吕玲绮", - std_lvlingqi_prefix: "标", - std_dc_yanghu: "标羊祜", - std_dc_yanghu_prefix: "标", - std_dc_luotong: "标骆统", - std_dc_luotong_prefix: "标", - std_lijue: "标李傕", - std_lijue_prefix: "标", - std_chengpu: "标程普", - std_chengpu_prefix: "标", - std_db_wenyang: "标文鸯", - std_db_wenyang_prefix: "标", - std_re_dengzhi: "标邓芝", - std_re_dengzhi_prefix: "标", - std_zhangyì: "标张翼", - std_zhangyì_prefix: "标", - std_chengyu: "标程昱", - std_chengyu_prefix: "标", - std_fanyufeng: "标樊玉凤", - std_fanyufeng_prefix: "标", - std_feiyi: "标费祎", - std_feiyi_prefix: "标", - stdcanshi: "残蚀", - stdcanshi_info: "锁定技,摸牌阶段,你改为摸X张牌(X为场上的已受伤角色且X至少为1)。然后本回合你使用【杀】或普通锦囊牌指定目标后,若其已受伤,你弃置一张牌。", - stdxiongyi: "雄异", - stdxiongyi_info: "限定技,出牌阶段,你可以选择任意名角色,这些角色依次选择是否使用一张不可被响应的【杀】,然后这些角色重复此流程直至有角色不使用【杀】。", - stdyouji: "游骑", - stdyouji_info: "主公技,准备阶段,你可以移动一名群势力角色的一张坐骑牌。", - stdfengpo: "凤魄", - stdfengpo_info: "当你使用【杀】造成伤害时,你可以弃置你或其的一张牌,若以此法弃置了方片牌,则此伤害+1。", - stddaoshu: "盗书", - stddaoshu_info: "每轮限一次,一名角色的准备阶段,你可以展示除其外一名角色的一张牌,然后令其获得此牌,且你与其本回合不能使用与此牌花色相同的牌。", - stddaizui: "戴罪", - stddaizui_info: "锁定技,当你受到伤害后,你视为本轮未发动过〖盗书〗。", - stdxiongxia: "凶侠", - stdxiongxia_info: "你可以将两张牌当作【决斗】对两名其他角色使用。你以此法使用的【决斗】结算完毕后,若所有目标角色都受到了此牌造成的伤害,则〖凶侠〗于本回合失效。", - stdhuizhan: "挥戟", - stdhuizhan_info: "你使用【杀】可以额外指定至多两个目标。若如此做,目标角色响应此【杀】时,其他目标角色可以代替其使用【闪】。", - stdmingfa: "明伐", - stdmingfa_info: "出牌阶段,你可以对一名体力值大于1的角色造成1点伤害,然后此技能失效直至其死亡或回复体力。", - stdjinjian: "进谏", - stdjinjian_info: "每回合每项各限一次,当你造成/受到伤害时,你可令此伤害+1/-1,然后你本回合内下一次造成的伤害-1/+1且不能触发〖进谏〗。", - stdrenzheng: "仁政", - stdrenzheng_info: "锁定技,当有伤害被防止时,你令当前回合角色摸一张牌。", - stdxiongsuan: "凶算", - stdxiongsuan_info: "锁定技,准备阶段,若你的体力值为全场最多,则你须对至少一名体力值等于你的角色各造成1点伤害。", - stdchunlao: "醇醪", - stdchunlao_info: "弃牌阶段结束时,若你本阶段弃置了不少于两张牌,则你可以用这些牌交换一名其他角色的手牌,然后其可以令你回复1点体力。", - stdquedi: "却敌", - stdquedi_info: "你可以将【杀】当作【决斗】使用。", - stdzhiyinmeng: "急盟", - stdzhiyinmeng_info: "准备阶段,你可以交给一名其他角色任意张牌,然后其可以交给你任意张牌。", - stdhehe: "和合", - stdhehe_info: "摸牌阶段结束时,你可以令至多两名手牌数与你相同的其他角色各摸一张牌。", - stdzhiyi: "执义", - stdzhiyi_info: "锁定技,一名角色的回合结束时,若你本回合使用过【杀】,则你视为使用【杀】或摸一张牌。", - stdshefu: "设伏", - stdshefu_info: "①结束阶段,你可以将一张手牌称为“伏兵”扣置于武将牌上。②一名角色使用牌时,你可以移去武将牌上的一张与此牌同名的“伏兵”并令此牌无效。", - stdyibing: "益兵", - stdyibing_info: "一名角色进入濒死状态时,你可以获得其一张牌。", - stdbazhan: "把盏", - stdbazhan_info: "出牌阶段限一次,你可以交给一名男性角色一张手牌,然后其可以交给你一张与此牌类别不同的牌。", - stdzhanying: "醮影", - stdzhanying_info: "锁定技,你的回合内,手牌数比回合开始时多的角色不能使用红色牌且受到的伤害+1。", - stdtiaohe: "调和", - stdtiaohe_info: "出牌阶段限一次,你可以弃置场上的一张装备牌和一张防具牌(不能为同一名角色的牌)。", - stdqiansu: "谦素", - stdqiansu_info: "当你成为锦囊牌的目标后,若你的装备区没有牌,则你可以摸一张牌。", }; export default translates; diff --git a/character/standard/voices.js b/character/standard/voices.js index 89d9221f50..4ae1ded239 100644 --- a/character/standard/voices.js +++ b/character/standard/voices.js @@ -102,9 +102,9 @@ export default { "#biyue1": "失礼了~", "#biyue2": "羡慕吧~", "#diaochan:die": "父亲大人,对不起……", - "#yaowu1": "好大一股杀气啊!", - "#yaowu2": "好大一股酒气啊!", - "#huaxiong:die": "皮厚不挡刀啊……", + "#yaowu1": "大人有大量,不和你计较!", + "#yaowu2": "哼,先让你尝点甜头!", + "#huaxiong:die": "这,怎么可能……", "#yicong1": "冲啊!", "#yicong2": "众将听令,排好阵势,御敌!", "#gongsunzan:die": "我军将败,我已无颜苟活于世……", diff --git a/character/swd.js b/character/swd.js index 1fca7a7475..d64493431e 100644 --- a/character/swd.js +++ b/character/swd.js @@ -64,7 +64,7 @@ game.import("character", function () { // swd_wushi:['male','wei',3,['zhoufu','yingbin','xuying']], // swd_lanmoshen:['female','wei',3,['bingjian','lieren']], swd_huanglei: ["male", "qun", 3, ["jilve", "gongshen", "gaizao"]], - // swd_libai:['female','qun',3,['miaobi','zhexian']], + // swd_libai:['male','qun',3,['miaobi','zhexian']], swd_kendi: ["male", "qun", 3, ["zhanxing", "kbolan"]], // swd_lijing:['male','qun',4,['tianyi','zhuhai']], swd_lilian: ["female", "qun", 3, ["swd_wuxie", "lqingcheng"]], @@ -379,158 +379,6 @@ game.import("character", function () { }, }, }, - cyzhencha: { - enable: "phaseUse", - usable: 1, - filter: function (event, player) { - if ( - !game.hasPlayer(function (current) { - return current != player && current.countCards("h"); - }) - ) { - return false; - } - if (!player.countCards("h", { type: "basic" })) return false; - var es = player.getCards("e"); - for (var i = 0; i < es.length; i++) { - if ( - !es[i].classList.contains("epic") && - !es[i].classList.contains("legend") && - !es[i].classList.contains("gold") - ) { - return true; - } - } - return false; - }, - filterCard: { type: "basic" }, - filterTarget: function (card, player, target) { - return target != player && target.countCards("h"); - }, - check: function (card) { - return 7 - get.value(card); - }, - content: function () { - "step 0"; - player.viewHandcards(target); - "step 1"; - if (target.countCards("h", { color: get.color(cards[0]) })) { - var es = player.getCards("e"); - es.randomSort(); - for (var i = 0; i < es.length; i++) { - if ( - !es[i].classList.contains("epic") && - !es[i].classList.contains("legend") && - !es[i].classList.contains("gold") - ) { - es[i].classList.add("gold"); - es[i].nopower = true; - es[i].storage.cyzhencha = true; - break; - } - } - var num = 0; - for (var i = 0; i < es.length; i++) { - if (es[i].storage.cyzhencha) { - num++; - } - } - var list = ["shuiyun", "liuzi", "yijin", "qingling", "qiandian"]; - for (var i = 0; i < list.length; i++) { - if (i < num) { - player.addSkill("cyzhencha_" + list[i]); - } - } - } else { - player.draw(); - } - }, - ai: { - order: 2, - result: { - player: function (player, target) { - return target.countCards("h"); - }, - }, - }, - }, - cyzhencha_shuiyun: { - trigger: { player: "phaseBegin" }, - direct: true, - thundertext: true, - content: function () { - "step 0"; - player - .chooseTarget( - [1, 1], - "水云:你可以弃置一名角色的一张牌", - function (card, player, target) { - if (player == target) return false; - return target.countCards("he") > 0; - } - ) - .set("autodelay", 0.5).ai = function (target) { - return -get.attitude(player, target); - }; - "step 1"; - if (result.bool) { - player.logSkill("cyzhencha_shuiyun", result.targets); - player.discardPlayerCard(result.targets[0], "he", true); - } else { - event.finish(); - } - }, - onremove: function (player) { - _status.event.insert(lib.skill.cyzhencha_shuiyun.content, { player: player }); - }, - }, - cyzhencha_liuzi: { - trigger: { player: "phaseDrawBegin" }, - frequent: true, - thundertext: true, - content: function () { - trigger.num++; - }, - onremove: function (player) { - player.draw(); - }, - }, - cyzhencha_yijin: { - trigger: { player: "phaseBegin" }, - direct: true, - thundertext: true, - content: function () { - "step 0"; - player - .chooseTarget( - [1, 1], - "水云:你可以弃置一名角色的一张牌", - function (card, player, target) { - if (player == target) return false; - return target.countCards("he") > 0; - } - ) - .set("autodelay", 0.5).ai = function (target) { - return -get.attitude(player, target); - }; - "step 1"; - if (result.bool) { - player.logSkill("cyzhencha_shuiyun", result.targets); - player.discardPlayerCard(result.targets[0], "he", true); - } else { - event.finish(); - } - }, - onremove: function (player) { - _status.event.insert(lib.skill.cyzhencha_shuiyun.content, { player: player }); - }, - }, - cyzhencha_qingling: { - inhert: "cyzhencha_shuiyun", - }, - cyzhencha_qiandian: { - inhert: "cyzhencha_shuiyun", - }, cyqiaoxie_old: { enable: "phaseUse", filterCard: function (card) { @@ -544,7 +392,6 @@ game.import("character", function () { current.add(get.subtype(es[i])); } if (current.length == 5) return false; - // if(get.is.altered('xianjiang')&&player.countCards('e')) return false; if (player.countCards("h", { type: "trick" })) return true; if (player.countCards("h", { type: "delay" })) return true; return false; @@ -1258,7 +1105,7 @@ game.import("character", function () { }, ai: { effect: { - target_use(card, player, target, current) { + target(card, player, target, current) { if ( target == player && lib.skill.gaizao.filterx(card, target) && @@ -1716,84 +1563,6 @@ game.import("character", function () { player.die(); }, }, - hjifeng: { - enable: "phaseUse", - filter: function (event, player) { - if (!player.countCards("h")) return false; - if (player.countCards("h", { type: "jiqi" })) return false; - return true; - }, - discard: false, - prepare: "throw2", - usable: 1, - check: function (card) { - return 6 - get.value(card); - }, - filterCard: true, - content: function () { - var name = get.suit(cards[0]); - ui.cardPile.insertBefore(cards[0], ui.cardPile.firstChild); - switch (name) { - case "spade": - name = "qinglongzhigui"; - break; - case "club": - name = "baishouzhihu"; - break; - case "diamond": - name = "zhuquezhizhang"; - break; - case "heart": - name = "xuanwuzhihuang"; - break; - } - player.gain(get.cardPile(name) || game.createCard(name), "draw"); - }, - ai: { - order: 4, - result: { - player: 1, - }, - }, - }, - hjifeng_old: { - trigger: { player: "phaseEnd" }, - filter: function (event, player) { - if (!player.countCards("he", { type: "equip" })) return false; - if (player.countCards("h", { type: "jiqi" })) return false; - if ( - get.cardPile(function (card) { - return get.type(card) == "jiqi"; - }) - ) - return true; - return false; - }, - direct: true, - content: function () { - "step 0"; - player - .chooseToDiscard("he", "祭风:是否弃置一张装备牌并获得一张祭器牌?", { - type: "equip", - }) - .set("ai", function (card) { - return 6 - get.value(card); - }).logSkill = "hjifeng"; - "step 1"; - if (result.bool) { - var card = - get.cardPile(function (card) { - return get.type(card) == "jiqi" && card.name.indexOf("yuchan") != 0; - }) || - get.cardPile(function (card) { - return get.type(card) == "jiqi"; - }); - if (card) { - player.gain(card, "draw"); - } - } - }, - }, lmazui: { audio: "mazui", enable: "phaseUse", @@ -2089,21 +1858,6 @@ game.import("character", function () { threaten: 1.5, }, }, - zaowu: { - enable: "phaseUse", - usable: 1, - filter: function (event, player) { - return player.countCards("h", { suit: ["spade", "heart"] }) > 0; - }, - filterCard: { suit: ["spade", "heart"] }, - viewAs: { name: "fengyinzhidan" }, - check: function (card) { - return 7 - get.value(card); - }, - ai: { - order: 8.5, - }, - }, huanxia: { enable: "chooseToUse", filterCard: function (card) { @@ -2176,31 +1930,6 @@ game.import("character", function () { }, }, }, - kongmo: { - trigger: { player: "useCardAfter" }, - forced: true, - filter: function (event, player) { - if (event.parent.name == "kongmo") return false; - if (!event.targets || !event.card) return false; - var type = get.type(event.card); - if (type != "basic" && type != "trick") return false; - var card = game.createCard(event.card.name, event.card.suit, event.card.number); - for (var i = 0; i < event.targets.length; i++) { - if (!event.targets[i].isAlive()) return false; - if (!player.canUse({ name: event.card.name }, event.targets[i], false, false)) { - return false; - } - } - return true; - }, - content: function () { - var card = game.createCard(trigger.card.name, trigger.card.suit, trigger.card.number); - player.useCard(card, trigger.targets); - }, - ai: { - threaten: 2, - }, - }, huajing: { trigger: { source: "damageEnd" }, filter: function (event, player) { @@ -2318,18 +2047,14 @@ game.import("character", function () { }, }, bingfeng2: { + mark: true, + marktext: "封", + intro: { + content: "不能使用或打出手牌" + }, mod: { - cardEnabled: function () { - return false; - }, - cardUsable: function () { - return false; - }, - cardRespondable: function () { - return false; - }, - cardSavable: function () { - return false; + cardEnabled2: function (card) { + if (get.position(card) == "h") return false; }, }, trigger: { player: "turnOverAfter" }, @@ -2925,65 +2650,6 @@ game.import("character", function () { }, }, }, - hzhenwei: { - trigger: { global: "shaBefore" }, - direct: true, - priority: 5, - filter: function (event, player) { - if (player == event.target || player == event.player) return false; - if (!player.countCards("he")) return false; - return get.distance(event.player, player, "attack") <= 1; - }, - content: function () { - "step 0"; - var save = false; - if (get.attitude(player, trigger.target) > 2) { - if ( - player.countCards("h", "shan") || - player.getEquip(2) || - trigger.target.hp == 1 || - player.hp > trigger.target.hp + 1 - ) { - if ( - !trigger.target.countCards("h", "shan") || - trigger.target.countCards("h") < player.countCards("h") - ) { - save = true; - } - } - } - var next = player.chooseToDiscard("he", get.prompt("hzhenwei")); - next.logSkill = ["hzhenwei", trigger.target]; - next.ai = function (card) { - if (save) { - return 7 - get.value(card); - } - return 0; - }; - "step 1"; - if (result.bool) { - trigger.target = player; - player.addSkill("hzhenwei2"); - game.delay(); - } - }, - ai: { - effect: { - target_use(card) { - if (card.name == "sha") return 1.3; - }, - }, - }, - }, - hzhenwei2: { - trigger: { target: "shaAfter" }, - forced: true, - popup: false, - content: function () { - player.draw(); - player.removeSkill("hzhenwei2"); - }, - }, fzhenwei: { trigger: { global: "respondEnd" }, filter: function (event, player) { @@ -3125,119 +2791,38 @@ game.import("character", function () { content: "card", }, }, - pingshen: { + guaili: { trigger: { source: "damageBegin" }, - unique: true, - silent: true, + filter: function (event) { + return ( + event.card && + event.card.name == "sha" && + event.parent.name != "_lianhuan" && + event.parent.name != "_lianhuan2" + ); + }, + forced: true, content: function () { - trigger.player.addSkill("pingshen2"); - trigger.player.storage.pingshen = player; + trigger.num++; + player.addSkill("guaili2"); }, - ai: { - neg: true + }, + guaili2: { + trigger: { source: "damageEnd" }, + forced: true, + popup: false, + content: function () { + player.removeSkill("guaili2"); + player.chooseToDiscard(2, true); }, }, - pingshen2: { + xingzhui: { enable: "phaseUse", - unique: true, - mark: true, - init: function (player) { - player.storage.pingshen2 = false; - }, - filter: function (event, player) { - return !player.storage.pingshen2 && player.storage.pingshen.isAlive(); - }, + usable: 1, filterCard: true, - filterTarget: function (card, player, target) { - return target == player.storage.pingshen; - }, - selectTarget: -1, position: "he", - content: function () { - player.storage.pingshen2 = true; - player.unmarkSkill("pingshen2"); - player.gain(target.getCards("h"), target); - target.$give(target.countCards("h"), player); - player.turnOver(); - player.addSkill("pingshen3"); - }, - check: function (card) { - return 8 - get.value(card); - }, - intro: { - content: "limited", - }, - ai: { - order: 10, - result: { - player: function (player) { - if (player.classList.contains("turnedover")) return 10; - if (get.attitude(player, player.storage.pingshen) >= 0) { - return 0; - } - if (player.storage.pingshen.countCards("h") > player.storage.pingshen.hp) - return 1; - return 0; - }, - }, - effect: { - target: function (card, player, target) { - if (!target.storage.pingshen2) { - if (card.name == "guiyoujie") return [0, 1]; - } - }, - }, - }, - }, - pingshen3: { - trigger: { player: "phaseUseEnd" }, - forced: true, - popup: false, - content: function () { - "step 0"; - player.removeSkill("pingshen3"); - if (player.storage.pingshen.classList.contains("dead")) { - event.finish(); - } else { - player.chooseCard("he", true, player.storage.pingshen.hp); - } - "step 1"; - player.storage.pingshen.gain(result.cards, player); - player.$give(result.cards.length, player.storage.pingshen); - }, - }, - guaili: { - trigger: { source: "damageBegin" }, - filter: function (event) { - return ( - event.card && - event.card.name == "sha" && - event.parent.name != "_lianhuan" && - event.parent.name != "_lianhuan2" - ); - }, - forced: true, - content: function () { - trigger.num++; - player.addSkill("guaili2"); - }, - }, - guaili2: { - trigger: { source: "damageEnd" }, - forced: true, - popup: false, - content: function () { - player.removeSkill("guaili2"); - player.chooseToDiscard(2, true); - }, - }, - xingzhui: { - enable: "phaseUse", - usable: 1, - filterCard: true, - position: "he", - filterTarget: function (card, player, target) { - return player != target && target.countCards("he") > 0; + filterTarget: function (card, player, target) { + return player != target && target.countCards("he") > 0; }, check: function (card) { if (get.type(card) == "equip") { @@ -3488,48 +3073,6 @@ game.import("character", function () { }, }, linyun4: {}, - bofeng: { - mod: { - targetInRange: function (card, player, target) { - if (card.name == "sha" && player.hp >= target.hp) { - return true; - } - }, - }, - trigger: { player: "shaBegin" }, - check: function (event, player) { - return get.attitude(player, event.target) < 0; - }, - content: function () { - "step 0"; - trigger.target.chooseToRespond({ name: "shan" }); - "step 1"; - if (result.bool == false) { - trigger.untrigger(); - trigger.directHit = true; - player.addTempSkill("bofeng2", "shaEnd"); - } - }, - ai: { - threaten: 1.3, - }, - }, - bofeng2: { - trigger: { source: "damageBegin" }, - filter: function (event) { - return ( - event.card && - event.card.name == "sha" && - event.parent.name != "_lianhuan" && - event.parent.name != "_lianhuan2" - ); - }, - forced: true, - popup: false, - content: function () { - trigger.num++; - }, - }, hutian: { trigger: { player: "phaseEnd" }, direct: true, @@ -4157,62 +3700,6 @@ game.import("character", function () { trigger.player.addTempSkill("fengyin", { player: "phaseBegin" }); }, }, - fengmo: { - enable: "phaseUse", - usable: 1, - filter: function () { - return ( - game.countPlayer(function (current) { - return current.getEquip(1); - }) >= 1 - ); - }, - filterTarget: function (card, player, target) { - return player != target && !target.isTurnedOver(); - }, - content: function () { - "step 0"; - event.targets = []; - event.num = 0; - var players = game.filterPlayer(); - for (var i = 0; i < players.length; i++) { - if (players[i].getEquip(1)) { - event.targets.push(players[i]); - } - } - event.targets.sort(lib.sort.seat); - "step 1"; - if (num < event.targets.length) { - var targetn = event.targets[num]; - var card = targetn.getEquip(1); - if (card) { - targetn.discard(card); - } - event.num++; - event.redo(); - } - "step 2"; - target.draw(event.targets.length); - "step 3"; - target.turnOver(); - }, - ai: { - result: { - target: function (player, target) { - if (target.hasSkillTag("noturn")) return 0; - var num = game.countPlayer(function (current) { - return current.getEquip(1); - }); - if (target.hp == 1 && num < 3) { - return (num - 3) / 1.5; - } - return num - 3; - }, - }, - order: 10, - expose: 0.1, - }, - }, duanyue: { enable: "phaseUse", usable: 1, @@ -4375,7 +3862,7 @@ game.import("character", function () { }, }, effect: { - player: function (card, player) { + player_use: function (card, player) { if (_status.currentPhase != player) return; if ( get.type(card) == "equip" && @@ -4497,74 +3984,6 @@ game.import("character", function () { expose: 0.3, }, }, - xiaozhan: { - trigger: { global: "useCard" }, - priority: 15, - filter: function (event, player) { - return ( - event.card.name == "sha" && - event.player != player && - player.countCards("h", "sha") > 0 && - event.targets.includes(player) == false - ); - }, - direct: true, - content: function () { - "step 0"; - var effect = 0; - for (var i = 0; i < trigger.targets.length; i++) { - effect += get.effect(trigger.targets[i], trigger.card, trigger.player, player); - } - var str = "是否弃置一张杀令" + get.translation(trigger.player); - if (trigger.targets && trigger.targets.length) { - str += "对" + get.translation(trigger.targets); - } - str += "的" + get.translation(trigger.card) + "失效?"; - player.chooseToDiscard("h", { name: "sha" }, str).ai = function (card) { - if (effect < 0) { - return 9 - get.value(card); - } - return -1; - }; - "step 1"; - if (result.bool) { - trigger.cancel(); - player.logSkill("xiaozhan"); - } - }, - ai: { - threaten: 1.2, - expose: 0.1, - }, - }, - chuanyue: { - enable: "phaseUse", - usable: 1, - filter: function (event, player) { - return player.countCards("h") > 0; - }, - selectCard: 2, - filterCard: true, - discard: false, - prepare: "throw", - filterTarget: function (card, player, target) { - return lib.filter.targetEnabled({ name: "juedou" }, player, target); - }, - check: function (card) { - return Math.max(7 - get.value(card), 7 - get.useful(card)); - }, - content: function () { - player.useCard({ name: "juedou" }, targets, cards).animate = false; - }, - ai: { - result: { - target: function (player, target) { - return get.effect(target, { name: "juedou" }, player, target); - }, - }, - order: 8, - }, - }, dangping: { trigger: { source: "damageAfter" }, direct: true, @@ -4655,33 +4074,6 @@ game.import("character", function () { }, duishi2: {}, duishi3: {}, - guisi: { - trigger: { target: "shaBefore" }, - popup: false, - direct: true, - filter: function (event, player) { - return player.countCards("h"); - }, - content: function () { - "step 0"; - player.chooseCard( - "是否交给" + get.translation(trigger.player) + "一张牌并取消此杀?" - ).ai = function (card) { - if (get.attitude(player, trigger.player) > 0) { - return 9 - get.value(card); - } - if (player.countCards("h", { name: "shan" })) return -1; - return 7 - get.value(card); - }; - "step 1"; - if (result.bool) { - player.logSkill("guisi"); - trigger.player.gain(result.cards, player); - player.$give(result.cards, trigger.player); - trigger.cancel(); - } - }, - }, lianwu: { mod: { selectTarget: function (card, player, range) { @@ -4997,45 +4389,6 @@ game.import("character", function () { player.chooseToDiscard(player.maxHp - player.hp, "he", true); }, }, - milesxiehun: { - trigger: { player: "phaseEnd" }, - forced: true, - content: function () { - "step 0"; - event.num = 0; - event.targets = game.filterPlayer(); - event.targets.remove(player); - for (var i = 0; i < event.targets.length; i++) { - event.targets.sort(lib.sort.random); - } - event.targets.splice(Math.max(1, player.maxHp - player.hp)); - //event.targets.unshift(player); - "step 1"; - if (event.num < event.targets.length) { - var target = event.targets[event.num]; - target.discard(target.getCards("he").randomGet()); - event.num++; - event.redo(); - } - }, - }, - liaochen: { - trigger: { player: "phaseEnd" }, - forced: true, - content: function () { - "step 0"; - event.num = 0; - event.targets = game.filterPlayer(); - "step 1"; - if (event.num < event.targets.length) { - if (event.targets[event.num].countCards("he")) { - event.targets[event.num].chooseToDiscard(true, "he"); - } - event.num++; - event.redo(); - } - }, - }, aojian: { enable: "phaseUse", usable: 1, @@ -5160,22 +4513,17 @@ game.import("character", function () { }, }, shejie2: { - unique: true, + mark: true, + marktext: "界", + intro: { + content: "不能使用或打出手牌直到下一回合开始" + }, trigger: { player: "phaseBegin" }, forced: true, priority: 10, mod: { - cardEnabled: function () { - return false; - }, - cardUsable: function () { - return false; - }, - cardRespondable: function () { - return false; - }, - cardSavable: function () { - return false; + cardEnabled2: function (card) { + if (get.position(card) == "h") return false; }, }, content: function () { @@ -5372,45 +4720,6 @@ game.import("character", function () { noh: true, }, }, - miejing: { - init: function (player) { - player.storage.miejing = false; - }, - enable: "phaseUse", - filter: function (event, player) { - //if(player.maxHp<=1) return false; - return !player.storage.miejing; - }, - intro: { - content: "limited", - }, - mark: true, - line: "thunder", - filterTarget: function (card, player, target) { - return player != target; - }, - selectTarget: -1, - delay: false, - contentBefore: function () { - "step 0"; - game.delayx(); - "step 1"; - var cards = player.getCards("hej"); - for (var i = 0; i < cards.length; i++) { - if (get.color(cards[i]) != "black") { - cards.splice(i, 1); - i--; - } - } - cards.sort(lib.sort.random); - player.discard(cards); - player.storage.miejing = true; - player.unmarkSkill("miejing"); - }, - content: function () { - target.damage("thunder"); - }, - }, zhanlu: { enable: "phaseUse", filterCard: function (card) { @@ -5521,35 +4830,6 @@ game.import("character", function () { threaten: 1.1, }, }, - benlei: { - enable: "phaseUse", - viewAs: { name: "jingleishan", nature: "thunder" }, - filterCard: function (card, player) { - return true; - }, - selectCard: 3, - position: "he", - prompt: "将三张牌当作惊雷闪使用", - check: function (card) { - return 4 - get.value(card); - }, - group: "benlei2", - ai: { - basic: { - order: 10, - }, - }, - }, - benlei2: { - trigger: { source: "damageAfter" }, - filter: function (event, player) { - return event.hasNature("thunder") && player.hp < player.maxHp; - }, - forced: true, - content: function () { - player.recover(); - }, - }, moyu: { trigger: { source: "dieAfter" }, filter: function (event, player) { @@ -6093,40 +5373,6 @@ game.import("character", function () { } }, }, - qiaoxie: { - group: ["qiaoxie2", "qiaoxie3"], - ai: { - effect: { - target: function (card, player, target, current) { - if (get.type(card) == "equip") return [1, 3]; - }, - }, - reverseEquip: true, - noe: true, - }, - }, - qiaoxie2: { - trigger: { player: "equipEnd" }, - frequent: true, - //filter:function(event,player){ - // for(var i=0;i 0; - }) - .set("autodelay", 0.5).ai = function (target) { - return -get.attitude(player, target); - }; - "step 1"; - if (result.bool) { - player.logSkill("qiaoxie3", result.targets); - player.discardPlayerCard(result.targets[0], "he", true); - } else { - event.finish(); - } - }, - }, - qiaoxie4: { - trigger: { player: ["loseEnd"] }, - frequent: true, - filter: function (event, player) { - if (typeof lib.cardType.hslingjian != "number") return false; - if (!player.equiping) return false; - for (var i = 0; i < event.cards.length; i++) { - if (event.cards[i].original == "e") return true; - } - return false; - }, - content: function () { - var list = get.typeCard("hslingjian"); - if (!list.length) { - return; - } - player.gain(game.createCard(list.randomGet()), "gain2"); - }, - }, meihuo: { trigger: { player: ["loseEnd"] }, direct: true, @@ -6374,20 +5572,6 @@ game.import("character", function () { expose: 0.2, }, }, - chuanyang: { - trigger: { player: "shaBegin" }, - check: function (event, player) { - return get.attitude(player, event.player) < 0; - }, - filter: function (event, player) { - // if(event.card&&get.color(event.card)=='red') return true; - // return false; - return get.distance(event.target, player, "attack") > 1; - }, - content: function () { - trigger.directHit = true; - }, - }, poxing: { trigger: { source: "damageBegin" }, filter: function (trigger, player) { @@ -6715,108 +5899,22 @@ game.import("character", function () { target: 2, }, }, - }, - lingwu: { - trigger: { player: "phaseAfter" }, - frequent: true, - filter: function (event, player) { - return player.countUsed() >= player.hp && event.skill != "lingwu"; - }, - content: function () { - player.insertPhase(); - }, - ai: { - order: -10, - result: { - target: 2, - }, - threaten: 1.5, - }, - }, - xianjiang_old: { - enable: "phaseUse", - position: "he", - usable: 1, - filterCard: function (card, player) { - if (player.storage.xianjiang && player.storage.xianjiang.includes(card)) return false; - return get.type(card) == "equip"; - }, - init: function (player) { - player.storage.xianjiang = []; - }, - check: function (card) { - return 10 - get.value(card); - }, - prompt: "将一张装备牌永久转化为任意一张装备牌", - content: function () { - "step 0"; - var list = []; - var suit = get.suit(cards[0]); - var number = get.number(cards[0]); - for (var i in lib.card) { - if (lib.card[i].mode && lib.card[i].mode.includes(lib.config.mode) == false) continue; - if (lib.card[i].type == "equip" && cards[0].name != i) { - if (get.equipValue({ name: i }) < 10) list.push([suit, number, i]); - } - } - var dialog = ui.create.dialog([list, "vcard"]); - player.chooseButton(dialog, true, function (button) { - return get.value({ name: button.link[2] }, player); - }); - "step 1"; - cards[0].init(result.buttons[0].link); - player.gain(cards[0]); - player.$gain(cards[0]); - game.delay(); - player.storage.xianjiang.add(cards[0]); - }, - ai: { - order: 9, - result: { - player: 1, - }, - threaten: 2, - }, - }, - xianjiang2: { - trigger: { player: "phaseUseBegin" }, - forced: true, - popup: false, - filter: function (event, player) { - return player.hasSkill("xianjiang"); - }, - content: function () { - player.storage.xianjiang = []; - }, - }, - xianjiang: { - enable: "phaseUse", - // alter:true, - filterCard: function (card) { - return get.type(card, "trick") == "trick"; - }, - usable: 1, - filter: function (event, player) { - if (get.is.altered("xianjiang") && player.countCards("e")) return false; - if (player.countCards("h", { type: "trick" })) return true; - if (player.countCards("h", { type: "delay" })) return true; - return false; - }, - selectCard: 1, - check: function (card) { - return 8 - get.value(card); + }, + lingwu: { + trigger: { player: "phaseAfter" }, + frequent: true, + filter: function (event, player) { + return player.countUsed() >= player.hp && event.skill != "lingwu"; }, content: function () { - var card = game.createCard(get.inpile("equip").randomGet()); - player.equip(card); - player.$gain2(card); - game.delay(); + player.insertPhase(); }, ai: { + order: -10, result: { - player: 1, + target: 2, }, - order: 9, + threaten: 1.5, }, }, shengong: { @@ -7057,154 +6155,6 @@ game.import("character", function () { threaten: 1.6, }, }, - jingjie: { - enable: "phaseUse", - init: function (player) { - player.storage.jingjie = false; - }, - mark: true, - intro: { - content: "limited", - }, - filter: function (event, player) { - return !player.storage.jingjie; - }, - content: function () { - "step 0"; - player.storage.jingjie = true; - player.unmarkSkill("jingjie"); - event.targets = game.filterPlayer(); - for (var i = 0; i < event.targets.length; i++) { - event.targets[i].discard(event.targets[i].getCards("hej"))._triggered = null; - } - "step 1"; - for (var i = 0; i < event.targets.length; i++) { - event.targets[i].directgain(get.cards(2)); - event.targets[i].$draw(2); - } - }, - ai: { - threaten: 1.3, - order: 1, - result: { - player: function (player) { - var num = 0, - players = game.filterPlayer(); - for (var i = 0; i < players.length; i++) { - var att = get.attitude(player, players[i]); - if (att > 0) { - num -= players[i].countCards("he") - 2; - } else if (att < 0) { - num += players[i].countCards("he") - 2; - } - } - if (player.hp == 1) return num - 1; - return num - players.length / 2; - }, - }, - }, - }, - ningjian: { - group: ["ningjian1", "ningjian2"], - ai: { - effect: { - target: function (card, player, target) { - if ( - target.countCards("he") && - (get.tag(card, "respondShan") || get.tag(card, "respondSha")) - ) - return 0.6; - }, - }, - respondSha: true, - respondShan: true, - }, - }, - ningjian1: { - enable: ["chooseToRespond", "chooseToUse"], - filterCard: { color: "black" }, - viewAs: { name: "sha" }, - position: "he", - prompt: "将一张黑色牌当杀打出", - check: function (card) { - return 6 - get.value(card); - }, - }, - ningjian2: { - enable: ["chooseToRespond", "chooseToUse"], - filterCard: { color: "red" }, - viewAs: { name: "shan" }, - position: "he", - prompt: "将一张红色牌当闪使用或打出", - check: function (card) { - return 6 - get.value(card); - }, - }, - duoren: { - trigger: { target: "shaMiss" }, - filter: function (event) { - return event.player.getEquip(1) != undefined; - }, - check: function (event, player) { - return get.attitude(player, event.player) < 0; - }, - priority: 5, - content: function () { - trigger.player.$give(trigger.player.getEquip(1), player); - player.gain(trigger.player.getEquip(1), trigger.player); - }, - ai: { - effect: { - target: function (card, player, target, current) { - if (card.name == "sha" && target.countCards("h") > 1 && player.getEquip(1)) { - return [1, 0.5, 0, -0.5]; - } - }, - }, - }, - // filter:function(event){ - // return event.player.countCards('e')>0; - // }, - // content:function(){ - // "step 0" - // player.choosePlayerCard('是否获得'+get.translation(trigger.player)+'的一张装备牌?', - // 'e',trigger.player).ai=get.buttonValue; - // "step 1" - // if(result.bool){ - // var card=result.buttons[0].link; - // trigger.player.$give(card,player); - // player.gain(card); - // } - // }, - }, - taixu: { - enable: "phaseUse", - filter: function (event, player) { - return !player.storage.taixu && player.countCards("hej"); - }, - filterTarget: function (card, player, target) { - return player != target && target.hp > 1; - }, - content: function () { - player.discard(player.getCards("hej")); - player.storage.taixu = true; - target.damage(player.maxHp - player.hp); - }, - ai: { - basic: { - order: 1, - }, - result: { - target: function (player, target) { - if (player.maxHp - player.hp < 2) return 0; - return -2; - }, - player: function (player, target) { - return -0.5 * player.countCards("he"); - }, - }, - }, - }, pozhen: { trigger: { player: "damageEnd" }, filter: function (event, player) { @@ -8407,7 +7357,7 @@ game.import("character", function () { }, ai: { effect: { - target_use(card, player, target) { + target(card, player, target) { if ( get.color(card) == "black" && get.attitude(target, player) < 0 && @@ -8419,51 +7369,6 @@ game.import("character", function () { }, }, }, - zaowu_old: { - enable: "phaseUse", - usable: 1, - position: "he", - filterCard: function (card, player, target) { - if (ui.selected.cards.length == 0) return true; - for (var i = 0; i < ui.selected.cards.length; i++) { - if (get.type(ui.selected.cards[i], "trick") == get.type(card, "trick")) return false; - } - return true; - }, - selectCard: 3, - check: function (card) { - return 10 - get.value(card); - }, - content: function () { - "step 0"; - var list = []; - var suit = ["heart", "diamond", "club", "spade"].randomGet(); - var number = Math.floor(Math.random() * 13) + 1; - for (var i in lib.card) { - if (lib.card[i].mode && lib.card[i].mode.includes(lib.config.mode) == false) continue; - if (get.value({ name: i }) >= 10) continue; - if (i != "list") list.push([suit, number, i]); - } - var dialog = ui.create.dialog([list, "vcard"]); - player.chooseButton(dialog, 2, true, function (button) { - return get.value({ name: button.link[2] }, player); - }); - "step 1"; - var cards = [ui.create.card(), ui.create.card()]; - cards[0].init(result.buttons[0].link); - cards[1].init(result.buttons[1].link); - player.gain(cards); - player.$gain(cards); - game.delay(); - }, - ai: { - order: 8, - result: { - player: 1, - }, - threaten: 1.6, - }, - }, xielv: { trigger: { player: "phaseDiscardEnd" }, filter: function (event, player) { @@ -8536,9 +7441,10 @@ game.import("character", function () { }, ai: { effect: { - target: function (card, player, target, current) { - if (card.name == "sha" && get.color(card) == "red") { - return [1, -2]; + player: function (card, player, target, current) { + if (get.tag(card, "damage") && !player.hasSkill("xiaomoyu2")) { + if (player.isDamaged()) return [1, 1.6]; + return [1, 0.8]; } }, }, @@ -8599,13 +7505,6 @@ game.import("character", function () { expose: 0.1, }, }, - xiangu: { - mod: { - maxHandcard: function (player, num) { - if (player.hp < player.maxHp) return num + player.maxHp - player.hp; - }, - }, - }, tianhuo: { enable: "phaseUse", filterTarget: function (card, player, target) { @@ -8991,23 +7890,6 @@ game.import("character", function () { player.loseHp(); }, }, - swdxueyi: { - trigger: { player: "phaseDrawBegin" }, - frequent: true, - content: function () { - trigger.num += player.maxHp - player.hp; - }, - ai: { - effect: { - target: function (card, player, target) { - if (get.tag(card, "damage")) { - if (target.hp == target.maxHp) return [0, 1]; - } - if (get.tag(card, "recover") && player.hp >= player.maxHp - 1) return [0, 0]; - }, - }, - }, - }, jifeng: { mod: { selectTarget: function (card, player, range) { @@ -9037,11 +7919,50 @@ game.import("character", function () { } }, }, + swd_xiuluo: { + trigger: { player: "phaseZhunbeiBegin" }, + filter: function (event, player) { + return player.countCards("j") > 0; + }, + direct: true, + content: function () { + var next = player.discardPlayerCard( + player, + 2, + "hj", + "是否一张手牌来弃置一张花色相同的判定牌?" + ); + next.filterButton = function (button) { + var card = button.link; + if (!lib.filter.cardDiscardable(card, player)) return false; + if (ui.selected.buttons.length == 0) return true; + if (get.position(ui.selected.buttons[0].link) == "h") { + if (get.position(card) != "j") return false; + } + if (get.position(ui.selected.buttons[0].link) == "j") { + if (get.position(card) != "h") return false; + } + return get.suit(card) == get.suit(ui.selected.buttons[0].link); + }; + next.ai = function (button) { + var card = button.link; + if (get.position(card) == "h") { + return 11 - get.value(card); + } + if (card.name == "lebu") return 5; + if (card.name == "bingliang") return 4; + if (card.name == "guiyoujie") return 3; + return 2; + }; + next.logSkill = "swd_xiuluo"; + }, + }, mohua2: { unique: true, trigger: { player: "dying" }, priority: 10, forced: true, + derivation: ["moyan", "miedao", "jifeng", "swd_xiuluo"], content: function () { "step 0"; player.removeSkill("miles_xueyi"); @@ -9073,151 +7994,6 @@ game.import("character", function () { player.draw(2); }, }, - liexin: { - trigger: { source: "damageBegin" }, - direct: true, - content: function () { - "step 0"; - player.chooseToDiscard("是否弃置一张牌使伤害+1?", "he").ai = function (card) { - if (get.attitude(player, trigger.player) < 0) { - return 7 - get.value(card); - } - }; - "step 1"; - if (result.bool) { - player.logSkill("liexin"); - trigger.num++; - } - }, - ai: { - threaten: 1.8, - }, - }, - mohua: { - trigger: { player: "dying" }, - priority: 10, - forced: true, - mode: ["identity"], - content: function () { - "step 0"; - var skills = ["wuying", "xiehun", "jumo"]; - if (lib.config.mode_choice.double_character) { - skills.push("swd_xiuluo"); - } - lib.character.swd_satan = ["", "qun", 6, skills, ["temp"]]; - if (!_status.ai.customAttitude) _status.ai.customAttitude = []; - _status.ai.customAttitude.push(function (from, to) { - if (from.storage.xiehun) { - if (to == game.zhu) return 10; - return -10; - } - if (to.storage.xiehun) { - return 0; - } - }); - player.uninit(); - player.init("swd_satan"); - player.hp = game.players.length; - player.update(); - game.zhu = player; - player.identity = "zhu"; - player.setIdentity("魔"); - player.identityShown = true; - var players = get.players(false, true); - for (var i = 0; i < players.length; i++) { - if (players[i] != player) { - players[i].identity = "fan"; - players[i].setIdentity("人"); - players[i].identityShown = true; - } - } - player.draw(2); - "step 1"; - while (_status.event.name != "phaseLoop") { - _status.event = _status.event.parent; - } - _status.event.player = player; - _status.event.step = 0; - ui.clear(); - }, - }, - wuying: { - mod: { - selectTarget: function (card, player, range) { - if (card.name == "sha") { - range[0] = -1; - range[1] = -1; - } - if (get.type(card) == "trick" && (range[0] == 1) & (range[1] == 1)) { - range[0] = -1; - range[1] = -1; - } - }, - }, - }, - xiehun: { - group: ["xiehun1", "xiehun2"], - intro: { - content: "已陷入混乱状态", - show: true, - }, - }, - xiehun1: { - trigger: { player: "phaseBegin" }, - forced: true, - popup: false, - content: function () { - if (game.me.storage.xiehun) ui.auto.show(); - for (var i = 0; i < game.players.length; i++) { - delete game.players[i].storage.xiehun; - } - if (ui.auto.innerHTML == "托管") _status.auto = false; - }, - }, - xiehun2: { - trigger: { source: "damageBegin" }, - filter: function (event, player) { - return event.player != player; - }, - forced: true, - content: function () { - trigger.player.storage.xiehun = true; - if (trigger.player == game.me) { - _status.auto = true; - ui.auto.hide(); - } - // player.chooseToDiscard(true,'h'); - }, - }, - jumo2: { - trigger: { player: "phaseDrawBegin" }, - forced: true, - priority: -10, - content: function () { - var num = Math.max(2, game.players.length - 1); - if (lib.config.mode_choice.double_character) { - num++; - } - trigger.num = Math.min(4, num); - }, - }, - jumo: { - trigger: { player: "phaseEnd" }, - forced: true, - content: function () { - var num = 0; - for (var i = 0; i < game.players.length; i++) { - if (player != game.players[i] && !game.players[i].storage.xiehun) num++; - } - num = 2 * num - game.players.length; - if (get.config("double_character")) { - num++; - } - if (num > 0) { - player.draw(num); - } - }, - }, duijue: { enable: "phaseUse", mark: true, @@ -9970,9 +8746,8 @@ game.import("character", function () { ai: { effect: { target: function (card, player, target, current) { - if (card.name == "guiyoujie") return [0, 2]; if (target.isTurnedOver()) { - if (get.tag(card, "damage")) return 0; + if (get.tag(card, "damage")) return "zeroplayertarget"; } }, }, @@ -10202,7 +8977,7 @@ game.import("character", function () { player: 1, }, effect: { - target: function (card, player, target) { + target_use: function (card, player, target) { if (player != target) return; if (get.subtype(card) == "equip5") { if (get.equipValue(card) <= 7) return 0; @@ -10238,7 +9013,7 @@ game.import("character", function () { return get.order({ name: "sha" }) + 0.1; }, effect: { - target: function (card, player) { + target_use: function (card, player) { if (get.subtype(card) == "equip1") { var num = 0, players = game.filterPlayer(); @@ -10375,9 +9150,6 @@ game.import("character", function () { cyqiaoxie_info: "每当你失去一张装备牌(使用除外),你可以随机观看三张机关牌,并使用其中一张。", cyqiaoxie_info_alter: "每当你装备一件装备,若你的手牌数不大于体力值,你可以摸一张牌;每当你失去一件装备牌,你可以随机观看2张机关牌,并使用其中一张。", - cyzhencha: "侦察", - cyzhencha_info: - "出牌阶段限一次,若你的装备区内的可强化装备,你可以弃置一张基本牌并观看一名其他角色的手牌,若其中有与你弃置的牌颜色相同的牌,你随机升级装备区内的一件装备,否则你摸一张牌;你根据装备区内升级的装备数获得额外技能。", cylingjia: "灵甲", cylingjia_info: "出牌阶段限一次,你可以弃置一张装备牌,然后令云狐随机装备一件装备(不替换现有装备)并将其强化。", @@ -10467,10 +9239,6 @@ game.import("character", function () { "限定技,出牌阶段,你可以令任意名角色各获得3点护甲,获得护甲的角色于每个准备阶段失去1点护甲,直到首次失去所有护甲或累计以此法失去3点护甲。", huanxia: "幻霞", huanxia_info: "你可以将一张红色牌当作【杀】使用,若此【杀】未造成伤害,你在结束阶段收回此牌。", - jingjie: "幻镜", - jingjie_info: "限定技,出牌阶段,你可以令所有角色弃置所有牌,然后摸两张牌(不触发任何技能)。", - kongmo: "恐魔", - kongmo_info: "锁定技,你使用基本牌或普通锦囊牌后将额外结算一次卡牌效果。", jufu: "巨斧", jufu_info: "锁定技,当你有武器牌时,【杀】造成的伤害+1。", huajing: "化精", @@ -10481,7 +9249,6 @@ game.import("character", function () { yudun_info: "锁定技,你无法使用锦囊牌;你可以将两张锦囊牌当作一张不计入出杀次数的【杀】使用。", bingfeng: "冰封", bingfeng2: "冰封", - bingfeng2_info: "不能使用或打出手牌。", bingfeng_info: "限定技,出牌阶段,你可以指定至多三个目标与其一同翻面,且处于翻面状态时不能使用或打出手牌;若如此做,你失去技能玄咒并减少1点体力上限。", guozao: "聒噪", @@ -10534,9 +9301,6 @@ game.import("character", function () { "出牌阶段限一次,你可以弃置一张黑桃牌对一名其他角色造成1点火焰伤害,然后你与距离该角色1以内的所有角色各弃置一张牌。", shending: "神丁", shending_info: "锁定技,若你没有宝物牌,视为装备了蓝格怪衣。", - hzhenwei: "镇卫", - hzhenwei_info: - "当一名其他角色成为【杀】的目标后,若你在【杀】的使用者的攻击范围内,你可以弃置一张牌将此【杀】转移给自己,并在【杀】结算完毕后摸一张牌。", shoulie: "狩猎", shoulie_info: "当你使用一张【杀】指定目标后,可以弃置一张手牌令此【杀】不可闪避。", hudun: "盾甲", @@ -10561,9 +9325,6 @@ game.import("character", function () { fuyan_info: "每当你受到一次伤害,可以令一名没有护甲的角色获得1点护甲值。", guaili: "怪力", guaili_info: "锁定技,你的【杀】造成的伤害+1,造成伤害后需弃置两张手牌。", - pingshen: "凭神", - pingshen2: "凭神", - pingshen_info: "锁定技,受到过你的伤害的角色可在回合内对你发动一次【离魂】(每局限发动一次)。", xingzhui: "星坠", xingzhui_info: "出牌阶段限一次,你可以弃置一张牌,并令一名有牌的其他角色弃置一张类别相同的牌,否则受到1点伤害。", @@ -10575,9 +9336,6 @@ game.import("character", function () { "限定技,当任意一名角色处于濒死状态时,若你的武将牌正朝上,可以将武将牌翻面,然后令场上所有存活角色将体力回复至体力上限。", shouyin_info_alter: "限定技,当任意一名角色处于濒死状态时,若你的武将牌正朝上,可以将武将牌翻面,然后令场上所有存活角色回复2点体力。", - bofeng: "搏风", - bofeng_info: - "锁定技,体力值不大于你的角色视为在你的攻击范围;当你使用【杀】指定目标时,可令目标额外打出一张闪,否则此【杀】不可闪避且造成的伤害+1。", hutian: "护天", hutian2: "护天", hutian3: "护天", @@ -10592,15 +9350,11 @@ game.import("character", function () { huanling: "幻灵", huanling2: "幻灵", huanling_info: "结束阶段,你可以选择一名角色与你同时翻面;翻面状态下,你防止一切伤害。", - xiaozhan: "消战", - xiaozhan_info: "其他角色使用【杀】时,若你不是【杀】的目标,可以弃置一张【杀】取消之。", xielei: "挟雷", xielei_info: "每当你使用或打出一张【杀】,可以弃置一张牌并对目标以外的一名角色造成1点雷电伤害。", dangping: "荡平", dangping_info: "每当你造成一次伤害,可以弃置一张手牌对其距离1以内的另一名角色造成1点伤害,每回合限一次。", - guisi: "归思", - guisi_info: "每当你成为【杀】的目标,你可以交给对方一张手牌并取消之。", duishi: "对诗", duishi_info: "出牌阶段,你可以弃置一张手牌,并指定一名有手牌的角色选择一项:1)弃置一张与之花色相同的手牌,本回合内对诗不能再次指定其为目标,2)令你获得其一张牌,对诗失效直到回合结束。", @@ -10623,14 +9377,9 @@ game.import("character", function () { rexue_info: "任意一名角色的准备阶段,你可以对其使用一张【杀】,并摸一张牌。", huopu: "火瀑", huopu_info: "出牌阶段限一次,你可以将一张红桃牌当作流星火羽使用。", - benlei: "奔雷", - benlei2: "奔雷", - benlei_info: "你可以将三张牌当惊雷闪使用;每当你造成一次雷属性伤害,你回复1点体力。", lingwu: "灵舞", lingwu_info: "回合结束后,若你在本回合内使用的牌数不少于当前体力值,你可以进行一个额外的回合(不可重复发动)。", - miejing: "灭境", - miejing_info: "限制技,你可以弃置所有黑色牌,然后令所有其他角色受到1点雷电伤害。", lingxin: "灵心", lingxin_info: "结束阶段,你可以亮出牌堆顶的三张牌,然后获得其中的红桃牌。", fushen: "附身", @@ -10647,28 +9396,18 @@ game.import("character", function () { shejie: "设界", shejie2: "设界", shejie_info: "每当你受到一次伤害,可以令伤害来源不能使用或打出其手牌,直到其下一回合开始。", - shejie2_info: "不能使用或打出手牌,直到下一回合开始。", yinyue: "引月", yinyue_info: "每当有一名角色回复一次体力,你可以令其摸一张牌,若该角色不是你且你的手牌数不大于该角色,你也摸一张牌。", yinyue_info_alter: "每当有一名角色回复一次体力,你可以令其摸一张牌。", mohua2: "魔化", mohua2_info: "锁定技,当你进入濒死状态时,你立即变身为撒旦,将体力回复至2,然后摸两张牌。", - liexin: "裂心", - liexin_info: "每当你即将造成伤害,你可以弃置一张牌令伤害+1。", - swdxueyi: "血裔", - swdxueyi_info: "锁定技,你摸牌阶段额外摸X张牌,X为你已损失的体力值。", moyan: "血焰", moyan_info: "出牌阶段,你可以弃置X张红色手牌,然后对至多X名角色各造成1点火焰伤害,X为你已损失的体力值。每阶段限一次。", aojian: "傲剑", aojian_info: "出牌阶段,你可以弃置X张手牌,然后对攻击范围内至多X名角色各造成1点伤害,X为你已损失的体力值。每阶段限一次。", - milesxiehun: "邪魂", - milesxiehun_info: - "锁定技,出牌阶段结束后,你令随机X名角色各弃置一张牌,X为你已损失的体力值且至少为1。", - liaochen: "撩尘", - liaochen_info: "锁定技,出牌阶段结束后,所有角色需弃置一张牌。", huanxing: "幻形", huanxing2: "幻形", huanxing_info: @@ -10691,9 +9430,6 @@ game.import("character", function () { mufeng_info_alter: "结束阶段,你可以将手牌数补至当前体力值。", mufeng_old2_info: "在一名角色的结束阶段,若你的手牌数比其少,你可以将手牌补至与该角色相同(最多补至5),每轮限一次。", - hjifeng: "祭风", - hjifeng_info: - "出牌阶段限一次,若你手牌中没有祭器牌,你可以将一张手牌置于牌堆顶,并根据其花色获得对应祭器:黑桃-青龙之圭;梅花-白兽之琥;方片-朱雀之璋;红桃-玄武之璜。", mufeng_old_info: "锁定技,每当你于回合外失去牌,你的防御距离+1;若防御距离的变化值超过了存活角色数的一半,则降至0。", lexue: "乐学", @@ -10701,8 +9437,6 @@ game.import("character", function () { "回合内,你随机获得制衡、集智、缔盟、驱虎中的一个技能;回合外,你随机获得遗计、急救、鬼道、反馈中的一个技能。", mingfu: "冥缚", mingfu_info: "出牌阶段限一次,你可以将一张梅花牌当鬼幽结使用。", - chuanyue: "穿月", - chuanyue_info: "出牌阶段限一次,你可以将两张手牌当决斗使用。", miedao: "灭道", miedao1: "灭道", @@ -10720,8 +9454,6 @@ game.import("character", function () { jikong_info: "准备阶段,你可以指定一名角色视为对其使用一张雷【杀】;每当你失去最后一张手牌,你可以指定一名角色视为对其使用一张雷【杀】(每回合限发动一次)。", jikong_info_alter: "准备阶段,你可以指定一名角色视为对其使用一张雷【杀】。", - xiangu: "仙骨", - xiangu_info: "锁定技,你的手牌上限不会因体力值的减少而减少。", hujing: "壶境", hujing_info: "锁定技,准备阶段,若弃牌堆中有炼妖壶,你装备之;当你的装备区内有炼妖壶时,你的手牌上限+2。", @@ -10751,9 +9483,6 @@ game.import("character", function () { tuzhen: "突阵", tuzhen_info: "当你造成一次伤害后,你可以弃置对方手牌中的非基本牌。", tuzhen_info_alter: "当你造成一次伤害后,你可以弃置对方手牌中的一张非基本牌。", - fengmo: "封魔", - fengmo_info: - "出牌阶段限一次,你可以弃置场上所有武器牌(至少两张),然后令一名未翻面的角色摸等量的牌并翻面。", pozhou: "破咒", pozhou_bg: "破", pozhou2: "破咒", @@ -10766,8 +9495,6 @@ game.import("character", function () { ningxian_info: "每当你受到一次伤害,你可以弃置任意张黑色牌并选择等量其他角色对其各造成1点伤害。", guanhu: "贯鹄", guanhu_info: "每当你使用【杀】造成伤害,你可以弃置对方一张手牌和一张装备牌。", - chuanyang: "穿杨", - chuanyang_info: "每当你使用一张【杀】,若你不在目标的攻击范围,你可以令此【杀】不可闪避。", fengming: "凤鸣", fengming_info: "出牌阶段限一次,你可以弃置一张装备牌,令一名角色恢复1点体力并摸一张牌。", duanxing: "锻星", @@ -10785,7 +9512,6 @@ game.import("character", function () { zhanlu: "沾露", luomu: "落木", - jifeng: "魔影", liaoyuan: "燎原", huanhun: "唤魂", daixing: "代形", @@ -10793,14 +9519,7 @@ game.import("character", function () { yishan2: "异闪", swd_wuxie: "无邪", lqingcheng: "倾城", - xianjiang: "仙匠", - xianjiang3: "仙匠", shengong: "神工", - ningjian: "凝剑", - ningjian1: "凝剑", - ningjian2: "凝剑", - taixu: "太虚", - duoren: "夺刃", tanlin: "探麟", tanlin2: "探麟", pozhen: "破阵", @@ -10816,8 +9535,6 @@ game.import("character", function () { xuehuang_bg: "凰", zhuyu: "朱羽", ningshuang: "凝霜", - zaowu: "造物", - // shouhua:'收化', xielv: "谐率", tianhuo: "天火", huanyin: "幻音", @@ -10830,14 +9547,7 @@ game.import("character", function () { guxing1: "孤星", guxing2: "孤星", poxing: "破星", - mohua: "魔化", miles_xueyi: "血裔", - wuying: "无影", - xiehun: "邪魂", - xiehun1: "邪魂", - xiehun2: "邪魂", - xiehun3: "邪魂", - jumo: "聚魔", duijue: "对决", duijue_bg: "决", yueren: "月刃", @@ -10850,10 +9560,6 @@ game.import("character", function () { suiyan: "碎岩", suiyan_info: "每当你造成一次伤害,可以弃置一张牌并弃置对方的全部装备牌。", xianyin: "散结", - qiaoxie: "巧械", - qiaoxie2: "巧械", - qiaoxie3: "巧械", - qiaoxie4: "巧械", mailun: "脉轮", mailun31: "脉轮", mailun32: "脉轮", @@ -10876,10 +9582,8 @@ game.import("character", function () { "准备阶段,若你的体力值小于上回合结束时的体力值,你可以将场上所有牌还原到你上一回合结束时的位置。", kunlunjing_info_alter: "准备阶段,若你的体力值小于上回合结束时的体力值,你可以将场上所有牌还原到你上一回合结束时的位置,然后失去1点体力。", - swd_xiuluo_info: "准备阶段,你可以弃一张手牌来弃置你判断区里的一张延时类锦囊(必须花色相同)。", + swd_xiuluo_info: "准备阶段,你可以弃一张手牌来弃置你判定区里的一张延时类锦囊(必须花色相同)。", xianyin_info: "出牌阶段,你可以令所有判定区内有牌的角色弃置判定区内的牌,然后交给你一张手牌。", - qiaoxie_info: - "每当你装备一张牌,可摸一张牌;每当你失去一张装备牌(不含替换),你可以弃置其他角色的一张牌。", mailun_info: "准备阶段,你可以选择一个脉轮效果直到下一回合开始。", guiyan_info: "出牌阶段,你可以观看一名角色的手牌,并获得其中一张梅花牌,每阶段限一次。当你首次进入濒死状态时,你须回复1点体力并失去技能鬼眼。", @@ -10892,15 +9596,8 @@ game.import("character", function () { "每当你使用一张【杀】,可以进行一次判定,若结果为黑色,你弃置目标一张牌,若结果为红色,你将此【杀】收回,每回合限发动一次。", duijue_info: "限定技,出牌阶段,你可以指定一名体力值大于1的其他角色,你结束出牌阶段,并在回合结束后将所有其他角色移出游戏,然后该角色与你轮流进行回合,直到有一方死亡或一共进行六个回合为止。", - wuying_info: "锁定技,你的【杀】和单体x锦囊目标锁定为范围内的所有角色。", - xiehun_info: - "锁定技,受到来自你伤害的角色进入混乱状态,行为不受控制,且会攻击队友,直到你的下一回合开始。", - jumo_info: - "锁定技,结束阶段,你摸X-1张牌,X为未进入混乱状态的角色数与进入混乱状态的角色数之差(若为双将则改为X)。", jifeng_info: "你的【杀】和单体锦囊可以额外指定任意个目标,若如此做,此卡牌有一定机率失效,指定的目标越多失效的概率越大。", - mohua_info: - "锁定技,在身份局中,当你进入濒死状态时,你立即变身为撒旦,体力上限变为现存角色数(至少为4),并成为其他所有角色的共同敌人。", miles_xueyi_info: "锁定技,你防止即将受到的伤害,然后失去1点体力。", duanyi_info: "出牌阶段限一次,你可以弃置两张【杀】,对一名角色造成1点伤害,然后其随机弃置X张牌,X为其已损失的体力值。", @@ -10931,17 +9628,8 @@ game.import("character", function () { swd_wuxie_info: "锁定技,你不能成为其他角色的延时锦囊的目标。", lqingcheng_info: "结束阶段,你可以进行判定,若为红色则可以继续判定,最多判定3次,判定结束后将判定成功的牌收入手牌。", - xianjiang_old_info: - "出牌阶段,你可以将一张装备牌永久转化为任意一张其它装备牌,一张牌在一个阶段只能转化一次。", - xianjiang_info: "出牌阶段限一次,你可以弃置一张锦囊牌并随机装备一件装备。", - xianjiang_info_alter: - "出牌阶段限一次,若你装备内没有牌,你可以弃置一张锦囊牌并随机装备一件装备。", shengong_info: "每当你需要打出一张【杀】或【闪】时,你可以弃置一名其他角色装备区内的一张武器牌或防具牌,视为打出一张【杀】或【闪】,然后该角色摸一张牌,你弃一张牌。", - ningjian_info: "你可以将一张红色牌当【闪】、黑色牌当【杀】使用或打出。", - taixu_info: - "限定技,你可以弃置你的所有牌(至少1张),并对一名体力值大于1的其他角色造成X点火焰伤害,X为你已损失的体力值且至少为1。", - duoren_info: "每当你闪避一张【杀】,你可以立即获得来源的武器牌。", tanlin_info: "出牌阶段限一次,你可以与一名其他角色进行拼点,若你赢,你获得双方拼点牌、对该角色使用卡牌无视距离且可以额外使用一张【杀】直到回合结束,若你没赢,你受到该角色的1点伤害。", tanlin_info_alter: @@ -10958,7 +9646,6 @@ game.import("character", function () { "结束阶段,你可以弃置一张牌并从三名随机武将中选择一个,在2X回合后你将其所有技能加入你的天书列表,X为其技能数;在技能加入天书列表时,或于出牌阶段,你可以装备一项天书列表中的技能。", swdtianshu_info: "出牌阶段,你可以弃置一张锦囊牌,然后获得一名其他角色的一项技能直到该角色死亡(替换以此法获得的前一个技能)。", - zaowu_info: "出牌阶段限一次,你可以将一张黑桃或红桃手牌当作封印之蛋使用。", luomei_info: "每当你使用或打出一张梅花花色的牌,你可以摸一张牌。", xingdian_info: "出牌阶段限一次,你可以弃置一张手牌,然后随机弃置两名敌人各一张牌。", yulin_info: "每当你即将受到伤害,你可以弃置一张装备牌抵消此伤害。", @@ -10970,7 +9657,6 @@ game.import("character", function () { zhuyu_info: "每当一名横置的角色即将受到伤害时,你可以弃置一张红色牌令此伤害+1并变为火属性。", ningshuang_info: "每当你成为黑色牌的目标,你可以弃置一张黑色牌将其横置,并摸一张牌,若其已经模置则改为将其翻面。", - zaowu_old_info: "出牌阶段,你可以弃置三张不同类型的牌,创造任意两张牌并获得之。", xielv_info: "弃牌阶段结束后,若你的所有手牌(至少两张)颜色均相同,你可以展示所有手牌,然后回复1点体力并弃置场上的所有判定牌。", }, diff --git a/character/tw/character.js b/character/tw/character.js index 98c9fcbd00..f0e2c5aa9a 100644 --- a/character/tw/character.js +++ b/character/tw/character.js @@ -1,8 +1,10 @@ const characters = { + huan_luxun: ["male", "wu", 3, ["twlifeng", "twniwo"]], + huan_liushan: ["male", "shu", 3, ["twguihan", "twrenxian", "twyanzuo"], ["zhu"]], licuilianzhaoquanding: ["double", "qun", 3, ["twciyin", "twchenglong"], ["name:李|翠莲-赵|全定"]], huan_zhugeliang: ["male", "shu", "3/4", ["twbeiding", "twjielv", "twhunyou"], ["name:诸葛|亮"]], - huan_jiangwei: ["male", "shu", 4, ["huan_jiangwei_A", "huan_jiangwei_B"]], - huan_guojia: ["male", "wei", 3, ["huan_guojia_A", "huan_guojia_B"]], + huan_jiangwei: ["male", "shu", 4, ["twqinghan", "twzhihuan"]], + huan_zhugeguo: ["female", "shu", 3, ["rexianyuan", "twlingyin"]], huan_zhanghe: ["male", "wei", 4, ["twkuiduan"]], huan_zhaoyun: ["male", "shu", 4, ["twjiezhan", "twlongjin"]], huan_simayi: ["male", "wei", 4, ["twzongquan", "twguimou"], ["name:司马|懿"]], diff --git a/character/tw/characterReplace.js b/character/tw/characterReplace.js index 390af94001..16b8f6aa7f 100644 --- a/character/tw/characterReplace.js +++ b/character/tw/characterReplace.js @@ -1,12 +1,13 @@ const characterReplaces = { tw_caocao: ["tw_caocao", "jsrg_caocao", "yj_caocao"], mateng: ["tw_mateng", "mateng", "std_mateng"], - xiahouen: ["tw_xiahouen", "jsrg_xiahouen"], + tw_xiahouen: ["tw_xiahouen", "jsrg_xiahouen"], jiangji: ["dc_jiangji", "tw_jiangji", "jiangji"], baoxin: ["tw_baoxin", "baoxin"], yanxiang: ["yanxiang", "tw_yanxiang"], liwei: ["liwei", "tw_liwei"], tw_jiling: ["jiling", "dc_jiling", "tw_jiling"], + tw_zhangji: ["tw_zhangji", "ol_tw_zhangji"], }; export default characterReplaces; diff --git a/character/tw/dynamicTranslate.js b/character/tw/dynamicTranslate.js index 8f17da7a03..dc57a68994 100644 --- a/character/tw/dynamicTranslate.js +++ b/character/tw/dynamicTranslate.js @@ -25,7 +25,7 @@ const dynamicTranslates = { }, twdengjian(player) { let str = "①其他角色的弃牌阶段结束时,你可以随机获得本回合所有造成伤害的牌对应的实体牌的其中一张与你本轮以此法获得的牌的颜色均不同的【杀】,称为“剑法”。"; - if (player.hasSkill("twdengjian_ban")) str = '' + str + ""; + if (player.isTempBanned("twdengjian")) str = '' + str + ""; str += "②你使用“剑法”牌不计入次数限制。"; return str; }, @@ -44,5 +44,13 @@ const dynamicTranslates = { twylyanshi(player) { return lib.translate[(player.storage.twduwang_ylyanshi ? "twylyanshix" : "twylyanshi") + "_info"]; }, + twjielv(player) { + if(player.storage.isInHuan) return lib.translate.twjielvx_info; + return lib.translate.twjielv_info; + }, + twbeiding(player) { + if(player.storage.isInHuan) return lib.translate.twbeidingx_info; + return lib.translate.twbeiding_info; + }, }; export default dynamicTranslates; diff --git a/character/tw/index.js b/character/tw/index.js index 9f799c18ec..e8caa7e25e 100644 --- a/character/tw/index.js +++ b/character/tw/index.js @@ -26,7 +26,9 @@ game.import("character", function () { characterIntro: { ...characterIntros }, characterReplace: { ...characterReplaces }, characterSubstitute: { - huan_zhugeliang: [], + huan_zhugeliang: [ + ["huan_zhugeliang_shadow", []], + ], }, card: { ...cards }, skill: { ...skills }, diff --git a/character/tw/skill.js b/character/tw/skill.js index 7b421804fb..4fc6396c75 100644 --- a/character/tw/skill.js +++ b/character/tw/skill.js @@ -2,6 +2,331 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { + //幻陆逊 + twlifeng: { + enable: "phaseUse", + filter(event, player) { + if (!player.countCards("he")) return false; + let cardx = player.getCards("he").randomGet(); + return player.countCards("he", card => get.number(card, player) != get.number(cardx, player)); + }, + filterCard(card, player) { + if (ui.selected.cards.length) return get.number(card, player) != get.number(ui.selected.cards[0], player); + return true; + }, + position: "he", + selectCard: 2, + filterTarget(card, player, target) { + if (ui.selected.cards.length < 2) return false; + let cards = ui.selected.cards, + num = Math.abs(get.number(cards[0], player) - get.number(cards[1], player)); + return get.distance(player, target) <= num; + }, + check(card) { + return 7 - get.value(card); + }, + complexSelect: true, + async content(event, player, target) { + await event.target.damage(); + }, + group: "twlifeng_effect", + subSkill: { + effect: { + trigger: { + source: "damageBegin3", + }, + filter(event, player) { + return event.getParent().name == "twlifeng"; + }, + async cost(event, trigger, player) { + const target = trigger.player, + cards = trigger.getParent().cards, + num1 = get.number(cards[0]), + num2 = get.number(cards[1]); + if (target.countCards("h")) { + let max = num1 > num2; + const result = await target + .chooseCard("是否重铸一张手牌?", `若此牌点数位于${num1}和${num2}之间,防止此伤害`) + .set("ai", card => { + const maxNum = get.event("maxNum"), + minNum = get.event("minNum"); + if (get.damageEffect(get.player(), get.event().getTrigger().source, get.player()) > 0) return 0; + if (get.number(card) >= minNum && get.number(card) <= minNum) return 15 - get.value(card); + return 8 - get.value(card); + }) + .set("maxNum", max ? num1 : num2) + .set("minNum", max ? num2 : num1) + .forResult(); + event.result = { + bool: result.bool, + cards: result.cards, + }; + } else { + const result = await target.chooseBool("是否摸一张牌?", `若此牌点数位于${num1}和${num2}之间,防止此伤害`).forResult(); + event.result = { + bool: result.bool, + }; + } + event.result.cost_data = [num1, num2]; + event.result.skill_popup = false; + }, + async content(event, trigger, player) { + let card, + nums = event.cost_data, + target = trigger.player; + if (event.cards?.length > 0) { + await target.recast(event.cards); + card = event.cards[0]; + } else { + const { result } = await target.draw(); + card = result[0]; + } + if (nums[0] > nums[1]) nums.reverse(); + if (nums[0] <= get.number(card) && nums[1] >= get.number(card)) { + trigger.cancel(); + player.tempBanSkill("twlifeng"); + } + }, + }, + }, + ai: { + order: 5, + result: { + target(player, target) { + return get.damageEffect(target, player, player); + }, + }, + }, + }, + twniwo: { + trigger: { + player: "phaseUseBegin", + }, + filter(event, player) { + return ( + player.countCards("h") && + game.hasPlayer(current => { + return current != player && current.countCards("h"); + }) + ); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2(event.name.slice(0, -5)), lib.filter.notMe) + .set("ai", target => { + return -get.attitude(get.player(), target) / (target.countCards("h") + 1); + }) + .forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + const dialog = ["选择你与" + get.translation(target) + "的等量张手牌"]; + if (player.countCards("h")) { + dialog.add("你的手牌"); + dialog.add(player.getCards("h")); + } + if (target.countCards("h")) { + dialog.add(get.translation(target) + "的手牌"); + let hs = target.getCards("h"); + if (player.hasSkillTag("viewHandcard", null, target, true)) dialog.add(hs); + else dialog.add([hs, "blank"]); + } + const result = await player + .chooseButton(dialog, true, [2, Infinity]) + .set("filterOk", () => { + const buttons = ui.selected.buttons; + return buttons.filter(i => get.owner(i.link) == get.player()).length * 2 == buttons.length; + }) + .set( + "cards", + (function () { + let cards = player + .getCards("h") + .slice(0) + .sort((a, b) => get.value(a) - get.value(b)); + let result = []; + while (result.length < target.countCards("h")) { + let card = cards.shift(); + if (get.value(card) <= 5) result.push(card); + else break; + } + return result.concat(target.getCards("h").randomGets(result.length)); + })() + ) + .set("ai", button => { + return get.event("cards").includes(button.link); + }) + .forResult(); + for (const owner of [player, target]) { + owner.addTempSkill("twniwo_block"); + owner.addGaintag( + result.links.filter(i => get.owner(i) == owner), + "twniwo" + ); + } + }, + subSkill: { + block: { + charlotte: true, + onremove(player) { + player.removeGaintag("twniwo"); + }, + mod: { + cardEnabled2(card) { + if (card.hasGaintag("twniwo")) return false; + }, + }, + }, + }, + }, + //幻刘禅 + twguihan: { + audio: 2, + enable: "phaseUse", + filter(event, player) { + return game.hasPlayer(target => lib.skill.twguihan.filterTarget(null, player, target)); + }, + filterTarget(card, player, target) { + return target != player && target.isDamaged() && target.countCards("h"); + }, + selectTarget: [1, 3], + usable: 1, + multiline: true, + multitarget: true, + async content(event, trigger, player) { + const card = get.cards(1, true)[0]; + await player.showCards([card], get.translation(player) + "发动了【归汉】"); + let num = 0; + for (const target of event.targets.sortBySeat()) { + const result = await target + .chooseCard("归汉:将一张" + get.translation(get.type2(card)) + "牌置于牌堆顶,或失去1点体力", (card, player) => { + return get.type2(card) == get.event().type; + }) + .set("type", get.type2(card)) + .set("ai", card => { + const player = get.player(); + if (get.effect(player, { name: "losehp" }, player, player) > 0) return 0; + return 7 - get.value(card); + }) + .forResult(); + if (!result.bool) await target.loseHp(); + else { + num++; + target.$throw(1, 1000); + await target.lose(result.cards, ui.cardPile, "insert"); + game.log(target, "将一张牌置于了牌堆顶"); + } + await game.delayx(); + } + const index = await player + .chooseControl() + .set("choiceList", ["摸" + get.cnNumber(num) + "张牌", "获得牌堆顶第" + get.cnNumber(num) + "张牌下的三张牌"]) + .set("prompt", "归汉:请选择一项") + .set("ai", () => { + const player = get.player(), + index = num >= 3 - num ? 0 : 1; + return player.hasSkillTag("nogain") ? 1 - index : index; + }) + .set("num", num) + .forResult("index"); + if (index == 0 && num > 0) await player.draw(3); + else if (ui.cardPile.childElementCount > num) { + const gains = Array.from(ui.cardPile.childNodes).slice(num).slice(0, 3); + if (gains.length > 0) await player.gain(gains, "gain2"); + } + }, + ai: { + order: 1, + threaten: 4.5, + result: { target: -1 }, + }, + }, + twrenxian: { + audio: 2, + enable: "phaseUse", + filter(event, player) { + return player.countCards("h", { type: "basic" }); + }, + usable: 1, + filterTarget: lib.filter.notMe, + filterCard: { type: "basic" }, + selectCard: -1, + lose: false, + discard: false, + delay: false, + position: "h", + async content(event, trigger, player) { + const target = event.target; + await player.give(event.cards, target); + target.addTempSkill("twrenxian_phase", { player: "twrenxian_phaseAfter" }); + target.markAuto("twrenxian_phase", event.cards); + }, + ai: { + order: 0.01, + threaten: 4.5, + result: { target: 1 }, + }, + locked: false, + mod: { + aiOrder(player, card, num) { + const cards = player.getCards("h", { type: "basic" }); + if (cards.length === 1 && cards.includes(card) && game.hasPlayer(target => target != player && get.attitude(player, target) > 0)) return 0; + }, + }, + subSkill: { + phase: { + charlotte: true, + onremove: true, + trigger: { global: "phaseAfter" }, + forced: true, + popup: false, + content() { + const next = player.insertPhase(); + player + .when({ global: "phaseBefore" }) + .filter(evt => evt == next) + .then(() => { + player.addTempSkill("twrenxian_mark", "phaseAfter"); + player.markAuto("twrenxian_mark", cards); + }) + .assign({ firstDo: true }) + .vars({ cards: player.getStorage("twrenxian_phase") }); + }, + }, + mark: { + mark: true, + charlotte: true, + onremove: true, + marktext: "令", + intro: { + markcount: () => 0, + content: "执行一个额外回合", + }, + mod: { + cardEnabled2(card, player) { + if (!player.getStorage("twrenxian_mark").includes(card)) return false; + }, + cardUsable(card, player, num) { + if (card.name == "sha") return Infinity; + }, + }, + }, + }, + }, + twyanzuo: { + trigger: { global: "damageSource" }, + filter(event, player) { + if (event.getParent("phase").skill !== "twrenxian_phase") return false; + const source = event.source; + return source && source != player && source.group == "shu"; + }, + usable: 3, + zhuSkill: true, + forced: true, + content() { + player.draw(); + }, + }, //李赵 twciyin: { audio: 2, @@ -225,62 +550,82 @@ const skills = { //幻诸葛亮 twbeiding: { audio: 2, - trigger: { - global: "phaseZhunbeiBegin", - }, - filter(event, player) { - return ( - player.getHp() > 0 && - get.inpileVCardList(info => { - if (!["basic", "trick"].includes(info[0])) return false; - return !player - .getStorage("twbeiding") - .map(i => i[0].name) - .includes(info[2]); - }).length - ); + audioname2: { huan_zhugeliang_shadow: "twbeidingx" }, + intro: { + content: "已记录牌名:$", }, - async cost(event, trigger, player) { - const num = player.getHp(), - vcards = get.inpileVCardList(info => { - if (!["basic", "trick"].includes(info[0])) return false; - return !player + mod: { + targetInRange(card, player, target) { + if (!player.storage.isInHuan) return; + if ( + player .getStorage("twbeiding") .map(i => i[0].name) - .includes(info[2]); - }); - const { - result: { bool, links }, - } = await player - .chooseButton([`${get.translation(event.name.slice(0, -5))}:你可以声明并记录至多${get.cnNumber(num)}个未以此法记录的牌名`, [vcards, "vcard"]], [1, num]) - .set("filterButton", button => { - return !ui.selected.buttons.some(buttonx => buttonx.link[2] == "sha") || button.link[2] != "sha"; - }) - .set("ai", button => { - const player = get.player(); - return player.getUseValue({ name: button.link[2], nature: button.link[3] }); - }); - event.result = { - bool: bool, - cost_data: links, - }; - }, - async content(event, trigger, player) { - const names = event.cost_data.map(link => [{ name: link[2], nature: link[3] }]); - game.log(player, "声明了", "#g" + get.translation(names)); - player.markAuto(event.name, names); - player.markAuto(event.name + "_use", names); - }, - intro: { - content: "已记录牌名:$", + .includes(card.name) + ) + return true; + }, }, - group: "twbeiding_use", + onremove: true, + derivation: "twbeidingx", + group: ["twbeiding_record", "twbeiding_use", "twbeiding_huan"], subSkill: { + record: { + audio: "twbeiding", + trigger: { + global: "phaseZhunbeiBegin", + }, + filter(event, player) { + if (player.storage.isInHuan) return false; + return ( + player.getHp() > 0 && + get.inpileVCardList(info => { + if (!["basic", "trick"].includes(info[0])) return false; + return !player + .getStorage("twbeiding") + .map(i => i[0].name) + .includes(info[2]); + }).length + ); + }, + async cost(event, trigger, player) { + const num = player.getHp(), + vcards = get.inpileVCardList(info => { + if (!["basic", "trick"].includes(info[0])) return false; + return !player + .getStorage("twbeiding") + .map(i => i[0].name) + .includes(info[2]); + }); + const { + result: { bool, links }, + } = await player + .chooseButton([`${get.translation(event.name.slice(0, -5))}:你可以声明并记录至多${get.cnNumber(num)}个未以此法记录的牌名`, [vcards, "vcard"]], [1, num]) + .set("filterButton", button => { + return !ui.selected.buttons.some(buttonx => buttonx.link[2] == "sha") || button.link[2] != "sha"; + }) + .set("ai", button => { + const player = get.player(); + return player.getUseValue({ name: button.link[2], nature: button.link[3] }); + }); + event.result = { + bool: bool, + cost_data: links, + }; + }, + async content(event, trigger, player) { + const names = event.cost_data.map(link => [{ name: link[2], nature: link[3] }]); + game.log(player, "声明了", "#g" + get.translation(names)); + player.markAuto("twbeiding", names); + player.markAuto("twbeiding_use", names); + }, + }, use: { trigger: { global: "phaseDiscardEnd", }, filter(event, player) { + if (player.storage.isInHuan) return false; const target = _status.currentPhase; if (!target || !target.isIn() || event.player != target) return false; return player.getStorage("twbeiding_use").length; @@ -303,28 +648,67 @@ const skills = { content: "本回合新增牌名:$", }, }, + huan: { + audio: "twbeiding", + trigger: { + player: ["useCard1", "useCardAfter"], + }, + filter(event, player, name) { + if (!player.storage.isInHuan) return false; + if ( + !player + .getStorage("twbeiding") + .map(i => i[0].name) + .includes(event.card.name) + ) + return false; + return name == "useCardAfter" || (name == "useCard1" && event.addCount !== false); + }, + forced: true, + async content(event, trigger, player) { + if (event.triggername == "useCard1") { + trigger.addCount = false; + const stat = player.getStat().card, + name = trigger.card.name; + if (typeof stat[name] == "number") stat[name]--; + } else { + await player.draw(); + player.unmarkAuto( + "twbeiding", + player.getStorage("twbeiding").filter(i => i[0].name == trigger.card.name) + ); + } + }, + }, }, }, twjielv: { audio: 2, - trigger: { - global: "phaseEnd", - }, - filter(event, player) { - return !player.hasHistory("useCard", evt => evt.targets && evt.targets.some(i => i == event.player)); - }, - forced: true, - async content(event, trigger, player) { - player.loseHp(); - }, - group: "twjielv_buff", + audioname2: { huan_zhugeliang_shadow: "twjielvx" }, + derivation: "twjielvx", + group: ["twjielv_lose", "twjielv_buff", "twjielv_huan"], subSkill: { + lose: { + audio: "twjielv", + trigger: { + global: "phaseEnd", + }, + filter(event, player) { + if (player.storage.isInHuan) return false; + return !player.hasHistory("useCard", evt => evt.targets && evt.targets.some(i => i == event.player)); + }, + forced: true, + async content(event, trigger, player) { + player.loseHp(); + }, + }, buff: { audio: "twjielv", trigger: { player: ["loseHpEnd", "damageEnd"], }, filter(event, player) { + if (player.storage.isInHuan) return false; return player.maxHp < 7 && event.num > 0; }, forced: true, @@ -333,6 +717,21 @@ const skills = { player.gainMaxHp(num); }, }, + huan: { + audio: "twjielv", + trigger: { + player: "loseMaxHpEnd", + }, + filter(event, player) { + if (!player.storage.isInHuan) return false; + return event.num > 0 && player.isDamaged(); + }, + forced: true, + async content(event, trigger, player) { + const num = Math.min(player.getDamagedHp(), trigger.num); + player.recover(num); + }, + }, }, }, twhunyou: { @@ -356,11 +755,12 @@ const skills = { player.insertPhase(); }) .then(() => { - player.changeSkin("twhunyou", "huan_zhugeliang_shadow"); - player.changeSkills(get.info("twhunyou").derivation, get.info("twchanggui").derivation); + player.storage.isInHuan = true; + player.changeSkin({ characterName: "huan_zhugeliang" }, "huan_zhugeliang_shadow"); + player.changeSkills(get.info("twhunyou").derivation, ["twhunyou"]); }); }, - derivation: ["twbeidingx", "twjielvx", "twhuanji", "twchanggui"], + derivation: ["twhuanji", "twchanggui"], subSkill: { buff: { trigger: { @@ -400,63 +800,10 @@ const skills = { }, }, twbeidingx: { - mod: { - targetInRange(card, player, target) { - if ( - player - .getStorage("twbeiding") - .map(i => i[0].name) - .includes(card.name) - ) - return true; - }, - }, audio: 2, - trigger: { - player: ["useCard1", "useCardAfter"], - }, - filter(event, player, name) { - if ( - !player - .getStorage("twbeiding") - .map(i => i[0].name) - .includes(event.card.name) - ) - return false; - return name == "useCardAfter" || (name == "useCard1" && event.addCount !== false); - }, - forced: true, - async content(event, trigger, player) { - if (event.triggername == "useCard1") { - trigger.addCount = false; - const stat = player.getStat().card, - name = trigger.card.name; - if (typeof stat[name] == "number") stat[name]--; - } else { - await player.draw(); - player.unmarkAuto( - "twbeiding", - player.getStorage("twbeiding").filter(i => i[0].name == trigger.card.name) - ); - } - }, - ai: { - combo: "twbeiding", - }, }, twjielvx: { audio: 2, - trigger: { - player: "loseMaxHpEnd", - }, - filter(event, player) { - return event.num > 0 && player.isDamaged(); - }, - forced: true, - async content(event, trigger, player) { - const num = Math.min(player.getDamagedHp(), trigger.num); - player.recover(num); - }, }, twhuanji: { audio: 2, @@ -538,13 +885,13 @@ const skills = { async content(event, trigger, player) { const num = player.maxHp - player.getHp(); await player[num > 0 ? "loseMaxHp" : "gainMaxHp"](Math.abs(num)); - player.changeSkin("twchanggui", "huan_zhugeliang"); - await player.changeSkills(get.info("twchanggui").derivation, get.info("twhunyou").derivation); + delete player.storage.isInHuan; + player.changeSkin({ characterName: "huan_zhugeliang" }, "huan_zhugeliang"); + await player.changeSkills(["twhunyou"], get.info("twhunyou").derivation); }, - derivation: ["twbeiding", "twjielv", "twhunyou"], }, //幻姜维 - huan_jiangwei_A: { + twqinghan: { audio: 2, enable: "phaseUse", usable: 1, @@ -607,7 +954,7 @@ const skills = { }, }, }, - group: "huan_jiangwei_A_compare", + group: "twqinghan_compare", subSkill: { compare: { trigger: { @@ -634,7 +981,7 @@ const skills = { }, }, }, - huan_jiangwei_B: { + twzhihuan: { audio: 2, trigger: { source: "damageBegin2", @@ -666,7 +1013,7 @@ const skills = { else choiceList[1] = '' + choiceList[1] + ""; const control = await player .chooseControl(choices, "cancel2") - .set("prompt", get.prompt("huan_jiangwei_B")) + .set("prompt", get.prompt("twzhihuan")) .set("choiceList", choiceList) .set("ai", () => { const choices = get.event("controls").slice(); @@ -700,7 +1047,7 @@ const skills = { }; }, async content(event, trigger, player) { - await trigger.cancel(); + trigger.cancel(); if (event.cost_data == "选项一") await player.gainPlayerCard(trigger.player, "e", true); else { for (let i = 1; i < 7; i++) { @@ -709,7 +1056,7 @@ const skills = { equip = get.cardPile(card => get.subtype(card, false) == sub && player.hasUseTarget(card)); if (equip) { player.$gain2(equip); - await game.asyncDelayx(); + await game.delayx(); await player.chooseUseTarget(equip, "nothrow", "nopopup", true); break; } @@ -725,18 +1072,105 @@ const skills = { } }, }, - //幻郭嘉 - huan_guojia_A: { + //幻诸葛果 + rexianyuan: { + audio: "twxianyuan", + trigger: { global: "phaseUseBegin" }, + filter(event, player) { + return event.player.hasMark("rexianyuan"); + }, + forced: true, + locked: false, + logTarget: "player", + async content(event, trigger, player) { + const target = trigger.player, + str = get.translation(target); + const num = target.countMark("rexianyuan"); + let choice; + if (!target.countCards("h")) choice = 1; + else + choice = await player + .chooseControl() + .set("choiceList", ["观看" + str + "的手牌并将其中至多" + get.cnNumber(num) + "张牌置于牌堆顶", "令" + str + "摸" + get.cnNumber(num) + "张牌"]) + .set("ai", () => (get.attitude(get.player(), get.event().getTrigger().player) > 0 ? 1 : 0)) + .forResult("index"); + if (typeof choice != "number") return; + if (choice == 0) { + const result = await player.choosePlayerCard(target, "h", "visible", [1, num], true, '###仙援###
    将其中至多' + get.cnNumber(num) + "张牌置于牌堆顶(先选择的在上)
    ").forResult(); + if (result.bool && result.cards?.length) { + const cards = result.cards.slice(); + target.$throw(cards.length, 1000); + await target.lose(cards, ui.cardPile, "insert"); + } + } else await target.draw(num); + if (_status.currentPhase !== player) target.clearMark("rexianyuan"); + }, + limit: 3, + intro: { content: "mark" }, + group: ["rexianyuan_give", "rexianyuan_gain"], + subSkill: { + give: { + audio: "twxianyuan", + enable: "phaseUse", + filter(event, player) { + return player.hasMark("rexianyuan") && game.hasPlayer(i => lib.skill.rexianyuan.subSkill.give.filterTarget(null, player, i)); + }, + filterTarget(card, player, target) { + return target != player && target.countMark("rexianyuan") < lib.skill.rexianyuan.limit; + }, + prompt: "将“仙援”标记分配给其他角色", + async content(event, trigger, player) { + const target = event.target; + const gives = Array.from({ length: player.countMark("rexianyuan") }).map((_, i) => get.cnNumber(i + 1) + "枚"); + let give; + if (gives.length == 1) give = 0; + else + give = await player + .chooseControl(gives) + .set("ai", () => 0) + .set("prompt", "仙援:将任意枚“仙援”标记分配给" + get.translation(target)) + .forResult("index"); + if (typeof give != "number") return; + give++; + player.removeMark("rexianyuan", give); + target.addMark("rexianyuan", give); + }, + ai: { + order: 1, + result: { + player: 1, + target(player, target) { + const sgn = get.sgn(get.attitude(player, target)); + return sgn == 0 ? 0.5 : sgn * (2 - sgn); + }, + }, + }, + }, + gain: { + audio: "twxianyuan", + trigger: { global: "roundStart" }, + filter(event, player) { + return player.countMark("rexianyuan") < lib.skill.rexianyuan.limit; + }, + forced: true, + locked: false, + content() { + player.addMark("rexianyuan", lib.skill.rexianyuan.limit - player.countMark("rexianyuan")); + }, + }, + }, + }, + twxianyuan: { audio: 2, enable: "phaseUse", onChooseToUse(event) { - if (!game.online && event.type == "phase" && !event.huan_guojia_A) { + if (!game.online && event.type == "phase" && !event.twxianyuan) { const player = event.player; event.set( - "huan_guojia_A", + "twxianyuan", player .getRoundHistory("useSkill", evt => { - return evt.skill == "huan_guojia_A"; + return evt.skill == "twxianyuan"; }) .reduce((list, evt) => { return list.add(evt.targets[0]); @@ -745,10 +1179,10 @@ const skills = { } }, filter(event, player) { - return player.countCards("he") && game.hasPlayer(target => lib.skill.huan_guojia_A.filterTarget(null, player, target)); + return player.countCards("he") && game.hasPlayer(target => lib.skill.twxianyuan.filterTarget(null, player, target)); }, filterTarget(card, player, target) { - return player != target && !get.event().huan_guojia_A.includes(target); + return player != target && !get.event().twxianyuan.includes(target); }, filterCard: true, selectCard: [1, 2], @@ -763,8 +1197,8 @@ const skills = { prompt: "将至多两张牌标记为“技一”并交给一名本轮未以此法交给其牌的角色", content() { const ID = player.playerid; - const skill = "huan_guojia_A_effect", - skillID = "huan_guojia_A_" + ID; + const skill = "twxianyuan_effect", + skillID = "twxianyuan_" + ID; if (!lib.skill[skillID]) { game.broadcastAll(skillID => { lib.skill[skillID] = { charlotte: true }; @@ -789,16 +1223,16 @@ const skills = { }, }, }, - group: ["huan_guojia_A_effect", "huan_guojia_A_remove"], + group: ["twxianyuan_effect", "twxianyuan_remove"], subSkill: { effect: { - audio: "huan_guojia_A", + audio: "twxianyuan", trigger: { global: "phaseUseBegin" }, filter(event, player) { - return event.player.hasCard(card => card.hasGaintag("huan_guojia_A_" + player.playerid), "h"); + return event.player.hasCard(card => card.hasGaintag("twxianyuan_" + player.playerid), "h"); }, prompt2(event, player) { - const num = event.player.storage["huan_guojia_A_effect"][player.playerid]; + const num = event.player.storage["twxianyuan_effect"][player.playerid]; return "观看其手牌并将其中至多" + get.cnNumber(num) + "张牌以任意顺序置于牌堆顶"; }, check(event, player) { @@ -807,7 +1241,7 @@ const skills = { logTarget: "player", async content(event, trigger, player) { const target = trigger.player, - num = target.storage["huan_guojia_A_effect"][player.playerid]; + num = target.storage["twxianyuan_effect"][player.playerid]; const result = await player .chooseToMove("技一:将" + get.translation(target) + "的至多" + get.cnNumber(num) + "张牌以任意顺序置于牌堆顶", true) .set("list", [[get.translation(target) + "的手牌", target.getCards("h"), "dcsushou_tag"], ["牌堆顶"]]) @@ -837,23 +1271,23 @@ const skills = { }, }, remove: { - audio: "huan_guojia_A", + audio: "twxianyuan", trigger: { player: "phaseBegin" }, filter(event, player) { - return game.hasPlayer(target => target.hasCard(card => card.hasGaintag("huan_guojia_A_" + player.playerid), "h")); + return game.hasPlayer(target => target.hasCard(card => card.hasGaintag("twxianyuan_" + player.playerid), "h")); }, forced: true, locked: false, async content(event, trigger, player) { - const targets = game.filterPlayer(target => target.hasCard(card => card.hasGaintag("huan_guojia_A_" + player.playerid), "h")); - const sum = targets.reduce((num, target) => num + target.countCards("h", card => card.hasGaintag("huan_guojia_A_" + player.playerid)), 0); - for (const target of targets) target.removeGaintag("huan_guojia_A_" + player.playerid); + const targets = game.filterPlayer(target => target.hasCard(card => card.hasGaintag("twxianyuan_" + player.playerid), "h")); + const sum = targets.reduce((num, target) => num + target.countCards("h", card => card.hasGaintag("twxianyuan_" + player.playerid)), 0); + for (const target of targets) target.removeGaintag("twxianyuan_" + player.playerid); await player.draw(sum); }, }, }, }, - huan_guojia_B: { + twlingyin: { audio: 2, trigger: { target: "useCardToTarget" }, filter(event, player) { @@ -908,7 +1342,9 @@ const skills = { evtx.name != "useCard" || !event.source.hasHistory("lose", evt => { if (evt.getParent() != evtx) return false; - return Object.keys(evt.gaintag_map || {}).includes("twkuiduan_card"); + for (var i in evt.gaintag_map) { + if (evt.gaintag_map[i].includes("twkuiduan_card")) return true; + } }) ) return false; @@ -1126,7 +1562,7 @@ const skills = { trigger.player.judging[0] = links[0]; trigger.orderingCards.addArray(links); game.log(trigger.player, "的判定牌改为", links[0]); - await game.asyncDelay(2); + await game.delay(2); const next = player.chooseToMove("鬼谋:将卡牌以任意顺序置于牌堆顶"); next.set("list", [["牌堆顶", cards]]); next.set("processAI", function (list) { @@ -1259,16 +1695,33 @@ const skills = { }, twpiankuang: { audio: 2, - getNum: (event, player) => Math.min(3, player.getHistory("sourceDamage", evt => evt.card && evt.card.name == event.card.name && evt.card != event.card).length), trigger: { + player: "useCardAfter", source: "damageBegin1", }, filter(event, player) { - return event.card && event.getParent().type == "card" && get.info("twpiankuang").getNum(event, player) > 0; + if (event.name == "useCard") return event.card.name == "sha" && player == _status.currentPhase && !player.hasHistory("sourceDamage", evt => evt.card == event.card); + return event.card?.name == "sha" && event.getParent().type == "card" && player.hasHistory("sourceDamage", evt => evt.card?.name == "sha"); }, forced: true, async content(event, trigger, player) { - trigger.num += get.info("twpiankuang").getNum(trigger, player); + if (trigger.name == "useCard") { + player.addTempSkill(event.name + "_effect"); + player.addMark(event.name + "_effect", 1, false); + } else trigger.num++; + }, + subSkill: { + effect: { + charlotte: true, + onremove: true, + markimage: "image/card/handcard.png", + intro: { content: "手牌上限-#" }, + mod: { + maxHandcard(player, num) { + return num - player.countMark("twpiankuang_effect"); + }, + }, + }, }, }, //诸葛均 @@ -1311,7 +1764,7 @@ const skills = { } if (count < 2) return; await game.asyncDraw(targets, 2); - await game.asyncDelay(); + await game.delay(); targets.unshift(player); for (const current of targets) { const cards = get.cards(count); @@ -1344,7 +1797,7 @@ const skills = { await game.cardsDiscard(discard); game.log(current, "将", discard, "置入了弃牌堆"); } - await game.asyncDelayx(); + await game.delayx(); } }, }, @@ -1362,16 +1815,19 @@ const skills = { ruleSkill: true, async content(event, trigger, player) { const beOfOneHeartLimit = player.storage.beOfOneHeartLimit || 1; - const targets = await player.chooseTarget("请选择你的“同心”角色", lib.filter.notMe, [1, beOfOneHeartLimit]).set("ai", function (target) { - const aiCheck = lib.skill.beOfOneHeart.aiCheck.slice(); - let eff = 0; - while (aiCheck.length) { - const func = aiCheck.shift(); - if (typeof func !== "function") continue; - eff += func.apply(this, arguments); - } - return eff; - }).forResultTargets(); + const targets = await player + .chooseTarget("请选择你的“同心”角色", lib.filter.notMe, [1, beOfOneHeartLimit]) + .set("ai", function (target) { + const aiCheck = lib.skill.beOfOneHeart.aiCheck.slice(); + let eff = 0; + while (aiCheck.length) { + const func = aiCheck.shift(); + if (typeof func !== "function") continue; + eff += func.apply(this, arguments); + } + return eff; + }) + .forResultTargets(); if (!targets || !targets.length) return; player.line(targets, "green"); game.log(player, "选择了", targets, "作为自己的同心角色"); @@ -1385,7 +1841,7 @@ const skills = { player.unmarkSkill("beOfOneHeart"); }) .finish(); - await game.asyncDelayx(); + await game.delayx(); }, marktext: "❤", aiCheck: [ @@ -1398,7 +1854,7 @@ const skills = { content(_, player) { return `当前同心角色:${get.translation(player.getStorage("beOfOneHeartWith"))}`; }, - } + }, }, twdaigui: { audio: 2, @@ -1418,7 +1874,7 @@ const skills = { .chooseTarget(get.prompt("twdaigui"), `选择至多${get.cnNumber(maxLimit)}名角色并亮出牌堆底等量的牌,令这些角色依次选择并获得其中一张。`, [1, maxLimit]) .set("ai", target => { const player = get.player(); - return get.attitude(player, target) * (player === target && player.needsToDiscard(1) ? 0.4: 1); + return get.attitude(player, target) * (player === target && player.needsToDiscard(1) ? 0.4 : 1); }) .forResult(); }, @@ -1437,7 +1893,7 @@ const skills = { cards, videoId ); - await game.asyncDelay(); + await game.delay(); const chooseableCards = cards.slice(); for (const current of targets) { if (!current.isIn() || !chooseableCards.length) continue; @@ -1495,7 +1951,7 @@ const skills = { } }, videoId); game.addVideo("cardDialog", null, videoId); - }, + }, }, twcairu: { audio: 2, @@ -1731,7 +2187,7 @@ const skills = { async content(event, trigger, player) { const targets = event.targets; await player.draw(targets.length + 1); - await game.asyncDelayx(); + await game.delayx(); for (const target of targets) { if ( !target.hasCard(card => { @@ -1758,7 +2214,7 @@ const skills = { }) .set("sourcex", player) .set("addCount", false); - await game.asyncDelayx(); + await game.delayx(); } }, }, @@ -1791,7 +2247,9 @@ const skills = { }).length, targets = game.players.slice().concat(game.dead.slice()); for (const target of targets) { - num += target.actionHistory[i].useCard.filter(evt => { + const historyx = target.actionHistory[target.actionHistory.length - (player.actionHistory.length - i)]; + if (!historyx) continue; + num += historyx.useCard.filter(evt => { return evt.card.name == "juedou" && evt.targets && evt.targets.includes(player); }).length; } @@ -2083,7 +2541,7 @@ const skills = { } if (player.getHp() > 0) await player.draw(player.getHp(), target.getHp() > 0 ? "nodelay" : "").set("gaintag", ["twjuexing"]); if (target.getHp() > 0) await target.draw(target.getHp()).set("gaintag", ["twjuexing"]); - await game.asyncDelay(); + await game.delay(); }, }, lizhan: { @@ -2124,43 +2582,32 @@ const skills = { twxiayong: { audio: 2, audioname: ["tw_yanliang"], + trigger: { global: "damageBegin1" }, + filter(event, player) { + if (event.getParent().type != "card" || event.card.name != "juedou" || !event.player.isIn()) return false; + const evt = event.getParent(); + if (evt && evt.targets && (event.player != player || player.countCards("h") > 0)) { + return evt.player === player || evt.targets.includes(player); + } + return false; + }, + logTarget: "player", + logAudio(event, player) { + return "twxiayong" + (event.player === player ? 1 : 2) + ".mp3"; + }, locked: true, - group: "twxiayong_effect", - subSkill: { - effect: { - trigger: { global: "damageBegin1" }, - filter(event, player) { - if (event.getParent().type != "card" || event.card.name != "juedou" || !event.player.isIn()) return false; - const evt = event.getParent() - if (evt && evt.targets && (event.player != player || player.countCards("h") > 0)) { - return (evt.player === player || evt.targets.includes(player)); - } - return false; - }, - forced: true, - popup: false, - async content(event, trigger, player) { - player.logSkill("twxiayong" + (trigger.player === player ? "1" : "2"), trigger.player); - if (trigger.player === player) { - const cards = player.getCards("h", card => { - return lib.filter.cardDiscardable(card, player, "twxiayong"); - }); - if (cards.length > 0) player.discard(cards.randomGet()); - } else { - trigger.increase("num"); - } - }, - }, + popup: false, + async content(event, trigger, player) { + if (trigger.player === player) { + const cards = player.getCards("h", card => { + return lib.filter.cardDiscardable(card, player, "twxiayong"); + }); + if (cards.length > 0) player.discard(cards.randomGet()); + } else { + trigger.increase("num"); + } }, }, - twxiayong1: { - audio: true, - audioname: ["tw_yanliang"], - sourceSkill: "twxiayong", - }, - twxiayong2: { - inherit: "twxiayong1", - }, //袁谭 twqiaosi: { audio: 2, @@ -2619,7 +3066,6 @@ const skills = { audio: 2, trigger: { global: "phaseDiscardEnd" }, filter(event, player) { - if (player.hasSkill("twdengjian_ban")) return false; return event.player != player && lib.skill.twdengjian.getCards(player, event.player).length; }, getCards(player, target) { @@ -2661,7 +3107,6 @@ const skills = { }, group: "twdengjian_buff", subSkill: { - ban: { charlotte: true }, buff: { mod: { aiOrder(player, card, num) { @@ -2707,12 +3152,10 @@ const skills = { if (!player.hasSkill("twxinshou_0")) return goon; if (!player.hasSkill("twxinshou_1")) return goon && game.hasPlayer(target => target != player); return ( - !player.hasSkill("twdengjian_ban") && game.hasPlayer(target => { if (target == player) return false; return !target.hasSkill("twdengjian", null, null, false); - }) && - player.hasSkill("twdengjian", null, null, false) + }) && player.hasSkill("twdengjian", null, null, false) ); }, direct: true, @@ -2744,12 +3187,11 @@ const skills = { if (bool) { const target = targets[0]; player.logSkill("twxinshou", target); - player.addSkill("twdengjian_ban"); + player.tempBanSkill("twdengjian", "forever"); target.addAdditionalSkills("twxinshou_" + player.playerid, "twdengjian"); player.popup("登剑"); target.popup("登剑"); game.log(player, "将", "#g【登剑】", "传授给了", target); - game.log(player, "的", "#g【登剑】", "被失效了"); player .when("phaseBegin") .then(() => { @@ -2761,7 +3203,7 @@ const skills = { const evt = history[i]; if (evt.name == "damage" && evt.card && evt.source && evt.card.name == "sha" && evt.source == target) { player.popup("洗具"); - player.removeSkill("twdengjian_ban"); + delete player.storage[`temp_ban_twdengjian`]; game.log(player, "结束了", "#g【登剑】", "的失效状态"); return; } @@ -3311,6 +3753,9 @@ const skills = { return event.hasNature(); }, forced: true, + logAudio(event, player, name) { + return name == "damageBegin2" ? "twfenwang2.mp3" : "twfenwang1.mp3"; + }, content: function () { "step 0"; if (event.triggername == "damageBegin2") { @@ -3978,12 +4423,12 @@ const skills = { twchungang: { audio: 2, init: () => { - game.addGlobalSkill("twchungang_global"); + game.addGlobalSkill("twchungang_global", null, null, false); }, onremove: player => { if ( !game.hasPlayer(i => { - return player !== i && i.hasSkill("twchungang"); + return i.hasSkill("twchungang"); }, true) ) game.removeGlobalSkill("twchungang_global"); @@ -4015,7 +4460,7 @@ const skills = { player: "dieAfter", }, filter(event, player) { - return !game.hasPlayer(i => i.hasSkill("twchungang"), true); + return !game.hasPlayer(i => i.hasSkill("twchungang", null, null, false), true); }, silent: true, forceDie: true, @@ -4068,9 +4513,10 @@ const skills = { content: function () { "step 0"; player.draw(); + "step 1"; if (player.countCards("he")) player.chooseCard("将一张牌置于" + get.translation(target) + "的武将牌上", "he", true); else event.finish(); - "step 1"; + "step 2"; if (result.bool) target.addToExpansion(result.cards, player, "give").gaintag.add("yishe"); }, ai: { @@ -5040,57 +5486,89 @@ const skills = { return player.countCards("he"); }, direct: true, - content: function () { - "step 0"; - var list = [[], []]; - for (var current of game.players) { - if (current == player) continue; - var cards = []; - var weapon = false; - for (var card of player.getCards("he")) { - if (!lib.filter.cardDiscardable(card, player)) continue; - if (get.subtype(card) == "equip1" && !ui.selected.cards.some(i => get.subtype(i) == "equip1")) { - if (16 - get.value(card) > 0) { - cards.push(card); - weapon = true; - } - } - if (7 - get.value(card) > 0) cards.push(card); + chooseAi: (event, player) => { + let cards = [], + wq = []; //把武器牌和其他能弃置的牌分别按value从小到大排序 + player.getCards("he", card => { + //[价值, id, 是否为武器牌] + if (!lib.filter.cardDiscardable(card, player)) return false; + if (get.subtype(card) == "equip1") wq.push([get.value(card, player), card.cardid, true]); + else cards.push([get.value(card, player), card.cardid]); + }); + cards.sort((a, b) => { + return a[0] - b[0]; + }); + wq.sort((a, b) => { + return a[0] - b[0]; + }); + let targets = [], //适合目标:[目标, 收益, 牌组] + damage = get.damageEffect(player, player, event.player); + game.countPlayer(cur => { + if (player === cur) return false; + let eff = get.damageEffect(cur, player, event.player); + let dui = eff + damage - 2 * (wq.length ? wq[0][0] : cards[0][0]); //对砸 + if (eff <= 0) { + if (dui > 0) targets.push([cur, dui, [wq.length ? wq[0][1] : cards[0][1]]]); //这都能卖血?! + return false; } - if (cards.length > current.hp) { - var val = 0; - for (var card of cards) { - if (get.subtype(card) != "equip1") val += get.value(card); - } - if (val < 30) list[0].push(current); + if ( + cards.length + wq.length <= cur.hp && //牌不够弃且没有武器可砸或者有但是太亏的不选 + (!wq.length || dui <= 0) + ) + return false; + let allcards = cards.concat(wq).sort((a, b) => { + return a[0] - b[0]; + }), + can; //所有可弃牌再从小到大排序 + if (allcards.length <= cur.hp) { + //牌不够弃拿一张武器崩血的 + targets.push([cur, dui, [wq[0][1]]]); + return false; } - if ((weapon && player.hp > 2) || get.damageEffect(player, current, player) > 10) list[1].push(current); - } - list[0].sort((a, b) => { - return get.damageEffect(b, player, player) - get.damageEffect(a, player, player); + can = eff - allcards.slice(0, cur.hp + 1).reduce((acc, val) => acc + val[0], 0); + if (!wq.length) { + //没武器只能凑数砸的 + if (can > 0) targets.push([cur, can, allcards.slice(0, cur.hp + 1).map(i => i[1])]); + return false; + } + let other = [wq[0]]; //拿最便宜的武器补刀 + for (let card of allcards) { + if (other.length > cur.hp) break; + if (wq[0][1] === card[1]) continue; + other.push(card); + } + if (can < 2 * eff - other.reduce((acc, val) => acc + val[0], 0)) { + //换一张武器牌的收益 + can = 2 * eff - other.reduce((acc, val) => acc + val[0], 0); + allcards = other.map(i => i[1]); + } + if (dui > can) { + can = dui; + allcards = [wq[0][1]]; + } + if (can > 0) targets.push([cur, can, allcards]); //这个时候can应该都是正的了,懒得再测了 }); + if (targets.length) + return targets.sort((a, b) => { + return b[1] - a[1]; + })[0]; + return [null, 0, []]; + }, + content: function () { + "step 0"; player.chooseCardTarget({ filterCard: lib.filter.cardDiscardable, selectCard: [1, Infinity], position: "he", filterTarget: lib.filter.notMe, prompt: get.prompt2("twliexi"), - targetsx: [list[0][0], list[1][0]], + aiSelected: lib.skill.twliexi.chooseAi(_status.event, player), ai1: function (card) { - var targetx = _status.event.targetsx[0]; - var hasWeapon = ui.selected.cards.some(i => get.subtype(i) == "equip1"); - if (!targetx) { - var targetx = _status.event.targetsx[1]; - if (get.subtype(card) == "equip1" && !hasWeapon) return 30 - get.value(card); - return -get.value(card); - } - if (ui.selected.cards.length > targetx.hp) return 0; - if (get.subtype(card) == "equip1" && !hasWeapon) return 30 - get.value(card); - return 7 - get.value(card); + if (get.event().aiSelected[2].includes(card.cardid)) return 30 - get.value(card); + return 0; }, ai2: function (target) { - var targetx = _status.event.targetsx[0] || _status.event.targetsx[1]; - if (targetx == target) return 10; + if (get.event().aiSelected[0] === target) return 10; return 0; }, }); @@ -5719,7 +6197,7 @@ const skills = { }, }, ai: { - combo: "twjuntun" + combo: "twjuntun", }, }, //蒋济 @@ -6714,19 +7192,16 @@ const skills = { } return true; }, + logAudio: () => "mibei1.mp3", + skillAnimation: true, + animationColor: "water", content: function () { player.awakenSkill("twmibei"); - player.logSkill("twmibei_achieve"); game.log(player, "成功完成使命"); player.addSkills("twmouli"); }, intro: { content: "已使用牌名:$" }, subSkill: { - achieve: { - audio: "mibei1", - skillAnimation: true, - animationColor: "water", - }, mark: { trigger: { player: "useCard1" }, filter: function (event, player) { @@ -6741,7 +7216,7 @@ const skills = { }, }, fail: { - audio: "mibei2", + audio: "mibei2.mp3", trigger: { player: "phaseUseEnd" }, forced: true, filter: function (event, player) { @@ -6824,7 +7299,7 @@ const skills = { var cards = []; for (var i = 0; i < ui.cardPile.childNodes.length; i++) { var card = ui.cardPile.childNodes[i]; - if (get.type(card) == "basic") cards.push(card); + if (get.type(card, null, false) == "basic") cards.push(card); } event.set("twmouli", cards); }, @@ -6899,7 +7374,7 @@ const skills = { var list = []; for (var i = 0; i < ui.cardPile.childNodes.length; i++) { var card = ui.cardPile.childNodes[i]; - if (get.type(card, player) == "basic" && !list.includes(card.name)) list.push(card.name); + if (get.type(card, null, false) == "basic" && !list.includes(card.name)) list.push(card.name); } if (tag == "respondSha") return list.includes("sha"); if (tag == "respondShan") return list.includes("shan"); @@ -7027,7 +7502,7 @@ const skills = { var evt = event.getl(player); if (!evt || !evt.cards2 || !evt.cards2.length) return false; for (var i of evt.cards2) { - if (get.type(i, player) != "basic") return true; + if (get.type(i, null, player) != "basic") return true; } return false; }, @@ -7036,7 +7511,7 @@ const skills = { var num = 0, evt = trigger.getl(player); for (var i of evt.cards2) { - if (get.type(i, player) != "basic" && num < 5) num++; + if (get.type(i, null, player) != "basic" && num < 5) num++; } player.chooseToGuanxing(num); player.chooseBool("羽化:是否摸" + get.cnNumber(num) + "张牌?").set("frequentSkill", "twyuhua"); @@ -7311,7 +7786,7 @@ const skills = { if (get.attitude(player, target) < 0 && player.hasSkill("twejian")) { var dam = get.damageEffect(target, player, target); if (dam > 0) return dam; - var type = get.type(card, target), + var type = get.type2(card, target), ts = target.getCards("he", function (card) { return get.type(card) == type; }); @@ -9931,7 +10406,7 @@ const skills = { }, }, }, - ai:{ + ai: { combo: "twzhenliang", }, }, @@ -10277,13 +10752,10 @@ const skills = { var target2 = result.targets[0]; player.line(target2, "green"); target - .chooseToUse( - function (card, player, event) { - if (get.name(card) != "sha") return false; - return lib.filter.filterCard.apply(this, arguments); - }, - "对" + get.translation(target2) + "使用一张杀,否则本回合使用伤害牌指定" + get.translation(player) + "为目标时须交给" + get.translation(player) + "两张牌,否则此牌对" + get.translation(player) + "无效" - ) + .chooseToUse(function (card, player, event) { + if (get.name(card) != "sha") return false; + return lib.filter.filterCard.apply(this, arguments); + }, "对" + get.translation(target2) + "使用一张杀,否则本回合使用伤害牌指定" + get.translation(player) + "为目标时须交给" + get.translation(player) + "两张牌,否则此牌对" + get.translation(player) + "无效") .set("targetRequired", true) .set("complexSelect", true) .set("filterTarget", function (card, player, target) { @@ -10413,6 +10885,7 @@ const skills = { } return 10 - get.value(card); }, + logAudio: () => 1, content: function () { player.give(cards, target).gaintag.add("twkujianx"); player.addSkill("twkujian_draw"); @@ -10438,7 +10911,7 @@ const skills = { }, }, effect: { - target: function (card, player, target) { + target_use: function (card, player, target) { if (player == target && get.type(card) == "equip") { if (player.countCards("e", { subtype: get.subtype(card) })) { if ( @@ -10455,7 +10928,7 @@ const skills = { }, subSkill: { draw: { - audio: "twkujian", + audio: "twkujian2.mp3", trigger: { global: ["useCardAfter", "respondAfter"] }, forced: true, logTarget: "player", @@ -10476,7 +10949,7 @@ const skills = { }, }, discard: { - audio: "twkujian", + audio: "twkujian3.mp3", trigger: { global: ["loseAfter", "equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], }, @@ -12780,13 +13253,10 @@ const skills = { direct: true, content: function () { player - .chooseToUse( - function (card, player, event) { - if (get.name(card) != "sha") return false; - return lib.filter.filterCard.apply(this, arguments); - }, - "侠望:是否对" + get.translation(trigger.source) + "使用一张杀?" - ) + .chooseToUse(function (card, player, event) { + if (get.name(card) != "sha") return false; + return lib.filter.filterCard.apply(this, arguments); + }, "侠望:是否对" + get.translation(trigger.source) + "使用一张杀?") .set("logSkill", "twxiawang") .set("complexSelect", true) .set("filterTarget", function (card, player, target) { @@ -13107,6 +13577,7 @@ const skills = { return game.hasPlayer(current => current != player) && (event.name != "phase" || game.phaseNumber == 0); }, forced: true, + logAudio: () => 1, content: function () { "step 0"; player.chooseTarget("请选择【随征】的目标", lib.translate.twsuizheng_info, lib.filter.notMe, true).set("ai", function (target) { @@ -13128,7 +13599,7 @@ const skills = { subSkill: { draw: { charlotte: true, - audio: "twsuizheng", + audio: "twsuizheng3.mp3", trigger: { global: "damageSource" }, filter: function (event, player) { return player.getStorage("twsuizheng").includes(event.source); @@ -13140,7 +13611,7 @@ const skills = { }, }, xianfu: { - audio: "twsuizheng", + audio: "twsuizheng2.mp3", trigger: { global: "damageEnd" }, filter: function (event, player) { return player.getStorage("twsuizheng").includes(event.player) && event.player.isIn(); @@ -14246,7 +14717,7 @@ const skills = { direct: true, usable: 1, filter: function (event, player) { - return event.isFirstTarget && event.targets.length > 0 && (event.card.name == "sha" || (get.type(event.card, false) == "trick" && get.tag(event.card, "damage") > 0)); + return event.isFirstTarget && event.targets.length > 0 && (event.card.name == "sha" || (get.type(event.card, null, false) == "trick" && get.tag(event.card, "damage") > 0)); }, content: function () { "step 0"; @@ -14750,7 +15221,7 @@ const skills = { } else event.finish(); "step 2"; var target = trigger.player; - if (target.getCards("h").includes(card) && get.type(card, target) == "equip" && target.hasUseTarget(card)) target.chooseUseTarget(card, "nopopup"); + if (target.getCards("h").includes(card) && get.type(card, null, target) == "equip" && target.hasUseTarget(card)) target.chooseUseTarget(card, "nopopup"); }, }, //Powered by @污言噫对 @@ -14924,10 +15395,12 @@ const skills = { twlihuo3: { trigger: { player: "useCardAfter" }, filter: function (event, player) { - return (event.card.twlihuo_buffed && + return ( + event.card.twlihuo_buffed && player.getHistory("sourceDamage", function (evt) { return evt.card == event.card && evt._dyinged; - }).length > 0); + }).length > 0 + ); }, forced: true, audio: "lihuo", @@ -15016,7 +15489,6 @@ const skills = { ) ) { if ( - get.attitude(player, target) < 0 && !trigger.player.hasSkillTag("jueqing", false, target) && !target.hasSkillTag("filterDamage", null, { @@ -15876,7 +16348,7 @@ const skills = { game.addGlobalSkill("twzhian_ai"); }, onremove: function (player) { - if (!game.hasPlayer(current => current.hasSkill("twzhian"), true)) game.removeGlobalSkill("twzhian_ai"); + if (!game.hasPlayer(current => current.hasSkill("twzhian", null, null, false), true)) game.removeGlobalSkill("twzhian_ai"); }, usable: 1, trigger: { global: "useCardAfter" }, @@ -15977,7 +16449,7 @@ const skills = { ai: { trigger: { player: "dieAfter" }, filter: function (event, player) { - return !game.hasPlayer(current => current.hasSkill("twzhian"), true); + return !game.hasPlayer(current => current.hasSkill("twzhian", null, null, false), true); }, silent: true, forceDie: true, @@ -16516,7 +16988,7 @@ const skills = { names = []; for (var i = 0; i < ui.discardPile.childNodes.length; i++) { var card = ui.discardPile.childNodes[i]; - if (get.type(card, false) == "basic" && !names.includes(card.name)) { + if (get.type(card, null, false) == "basic" && !names.includes(card.name)) { cards.push(card); names.push(card.name); } @@ -16533,7 +17005,7 @@ const skills = { names = []; for (var i = 0; i < ui.discardPile.childNodes.length; i++) { var card = ui.discardPile.childNodes[i]; - if (get.type(card, false) == "basic" && !names.includes(card.name)) { + if (get.type(card, null, false) == "basic" && !names.includes(card.name)) { cards.push(card); names.push(card.name); } @@ -16570,7 +17042,7 @@ const skills = { return ( !player.hasSkill("twhengjiang2") && event.targets.length == 1 && - ["basic", "trick"].includes(get.type(event.card, false)) && + ["basic", "trick"].includes(get.type(event.card, null, false)) && player.isPhaseUsing() && game.hasPlayer(function (current) { return player.inRange(current) && lib.filter.targetEnabled2(event.card, player, current); @@ -16661,6 +17133,10 @@ const skills = { if (get.position(card) == "h") return 9 - get.value(card); return 7 - get.value(card); }, + logAudio(event, player) { + const num = Math.max(get.equipNum(event.cards[0]), 3); + return "yuanhu" + num + ".mp3"; + }, content: function () { "step 0"; target.equip(cards[0]); @@ -17640,30 +18116,28 @@ const skills = { dingfa: { audio: 2, trigger: { player: "phaseDiscardAfter" }, - direct: true, - filter: function (event, player) { - var num = 0; - player.getHistory("lose", function (evt) { + filter(event, player) { + let num = 0; + player.getHistory("lose", evt => { num += evt.cards2.length; }); return num >= player.hp; }, - content: function () { - "step 0"; - player - .chooseTarget(get.prompt("dingfa"), "操作提示:选择自己以回复体力,或选择其他角色以造成伤害", function (card, player, target) { + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt(event.name.slice(0, -5)), "操作提示:选择自己以回复体力,或选择其他角色以造成伤害", (card, player, target) => { return target == player ? player.isDamaged() : true; }) - .set("ai", function (target) { + .set("ai", target => { + const player = get.player(); return target != player ? get.damageEffect(target, player, player) : get.recoverEffect(player, player, player); - }); - "step 1"; - if (result.bool) { - var target = result.targets[0]; - player.logSkill("dingfa", target); - if (target == player) player.recover(); - else target.damage(); - } + }) + .forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + if (target == player) await player.recover(); + else await target.damage(); }, }, dz_mantianguohai: { diff --git a/character/tw/sort.js b/character/tw/sort.js index c0524dca15..c338399b2d 100644 --- a/character/tw/sort.js +++ b/character/tw/sort.js @@ -7,7 +7,7 @@ const characterSort = { tw_yunchouyan: ["tw_jiangqing"], tw_zhu: ["tw_beimihu", "tw_ol_sunjian", "ol_liuyu", "tw_menghuo"], tw_swordsman: ["xia_yuzhenzi", "xia_shie", "xia_shitao", "xia_guanyu", "xia_liubei", "xia_xiahousone", "xia_xiahoudun", "xia_zhangwei", "xia_xushu", "xia_wangyue", "xia_liyàn", "xia_tongyuan", "xia_lusu", "xia_dianwei", "xia_zhaoe", "xia_xiahouzie"], - tw_beidingzhongyuan: ["huan_zhugeliang","huan_jiangwei","huan_zhanghe", "huan_guojia", "huan_weiyan", "huan_simayi", "huan_zhaoyun"], + tw_beidingzhongyuan: ["huan_luxun", "huan_liushan", "huan_zhugeliang", "huan_jiangwei", "huan_zhanghe", "huan_zhugeguo", "huan_weiyan", "huan_simayi", "huan_zhaoyun"], tw_mobile: ["nashime", "tw_gexuan", "tw_zhugeguo"], tw_mobile2: ["tw_chengpu", "tw_guohuai", "old_quancong", "tw_caoxiu", "tw_guanqiujian", "tw_re_fazheng", "tw_madai", "tw_zhangfei", "tw_guyong", "tw_handang", "tw_xuezong", "tw_yl_luzhi"], tw_yijiang: ["tw_caoang", "tw_caohong", "tw_zumao", "tw_dingfeng", "tw_maliang", "tw_xiahouba"], diff --git a/character/tw/translate.js b/character/tw/translate.js index d195f530f7..071709a743 100644 --- a/character/tw/translate.js +++ b/character/tw/translate.js @@ -680,8 +680,6 @@ const translates = { twjuexing: "绝行", twjuexing_info: "出牌阶段限一次。你可以视为对一名其他角色使用一张【决斗】。此牌对一名角色生效时,你与其将所有手牌扣置于武将牌上,然后各摸等同于当前体力值的牌。此牌结算结束后,你与所有目标角色弃置本次以此法摸的牌,然后获得扣置于武将牌上的牌。历战:当你因〖绝行〗摸牌时,摸牌数+1。", twxiayong: "狭勇", - twxiayong1: "狭勇", - twxiayong2: "狭勇", twxiayong_info: "锁定技。当你使用的【决斗】或目标角色包括你的【决斗】造成伤害时,若受伤角色为你,则你随机弃置一张手牌;否则你令此伤害+1。", twqiaosi: "峭嗣", twqiaosi_info: "结束阶段,你可以获得由其他角色区域直接置入或经由处理区置入弃牌堆的所有牌,然后若你以此法获得的牌数小于你的体力值,则你失去1点体力。", @@ -702,10 +700,10 @@ const translates = { chenjie_info: "一名角色的判定牌生效前,你可打出一张花色相同的牌。系统将你打出的牌作为新判定牌,将原判定牌置入弃牌堆。然后你摸两张牌。", huan_weiyan: "幻魏延", huan_weiyan_prefix: "幻", - twqiji: "奇计", + twqiji: "奇击", twqiji_info: "出牌阶段开始时,你可以视为对一名其他角色使用X张无距离限制且不计入次数的【杀】,此【杀】指定目标时,其可以选择一名本回合未以此法选择的其他角色,被选择的角色摸一张牌,然后其可以将此【杀】的目标转移给自己(X为出牌阶段开始时你手牌的类型数)。", twpiankuang: "偏狂", - twpiankuang_info: "锁定技,你使用的牌造成的伤害+Y(Y为你本回合使用过的且造成过伤害的相同牌名的牌的数量,且至多为3)。", + twpiankuang_info: "锁定技。①当你使用【杀】造成伤害时,若你本回合使用【杀】造成过伤害,此伤害+1。②你的回合内,当你使用【杀】结算结束后,若此【杀】未造成伤害,本回合你的手牌上限-1。", huan_simayi: "幻司马懿", huan_simayi_prefix: "幻", twzongquan: "纵权", @@ -722,18 +720,20 @@ const translates = { huan_zhanghe_prefix: "幻", twkuiduan: "溃端", twkuiduan_info: "锁定技。①当你使用【杀】指定唯一目标后,你与其的随机两张手牌获得“溃端”标记,这些牌视为无属性【杀】。②一名角色使用含“溃端”标记的牌造成伤害时,若其含“溃端”标记的手牌数大于受伤角色含“溃端”标记的手牌数,则此伤害+1。", - huan_guojia: "幻郭嘉", - huan_guojia_prefix: "幻", - huan_guojia_A: "技一", - huan_guojia_A_info: "①出牌阶段限三次,你可以将至多两张牌标记为“技一”并交给一名本轮未以此法交给其牌的角色。②拥有“技一”标记牌的角色的出牌阶段开始时,你可以观看其手牌并将其中至多X张牌以任意顺序置于牌堆顶(X为你本局游戏发动〖技一〗交给其的牌数)。③回合开始时,你移去所有角色手牌中的“技一”标记,然后摸等量的牌。", - huan_guojia_B: "技二", - huan_guojia_B_info: "当你成为普通锦囊牌的目标时,你可以展示牌堆顶的一张牌,若此牌与使用的牌的:颜色相同,你获得此牌;花色相同,你令此牌对你无效;颜色不同,你将此牌置入弃牌堆。", + huan_zhugeguo: "幻诸葛果", + huan_zhugeguo_prefix: "幻", + twxianyuan: "仙援", + twxianyuan_info: "①出牌阶段限三次,你可以将至多两张牌标记为“仙援”并交给一名本轮未以此法交给其牌的角色。②拥有“仙援”标记牌的角色的出牌阶段开始时,你可以观看其手牌并将其中至多X张牌以任意顺序置于牌堆顶(X为你本局游戏发动〖仙援〗交给其的牌数)。③回合开始时,你移去所有角色手牌中的“仙援”标记,然后摸等量的牌。", + rexianyuan: "仙援", + rexianyuan_info: "①一轮游戏开始时,你获得3枚“仙援”标记(一名角色至多拥有3枚“仙援”标记)。②出牌阶段,你可以将“仙援”标记分配给其他角色。③拥有“仙援”标记的角色的出牌阶段开始时,你选择一项:⒈观看其手牌,将其中至多X张牌置于牌堆顶;⒉令其摸X张牌(X为其拥有的“仙援”标记数)。然后若当前回合角色不为你,则移去其所有“仙援”标记。", + twlingyin: "灵隐", + twlingyin_info: "当你成为普通锦囊牌的目标时,你可以展示牌堆顶的一张牌,若此牌与使用的牌的:颜色相同,你获得此牌;花色相同,你令此牌对你无效;颜色不同,你将此牌置入弃牌堆。", huan_jiangwei: "幻姜维", huan_jiangwei_prefix: "幻", - huan_jiangwei_A: "技一", - huan_jiangwei_A_info: "①出牌阶段限一次,你可使用一张装备牌与一名其他角色拼点,若你赢,你可视为对其使用一张以其为唯一目标的普通锦囊牌;若两张拼点牌颜色相同,你与其获得对方的拼点牌。②你的拼点牌点数+X(X为你装备区牌数的两倍)。", - huan_jiangwei_B: "技二", - huan_jiangwei_B_info: "当你使用【杀】对目标角色造成伤害时,你可以防止此伤害并选择一项:1.获得其装备区里的一张牌;2.获得并使用一张牌堆或弃牌堆中你空置装备栏对应类别的装备牌,然后其下次使用【闪】时随机弃置两张手牌。", + twqinghan: "擎汉", + twqinghan_info: "①出牌阶段限一次,你可使用一张装备牌与一名其他角色拼点,若你赢,你可视为对其使用一张以其为唯一目标的普通锦囊牌;若两张拼点牌颜色相同,你与其获得对方的拼点牌。②你的拼点牌点数+X(X为你装备区牌数的两倍)。", + twzhihuan: "治宦", + twzhihuan_info: "当你使用【杀】对目标角色造成伤害时,你可以防止此伤害并选择一项:1.获得其装备区里的一张牌;2.获得并使用一张牌堆或弃牌堆中你空置装备栏对应类别的装备牌,然后其下次使用【闪】时随机弃置两张手牌。", huan_zhugeliang: "幻诸葛亮", huan_zhugeliang_prefix: "幻", twbeiding: "北定", @@ -755,6 +755,20 @@ const translates = { twciyin_info: "①你或同心角色的准备阶段,你可以亮出牌堆顶X张牌,然后将其中任意张♠或♥牌置于武将牌上,称为“荫”,然后将其余牌放回牌堆顶(X为当前回合角色的体力值的两倍,且至多为10)。②你每获得三张“荫”后,你选择本局游戏未选择的一项:1.增加1点体力上限并回复1点体力;2.将手牌补至体力上限。", twchenglong: "成龙", twchenglong_info: "觉醒技,一名角色的结束阶段,若你已经执行过〖慈荫〗所有选项,你获得武将牌上的所有“荫”并失去〖慈荫〗,然后你从四张蜀势力或群势力武将牌中选择至多两个技能描述中含【杀】或【闪】的技能获得之。", + huan_liushan: "幻刘禅", + huan_liushan_prefix: "幻", + twguihan: "归汉", + twguihan_info: "出牌阶段限一次,你可以选择至多三名已受伤且有手牌的其他角色。你展示牌堆顶的一张牌,然后这些角色依次选择一项:①将一张与此牌类别相同的牌置于牌堆顶;②失去1点体力。然后你选择一项,摸X张牌,获得牌堆顶第X张牌下的三张牌(X为本次选择选项①的角色数)。", + twrenxian: "任贤", + twrenxian_info: "出牌阶段限一次,你可以将手牌中的所有基本牌交给一名其他角色,然后令其于本回合结束后执行一个额外的回合(只能使用你交给其的牌,且使用【杀】无次数限制)。", + twyanzuo: "延祚", + twyanzuo_info: "主公技,锁定技。每回合限三次,其他蜀势力角色于〖任贤〗回合造成伤害后,你摸一张牌。", + huan_luxun: "幻陆逊", + huan_luxun_prefix: "幻", + twlifeng: "砺锋", + twlifeng_info: "出牌阶段 你可弃置两张不同点数的牌,然后对一名距离x以内的角色造成一点伤害(x为你弃置牌点数的差)。该角色因此受到伤害时,其可重铸一张手牌(若没有手牌,则改为摸一张牌),若此牌点数与你弃置的两张牌点数相同,或处于两张牌点数之间,其防止此伤害,且【砺锋】失效直到回合结束。", + twniwo: "逆涡", + twniwo_info: "出牌阶段开始时,你可选择一名其他角色,然后选择你与其等量的手牌。若如此做,直到本回合结束,你与其均无法使用或打出你以此法选择的牌。", }; export default translates; diff --git a/character/tw/voices.js b/character/tw/voices.js index 1168415bf6..4d4911bcf8 100644 --- a/character/tw/voices.js +++ b/character/tw/voices.js @@ -1,4 +1,14 @@ export default { + "#twqinghan1": "二十四代终未尽,今以一隅誓还天!", + "#twqinghan2": "维继丞相遗托,当负擎汉之重。", + "#twzhihuan1": "贪心祸国谗言媚主,汝罪不容诛!", + "#twzhihuan2": "阉宦小人,何以蔽天!", + "#huan_jiangwei:die": "九州未定,维……有负丞相遗托。", + "#twlingyin1": "我自逍遥天地,何拘凡尘俗法。", + "#twlingyin2": "朝暮露霞雾,夜枕夕缠绵。", + "#twxianyuan1": "顺天者,天助之。", + "#twxianyuan2": "所思所寻,皆得天应。", + "#huan_zhugeguo:die": "仙缘已了,魂入轮回。", "#twbeiding1": "众将同心扶汉,北伐或可功成。", "#twbeiding2": "虽失天时地利,亦有三分胜机。", "#twjielv1": "竭一国之材,尽万人之力。", diff --git a/character/xiake.js b/character/xiake.js index 84f5234f11..630c31b6ab 100644 --- a/character/xiake.js +++ b/character/xiake.js @@ -6,7 +6,7 @@ game.import("character", function () { xk_guyuexuan: ["male", "qun", 4, ["rouquan", "gzhenji"]], xk_jinji: ["male", "shu", 4, ["zhongzhan", "lianpo"]], // xk_shenxiangyun:['female','wei',3,['zhenjiu']], - // xk_fujianhan: ["male", "qun", 4, ["zuijian", "zitong"]], + // xk_fujianhan: ["male", "qun", 4, ["zitong"]], }, skill: { zhongzhan: { diff --git a/character/xianding/card.js b/character/xianding/card.js index 339352456b..32da445c80 100644 --- a/character/xianding/card.js +++ b/character/xianding/card.js @@ -97,16 +97,7 @@ const cards = { }, loseDelay: false, onLose: function () { - var next = game.createEvent("baiyin_recover"); - event.next.remove(next); - var evt = event.getParent(); - if (evt.getlx === false) evt = evt.getParent(); - evt.after.push(next); - next.player = player; - next.setContent(function () { - if (player.isDamaged()) player.logSkill("pyzhuren_club"); - player.recover(); - }); + player.addTempSkill("pyzhuren_club_lose"); }, }, pyzhuren_spade: { diff --git a/character/xianding/character.js b/character/xianding/character.js index ab1f6a6751..09f9e5e019 100644 --- a/character/xianding/character.js +++ b/character/xianding/character.js @@ -1,5 +1,9 @@ const characters = { - dc_sb_guojia: ["male", "wei", 3, ["dcxianmou", "dclunshi"]], + dc_sb_jushou: ["male", "qun", 3, ["dcsbzuojun", "dcsbmuwang"]], + dc_sb_chengyu: ["male", "wei", 3, ["dcshizha", "dcgaojian"]], + dc_lingcao: ["male", "wu", "4/5", ["dcdufeng"]], + zhugejing: ["male", "qun", 3, ["dcyanzuo", "dczuyin", "dcpijian"], ["name:诸葛|京"]], + liutan: ["female", "shu", 3, ["dcjingyin", "dcchixing"]], bianyue: ["female", "wei", 3, ["dcbizu", "dcwuxie"]], zhupeilan: ["female", "wu", 3, ["dccilv", "dctongdao"]], dc_sb_zhangxiu: ["male", "qun", 4, ["dcsbfuxi", "dcsbhaoyi"]], diff --git a/character/xianding/characterReplace.js b/character/xianding/characterReplace.js index f03e5d3c35..039e8a3c38 100644 --- a/character/xianding/characterReplace.js +++ b/character/xianding/characterReplace.js @@ -2,7 +2,7 @@ const characterReplaces = { wenyang: ["wenyang", "db_wenyang", "diy_wenyang", "std_db_wenyang"], gexuan: ["gexuan", "tw_gexuan"], panshu: ["panshu", "re_panshu"], - yangwan: ["yangwan", "sp_yangwan"], + yangwan: ["yangwan", "sp_yangwan", "jd_sp_yangwan"], sunyi: ["re_sunyi", "sunyi", "tw_sunyi"], fengfangnv: ["fengfangnv", "re_fengfangnv"], luotong: ["dc_luotong", "luotong", "std_dc_luotong"], @@ -12,10 +12,12 @@ const characterReplaces = { qinghegongzhu: ["qinghegongzhu", "dc_qinghegongzhu"], caofang: ["caofang", "jsrg_caofang"], caomao: ["caomao", "mb_caomao"], - sp_zhenji: ["sp_zhenji", "jsrg_zhenji"], + sp_zhenji: ["sp_zhenji", "jsrg_zhenji", "mb_sp_zhenji"], zhugejin: ["zhugejin", "dc_sb_zhugejin"], caoang: ["caoang", "dc_sb_caoang"], zhangxiu: ["zhangxiu", "dc_sb_zhangxiu"], + yuanji: ["yuanji", "ol_yuanji"], + zhangfen: ["zhangfen", "mb_zhangfen"], }; export default characterReplaces; diff --git a/character/xianding/dynamicTranslate.js b/character/xianding/dynamicTranslate.js index 5dd6ec90e2..fc74250c92 100644 --- a/character/xianding/dynamicTranslate.js +++ b/character/xianding/dynamicTranslate.js @@ -68,10 +68,10 @@ const dynamicTranslates = { var storage = player.storage.dcsbmengmou; var str = "转换技,每回合每项各限一次,当你得到其他角色的牌后,或其他角色得到你的牌后:"; if (!storage) str += ''; - str += "阴,你可以令该角色使用至多X张【杀】,且其每以此法造成1点伤害,其回复1点体力;"; + str += "阳,你可以令该角色使用至多X张【杀】,且其每以此法造成1点伤害,其回复1点体力;"; if (!storage) str += ""; if (storage) str += ''; - str += "阳,你可令该角色打出至多X张【杀】,然后其失去Y点体力。"; + str += "阴,你可令该角色打出至多X张【杀】,然后其失去Y点体力。"; if (storage) str += ""; str += "(X为你的体力上限,Y为X-其打出【杀】数)"; return str; @@ -80,16 +80,16 @@ const dynamicTranslates = { var storage = player.storage.dcsbyingmou; var str = "转换技,每回合限一次,你对其他角色使用牌后,你可以选择其中一名目标角色:"; if (!storage) str += ''; - str += "阴,你将手牌数摸至与其相同(至多摸五张),然后视为对其使用一张【火攻】;"; + str += "阳,你将手牌数摸至与其相同(至多摸五张),然后视为对其使用一张【火攻】;"; if (!storage) str += ""; if (storage) str += ''; - str += "阳,令一名手牌数为全场最大的角色对其使用手牌中所有的【杀】和伤害类锦囊牌(若其没有可使用的牌则将手牌数弃至与你相同)。"; + str += "阴,令一名手牌数为全场最大的角色对其使用手牌中所有的【杀】和伤害类锦囊牌(若其没有可使用的牌则将手牌数弃至与你相同)。"; if (storage) str += ""; return str; }, dcsbquanmou(player) { - if (player.storage.dcsbquanmou) return '转换技。出牌阶段每名角色限一次,你可以令一名攻击范围内的其他角色交给你一张牌。阴:当你于本阶段内下次对其造成伤害时,取消之;阳:当你于本阶段内下次对其造成伤害后,你可以选择除其外的至多三名其他角色,对这些角色依次造成1点伤害。'; - return '转换技。出牌阶段每名角色限一次,你可以令一名攻击范围内的其他角色交给你一张牌。阴:当你于本阶段内下次对其造成伤害时,取消之;阳:当你于本阶段内下次对其造成伤害后,你可以选择除其外的至多三名其他角色,对这些角色依次造成1点伤害。'; + if (player.storage.dcsbquanmou) return '转换技。出牌阶段每名角色限一次,你可以令一名攻击范围内的其他角色交给你一张牌。阳:当你于本阶段内下次对其造成伤害时,取消之;阴:当你于本阶段内下次对其造成伤害后,你可以选择除其外的至多三名其他角色,对这些角色依次造成1点伤害。'; + return '转换技。出牌阶段每名角色限一次,你可以令一名攻击范围内的其他角色交给你一张牌。阳:当你于本阶段内下次对其造成伤害时,取消之;阴:当你于本阶段内下次对其造成伤害后,你可以选择除其外的至多三名其他角色,对这些角色依次造成1点伤害。'; }, dcshouzhi(player) { let skillName = "dcshouzhi"; @@ -98,25 +98,14 @@ const dynamicTranslates = { }, dcsbfumou(player) { const storage = player.storage.dcsbfumou; - var str = "转换技,出牌阶段限一次,你可以观看一名其他角色A的手牌并展示其一半手牌:"; + var str = "转换技,出牌阶段限一次,你可以观看一名其他角色A的手牌并展示其至多一半手牌:"; if (!storage) str += ''; - str += "阴,并将这些牌交给另一名其他角色B,然后你与A各摸X张牌(X为A以此法失去的手牌数);"; + str += "阳,并将这些牌交给另一名其他角色B,然后你与A各摸X张牌(X为A以此法失去的手牌数);"; if (!storage) str += ""; if (storage) str += ''; - str += "阳,令A依次使用这些牌中所有其可以使用的牌(无距离限制且不可被响应)。"; + str += "阴,令A依次使用这些牌中所有其可以使用的牌(无距离限制且不可被响应)。"; if (storage) str += ""; return str; }, - dcxianmou(player) { - const storage = player.storage.dcxianmou; - var str = "转换技,你失去过牌的回合结束时,你可以:"; - if (!storage) str += ''; - str += "阴,观看牌堆顶五张牌并获得至多X张牌,若未获得X张牌则获得〖遗计〗直到再发动此项;"; - if (!storage) str += ""; - if (storage) str += ''; - str += "阳,观看一名角色手牌并弃置其中至多X张牌,若弃置X张牌则你进行一次【闪电】判定。"; - if (storage) str += ""; - return str+="(X为你本回合失去牌数)"; - }, }; export default dynamicTranslates; diff --git a/character/xianding/index.js b/character/xianding/index.js index 2e67ed2a80..3c9df1a07a 100644 --- a/character/xianding/index.js +++ b/character/xianding/index.js @@ -20,11 +20,18 @@ game.import("character", function () { xianding: characterSort, }, characterSubstitute: { - dc_sb_simayi: [], - dc_sb_zhouyu: [], - dc_sb_lusu: [], - dc_sb_jiaxu: [], - dc_sb_guojia: [], + dc_sb_simayi: [ + ["dc_sb_simayi_shadow", []], + ], + dc_sb_zhouyu: [ + ["dc_sb_zhouyu_shadow", []], + ], + dc_sb_lusu: [ + ["dc_sb_lusu_shadow", []], + ], + dc_sb_jiaxu: [ + ["dc_sb_jiaxu_shadow", []], + ], }, characterFilter: { ...characterFilters }, characterTitle: { diff --git a/character/xianding/intro.js b/character/xianding/intro.js index 34a7d32b7f..4ede0a4bdb 100644 --- a/character/xianding/intro.js +++ b/character/xianding/intro.js @@ -1,4 +1,5 @@ const characterIntro = { + liutan: "柳氏,姜维之妻。唯一的记载来自《大唐敕修烈山四岳天水郡姜姓古谱总世系》:“维字伯约,初仕魏中郎将,后归蜀汉,封大将军、平襄侯,夫人柳氏。”", cuimao: "请分别查看「崔琰」和「毛玠」的武将介绍。", bailingyun: "柏灵筠,女,是电视剧《大军师司马懿之军师联盟》、《虎啸龙吟》中的主要角色之一,由张钧甯饰演。20岁,是曹丕赏赐司马懿的美人,也是曹丕的眼线,被送入司马府中为妾室。柔弱美貌、心机极深。", caoxian: "曹宪(生卒年不详),女,沛国谯县(今安徽省亳州市)人。东汉末年历史人物,汉献帝刘协嫔妃,魏武帝曹操女儿。建安十八年,嫁给汉献帝刘协,受封为贵人。黄初元年(220年),兄弟曹丕称帝后,汉献帝成为山阳公,不知所终。", @@ -57,6 +58,7 @@ const characterIntro = { guanyue: "关樾,传说记载之人物,声称是关羽之孙,关平长子。未见载于正史,仅记载于清朝地方志以及传说。清·《江陵县志》:“娶镇东将军女赵氏。生子樾,世居江陵。”。清·《关氏宗谱·江陵县儒学册结》:“平子樾,因守祖、父陵墓遂家于荆州焉,此荆州之关氏所由来也。”", zhupeilan: "景皇后朱氏(234年―265年),吴郡吴县(今江苏省苏州市)人,吴景帝孙休的皇后,野史记载其名为朱佩兰。骠骑将军朱据与朱公主的独生女,吴末帝孙皓的表姐和叔母。出身江南四大姓之一吴郡朱氏。赤乌末年,与孙休成婚,永安元年(258年),孙休继位,封为夫人,永安五年(262年),被立为皇后。孙休去世后为太后,甘露元年秋(265年)被孙皓逼杀,葬于定陵。", bianyue: "魏高贵乡公皇后卞氏,琅琊开阳(山东临沂县)人,曹魏高贵乡公曹髦的皇后,魏武帝曹操武宣卞皇后弟弟卞秉的曾孙女。卞皇后祖父为卞兰,卞兰之弟卞琳的女儿又为魏元帝曹奂皇后,故元帝卞皇后是高贵乡公卞皇后的堂姑。《三国志·魏书·三少帝纪第四》:“(正元二年)三月,立皇后卞氏,大赦。夏四月甲寅,封后父卞隆为列侯。”——这是《三国志》对她唯一的记载。", + zhugejing: "诸葛京(生卒年不详),字行宗;三国名臣诸葛亮之孙,诸葛瞻次子。诸葛瞻与诸葛京之兄诸葛尚在绵竹抗击魏军战死后,与诸葛亮有直系血缘关系的仅存诸葛京一脉。蜀汉灭亡之后,他与诸葛攀之子诸葛显于咸熙元年(264年)内移河东,初任郿县令,后任江州刺史。" }; export default characterIntro; diff --git a/character/xianding/skill.js b/character/xianding/skill.js index 86fa742ce6..1db7a2ec35 100644 --- a/character/xianding/skill.js +++ b/character/xianding/skill.js @@ -3,137 +3,549 @@ import cards from "../sp2/card.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { - //新谋郭嘉 - dcxianmou: { - mark: true, - marktext: "☯", - zhuanhuanji(player, skill) { - player.storage[skill] = !player.storage[skill]; - player.changeSkin({ characterName: "dc_sb_guojia" }, "dc_sb_guojia" + (player.storage[skill] ? "_shadow" : "")); + //谋沮授 + dcsbzuojun: { + audio: 2, + enable: "phaseUse", + usable: 1, + filterTarget: true, + async content(event, trigger, player) { + const target = event.targets[0]; + const { result } = await target.draw(3); + const { + result: { index }, + } = await target + .chooseControl() + .set("choiceList", [`${get.translation(result)}不能被你使用且不计入你的手牌上限`, `失去1点体力,再摸一张牌并使用其中任意张牌,然后弃置其余牌`]) + .set("ai", () => { + const player = get.player(), + cards = get.event("cards"); + let eff = get.effect(player, { name: "losehp" }, player, player) + get.effect(player, { name: "draw" }, player, player); + for (const card of cards) { + eff += player.getUseValue(card); + } + return eff > 6 ? 1 : 0; + }) + .set("cards", result); + if (index == 0) { + target.addGaintag(result, "dcsbzuojun_tag"); + target.addSkill("dcsbzuojun_effect"); + target + .when({ player: "phaseEnd" }) + .filter(evt => evt != event.getParent("phase")) + .assign({ + firstDo: true, + }) + .then(() => { + player.removeGaintag("dcsbzuojun_tag", toRemove); + if (!player.hasCard(card => card.hasGaintag("dcsbzuojun_tag"))) { + player.removeSkill("dcsbzuojun_effect"); + } + }) + .vars({ toRemove: result }); + } else { + await target.loseHp(); + const { result: result2 } = await target.draw(); + let cards = result.slice().concat(result2); + while (cards.some(i => get.owner(i) == target && target.hasUseTarget(i))) { + const result = await target + .chooseToUse(function (card, player, event) { + if (get.itemtype(card) != "card" || !get.event("cards").includes(card)) return false; + return lib.filter.filterCard.apply(this, arguments); + }, "佐军:是否使用其中的一张牌?") + .set("cards", cards) + .set("addCount", false) + .forResult(); + if (result.bool) { + cards.removeArray(result.cards); + await game.delayx(); + } else break; + } + cards = cards.filter(i => get.owner(i) == target); + if (cards.length) await target.discard(cards); + } }, - intro: { - content: function (storage) { - if (!storage) return "你失去过牌的回合结束时,你可以观看牌堆顶五张牌并获得至多X张牌,若未获得X张牌则获得〖遗计〗直到再发动此项(X为你本回合失去牌数)"; - return "你失去过牌的回合结束时,你可以观看一名角色手牌并弃置其中至多X张牌,若弃置X张牌则你进行一次【闪电】判定(X为你本回合失去牌数)"; + ai: { + order: 10, + result: { + target: 1, + }, + }, + subSkill: { + tag: {}, + effect: { + charlotte: true, + onremove(player) { + player.removeGaintag("dcsbzuojun_tag"); + }, + mod: { + ignoredHandcard(card, player) { + if (card.hasGaintag("dcsbzuojun_tag")) return true; + }, + cardDiscardable(card, player, name) { + if (name == "phaseDiscard" && card.hasGaintag("dcsbzuojun_tag")) return false; + }, + cardEnabled(card, player) { + if (card.cards?.some(i => i.hasGaintag("dcsbzuojun_tag"))) return false; + }, + cardSavable(card, player) { + if (card.cards?.some(i => i.hasGaintag("dcsbzuojun_tag"))) return false; + }, + }, }, }, + }, + dcsbmuwang: { audio: 2, - audioname: ["dc_sb_guojia_shadow"], trigger: { - global: "phaseEnd", + player: "loseAfter", + global: ["cardsDiscardAfter", "loseAsyncAfter", "equipAfter"], }, + forced: true, filter(event, player) { - return player.getHistory("lose", evt => evt.cards2 && evt.cards2.length).length; - }, - async cost(event, trigger, player) { - let num = 0; - player.getHistory("lose", evt => { - if (evt.cards2) num += evt.cards2.length; - }); - if (player.storage.dcxianmou) { - event.result = await player.chooseTarget(get.prompt("dcxianmou"), `观看一名角色手牌并弃置其中至多${num}张牌`, function (card, player, target) { - return target.countCards("h"); - }).set("ai", function (target) { - const player = _status.event.player; - return get.effect(target, { name: "guohe_copy2" }, player, player); - }).forResult(); - } - else { - event.result = await player.chooseBool(get.prompt("dcxianmou"), `观看牌堆顶五张牌并获得至多${num}张牌`).forResult(); + if (player.getHistory("useSkill", evt => evt.skill == "dcsbmuwang").length) return false; + const filter = card => ["basic", "trick"].includes(get.type(card)); + if (event.name != "cardsDiscard") { + return event.getd(player, "cards2").filter(filter).length > 0; + } else { + if (event.cards.filterInD("d").filter(filter).length <= 0) return false; + const evt = event.getParent(); + if (evt.name != "orderingDiscard") return false; + const evtx = evt.relatedEvent || evt.getParent(); + if (evtx.player != player) return false; + return player.hasHistory("lose", evtxx => { + return evtx == (evtxx.relatedEvent || evtxx.getParent()); + }); } }, async content(event, trigger, player) { - let num = 0; - player.getHistory("lose", evt => { - if (evt.cards2) num += evt.cards2.length; - }); - player.changeZhuanhuanji("dcxianmou"); - if (player.storage.dcxianmou) { - player.addAdditionalSkills("dcxianmou", []); - let cards = game.cardsGotoOrdering(get.cards(5)).cards; - const result = await player.chooseButton([`是否获得至多${num}张牌?`, cards], [1, num]).set("ai", function (button) { - if (ui.selected.buttons.length + 1 >= _status.event.maxNum) return 0; - return get.value(button.link); - }).set("maxNum", num).forResult(); - if (result.bool) await player.gain(result.links, "gain2"); - if (!result.bool || result.links.length < num) await player.addAdditionalSkills("dcxianmou", "new_reyiji"); - } - else { - const target = event.targets[0]; - const result = await player.discardPlayerCard(target, "h", `是否弃置${get.translation(target)}至多${num}张牌?`, [1, num], "visible").set("ai", function (button) { - if (ui.selected.buttons.length + 1 >= _status.event.maxNum) return 5 - get.value(button.link); - return get.value(button.link); - }).set("maxNum", num).forResult(); - if (result.bool && result.links.length >= num) await player.executeDelayCardEffect("shandian"); + let cards; + if (trigger.name != "cardsDiscard") { + cards = trigger.getd(player, "cards2"); + } else cards = trigger.cards.filterInD("d"); + cards = cards.filter(card => ["basic", "trick"].includes(get.type(card))); + if (cards.length) { + const next = player.gain(cards, "gain2"); + next.gaintag.add("dcsbmuwang_tag"); + await next; + player.addTempSkill("dcsbmuwang_lose"); } }, - derivation: "new_reyiji", - group: "dcxianmou_change", subSkill: { - change: { - audio: "dcxianmou", - audioname: ["dc_sb_guojia_shadow"], + tag: {}, + lose: { + charlotte: true, + onremove(player) { + player.removeGaintag("dcsbmuwang_tag"); + }, trigger: { - global: "phaseBefore", - player: "enterGame", + player: "loseAfter", + global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], }, filter(event, player) { - return event.name != "phase" || game.phaseNumber == 0; - }, - prompt2(event, player) { - //无名杀先阳后阴,不要问为什么 - return "切换【先谋】为状态" + (player.storage.dcsbyingmou ? "阳" : "阴"); + if (!player.countCards("he")) return false; + const evt = event.getl(player); + if (!evt || !evt.cards2 || !evt.cards2.length) return false; + if (event.name == "lose") { + return evt.cards2.some(card => (evt.gaintag_map[card.cardid] || []).includes("dcsbmuwang_tag")); + } + return player.hasHistory("lose", evt => { + if (event != evt.getParent()) return false; + return evt.cards2.some(card => (evt.gaintag_map[card.cardid] || []).includes("dcsbmuwang_tag")); + }); }, - check: () => Math.random() > 0.5, - content() { - player.changeZhuanhuanji("dcxianmou"); + forced: true, + popup: false, + async content(event, trigger, player) { + if (player.countCards("he")) await player.chooseToDiscard("he", true); }, }, }, }, - dclunshi: { + //谋汉尼拔 + dcshizha: { audio: 2, - position: "hs", - enable: "chooseToUse", + trigger: { + global: "useCard", + }, + usable: 1, filter(event, player) { - if (!player.countCards("hs")) return false; - if (player.countCards("h", { color: "black" }) != player.countCards("h", { color: "red" })) return false; - if (event.type != "wuxie") return false; - let info = event.info_map; - if (!info || get.type(info.card) != "trick") return false; - return info.player != info.target; + if (event.player == player) return false; + let history = game.getGlobalHistory("everything"); + for (let i = history.length - 1; i >= 0; i--) { + const evt = history[i]; + if (evt == event || evt.player != event.player) continue; + if (evt.name == "useCard") return false; + if (evt.name == "changeHp") return true; + } + return false; }, - filterCard: true, - viewAs: { - name: "wuxie", + check(event, player) { + let eff = 0; + if (event.card.name == "wuxie" || event.card.name == "shan") { + if (get.attitude(player, event.player) < -1) { + eff = -1; + } + } else if (event.targets && event.targets.length) { + for (var i = 0; i < event.targets.length; i++) { + eff += get.effect(event.targets[i], event.card, event.player, player); + } + } + return eff <= 0; }, - viewAsFilter(player) { - if (!player.countCards("hs")) return false; - if (player.countCards("h", { color: "black" }) != player.countCards("h", { color: "red" })) return false; - return true; + logTarget: "player", + async content(event, trigger, player) { + trigger.targets.length = 0; + trigger.all_excluded = true; + if (trigger.cards && trigger.cards.someInD()) await player.gain(trigger.cards.filterInD(), "gain2"); }, - prompt: "将一张手牌当无懈可击使用", - check: function (card) { - return 8 - get.value(card); + }, + dcgaojian: { + audio: 2, + trigger: { + global: "cardsDiscardAfter", + }, + filter(event, player) { + if (!player.isPhaseUsing()) return false; + var evt = event.getParent(); + if (evt.name != "orderingDiscard") return false; + var evtx = evt.relatedEvent || evt.getParent(); + return evtx.name == "useCard" && evtx.player == player && get.type2(evtx.card) == "trick"; + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2("dcgaojian"), lib.filter.notMe) + .set("ai", target => { + return get.attitude(get.player(), target); + }) + .forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + let showCards = [], + useCard; + while (showCards.length < 5) { + const cards = game.cardsGotoOrdering(get.cards()).cards; + showCards.addArray(cards); + target.showCards(cards, get.translation(player) + "发动了【告谏】"); + if (get.type2(cards[0]) == "trick") { + useCard = cards[0]; + break; + } + } + if (useCard && target.hasUseTarget(useCard)) { + const result = await target + .chooseControl("使用牌", "交换牌") + .set("choiceList", [`使用${get.translation(useCard)}`, `使用任意张手牌与${get.translation(showCards)}中的等量牌交换`]) + .set("ai", () => { + if (_status.event.useValue > 2) return "使用牌"; + return "交换牌"; + }) + .set("useValue", target.getUseValue(useCard)) + .forResult(); + if (result.control == "使用牌") { + await target.chooseUseTarget(useCard, true); + return; + } + } + if (!target.countCards("h") || !showCards.length) return; + const result = await target + .chooseToMove("告谏:是否交换其中任意张牌?") + .set("list", [ + ["你的手牌", target.getCards("h"), "dcgaojian_tag"], + ["展示牌", showCards], + ]) + .set("filterMove", (from, to) => { + return typeof to != "number"; + }) + .set("filterOk", moved => { + return moved[1].some(card => get.owner(card)); + }) + .set("processAI", list => { + const num = Math.min(list[0][1].length, list[1][1].length); + const player = get.event("player"); + const cards1 = list[0][1].slice().sort((a, b) => get.value(a, "raw") - get.value(b, "raw")); + const cards2 = list[1][1].slice().sort((a, b) => get.value(b, "raw") - get.value(a, "raw")); + return [cards1.slice().addArray(cards2.slice(0, num)), cards2.slice().addArray(cards1.slice(0, num))]; + }) + .forResult(); + if (result.bool) { + const lose = result.moved[1].slice(); + const gain = result.moved[0].slice().filter(i => !get.owner(i)); + if (lose.some(i => get.owner(i))) + await target.lose( + lose.filter(i => get.owner(i)), + ui.special + ); + for (let i = lose.length - 1; i--; i >= 0) { + ui.cardPile.insertBefore(lose[i], ui.cardPile.firstChild); + } + game.updateRoundNumber(); + if (gain.length) await target.gain(gain, "draw"); + } else { + if (!topCards.length) return; + for (let i = topCards.length - 1; i--; i >= 0) { + ui.cardPile.insertBefore(topCards[i], ui.cardPile.firstChild); + } + game.updateRoundNumber(); + } + }, + }, + //诸葛京 + dcyanzuo: { + audio: 2, + enable: "phaseUse", + usable: 3, + filter(event, player) { + var count = player.getStat("skill").dcyanzuo; + if (count && count > player.countMark("dcyanzuo_zuyin")) return false; + return player.countCards("he", card => ["trick", "basic"].includes(get.type(card, player))); + }, + filterCard(card, player) { + return ["trick", "basic"].includes(get.type(card, player)); + }, + check(card) { + const player = _status.event.player; + return player.getUseValue(card) + 3; + }, + position: "he", + lose: false, + discard: false, + async content(event, trigger, player) { + const next = player.addToExpansion(event.cards, player, "give"); + next.gaintag.add("dcyanzuo"); + await next; + const cards = player.getExpansions("dcyanzuo"); + const result = await player + .chooseButton(["是否视为使用其中一张牌?", cards]) + .set("filterButton", button => { + const player = _status.event.player; + const card = { + name: get.name(button.link), + suit: get.suit(button.link), + isCard: true, + }; + return player.hasUseTarget(card); + }) + .set("ai", button => { + const player = _status.event.player; + const card = { + name: get.name(button.link), + suit: get.suit(button.link), + isCard: true, + }; + return player.getUseValue(card); + }) + .forResult(); + if (result.bool) { + const card = { + name: get.name(result.links[0]), + suit: get.suit(result.links[0]), + isCard: true, + }; + await player.chooseUseTarget(card, true, false); + } + }, + ai: { + order: 9, + result: { + player: 1, + }, + }, + onremove(player, skill) { + const cards = player.getExpansions(skill); + if (cards.length) player.loseToDiscardpile(cards); + player.clearMark("dcyanzuo_zuyin", false); + }, + intro: { + markcount: "expansion", + content: "expansion", + mark(dialog, storage, player) { + const cards = player.getExpansions("dcyanzuo"); + if (cards.length) dialog.addSmall(cards); + const marks = player.countMark("dcyanzuo_zuyin"); + if (marks > 0) dialog.addText(`〖研作〗发动次数+${marks}`); + }, + }, + }, + dczuyin: { + audio: 2, + forced: true, + trigger: { + target: "useCardToTargeted", + }, + filter(event, player) { + if (event.player == player) return false; + return event.card.name == "sha" || get.type(event.card) == "trick"; + }, + async content(event, trigger, player) { + const cards = player.getExpansions("dcyanzuo"); + if (cards.some(card => card.name == trigger.card.name)) { + trigger.getParent().all_excluded = true; + trigger.getParent().targets.length = 0; + const discards = cards.filter(card => card.name == trigger.card.name); + if (discards.length) await player.loseToDiscardpile(discards); + } else { + const card = get.cardPile(card => card.name == trigger.card.name); + if (card){ + const next = player.addToExpansion(card, "gain2"); + next.gaintag.add("dcyanzuo"); + await next; + } + if (player.countMark("dcyanzuo_zuyin") < 2 && player.hasSkill("dcyanzuo", null, null, false)) player.addMark("dcyanzuo_zuyin", 1, false); + } + }, + }, + dcpijian: { + audio: 2, + trigger: { + player: "phaseEnd", + }, + filter(event, player) { + return player.getExpansions("dcyanzuo").length >= game.countPlayer(); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2("dcpijian")) + .set("ai", target => { + const player = _status.event.player; + return get.damageEffect(target, player, player); + }) + .forResult(); + }, + async content(event, trigger, player) { + await player.loseToDiscardpile(player.getExpansions("dcyanzuo")); + const target = event.targets[0]; + await target.damage(2); + }, + }, + //凌操 + dcdufeng: { + audio: 2, + trigger: { player: "phaseUseBegin" }, + forced: true, + async content(event, trigger, player) { + const list = []; + for (let i = 1; i < 6; i++) { + if (player.isDisabled(i)) continue; + list.push("equip" + i); + } + list.push("cancel2"); + const next = player.chooseControl(list); + next.set("prompt", "独锋:请废除一个装备栏,或点击“取消”失去1点体力"); + next.set("ai", () => { + const list = get.event().list.slice(), + player = get.player(); + if (player.hp <= 2 && list.length > 1) list.remove("cancel2"); + const listx = list.filter(subtype => !player.getEquips(subtype).length); + if (listx.length) return listx.randomGet(); + return list.randomGet(); + }); + next.set("list", list); + const { result } = await next; + if (result.control == "cancel2") await player.loseHp(); + else await player.disableEquip(result.control); + if (!player.isIn()) return; + const num = Math.min(player.countDisabled() + player.getDamagedHp(), player.maxHp); + await player.draw(num); + player.addTempSkill("dcdufeng_effect"); + player.addMark("dcdufeng_effect", num, false); }, - group: "dclunshi_nowuxie", subSkill: { - nowuxie: { - trigger: { - player: "useCard", + effect: { + charlotte: true, + onremove: true, + intro: { + content: "本回合攻击范围与使用【杀】的次数上限均为#", }, - forced: true, - locked: false, - popup: false, - filter: function (event, player) { - return event.card.name == "wuxie" && event.skill && event.skill == "dclunshi"; + mod: { + attackRangeBase(player, num) { + return player.countMark("dcdufeng_effect"); + }, + cardUsable(card, player, num) { + if (card.name == "sha") return player.countMark("dcdufeng_effect"); + }, }, - content: function () { - trigger.directHit.addArray(game.players); + }, + }, + }, + //柳婒 + dcjingyin: { + audio: 2, + trigger: { global: "useCardAfter" }, + filter(event, player) { + if (_status.currentPhase === event.player) return false; + if (!game.hasPlayer(target => target != event.player)) return false; + return event.card.name == "sha" && event.cards && event.cards.someInD(); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt("dcjingyin"), "令一名角色获得" + get.translation(trigger.cards.filterInD()), (card, player, target) => { + return target != get.event().getTrigger().player; + }) + .set("ai", target => { + const player = get.event().player, + cards = get.event().getTrigger().cards.filterInD(); + return cards.reduce((sum, card) => sum + get.value(card, target) * get.value(card, player), 0); + }) + .forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + target.addSkill("dcjingyin_tag"); + target.gain(trigger.cards.filterInD(), "gain2").set("gaintag", "dcjingyin_tag"); + }, + subSkill: { + tag: { + charlotte: true, + mod: { + /* + targetInRange(card, player, target) { + if (!card.cards) return; + if (card.cards.some(i => i.hasGaintag("dcjingyin_tag"))) return true; + }, + */ + cardUsable(card, player, target) { + if (!card.cards) return; + if (card.cards.some(i => i.hasGaintag("dcjingyin_tag"))) return Infinity; + }, + aiOrder: function (player, card, num) { + if (get.itemtype(card) == "card" && card.hasGaintag("dcjingyin_tag")) return num - 0.1; + }, }, }, }, }, + dcchixing: { + audio: 2, + trigger: { global: "phaseUseEnd" }, + filter(event, player) { + return lib.skill.dcchixing.getNum(event).length; + }, + frequent: true, + async content(event, trigger, player) { + const result = await player.draw(lib.skill.dcchixing.getNum(trigger).length).forResult(); + if (Array.isArray(result) && result.some(card => get.name(card, false) == "sha")) { + await player + .chooseToUse(function (card) { + const evt = _status.event; + if (!lib.filter.cardEnabled(card, evt.player, evt)) return false; + let cards = [card]; + if (Array.isArray(card.cards)) cards.addArray(card.cards); + return cards.containsSome(...evt.cards) && get.name(card, false) == "sha"; + }, "迟行:是否使用一张【杀】?") + .set("cards", result); + } + }, + getNum(event) { + return game + .getGlobalHistory("everything", evt => { + if (evt.getParent("phaseUse") != event) return false; + return evt.name == "cardsDiscard" || (evt.name == "lose" && evt.position == ui.discardPile); + }) + .reduce((list, evt) => list.addArray(evt.cards.filter(i => i.name == "sha")), []); + }, + }, //卞玥 dcbizu: { audio: 2, @@ -167,47 +579,54 @@ const skills = { dcwuxie: { audio: 2, trigger: { - player: "gainAfter", - global: "loseAsyncAfter", + player: "phaseUseEnd", }, filter(event, player) { - const cards = event.getg(player).filter(i => get.owner(i) == player && get.position(i) == "h" && get.tag(i, "damage")); - return cards.length; + return game.hasPlayer(current => current != player && current.countCards("h")); }, - usable: 1, async cost(event, trigger, player) { - const cards = trigger.getg(player).filter(i => get.owner(i) == player && get.position(i) == "h" && get.tag(i, "damage")); event.result = await player - .chooseCardTarget({ - prompt: get.prompt("dcwuxie"), - prompt2: "将获得的任意张伤害牌置于牌堆底并令一名其他角色弃置等量的牌", - filterTarget: lib.filter.notMe, - filterCard: card => get.event().cards.includes(card), - cards: cards, - selectCard: [1, cards.length], - ai1(card) { - return 3 / (Math.abs(get.value(card)) + 0.1); - }, - ai2(target) { - const player = get.player(); - return get.effect(target, { name: "guohe_copy2" }, player, player) * ui.selected.cards.length; - }, + .chooseTarget(get.prompt2("dcwuxie"), function (card, player, target) { + return target != player && target.countCards("h"); + }) + .set("ai", target => { + const player = get.player(); + return -get.attitude(player, target) * target.countCards("h"); }) - .set("cards", cards) .forResult(); }, async content(event, trigger, player) { const target = event.targets[0], - cards = event.cards, - num = cards.length; - await player.lose(cards, ui.cardPile); - for (let i = 0; i < cards.length; i++) { - const card = cards[i]; - card.fix(); - ui.cardPile.appendChild(card); + cards1 = player.getCards("h", card => get.tag(card, "damage")), + cards2 = target.getCards("h", card => get.tag(card, "damage")); + if (cards1.length) { + player.$throw(cards1.length, 1000); + await player.lose(cards1, ui.cardPile); + for (let i = 0; i < cards1.length; i++) { + const card = cards1[i]; + card.fix(); + ui.cardPile.appendChild(card); + } + } + if (cards2.length) { + target.$throw(cards2.length, 1000); + await target.lose(cards2, ui.cardPile); + for (let i = 0; i < cards2.length; i++) { + const card = cards2[i]; + card.fix(); + ui.cardPile.appendChild(card); + } + } + await game.delayx(); + if (cards1.length != cards2.length) { + const recover = cards1.length < cards2.length ? target : player; + if (!recover.isDamaged()) return; + const result = await player + .chooseBool("是否令" + get.translation(recover) + "回复1点体力?") + .set("choice", get.recoverEffect(recover, player, player) > 0) + .forResult(); + if (result.bool) await recover.recover(); } - await game.asyncDelayx(); - if (target.countCards("he")) await target.chooseToDiscard(num, "he", true); }, }, //朱佩兰 @@ -268,7 +687,7 @@ const skills = { mark: true, intro: { markcount: storage => 3 - (storage || []).length, - content: storage => ((storage || []).length ? ("已移去了" + storage + "项") : "暂未移去任何项"), + content: storage => ((storage || []).length ? "已移去了" + storage + "项" : "暂未移去任何项"), }, subSkill: { effect: { @@ -325,8 +744,8 @@ const skills = { //抽象 //混沌初开——牢戏 Object.keys(target.storage) - .filter(i => gainSkills.some(skill => i.startsWith(skill))) - .forEach(storage => delete target.storage[storage]); + .filter(i => gainSkills.some(skill => i.startsWith(skill))) + .forEach(storage => delete target.storage[storage]); target.addSkill(gainSkills); const suffixs = ["used", "round", "block", "blocker"]; for (const skill of gainSkills) { @@ -542,14 +961,18 @@ const skills = { evt = event.getParent(); colors = colors.filter(color => evt.filterCard(get.autoViewAs(lib.skill.dcsbwuwei.viewAs, player.getCards("h", { color: color })), player, evt)); colors = colors.map(color => (color == "none" ? "none2" : color)); - const result = await player.chooseControl(colors, "cancel2").set("prompt", "武威:将一种颜色的所有手牌当作【杀】使用").set("ai", () => { - const player = get.event().player; - let controls = get.event().controls.slice(); - controls.remove("cancel2"); - return controls.sort((a, b) => { - return player.countCards("h", { color: a == "none2" ? "none" : a }) - player.countCards("h", { color: b == "none2" ? "none" : b }); - })[0]; - }).forResult(); + const result = await player + .chooseControl(colors, "cancel2") + .set("prompt", "武威:将一种颜色的所有手牌当作【杀】使用") + .set("ai", () => { + const player = get.event().player; + let controls = get.event().controls.slice(); + controls.remove("cancel2"); + return controls.sort((a, b) => { + return player.countCards("h", { color: a == "none2" ? "none" : a }) - player.countCards("h", { color: b == "none2" ? "none" : b }); + })[0]; + }) + .forResult(); const color = result.control == "none2" ? "none" : result.control; if (color == "cancel2") { evt.goto(0); @@ -607,7 +1030,7 @@ const skills = { .set("filterButton", button => { const selected = ui.selected.buttons.slice().map(i => i.link); if (selected.length >= get.event().selectButton[0]) return false; - return button.link !=1 || !selected.includes(1); + return button.link != 1 || !selected.includes(1); }) .set("ai", button => { const selected = ui.selected.buttons.slice().map(i => i.link); @@ -678,7 +1101,11 @@ const skills = { player.addTempSkill("dcsbwuwei_count"); player.addMark("dcsbwuwei_count", result.links.filter(count => count == 2).length, false); } - if ( Array.from({length:3}).map( (_,i) => i).every(i => result.links.includes(i))) { + if ( + Array.from({ length: 3 }) + .map((_, i) => i) + .every(i => result.links.includes(i)) + ) { trigger.baseDamage++; game.log(trigger.card, "造成的伤害", "#y+1"); } @@ -783,7 +1210,7 @@ const skills = { const card = result.links[0]; cards.remove(card); player.$gain2(card, false); - await game.asyncDelayx(); + await game.delayx(); await player.chooseUseTarget(true, card, false); } } @@ -793,83 +1220,84 @@ const skills = { }, }, //典韦 - dcsbkuangzhan:{ + dcsbkuangzhan: { audio: 2, - enable:"phaseUse", - usable:1, - filter(event,player){ - return player.countCards('h'){ - if(evt.getParent(event.name)==event) num+=evt.cards.length; + let num = 0; + player.getHistory("gain", evt => { + if (evt.getParent(event.name) == event) num += evt.cards.length; }); - while(num>0&&player.countCards('h')){ + while (num > 0 && player.countCards("h")) { num--; - if(!game.hasPlayer(current=>player.canCompare(current))) break; - const result=await player.chooseTarget('狂战:与一名角色拼点',true,function(card,player,target){ - return target!=player&&player.canCompare(target); - }).set('ai',function(target){ - const player=get.player(); - if(target.countCards('h')>=player.countCards('h')) return 0; - return get.effect(target,{name:'sha'},player,player)+1; - }).forResult(); - const target=result.targets[0]; - const compare=await player.chooseToCompare(target).forResult(); - if(!player.storage[event.name]){ - player.storage[event.name]=[]; - player.when({global:"phaseEnd"}).then(()=>{ + if (!game.hasPlayer(current => player.canCompare(current))) break; + const result = await player + .chooseTarget("狂战:与一名角色拼点", true, function (card, player, target) { + return target != player && player.canCompare(target); + }) + .set("ai", function (target) { + const player = get.player(); + if (target.countCards("h") >= player.countCards("h")) return 0; + return get.effect(target, { name: "sha" }, player, player) + 1; + }) + .forResult(); + const target = result.targets[0]; + const compare = await player.chooseToCompare(target).forResult(); + if (!player.storage[event.name]) { + player.storage[event.name] = []; + player.when({ global: "phaseEnd" }).then(() => { delete player.storage.dcsbkuangzhan; }); } - if(compare.bool){ + if (compare.bool) { player.storage[event.name].add(target); - let card={name:'sha',isCard:true}; - let targets=player.storage[event.name].filter(current=>current!=player&&player.canUse(card,current,false)); - await player.useCard(card,targets,false); - } - else{ + let card = { name: "sha", isCard: true }; + let targets = player.storage[event.name].filter(current => current != player && player.canUse(card, current, false)); + await player.useCard(card, targets, false); + } else { player.storage[event.name].add(player); - let card={name:'sha',isCard:true}; - if(target.canUse(card,player,false)) await target.useCard(card,player,false); + let card = { name: "sha", isCard: true }; + if (target.canUse(card, player, false)) await target.useCard(card, player, false); } } }, - ai:{ - order:1, - result:{ - player(player,target){ - let num=player.maxHp-player.countCards('h'); - for(let i of game.players){ - if(get.attitude(player,i)<=0) num-=i.countCards('h'); + ai: { + order: 1, + result: { + player(player, target) { + let num = player.maxHp - player.countCards("h"); + for (let i of game.players) { + if (get.attitude(player, i) <= 0) num -= i.countCards("h"); } - if(num<=0) return 1; - return 0; + if (num <= 0) return 1; + return 0; }, }, }, }, - dcsbkangyong:{ + dcsbkangyong: { audio: 2, - trigger:{ - player:["phaseBegin","phaseEnd"], + trigger: { + player: ["phaseBegin", "phaseEnd"], }, - filter(event,player,name){ - if(name=="phaseBegin") return player.isDamaged(); - return event.kangyongRecover&&player.hp>1; + filter(event, player, name) { + if (name == "phaseBegin") return player.isDamaged(); + return event.kangyongRecover && player.hp > 1; }, - forced:true, - async content(event,trigger,player){ - if(event.triggername=="phaseBegin"){ - const num=player.maxHp-player.hp; - await player.recover(num) - trigger.kangyongRecover=num; - } - else{ - const num=Math.min(player.hp-1,trigger.kangyongRecover); - if(num>0) await player.loseHp(num); + forced: true, + async content(event, trigger, player) { + if (event.triggername == "phaseBegin") { + const num = player.maxHp - player.hp; + await player.recover(num); + trigger.kangyongRecover = num; + } else { + const num = Math.min(player.hp - 1, trigger.kangyongRecover); + if (num > 0) await player.loseHp(num); } }, }, @@ -1227,7 +1655,7 @@ const skills = { num = Math.ceil(target.countCards("h") / 2); player.changeZhuanhuanji("dcsbfumou"); let cards = await player - .choosePlayerCard("覆谋:选择展示" + get.translation(target) + "的" + get.cnNumber(num) + "张牌", target, "h", num, true) + .choosePlayerCard("覆谋:选择展示" + get.translation(target) + "的至多" + get.cnNumber(num) + "张牌", target, "h", [1, num], true) .set("ai", card => { const player = get.event("player"), storage = get.event("storage"), @@ -1273,8 +1701,8 @@ const skills = { mark: true, intro: { content(storage) { - if (storage) return "转换技,出牌阶段限一次,你可以观看一名其他角色的手牌并展示其一半手牌,令其依次使用这些牌中所有其可以使用的牌(无距离限制且不可被响应)。"; - return "转换技,出牌阶段限一次,你可以观看一名其他角色A的手牌并展示其一半手牌并将这些牌交给另一名其他角色B,然后你与A各摸X张牌(X为A以此法失去的手牌数)。"; + if (storage) return "转换技,出牌阶段限一次,你可以观看一名其他角色的手牌并展示其至多一半手牌,令其依次使用这些牌中所有其可以使用的牌(无距离限制且不可被响应)。"; + return "转换技,出牌阶段限一次,你可以观看一名其他角色A的手牌并展示其至多一半手牌并将这些牌交给另一名其他角色B,然后你与A各摸X张牌(X为A以此法失去的手牌数)。"; }, }, ai: { @@ -1366,7 +1794,7 @@ const skills = { const { cards } = event; if (cards && cards.length) await player.discard(cards); else await player.draw(2); - await game.asyncDelayx(); + await game.delayx(); }, }, dcfenhui: { @@ -1408,7 +1836,7 @@ const skills = { effect: { audio: "dcfenhui", trigger: { - global: ["damageBegin1","die"], + global: ["damageBegin1", "die"], }, filter(event, player) { return event.player.hasMark("dcfenhui_mark"); @@ -1629,13 +2057,24 @@ const skills = { return game.hasPlayer(current => { if (current === player) return false; const evt = event.getl(current); - return evt && evt.hs.length + evt.es.length + evt.js.length > 0; + if (!evt) return false; + return evt.hs.some(i => cards.includes(i)) || evt.es.some(i => cards.includes(i)) || evt.js.some(i => cards.includes(i)); }); }, forced: true, locked: false, async content(event, trigger, player) { - player.addGaintag(trigger.getg(player), "dcjuewu_two"); + let gcards = trigger.getg(player), + cards = []; + game.countPlayer(current => { + if (current === player) return false; + const evt = trigger.getl(current); + if (!evt) return false; + cards.addArray(evt.hs.filter(i => gcards.includes(i))); + cards.addArray(evt.es.filter(i => gcards.includes(i))); + cards.addArray(evt.js.filter(i => gcards.includes(i))); + }); + player.addGaintag(cards, "dcjuewu_two"); player.addSkill("dcjuewu_two"); }, }, @@ -1912,7 +2351,7 @@ const skills = { await target.draw(num); await target.recover(); } - if (!event.isMine() && !event.isOnline()) await game.asyncDelayx(); + if (!event.isMine() && !event.isOnline()) await game.delayx(); } }, }; @@ -1930,11 +2369,11 @@ const skills = { result: { player(player) { const enemies = game.filterPlayer(current => { - return (!get.rawAttitude || get.rawAttitude(player, current) < 0) && get.attitude(player, current) >= 0; - }), - knownEnemies = game.filterPlayer(current => { - return get.attitude(player, current) < 0; - }); + return (!get.rawAttitude || get.rawAttitude(player, current) < 0) && get.attitude(player, current) >= 0; + }), + knownEnemies = game.filterPlayer(current => { + return get.attitude(player, current) < 0; + }); if ((!knownEnemies.length && player.countCards("e") > 1) || (player.getHp() > 3 && enemies.length > 0 && knownEnemies.length < 2 && knownEnemies.length < enemies.length && !knownEnemies.some(enemy => get.attitude(player, enemy) <= -9))) return 0; const val1 = game .filterPlayer() @@ -2068,7 +2507,7 @@ const skills = { if (card) await target.chooseUseTarget(card, true).set("nopopup", true); else { game.log("但是牌堆里没有", target, "的装备!"); - await game.asyncDelayx(); + await game.delayx(); } } if (target.countCards("h") < game.countPlayer()) return; @@ -2171,7 +2610,7 @@ const skills = { toGain.push(gainableCards[0]); } if (toGain.length) await player.gain(toGain, "giveAuto"); - await game.asyncDelayx(); + await game.delayx(); }, ai: { threaten: 5.8, @@ -2282,7 +2721,7 @@ const skills = { }, ai: { effect: { - player_use(card, player, target, current) { + player(card, player, target, current) { if (get.type(card) == "trick" && player.getStorage("dcjujian_forbid").includes(target)) return "zeroplayertarget"; }, }, @@ -2362,7 +2801,6 @@ const skills = { return event.name != "phase" || game.phaseNumber == 0; }, prompt2(event, player) { - //无名杀先阳后阴,不要问为什么 return "切换【权谋】为状态" + (player.storage.dcsbquanmou ? "阳" : "阴"); }, check: () => Math.random() > 0.5, @@ -2415,7 +2853,7 @@ const skills = { mark: true, marktext: "讨", intro: { - name: "权谋 - 阳", + name: "权谋 - 阴", content: () => { return `当你下次受到${get.translation(_status.currentPhase)}造成的伤害后,其可以对除你之外的至多三名其他角色各造成1点伤害。`; }, @@ -2460,7 +2898,7 @@ const skills = { mark: true, marktext: "抚", intro: { - name: "权谋 - 阴", + name: "权谋 - 阳", content: () => { return `当你下次受到${get.translation(_status.currentPhase)}造成的伤害时,防止此伤害。`; }, @@ -2520,16 +2958,12 @@ const skills = { return get.order(card); return -1; } - //如果自己没有其他的闪桃就不响应 - else { - const needsTao = player.hp <= 1; - const shanAndTao = player.getCards("hs", card => { - const name = get.name(card); - return name == "shan" || (needsTao && name == "shan"); - }); - shanAndTao.remove(card); - if (card.cards) shanAndTao.removeArray(card.cards); - if (!shanAndTao.length) return 0; + else { //不残或者没有其他的闪就不响应 + if (player.hp > 1 || !player.hasCard("hs", i => { + if (i == card || card.cards && card.cards.includes(i)) return false; + let name = get.name(i, player); + return name == "shan" || name == "tao" || name == "jiu"; + })) return 0; } return event.getRand("dcsbpingliao") > 1 / Math.max(1, player.hp) ? 0 : get.order(card); }) @@ -2538,7 +2972,7 @@ const skills = { if (result.bool) { respondedTargets.push(target); if (!trigger.targets.includes(target)) nonnonTargetResponded = true; - await game.asyncDelay(); + await game.delay(); } else if (trigger.targets.includes(target)) unrespondedTargets.push(target); } } @@ -2852,7 +3286,7 @@ const skills = { player.logSkill("dcanjing", targets); for (const target of targets) await target.draw(); const minHp = targets.map(i => i.getHp()).sort((a, b) => a - b)[0]; - await game.asyncDelayx(); + await game.delayx(); for (const target of targets) { if (!target.isIn()) continue; if (target.getHp() === minHp) await target.recover(); @@ -2990,7 +3424,7 @@ const skills = { const card = links[0]; cards.remove(card); player.$gain2(card, false); - await game.asyncDelayx(); + await game.delayx(); await player.chooseUseTarget(true, card, false); cards = cards.filterInD(); if (cards.length) { @@ -3605,7 +4039,6 @@ const skills = { return event.name != "phase" || game.phaseNumber == 0; }, prompt2(event, player) { - //无名杀先阳后阴,不要问为什么 return "切换【英谋】为状态" + (player.storage.dcsbyingmou ? "阳" : "阴"); }, check: () => Math.random() > 0.5, @@ -3855,7 +4288,6 @@ const skills = { return event.name != "phase" || game.phaseNumber == 0; }, prompt2(event, player) { - //无名杀先阳后阴,不要问为什么 return "切换【盟谋】为状态" + (player.storage.dcsbmengmou ? "阳" : "阴"); }, check: () => Math.random() > 0.5, @@ -4434,7 +4866,7 @@ const skills = { source.line(target, "fire"); const type = get.type2(event.cards[0]); await source.discard(event.cards).set("discarder", source); - //await game.asyncDelayx(); + //await game.delayx(); const cardsToDiscard = target.getExpansions("dcxiaoyin").filter(card => get.type2(card, false) === type); if (cardsToDiscard.length === 1) await target.loseToDiscardpile(cardsToDiscard); else if (cardsToDiscard.length > 1) { @@ -4589,7 +5021,7 @@ const skills = { return [1, -2]; } else { if (get.attitude(player, target) > 0 && target.hp > 1) { - return 0; + return "zeroplayertarget"; } if (get.attitude(player, target) < 0 && !player.hasSkillTag("damageBonus")) { if (card.name == "sha") return; @@ -4614,7 +5046,7 @@ const skills = { if (enemies.length == 1 && enemies[0] == target && player.needsToDiscard()) { return; } - return 0; + return "zeroplayertarget"; } } } @@ -4757,7 +5189,7 @@ const skills = { game.addGlobalSkill("dcshangyu_ai"); }, onremove: () => { - if (!game.hasPlayer(i => i.hasSkill("dcshangyu"), true)) game.removeGlobalSkill("dcshangyu_ai"); + if (!game.hasPlayer(i => i.hasSkill("dcshangyu", null, null, false), true)) game.removeGlobalSkill("dcshangyu_ai"); }, trigger: { global: "phaseBefore", @@ -4844,7 +5276,7 @@ const skills = { player: "dieAfter", }, filter: () => { - return !game.hasPlayer(i => i.hasSkill("dcshangyu"), true); + return !game.hasPlayer(i => i.hasSkill("dcshangyu", null, null, false), true); }, silent: true, forceDie: true, @@ -5647,12 +6079,16 @@ const skills = { if (event.name == "die") return true; return event.name != "phase" || game.phaseNumber == 0; }, - content: function () { + content: function* (event, map) { + const player = map.player; + player.removeSkill("dctongye_buff"); player.addSkill("dctongye_buff"); var num = game.countGroup(); if (num <= 4) { player.addMark("dctongye_handcard", 3, false); game.log(player, "手牌上限", "#y+3"); + player.addMark("dctongye_draw", 4 - num, false); + game.log(player, "摸牌阶段额定摸牌数", "#y+" + parseFloat(4 - num)); } if (num <= 3) { player.addMark("dctongye_range", 3, false); @@ -5663,8 +6099,7 @@ const skills = { game.log(player, "使用杀的次数上限", "#y+3"); } if (num <= 1) { - player.addMark("dctongye_draw", 3, false); - game.log(player, "摸牌阶段额定摸牌数", "#y+3"); + yield player.recover(3); } }, subSkill: { @@ -6152,7 +6587,7 @@ const skills = { }, target, target - )) + )) ); }) .set("card", card); @@ -6326,7 +6761,7 @@ const skills = { filter: function (event, player) { if (player != _status.currentPhase) return false; if (!event.isFirstTarget) return false; - if (event.card.name != "sha" && get.type(event.card, false) != "trick") return false; + if (event.card.name != "sha" && get.type(event.card, null, false) != "trick") return false; if (player.countCards("h") != player.getHistory("useCard").indexOf(event.getParent()) + 1) return false; return event.targets.some(target => { return target != player && target.isIn(); @@ -6369,7 +6804,7 @@ const skills = { var del = player.countCards("h") - cardsh.length - player.getHistory("useCard").length - 1; if (del < 0) return; if (del > 0) { - if (card.name == "sha" || get.type(card, false) != "trick") return num / 3; + if (card.name == "sha" || get.type(card, null, player) != "trick") return num / 3; return num + 1; } return num + 15; @@ -6394,7 +6829,7 @@ const skills = { }) ) return false; - if (!["basic", "trick"].includes(get.type(event.card, false))) return false; + if (!["basic", "trick"].includes(get.type(event.card, null, false))) return false; if (event.getParent(2).name == "dcchanjuan") return false; return !player.storage.dcchanjuan[event.card.name] || player.storage.dcchanjuan[event.card.name] < 2; }, @@ -6920,7 +7355,7 @@ const skills = { if (name != "phase") return false; }, effect: { - target_use(card, player, target) { + target(card, player, target) { if (player === target || typeof card !== "object" || get.color(card) !== "black") return; if (target.hasSkill("jiu")) { if ( @@ -6965,7 +7400,7 @@ const skills = { game.cardsGotoOrdering(cards); var next = player.chooseToMove(); next.set("list", [["牌堆顶", cards], ["牌堆底"]]); - next.set("prompt", "尽瘁:点击将牌移动到牌堆顶或牌堆底"); + next.set("prompt", "尽瘁:点击或拖动将牌移动到牌堆顶或牌堆底"); next.processAI = function (list) { var cards = list[0][1], player = _status.event.player; @@ -7059,7 +7494,7 @@ const skills = { audio: 2, trigger: { player: "useCard" }, filter: function (event, player) { - if (!player.isPhaseUsing() || player.hasSkill("dcqingshi_blocker")) return false; + if (!player.isPhaseUsing()) return false; if (player.getStorage("dcqingshi_clear").includes(event.card.name)) return false; if ( player.hasCard(card => { @@ -7173,7 +7608,7 @@ const skills = { content3: function () { "step 0"; player.draw(3); - player.addTempSkill("dcqingshi_blocker"); + player.tempBanSkill("dcqingshi"); }, subSkill: { ex: { @@ -7201,7 +7636,6 @@ const skills = { onremove: true, charlotte: true, }, - blocker: { charlotte: true }, }, ai: { threaten: 6, @@ -7557,35 +7991,24 @@ const skills = { }, filterTarget: true, getCards: function (player, bool) { - var cards = Array.from(ui.discardPile.childNodes); - var gains = cards.slice(0); - var history = game.getAllGlobalHistory("cardMove", function (evt) { - if (evt.name == "lose") return evt.position == ui.discardPile; - return evt.name == "cardsDiscard"; - }); - for (var i = history.length - 1; i >= 0; i--) { - var evt = history[i]; - var cards2 = evt.cards.filter(function (card) { - return cards.includes(card); - }); - if (cards2.length) { - if (!lib.skill.dcjijiao.isUse(evt, player)) { - gains.removeArray(cards2); + const cards = Array.from(ui.discardPile.childNodes); + const gains = game + .getAllGlobalHistory("everything", evt => { + if (evt.name == "lose" || evt.name == "loseAsync") { + if (evt.type != "discard" || evt.getlx === false) return false; + return evt.getl(player)?.cards2?.length > 0; } - cards.removeArray(cards2); - } - if (!cards.length) break; - } + if (evt.name == "useCard") return evt.cards?.length > 0; + return false; + }) + .reduce((list, evt) => { + if (evt.name == "useCard") return list.addArray(evt.cards); + return list.addArray(evt.getl(player)?.cards2); + }, []) + .filter(i => cards.includes(i)); if (bool) return gains.some(card => get.type(card) == "trick"); return gains.filter(card => get.type(card) == "trick"); }, - isUse: function (event, player) { - if (event.name != "cardsDiscard") return event.type == "discard" && event.player == player; - var evtx = event.getParent(); - if (evtx.name != "orderingDiscard") return false; - var evt2 = evtx.relatedEvent || evtx.getParent(); - return evt2.name == "useCard" && evt2.player == player; - }, content: function () { player.awakenSkill("dcjijiao"); var cards = lib.skill.dcjijiao.getCards(player); @@ -8166,28 +8589,31 @@ const skills = { onremove: true, charlotte: true, direct: true, - content: function () { - "step 0"; - event.cards = player.getStorage("dcshexue_study"); - "step 1"; - var card = cards.pop(); - if (trigger.player.hasUseTarget(card, false)) { - game.broadcastAll(function (card) { - lib.skill.dcshexue_backup.viewAs = card; - lib.skill.dcshexue_backup.prompt = "设学:是否将一张牌当做" + get.translation(card) + "使用?"; - }, card); - var next = trigger.player.chooseToUse(); - next.set("openskilldialog", `###${get.prompt("dcshexue_study")}###将一张牌当做${get.translation(card.nature) || ""}【${get.translation(card.name)}】使用`); - next.set("norestore", true); - next.set("addCount", false); - next.set("_backupevent", "dcshexue_backup"); - next.set("custom", { + async content(event, trigger, player) { + let cards = player.getStorage("dcshexue_study"); + const result = await player.chooseButton(["设学:是否将一张牌当作其中一张牌使用?", [cards, "vcard"]]) + .set("ai", button => { + return get.event().player.getUseValue(button.link, false); + }) + .forResult(); + if (!result.bool) return; + const card = result.links[0]; + if (!trigger.player.hasUseTarget(card, false)) return; + game.broadcastAll(function (card) { + lib.skill.dcshexue_backup.viewAs = card; + lib.skill.dcshexue_backup.prompt = "设学:是否将一张牌当做" + get.translation(card) + "使用?"; + }, card); + await trigger.player.chooseToUse() + .set("openskilldialog", `###${get.prompt("dcshexue_study")}### + 将一张牌当做${get.translation(card.nature) || ""}【${get.translation(card.name)}】使用`) + .set("norestore", true) + .set("addCount", false) + .set("_backupevent", "dcshexue_backup") + .set("custom", { add: {}, replace: { window: function () {} }, - }); - next.backup("dcshexue_backup"); - } - if (cards.length) event.redo(); + }) + .backup("dcshexue_backup"); }, }, studyclear: { @@ -8241,7 +8667,7 @@ const skills = { effect: { player_use(card, player, target) { var evt = player.getLastUsed(); - if (evt && evt.targets.includes(target)) return [1.5, 0]; + if (evt && evt.targets.includes(target)) return [1, 1]; }, }, }, @@ -8479,7 +8905,7 @@ const skills = { game.addGlobalSkill("dcyuandi_ai"); }, onremove: () => { - if (!game.hasPlayer(i => i.hasSkill("dcyuandi"), true)) game.removeGlobalSkill("dcyuandi_ai"); + if (!game.hasPlayer(i => i.hasSkill("dcyuandi", null, null, false), true)) game.removeGlobalSkill("dcyuandi_ai"); }, trigger: { global: "useCard" }, filter: function (event, player) { @@ -8550,7 +8976,7 @@ const skills = { }, trigger: { player: "dieAfter" }, filter: () => { - return !game.hasPlayer(i => i.hasSkill("dcyuandi"), true); + return !game.hasPlayer(i => i.hasSkill("dcyuandi", null, null, false), true); }, silent: true, forceDie: true, @@ -8827,7 +9253,7 @@ const skills = { target: function (card, player, target, current) { if (get.type(card) == "delay" && current < 0) { var current = _status.currentPhase; - if (current.getSeatNum() > target.getSeatNum()) return "zerotarget"; + if (current.getSeatNum() > target.getSeatNum()) return 0.1; } }, }, @@ -8839,7 +9265,7 @@ const skills = { game.addGlobalSkill("dcaichen_hit"); }, onremove: function (player) { - if (!game.hasPlayer(current => current.hasSkill("dcaichen"), true)) game.removeGlobalSkill("dcaichen_hit"); + if (!game.hasPlayer(current => current.hasSkill("dcaichen", null, null, false), true)) game.removeGlobalSkill("dcaichen_hit"); }, trigger: { player: ["loseAfter", "phaseDiscardBefore"], @@ -8868,7 +9294,7 @@ const skills = { hit: { trigger: { player: "dieAfter" }, filter: function (event, player) { - return !game.hasPlayer(current => current.hasSkill("dcaichen"), true); + return !game.hasPlayer(current => current.hasSkill("dcaichen", null, null, false), true); }, silent: true, forceDie: true, @@ -9168,7 +9594,7 @@ const skills = { const cards = []; game.countPlayer2(current => { current.getHistory("lose", evt => { - if (evt.type == "discard") cards.addArray(evt.cards2.filterInD("d")); + if (evt.type == "discard") cards.addArray(evt.cards.filterInD("d")); }); }); return cards; @@ -9184,7 +9610,7 @@ const skills = { const card = new lib.element.VCard({ name }); if (player.canUse(card, target)) { await player.useCard(card, target); - await game.asyncDelayx(); + await game.delayx(); break; } } @@ -9453,7 +9879,7 @@ const skills = { "bool", (function () { if (!player.hasSkill("dcanzhi")) return Math.random() < 0.5; - if (player.hasSkill("dcanzhi_blocker")) { + if (player.isTempBanned("dcanzhi")) { var next = _status.currentPhase.getNext(); var judges = next.getCards("j"); var val = 0; @@ -9506,9 +9932,6 @@ const skills = { }, dcanzhi: { enable: "phaseUse", - filter: function (event, player) { - return !player.hasSkill("dcanzhi_blocker"); - }, group: "dcanzhi_damage", content: function () { "step 0"; @@ -9521,7 +9944,7 @@ const skills = { player.removeSkill("dcxialei_clear"); event.finish(); } else if (result.color == "black") { - player.addTempSkill("dcanzhi_blocker"); + player.tempBanSkill("dcanzhi"); player .chooseTarget("暗织:是否令一名非当前回合角色获得本回合进入弃牌堆的两张牌?", (card, player, target) => { return target != _status.currentPhase; @@ -9571,9 +9994,6 @@ const skills = { damage: { audio: "dcanzhi", trigger: { player: "damageEnd" }, - filter: function (event, player) { - return !player.hasSkill("dcanzhi_blocker"); - }, check: function (event, player) { return game.hasPlayer(current => { return get.attitude(player, current) > 0 && current != _status.currentPhase; @@ -9581,11 +10001,50 @@ const skills = { }, prompt2: "你判定,若结果为红色,你重置〖霞泪〗的观看牌数;若结果为黑色,〖暗织〗于本回合失效,然后你可以令一名非当前回合角色获得本回合进入弃牌堆的两张牌。", content: function () { - event.setContent(lib.skill.dcanzhi.content); - event.goto(0); + "step 0"; + player.judge(result => { + if (get.color(result) == "red") return _status.event.getParent().player.countMark("dcxialei_clear") / 2; + return 2; + }).judge2 = result => result.bool; + "step 1"; + if (result.color == "red") { + player.removeSkill("dcxialei_clear"); + event.finish(); + } else if (result.color == "black") { + player.tempBanSkill("dcanzhi"); + player + .chooseTarget("暗织:是否令一名非当前回合角色获得本回合进入弃牌堆的两张牌?", (card, player, target) => { + return target != _status.currentPhase; + }) + .set("ai", target => { + return get.effect(target, { name: "wuzhong" }, _status.event.player); + }); + } else event.finish(); + "step 2"; + if (result.bool) { + var target = result.targets[0]; + event.target = target; + player.line(target); + var cards = []; + game.getGlobalHistory("cardMove", evt => { + if ((evt.name == "lose" && evt.position == ui.discardPile) || evt.name == "cardsDiscard") { + cards.addArray(evt.cards.filterInD("d")); + } + }); + if (cards.length) { + player.chooseButton(["暗织:选择令" + get.translation(target) + "获得的牌", cards], true, Math.min(cards.length, 2)).set("ai", button => { + var player = _status.event.player, + target = _status.event.getParent().target; + return get.sgnAttitude(player, target) * get.value(button.link, target); + }); + } + } else event.finish(); + "step 3"; + if (result.bool) { + target.gain(result.links, "gain2"); + } }, }, - blocker: { charlotte: true }, }, }, //十周年王允 @@ -9745,6 +10204,7 @@ const skills = { current.getStat().isSkipped = true; }); var evt = player.insertPhase(); + evt.relatedEvent = trigger.relatedEvent || trigger.getParent(2); if (trigger.skill) evt.skill = trigger.skill; else delete evt.skill; game.broadcastAll(function (player) { @@ -9803,6 +10263,23 @@ const skills = { }, }, all: { + mod: { + aiOrder(player, card, num) { + if (num <= 0) return; + if (get.tag(card, "recover") && !_status.event.dying && player.hp > 0) return 0; + if (get.tag(card, "damage")) { + if (card.name == "sha" && game.hasPlayer(cur => { + return ( + cur.hp < 2 && + player.canUse(card, cur, null, true) && + get.effect(cur, card, player, player) > 0 + ); + })) return num; + if (player.needsToDiscard()) return num / 5; + return 0; + } + } + }, trigger: { player: "dieAfter" }, filter: function (event, player) { return !game.hasPlayer(current => current.hasSkill("dcwumei_wake"), true); @@ -9812,14 +10289,6 @@ const skills = { content: function () { game.removeGlobalSkill("dcwumei_all"); }, - ai: { - effect: { - player_use(card, player, target) { - if (get.tag(card, "recover") && target.hp > 0) return 0; - if (get.tag(card, "damage")) return 0.5; - }, - }, - }, }, }, }, @@ -10090,7 +10559,7 @@ const skills = { }, ai: { effect: { - target_use(card, player, target) { + target(card, player, target) { if (player === target) return; if ( game.hasPlayer2(current => { @@ -10639,7 +11108,10 @@ const skills = { if (typeof card != "object") return; var storage = player.getStorage("olddcxiangmian_countdown"); for (var i = 0; i < storage.length / 3; i++) { - if (get.suit(card, player) == storage[i * 3 + 1] && storage[i * 3 + 2] == 1 && !player.canSave(player) && !get.tag(card, "save")) return "zeroplayertarget"; + if (get.suit(card, player) == storage[i * 3 + 1] && storage[i * 3 + 2] == 1) { + if (!player.canSave(player) && !get.tag(card, "save")) return [0, -100, 0, 0]; + return [1, -2 * player.hp, 1, 0]; + } } }, }, @@ -10741,7 +11213,10 @@ const skills = { if (typeof card != "object") return; var storage = player.getStorage("dcxiangmian_countdown"); for (var i = 0; i < storage.length / 3; i++) { - if ((storage[i * 3 + 2] == 1 || get.suit(card, player) == storage[i * 3 + 1]) && !player.canSave(player) && !get.tag(card, "save")) return "zeroplayertarget"; + if (storage[i * 3 + 2] == 1 || get.suit(card, player) == storage[i * 3 + 1]) { + if (!player.canSave(player) && !get.tag(card, "save")) return [0, -100, 0, 0]; + return [1, -2 * player.hp, 1, 0]; + } } }, }, @@ -10881,20 +11356,9 @@ const skills = { marktext: "刚", intro: { name: "刚硬", - content: "属性目标:回复体力,或于得到牌后手牌数大于体力值", + content: "属性目标:回复体力,或手牌数大于体力值", }, charlotte: true, - silent: true, - forced: true, - nopop: true, - lastDo: true, - trigger: { player: "gainEnd" }, - filter: function (event, player) { - return player.countCards("h") > player.hp; - }, - content: function () { - trigger._dctongguan_gangying = true; - }, }, duomou: { marktext: "谋", @@ -10939,9 +11403,7 @@ const skills = { var target = event.player; if ( (target.hasSkill("dctongguan_gangying") && - (target.hasHistory("gain", function (evt) { - return evt._dctongguan_gangying == true; - }) || + (target.countCards("h") > target.hp || game.getGlobalHistory("changeHp", function (evt) { return evt.player == target && (evt.getParent().name == "recover" || target.countCards("h") > target.hp); }).length > 0)) || @@ -10989,9 +11451,7 @@ const skills = { rules: [ target => target.getHistory("sourceDamage").length, target => - target.hasHistory("gain", function (evt) { - return evt._dctongguan_gangying; - }) || + target.countCards("h") > target.hp || game.getGlobalHistory("changeHp", function (evt) { return evt.player == target && evt.getParent().name == "recover"; }).length > 0 || @@ -11096,7 +11556,7 @@ const skills = { } game.delayx(); event.goto(1); - ("step 10"); + "step 10"; if (!game.hasPlayer(current => current != player)) event._result = { bool: false }; else player @@ -11111,7 +11571,7 @@ const skills = { } return att / 3; }); - ("step 11"); + "step 11"; if (result.bool) { var target = result.targets[0]; player.logSkill("dcmengjie", target); @@ -12651,9 +13111,8 @@ const skills = { var list = player.storage.dcgeyuan.filter(i => lib.skill.dcgeyuan.filterNumber(player, i)); if (!list.length) return 0; list = list.map(num => { - var list = [1, 10, 11, 12, 13]; - if (list.includes(num)) return ["A", "X", "J", "Q", "K"][list.indexOf(num)]; - return parseFloat(num); + if (num == 10) return "X"; + return get.strNumber(num); }); return list.reduce((str, num) => { return str + num; @@ -14055,7 +14514,7 @@ const skills = { } else event.finish(); } else if (target.isLinked()) target.link(); "step 3"; - if (target.isIn()){ + if (target.isIn()) { target.addSkill("baoshu_draw"); target.addMark("baoshu", event.num2); } @@ -14068,10 +14527,10 @@ const skills = { intro: { name2: "梳", content: "mark", - onunmark(storage, player){ + onunmark(storage, player) { delete player.storage.baoshu; player.removeSkill("baoshu_draw"); - } + }, }, //group: "baoshu_draw", subSkill: { @@ -14111,7 +14570,7 @@ const skills = { game.cardsGotoOrdering(cards); var next = player.chooseToMove(); next.set("list", [["牌堆顶", cards], ["牌堆底"]]); - next.set("prompt", "天运:点击将牌移动到牌堆顶或牌堆底"); + next.set("prompt", "天运:点击或拖动将牌移动到牌堆顶或牌堆底"); next.processAI = function (list) { var cards = list[0][1]; return [[], cards]; @@ -14193,6 +14652,7 @@ const skills = { trigger: { global: "roundStart" }, forced: true, locked: false, + derivation: "iwasawa_refenyin", content: function () { "step 0"; var next = player @@ -14322,7 +14782,7 @@ const skills = { return evtx && evtx.name == "xinyingbing" && evtx._trigger.target == target; }) ) - return [1, 1]; + return [1, 2]; }, }, combo: "xinzhoufu", @@ -16001,6 +16461,8 @@ const skills = { if (!player.storage.rezhongjian2) return true; return !player.storage.rezhongjian2[0].includes(target) && !player.storage.rezhongjian2[1].includes(target); }, + line: false, + log: "notarget", content: function () { "step 0"; player @@ -16081,8 +16543,7 @@ const skills = { dialog.add([storage[1], "player"]); } } else { - var list = storage[0].concat(storage[1]).sortBySeat(player); - dialog.add([list, "player"]); + dialog.addText(get.translation(player) + "共选择了" + get.cnNumber(storage[0].length + storage[1].length) + "人"); } }, }, @@ -16457,16 +16918,13 @@ const skills = { if (!trigger.getParent().lvli6) { trigger.getParent().goto(0); } - game.broadcastAll( - function (str) { - var dialog = ui.create.dialog(str); - dialog.classList.add("center"); - setTimeout(function () { - dialog.close(); - }, 1000); - }, - get.translation(player) + "声明的" + get.translation(trigger.card.name) + "并没有生效" - ); + game.broadcastAll(function (str) { + var dialog = ui.create.dialog(str); + dialog.classList.add("center"); + setTimeout(function () { + dialog.close(); + }, 1000); + }, get.translation(player) + "声明的" + get.translation(trigger.card.name) + "并没有生效"); game.log("然而什么都没有发生"); game.delay(2); } @@ -16706,7 +17164,7 @@ const skills = { ai: { effect: { target: function (card) { - if (card.name == "nanman") return "zerotarget"; + if (card.name == "nanman") return "zeroplayertarget"; }, }, }, @@ -16901,193 +17359,171 @@ const skills = { return get.distance(player, current) <= 1 && current.countDiscardableCards(player, "hej") > 0; }); }, - async cost(event, trigger, player){ + async cost(event, trigger, player) { if (!["identity", "guozhan"].includes(get.mode())) { - event.result = await player.chooseTarget(function (card, player, target) { - return target.isFriendOf(player) && target.countDiscardableCards(player, "hej") > 0; - }, get.prompt2("wlcuorui")).set("ai", function (target) { - if (target.countCards("e", function (card) { - return card.name != "tengjia" && get.value(card, target) <= 0; - })) return 10; - if (target.countCards("j", function (card) { - return get.effect(target, { name: card.viewAs || card.name }, target, target) < 0; - })) return 10; - return Math.random() + 0.2 - 1 / target.countCards("hej"); - }).forResult(); + event.result = await player + .chooseTarget(function (card, player, target) { + return target.isFriendOf(player) && target.countDiscardableCards(player, "hej") > 0; + }, get.prompt2("wlcuorui")) + .set("ai", function (target) { + if ( + target.countCards("e", function (card) { + return card.name != "tengjia" && get.value(card, target) <= 0; + }) + ) + return 10; + if ( + target.countCards("j", function (card) { + return get.effect(target, { name: card.viewAs || card.name }, target, target) < 0; + }) + ) + return 10; + return Math.random() + 0.2 - 1 / target.countCards("hej"); + }) + .forResult(); } else { - event.result = await player.chooseTarget(function (card, player, target) { - return get.distance(player, target) <= 1 && target.countDiscardableCards(player, "hej") > 0; - }, get.prompt2("wlcuorui")).set("ai", function (target) { - if (game.hasPlayer(current => { - return current != target && get.attitude(_status.event.player, current) < 0; - })) return get.effect(target, { name: "guohe" }, player, player) + 10; - return 0; - }).forResult(); + event.result = await player + .chooseTarget(function (card, player, target) { + return get.distance(player, target) <= 1 && target.countDiscardableCards(player, "hej") > 0; + }, get.prompt2("wlcuorui")) + .set("ai", function (target) { + if ( + game.hasPlayer(current => { + return current != target && get.attitude(_status.event.player, current) < 0; + }) + ) + return get.effect(target, { name: "guohe" }, player, player) + 10; + return 0; + }) + .forResult(); } }, - content: function () { - "step 0"; - var target = targets[0]; - event.target = target; - player.discardPlayerCard(target, "hej", true); - if (["identity", "guozhan"].includes(get.mode())) event.goto(6); - "step 1"; - if (!result.cards || !result.cards.length) { - event.finish(); - return; - } - var color = get.color(result.cards[0], result.cards[0].original == "j" ? false : target); - event.color = color; - var list = []; + async content(event, trigger, player) { + const target = event.targets[0]; + const result = await player.discardPlayerCard(target, "hej", true).forResult(); + const card = result.cards[0]; + const str = ["identity", "guozhan"].includes(get.mode()) ? "另一名其他角色" : "对手"; + const filter = ["identity", "guozhan"].includes(get.mode()) ? (current) => { + if (current == player || current == target) return false; + return true; + } : (current) => { + return current.isEnemyOf(player); + }; + const list = []; if (game.hasPlayer(function (current) { - return (get.mode() == "versus" ? current.isEnemyOf(player) : current != player && current != target) && current.countCards("h"); + return filter(current) && current.countCards("h"); })) list.push("展示手牌"); if (game.hasPlayer(function (current) { - return (get.mode() == "versus" ? current.isEnemyOf(player) : current != player && current != target) && current.countCards("e", { color: color }); + return filter(current) && current.countCards("e", { color: get.color(card) }); })) list.push("弃置装备"); - if (!list.length) { - event.finish(); - return; - } - if (list.length == 1) event._result = { control: list[0] }; - else player.chooseControl(list).set("prompt", "挫锐:展示对手的至多两张手牌,或弃置对手装备区内至多两张" + get.translation(color) + "牌").set("ai", function () { - var player = _status.event.player; - var color = _status.event.getParent().color; - if (game.countPlayer(function (current) { - if (!current.isEnemyOf(player)) return false; - return current.countCards("e", function (card) { - return get.color(card) == color && get.value(card) > 0; - }); - }) > 1) return 1; - return 0; - }); - "step 2"; - if (result.control == "弃置装备") event.goto(5); + if (!list.length) return; + let result2; + if (list.length == 1) result2 = { control: list[0] }; else { - var dialog = ["请选择要展示的牌"]; - var list = game.filterPlayer(function (current) { - return current.isEnemyOf(player) && current.countCards("h"); - }).sortBySeat(); - for (var i of list) { + result2 = await player + .chooseControl(list) + .set("prompt", "挫锐:展示" + str + "的至多两张手牌,或弃置" + str + "装备区内至多两张" + get.translation(get.color(card)) + "牌") + .set("resultx", function () { + let color = get.color(card); + if ( + game.countPlayer(function (current) { + if (!filter(current)) return false; + return current.countCards("e", function (card) { + return get.color(card) == color && get.value(card) > 0; + }); + }) > 1 + ) + return 1; + return 0; + }()) + .set("ai", () => _status.event.resultx) + .forResult(); + } + if (result2.control == "展示手牌") { + let dialog = ["请选择要展示的牌"]; + let targets = game + .filterPlayer(function (current) { + return filter(current) && current.countCards("h"); + }) + .sortBySeat(); + for (let i of targets) { dialog.push('
    ' + get.translation(i) + "
    "); if (player.hasSkillTag("viewHandcard", null, i, true)) dialog.push(i.getCards("h")); else dialog.push([i.getCards("h"), "blank"]); } - player.chooseButton([1, 2], true).set("createDialog", dialog).set("ai", function (button) { - var color = get.color(button.link) == _status.event.getParent().color; - return color ? Math.random() : 0.35; - }); - } - "step 3"; - player.showCards(result.links); - var map = {}; - var map2 = {}; - for (var i of result.links) { - var id = get.owner(i).playerid; - if (!map[id]) map[id] = []; - map[id].push(i); - if (get.color(i) != event.color) continue; - if (!map2[id]) map2[id] = []; - map2[id].push(i); - } - for (var i in map) { - var source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; - if (map2[i]) player.gain(map2[i], source, "bySelf", "give"); - player.line(source); - game.log(player, "展示了", source, "的", map[i]); - } - event.next.sort(function (a, b) { - return lib.sort.seat(a.source || a.player, b.source || b.player); - }); - event.finish(); - "step 4"; - var dialog = ["请选择要弃置的牌"]; - var list = game.filterPlayer(function (current) { - return ( - current.isEnemyOf(player) && - current.countCards("e", function (card) { - return get.color(card) == event.color; + const result2 = await player + .chooseButton([1, 2], true) + .set("createDialog", dialog) + .set("color", get.color(card)) + .set("filterButton", button => { + if (!["identity", "guozhan"].includes(get.mode())) return true; + if (!ui.selected.buttons.length) return true; + return get.owner(button.link) == get.owner(ui.selected.buttons[0].link); }) - ); - }).sortBySeat(); - for (var i of list) { - dialog.push('
    ' + get.translation(i) + "
    "); - dialog.push(i.getCards("e", function (card) { - return get.color(card) == event.color; - })); - } - player.chooseButton([1, 2], true).set("createDialog", dialog).set("ai", function (button) { - var owner = get.owner(button.link); - return get.value(button.link, owner); - }); - "step 5"; - var map = {}; - for (var i of result.links) { - if (get.color(i) != event.color) continue; - var id = get.owner(i).playerid; - if (!map[id]) map[id] = []; - map[id].push(i); - } - for (var i in map) { - (_status.connectMode ? lib.playerOL : game.playerMap)[i].discard(map[i], "notBySelf").discarder = player; - } - event.next.sort(function (a, b) { - return lib.sort.seat(a.player, b.player); - }); - event.finish(); - "step 6"; - if (!result.cards || !result.cards.length) { - event.finish(); - return; + .set("ai", button => { + let color = get.color(button.link) == _status.event.color; + return color ? Math.random() : 0.35; + }) + .forResult(); + await player.showCards(result2.links); + let map = {}; + let map2 = {}; + for (let i of result2.links) { + let id = get.owner(i).playerid; + if (!map[id]) map[id] = []; + map[id].push(i); + if (get.color(i) != get.color(card)) continue; + if (!map2[id]) map2[id] = []; + map2[id].push(i); + } + for (let i in map) { + let source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; + if (map2[i]) await player.gain(map2[i], source, "bySelf", "give"); + player.line(source); + game.log(player, "展示了", source, "的", map[i]); + } } - var color = get.color(result.cards[0], result.cards[0].original == "j" ? false : target); - if (game.hasPlayer(current => { - return current != player && current != target && current.hasCard(card => { - const position = get.position(card); - if (position === "h") return true; - return position === "e" && get.color(card, current) === color; - }, "he"); - })) { - event.color = color; - var next = player.chooseTarget(true, "挫锐:选择另一名其他角色", "弃置该角色装备区里至多两张" + get.translation(event.color) + "牌;或展示该角色的至多两张手牌,然后获得其中的" + get.translation(event.color) + "牌"); - next.set("filterTarget", (card, player, target) => { - const evt = get.event().getParent(), color = evt.color; - return target != player && target != evt.target && target.hasCard(card => { - const position = get.position(card); - if (position === "h") return true; - return position === "e" && get.color(card, target) === color; - }, "he"); - }); - next.set("ai", target => { - return -get.attitude(_status.event.player, target) * target.countCards("he") + 0.1; - }); - } else event.finish(); - "step 7"; - if (result.bool) { - var targetx = result.targets[0]; - event.targetx = targetx; - player.line(targetx); - player.choosePlayerCard(targetx, "he", true, [1, 2]).set("prompt", "展示至多两张手牌,或弃置至多两张" + get.translation(event.color) + "装备").set("filterButton", button => { - if (ui.selected.buttons.length) { - var linkx = ui.selected.buttons[0].link; - if (get.position(button.link) != get.position(linkx)) return false; - } - if (get.position(button.link) == "e") return get.color(button.link, _status.event.target) == _status.event.getParent().color; - return true; - }).set("target", targetx); - } else event.finish(); - "step 8"; - if (result.bool) { - var cards = result.links; - if (get.position(cards[0]) == "e") { - event.targetx.discard(cards, "notBySelf").discarder = player; - event.finish(); - } else { - player.showCards(cards, get.translation(event.targetx) + "因【挫锐】展示的牌"); - var cards2 = cards.filter(card => { - return get.color(card) == event.color; - }); - if (cards2.length) player.gain(cards2, event.targetx, "give"); + else { + let dialog = ["请选择要弃置的牌"]; + let targets = game + .filterPlayer(function (current) { + return filter(current) && current.countCards("e", function (cardx) { + return get.color(card) == get.color(cardx); + }); + }) + .sortBySeat(); + for (let i of targets) { + dialog.push('
    ' + get.translation(i) + "
    "); + dialog.push( + i.getCards("e", function (cardx) { + return get.color(card) == get.color(cardx); + }) + ); + } + const result2 = await player + .chooseButton([1, 2], true) + .set("createDialog", dialog) + .set("filterButton", button => { + if (!["identity", "guozhan"].includes(get.mode())) return true; + if (!ui.selected.buttons.length) return true; + return get.owner(button.link) == get.owner(ui.selected.buttons[0].link); + }) + .set("ai", function (button) { + let owner = get.owner(button.link); + return get.value(button.link, owner); + }) + .forResult(); + let map = {}; + for (let i of result2.links) { + if (get.color(i) != get.color(card)) continue; + let id = get.owner(i).playerid; + if (!map[id]) map[id] = []; + map[id].push(i); + } + for (let i in map) { + const next = (_status.connectMode ? lib.playerOL : game.playerMap)[i].discard(map[i], "notBySelf"); + next.discarder = player; + await next; } } }, @@ -17569,6 +18005,33 @@ const skills = { equipValue: 4.5, }, }, + subSkill: { + lose: { + audio: "pyzhuren_club", + forced: true, + charlotte: true, + equipSkill: true, + trigger: { + player: "loseAfter", + global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], + }, + filter: (event, player) => { + return player.isDamaged() && !player.hasSkillTag("unequip2"); + }, + getIndex(event, player) { + const evt = event.getl(player); + const lostCards = []; + evt.es.forEach(card => { + const VEquip = evt.vcard_map.get(card); + if (VEquip.name === "pyzhuren_club") lostCards.add(VEquip); + }); + return lostCards.length; + }, + async content(event, trigger, player) { + await player.recover(); + }, + }, + }, }, pyzhuren_spade: { audio: true, diff --git a/character/xianding/sort.js b/character/xianding/sort.js index 825bad827a..3f1761a6b3 100644 --- a/character/xianding/sort.js +++ b/character/xianding/sort.js @@ -1,22 +1,24 @@ const characterSort = { - sp2_huben: ["chendong", "wangshuang", "wenyang", "re_liuzan", "dc_huangzu", "wulan", "leitong", "chentai", "dc_duyu", "dc_wangjun", "dc_xiahouba", "old_huangfusong", "huzun"], + sp2_huben: ["chendong", "wangshuang", "wenyang", "re_liuzan", "dc_huangzu", "wulan", "leitong", "chentai", "dc_duyu", "dc_wangjun", "dc_xiahouba", "old_huangfusong", "huzun", "dc_lingcao"], sp2_shengun: ["puyuan", "guanlu", "gexuan", "wufan", "re_zhangbao", "dukui", "zhaozhi", "zhujianping", "dc_zhouxuān", "zerong"], sp2_bizhe: ["dc_luotong", "dc_wangchang", "chengbing", "dc_yangbiao", "ruanji", "cuimao"], sp2_huangjia: ["caomao", "liubian", "dc_liuyu", "quanhuijie", "dingshangwan", "yuanji", "xielingyu", "sunyu", "ganfurenmifuren", "dc_ganfuren", "dc_mifuren", "dc_shixie", "caofang", "zhupeilan", "bianyue"], sp2_zhangtai: ["guozhao", "fanyufeng", "ruanyu", "yangwan", "re_panshu"], - sp2_jinse: ["caojinyu", "re_sunyi", "re_fengfangnv", "caohua", "laiyinger", "zhangfen", "zhugeruoxue", "caoxian", "dc_qinghegongzhu", "zhugemengxue"], + sp2_jinse: ["liutan", "caojinyu", "re_sunyi", "re_fengfangnv", "caohua", "laiyinger", "zhangfen", "zhugeruoxue", "caoxian", "dc_qinghegongzhu", "zhugemengxue"], sp2_yinyu: ["zhouyi", "luyi", "sunlingluan", "caoyi"], sp2_wangzhe: ["dc_daxiaoqiao", "dc_sp_machao", "sp_zhenji"], sp2_doukou: ["re_xinxianying", "huaman", "xuelingyun", "dc_ruiji", "duanqiaoxiao", "tianshangyi", "malingli", "bailingyun"], sp2_jichu: ["zhaoang", "dc_liuye", "dc_wangyun", "yanghong", "huanfan", "xizheng", "lvfan"], - sp2_yuxiu: ["dongguiren", "dc_tengfanglan", "zhangjinyun", "zhoubuyi", "dc_xujing", "guanyue"], + sp2_yuxiu: ["dongguiren", "dc_tengfanglan", "zhangjinyun", "zhoubuyi", "dc_xujing", "guanyue", "zhugejing"], sp2_qifu: ["dc_guansuo", "xin_baosanniang", "dc_zhaoxiang"], sp2_gaoshan: ["wanglang", "liuhui", "zhangjian"], sp2_wumiao: ["wu_zhugeliang", "wu_luxun", "wu_guanyu"], - sp2_mouding: ["dc_sb_jiaxu", "dc_sb_lusu", "dc_sb_zhouyu", "dc_sb_simayi", "dc_sb_guojia"], + sp2_mouding: ["dc_sb_jiaxu", "dc_sb_lusu", "dc_sb_zhouyu", "dc_sb_simayi"], sp2_zhonghu: ["dc_jiangji", "dc_wangling", "dc_simashi", "dc_caoshuang"], sp2_zijing: ["dc_sb_zhugejin", "dc_sb_guanping"], sp2_dushi: ["dc_sb_caoang", "dc_sb_zhangxiu", "dc_sb_dianwei"], + sp2_zhoulang: ["dc_sb_chengyu"], + sp2_qizuo: ["dc_sb_jushou"], sp2_waitingforsort: [], }; @@ -39,6 +41,8 @@ const characterSortTranslate = { sp2_zhonghu: "冢虎狼顾", sp2_zijing: "子敬邀刀", sp2_dushi: "毒士鸩计", + sp2_zhoulang: "周郎将计", + sp2_qizuo: "奇佐论胜", sp2_waitingforsort: "等待分包", }; diff --git a/character/xianding/translate.js b/character/xianding/translate.js index 0bce5adbfe..79e3bb24aa 100644 --- a/character/xianding/translate.js +++ b/character/xianding/translate.js @@ -85,7 +85,7 @@ const translates = { re_xinxianying_prefix: "新杀", rezhongjian: "忠鉴", rezhongjian2: "忠鉴", - rezhongjian_info: "出牌阶段限一次,你可以选择一名本回合内未选择过的角色。你令其获得一项效果直至你的下回合开始:①其下次造成伤害后弃置两张牌,然后你摸一张牌。②其下次受到伤害后摸两张牌,然后你摸一张牌。", + rezhongjian_info: "出牌阶段限一次,你可以选择一名本回合内未选择过的角色(其他角色不可见)。你令其获得一项效果直至你的下回合开始:①其下次造成伤害后弃置两张牌,然后你摸一张牌。②其下次受到伤害后摸两张牌,然后你摸一张牌。", recaishi: "才识", recaishi3: "才识", recaishi_info: "摸牌阶段结束时,若你于本阶段内因摸牌而获得的所有的牌:花色均相同,你将〖忠鉴〗于本回合内改为“出牌阶段限两次”。不均相同,你可回复1点体力。若如此做,你本回合内不能对自己使用牌。", @@ -262,11 +262,11 @@ const translates = { dctongguan: "统观", dctongguan_info: "一名角色的第一个回合开始时,你为其选择一项属性(每个属性至多选两次,且仅对你可见)。", dcmengjie: "梦解", - dcmengjie_info: "一名角色的回合结束时,若其本回合完成了其〖统观〗属性,你执行对应效果:
  • 「武勇」造成伤害:对一名其他角色造成1点伤害;
  • 「刚硬」回复体力,或于得到牌后手牌数大于体力值:令一名角色回复1点体力;
  • 「多谋」于摸牌阶段外摸牌:摸两张牌;
  • 「果决」弃置或获得其他角色的牌:弃置一名角色区域内至多两张牌;
  • 「仁智」交给其他角色牌:令一名其他角色将手牌补至体力上限(至多摸五张)。", + dcmengjie_info: "一名角色的回合结束时,若其本回合完成了其〖统观〗属性,你执行对应效果:
  • 「武勇」造成伤害:对一名其他角色造成1点伤害;
  • 「刚硬」回复体力,或手牌数大于体力值:令一名角色回复1点体力;
  • 「多谋」于摸牌阶段外摸牌:摸两张牌;
  • 「果决」弃置或获得其他角色的牌:弃置一名角色区域内至多两张牌;
  • 「仁智」交给其他角色牌:令一名其他角色将手牌补至体力上限(至多摸五张)。", dctongguan_wuyong: "武勇", dctongguan_wuyong_info: "任务目标:造成伤害。", dctongguan_gangying: "刚硬", - dctongguan_gangying_info: "任务目标:回复体力,或于得到牌后手牌数大于体力值。", + dctongguan_gangying_info: "任务目标:回复体力,或手牌数大于体力值。", dctongguan_duomou: "多谋", dctongguan_duomou_info: "任务目标:于摸牌阶段外摸牌。", dctongguan_guojue: "果决", @@ -403,7 +403,7 @@ const translates = { dcjiudun_info: "①以你为目标的【酒】(使用方法①)的作用效果改为“目标对应的角色使用的下一张【杀】的伤害基数+1”。②当你成为其他角色使用黑色牌的目标后,若你:未处于【酒】状态,你可以摸一张牌并视为使用一张【酒】;处于【酒】状态,你可以弃置一张手牌令此牌对你无效。", ganfurenmifuren: "甘夫人糜夫人", dcchanjuan: "婵娟", - dcchanjuan_info: "每种牌名限两次。当你使用手牌中仅指定单一目标的【杀】或普通锦囊牌结算结束后,你可以视为使用一张名称和属性均相同的牌。若这两张牌指定的目标完全相同,你摸一张牌。", + dcchanjuan_info: "每种牌名限两次。当你使用手牌中仅指定单一目标的基本牌或普通锦囊牌结算结束后,你可以视为使用一张名称和属性均相同的牌。若这两张牌指定的目标完全相同,你摸一张牌。", dcxunbie: "殉别", dcxunbie_info: "限定技。当你进入濒死状态时,你可以将此武将牌替换为“甘夫人”或“糜夫人”(不能选择已在场上的武将)。然后回复至1点体力并防止所有伤害直到本回合结束。", dc_mifuren: "糜夫人", @@ -437,9 +437,9 @@ const translates = { dcmianyao: "免徭", dcmianyao_info: "摸牌阶段结束时,你可以展示手牌中点数最小的一张牌并将此牌随机插入牌堆中。然后你于此回合结束时摸等同于此牌点数的牌。", dcchangqu: "长驱", - dcchangqu_info: "出牌阶段限一次。你可以开一艘战舰(你从你的上家或下家开始选择任意名座位连续的其他角色,且起点角色获得“战舰”标记)。这些角色按照你选择的顺序依次执行:{若其有本次获得的“战舰”,其选择一项:1.交给你X张手牌,然后将“战舰”移动给你选择的下一名目标角色;2.令其下次受到的属性伤害值+X,然后横置(X为本次〖长驱〗中选项一被选择过的次数且至少为1)。}。", + dcchangqu_info: "出牌阶段限一次。你可以从你的上家或下家开始选择任意名座位连续的其他角色,且起点角色获得“战舰”标记。这些角色按照你选择的顺序依次执行:{若其有本次获得的“战舰”,其选择一项:1.交给你X张手牌,然后将“战舰”移动给你选择的下一名目标角色;2.令其下次受到的属性伤害值+X,然后横置(X为本次〖长驱〗中选项一被选择过的次数且至少为1)。}。", dctongye: "统业", - dctongye_info: "锁定技。游戏开始时或一名角色死亡后,若场上势力数:不大于4,你的手牌上限+3;不大于3,你的攻击范围+3;不大于2,你使用【杀】的次数上限+3;不大于1,你摸牌阶段额定摸牌数+3。", + dctongye_info: "锁定技。游戏开始时或一名角色死亡后,若X≤4,则你重置因〖统业〗获得的效果,然后根据X值获得对应效果:≤4,你的手牌上限+3;≤3,你的攻击范围+3,摸牌阶段额定摸牌数+4-X;≤2,你使用【杀】的次数上限+3;≤1,你回复3点体力。(X为场上势力数)。", tianshangyi: "田尚衣", dcposuo: "婆娑", dcposuo_info: "出牌阶段,若你本阶段未对其他角色造成过伤害,则你可以将一张你本阶段未以此法使用过的花色的手牌当作任意一张存在于游戏的同花色伤害牌使用。", @@ -505,13 +505,13 @@ const translates = { dcsbmingshi: "明势", dcsbmingshi_info: "摸牌阶段,你可以多摸两张牌,然后展示三张牌并令一名其他角色选择获得其中的一张牌。", dcsbmengmou: "盟谋", - dcsbmengmou_info: "转换技,每回合每项各限一次,当你得到其他角色的牌后,或其他角色得到你的牌后:阴,你可以令该角色使用至多X张【杀】,且其每以此法造成1点伤害,其回复1点体力;阳,你可令该角色打出至多X张【杀】,然后其失去Y点体力。(X为你的体力上限,Y为X-其打出【杀】数)", + dcsbmengmou_info: "转换技。①游戏开始时,你可以转换此技能状态;②每回合每项各限一次,当你得到其他角色的牌后,或其他角色得到你的牌后:阳,你可以令该角色使用至多X张【杀】,且其每以此法造成1点伤害,其回复1点体力;阴,你可令该角色打出至多X张【杀】,然后其失去Y点体力。(X为你的体力上限,Y为X-其打出【杀】数)", dc_sb_zhouyu: "新杀谋周瑜", dc_sb_zhouyu_prefix: "新杀谋", dcsbronghuo: "融火", dcsbronghuo_info: "锁定技,当你使用火【杀】或【火攻】时,此牌伤害基值改为场上势力数。", dcsbyingmou: "英谋", - dcsbyingmou_info: "转换技,每回合限一次,当你对其他角色使用牌后,你可以选择其中一名目标角色:阴,你将手牌数摸至与其相同(至多摸五张),然后视为对其使用一张【火攻】;阳,令一名手牌数为全场最大的角色对其使用手牌中所有的【杀】和伤害类锦囊牌(若其没有可使用的牌则将手牌数弃至与你相同)。", + dcsbyingmou_info: "转换技。①游戏开始时,你可以转换此技能状态;②每回合限一次,当你对其他角色使用牌后,你可以选择其中一名目标角色:阳,你将手牌数摸至与其相同(至多摸五张),然后视为对其使用一张【火攻】;阴,令一名手牌数为全场最大的角色对其使用手牌中所有的【杀】和伤害类锦囊牌(若其没有可使用的牌则将手牌数弃至与你相同)。", caoxian: "曹宪", dclingxi: "灵犀", dclingxi_info: "出牌阶段开始和结束时,你可以将至多X张牌称为“翼”置于你的武将牌上(X为你的体力上限)。当你失去武将牌上的“翼”时,你将手牌数调整至Y张(Y为你武将牌上的“翼”所含有的花色数的两倍)。", @@ -556,7 +556,7 @@ const translates = { dc_sb_simayi: "新杀谋司马懿", dc_sb_simayi_prefix: "新杀谋", dcsbquanmou: "权谋", - dcsbquanmou_info: "转换技。出牌阶段每名角色限一次,你可以令一名攻击范围内的其他角色交给你一张牌。阴:当你于本阶段内下次对其造成伤害时,取消之;阳:当你于本阶段内下次对其造成伤害后,你可以选择除其外的至多三名其他角色,对这些角色依次造成1点伤害。", + dcsbquanmou_info: "转换技。①游戏开始时,你可以转换此技能状态;②出牌阶段每名角色限一次,你可以令一名攻击范围内的其他角色交给你一张牌。阳:当你于本阶段内下次对其造成伤害时,取消之;阴:当你于本阶段内下次对其造成伤害后,你可以选择除其外的至多三名其他角色,对这些角色依次造成1点伤害。", dcsbpingliao: "平辽", dcsbpingliao_info: "锁定技。当你声明使用【杀】时,你令此【杀】的目标对其他角色不可见,且你令攻击范围内的其他角色依次选择是否打出一张红色基本牌。所有角色选择完成后,此牌的目标角色中没有以此法打出牌的角色本回合内无法使用或打出手牌;若有不为此牌目标的角色以此法打出了牌,则你摸两张牌,且你本回合使用【杀】的次数上限+1。", caofang: "曹芳", @@ -598,7 +598,7 @@ const translates = { dcsbrushi: "入世", dcsbrushi_info: "限定技,出牌阶段,你可以将你当前〖覆谋〗的状态、你的手牌数和你的体力值调整为你发动〖肃身〗时的记录,然后重置〖覆谋〗的发动次数。", dcsbfumou: "覆谋", - dcsbfumou_info: "转换技,出牌阶段限一次,你可以观看一名其他角色A的手牌并展示其一半手牌:阴,并将这些牌交给另一名其他角色B,然后你与A各摸X张牌(X为A以此法失去的手牌数);阳,令A依次使用这些牌中所有其可以使用的牌(无距离限制且不可被响应)。", + dcsbfumou_info: "转换技。①游戏开始时,你可以转换此技能状态;②出牌阶段限一次,你可以观看一名其他角色A的手牌并展示其至多一半手牌:阳,并将这些牌交给另一名其他角色B,然后你与A各摸X张牌(X为A以此法失去的手牌数);阴,令A依次使用这些牌中所有其可以使用的牌(无距离限制且不可被响应)。", dc_sb_zhugejin: "新杀谋诸葛瑾", dc_sb_zhugejin_prefix: "新杀谋", dcsbtaozhou: "讨州", @@ -623,10 +623,10 @@ const translates = { dcsbzhiwang_info: "每回合限一次,当你因受到牌造成的伤害进入濒死状态时,你可以将此伤害改为无来源并选择一名其他角色,其于本回合结束时可以使用本回合令你进入濒死状态的牌。", dc_sb_dianwei: "新杀谋典韦", dc_sb_dianwei_prefix: "新杀谋", - dcsbkuangzhan:"狂战", - dcsbkuangzhan_info:"出牌阶段限一次,你可以将手牌摸至体力上限并进行X次拼点。若你赢,你视为对所有本回合拼点未赢的其他角色使用一张【杀】;若你未赢,视为其对你使用一张【杀】。(X为你以此法获得的牌数)", - dcsbkangyong:"亢勇", - dcsbkangyong_info:"锁定技,回合开始时,你回满体力;回合结束时,你失去等量体力(至少保留1点)。", + dcsbkuangzhan: "狂战", + dcsbkuangzhan_info: "出牌阶段限一次,你可以将手牌摸至体力上限并进行X次拼点。若你赢,你视为对所有本回合拼点未赢的其他角色使用一张【杀】;若你未赢,视为其对你使用一张【杀】。(X为你以此法获得的牌数)", + dcsbkangyong: "亢勇", + dcsbkangyong_info: "锁定技,回合开始时,你回满体力;回合结束时,你失去等量体力(至少保留1点)。", dc_sb_guanping: "新杀谋关平", dc_sb_guanping_prefix: "新杀谋", dcsbwuwei: "武威", @@ -646,13 +646,36 @@ const translates = { dcbizu: "庇族", dcbizu_info: "出牌阶段,你可以令所有手牌数与你相同的角色摸一张牌。然后若这些角色与本回合此前某次发动〖庇族〗的目标角色均相同,本回合〖庇族〗失效。", dcwuxie: "无胁", - dcwuxie_info: "每回合限一次,当你获得牌后,你可以将其中任意张伤害牌置于牌堆底并令一名其他角色弃置等量张牌。", - dc_sb_guojia: "新杀谋郭嘉", - dc_sb_guojia_prefix: "新杀谋", - dcxianmou: "先谋", - dcxianmou_info: "转换技,你失去过牌的回合结束时,你可以:阴,观看牌堆顶五张牌并获得至多X张牌,若未获得X张牌则获得〖遗计〗直到再发动此项;阳,观看一名角色手牌并弃置其中至多X张牌,若弃置X张牌则你进行一次【闪电】判定。(X为你本回合失去牌数)", - dclunshi: "论势", - dclunshi_info: "一名角色对其以外的角色使用普通锦囊牌的结算中,若你手牌中两张颜色的牌数量相同,你可将一张手牌当作不可被响应的【无懈可击】使用。", + dcwuxie_info: "出牌阶段结束时,你可以选择一名其他角色,与其将手牌中所有伤害牌置入牌堆底,然后你可令放置牌较多的一方回复1点体力。", + liutan: "柳婒", + dcjingyin: "经音", + dcjingyin_info: "一名角色于回合外使用【杀】结算完毕后,你可以令一名使用者外的角色获得此【杀】对应的所有实体牌,且其使用这些牌无次数限制。", + dcchixing: "迟行", + dcchixing_info: "一名角色的出牌阶段结束时,若本阶段有【杀】进入弃牌堆,则你可以摸X张牌(X为本阶段进入弃牌堆的【杀】数),若你以此法获得了【杀】,则你可以使用其中的一张。", + zhugejing: "诸葛京", + dcyanzuo: "研作", + dcyanzuo_info: "出牌阶段限一次,你可以将一张基本牌或普通锦囊牌置于武将牌上,然后视为使用一张“研作”牌。", + dczuyin: "祖荫", + dczuyin_info: "锁定技,你成为其他角色使用【杀】或普通锦囊牌的目标后,若你有与此牌同名的“研作”牌,令此牌无效并弃置所有同名“研作”牌;否则从牌堆或弃牌堆中将一张同名牌置于武将牌上,然后令〖研作〗发动次数+1(至多为3)。", + dcpijian: "辟剑", + dcpijian_info: "结束阶段,若你的“研作”牌数不小于存活人数,你可弃置这些牌,对一名角色造成2点伤害。", + dc_lingcao: "新杀凌操", + dc_lingcao_prefix: "新杀", + dcdufeng: "独锋", + dcdufeng_info: "锁定技。出牌阶段开始时,你失去1点体力或废除一个装备栏,摸X张牌,然后你的攻击范围与使用【杀】的次数上限均为X直到回合结束(X为你已废除的装备栏数与损失的体力值之和,至多为你的体力上限)。", + dc_sb_chengyu: "新杀谋程昱", + dc_sb_chengyu_prefix: "新杀谋", + dcshizha: "识诈", + dcshizha_info: "每回合限一次,其他角色使用牌时,若此牌是其本回合体力变化后使用的首张牌,你可令此牌无效并获得此牌。", + dcgaojian: "告谏", + dcgaojian_info: "出牌阶段,你使用锦囊牌结算完成进入弃牌堆后,可以选择一名其他角色。其依次展示牌堆顶的牌直到出现锦囊牌(至多展示五张),然后选择一项:1.使用此牌,2.用任意张手牌与等量展示牌交换。", + dcgaojian_tag: "手牌", + dc_sb_jushou: "新杀谋沮授", + dc_sb_jushou_prefix: "新杀谋", + dcsbzuojun: "佐军", + dcsbzuojun_info: "出牌阶段限一次,你可以令一名角色摸三张牌并令其选择一项:1.直到其下个回合结束,其不能使用这些牌且这些牌不计入手牌上限;2.失去1点体力,摸一张牌并使用因此获得的任意张牌,然后弃置其余牌。", + dcsbmuwang: "暮往", + dcsbmuwang_info: "锁定技,当你每回合首次失去的基本牌或普通锦囊牌进入弃牌堆时,你获得之。当你本回合再次失去这些牌后,你弃置一张牌。", }; export default translates; diff --git a/character/xianding/voices.js b/character/xianding/voices.js index 12003108b8..79b93ed2ac 100644 --- a/character/xianding/voices.js +++ b/character/xianding/voices.js @@ -1,11 +1,38 @@ export default { + "#dcbizu1": "花既繁于枝,当为众乔灌荫。", + "#dcbizu2": "手执金麾伞,可为我族遮风挡雨。", + "#dcwuxie1": "一介弱质女流,安能登辇拔剑?", + "#dcwuxie2": "主上既亡,我当为生者计。", + "#bianyue:die": "空怀悲怆之心,未有杀贼之力。", + "#dcjingyin1": "金柝越关山,唯送君于南。", + "#dcjingyin2": "燕燕于飞,寒江照孤影。", + "#dcchixing1": "孤鸿鸣晚林,泪垂大江流。", + "#dcchixing2": "若路的尽头是离别,妾宁愿蹒跚一世。", + "#liutan:die": "孤灯照长夜,羹熟唤何人?", + "#dcshizha1": "不好,江东鼠辈欲乘东风来袭! ", + "#dcshizha2": "江上起东风,恐战局生变。", + "#dcgaojian1": "江东不乏能人,主公不可小觑。", + "#dcgaojian2": "狮子搏兔,亦须尽其全力。", + "#dc_sb_chengyu:die": "乌鹊南飞,何枝可依啊……", + "#dcsbkangyong1": "此猛士之血,其与醇酒孰烈乎?", + "#dcsbkangyong2": "歃血为誓,城在则人在。", + "#dcsbkuangzhan1": "平生不修礼乐,唯擅杀人放火。", + "#dcsbkuangzhan2": "宛城乃曹公掌中之物,谁敢染指。", + "#dc_sb_dianwei:die": "主公无恙,韦虽死犹生。", "#dcsbsushen1": "谋先于行则昌,行先于谋则亡。", "#dcsbsushen2": "天行五色,雪覆林间睡狐,独我执白。", + "#dcsbsushen_dc_sb_jiaxu_shadow1": "我有三窟之筹谋,不蹈背水之维谷。", + "#dcsbsushen_dc_sb_jiaxu_shadow2": "已积千里跬步,欲履万里河山。", "#dcsbfumou1": "恩仇付浊酒,荡平劫波,且做英雄吼。", "#dcsbfumou2": "人无恒敌,亦无恒友,唯有恒利。", + "#dcsbfumou_dc_sb_jiaxu_shadow1": "不周之柱已折,这世间当起一阵风,落一场雨。", + "#dcsbfumou_dc_sb_jiaxu_shadow2": "善谋者,不与善战者争功。", "#dcsbrushi1": "孤立川上,观逝者如东去之流水。", "#dcsbrushi2": "九州如画,怎可空老人间?", + "#dcsbrushi_dc_sb_jiaxu_shadow1": "曾寄青鸟凌云志,归来城头看王旗。", + "#dcsbrushi_dc_sb_jiaxu_shadow2": "烽火照长安,淯水洗枯骨,今日对弈何人?", "#dc_sb_jiaxu:die": "辛者抱薪,妄燃烽火以戏诸侯……", + "#dc_sb_jiaxu_shadow:die": "未见青山草木,枯骨徒付浊流……", "#dcsbfuxi1": "可因势而附,亦可因势而袭。", "#dcsbfuxi2": "仗剑在手,或亮之,或藏之。", "#dcsbhaoyi1": "今缴丧敌之炙,且宴麾下袍泽。", @@ -50,9 +77,14 @@ export default { "#caofang:die": "匹夫无罪,怀璧其罪……", "#dcsbquanmou1": "洛水为誓,皇天为证,吾意不在刀兵。", "#dcsbquanmou2": "以谋代战,攻形不以力,攻心不以勇。", + "#dcsbquanmou_dc_sb_simayi_shadow1": "鸿门之宴虽歇,会稽之胆尚悬,孤岂姬、项之辈!", + "#dcsbquanmou_dc_sb_simayi_shadow2": "昔藏青锋于沧海,今潮落,可现兵!", "#dcsbpingliao1": "烽烟起大荒,戎军远役,问不臣者谁?", "#dcsbpingliao2": "挥斥千军之贲,长驱万里之远。", + "#dcsbpingliao_dc_sb_simayi_shadow1": "率土之滨皆为王城,辽土亦居普天之下。", + "#dcsbpingliao_dc_sb_simayi_shadow2": "青云远上,寒风试刃,北雁当寄红绫。", "#dc_sb_simayi:die": "以权谋而立者,必失大义于千秋……", + "#dc_sb_simayi_shadow:die": "人立中流,非己力可向,实大势所迫。", "#duanxie1": "区区绳索就想挡住吾等去路?!", "#duanxie2": "以身索敌,何惧同伤!", "#fenming1": "东吴男儿,岂是贪生怕死之辈?", @@ -87,9 +119,14 @@ export default { "#caoxian:die": "恨生枭雄府,恨嫁君王家……", "#dcsbronghuo1": "火莲绽江矶,炎映三千弱水。", "#dcsbronghuo2": "奇志吞樯橹,潮平百万寇贼。", + "#dcsbronghuo_dc_sb_zhouyu_shadow1": "江东多锦绣,离火起曹贼毕,九州同忾。", + "#dcsbronghuo_dc_sb_zhouyu_shadow2": "星火乘风,风助火势,其必成燎原之姿。", "#dcsbyingmou1": "行计以险,纵略以奇,敌虽百万亦戏之如犬豕。", "#dcsbyingmou2": "若生铸剑为犁之心,须有纵钺止戈之力。", + "#dcsbyingmou_dc_sb_zhouyu_shadow1": "既遇知己之明主,当福祸共之,荣辱共之。", + "#dcsbyingmou_dc_sb_zhouyu_shadow2": "将者,贵在知敌虚实,而后避实而击虚。", "#dc_sb_zhouyu:die": "人生之艰难,犹如不息之长河……", + "#dc_sb_zhouyu_shadow:die": "大业未成,奈何身付黄泉……", "#dcsbmingshi1": "联刘以抗曹,此可行之大势。", "#dcsbmingshi2": "强敌在北,唯协力可御之。", "#dcsbmingshi_dc_sb_lusu_shadow1": "今天下春秋已定,君不见南北沟壑乎?", @@ -99,6 +136,7 @@ export default { "#dcsbmengmou_dc_sb_lusu_shadow1": "合左抑右,定两家之盟。", "#dcsbmengmou_dc_sb_lusu_shadow2": "求同存异,邀英雄问鼎。", "#dc_sb_lusu:die": "虎可为之用,亦可为之伤……", + "#dc_sb_lusu_shadow:die": "青龙已巢,以何驱之?", "#dcqiongying1": "冰心碎玉壶,光转琼英灿。", "#dcqiongying2": "玉心玲珑意,撷英倚西楼。", "#dcnuanhui1": "暖阳映雪,可照八九之风光。", diff --git a/character/xianjian.js b/character/xianjian.js index 29b32da9f7..84f5907a64 100644 --- a/character/xianjian.js +++ b/character/xianjian.js @@ -94,11 +94,6 @@ game.import("character", function () { pal_xuanxiao: "天赋异禀,资质极佳,是万中无一的修仙奇才,和夙玉用双剑束缚幻瞑界吸取灵力并引发琼华派与妖界之战。因夙玉离开昆仑,修炼双剑中断,他被邪火入侵而走火入魔,打伤数名师兄弟,被夙瑶联合青阳、重光与宗炼长老冰封19年,因此逢缘与云天河结拜。", - // pal_jiangyunfan:'', - // pal_tangyurou:'', - // pal_longyou:'', - // pal_xiaoman:'', - pal_xiahoujinxuan: "夏侯世家的少主。因不喜舞枪弄剑,专爱趣闻逸史,让父亲深感恨铁不成钢;好在他对于仙术符法也有所涉略,没沦落到手无缚鸡之力的境地。", pal_muchanglan: @@ -164,7 +159,7 @@ game.import("character", function () { threaten: 2, expose: 0.2, effect: { - player: function (card, player) { + player_use: function (card, player) { if (_status.currentPhase != player) return; if (_status.event.name != "chooseToUse" || _status.event.player != player) return; var num = player.needsToDiscard(); @@ -506,7 +501,7 @@ game.import("character", function () { }, ai: { effect: { - player: function (card, player, target) { + player_use: function (card, player, target) { if (_status.currentPhase != player) return; if ( card.name == "sha" && @@ -778,7 +773,7 @@ game.import("character", function () { ai: { effect: { target: function (card, player, target) { - if (card.name == "bingliang" || card.name == "caomu") return 0; + if (card.name == "bingliang" || card.name == "caomu") return [0, 0]; }, }, }, @@ -823,7 +818,7 @@ game.import("character", function () { nodamage: true, effect: { target: function (card, player, target, current) { - if (get.tag(card, "damage")) return [0, 0]; + if (get.tag(card, "damage")) return "zeroplayertarget"; }, }, }, @@ -2810,7 +2805,7 @@ game.import("character", function () { forced: true, unique: true, forceunique: true, - filter: function () { + filter: function (event, player) { return Math.random() < 0.5 && [player.name1, player.name2].includes("pal_longkui"); }, derivation: ["diesha", "guijiang"], @@ -3074,7 +3069,7 @@ game.import("character", function () { return get.order({ name: "sha" }) + 0.1; }, effect: { - player: function (card, player) { + player_use: function (card, player) { if (_status.currentPhase != player) return; if ( card.name == "sha" && @@ -3255,7 +3250,7 @@ game.import("character", function () { }, ai: { effect: { - player: function (card, player) { + player_use: function (card, player) { if (_status.currentPhase != player) return; if (get.is.altered("shuiyun")) return; if ( @@ -4157,7 +4152,7 @@ game.import("character", function () { }, ai: { effect: { - target_use(card, player, target) { + target(card, player, target) { if ( target.storage.xjzhimeng2 && get.type(card, "trick") == get.type(target.storage.xjzhimeng2, "trick") @@ -4328,9 +4323,9 @@ game.import("character", function () { nothunder: true, effect: { target: function (card, player, target, current) { - if (card.name == "tiesuo") return 0; - if (get.tag(card, "fireDamage")) return 0; - if (get.tag(card, "thunderDamage")) return 0; + if (card.name == "tiesuo") return [0, 0]; + if (get.tag(card, "fireDamage")) return [0, 0, 0, 0]; + if (get.tag(card, "thunderDamage")) return [0, 0, 0, 0]; }, }, }, diff --git a/character/xinghuoliaoyuan/character.js b/character/xinghuoliaoyuan/character.js deleted file mode 100644 index 3a388ff22b..0000000000 --- a/character/xinghuoliaoyuan/character.js +++ /dev/null @@ -1,16 +0,0 @@ -const characters = { - wangcan: ["male", "qun", 3, ["xinfu_sanwen", "xinfu_qiai", "xinfu_denglou"]], - sp_taishici: ["male", "qun", 4, ["xinfu_jixu"], ["name:太史|慈"]], - re_jsp_pangtong: ["male", "wu", 3, ["xinfu_guolun", "xinfu_songsang"]], - lvdai: ["male", "wu", 4, ["xinfu_qinguo"]], - re_zhangliang: ["male", "qun", 4, ["xinfu_jijun", "xinfu_fangtong"]], - lvqian: ["male", "wei", 4, ["xinfu_weilu", "xinfu_zengdao"]], - panjun: ["male", "wu", 3, ["xinfu_guanwei", "xinfu_gongqing"]], - duji: ["male", "wei", 3, ["xinfu_andong", "xinfu_yingshi"]], - zhoufang: ["male", "wu", 3, ["xinfu_duanfa", "xinfu_youdi"]], - yanjun: ["male", "wu", 3, ["xinfu_guanchao", "xinfu_xunxian"]], - liuyao: ["male", "qun", 4, ["xinfu_kannan", "twniju"], ["zhu"]], - liuyan: ["male", "qun", 3, ["xinfu_tushe", "xinfu_limu"]], -}; - -export default characters; diff --git a/character/xinghuoliaoyuan/characterReplace.js b/character/xinghuoliaoyuan/characterReplace.js deleted file mode 100644 index c73e1a74d4..0000000000 --- a/character/xinghuoliaoyuan/characterReplace.js +++ /dev/null @@ -1,9 +0,0 @@ -const characterReplaces = { - duji: ["duji", "re_duji", "ns_duji"], - sp_taishici: ["sp_taishici", "re_sp_taishici"], - mazhong: ["mazhong", "re_mazhong"], - wenpin: ["wenpin", "re_wenpin"], - liuyan: ["liuyan", "jsrg_liuyan", "junk_liuyan"], -}; - -export default characterReplaces; diff --git a/character/xinghuoliaoyuan/intro.js b/character/xinghuoliaoyuan/intro.js deleted file mode 100644 index 787e2e7283..0000000000 --- a/character/xinghuoliaoyuan/intro.js +++ /dev/null @@ -1,14 +0,0 @@ -const characterIntro = { - wangcan: "王粲(177年-217年2月17日),字仲宣。山阳郡高平县(今山东微山两城镇)人。东汉末年文学家,“建安七子”之一,太尉王龚曾孙、司空王畅之孙。", - re_jsp_pangtong: "庞统,字士元,襄阳(治今湖北襄阳)人。三国时刘备帐下谋士,官拜军师中郎将。才智与诸葛亮齐名,人称“凤雏”。在进围雒县时,统率众攻城,不幸被流矢击中去世,时年三十六岁。追赐统为关内侯,谥曰靖侯。庞统死后,葬于落凤庞统墓坡。", - lvdai: "吕岱(161年-256年),字定公,广陵海陵(今江苏如皋)人。三国时期吴国重臣、将领。吕岱一生戮力奉公,为孙吴开疆拓土,功勋赫赫。太平元年(256年),吕岱去世,年九十六。", - lvqian: "吕虔(生卒年不详),字子恪。任城国(今山东济宁东南)人。汉末至三国曹魏时期将领。 吕虔有勇有谋,曹操在兖州时,任命他为从事,率领家丁驻守湖陆。后升任泰山太守,与夏侯渊共同镇压济南等地的黄巾军。被推举为秀才,加任骑都尉,仍管辖泰山郡。 曹丕继任魏王后,加吕虔为裨将军,封益寿亭侯。再升任徐州刺史,加任威虏将军。任用王祥为别驾,将民政事务都委托于他,为世人所称赞。曹叡继位后,改封万年亭侯。吕虔死后,其子吕翻世袭万年亭侯。", - panjun: "潘濬(一作潘浚)(?-239年),字承明。武陵郡汉寿县(今湖南汉寿)人。三国时期吴国重臣,蜀汉大司马蒋琬的表弟。 潘濬为人聪察,对问有机理,拜大儒宋忠为师,得到“建安七子”之一的王粲赏识。不到三十,即被荆州牧刘表任命为江夏从事,因按杀贪污的沙羡长而闻名。建安十六年(211年),被刘备任命为荆州治中从事,与守臣关羽不睦。建安二十四年(219年),孙权得荆州,拜潘濬为辅军中郎将。又迁奋威将军,封常迁亭侯。孙权称帝后,拜少府,进封刘阳侯,又改太常。黄龙三年(231年),授假节,与吕岱率军五万平五溪蛮夷叛乱,经三年而斩获数万,使得一方宁静。潘濬为人刚正不阿,在吕壹弄权时,屡请孙权将其诛杀。甚至想亲手击杀吕壹,使吕壹对他非常畏惧。 赤乌二年(239年),潘濬去世。", - duji: "杜畿(163年—224年),字伯侯,京兆杜陵(今陕西西安东南)人。东汉末及三国时曹魏官吏及将领。西汉御史大夫杜延年的后代。历官郡功曹、守郑县令,善于断案。荀彧将他举荐给曹操,曹操任命他为司空司直,调任护羌校尉,使持节领西平太守。 曹丕受禅登基后,封杜畿为丰乐亭侯。官至尚书仆射。后在陶河试航时遇上大风沉没,杜畿淹死,死时六十二岁,曹丕为之涕泣,追赠其为太仆,谥戴侯。", - zhoufang: "周鲂(生卒年不详),字子鱼。吴郡阳羡县(今江苏宜兴)人。三国时期吴国将领。周鲂年少时好学,被举为孝廉。历任宁国县长、怀安县长、钱塘侯相,一月之内,便斩杀作乱的彭式及其党羽,因而升任丹阳西部都尉。彭绮率数万人反叛时,周鲂被任命为鄱阳太守,与胡综共同将其生擒,因功加职昭义校尉。后诈降曹休,诱其率军接应,使曹休在石亭之战中一败涂地,战后因功被加职为裨将军,封关内侯。贼帅董嗣凭险骚扰豫章等郡,周鲂派间谍将其诱杀,不费兵卒即安定数郡。周鲂在鄱阳赏罚分明、恩威并施,于任职十三年后去世。", - yanjun: "严畯(生卒年不详),字曼才,彭城(治今江苏徐州)人,三国时期孙吴官员、学者。性情忠厚,待人以诚。少好学,精通《诗》、《书》、《三礼》,又好《说文》。避乱江东,与诸葛瑾、步骘是好朋友,被张昭推荐给孙权作骑都尉、从事中郎。建安二十二年(217年),横江将军鲁肃去世,孙权打算让严畯接替其位。严畯很有自知之明,知道自己没有能力对抗在荆州的关羽和北面的曹魏,便坚决不接受此任命。后来担任尚书令。严畯享年七十八岁。著有《孝经传》、《潮水论》。", - liuyao: "刘繇(一读yóu)(156年-197年),字正礼。东莱牟平(今山东牟平)人。东汉末年宗室、大臣,汉末群雄之一,齐悼惠王刘肥之后,太尉刘宠之侄。
    刘繇最初被推举为孝廉,授郎中。任下邑县长时,因拒郡守请托而弃官。后被征辟为司空掾属,除授侍御史,因战乱而不到任,避居淮浦。兴平元年(194年),被任命为扬州刺史。他先后与袁术、孙策交战,一度被朝廷加授为扬州牧、振武将军,但最终还是败归丹徒。此后,刘繇又击破反叛的笮融,旋即病逝,年四十二。", - liuyan: "刘焉(?-194年),字君郎(《华阳国志》又作君朗)。江夏郡竟陵县(今湖北省天门市)人。东汉末年宗室、军阀,汉末群雄之一,西汉鲁恭王刘余之后。
    刘焉初以汉朝宗室身份,拜为中郎,历任雒阳令、冀州刺史、南阳太守、宗正、太常等官。因益州刺史郄俭在益州大肆聚敛,贪婪成风,加上当时天下大乱。刘焉欲取得一安身立命之所,割据一方,于是向朝廷求为益州牧,封阳城侯,前往益州整饬吏治。郄俭为黄巾军所杀,刘焉进入益州,派张鲁盘踞汉中,张鲁截断交通,斩杀汉使,从此益州与中央道路不通。刘焉进一步对内打击地方豪强,巩固自身势力,益州因而处于半独立的状态。兴平元年(194年),刘焉因背疮迸发而逝世,其子刘璋继领益州牧。", -}; - -export default characterIntro; diff --git a/character/xinghuoliaoyuan/perfectPairs.js b/character/xinghuoliaoyuan/perfectPairs.js deleted file mode 100644 index d66d955b06..0000000000 --- a/character/xinghuoliaoyuan/perfectPairs.js +++ /dev/null @@ -1,11 +0,0 @@ -export default { - lijue: ["guosi", "jiaxu"], - zhangji: ["zhangxiu", "drlt_zhangxiu", "zoushi"], - xf_sufei: ["ganning"], - //baosanniang:['guansuo'], - simahui: ["pangdegong"], - zhangqiying: ["zhanglu"], - pangtong: ["zhugejin"], - taishici: ["liuyao", "kongrong"], - //zhaotongzhaoguang:['zhaoyun','mayunlu'], -}; diff --git a/character/xinghuoliaoyuan/skill.js b/character/xinghuoliaoyuan/skill.js deleted file mode 100644 index 83e59132c9..0000000000 --- a/character/xinghuoliaoyuan/skill.js +++ /dev/null @@ -1,1694 +0,0 @@ -import { lib, game, ui, get, ai, _status } from "../../noname.js"; - -/** @type { importCharacterConfig['skill'] } */ -const skills = { - xinyingshi: { - audio: "xinfu_yingshi", - trigger: { player: "phaseUseBegin" }, - direct: true, - filter: function (event, player) { - return ( - player.countCards("he") > 0 && - !game.hasPlayer(function (current) { - return current.getExpansions("xinyingshi_cards").length > 0; - }) - ); - }, - content: function () { - "step 0"; - player.chooseCardTarget({ - filterCard: true, - filterTarget: lib.filter.notMe, - selectCard: [1, player.countCards("he")], - position: "he", - prompt: get.prompt("xinyingshi"), - prompt2: "将任意张牌置于一名其他角色的武将牌上作为“酬”", - ai1: function (card) { - return 1 - player.getUseValue(card); - }, - ai2: function (target) { - var player = _status.event.player; - return ( - (1 + - game.countPlayer(function (current) { - return get.attitude(player, current) > 0 && current.inRange(target) && get.damageEffect(target, current, player) > 0; - })) * - -get.attitude(player, target) - ); - }, - }); - "step 1"; - if (result.bool) { - var target = result.targets[0], - cards = result.cards; - player.logSkill("xinyingshi", target); - target.addSkill("xinyingshi_cards"); - target.addToExpansion(player, "give", cards).gaintag.add("xinyingshi_cards"); - target.storage.xinyingshi_source = player; - } - }, - subSkill: { - cards: { - trigger: { player: "damageSource" }, - forced: true, - charlotte: true, - filter: function (event, player) { - return event.source && event.source.isIn() && event.card && event.getParent().type == "card" && player.getExpansions("xinyingshi_cards").length; - }, - logTarget: "source", - content: function () { - "step 0"; - event.target = trigger.source; - event.target.chooseButton(["应势:请选择你的赏金", player.getExpansions("xinyingshi_cards")]); - "step 1"; - if (result.bool) { - var cards = [result.links[0]]; - for (var i = 0; i < ui.cardPile.childNodes.length; i++) { - var card = ui.cardPile.childNodes[i]; - if (card.number == cards[0].number && card.suit == cards[0].suit) cards.push(card); - } - player.$give(cards[0], target); - if (cards.length > 1) { - setTimeout( - function () { - target.$gain2(cards.slice(1)); - }, - get.delayx(200, 200) - ); - game.log(target, "从牌堆获得了", cards.slice(1)); - } - game.delay(0, get.delayx(500, 500)); - target.gain(cards); - } - "step 2"; - if (!player.getExpansions("xinyingshi_cards").length) player.removeSkill("xinyingshi_cards"); - }, - marktext: "酬", - intro: { - content: "expansion", - markcount: "expansion", - }, - ai: { threaten: 3 }, - group: "xinyingshi_regain", - onremove: function (player, skill) { - var cards = player.getExpansions(skill); - if (cards.length) player.loseToDiscardpile(cards); - delete player.storage.xinyingshi_source; - }, - }, - regain: { - trigger: { player: "die" }, - forced: true, - charlotte: true, - forceDie: true, - filter: function (event, player) { - return player.storage.xinyingshi_source && player.storage.xinyingshi_source.isIn() && player.getExpansions("xinyingshi_cards").length > 0; - }, - content: function () { - player.storage.xinyingshi_source.gain(player.getExpansions("xinyingshi_cards"), player, "give", "bySelf"); - }, - }, - }, - }, - xinfu_guolun: { - audio: 2, - enable: "phaseUse", - usable: 1, - filter: function (event, player) { - return player.countCards("h") > 0; - }, - filterTarget: function (card, player, target) { - return target != player && target.countCards("h") > 0; - }, - content: function () { - "step 0"; - player.choosePlayerCard(target, true, "h"); - "step 1"; - event.cardt = result.cards[0]; - target.showCards(event.cardt); - player.chooseCard("he").set("ai", function (card) { - var event = _status.event.getParent(), - player = event.player; - var numt = get.number(event.cardt); - var att = get.attitude(player, target); - var value = get.value(event.cardt); - var num = get.number(card); - if (num < numt || att > 2) return value + 6 - get.value(card); - else if (num == numt) return value - get.value(card); - return -1; - }); - "step 2"; - if (!result.bool) event.finish(); - else { - player.showCards(result.cards); - event.cardp = result.cards[0]; - } - "step 3"; - player.swapHandcards(target, [event.cardp], [event.cardt]); - "step 4"; - var nump = get.number(event.cardp, player); - var numt = get.number(event.cardt, target); - if (nump < numt) { - player.draw(); - } else if (nump > numt) { - target.draw(); - } - }, - ai: { - threaten: 1.5, - order: 8, - result: { - player: function (player, target) { - if (get.attitude(player, target) > 0) return 1.5; - return 0.5; - }, - }, - }, - }, - xinfu_zhanji: { - audio: 2, - trigger: { - player: "gainAfter", - }, - forced: true, - filter: function (event, player) { - if (!player.isPhaseUsing()) return false; - return event.getParent().name == "draw" && event.getParent(2).name != "xinfu_zhanji"; - }, - content: function () { - player.draw("nodelay"); - }, - }, - xinfu_songsang: { - limited: true, - skillAnimation: true, - animationColor: "wood", - audio: 2, - derivation: "xinfu_zhanji", - trigger: { global: "dieAfter" }, - logTarget: "player", - async content(e, t, player) { - player.awakenSkill("xinfu_songsang"); - if (player.isDamaged()) { - player.recover(); - } else player.gainMaxHp(); - player.addSkills("xinfu_zhanji"); - }, - }, - xinfu_jixu: { - audio: 2, - enable: "phaseUse", - usable: 1, - filter: function (event, player) { - return player.countCards("h") > 0; - }, - filterTarget: function (card, player, target) { - if (player == target) return false; - if (ui.selected.targets.length) { - return target.hp == ui.selected.targets[0].hp; - } - return true; - }, - selectTarget: [1, Infinity], - multitarget: true, - multiline: true, - content: function () { - "step 0"; - targets.sort(lib.sort.seat); - "step 1"; - if (!event.num) event.num = 0; - if (!event.caicuolist) event.caicuolist = []; - targets[event.num].chooseBool("是否押杀?").ai = function (event, player) { - var evt = _status.event.getParent(); - if (get.attitude(targets[event.num], evt.player) > 0) return evt.player.countCards("h", "sha") ? false : true; - return Math.random() < 0.5; - }; - "step 2"; - if (result.bool) { - targets[event.num].chat("有杀"); - game.log(targets[event.num], "认为", player, "#g有杀"); - if (!player.countCards("h", "sha")) event.caicuolist.add(targets[event.num]); - } else { - targets[event.num].chat("没杀"); - game.log(targets[event.num], "认为", player, "#y没有杀"); - if (player.countCards("h", "sha")) event.caicuolist.add(targets[event.num]); - } - event.num++; - game.delay(); - if (event.num < targets.length) event.goto(1); - "step 3"; - player.popup(player.countCards("h", "sha") ? "有杀" : "没杀"); - game.log(player, player.countCards("h", "sha") ? "有杀" : "没杀"); - if (event.caicuolist.length == 0) { - var evt = _status.event.getParent("phaseUse"); - if (evt && evt.name == "phaseUse") { - evt.skipped = true; - event.finish(); - } - } else { - player.draw(event.caicuolist.length); - if (player.countCards("h", "sha")) { - player.addTempSkill("jixu_sha"); - player.storage.jixu_sha = event.caicuolist; - event.finish(); - } else event.num = 0; - } - "step 4"; - if (event.num < event.caicuolist.length) { - var target = event.caicuolist[event.num]; - player.discardPlayerCard(true, "he", target); - event.num++; - event.redo(); - } - }, - ai: { - order: function () { - return get.order({ name: "sha" }) + 0.1; - }, - result: { - target: function (player, target) { - var raweffect = function (player, target) { - if (player.countCards("h", "sha")) { - return get.effect(target, { name: "sha" }, player, target); - } else { - var att = get.attitude(player, target); - var nh = target.countCards("h"); - if (att > 0) { - if (target.getEquip("baiyin") && target.isDamaged() && get.recoverEffect(target, player, player) > 0) { - if (target.hp == 1 && !target.hujia) return 1.6; - if (target.hp == 2) return 0.01; - return 0; - } - } - var es = target.getCards("e"); - var noe = es.length == 0 || target.hasSkillTag("noe"); - var noe2 = es.length == 1 && es[0].name == "baiyin" && target.isDamaged(); - var noh = nh == 0 || target.hasSkillTag("noh"); - if (noh && (noe || noe2)) return 0; - if (att <= 0 && !target.countCards("he")) return 1.5; - return -1.5; - } - }; - var num = game.countPlayer(function (current) { - return current != player && current.hp == target.hp && raweffect(player, current) * get.attitude(player, current) > 0; - }); - return raweffect(player, target) * Math.max(0, num - 1); - }, - }, - expose: 0.4, - }, - }, - jixu_sha: { - audio: "xinfu_jixu", - trigger: { - player: "useCard", - }, - onremove: function (player) { - delete player.storage.jixu_sha; - }, - filter: function (event, player) { - if (event.card.name == "sha") { - return game.hasPlayer(function (current) { - return current != player && player.storage.jixu_sha.includes(current) && !event.targets.includes(current); - }); - } - return false; - }, - forced: true, - silent: true, - popup: false, - content: function () { - player.logSkill("xinfu_jixu"); - for (var i = 0; i < player.storage.jixu_sha.length; i++) { - if (!trigger.targets.includes(player.storage.jixu_sha[i]) && player.canUse("sha", player.storage.jixu_sha[i], false)) { - player.line(player.storage.jixu_sha[i], trigger.card.nature); - trigger.targets.push(player.storage.jixu_sha[i]); - } - } - }, - }, - xinfu_sanwen: { - audio: 2, - usable: 1, - trigger: { - player: "gainAfter", - global: "loseAsyncAfter", - }, - filter: function (event, player) { - var cards = event.getg(player); - if (!cards || !cards.length) return false; - var namelist = []; - var namedlist = []; - for (var i = 0; i < cards.length; i++) { - namelist.add(get.name(cards[i])); - } - var hs = player.getCards("h"); - for (var j = 0; j < hs.length; j++) { - if (namelist.includes(get.name(hs[j])) && !cards.includes(hs[j])) return true; - } - return false; - }, - content: function () { - "step 0"; - var namelist = []; - var namedlist = []; - var nameddlist = []; - var namedddlist = []; - var cards = trigger.getg(player); - for (var i = 0; i < cards.length; i++) { - namelist.add(get.name(cards[i])); - } - var hs = player.getCards("h"); - for (var j = 0; j < hs.length; j++) { - if (namelist.includes(get.name(hs[j])) && !cards.includes(hs[j])) { - namedlist.push(hs[j]); - namedddlist.add(get.name(hs[j])); - } - } - for (var k = 0; k < cards.length; k++) { - if (namedddlist.includes(get.name(cards[k]))) nameddlist.push(cards[k]); - } - var showlist = namedlist.concat(nameddlist); - player.showCards(showlist); - player.discard(nameddlist); - player.draw(2 * nameddlist.length); - }, - }, - xinfu_qiai: { - skillAnimation: true, - animationColor: "gray", - trigger: { player: "dying" }, - limited: true, - audio: 2, - content: function () { - "step 0"; - player.awakenSkill("xinfu_qiai"); - event.targets = game - .filterPlayer(function (current) { - return current != player; - }) - .sortBySeat(); - if (!event.targets.length) event.finish(); - "step 1"; - event.current = event.targets.shift(); - if (!event.current.countCards("he")) event.goto(3); - else - event.current.chooseCard("交给" + get.translation(player) + "一张牌", "he", true).set("ai", function (card) { - var evt = _status.event.getParent(); - if (get.attitude(_status.event.player, evt.player) > 2) { - if (card.name == "jiu") return 120; - if (card.name == "tao") return 110; - } - return 100 - get.value(card); - }); - "step 2"; - if (result.bool && result.cards && result.cards.length) { - event.current.give(result.cards, player); - } - "step 3"; - if (event.targets.length > 0) event.goto(1); - }, - }, - xinfu_denglou: { - audio: 2, - trigger: { - player: "phaseJieshuBegin", - }, - limited: true, - filter: function (event, player) { - return player.countCards("h") == 0; - }, - skillAnimation: true, - animationColor: "gray", - content: function () { - "step 0"; - player.awakenSkill("xinfu_denglou"); - event.cards = get.cards(4); - event.gains = []; - event.discards = []; - var content = ["牌堆顶的四张牌", event.cards]; - game.log(player, "观看了", "#y牌堆顶的四张牌"); - player.chooseControl("ok").set("dialog", content); - "step 1"; - if (get.type(event.cards[0]) != "basic") { - event.gains.push(event.cards[0]); - event.cards.remove(event.cards[0]); - } else { - var bool = game.hasPlayer(function (current) { - return player.canUse(event.cards[0], current); - }); - if (bool) { - player.chooseUseTarget(event.cards[0], true, false); - } else event.discards.push(event.cards[0]); - event.cards.remove(event.cards[0]); - } - "step 2"; - if (event.cards.length) event.goto(1); - else { - if (event.gains.length) player.gain(event.gains, "gain2"); - if (event.discards.length) { - player.$throw(event.discards); - game.cardsDiscard(event.discards); - } - } - }, - }, - qinguo_use: { audio: 2 }, - xinfu_qinguo: { - group: "xinfu_qinguo_recover", - audio: "qinguo_use", - subfrequent: ["recover"], - trigger: { - player: "useCardEnd", - }, - filter: function (event, player) { - return get.type(event.card) == "equip"; - }, - direct: true, - content: function () { - player.chooseUseTarget({ name: "sha" }, get.prompt("xinfu_qinguo"), "视为使用一张【杀】", false).logSkill = "xinfu_qinguo"; - }, - subSkill: { - recover: { - audio: "qinguo_use", - trigger: { - player: "loseAfter", - global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], - }, - prompt: "是否发动【勤国】回复1点体力?", - filter: function (event, player) { - if (player.isHealthy() || player.countCards("e") != player.hp) return false; - var evt = event.getl(player); - if (event.name == "equip" && event.player == player) return !evt || evt.cards.length != 1; - return evt && evt.es.length; - }, - frequent: true, - content: function () { - player.recover(); - }, - }, - }, - ai: { - effect: { - target: function (card, player, target, current) { - if ( - get.type(card) == "equip" && - !get.cardtag(card, "gifts") && - game.hasPlayer(function (current) { - return target.canUse("sha", current); - }) - ) - return [1, 1.5]; - }, - }, - noe: true, - reverseEquip: true, - skillTagFilter: function (player, tag, arg) { - if (tag == "noe") return player.countCards("e") == player.hp + 1; - return game.hasPlayer(function (current) { - return player.canUse("sha", current); - }); - }, - }, - }, - xinfu_jijun: { - ai: { - reverseEquip: true, - effect: { - target: function (card, player, target, current) { - if (get.type(card) == "equip" && player == target && player == _status.currentPhase && get.subtype(card) == "equip1") return [1, 3]; - }, - }, - combo: "xinfu_fangtong", - }, - audio: 2, - trigger: { - player: "useCardToPlayered", - }, - frequent: true, - filter: function (event, player) { - if (player != _status.currentPhase) return false; - if (event.getParent().triggeredTargets3.length > 1) return false; - if (get.type(event.card) == "equip" && get.subtype(event.card) != "equip1") return false; - if (event.targets.includes(player)) return true; - return false; - }, - callback: function () { - player.addToExpansion(card, "gain2").gaintag.add("xinfu_jijun"); - }, - content: function () { - player.judge(function (card) { - return 1; - }).callback = lib.skill.xinfu_jijun.callback; - }, - onremove: function (player, skill) { - var cards = player.getExpansions(skill); - if (cards.length) player.loseToDiscardpile(cards); - }, - intro: { - content: "expansion", - markcount: "expansion", - mark: function (dialog, content, player) { - var content = player.getExpansions("xinfu_jijun"); - if (content && content.length) { - dialog.addAuto(content); - if (player == game.me || player.isUnderControl()) { - var list = lib.skill.xinfu_fangtong.getAuto(player); - if (list.length > 0) { - dialog.addText("
  • 推荐方案:" + get.translation(list[0]) + "+ " + get.translation(list.slice(1))); - } - } - } - }, - }, - marktext: "方", - }, - xinfu_fangtong: { - getAuto: function (player) { - var hs = player.getCards("he"); - var ss = player.getExpansions("xinfu_jijun"); - var bool = false, - max = Math.pow(2, ss.length), - index, - i; - for (i = 0; i < hs.length; i++) { - for (var j = 1; j < max; j++) { - var num = get.number(hs[i]); - index = j.toString(2); - while (index.length < ss.length) { - index = "0" + index; - } - for (var k = 0; k < ss.length; k++) { - if (index[k] == "1") num += get.number(ss[k]); - } - if (num == 36) { - bool = true; - break; - } - } - if (bool) break; - } - if (!bool) return []; - var list = [hs[i]]; - for (var k = 0; k < ss.length; k++) { - if (index[k] == "1") list.push(ss[k]); - } - return list; - }, - audio: 2, - trigger: { - player: "phaseJieshuBegin", - }, - filter: function (event, player) { - return player.countCards("he") > 0 && player.getExpansions("xinfu_jijun").length > 0; - }, - direct: true, - skillAnimation: true, - animationColor: "metal", - content: function () { - "step 0"; - var info = ["是否发动【方统】?"]; - info.push('
    ' + get.translation(player) + "的“方”
    "); - info.push(player.getExpansions("xinfu_jijun")); - if (player.countCards("h")) { - info.push('
    ' + get.translation(player) + "的手牌区
    "); - info.push(player.getCards("h")); - } - if (player.countCards("e")) { - info.push('
    ' + get.translation(player) + "的装备区
    "); - info.push(player.getCards("e")); - } - var next = player.chooseButton(); - next.set("createDialog", info); - next.set("selectButton", function () { - var num = 0; - for (var i = 0; i < ui.selected.buttons.length; i++) { - num += get.number(ui.selected.buttons[i]); - } - if (num == 36) return ui.selected.buttons.length; - return ui.selected.buttons.length + 2; - }); - next.set("filterButton", function (button) { - var player = _status.event.player, - cards = player.getExpansions("xinfu_jijun"); - if (ui.selected.buttons.length) { - if (!cards.includes(button.link)) return false; - } else if (cards.includes(button.link)) return false; - var num = 0; - for (var i = 0; i < ui.selected.buttons.length; i++) { - num += get.number(ui.selected.buttons[i]); - } - return get.number(button.link) + num <= 36; - }); - next.set("autolist", lib.skill.xinfu_fangtong.getAuto(player)); - next.set("processAI", function () { - if (_status.event.autolist && _status.event.autolist.length > 0) { - return { - bool: true, - links: _status.event.autolist, - }; - } - return { bool: false }; - }); - next.set("complexSelect", true); - "step 1"; - if (result.bool) { - player.logSkill("xinfu_fangtong"); - var tothrow = []; - var cards = result.links.slice(0); - for (var i = 0; i < cards.length; i++) { - if (get.position(cards[i]) == "x") { - tothrow.push(cards[i]); - } else { - player.discard(cards[i]).delay = false; - } - } - player.loseToDiscardpile(tothrow); - player - .chooseTarget("选择一个目标并对其造成3点雷电伤害", true, function (card, player, target) { - return target != player; - }) - .set("ai", function (target) { - return get.damageEffect(target, _status.event.player, _status.event.player, "thunder"); - }); - } else { - event.finish(); - } - "step 2"; - var target = result.targets[0]; - player.line(target, "thunder"); - target.damage(3, "thunder"); - }, - ai: { - combo: "xinfu_jijun", - }, - }, - xinfu_weilu: { - audio: 2, - trigger: { - player: "damageEnd", - }, - filter: function (event, player) { - return event.source && event.source.isIn() && !player.getStorage("xinfu_weilu_effect").includes(event.source); - }, - check: function (event, player) { - return get.effect(event.source, { name: "losehp" }, player, player) >= 0; - }, - forced: true, - logTarget: "source", - content: function () { - player.addTempSkill("xinfu_weilu_effect", { player: "die" }); - player.markAuto("xinfu_weilu_effect", [trigger.source]); - game.delayx(); - }, - ai: { - maixie_defend: true, - threaten: 0.85, - effect: { - target: function (card, player, target) { - if (player.hasSkillTag("jueqing", false, target)) return; - return 0.9; - }, - }, - }, - subSkill: { - effect: { - audio: "xinfu_weilu", - trigger: { player: "phaseUseBegin" }, - charlotte: true, - forced: true, - logTarget: function (event, player) { - return player.getStorage("xinfu_weilu_effect").filter(function (current) { - return current.isIn() && current.hp > 1; - }); - }, - content: function () { - "step 0"; - var targets = player.getStorage("xinfu_weilu_effect"); - player.removeSkill("xinfu_weilu_effect"); - event.targets = targets.sortBySeat(); - "step 1"; - var target = targets.shift(); - if (target.isIn() && target.hp > 1) { - event._delay = true; - var num = target.hp - 1; - player.markAuto("xinfu_weilu_recover", [[target, num]]); - target.loseHp(num); - } - if (targets.length > 0) event.redo(); - else if (!event._delay) event.finish(); - "step 2"; - player.addTempSkill("xinfu_weilu_recover", { - player: ["phaseUseAfter", "phaseAfter"], - }); - game.delayx(); - }, - onremove: true, - intro: { content: "已将$列入“威虏”战略打击目标" }, - }, - recover: { - audio: "xinfu_weilu", - charlotte: true, - trigger: { player: "phaseUseEnd" }, - forced: true, - filter: function (event, player) { - var targets = player.getStorage("xinfu_weilu_recover"); - for (var i of targets) { - if (i[0].isIn() && i[0].isDamaged()) return true; - } - return false; - }, - onremove: true, - logTarget: function (event, player) { - var logs = [], - targets = player.getStorage("xinfu_weilu_recover"); - for (var i of targets) { - if (i[0].isIn() && i[0].isDamaged()) logs.add(i[0]); - } - return logs; - }, - content: function () { - "step 0"; - event.list = player.getStorage("xinfu_weilu_recover").slice(0); - event.list.sort(function (a, b) { - return lib.sort.seat(a[0], b[0]); - }); - "step 1"; - var group = event.list.shift(); - if (group[0].isIn() && group[0].isDamaged()) { - group[0].recover(group[1]); - event._delay = true; - } - if (event.list.length > 0) event.redo(); - else if (!event._delay) event.finish(); - "step 2"; - game.delayx(); - }, - }, - }, - }, - xinfu_zengdao: { - audio: 2, - limited: true, - enable: "phaseUse", - filter: function (event, player) { - return player.countCards("e") > 0; - }, - filterTarget: lib.filter.notMe, - skillAnimation: true, - animationColor: "thunder", - position: "e", - filterCard: true, - selectCard: [1, Infinity], - discard: false, - lose: false, - content: function () { - player.awakenSkill("xinfu_zengdao"); - target.addToExpansion(cards, player, "give").gaintag.add("xinfu_zengdao2"); - target.addSkill("xinfu_zengdao2"); - }, - ai: { - order: function () { - var player = _status.event.player, - num = 0; - if (player.hasCard(card => get.value(card, player) < 0, "e")) return 9; - for (var i = 1; i < 6; i++) { - num += player.countEquipableSlot(i); - } - if (num <= 2) return 9; - var targets = player.getStorage("xinfu_weilu_recover"), - num = 0; - if ( - player.hp <= 2 || - !game.hasPlayer(current => { - if (player == current || get.attitude(player, current) < 0 || current.hp <= 1) return false; - for (var arr of targets) { - if (current == arr[0]) break; - } - return current.hp > 2 || current.countCards("hs") > 2; - }) - ) - return 1; - return 0; - }, - result: { - target: function (player, target) { - if (target.hasValueTarget({ name: "sha", isCard: true })) return ui.selected.cards.length; - return 0; - }, - }, - }, - }, - xinfu_zengdao2: { - trigger: { source: "damageBegin1" }, - forced: true, - charlotte: true, - filter: function (event, player) { - return player.getExpansions("xinfu_zengdao2").length > 0; - }, - content: function () { - "step 0"; - player.chooseCardButton("将一张“刀”置入弃牌堆", player.getExpansions("xinfu_zengdao2"), true); - "step 1"; - if (result.bool) { - trigger.num++; - player.loseToDiscardpile(result.links); - } - }, - marktext: "刀", - intro: { - content: "expansion", - markcount: "expansion", - onunmark: function (storage, player) { - player.removeSkill("xinfu_zengdao2"); - }, - }, - }, - xinfu_guanwei: { - audio: 2, - usable: 1, - init: () => { - game.addGlobalSkill("xinfu_guanwei_ai"); - }, - onremove: () => { - if (!game.hasPlayer(i => i.hasSkill("xinfu_guanwei"), true)) game.removeGlobalSkill("xinfu_guanwei_ai"); - }, - trigger: { - global: "phaseUseEnd", - }, - filter: function (event, player) { - var history = event.player.getHistory("useCard"); - var num = 0; - var suit = false; - for (var i = 0; i < history.length; i++) { - var suit2 = get.suit(history[i].card); - if (!lib.suit.includes(suit2)) return false; - if (suit && suit != suit2) return false; - suit = suit2; - num++; - } - return num > 1; - }, - direct: true, - content: function () { - "step 0"; - var target = trigger.player; - player - .chooseToDiscard("he", get.prompt("xinfu_guanwei", trigger.player), "弃置一张牌,令其摸两张牌并进行一个额外的出牌阶段。") - .set("ai", function (card) { - if (get.attitude(_status.event.player, _status.event.targetx) < 1) return 0; - return 9 - get.value(card); - }) - .set("logSkill", ["xinfu_guanwei", target]) - .set("targetx", target); - "step 1"; - if (result.bool) { - player.line(trigger.player, "green"); - trigger.player.draw(2); - } else { - player.storage.counttrigger.xinfu_guanwei--; - event.finish(); - } - "step 2"; - var next = trigger.player.phaseUse(); - event.next.remove(next); - trigger.getParent("phase").next.push(next); - }, - ai: { - expose: 0.5, - }, - subSkill: { - ai: { - trigger: { player: "dieAfter" }, - filter: () => { - return !game.hasPlayer(i => i.hasSkill("xinfu_guanwei"), true); - }, - silent: true, - forceDie: true, - content: () => { - game.removeGlobalSkill("xinfu_guanwei_ai"); - }, - ai: { - effect: { - player_use(card, player, target) { - if (typeof card != "object" || !player.isPhaseUsing()) return; - var hasPanjun = game.hasPlayer(function (current) { - return ( - current.hasSkill("xinfu_guanwei") && - (!current.storage.counttrigger || !current.storage.counttrigger.xinfu_guanwei) && - get.attitude(current, player) >= 1 && - current.hasCard(function (card) { - return get.value(card) < 7 || (current != game.me && !current.isUnderControl() && !current.isOnline() && get.value(card) < 9); - }, "he") - ); - }); - if (!hasPanjun) return; - var suitx = get.suit(card); - var history = player.getHistory("useCard"); - if (!history.length) { - var val = 0; - if ( - player.hasCard(function (cardx) { - return get.suit(cardx) == suitx && card != cardx && (!card.cards || !card.cards.includes(cardx)) && player.hasValueTarget(cardx); - }, "hs") - ) - val = [2, 0.1]; - if (val) return val; - return; - } - var num = 0; - var suit = false; - for (var i = 0; i < history.length; i++) { - var suit2 = get.suit(history[i].card); - if (!lib.suit.includes(suit2)) return; - if (suit && suit != suit2) return; - suit = suit2; - num++; - } - if (suitx == suit && num == 1) return [1, 0.1]; - if ( - suitx != suit && - (num > 1 || - (num <= 1 && - player.hasCard(function (cardx) { - return get.suit(cardx) == suit && player.hasValueTarget(cardx); - }, "hs"))) - ) - return "zeroplayertarget"; - }, - }, - }, - }, - }, - }, - xinfu_gongqing_gz_panjun: { audio: 2 }, - xinfu_gongqing: { - audio: 2, - audioname2: { gz_panjun: "xinfu_gongqing_gz_panjun" }, - trigger: { - player: ["damageBegin3", "damageBegin4"], - }, - forced: true, - filter: function (event, player, name) { - if (!event.source) return false; - var range = event.source.getAttackRange(); - if (name == "damageBegin3") return range > 3; - return event.num > 1 && range < 3; - }, - preHidden: true, - content: function () { - trigger.num = event.triggername == "damageBegin4" ? 1 : trigger.num + 1; - }, - ai: { - filterDamage: true, - skillTagFilter: function (player, tag, arg) { - if (arg && arg.player) { - if (arg.player.hasSkillTag("jueqing", false, player)) return false; - if (arg.player.getAttackRange() < 3) return true; - } - return false; - }, - }, - }, - xinfu_andong: { - subSkill: { - add: { - sub: true, - mod: { - ignoredHandcard: function (card, player) { - if (get.suit(card) == "heart") { - return true; - } - }, - cardDiscardable: function (card, player, name) { - if (name == "phaseDiscard" && get.suit(card) == "heart") return false; - }, - }, - }, - }, - audio: 2, - trigger: { - player: "damageBegin4", - }, - filter: function (event, player) { - return get.itemtype(event.source) == "player"; - }, - logTarget: "source", - content: function () { - "step 0"; - if (!trigger.source.countCards("h")) event._result = { index: 1 }; - else - trigger.source.chooseControlList(["令" + get.translation(player) + "观看你的手牌,并获得其中所有的红桃牌。", "防止即将对" + get.translation(player) + "造成的伤害,并使自己本回合内的红桃手牌不计入手牌上限。"], true).set("ai", function (event, player) { - var target = _status.event.getParent().player; - var player = _status.event.player; - if (get.attitude(player, target) > 0) return 1; - return 0; - }); - "step 1"; - if (result.index == 1) { - trigger.cancel(); - trigger.source.addTempSkill("xinfu_andong_add"); - event.finish(); - } else { - player.viewHandcards(trigger.source); - } - "step 2"; - var cards = trigger.source.getCards("h"); - var togain = []; - for (var i = 0; i < cards.length; i++) { - if (get.suit(cards[i]) == "heart") togain.push(cards[i]); - } - if (togain.length) player.gain(togain, trigger.source, "giveAuto", "bySelf"); - }, - }, - xinfu_yingshi: { - audio: 2, - group: ["yingshi_die"], - trigger: { - player: "phaseUseBegin", - }, - direct: true, - filter: function (event, player) { - return ( - player.countCards("he", { suit: "heart" }) > 0 && - !game.hasPlayer(function (current) { - return current.hasSkill("yingshi_heart"); - }) - ); - }, - content: function () { - "step 0"; - player - .chooseTarget(get.prompt2("xinfu_yingshi"), function (card, player, target) { - return target != player; - }) - .set("ai", function () { - return -1; - }); - "step 1"; - if (result.bool) { - var cards = player.getCards("he", { suit: "heart" }); - var target = result.targets[0]; - player.logSkill("xinfu_yingshi", target); - target.addSkill("yingshi_heart"); - target.addToExpansion(cards, player, "give").gaintag.add("xinfu_yingshi"); - } - }, - marktext: "酬", - intro: { - markcount: "expansion", - content: "expansion", - onunmark: function (storage, player) { - player.removeSkill("yingshi_heart"); - }, - }, - }, - yingshi_heart: { - charlotte: true, - trigger: { player: "damageEnd" }, - filter: function (event, player) { - return event.source && event.source.isIn() && event.card && event.card.name == "sha" && player.getExpansions("xinfu_yingshi").length > 0; - }, - forced: true, - logTarget: "source", - content: function () { - "step 0"; - trigger.source.chooseCardButton("应势:选择获得一张“酬”", player.getExpansions("xinfu_yingshi"), true); - "step 1"; - if (result.bool) { - trigger.source.gain(result.links, player, "give"); - } - }, - }, - yingshi_die: { - audio: "xinfu_yingshi", - forced: true, - trigger: { global: "die" }, - logTarget: "player", - filter: function (event, player) { - return event.player.getExpansions("xinfu_yingshi").length > 0; - }, - content: function () { - var target = trigger.player; - player.gain(target.getExpansions("xinfu_yingshi"), target, "give", "bySelf"); - }, - }, - xinfu_duanfa: { - init: function (player) { - player.storage.xinfu_duanfa = 0; - }, - audio: 2, - enable: "phaseUse", - position: "he", - filter: function (card, player) { - return player.storage.xinfu_duanfa < player.maxHp; - }, - filterCard: function (card) { - return get.color(card) == "black"; - }, - selectCard: function () { - var player = _status.event.player; - return [1, player.maxHp - player.storage.xinfu_duanfa]; - }, - check: function (card) { - return 6 - get.value(card); - }, - delay: false, - content: function () { - player.draw(cards.length); - player.storage.xinfu_duanfa += cards.length; - }, - group: "xinfu_duanfa_clear", - subSkill: { - clear: { - trigger: { - player: "phaseBefore", - }, - forced: true, - silent: true, - popup: false, - content: function () { - player.storage.xinfu_duanfa = 0; - }, - sub: true, - }, - }, - ai: { - order: 1, - result: { - player: 1, - }, - }, - }, - xinfu_youdi: { - audio: 2, - trigger: { - player: "phaseJieshuBegin", - }, - direct: true, - filter: function (event, player) { - return player.countCards("h") > 0; - }, - content: function () { - "step 0"; - player - .chooseTarget(get.prompt2("xinfu_youdi"), function (card, player, target) { - return player != target; - }) - .set("ai", function (target) { - var player = _status.event.player; - if (player.countCards("h", "sha") > player.countCards("h") / 3 && player.countCards("h", { color: "red" }) > player.countCards("h") / 2) return 0; - if (target.countCards("he") == 0) return 0.1; - return -get.attitude(_status.event.player, target); - }); - "step 1"; - if (result.bool) { - game.delay(); - player.logSkill("xinfu_youdi", result.targets); - event.target = result.targets[0]; - event.target.discardPlayerCard(player, "h", true); - } else { - event.finish(); - } - "step 2"; - if (get.color(result.links[0]) != "black") player.draw("nodelay"); - if (result.links[0].name != "sha" && event.target.countCards("he")) { - player.gainPlayerCard("he", event.target, true); - } - }, - ai: { - expose: 0.3, - threaten: 1.4, - }, - }, - xinfu_guanchao: { - subSkill: { - dizeng: { - mark: true, - marktext: "增", - intro: { - content: "单调递增", - }, - trigger: { - player: "useCard", - }, - audio: "xinfu_guanchao", - forced: true, - mod: { - aiOrder: function (player, card, num) { - if (typeof card.number != "number") return; - var history = player.getHistory("useCard", function (evt) { - return ( - evt.isPhaseUsing() && - evt.getParent("phaseUse") === _status.event.getParent("phaseUse") - ); - }); - if (history.length == 0) return num + 10 * (14 - card.number); - var num = get.number(history[0].card); - if (!num) return; - for (var i = 1; i < history.length; i++) { - var num2 = get.number(history[i].card); - if (!num2 || num2 <= num) return; - num = num2; - } - if (card.number > num) return num + 10 * (14 - card.number); - }, - }, - filter: function (event, player) { - var history = player.getHistory("useCard", function (evt) { - return ( - evt.isPhaseUsing() && - evt.getParent("phaseUse") === event.getParent("phaseUse") - ); - }); - if (history.length < 2) return false; - var num = get.number(history[0].card); - if (!num) return false; - for (var i = 1; i < history.length; i++) { - var num2 = get.number(history[i].card); - if (!num2 || num2 <= num) return false; - num = num2; - } - return true; - }, - content: function () { - player.draw(); - }, - sub: true, - }, - dijian: { - mark: true, - marktext: "减", - intro: { - content: "单调递减", - }, - init: function (player) { - player.storage.guanchao = 0; - }, - onremove: function (player) { - delete player.storage.guanchao; - }, - trigger: { - player: "useCard", - }, - audio: "xinfu_guanchao", - forced: true, - mod: { - aiOrder: function (player, card, num) { - if (typeof card.number != "number") return; - var history = player.getHistory("useCard", function (evt) { - return ( - evt.isPhaseUsing() && - evt.getParent("phaseUse") === _status.event.getParent("phaseUse") - ); - }); - if (history.length == 0) return num + 10 * card.number; - var num = get.number(history[0].card); - if (!num) return; - for (var i = 1; i < history.length; i++) { - var num2 = get.number(history[i].card); - if (!num2 || num2 >= num) return; - num = num2; - } - if (card.number < num) return num + 10 * card.number; - }, - }, - filter: function (event, player) { - var history = player.getHistory("useCard", function (evt) { - return ( - evt.isPhaseUsing() && - evt.getParent("phaseUse") === event.getParent("phaseUse") - ); - }); - if (history.length < 2) return false; - var num = get.number(history[0].card); - if (!num) return false; - for (var i = 1; i < history.length; i++) { - var num2 = get.number(history[i].card); - if (!num2 || num2 >= num) return false; - num = num2; - } - return true; - }, - content: function () { - player.draw(); - }, - sub: true, - }, - }, - audio: 2, - trigger: { - player: "phaseUseBegin", - }, - direct: true, - content: function () { - "step 0"; - var list = ["递增", "递减", "取消"]; - player - .chooseControl(list) - .set("prompt", get.prompt2("xinfu_guanchao")) - .set("ai", function () { - return [0, 1].randomGet(); - }); - "step 1"; - switch (result.control) { - case "递增": { - player.logSkill("xinfu_guanchao"); - player.addTempSkill("xinfu_guanchao_dizeng", "phaseUseEnd"); - break; - } - case "递减": { - player.logSkill("xinfu_guanchao"); - player.addTempSkill("xinfu_guanchao_dijian", "phaseUseEnd"); - break; - } - case "取消": { - break; - } - } - }, - }, - xinfu_xunxian: { - usable: 1, - audio: 2, - trigger: { - player: ["useCardAfter", "respond"], - }, - filter: function (event, player) { - if ( - get.itemtype(event.cards) !== "cards" || - !game.hasPlayer(current => { - if (current === player) return false; - return current.getHp() > player.getHp() || current.countCards("h") > player.countCards("h"); - }) - ) - return false; - for (var i = 0; i < event.cards.length; i++) { - if (event.cards[i].isInPile()) { - return true; - } - } - return false; - }, - async cost(event, trigger, player) { - event.result = await player - .chooseTarget(get.prompt2("xinfu_xunxian"), (card, player, target) => { - if (target === player) return false; - return target.getHp() > player.getHp() || target.countCards("h") > player.countCards("h"); - }) - .set("ai", target => { - let att = get.attitude(_status.event.player, target), - name = _status.event.cards[0].name; - if (att < 3) return 0; - if (target.hasJudge("lebu")) att /= 5; - if (name === "sha" && target.hasSha()) att /= 5; - if (name === "wuxie" && target.needsToDiscard(_status.event.cards)) att /= 5; - return att / (1 + get.distance(player, target, "absolute")); - }) - .set("cards", trigger.cards) - .forResult(); - }, - async content(event, trigger, player) { - let list = []; - for (let i = 0; i < trigger.cards.length; i++) { - if (trigger.cards[i].isInPile()) { - list.push(trigger.cards[i]); - } - } - if (get.mode() !== "identity" || player.identity !== "nei") player.addExpose(0.2); - event.targets[0].gain(list, "gain2").giver = player; - }, - }, - xinfu_kannan: { - audio: 2, - subSkill: { - phase: { - sub: true, - }, - }, - enable: "phaseUse", - filter: function (event, player) { - if (player.hasSkill("xinfu_kannan_phase")) return false; - if (player.getStat().skill.xinfu_kannan >= player.hp) return false; - return player.countCards("h") > 0; - }, - filterTarget: function (card, player, target) { - if (target.hasSkill("xinfu_kannan_phase")) return false; - return player.canCompare(target); - }, - ai: { - order: function () { - return get.order({ name: "sha" }) + 0.4; - }, - result: { - target: function (player, target) { - if ( - player.hasCard(function (card) { - if (get.position(card) != "h") return false; - var val = get.value(card); - if (val < 0) return true; - if (val <= 5) { - return card.number >= 12; - } - if (val <= 6) { - return card.number >= 13; - } - return false; - }) - ) - return -1; - return 0; - }, - }, - }, - content: function () { - "step 0"; - player.chooseToCompare(target); - "step 1"; - if (result.bool) { - player.addTempSkill("xinfu_kannan_phase"); - if (!player.hasSkill("kannan_eff")) { - player.addSkill("kannan_eff"); - } else { - if (!player.storage.kannan_eff) player.storage.kannan_eff = 0; - } - player.storage.kannan_eff++; - player.markSkill("kannan_eff"); - } else { - target.addTempSkill("xinfu_kannan_phase"); - if (!target.hasSkill("kannan_eff")) { - target.addSkill("kannan_eff"); - } else { - if (!target.storage.kannan_eff) player.storage.kannan_eff = 0; - //target.storage.kannan_eff++; - //target.markSkill('kannan_eff'); - } - target.storage.kannan_eff++; - target.markSkill("kannan_eff"); - } - }, - }, - kannan_eff: { - mark: true, - intro: { - content: "下一张杀的伤害基数+#", - }, - trigger: { - player: "useCard", - }, - filter: function (event) { - return event.card && event.card.name == "sha"; - }, - forced: true, - content: function () { - if (!trigger.baseDamage) trigger.baseDamage = 1; - trigger.baseDamage += player.storage.kannan_eff; - player.removeSkill("kannan_eff"); - }, - init: function (player) { - player.storage.kannan_eff = 0; - }, - onremove: function (player) { - delete player.storage.kannan_eff; - }, - ai: { - damageBonus: true, - }, - }, - xinfu_tushe: { - audio: 2, - mod: { - aiOrder(player, card, num) { - if (get.tag(card, "multitarget")) { - if (player.countCards("h", { type: "basic" })) return num / 10; - return num * 10; - } - if (get.type(card) === "basic") return num + 10; - }, - aiValue(player, card, num) { - if (card.name === "zhangba") { - let fact = n => { - if (n > 1) return n * fact(n - 1); - return 1; - }, - basic = 0; - return fact( - Math.min( - player.countCards("hs", i => { - if (get.tag(i, "multitarget")) return 2; - if (!["shan", "tao", "jiu"].includes(card.name)) return 1; - basic++; - }) / - (1 + basic), - player.getCardUsable("sha") - ) - ); - } - if (["shan", "tao", "jiu"].includes(card.name)) { - if (player.getEquip("zhangba") && player.countCards("hs") > 1) return 0.01; - return num / 2; - } - if (get.tag(card, "multitarget")) return num + game.players.length; - }, - aiUseful(player, card, num) { - if (get.name(card, player) === "shan") { - if ( - player.countCards("hs", i => { - if (card === i || (card.cards && card.cards.includes(i))) return false; - return get.name(i, player) === "shan"; - }) - ) - return -1; - return num / Math.pow(Math.max(1, player.hp), 2); - } - }, - }, - trigger: { - player: "useCardToPlayered", - }, - locked: false, - frequent: true, - filter: function (event, player) { - if (get.type(event.card) == "equip") return false; - if (event.getParent().triggeredTargets3.length > 1) return false; - return event.targets.length > 0 && !player.countCards("h", { type: "basic" }); - }, - content: function () { - player.draw(trigger.targets.length); - }, - ai: { - presha: true, - pretao: true, - threaten: 1.8, - effect: { - player_use(card, player, target) { - if ( - typeof card === "object" && - card.name !== "shan" && - get.type(card) !== "equip" && - !player.countCards("h", i => { - if (card === i || (card.cards && card.cards.includes(i))) return false; - return get.type(i) === "basic"; - }) - ) { - let targets = [], - evt = _status.event.getParent("useCard"); - targets.addArray(ui.selected.targets); - if (evt && evt.card == card) targets.addArray(evt.targets); - if (targets.length) return [1, targets.length]; - if (get.tag(card, "multitarget")) return [1, game.players.length - 1]; - return [1, 1]; - } - }, - }, - }, - }, - xinfu_limu: { - mod: { - targetInRange: function (card, player, target) { - if (player.countCards("j") && player.inRange(target)) { - return true; - } - }, - cardUsableTarget: function (card, player, target) { - if (player.countCards("j") && player.inRange(target)) return true; - }, - aiOrder(player, card, num) { - if (get.type(card, "delay") && player.canUse(card, player) && player.canAddJudge(card)) return 15; - }, - }, - locked: false, - audio: 2, - enable: "phaseUse", - discard: false, - filter: function (event, player) { - if (player.hasJudge("lebu")) return false; - return player.countCards("hes", { suit: "diamond" }) > 0; - }, - viewAs: { name: "lebu" }, - //prepare:"throw", - position: "hes", - filterCard: function (card, player, event) { - return get.suit(card) == "diamond" && player.canAddJudge({ name: "lebu", cards: [card] }); - }, - selectTarget: -1, - filterTarget: function (card, player, target) { - return player == target; - }, - check(card) { - var player = _status.event.player; - if (!player.getEquip("zhangba")) { - let damaged = player.maxHp - player.hp - 1; - if ( - player.countCards("h", function (cardx) { - if (cardx == card) return false; - if (cardx.name == "tao") { - if (damaged < 1) return true; - damaged--; - } - return ["shan", "jiu"].includes(cardx.name); - }) > 0 - ) - return 0; - } - if (card.name == "shan") return 15; - if (card.name == "tao" || card.name == "jiu") return 10; - return 9 - get.value(card); - }, - onuse: function (links, player) { - var next = game.createEvent("limu_recover", false, _status.event.getParent()); - next.player = player; - next.setContent(function () { - player.recover(); - }); - }, - ai: { - result: { - target(player, target) { - let res = lib.card.lebu.ai.result.target(player, target); - if (target.isDamaged()) return res + 2 * Math.abs(get.recoverEffect(target, player, target)); - return res; - }, - ignoreStatus: true, - }, - order(item, player) { - if (player.hp > 1 && player.countCards("j")) return 0; - return 12; - }, - effect: { - target(card, player, target) { - if (target.isPhaseUsing() && typeof card === "object" && get.type(card, target) === "delay" && !target.countCards("j")) { - let shas = - target.getCards("hs", i => { - if (card === i || (card.cards && card.cards.includes(i))) return false; - return get.name(i, target) === "sha" && target.getUseValue(i) > 0; - }) - target.getCardUsable("sha"); - if (shas > 0) return [1, 1.5 * shas]; - } - }, - }, - }, - }, -}; - -export default skills; diff --git a/character/xinghuoliaoyuan/sort.js b/character/xinghuoliaoyuan/sort.js deleted file mode 100644 index ddad8554b9..0000000000 --- a/character/xinghuoliaoyuan/sort.js +++ /dev/null @@ -1,19 +0,0 @@ -const characterSort = { - // xinghuoliaoyuan_tianfu:[], - xinghuoliaoyuan_tianliang: ["duji", "liuyan", "yanjun"], - xinghuoliaoyuan_tianji: ["panjun", "wangcan"], - xinghuoliaoyuan_tiantong: ["re_jsp_pangtong", "sp_taishici"], - xinghuoliaoyuan_tianxiang: ["lvdai", "zhoufang", "liuyao"], - xinghuoliaoyuan_qisha: ["lvqian", "re_zhangliang"], -}; - -const characterSortTranslate = { - xinghuoliaoyuan_tianfu: "天府", - xinghuoliaoyuan_tianliang: "天梁", - xinghuoliaoyuan_tianji: "天机", - xinghuoliaoyuan_tiantong: "天同", - xinghuoliaoyuan_tianxiang: "天相", - xinghuoliaoyuan_qisha: "七杀", -}; - -export { characterSort, characterSortTranslate }; diff --git a/character/xinghuoliaoyuan/translate.js b/character/xinghuoliaoyuan/translate.js deleted file mode 100644 index ef3ac94ed4..0000000000 --- a/character/xinghuoliaoyuan/translate.js +++ /dev/null @@ -1,85 +0,0 @@ -const translates = { - xinghuoliaoyuan: "星火燎原", - sp_taishici: "SP太史慈", - sp_taishici_prefix: "SP", - wangcan: "王粲", - re_jsp_pangtong: "SP庞统", - re_jsp_pangtong_prefix: "SP", - lvdai: "吕岱", - re_zhangliang: "张梁", - lvqian: "吕虔", - panjun: "潘濬", - duji: "杜畿", - zhoufang: "周鲂", - yanjun: "严畯", - liuyao: "刘繇", - liuyan: "刘焉", - xinfu_guolun: "过论", - xinfu_guolun_info: "出牌阶段限一次,你可以展示一名其他角色的手牌,然后展示你的一张牌。你与其交换这两张牌,然后展示的牌点数较小的角色摸一张牌。", - xinfu_zhanji: "展骥", - xinfu_zhanji_info: "锁定技。你的出牌阶段内,当你因摸牌且不是因为此技能效果而得到牌后,你摸一张牌。", - xinfu_songsang: "送丧", - xinfu_songsang_info: "限定技,其他角色死亡时,你可以回复1点体力(若你未受伤,则改为加1点体力上限);然后获得技能〖展骥〗。", - xinfu_jixu: "击虚", - xinfu_jixu_info: "出牌阶段限一次,若你有手牌,你可以令任意名体力值相等的其他角色猜测你的手牌中是否有【杀】。然后,你摸X张牌(X为猜错的角色数)。若你有【杀】,则你本回合内使用【杀】时,所有这些角色均成为【杀】的目标;若你没有【杀】,则你弃置所有这些角色的各一张牌。若X为零,你结束出牌阶段。", - jixu_sha: "击虚", - jixu_sha_info: "", - xinfu_sanwen: "散文", - xinfu_sanwen_info: "每回合限一次。当你得到牌后,若你的原手牌中有与这些牌名称相同的牌,则你可以展示这些牌,弃置新得到的同名牌并摸两倍的牌。", - xinfu_qiai: "七哀", - xinfu_qiai_info: "限定技,当你进入濒死状态时,你可以令所有其他角色依次交给你一张牌。", - xinfu_denglou: "登楼", - xinfu_denglou_info: "限定技,结束阶段,若你没有手牌,则你可以观看牌堆顶的四张牌,依次使用其中的所有基本牌(不能使用则弃置),然后获得其余的牌。", - qinguo_use: "勤国", - qinguo_use_info: "", - xinfu_qinguo: "勤国", - xinfu_qinguo_info: "当你使用的装备牌结算完成时,你可以视为使用一张【杀】;当你因使用或失去装备牌导致装备区内牌的数量发生变化后,若你装备区内牌的数量等于你的体力值,则你回复1点体力。", - qinguo_lose: "勤国", - qinguo_lose_info: "", - xinfu_jijun: "集军", - xinfu_jijun_info: "当你于回合内使用非装备牌或武器牌指定目标后,若你是此牌的目标,你可以进行一次判定。然后,你将判定牌置于自己的武将牌上,称之为「方」。", - xinfu_fangtong: "方统", - xinfu_fangtong_info: "结束阶段,你可以弃置总点数之和为36的一张牌与任意张「方」,并对一名其他角色造成3点雷电伤害。", - xinfu_weilu: "威虏", - xinfu_weilu_info: "锁定技,当你受到伤害后,伤害来源获得一枚「虏」。你的下个出牌阶段开始时,所有有「虏」的角色将体力失去至1点。此阶段结束后,这些角色回复以此法失去的体力。", - weilu_effect: "威虏", - weilu_effect_info: "", - weilu_effect2: "威虏", - weilu_effect2_info: "", - xinfu_zengdao: "赠刀", - xinfu_zengdao_info: "限定技,出牌阶段,你可以将装备区内的任意张牌置于一名其他角色的武将牌旁,称之为“刀”。该角色造成伤害时,其须移去一张“刀”,然后此伤害+1。", - xinfu_zengdao2: "赠刀", - xinfu_zengdao2_info: "", - xinfu_guanwei: "观微", - xinfu_guanwei_info: "每回合限一次。一名角色的出牌阶段结束时,若其本回合使用过两张以上的牌且这些牌均有花色且花色均相同,则你可以弃置一张牌,令其摸两张牌并进行一个额外的出牌阶段。", - xinfu_gongqing: "公清", - xinfu_gongqing_info: "锁定技。当你受到伤害时,若伤害来源的攻击范围:<3,则你令此伤害的数值减为1。>3,你令此伤害+1。", - xinfu_andong: "安东", - xinfu_andong_info: "当你受到伤害时,你可以令伤害来源选择一项:1.令你观看其的手牌并获得其中的所有红桃牌;2.防止此伤害,然后其本回合内的红桃手牌不计入手牌上限。", - xinfu_yingshi: "应势", - xinfu_yingshi_info: "出牌阶段开始时,若场上的所有角色均没有「酬」,则你可以将所有的红桃牌置于一名其他角色的武将牌旁,称之为「酬」。有「酬」的角色受到【杀】的伤害后/死亡时,伤害来源/你获得其中的一张/所有的「酬」。", - yingshi_heart: "应势", - yingshi_heart_info: "", - yingshi_die: "应势", - yingshi_die_info: "", - xinfu_duanfa: "断发", - xinfu_duanfa_info: "出牌阶段,你可以弃置任意张黑色牌,然后摸等量的牌。(每回合内限X张,X为你的体力上限)", - xinfu_youdi: "诱敌", - xinfu_youdi_info: "结束阶段开始时,你可以令一名其他角色弃置你的一张手牌,若此牌:不为黑色,你摸一张牌。不为【杀】,你获得该角色的一张牌。", - xinfu_guanchao: "观潮", - xinfu_guanchao_info: "出牌阶段开始时,你可以选择获得一项效果直到回合结束:1.当你使用牌时,若你此阶段使用过的所有牌的点数为递增,你摸一张牌;2.当你使用牌时,若你此阶段使用过的所有牌的点数为递减,你摸一张牌。", - xinfu_xunxian: "逊贤", - xinfu_xunxian_info: "每回合限一次。当你使用或打出的牌结算完成后,你可以将其对应的所有实体牌交给一名手牌数或体力值大于你的角色。", - xinfu_kannan: "戡难", - xinfu_kannan_info: "出牌阶段限X次,你可以与一名本回合内未成为过〖戡难〗目标的角色拼点。若你赢,你使用的下一张【杀】的伤害值基数+1,且你本回合内不能再发动〖戡难〗。若你没赢,其使用的下一张【杀】的伤害值基数+1。(X为你的体力值)。", - kannan_eff: "戡难", - kannan_eff_info: "", - xinfu_tushe: "图射", - xinfu_tushe_info: "当你使用非装备牌指定目标后,若你没有基本牌,则你可以摸X张牌。(X为此牌指定的目标数)", - xinfu_limu: "立牧", - xinfu_limu_info: "出牌阶段,你可以将一张♦牌当做【乐不思蜀】对自己使用,然后回复1点体力。只要你的判定区内有牌,你对攻击范围内的其他角色使用牌便没有次数和距离限制。", - xinyingshi: "应势", - xinyingshi_info: "出牌阶段开始时,若场上所有角色的武将牌上均没有“酬”,则你可以将任意张牌置于一名角色的武将牌上,称为“酬”。若如此做:当有角色使用牌对有“酬”的角色造成伤害后,其可以获得一张“酬”,并获得牌堆中所有与“酬”花色点数均相同的牌;有“酬”的角色死亡时,你获得其所有“酬”。", -}; - -export default translates; diff --git a/character/xinghuoliaoyuan/voices.js b/character/xinghuoliaoyuan/voices.js deleted file mode 100644 index 0ff97db238..0000000000 --- a/character/xinghuoliaoyuan/voices.js +++ /dev/null @@ -1,60 +0,0 @@ -export default { - "#xinfu_sanwen1": "文若春华,思若泉涌。", - "#xinfu_sanwen2": "独步汉南,散文天下。", - "#xinfu_qiai1": "未知身死处,何能两相完?", - "#xinfu_qiai2": "悟彼下泉人,喟然伤心肝。", - "#xinfu_denglou1": "登兹楼以四望兮,聊暇日以销忧。", - "#xinfu_denglou2": "惟日月之逾迈兮,俟河清其未极。", - "#wangcan:die": "一作驴鸣悲,万古送葬别……", - "#xinfu_jixu1": "击虚箭射,懈敌戒备。", - "#xinfu_jixu2": "虚实难辨,方迷敌方之心!", - "#sp_taishici:die": "刘繇之见,短浅也……", - "#xinfu_guolun1": "品过是非,讨评好坏。", - "#xinfu_guolun2": "若有天下太平时,必讨四海之内才。", - "#xinfu_songsang1": "送丧至东吴,使命已完。", - "#xinfu_songsang2": "送丧虽至,吾与孝则得相交。", - "#re_jsp_pangtong:die": "我终究……不得东吴赏识……", - "#qinguo_use1": "为国勤事,体素精勤。", - "#qinguo_use2": "忠勤为国,通达治体。", - "#lvdai:die": "再也不能,为吴国奉身了……", - "#xinfu_jijun1": "集万千义军,定天下大局!", - "#xinfu_jijun2": "集民力万千,亦可为军!", - "#xinfu_fangtong1": "统领方队,为民意所举!", - "#xinfu_fangtong2": "三十六方,必为大统!", - "#re_zhangliang:die": "人公也难逃被人所杀……", - "#xinfu_weilu1": "贼人势大,需从长计议。", - "#xinfu_weilu2": "时机未到,先行撤退。", - "#xinfu_zengdao1": "有功赏之,有过罚之。", - "#xinfu_zengdao2": "治军之道,功过分明。", - "#lvqian:die": "我自泰山郡以来,百姓获安,镇军伐贼,此生已无憾!", - "#xinfu_guanwei1": "今日宴请诸位,有要事相商。", - "#xinfu_guanwei2": "天下未定,请主公以大局为重。", - "#xinfu_gongqing1": "尔辈何故与降虏交善。", - "#xinfu_gongqing2": "豪将在外,增兵必成祸患啊!", - "#panjun:die": "耻失荆州,耻失荆州啊!", - "#xinfu_andong1": "勇足以当大难,智涌以安万变。", - "#xinfu_andong2": "宽猛克济,方安河东之民。", - "#xinfu_yingshi1": "应民之声,势民之根。", - "#xinfu_yingshi2": "应势而谋,顺民而为。", - "#duji:die": "试船而溺之,虽亡而忠至……", - "#xinfu_duanfa1": "身体发肤,受之父母。", - "#xinfu_duanfa2": "今断发以明志,尚不可证吾之心意?", - "#xinfu_youdi1": "东吴已容不下我,愿降以保周全。", - "#xinfu_youdi2": "笺书七条,足以表我归降之心。", - "#zhoufang:die": "功亏一篑,功亏一篑啊……", - "#xinfu_guanchao1": "朝夕之间,可知所进退。", - "#xinfu_guanchao2": "月盈,潮起晨暮也;月亏,潮起日半也。", - "#xinfu_xunxian1": "督军之才,子明强于我甚多。", - "#xinfu_xunxian2": "此间重任,公卿可担之。", - "#yanjun:die": "著作,还……没完成……", - "#xinfu_kannan1": "俊才之杰,材匪戡难。", - "#xinfu_kannan2": "戡,克也,难,攻之。", - "#liuyao:die": "伯符小儿,还我子义!", - "#xinfu_tushe1": "非英杰不图?吾既谋之且射毕!", - "#xinfu_tushe2": "汉室衰微,朝纲祸乱,必图后福。", - "#xinfu_limu1": "米贼作乱,吾必为益州自保。", - "#xinfu_limu2": "废史立牧,可得一方安定。", - "#liuyan:die": "背疮难治,世子难继……", - "#xinfu_zhanji1": "公瑾安全至吴,心安之。", - "#xinfu_zhanji2": "功曹之恩,吾必有展骥之机。", -}; diff --git a/character/yijiang/card.js b/character/yijiang/card.js index 1fd2fa8b31..f0d5e22f88 100644 --- a/character/yijiang/card.js +++ b/character/yijiang/card.js @@ -1,10 +1,5 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; -const cards = { - lukai_spade: { fullskin: true }, - lukai_heart: { fullskin: true }, - lukai_diamond: { fullskin: true }, - lukai_club: { fullskin: true }, -}; +const cards = {}; export default cards; diff --git a/character/yijiang/character.js b/character/yijiang/character.js index b352d01260..2daa005924 100644 --- a/character/yijiang/character.js +++ b/character/yijiang/character.js @@ -1,16 +1,4 @@ const characters = { - xiahoumao: ["male", "wei", 4, ["tongwei", "cuguo"], ["name:夏侯|楙"]], - chenshi: ["male", "shu", 4, ["qingbei"]], - sunli: ["male", "wei", 4, ["kangli"]], - feiyao: ["male", "wei", 4, ["zhenfeng"]], - wuanguo: ["male", "qun", 4, ["diezhang", "duanwan"]], - hanlong: ["male", "wei", 4, ["duwang", "cibei"]], - yj_qiaozhou: ["male", "shu", 3, ["shiming", "jiangxi"]], - yj_sufei: ["male", "wu", 4, ["shuojian"]], - liwan: ["female", "wei", 3, ["liandui", "biejun"]], - zhugeshang: ["male", "shu", 3, ["sangu", "yizu"], ["name:诸葛|尚"]], - kebineng: ["male", "qun", 4, ["kousheng"]], - lukai: ["male", "wu", 4, ["lkbushi", "lkzhongzhuang"]], xin_fazheng: ["male", "shu", 3, ["xinxuanhuo", "xinenyuan"]], guanzhang: ["male", "shu", 4, ["fuhun"], ["name:关|兴-张|苞"]], wangyi: ["female", "wei", 3, ["zhenlie", "miji"]], @@ -92,11 +80,6 @@ const characters = { old_huaxiong: ["male", "qun", 6, ["shiyong"]], yujin: ["male", "wei", 4, ["rezhenjun"], ["die:ol_yujin.mp3"]], - - linghuyu: ["male", "wei", 4, ["xvzhi"], ["name:令狐|愚"]], - yj_simafu: ["male", "wei", 3, ["beiyu", "duchi"], ["name:司马|孚"]], - yj_xuangongzhu: ["female", "wei", 3, ["yjqimei", "yjzhuiji"], ["name:司马|null"]], - xukun: ["male", "wu", 4, ["fazhu"]], }; export default characters; diff --git a/character/yijiang/characterReplace.js b/character/yijiang/characterReplace.js index 27eb186a95..9f9b88c948 100644 --- a/character/yijiang/characterReplace.js +++ b/character/yijiang/characterReplace.js @@ -1,34 +1,34 @@ const characterReplaces = { caozhi: ["caozhi", "dc_caozhi", "re_caozhi", "ps_caozhi"], - zhangchunhua: ["zhangchunhua", "re_zhangchunhua", "jin_zhangchunhua", "star_zhangchunhua"], - yujin: ["yujin", "yujin_yujin", "ol_yujin", "sb_yujin", "xin_yujin", "re_yujin"], + zhangchunhua: ["zhangchunhua", "re_zhangchunhua", "ol_zhangchunhua", "jin_zhangchunhua", "star_zhangchunhua"], + yujin: ["yujin", "yujin_yujin", "ol_yujin", "sb_yujin", "xin_yujin", "re_yujin", "jd_sb_yujin"], dc_xushu: ["re_xushu", "dc_xushu"], - xushu: ["xin_xushu", "xushu"], - fazheng: ["xin_fazheng", "ol_fazheng", "re_fazheng", "sb_fazheng", "tw_re_fazheng", "fazheng"], + xushu: ["xin_xushu", "xushu", "std_xushu"], + fazheng: ["xin_fazheng", "ol_fazheng", "re_fazheng", "sb_fazheng", "tw_re_fazheng", "fazheng", "jd_sb_fazheng"], masu: ["xin_masu", "re_masu", "masu"], xusheng: ["xusheng", "xin_xusheng", "re_xusheng", "old_xusheng"], wuguotai: ["wuguotai", "xin_wuguotai", "re_wuguotai", "ol_wuguotai"], lingtong: ["lingtong", "xin_lingtong", "ol_lingtong", "re_lingtong", "old_lingtong"], gaoshun: ["gaoshun", "xin_gaoshun", "ol_gaoshun", "re_gaoshun", "sb_gaoshun", "old_gaoshun"], - zhonghui: ["zhonghui", "xin_zhonghui", "re_zhonghui", "old_zhonghui", "pe_zhonghui", "clan_zhonghui", "yj_zhonghui"], + zhonghui: ["zhonghui", "xin_zhonghui", "re_zhonghui", "old_zhonghui", "pe_zhonghui", "clan_zhonghui", "yj_zhonghui", "std_zhonghui"], wangyi: ["wangyi", "ol_wangyi", "re_wangyi", "old_wangyi"], caozhang: ["caozhang", "ol_caozhang", "re_caozhang", "xin_caozhang"], guanzhang: ["guanzhang", "re_guanzhang", "old_guanzhang"], madai: ["old_madai", "re_madai", "tw_madai", "madai"], - liaohua: ["liaohua", "re_liaohua", "xin_liaohua"], + liaohua: ["liaohua", "re_liaohua", "xin_liaohua", "ty_liaohua"], bulianshi: ["bulianshi", "dc_bulianshi", "re_bulianshi", "old_bulianshi"], handang: ["handang", "xin_handang", "re_handang", "tw_handang", "sb_handang", "old_handang"], chengpu: ["chengpu", "ol_chengpu", "re_chengpu", "xin_chengpu", "tw_chengpu", "ns_chengpu", "std_chengpu"], - liubiao: ["liubiao", "xin_liubiao", "re_liubiao", "jsrg_liubiao", "sb_liubiao", "oldre_liubiao", "old_liubiao", "ol_liubiao"], + liubiao: ["liubiao", "xin_liubiao", "re_liubiao", "jsrg_liubiao", "sb_liubiao", "oldre_liubiao", "old_liubiao", "ol_liubiao", "std_liubiao"], manchong: ["manchong", "re_manchong"], - caochong: ["caochong", "re_caochong", "old_caochong"], + caochong: ["caochong", "re_caochong", "old_caochong", "ol_caochong"], guohuai: ["guohuai", "re_guohuai", "xin_guohuai", "tw_guohuai", "ol_guohuai"], jianyong: ["jianyong", "ol_jianyong", "re_jianyong", "xin_jianyong"], panzhangmazhong: ["panzhangmazhong", "re_panzhangmazhong", "xin_panzhangmazhong"], yufan: ["yufan", "ol_yufan", "xin_yufan", "re_yufan"], zhuran: ["zhuran", "re_zhuran", "xin_zhuran", "old_zhuran"], liru: ["xin_liru", "liru", "dc_liru", "re_liru", "yj_liru", "ol_liru"], - fuhuanghou: ["fuhuanghou", "re_fuhuanghou", "xin_fuhuanghou", "old_fuhuanghou"], + fuhuanghou: ["fuhuanghou", "re_fuhuanghou", "xin_fuhuanghou", "old_fuhuanghou", "std_fuhuanghou"], chenqun: ["chenqun", "dc_chenqun", "re_chenqun", "old_chenqun"], hanhaoshihuan: ["hanhaoshihuan", "re_hanhaoshihuan"], caozhen: ["caozhen", "re_caozhen", "xin_caozhen", "old_caozhen"], @@ -45,21 +45,21 @@ const characterReplaces = { zhangrang: ["zhangrang", "ol_zhangrang", "junk_zhangrang"], jikang: ["jikang", "re_jikang", "dc_jikang"], xinxianying: ["xinxianying", "re_xinxianying", "ol_xinxianying", "sp_xinxianying"], - gongsunyuan: ["gongsunyuan", "re_gongsunyuan"], + gongsunyuan: ["gongsunyuan", "re_gongsunyuan", "std_gongsunyuan"], zhoucang: ["zhoucang", "re_zhoucang", "xin_zhoucang"], guotufengji: ["guotufengji", "re_guotufengji"], guanping: ["guanping", "re_guanping", "dc_sb_guanping"], caifuren: ["caifuren", "re_caifuren", "xin_caifuren", "ol_caifuren"], guyong: ["guyong", "re_guyong", "xin_guyong", "tw_guyong"], - yj_jushou: ["yj_jushou", "re_jushou", "xin_jushou"], + yj_jushou: ["yj_jushou", "re_jushou", "xin_jushou", "dc_sb_jushou"], guohuanghou: ["guohuanghou", "re_guohuanghou"], liuchen: ["liuchen", "re_liuchen"], liufeng: ["liufeng", "re_liufeng"], sundeng: ["sundeng", "re_sundeng", "ns_sundeng"], - caiyong: ["caiyong", "re_caiyong"], + caiyong: ["caiyong", "re_caiyong", "yue_caiyong"], chengong: ["chengong", "re_chengong", "sb_chengong"], xunyou: ["xunyou", "re_xunyou", "clan_xunyou"], - xuezong: ["xuezong", "tw_xuezong"], + xuezong: ["xuezong", "tw_xuezong", "std_xuezong"], huanghao: ["huanghao", "dc_huanghao", "old_huanghao"], caorui: ["caorui", "re_caorui", "old_caorui"], sunziliufang: ["sunziliufang", "dc_sunziliufang"], @@ -70,6 +70,7 @@ const characterReplaces = { wuxian: ["wuxian", "clan_wuxian"], simafu: ["mb_simafu", "simafu", "yj_simafu"], xuangongzhu: ["yj_xuangongzhu", "xuangongzhu"], + cenhun: ["cenhun", "std_cenhun"], }; export default characterReplaces; diff --git a/character/yijiang/dynamicTranslate.js b/character/yijiang/dynamicTranslate.js index db1c22a7b0..cb14680591 100644 --- a/character/yijiang/dynamicTranslate.js +++ b/character/yijiang/dynamicTranslate.js @@ -24,26 +24,6 @@ const dynamicTranslates = { if (player.hasSkill("funan_jiexun")) return "其他角色使用或打出牌响应你使用的牌时,你可获得其使用或打出的牌。"; return "其他角色使用或打出牌响应你使用的牌时,你可令其获得你使用的牌(其本回合不能使用或打出这些牌),然后你获得其使用或打出的牌。"; }, - lkbushi(player) { - var list = lib.skill.lkbushi.getBushi(player).map(i => get.translation(i)); - return "①你使用" + list[0] + "牌无次数限制。②当你使用或打出" + list[1] + "牌后,你摸一张牌。③当你成为" + list[2] + "牌的目标后,你可以弃置一张牌,令此牌对你无效。④结束阶段开始时,你从牌堆或弃牌堆获得一张" + list[3] + "牌。⑤准备阶段开始时,你可调整此技能中四种花色的对应顺序。"; - }, - diezhang(player) { - var str = ""; - str += player.storage.duanwan ? "" : "①出牌阶段,你使用【杀】的次数上限+1。②"; - str += "转换技" + (player.storage.duanwan ? ",每回合限一次" : "") + "。"; - var cnNum = get.cnNumber(player.storage.duanwan ? 2 : 1); - var yinStr = "阴:当你使用牌被其他角色抵消后,你可以弃置一张牌,视为对其使用" + cnNum + "张【杀】"; - var yangStr = "阳:当其他角色使用牌被你抵消后,你可以摸" + cnNum + "张牌,视为对其使用一张【杀】"; - if (player.storage.diezhang) { - if (player.storage.duanwan) yinStr = '' + yinStr + ""; - yangStr = '' + yangStr + ""; - } else { - yinStr = '' + yinStr + ""; - if (player.storage.duanwan) yangStr = '' + yangStr + ""; - } - return str + yinStr + ";" + yangStr + "。"; - }, }; export default dynamicTranslates; diff --git a/character/yijiang/index.js b/character/yijiang/index.js index 70722c5cce..c7ae2cc19e 100644 --- a/character/yijiang/index.js +++ b/character/yijiang/index.js @@ -21,6 +21,7 @@ game.import("character", function () { characterSort: { yijiang: characterSort, }, + characterSubstitute: {}, characterFilter: { ...characterFilters }, characterTitle: {}, dynamicTranslate: { ...dynamicTranslates }, diff --git a/character/yijiang/intro.js b/character/yijiang/intro.js index 008242b953..98efd7432a 100644 --- a/character/yijiang/intro.js +++ b/character/yijiang/intro.js @@ -1,16 +1,4 @@ const characterIntro = { - linghuyu: "令狐愚(?-249年),字公治,太原人。曹魏时期将领, 原名浚。太尉王凌的外甥,弘农太守令狐邵之侄。黄初年间出任和戎护军,后任曹爽府长史、兖州刺史。嘉平年间,与王凌一起密谋废除曹芳,共立楚王曹彪,事未行而病卒。嘉平三年(251年),事泄,王凌服毒自尽,与此事相连者,皆夷三族。王凌及令狐愚被开棺暴尸三日, 亲土埋之。", - xukun: "徐琨,字号不详,吴郡富春县(今浙江省杭州市富阳区)人。三国时期吴国开国功臣,武烈皇帝孙坚的外甥,吴大帝孙权的表兄弟,徐夫人的生父。出身吴郡豪门,最初担任郡吏。投靠舅舅孙坚,参与征伐董卓有功,拜偏将军。孙坚逝后,追随孙策,攻讨扬州刺史刘繇,采取奇袭作战方式,占领丹阳郡,为孙策开拓江东事业奠定基础,领丹杨太守。适逢吴景归附江东,改授督军中郎将。孙权嗣位后,平定庐江太守李术叛乱,击破皖城,册封广德侯,加号平虏将军。后来,随孙权征讨黄祖,身中流矢,不治而亡。", - sunli: "孙礼(?—250年),字德达,涿郡容城县人。三国时期曹魏名将。曹操平定幽州后,孙礼被征召为司空军谋掾。后被任命为河间郡丞,升至荥阳都尉。后孙礼被调为鲁国相。历任山阳、平原、平昌、琅邪郡太守。从大司马曹休在夹石征吴,孙礼谏其不可深入作战,曹休不听遂战败。后孙礼调任阳平郡太守。明帝时入为尚书,受遗诏拜大将军长史,加散骑常侍。曹爽令孙礼出任扬州刺史,加管伏波将军,赐爵关内侯。孙礼率兵御东吴军队,奋不顾身,贼众乃退。朝廷赐绢七百匹,孙礼皆以绢付亡者家,无以入身。后征拜少府,出为荆州刺史,迁冀州牧。爽见礼奏,大怒,劾礼怨望,结刑五岁。在家期年,众人多以为言,除城门校尉。出为并州刺史,加振武将军,使持节,护匈奴中郎将。爽诛后,入为司隶校尉。迁司空,封大利亭侯,邑一百户。嘉平二年(250年),孙礼去世,谥号景侯。其孙孙元继承爵位。《全三国文》录有孙礼文一篇《清河平原争界案图宜属平原疏》。陈寿评曰“孙礼刚断伉厉”。", - xiahoumao: "夏侯楙,字子林,沛国谯县(今安徽省亳州市)人,曹魏名将夏侯惇之子,三国时期魏国官员、将领,其妻为曹操之女清河公主。在魏国历任侍中、尚书、安西将军、镇东将军,假节,封列侯。曾一度驻守曹魏都城长安,但蜀汉北伐后就被调离。", - chenshi: "陈式,生卒年不详,三国时期蜀汉将领。最初为刘备军中重要的基层指挥官,后成长为高级将领。在诸葛亮第三次北伐期间,在诸葛亮的军事指挥下攻克了魏国的武都、阴平二郡。", - feiyao: "费曜(生卒年不详),又作费瑶、费繇,三国时期曹魏将领。魏初,参与平河西之乱。明帝时官任后将军,跟随曹真、司马懿多次对抗蜀汉。《三国演义》中作“费耀”,随曹真和诸葛亮的第二次北伐军作战。怀疑姜维作内应是假,自告奋勇替曹真出征,结果被事先埋伏的姜维包围,自尽而死。", - wuanguo: "武安国,历史小说《三国演义》中人物,是北海太守孔融的部将,兵器为一把长柄铁锤,重五十余斤。诸侯伐董时,双方于虎牢关相峙,吕布撰战,一合而斩穆顺,关东军大惊。北海太守孔融部将武安国,使铁锤飞马而出,吕布挥戟拍马来迎,战到十余合,一戟砍断安国手腕,安国弃锤于地而走,八路军兵齐出,这才救了他性命。", - hanlong: "韩龙,汉末三国时期刺客。韩龙使得魏国北方边得到数十年的安宁,减少魏国的军政压力,得以休养生息。太和二年,豫遣译夏舍诣比能女婿郁筑鞬部,舍为鞬所杀。其秋,豫将西部鲜卑蒲头、泄归泥出塞讨郁筑鞬,大破之。还至马城,比能自将三万骑围豫七日。上谷太守阎志,阎柔之弟也,素为鲜卑所信。志往解喻,即解围去。后幽州刺史王雄并领校尉,抚以恩信。比能数款塞,诣州奉贡献。至青龙元年,比能诱纳步度根,使叛并州,与结和亲,自勒万骑迎其累重於陉北。并州刺史毕轨遣将军苏尚、董弼等击之,比能遣子将骑与尚等会战於楼烦,临陈害尚、弼。至三年中,雄遣勇士韩龙刺杀比能,更立其弟。", - liwan: "李婉(生卒年不详),字淑文,里居不详,贾充之妻,魏晋时期才女,约景元年间(260年前后)在世。著有《典戒》。《隋书·经籍志》载李婉有文集一卷,今失传。", - zhugeshang: "诸葛尚(244年2月-263年11月),琅琊阳都(今山东沂南)人,诸葛瞻长子,诸葛亮之孙。诸葛尚博览兵书且精通武艺。炎兴元年(公元263年),出任先锋,抗拒魏国大将邓艾,与其父诸葛瞻同战死于绵竹,时年十九岁。", - kebineng: "轲比能(?~235年),为中国三国时期的鲜卑首领之一。轲比能出身鲜卑支部,因他作战勇敢,执法公平,不贪财物,所以被鲜卑民众推举为大人。轲比能因其部落近塞,所以他抓住有利条件积极学习汉族先进技术和文化,促进了鲜卑族的进步和北方的民族融合。轲比能统率下的部众,战守有法,战斗力相当强大。自曹操北征后向曹氏进贡表示效忠。魏文帝时,轲比能受封附义王。轲比能在进行部落统一战争时,受魏国干涉,受沉重打击,于是对魏怀贰,献书魏帝表忠,以麻痹魏庭,使之放松警惕。此后,轲比能的部众变得强盛,控弦十余万骑,为害魏国边境。每次钞略得财物,轲比能都公开透明地均平分配,所以得部众死力,各部大人都敬畏之。实力强大后,他继续部落统一战争,于是威行诸部落,建立起强大的鲜卑族政权。深感威胁的魏国幽州刺史王雄派刺客韩龙将其刺杀,其政权立刻崩溃,鲜卑民族再次陷入混战。", - lukai: "陆凯(198-269年),字敬风,吴郡吴县(今江苏省苏州市)人。三国时期吴国重臣,丞相陆逊的族侄,大司马陆抗的族兄。黄武年间,举孝廉出身,曾任永兴县长、诸暨县长,颇有治绩。拜建武都尉、儋耳太守,与聂友率军讨伐朱崖和儋耳,迁建武校尉。五凤二年(255年),讨斩零陵山贼陈毖,拜偏将军、巴丘督,册封都乡侯。迁武昌右部督,随军进入寿春。后拜荡魏将军,加号绥远将军。吴景帝孙休继位,拜征北将军、假节、领豫州牧。孙皓即位,迁任镇西大将军,都督巴丘,又领荆州牧,进封嘉兴侯。宝鼎元年(266年),迁左丞相。以正直及屡次劝谏孙皓而闻名。建衡元年(269年),去世,时年七十二。", caozhi: "字子建,沛国谯人,三国曹魏著名文学家,建安文学代表人物。魏武帝曹操之子,魏文帝曹丕之弟,生前曾为陈王,去世后谥号“思”,因此又称陈思王。南朝宋文学家谢灵运更有“天下才有一石,曹子建独占八斗”的评价。王士祯尝论汉魏以来二千年间诗家堪称“仙才”者,曹植、李白、苏轼三人耳。", gaoshun: "中国东汉末年将领,吕布帐下中郎将。史载高顺为人清白有威严,不好饮酒,所统率的部队精锐非常,号称“陷阵营”。屡进忠言于吕布,吕布虽知其忠而不能用。曹操击破吕布后,高顺被曹操所杀。", chengong: "字公台,东汉末年吕布帐下谋士,东郡东武阳人。性情刚直,足智多谋,年少时与海内知名之士相互结交。192年,陈宫等人主张曹操接任兖州牧。但此后陈宫因曹操杀害边让而与曹操反目,并游说张邈等人背叛曹操迎吕布入兖州,辅助吕布攻打曹操。吕布战败后,随吕布等一同被曹操所擒,决意赴死。", diff --git a/character/yijiang/skill.js b/character/yijiang/skill.js index e495e10228..88d393668f 100644 --- a/character/yijiang/skill.js +++ b/character/yijiang/skill.js @@ -2,1947 +2,6 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { - //一将2024 - //令狐愚 - xvzhi: { - audio: 2, - enable: "phaseUse", - filter(event, player) { - return ( - game.countPlayer(target => { - return lib.skill.xvzhi.filterTarget(null, player, target); - }) > 1 - ); - }, - filterTarget(card, player, target) { - const stat = player.getStat("xvzhi"); - return target.countCards("h") && (!stat || !stat.includes(target)); - }, - selectTarget: 2, - usable: 1, - multiline: true, - multitarget: true, - async content(event, trigger, player) { - const targets = event.targets; - if (!player.getStat().xvzhi) player.getStat().xvzhi = []; - player.getStat().xvzhi.addArray(targets); - if (targets.some(i => !i.countCards("h"))) return; - const result = await player - .chooseCardOL(targets, "h", true, [1, Infinity], "蓄志:选择任意张手牌并与对方交换") - .set("ai", card => { - const player = get.event("player"), - target = get - .event() - .getParent(2) - .targets.find(i => i != player); - const sha = new lib.element.VCard({ name: "sha" }); - const playerEffect = player.hasUseTarget(sha, false) - ? Math.max( - ...game - .filterPlayer(current => player.canUse(sha, current, false)) - .map(current => { - return get.effect(current, sha, player, player); - }) - ) - : 0; - const targetEffect = target.hasUseTarget(sha, false) - ? Math.max( - ...game - .filterPlayer(current => target.canUse(sha, current, false)) - .map(current => { - return get.effect(current, sha, player, player); - }) - ) - : 0; - return 5 + 2 * get.sgn(playerEffect - targetEffect) - get.value(card); - }) - .forResult(); - await targets[0].swapHandcards(targets[1], result[0].cards, result[1].cards); - if (result[0].cards.length == result[1].cards.length) { - await player.draw(2); - player.getStat("skill").xvzhi--; - } else { - const aim = targets[result[0].cards.length > result[1].cards.length ? 0 : 1]; - const sha = new lib.element.VCard({ name: "sha" }); - if (aim.hasUseTarget(sha, false)) { - await aim.chooseUseTarget(sha, true, false, "nodistance"); - } - } - }, - ai: { - order: 5, - result: { - target(player, target) { - return get.sgn(get.attitude(player, target)) * target.countCards("h"); - }, - }, - }, - }, - //司马孚 - beiyu: { - audio: 2, - enable: "phaseUse", - filter(event, player) { - return player.countCards("h") < player.maxHp; - }, - usable: 1, - async content(event, trigger, player) { - await player.drawTo(player.maxHp); - if (!player.countCards("h")) return; - const suits = player - .getCards("h") - .reduce((list, card) => list.add(get.suit(card)), []) - .sort((a, b) => lib.suit.indexOf(b) - lib.suit.indexOf(a)); - const result = await player - .chooseControl(suits) - .set("prompt", "备预:将一种花色的手牌牌置于牌堆底") - .set("ai", () => { - const player = get.event("player"); - let suits = get.event("controls").slice(); - suits.sort((a, b) => player.countCards("h", { suit: a }) - player.countCards("h", { suit: b })); - return suits[0]; - }) - .forResult(); - if (result.control) { - const suit = result.control, - cards = player.getCards("h", { suit: suit }); - if (cards.length) { - let resultx; - if (cards.length == 1) { - resultx = { bool: true, moved: [cards] }; - } else { - resultx = await player - .chooseToMove("备预:将牌按顺序置于牌堆底", true) - .set("list", [["牌堆底", cards]]) - .set("processAI", list => { - return [list[0][1].slice(0)]; - }) - .forResult(); - } - if (resultx.bool) { - const moved = resultx.moved[0]; - if (moved.length) { - await player.lose(cards, ui.cardPile); - for (let i = 0; i < moved.length; i++) { - const card = moved[i]; - card.fix(); - ui.cardPile.appendChild(card); - } - } - } - } - } - }, - ai: { - order: 0.001, - result: { player: 1 }, - }, - }, - duchi: { - audio: 2, - trigger: { target: "useCardToTargeted" }, - filter(event, player) { - return event.player != player; - }, - usable: 1, - logTarget: "player", - check(event, player) { - return get.effect(player, event.card, event.player, player) <= 0; - }, - async content(event, trigger, player) { - await player.draw().set("bottom", true); - if (player.countCards("h")) { - await player.showHandcards(get.translation(player) + "发动了【督持】"); - const colors = player.getCards("h").reduce((list, card) => list.add(get.color(card)), []); - if (colors.length == 1) { - player.popup("洗具"); - trigger.getParent().excluded.add(player); - return; - } - } - player.popup("杯具"); - }, - ai: { threaten: 0.8 }, - }, - //宣公主 - yjqimei: { - audio: 2, - enable: "phaseUse", - filter(event, player) { - const count = player.getStat("skill").yjqimei; - if (count && count > 0 && !player.hasSkill("yjqimei_rewrite")) return false; - return true; - }, - filterTarget: lib.filter.notMe, - usable: 2, - async content(event, trigger, player) { - const target = event.target; - await player.draw(2, "nodelay"); - await target.draw(2); - const targets = [player, target].filter(current => current.countDiscardableCards(current, "he")); - if (targets.length) { - const result = await player - .chooseCardOL(targets, "he", true, 2, "齐眉:请弃置两张牌", (card, player, target) => { - return lib.filter.cardDiscardable(card, player); - }) - .forResult(); - if (result.length == 1) targets[0].discard(result[0].cards); - else { - await game - .loseAsync({ - lose_list: [ - [targets[0], result[0].cards], - [targets[1], result[1].cards], - ], - }) - .setContent("discardMultiple"); - await game.asyncDelayx(); - } - let cards = result.reduce((list, evt) => { - list.addArray(evt.cards); - return list; - }, []); - const suits = cards.reduce((list, card) => list.add(get.suit(card)), []); - switch (suits.length) { - case 1: - while (cards.length) { - const card = cards.shift(); - if (player.hasUseTarget(card)) { - player.$gain2(card, false); - await game.asyncDelayx(); - await player.chooseUseTarget(true, card, false); - } - } - break; - case 2: - for (const current of [player, target]) { - if (!current.isIn()) continue; - if (current.isLinked()) await current.link(false); - if (current.isTurnedOver()) await current.turnOver(false); - } - break; - case 3: - for (const current of [player, target]) { - if (current.isIn() && !current.isLinked()) await current.link(true); - } - break; - case 4: - await player.draw("nodelay"); - await target.draw(); - player.addTempSkill("yjqimei_rewrite"); - break; - } - } - }, - ai: { - order: 9, - result: { - target(player, target) { - const att = get.sgn(get.attitude(player, target)); - return (2 + att) * att; - }, - }, - }, - subSkill: { rewrite: { charlotte: true } }, - }, - yjzhuiji: { - audio: 2, - trigger: { player: "die" }, - filter(event, player) { - return game.hasPlayer(target => { - return ( - target != player && - Array.from({ length: 5 }) - .map((_, i) => i + 1) - .some(i => target.hasEmptySlot(i)) - ); - }); - }, - forceDie: true, - skillAnimation: true, - animationColor: "water", - async cost(event, trigger, player) { - event.result = await player - .chooseTarget(get.prompt2("yjzhuiji"), (card, player, target) => { - return ( - target != player && - Array.from({ length: 5 }) - .map((_, i) => i + 1) - .some(i => target.hasEmptySlot(i)) - ); - }) - .set("ai", target => { - const player = get.event("player"); - return ( - get.sgn(get.attitude(player, target)) * - Array.from({ length: 5 }) - .map((_, i) => i + 1) - .reduce((sum, i) => sum + target.countEmptySlot(i), 0) - ); - }) - .set("forceDie", true) - .forResult(); - }, - async content(event, trigger, player) { - const target = event.targets[0]; - let num = 1, - cards = []; - while (num <= 5) { - while (target.hasEmptySlot(num)) { - const card = get.cardPile2(card => { - return !cards.includes(card) && get.subtype(card) == "equip" + num && target.canUse(card, target); - }); - if (card) { - cards.push(card); - target.$gain2(card, false); - await game.asyncDelayx(); - await target.chooseUseTarget(card, true, "nopopup"); - } else break; - } - num++; - } - if (cards.length) { - target.addSkill("yjzhuiji_buff"); - target.markAuto("yjzhuiji_buff", cards); - } - }, - subSkill: { - buff: { - charlotte: true, - mod: { - aiValue(player, card, num) { - if (player.getStorage("yjzhuiji_buff").includes(card)) return num + 100; - }, - aiUseful(player, card, num) { - if (player.getStorage("yjzhuiji_buff").includes(card)) return num / 114514; - }, - }, - trigger: { - player: "loseAfter", - global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], - }, - filter(event, player) { - const evt = event.getl(player); - return evt && evt.es && evt.es.some(i => player.getStorage("yjzhuiji_buff").includes(i)); - }, - forced: true, - popup: false, - firstDo: true, - content() { - const evt = trigger.getl(player); - const cards = evt.es.filter(i => player.getStorage("yjzhuiji_buff").includes(i)); - player.unmarkAuto("yjzhuiji_buff", cards); - for (const card of cards) player.disableEquip(get.subtype(card)); - }, - intro: { - mark(dialog, storage) { - if (storage && storage.length) dialog.addSmall([storage, "vcard"]); - else return "暂无装备"; - }, - }, - }, - }, - }, - //徐琨(菜不菜我不知道) - fazhu: { - audio: 3, - trigger: { player: "phaseZhunbeiBegin" }, - filter(event, player) { - return player.hasCard(card => !get.tag(card, "damage") && player.canRecast(card), "hej"); - }, - async cost(event, trigger, player) { - event.result = await player - .choosePlayerCard(get.prompt(event.name.slice(0, -5)), player, "hej", [1, Infinity]) - .set("ai", button => { - const card = button.link; - if (get.position(card) == "j") return 10; - return 6 - get.value(card); - }) - .set("filterButton", button => { - const card = button.link; - return !get.tag(card, "damage") && player.canRecast(card); - }) - .forResult(); - }, - async content(event, trigger, player) { - await player.recast(event.cards); - const cards = player - .getHistory("gain", evt => evt.getParent(3) == event) - .reduce((list, evt) => { - list.addArray(evt.cards); - return list; - }, []); - let num = Math.min(cards.length, game.countPlayer()), - list = []; - if (!num) return; - if (_status.connectMode) game.broadcastAll(() => (_status.noclearcountdown = true)); - while (num - list.length > 0 && cards.some(i => get.owner(i) == player && get.position(i) == "h" && !i.hasGaintag("olsujian_given"))) { - const result = await player - .chooseCardTarget({ - prompt: "筏铸:将以此法获得的牌交给任意角色各一张", - position: "he", - animate: false, - filterCard(card, player) { - if (!get.event("cards").includes(card)) return false; - return !get.event("list").some(list => list[1] == card); - }, - filterTarget(card, player, target) { - return !get.event("list").some(list => list[0] == target); - }, - ai1(card) { - if (card.name == "sha") return 2.5; - return 1 + Math.random(); - }, - ai2(target) { - return get.attitude(get.event("player"), target); - }, - }) - .set("forced", !list.length) - .set("list", list) - .set("cards", cards) - .forResult(); - if (result.bool) { - list.push([result.targets[0], result.cards[0]]); - player.addGaintag(result.cards, "olsujian_given"); - } else break; - } - if (_status.connectMode) { - game.broadcastAll(() => { - delete _status.noclearcountdown; - game.stopCountChoose(); - }); - } - if (list.length) { - const targets = list.slice().map(list => list[0]); - await game - .loseAsync({ - gain_list: list, - player: player, - cards: list.slice().map(list => list[1]), - giver: player, - animate: "giveAuto", - }) - .setContent("gaincardMultiple"); - for (const target of targets) { - await target - .chooseToUse(function (card, player, event) { - if (get.name(card) != "sha") return false; - return lib.filter.cardEnabled.apply(this, arguments); - }) - .set("openskilldialog", "筏铸:是否使用一张【杀】(无距离限制)?") - .set("norestore", true) - .set("custom", { - add: {}, - replace: { window: function () {} }, - }) - .set("targetRequired", true) - .set("complexSelect", true) - .set("filterTarget", function (card, player, target) { - return lib.filter.targetEnabled.apply(this, arguments); - }) - .set("addCount", false); - } - } - }, - ai: { - effect: { - target(card, player, target) { - if (!card || get.type(card) != "delay") return; - if (!get.tag(card, "damage") && target.canRecast(card)) return "zeroplayertarget"; - }, - }, - }, - }, - //一将2023 - //孙礼 - kangli: { - audio: 2, - trigger: { - player: "damageEnd", - source: "damageSource", - }, - forced: true, - locked: false, - content: function () { - player.draw(2).gaintag = ["kangli"]; - player.when({ source: "damageBegin1" }).then(() => { - var cards = player.getCards("h", card => card.hasGaintag("kangli") && lib.filter.cardDiscardable(card, player, "kangli")); - if (cards.length) player.discard(cards); - }); - }, - ai: { - maixie: true, - }, - }, - //夏侯楙 - tongwei: { - audio: 2, - enable: "phaseUse", - usable: 1, - filter: function (event, player) { - return player.countCards("he", card => lib.skill.tongwei.filterCard(card, player)) > 1 && game.hasPlayer(i => i != player); - }, - filterTarget: lib.filter.notMe, - filterCard: lib.filter.cardRecastable, - selectCard: 2, - position: "he", - discard: false, - lose: false, - delay: false, - popname: true, - check: function (card) { - var num = 6.5; - if (ui.selected.cards.length) { - var cardx = ui.selected.cards[0]; - num = get.number(cardx); - } - var del = Math.abs(get.number(card) - num); - return 5 + del / 5 - get.value(card); - }, - content: function () { - "step 0"; - player.recast(cards); - "step 1"; - var numbers = cards.map(c => get.number(c, player)).sort((a, b) => a - b); - target.when("useCard1").then(() => { - trigger._tongwei_checked = true; - }); - target - .when("useCardAfter") - .assign({ - numbers: numbers, - playerx: player, - mod: { - aiOrder: function (player, card, num) { - var number = get.number(card); - if (typeof number != "number" || number <= numbers[0] || number >= numbers[1]) return num + 10; - }, - }, - }) - .filter((event, player) => { - return event._tongwei_checked; - }) - .then(() => { - var number = get.number(trigger.card); - var numbers = get.info(event.name).numbers; - event.playerx = get.info(event.name).playerx; - if (typeof number != "number" || number <= numbers[0] || number >= numbers[1]) event.finish(); - }) - .then(() => { - var playerx = event.playerx; - var names = ["sha", "guohe"].filter(name => playerx.canUse({ name: name, isCard: true }, player, false)); - if (!names.length) event.finish(); - else if (names.length == 1) event._result = { links: [[null, null, names[0]]] }; - else - playerx - .chooseButton([`请选择要视为对${get.translation(player)}使用的牌`, [names, "vcard"]], true) - .set("ai", button => { - return button.link[0][2] == _status.event.choice; - }) - .set( - "choice", - (function () { - var list = names - .map(name => { - return [name, get.effect(player, { name: name, isCard: true }, playerx, playerx)]; - }) - .sort((a, b) => { - return b[1] - a[1]; - }); - return list[0][0]; - })() - ); - }) - .then(() => { - var name = result.links[0][2]; - var card = { name: name, isCard: true }, - playerx = event.playerx; - if (playerx.canUse(card, player, false)) playerx.useCard(card, player, "tongwei"); - }); - }, - ai: { - expose: 0.2, - order: 7, - threaten: 2.2, - result: { - target: -1, - }, - }, - }, - cuguo: { - audio: 2, - trigger: { player: ["shaMiss", "eventNeutralized"] }, - filter: function (event, player) { - if (event.type != "card" && event.name != "_wuxie") return false; - if ( - !event.target || - !event.target.isIn() || - !player.canUse( - { - name: event.card.name, - nature: event.card.nature, - isCard: true, - }, - event.target, - false - ) - ) - return false; - if (!player.hasCard(card => lib.filter.cardDiscardable(card, player), "he")) return false; - var history = game.getGlobalHistory("everything"); - for (var evt of history) { - if (evt._neutralized || (evt.responded && (!evt.result || !evt.result.bool))) { - var evtx = evt.getParent(); - return evtx.name == "useCard" && evtx.player == player && evt == event; - } - } - return false; - }, - forced: true, - direct: true, - content: function () { - "step 0"; - var card = { - name: trigger.card.name, - nature: trigger.card.nature, - isCard: true, - storage: { cuguo: true }, - }; - event.card = card; - player.chooseToDiscard("蹙国:请弃置一张牌", `视为你对${get.translation(trigger.target)}使用一张${get.translation(card.nature || "")}【${get.translation(card.name)}】`, "he", true).set("logSkill", ["cuguo", trigger.target]); - "step 1"; - if (player.canUse(card, trigger.target, false)) { - player.useCard(card, trigger.target); - player - .when("useCardAfter") - .filter(event => { - return event.card.storage && event.card.storage.cuguo; - }) - .then(() => { - if ( - game.hasGlobalHistory("everything", evt => { - if (evt._neutralized || (evt.responded && (!evt.result || !evt.result.bool))) { - if (evt.getParent() == trigger) return true; - } - return false; - }) - ) { - player.loseHp(); - } - }); - } - }, - }, - //陈式 - qingbei: { - audio: 2, - trigger: { global: "roundStart" }, - direct: true, - content: function () { - "step 0"; - var next = player.chooseButton(['###擎北:是否选择任意种花色?###
    你不能于本轮能使用这些花色,且使用牌后摸等同于选择花色数的牌
    ', [lib.suit.map(i => ["", "", "lukai_" + i]), "vcard"]], [1, 4]); - next.set("ai", button => { - var player = _status.event.player; - var suit = button.link[2].slice(6); - var val = player - .getCards("hs", { suit: suit }) - .map(card => { - return get.value(card) + player.getUseValue(card) / 3; - }) - .reduce((p, c) => { - return p + c; - }, 0); - if (val > 10 && ui.selected.buttons.length > 0) return -1; - if (val > 6 && ui.selected.buttons.length == 2) return -1; - if (ui.selected.buttons.length == 3) return -1; - return 1 + 1 / val; - }); - "step 1"; - if (result.bool) { - var suits = result.links.map(i => i[2].slice(6)); - player.logSkill("qingbei"); - player.addTempSkill("qingbei_effect", "roundStart"); - player.setStorage("qingbei_effect", suits); - player.markSkill("qingbei_effect"); - } - }, - ai: { - threaten: 2.3, - }, - subSkill: { - effect: { - audio: "qingbei", - trigger: { player: "useCardAfter" }, - charlotte: true, - onremove: true, - forced: true, - filter: function (event, player) { - if (!lib.suit.includes(get.suit(event.card))) return false; - return player.getStorage("qingbei_effect").length; - }, - content: function () { - player.draw(player.getStorage("qingbei_effect").length); - }, - mark: true, - intro: { - content: storage => `本轮内不能使用${get.translation(storage)}花色的牌,且使用一张有花色的牌后摸${get.cnNumber(storage.length)}张牌`, - }, - mod: { - cardEnabled: function (card, player) { - if (player.getStorage("qingbei_effect").includes(get.suit(card))) return false; - }, - cardSavable: function (card, player) { - if (player.getStorage("qingbei_effect").includes(get.suit(card))) return false; - }, - }, - }, - }, - }, - //费曜 - zhenfeng: { - audio: 2, - trigger: { global: "useCard" }, - usable: 1, - filter: function (event, player) { - return event.player != player && event.player == _status.currentPhase && event.player.countCards("h") <= event.player.getHp(); - }, - check: function (event, player) { - var type = get.type2(event.card, event.player); - if (type == "equip" && event.player.hasCard(card => event.player.hasValueTarget(card))) return false; - if (get.attitude(player, event.player) > 0 && event.player.getHp() + event.player.countCards("hs", ["shan", "caochuan"]) <= 3) return false; - return true; - }, - onremove: true, - logTarget: "player", - content: function () { - "step 0"; - var choices = Array.from({ length: trigger.player.countCards("h") + 1 }).map((_, i) => get.cnNumber(i, true)); - var type = get.type2(trigger.card, trigger.player); - player - .chooseControl(choices) - .set("prompt", "镇锋:猜测其手牌中的" + get.translation(type) + "牌数") - .set("ai", () => { - return _status.event.choice; - }) - .set( - "choice", - (function () { - var num = trigger.player.countCards("h", card => get.type2(card) == type); - var knownNum = trigger.player.countKnownCards(_status.event.player, card => get.type2(card) == type); - if (trigger.player.isAllCardsKnown(_status.event.player)) { - return knownNum; - } - var restNum = num - knownNum; - var numx; - if (type == "basic") numx = num + Math.floor(Math.random() * restNum + 1); - else if (type == "trick") { - if (num > 2) numx = 2; - else numx = 1; - if (Math.random() < 0.5) { - numx += Math.random() > 0.5 ? 1 : -1; - } - } else { - numx = [0, 1].randomGet(); - } - if (numx < knownNum) numx = knownNum; - else if (numx >= choices.length) numx = choices.length - 1; - return numx; - })() - ); - "step 1"; - var guessedNum = result.index; - player.chat("我猜" + get.cnNumber(guessedNum) + "张"); - game.log(player, "猜测", trigger.player, "有", get.cnNumber(guessedNum) + "张" + get.translation(type) + "牌"); - event.guessedNum = guessedNum; - game.delay(); - "step 2"; - var type = get.type2(trigger.card, trigger.player); - var count = trigger.player.countCards("h", card => get.type2(card) == type); - var guessedNum = event.guessedNum; - if (count == guessedNum) { - player.popup("洗具"); - game.log(player, "猜测", "#g正确"); - if (player.countMark("zhenfeng") < 5) player.addMark("zhenfeng", 1, false); - player.draw(player.countMark("zhenfeng")); - if (player.canUse("sha", trigger.player, false)) player.useCard({ name: "sha", isCard: true }, trigger.player); - } else { - player.popup("杯具"); - game.log(player, "猜测", "#y错误"); - player.clearMark("zhenfeng"); - if (Math.abs(count - guessedNum) > 1 && trigger.player.canUse("sha", player, false)) { - trigger.player.useCard({ name: "sha", isCard: true }, player, false, "noai"); - } - } - }, - intro: { - content: "已连续猜对#次", - }, - }, - //新杀小加强 李严 - dcduliang: { - enable: "phaseUse", - usable: 1, - filterTarget: function (card, player, target) { - return player != target && target.countCards("he") > 0; - }, - audio: "duliang", - content: function () { - "step 0"; - player.gainPlayerCard(target, "he", true); - "step 1"; - var name = get.translation(target); - player - .chooseControl(function () { - return Math.random() < 0.5 ? "选项一" : "选项二"; - }) - .set("prompt", "督粮:请选择一项") - .set("choiceList", ["你观看牌堆顶的两张牌,然后令" + name + "获得其中的一或两张基本牌", "令" + name + "于下回合的摸牌阶段额外摸一张牌"]); - "step 2"; - if (result.control == "选项一") { - var cards = get.cards(2), - bool = false; - event.cards = cards; - game.cardsGotoOrdering(cards); - for (var card of cards) { - if (get.type(card) == "basic") { - bool = true; - break; - } - } - player - .chooseButton(["督粮:选择令" + get.translation(target) + "获得的牌", cards], [1, 2], bool) - .set("filterButton", button => { - return get.type(button.link) == "basic"; - }) - .set("ai", button => { - return _status.event.sgn * get.value(button.link); - }) - .set("sgn", get.sgnAttitude(player, target) > 0); - } else { - target.addTempSkill("dcduliang2", { player: "phaseAfter" }); - target.addMark("dcduliang2", 1, false); - event.finish(); - } - "step 3"; - if (result.bool) { - var cardsx = result.links; - target.gain(cardsx, "draw"); - game.log(target, "获得了" + get.cnNumber(cardsx.length) + "张牌"); - cards.removeArray(cardsx); - cards.reverse(); - } - for (var i = 0; i < cards.length; i++) { - ui.cardPile.insertBefore(cards[i], ui.cardPile.firstChild); - } - game.updateRoundNumber(); - }, - ai: { - order: 4, - result: { - target: -1, - player: 0.1, - }, - }, - }, - dcduliang2: { - trigger: { player: "phaseDrawBegin" }, - forced: true, - mark: true, - audio: false, - onremove: true, - charlotte: true, - intro: { - content: "下回合的摸牌阶段额外摸#张牌", - }, - content: function () { - trigger.num += player.countMark("dcduliang2"); - }, - }, - //苏飞 - shuojian: { - audio: 2, - enable: "phaseUse", - usable: 3, - filterTarget: lib.filter.notMe, - filterCard: true, - position: "he", - discard: false, - lose: false, - delay: false, - check: function (card, player) { - return 6 - get.value(card); - }, - content: function () { - "step 0"; - player.give(cards, target); - "step 1"; - var num = 3 - get.skillCount("shuojian") + 1; - event.num = num; - event.num2 = num; - if (event.num == 0) event.finish(); - "step 2"; - var forced = num != event.num2; - var prompt = "###" + get.translation(player) + "对你发动了【数谏】###视为使用" + get.cnNumber(num) + "张【过河拆桥】" + (forced ? "" : "且" + get.translation(player) + "此技能本回合失效,或点击“取消”令其摸" + get.cnNumber(num) + "张牌"); - if (!target.hasUseTarget({ name: "guohe" })) event._result = { bool: false }; - else - target - .chooseUseTarget(prompt, "guohe", forced) - .set("ai", function () { - var evt = _status.event; - if (evt.name == "chooseTarget") evt = evt.getParent(); - if (!evt.goon) return 0; - return get.effect_use.apply(this, arguments); - }) - .set("goon", target.getUseValue({ name: "guohe" }) > (get.sgnAttitude(target, player) * player.getUseValue({ name: "wuzhong" })) / (2 - num * 0.4)); - "step 3"; - if (!result.bool) { - player.draw(num); - if (num > 1) player.chooseToDiscard("he", num - 1, true); - event.finish(); - } - "step 4"; - if (--event.num2 > 0) { - event.goto(2); - } else player.tempBanSkill("shuojian"); - }, - ai: { - expose: 0.15, - order: 8, - result: { target: 1 }, - }, - }, - //谯周 - shiming: { - audio: 2, - trigger: { global: "phaseDrawBegin1" }, - filter: function (event, player) { - return !player.hasSkill("shiming_round"); - }, - check: function (event, player) { - return true; //get.attitude(player,event.player)<0||get.damageEffect(event.player,event.player,player)>0; - }, - logTarget: "player", - content: function () { - "step 0"; - player.addTempSkill("shiming_round", "roundStart"); - var cards = get.cards(3); - player - .chooseButton(["识命:是否将其中一张置于牌堆底?", cards.slice(0)]) - .set("ai", button => { - var att = _status.event.att, - damage = _status.event.damage, - val = get.value(button.link, _status.event.player); - if ((att > 0 && damage < 0) || (att <= 0 && damage > 0)) return 6 - val; - return val - 5.99; - }) - .set("att", get.attitude(player, trigger.player)) - .set("damage", get.damageEffect(trigger.player, trigger.player, player) > 0 && trigger.player.hp <= 3 ? 1 : -1); - while (cards.length) ui.cardPile.insertBefore(cards.pop(), ui.cardPile.firstChild); - "step 1"; - if (result.bool) { - var card = result.links[0]; - card.fix(); - ui.cardPile.appendChild(card); - player.popup("一下", "wood"); - game.log(player, "将一张牌置于了牌堆底"); - } - "step 2"; - trigger.player - .chooseBool("是否跳过摸牌阶段并对自己造成1点伤害,然后从牌堆底摸三张牌?") - .set("ai", () => _status.event.bool) - .set("bool", get.damageEffect(trigger.player, trigger.player) >= -6 || trigger.player.hp > 3); - "step 3"; - if (result.bool) { - trigger.cancel(); - trigger.player.damage(trigger.player); - } else event.finish(); - "step 4"; - trigger.player.draw(3, "bottom"); - }, - subSkill: { - round: { - mark: true, - intro: { content: "本轮已发动〖识命〗" }, - }, - }, - }, - jiangxi: { - audio: 2, - trigger: { global: "phaseEnd" }, - filter: function (event, player) { - var zhu = game.findPlayer(i => i.getSeatNum() == 1); - return ( - (zhu && - player.hasSkill("shiming_round") && - (game.getGlobalHistory("changeHp", evt => { - return evt.player == zhu && evt._dyinged; - }).length > 0 || - zhu.getHistory("damage").length == 0)) || - !game.hasPlayer2(current => current.getHistory("damage").length > 0) - ); - }, - direct: true, - content: function () { - "step 0"; - if (player.hasSkill("shiming_round")) { - var zhu = game.findPlayer(i => i.getSeatNum() == 1); - if ( - game.getGlobalHistory("changeHp", evt => { - return evt.player == zhu && evt._dyinged; - }).length > 0 || - zhu.getHistory("damage").length == 0 - ) { - player.chooseBool(get.prompt("jiangxi"), "重置〖识命〗"); - } - } else event.goto(2); - "step 1"; - if (result.bool) { - player.logSkill("jiangxi"); - event.logged = true; - player.removeSkill("shiming_round"); - player.draw(); - } - "step 2"; - if (!game.hasPlayer2(current => current.getHistory("damage").length > 0)) { - player - .chooseBool(get.prompt("jiangxi"), "与" + get.translation(trigger.player) + "各摸一张牌") - .set("ai", () => _status.event.bool) - .set("bool", trigger.player.getUseValue({ name: "wuzhong" }) + player.getUseValue({ name: "wuzhong" }) > 0); - } else event.finish(); - "step 3"; - if (result.bool) { - if (!event.logged) player.logSkill("jiangxi"); - trigger.player.draw("nodelay"); - player.draw(); - } - }, - }, - //韩龙 - duwang: { - audio: 2, - trigger: { - global: "phaseBefore", - player: "enterGame", - }, - forced: true, - filter: function (event, player) { - return event.name != "phase" || game.phaseNumber == 0; - }, - content: function () { - var cards = []; - for (var i = 0; i < ui.cardPile.childNodes.length; i++) { - var card = ui.cardPile.childNodes[i]; - if (card.name != "sha") cards.push(card); - if (cards.length >= 5) break; - } - if (cards.length) player.addToExpansion(cards, "gain2").gaintag.add("duwang"); - }, - marktext: "刺", - intro: { - name: "刺", - name2: "刺", - content: "expansion", - markcount: "expansion", - }, - mod: { - globalFrom: function (from, to, distance) { - return distance + Math.min(1, from.getExpansions("duwang").filter(i => i.name != "sha").length); - }, - globalTo: function (from, to, distance) { - return distance + Math.min(1, to.getExpansions("duwang").filter(i => i.name != "sha").length); - }, - }, - }, - cibei: { - audio: 2, - trigger: { global: "cardsDiscardAfter" }, - filter: function (event, player) { - if (!player.getExpansions("duwang").filter(i => i.name != "sha").length) return false; - var evt = event.getParent(); - if (evt.name != "orderingDiscard") return false; - var evtx = evt.relatedEvent || evt.getParent(); - return ( - evtx.name == "useCard" && - evtx.card.name == "sha" && - event.cards.filterInD("d").length && - game.hasPlayer2(current => - current.hasHistory("sourceDamage", evtxx => { - return evtxx.card == evtx.card; - }) - ) - ); - }, - direct: true, - group: "cibei_fullyReady", - content: function () { - "step 0"; - player.chooseButton(["###" + get.prompt("cibei") + '###
    将一张“刺”置入弃牌堆,并将' + get.translation(trigger.cards.filterInD("d")) + "置入“刺”
    ", player.getExpansions("duwang")]).set("filterButton", button => { - return button.link.name != "sha"; - }); - "step 1"; - if (result.bool) { - player.logSkill("cibei"); - player.loseToDiscardpile(result.links); - player.addToExpansion(trigger.cards.filterInD("d"), "gain2").gaintag.add("duwang"); - if (game.hasPlayer(current => current.countDiscardableCards(player, "hej") > 0)) - player - .chooseTarget("刺北:弃置一名角色区域内的一张牌", true, (card, player, target) => { - return target.countDiscardableCards(player, "hej") > 0; - }) - .set("ai", target => { - return get.effect(target, { name: "guohe" }, _status.event.player); - }); - } else event.finish(); - "step 2"; - if (result.bool) { - var target = result.targets[0]; - player.line(target); - player.discardPlayerCard(target, "hej", true); - player.addExpose(0.1); - } - }, - ai: { - combo: "duwang", - }, - subSkill: { - fullyReady: { - trigger: { global: "phaseEnd" }, - forced: true, - locked: false, - filter: function (event, player) { - var storage = player.getExpansions("duwang"); - return storage.length > 0 && storage.every(i => i.name == "sha"); - }, - content: function () { - player.gain(player.getExpansions("duwang"), "gain2").gaintag.add("cibei_mark"); - player.addSkill("cibei_mark"); - }, - }, - mark: { - trigger: { player: "useCard1" }, - onremove: true, - charlotte: true, - silent: true, - firstDo: true, - filter: function (event, player) { - return player.hasHistory("lose", evt => { - if (evt.getParent() != event) return false; - for (var i in evt.gaintag_map) { - if (evt.gaintag_map[i].includes("cibei_mark")) return true; - } - return false; - }); - }, - content: function () { - if (trigger.addCount !== false) { - trigger.addCount = false; - var stat = player.getStat().card, - name = trigger.card.name; - if (typeof stat[name] == "number") stat[name]--; - } - }, - mod: { - ignoredHandcard: function (card, player) { - if (card.hasGaintag("cibei_mark")) return true; - }, - cardDiscardable: function (card, player, name) { - if (card.hasGaintag("cibei_mark")) return false; - }, - canBeDiscarded: function (card) { - if (card.hasGaintag("cibei_mark")) return false; - }, - targetInRange: function (card, player, target) { - if (!card.cards) return; - for (var i of card.cards) { - if (i.hasGaintag("cibei_mark")) return true; - } - }, - cardUsable: function (card, player) { - if (!card.cards) return; - for (var i of card.cards) { - if (i.hasGaintag("cibei_mark")) return true; - } - }, - }, - }, - }, - }, - //武安国 - diezhang: { - audio: 2, - locked: false, - zhuanhuanji: function (player, skill) { - if (!player.storage.duanwan) player.storage[skill] = !player.storage[skill]; - }, - trigger: { global: ["eventNeutralized", "shaMiss"] }, - filter: function (event, player) { - if (player.hasSkill("diezhang_used")) return false; - if (event.type != "card") return false; - var evt = event._neutralize_event; - var user, responder; - if (event.name == "sha") { - user = event.player; - responder = event.target; - } else { - if (evt.type != "card") return false; - user = event.player; - responder = evt.player; - } - if (!player.storage.diezhang) { - if (user != player || responder == player) return false; - return player.countDiscardableCards(player, "he") > 0 && player.canUse("sha", responder, false); - } else { - if (user == player || responder != player) return false; - return player.canUse("sha", user, false); - } - }, - direct: true, - content: function () { - "step 0"; - var evt = trigger._neutralize_event; - var user, responder; - if (trigger.name == "sha") { - user = trigger.player; - responder = trigger.target; - } else { - user = trigger.player; - responder = evt.player; - } - var num = player.storage.duanwan ? 2 : 1; - event.num = num; - if (!player.storage.diezhang) { - var target = responder; - event.target = target; - var next = player - .chooseToDiscard(get.prompt("diezhang", target), "弃置一张牌,视为对其使用" + get.cnNumber(num) + "张【杀】", "he") - .set("ai", card => { - if (_status.event.goon) return 6 - get.value(card); - return 0; - }) - .set("logSkill", ["diezhang", target]); - } else { - var target = user; - event.target = target; - var next = player.chooseBool(get.prompt("diezhang", target), "摸" + get.cnNumber(num) + "张牌,视为对其使用一张【杀】").set("ai", () => _status.event.goon); - } - next.set("goon", get.effect(target, { name: "sha" }, player, player) > 0); - "step 1"; - if (result.bool) { - if (player.storage.duanwan) player.addTempSkill("diezhang_used"); - player.changeZhuanhuanji("diezhang"); - if (!result.cards || !result.cards.length) { - player.logSkill("diezhang", target); - player.draw(num, "nodelay"); - player.useCard({ name: "sha", isCard: true }, target, false); - } else while (num--) player.useCard({ name: "sha", isCard: true }, target, false); - } - }, - marktext: "☯", - mark: true, - intro: { - content: function (storage, player) { - var cnNum = get.cnNumber(player.storage.duanwan ? 2 : 1); - if (storage) return "当其他角色使用牌被你抵消后,你可以摸" + cnNum + "张牌,视为对其使用一张【杀】。"; - return "当你使用牌被其他角色抵消后,你可以弃置一张牌,视为对其使用" + cnNum + "张【杀】。"; - }, - }, - mod: { - cardUsable: function (card, player, num) { - if (!player.storage.duanwan && card.name == "sha") return num + 1; - }, - }, - subSkill: { used: { charlotte: true } }, - }, - duanwan: { - audio: 2, - enable: "chooseToUse", - skillAnimation: true, - animationColor: "soil", - limited: true, - filter: function (event, player) { - return event.type == "dying" && player == event.dying; - }, - content: function () { - player.changeZhuanhuanji("diezhang"); - player.awakenSkill("duanwan"); - var num = 2 - player.hp; - if (num > 0) player.recover(num); - }, - ai: { - save: true, - skillTagFilter: function (player, tag, target) { - return player == target; - }, - result: { player: 1 }, - }, - }, - //李婉 - liandui: { - audio: 2, - trigger: { global: "useCard" }, - filter: function (event, player) { - const history = game.getAllGlobalHistory("useCard"); - const index = history.indexOf(event); - if (index <= 0) return false; - const previous = history[index - 1].player; - if (event.player == player && previous != player && previous.isIn()) return true; - if (event.player != player && previous == player) return true; - return false; - }, - async cost(event, trigger, player) { - if (!trigger.player) return; - const history = game.getAllGlobalHistory("useCard"); - const index = history.indexOf(trigger); - const previous = history[index - 1].player; - const { result } = await trigger.player - .chooseBool("是否对" + get.translation(previous) + "发动【联对】?", "令" + get.translation(previous) + "摸两张牌") - .set("ai", () => _status.event.bool) - .set("bool", get.effect(previous, { name: "draw" }, trigger.player, trigger.player) > 0); - if (result.bool) event.result = { bool: true, cost_data: previous }; - }, - async content(event, trigger, player) { - const { cost_data: previous } = event; - previous.draw(2); - }, - }, - biejun: { - audio: 2, - global: "biejun_give", - trigger: { player: "damageBegin4" }, - filter: function (event, player) { - return ( - !player.hasSkill("biejun_used") && - player.countCards("h", card => { - return card.hasGaintag("biejun"); - }) == 0 - ); - }, - prompt2: "翻面并防止此伤害", - check: function (event, player) { - return player.isTurnedOver() || event.num >= player.hp || get.distance(_status.currentPhase, player, "absolute") >= 3; - }, - content: function () { - player.addTempSkill("biejun_used"); - player.turnOver(); - trigger.cancel(); - }, - ai: { - effect: { - target: function (card, player, target) { - if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; - if (get.tag(card, "damage")) { - if (player.getNext() == target && lib.skill.biejun.filter(null, target) && target.isTurnedOver()) return [0, 1]; - } - }, - }, - }, - subSkill: { - used: { charlotte: true }, - give: { - audio: 2, - enable: "phaseUse", - usable: 1, - filter: function (event, player) { - if (!player.countCards("h")) return false; - var targets = game.filterPlayer(function (current) { - return current != player && current.hasSkill("biejun"); - }); - if (!targets.length) return false; - return true; - }, - selectCard: 1, - filterCard: true, - filterTarget: function (card, player, target) { - return target.hasSkill("biejun"); - }, - selectTarget: function () { - var player = _status.event.player; - var targets = game.filterPlayer(function (current) { - return current != player && current.hasSkill("biejun"); - }); - return targets.length > 1 ? 1 : -1; - }, - complexSelect: true, - prompt: function () { - var player = _status.event.player; - var targets = game.filterPlayer(function (current) { - return current != player && current.hasSkill("biejun"); - }); - return "将一张手牌交给" + get.translation(targets) + (targets.length > 1 ? "中的一人" : ""); - }, - position: "h", - discard: false, - lose: false, - delay: false, - check: function (card) { - var player = _status.event.player; - if ( - game.hasPlayer(function (current) { - return lib.skill.biejun_give.filterTarget(null, player, current) && get.attitude(player, current) > 0; - }) - ) { - return 5 - get.value(card); - } - return -get.value(card); - }, - content: function () { - game.trySkillAudio("biejun", target); - player.give(cards, target).gaintag.add("biejun"); - target.addTempSkill("biejun_tag"); - }, - ai: { - order: 2, - result: { target: 1 }, - }, - }, - tag: { - charlotte: true, - forced: true, - onremove: function (player) { - player.removeGaintag("biejun"); - }, - }, - }, - }, - //诸葛尚 - sangu: { - audio: 2, - trigger: { player: "phaseJieshuBegin" }, - direct: true, - getEffect: function (player, target, event, list1, list2) { - let att = get.attitude(player, target); - if (att === 0) return 0; - let getv = function (name, player, arg) { - let v = event.getTempCache("sangu", player.id + name); - if (typeof v === "number") return v; - v = player.getUseValue({ name: name, storage: { sangu: true } }, arg); - event.putTempCache("sangu", player.id + name, v); - return v; - }; - if (att < 0) { - for (let i of list1) { - if (getv(i, target) <= 0 || getv(i, target) <= 0) return -att * Math.sqrt(get.threaten(target)) * 2; - } - return 0; - } else { - let list = list1.concat(player.hp > 1 ? list2 : []), - eff = 0; - list.sort(function (a, b) { - return getv(b, target) - getv(a, target); - }); - list = list.slice(3); - for (let i of list) { - let res = getv(i, target); - if (res <= 5) break; - else eff += res; - } - return Math.sqrt(eff / 1.5) * att; - } - }, - content: function () { - "step 0"; - event.list1 = []; - event.list2 = []; - event.used = []; - player.getHistory("useCard", function (evt) { - event.used.add(evt.card.name); - }); - for (let name of lib.inpile) { - let add = false, - type = get.type(name); - if (name === "sha") add = true; - else if (type === "trick") { - let info = lib.card[name]; - if (info && !info.singleCard && !info.notarget) add = true; - } - if (!add) continue; - if (event.used.includes(name)) event.list1.push(name); - else event.list2.push(name); - } - if (!event.list1.length && !event.list2.length) event.finish(); - else - player - .chooseTarget(get.prompt2("sangu"), lib.filter.notMe) - .set("ai", function (target) { - return lib.skill.sangu.getEffect(_status.event.player, target, _status.event.getTrigger(), _status.event.list1, _status.event.list2); - }) - .set("list1", event.list1) - .set("list2", event.list2); - "step 1"; - if (result.bool) { - var target = result.targets[0]; - player.logSkill("sangu", target); - event.target = target; - } else event.finish(); - "step 2"; - var dialog = ["为" + get.translation(target) + "选择至多三个牌名"]; - if (event.list1.length) { - dialog.push('
    本回合已使用过的牌
    '); - dialog.push([event.list1.map(i => [get.type(i), "", i]), "vcard"]); - } - if (event.list2.length) { - dialog.push('
    本回合未使用过的牌
    '); - dialog.push([event.list2.map(i => [get.type(i), "", i]), "vcard"]); - } - player - .chooseButton(dialog, true, [1, 3]) - .set("ai", function (button) { - let name = button.link[2], - list = _status.event.list, - player = _status.event.player, - target = _status.event.getParent().target, - trigger = _status.event.getTrigger(), - getv = (name, player) => { - let v = trigger.getTempCache("sangu", player.id + name); - if (typeof v === "number") return v; - v = player.getUseValue({ name: name, storage: { sangu: true } }); - trigger.putTempCache("sangu", player.id + name, v); - return v; - }; - if (get.attitude(player, target) < 0) { - if (!list.includes(name)) return 0; - return -getv(name, target); - } else { - if (player.hp < 2 && !list.includes(name)) return 0; - let val = getv(name, target), - base = 5; - val = Math.min(15, val - base); - if (name === "wuzhong" || name === "dongzhuxianji") val += 15; - else if (name === "shunshou") val += 6; - return val; - } - }) - .set("list", event.list1); - "step 3"; - if (result.bool) { - var names = result.links.map(i => i[2]); - if (!target.storage.sangu_effect) target.storage.sangu_effect = []; - target.storage.sangu_effect = target.storage.sangu_effect.concat(names); - game.log(player, "为", target, "选择了", "#y" + get.translation(names)); - target.addTempSkill("sangu_effect", { player: "phaseUseAfter" }); - target.markSkill("sangu_effect"); - var bool = true; - for (var i of names) { - if (!event.used.includes(i)) { - bool = false; - break; - } - } - if (bool) { - target.addTempSkill("sangu_prevent", { player: "phaseUseAfter" }); - target.markAuto("sangu_prevent", [player]); - } - } - }, - ai: { - effect: { - target: function (card, player, target, current) { - if (get.tag(card, "damage") && card.storage && card.storage.sangu) return "zeroplayertarget"; - }, - }, - }, - subSkill: { - effect: { - trigger: { player: "phaseUseBegin" }, - charlotte: true, - forced: true, - popup: false, - content: function () { - player.addTempSkill("sangu_viewas"); - }, - onremove: true, - intro: { - mark: function (dialog, storage, player) { - if (!storage || !storage.length) return "当前无可用牌"; - dialog.add([[storage[0]], "vcard"]); - if (storage.length > 1) dialog.addSmall([storage.slice(1), "vcard"]); - }, - content: "$", - }, - }, - viewas: { - mod: { - hiddenCard: function (player, name) { - var storage = player.getStorage("sangu_effect"); - if (storage.length) return name == storage[0]; - }, - cardname: function (card, player) { - if (_status.event.name != "chooseToUse" || _status.event.skill) return; - var storage = player.getStorage("sangu_effect"); - if (storage.length) return storage[0]; - }, - cardnature: function (card, player) { - if (_status.event.name != "chooseToUse" || _status.event.skill) return; - var storage = player.getStorage("sangu_effect"); - if (storage.length) return false; - }, - }, - trigger: { player: ["useCard", "respond"] }, - forced: true, - charlotte: true, - filter: function (event, player) { - return event.cards.length > 0 && player.getStorage("sangu_effect").length > 0; - }, - content: function () { - if (!trigger.card.storage) trigger.card.storage = {}; - trigger.card.storage.sangu = true; - player.unmarkAuto("sangu_effect", [player.getStorage("sangu_effect")[0]]); - }, - }, - prevent: { - trigger: { source: "damageBegin2" }, - forced: true, - charlotte: true, - onremove: true, - filter: function (event, player) { - return event.card && event.card.storage && event.card.storage.sangu && player.getStorage("sangu_prevent").includes(event.player); - }, - content: function () { - trigger.cancel(); - }, - }, - }, - }, - yizu: { - audio: 2, - trigger: { target: "useCardToTargeted" }, - forced: true, - usable: 1, - filter: function (event, player) { - return player.isDamaged() && player.hp <= event.player.hp && (event.card.name == "sha" || event.card.name == "juedou"); - }, - content: function () { - player.recover(); - }, - ai: { - effect: { - target_use(card, player, target, current) { - if (target.isHealthy() || (card.name != "sha" && card.name != "juedou")) return; - if (target.storage.counttrigger && target.storage.counttrigger.yizu && current < 0) return 5; - if (player.hp < target.hp) return; - if (current > 0) return 1.2; - if (get.attitude(player, target) >= 0) return; - var copy = get.effect(target, { name: "shacopy" }, player, player); - if ( - copy > 0 && - player.isPhaseUsing() && - Math.min( - player.getCardUsable("sha"), - player.countCards("hs", function (card) { - return get.name(card) == "sha" && player.canUse(card, target, null, true); - }) - ) >= 2 - ) - return; - return [0, 2]; - }, - }, - }, - }, - //轲比能 - kousheng: { - audio: 2, - trigger: { player: "phaseUseBegin" }, - direct: true, - filter: function (event, player) { - return player.countCards("h") > 0; - }, - content: function () { - "step 0"; - player - .chooseCard("h", [1, player.countCards("h")], get.prompt("kousheng"), "你可以选择任意张手牌,这些手牌于本回合内视为无次数限制的【杀】。但当有角色受到这些【杀】的伤害后,其可以用所有手牌交换剩余的牌。") - .set("standard", player.getUseValue({ name: "sha" }, null, true)) - .set("ai", function (card) { - var player = _status.event.player, - standard = _status.event.standard; - if (standard <= 0) return 0; - var eff = player.getUseValue(card, null, true); - if (eff <= standard) return standard - eff + 0.1; - return 0; - }); - "step 1"; - if (result.bool) { - player.logSkill("kousheng"); - player.addGaintag(result.cards, "kousheng"); - player.addTempSkill("kousheng_effect"); - game.delayx(); - } - }, - subSkill: { - effect: { - audio: "kousheng", - trigger: { player: "useCard1" }, - forced: true, - charlotte: true, - firstDo: true, - filter: function (event, player) { - if (event.card.name != "sha") return false; - return player.hasHistory("lose", function (evt) { - if (evt.getParent() != event) return false; - for (var i in evt.gaintag_map) { - if (evt.gaintag_map[i].includes("kousheng")) return true; - } - return false; - }); - }, - content: function () { - if (!trigger.card.storage) trigger.card.storage = {}; - trigger.card.storage.kousheng = true; - if (trigger.addCount !== false) { - trigger.addCount = false; - player.getStat("card").sha--; - } - }, - onremove: function (player) { - player.removeGaintag("kousheng"); - }, - mod: { - cardUsable: function (card, player, target) { - if (card.name != "sha" || !card.cards) return; - for (var i of card.cards) { - if (i.hasGaintag("kousheng")) return Infinity; - } - }, - cardname: function (card) { - if (get.itemtype(card) == "card" && card.hasGaintag("kousheng")) return "sha"; - }, - cardnature: function (card) { - if (get.itemtype(card) == "card" && card.hasGaintag("kousheng")) return false; - }, - }, - group: "kousheng_damage", - }, - damage: { - audio: "kousheng", - trigger: { source: "damageSource" }, - forced: true, - filter: function (event, player) { - if (!event.card || !event.card.storage || !event.card.storage.kousheng || event.getParent().type != "card") return false; - var target = event.player; - return ( - target.isIn() && - player.hasCard(function (card) { - return card.hasGaintag("kousheng"); - }, "h") - ); - }, - content: function () { - "step 0"; - var target = trigger.player; - event.target = target; - var cards = player.getCards("h", function (card) { - return card.hasGaintag("kousheng"); - }); - event.cards = cards; - var str = get.translation(player); - player.showCards(cards, str + "的【寇旌】牌"); - if (target.countCards("h") > 0) - target.chooseBool("是否交换“寇旌”牌?", "用你的所有手牌交换" + str + "的下列“寇旌”牌:" + get.translation(cards)).set("ai", function () { - var player = _status.event.player, - target = _status.event.getParent().player; - if (player.hasShan() || player.countCards("hs", { name: ["tao", "jiu"] }) > 0 || get.attitude(player, target) >= 0) return false; - var hs1 = player.getCards("h"), - hs2 = _status.event.getParent().cards; - if (hs2.length >= player.hp) return true; - if (get.value(hs1, player) >= get.value(hs2, target)) return false; - return true; - }); - else event.finish(); - "step 1"; - if (result.bool) { - player.swapHandcards(target, cards, target.getCards("h")); - } - }, - }, - }, - }, - //陆凯 - lkbushi: { - audio: 2, - getBushi: function (player) { - if (!player.storage.lkbushi) return ["spade", "heart", "club", "diamond"]; - return player.storage.lkbushi; - }, - onremove: true, - trigger: { player: "phaseZhunbeiBegin" }, - direct: true, - locked: false, - content: function () { - "step 0"; - var list = lib.skill.lkbushi.getBushi(player); - list = list.map(function (i) { - return ["", "", "lukai_" + i]; - }); - var next = player.chooseToMove("卜筮:是否调整〖卜筮〗的花色顺序?"); - next.set("list", [ - [ - "无次数限制/使用打出摸牌
    可弃牌无效/结束阶段获得", - [list, "vcard"], - function (list) { - var list2 = list.map(function (i) { - return get.translation(i[2].slice(6)); - }); - return "你使用" + list2[0] + "牌时无次数限制;使用或打出" + list2[1] + "时,摸一张牌;
    成为" + list2[2] + "牌目标后可弃一张牌无效;结束阶段获得一张" + list2[3] + "牌"; - }, - ], - ]); - next.set("processAI", function () { - var player = _status.event.player; - var list = lib.skill.lkbushi.getBushi(player); - var list2 = []; - var hs = player.getCards("hs", function (card) { - return player.hasValueTarget(card); - }); - list.sort(function (a, b) { - return hs.filter(i => get.suit(i) == b).length - hs.filter(i => get.suit(i) == a).length; - }); - list2.push(list.shift()); - hs = player.getCards("hs", "sha"); - list.sort(function (a, b) { - return hs.filter(i => get.suit(i) == b).length - hs.filter(i => get.suit(i) == a).length; - }); - list2.unshift(list.shift()); - list.randomSort(); - list2.addArray(list); - return [list2.map(i => ["", "", "lukai_" + i])]; - }); - "step 1"; - if (result.bool) { - var list = lib.skill.lkbushi.getBushi(player), - list2 = result.moved[0].map(function (i) { - return i[2].slice(6); - }); - for (var i = 0; i < 4; i++) { - if (list[i] != list2[i]) { - player.logSkill("lkbushi"); - player.storage.lkbushi = list2; - var str = "#g"; - for (var j = 0; j < 4; j++) { - str += get.translation(list2[j]); - if (j != 3) str += "/"; - } - game.log(player, "将", "#g【卜筮】", "的花色序列改为", str); - game.delayx(); - break; - } - } - } - }, - mark: true, - marktext: "筮", - intro: { - content: function (storage, player) { - var list = lib.skill.lkbushi.getBushi(player).map(i => get.translation(i)); - return "①你使用" + list[0] + "牌无次数限制。②当你使用或打出" + list[1] + "牌后,你摸一张牌。③当你成为" + list[2] + "牌的目标后,你可以弃置一张牌,令此牌对你无效。④结束阶段开始时,你从牌堆或弃牌堆获得一张" + list[3] + "牌。⑤准备阶段开始时,你可调整此技能中四种花色的对应顺序。"; - }, - }, - group: ["lkbushi_unlimit", "lkbushi_draw", "lkbushi_defend", "lkbushi_gain"], - subSkill: { - unlimit: { - mod: { - cardUsable: function (card, player) { - const list = lib.skill.lkbushi.getBushi(player), - suit = get.suit(card); - if (suit === "unsure" || list[0] === suit) return Infinity; - }, - }, - trigger: { player: "useCard1" }, - forced: true, - popup: false, - silent: true, - firstDo: true, - filter: function (event, player) { - if (event.addCount === false) return true; - var list = lib.skill.lkbushi.getBushi(player); - return list[0] == get.suit(event.card); - }, - content: function () { - trigger.addCount = false; - var stat = player.getStat().card, - name = trigger.card.name; - if (stat[name] && typeof stat[name] == "number") stat[name]--; - }, - }, - draw: { - audio: "lkbushi", - trigger: { player: ["useCard", "respond"] }, - forced: true, - locked: false, - filter: function (event, player) { - var list = lib.skill.lkbushi.getBushi(player); - return list[1] == get.suit(event.card); - }, - content: function () { - player.draw(); - }, - }, - defend: { - audio: "lkbushi", - trigger: { target: "useCardToTargeted" }, - direct: true, - filter: function (event, player) { - var list = lib.skill.lkbushi.getBushi(player); - return list[2] == get.suit(event.card) && !event.excluded.includes(player) && player.countCards("he") > 0; - }, - content: function () { - "step 0"; - player - .chooseToDiscard("he", get.prompt("lkbushi"), "弃置一张牌,令" + get.translation(trigger.card) + "对你无效") - .set("ai", function (card) { - if (_status.event.eff >= 0) return false; - return -_status.event.eff * 1.1 - get.value(card); - }) - .set("eff", get.effect(player, trigger.card, trigger.player, player)).logSkill = ["lkbushi_defend", trigger.player]; - "step 1"; - if (result.bool) { - trigger.excluded.add(player); - } - }, - }, - gain: { - audio: "lkbushi", - trigger: { player: "phaseJieshuBegin" }, - forced: true, - locked: false, - content: function () { - var list = lib.skill.lkbushi.getBushi(player); - var card = get.cardPile(function (card) { - return get.suit(card, false) == list[3]; - }); - if (card) player.gain(card, "gain2"); - }, - }, - }, - }, - lkzhongzhuang: { - audio: 2, - trigger: { source: ["damageBegin1", "damageBegin4"] }, - forced: true, - filter: function (event, player, name) { - if (!event.card || event.card.name != "sha" || event.getParent().type != "card") return false; - var range = player.getAttackRange(); - if (name == "damageBegin1") return range > 3; - return range < 3 && event.num > 1; - }, - content: function () { - if (event.triggername == "damageBegin1") trigger.num++; - else trigger.num = 1; - }, - global: "lkzhongzhuang_ai", - subSkill: { - ai: { - ai: { - filterDamage: true, - skillTagFilter: function (player, tag, arg) { - if (arg && arg.card && arg.card.name == "sha") { - if (arg.player && arg.player.hasSkill("lkzhongzhuang") && arg.player.getAttackRange() < 3) return true; - } - return false; - }, - }, - }, - }, - }, //顾雍 olbingyi: { audio: "bingyi", @@ -3076,13 +1135,12 @@ const skills = { }, xintaoluan: { hiddenCard: function (player, name) { - return !player.getStorage("xintaoluan").includes(name) && player.countCards("hes") > 0 && !player.hasSkill("xintaoluan3") && lib.inpile.includes(name); + return !player.getStorage("xintaoluan").includes(name) && player.countCards("hes") > 0 && lib.inpile.includes(name); }, audio: "taoluan", enable: "chooseToUse", filter: function (event, player) { return ( - !player.hasSkill("xintaoluan3") && player.hasCard(card => lib.inpile.some(name => { if (player.getStorage("xintaoluan").includes(name)) return false; @@ -3159,7 +1217,7 @@ const skills = { respondSha: true, respondShan: true, skillTagFilter: function (player, tag, arg) { - if (!player.countCards("hes") || player.hasSkill("taoluan3")) return false; + if (!player.countCards("hes") || player.isTempBanned("xintaoluan")) return false; if (tag == "respondSha" || tag == "respondShan") { if (arg == "respond") return false; return !player.getStorage("taoluan").includes(tag == "respondSha" ? "sha" : "shan"); @@ -3235,12 +1293,11 @@ const skills = { if (result.bool) { target.give(result.cards, player, "give"); } else { - player.addTempSkill("xintaoluan3"); + player.tempBanSkill("xintaoluan"); player.loseHp(num); } }, }, - xintaoluan3: { charlotte: true }, xintaoluan_backup: {}, xincaishi: { trigger: { @@ -4177,6 +2234,12 @@ const skills = { onCompare: function (player) { return game.cardsGotoOrdering(get.cards()).cards; }, + ai: { + forceWin: true, + skillTagFilter(player, tag, arg) { + return arg.card && get.suit(arg.card, false) == 'heart'; + }, + }, group: "tianbian_number", subSkill: { number: { @@ -4684,7 +2747,7 @@ const skills = { } } } - var next = player.chooseToMove("通博:是否交换“书”和手牌?").set("four", four).set("suits2", suits2).set("nofour", nofour); + var next = player.chooseToMove("通博:是否交换“书”和手牌?").set("four", four).set("nofour", nofour); next.set("list", [ [get.translation(player) + "(你)的“书”", expansions], ["你的牌", player.getCards("he")], @@ -5724,13 +3787,12 @@ const skills = { }, taoluan: { hiddenCard: function (player, name) { - return !player.getStorage("taoluan").includes(name) && player.countCards("hes") > 0 && !player.hasSkill("taoluan3") && lib.inpile.includes(name); + return !player.getStorage("taoluan").includes(name) && player.countCards("hes") > 0 && lib.inpile.includes(name); }, audio: 2, enable: "chooseToUse", filter: function (event, player) { return ( - !player.hasSkill("taoluan3") && player.hasCard(card => lib.inpile.some(name => { if (player.getStorage("taoluan").includes(name)) return false; @@ -5794,7 +3856,7 @@ const skills = { respondSha: true, respondShan: true, skillTagFilter: function (player, tag, arg) { - if (!player.countCards("hes") || player.hasSkill("taoluan3")) return false; + if (!player.countCards("hes") || player.isTempBanned("taoluan")) return false; if (tag == "respondSha" || tag == "respondShan") { if (arg == "respond") return false; return !player.getStorage("taoluan").includes(tag == "respondSha" ? "sha" : "shan"); @@ -5873,12 +3935,11 @@ const skills = { if (result.bool) { target.give(result.cards, player); } else { - player.addTempSkill("taoluan3"); + player.tempBanSkill("taoluan"); player.loseHp(); } }, }, - taoluan3: { charlotte: true }, taoluan_backup: {}, jishe: { audio: 2, @@ -6069,14 +4130,14 @@ const skills = { if (mode == "identity" && _status.mode == "purple") return false; }, getZhu: player => { - if (get.mode == "doudizhu") return game.findPlayer(i => i.identity == "zhu"); + if (get.mode() == "doudizhu") return game.findPlayer(i => i.identity == "zhu"); return get.zhu(player); }, trigger: { player: "phaseJieshuBegin" }, direct: true, filter: function (event, player) { var zhu = get.info("qinqing").getZhu(player); - if (!zhu || (get.mode != "doudizhu" && !zhu.isZhu)) return false; + if (!zhu || (get.mode() != "doudizhu" && !zhu.isZhu)) return false; return game.hasPlayer(function (current) { return current != zhu && current.inRange(zhu); }); @@ -6408,7 +4469,7 @@ const skills = { dialog: function (event, player) { var list = []; for (var i of lib.inpile) { - var type = get.type(i, false); + var type = get.type(i, null, false); if (type == "basic" || type == "trick") { var card = { name: i, @@ -6532,7 +4593,7 @@ const skills = { target: (card, player, target) => { if (!get.tag(card, "damage")) return; if (target.hp < 2 || player.hasSkillTag("jueqing", false, target)) return 1.5; - return [1, 1]; + return [1, 0.8]; }, }, }, @@ -7540,7 +5601,7 @@ const skills = { }, ai: { effect: { - player: function (card, player, target) { + player_use: function (card, player, target) { if (_status.currentPhase != player) return; if (card.name == "sha" && !player.needsToDiscard() && !player.getExpansions("chunlao").length && target.hp > 1) { return "zeroplayertarget"; @@ -8162,7 +6223,7 @@ const skills = { game.addGlobalSkill("longyin_order"); }, onremove: player => { - if (!game.hasPlayer(current => current.hasSkill("longyin"), true)) game.removeGlobalSkill("longyin_order"); + if (!game.hasPlayer(current => current.hasSkill("longyin", null, null, false), true)) game.removeGlobalSkill("longyin_order"); }, trigger: { global: "useCard" }, direct: true, @@ -8246,7 +6307,7 @@ const skills = { }, trigger: { player: "dieAfter" }, filter: (event, player) => { - return !game.hasPlayer(current => current.hasSkill("longyin"), true); + return !game.hasPlayer(current => current.hasSkill("longyin", null, null, false), true); }, silent: true, forceDie: true, @@ -8725,7 +6786,7 @@ const skills = { player.$throw(cardx, 1000, "nobroadcast"); }, target); if (player == game.me) { - await game.asyncDelay(0.5); + await game.delay(0.5); } } }; @@ -8982,9 +7043,70 @@ const skills = { group: ["zhanjue4"], ai: { damage: true, - order: 1, + order(item, player) { + if (player.countCards("h") > 1) return 0.8; + return 8; + }, + tag: { + respond: 2, + respondSha: 2, + damage: 1, + }, + result: { + player(player, target) { + let td = get.damageEffect(target, player, target); + if (!td) return 0; + let hs = player.getCards("h"), + val = hs.reduce((acc, i) => acc - get.value(i, player), 0) / 6 + 1; + if (td > 0) return val; + if (player.hasSkillTag( + "directHit_ai", + true, + { + target: target, + card: get.autoViewAs({ name: "juedou" }, hs), + } + )) return val; + let pd = get.damageEffect(player, target, player), + att = get.attitude(player, target); + if (att > 0 && get.damageEffect(target, player, player) > pd) return val; + let ts = target.mayHaveSha(player, "respond", null, "count"); + if (ts < 1 && ts * 8 < Math.pow(player.hp, 2)) return val; + let damage = pd / get.attitude(player, player), + ps = player.mayHaveSha(player, "respond", hs, "count"); + if (att > 0) { + if (ts < 1) return val; + return val + damage + 1; + } + if (pd >= 0) return val + damage + 1; + if (ts - ps + Math.exp(0.8 - player.hp) < 1) return val - ts; + return val + damage + 1 - ts; + }, + target(player, target) { + let td = get.damageEffect(target, player, target) / get.attitude(target, target); + if (!td) return 0; + let hs = player.getCards("h"); + if (td > 0 || player.hasSkillTag( + "directHit_ai", + true, + { + target: target, + card: get.autoViewAs({ name: "juedou" }, hs), + } + )) return td + 1; + let pd = get.damageEffect(player, target, player), + att = get.attitude(player, target); + if (att > 0) return td + 1; + let ts = target.mayHaveSha(player, "respond", null, "count"), + ps = player.mayHaveSha(player, "respond", hs, "count"); + if (ts < 1) return td + 1; + if (pd >= 0) return 0; + if (ts - ps < 1) return td + 1 - ts; + return -ts; + }, + }, effect: { - player: function (card, player, target) { + player_use: function (card, player, target) { if (_status.event.skill == "zhanjue") { if ( player.hasSkillTag( @@ -9381,97 +7503,6 @@ const skills = { }, }, }, - // taoxi:{ - // audio: "qingxi", - // trigger:{player:'useCardToPlayered'}, - // filter:function(event,player){ - // return _status.currentPhase==player&&event.targets.length==1&& - // event.target.countCards('h')>0&&!player.hasSkill('taoxi4')&&player!=event.target; - // }, - // check:function(event,player){ - // return get.attitude(player,event.target)<0; - // }, - // intro:{ - // content:'card' - // }, - // content:function(){ - // var card=trigger.target.getCards('h').randomGet(); - // player.showCards([card]); - // player.storage.taoxi=card; - // player.storage.taoxi2=trigger.target; - // player.syncStorage('taoxi'); - // player.markSkill('taoxi'); - // player.addTempSkill('taoxi4'); - // }, - // group:['taoxi2','taoxi3'] - // }, - // taoxi2:{ - // audio:false, - // enable:'phaseUse', - // filter:function(event,player){ - // if(player.storage.taoxi&&player.storage.taoxi2&& - // get.owner(player.storage.taoxi)==player.storage.taoxi2&& - // lib.filter.filterCard(player.storage.taoxi,player,event)){ - // return true; - // } - // return false; - // }, - // filterTarget:function(card,player,target){ - // return player.canUse(player.storage.taoxi,target); - // }, - // selectTarget:function(){ - // var info=get.info(_status.event.player.storage.taoxi); - // if(info.notarget) return -1; - // return get.select(info.selectTarget); - // }, - // multitarget:true, - // multiline:true, - // content:function(){ - // 'step 0' - // var card=player.storage.taoxi; - // if(!card){ - // event.finish(); - // return; - // } - // var owner=get.owner(card); - // if(owner){ - // owner.lose(card,ui.special); - // } - // event.card=card; - // player.$throw(card); - // 'step 1' - // player.useCard(event.card,targets).animate=false; - // delete player.storage.taoxi; - // delete player.storage.taoxi2; - // player.unmarkSkill('taoxi'); - // }, - // ai:{ - // order:8, - // result:{ - // target:function(player,target){ - // return get.effect(target,player.storage.taoxi,player,target); - // }, - // player:1 - // } - // } - // }, - // taoxi3:{ - // trigger:{player:'phaseJieshuBegin'}, - // forced:true, - // popup:false, - // filter:function(event,player){ - // return player.storage.taoxi?true:false; - // }, - // content:function(){ - // if(get.owner(player.storage.taoxi)==player.storage.taoxi2){ - // player.loseHp(); - // } - // delete player.storage.taoxi; - // delete player.storage.taoxi2; - // player.unmarkSkill('taoxi'); - // } - // }, - // taoxi4:{}, taoxi: { audio: "qingxi", trigger: { player: "useCardToPlayered" }, @@ -11121,7 +9152,7 @@ const skills = { }, ai: { effect: { - target_use(card, player, target) { + target(card, player, target) { if (get.type(card) == "trick" && player !== target) return [1, 1]; }, } @@ -11455,6 +9486,25 @@ const skills = { ai: { expose: 0.2, }, + global: "faen_global", + subSkill: { + global: { + ai: { + effect: { + target(card, player, target) { + if (card.name == "tiesuo" && !target.isLinked()) return [1, 0.6 * game.countPlayer(cur => { + return ( + cur.hasSkill("faen") || + cur.hasSkill("oldfaen") || + cur.hasSkill("refaen") || + cur.hasSkill("dcfaen") + ) && get.attitude(target, cur) > 0; + })]; + } + } + } + } + }, }, jiaojin: { audio: 2, @@ -11540,7 +9590,6 @@ const skills = { audio: 2, trigger: { player: "useCardToPlayer" }, filter: function (event, player) { - if (player.hasSkill("rechanhui2")) return false; if (event.targets.length > 1) return false; var card = event.card; if (card.name == "sha" || get.type(card) == "trick") return true; @@ -11583,12 +9632,10 @@ const skills = { } else { game.log(event.target, "成为了", trigger.card, "的额外目标"); trigger.getParent().targets.push(event.target); - player.addTempSkill("rechanhui2"); + player.tempBanSkill("rechanhui"); } }, }, - rechanhui2: { charlotte: true }, - rejiaojin2: { charlotte: true }, rejiaojin: { audio: 2, trigger: { target: "useCardToTargeted" }, @@ -11598,8 +9645,7 @@ const skills = { event.player != player && player.countCards("he", function (card) { return _status.connectMode || get.type(card) == "equip"; - }) && - !player.hasSkill("rejiaojin2") + }) ); }, direct: true, @@ -11622,7 +9668,7 @@ const skills = { var cards = trigger.cards.filterInD(); if (cards.length) player.gain(cards, "gain2", "log"); trigger.excluded.push(player); - if (trigger.player.hasSex("female")) player.addTempSkill("rejiaojin2"); + if (trigger.player.hasSex("female")) player.tempBanSkill("rejiaojin"); } }, }, @@ -12559,7 +10605,7 @@ const skills = { next.set("processAI", function (list) { var cards = list[0][1].slice(0), cards2 = cards.filter(function (i) { - return get.type(i, false) == "equip"; + return get.type(i, null, false) == "equip"; }), cards3; if (cards2.length) { @@ -12805,7 +10851,7 @@ const skills = { return arg && arg.jiu == true; }, effect: { - target_use(card, player, target) { + target(card, player, target) { if (target.hp <= 0 && target.hasSkill("zhenlie_lose") && get.tag(card, "recover")) return [1, 1.2]; }, }, @@ -12830,10 +10876,10 @@ const skills = { }, ai: { effect: { - target_use(card, player, target, current) { + target(card, player, target, current) { if (get.type(card) == "trick" && player != target) return "zeroplayertarget"; }, - player_use(card, player, target, current) { + player(card, player, target, current) { if (get.type(card) == "trick" && player != target) return "zeroplayertarget"; }, }, @@ -13007,24 +11053,21 @@ const skills = { }, ai: { effect: { - target_use(card, player, target) { + target(card, player, target) { if (player == target && get.subtypes(card).includes("equip2")) { if (get.equipValue(card) <= 8) return 0; } if (!player.hasEmptySlot(2)) return; - if (card.name == "sha" && get.color(card) == "black") return "zerotarget"; + if (card.name == "sha" && get.color(card) == "black") return "zeroplayertarget"; }, }, }, }, jueqing: { + audio: 2, + audioname: ["ol_zhangchunhua"], trigger: { source: "damageBefore" }, forced: true, - audio: 2, - //priority:16, - check: function () { - return false; - }, content: function () { trigger.cancel(); trigger.player.loseHp(trigger.num); @@ -13035,6 +11078,7 @@ const skills = { }, shangshi: { audio: 2, + audioname: ["ol_zhangchunhua"], trigger: { player: ["loseAfter", "changeHp", "gainMaxHpAfter", "loseMaxHpAfter"], global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], @@ -13131,7 +11175,7 @@ const skills = { }, jiushi: { audio: "jiushi1", - group: ["jiushi1", "jiushi2", "jiushi3"], + group: ["jiushi1", "jiushi3"], }, jiushi1: { audio: 2, @@ -13202,7 +11246,6 @@ const skills = { }, effect: { target: function (card, player, target) { - if (card.name == "guiyoujie") return [0, 0.5]; if (target.isTurnedOver()) { if (get.tag(card, "damage")) { if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; @@ -13214,17 +11257,6 @@ const skills = { }, }, }, - jiushi2: { - trigger: { player: "damageBegin3" }, - silent: true, - firstDo: true, - filter: function (event, player) { - return player.classList.contains("turnedover"); - }, - content: function () { - trigger.jiushi = true; - }, - }, jiushi3: { audio: "jiushi1", trigger: { player: "damageEnd" }, @@ -13752,7 +11784,8 @@ const skills = { group: ["enyuan1", "enyuan2"], }, enyuan1: { - audio: ["enyuan3.mp3", "enyuan4.mp3"], + audio: "enyuan", + logAudio: () => ["enyuan3.mp3", "enyuan4.mp3"], trigger: { player: "damageEnd" }, forced: true, filter: function (event, player) { @@ -13791,7 +11824,8 @@ const skills = { }, }, enyuan2: { - audio: ["enyuan1.mp3", "enyuan2.mp3"], + audio: "enyuan", + logAudio: () => ["enyuan1.mp3", "enyuan2.mp3"], trigger: { player: "recoverEnd" }, forced: true, logTarget: "source", @@ -14543,20 +12577,14 @@ const skills = { } }, intro: { - markcount: function (card, player) { - var num = get.number(card, player); - var list = [1, 11, 12, 13]; - if (list.includes(num)) return ["A", "J", "Q", "K"][list.indexOf(num)]; - return parseFloat(num); + markcount(card, player) { + return get.strNumber(get.number(card, player)); }, content: function (card, player) { var suit = get.suit(card, player); var num = get.number(card, player); var str = "
  • 上一张牌的花色:" + get.translation(suit); - str += "
  • 上一张牌的点数:"; - var list = [1, 11, 12, 13]; - if (list.includes(num)) str += ["A(1)", "J(11)", "Q(12)", "K(13)"][list.indexOf(num)]; - else str += parseFloat(num); + str += "
  • 上一张牌的点数:" + get.strNumber(num); return str; }, }, @@ -14769,6 +12797,17 @@ const skills = { combo: "zyexin", }, }, + _jiushi_check: { + trigger: { player: "damageBegin3" }, + silent: true, + firstDo: true, + filter: function (event, player) { + return player.classList.contains("turnedover"); + }, + content: function () { + trigger.jiushi = true; + }, + }, }; export default skills; diff --git a/character/yijiang/sort.js b/character/yijiang/sort.js index d8dcb2459c..2ff3306879 100644 --- a/character/yijiang/sort.js +++ b/character/yijiang/sort.js @@ -6,9 +6,6 @@ const characterSort = { yijiang_2015: ["caoxiu", "caorui", "zhongyao", "xiahoushi", "liuchen", "zhangyi", "zhuzhi", "quancong", "sunxiu", "gongsunyuan", "guotufengji"], yijiang_2016: ["guohuanghou", "sunziliufang", "huanghao", "liyan", "sundeng", "cenhun", "zhangrang", "liuyu"], yijiang_2017: ["xinxianying", "jikang", "wuxian", "qinmi", "xuezong", "xushi", "caiyong", "caojie"], - yijiang_2022: ["lukai", "kebineng", "zhugeshang", "liwan", "wuanguo", "hanlong", "yj_sufei", "yj_qiaozhou"], - yijiang_2023: ["xiahoumao", "chenshi", "sunli", "feiyao"], - yijiang_2024: ["linghuyu", "yj_simafu", "yj_xuangongzhu", "xukun"], }; const characterSortTranslate = { @@ -19,9 +16,6 @@ const characterSortTranslate = { yijiang_2015: "一将成名2015", yijiang_2016: "原创设计2016", yijiang_2017: "原创设计2017", - yijiang_2022: "原创设计2022", - yijiang_2023: "一将成名2023", - yijiang_2024: "一将成名2024", }; export { characterSort, characterSortTranslate }; diff --git a/character/yijiang/translate.js b/character/yijiang/translate.js index a820e53831..ef0fbff353 100644 --- a/character/yijiang/translate.js +++ b/character/yijiang/translate.js @@ -524,7 +524,7 @@ const translates = { jujian_info: "出牌阶段限一次,你可以弃至多三张牌,然后令一名其他角色摸等量的牌。若你以此法弃牌不少于三张且均为同一类别,你回复1点体力。", xinjujian_info: "结束阶段开始时,你可以弃置一张非基本牌并选择一名其他角色,令其选择一项:1.摸两张牌;2.回复1点体力;3.将其武将牌翻转至正面朝上并重置之。", luoying_info: "当其他角色的梅花牌因弃置或判定而进入弃牌堆后,你可以获得之。", - jiushi_info: "当你需要使用一张【酒】时,若你的武将牌正面朝上,则你可以将武将牌翻面并视为使用了一张【酒】;当你受到伤害时,若你的武将牌背面朝上,则你可在此伤害结算后将武将牌翻回正面。", + jiushi_info: "当你需要使用一张【酒】时,若你的武将牌正面朝上,则你可以将武将牌翻面并视为使用了一张【酒】;当你受到伤害后,若你的武将牌于受到伤害时背面向上,你可以翻面。", jueqing_info: "锁定技,你即将造成的伤害均视为失去体力。", shangshi_info: "当你的手牌数小于X时,你可以将手牌摸至X张(X为你已损失的体力值)。", xuanfeng_info: "当你失去装备区内的牌时,或于弃牌阶段弃置了两张或更多的手牌后,你可以依次弃置一至两名其他角色的共计两张牌。", @@ -545,7 +545,6 @@ const translates = { buyi_info: "当有角色进入濒死状态时,你可以展示该角色的一张手牌:若此牌不为基本牌,则该角色弃置此牌并回复1点体力。", mingce_info: "出牌阶段,你可以交给一名其他角色一张装备牌或【杀】,然后令该角色选择一项:1. 视为对其攻击范围内的另一名由你指定的角色使用一张【杀】。2. 摸一张牌。每回合限一次。", zhichi_info: "锁定技,当你于回合外受到伤害后,所有【杀】或普通锦囊牌对你无效直到回合结束。", - zhichi2_info: "智迟已发动", pojun_info: "当你使用【杀】造成伤害后,你可以令受伤角色摸X张牌,然后其翻面(X为该角色的体力值且至多为5)。", shiyong: "恃勇", shiyong_info: "锁定技,当你受到一次红色【杀】或【酒】【杀】造成的伤害后,须减1点体力上限。", @@ -578,83 +577,6 @@ const translates = { xinzhaofu_info: "主公技,限定技。出牌阶段,你可选择至多两名其他角色。这两名角色视为在所有其他吴势力角色的攻击范围内。", olbingyi: "秉壹", olbingyi_info: "每阶段限一次。当你因弃置而失去牌后,你可以展示所有手牌。若这些牌的颜色均相同,则你可以与至多X名其他角色各摸一张牌(X为你的手牌数)。", - lukai: "陆凯", - lukai_spade: "♠", - lukai_spade_bg: "♠️", - lukai_heart: "♥", - lukai_heart_bg: "♥️", - lukai_club: "♣", - lukai_club_bg: "♣", - lukai_diamond: "♦", - lukai_diamond_bg: "♦️️", - lkbushi: "卜筮", - lkbushi_info: "①你使用♠牌无次数限制。②当你使用或打出♥牌后,你摸一张牌。③当你成为♣牌的目标后,你可以弃置一张牌,令此牌对你无效。④结束阶段开始时,你从牌堆或弃牌堆获得一张♦牌。⑤准备阶段开始时,你可调整此技能中四种花色的对应顺序。", - lkzhongzhuang: "忠壮", - lkzhongzhuang_info: "锁定技。①当你因执行【杀】的效果而造成伤害时,若你的攻击范围大于3,则此伤害+1。②当一名角色受到你因执行【杀】的效果而造成的伤害时,若你的攻击范围小于3,则此伤害改为1。", - kebineng: "轲比能", - kousheng: "寇旌", - kousheng_info: "①出牌阶段开始时,你可以选择任意张手牌,这些牌称为“寇旌”直到回合结束。②你的“寇旌”均视为【杀】且无次数限制。③当你因执行对应实体牌包含“寇旌”的【杀】的效果而造成伤害后,你展示所有“寇旌”牌,然后目标角色可以用所有手牌交换这些牌。", - zhugeshang: "诸葛尚", - sangu: "三顾", - sangu_info: "结束阶段,你可以选择至多三个{【杀】或不为notarget或singleCard的普通锦囊牌}中的牌名,然后令一名其他角色记录这些牌名。该角色的下个出牌阶段开始时,其的手牌于其需要使用牌时均视为其记录中的第一张牌直到此阶段结束,且当其使用或打出有对应实体牌的牌时,移除这些牌中的第一张牌。若你以此法选择过的牌名均为你本回合内使用过的牌名,则防止你因其以此法使用牌造成的伤害。", - yizu: "轶祖", - yizu_info: "锁定技。每回合限一次,当你成为【杀】或【决斗】的目标后,若你的体力值不大于使用者的体力值,则你回复1点体力。", - liwan: "李婉", - liandui: "联对", - liandui_info: "①当你使用牌时,若本局游戏内上一张被使用的牌的使用者不为你,你可以令其摸两张牌。②其他角色使用牌时,若本局游戏内上一张被使用的牌的使用者为你,其可以令你摸两张牌。", - biejun: "别君", - biejun_info: "①其他角色的出牌阶段限一次。其可以将一张手牌交给你。②每回合限一次。当你受到伤害时,若你手牌中没有本回合因〖别君①〗得到的牌,你可以翻面并防止此伤害。", - yj_sufei: "苏飞", - shuojian: "数谏", - shuojian_info: "出牌阶段限三次。你可以交给一名其他角色一张牌,其选择一项:1.令你摸X张牌并弃置X-1张牌;2.视为使用X张【过河拆桥】,然后此技能本回合失效(X为此技能本阶段剩余发动次数+1)。", - yj_qiaozhou: "谯周", - shiming: "识命", - shiming_info: "每轮限一次。一名角色的摸牌阶段,你可以观看牌堆顶的三张牌,并可以将其中一张置于牌堆底。然后该角色可以改为对自己造成1点伤害,然后从牌堆底摸三张牌。", - jiangxi: "将息", - jiangxi_info: "一名角色的回合结束时,若一号位于此回合内进入过濒死状态或未受到过伤害,你可以重置〖识命〗并摸一张牌;若所有角色均未受到过伤害,你可以与当前回合角色各摸一张牌。", - hanlong: "韩龙", - duwang: "独往", - duwang_info: "锁定技。①游戏开始时,你从牌堆顶将五张不为【杀】的牌置于武将牌上,称为“刺”。②若你有牌名不为【杀】“刺”,你至其他角色或其他角色至你的距离+1。", - cibei: "刺北", - cibei_info: "①当一名角色使用【杀】造成伤害且此牌对应的实体牌进入弃牌堆后,你可以将一张不为【杀】的“刺”置入弃牌堆,并将这些牌置入“刺”,然后弃置一名角色区域里的一张牌。②一名角色的回合结束时,若你的“刺”均为【杀】,你获得所有“刺”,且这些牌不能被弃置,不计入手牌上限,且当你使用对应实体牌包含这些牌的牌时无次数和距离限制。", - wuanguo: "武安国", - diezhang: "叠嶂", - diezhang_info: "转换技。①出牌阶段,你使用【杀】的次数上限+1。②阴:当你使用牌被其他角色抵消后,你可以弃置一张牌,视为对其使用X张【杀】;阳:当其他角色使用牌被你抵消后,你可以摸X张牌,视为对其使用一张【杀】(X为1)。", - duanwan: "断腕", - duanwan_info: "限定技。当你处于濒死状态时,你可以将体力回复至2点,然后删除〖叠嶂①〗和当前转换技状态的〖叠嶂②〗分支,并将〖叠嶂〗修改为“每回合限一次”且将X修改为2。", - dcduliang: "督粮", - dcduliang2: "督粮", - dcduliang_info: "出牌阶段限一次。你可以获得一名其他角色的一张牌,然后选择一项:1.你观看牌堆顶的两张牌,然后令其获得其中的一或两张基本牌;2.令其于下回合的摸牌阶段额外摸一张牌。", - sunli: "孙礼", - kangli: "伉厉", - kangli_info: "当你造成或受到伤害后,你摸两张牌。然后你下次造成伤害时弃置这些牌。", - xiahoumao: "夏侯楙", - tongwei: "统围", - tongwei_info: "出牌阶段限一次。你可以重铸两张牌并指定一名其他角色,当其使用的下一张牌结算结束后,若此牌点数在你上次以此法重铸的牌的点数之间,你视为对其使用一张【杀】或【过河拆桥】。", - cuguo: "蹙国", - cuguo_info: "锁定技。当你于一回合使用牌首次被抵消后,你弃置一张牌,视为对此牌的目标角色使用一张该被抵消的牌。此牌结算结束后,若此牌被抵消,你失去1点体力。", - chenshi: "陈式", - qingbei: "擎北", - qingbei_info: "一轮游戏开始时,你可以选择任意种花色,你不能于本轮内使用这些花色的牌。然后当你于本轮使用一张有花色的牌结算结束后,你摸等同于你上一次〖擎北〗选择过的花色数的牌。", - feiyao: "费曜", - zhenfeng: "镇锋", - zhenfeng_info: "每回合限一次。当其他角色于其回合内使用牌时,若其手牌数不大于其体力值,你可以猜测其手牌中与此牌类别相同的牌数。若你猜对,你摸X张牌并视为对其使用一张【杀】(X为你连续猜对的次数且至多为5);若你猜错且差值大于1,其视为对你使用一张【杀】。", - linghuyu: "令狐愚", - yj_simafu: "司马孚", - yj_xuangongzhu: "宣公主", - xukun: "徐琨", - xvzhi: "蓄志", - xvzhi_info: "出牌阶段限一次,你可令两名角色各选择任意张手牌并交换这些牌,然后获得牌数较少的角色视为使用无视距离的【杀】;若获得牌数相等,你摸两张牌且可以对此阶段未以此法选择过的角色再发动一次〖蓄志〗。", - beiyu: "备预", - beiyu_info: "出牌阶段限一次,你可将手牌摸至体力上限,然后你将一种花色的所有手牌置于牌堆底。", - duchi: "督持", - duchi_info: "每回合限一次,当你成为其他角色使用牌的目标后,你可从牌堆底摸一张牌并展示所有手牌,若颜色均相同,则此牌对你无效。", - yjqimei: "齐眉", - yjqimei_info: "出牌阶段限一次,你可以选择一名其他角色,你与其各摸两张牌并弃置两张牌,然后你根据你与其弃置牌的花色总数执行以下效果:1、你依次使用这些弃置的牌中可以使用的牌;2、你与其复原武将牌;3、你与其横置武将牌;4、你与其各摸一张牌,然后你修改〖齐眉〗为“出牌阶段限两次”直到回合结束。", - yjzhuiji: "追姬", - yjzhuiji_info: "当你死亡时,你可以令一名角色从牌堆和弃牌堆中的随机使用任意装备牌直至其没有空置的装备栏。若如此做,当其失去以此法使用的装备牌后,其废除对应的装备栏。", - fazhu: "筏铸", - fazhu_info: "准备阶段,你可以重铸你的区域内任意张非伤害牌,然后将以此法获得的牌交给至多等量名角色各一张,这些角色可以依次使用一张无距离限制的【杀】。", }; export default translates; diff --git a/character/yijiang/voices.js b/character/yijiang/voices.js index 4c658aff22..89a0d0449d 100644 --- a/character/yijiang/voices.js +++ b/character/yijiang/voices.js @@ -1,59 +1,4 @@ export default { - "#zhenfeng1": "河西诸贼作乱,吾当驱万里之远。", - "#zhenfeng2": "可折诸葛之锋而御者,独我其谁。", - "#feiyao:die": "姜维,你果然是蜀军内应!", - // 击、逆、泰、每,懂? - "#fazhu1": "击风雨于共济,逆流亦溯千帆。", - "#fazhu2": "泰山轻于大义,每思志士、何惧临渊。", - "#fazhu3": "大江潮起,伐苇成舟,载江南春风。", - "#xukun:die": "何处射来的流矢?", - "#kangli1": "地界纷争皋陶难断,然图藏天府,坐上可明。", - "#kangli2": "正至歉岁,难征百姓于役,望陛下明鉴。", - "#sunli:die": "国无矩不立,何谓之方圆?", - "#tongwei1": "集关西诸路大军,必雪当年长坂坡之耻。", - "#tongwei2": "手织天网十万尺,欲擒飞龙落彀中。", - "#cuguo1": "身担父命,怎可蜷于宫阙。", - "#cuguo2": "体承国运,岂能缩居朝堂。", - "#xiahoumao:die": "一将无能,徒累死三军……", - "#qingbei1": "待追上那司马懿,定教他没好果子吃!", - "#qingbei2": "身若不周,吾一人可作擎北之柱。", - "#chenshi:die": "丞相、丞相!是魏延指使我的!", - "#diezhang1": "某家这大锤,舞起来那叫一个万夫莫敌。", - "#diezhang2": "贼吕布何在?某家来取汝性命了!", - "#duanwan1": "好你个吕奉先,竟敢卸我膀子!", - "#duanwan2": "汝这匹夫,为何往手腕上招呼?", - "#wuanguo:die": "吕奉先,你给某家等着!", - "#duwang1": "此去,欲诛敌莽、杀单于。", - "#duwang2": "风萧萧兮易水寒,壮士一去兮不复还!", - "#cibei1": "匹夫一怒,流血二人,天下缟素。", - "#cibei2": "我欲效专诸、聂政之旧事,逐天狼于西北。", - "#hanlong:die": "杀轲比能者,韩龙也!", - "#shiming1": "今天命在北,我等已尽人事。", - "#shiming2": "益州国疲民敝,非人力可续之。", - "#jiangxi1": "典午忽兮,月酉没兮。", - "#jiangxi2": "周慕孔子遗风,可与刘、扬同轨。", - "#yj_qiaozhou:die": "炎汉百年之业,吾一言毁之……", - "#shuojian1": "我数荐卿而祖不用,其之失也。", - "#shuojian2": "兴霸乃当世豪杰,何患无爵。", - "#yj_sufei:die": "兴霸何在?吾命休矣……", - "#liandui1": "以句相联,抒离散之苦。", - "#liandui2": "以诗相对,颂哀怨之情。", - "#biejun1": "彼岸荼蘼远,落寞北风凉。", - "#biejun2": "此去经年,不知何时能归?", - "#liwan:die": "生不能同寝,死亦难同穴……", - "#sangu1": "思报君恩,尽父子之忠。", - "#sangu2": "欲酬三顾,竭三代之力。", - "#yizu1": "仿祖父行事,可阻敌袭。", - "#yizu2": "习先人故智,可御寇侵。", - "#zhugeshang:die": "父子荷国重恩,当尽忠以报!", - "#kousheng1": "驰马掠野,塞外称雄。", - "#kousheng2": "控弦十万,纵横漠南。", - "#kebineng:die": "草原雄鹰,折翼于此……", - "#lkbushi1": "论演玄意,以筮辄验。", - "#lkbushi2": "手不释书,好研经卷。", - "#lkzhongzhuang1": "秽尘天听,卿有不测之祸!", - "#lkzhongzhuang2": "倾乱国政,安得寿终正寝?", - "#lukai:die": "不听忠言,国将亡矣……", "#xinxuanhuo1": "收人钱财,替人消灾。", "#xinxuanhuo2": "哼,叫你十倍奉还!", "#xinenyuan1": "报之以李,还之以桃。", @@ -265,9 +210,11 @@ export default { "#qinwang11": "国有危难,哪位将军请战?", "#qinwang12": "大厦倾危,谁堪栋梁!", "#liuchen:die": "无言对百姓,有愧,见先祖……", - "#wurong1": "兵不血刃,亦可先声夺人。", - "#wurong2": "从则安之,犯则诛之。", - "#zhangyi:die": "大丈夫当战死沙场,马革裹尸而还……", + "#wurong1": "兵不血刃,亦可先声夺人!", + "#wurong2": "从,则安之;犯,则诛之。", + "#shizhi1": "捐躯赴难,视死如归。", + "#shizhi2": "矢志于国,至死不渝。", + "#zhangyi:die": "大丈夫当战死沙场,马革裹尸而还。", "#yanzhu1": "大局已定,你还是放弃吧。", "#yanzhu2": "不诛此权臣,朕,何以治天下?", "#xingxue1": "文修武备,才是兴国之道。", diff --git a/character/yingbian/character.js b/character/yingbian/character.js index 097dc1f60f..1dcfcd5480 100644 --- a/character/yingbian/character.js +++ b/character/yingbian/character.js @@ -1,16 +1,16 @@ const characters = { - chengjichengcui: ["male", "jin", 6, ["oltousui", "olchuming"],['name:成|济-成|倅']], + chengjichengcui: ["male", "jin", 6, ["oltousui", "olchuming"], ["name:成|济-成|倅"]], wangxiang: ["male", "jin", 3, ["bingxin"]], jin_jiachong: ["male", "jin", 3, ["xiongshu", "jianhui"]], - xuangongzhu: ["female", "jin", 3, ["gaoling", "qimei", "ybzhuiji"], ["hiddenSkill", 'name:司马|null']], + xuangongzhu: ["female", "jin", 3, ["gaoling", "qimei", "ybzhuiji"], ["hiddenSkill", "name:司马|null"]], xinchang: ["male", "jin", 3, ["canmou", "congjian"]], yangzhi: ["female", "jin", 3, ["xinwanyi", "maihuo"]], yangyan: ["female", "jin", 3, ["xinxuanbei", "xianwan"]], ol_huaxin: ["male", "wei", 3, ["caozhao", "olxibing"]], zhongyan: ["female", "jin", 3, ["bolan", "yifa"], ["clan:颍川钟氏"]], weiguan: ["male", "jin", 3, ["zhongyun", "shenpin"]], - cheliji: ["male", "qun", 4, ["chexuan", "qiangshou"], ['name:彻里|吉']], - simazhou: ["male", "jin", 4, ["recaiwang", "naxiang"], ['name:司马|伷']], + cheliji: ["male", "qun", 4, ["chexuan", "qiangshou"], ["name:彻里|吉"]], + simazhou: ["male", "jin", 4, ["recaiwang", "naxiang"], ["name:司马|伷"]], ol_lisu: ["male", "qun", 3, ["qiaoyan", "xianzhu"]], jin_yanghuiyu: ["female", "jin", 3, ["huirong", "ciwei", "caiyuan"], ["hiddenSkill"]], shibao: ["male", "jin", 4, ["zhuosheng"]], @@ -18,9 +18,9 @@ const characters = { jin_simayi: ["male", "jin", 3, ["buchen", "smyyingshi", "xiongzhi", "xinquanbian"], ["hiddenSkill", "name:司马|懿"]], jin_wangyuanji: ["female", "jin", 3, ["shiren", "yanxi"], ["hiddenSkill"]], jin_simazhao: ["male", "jin", 3, ["tuishi", "xinchoufa", "zhaoran", "chengwu"], ["zhu", "hiddenSkill", "name:司马|昭"]], - jin_xiahouhui: ["female", "jin", 3, ["baoqie", "jyishi", "shiduo"], ["hiddenSkill","name:夏侯|徽"]], + jin_xiahouhui: ["female", "jin", 3, ["baoqie", "jyishi", "shiduo"], ["hiddenSkill", "name:夏侯|徽"]], jin_simashi: ["male", "jin", "3/4", ["taoyin", "yimie", "ruilve", "tairan"], ["hiddenSkill", "zhu", "name:司马|师"]], - zhanghuyuechen: ["male", "jin", 4, ["xijue"], ['name:张|虎-乐|綝']], + zhanghuyuechen: ["male", "jin", 4, ["xijue"], ["name:张|虎-乐|綝"]], duyu: ["male", "jin", 4, ["sanchen", "zhaotao"]], }; diff --git a/character/yingbian/characterReplace.js b/character/yingbian/characterReplace.js index a633c0ba03..a4fc937349 100644 --- a/character/yingbian/characterReplace.js +++ b/character/yingbian/characterReplace.js @@ -1,9 +1,11 @@ const characterReplaces = { - yanghu: ["jin_yanghu", "dc_yanghu", "sp_yanghu", "std_dc_yanghu"], - jiachong: ["dc_jiachong", "jin_jiachong", "jiachong"], + jin_yanghu: ["jin_yanghu", "dc_yanghu", "sp_yanghu", "std_dc_yanghu"], + jiachong: ["dc_jiachong", "jin_jiachong", "jiachong", "mb_jiachong"], yangyan: ["yangyan", "old_yangyan"], yangzhi: ["yangzhi", "old_yangzhi"], zhongyan: ["zhongyan", "clan_zhongyan"], + simazhou: ["simazhou", "mb_simazhou"], + jin_xiahouhui: ["jin_xiahouhui", "jd_jin_xiahouhui"], }; export default characterReplaces; diff --git a/character/yingbian/skill.js b/character/yingbian/skill.js index 2edf22d2b8..8bdc5912aa 100644 --- a/character/yingbian/skill.js +++ b/character/yingbian/skill.js @@ -387,7 +387,7 @@ const skills = { audio: "wanyi", trigger: { player: "useCardToTargeted" }, filter: function (event, player) { - return player != event.target && event.targets.length == 1 && (event.card.name == "sha" || get.type(event.card, false) == "trick") && event.target.countCards("he") > 0; + return player != event.target && event.targets.length == 1 && (event.card.name == "sha" || get.type(event.card, null, false) == "trick") && event.target.countCards("he") > 0; }, locked: false, logTarget: "target", @@ -957,15 +957,7 @@ const skills = { trigger: { player: "showCharacterAfter" }, hiddenSkill: true, filter: function (event, player) { - return ( - event.toShow.some(name => { - return get.character(name, 3).includes("gaoling"); - }) && - player != _status.currentPhase && - game.hasPlayer(function (current) { - return current.isDamaged(); - }) - ); + return event.toShow?.some(i => get.character(i).skills?.includes("gaoling")) && player != _status.currentPhase && game.hasPlayer(current => current.isDamaged()); }, direct: true, content: function () { @@ -1494,7 +1486,7 @@ const skills = { return player.countCards("j") == 1; }, effect: { - target: function (card, player, target, current) { + target_use: function (card, player, target, current) { if (card && (card.name == "shandian" || card.name == "fulei") && player == target && !target.countCards("j") && target.isPhaseUsing() && target.hasValueTarget({ name: "sha" }, null, true)) return [1, 2]; }, }, @@ -1904,7 +1896,7 @@ const skills = { hiddenSkill: true, filter: function (event, player) { var target = _status.currentPhase; - return event.toShow.includes("jin_simayi") && target && target != player && target.countGainableCards(player, "he") > 0; + return event.toShow?.some(i => get.character(i).skills?.includes("buchen")) && target && target != player && target.countGainableCards(player, "he") > 0; }, direct: true, content: function () { @@ -2314,7 +2306,7 @@ const skills = { }, }, ai: { - combo: "chexuan" + combo: "chexuan", }, }, cheliji_sichengliangyu: { @@ -2554,8 +2546,7 @@ const skills = { forced: true, filter: function (event, player) { return ( - event.toShow && - event.toShow.includes("jin_yanghuiyu") && + event.toShow?.some(i => get.character(i).skills?.includes("huirong")) && game.hasPlayer(function (target) { var num = target.countCards("h"); return num > target.hp || num < Math.min(5, target.hp); @@ -2590,7 +2581,7 @@ const skills = { game.addGlobalSkill("ciwei_ai"); }, onremove: () => { - if (!game.hasPlayer(i => i.hasSkill("ciwei"), true)) game.removeGlobalSkill("ciwei_ai"); + if (!game.hasPlayer(i => i.hasSkill("ciwei", null, null, false), true)) game.removeGlobalSkill("ciwei_ai"); }, trigger: { global: "useCard" }, direct: true, @@ -2652,7 +2643,7 @@ const skills = { }, trigger: { player: "dieAfter" }, filter: () => { - return !game.hasPlayer(i => i.hasSkill("ciwei"), true); + return !game.hasPlayer(i => i.hasSkill("ciwei", null, null, false), true); }, silent: true, forceDie: true, @@ -2926,7 +2917,7 @@ const skills = { mod: { cardEnabled2: function (card, player) { var stat = player.getStat("skill"); - if (stat.xinquanbian && stat.xinquanbian >= player.maxHp && get.position(card) == "h" && get.type(card, player) != "equip") return false; + if (stat.xinquanbian && stat.xinquanbian >= player.maxHp && get.position(card) == "h" && get.type(card, null, player) != "equip") return false; }, }, }, @@ -2939,7 +2930,7 @@ const skills = { }, filter: function (event, player) { var target = _status.currentPhase; - return target && target != player && target.isAlive(); + return player != target && target && target.isAlive() && event.toShow?.some(i => get.character(i).skills?.includes("taoyin")); }, check: function (event, player) { return get.attitude(player, _status.currentPhase) < 0; @@ -3126,7 +3117,7 @@ const skills = { forced: true, hiddenSkill: true, filter: function (event, player) { - return event.toShow && event.toShow.includes("jin_xiahouhui"); + return event.toShow?.some(i => get.character(i).skills?.includes("baoqie")); }, content: function () { "step 0"; @@ -3240,7 +3231,7 @@ const skills = { hiddenSkill: true, filter: function (event, player) { var target = _status.currentPhase; - return player != target && target && target.isAlive() && event.toShow && event.toShow.includes("jin_simazhao"); + return player != target && target && target.isAlive() && event.toShow?.some(i => get.character(i).skills?.includes("tuishi")); }, content: function () { player.addTempSkill("tuishi2"); @@ -3502,7 +3493,7 @@ const skills = { return _status.currentPhase; }, filter: function (event, player) { - if (!event.toShow || !event.toShow.includes("jin_wangyuanji")) return false; + if (!event.toShow?.some(i => get.character(i).skills?.includes("shiren"))) return false; var target = _status.currentPhase; return target && target != player && target.isAlive() && target.countCards("h") > 0; }, @@ -3693,7 +3684,7 @@ const skills = { pozhu: { enable: "phaseUse", viewAsFilter: function (player) { - return !player.hasSkill("pozhu3", null, null, false) && player.countCards("hs") > 0; + return player.countCards("hs") > 0; }, viewAs: { name: "chuqibuyi" }, filterCard: true, @@ -3716,10 +3707,9 @@ const skills = { ); }, content: function () { - player.addTempSkill("pozhu3"); + player.tempBanSkill("pozhu"); }, }, - pozhu3: { charlotte: true }, xijue: { audio: 2, trigger: { @@ -3728,13 +3718,18 @@ const skills = { }, forced: true, filter: function (event, player) { - if (player._xijue) return false; - if (get.mode() == "guozhan") return event.name == "showCharacter" && event.toShow && event.toShow.includes("gz_zhanghuyuechen"); + if (get.mode() == "guozhan") + return ( + game + .getAllGlobalHistory("everything", evt => { + return evt.name == "showCharacter" && evt.toShow?.some(i => get.character(i).skills?.includes("xijue")); + }) + .indexOf(event) == 0 + ); return event.name != "showCharacter" && (event.name != "phase" || game.phaseNumber == 0); }, content: function () { player.addMark("xijue", 4); - player._xijue = true; }, intro: { name2: "爵", @@ -3833,7 +3828,7 @@ const skills = { } var next = player.chooseToDiscard(`是否弃置一枚“爵”和一张${get.mode() == "guozhan" ? "基本" : "手"}牌,对${get.translation(trigger.player)}发动【骁果】?`, "h", function (card, player) { if (get.mode() != "guozhan") return true; - return get.type(card, player) == "basic"; + return get.type(card, null, player) == "basic"; }); next.set("ai", function (card) { if (_status.event.nono) return 0; @@ -3953,7 +3948,7 @@ const skills = { forced: true, hiddenSkill: true, filter: function (event, player) { - return event.toShow.includes("jin_zhangchunhua") && player != _status.currentPhase; + return event.toShow?.some(i => get.character(i).skills?.includes("xuanmu")) && player != _status.currentPhase; }, content: function () { player.addTempSkill("xuanmu2"); diff --git a/character/yxs.js b/character/yxs.js index a601bcef1d..c1fb32dede 100644 --- a/character/yxs.js +++ b/character/yxs.js @@ -48,91 +48,49 @@ game.import("character", function () { yxs_lanlinwang: ["male", "shu", 4, ["guimian", "lyuxue"], ["name:高|肃"]], }, characterIntro: { - yxs_qinqiong: - "秦琼(?—638年),字叔宝,齐州历城(今山东济南市)人,隋末唐初名将。初为隋将,先后在来护儿、张须陀、裴仁基帐下任职,因勇武过人而远近闻名。后随裴仁基投奔瓦岗军领袖李密,瓦岗败亡后转投王世充,因见王世充为人奸诈,与程咬金等人一起投奔李唐。投唐后随李世民南征北战,是一个能在万马军中取敌将首级的勇将,但也因此浑身是伤。唐统一后,秦琼久病缠身,于贞观十二年(638)病逝。生前官至左武卫大将军、翼国公,死后追赠为徐州都督、胡国公,谥曰“壮”。贞观十七年被列入凌烟阁二十四功臣。", - yxs_wuzetian: - "中国历史上唯一一个正统的女皇帝,也是继位年龄最大的皇帝(67岁即位),又是寿命最长的皇帝之一(终年82岁)。唐高宗时为皇后(655—683)、唐中宗和唐睿宗时为皇太后(683—690),后自立为武周皇帝(690—705),改国号“唐”为“周”,定都洛阳,并号其为“神都”。史称“武周”或“南周”,705年退位。武则天也是一位女诗人和政治家。", - yxs_caocao: - " 曹操(155年7月18日-220年3月15日),字孟德,一名吉利,小字阿瞒,汉族,沛国谯(今安徽省亳州市)人。曹操生于宦官之家,适逢乱世,但是胸怀大志,参与剿灭董卓战争,之后在官渡大败袁绍,占据北方,挟天子以令诸侯。最后兵败赤壁,与吴,蜀三分天下。", - yxs_mozi: - " 宋国大夫,名翟,鲁人(今山东滕州人)。墨子是我国战国时期著名的思想家、教育家、科学家、军事家、社会活动家,墨家学派的创始人。墨子曾阻止鲁阳文君攻郑,说服公输般而止楚攻宋。楚惠王打算以书社封墨子,越王也打算以吴之地方五百里以封墨子,但墨子都没有接受。其创立墨家学说,并有《墨子》一书传世。", - yxs_bole: - "伯乐,名孙阳,字子良,一作王良。春秋齐(今山东省威武)人。善于相马,为赵简子御。相传天上御者名伯乐,因其善相,遂号之,传至今。初,见老骥 拖车,喘息不定,伯乐哀之,马亦哀啼,方知乃良驹。后世长以伯乐比喻慧眼识人者。", - yxs_aijiyanhou: - "埃及艳后即克丽奥佩托拉七世,是古埃及托勒密王朝的最后一任法老。她通过政治联姻为古埃及赢取了22年的和平。埃及艳后的一生富有戏剧性,特别是卷入罗马共和末期的政治漩涡,同恺撒、安东尼关系密切,并伴以种种传闻逸事,使她成为文学和艺术作品中的著名人物。", - yxs_diaochan: - "中国古代四大美女之一,今山西忻州人,有野史说其姓霍,无名,又有一说称其任姓,小字红昌。貂蝉是东汉末年司徒王允的义女,国色天香,有倾国倾城之貌,相传貂婵在后花园拜月时,忽然轻风吹来,一块浮云将那皎洁的明月遮住。这时正好王允瞧见,便说我的女儿和月亮比美,月亮比不过,赶紧躲在云彩后面。此后,世人常用“闭月”来形容貂婵的美貌。", - yxs_yangyuhuan: - "唐朝贵妃,名玉环,字太真,蒲州永乐人(今山西永济)。杨玉环自小习音律,善歌舞,姿色超群。27岁时,得唐玄宗宠幸,召入宫中,封为贵妃。杨贵妃天生丽质,回眸一笑百媚生,六宫粉黛无颜色,堪称大唐第一美女,此后千余年无出其右者。其与西施、昭君、貂蝉并称中国古代四大美女。", - yxs_baosi: - "褒姒,周幽王姬宫涅的王后,褒姒原是一名弃婴,被一对做小买卖的夫妻收养,在褒国(今陕西省汉中西北)长大,公元前七七九年(周幽王三年),周幽王征伐有褒国,褒人献出美女褒姒乞降,幽王爱如掌上明珠,立为妃,宠冠周王宫,翌年,褒姒生子伯服(一作伯般),幽王对她更加宠爱,竟废去王后申氏和太子宜臼,册立褒姒为王后,立伯服为太子,周太史伯阳叹气道:“周王室已面临大祸,这是不可避免的了。”", - yxs_napolun: - "法兰西第一共和国执政、法兰西第一帝国皇帝,出生在法国科西嘉岛,是一位卓越的军事天才。他多次击败保王党的反扑和反法同盟的入侵,捍卫了法国大革命的成果。他颁布的《民法典》更是成为了后世资本主义国家的立法蓝本。他执政期间多次对外扩张,形成了庞大的帝国体系,创造了一系列军事奇迹。", + yxs_qinqiong: "秦琼(?—638年),字叔宝,齐州历城(今山东济南市)人,隋末唐初名将。初为隋将,先后在来护儿、张须陀、裴仁基帐下任职,因勇武过人而远近闻名。后随裴仁基投奔瓦岗军领袖李密,瓦岗败亡后转投王世充,因见王世充为人奸诈,与程咬金等人一起投奔李唐。投唐后随李世民南征北战,是一个能在万马军中取敌将首级的勇将,但也因此浑身是伤。唐统一后,秦琼久病缠身,于贞观十二年(638)病逝。生前官至左武卫大将军、翼国公,死后追赠为徐州都督、胡国公,谥曰“壮”。贞观十七年被列入凌烟阁二十四功臣。", + yxs_wuzetian: "中国历史上唯一一个正统的女皇帝,也是继位年龄最大的皇帝(67岁即位),又是寿命最长的皇帝之一(终年82岁)。唐高宗时为皇后(655—683)、唐中宗和唐睿宗时为皇太后(683—690),后自立为武周皇帝(690—705),改国号“唐”为“周”,定都洛阳,并号其为“神都”。史称“武周”或“南周”,705年退位。武则天也是一位女诗人和政治家。", + yxs_caocao: " 曹操(155年7月18日-220年3月15日),字孟德,一名吉利,小字阿瞒,汉族,沛国谯(今安徽省亳州市)人。曹操生于宦官之家,适逢乱世,但是胸怀大志,参与剿灭董卓战争,之后在官渡大败袁绍,占据北方,挟天子以令诸侯。最后兵败赤壁,与吴,蜀三分天下。", + yxs_mozi: " 宋国大夫,名翟,鲁人(今山东滕州人)。墨子是我国战国时期著名的思想家、教育家、科学家、军事家、社会活动家,墨家学派的创始人。墨子曾阻止鲁阳文君攻郑,说服公输般而止楚攻宋。楚惠王打算以书社封墨子,越王也打算以吴之地方五百里以封墨子,但墨子都没有接受。其创立墨家学说,并有《墨子》一书传世。", + yxs_bole: "伯乐,名孙阳,字子良,一作王良。春秋齐(今山东省威武)人。善于相马,为赵简子御。相传天上御者名伯乐,因其善相,遂号之,传至今。初,见老骥 拖车,喘息不定,伯乐哀之,马亦哀啼,方知乃良驹。后世长以伯乐比喻慧眼识人者。", + yxs_aijiyanhou: "埃及艳后即克丽奥佩托拉七世,是古埃及托勒密王朝的最后一任法老。她通过政治联姻为古埃及赢取了22年的和平。埃及艳后的一生富有戏剧性,特别是卷入罗马共和末期的政治漩涡,同恺撒、安东尼关系密切,并伴以种种传闻逸事,使她成为文学和艺术作品中的著名人物。", + yxs_diaochan: "中国古代四大美女之一,今山西忻州人,有野史说其姓霍,无名,又有一说称其任姓,小字红昌。貂蝉是东汉末年司徒王允的义女,国色天香,有倾国倾城之貌,相传貂婵在后花园拜月时,忽然轻风吹来,一块浮云将那皎洁的明月遮住。这时正好王允瞧见,便说我的女儿和月亮比美,月亮比不过,赶紧躲在云彩后面。此后,世人常用“闭月”来形容貂婵的美貌。", + yxs_yangyuhuan: "唐朝贵妃,名玉环,字太真,蒲州永乐人(今山西永济)。杨玉环自小习音律,善歌舞,姿色超群。27岁时,得唐玄宗宠幸,召入宫中,封为贵妃。杨贵妃天生丽质,回眸一笑百媚生,六宫粉黛无颜色,堪称大唐第一美女,此后千余年无出其右者。其与西施、昭君、貂蝉并称中国古代四大美女。", + yxs_baosi: "褒姒,周幽王姬宫涅的王后,褒姒原是一名弃婴,被一对做小买卖的夫妻收养,在褒国(今陕西省汉中西北)长大,公元前七七九年(周幽王三年),周幽王征伐有褒国,褒人献出美女褒姒乞降,幽王爱如掌上明珠,立为妃,宠冠周王宫,翌年,褒姒生子伯服(一作伯般),幽王对她更加宠爱,竟废去王后申氏和太子宜臼,册立褒姒为王后,立伯服为太子,周太史伯阳叹气道:“周王室已面临大祸,这是不可避免的了。”", + yxs_napolun: "法兰西第一共和国执政、法兰西第一帝国皇帝,出生在法国科西嘉岛,是一位卓越的军事天才。他多次击败保王党的反扑和反法同盟的入侵,捍卫了法国大革命的成果。他颁布的《民法典》更是成为了后世资本主义国家的立法蓝本。他执政期间多次对外扩张,形成了庞大的帝国体系,创造了一系列军事奇迹。", kaisa: "凯撒是罗马共和国末期杰出的军事统帅、政治家。他公元前60年与庞培、克拉苏秘密结成前三巨头同盟,随后出任高卢总督,在大约8年的时间内征服了高卢全境(今法国一带),还袭击了日耳曼和不列颠。前49年,他率军占领罗马,打败庞培,集大权于一身,实行独裁统治并制定了《儒略历》。", - yxs_zhuyuanzhang: - " 朱元璋,明王朝的开国皇帝。原名重八,后取名兴宗。汉族,濠州(今安徽凤阳县东)钟离太平乡人。朱元璋自幼贫寒,父母兄长均死于瘟疫,孤苦无依,入皇觉寺为小沙弥,入寺不到二个月,因荒年寺租难收,寺主封仓遣散众僧,只得离乡为游方僧,后参加了起义军,并改名“朱元璋”意为诛(朱)灭元朝的璋(璋,古代的一种玉器)。25岁时参加郭子兴领导的红巾军反抗蒙元暴政,在郭子兴手下,率兵出征,有攻必克;因此郭便把养女马氏嫁与了他。元至正二十八年(1368),在基本击破各路农民起义军和扫平元的残余势力后,于南京称帝,国号大明,年号洪武,建立了全国统一的封建政权。朱元璋统治时期被称为“洪武之治”。葬于明孝陵。", - yxs_jinke: - "荆轲,喜好读书击剑,为人慷慨侠义。后游历到燕国,被称为“荆卿”(或荆叔),随之由燕国智勇深沉的“节侠”田光推荐给太子丹,拜为上卿。秦国灭赵后,兵锋直指燕国南界,太子丹震惧,与田光密谋,决定派荆轲入秦行刺秦王。荆轲献计太子丹,拟以秦国叛将樊于期之头及燕督亢(今河北涿县、易县、固安一带,是一块肥沃的土地)地图进献秦王,相机行刺。太子丹不忍杀樊于期,荆轲只好私见樊于期,告以实情,樊于期为成全荆轲而自刎。", - yxs_libai: - "字太白,号青莲居士,又号“谪仙人”,祖籍陇西郡成纪县(今甘肃省平凉市静宁县南)。李白是唐朝著名的浪漫主义诗人,有“诗仙”之称。李白生平作诗无数,存世诗文达千余篇之多,《蜀道难》、《行路难》、《梦游天姥吟留别》、《将进酒》等诗篇脍炙人口,妇孺皆知,另有《李太白集》传世。", - yxs_luban: - " 鲁班,姓公输,名般。战国时期鲁国公族之后,故又称公输子、班输等。出身于工匠世家,是我国古代最著名的发明家、建筑家。鲁班一生发明无数,而最具贡献意义的则要数木工使用的工具,诸如墨斗、锯、和鲁班尺等。为后世的建筑学提供了最基础的工具。除此之外,相传石磨、云梯等工具也是鲁班发明。", - yxs_lvzhi: - " 吕雉,西汉开国皇帝高祖刘邦的原配夫人,中国历史上第一位掌权的女性统治者,是历史上有记载以来的第一位皇后、皇太后。于高祖刘邦死后掌握政权,实行高祖的“黄老政治”,百姓安乐民富国强,为“文景之治”奠定了坚实的基础。", - yxs_goujian: - "勾践,又写作句践,在出土文物“越王勾践剑”里写为鸠浅,司马贞《史记索隐》引《纪年》作菼执。是中国春秋时代后期的越国君主。有关他的先世,有说“其先禹之苗裔”,亦有说“先世无所考”,也有说他是“祝融之后”并且是楚国的芈姓,众说纷纭。父亲则是越侯允常。", - yxs_lishimin: - " 李世民,唐朝第二位皇帝。他的前半生是立下赫赫武功的军事家。平窦建德、王世充之后,始大量接触文学与书法,有《温泉铭》、《晋祠铭》等墨宝传世。后在玄武门之变杀死自己的兄弟李建成、李元吉两人,成为太子,唐高祖不久被迫让位。世民即位为帝后,积极听取群臣的意见、努力学习文治天下,成功转型为中国史上最出名的政治家与明君之一。唐太宗开创了历史上的“贞观之治”,经过主动消灭群雄割据势力,虚心纳谏、在国内厉行节约、使百姓休养生息,终于使得社会出现了国泰民安的局面。此举为后来的开元盛世奠定了重要的基础,将中国传统农业社会推向一个高峰。", - yxs_huamulan: - " 花木兰是中国文学作品中的一位代父从军的巾帼英雄,其真实性不详。花木兰最早出现于南北朝一首叙事诗《木兰辞》中,该诗约作于北魏,最初录于南朝陈的《古今乐录》,僧人智匠在《古今乐录》称:“木兰不知名。”", - yxs_luobinhan: - "罗宾汉是英国民间传说中的侠盗式的一个英雄人物,人称汉丁顿伯爵。他武艺出众、机智勇敢、聪明,仇视官吏和教士,是一位劫富济贫、行侠仗义的绿林英雄。传说他住在诺丁汉雪伍德森林。从14世纪中叶起,关于罗宾汉的民谣和传说就开始在民间流传。罗宾汉最突出的就是射箭术高超。现代射箭比赛里就有“罗宾汉”这一术语,指射中另一支已中靶心的箭。", - yxs_chengjisihan: - "成吉思汗,名铁木真,孛儿只斤氏,奇渥温姓,乞颜(起延)部人。从小遭受结拜兄弟札木合迫害,形成刚毅坚韧的性格。1206年,被推举为蒙古帝国的大汗,统一蒙古各部,为之后的进攻中原提供了坚实的基础。", - yxs_mingchenghuanghou: - "明成皇后,朝鲜近代史上的女政治家,本名闵兹映,通称闵妃,是朝鲜京畿道骊州郡人。她是朝鲜王朝高宗李熙的王妃,骊兴闵氏外戚集团的核心人物,19世纪末朝鲜的实际统治者。由于闵妃早期主张开放、后期力抗日本并身死殉难,故深受后世韩国人民的尊崇。 1897年,高宗李熙改国号称“大韩帝国”,追谥闵妃为“孝慈元圣正化合天明成皇后”,故现今韩国史学家多称她为“明成皇后”。", - yxs_wangzhaojun: - "王昭君,名嫱,字昭君,晋朝时为避司马昭讳,又称“明妃”,汉元帝时期宫女,汉族,西汉南郡秭归(今湖北省兴山县)人。匈奴呼韩邪单于阏氏。 “昭君出塞”是汉匈交往上的大事,稳定了汉朝和匈奴的外交关系,《汉书.匈奴传》和《后汉书.南匈奴传》都记载了这件事。相传和亲途中,南飞的大雁听到昭君奏起悲壮的离别之曲,看到骑在马上的这位美丽女子,忘记摆动翅膀,跌落地下,因此得“落雁”之名。昭君出塞的故事也被后世传为佳话。", - yxs_luocheng: - "《隋唐》说书和《说唐传》中的虚构人物,隋唐十八杰中列第七,十六杰列第八。在清初禇人获的讲史小说《隋唐演义》中,也虚构了罗成,是燕山罗艺的儿子,秦琼的表弟,精通枪法。", - yxs_direnjie: - "唐武周时期杰出的著名政治家,时任豫州刺史、魏州刺史等要职,官至凤阁鸾台平章事、内史,卒后追封梁国公。狄仁杰生于贞观、卒于武周时期,经历了大唐鼎盛和动乱的年代。其一生秉承了以民为本、不畏权贵、为民请命的宗旨。狄仁杰通晓了吏治、兵刑等法律制度,在任大理丞任期内解决了诸多案件,被誉为“神探”。狄仁杰为官清廉,素有政绩,有辅国安邦之能,史称“唐室砥柱”。", - yxs_sunwu: - "著名军事家,字长卿,中国春秋时期齐国乐安人。曾率领吴国军队大破数倍于己的楚国军队,占领了楚国都城郢城,几乎亡楚。其著有巨作《孙子兵法》十三篇,为后世兵法家所推崇,被誉为“兵学圣典”,置于《武经七书》之首,被译为英文、法文、德文、日文,成为国际间最著名的兵学典范之书。后人尊称其为孙子、孙武子、兵圣、百世兵家之师、东方兵学的鼻祖。", - yxs_chengyaojin: - "程咬金,原名咬金,后更名知节,字义贞,中国济州东阿斑鸠店人(现山东省东平县斑鸠店)。“凌烟阁二十四功臣”之一,唐朝开国名将。隋朝末年,隋炀帝杨广统治残暴,骄奢荒淫,民不聊生,最终爆发了大规模的农民起义。程咬金先入瓦岗军,投王世充,后降唐,成为秦王李世民的骨干成员。据史书记载,程咬金“少骁勇,善用马槊。”而在以《说唐》为代表的系列话本及历史演义小说中,程咬金则使得一柄八卦宣花斧,以“三板斧”武艺著称,是一名性格直爽、粗中有细的福将。", - yxs_yujix: - "虞姬,又称虞美人,西楚霸王项羽爱姬,相传为江苏沭阳县颜集乡人,一说苏州常熟人。公元前209年,项羽与叔父项梁起义反秦。项羽军中战将虞子期的妹妹虞姬,貌美好武,倾慕年轻勇猛的项羽,嫁其为妾,常伴左右随军出征,至终形影不离。 公元前202年,项羽在垓下之战中被刘邦、韩信、彭越三方大军合围困于垓下(今安徽灵璧县城南沱河北岸城后村),身陷十面埋伏,兵孤粮缺,夜闻四面楚歌,楚军士气尽失。项羽认为大势已去,帐中酌酒,对着虞姬唱起悲壮的“垓下歌”。虞姬拔剑起舞,含泪唱和:“汉兵已略地,四面楚歌声。大王义气尽,贱妾何聊生。”为免后顾之忧影响项羽突围,唱毕于其面前自刎。", - yxs_xiangyu: - "项籍(前232—前202)字羽,通常被称作项羽,中国古代著名将领及政治人物,汉族,秦下相(今江苏省宿迁市宿城区)人。秦末时被楚怀王熊心封为鲁公,在前207年的决定性战役巨鹿之战中统率楚军大破秦军。秦亡后自封“西楚霸王”,统治黄河及长江下游的梁楚九郡。后在楚汉战争中为汉高祖刘邦所败,在乌江(今安徽和县)自刎而死。", - yxs_yingzheng: - "秦始皇,赢姓,赵氏,名政,秦庄襄王之子。秦始皇22岁时,在雍城举行国君成人加冕仪式,开始“亲理朝政”。后除掉吕不韦,嫪毐等人,重用李斯,尉缭。自公元前230年至前221年,采取由近及远,集中力量,各个击破的策略,先后灭六国,完成统一中国的大业。同时建立起历史上第一个书同文,度同制,车同轨,行同伦的中央集权国家——秦朝。", - yxs_yuefei: - " 岳飞(1103年-1142年),字鹏举,相州汤阴(今属河南)人。南宋军事家,中国历史上著名的抗金名将。绍兴十一年(1142)十二月二十九日,秦桧以“莫须有”的罪名将岳飞毒死于临安风波亭。1162年,宋孝宗时诏复官,谥武穆,宁宗时追封为鄂王,改谥忠武,有《岳武穆集》传世。", - yxs_fuermosi: - "福尔摩斯,是一个虚构的侦探人物,是由19世纪末20世纪初的英国侦探小说家阿瑟?柯南·道尔所塑造的一个才华横溢的侦探形象。福尔摩斯不但头脑冷静、观察力敏锐、推理能力极强;而且,他的剑术、拳术和小提琴演奏水平也相当高超,已经成为侦探小说中的典型代表人物之一。", - yxs_guiguzi: - "本名王诩,春秋时纵横家,卫国(今河南鹤壁一带)人。曾隐于清溪鬼谷,常入云梦采药修道,弟子无数。有张仪、苏秦、孙膑、庞涓四弟子。精于兵法、奇门遁甲、五行八卦之学。后人称之为王禅老祖。今传《鬼谷子》十四篇。", - yxs_xiaoqiao: - "小乔,庐江皖县(今安徽潜山)人。 史书中称小桥,是中国汉末三国时期的女性, 乔公的次女,东吴名将周瑜的妻子。传说与其姐大乔均为绝世美女。合称“二乔”。", - yxs_luzhishen: - "鲁智深,梁山泊第十三位好汉,十员步军头领第一名。鲁智深原名鲁达,绰号花和尚。是经略的提辖,因为见郑屠欺侮金翠莲父女,三拳打死了镇关西。被官府追捕,逃到五台山削发为僧,改名鲁智深。", - yxs_zhaoyong: - "赵武灵王,战国中后期赵国君主,嬴姓,赵氏,名雍。赵武灵王在位时,推行的“胡服骑射”政策,赵国因而得以强盛,灭中山国,败林胡、楼烦二族,辟云中、雁门、代三郡,并修筑了“赵长城”。", - yxs_yangguang: - "隋炀帝杨广,是隋朝第二代皇帝,华阴(今陕西华阴)人,生于隋京师长安。杨广在位期间修建大运河,营建东都迁都洛阳城,开创科举制度,亲征吐谷浑,三征高句丽。但因为杨广滥用民力,导致了隋朝的灭亡,618年在江都被部下缢杀。", - yxs_tangbohu: - "唐伯虎,名寅,字伯虎,自号六如居士,明代诗人、画家,吴县(今江苏苏州)人。出身富商家庭,后家道衰落,因祝枝山之劝而潜心读书。公试时为状元,会试时候因科场舞弊案牵连而被斥为吏。后绝意仕途,以卖画为生。唐伯虎为人玩世不恭而又才气横溢,诗文擅名,与祝枝山、文征明、徐祯卿并称“江南四大才子”,画名更著,与沈周、文征明、仇英并称“吴门四家”。民间盛传其点秋香的故事。", - yxs_zhangsanfeng: - "明朝最著名的武术家、道士。原名张通,字君宝,在武当山开山立派,成为武当派开山祖师。明英宗赐号“通微显化真人”;明宪宗特封号为“韬光尚志真仙”;明世宗赠封他为“清虚元妙真君”。传说其丰姿魁伟,大耳圆目,须髯如戟。无论寒暑,只一衲一蓑,一餐能食升斗,或数日一食,或数月不食,事能前知。其在武术上的造诣和超乎寻常的长寿都为后人称道。 曾传洪武年间,两度受朱元璋诏请入京,皆避而不见。其与明初巨贾沈万三亦有交际。其所创太极拳一直延续至今,成为后人养身妙术。", - yxs_nandinggeer: - "出生于意大利,英国护士和统计学家。她谙熟数学,精通英、法、德、意四门语言,除古典文学外,还精于自然科学、历史和哲学,擅长音乐与绘画。在德国学习护理后,曾往伦敦的医院工作。南丁格尔于1854年和38位护士到克里米亚野战医院工作,成为该院的护士长,被称为“克里米亚的天使”又称“提灯女神”。1860年6月15日,南丁格尔在伦敦成立世界第一所护士学校。为了纪念她的成就,1912年,国际护士会倡仪各国医院和护士学校定每年5月12日南丁格尔诞辰日举行纪念活动,并将5月12日定为“国际护士节”,以缅怀和纪念这位伟大的女性。", - yxs_weizhongxian: - "魏忠贤(1568年-1627年12月11日),字完吾,北直隶肃宁(今河北沧州肃宁县)人,汉族,原名李进忠。由才人王氏复姓,出任秉笔太监后,改名魏忠贤。明朝末期宦官。明熹宗时期,出任司礼秉笔太监,极受宠信,被称为“九千九百岁”,排除异己,专断国政,以致人们“只知有忠贤,而不知有皇上”。朱由检继位后,打击惩治阉党,治魏忠贤十大罪,命逮捕法办,自缢而亡,其余党亦被肃清。", - yxs_meixi: - '妺喜,姓嬉(喜),生卒年不详,亦作妺嬉、末喜、末嬉,有施氏之女,夏朝最后一位君主夏桀的王后。根据先秦时代记述女子名时所用的全称和简称方式,妺喜应姓喜,即嬉(也作僖)。由于其名字的“妺”字与“妹妹”的“妹”字字形相似,且在《庄子》等作中也有以妺为妹的用法,因此常误作"妹喜"。', - yxs_lanlinwang: - "高长恭(541年―573年),又名高孝瓘、高肃,祖籍渤海调蓨(今河北省景县),神武帝高欢之孙,文襄帝高澄第四子,生母不详,南北朝时期北齐宗室、将领,封爵兰陵郡王。高长恭貌柔心壮,音容兼美。为将躬勤细事,每得甘美,虽一瓜数果,必与将士分享。累次升任至并州刺史。突厥攻入晋阳,高长恭奋力将其击退。邙山之战,高长恭为中军,率领五百骑兵再入周军包围圈,直至金墉城下,因高长恭戴着头盔,城中的人不确定是敌军或是我军,直到高长恭把头盔脱下来城上的人才知道是高长恭,派弓箭手开始放箭保护他,之后高长恭成功替金墉解围,高长恭在此次战中威名大振,士兵们为此战而讴歌他,即后来知名的《兰陵王入阵曲》。", + yxs_zhuyuanzhang: " 朱元璋,明王朝的开国皇帝。原名重八,后取名兴宗。汉族,濠州(今安徽凤阳县东)钟离太平乡人。朱元璋自幼贫寒,父母兄长均死于瘟疫,孤苦无依,入皇觉寺为小沙弥,入寺不到二个月,因荒年寺租难收,寺主封仓遣散众僧,只得离乡为游方僧,后参加了起义军,并改名“朱元璋”意为诛(朱)灭元朝的璋(璋,古代的一种玉器)。25岁时参加郭子兴领导的红巾军反抗蒙元暴政,在郭子兴手下,率兵出征,有攻必克;因此郭便把养女马氏嫁与了他。元至正二十八年(1368),在基本击破各路农民起义军和扫平元的残余势力后,于南京称帝,国号大明,年号洪武,建立了全国统一的封建政权。朱元璋统治时期被称为“洪武之治”。葬于明孝陵。", + yxs_jinke: "荆轲,喜好读书击剑,为人慷慨侠义。后游历到燕国,被称为“荆卿”(或荆叔),随之由燕国智勇深沉的“节侠”田光推荐给太子丹,拜为上卿。秦国灭赵后,兵锋直指燕国南界,太子丹震惧,与田光密谋,决定派荆轲入秦行刺秦王。荆轲献计太子丹,拟以秦国叛将樊于期之头及燕督亢(今河北涿县、易县、固安一带,是一块肥沃的土地)地图进献秦王,相机行刺。太子丹不忍杀樊于期,荆轲只好私见樊于期,告以实情,樊于期为成全荆轲而自刎。", + yxs_libai: "字太白,号青莲居士,又号“谪仙人”,祖籍陇西郡成纪县(今甘肃省平凉市静宁县南)。李白是唐朝著名的浪漫主义诗人,有“诗仙”之称。李白生平作诗无数,存世诗文达千余篇之多,《蜀道难》、《行路难》、《梦游天姥吟留别》、《将进酒》等诗篇脍炙人口,妇孺皆知,另有《李太白集》传世。", + yxs_luban: " 鲁班,姓公输,名般。战国时期鲁国公族之后,故又称公输子、班输等。出身于工匠世家,是我国古代最著名的发明家、建筑家。鲁班一生发明无数,而最具贡献意义的则要数木工使用的工具,诸如墨斗、锯、和鲁班尺等。为后世的建筑学提供了最基础的工具。除此之外,相传石磨、云梯等工具也是鲁班发明。", + yxs_lvzhi: " 吕雉,西汉开国皇帝高祖刘邦的原配夫人,中国历史上第一位掌权的女性统治者,是历史上有记载以来的第一位皇后、皇太后。于高祖刘邦死后掌握政权,实行高祖的“黄老政治”,百姓安乐民富国强,为“文景之治”奠定了坚实的基础。", + yxs_goujian: "勾践,又写作句践,在出土文物“越王勾践剑”里写为鸠浅,司马贞《史记索隐》引《纪年》作菼执。是中国春秋时代后期的越国君主。有关他的先世,有说“其先禹之苗裔”,亦有说“先世无所考”,也有说他是“祝融之后”并且是楚国的芈姓,众说纷纭。父亲则是越侯允常。", + yxs_lishimin: " 李世民,唐朝第二位皇帝。他的前半生是立下赫赫武功的军事家。平窦建德、王世充之后,始大量接触文学与书法,有《温泉铭》、《晋祠铭》等墨宝传世。后在玄武门之变杀死自己的兄弟李建成、李元吉两人,成为太子,唐高祖不久被迫让位。世民即位为帝后,积极听取群臣的意见、努力学习文治天下,成功转型为中国史上最出名的政治家与明君之一。唐太宗开创了历史上的“贞观之治”,经过主动消灭群雄割据势力,虚心纳谏、在国内厉行节约、使百姓休养生息,终于使得社会出现了国泰民安的局面。此举为后来的开元盛世奠定了重要的基础,将中国传统农业社会推向一个高峰。", + yxs_huamulan: " 花木兰是中国文学作品中的一位代父从军的巾帼英雄,其真实性不详。花木兰最早出现于南北朝一首叙事诗《木兰辞》中,该诗约作于北魏,最初录于南朝陈的《古今乐录》,僧人智匠在《古今乐录》称:“木兰不知名。”", + yxs_luobinhan: "罗宾汉是英国民间传说中的侠盗式的一个英雄人物,人称汉丁顿伯爵。他武艺出众、机智勇敢、聪明,仇视官吏和教士,是一位劫富济贫、行侠仗义的绿林英雄。传说他住在诺丁汉雪伍德森林。从14世纪中叶起,关于罗宾汉的民谣和传说就开始在民间流传。罗宾汉最突出的就是射箭术高超。现代射箭比赛里就有“罗宾汉”这一术语,指射中另一支已中靶心的箭。", + yxs_chengjisihan: "成吉思汗,名铁木真,孛儿只斤氏,奇渥温姓,乞颜(起延)部人。从小遭受结拜兄弟札木合迫害,形成刚毅坚韧的性格。1206年,被推举为蒙古帝国的大汗,统一蒙古各部,为之后的进攻中原提供了坚实的基础。", + yxs_mingchenghuanghou: "明成皇后,朝鲜近代史上的女政治家,本名闵兹映,通称闵妃,是朝鲜京畿道骊州郡人。她是朝鲜王朝高宗李熙的王妃,骊兴闵氏外戚集团的核心人物,19世纪末朝鲜的实际统治者。由于闵妃早期主张开放、后期力抗日本并身死殉难,故深受后世韩国人民的尊崇。 1897年,高宗李熙改国号称“大韩帝国”,追谥闵妃为“孝慈元圣正化合天明成皇后”,故现今韩国史学家多称她为“明成皇后”。", + yxs_wangzhaojun: "王昭君,名嫱,字昭君,晋朝时为避司马昭讳,又称“明妃”,汉元帝时期宫女,汉族,西汉南郡秭归(今湖北省兴山县)人。匈奴呼韩邪单于阏氏。 “昭君出塞”是汉匈交往上的大事,稳定了汉朝和匈奴的外交关系,《汉书.匈奴传》和《后汉书.南匈奴传》都记载了这件事。相传和亲途中,南飞的大雁听到昭君奏起悲壮的离别之曲,看到骑在马上的这位美丽女子,忘记摆动翅膀,跌落地下,因此得“落雁”之名。昭君出塞的故事也被后世传为佳话。", + yxs_luocheng: "《隋唐》说书和《说唐传》中的虚构人物,隋唐十八杰中列第七,十六杰列第八。在清初禇人获的讲史小说《隋唐演义》中,也虚构了罗成,是燕山罗艺的儿子,秦琼的表弟,精通枪法。", + yxs_direnjie: "唐武周时期杰出的著名政治家,时任豫州刺史、魏州刺史等要职,官至凤阁鸾台平章事、内史,卒后追封梁国公。狄仁杰生于贞观、卒于武周时期,经历了大唐鼎盛和动乱的年代。其一生秉承了以民为本、不畏权贵、为民请命的宗旨。狄仁杰通晓了吏治、兵刑等法律制度,在任大理丞任期内解决了诸多案件,被誉为“神探”。狄仁杰为官清廉,素有政绩,有辅国安邦之能,史称“唐室砥柱”。", + yxs_sunwu: "著名军事家,字长卿,中国春秋时期齐国乐安人。曾率领吴国军队大破数倍于己的楚国军队,占领了楚国都城郢城,几乎亡楚。其著有巨作《孙子兵法》十三篇,为后世兵法家所推崇,被誉为“兵学圣典”,置于《武经七书》之首,被译为英文、法文、德文、日文,成为国际间最著名的兵学典范之书。后人尊称其为孙子、孙武子、兵圣、百世兵家之师、东方兵学的鼻祖。", + yxs_chengyaojin: "程咬金,原名咬金,后更名知节,字义贞,中国济州东阿斑鸠店人(现山东省东平县斑鸠店)。“凌烟阁二十四功臣”之一,唐朝开国名将。隋朝末年,隋炀帝杨广统治残暴,骄奢荒淫,民不聊生,最终爆发了大规模的农民起义。程咬金先入瓦岗军,投王世充,后降唐,成为秦王李世民的骨干成员。据史书记载,程咬金“少骁勇,善用马槊。”而在以《说唐》为代表的系列话本及历史演义小说中,程咬金则使得一柄八卦宣花斧,以“三板斧”武艺著称,是一名性格直爽、粗中有细的福将。", + yxs_yujix: "虞姬,又称虞美人,西楚霸王项羽爱姬,相传为江苏沭阳县颜集乡人,一说苏州常熟人。公元前209年,项羽与叔父项梁起义反秦。项羽军中战将虞子期的妹妹虞姬,貌美好武,倾慕年轻勇猛的项羽,嫁其为妾,常伴左右随军出征,至终形影不离。 公元前202年,项羽在垓下之战中被刘邦、韩信、彭越三方大军合围困于垓下(今安徽灵璧县城南沱河北岸城后村),身陷十面埋伏,兵孤粮缺,夜闻四面楚歌,楚军士气尽失。项羽认为大势已去,帐中酌酒,对着虞姬唱起悲壮的“垓下歌”。虞姬拔剑起舞,含泪唱和:“汉兵已略地,四面楚歌声。大王义气尽,贱妾何聊生。”为免后顾之忧影响项羽突围,唱毕于其面前自刎。", + yxs_xiangyu: "项籍(前232—前202)字羽,通常被称作项羽,中国古代著名将领及政治人物,汉族,秦下相(今江苏省宿迁市宿城区)人。秦末时被楚怀王熊心封为鲁公,在前207年的决定性战役巨鹿之战中统率楚军大破秦军。秦亡后自封“西楚霸王”,统治黄河及长江下游的梁楚九郡。后在楚汉战争中为汉高祖刘邦所败,在乌江(今安徽和县)自刎而死。", + yxs_yingzheng: "秦始皇,赢姓,赵氏,名政,秦庄襄王之子。秦始皇22岁时,在雍城举行国君成人加冕仪式,开始“亲理朝政”。后除掉吕不韦,嫪毐等人,重用李斯,尉缭。自公元前230年至前221年,采取由近及远,集中力量,各个击破的策略,先后灭六国,完成统一中国的大业。同时建立起历史上第一个书同文,度同制,车同轨,行同伦的中央集权国家——秦朝。", + yxs_yuefei: " 岳飞(1103年-1142年),字鹏举,相州汤阴(今属河南)人。南宋军事家,中国历史上著名的抗金名将。绍兴十一年(1142)十二月二十九日,秦桧以“莫须有”的罪名将岳飞毒死于临安风波亭。1162年,宋孝宗时诏复官,谥武穆,宁宗时追封为鄂王,改谥忠武,有《岳武穆集》传世。", + yxs_fuermosi: "福尔摩斯,是一个虚构的侦探人物,是由19世纪末20世纪初的英国侦探小说家阿瑟?柯南·道尔所塑造的一个才华横溢的侦探形象。福尔摩斯不但头脑冷静、观察力敏锐、推理能力极强;而且,他的剑术、拳术和小提琴演奏水平也相当高超,已经成为侦探小说中的典型代表人物之一。", + yxs_guiguzi: "本名王诩,春秋时纵横家,卫国(今河南鹤壁一带)人。曾隐于清溪鬼谷,常入云梦采药修道,弟子无数。有张仪、苏秦、孙膑、庞涓四弟子。精于兵法、奇门遁甲、五行八卦之学。后人称之为王禅老祖。今传《鬼谷子》十四篇。", + yxs_xiaoqiao: "小乔,庐江皖县(今安徽潜山)人。 史书中称小桥,是中国汉末三国时期的女性, 乔公的次女,东吴名将周瑜的妻子。传说与其姐大乔均为绝世美女。合称“二乔”。", + yxs_luzhishen: "鲁智深,梁山泊第十三位好汉,十员步军头领第一名。鲁智深原名鲁达,绰号花和尚。是经略的提辖,因为见郑屠欺侮金翠莲父女,三拳打死了镇关西。被官府追捕,逃到五台山削发为僧,改名鲁智深。", + yxs_zhaoyong: "赵武灵王,战国中后期赵国君主,嬴姓,赵氏,名雍。赵武灵王在位时,推行的“胡服骑射”政策,赵国因而得以强盛,灭中山国,败林胡、楼烦二族,辟云中、雁门、代三郡,并修筑了“赵长城”。", + yxs_yangguang: "隋炀帝杨广,是隋朝第二代皇帝,华阴(今陕西华阴)人,生于隋京师长安。杨广在位期间修建大运河,营建东都迁都洛阳城,开创科举制度,亲征吐谷浑,三征高句丽。但因为杨广滥用民力,导致了隋朝的灭亡,618年在江都被部下缢杀。", + yxs_tangbohu: "唐伯虎,名寅,字伯虎,自号六如居士,明代诗人、画家,吴县(今江苏苏州)人。出身富商家庭,后家道衰落,因祝枝山之劝而潜心读书。公试时为状元,会试时候因科场舞弊案牵连而被斥为吏。后绝意仕途,以卖画为生。唐伯虎为人玩世不恭而又才气横溢,诗文擅名,与祝枝山、文征明、徐祯卿并称“江南四大才子”,画名更著,与沈周、文征明、仇英并称“吴门四家”。民间盛传其点秋香的故事。", + yxs_zhangsanfeng: "明朝最著名的武术家、道士。原名张通,字君宝,在武当山开山立派,成为武当派开山祖师。明英宗赐号“通微显化真人”;明宪宗特封号为“韬光尚志真仙”;明世宗赠封他为“清虚元妙真君”。传说其丰姿魁伟,大耳圆目,须髯如戟。无论寒暑,只一衲一蓑,一餐能食升斗,或数日一食,或数月不食,事能前知。其在武术上的造诣和超乎寻常的长寿都为后人称道。 曾传洪武年间,两度受朱元璋诏请入京,皆避而不见。其与明初巨贾沈万三亦有交际。其所创太极拳一直延续至今,成为后人养身妙术。", + yxs_nandinggeer: "出生于意大利,英国护士和统计学家。她谙熟数学,精通英、法、德、意四门语言,除古典文学外,还精于自然科学、历史和哲学,擅长音乐与绘画。在德国学习护理后,曾往伦敦的医院工作。南丁格尔于1854年和38位护士到克里米亚野战医院工作,成为该院的护士长,被称为“克里米亚的天使”又称“提灯女神”。1860年6月15日,南丁格尔在伦敦成立世界第一所护士学校。为了纪念她的成就,1912年,国际护士会倡仪各国医院和护士学校定每年5月12日南丁格尔诞辰日举行纪念活动,并将5月12日定为“国际护士节”,以缅怀和纪念这位伟大的女性。", + yxs_weizhongxian: "魏忠贤(1568年-1627年12月11日),字完吾,北直隶肃宁(今河北沧州肃宁县)人,汉族,原名李进忠。由才人王氏复姓,出任秉笔太监后,改名魏忠贤。明朝末期宦官。明熹宗时期,出任司礼秉笔太监,极受宠信,被称为“九千九百岁”,排除异己,专断国政,以致人们“只知有忠贤,而不知有皇上”。朱由检继位后,打击惩治阉党,治魏忠贤十大罪,命逮捕法办,自缢而亡,其余党亦被肃清。", + yxs_meixi: '妺喜,姓嬉(喜),生卒年不详,亦作妺嬉、末喜、末嬉,有施氏之女,夏朝最后一位君主夏桀的王后。根据先秦时代记述女子名时所用的全称和简称方式,妺喜应姓喜,即嬉(也作僖)。由于其名字的“妺”字与“妹妹”的“妹”字字形相似,且在《庄子》等作中也有以妺为妹的用法,因此常误作"妹喜"。', + yxs_lanlinwang: "高长恭(541年―573年),又名高孝瓘、高肃,祖籍渤海调蓨(今河北省景县),神武帝高欢之孙,文襄帝高澄第四子,生母不详,南北朝时期北齐宗室、将领,封爵兰陵郡王。高长恭貌柔心壮,音容兼美。为将躬勤细事,每得甘美,虽一瓜数果,必与将士分享。累次升任至并州刺史。突厥攻入晋阳,高长恭奋力将其击退。邙山之战,高长恭为中军,率领五百骑兵再入周军包围圈,直至金墉城下,因高长恭戴着头盔,城中的人不确定是敌军或是我军,直到高长恭把头盔脱下来城上的人才知道是高长恭,派弓箭手开始放箭保护他,之后高长恭成功替金墉解围,高长恭在此次战中威名大振,士兵们为此战而讴歌他,即后来知名的《兰陵王入阵曲》。", }, characterTitle: { yxs_qinqiong: "Sukincen", @@ -151,11 +109,7 @@ game.import("character", function () { }, content: function () { player.addTempSkill("yxs_fanji2", "shaAfter"); - player.chooseToUse( - { name: "sha" }, - trigger.source, - "反击:是否对" + get.translation(trigger.source) + "使用一张杀?" - ).logSkill = "yxs_fanji"; + player.chooseToUse({ name: "sha" }, trigger.source, "反击:是否对" + get.translation(trigger.source) + "使用一张杀?").logSkill = "yxs_fanji"; }, }, yxs_fanji2: { @@ -203,14 +157,9 @@ game.import("character", function () { content: function () { "step 0"; player - .chooseTarget( - "选择【门神】的目标", - lib.translate.yxs_menshen_info, - true, - function (card, player, target) { - return target != player; - } - ) + .chooseTarget("选择【门神】的目标", lib.translate.yxs_menshen_info, true, function (card, player, target) { + return target != player; + }) .set("ai", function (target) { return get.attitude(player, target); }); @@ -316,12 +265,7 @@ game.import("character", function () { yaoji: { trigger: { player: "damageEnd" }, filter: function (event, player) { - return ( - event.source && - event.source.isIn() && - event.source != player && - !event.source.hasJudge("lebu") - ); + return event.source && event.source.isIn() && event.source != player && !event.source.hasJudge("lebu"); }, check: function (event, player) { return get.attitude(player, event.source) <= 0; @@ -359,9 +303,7 @@ game.import("character", function () { var nh = player.countCards("h"); if ( game.hasPlayer(function (current) { - return ( - get.attitude(player, current) <= 0 && current.countCards("h") == nh + 1 - ); + return get.attitude(player, current) <= 0 && current.countCards("h") == nh + 1; }) ) { return 9; @@ -431,11 +373,7 @@ game.import("character", function () { direct: true, content: function () { "step 0"; - var next = player.chooseToDiscard( - "e", - get.prompt("wlianhuan", trigger.player), - "弃置一张装备区内的牌使伤害+1" - ); + var next = player.chooseToDiscard("e", get.prompt("wlianhuan", trigger.player), "弃置一张装备区内的牌使伤害+1"); next.ai = function (card) { if (get.attitude(player, trigger.player) < 0) { return 7 - get.value(card); @@ -453,10 +391,7 @@ game.import("character", function () { enable: "phaseUse", filterCard: { suit: "heart" }, filterTarget: function (card, player, target) { - return ( - get.distance(player, target) <= 1 && - lib.filter.cardEnabled({ name: "tao" }, target, target) - ); + return get.distance(player, target) <= 1 && lib.filter.cardEnabled({ name: "tao" }, target, target); }, check: function (card) { return 8 - get.value(card); @@ -706,10 +641,9 @@ game.import("character", function () { "step 2"; if (event.targets && event.targets.length) { event.target = event.targets.shift(); - event.target.chooseCard("交给" + get.translation(player) + "一张手牌", true).ai = - function (card) { - return -get.value(card); - }; + event.target.chooseCard("交给" + get.translation(player) + "一张手牌", true).ai = function (card) { + return -get.value(card); + }; } else { event.finish(); } @@ -731,11 +665,7 @@ game.import("character", function () { if (!target.hasFriend()) return; var players = game.filterPlayer(); for (var i = 0; i < players.length; i++) { - if ( - players[i].group != "qun" && - get.attitude(player, players[i]) <= 0 && - players[i] != player - ) { + if (players[i].group != "qun" && get.attitude(player, players[i]) <= 0 && players[i] != player) { if (target.hp >= 4) return [1, get.tag(card, "damage") * 2]; if (target.hp == 3) return [1, get.tag(card, "damage") * 1.5]; if (target.hp == 2) return [1, get.tag(card, "damage") * 0.5]; @@ -816,11 +746,7 @@ game.import("character", function () { forceunique: true, enable: "phaseUse", filter: function (event, player) { - return ( - !player.hasSkill("tongyu_guiyin") && - !player.getStat("damage") && - [player.name1, player.name2].includes("yxs_luobinhan") - ); + return !player.hasSkill("tongyu_guiyin") && !player.getStat("damage") && [player.name1, player.name2].includes("yxs_luobinhan"); }, derivation: ["lzhangyi", "jimin", "tongyu"], content: function () { @@ -852,11 +778,7 @@ game.import("character", function () { forceunique: true, enable: "phaseUse", filter: function (event, player) { - return ( - player.countCards("he") > 0 && - !player.hasSkill("tongyu_guiyin") && - [player.name1, player.name2].includes("yxs_luobinhan") - ); + return player.countCards("he") > 0 && !player.hasSkill("tongyu_guiyin") && [player.name1, player.name2].includes("yxs_luobinhan"); }, filterCard: true, position: "he", @@ -1053,11 +975,7 @@ game.import("character", function () { frequent: true, filter: function (event) { if (event._notrigger.includes(event.player)) return false; - return ( - event.player.isAlive() && - event.parent.name == "yanyi" && - event.player.hp < event.player.maxHp - ); + return event.player.isAlive() && event.parent.name == "yanyi" && event.player.hp < event.player.maxHp; }, content: function () { "step 0"; @@ -1177,8 +1095,7 @@ game.import("character", function () { ) ) return false; - if (event.target.hasSkillTag("respondShan") && event.target.countCards("h") >= 3) - return false; + if (event.target.hasSkillTag("respondShan") && event.target.countCards("h") >= 3) return false; return true; }, logTarget: "target", @@ -1303,12 +1220,9 @@ game.import("character", function () { } "step 1"; var source = target; - player.chooseTarget( - "选择一个目标送出" + get.translation(event.card), - function (card, player, target) { - return target != player; - } - ).ai = function (target) { + player.chooseTarget("选择一个目标送出" + get.translation(event.card), function (card, player, target) { + return target != player; + }).ai = function (target) { var att = get.attitude(player, target); if (att > 3 && player.countCards("h") > target.countCards("h")) { return att; @@ -1460,7 +1374,7 @@ game.import("character", function () { }, ai: { effect: { - target_use(card, player, target, current) { + target(card, player, target, current) { if (get.type(card) == "trick" || card.name == "sha") return "zeroplayertarget"; }, }, @@ -1469,9 +1383,7 @@ game.import("character", function () { tiewan: { trigger: { global: "useCardAfter" }, filter: function (event, player) { - return ( - get.type(event.card.viewAs || event.card.name) == "delay" && event.player != player - ); + return get.type(event.card.viewAs || event.card.name) == "delay" && event.player != player; }, direct: true, content: function () { @@ -1540,8 +1452,7 @@ game.import("character", function () { }, effect: { target: function (card, player, target, current) { - if (get.tag(card, "respondShan") && current < 0 && !target.countCards("e")) - return 0.6; + if (get.tag(card, "respondShan") && current < 0 && !target.countCards("e")) return 0.6; }, }, }, @@ -1556,11 +1467,7 @@ game.import("character", function () { if (nh == 0) return false; var players = game.filterPlayer(); for (var i = 0; i < players.length; i++) { - if ( - players[i] != player && - players[i] != event.player && - players[i].countCards("h") <= nh - ) { + if (players[i] != player && players[i] != event.player && players[i].countCards("h") <= nh) { return true; } } @@ -1677,12 +1584,7 @@ game.import("character", function () { if (info) { var skills = info[3]; for (var j = 0; j < skills.length; j++) { - if ( - lib.translate[skills[j] + "_info"] && - lib.skill[skills[j]] && - !lib.skill[skills[j]].unique && - !player.hasSkill(skills[j]) - ) { + if (lib.translate[skills[j] + "_info"] && lib.skill[skills[j]] && !lib.skill[skills[j]].unique && !player.hasSkill(skills[j])) { return true; } } @@ -1690,11 +1592,7 @@ game.import("character", function () { return false; }, ai1: function (card) { - if ( - player.additionalSkills.yizhuang && - player.additionalSkills.yizhuang.length > 0 - ) - return 0; + if (player.additionalSkills.yizhuang && player.additionalSkills.yizhuang.length > 0) return 0; return 7 - get.value(card); }, ai2: function (target) { @@ -1717,12 +1615,7 @@ game.import("character", function () { var list = []; var skills = lib.character[name][3]; for (var j = 0; j < skills.length; j++) { - if ( - lib.translate[skills[j] + "_info"] && - lib.skill[skills[j]] && - !lib.skill[skills[j]].unique && - !player.hasSkill(skills[j]) - ) { + if (lib.translate[skills[j] + "_info"] && lib.skill[skills[j]] && !lib.skill[skills[j]].unique && !player.hasSkill(skills[j])) { list.push(skills[j]); } } @@ -1796,22 +1689,13 @@ game.import("character", function () { trigger: { global: "dying" }, priority: 9, filter: function (event, player) { - return ( - event.player.hp <= 0 && - (player.countCards("h", "jiu") > 0 || - player.countCards("h", { color: "black" }) >= 2) && - player != event.player - ); + return event.player.hp <= 0 && (player.countCards("h", "jiu") > 0 || player.countCards("h", { color: "black" }) >= 2) && player != event.player; }, direct: true, content: function () { "step 0"; var goon = get.attitude(player, trigger.player) < 0; - var next = player.chooseToDiscard( - "鸠杀:是否弃置一张酒或两张黑色手牌令" + - get.translation(trigger.player) + - "立即死亡?" - ); + var next = player.chooseToDiscard("鸠杀:是否弃置一张酒或两张黑色手牌令" + get.translation(trigger.player) + "立即死亡?"); next.ai = function (card) { if (ui.selected.cards.length) { if (ui.selected.cards[0].name == "jiu") return 0; @@ -2137,13 +2021,9 @@ game.import("character", function () { content: function () { "step 0"; var num = Math.max(1, player.maxHp - player.hp); - player.chooseTarget( - "婉歌:获得至多" + get.cnNumber(num) + "名角色的一张手牌", - [1, num], - function (card, player, target) { - return target.countCards("h") && target != player; - } - ).ai = function (target) { + player.chooseTarget("婉歌:获得至多" + get.cnNumber(num) + "名角色的一张手牌", [1, num], function (card, player, target) { + return target.countCards("h") && target != player; + }).ai = function (target) { return -get.attitude(player, target); }; player.removeSkill("wange2"); @@ -2220,13 +2100,7 @@ game.import("character", function () { } var effect = 0; for (var i = 0; i < players.length; i++) { - if ( - players[i].sex == "male" && - players[i] != target && - players[i] != player && - players[i].countCards("he") - ) - effect += get.effect(target, { name: "sha" }, players[i], target); + if (players[i].sex == "male" && players[i] != target && players[i] != player && players[i].countCards("he")) effect += get.effect(target, { name: "sha" }, players[i], target); } return effect; }, @@ -2247,9 +2121,7 @@ game.import("character", function () { discardcards[i].discard(); } } - player.chooseControl("heart2", "diamond2", "club2", "spade2", "cancel").ai = function ( - event - ) { + player.chooseControl("heart2", "diamond2", "club2", "spade2", "cancel").ai = function (event) { if (Math.random() < 0.5) return "club2"; if (Math.random() < 0.5) return "spade2"; if (Math.random < 2 / 3) return "diamond2"; @@ -2310,21 +2182,13 @@ game.import("character", function () { filter: function (event, player) { if (player.hasSkill("bolehuiyan4")) return false; if (event.target.isUnderControl()) return false; - return ( - event.player != player && event.target != player && event.target.countCards("h") > 0 - ); + return event.player != player && event.target != player && event.target.countCards("h") > 0; }, group: ["bolehuiyan2", "bolehuiyan3"], content: function () { "step 0"; if (event.isMine()) { - event.dialog = ui.create.dialog( - "慧眼:预言" + - get.translation(trigger.player) + - "对" + - get.translation(trigger.target) + - "的杀能否命中" - ); + event.dialog = ui.create.dialog("慧眼:预言" + get.translation(trigger.player) + "对" + get.translation(trigger.target) + "的杀能否命中"); } player.chooseControl("能命中", "不能命中", "cancel").ai = function (event) { if (trigger.player.hasSkill("wushuang")) return 0; @@ -2405,13 +2269,9 @@ game.import("character", function () { content: function () { "step 0"; if (event.isMine()) { - event.dialog = ui.create.dialog( - "慧眼:预言" + get.translation(trigger.player) + "的" + trigger.judgestr + "判定" - ); + event.dialog = ui.create.dialog("慧眼:预言" + get.translation(trigger.player) + "的" + trigger.judgestr + "判定"); } - player.chooseControl("heart2", "diamond2", "club2", "spade2", "cancel").ai = function ( - event - ) { + player.chooseControl("heart2", "diamond2", "club2", "spade2", "cancel").ai = function (event) { switch (Math.floor(Math.random() * 4)) { case 0: return "heart2"; @@ -2540,10 +2400,7 @@ game.import("character", function () { next.set("prompt2", "(共需打出2张杀)"); next.autochoose = lib.filter.autoRespondSha; next.ai = function (card) { - if ( - get.attitude(trigger.turn, player) < 0 && - trigger.turn.countCards("h", "sha") > 1 - ) { + if (get.attitude(trigger.turn, player) < 0 && trigger.turn.countCards("h", "sha") > 1) { return get.unuseful2(card); } return -1; @@ -2574,12 +2431,7 @@ game.import("character", function () { trigger: { global: "useCard" }, priority: 15, filter: function (event, player) { - return ( - event.card.name == "sha" && - event.player != player && - player.countCards("h", "sha") > 0 && - event.targets.includes(player) == false - ); + return event.card.name == "sha" && event.player != player && player.countCards("h", "sha") > 0 && event.targets.includes(player) == false; }, direct: true, content: function () { @@ -2613,38 +2465,6 @@ game.import("character", function () { expose: 0.2, }, }, - feiming: { - trigger: { player: "damageEnd" }, - check: function (event, player) { - return get.attitude(player, event.source) <= 0; - }, - filter: function (event, player) { - return event.source && event.source != player; - }, - content: function () { - "step 0"; - trigger.source.chooseCard("交出一张红桃牌或失去1点体力", function (card) { - return get.suit(card) == "heart"; - }).ai = function (card) { - return 6 - get.value(card); - }; - "step 1"; - if (result.bool) { - player.gain(result.cards[0], trigger.source); - trigger.source.$give(1, player); - } else { - trigger.source.loseHp(); - } - }, - ai: { - maixie_defend: true, - effect: { - target: function (card, player, target) { - if (get.tag(card, "damage")) return [1, 0, 0, -1]; - }, - }, - }, - }, jianai: { trigger: { player: "recoverEnd" }, check: function (event, player) { @@ -2696,11 +2516,7 @@ game.import("character", function () { }, content: function () { "step 0"; - var next = player.chooseToDiscard( - "he", - "是否弃置一张黑色牌并收回" + get.translation(trigger.cards.filterInD()) + "?", - { color: "black" } - ); + var next = player.chooseToDiscard("he", "是否弃置一张黑色牌并收回" + get.translation(trigger.cards.filterInD()) + "?", { color: "black" }); next.ai = function (card) { return get.value(trigger.card) - get.value(card); }; @@ -2738,28 +2554,13 @@ game.import("character", function () { trigger: { global: "useCardAfter" }, direct: true, filter: function (event, player) { - return ( - _status.currentPhase != player && - event.player != player && - get.type(event.card) == "trick" && - event.cards.filterInD().length > 0 && - !player.hasSkill("zhulu2") && - player.countCards("he", { suit: get.suit(event.card) }) > 0 - ); + return _status.currentPhase != player && event.player != player && get.type(event.card) == "trick" && event.cards.filterInD().length > 0 && !player.hasSkill("zhulu2") && player.countCards("he", { suit: get.suit(event.card) }) > 0; }, content: function () { "step 0"; var val = get.value(trigger.card); var suit = get.suit(trigger.card); - var next = player.chooseToDiscard( - "he", - "逐鹿:是否弃置一张" + - get.translation(suit) + - "牌并获得" + - get.translation(trigger.cards.filterInD()) + - "?", - { suit: suit } - ); + var next = player.chooseToDiscard("he", "逐鹿:是否弃置一张" + get.translation(suit) + "牌并获得" + get.translation(trigger.cards.filterInD()) + "?", { suit: suit }); next.ai = function (card) { return val - get.value(card); }; @@ -2793,14 +2594,7 @@ game.import("character", function () { if (!target.hasJudge(judges[i].viewAs || judges[i].name)) return true; } if (target.isMin()) return false; - if ( - (from.getEquip(1) && !target.getEquip(1)) || - (from.getEquip(2) && !target.getEquip(2)) || - (from.getEquip(3) && !target.getEquip(3)) || - (from.getEquip(4) && !target.getEquip(4)) || - (from.getEquip(5) && !target.getEquip(5)) - ) - return true; + if ((from.getEquip(1) && !target.getEquip(1)) || (from.getEquip(2) && !target.getEquip(2)) || (from.getEquip(3) && !target.getEquip(3)) || (from.getEquip(4) && !target.getEquip(4)) || (from.getEquip(5) && !target.getEquip(5))) return true; return false; } else { return target.countCards("ej") > 0; @@ -2830,9 +2624,7 @@ game.import("character", function () { if (get.position(result.buttons[0].link) == "e") { event.targets[1].equip(result.buttons[0].link); } else if (result.buttons[0].link.viewAs) { - event.targets[1].addJudge({ name: result.buttons[0].link.viewAs }, [ - result.buttons[0].link, - ]); + event.targets[1].addJudge({ name: result.buttons[0].link.viewAs }, [result.buttons[0].link]); } else { event.targets[1].addJudge(result.buttons[0].link); } @@ -2850,14 +2642,7 @@ game.import("character", function () { var players = game.filterPlayer(); for (var i = 0; i < players.length; i++) { if (get.attitude(player, players[i]) > 0) { - if ( - (target.getEquip(1) && !players[i].getEquip(1)) || - (target.getEquip(2) && !players[i].getEquip(2)) || - (target.getEquip(3) && !players[i].getEquip(3)) || - (target.getEquip(4) && !players[i].getEquip(4)) || - (target.getEquip(5) && !players[i].getEquip(5)) - ) - return -1; + if ((target.getEquip(1) && !players[i].getEquip(1)) || (target.getEquip(2) && !players[i].getEquip(2)) || (target.getEquip(3) && !players[i].getEquip(3)) || (target.getEquip(4) && !players[i].getEquip(4)) || (target.getEquip(5) && !players[i].getEquip(5))) return -1; } } } @@ -2885,9 +2670,16 @@ game.import("character", function () { player.draw(2); }, ai: { + noh: true, + skillTagFilter(player, tag, arg) { + if (tag === "noh") return player.countCards("h") === 1; + }, effect: { - target: function (card) { - if (card.name == "guohe" || card.name == "liuxinghuoyu") return 0.5; + player_use(card, player, target) { + if (player.countCards("h") === 1) return [1, 0.8]; + }, + target(card, player, target) { + if (get.tag(card, "loseCard") && target.countCards("h") === 1) return 0.5; }, }, }, @@ -2950,10 +2742,7 @@ game.import("character", function () { lib.skill.miaobix.viewAs = card; var next = player.chooseToUse(); next.logSkill = "miaobi"; - next.set( - "openskilldialog", - "妙笔:将一张手牌当" + get.translation(card) + "使用" - ); + next.set("openskilldialog", "妙笔:将一张手牌当" + get.translation(card) + "使用"); next.set("norestore", true); next.set("_backupevent", "miaobix"); next.set("custom", { @@ -3029,25 +2818,16 @@ game.import("character", function () { return !get.info(button.link).unique; }; "step 1"; - if (result.links[0]) { - cards[0].init([ - result.links[0].suit, - result.links[0].number, - result.links[0].name, - result.links[0].nature, - ]); - event.card = cards[0]; - player.chooseTarget( - "选择一个角色装备" + get.translation(result.links), - function (card, player, target) { - return !target.isMin(); - } - ).ai = function (target) { - if (!target.countCards("e", { subtype: get.subtype(event.card) })) { - return get.attitude(player, target); - } - return 0; - }; + if (result.bool) { + event.card = get.autoViewAs({ name: result.links[0].name }, event.cards); + player + .chooseTarget("神工:选择一个角色装备" + get.translation(event.card) + "(" + get.translation(event.cards) + ")", function (card, player, target) { + return target.canEquip(get.event().getParent().card, true); + }) + .set("ai", target => { + const card = get.event().getParent().card; + return get.equipValue(card, target) * get.attitude(get.player(), target); + }); } else { event.finish(); } @@ -3125,13 +2905,11 @@ game.import("character", function () { yxs_fanji: "反击", yxs_fanji2: "反击", - yxs_fanji_info: - "当你受到【杀】或【决斗】造成的伤害后,你可以对伤害来源使用一张【杀】。若此【杀】为红色,其不可闪避。", + yxs_fanji_info: "当你受到【杀】或【决斗】造成的伤害后,你可以对伤害来源使用一张【杀】。若此【杀】为红色,其不可闪避。", yxs_menshen: "门神", yxs_menshen2: "门神", yxs_menshen3: "门神", - yxs_menshen_info: - "回合结束阶段,你可选择一名其他角色,若如此做,直到你的下回合开始,所有角色对该角色使用的【杀】或【决斗】均视为对你使用。", + yxs_menshen_info: "回合结束阶段,你可选择一名其他角色,若如此做,直到你的下回合开始,所有角色对该角色使用的【杀】或【决斗】均视为对你使用。", zhuxin: "诛心", zhuxin_info: "出牌阶段限一次,你可以与一名其他角色拼点,若你赢,你对其造成1点伤害。", wlianhuan: "连环", @@ -3144,13 +2922,11 @@ game.import("character", function () { guimian_info: "锁定技,每当你在出牌阶段使用【杀】造成伤害,本阶段内出【杀】次数上限+1。", lyuxue: "浴血", lyuxue2: "浴血", - lyuxue_info: - "锁定技,每当你造成一次伤害,若目标没有浴血标记,你令其获得一个浴血标记;当一名角色失去浴血标记时,其失去1点体力;准备阶段,若场上浴血标记的数量不少于存活角色数的一半(向下取整),你清空浴血标记;当你即将死亡时,你清空浴血标记。", + lyuxue_info: "锁定技,每当你造成一次伤害,若目标没有浴血标记,你令其获得一个浴血标记;当一名角色失去浴血标记时,其失去1点体力;准备阶段,若场上浴血标记的数量不少于存活角色数的一半(向下取整),你清空浴血标记;当你即将死亡时,你清空浴血标记。", huli: "护理", huli_info: "出牌阶段,你可以将一张红桃手牌当作【桃】对距离1以内的角色使用。", yixin: "医心", - yixin_info: - "限定技,你可以弃置两张牌,然后令一名已受伤角色回复X点体力并摸4-X张牌(X为该角色已损失的体力值且不超过4)。", + yixin_info: "限定技,你可以弃置两张牌,然后令一名已受伤角色回复X点体力并摸4-X张牌(X为该角色已损失的体力值且不超过4)。", xianqu: "先驱", xianqu_info: "锁定技,你不能成为点数小于8的【杀】的目标。", zbudao: "布道", @@ -3164,75 +2940,60 @@ game.import("character", function () { shiqin: "弑亲", shiqin_info: "锁定技,其他群势力角色濒死时,你令其立即死亡。", yjujian: "拒谏", - yjujian_info: - "出牌阶段限一次,你可以交给一名其他角色一张牌,该角色的锦囊牌不能指定你为目标直到你的下一回合开始。", + yjujian_info: "出牌阶段限一次,你可以交给一名其他角色一张牌,该角色的锦囊牌不能指定你为目标直到你的下一回合开始。", yaoyi: "徭役", yaoyi_info: "每当你受到一次伤害,你可以令至多2名非群势力角色交给你一张手牌。", zyhufu: "胡服", - zyhufu_info: - "锁定技,当你的装备区内没有防具牌时,你摸牌阶段额外摸一张牌;当你装备区内有防具牌时,你的手牌上限+5。", + zyhufu_info: "锁定技,当你的装备区内没有防具牌时,你摸牌阶段额外摸一张牌;当你装备区内有防具牌时,你的手牌上限+5。", hanbei: "捍北", hanbei_info: "锁定技,你的装备区有马时,你的【杀】不可闪避。", kuangchan: "狂禅", kuangchan_info: "锁定技,你做主公时,不增加体力上限。", yxsdili: "底力", - // yxsdili_info:'锁定技,摸牌阶段,你额外摸X张牌,X为你已损失的体力值。', yxsdili_info: "锁定技,摸牌阶段,你额外摸X张牌,X为你已损失的体力值的一半,向上取整且最多为2。", chujia: "初嫁", - chujia_info: - "出牌阶段限一次,你可以弃置两张相同颜色的手牌,指定任意一名角色摸X张牌。(X为该角色已损失的体力值)", + chujia_info: "出牌阶段限一次,你可以弃置两张相同颜色的手牌,指定任意一名角色摸X张牌。(X为该角色已损失的体力值)", zhijie: "知节", zhijie_info: "出牌阶段限一次,你的红桃手牌可以当做【无中生有】使用。", baihe: "捭阖", - baihe_info: - "出牌阶段限一次,你可以弃置一张牌,选择以下1项执行:(1)横置1名未横置角色,该角色摸一张牌;(2)重置一名已横置角色,该角色弃置一张手牌。", + baihe_info: "出牌阶段限一次,你可以弃置一张牌,选择以下1项执行:(1)横置1名未横置角色,该角色摸一张牌;(2)重置一名已横置角色,该角色弃置一张手牌。", yinyang: "阴阳", yinyang_info: "出牌阶段限一次,你可以弃置两张手牌并选择3名角色,分别横置或重置这些角色。", xiushen: "修身", - // xiushen_info:'锁定技,结束阶段,若场上有横置角色,你摸两张牌。', xiushen_info: "锁定技,出牌阶段结束时,若场上有横置角色,你摸两张牌。", yanyi: "演绎", - yanyi_info: - "出牌阶段限一次,你可以弃置一张黑色牌,指定1名角色和1种花色,若被指定角色的手牌中含有此花色,则受到1点伤害。", + yanyi_info: "出牌阶段限一次,你可以弃置一张黑色牌,指定1名角色和1种花色,若被指定角色的手牌中含有此花色,则受到1点伤害。", jiean: "结案", - jiean_info: - "每当【演绎】造成伤害时,你可以摸X张牌,并以任意数量分配给任意角色(X为被【演绎】造成伤害角色的已损失体力值)。", + jiean_info: "每当【演绎】造成伤害时,你可以摸X张牌,并以任意数量分配给任意角色(X为被【演绎】造成伤害角色的已损失体力值)。", wumu: "武穆", wumu_info: "锁定技,你的黑色【杀】无视距离,红色【杀】不计入回合内的出杀限制。", ysheshen: "舍身", ysheshen_info: "每当你受到1点伤害,可以观看牌堆顶的两张牌,并将其交给任意1~2名角色。", sanbanfu: "三板斧", - sanbanfu_info: - "当你对其他角色使用【杀】时,你可以使此【杀】有如下效果:若对方没有出【闪】,其受到2点伤害;若对方打出了一张【闪】,你与其各受到1点伤害;若对方打出了两张【闪】,你受到1点伤害。", + sanbanfu_info: "当你对其他角色使用【杀】时,你可以使此【杀】有如下效果:若对方没有出【闪】,其受到2点伤害;若对方打出了一张【闪】,你与其各受到1点伤害;若对方打出了两张【闪】,你受到1点伤害。", bingsheng: "兵圣", - bingsheng_info: - "出牌阶段限一次,你可以弃置两张花色不同的手牌,指定一名其他角色使其体力值与你相同(体力最多变化2点)。", + bingsheng_info: "出牌阶段限一次,你可以弃置两张花色不同的手牌,指定一名其他角色使其体力值与你相同(体力最多变化2点)。", taolue: "韬略", taolue_info: "锁定技,你的手牌上限+1。", shentan: "神探", - shentan_info: - "出牌阶段限一次,你可以弃置一张牌,获得距离2以内的一名角色的手牌,并可以将其交给任意一名角色。", + shentan_info: "出牌阶段限一次,你可以弃置一张牌,获得距离2以内的一名角色的手牌,并可以将其交给任意一名角色。", hanqiang: "寒枪", hanqiang_info: "锁定技,当你没装备武器时,攻击范围+1。", biaoqi: "骠骑", - biaoqi_info: - "锁定技,当你出【杀】指定目标后,若你的攻击范围大于目标体力值,则此【杀】不可闪避;若你的攻击范围小于目标体力值,你摸一张牌。", + biaoqi_info: "锁定技,当你出【杀】指定目标后,若你的攻击范围大于目标体力值,则此【杀】不可闪避;若你的攻击范围小于目标体力值,你摸一张牌。", wluoyan: "落雁", wluoyan_info: "锁定技,你防止即将受到的伤害,改为失去1点体力。", heqin: "和亲", heqin2: "和亲", heqin3: "和亲", - heqin_info: - "限定技,你可以与场上一名男性角色形成【和亲】状态,你与该男性角色于摸牌阶段摸牌数+1。你或者男性角色阵亡时,【和亲】状态消失。", + heqin_info: "限定技,你可以与场上一名男性角色形成【和亲】状态,你与该男性角色于摸牌阶段摸牌数+1。你或者男性角色阵亡时,【和亲】状态消失。", chajue: "察觉", chajue2: "察觉", - chajue_info: - "锁定技,你的回合外,你每受到一次伤害,任何【杀】或普通锦囊牌均对你无效,直到你的回合开始。", + chajue_info: "锁定技,你的回合外,你每受到一次伤害,任何【杀】或普通锦囊牌均对你无效,直到你的回合开始。", tiewan: "铁腕", tiewan_info: "每当其他角色使用延时类锦囊牌时,你可以立即将一张红色牌当作【乐不思蜀】使用。", qianglue: "强掠", - qianglue_info: - "每当你的【杀】被闪避时,你可以进行一次判定,若结果为黑色,你可以获得对方的一张牌。", + qianglue_info: "每当你的【杀】被闪避时,你可以进行一次判定,若结果为黑色,你可以获得对方的一张牌。", xiadao: "侠盗", xiadao_info: "每当你造成一次伤害,你可以令一名手牌数不少于受伤害角色的另一名角色获得其一张手牌。", jimin: "机敏", @@ -3242,116 +3003,91 @@ game.import("character", function () { tongyu: "统御", tongyu_info: "出牌阶段,你可以弃置一张牌,并转变为罗宾汉(每回合只能转变一次)。", lguiyin: "归隐", - lguiyin_info: - "出牌阶段,若你本回合内未造成伤害,你可以摸一张牌,并转变为汉丁顿伯爵(每回合只能转变一次)。", + lguiyin_info: "出牌阶段,若你本回合内未造成伤害,你可以摸一张牌,并转变为汉丁顿伯爵(每回合只能转变一次)。", lzhangyi: "仗义", lzhangyi_info: "你可以将你弃置的卡牌交给一名其他角色。", yizhuang: "易装", yizhuang2: "易装", - yizhuang_info: - "准备阶段,你可以弃置一张牌并选择一名男性角色,获得其所有技能,直到你首次受到伤害。", + yizhuang_info: "准备阶段,你可以弃置一张牌并选择一名男性角色,获得其所有技能,直到你首次受到伤害。", kongju: "控局", - kongju_info: - "锁定技,你的手牌上限为你的体力上限;当你的手牌数小于体力上限时,你不能成为过河拆桥或顺手牵羊的目标;当你的手牌数大于体力上限时,你不能成为乐不思蜀的目标。", + kongju_info: "锁定技,你的手牌上限为你的体力上限;当你的手牌数小于体力上限时,你不能成为过河拆桥或顺手牵羊的目标;当你的手牌数大于体力上限时,你不能成为乐不思蜀的目标。", tuqiang: "图强", tuqiang_info: "每当你使用或打出一张【闪】,你可以摸一张牌。", zhensha: "鸩杀", - zhensha_info: - "当场上有角色进入濒死状态时,你可以弃置一张【酒】或两张黑色手牌,则该角色立即死亡。", + zhensha_info: "当场上有角色进入濒死状态时,你可以弃置一张【酒】或两张黑色手牌,则该角色立即死亡。", xumou: "蓄谋", xumou_info: "结束阶段,你可以将武将牌翻面并摸三张牌。", guifu: "鬼斧", - guifu_info: - "出牌阶段限一次,你可以指定一名角色装备区内的一张牌,将其弃掉,自己和对方同时摸取一张牌。", + guifu_info: "出牌阶段限一次,你可以指定一名角色装备区内的一张牌,将其弃掉,自己和对方同时摸取一张牌。", lshengong: "神工", - lshengong_info: - "出牌阶段限一次,你可以选定场上任意一名角色的装备区的非特殊牌,出自己的一张手牌复制该装备,然后可以选择装备上自己或者别的角色的装备区。", + lshengong_info: "出牌阶段限一次,你可以选定场上任意一名角色的装备区的非特殊牌,出自己的一张手牌复制该装备,然后可以选择装备上自己或者别的角色的装备区。", zhexian: "谪仙", zhexian_info: "当你于一名其他角色的回合内首次失去牌时,你可以摸一张牌。", miaobi: "妙笔", - miaobi_info: - "出牌阶段限一次,你可以弃置一名其他角色的一张牌,若此牌是基本牌或普通锦囊,你可以将一张手牌当此牌使用;否则你须弃置一张牌。", + miaobi_info: "出牌阶段限一次,你可以弃置一名其他角色的一张牌,若此牌是基本牌或普通锦囊,你可以将一张手牌当此牌使用;否则你须弃置一张牌。", cike: "刺客", - cike_info: - "你对其他角色出【杀】时可以选择做一次判定:若判定牌为红色花色,则此【杀】不可回避,直接命中;若判定牌为黑色花色,你可以选择弃掉对方一张牌。", + cike_info: "你对其他角色出【杀】时可以选择做一次判定:若判定牌为红色花色,则此【杀】不可回避,直接命中;若判定牌为黑色花色,你可以选择弃掉对方一张牌。", qiangyun: "强运", qiangyun_info: "每当你失去最后一张手牌,可摸两张牌。", ducai: "独裁", ducai2: "独裁", ducai3: "独裁", - ducai_info: - "出牌阶段限一次,你可以弃置一张牌,则本轮内除你外的角色不能使用或打出与该手牌花色相同的手牌。", + ducai_info: "出牌阶段限一次,你可以弃置一张牌,则本轮内除你外的角色不能使用或打出与该手牌花色相同的手牌。", tongling: "统领", tongling_info: "锁定技,每当一名友方角色造成一次伤害,你获得1个统领标记(标记上限为3)。", fanpu: "反扑", - fanpu_info: - "出牌阶段限一次,你可以移去3枚统领标记并视为对攻击范围内的至多3名角色使用一张【杀】。", + fanpu_info: "出牌阶段限一次,你可以移去3枚统领标记并视为对攻击范围内的至多3名角色使用一张【杀】。", fenghuo: "烽火", fenghuo_info: "你可以将一张装备区内的牌当作【南蛮入侵】使用。", yxsweiyi: "威仪", yxsweiyi_info: "每当你受到一次伤害,可以令伤害来源弃置两张牌。", xieling: "挟令", - xieling_info: - "出牌阶段,弃掉两张手牌,将任意一名角色装备区或判定区的牌移动到另一名角色对应的区域。", + xieling_info: "出牌阶段,弃掉两张手牌,将任意一名角色装备区或判定区的牌移动到另一名角色对应的区域。", baye: "霸业", baye_info: "出牌阶段,你可以将一张牌当做本回合内前一张使用的牌来使用。每回合限用一次。", nvquan: "女权", nvquan1: "女权", nvquan2: "女权", - nvquan_info: - "你对男性角色使用【杀】或【决斗】时,对方需连续打出两张【闪】或【杀】响应;你不能成为男性角色的决斗目标。", + nvquan_info: "你对男性角色使用【杀】或【决斗】时,对方需连续打出两张【闪】或【杀】响应;你不能成为男性角色的决斗目标。", qiandu: "迁都", qiandu_info: "出牌阶段,你可以弃一张黑色手牌,和一名存活的玩家与其交换位置。每回合限一次。", budao: "补刀", - budao_info: - "你的回合外,你的攻击范围的一名角色受到【杀】的伤害时,你可以对其使用一张【杀】,只要你的【杀】对目标角色造成了伤害,你就可以继续对其使用【杀】。", + budao_info: "你的回合外,你的攻击范围的一名角色受到【杀】的伤害时,你可以对其使用一张【杀】,只要你的【杀】对目标角色造成了伤害,你就可以继续对其使用【杀】。", feigong: "非攻", feigong_info: "其他角色使用【杀】时,若你不是【杀】的目标,可以弃置一张【杀】取消之。", jianai: "兼爱", jianai_info: "每当你回复1点体力,可以令所有其他角色回复1点体力。", bolehuiyan: "慧眼", - bolehuiyan_info: - "当一名有手牌的其他角色成为来源不为你的【杀】的目标时,你可以预言此【杀】能否命中,若预言正确,你摸一张牌,否则你须弃置一张牌。每回合限发动一次。", + bolehuiyan_info: "当一名有手牌的其他角色成为来源不为你的【杀】的目标时,你可以预言此【杀】能否命中,若预言正确,你摸一张牌,否则你须弃置一张牌。每回合限发动一次。", xiangma: "相马", - xiangma_info: - "锁定技,只要你的体力值大于2点,你的进攻距离+1;只要你的体力值为2点或更低,你的防御距离+1。", + xiangma_info: "锁定技,只要你的体力值大于2点,你的进攻距离+1;只要你的体力值为2点或更低,你的防御距离+1。", seyou: "色诱", - seyou_info: - "限定技,出牌阶段,你可以指定任意1名角色,其他所有男性角色需选择1项执行:(1)对你指定的角色出【杀】;(2)令你获得其一张牌。", + seyou_info: "限定技,出牌阶段,你可以指定任意1名角色,其他所有男性角色需选择1项执行:(1)对你指定的角色出【杀】;(2)令你获得其一张牌。", sheshi: "蛇噬", - sheshi_info: - "每受到1次伤害,可以指定1种花色,依次展示牌堆顶的牌,直到出现指定花色的牌为止,你获得与指定花色不同花色的所有牌(最多展示四张牌)。", + sheshi_info: "每受到1次伤害,可以指定1种花色,依次展示牌堆顶的牌,直到出现指定花色的牌为止,你获得与指定花色不同花色的所有牌(最多展示四张牌)。", fengyi: "凤仪", fengyi_info: "出牌阶段,你可以弃一张手牌,指定任意目标摸两张牌。(每回合限用一次)", wange: "婉歌", - wange_info: - "摸牌时,你可以少摸一张牌,则结束阶段你可以抽取一名其他角色的手牌,至少1张,至多X张(X为你当前的掉血量)。", + wange_info: "摸牌时,你可以少摸一张牌,则结束阶段你可以抽取一名其他角色的手牌,至少1张,至多X张(X为你当前的掉血量)。", nichang: "霓裳", nichang2: "霓裳", nichang_info: "摸牌时,你可以选择不摸牌,并在结束阶段展示手牌,每少一种花色摸一张牌。", fengyan: "丰艳", fengyan_info: "你可以获得其他男性角色的红色判定牌。", zhulu: "逐鹿", - zhulu_info: - "回合外,当有普通锦囊牌结算完毕后,你可以立即弃掉一张相同花色手牌或装备区的牌,获得这张锦囊牌。", + zhulu_info: "回合外,当有普通锦囊牌结算完毕后,你可以立即弃掉一张相同花色手牌或装备区的牌,获得这张锦囊牌。", jieyong: "节用", jieyong2: "节用", jieyong_info: "你使用的卡牌结算完成后,你可以弃置一张黑色牌并重新获得之。(每回合限一次)", shangtong: "尚同", shangtong_info: "每当你令其他角色恢复1点血量或掉1点血量时,你可以摸一张牌(摸牌上限为4)。", - feiming: "非命", - feiming_info: - "其他角色对你造成伤害时,你可以令该角色须选择1项执行:1,将1张红桃花色手牌交给你;2,失去1点血量。", yxsrenwang: "人望", - yxsrenwang_info: - "出牌阶段,你可以弃置两张牌并指定一名手牌数大于你的角色,你摸牌至与该角色手牌数相等,每阶段限一次。", + yxsrenwang_info: "出牌阶段,你可以弃置两张牌并指定一名手牌数大于你的角色,你摸牌至与该角色手牌数相等,每阶段限一次。", shiwei: "施威", - shiwei_info: - "当其他角色失去最后一张手牌时,你可以将牌堆顶的一张牌背面朝上置于该角色面前,该角色回合,跳过出牌阶段并弃掉这张牌。", + shiwei_info: "当其他角色失去最后一张手牌时,你可以将牌堆顶的一张牌背面朝上置于该角色面前,该角色回合,跳过出牌阶段并弃掉这张牌。", yxswushuang: "无双", - yxswushuang_info: - "出牌阶段,你使用【杀】时可同时打出两张【杀】,则该【杀】具有以下效果之一:1,伤害+1;2,额外指定两个目标。", + yxswushuang_info: "出牌阶段,你使用【杀】时可同时打出两张【杀】,则该【杀】具有以下效果之一:1,伤害+1;2,额外指定两个目标。", xiaoyong: "骁勇", xiaoyong_info: "你可以将黑色手牌当作【杀】来使用。", yxsqinzheng: "亲征", diff --git a/character/zhuogui.js b/character/zhuogui.js index 1aa6f7efc5..cf867ed739 100644 --- a/character/zhuogui.js +++ b/character/zhuogui.js @@ -15,7 +15,7 @@ game.import("character", function () { ai: { effect: { target: function (card, player, target, current) { - if (card.name == "lebu" && card.name == "bingliang") return 0.8; + if (card.name == "lebu" || card.name == "bingliang") return 0.8; }, }, }, @@ -200,7 +200,7 @@ game.import("character", function () { }, ai: { effect: { - target: function (card, player, target, current) { + target_use: function (card, player, target, current) { if (get.type(card) == "delay" && target.countCards("j") == 0) return 0.1; }, }, diff --git a/docker/docker.md b/docker/docker.md index 1a73ed3927..edcfae5afe 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -1,6 +1,6 @@ ### 使用 docker 运行 noname -/docker/index.js 来自[noname-server](https://github.com/nonameShijian/noname-server) +/docker/index.js.deprecated 来自[noname-server](https://github.com/nonameShijian/noname-server) 1.克隆存储库 diff --git a/docker/index.js b/docker/index.js deleted file mode 100644 index 39052fd8da..0000000000 --- a/docker/index.js +++ /dev/null @@ -1,311 +0,0 @@ -try { - const express = require("express"); - const minimist = require("minimist"); - const bodyParser = require("body-parser"); - const app = express(); - const fs = require("fs"); - const path = require("path"); - - const oneYear = 60 * 1000 * 60 * 24 * 365; - - // 解析命令行参数 - // 示例: -s --maxAge 100 - const argv = minimist(process.argv.slice(2), { - alias: { server: "s" }, - default: { maxAge: oneYear }, - }); - - app.use( - bodyParser.json({ - limit: "10240mb", - }) - ); - app.use( - bodyParser.urlencoded({ - limit: "10240mb", - extended: true, //需明确设置 - }) - ); - function join(url) { - return path.join(__dirname, url); - } - - function isInProject(url) { - return path.normalize(join(url)).startsWith(__dirname); - } - - // parse application/x-www-form-urlencoded - app.use(bodyParser.urlencoded({ extended: false })); - // parse application/json - app.use(bodyParser.json()); - - // 全局 中间件 解决所有路由的 跨域问题 - app.all("*", function (req, res, next) { - res.header("Access-Control-Allow-Origin", "*"); - res.header( - "Access-Control-Allow-Headers", - "X-Requested-With,Content-Type" - ); - res.header("Access-Control-Allow-Methods", "GET,POST,OPTIONS"); - next(); - }); - - // 根据参数设置 maxAge - const maxAge = argv.server ? argv.maxAge : 0; - - app.use(express.static(__dirname, { maxAge: maxAge })); - - app.get("/", (req, res) => { - res.send(fs.readFileSync(join("index.html"))); - }); - - app.get("/createDir", (req, res) => { - const { dir } = req.query; - if (!isInProject(dir)) { - throw new Error(`只能访问${__dirname}的文件或文件夹`); - } - if (!fs.existsSync(join(dir))) { - fs.mkdirSync(join(dir), { recursive: true }); - } else { - if (!fs.statSync(join(dir)).isDirectory()) { - throw new Error(`${join(dir)}不是文件夹`); - } - } - res.json(successfulJson(true)); - }); - - app.get("/removeDir", (req, res) => { - const { dir } = req.query; - if (!isInProject(dir)) { - throw new Error(`只能访问${__dirname}的文件或文件夹`); - } - if (fs.existsSync(join(dir))) { - if (!fs.statSync(join(dir)).isDirectory()) { - throw new Error(`${join(dir)}不是文件夹`); - } - fs.rmdirSync(join(dir), { recursive: true }); - } - res.json(successfulJson(true)); - }); - - app.get("/readFile", (req, res) => { - const { fileName } = req.query; - if (!isInProject(fileName)) { - throw new Error(`只能访问${__dirname}的文件或文件夹`); - } - if (fs.existsSync(join(fileName))) { - res.json( - successfulJson( - Array.prototype.slice.call( - new Uint8Array(fs.readFileSync(join(fileName))) - ) - ) - ); - } else { - res.json(failedJson(404, "文件不存在")); - } - }); - - app.get("/readFileAsText", (req, res) => { - const { fileName } = req.query; - if (!isInProject(fileName)) { - throw new Error(`只能访问${__dirname}的文件或文件夹`); - } - if (fs.existsSync(join(fileName))) { - res.json(successfulJson(fs.readFileSync(join(fileName), "utf-8"))); - } else { - res.json(failedJson(404, "文件不存在")); - } - }); - - app.post("/writeFile", (req, res) => { - const { path: p, data } = req.body; - if (!isInProject(p)) { - throw new Error(`只能访问${__dirname}的文件或文件夹`); - } - fs.mkdirSync(path.dirname(join(p)), { recursive: true }); - fs.writeFileSync(join(p), Buffer.from(data)); - res.json(successfulJson(true)); - }); - - app.get("/removeFile", (req, res) => { - const { fileName } = req.query; - if (!isInProject(fileName)) { - throw new Error(`只能访问${__dirname}的文件或文件夹`); - } - if (!fs.existsSync(join(fileName))) { - throw new Error(`文件不存在`); - } - const stat = fs.statSync(join(fileName)); - if (stat.isDirectory()) { - throw new Error("不能删除文件夹"); - } - fs.unlinkSync(join(fileName)); - res.json(successfulJson(true)); - }); - - app.get("/getFileList", (req, res) => { - const { dir } = req.query; - if (!isInProject(dir)) { - throw new Error(`只能访问${__dirname}的文件或文件夹`); - } - if (!fs.existsSync(join(dir))) { - throw new Error(`文件夹不存在`); - } - const stat = fs.statSync(join(dir)); - if (stat.isFile()) { - throw new Error("getFileList只适用于文件夹而不是文件"); - } - const files = [], - folders = []; - try { - fs.readdir(join(dir), (err, filelist) => { - if (err) { - res.json(failedJson(500, String(err))); - return; - } - for (let i = 0; i < filelist.length; i++) { - if (filelist[i][0] != "." && filelist[i][0] != "_") { - if ( - fs - .statSync(join(dir) + "/" + filelist[i]) - .isDirectory() - ) { - folders.push(filelist[i]); - } else { - files.push(filelist[i]); - } - } - } - res.json(successfulJson({ folders, files })); - }); - } catch (e) { - res.json(failedJson(500, String(e))); - } - }); - - app.get("/checkFile", (req, res) => { - const { fileName } = req.query; - if (!isInProject(fileName)) { - throw new Error(`只能访问${__dirname}的文件或文件夹`); - } - try { - if (fs.statSync(join(fileName)).isFile()) { - res.json(successfulJson()); - } else { - res.json(failedJson(404, "不是一个文件")); - } - } catch (error) { - res.json(failedJson(404, "文件不存在或无法访问")); - } - }); - - app.get("/checkDir", (req, res) => { - const { dir } = req.query; - if (!isInProject(dir)) { - throw new Error(`只能访问${__dirname}的文件或文件夹`); - } - try { - if (fs.statSync(join(dir)).isDirectory()) { - res.json(successfulJson()); - } else { - res.json(failedJson(404, "不是一个文件夹")); - } - } catch (error) { - res.json(failedJson(404, "文件夹不存在或无法访问")); - } - }); - - app.use((req, res, next) => { - res.status(404).send("Sorry can't find that!"); - }); - - app.use(function (err, req, res, next) { - console.log(err); - return res.json(failedJson(400, String(err))); - }); - - app.listen(8089, () => { - console.log("应用正在使用 8089 端口以提供无名杀本地服务器功能!"); - if (!process.argv[2]) - require("child_process").exec("start http://localhost:8089/"); - }); - - class ReturnData { - success; - - code; - - errorMsg; - - data; - - constructor() {} - - getSuccess() { - return this.success; - } - - setSuccess(success) { - this.success = success; - } - - getCode() { - return this.code; - } - - setCode(errorCode) { - this.code = errorCode; - } - - getErrorMsg() { - return this.errorMsg; - } - - setErrorMsg(errorMsg) { - this.errorMsg = errorMsg; - } - - getData() { - this.data; - } - - setData(data) { - this.data = data; - } - } - - /** - * Business is successful. - * - * @param data return data. - * - * @return json. - */ - function successfulJson(data) { - const returnData = new ReturnData(); - returnData.setSuccess(true); - returnData.setCode(200); - returnData.setData(data); - return returnData; - } - - /** - * Business is failed. - * - * @param code error code. - * @param message message. - * - * @return json. - */ - function failedJson(code, message) { - const returnData = new ReturnData(); - returnData.setSuccess(false); - returnData.setCode(code); - returnData.setErrorMsg(message); - return returnData; - } -} catch (e) { - console.error("本地服务器启动失败: "); - console.error(e); -} diff --git a/docker/start.sh b/docker/start.sh index 09ed3817ed..940ed8eec4 100644 --- a/docker/start.sh +++ b/docker/start.sh @@ -1,2 +1,2 @@ -node noname-server.js --server & -(cd game && node server.js) +node --experimental-default-type=module noname-server.js --server & +(cd game && node --experimental-default-type=commonjs server.js) diff --git a/docs/async-guide.md b/docs/async-guide.md index 86ce6a3a01..07ca741e51 100644 --- a/docs/async-guide.md +++ b/docs/async-guide.md @@ -1,6 +1,6 @@ # Async 章节 -无名杀在v1.10.6的时候由 @nonameShijian 引入了一种全新的技能效果代码写法,这种写法与原有写法最大的区别在于,这种写法的content函数是一个带有`async`标识符的函数,而不是原来存在`step`字样的普通函数。 +无名杀在v1.10.6的时候由 @nonameShijian 引入了一种全新的技能效果代码写法,这种写法与原有写法最大的区别在于,这种写法的content函数是一个带有 `async`标识符的函数,而不是原来存在 `step`字样的普通函数。 比如原来的写法是: @@ -26,21 +26,21 @@ let skill = { } ``` -我们称这种新的写法叫做`Async Content`;为了区分,我们将原来那种写法称作`Step Content` +我们称这种新的写法叫做 `Async Content`;为了区分,我们将原来那种写法称作 `Step Content` -相比于原来的`Step Content`,`Async Content`在设计上更加贴近原有的Javascript语法,并且能很方便的实现之前`Step Content`无法做到或很难做到的事情,故无名杀未来更新武将的技能代码中将主要使用这种形式,这也将成为无名杀未来的开发方向 +相比于原来的 `Step Content`,`Async Content`在设计上更加贴近原有的Javascript语法,并且能很方便的实现之前 `Step Content`无法做到或很难做到的事情,故无名杀未来更新武将的技能代码中将主要使用这种形式,这也将成为无名杀未来的开发方向 本章节将简单的介绍: -- 了解`async`函数 -- `Async Content`的形式与使用 -- `Async Content`相比原有形式的优势 +- 了解 `async`函数 +- `Async Content`的形式与使用 +- `Async Content`相比原有形式的优势 > 此章节面向于JavaScript基础稍微薄弱的,对于async函数相关用法不熟悉的开发者,所以本章节在编写时偏向于技能写法,而不是专业的JavaScript异步编程讲解,如果想要了解更加详细的JavaScript异步编程,请参考[JavaScript异步编程指南](https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Asynchronous) -## 一、了解`async`函数 +## 一、了解 `async`函数 -一般来说,async函数只需要在函数的声明前加上`async`标识符即可,如: +一般来说,async函数只需要在函数的声明前加上 `async`标识符即可,如: ```javascript // 命名函数 @@ -52,10 +52,10 @@ let anonymous = async function () { ... } 被标记为async的函数拥有以下特性: -- 必然返回一个Promise对象 -- 可以在async函数中使用`await`来等待一个Promise对象 +- 必然返回一个Promise对象 +- 可以在async函数中使用 `await`来等待一个Promise对象 -此时我们就又引入了两个概念:`Promise`和`await` +此时我们就又引入了两个概念:`Promise`和 `await` ### `Promise` @@ -63,7 +63,7 @@ Promise是JavaScript中的一种异步编程解决方案,它允许你以一种 在最初的Javascript异步编程中,我们通常使用回调函数来处理异步操作,但是这种方式存在一些问题,比如回调地狱和难以阅读 -我们会在后文需要用到`Promise`的地方再介绍这个概念,这里仅作提出 +我们会在后文需要用到 `Promise`的地方再介绍这个概念,这里仅作提出 由于无名杀编写技能并不会出现回调地狱的情况,所以这里我们不会对Promise进行过多的介绍,如果你对Promise感兴趣,可以参考[Promise对象](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise) @@ -71,17 +71,17 @@ Promise是JavaScript中的一种异步编程解决方案,它允许你以一种 `await`是JavaScript中的一个关键字,它允许你在async函数中等待一个Promise对象的状态发生变化 -`await`与`async`共同组成了新的异步形态,使`Javascript`的异步能像同步代码般编写 +`await`与 `async`共同组成了新的异步形态,使 `Javascript`的异步能像同步代码般编写 -事实上,`await`不仅会等待一个`Promise`事件,它还能等待别的符合要求的东西,这类东西我们称作可`await`的东西;我们将在后文再次介绍这个概念 +事实上,`await`不仅会等待一个 `Promise`事件,它还能等待别的符合要求的东西,这类东西我们称作可 `await`的东西;我们将在后文再次介绍这个概念 -如果你对`await`感兴趣,可以参考[async 和 await](https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Asynchronous/Promises#async_%E5%92%8C_await),本章节仅针对无名杀技能中使用的`await`进行介绍 +如果你对 `await`感兴趣,可以参考[async 和 await](https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Asynchronous/Promises#async_%E5%92%8C_await),本章节仅针对无名杀技能中使用的 `await`进行介绍 ## 二、`Async Content`的形式与使用 ### 1. `Async Content`怎么用 -我们先来看看一个`Step Content`的技能: +我们先来看看一个 `Step Content`的技能: ```javascript let skill = { @@ -97,7 +97,7 @@ let skill = { 这个技能对应的描述是: `当你回合开始时,你摸两张牌` -然后我们再来看一个`Async Content`的技能: +然后我们再来看一个 `Async Content`的技能: ```javascript let skill = { @@ -112,34 +112,34 @@ let skill = { 这两处代码有下面几处变化: -1. 添加了`async`在函数前面 +1. 添加了 `async`在函数前面 2. 添加了三个参数: `event`,`trigger`,`player` -3. 函数里面的`"step 0"`被删除了 -4. `player.draw`之前添加了`await` +3. 函数里面的 `"step 0"`被删除了 +4. `player.draw`之前添加了 `await` 接下来我们来具体聊聊这些改变究竟带来了什么 -### 2. `Async Content`相对于`Step Content`的有啥变化 +### 2. `Async Content`相对于 `Step Content`的有啥变化 -`Async Content`可以让`content`这类step写法的函数贴近普通的函数 +`Async Content`可以让 `content`这类step写法的函数贴近普通的函数 -例如,函数`filter`要求你写出`(event, player, name)`参数,然后你才可以用`event`/`player`/`name`三个变量 +例如,函数 `filter`要求你写出 `(event, player, name)`参数,然后你才可以用 `event`/`player`/`name`三个变量 -而`Async Content`也是如此,你需要写出`(event, trigger, player)`三个由无名杀提供的参数才能使用`event`/`trigger`/`player`三个变量 +而 `Async Content`也是如此,你需要写出 `(event, trigger, player)`三个由无名杀提供的参数才能使用 `event`/`trigger`/`player`三个变量 -这样的好处是统一规范了函数写法,减少了新开发者的疑惑,你所使用的`event`/`trigger`/`player`都是你看得到的 +这样的好处是统一规范了函数写法,减少了新开发者的疑惑,你所使用的 `event`/`trigger`/`player`都是你看得到的 -到这里你可能会反应过来,平常在`step`写法中经常直接使用`card`/`target`/`num`等变量,现在参数里面没有这些变量,要怎么样引用这些变量呢? +到这里你可能会反应过来,平常在 `step`写法中经常直接使用 `card`/`target`/`num`等变量,现在参数里面没有这些变量,要怎么样引用这些变量呢? -如果你稍微了解过Javascript的语法,你应该明白`Step Content`的`step x`本应该没任何作用,而无名杀中则通过动态编译使`step x`转换成了普通的Javascript代码,而这一过程中同时将`card`/`target`/`num`等变量注入在函数参数内,使得我们能直接调用 +如果你稍微了解过Javascript的语法,你应该明白 `Step Content`的 `step x`本应该没任何作用,而无名杀中则通过动态编译使 `step x`转换成了普通的Javascript代码,而这一过程中同时将 `card`/`target`/`num`等变量注入在函数参数内,使得我们能直接调用 -而`card`/`target`/`num`等变量,均为`event`的属性;换言之,我们用`event.card`/`event.target`/`event.num`就可以代替原本的`card`/`target`/`num`这些变量了 +而 `card`/`target`/`num`等变量,均为 `event`的属性;换言之,我们用 `event.card`/`event.target`/`event.num`就可以代替原本的 `card`/`target`/`num`这些变量了 -你或许已经注意到了,`Async Content`省去了编译过程。在原有的`Step Content`中,如果函数出现报错,会发现提示的报错位置是一个`VM xx`,这个标识就是Javascript引擎存储动态编译代码的地方,但这种情况下我们的调试问题将受到影响。而`Async Content`不会经过动态编译,故报错/调试代码将会变得更加简单 +你或许已经注意到了,`Async Content`省去了编译过程。在原有的 `Step Content`中,如果函数出现报错,会发现提示的报错位置是一个 `VM xx`,这个标识就是Javascript引擎存储动态编译代码的地方,但这种情况下我们的调试问题将受到影响。而 `Async Content`不会经过动态编译,故报错/调试代码将会变得更加简单 -值得注意的是,`event.step`变量在async函数中不再有意义,因为没有了`step`标注,本体也无法确定async函数执行到了哪一步,自然`event.step`的值也就没有了意义 +值得注意的是,`event.step`变量在async函数中不再有意义,因为没有了 `step`标注,本体也无法确定async函数执行到了哪一步,自然 `event.step`的值也就没有了意义 -### 3. 那么`Async Content`如何写出分步的效果呢? +### 3. 那么 `Async Content`如何写出分步的效果呢? 上文已经提到过,`Step Content`会经过动态编译 @@ -171,9 +171,9 @@ let skill = { 而分步的作用正是等待这一步所有结算完成,再执行下一步 -如果不分步就执行`countCards`,会导致我们读取的是摸牌前的手牌数量(因为此时摸牌还没开始),从而导致效果与描述不一致 +如果不分步就执行 `countCards`,会导致我们读取的是摸牌前的手牌数量(因为此时摸牌还没开始),从而导致效果与描述不一致 -在经过动态编译后,content函数会变成这样: +在经过动态编译后(v1.10.15前),content函数会变成这样: ```javascript let skill = { @@ -200,9 +200,9 @@ let skill = { 很抱歉我在此处使用了很丑陋的代码,但这确实是编译后理应拥有的结果。 -我们发现,编译后的`content`函数,在`event.step == 0`时,会只执行到`player.draw(2);`,然后结束函数的执行;无名杀引擎会自动让`event.step++`,然后等待摸牌结束后,再次执行这个函数。此时我们的`event.step == 1`,就会开始检查手牌是否大于5,然后根据情况决定是否执行弃牌。 +我们发现,编译后的 `content`函数,在 `event.step == 0`时,会只执行到 `player.draw(2);`,然后结束函数的执行;无名杀引擎会自动让 `event.step++`,然后等待摸牌结束后,再次执行这个函数。此时我们的 `event.step == 1`,就会开始检查手牌是否大于5,然后根据情况决定是否执行弃牌。 -此时如果我们要在弃牌后才开始获得标记,就需要在选择弃牌和获得标记间添加新的`step`,这样就会变成下面的情况: +此时如果我们要在弃牌后才开始获得标记,就需要在选择弃牌和获得标记间添加新的 `step`,这样就会变成下面的情况: ```javascript function (...) { @@ -222,9 +222,9 @@ function (...) { } ``` -这样我们就会在`player.chooseToDiscard`后才开始获得标记 +这样我们就会在 `player.chooseToDiscard`后才开始获得标记 -综上所述,我们已经明白了`Step Content`的基本原理。而不难发现,`Step Content`所作的一切,大部分情况下,是为了**等事件运行完**。 +综上所述,我们已经明白了 `Step Content`的基本原理。而不难发现,`Step Content`所作的一切,大部分情况下,是为了**等事件运行完**。 虽然我们并未详细讲过什么是“异步”,但你大概能反应过来,上面所说的“等事件运行完”,就是异步。 @@ -248,11 +248,11 @@ let skill = { }; ``` -我们可以看到分步没有了,取而代之的是每次操作前面附加了一个`await`;这个`await`表示的是,会等待后面的代码运行完毕,再执行后续的代码 +我们可以看到分步没有了,取而代之的是每次操作前面附加了一个 `await`;这个 `await`表示的是,会等待后面的代码运行完毕,再执行后续的代码 而此时,你可能会有疑惑:如果我现在需要获得所摸的牌,我该怎么办? -原先分步情况下你可以在下一步中用`result`变量来获取上一步事件的结果,而现在,当我们`await`之后,我们可以这样做: +原先分步情况下你可以在下一步中用 `result`变量来获取上一步事件的结果,而现在,当我们 `await`之后,我们可以这样做: ```javascript let drawEvent = await player.draw(2); @@ -260,11 +260,11 @@ let drawEvent = await player.draw(2); 你或许也发现了,无论是无名杀的分步,还是Javascript原来的回调异步,都会存在“结果”。就好比你做一件事,就算最后没有因为这件事得到任何东西,此时的情况也是一种“结果” -而`await`也同理,在等待事件结束后,便会得到这个“结果”。而对于`player.draw(2)`这种常见的,需要分步得到`result`的,我们称之为“事件“的东西,`await`后返回的,是事件本身;而事件的结果,则是该事件的`result`属性 +而 `await`也同理,在等待事件结束后,便会得到这个“结果”。而对于 `player.draw(2)`这种常见的,需要分步得到 `result`的,我们称之为“事件“的东西,`await`后返回的,是事件本身;而事件的结果,则是该事件的 `result`属性 -我们把“`await`后会等待后续事物执行完毕,并返回新的东西”的东西,简单的称作能`await`的东西;在后文中我们会再次讨论这块的内容 +我们把“`await`后会等待后续事物执行完毕,并返回新的东西”的东西,简单的称作能 `await`的东西;在后文中我们会再次讨论这块的内容 -换句话说,摸牌函数返回的`drawEvent`事件,是一个可`await`的东西;而`await`一个事件,就是等待一个事件运行结束,并获取这个事件本身 +换句话说,摸牌函数返回的 `drawEvent`事件,是一个可 `await`的东西;而 `await`一个事件,就是等待一个事件运行结束,并获取这个事件本身 故我们接下来就能这样获取我们所摸的牌: @@ -272,7 +272,7 @@ let drawEvent = await player.draw(2); let cards = drawEvent.result; ``` -如果你不需要事件,只需要对应的结果,无名杀提供了对应的方法,你可以使用`forResult`函数: +如果你不需要事件,只需要对应的结果,无名杀提供了对应的方法,你可以使用 `forResult`函数: ```javascript let cards = await player.draw(2).forResult(); @@ -284,9 +284,9 @@ let cards = await player.draw(2).forResult(); let { result: cards } = await player.draw(2); ``` -两种方法都能得到结果,只要不混用就行;如果你对Javascript的新语法不熟悉,只需要简单的使用`forResult`就行 +两种方法都能得到结果,只要不混用就行;如果你对Javascript的新语法不熟悉,只需要简单的使用 `forResult`就行 -实际上`await`没有那么死板,你完全可以把`await`放在任何你想要的地方,只有能`await`的情况才会等待,反之会原封不动的将值返回过来 +实际上 `await`没有那么死板,你完全可以把 `await`放在任何你想要的地方,只有能 `await`的情况才会等待,反之会原封不动的将值返回过来 就比如,你可以: @@ -294,25 +294,25 @@ let { result: cards } = await player.draw(2); await player.addTempSkill("jiang"); ``` -`player.addTempSkill`并不需要等待,但你等待也不会出啥问题,此时`await`后的返回值仍然是`player.addTempSkill`原有的返回值;`await`只会处理需要等待的东西 +`player.addTempSkill`并不需要等待,但你等待也不会出啥问题,此时 `await`后的返回值仍然是 `player.addTempSkill`原有的返回值;`await`只会处理需要等待的东西 ### 4. 一些原有操作的代替品 如果你了解无名杀的技能代码,你一定会知道下面三个函数: -- `event.goto`: 跳转到指定步 -- `event.redo`: 重新执行当前步 -- `event.finish`: 结束当前事件 +- `event.goto`: 跳转到指定步 +- `event.redo`: 重新执行当前步 +- `event.finish`: 结束当前事件 -如果要使用`Async Content`,那么这些函数自然需要替换,因为已经不再需要`step`这个概念了;至于`event.finish`,因为`Async Content`的机制很复杂,故将`event.finish`的操作交给无名杀会是个更好的选择 +如果要使用 `Async Content`,那么这些函数自然需要替换,因为已经不再需要 `step`这个概念了;至于 `event.finish`,因为 `Async Content`的机制很复杂,故将 `event.finish`的操作交给无名杀会是个更好的选择 -#### 代替`event.finish` +#### 代替 `event.finish` -我们先从`event.finish`开始,它的作用是结束当前事件,那么如何替代它呢? +我们先从 `event.finish`开始,它的作用是结束当前事件,那么如何替代它呢? `Async Content`的核心就是使用async函数,而且我们只会执行一遍async函数;也就是说,如果我们要结束一个事件,只需要结束这个函数的执行就行。那如果要退出一个函数,你会使用什么呢? -我们知道,`return`语句会中断函数的执行,并将后面的值作为函数的返回值。那么,对于`Async Content`,我们只需要在需要结束的时候提前`return`,就能达到效果。 +我们知道,`return`语句会中断函数的执行,并将后面的值作为函数的返回值。那么,对于 `Async Content`,我们只需要在需要结束的时候提前 `return`,就能达到效果。 也就是说你可以把 @@ -326,29 +326,25 @@ if (!result.bool) event.finish(); if (!result.bool) return; ``` -同时,如果你在分步中使用`event.finish()`结束事件,代码并不会立刻停止执行,当前步后面的代码依旧会继续执行,直到当前步结束为止。如果你要阻止后续代码的执行,你还需要额外进行处理才能不继续执行后续代码 +同时,如果你在分步中使用 `event.finish()`结束事件,代码并不会立刻停止执行,当前步后面的代码依旧会继续执行,直到当前步结束为止。如果你要阻止后续代码的执行,你还需要额外进行处理才能不继续执行后续代码 -而`return`会立刻停止函数执行,不需要你再额外进行处理 +而 `return`会立刻停止函数执行,不需要你再额外进行处理 -当然你可能会问,`Async Content`需不需要确切的返回值?不需要,甚至不应该要,因为实现的复杂性,如果你返回了一个可`await`的东西,那么无名杀也会等后面的东西执行完毕才认为这个函数执行完毕,而这可能会导致这个函数循环等待而永远无法执行完毕;故在任何情况下,`Async Content`的`return`后面都不应该跟任何东西 +当然你可能会问,`Async Content`需不需要确切的返回值?不需要,甚至不应该要,因为实现的复杂性,如果你返回了一个可 `await`的东西,那么无名杀也会等后面的东西执行完毕才认为这个函数执行完毕,而这可能会导致这个函数循环等待而永远无法执行完毕;故在任何情况下,`Async Content`的 `return`后面都不应该跟任何东西 -就比如,如果你尝试`return event.finish()`这条在`Step Content`中非常常见的代码,由于`event.finish()`会返回被结束的事件,故`event`的函数就会等待`event`的结束——而在`event`的函数执行完前,`event`都不会结束,故此时`event`将永远无法执行完成,这也是非常经典的循环引用 - -如果你因为一些操作必须得有,请使用`void`语句,这个语句会无视后面的值,一律返回`undefined`,比如: +如果你因为一些操作必须得有,请使用 `void`语句,这个语句会无视后面的值,一律返回 `undefined`,比如: ```javascript return void await player.draw(2); ``` -我们不但等待了`player.draw`,而且返回的内容也是`undefined` - -> 实际上,我们现在所提到的事件,比如`player.draw`所返回的东西,实际上并不是`GameEvent`,而是`GameEventPromise`,前者并不是可`await`的东西,而后者是。`GameEventPromise`的诞生就是为了使无名杀的事件成为一个可`await`的东西,这里面涉及到一些复杂的实现,本章节不在此阐述。你可以对一个`GameEventPromise`使用`toEvent`函数来获取本身的事件,如`player.draw(2).toEvent()`;你也可以对一个事件本身调用`toPromise`函数来获取对应的`GameEventPromise` +我们不但等待了 `player.draw`,而且返回的内容也是 `undefined` -#### 代替`event.goto`与`event.redo` +#### 代替 `event.goto`与 `event.redo` -如果你曾看过远古计算机代码,你或许会发现,`Step Content`的`evnet.goto`和`event.redo`,很有当年的循环风格。但事实证明,这种风格在代码复杂起来时,会变得难以维护,故我们必然会寻找方法替代——故我们发明了循环语句 +如果你曾看过远古计算机代码,你或许会发现,`Step Content`的 `evnet.goto`和 `event.redo`,很有当年的循环风格。但事实证明,这种风格在代码复杂起来时,会变得难以维护,故我们必然会寻找方法替代——故我们发明了循环语句 -比如下面这段代码使用了`event.redo`: +比如下面这段代码使用了 `event.redo`: ```javascript let target = event.targets.shift(); @@ -367,7 +363,7 @@ while (event.targets.length) { 这样写出来的代码也更加清晰,你可以一眼看出来这是一个循环,对吧? -当然,因为我们已经用上了循环,不再需要通过`event.targets.length`来区分有没有遍历完,所以我们甚至能直接这样写: +当然,因为我们已经用上了循环,不再需要通过 `event.targets.length`来区分有没有遍历完,所以我们甚至能直接这样写: ```javascript for (let target of event.targets) { @@ -375,50 +371,42 @@ for (let target of event.targets) { } ``` -而`event.goto`也是同理,你可以用`if`、`while`、`for`、`break`、`continue`等语句来代替它,从而达到更好的可读性 +而 `event.goto`也是同理,你可以用 `if`、`while`、`for`、`break`、`continue`等语句来代替它,从而达到更好的可读性 -这块的内容由于因具体情况会变得异常复杂,故本章节将本块内容当成附加内容,将在后文补充一些个人的方法和习惯;本体的标准包代码已全面换成`Async Content`的形式,可前往学习。 +这块的内容由于因具体情况会变得异常复杂,故本章节将本块内容当成附加内容,将在后文补充一些个人的方法和习惯;本体的标准包代码已全面换成 `Async Content`的形式,可前往学习。 ### 5. async使用的一些细节补充 -看到这里,你对于`Async Content`的大致特点已经掌握,那接下来我们就来对一些实战中可能遇到的问题进行补充吧 +看到这里,你对于 `Async Content`的大致特点已经掌握,那接下来我们就来对一些实战中可能遇到的问题进行补充吧 -#### 1. 什么情况下必须要使用`await`? +#### 1. 什么情况下必须要使用 `await`? -我们都知道,在Javascript中,`await`一个不需要`await`的东西不会有任何问题,故你可以在任何操作下都尝试`await`。但这会让代码的无用`await`变得很多,所以我们需要判断什么时候该用`await` +我们都知道,在Javascript中,`await`一个不需要 `await`的东西不会有任何问题,故你可以在任何操作下都尝试 `await`。但这会让代码的无用 `await`变得很多,所以我们需要判断什么时候该用 `await` 非常幸运,在无名杀中,你可以查看操作是否有以下情况: -1. 会触发时机。触发时机意味着可能进行插入结算,你需要等待所有插入结算的完成,故而使用`await`(包括使用`event.trigger`来主动触发时机也需要`await`) -2. 等待玩家确认。如果有个操作需要玩家点击确认,或者会弹出窗口给玩家查看时,你需要等待玩家确认完毕,所以也使用`await` -3. `asyncDelay`/`asyncDelayx`等带`async`字符的函数,这些操作一般都会返回一个可`await`的东西,故我们需要`await`来保证函数执行完毕 +1. 会触发时机。触发时机意味着可能进行插入结算,你需要等待所有插入结算的完成,故而使用 `await`(包括使用 `event.trigger`来主动触发时机也需要 `await`) +2. 等待玩家确认。如果有个操作需要玩家点击确认,或者会弹出窗口给玩家查看时,你需要等待玩家确认完毕,所以也使用 `await` +3. `asyncDraw`等带 `async`字符的函数,这些操作一般都会返回一个可 `await`的东西,故我们需要 `await`来保证函数执行完毕 -顺带一提,有些异步的情况不能用`await`来等待,或者说使用`await`并不会起到效果。这类情况基本上都是无名杀的古老异步代码,因为在那个时代并不存在`Promise`,且没人尝试在后来适配这些异步代码,所以你只能通过原先给定的特殊方式来等待,比如说回调函数 +顺带一提,有些异步的情况不能用 `await`来等待,或者说使用 `await`并不会起到效果。这类情况基本上都是无名杀的古老异步代码,因为在那个时代并不存在 `Promise`,且没人尝试在后来适配这些异步代码,所以你只能通过原先给定的特殊方式来等待,比如说回调函数 #### 2. delay与delayx -需要注意的是,在`Async Content`里面,我们不能再使用`game.delay`/`game.delayx`/`game.resume`这三样了,我们需要替代方案 - -本体对于这种情况已经准备好了,来看看这两个新函数: +在 `Async Content`里面,当使用 `game.delay`/`game.delayx`时,我们也可以进行 `await`: ```javascript -await game.asyncDelay(); -await game.asyncDelayx(); +await game.delay(); +await game.delayx(); ``` -请注意哦,他们必须加上`await`,否则是不会产生任何效果的 - -那么有了这两个函数,你在编写代码时就可以进行替换了哦 - -将`game.delay()`替换为`await game.asyncDelay()`、`game.delayx()`替换为`await game.asyncDelayx()`,即可在async函数中实现类似的效果 - #### 3. Promise的使用 -上面我们提到了`game.resume`不能在async函数中使用,但是我们没有给出解决方案——这是因为使用`game.resume`需要我们会使用`Promise` +除了 `game.resume`外,我们还可以使用 `Promise`来实现类似的功能。 **Promise的概念** -在之前介绍async函数的时候,我们就稍微提到过这个概念;我们当时说`Promise`是无名杀的一种异步解决方案;这里我们不得不简单说明下`Promise`的历史,来理解`Promise`的诞生 +在之前介绍async函数的时候,我们就稍微提到过这个概念;我们当时说 `Promise`是无名杀的一种异步解决方案;这里我们不得不简单说明下 `Promise`的历史,来理解 `Promise`的诞生 当时人们为了解决回调地狱,就开始着手设计新的异步形态,同时要比较方便的兼容原有异步;此时就有人尝试提出了这样的概念: @@ -451,17 +439,17 @@ someAsyncFunction() .then(...) ``` -而要实现链式调用,就需要一个对象来承载:这就是`Promise`的诞生,它将原本的回调地狱变成了链式调用,让代码变得清晰易懂 +而要实现链式调用,就需要一个对象来承载:这就是 `Promise`的诞生,它将原本的回调地狱变成了链式调用,让代码变得清晰易懂 `Promise`类似于一个通知,比如你点了一份外卖,如果你要知道外卖有没有完成,你肯定是查看外卖app是否显示已送达 而不是跑到楼下去看看外卖员有没有到对吧? -`Promise`此时充当了一个外卖app的作用,当你对它使用`await`时,你的代码会暂停执行,等待`Promise`提供者确认任务完成之后,`Promise`就会结束你代码的等待,并继续向下执行 +`Promise`此时充当了一个外卖app的作用,当你对它使用 `await`时,你的代码会暂停执行,等待 `Promise`提供者确认任务完成之后,`Promise`就会结束你代码的等待,并继续向下执行 -> 我们前文说过,可`await`的东西不一定是`Promise`,实际上满足[Promise A+](https://promisesaplus.com/)标准的都是可`await`的东西,感兴趣的可以了解一下 +> 我们前文说过,可 `await`的东西不一定是 `Promise`,实际上满足[Promise A+](https://promisesaplus.com/)标准的都是可 `await`的东西,感兴趣的可以了解一下 **Promise的语法** -我们来看看`Promise`的创建: +我们来看看 `Promise`的创建: ```javascript let promise = new Promise((resolve, reject) => { ... }); @@ -469,21 +457,21 @@ let promise = new Promise((resolve, reject) => { ... }); 和其他对象一样,`Promise`也是通过构造函数构建的,而构造函数则接收一个回调函数——毕竟要取代原来的回调函数,你也必须提供一个回调函数 -而回调函数则接收两个参数,这两个参数分别对应`resolve`与`reject`,这两个参数都是`Promise`提供的回调函数,其中`resolve`则表示,一切顺利后,使用这个回调函数,而`reject`则表示出问题后使用这个回调函数 +而回调函数则接收两个参数,这两个参数分别对应 `resolve`与 `reject`,这两个参数都是 `Promise`提供的回调函数,其中 `resolve`则表示,一切顺利后,使用这个回调函数,而 `reject`则表示出问题后使用这个回调函数 -这两个回调函数都可以接收一个参数,这个参数将会被`Promise`储存下来,而你可以通过`await`这个`Promise`来获取这个值(当然如果`reject`了就改为报错) +这两个回调函数都可以接收一个参数,这个参数将会被 `Promise`储存下来,而你可以通过 `await`这个 `Promise`来获取这个值(当然如果 `reject`了就改为报错) -在最新的Javascript中,提供了一个函数`Promise.withResolvers`,这个函数会将`Promise`本身和其`resolve`和`reject`包含在一个对象中返回;当你代码中的`resolve`和`reject`需要和`Promise`对象同一作用域时,就能使用这个函数,如下面所示: +在最新的Javascript中,提供了一个函数 `Promise.withResolvers`,这个函数会将 `Promise`本身和其 `resolve`和 `reject`包含在一个对象中返回;当你代码中的 `resolve`和 `reject`需要和 `Promise`对象同一作用域时,就能使用这个函数,如下面所示: ```javascript let { promise, resolve, reject } = Promise.withResolvers(); ``` -在后文中,为了防止演示代码的层级过多,我们将统一使用`Promise.withResolvers`来创建`Promise`,尽管大部分例子下直接用构造函数创建`Promise`会更简洁 +在后文中,为了防止演示代码的层级过多,我们将统一使用 `Promise.withResolvers`来创建 `Promise`,尽管大部分例子下直接用构造函数创建 `Promise`会更简洁 **代码演示** -接下来我们来看看如何用`Promise`演示外卖送达的流程 +接下来我们来看看如何用 `Promise`演示外卖送达的流程 ```javascript // 外卖平台部分 @@ -505,19 +493,19 @@ let waimaiPromise = dianCan() // 调用并获取promise await waimaiPromise // 等待外卖送达 ``` -从上面可以看出,如果要使用`Promise`,我们需要三个部分: +从上面可以看出,如果要使用 `Promise`,我们需要三个部分: -1. 创建`Promise` -2. 等待`Promise` -3. 通知`Promise` +1. 创建 `Promise` +2. 等待 `Promise` +3. 通知 `Promise` **使用示例** -那么我们来实现一个简单的效果,用`await`暂停代码5秒: +那么我们来实现一个简单的效果,用 `await`暂停代码5秒: -我们的思路应该是这样的,首先我们肯定要创建一个`Promise`,这样才可以使用`await` +我们的思路应该是这样的,首先我们肯定要创建一个 `Promise`,这样才可以使用 `await` -然后我们要在5秒后执行`resolve`函数,让`await`结束等待 +然后我们要在5秒后执行 `resolve`函数,让 `await`结束等待 ```javascript var { promise, resolve } = Promise.withResolvers(); // 创建promise @@ -525,44 +513,19 @@ setTimeout(resolve, 5000); // 将resolve传递给setTimeout,setTimeout是一 await promise; // 等待直到resolve在5秒后被调用 ``` -你有没有发现,我们已经实现了类似`game.asyncDelay`的功能了;而事实上无名杀本体的`game.asyncDelay`也就是使用这种方式实现的功能 +你有没有发现,我们已经实现了类似 `game.delay`的功能了;而事实上无名杀本体的 `game.delay`也就是使用这种方式实现的功能 -当你掌握了`Promise`的使用时,你就可以进入下面的一节了 +当你掌握了 `Promise`的使用时,你就可以进入下面的一节了 #### 4. pause与resume -`game.pause`与`game.resume`是一对游戏内暂停函数,与玩家暂停不同,它们用于`等待游戏动画`/`等待玩家确定`这类耗时的操作时使用 - -在分步中,如果你要等待玩家按下确定再执行下一步,你需要先执行`game.pause`,这将启动游戏内暂停,直到你执行`game.resume`之前,下一步都不会执行 - -而到了async函数里面,`game.resume`不再可以使用,这会导致事件被重复执行,出现不可预料的问题 - -那么如果要实现原来的效果要如何做呢? - -这就要用到我们的`Promise`了,假设`button`是一个按钮,我们要等待按钮按下再继续执行,这种代码应该这样写: - -```javascript -// 创建一个Promise来等待 -let { promise, resolve } = Promise.withResolvers(); - -// 监听按钮点击,当按钮点击时执行大括号里面的代码 -button.listen(() => { - _status.paused = false; // 手动关闭游戏内暂停,而不是执行`game.resume` - resolve(); // 结束await的等待 - game.log("玩家点击了按钮"); -}); - -// 启动游戏内暂停 -game.pause(); -// 暂停代码的执行并等待点击 -await promise; -``` +`game.pause`与 `game.resume`是一对游戏内暂停函数,与玩家暂停不同,它们用于 `等待游戏动画`/`等待玩家确定`这类耗时的操作时使用 -这里可能会有人疑惑,为什么已经用了`Promise`还要追加`game.pause`? +在分步中,如果你要等待玩家按下确定再执行下一步,你需要先执行 `game.pause`,这将启动游戏内暂停,直到你执行 `game.resume`之前,下一步都不会执行 -这是因为`Promise`只是暂停了当前代码的执行,并没有启动`游戏内暂停`,这会导致游戏其他部分并不知道已经暂停了,我们需要补充`game.pause`来告诉游戏已经暂停 +而到了async函数里面,我们可以使用更加优雅的办法(`Promise`)来替代 `game.pause`与 `game.resume`: -在v1.10.13后,`Async Content`中已经不再需要`game.pause`,故你可以这样写: +假设 `button`是一个按钮,我们要等待按钮按下再继续执行,这种代码应该这样写: ```javascript // 创建一个Promise来等待 @@ -578,7 +541,7 @@ button.listen(() => { await promise; ``` -当然,你为了兼容旧版本,你也可以继续使用`game.pause`,这在新版本中只是没有效果,但并不会造成错误或者其他影响 +当然,你也可以继续使用 `game.pause`,这并不会造成错误或者其他影响 #### 5. async的其他优势 @@ -599,92 +562,81 @@ function funA() { } ``` -在上面的代码中,对于`funB`函数来说,无论`v1`还是`v2`变量都不是它声明的,但是它可以通过闭包访问来获取这些变量 +在上面的代码中,对于 `funB`函数来说,无论 `v1`还是 `v2`变量都不是它声明的,但是它可以通过闭包访问来获取这些变量 -在`Step Content`中,因为代码被动态编译了,导致无法使用闭包;这种情况下,你如果要访问你其他地方定义的变量,必须将这个变量暴露为公共变量,不利于扩展对自身数据的封闭管理 +在 `Step Content`中,因为代码被动态编译了,导致无法使用闭包;这种情况下,你如果要访问你其他地方定义的变量,必须将这个变量暴露为公共变量,不利于扩展对自身数据的封闭管理 -而在`Async Content`中,你可以直接在里面访问到你外层定义的变量,这是`Step Content`不具备的优势 +而在 `Async Content`中,你可以直接在里面访问到你外层定义的变量,这是 `Step Content`不具备的优势 **更好的调试** `Async Content`支持电脑上的开发者工具进行断点调试 -在电脑上可以按`Ctrl+Shift+I`打开开发工具,然后在`源代码`/`Sources`里面找到你觉得有问题的代码,在编辑器左边的行数点击一下,会出现一个蓝色的箭头,代表此行已经被打上断点 +在电脑上可以按 `Ctrl+Shift+I`打开开发工具,然后在 `源代码`/`Sources`里面找到你觉得有问题的代码,在编辑器左边的行数点击一下,会出现一个蓝色的箭头,代表此行已经被打上断点 断点被打上后,当代码执行到此行时,开发工具会暂停代码的执行,此时你可以在开发工具里面观察各个变量的值,或者执行额外的代码 -另外使用`Async Content`的技能出现错误时,不会出现报错信息不正确的问题`Async Content`同样也是因为没有二次编译,不会丢失错误信息,增加你的错误排查效率 +另外使用 `Async Content`的技能出现错误时,不会出现报错信息不正确的问题 `Async Content`同样也是因为没有二次编译,不会丢失错误信息,增加你的错误排查效率 ## 三、`Async Content`相比原有形式的优势 -`Async Content`相比`Step Content`的优势上文已经说明,但无名杀实际还存在其他的content形式,故我们再看看其他的content形式与`Async Content`的对比 +`Async Content`相比 `Step Content`的优势上文已经说明,但无名杀实际还存在其他的content形式,故我们再看看其他的content形式与 `Async Content`的对比 -### `Array Content` +### `Generator Content` -为了解决不再动态编译,实际上无名杀可以使用一种很原始的分步方法;就比如之前的技能,可以这么写: +`Generator Content`通过“生成器”来等待事件结束。比如之前演示的技能,就可以这样写: ```javascript { - content: [ - (event, { player }) => { - player.addTempSkill("jiang"); - return player.draw(2); - }, - (event, { player }, result) => { - // result就是player.draw摸的牌 - if (player.countCards("h") > 5) - return player.chooseToDiscard(2, true); - }, - (event, { player }) => { - player.addMark("jiang"); + content: function * (event, { player }) { + let cards = yield player.draw(2); + + if (player.countCards("h") > 5) { + yield player.chooseToDiscard(2, true); } - ] + + player.addMark("jiang"); + } } ``` -你应该能看明白,就是将`Step Content`中的`content`属性换成了一个数组,数组中每个函数都是一个`step`,返回需要等待的事件,其中第一个参数则是当前事件,第二个参数是所有`Step Content`给出的参数,没用上的第三个参数则是需要等待事件的结果——这种参数形式被标记为“旧参数格式”,目前已被`Async Content`的参数形式取代 - -这种写法具有`Step Content`的所有优势,也具备调试功能,但由于过于丑陋,且现阶段并未支持异步功能,故被抛弃 - -当然你或许听到过一个幽灵... +在 `Generator Content`中,`Step Content`中的 `content`属性被换成了一个数组,数组中每个函数都是一个 `step`,返回需要等待的事件,其中第一个参数则是当前事件,第二个参数是所有 `Step Content`给出的参数,没用上的第三个参数则是需要等待事件的结果——这种参数形式被标记为“旧参数格式”,目前已被 `Async Content`的参数形式取代 -### `Async Contents` +你会发现,这很像 `Async Content`。实际上,当时 `Generator Content`或许会代替现在 `Async Content`的地位,因为两者的优缺点一致,`Generator Content`也能轻松实现异步功能;但时至今日,我们庆幸最终采用了 `Async Content`,并将事件改成了可 `await`的东西——这使得等待归一,从而使代码能实现更多功能,而 `Generator Content`的 `yield`却无法简单的实现 -和`Async Content`仅差了一个单词的`Async Contents`,从名字看就明白这个形式拥有`Async Content`的特点,并提供分步功能,但你却从来没看到有人使用过,只有不知道什么人在一遍遍传递这个幽灵的名号 - -因为`Async Contents`目前还是“废弃中”的状态 - -回到v1.10.6,当`Async Content`出来之后,我们就希望将无名杀本体的`Step Content`全部用新的写法代替;但`Async Content`有个缺点:并不支持跳步,这使得一些必须要跳步的情况无法用`Async Content`代替。因此,`Async Contents`被提上了议程 - -但在实现过程中,出了个差错:`Async Content`在v1.10.6时存在一个不明显的Bug,这个Bug不会对普通的`Async Content`造成任何影响,但对基于`Async Content`的`Async Contents`造成了非常大的影响,使得`Async Contents`完全无法发挥原有的功能。故`Async Contents`最终遭到了废弃,且为了防止错误使用`Async Contents`,相关代码已被删除 +只不过这一点过于复杂,本章节不会阐述,但额外章节会考虑讲述这一方面的内容 -现在导致`Async Contents`的Bug已被修复,但`Asnyc Contents`目前已经没人去实现了,本体的残留代码也无法直接使用。现在`Async Contents`就像个幽灵一样,徘徊在无名杀的代码群中,或许有一天我们还能再次看到这玩意 +### `Array Content` -### `Generator Content` +在v1.10.15中,由于旧的`Array Content`并没有人用,故新的`Array Content`取代了原有的`Array Content`,成为了目前无名杀解决跳步残留的方法之一 -`Generator Content`和`Asnyc Content`很像,这个形式通过“生成器”来等待事件结束,使用的是旧函数格式,就比如之前演示的技能,就可以这样写: +比如之前的技能,就可以这么写: ```javascript { - content: function * (event, { player }) { - let cards = yield player.draw(2); - - if (player.countCards("h") > 5) { - yield player.chooseToDiscard(2, true); + content: [ + async (event, trigger, player) => { + player.addTempSkill("jiang"); + await player.draw(2); + }, + async (event, trigger, player) => { + if (player.countCards("h") > 5){ + //return的事件会自动await,并将结果存入event._result + return player.chooseToDiscard(2, true); + } + }, + async (event, trigger, player) => { + player.addMark("jiang"); } - - player.addMark("jiang"); - } + ] } ``` -你会发现,这很像`Async Content`。实际上,当时`Generator Content`或许会代替现在`Async Content`的地位,因为两者的优缺点一致,`Generator Content`也能轻松实现异步功能;但时至今日,我们庆幸最终采用了`Async Content`,并将事件改成了可`await`的东西——这使得等待归一,从而使代码能实现更多功能,而`Generator Content`的`yield`却无法简单的实现 - -只不过这一点过于复杂,本章节不会阐述,但额外章节会考虑讲述这一方面的内容 +由于 `Array Content`的强大兼容性,在v1.10.15后 `Async Content` 和 `Step Content` 会在运行时被封装为 `Array Content`,从而更好地进行生命周期管理 --- -好了,到此你就已经彻底的把`Async Content`的关键知识浏览了一遍,如果要更好的巩固它,可以试着把你之前的技能改成`Async Content`试试 +好了,到此你就已经彻底的把 `Async Content`的关键知识浏览了一遍,如果要更好的巩固它,可以试着把你之前的技能改成 `Async Content`试试 未来可以遇见的是,`Asnyc Content`必将慢慢成为主流,而无名杀的代码环境也会逐渐使用async函数——这是Javascript的选择,也将是无名杀的选择 diff --git a/extension/boss/extension.js b/extension/boss/extension.js index ae63473b08..ade388048b 100644 --- a/extension/boss/extension.js +++ b/extension/boss/extension.js @@ -35,12 +35,11 @@ game.import("play", function () { get.config("versus_mode") != "jiange" ) { lib.characterPack.mode_extension_jiange = list2; - for (var i in list2) { - lib.characterPack.mode_extension_jiange[i] = list2[i]; + for (var i in lib.characterPack.mode_extension_jiange) { lib.characterPack.mode_extension_jiange[i][4].push( "mode:versus" ); - lib.character[i] = list2[i]; + lib.character[i] = lib.characterPack.mode_extension_jiange[i]; if (typeof lib.character[i][2] != "number") { lib.character[i][2] = Infinity; } diff --git a/game/asset.js b/game/asset.js index 13bb0192c9..0b48c648b0 100644 --- a/game/asset.js +++ b/game/asset.js @@ -181,9 +181,9 @@ window.noname_asset_list = [ "audio/card/male/yuanjiao.mp3", "audio/card/male/zhibi.mp3", - "audio/card/female/fudichouxin.mp3", - "audio/card/female/toulianghuanzhu.mp3", - "audio/card/female/wangmeizhike.mp3", + "audio/card/male/fudichouxin.mp3", + "audio/card/male/toulianghuanzhu.mp3", + "audio/card/male/wangmeizhike.mp3", /*cardaudio end*/ /*dieaudio begin*/ @@ -373,8 +373,6 @@ window.noname_asset_list = [ "audio/die/duosidawang.mp3", "audio/die/duxi.mp3", "audio/die/duyu.mp3", - "audio/die/erqiao.mp3", - "audio/die/erzhang.mp3", "audio/die/fanchou.mp3", "audio/die/fanjiangzhangda.mp3", "audio/die/fanyufeng.mp3", @@ -409,7 +407,6 @@ window.noname_asset_list = [ "audio/die/guanping.mp3", "audio/die/guanqiujian.mp3", "audio/die/guansuo.mp3", - "audio/die/guanxingzhangbao.mp3", "audio/die/guanyinping.mp3", "audio/die/guanyu.mp3", "audio/die/guanyue.mp3", @@ -1229,7 +1226,6 @@ window.noname_asset_list = [ "audio/die/xin_guozhao.mp3", "audio/die/xin_guyong.mp3", "audio/die/xin_handang.mp3", - "audio/die/xin_hansui.mp3", "audio/die/xin_jianyong.mp3", "audio/die/xin_jushou.mp3", "audio/die/xin_liaohua.mp3", @@ -2510,6 +2506,7 @@ window.noname_asset_list = [ "audio/skill/dczhuiyi1.mp3", "audio/skill/dczhuiyi2.mp3", "audio/skill/dczhuoli1.mp3", + "audio/skill/dczhuoli2.mp3", "audio/skill/dczifu1.mp3", "audio/skill/dczifu2.mp3", "audio/skill/dczigu1.mp3", @@ -3997,8 +3994,8 @@ window.noname_asset_list = [ "audio/skill/olmiuyan2.mp3", "audio/skill/olniepan1.mp3", "audio/skill/olniepan2.mp3", - "audio/skill/olningwu1.mp3", - "audio/skill/olningwu2.mp3", + "audio/skill/olninge1.mp3", + "audio/skill/olninge2.mp3", "audio/skill/olnishou1.mp3", "audio/skill/olnishou2.mp3", "audio/skill/olpijing1.mp3", @@ -4642,6 +4639,8 @@ window.noname_asset_list = [ "audio/skill/reweimu2.mp3", "audio/skill/rewurong1.mp3", "audio/skill/rewurong2.mp3", + "audio/skill/reshizhi1.mp3", + "audio/skill/reshizhi2.mp3", "audio/skill/rexiantu1.mp3", "audio/skill/rexiantu2.mp3", "audio/skill/rexianzhen1.mp3", @@ -5794,6 +5793,8 @@ window.noname_asset_list = [ "audio/skill/wuqin2.mp3", "audio/skill/wurong1.mp3", "audio/skill/wurong2.mp3", + "audio/skill/shizhi1.mp3", + "audio/skill/shizhi2.mp3", "audio/skill/wushen1.mp3", "audio/skill/wushen2.mp3", "audio/skill/wusheng_dc_jsp_guanyu1.mp3", @@ -6123,8 +6124,6 @@ window.noname_asset_list = [ "audio/skill/xinlianhuan_ol_pangtong2.mp3", "audio/skill/xinlianhuan1.mp3", "audio/skill/xinlianhuan2.mp3", - "audio/skill/xinniluan1.mp3", - "audio/skill/xinniluan2.mp3", "audio/skill/xinpaiyi1.mp3", "audio/skill/xinpaiyi2.mp3", "audio/skill/xinpingkou1.mp3", @@ -7618,7 +7617,6 @@ window.noname_asset_list = [ "image/character/guanping.jpg", "image/character/guanqiujian.jpg", "image/character/guansuo.jpg", - "image/character/guanxingzhangbao.jpg", "image/character/guanyinping.jpg", "image/character/guanyu.jpg", "image/character/guanyue.jpg", @@ -7780,7 +7778,6 @@ window.noname_asset_list = [ "image/character/hhzz_takaramono2.jpg", "image/character/hidden_image.jpg", "image/character/hs_aedwin.jpg", - "image/character/hs_aerfusi.jpg", "image/character/hs_aiqinvyao.jpg", "image/character/hs_alakir.jpg", "image/character/hs_alextrasza.jpg", @@ -7791,12 +7788,10 @@ window.noname_asset_list = [ "image/character/hs_antonidas.jpg", "image/character/hs_ashamoer.jpg", "image/character/hs_aya.jpg", - "image/character/hs_baiguyoulong.jpg", "image/character/hs_bannabusi.jpg", "image/character/hs_barnes.jpg", "image/character/hs_bchillmaw.jpg", "image/character/hs_bilanyoulong.jpg", - "image/character/hs_bingshuangnvwang.jpg", "image/character/hs_blingtron.jpg", "image/character/hs_bolvar.jpg", "image/character/hs_brann.jpg", @@ -7805,7 +7800,6 @@ window.noname_asset_list = [ "image/character/hs_fachaotuteng.jpg", "image/character/hs_fandral.jpg", "image/character/hs_fengjianhuanfengzhe.jpg", - "image/character/hs_fenjie.jpg", "image/character/hs_finley.jpg", "image/character/hs_fuding.jpg", "image/character/hs_guldan.jpg", @@ -7830,7 +7824,6 @@ window.noname_asset_list = [ "image/character/hs_lafamu.jpg", "image/character/hs_laila.jpg", "image/character/hs_laxiao.jpg", - "image/character/hs_lazi.jpg", "image/character/hs_liadrin.jpg", "image/character/hs_loatheb.jpg", "image/character/hs_lreno.jpg", @@ -7848,7 +7841,6 @@ window.noname_asset_list = [ "image/character/hs_nate.jpg", "image/character/hs_neptulon.jpg", "image/character/hs_nozdormu.jpg", - "image/character/hs_nuogefu.jpg", "image/character/hs_pengpeng.jpg", "image/character/hs_pyros.jpg", "image/character/hs_pyros1.jpg", @@ -7877,13 +7869,10 @@ window.noname_asset_list = [ "image/character/hs_tyrande.jpg", "image/character/hs_waleera.jpg", "image/character/hs_walian.jpg", - "image/character/hs_wolazi.jpg", "image/character/hs_wujiyuansu.jpg", "image/character/hs_wuther.jpg", - "image/character/hs_wuyaowang.jpg", "image/character/hs_wvelen.jpg", "image/character/hs_xialikeer.jpg", - "image/character/hs_xiangyaqishi.jpg", "image/character/hs_xsylvanas.jpg", "image/character/hs_xuanzhuanjijia.jpg", "image/character/hs_xuefashi.jpg", @@ -7897,7 +7886,6 @@ window.noname_asset_list = [ "image/character/hs_yngvar.jpg", "image/character/hs_yogg.jpg", "image/character/hs_ysera.jpg", - "image/character/hs_yuhuozhe.jpg", "image/character/hs_zhanzhenggushu.jpg", "image/character/hs_zhihuanhua.jpg", "image/character/hs_zhishigushu.jpg", @@ -8045,7 +8033,6 @@ window.noname_asset_list = [ "image/character/key_godan.jpg", "image/character/key_harukakanata.jpg", "image/character/key_haruko.jpg", - "image/character/key_hina.jpg", "image/character/key_hinata.jpg", "image/character/key_hiroto.jpg", "image/character/key_hisako.jpg", @@ -8225,12 +8212,9 @@ window.noname_asset_list = [ "image/character/mizhu.jpg", "image/character/mp_liuling.jpg", "image/character/mp_wangrong.jpg", - "image/character/mtg_ayeni.jpg", "image/character/mtg_jiding.jpg", "image/character/mtg_jiesi.jpg", "image/character/mtg_lilianna.jpg", - "image/character/mtg_nisha.jpg", - "image/character/mtg_qianzhuo.jpg", "image/character/muludawang.jpg", "image/character/mushun.jpg", "image/character/nanhualaoxian.jpg", @@ -8265,7 +8249,6 @@ window.noname_asset_list = [ "image/character/ns_jinke.jpg", "image/character/ns_lijue.jpg", "image/character/ns_limi.jpg", - "image/character/ns_lisu.jpg", "image/character/ns_liuzhang.jpg", "image/character/ns_luyusheng.jpg", "image/character/ns_lvmeng.jpg", @@ -8408,7 +8391,6 @@ window.noname_asset_list = [ "image/character/old_lingju.jpg", "image/character/old_lingtong.jpg", "image/character/old_liubiao.jpg", - "image/character/old_liuzan.jpg", "image/character/old_liyan.jpg", "image/character/old_machao.jpg", "image/character/old_madai.jpg", @@ -9017,7 +8999,6 @@ window.noname_asset_list = [ "image/character/swd_youzhao.jpg", "image/character/swd_yuchiyanhong.jpg", "image/character/swd_yuli.jpg", - "image/character/swd_yunhu.jpg", "image/character/swd_yuwentuo.jpg", "image/character/swd_yuxiaoxue.jpg", "image/character/swd_zhanggao.jpg", diff --git a/game/codemirror.js b/game/codemirror.js index 82ac6d5c17..c308ff3c63 100644 --- a/game/codemirror.js +++ b/game/codemirror.js @@ -489,7 +489,7 @@ var CodeMirror = (function () { // (when the bar is hidden). If it is still visible, we keep // it enabled, if it's hidden, we disable pointer events. var box = bar.getBoundingClientRect(); - var elt = document.elementFromPoint(box.left + 1, box.bottom - 1); + var elt = document.elementint(box.left + 1, box.bottom - 1); if (elt != bar) bar.style.pointerEvents = "none"; else delay.set(1000, maybeDisable); } diff --git a/game/config.js b/game/config.js index 7f52cea4a0..b7d3cd044e 100644 --- a/game/config.js +++ b/game/config.js @@ -16,7 +16,7 @@ window.config = { zhinang_tricks: ["guohe", "wuxie", "wuzhong", "dongzhuxianji"], connect_zhinang_tricks: ["guohe", "wuxie", "wuzhong", "dongzhuxianji"], all: { - sgscharacters: ["standard", "shenhua", "xinghuoliaoyuan", "refresh", "yijiang", "sp", "sp2", "xianding", "huicui", "extra", "old", "mobile", "shiji", "tw", "yingbian", "offline", "jsrg", "sb", "clan", "collab", "onlyOL"], + sgscharacters: ["standard", "shenhua", "refresh", "yijiang", "newjiang", "sixiang", "sp", "sp2", "xianding", "huicui", "extra", "old", "mobile", "shiji", "tw", "yingbian", "offline", "jsrg", "sb", "clan", "collab", "onlyOL"], sgscards: ["standard", "extra", "sp", "guozhan", "zhulu", "yingbian", "yongjian"], sgsmodes: ["identity", "guozhan", "versus", "doudizhu", "single", "brawl", "connect"], stockmode: ["identity", "guozhan", "versus", "boss", "doudizhu", "single", "chess", "stone", "connect", "brawl", "tafang"], @@ -129,8 +129,8 @@ window.config = { sort: "type_sort", cards: ["standard", "extra"], - characters: ["standard", "shenhua", "sp", "sp2", "yijiang", "refresh", "xinghuoliaoyuan", "mobile", "extra", "yingbian", "sb", "tw", "offline", "clan", "collab", "xianding", "huicui", "shiji", "jsrg", "onlyOL"], - moderned_chracters: ["standard", "shenhua", "sp", "sp2", "yijiang", "refresh", "xinghuoliaoyuan", "mobile", "extra", "yingbian", "sb", "tw", "offline", "clan", "collab", "xianding", "huicui", "shiji", "onlyOL", "jsrg", "old", "diy", "ddd", "key"], + characters: ["standard", "shenhua", "sp", "sp2", "yijiang", "newjiang", "sixiang", "refresh", "mobile", "extra", "yingbian", "sb", "tw", "offline", "clan", "collab", "xianding", "huicui", "shiji", "jsrg", "onlyOL"], + moderned_chracters: ["standard", "shenhua", "sp", "sp2", "yijiang", "newjiang", "sixiang", "refresh", "mobile", "extra", "yingbian", "sb", "tw", "offline", "clan", "collab", "xianding", "huicui", "shiji", "onlyOL", "jsrg", "old", "diy", "ddd", "key"], connect_characters: ["diy"], connect_cards: ["huanlekapai", "guozhan", "sp", "zhulu", "yingbian", "yongjian"], plays: [], @@ -225,7 +225,6 @@ window.config = { // ['jiang','chongzhen'], // ['fenji','yuling'], ["jiushi", "guixin"], - ["xiuhua", "qiaoxie"], ["xiuhua", "xuanfeng"], ["xiuhua", "duanxing"], ["xiuhua", "xiaoji"], diff --git a/game/directory.js b/game/directory.js index bca4a4b848..0c4762f8f0 100644 --- a/game/directory.js +++ b/game/directory.js @@ -1,3 +1,5 @@ +// 通过比对本地文件来自动修改asset.js和update.js +// 年久失修 var fs = require("fs"); var path = require("path"); var exec = require("child_process").exec; @@ -12,7 +14,7 @@ if (process.argv[2]) { if (/[0-9]/.test(process.argv[2][0])) { newversion = true; updates.update = updates.version; - updates.version = "1.9." + process.argv[2]; + updates.version = "1.10." + process.argv[2]; commit = updates.version; } else { commit = process.argv[2]; diff --git a/game/generateChanged.js b/game/generateChanged.js new file mode 100644 index 0000000000..43595f79e6 --- /dev/null +++ b/game/generateChanged.js @@ -0,0 +1,118 @@ +// 通过比对git信息来获取改动的文件列表 +// 然后生成zip文件 +// 使用 node game/listChangedFiles.js commitHash +// 命令参数是对应commit的SHA +// 生成的压缩包在game目录下 +const { exec } = require("child_process"); +const path = require("path"); +const fs = require("fs"); +const JSZip = require("./jszip.js"); + +const joinRootPath = p => path.join(__dirname, "../", p); + +function formatDate(date = new Date()) { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, "0"); // getMonth() 返回的是0-11,所以需要加1 + const day = String(date.getDate()).padStart(2, "0"); + return `${year}${month}${day}`; +} + +function collectFilesSync(paths, filter = (_path) => true) { + const fileList = []; + + function collectFilesInDirectory(directoryPath) { + try { + const entries = fs.readdirSync(directoryPath, { + withFileTypes: true, + }); + + for (const entry of entries) { + const fullPath = path.join(directoryPath, entry.name); + // 添加过滤函数 + if (!filter(fullPath)) continue; + + if (entry.isDirectory()) { + // 如果是目录,则递归进入 + collectFilesInDirectory(fullPath); + } else { + // 如果是文件,则添加到文件列表中 + fileList.push(fullPath); + } + } + } catch (error) { + console.error(`Error processing directory ${directoryPath}:`, error); + } + } + + for (const item of paths) { + if (fs.existsSync(item)) { + const stats = fs.lstatSync(item); + + if (stats.isDirectory()) { + // 如果是目录,则递归收集文件 + collectFilesInDirectory(item); + } else { + // 如果是文件,则直接添加到列表中 + fileList.push(item); + } + } else { + console.error(`The path ${item} does not exist.`); + } + } + + return fileList.map(v => v.slice(path.join(__dirname, "..").length + 1)); +} + +function compareFilesWithCommit(commitHash = "HEAD") { + console.log(`exec git diff --name-only ${commitHash}`); + exec(`git diff --name-only ${commitHash}`, (error, stdout) => { + if (error) { + console.error(`exec error: ${error}`); + return; + } + + const zip = new JSZip(); + + let filesArray = stdout.split("\n").filter(v => { + const filePath = path.join(__dirname, "../", v); + return fs.existsSync(filePath) && fs.lstatSync(filePath).isFile(); + + }); + + const nonameExtensions = ["boss", "cardpile", "coin", "wuxing"].map(name => joinRootPath(`extension/${name}`)); + + filesArray.push(...collectFilesSync([joinRootPath("card"), joinRootPath("character"), joinRootPath("game"), joinRootPath("layout"), joinRootPath("mode"), joinRootPath("noname"), joinRootPath("theme"), joinRootPath("index.html"), joinRootPath("LICENSE"), joinRootPath("noname-compatible.js"), joinRootPath("noname.js"), joinRootPath("README.md"), joinRootPath("service-worker.js"), joinRootPath("tsconfig.json")])); + + // 单独处理extension目录,使扩展不会被打包 + filesArray.push(...collectFilesSync([joinRootPath("extension")], path => nonameExtensions.some(extPath => path.startsWith(extPath)))); + + filesArray = [...new Set(filesArray.map(v => v.replace(/\\/g, "/")))].sort((a, b) => { + if (a > b) return 1; + if (a < b) return -1; + return 0; + }); + + // fs.writeFileSync(path.join(__dirname, "filesArray.txt"), filesArray.join('\n')); + + filesArray.forEach(v => { + const filePath = path.join(__dirname, "../", v); + if (fs.existsSync(filePath) && fs.lstatSync(filePath).isDirectory()) { + zip.folder(v); + return; + } + if (fs.existsSync(filePath) && fs.lstatSync(filePath).isFile()) { + if (zip.file(v) === null) { + zip.file(v, fs.readFileSync(filePath)); + } + } + }); + + // noinspection JSDeprecatedSymbols + const result = zip.generate({ type: "nodebuffer" }); + fs.writeFileSync(path.join(__dirname, `测试包-${formatDate()}.zip`), result); + }); +} + +if (process.argv[2]) { + compareFilesWithCommit(process.argv[2]); +} diff --git a/game/package.js b/game/package.js index d50575b1b2..8eb3149dc9 100644 --- a/game/package.js +++ b/game/package.js @@ -1,26 +1,36 @@ window.noname_package = { character: { + //经典标包+神话再临 standard: "标准", - refresh: "界限突破", shenhua: "神话再临", + extra: "神将", + //一将成名+界限突破 yijiang: "一将成名", + refresh: "界限突破", + //新时代通用武将 sp: "璀璨星河", + sp2: "系列专属", + newjiang: "新一将成名", + //OL服 onlyOL: "OL专属", yingbian: "文德武备", clan: "门阀士族", - xinghuoliaoyuan: "星火燎原", + //十周年服 huicui: "群英荟萃", xianding: "限定专属", - sp2: "系列专属", - extra: "神将", + //移动服+外服 mobile: "移动版", shiji: "始计篇", sb: "谋攻篇", tw: "外服武将", + //各服联动+怀旧 collab: "联动卡", + old: "怀旧", + //线下系列 offline: "线下武将", jsrg: "江山如故", - old: "怀旧", + sixiang: "四象封印", + //DIY系列 diy: "DIY", ddd: "3D精选", key: "Key", @@ -48,6 +58,7 @@ window.noname_package = { hearth: "炉石传说", gwent: "昆特牌", mtg: "万智牌", + xianxia: "线下卡牌", huanlekapai: "欢乐卡牌", }, play: { diff --git a/game/source.js b/game/source.js index dc3f89326f..c0c85794e1 100644 --- a/game/source.js +++ b/game/source.js @@ -9,6 +9,7 @@ window.noname_source_list = [ "noname/game/check.js", "noname/game/compatible.js", "noname/game/index.js", + "noname/game/PauseManager.js", "noname/game/promises.js", "noname/game/dynamic-style/index.js", "noname/get/audio.js", @@ -23,6 +24,7 @@ window.noname_source_list = [ "noname/init/cordova.js", "noname/init/import.js", "noname/init/index.js", + "noname/init/loading.js", "noname/init/node.js", "noname/init/onload.js", "noname/init/polyfill.js", @@ -41,6 +43,13 @@ window.noname_source_list = [ "noname/library/cache/childNodesWatcher.js", "noname/library/channel/index.js", "noname/library/crypt/md5.js", + "noname/library/element/GameEvent/compilers/ArrayCompiler.js", + "noname/library/element/GameEvent/compilers/AsyncCompiler.js", + "noname/library/element/GameEvent/compilers/ContentCompiler.js", + "noname/library/element/GameEvent/compilers/ContentCompilerBase.js", + "noname/library/element/GameEvent/compilers/StepCompiler.js", + "noname/library/element/GameEvent/compilers/YieldCompiler.js", + "noname/library/element/GameEvent/GameEventManager.js", "noname/library/element/button.js", "noname/library/element/card.js", "noname/library/element/character.js", @@ -99,6 +108,7 @@ window.noname_source_list = [ "card/sp.js", "card/standard.js", "card/swd.js", + "card/xianxia.js", "card/yingbian.js", "card/yongjian.js", "card/yunchou.js", @@ -224,6 +234,19 @@ window.noname_source_list = [ "character/mobile/sort.js", "character/mobile/translate.js", "character/mobile/voices.js", + "character/newjiang/card.js", + "character/newjiang/character.js", + "character/newjiang/characterFilter.js", + "character/newjiang/characterReplace.js", + "character/newjiang/dynamicTranslate.js", + "character/newjiang/index.js", + "character/newjiang/intro.js", + "character/newjiang/perfectPairs.js", + "character/newjiang/pinyin.js", + "character/newjiang/skill.js", + "character/newjiang/sort.js", + "character/newjiang/translate.js", + "character/newjiang/voices.js", "character/offline/card.js", "character/offline/character.js", "character/offline/characterFilter.js", @@ -311,6 +334,19 @@ window.noname_source_list = [ "character/shiji/sort.js", "character/shiji/translate.js", "character/shiji/voices.js", + "character/sixiang/card.js", + "character/sixiang/character.js", + "character/sixiang/characterFilter.js", + "character/sixiang/characterReplace.js", + "character/sixiang/dynamicTranslate.js", + "character/sixiang/index.js", + "character/sixiang/intro.js", + "character/sixiang/perfectPairs.js", + "character/sixiang/pinyin.js", + "character/sixiang/skill.js", + "character/sixiang/sort.js", + "character/sixiang/translate.js", + "character/sixiang/voices.js", "character/sp/card.js", "character/sp/character.js", "character/sp/characterFilter.js", @@ -375,19 +411,6 @@ window.noname_source_list = [ "character/xianding/sort.js", "character/xianding/translate.js", "character/xianding/voices.js", - "character/xinghuoliaoyuan/card.js", - "character/xinghuoliaoyuan/character.js", - "character/xinghuoliaoyuan/characterFilter.js", - "character/xinghuoliaoyuan/characterReplace.js", - "character/xinghuoliaoyuan/dynamicTranslate.js", - "character/xinghuoliaoyuan/index.js", - "character/xinghuoliaoyuan/intro.js", - "character/xinghuoliaoyuan/perfectPairs.js", - "character/xinghuoliaoyuan/pinyin.js", - "character/xinghuoliaoyuan/skill.js", - "character/xinghuoliaoyuan/sort.js", - "character/xinghuoliaoyuan/translate.js", - "character/xinghuoliaoyuan/voices.js", "character/yijiang/card.js", "character/yijiang/character.js", "character/yijiang/characterFilter.js", @@ -425,6 +448,7 @@ window.noname_source_list = [ "game/config.js", "game/core-js-bundle.js", "game/directory.js", + "game/generateChanged.js", "game/entry.js", "game/fallback.js", "game/game.js", diff --git a/game/update.js b/game/update.js index b4e221aa46..b86c8b8513 100644 --- a/game/update.js +++ b/game/update.js @@ -1,10 +1,11 @@ window.noname_update = { - version: "1.10.14", + version: "1.10.15", update: "NULL", //新版本更新文件较多,直接强制进行全量更新 changeLog: [ - "注意!!!我们已经将无名杀的版本的最低内核需求从Chromium 77升级到Chromium 85(iOS系统的需求仍为14.5以上版本的系统,没有发生变化),请在更新前将您使用的无名杀客户端升级到最新版本!", + "未来规划: 无名杀将推迟下一次更新的时间全力解决遗留的bug,以及底层对扩展进行更规范的管理和开放接口", + "在上述过程结束后(即下个版本更新后),无名杀将进行与三国杀的解耦,武将包、卡牌包、模式、游戏素材等将会进行大幅度改动(覆盖本体文件的扩展需要额外关注后续信息),游戏客户端也将会进行必要的升级", "大量的新武将", - "bug修复", + "其他bug修复,AI优化与台词调整", ], files: [], }; diff --git a/game/vue.esm-browser.js b/game/vue.esm-browser.js index fac296fac2..f5c01f7e14 100644 --- a/game/vue.esm-browser.js +++ b/game/vue.esm-browser.js @@ -1,3 +1,4 @@ +// @ts-nocheck /** * vue v3.4.21 * (c) 2018-present Yuxi (Evan) You and Vue contributors @@ -69,6 +70,10 @@ const hyphenate = cacheStringFunction( const capitalize = cacheStringFunction((str) => { return str.charAt(0).toUpperCase() + str.slice(1); }); +/** + * @template {String}T + * @type {(str: T) => T extends "" ? "" : `on${Capitalize}`} + */ const toHandlerKey = cacheStringFunction((str) => { const s = str ? `on${capitalize(str)}` : ``; return s; @@ -325,6 +330,9 @@ function looseIndexOf(arr, val) { return arr.findIndex((item) => looseEqual(item, val)); } +/** + * @type {(val: unknown) => string} + */ const toDisplayString = (val) => { return isString(val) ? val : val == null ? "" : isArray(val) || isObject(val) && (val.toString === objectToString || !isFunction(val.toString)) ? JSON.stringify(val, replacer, 2) : String(val); }; @@ -448,9 +456,15 @@ function recordEffectScope(effect, scope = activeEffectScope) { scope.effects.push(effect); } } +/** + * @type {import("@vue/reactivity").getCurrentScope} + */ function getCurrentScope() { return activeEffectScope; } +/** + * @type {import("@vue/reactivity").onScopeDispose} + */ function onScopeDispose(fn) { if (activeEffectScope) { activeEffectScope.cleanups.push(fn); @@ -1238,6 +1252,11 @@ function targetTypeMap(rawType) { function getTargetType(value) { return value["__v_skip"] || !Object.isExtensible(value) ? 0 /* INVALID */ : targetTypeMap(toRawType(value)); } +/** + * @template T + * @param {T} target + * @return {UnwrapNestedRefs} + */ function reactive(target) { if (isReadonly(target)) { return target; @@ -1259,6 +1278,9 @@ function shallowReactive(target) { shallowReactiveMap ); } +/** + * @type {import("@vue/reactivity").readonly} + */ function readonly(target) { return createReactiveObject( target, @@ -1317,6 +1339,9 @@ function isShallow(value) { function isProxy(value) { return isReactive(value) || isReadonly(value); } +/** + * @type {import("@vue/reactivity").toRaw} + */ function toRaw(observed) { const raw = observed && observed["__v_raw"]; return raw ? toRaw(raw) : observed; @@ -1435,6 +1460,17 @@ function triggerRefValue(ref2, dirtyLevel = 4, newVal) { function isRef(r) { return !!(r && r.__v_isRef === true); } +/** + * @template {any} T + * @overload + * @returns {import("@vue/reactivity").Ref} + */ +/** + * @template T + * @overload + * @param {T} value + * @returns {import("@vue/reactivity").Ref>} + */ function ref(value) { return createRef(value, false); } @@ -1472,9 +1508,15 @@ class RefImpl { function triggerRef(ref2) { triggerRefValue(ref2, 4, ref2.value ); } +/** + * @type {import("@vue/reactivity").unref} + */ function unref(ref2) { return isRef(ref2) ? ref2.value : ref2; } +/** + * @type {import("@vue/reactivity").toValue} + */ function toValue(source) { return isFunction(source) ? source() : unref(source); } @@ -1514,6 +1556,11 @@ class CustomRefImpl { function customRef(factory) { return new CustomRefImpl(factory); } +/** + * @template {Object} T + * @param {T} object + * @return {import("@vue/runtime-core").ToRefs} + */ function toRefs(object) { if (!isProxy(object)) { warn$2(`toRefs() expects a reactive object but received a plain one.`); @@ -1552,6 +1599,29 @@ class GetterRefImpl { return this._getter(); } } +/** + * @template T + * @overload + * @param {T} source + * @returns {T extends () => infer R ? Readonly> : T extends import("@vue/runtime-core").Ref ? T : import("@vue/runtime-core").Ref>} + */ +/** + * @template {object} T + * @template {keyof T} K + * @overload + * @param {T} source + * @param {K} key + * @returns {import("@vue/runtime-core").ToRef} + */ +/** + * @template {object} T + * @template {keyof T} K + * @overload + * @param {T} source + * @param {K} key + * @param {T[K]} defaultValue + * @return {import("@vue/runtime-core").ToRef>} + */ function toRef(source, key, defaultValue) { if (isRef(source)) { return source; @@ -3370,6 +3440,12 @@ function watchSyncEffect(effect, options) { ); } const INITIAL_WATCHER_VALUE = {}; +/** + * @param {Parameters[0]} source + * @param {Parameters[1]} cb + * @param {Parameters[2]} [options] + * @return {ReturnType} + */ function watch(source, cb, options) { if (!isFunction(cb)) { warn$1( @@ -3981,6 +4057,9 @@ function getTransitionRawChildren(children, keepComment = false, parentKey) { /*! #__NO_SIDE_EFFECTS__ */ // @__NO_SIDE_EFFECTS__ +/** + * @return {ReturnType} + */ function defineComponent(options, extraOptions) { return isFunction(options) ? ( // #8326: extend call and options.name access are considered side-effects @@ -3992,6 +4071,9 @@ function defineComponent(options, extraOptions) { const isAsyncWrapper = (i) => !!i.type.__asyncLoader; /*! #__NO_SIDE_EFFECTS__ */ // @__NO_SIDE_EFFECTS__ +/** + * @type {import("@vue/runtime-core").defineAsyncComponent} + */ function defineAsyncComponent(source) { if (isFunction(source)) { source = { loader: source }; @@ -4324,9 +4406,15 @@ function matches(pattern, name) { } return false; } +/** + * @type {import("@vue/runtime-core").onActivated} + */ function onActivated(hook, target) { registerKeepAliveHook(hook, "a", target); } +/** + * @type {import("@vue/runtime-core").onDeactivated} + */ function onDeactivated(hook, target) { registerKeepAliveHook(hook, "da", target); } @@ -4403,19 +4491,49 @@ const createHook = (lifecycle) => (hook, target = currentInstance) => ( // post-create lifecycle registrations are noops during SSR (except for serverPrefetch) (!isInSSRComponentSetup || lifecycle === "sp") && injectHook(lifecycle, (...args) => hook(...args), target) ); +/** + * @type {(hook: () => any, target?: import("@vue/runtime-core").ComponentInternalInstance | null) => false | Function | undefined} + */ const onBeforeMount = createHook("bm"); +/** + * @type {(hook: () => any, target?: import("@vue/runtime-core").ComponentInternalInstance | null) => false | Function | undefined} + */ const onMounted = createHook("m"); +/** + * @type {(hook: () => any, target?: import("@vue/runtime-core").ComponentInternalInstance | null) => false | Function | undefined} + */ const onBeforeUpdate = createHook("bu"); +/** + * @type {(hook: () => any, target?: import("@vue/runtime-core").ComponentInternalInstance | null) => false | Function | undefined} + */ const onUpdated = createHook("u"); +/** + * @type {(hook: () => any, target?: import("@vue/runtime-core").ComponentInternalInstance | null) => false | Function | undefined} + */ const onBeforeUnmount = createHook("bum"); +/** + * @type {(hook: () => any, target?: import("@vue/runtime-core").ComponentInternalInstance | null) => false | Function | undefined} + */ const onUnmounted = createHook("um"); +/** + * @type {(hook: () => any, target?: import("@vue/runtime-core").ComponentInternalInstance | null) => false | Function | undefined} + */ const onServerPrefetch = createHook("sp"); +/** + * @type {(hook: () => any, target?: import("@vue/runtime-core").ComponentInternalInstance | null) => false | Function | undefined} + */ const onRenderTriggered = createHook( "rtg" ); +/** + * @type {(hook: () => any, target?: import("@vue/runtime-core").ComponentInternalInstance | null) => false | Function | undefined} + */ const onRenderTracked = createHook( "rtc" ); +/** + * @type {(hook: () => any, target?: import("@vue/runtime-core").ComponentInternalInstance | null) => false | Function | undefined} + */ function onErrorCaptured(hook, target = currentInstance) { injectHook("ec", hook, target); } @@ -4525,7 +4643,9 @@ function ensureValidVNode(vnodes) { return true; }) ? vnodes : null; } - +/** + * @type {import("@vue/runtime-core").toHandlers} + */ function toHandlers(obj, preserveCaseIfNecessary) { const ret = {}; if (!isObject(obj)) { @@ -5520,6 +5640,12 @@ function provide(key, value) { provides[key] = value; } } +/** + * @param {Parameters[0]} key + * @param {Parameters[1]} defaultValue + * @param {Parameters[2]} treatDefaultAsFactory + * @return {ReturnType} + */ function inject(key, defaultValue, treatDefaultAsFactory = false) { const instance = currentInstance || currentRenderingInstance; if (instance || currentApp) { @@ -8998,6 +9124,9 @@ function createComponentInstance(vnode, parent, suspense) { return instance; } let currentInstance = null; +/** + * @type {() => import("@vue/runtime-core").ComponentInternalInstance | null} + */ const getCurrentInstance = () => currentInstance || currentRenderingInstance; let internalSetCurrentInstance; let setInSSRSetupState; @@ -9316,6 +9445,9 @@ function isClassComponent(value) { return isFunction(value) && "__vccOpts" in value; } +/** + * @type {import("@vue/runtime-core").computed} + */ const computed = (getterOrOptions, debugOptions) => { const c = computed$1(getterOrOptions, debugOptions, isInSSRComponentSetup); { @@ -9380,6 +9512,12 @@ function useModel(props, name, options = EMPTY_OBJ) { return res; } +/** + * @param {Parameters[0]} type + * @param {Parameters[1]} propsOrChildren + * @param {Parameters[2]} children + * @return {ReturnType} + */ function h(type, propsOrChildren, children) { const l = arguments.length; if (l === 2) { @@ -11050,12 +11188,21 @@ function ensureHydrationRenderer() { enabledHydration = true; return renderer; } +/** + * @type {import("@vue/runtime-dom").RootRenderFunction} + */ const render = (...args) => { ensureRenderer().render(...args); }; +/** + * @type {import("@vue/runtime-dom").RootHydrateFunction} + */ const hydrate = (...args) => { ensureHydrationRenderer().hydrate(...args); }; +/** + * @type {import("@vue/runtime-dom").CreateAppFunction} + */ const createApp = (...args) => { const app = ensureRenderer().createApp(...args); { @@ -11081,6 +11228,9 @@ const createApp = (...args) => { }; return app; }; +/** + * @type {import("@vue/runtime-dom").CreateAppFunction} + */ const createSSRApp = (...args) => { const app = ensureHydrationRenderer().createApp(...args); { @@ -16631,6 +16781,11 @@ function getCache(options) { } return c; } +/** + * @param {string | HTMLElement} template + * @param {import("@vue/compiler-dom").CompilerOptions} [options] + * @return {import("@vue/runtime-core").RenderFunction} + */ function compileToFunction(template, options) { if (!isString(template)) { if (template.nodeType) { diff --git a/image/card/tiejili.png b/image/card/tiejili.png new file mode 100644 index 0000000000..a9865724f9 Binary files /dev/null and b/image/card/tiejili.png differ diff --git a/image/card/yiwu_click.png b/image/card/yiwu_click.png new file mode 100644 index 0000000000..9ce95ec299 Binary files /dev/null and b/image/card/yiwu_click.png differ diff --git a/image/card/yiwu_female.png b/image/card/yiwu_female.png new file mode 100644 index 0000000000..fe3c161a26 Binary files /dev/null and b/image/card/yiwu_female.png differ diff --git a/image/card/yiwu_male.png b/image/card/yiwu_male.png new file mode 100644 index 0000000000..0cca9490b3 Binary files /dev/null and b/image/card/yiwu_male.png differ diff --git a/image/character/dc_sb_chengyu.jpg b/image/character/dc_sb_chengyu.jpg new file mode 100644 index 0000000000..a3ab9ca01d Binary files /dev/null and b/image/character/dc_sb_chengyu.jpg differ diff --git a/image/character/dc_sb_jiaxu.jpg b/image/character/dc_sb_jiaxu.jpg index 6bdc6bb610..818616d55b 100644 Binary files a/image/character/dc_sb_jiaxu.jpg and b/image/character/dc_sb_jiaxu.jpg differ diff --git a/image/character/dc_sb_jiaxu_shadow.jpg b/image/character/dc_sb_jiaxu_shadow.jpg index 818616d55b..6bdc6bb610 100644 Binary files a/image/character/dc_sb_jiaxu_shadow.jpg and b/image/character/dc_sb_jiaxu_shadow.jpg differ diff --git a/image/character/dc_sb_jushou.jpg b/image/character/dc_sb_jushou.jpg new file mode 100644 index 0000000000..e0a0c6d75b Binary files /dev/null and b/image/character/dc_sb_jushou.jpg differ diff --git a/image/character/guanxingzhangbao.jpg b/image/character/guanxingzhangbao.jpg deleted file mode 100755 index 466edad00b..0000000000 Binary files a/image/character/guanxingzhangbao.jpg and /dev/null differ diff --git a/image/character/hs_aerfusi.jpg b/image/character/hs_aerfusi.jpg deleted file mode 100644 index 51d0b3817a..0000000000 Binary files a/image/character/hs_aerfusi.jpg and /dev/null differ diff --git a/image/character/hs_baiguyoulong.jpg b/image/character/hs_baiguyoulong.jpg deleted file mode 100644 index fd138bfb58..0000000000 Binary files a/image/character/hs_baiguyoulong.jpg and /dev/null differ diff --git a/image/character/hs_bingshuangnvwang.jpg b/image/character/hs_bingshuangnvwang.jpg deleted file mode 100644 index 529758c405..0000000000 Binary files a/image/character/hs_bingshuangnvwang.jpg and /dev/null differ diff --git a/image/character/hs_fenjie.jpg b/image/character/hs_fenjie.jpg deleted file mode 100644 index 1c196d74e7..0000000000 Binary files a/image/character/hs_fenjie.jpg and /dev/null differ diff --git a/image/character/hs_lazi.jpg b/image/character/hs_lazi.jpg deleted file mode 100644 index 0fdadae52c..0000000000 Binary files a/image/character/hs_lazi.jpg and /dev/null differ diff --git a/image/character/hs_nuogefu.jpg b/image/character/hs_nuogefu.jpg deleted file mode 100644 index bf3673d11b..0000000000 Binary files a/image/character/hs_nuogefu.jpg and /dev/null differ diff --git a/image/character/hs_wolazi.jpg b/image/character/hs_wolazi.jpg deleted file mode 100644 index 17163dca74..0000000000 Binary files a/image/character/hs_wolazi.jpg and /dev/null differ diff --git a/image/character/hs_wuyaowang.jpg b/image/character/hs_wuyaowang.jpg deleted file mode 100644 index c8505fccc1..0000000000 Binary files a/image/character/hs_wuyaowang.jpg and /dev/null differ diff --git a/image/character/hs_xiangyaqishi.jpg b/image/character/hs_xiangyaqishi.jpg deleted file mode 100644 index f9854a9f98..0000000000 Binary files a/image/character/hs_xiangyaqishi.jpg and /dev/null differ diff --git a/image/character/hs_yuhuozhe.jpg b/image/character/hs_yuhuozhe.jpg deleted file mode 100644 index 4375af214d..0000000000 Binary files a/image/character/hs_yuhuozhe.jpg and /dev/null differ diff --git a/image/character/huan_jiangwei.jpg b/image/character/huan_jiangwei.jpg new file mode 100644 index 0000000000..46da22b6a8 Binary files /dev/null and b/image/character/huan_jiangwei.jpg differ diff --git a/image/character/huan_zhugeguo.jpg b/image/character/huan_zhugeguo.jpg new file mode 100644 index 0000000000..8dfd844801 Binary files /dev/null and b/image/character/huan_zhugeguo.jpg differ diff --git a/image/character/jd_simayan.jpg b/image/character/jd_simayan.jpg new file mode 100644 index 0000000000..33b2d6b117 Binary files /dev/null and b/image/character/jd_simayan.jpg differ diff --git a/image/character/jx_guanyu.jpg b/image/character/jx_guanyu.jpg new file mode 100644 index 0000000000..2f94599011 Binary files /dev/null and b/image/character/jx_guanyu.jpg differ diff --git a/image/character/jx_shen_caoren.jpg b/image/character/jx_shen_caoren.jpg new file mode 100644 index 0000000000..04d1192850 Binary files /dev/null and b/image/character/jx_shen_caoren.jpg differ diff --git a/image/character/jx_shen_liubiao.jpg b/image/character/jx_shen_liubiao.jpg new file mode 100644 index 0000000000..76f13bd009 Binary files /dev/null and b/image/character/jx_shen_liubiao.jpg differ diff --git a/image/character/jx_sunjian.jpg b/image/character/jx_sunjian.jpg new file mode 100644 index 0000000000..d381b8ec93 Binary files /dev/null and b/image/character/jx_sunjian.jpg differ diff --git a/image/character/jx_zhouyu.jpg b/image/character/jx_zhouyu.jpg new file mode 100644 index 0000000000..4e822a3a29 Binary files /dev/null and b/image/character/jx_zhouyu.jpg differ diff --git a/image/character/key_hina.jpg b/image/character/key_hina.jpg deleted file mode 100644 index 4ca7a2fe23..0000000000 Binary files a/image/character/key_hina.jpg and /dev/null differ diff --git a/image/character/kongshu.jpg b/image/character/kongshu.jpg new file mode 100644 index 0000000000..eecad22e77 Binary files /dev/null and b/image/character/kongshu.jpg differ diff --git a/image/character/liuhui.jpg b/image/character/liuhui.jpg index 6f6c0494d6..9abbede39d 100644 Binary files a/image/character/liuhui.jpg and b/image/character/liuhui.jpg differ diff --git a/image/character/liutan.jpg b/image/character/liutan.jpg new file mode 100644 index 0000000000..3e3d14fa63 Binary files /dev/null and b/image/character/liutan.jpg differ diff --git a/image/character/liuxiecaojie.jpg b/image/character/liuxiecaojie.jpg new file mode 100644 index 0000000000..1ff86be7c3 Binary files /dev/null and b/image/character/liuxiecaojie.jpg differ diff --git a/image/character/liuxiecaojie_shadow.jpg b/image/character/liuxiecaojie_shadow.jpg new file mode 100644 index 0000000000..bd8a242fb4 Binary files /dev/null and b/image/character/liuxiecaojie_shadow.jpg differ diff --git a/image/character/mb_simazhou.jpg b/image/character/mb_simazhou.jpg new file mode 100644 index 0000000000..bb59f4445f Binary files /dev/null and b/image/character/mb_simazhou.jpg differ diff --git a/image/character/mb_wenqin.jpg b/image/character/mb_wenqin.jpg new file mode 100644 index 0000000000..df9be6ae1c Binary files /dev/null and b/image/character/mb_wenqin.jpg differ diff --git a/image/character/mb_zhangfen.jpg b/image/character/mb_zhangfen.jpg new file mode 100644 index 0000000000..62770ea1ec Binary files /dev/null and b/image/character/mb_zhangfen.jpg differ diff --git a/image/character/mtg_ayeni.jpg b/image/character/mtg_ayeni.jpg deleted file mode 100644 index c3b5e65da6..0000000000 Binary files a/image/character/mtg_ayeni.jpg and /dev/null differ diff --git a/image/character/mtg_nisha.jpg b/image/character/mtg_nisha.jpg deleted file mode 100644 index f2d043c3c0..0000000000 Binary files a/image/character/mtg_nisha.jpg and /dev/null differ diff --git a/image/character/mtg_qianzhuo.jpg b/image/character/mtg_qianzhuo.jpg deleted file mode 100644 index 403cf1b1b4..0000000000 Binary files a/image/character/mtg_qianzhuo.jpg and /dev/null differ diff --git a/image/character/ns_lisu.jpg b/image/character/ns_lisu.jpg deleted file mode 100644 index e7a96a3647..0000000000 Binary files a/image/character/ns_lisu.jpg and /dev/null differ diff --git a/image/character/ol_caochong.jpg b/image/character/ol_caochong.jpg new file mode 100644 index 0000000000..54487f8066 Binary files /dev/null and b/image/character/ol_caochong.jpg differ diff --git a/image/character/ol_kebineng.jpg b/image/character/ol_kebineng.jpg new file mode 100644 index 0000000000..74a588d24c Binary files /dev/null and b/image/character/ol_kebineng.jpg differ diff --git a/image/character/ol_sb_kongrong.jpg b/image/character/ol_sb_kongrong.jpg new file mode 100644 index 0000000000..0d9c88ac60 Binary files /dev/null and b/image/character/ol_sb_kongrong.jpg differ diff --git a/image/character/ol_sb_sunjian.jpg b/image/character/ol_sb_sunjian.jpg new file mode 100644 index 0000000000..d4d81f89f6 Binary files /dev/null and b/image/character/ol_sb_sunjian.jpg differ diff --git a/image/character/ol_sunru.jpg b/image/character/ol_sunru.jpg new file mode 100644 index 0000000000..437549ceb4 Binary files /dev/null and b/image/character/ol_sunru.jpg differ diff --git a/image/character/ol_yuanji.jpg b/image/character/ol_yuanji.jpg new file mode 100644 index 0000000000..6bc0c0498a Binary files /dev/null and b/image/character/ol_yuanji.jpg differ diff --git a/image/character/ol_zhangchunhua.jpg b/image/character/ol_zhangchunhua.jpg new file mode 100644 index 0000000000..3e428c7437 Binary files /dev/null and b/image/character/ol_zhangchunhua.jpg differ diff --git a/image/character/old_liuzan.jpg b/image/character/old_liuzan.jpg deleted file mode 100644 index 331680c7d6..0000000000 Binary files a/image/character/old_liuzan.jpg and /dev/null differ diff --git a/image/character/shen_dianwei.jpg b/image/character/shen_dianwei.jpg index 6750f51f1c..08ce0987e4 100644 Binary files a/image/character/shen_dianwei.jpg and b/image/character/shen_dianwei.jpg differ diff --git a/image/character/shen_machao.jpg b/image/character/shen_machao.jpg index c772dfaa69..5d658230e4 100644 Binary files a/image/character/shen_machao.jpg and b/image/character/shen_machao.jpg differ diff --git a/image/character/std_cenhun.jpg b/image/character/std_cenhun.jpg new file mode 100644 index 0000000000..84233fc251 Binary files /dev/null and b/image/character/std_cenhun.jpg differ diff --git a/image/character/std_fuhuanghou.jpg b/image/character/std_fuhuanghou.jpg new file mode 100644 index 0000000000..758537c165 Binary files /dev/null and b/image/character/std_fuhuanghou.jpg differ diff --git a/image/character/std_gongsunyuan.jpg b/image/character/std_gongsunyuan.jpg new file mode 100644 index 0000000000..025d912803 Binary files /dev/null and b/image/character/std_gongsunyuan.jpg differ diff --git a/image/character/std_guanxing.jpg b/image/character/std_guanxing.jpg new file mode 100644 index 0000000000..a15b0538d1 Binary files /dev/null and b/image/character/std_guanxing.jpg differ diff --git a/image/character/std_huaxin.jpg b/image/character/std_huaxin.jpg new file mode 100644 index 0000000000..d1c109ec25 Binary files /dev/null and b/image/character/std_huaxin.jpg differ diff --git a/image/character/std_jiangwan.jpg b/image/character/std_jiangwan.jpg new file mode 100644 index 0000000000..f39b155641 Binary files /dev/null and b/image/character/std_jiangwan.jpg differ diff --git a/image/character/std_liubiao.jpg b/image/character/std_liubiao.jpg new file mode 100644 index 0000000000..57c32acf62 Binary files /dev/null and b/image/character/std_liubiao.jpg differ diff --git a/image/character/std_liuzhang.jpg b/image/character/std_liuzhang.jpg new file mode 100644 index 0000000000..961024b282 Binary files /dev/null and b/image/character/std_liuzhang.jpg differ diff --git a/image/character/std_maliang.jpg b/image/character/std_maliang.jpg new file mode 100644 index 0000000000..3d83fed533 Binary files /dev/null and b/image/character/std_maliang.jpg differ diff --git a/image/character/pengyang.jpg b/image/character/std_pengyang.jpg similarity index 100% rename from image/character/pengyang.jpg rename to image/character/std_pengyang.jpg diff --git a/image/character/std_simashi.jpg b/image/character/std_simashi.jpg new file mode 100644 index 0000000000..fb98c28b99 Binary files /dev/null and b/image/character/std_simashi.jpg differ diff --git a/image/character/std_sunshao.jpg b/image/character/std_sunshao.jpg new file mode 100644 index 0000000000..6802f48fff Binary files /dev/null and b/image/character/std_sunshao.jpg differ diff --git a/image/character/std_wanglang.jpg b/image/character/std_wanglang.jpg new file mode 100644 index 0000000000..02f59378ba Binary files /dev/null and b/image/character/std_wanglang.jpg differ diff --git a/image/character/std_wangyuanji.jpg b/image/character/std_wangyuanji.jpg new file mode 100644 index 0000000000..1b5e695741 Binary files /dev/null and b/image/character/std_wangyuanji.jpg differ diff --git a/image/character/std_xuezong.jpg b/image/character/std_xuezong.jpg new file mode 100644 index 0000000000..bef616504f Binary files /dev/null and b/image/character/std_xuezong.jpg differ diff --git a/image/character/std_xushu.jpg b/image/character/std_xushu.jpg new file mode 100644 index 0000000000..8083402af8 Binary files /dev/null and b/image/character/std_xushu.jpg differ diff --git a/image/character/std_zhonghui.jpg b/image/character/std_zhonghui.jpg new file mode 100644 index 0000000000..f9c4006e57 Binary files /dev/null and b/image/character/std_zhonghui.jpg differ diff --git a/image/character/swd_yunhu.jpg b/image/character/swd_yunhu.jpg deleted file mode 100644 index d4e18b3c83..0000000000 Binary files a/image/character/swd_yunhu.jpg and /dev/null differ diff --git a/image/character/ty_anying.jpg b/image/character/ty_anying.jpg new file mode 100644 index 0000000000..6e62c0b883 Binary files /dev/null and b/image/character/ty_anying.jpg differ diff --git a/image/character/ty_anyingx.jpg b/image/character/ty_anyingx.jpg new file mode 100644 index 0000000000..6e62c0b883 Binary files /dev/null and b/image/character/ty_anyingx.jpg differ diff --git a/image/character/ty_buzhi.jpg b/image/character/ty_buzhi.jpg new file mode 100644 index 0000000000..ac5d2a3d09 Binary files /dev/null and b/image/character/ty_buzhi.jpg differ diff --git a/image/character/ty_chengjix.jpg b/image/character/ty_chengjix.jpg new file mode 100644 index 0000000000..68289d03b7 Binary files /dev/null and b/image/character/ty_chengjix.jpg differ diff --git a/image/character/ty_chenshi.jpg b/image/character/ty_chenshi.jpg new file mode 100644 index 0000000000..e80f53aa5e Binary files /dev/null and b/image/character/ty_chenshi.jpg differ diff --git a/image/character/ty_fanjiang.jpg b/image/character/ty_fanjiang.jpg new file mode 100644 index 0000000000..67f1b79b96 Binary files /dev/null and b/image/character/ty_fanjiang.jpg differ diff --git a/image/character/ty_ganning.jpg b/image/character/ty_ganning.jpg new file mode 100644 index 0000000000..1a7994bc04 Binary files /dev/null and b/image/character/ty_ganning.jpg differ diff --git a/image/character/ty_guanxing.jpg b/image/character/ty_guanxing.jpg new file mode 100644 index 0000000000..f333e15f16 Binary files /dev/null and b/image/character/ty_guanxing.jpg differ diff --git a/image/character/ty_guanyinping.jpg b/image/character/ty_guanyinping.jpg new file mode 100644 index 0000000000..d13ccf0ca7 Binary files /dev/null and b/image/character/ty_guanyinping.jpg differ diff --git a/image/character/ty_guanyu.jpg b/image/character/ty_guanyu.jpg new file mode 100644 index 0000000000..d394ed0674 Binary files /dev/null and b/image/character/ty_guanyu.jpg differ diff --git a/image/character/ty_huangzhong.jpg b/image/character/ty_huangzhong.jpg new file mode 100644 index 0000000000..af541a522c Binary files /dev/null and b/image/character/ty_huangzhong.jpg differ diff --git a/image/character/ty_liaohua.jpg b/image/character/ty_liaohua.jpg new file mode 100644 index 0000000000..7552bb2788 Binary files /dev/null and b/image/character/ty_liaohua.jpg differ diff --git a/image/character/ty_liubei.jpg b/image/character/ty_liubei.jpg new file mode 100644 index 0000000000..fd0d7b7613 Binary files /dev/null and b/image/character/ty_liubei.jpg differ diff --git a/image/character/ty_liue.jpg b/image/character/ty_liue.jpg new file mode 100644 index 0000000000..81418c2b22 Binary files /dev/null and b/image/character/ty_liue.jpg differ diff --git a/image/character/ty_luxun.jpg b/image/character/ty_luxun.jpg new file mode 100644 index 0000000000..d566560bcf Binary files /dev/null and b/image/character/ty_luxun.jpg differ diff --git a/image/character/ty_shamoke.jpg b/image/character/ty_shamoke.jpg new file mode 100644 index 0000000000..8c03e6b5b8 Binary files /dev/null and b/image/character/ty_shamoke.jpg differ diff --git a/image/character/ty_shen_guanyu.jpg b/image/character/ty_shen_guanyu.jpg new file mode 100644 index 0000000000..01e98c61aa Binary files /dev/null and b/image/character/ty_shen_guanyu.jpg differ diff --git a/image/character/ty_shen_liubei.jpg b/image/character/ty_shen_liubei.jpg new file mode 100644 index 0000000000..1dc9132324 Binary files /dev/null and b/image/character/ty_shen_liubei.jpg differ diff --git a/image/character/ty_shen_zhangfei.jpg b/image/character/ty_shen_zhangfei.jpg new file mode 100644 index 0000000000..3f5df7dc67 Binary files /dev/null and b/image/character/ty_shen_zhangfei.jpg differ diff --git a/image/character/ty_shicong.jpg b/image/character/ty_shicong.jpg new file mode 100644 index 0000000000..ac02252d08 Binary files /dev/null and b/image/character/ty_shicong.jpg differ diff --git a/image/character/ty_sunquan.jpg b/image/character/ty_sunquan.jpg new file mode 100644 index 0000000000..88788ec26c Binary files /dev/null and b/image/character/ty_sunquan.jpg differ diff --git a/image/character/ty_tanxiong.jpg b/image/character/ty_tanxiong.jpg new file mode 100644 index 0000000000..142891ac05 Binary files /dev/null and b/image/character/ty_tanxiong.jpg differ diff --git a/image/character/ty_wangque.jpg b/image/character/ty_wangque.jpg new file mode 100644 index 0000000000..26cc5ba306 Binary files /dev/null and b/image/character/ty_wangque.jpg differ diff --git a/image/character/ty_wuque.jpg b/image/character/ty_wuque.jpg new file mode 100644 index 0000000000..392a9a0b98 Binary files /dev/null and b/image/character/ty_wuque.jpg differ diff --git a/image/character/ty_yanque.jpg b/image/character/ty_yanque.jpg new file mode 100644 index 0000000000..be8d233d0b Binary files /dev/null and b/image/character/ty_yanque.jpg differ diff --git a/image/character/ty_zhangda.jpg b/image/character/ty_zhangda.jpg new file mode 100644 index 0000000000..3d037ae6b0 Binary files /dev/null and b/image/character/ty_zhangda.jpg differ diff --git a/image/character/ty_zhaorong.jpg b/image/character/ty_zhaorong.jpg new file mode 100644 index 0000000000..062fd441b5 Binary files /dev/null and b/image/character/ty_zhaorong.jpg differ diff --git a/image/character/xunyuxunyou.jpg b/image/character/xunyuxunyou.jpg new file mode 100644 index 0000000000..8521c6c384 Binary files /dev/null and b/image/character/xunyuxunyou.jpg differ diff --git a/image/character/yj_majun.jpg b/image/character/yj_majun.jpg new file mode 100644 index 0000000000..82a5f93b5d Binary files /dev/null and b/image/character/yj_majun.jpg differ diff --git a/image/character/yj_sb_guojia.jpg b/image/character/yj_sb_guojia.jpg new file mode 100644 index 0000000000..594015925c Binary files /dev/null and b/image/character/yj_sb_guojia.jpg differ diff --git a/image/character/yj_sb_guojia_shadow.jpg b/image/character/yj_sb_guojia_shadow.jpg new file mode 100644 index 0000000000..eb7d36395e Binary files /dev/null and b/image/character/yj_sb_guojia_shadow.jpg differ diff --git a/image/character/yj_tianchuan.jpg b/image/character/yj_tianchuan.jpg new file mode 100644 index 0000000000..921e1171fb Binary files /dev/null and b/image/character/yj_tianchuan.jpg differ diff --git a/image/character/zhugejing.jpg b/image/character/zhugejing.jpg new file mode 100644 index 0000000000..1dadf529ee Binary files /dev/null and b/image/character/zhugejing.jpg differ diff --git a/index.html b/index.html index 9573fe2c02..1be6a393ae 100755 --- a/index.html +++ b/index.html @@ -140,7 +140,7 @@ ) { window.initReadWriteFunction = async function (game) { return new Promise((resolve, reject) => { - fetch(`./readFile?fileName=noname.js`) + fetch(`./checkFile?fileName=noname.js`) .then((response) => { return response.json(); }) @@ -151,6 +151,71 @@ .catch(reject); function callback() { + + /** + * 检查指定的路径是否是一个文件 + * + * @param {string} fileName - 需要查询的路径 + * @param {(result: -1 | 0 | 1) => void} [callback] - 回调函数;接受的参数意义如下: + * - `-1`: 路径不存在或无法访问 + * - `0`: 路径的内容不是文件 + * - `1`: 路径的内容是文件 + * @param {(err: Error) => void} [onerror] - 接收错误的回调函数 + * @return {void} - 由于三端的异步需求和历史原因,文件管理必须为回调异步函数 + */ + game.checkFile = function (fileName, callback, onerror) { + fetch(`./checkFile?fileName=${fileName}`) + .then(response => response.json()) + .then(result => { + if (result) { + if (result.success) { + callback?.(1); + return; + } + + if (result.code === 404) { + if (result.errorMsg === "不是一个文件") return void callback?.(0); + else if (result.errorMsg === "文件不存在或无法访问") return void callback?.(-1); + } + } + + onerror?.(result?.errorMsg); + }) + .catch(onerror); + } + + /** + * 检查指定的路径是否是一个目录 + * + * @param {string} dir - 需要查询的路径 + * @param {(result: -1 | 0 | 1) => void} [callback] - 回调函数;接受的参数意义如下: + * - `-1`: 路径不存在或无法访问 + * - `0`: 路径的内容不是目录 + * - `1`: 路径的内容是目录 + * @param {(err: Error) => void} [onerror] - 接收错误的回调函数 + * @return {void} - 由于三端的异步需求和历史原因,文件管理必须为回调异步函数 + */ + game.checkDir = function (dir, callback, onerror) { + fetch(`./checkDir?dir=${dir}`) + .then(response => response.json()) + .then(result => { + if (result) { + if (result.success) { + callback?.(1); + return; + } + + if (result.code === 404) { + if (result.errorMsg === "不是一个文件夹") return void callback?.(0); + else if (result.errorMsg === "文件夹不存在或无法访问") return void callback?.(-1); + } + } + + onerror?.(result?.errorMsg); + }) + .catch(onerror); + } + game.readFile = function (fileName, callback = () => {}, error = () => {}) { fetch(`./readFile?fileName=${fileName}`) .then((response) => { diff --git a/layout/default/layout.css b/layout/default/layout.css index 9f75f4b2f2..7b5e087fcd 100644 --- a/layout/default/layout.css +++ b/layout/default/layout.css @@ -3803,6 +3803,8 @@ div:hover > .intro { background: rgba(0, 0, 0, 0.2); box-shadow: rgba(0, 0, 0, 0.3) 0 0 0 1px; border-radius: 4px; + padding-left: 30px; + padding-right: 30px; } .tdnode { diff --git a/layout/mobile/equip.css b/layout/mobile/equip.css index 16d6664b6f..64f6e0d401 100644 --- a/layout/mobile/equip.css +++ b/layout/mobile/equip.css @@ -107,24 +107,24 @@ background: linear-gradient(rgba(0, 133, 255, 0.6), rgba(0, 133, 255, 0.5)) !important; box-shadow: rgba(0, 0, 0, 0.4) 0 1px 0 0 !important; } -#arena:not(.chess).textequip .player[data-position="0"] .equips > .card.fire, -.player:not([data-position="0"]) .equips > .card.fire, -#arena.chess .player .equips > .card.fire { +#arena:not(.chess).textequip .player[data-position="0"] .equips > .card.fire:not(.fakeequip), +.player:not([data-position="0"]) .equips > .card.fire:not(.fakeequip), +#arena.chess .player .equips > .card.fire:not(.fakeequip) { color: rgb(255, 119, 63); } -#arena:not(.chess).textequip .player[data-position="0"] .equips > .card.thunder, -.player:not([data-position="0"]) .equips > .card.thunder, -#arena.chess .player .equips > .card.thunder { +#arena:not(.chess).textequip .player[data-position="0"] .equips > .card.thunder:not(.fakeequip), +.player:not([data-position="0"]) .equips > .card.thunder:not(.fakeequip), +#arena.chess .player .equips > .card.thunder:not(.fakeequip) { color: rgb(117, 186, 255); } -#arena:not(.chess).textequip .player[data-position="0"] .equips > .card.poison, -.player:not([data-position="0"]) .equips > .card.poison, -#arena.chess .player .equips > .card.poison { +#arena:not(.chess).textequip .player[data-position="0"] .equips > .card.poison:not(.fakeequip), +.player:not([data-position="0"]) .equips > .card.poison:not(.fakeequip), +#arena.chess .player .equips > .card.poison:not(.fakeequip) { color: rgb(104, 221, 127); } -#arena:not(.chess).textequip .player[data-position="0"] .equips > .card.brown, -.player:not([data-position="0"]) .equips > .card.brown, -#arena.chess .player .equips > .card.brown { +#arena:not(.chess).textequip .player[data-position="0"] .equips > .card.brown:not(.fakeequip), +.player:not([data-position="0"]) .equips > .card.brown:not(.fakeequip), +#arena.chess .player .equips > .card.brown:not(.fakeequip) { color: rgb(195, 161, 223); } diff --git a/layout/newlayout/equip.css b/layout/newlayout/equip.css index 900eedf9a4..9c96cf4e59 100644 --- a/layout/newlayout/equip.css +++ b/layout/newlayout/equip.css @@ -77,16 +77,16 @@ border-style: solid; border-image: linear-gradient(to right, rgba(0, 103, 205, 0.4) 70%, transparent) 100% 0 0; } -.player .equips > .card.fire { +.player .equips > .card.fire:not(.fakeequip) { color: rgb(255, 119, 63); } -.player .equips > .card.thunder { +.player .equips > .card.thunder:not(.fakeequip) { color: rgb(117, 186, 255); } -.player .equips > .card.poison { +.player .equips > .card.poison:not(.fakeequip) { color: rgb(104, 221, 127); } -.player .equips > .card.brown { +.player .equips > .card.brown:not(.fakeequip) { color: rgb(195, 161, 223); } diff --git a/mode/boss.js b/mode/boss.js index 2bb3a2da50..d018761388 100644 --- a/mode/boss.js +++ b/mode/boss.js @@ -1,8 +1,12 @@ -"use strict"; -game.import("mode", function (lib, game, ui, get, ai, _status) { +import { lib, game, ui, get, ai, _status } from '../noname.js'; +export const type = 'mode'; +/** + * @type { () => importModeConfig } + */ +export default () => { return { name: "boss", - start: function () { + start() { "step 0"; var playback = localStorage.getItem(lib.configprefix + "playback"); if (playback) { @@ -70,7 +74,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.onresume = onresume; game.onresume2 = onresume; ui.create.div(bosslist); - + event.current = null; var list = []; if (lib.storage.current == undefined) lib.storage.current = "boss_hundun"; @@ -105,7 +109,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { player.node.identity.dataset.color = info[5]; // bosslistlinks[cfg]=player; player.classList.add("bossplayer"); - + if (lib.storage.current == i) { event.current = player; player.classList.add("highlight"); @@ -115,7 +119,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _status.bosschoice.link = lib.boss[i].controlid || i; } } - + // if(!get.config(cfg)){ // player.style.display='none'; // } @@ -142,9 +146,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { setTimeout(function () { ui.control.style.transitionProperty = ""; }, 1000); - + ui.window.appendChild(bosslist); - + setTimeout(function () { if (event.current) { var left = event.current.offsetLeft - (ui.window.offsetWidth - 180) / 2; @@ -206,7 +210,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { for (var i in lib.boss[event.current.name]) { game.bossinfo[i] = lib.boss[event.current.name][i]; } - + setTimeout(function () { ui.control.classList.remove("bosslist"); }, 500); @@ -308,7 +312,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ui.arena.classList.add("single-handcard"); ui.window.classList.add("single-handcard"); game.onSwapControl(); - + if (lib.config.show_handcardbutton) { lib.setPopped( ui.create.system("手牌", null, true), @@ -339,10 +343,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ui.create.system("重整", null, true), function () { var uiintro = ui.create.dialog("hidden"); - + uiintro.add("重整"); var table = ui.create.div(".bosschongzheng"); - + var tr, td, added = false; @@ -397,7 +401,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (get.config("single_control") || game.me == game.boss) { ui.single_swap.style.display = "none"; } - + ui.arena.appendChild(boss); if (boss.bossinginfo) { var rect = boss.getBoundingClientRect(); @@ -415,14 +419,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss.node.equips.style.opacity = ""; }, 500); } - + event.bosslist.delete(); - + game.arrangePlayers(); for (var i = 0; i < game.players.length; i++) { game.players[i].node.action.innerHTML = "行动"; } - + var players = get.players(lib.sort.position); var info = []; for (var i = 0; i < players.length; i++) { @@ -869,7 +873,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["qun", "hiddenboss", "bossallowed"], "qun", ], - + boss_xiangliu: [ "male", "qun", @@ -902,7 +906,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["qun", "boss", "bossallowed"], "qun", ], - + boss_qingmushilian: [ "male", "", @@ -933,7 +937,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["boss_shenyi", "boss_shenen", "boss_qingyi"], ["wu", "hiddenboss", "bossallowed"], ], - + boss_chiyanshilian: [ "male", "", @@ -970,7 +974,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["boss_shenyi", "boss_shenen", "boss_chiyi"], ["shu", "hiddenboss", "bossallowed"], ], - + boss_baimangshilian: [ "male", "", @@ -1007,7 +1011,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["boss_shenyi", "boss_shenen", "boss_baiyi"], ["qun", "hiddenboss", "bossallowed"], ], - + boss_xuanlinshilian: [ "male", "", @@ -1044,7 +1048,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["boss_shenyi", "boss_shenen", "boss_zaoyi"], ["wei", "hiddenboss", "bossallowed"], ], - + boss_zhuoguiquxie: [ "male", "", @@ -1099,7 +1103,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["shu", "hiddenboss", "bossallowed"], "shu", ], - + boss_baiwuchang: [ "male", "shen", @@ -1170,7 +1174,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["boss_guimei", "boss_guihuo", "boss_minbao", "boss_bianshen2"], ["shu", "hiddenboss", "bossallowed"], ], - + boss_qinguangwang: [ "male", "qun", @@ -1257,7 +1261,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["shu", "hiddenboss", "bossallowed"], ], //boss_shikieiki:['female','qun',8,['boss_yingzhong'],['qun','hiddenboss','bossallowed']], - + boss_lvbu1: [ "male", "shen", @@ -1282,7 +1286,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["qun", "hiddenboss", "bossallowed"], "qun", ], - + boss_caocao: [ "male", "shen", @@ -1315,7 +1319,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["wei", "boss", "bossallowed"], "wei", ], - + boss_liubei: [ "male", "shen", @@ -1348,7 +1352,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["shu", "boss", "bossallowed"], "zhu", ], - + boss_zhouyu: [ "male", "shen", @@ -1357,7 +1361,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["wu", "boss", "bossallowed"], "zhu", ], - + boss_caiwenji: [ "female", "shen", @@ -1375,7 +1379,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "shu", ], boss_zuoci: ["male", "shen", 0, ["huanhua"], ["qun", "boss", "bossallowed"], "shu"], - + boss_diaochan: [ "female", "shen", @@ -1400,7 +1404,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["qun", "boss", "bossallowed"], "shu", ], - + boss_sunce: [ "male", "shen", @@ -1409,7 +1413,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["qun", "boss", "bossallowed", "InitFilter:noZhuHp:noZhuSkill", "die:sunce"], "wu", ], - + // boss_nianshou:['male','shen',Infinity,['boss_nianrui','boss_qixiang','boss_damagecount'],['boss'],'shu'], // boss_yuji:['male','qun',8,[],['boss','bossallowed'],'nei'], // boss_shuijing:['male','qun',8,[],['boss','bossallowed'],'wei'], @@ -1435,7 +1439,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "gubuzifeng", ], }, - init: function () { + init() { for (var i in lib.characterPack.mode_boss) { if (lib.characterPack.mode_boss[i].isHiddenBoss) continue; lib.mode.boss.config[i + "_boss_config"] = { @@ -1465,7 +1469,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { player = game.boss; delete game.boss; } - + player.delete(); game.players.remove(player); game.dead.remove(player); @@ -1584,7 +1588,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ui.versushighlight = game.me; game.me.classList.add("current_action"); // game.me.line(ui.fakeme,{opacity:0.5,dashed:true}); - + ui.fakeme.style.backgroundImage = game.me.node.avatar.style.backgroundImage; // ui.fakeme.style.backgroundSize='cover'; } @@ -1672,7 +1676,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.changeCoin(-3); } list.randomSort(); - + var buttons = ui.create.div(".buttons"); var node = _status.event.dialog.buttons[0].parentNode; _status.event.dialog.buttons = ui.create.buttons( @@ -1683,7 +1687,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _status.event.dialog.content.insertBefore(buttons, node); buttons.addTempClass("start"); node.remove(); - + game.uncheck(); game.check(); }; @@ -1754,7 +1758,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }; if (!ui.cheat && get.config("change_choice")) ui.create.cheat(); if (!ui.cheat2 && get.config("free_choose")) ui.create.cheat2(); - + event.asboss = ui.create.control("应战", function () { event.boss = true; event.enemy = []; @@ -2013,7 +2017,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var dialog = control.dialog; dialog.content.removeChild(control.backup1); dialog.buttons.removeArray(control.backup2); - + game.uncheck(); game.check(); } else { @@ -2042,7 +2046,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { dialog.buttons.addArray(this.backup2); } this.classList.toggle("glow"); - + game.uncheck(); game.check(); }); @@ -2543,8 +2547,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { return target.isFriendOf(player); }) .set("forceDie", true).ai = function (target) { - return get.attitude(_status.event.player, target); - }; + return get.attitude(_status.event.player, target); + }; "step 1"; if (result.bool) { var target = result.targets[0]; @@ -2749,8 +2753,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { get.prompt("noda_axe", trigger.target), 2, "弃置两张牌,令" + - get.translation(trigger.target) + - "本回合内不能使用或打出牌且防具技能无效。", + get.translation(trigger.target) + + "本回合内不能使用或打出牌且防具技能无效。", function (card, player) { return card != player.getEquip(1); } @@ -2921,8 +2925,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { .chooseControl(list) .set("prompt", "请选择下一个出战的角色") .set("forceDie", true).ai = function () { - return list.randomGet(); - }; + return list.randomGet(); + }; "step 2"; _status.shidianyanluo_level++; game.changeBoss(result.control); @@ -3211,8 +3215,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } ) .set("forceDie", true).ai = function (target) { - return -get.attitude(_status.event.player, target); - }; + return -get.attitude(_status.event.player, target); + }; "step 1"; if (result.bool) { var target = result.targets[0]; @@ -3325,11 +3329,11 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { effect: { target: function (card, player, target, current) { if (!target.hasEmptySlot("equip2")) return; - if (card.name == "nanman" || card.name == "wanjian") return "zerotarget"; + if (card.name == "nanman" || card.name == "wanjian") return "zeroplayertarget"; if (card.name == "sha") { var equip1 = player.getEquip(1); if (equip1 && equip1.name == "zhuque") return 1.9; - if (!game.hasNature(card)) return "zerotarget"; + if (!game.hasNature(card)) return "zeroplayertarget"; } }, }, @@ -3352,7 +3356,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { target.damage("fire"); }, }, - + boss_huoxing: { trigger: { player: "die" }, forceDie: true, @@ -4209,7 +4213,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + boss_yaoshou: { mod: { globalFrom: function (from, to, distance) { @@ -6906,15 +6910,15 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { .set("prompt", get.prompt("boss_yuance")) .set("choiceList", [ "若判定结果为黑色," + - playername + - "失去1点体力,否则" + - sourcename + - "失去1点体力", + playername + + "失去1点体力,否则" + + sourcename + + "失去1点体力", "若判定结果为红色," + - playername + - "回复1点体力,否则" + - sourcename + - "回复1点体力", + playername + + "回复1点体力,否则" + + sourcename + + "回复1点体力", ]); "step 1"; var att1 = get.attitude(player, trigger.player); @@ -7136,7 +7140,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_zhangwu_ai: { ai: { effect: { - target: function (card, player, target) { + target_use: function (card, player, target) { if (get.tag(card, "recover") && card.name != "recover") { for (var i = 0; i < game.players.length; i++) { if ( @@ -7171,10 +7175,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { return player.countCards("h") == 0; }, x6: function (player, event) { - if(event.hasNature) return event.hasNature("fire"); + if (event.hasNature) return event.hasNature("fire"); }, x5: function (player, event) { - if(event.hasNature) return event.hasNature("thunder"); + if (event.hasNature) return event.hasNature("thunder"); }, x4: function (player, event) { return event.name == "loseHp"; @@ -7369,7 +7373,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { event.dialog = ui.create.dialog(judgestr); event.dialog.classList.add("center"); event.dialog.videoId = event.videoId; - + game.addVideo("judge1", player, [get.cardInfo(card), judgestr, event.videoId]); for (var i = 0; i < event.cards.length; i++) event.cards[i].discard(); // var node=card.copy('thrown','center',ui.arena).addTempClass('start'); @@ -7428,12 +7432,12 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "step 0"; player.chooseCard( get.translation(trigger.player) + - "的" + - (trigger.judgestr || "") + - "判定为" + - get.translation(trigger.player.judging[0]) + - "," + - get.prompt("tiandao"), + "的" + + (trigger.judgestr || "") + + "判定为" + + get.translation(trigger.player.judging[0]) + + "," + + get.prompt("tiandao"), "he" ).ai = function (card) { var trigger = _status.event.parent._trigger; @@ -7590,7 +7594,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, ai: { effect: { - target: function (card, player, target) { + target_use: function (card, player, target) { if (get.tag(card, "respondShan")) { var shans = target.countCards("h", "shan"); var hs = target.countCards("h"); @@ -7640,7 +7644,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ai: { mingzhi: false, effect: { - target: function (card, player, target) { + target_use: function (card, player, target) { if (get.tag(card, "respondShan")) { var shans = target.countCards("h", "shan"); var hs = target.countCards("h"); @@ -7921,7 +7925,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ai: { effect: { target: function (card, player, target, current) { - if (card.name == "lebu" && card.name == "bingliang") return 0.8; + if (card.name == "lebu" || card.name == "bingliang") return 0.8; }, }, }, @@ -8269,9 +8273,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, ai: { effect: { - target_use: function (card, player, target, current) { + target: function (card, player, target, current) { if (target.getEquip(2)) return; - return lib.skill.tengjia1.ai.effect.target_use.apply(this, arguments); + return lib.skill.tengjia1.ai.effect.target.apply(this, arguments); }, }, }, @@ -8538,7 +8542,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, ai: { effect: { - target: function (card, player, target, current) { + target_use: function (card, player, target, current) { if (get.tag(card, "respondShan")) { var hastarget = false, players = game.filterPlayer(); @@ -8764,7 +8768,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { threaten: 0.8, effect: { target: function (card) { - if (card.name == "bingliang") return 0; + if (card.name == "bingliang") return [0, 0]; }, }, }, @@ -8946,7 +8950,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { effect: { target: function (card) { if (get.tag(card, "fireDamage")) { - return [0, 2]; + return [0, 2, 0, 0]; } }, }, @@ -9206,7 +9210,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, ai: { effect: { - player: function (card) { + player_use: function (card) { if (get.color(card) == "black") { return [1, 2]; } @@ -9838,7 +9842,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { zhu: "神", cai: "盟", zhong: "从", - + boss_chi: "魑", boss_mo: "魅", boss_wang: "魍", @@ -9850,14 +9854,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_luocha: "罗刹", boss_yecha: "夜叉", boss_zhuoguiquxie: "捉鬼驱邪", - + boss_nianshou: "年兽", boss_nianshou_heti: "年兽", boss_nianshou_jingjue: "警觉年兽", boss_nianshou_renxing: "任性年兽", boss_nianshou_baonu: "暴怒年兽", boss_nianshou_ruizhi: "睿智年兽", - + boss_shuijing: "水镜先生", boss_huangyueying: "奇智女杰", boss_zhangchunhua: "冷血皇后", @@ -9880,13 +9884,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_diaochan: "绝代妖姬", boss_guojia: "世之奇士", boss_caocao: "魏武大帝", - + boss_chiyanshilian: "夏之试炼", boss_zhuque: "朱雀", boss_huoshenzhurong: "火神祝融", boss_yanling: "焰灵", boss_yandi: "炎帝", - + boss_hundun: "混沌", boss_qiongqi: "穷奇", boss_taowu: "梼杌", @@ -9896,7 +9900,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_zhuyan: "朱厌", boss_bifang: "毕方", boss_yingzhao: "英招", - + boss_yaoshou: "妖兽", boss_yaoshou_info: "锁定技,你与其他角色计算-2。", boss_duqu: "毒躯", @@ -9939,7 +9943,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_sipu_switch: "司圃", boss_sipu_info: "体力值首次减少至一半或更少时激活此技能。锁定技,你的出牌阶段内,若你使用的牌数小于等于2张,其他角色无法使用或打出牌。", - + boss_wuzang: "无脏", boss_wuzang_info: "锁定技,摸牌阶段,你的摸牌基数改为X(X为你的体力值一半且至少为5);你的手牌上限基数为0。", @@ -10002,25 +10006,25 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { honghuangzhili_cbg: "洪", honghuangzhili_info: "若该角色的势力是神,你获得其一张牌,其〖神裔〗无效直到其下家的回合(这个下家是动态变化的,会随着一个人的死或者复活而变化)开始;若该角色的势力不是神,其翻面。", - + boss_qingmushilian: "春之试炼", boss_qinglong: "青龙", boss_mushengoumang: "木神勾芒", boss_shujing: "树精", boss_taihao: "太昊", - + boss_baimangshilian: "秋之试炼", boss_baihu: "白虎", boss_jinshenrushou: "金神蓐收", boss_mingxingzhu: "明刑柱", boss_shaohao: "少昊", - + boss_xuanlinshilian: "冬之试炼", boss_xuanwu: "玄武", boss_shuishenxuanming: "水神玄冥", boss_shuishengonggong: "水神共工", boss_zhuanxu: "颛顼", - + boss_lingqu: "灵躯", boss_lingqu_info: "锁定技,当你受到伤害后,你摸一张牌,然后手牌上限+1;防止你受到的大于1点的伤害。", @@ -10083,7 +10087,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_qingyi: "青仪", boss_qingyi_info: "锁定技,第三轮开始时,己方角色各回复1点体力;第五轮开始时,敌方角色各失去1点体力;第七轮开始时,复活木神勾芒和树精,使其各摸三张牌,各+1体力上限,然后各回复3点体力。", - + boss_guimou: "鬼谋", boss_guimou_info: "结束阶段,你可以令一名随机的其他角色进入混乱状态直到其下一回合结束。", boss_yuance: "远策", @@ -10118,7 +10122,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "锁定技,在你的判定牌生效前,你观看牌堆顶的七张牌并选择一张作为判定结果,此结果不可更改。", fengqi: "风起", fengqi_info: "准备阶段和结束阶段,你可以视为使用任意一张普通锦囊牌。", - + jiaoxia: "皎霞", jiaoxia_info: "每当你成为红色牌的目标,你可以摸一张牌。", lingbo: "凌波", @@ -10136,7 +10140,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { mazui2: "麻醉", mazui_info: "出牌阶段限一次,你可以将一张黑色手牌置于一名角色的武将牌上,该角色造成的下一次伤害-1,然后获得此牌。", - + boss_nbianshen: "变形", boss_nbianshenx: "变形", boss_nbianshenx_info: "你从第二轮开始,每一轮幻化为警觉、任性、睿智、暴怒四种随机状态中的一种。", @@ -10155,7 +10159,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "锁定技,摸牌阶段,你改为摸X张牌(X为4到你体力值间的随机数);若你的体力值小于5,则你使用【杀】造成的伤害+1且无次数限制。", boss_shouyi: "兽裔", boss_shouyi_info: "锁定技,你使用牌无距离限制。", - + boss_nianrui: "年瑞", boss_nianrui_info: "锁定技,摸牌阶段,你额外摸两张牌。", boss_qixiang: "祺祥", @@ -10163,12 +10167,12 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_qixiang2: "祺祥", boss_qixiang_info: "乐不思蜀判定时,你的方块判定牌视为红桃;兵粮寸断判定时,你的黑桃判定牌视为草花。", - + qiwu: "栖梧", qiwu_info: "锁定技。每当你使用一张梅花牌,你回复1点体力。", jizhen: "激阵", jizhen_info: "结束阶段,你可以令所至多两名已受伤角色摸一张牌。", - + boss_yushou: "驭兽", boss_yushou_info: "出牌阶段开始时,你可以对所有敌方角色使用一张【南蛮入侵】。", boss_moyany: "魔炎", @@ -10180,7 +10184,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_mojian_info: "出牌阶段开始时,你可以对所有敌方角色使用一张【万箭齐发】。", boss_danshu: "丹术", boss_danshu_info: "每当你于回合外失去牌时,你可以进行一次判定,若结果为红色,你回复1点体力。", - + boss_zuijiu: "醉酒", boss_zuijiu_info: "锁定技,你因【杀】造成伤害时,此伤害+1。", boss_taiping: "太平", @@ -10189,7 +10193,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_suoming_info: "结束阶段,将任意名未被横置的其他角色的武将牌横置。", boss_xixing: "吸星", boss_xixing_info: "准备阶段,对任意一名横置的其他角色造成1点雷电伤害,然后回复1点体力。", - + boss_baolian: "暴敛", boss_baolian_info: "锁定技,结束阶段,你摸两张牌。", boss_manjia: "蛮甲", @@ -10200,7 +10204,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_guiji_info: "锁定技,准备阶段结束时,若你的判定区内有牌,你随机弃置其中一张牌。", boss_lianyu: "炼狱", boss_lianyu_info: "结束阶段,你可以对所有敌方角色造成1点火焰伤害。", - + boss_guihuo: "鬼火", boss_guihuo_info: "结束阶段,你可以对一名其他角色造成1点火焰伤害。", boss_minbao: "冥爆", @@ -10215,7 +10219,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_didong_info: "结束阶段,你可以选择一名敌方角色将其武将牌翻面。", boss_shanbeng: "山崩", boss_shanbeng_info: "锁定技,当你死亡时,你令所有其他角色弃置其装备区内的所有牌。", - + boss_chiyan_intro1: " 第一关", boss_chiyan_intro1_info: "挑战朱雀", boss_chiyan_intro2: " 第二关", @@ -10224,7 +10228,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_chiyan_intro3_info: "挑战炎帝、火神祝融、焰灵", boss_chiyan_intro3_append: "每通过一关,游戏轮数清零,阵亡角色复活,所有角色重置武将和区域内的牌,并获得4-X张起始手牌,X为阵亡角色数。", - + boss_qingmu_intro1: " 第一关", boss_qingmu_intro1_info: "挑战青龙", boss_qingmu_intro2: " 第二关", @@ -10233,7 +10237,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_qingmu_intro3_info: "挑战太昊、木神勾芒、树精", boss_qingmu_intro3_append: "每通过一关,游戏轮数清零,阵亡角色复活,所有角色重置武将和区域内的牌,并获得4-X张起始手牌,X为阵亡角色数。", - + boss_xuanlin_intro1: " 第一关", boss_xuanlin_intro1_info: "挑战玄武", boss_xuanlin_intro2: " 第二关", @@ -10242,7 +10246,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_xuanlin_intro3_info: "挑战颛顼、水神玄冥、水神共工", boss_xuanlin_intro3_append: "每通过一关,游戏轮数清零,阵亡角色复活,所有角色重置武将和区域内的牌,并获得4-X张起始手牌,X为阵亡角色数。", - + boss_baimang_intro1: " 第一关", boss_baimang_intro1_info: "挑战白虎", boss_baimang_intro2: " 第二关", @@ -10251,7 +10255,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_baimang_intro3_info: "挑战少昊、金神蓐收、明刑柱", boss_baimang_intro3_append: "每通过一关,游戏轮数清零,阵亡角色复活,所有角色重置武将和区域内的牌,并获得4-X张起始手牌,X为阵亡角色数。", - + boss_bianshen_intro1: " 第一关", boss_bianshen_intro1_info: "挑战魑、魅、魍、魉中的随机一个", boss_bianshen_intro2: " 第二关", @@ -10266,7 +10270,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { // boss_bianshen3_info:'你死亡后,随机召唤白无常、黑无常中的一个。', // boss_bianshen4:'后援', // boss_bianshen4_info:'你死亡后,随机召唤罗刹、夜叉中的一个。', - + boss_qiangzheng: "强征", boss_qiangzheng_info: "锁定技,结束阶段,你获得每个敌方角色的一张手牌。", boss_baolin: "暴凌", @@ -10277,7 +10281,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_shengshou_info: "每当你使用一张牌,你可以进行一次判定,若为红色,你回复1点体力。", wuqin: "五禽戏", wuqin_info: "结束阶段,若你没有手牌,可以摸三张牌。", - + boss_konghun: "控心", boss_konghun_info: "结束阶段,你可以指定一名敌人令其进入混乱状态(不受对方控制,并将队友视为敌人)直到下一回合开始。", @@ -10287,18 +10291,18 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { fengwu_info: "出牌阶段限一次,可令除你外的所有角色依次对与其距离最近的另一名角色使用一张【杀】,无法如此做者失去1点体力。", boss_wange: "笙歌", - + huanhua: "幻化", huanhua_info: "锁定技,游戏开始时,你获得其他角色的所有技能,体力上限变为其他角色之和;其他角色于摸牌阶段摸牌时,你摸等量的牌;其他角色于弃牌阶段弃牌时,你弃置等量的手牌。", - + boss_leiji: "雷击", boss_leiji_info: "每当你使用或打出一张【闪】,可令任意一名角色进行一次判定,若结果为黑色,其受到1点雷电伤害,然后你摸一张牌。", jidian: "亟电", jidian_info: "每当你造成一次伤害,可以指定距离受伤害角色1以内的一名其他角色进行判定,若结果为黑色,该角色受到1点雷电伤害。", - + tinqin: "听琴", boss_guihan: "归汉", boss_guihan_info: @@ -10316,24 +10320,24 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_xianyin: "仙音", boss_xianyin_info: "每当你于回合外失去牌,你可以进行一次判定,若为红色,你令一名敌人失去1点体力。", - + boss_yuhuo: "浴火", boss_yuhuo_info: "觉醒技,在你涅槃后,你获得技能〖神威〗、〖朱羽〗。", boss_tianyu: "天狱", boss_tianyu_info: "锁定技,结束阶段,你解除横置状态,除你之外的所有角色进入横置状态。", - + boss_jizhi: "集智", boss_jizhi_info: "每当你使用一张非转化的非基本牌,你可以摸一张牌并展示之。", boss_guiyin: "归隐", boss_guiyin_info: "锁定技,体力值比你多的角色无法在回合内对你使用卡牌。", boss_gongshen: "工神", boss_gongshen_info: "锁定技,除你之外的角色没有装备区;你不能成为其他角色的延时锦囊牌的目标。", - + fanghua: "芳华", fanghua_info: "结束阶段,你可以令所有已翻面角色失去1点体力。", tashui: "踏水", tashui_info: "每当你使用或打出一张黑色牌,你可以令一名其他角色翻面。", - + boss_wuxin: "无心", boss_wuxin_info: "锁定技,你防止即将受到的伤害,改为失去1点体力;你不能成为其他角色的延时锦囊的目标。", @@ -10341,7 +10345,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { shangshix2: "伤逝", shangshix_info: "锁定技,你的手牌数至少为4,结束阶段,若你的体力值大于1,你令场上所有角色失去1点体力。", - + boss_baonu: "暴怒", boss_baonu_info: "锁定技,当你的体力值降至4或更低时,你变身为暴怒战神或神鬼无前,并立即开始你的回合。", @@ -10357,13 +10361,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { jiwu: "极武", jiwu_info: "出牌阶段,你可以弃置一张牌,然后获得获得以下一项技能直到回合结束:〖强袭〗、〖铁骑〗、〖旋风〗、〖完杀〗。", - + boss_jingjia: "精甲", boss_jingjia_info: "锁定技,游戏开始时,将本局游戏中加入的装备随机置入你的装备区。", boss_aozhan: "鏖战", boss_aozhan_info: "锁定技,若你装备区内有:武器牌,你可以多使用一张【杀】;防具牌,防止你受到的超过1点的伤害;坐骑牌,摸牌阶段多摸一张牌;宝物牌,跳过你的判定阶段。", - + boss_qinguangwang_ab: "秦广王", boss_qinguangwang: "秦广王·蒋子文", boss_panguan: "判官", @@ -10491,7 +10495,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "boss_sdyl_playerlevel4_info":"摸牌阶段多摸一张牌,起始手牌+1。", "boss_sdyl_playerlevel5":"重生", "boss_sdyl_playerlevel5_info":"限定技,当你处于濒死状态时,你可以弃置所有判定区牌,然后复原你的武将牌,将手牌补充至手牌体力上限(至多为5),将体力回复至体力上限。", - + "boss_sdyl_bosslevel1":"一阶", "boss_sdyl_bosslevel1_info":"", "boss_sdyl_bosslevel2":"二阶", @@ -10515,12 +10519,12 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_taoni: "讨逆", boss_taoni_info: "锁定技,游戏开始时,每名角色回合开始时或你死亡时,你检查存活角色的合法性。若有角色存在非法行为,则你终止本局游戏。", - + boss_xhuanren: "关卡说明", boss_xhuanren_info: "", boss_xhuanren_info_boss: "第一关:挑战秦广王
    第二关:挑战楚江王,宋帝王,五官王,阎罗王中的一个
    第三关:挑战卞城王,泰山王,都市王,平等王中的一个
    第四关:挑战转轮王", - + boss_newhuanren: "关卡说明", boss_newhuanren_info: "", boss_newhuanren_info_boss: @@ -10559,10 +10563,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "当你减少1点体力上限后,你可令一名其他角色增加1点体力上限并回复1点体力。", shenzhixiunvfu: "神之修女服", shenzhixiunvfu_info: "没什么实际作用的衣服,仅仅是显得像个神而已。", - + mode_boss_card_config: "挑战卡牌", mode_boss_character_config: "挑战武将", - + // 台词部分 "#boss_lvbu1:die": "虎牢关,失守了……", "#xiuluo1": "准备受死吧!", @@ -10592,5 +10596,5 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { return from.side === to.side ? num : -num; }, }, - }; -}); + } +} diff --git a/mode/brawl.js b/mode/brawl.js index 716777d0b2..9ff0184e74 100644 --- a/mode/brawl.js +++ b/mode/brawl.js @@ -1,11 +1,15 @@ -"use strict"; -game.import("mode", function (lib, game, ui, get, ai, _status) { +import { lib, game, ui, get, ai, _status } from "../noname.js"; +export const type = 'mode'; +/** + * @type { () => importModeConfig } + */ +export default () => { return { name: "brawl", game: { syncMenu: true, }, - start: function () { + start() { ui.auto.hide(); if (!lib.storage.scene) { lib.storage.scene = {}; @@ -113,11 +117,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { node.nodes = [showcase]; showcase.style.height = "100%"; } else { - node.nodes = [ - ui.create.div(".caption", caption), - ui.create.div(".text center", intro), - showcase, - ]; + node.nodes = [ui.create.div(".caption", caption), ui.create.div(".text center", intro), showcase]; } node.link = name; node._nostart = info.nostart; @@ -164,11 +164,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } } else { ui.create.control("重新开始", function () { - if ( - stage.mode == "sequal" && - bool && - level.index == stage.scenes.length - 1 - ) { + if (stage.mode == "sequal" && bool && level.index == stage.scenes.length - 1) { game.save("directStage", [stage.name, 0], "brawl"); } else { game.save("directStage", [stage.name, level.index], "brawl"); @@ -369,10 +365,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { huanhuazhizhan: { name: "幻化之战", mode: "identity", - intro: [ - "杀死所有其他角色,成为最后的存活者", - "所有角色改为四血白板,依靠灵力值获得技能。灵力值可以通过各种方式获得", - ], + intro: ["杀死所有其他角色,成为最后的存活者", "所有角色改为四血白板,依靠灵力值获得技能。灵力值可以通过各种方式获得"], showcase: function (init) { if (init) { this.nodes = []; @@ -390,16 +383,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var dy = Math.round(ly * Math.sin(deg)); node.style.transform = "translate(" + dx + "px," + dy + "px)"; }; - var characterz = [ - "guyong", - "litong", - "mazhong", - "fuwan", - "chengpu", - "liaohua", - "xinxianying", - "liuyu", - ]; + var characterz = ["guyong", "litong", "mazhong", "fuwan", "chengpu", "liaohua", "xinxianying", "liuyu"]; for (var i = 0; i < 8; i++) { var node = ui.create.player(null, true); this.nodes.push(node); @@ -553,18 +537,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { for (var j = 0; j < list.length; j++) { if (skills.includes(list[j]) || banned.includes(list[j])) continue; var info = get.info(list[j]); - if ( - !info || - info.zhuSkill || - info.juexingji || - info.charlotte || - info.limited || - info.hiddenSkill || - info.dutySkill || - info.groupSkill || - (info.ai && info.ai.combo) - ) - continue; + if (!info || info.zhuSkill || info.juexingji || info.charlotte || info.limited || info.hiddenSkill || info.dutySkill || info.groupSkill || (info.ai && info.ai.combo)) continue; skills.push(list[j]); } } @@ -657,7 +630,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { content: function () { "step 0"; player.changeLingli(-2); - "step 1"; + ("step 1"); event.skills = lib.huanhuazhizhan.skills; var skills = event.skills; skills.randomSort(); @@ -676,7 +649,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { player.chooseControl(event.list).set("ai", function () { return 0; }).dialog = dialog; - "step 2"; + ("step 2"); if (result.control == "刷新") { player.changeLingli(-1); event.goto(1); @@ -685,10 +658,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { event.skill = result.control; if (player.skillH.length == 3) { event.lose = true; - player.chooseControl(player.skillH).prompt = - "选择失去1个已有技能"; + player.chooseControl(player.skillH).prompt = "选择失去1个已有技能"; } - "step 3"; + ("step 3"); if (event.lose) player.removeSkillH(result.control); player.addSkillH(event.skill); }, @@ -718,11 +690,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { order: 10, result: { player: function (player) { - return player.storage._lingli - - 2 * (3 - player.skillH.length) > - 0 - ? 1 - : 0; + return player.storage._lingli - 2 * (3 - player.skillH.length) > 0 ? 1 : 0; }, }, }, @@ -745,12 +713,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { forceDie: true, popup: false, filter: function (event, player) { - return ( - (_status._aozhan && - !player.getStat("damage") && - player.isAlive()) || - event._lastDead != undefined - ); + return (_status._aozhan && !player.getStat("damage") && player.isAlive()) || event._lastDead != undefined; }, content: function () { "step 0"; @@ -760,19 +723,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.log(player, "本回合内未造成伤害,触发死战模式惩罚"); } if (trigger._lastDead == undefined) event.goto(2); - "step 1"; + ("step 1"); var type = get.rand(1, 8); event.type = type; trigger._lastDead.playerfocus(1200); - player.$fullscreenpop( - "乾坤八卦·" + - ["离", "坎", "乾", "震", "兑", "艮", "巽", "坤"][ - type - 1 - ], - get.groupnature(trigger._lastDead.group, "raw") - ); + player.$fullscreenpop("乾坤八卦·" + ["离", "坎", "乾", "震", "兑", "艮", "巽", "坤"][type - 1], get.groupnature(trigger._lastDead.group, "raw")); game.delay(1.5); - "step 2"; + ("step 2"); var type = event.type; switch (type) { case 1: { @@ -795,8 +752,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { case 4: { game.countPlayer(function (current) { var he = current.getCards("he"); - if (he.length) - current.discard(he.randomGet()).delay = false; + if (he.length) current.discard(he.randomGet()).delay = false; }); break; } @@ -810,10 +766,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var cards = []; game.countPlayer(function (current) { var card = get.cardPile(function (card) { - return ( - !cards.includes(card) && - get.type(card) == "equip" - ); + return !cards.includes(card) && get.type(card) == "equip"; }); if (card) { cards.push(card); @@ -841,21 +794,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { case 8: { trigger._lastDead.revive(null, false); trigger._lastDead.uninit(); - trigger._lastDead.init( - [ - "hhzz_shiona", - "hhzz_kanade", - "hhzz_takaramono1", - "hhzz_takaramono2", - ].randomGet() - ); - trigger._lastDead.skillH = - lib.character[trigger._lastDead.name][3].slice(0); + trigger._lastDead.init(["hhzz_shiona", "hhzz_kanade", "hhzz_takaramono1", "hhzz_takaramono2"].randomGet()); + trigger._lastDead.skillH = lib.character[trigger._lastDead.name][3].slice(0); trigger._lastDead.addSkill("hhzz_noCard"); break; } } - "step 3"; + ("step 3"); if (game.playerx().length <= 4 && !_status._aozhan) { game.countPlayer2(function (current) { delete current._toKill; @@ -864,10 +809,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ui.huanhuazhizhan.innerHTML = "死战模式"; _status._aozhan = true; game.playBackgroundMusic(); - trigger._lastDead.$fullscreenpop( - "死战模式", - get.groupnature(trigger._lastDead.group, "raw") || "fire" - ); + trigger._lastDead.$fullscreenpop("死战模式", get.groupnature(trigger._lastDead.group, "raw") || "fire"); } else game.randomMission(); }, }, @@ -941,8 +883,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { content: function () { var source = trigger.source; source.draw(); - if (source.skillH.length == 3) - source.removeSkillH(source.skillH.randomGet()); + if (source.skillH.length == 3) source.removeSkillH(source.skillH.randomGet()); var skills = lib.huanhuazhizhan.skills; skills.randomSort(); for (var i = 0; i < skills.length; i++) { @@ -964,8 +905,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { content: function () { var source = trigger.source; source.draw(3); - if (source.skillH.length == 3) - source.removeSkillH(source.skillH.randomGet()); + if (source.skillH.length == 3) source.removeSkillH(source.skillH.randomGet()); var skills = lib.huanhuazhizhan.skills; skills.randomSort(); for (var i = 0; i < skills.length; i++) { @@ -1009,20 +949,16 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { hhzz_jubao: "聚宝", hhzz_huilei_info: "锁定技,杀死你的角色弃置所有的牌。", hhzz_youlian_info: "锁定技,杀死你的角色弃置所有牌并随机失去一个技能。", - hhzz_zhencang_info: - "锁定技,杀死你的角色摸一张牌并随机获得一个技能(已满则先随机移除一个)。", - hhzz_huizhen_info: - "锁定技,杀死你的角色摸三张牌并随机获得一个技能(已满则先随机移除一个)。", - hhzz_jubao_info: - "锁定技,当你受到伤害的点数确定时,伤害来源随机获得你区域内的X张牌(X为伤害点数)。", + hhzz_zhencang_info: "锁定技,杀死你的角色摸一张牌并随机获得一个技能(已满则先随机移除一个)。", + hhzz_huizhen_info: "锁定技,杀死你的角色摸三张牌并随机获得一个技能(已满则先随机移除一个)。", + hhzz_jubao_info: "锁定技,当你受到伤害的点数确定时,伤害来源随机获得你区域内的X张牌(X为伤害点数)。", hhzz_shiona: "汐奈", hhzz_kanade: "立华奏", hhzz_takaramono1: "坚实宝箱", hhzz_takaramono2: "普通宝箱", hhzz_toulianghuanzhu: "偷梁换柱", hhzz_fudichouxin: "釜底抽薪", - hhzz_toulianghuanzhu_info: - "出牌阶段,对一名角色使用,随机更换其一个技能。可重铸。", + hhzz_toulianghuanzhu_info: "出牌阶段,对一名角色使用,随机更换其一个技能。可重铸。", hhzz_fudichouxin_info: "出牌阶段,对一名角色使用,随机弃置其一个技能。", nei: " ", nei2: " ", @@ -1135,23 +1071,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { player._toKill = list[0]; player._toSave = list[1]; } - ui.huanhuazhizhan.innerHTML = - "击杀" + - get.translation(game.me._toKill) + - ",保护" + - get.translation(game.me._toSave); + ui.huanhuazhizhan.innerHTML = "击杀" + get.translation(game.me._toKill) + ",保护" + get.translation(game.me._toSave); }, getSkillDialog: function (skills, prompt) { var dialog = ui.create.dialog("hidden", "forcebutton"); if (prompt) dialog.addText(prompt); for (var i = 0; i < skills.length; i++) { - dialog.add( - '" - ); + dialog.add('"); } dialog.addText("
    "); return dialog; @@ -1169,36 +1095,19 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { current._hSeat = i; current.identity = "nei"; current.setNickname(get.cnNumber(i, true) + "号位"); - for (var ii in lib.huanhuazhizhan.eltp) - current[ii] = lib.huanhuazhizhan.eltp[ii]; + for (var ii in lib.huanhuazhizhan.eltp) current[ii] = lib.huanhuazhizhan.eltp[ii]; current = current.next; i++; if (current == game.zhu) break; } ui.arena.classList.add("choose-character"); - game.me.chooseButton( - [ - "请选择角色形象", - [_status.characterlist.randomRemove(5), "character"], - ], - true - ).onfree = true; - "step 1"; + game.me.chooseButton(["请选择角色形象", [_status.characterlist.randomRemove(5), "character"]], true).onfree = true; + ("step 1"); game.me.init(result.links[0]); var list = ["xiandeng", "shulv", "xisheng"]; - game.me.chooseControl(list).dialog = game.getSkillDialog( - list, - "选择要获得的初始技能" - ); - "step 2"; - var list = [ - "_lingli", - "_lingli_round", - "_lingli_draw", - "_lingli_save", - "_hhzz_qiankunbagua", - "_lingli_damage", - ]; + game.me.chooseControl(list).dialog = game.getSkillDialog(list, "选择要获得的初始技能"); + ("step 2"); + var list = ["_lingli", "_lingli_round", "_lingli_draw", "_lingli_save", "_hhzz_qiankunbagua", "_lingli_damage"]; for (var i = 0; i < list.length; i++) { game.addGlobalSkill(list[i]); } @@ -1206,32 +1115,20 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.countPlayer(function (current) { if (!current.name) { current.init(_status.characterlist.randomRemove(1)[0]); - current.addSkillH( - ["xiandeng", "shulv", "xisheng"].randomGet() - ); + current.addSkillH(["xiandeng", "shulv", "xisheng"].randomGet()); } current.storage._lingli = 0; current.markSkill("_lingli"); }); game.showIdentity(true); - "step 3"; + ("step 3"); game.randomMission(); - var list = [ - game.createCard("hhzz_fudichouxin"), - game.createCard("hhzz_toulianghuanzhu"), - game.createCard("hhzz_toulianghuanzhu"), - game.createCard("hhzz_toulianghuanzhu"), - ]; + var list = [game.createCard("hhzz_fudichouxin"), game.createCard("hhzz_toulianghuanzhu"), game.createCard("hhzz_toulianghuanzhu"), game.createCard("hhzz_toulianghuanzhu")]; for (var i = 0; i < list.length; i++) { - ui.cardPile.insertBefore( - list[i], - ui.cardPile.childNodes[ - get.rand(ui.cardPile.childElementCount) - ] - ); + ui.cardPile.insertBefore(list[i], ui.cardPile.childNodes[get.rand(ui.cardPile.childElementCount)]); } game.updateRoundNumber(); - "step 4"; + ("step 4"); setTimeout(function () { ui.arena.classList.remove("choose-character"); }, 500); @@ -1273,18 +1170,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { character: { hhzz_shiona: ["female", "key", 1, ["hhzz_huilei"]], hhzz_kanade: ["female", "key", 2, ["hhzz_youlian"]], - hhzz_takaramono1: [ - "male", - "qun", - 5, - ["hhzz_jubao", "hhzz_huizhen"], - ], - hhzz_takaramono2: [ - "male", - "qun", - 3, - ["hhzz_jubao", "hhzz_zhencang"], - ], + hhzz_takaramono1: ["male", "qun", 5, ["hhzz_jubao", "hhzz_huizhen"]], + hhzz_takaramono2: ["male", "qun", 3, ["hhzz_jubao", "hhzz_zhencang"]], }, translate: { _lingli: "聚灵", @@ -1296,14 +1183,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { hhzz_huizhen: "汇珍", hhzz_jubao: "聚宝", hhzz_huilei_info: "锁定技,杀死你的角色弃置所有的牌。", - hhzz_youlian_info: - "锁定技,杀死你的角色弃置所有牌并随机失去一个技能。", - hhzz_zhencang_info: - "锁定技,杀死你的角色摸一张牌并随机获得一个技能(已满则先随机移除一个)。", - hhzz_huizhen_info: - "锁定技,杀死你的角色摸三张牌并随机获得一个技能(已满则先随机移除一个)。", - hhzz_jubao_info: - "锁定技,当你受到伤害的点数确定时,伤害来源随机获得你区域内的X张牌(X为伤害点数)。", + hhzz_youlian_info: "锁定技,杀死你的角色弃置所有牌并随机失去一个技能。", + hhzz_zhencang_info: "锁定技,杀死你的角色摸一张牌并随机获得一个技能(已满则先随机移除一个)。", + hhzz_huizhen_info: "锁定技,杀死你的角色摸三张牌并随机获得一个技能(已满则先随机移除一个)。", + hhzz_jubao_info: "锁定技,当你受到伤害的点数确定时,伤害来源随机获得你区域内的X张牌(X为伤害点数)。", nei: " ", nei2: " ", hhzz_shiona: "汐奈", @@ -1312,10 +1195,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { hhzz_takaramono2: "普通宝箱", hhzz_toulianghuanzhu: "偷梁换柱", hhzz_fudichouxin: "釜底抽薪", - hhzz_toulianghuanzhu_info: - "出牌阶段,对一名角色使用,随机更换其一个技能。可重铸。", - hhzz_fudichouxin_info: - "出牌阶段,对一名角色使用,随机弃置其一个技能。", + hhzz_toulianghuanzhu_info: "出牌阶段,对一名角色使用,随机更换其一个技能。可重铸。", + hhzz_fudichouxin_info: "出牌阶段,对一名角色使用,随机弃置其一个技能。", }, }); }); @@ -1380,11 +1261,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (game.bannedcards) game.bannedcards.remove("du"); var num = Math.ceil(list.length / 10); while (num--) { - list.push([ - ["heart", "diamond", "club", "spade"].randomGet(), - Math.ceil(Math.random() * 13), - "du", - ]); + list.push([["heart", "diamond", "club", "spade"].randomGet(), Math.ceil(Math.random() * 13), "du"]); } return list; }, @@ -1426,7 +1303,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { player1 = this.player1; player2 = this.player2; } - + var createCard = function (wuxie) { var card; if (wuxie) { @@ -1441,17 +1318,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { card.style.margin = 0; return card; }; - + var func = function () { - game.linexy( - [ - player1.getLeft() + player1.offsetWidth / 2, - player1.getTop() + player1.offsetHeight / 2, - player2.getLeft() + player2.offsetWidth / 2, - player2.getTop() + player2.offsetHeight / 2, - ], - node - ); + game.linexy([player1.getLeft() + player1.offsetWidth / 2, player1.getTop() + player1.offsetHeight / 2, player2.getLeft() + player2.offsetWidth / 2, player2.getTop() + player2.offsetHeight / 2], node); var card = createCard(true); card.style.left = "43px"; card.style.top = "58px"; @@ -1463,7 +1332,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { card.delete(); }, 1000); player1.node.count.innerHTML = "1"; - + setTimeout(function () { if (!node.showcaseinterval) return; player1.node.count.innerHTML = "2"; @@ -1479,19 +1348,11 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { card.delete(); }, 1000); }, 300); - + setTimeout(function () { if (!node.showcaseinterval) return; player2.node.count.innerHTML = "1"; - game.linexy( - [ - player2.getLeft() + player2.offsetWidth / 2, - player2.getTop() + player2.offsetHeight / 2, - player1.getLeft() + player1.offsetWidth / 2, - player1.getTop() + player1.offsetHeight / 2, - ], - node - ); + game.linexy([player2.getLeft() + player2.offsetWidth / 2, player2.getTop() + player2.offsetHeight / 2, player1.getLeft() + player1.offsetWidth / 2, player1.getTop() + player1.offsetHeight / 2], node); var card = createCard(true); card.style.left = "auto"; card.style.right = "43px"; @@ -1503,7 +1364,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { setTimeout(function () { card.delete(); }, 700); - + setTimeout(function () { if (!node.showcaseinterval) return; player2.node.count.innerHTML = "2"; @@ -1528,12 +1389,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { init: function () { for (var i in lib.character) { var skills = lib.character[i][3]; - if ( - skills.includes("jizhi") || - skills.includes("rejizhi") || - skills.includes("lingzhou") || - skills.includes("sbaiyin") - ) { + if (skills.includes("jizhi") || skills.includes("rejizhi") || skills.includes("lingzhou") || skills.includes("sbaiyin")) { delete lib.character[i]; } } @@ -1555,12 +1411,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { weiwoduzun: { name: "唯我独尊", mode: "identity", - intro: [ - "牌堆中杀的数量增加30%", - "游戏开始时,主公获得一枚战神标记", - "拥有战神标记的角色杀造成的伤害+1", - "受到杀造成的伤害后战神印记将移到伤害来源的武将牌上", - ], + intro: ["牌堆中杀的数量增加30%", "游戏开始时,主公获得一枚战神标记", "拥有战神标记的角色杀造成的伤害+1", "受到杀造成的伤害后战神印记将移到伤害来源的武将牌上"], showcase: function (init) { var node = this; var player; @@ -1793,7 +1644,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var list = get.characterSurname(i); for (var j of list) { var surname = j[0]; - if(!surname){ + if (!surname) { continue; } if (!map[surname]) { @@ -1841,26 +1692,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { tongqueduopao: { name: "铜雀夺袍", mode: "identity", - intro: [ - "主公必选曹操", - "其余玩家从曹休、文聘、曹洪、张郃、夏侯渊、徐晃、许褚这些武将中随机选中一个", - "游戏开始时将麒麟弓和爪黄飞电各置于每名角色的装备区内,大宛马洗入牌堆,移除其他的武器牌和坐骑牌", - ], + intro: ["主公必选曹操", "其余玩家从曹休、文聘、曹洪、张郃、夏侯渊、徐晃、许褚这些武将中随机选中一个", "游戏开始时将麒麟弓和爪黄飞电各置于每名角色的装备区内,大宛马洗入牌堆,移除其他的武器牌和坐骑牌"], init: function () { game.saveConfig("player_number", "8", "identity"); game.saveConfig("double_character", false, "identity"); }, showcase: function (init) { var node = this; - var list = [ - "re_caoxiu", - "re_wenpin", - "tw_re_caohong", - "re_zhanghe", - "ol_xiahouyuan", - "ol_xuhuang", - "re_xuzhu", - ]; + var list = ["re_caoxiu", "re_wenpin", "tw_re_caohong", "re_zhanghe", "ol_xiahouyuan", "ol_xuhuang", "re_xuzhu"]; list.randomSort(); list.push("re_caocao"); var func = function () { @@ -1882,7 +1721,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { node.appendChild(card); ui.refresh(card); }; - + var list2 = ["qilin", "dawan", "zhuahuang"]; var func2 = function () { var card = game.createCard(list2.shift(), "noclick"); @@ -1899,7 +1738,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { node.appendChild(card); ui.refresh(card); }; - + if (init) { node.nodes = []; } else { @@ -1946,11 +1785,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } } for (var i = 0; i < 8; i++) { - list.push([ - ["heart", "diamond", "club", "spade"].randomGet(), - Math.ceil(Math.random() * 13), - "dawan", - ]); + list.push([["heart", "diamond", "club", "spade"].randomGet(), Math.ceil(Math.random() * 13), "dawan"]); } return list; }, @@ -1962,15 +1797,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } }, submode: "normal", - list: [ - "re_caoxiu", - "re_wenpin", - "tw_re_caohong", - "re_zhanghe", - "ol_xiahouyuan", - "ol_xuhuang", - "re_xuzhu", - ], + list: ["re_caoxiu", "re_wenpin", "tw_re_caohong", "re_zhanghe", "ol_xiahouyuan", "ol_xuhuang", "re_xuzhu"], chooseCharacterFixed: true, chooseCharacterAi: function (player) { if (player == game.zhu) { @@ -2062,7 +1889,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (get.config("choose_group")) { var list = lib.group.slice(0); list.remove("shen"); - game.players.forEach((i) => { + game.players.forEach(i => { if (i.group == "shen" && i != game.me) { var group = list.randomGet(); i.group = group; @@ -2180,12 +2007,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var map3 = []; var banned = ["zuoci", "re_zuoci", "tw_xiahouba"]; for (var i in lib.character) { - if ( - lib.filter.characterDisabled2(i) || - lib.filter.characterDisabled(i) || - banned.includes(i) - ) - continue; + if (lib.filter.characterDisabled2(i) || lib.filter.characterDisabled(i) || banned.includes(i)) continue; var group = lib.character[i][1]; if (group && map[group]) map[group].push(i); } @@ -2203,8 +2025,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { trigger: { player: "phaseBegin" }, direct: true, popup: "魏业", - prompt2: - "回合开始时,你可以弃置一张牌并指定一名敌方角色,该角色须弃置一张牌,否则你摸一张牌。", + prompt2: "回合开始时,你可以弃置一张牌并指定一名敌方角色,该角色须弃置一张牌,否则你摸一张牌。", filter: function (event, player) { return player.group == "wei" && player.countCards("he") > 0; }, @@ -2224,23 +2045,19 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { return 1 / (1 + target.countCards("he")); }, }); - "step 1"; + ("step 1"); if (result.bool) { player.logSkill(event.name, result.targets); player.discard(result.cards); - result.targets[0].chooseToDiscard( - "弃置一张牌,或令" + get.translation(player) + "摸一张牌", - "he" - ).ai = lib.skill.zhiheng.check; + result.targets[0].chooseToDiscard("弃置一张牌,或令" + get.translation(player) + "摸一张牌", "he").ai = lib.skill.zhiheng.check; } else event.finish(); - "step 2"; + ("step 2"); if (!result.bool) player.draw(); }, }, _jiazu_shu: { popup: "蜀义", - prompt2: - "你使用【杀】上限+1;出牌阶段结束时,若你于此阶段使用【杀】次数不少于2,摸一张牌。", + prompt2: "你使用【杀】上限+1;出牌阶段结束时,若你于此阶段使用【杀】次数不少于2,摸一张牌。", mod: { cardUsable: function (card, player, num) { if (card.name == "sha" && player.group == "shu") return num + 1; @@ -2252,11 +2069,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { return ( player.group == "shu" && player.getHistory("useCard", function (evt) { - return ( - evt.card && - evt.card.name == "sha" && - evt.getParent("phaseUse") == event - ); + return evt.card && evt.card.name == "sha" && evt.getParent("phaseUse") == event; }).length > 1 ); }, @@ -2278,15 +2091,11 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, _jiazu_qun: { popup: "群心", - prompt2: - "锁定技,弃牌阶段开始时,若你的手牌数比体力值多2或更多,你本回合手牌上限+1;若你已损失体力值大于1,你手牌上限+1", + prompt2: "锁定技,弃牌阶段开始时,若你的手牌数比体力值多2或更多,你本回合手牌上限+1;若你已损失体力值大于1,你手牌上限+1", trigger: { player: "phaseDiscardBegin" }, forced: true, filter: function (event, player) { - return ( - player.group == "qun" && - (player.isDamaged() || player.countCards("h") - player.hp > 1) - ); + return player.group == "qun" && (player.isDamaged() || player.countCards("h") - player.hp > 1); }, content: function () { var num = 0; @@ -2299,19 +2108,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _jiazu_jin: { trigger: { player: "phaseDrawEnd" }, popup: "晋势", - prompt2: - "摸牌阶段结束时,你可以展示你于此阶段内因摸牌而得到的牌。若这些牌的花色均不同,则你摸一张牌。", + prompt2: "摸牌阶段结束时,你可以展示你于此阶段内因摸牌而得到的牌。若这些牌的花色均不同,则你摸一张牌。", filter: function (event, player) { var hs = player.getCards("h"); return ( player.group == "jin" && hs.length > 0 && player.getHistory("gain", function (evt) { - if ( - evt.getParent().name != "draw" || - evt.getParent("phaseDraw") != event - ) - return false; + if (evt.getParent().name != "draw" || evt.getParent("phaseDraw") != event) return false; for (var i of evt.cards) { if (hs.includes(i)) return true; } @@ -2324,11 +2128,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { cards = [], suits = []; player.getHistory("gain", function (evt) { - if ( - evt.getParent().name != "draw" || - evt.getParent("phaseDraw") != event - ) - return false; + if (evt.getParent().name != "draw" || evt.getParent("phaseDraw") != event) return false; for (var i of evt.cards) { if (hs.includes(i)) { cards.add(i); @@ -2343,11 +2143,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { cards = [], suits = []; player.getHistory("gain", function (evt) { - if ( - evt.getParent().name != "draw" || - evt.getParent("phaseDraw") != trigger - ) - return false; + if (evt.getParent().name != "draw" || evt.getParent("phaseDraw") != trigger) return false; for (var i of evt.cards) { if (hs.includes(i)) { cards.add(i); @@ -2366,14 +2162,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { filter: function (event, player) { return player.group == "key"; }, - prompt2: - "出牌阶段限一次,你可以摸一张牌并获得1点护甲。若如此做,你于当前回合结束时失去1点体力。", + prompt2: "出牌阶段限一次,你可以摸一张牌并获得1点护甲。若如此做,你于当前回合结束时失去1点体力。", content: function () { "step 0"; player.draw(); - "step 1"; + ("step 1"); player.changeHujia(1); - "step 2"; + ("step 2"); var evt = event.getParent("phase"); if (evt && evt.after) { var next = player.loseHp(); @@ -2421,12 +2216,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { trigger: { source: "damageEnd" }, forced: true, filter: function (event, player) { - return ( - player._jiazuAwaken && - player.group == "shu" && - event.card && - event.card.name == "sha" - ); + return player._jiazuAwaken && player.group == "shu" && event.card && event.card.name == "sha"; }, content: function () { player.draw(); @@ -2440,11 +2230,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { trigger: { player: "useCard" }, forced: true, filter: function (event, player) { - return ( - player._jiazuAwaken && - player.group == "wu" && - get.type(event.card) == "equip" - ); + return player._jiazuAwaken && player.group == "wu" && get.type(event.card) == "equip"; }, content: function () { player.draw(); @@ -2458,13 +2244,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { trigger: { player: "useCardToPlayered" }, forced: true, filter: function (event, player) { - if ( - !player._jiazuAwaken || - player.group != "qun" || - !event.isFirstTarget || - get.type(event.card, "trick") != "trick" - ) - return false; + if (!player._jiazuAwaken || player.group != "qun" || !event.isFirstTarget || get.type(event.card, "trick") != "trick") return false; for (var i = 0; i < event.targets.length; i++) { if (event.targets[i] != player) return true; } @@ -2540,13 +2320,11 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { skill: { _jiazu_wei: { popup: "魏业", - prompt2: - "回合开始时,你可以弃置一张牌并指定一名敌方角色,该角色须弃置一张牌,否则你摸一张牌。", + prompt2: "回合开始时,你可以弃置一张牌并指定一名敌方角色,该角色须弃置一张牌,否则你摸一张牌。", }, _jiazu_shu: { popup: "蜀义", - prompt2: - "你使用【杀】上限+1;出牌阶段结束时,若你于此阶段使用【杀】次数不少于2,摸一张牌。", + prompt2: "你使用【杀】上限+1;出牌阶段结束时,若你于此阶段使用【杀】次数不少于2,摸一张牌。", }, _jiazu_wu: { popup: "吴耀", @@ -2554,18 +2332,15 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, _jiazu_qun: { popup: "群心", - prompt2: - "锁定技,弃牌阶段开始时,若你的手牌数比体力值多2或更多,你本回合手牌上限+1;若你已损失体力值大于1,你手牌上限+1", + prompt2: "锁定技,弃牌阶段开始时,若你的手牌数比体力值多2或更多,你本回合手牌上限+1;若你已损失体力值大于1,你手牌上限+1", }, _jiazu_jin: { popup: "晋势", - prompt2: - "摸牌阶段结束时,你可以展示你于此阶段内因摸牌而得到的牌。若这些牌的花色均不同,则你摸一张牌。", + prompt2: "摸牌阶段结束时,你可以展示你于此阶段内因摸牌而得到的牌。若这些牌的花色均不同,则你摸一张牌。", }, _jiazu_key: { popup: "键魂", - prompt2: - "出牌阶段限一次,你可以摸一张牌并获得1点护甲。若如此做,你于当前回合结束时失去1点体力。", + prompt2: "出牌阶段限一次,你可以摸一张牌并获得1点护甲。若如此做,你于当前回合结束时失去1点体力。", }, _jiazu_awaken_wei: { popup: "许昌", @@ -2695,11 +2470,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { node.showcaseinterval = setInterval(func, 6000); func(); }, - intro: [ - "玩家在选将时可从8张武将牌里选择两张武将牌,一张面向大家可见(加入游戏),另一张是隐藏面孔(暗置)", - "选择的两张武将牌需满足以下至少两个条件:1.性别相同;2.体力上限相同;3.技能数量相同", - "每名玩家在其回合开始或回合结束时,可以选择将自己的武将牌弃置,然后使用暗置的武将牌进行剩余的游戏", - ], + intro: ["玩家在选将时可从8张武将牌里选择两张武将牌,一张面向大家可见(加入游戏),另一张是隐藏面孔(暗置)", "选择的两张武将牌需满足以下至少两个条件:1.性别相同;2.体力上限相同;3.技能数量相同", "每名玩家在其回合开始或回合结束时,可以选择将自己的武将牌弃置,然后使用暗置的武将牌进行剩余的游戏"], content: { submode: "two", chooseCharacterBefore: function () { @@ -2716,14 +2487,11 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "step 0"; player .chooseControl("确定", "取消") - .set("dialog", [ - "是否替换自己的武将牌?", - [[player._backupCharacter], "character"], - ]) + .set("dialog", ["是否替换自己的武将牌?", [[player._backupCharacter], "character"]]) .set("ai", function () { return Math.random() < 0.15 ? "确定" : "取消"; }); - "step 1"; + ("step 1"); if (result.control == "确定") { game.log(player, "将", player.name, "替换为了", player._backupCharacter); player.reinit(player.name, player._backupCharacter); @@ -2749,32 +2517,29 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var bool = Math.random() < 0.5; var bool2 = Math.random() < 0.5; var ref = game.players[0]; - + ref.side = bool; ref.next.side = bool2; ref.next.next.side = !bool; ref.previous.side = !bool2; - + var firstChoose = game.players.randomGet(); if (firstChoose.next.side == firstChoose.side) { firstChoose = firstChoose.next; } _status.firstAct = firstChoose; for (var i = 0; i < 4; i++) { - firstChoose.node.name.innerHTML = get.verticalStr( - get.cnNumber(i + 1, true) + "号位" - ); + firstChoose.node.name.innerHTML = get.verticalStr(get.cnNumber(i + 1, true) + "号位"); firstChoose = firstChoose.next; } - + for (var i = 0; i < game.players.length; i++) { if (game.players[i].side == game.me.side) { game.players[i].node.identity.firstChild.innerHTML = "友"; } else { game.players[i].node.identity.firstChild.innerHTML = "敌"; } - game.players[i].node.identity.dataset.color = - game.players[i].side + "zhu"; + game.players[i].node.identity.dataset.color = game.players[i].side + "zhu"; } var list = []; for (i in lib.character) { @@ -2795,25 +2560,18 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { return num > 1; }; var list2 = list.randomGets(8); - var next = game.me.chooseButton(2, true, [ - "请选择您的武将牌", - [list2, "character"], - ]); + var next = game.me.chooseButton(2, true, ["请选择您的武将牌", [list2, "character"]]); next.set("onfree", true); next.set("filterButton", function (button) { if (!ui.selected.buttons.length) { for (var i = 0; i < list2.length; i++) { - if ( - list2[i] != button.link && - event.filterChoice(button.link, list2[i]) - ) - return true; + if (list2[i] != button.link && event.filterChoice(button.link, list2[i])) return true; } return false; } return event.filterChoice(button.link, ui.selected.buttons[0].link); }); - "step 1"; + ("step 1"); game.me.init(result.links[0]); game.me._backupCharacter = result.links[1]; _status.characterlist.removeArray(result.links); @@ -2885,15 +2643,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { player2.style.transform = "scale(0.9)"; setTimeout(function () { if (!player2) return; - game.linexy( - [ - player1.getLeft() + player1.offsetWidth / 2, - player1.getTop() + player1.offsetHeight / 2, - player2.getLeft() + player2.offsetWidth / 2, - player2.getTop() + player2.offsetHeight / 2, - ], - node - ); + game.linexy([player1.getLeft() + player1.offsetWidth / 2, player1.getTop() + player1.offsetHeight / 2, player2.getLeft() + player2.offsetWidth / 2, player2.getTop() + player2.offsetHeight / 2], node); setTimeout(function () { var popup = ui.create.div(".damage"); popup.innerHTML = "-1"; @@ -2918,14 +2668,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { node.showcaseinterval = setInterval(func, 2600); func(); }, - intro: [ - "无尽而漫长的单挑试炼", - lib.config.qianlidanji_level - ? "你的最高纪录是连续通过" + - lib.config.qianlidanji_level + - "关,是否能够突破这一记录呢?" - : "你能否过五关斩六将,击败古城战神蔡阳呢?", - ], + intro: ["无尽而漫长的单挑试炼", lib.config.qianlidanji_level ? "你的最高纪录是连续通过" + lib.config.qianlidanji_level + "关,是否能够突破这一记录呢?" : "你能否过五关斩六将,击败古城战神蔡阳呢?"], init: function () { if (!_status.qianlidanji) _status.qianlidanji = { @@ -2960,9 +2703,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "将一张防具牌置入装备区并摸一张牌", function () { var card = get.cardPile(function (card) { - return ( - get.subtype(card) == "equip2" && !get.cardtag(card, "gifts") - ); + return get.subtype(card) == "equip2" && !get.cardtag(card, "gifts"); }); if (card) game.zhu.equip(card); game.zhu.draw(); @@ -2972,9 +2713,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "将一张武器牌置入装备区并摸一张牌", function () { var card = get.cardPile(function (card) { - return ( - get.subtype(card) == "equip1" && !get.cardtag(card, "gifts") - ); + return get.subtype(card) == "equip1" && !get.cardtag(card, "gifts"); }); if (card) game.zhu.equip(card); game.zhu.draw(); @@ -3005,15 +2744,11 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "将一张武器牌和一张防具牌置入装备区", function () { var card = get.cardPile(function (card) { - return ( - get.subtype(card) == "equip1" && !get.cardtag(card, "gifts") - ); + return get.subtype(card) == "equip1" && !get.cardtag(card, "gifts"); }); if (card) game.zhu.equip(card); var card2 = get.cardPile(function (card) { - return ( - get.subtype(card) == "equip2" && !get.cardtag(card, "gifts") - ); + return get.subtype(card) == "equip2" && !get.cardtag(card, "gifts"); }); if (card2) game.zhu.equip(card2); }, @@ -3022,15 +2757,11 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "将一张武器牌和一张防御坐骑牌置入装备区", function () { var card = get.cardPile(function (card) { - return ( - get.subtype(card) == "equip1" && !get.cardtag(card, "gifts") - ); + return get.subtype(card) == "equip1" && !get.cardtag(card, "gifts"); }); if (card) game.zhu.equip(card); var card2 = get.cardPile(function (card) { - return ( - get.subtype(card) == "equip3" && !get.cardtag(card, "gifts") - ); + return get.subtype(card) == "equip3" && !get.cardtag(card, "gifts"); }); if (card2) game.zhu.equip(card2); }, @@ -3051,9 +2782,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var list = []; while (list.length < 2) { var card = get.cardPile(function (card) { - return ( - !list.includes(card) && get.type(card, "trick") == "trick" - ); + return !list.includes(card) && get.type(card, "trick") == "trick"; }); if (!card) break; list.push(card); @@ -3142,9 +2871,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "将一张宝物牌置入装备区并摸一张牌", function () { var card = get.cardPile(function (card) { - return ( - get.subtype(card) == "equip5" && !get.cardtag(card, "gifts") - ); + return get.subtype(card) == "equip5" && !get.cardtag(card, "gifts"); }); if (card) game.zhu.equip(card); game.zhu.draw(); @@ -3180,10 +2907,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { delete game.zhu._oldniepan; } _status.qianlidanji.completeNumber++; - if ( - !lib.config.qianlidanji_level || - lib.config.qianlidanji_level < _status.qianlidanji.completeNumber - ) { + if (!lib.config.qianlidanji_level || lib.config.qianlidanji_level < _status.qianlidanji.completeNumber) { lib.config.qianlidanji_level = _status.qianlidanji.completeNumber; game.saveConfig("qianlidanji_level", lib.config.qianlidanji_level); } @@ -3219,7 +2943,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ui.discardPile.appendChild(cards.shift()); } } - "step 1"; + ("step 1"); if (game.fellow) { game.dead.remove(game.fellow); game.fellow.remove(); @@ -3247,14 +2971,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.zhu .chooseControl() .set("choiceList", list) - .set( - "prompt", - "请选择一项奖励(当前已通过" + - _status.qianlidanji.completeNumber + - "关)" - ); + .set("prompt", "请选择一项奖励(当前已通过" + _status.qianlidanji.completeNumber + "关)"); } - "step 2"; + ("step 2"); if (_status.qianlidanji.completeNumber != 5) { if (result.index == 3) { game.over(true); @@ -3263,17 +2982,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { event.reward = event.list[result.index]; } _status.characterlist.removeArray(_status.qianlidanji.used); - if (_status.qianlidanji.completeNumber == 5) - event._result = { links: ["caiyang"] }; - else - game.zhu.chooseButton( - [ - "选择下一关出战的对手", - [_status.characterlist.randomGets(3), "character"], - ], - true - ); - "step 3"; + if (_status.qianlidanji.completeNumber == 5) event._result = { links: ["caiyang"] }; + else game.zhu.chooseButton(["选择下一关出战的对手", [_status.characterlist.randomGets(3), "character"]], true); + ("step 3"); _status.event.getParent("phaseLoop").player = game.zhu; var source = game.fan; var name = result.links[0]; @@ -3311,7 +3022,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { source.gain(get.cards(gain))._triggered = null; game.triggerEnter(source); if (event.reward) event.reward(); - "step 4"; + ("step 4"); var cards = Array.from(ui.ordering.childNodes); while (cards.length) { cards.shift().discard(); @@ -3319,9 +3030,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var evt = _status.event.getParent("phase"); if (evt) { game.resetSkills(); - _status.event = evt; - _status.event.finish(); - _status.event.untrigger(true); + let evtx=_status.event; + while(evtx!=evt){ + evtx.finish(); + evtx.untrigger(true); + evtx = evtx.getParent(); + } + evtx.finish(); + evtx.untrigger(true); } }, }; @@ -3349,7 +3065,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.fan.setIdentity(); game.fan.identityShown = true; game.fan.node.identity.classList.remove("guessing"); - + event.list = []; for (var i in lib.character) { if (lib.filter.characterDisabled(i)) continue; @@ -3370,7 +3086,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } dialog.setCaption("选择角色"); game.me.chooseButton(dialog, true).set("onfree", true); - + ui.create.cheat = function () { _status.createControl = ui.cheat2; ui.cheat = ui.create.control("更换", function () { @@ -3380,17 +3096,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (game.changeCoin) { game.changeCoin(-3); } - + event.list.randomSort(); list = event.list.slice(0, 5); - + var buttons = ui.create.div(".buttons"); var node = _status.event.dialog.buttons[0].parentNode; - _status.event.dialog.buttons = ui.create.buttons( - list, - "character", - buttons - ); + _status.event.dialog.buttons = ui.create.buttons(list, "character", buttons); _status.event.dialog.content.insertBefore(buttons, node); buttons.addTempClass("start"); node.remove(); @@ -3410,7 +3122,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } else { event.dialogxx = ui.create.characterDialog("heightset"); } - + ui.create.cheat2 = function () { ui.cheat2 = ui.create.control("自由选将", function () { if (this.dialog == _status.event.dialog) { @@ -3451,7 +3163,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (!ui.cheat && get.config("change_choice")) ui.create.cheat(); if (!ui.cheat2 && get.config("free_choose")) ui.create.cheat2(); } - "step 1"; + ("step 1"); if (ui.cheat) { ui.cheat.close(); delete ui.cheat; @@ -3464,10 +3176,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.zhu.init(result.buttons[0].link); _status.characterlist.remove(result.buttons[0].link); _status.qianlidanji.used.add(result.buttons[0].link); - game.zhu - .chooseControl("地狱", "困难", "普通", "简单", "无双") - .set("prompt", "请选择游戏难度"); - "step 2"; + game.zhu.chooseControl("地狱", "困难", "普通", "简单", "无双").set("prompt", "请选择游戏难度"); + ("step 2"); var hp = Math.floor(result.index / 2); event.draw = Math.floor((result.index + 1) / 2); if (hp) { @@ -3475,14 +3185,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.zhu.maxHp += hp; game.zhu.update(); } - game.zhu.chooseButton( - [ - "请选择对手的登场武将", - [_status.characterlist.randomGets(3), "character"], - ], - true - ); - "step 3"; + game.zhu.chooseButton(["请选择对手的登场武将", [_status.characterlist.randomGets(3), "character"]], true); + ("step 3"); game.fan.init(result.links[0]); _status.characterlist.remove(result.links[0]); _status.qianlidanji.used.add(result.links[0]); @@ -3492,7 +3196,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { setTimeout(function () { ui.arena.classList.remove("choose-character"); }, 500); - + var pack = { character: { pujing: ["male", "qun", 1, [], []], @@ -3526,7 +3230,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.addOverDialog = function (dialog) { dialog.addText("共计通过" + _status.qianlidanji.completeNumber + "关"); }; - lib.element.player.dieAfter = function () { + lib.element.player.dieAfter2 = function () { if (this == game.fellow) return; _status.characterlist.removeArray(_status.qianlidanji.used); if (game.zhu == this || !_status.characterlist.length) { @@ -3538,8 +3242,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { next.setContent(_status.qianlidanji.replace_character); } }; - lib.element.player.dieAfter2 = function () { + lib.element.player.dieAfter = function (source) { _status.characterlist.removeArray(_status.qianlidanji.used); + let next = game.createEvent("dieAfter", false); + next.player = this; + next.forceDie = true; + next.source = source; + next.setContent("emptyEvent"); }; game.zhu.dieAfter = lib.element.player.dieAfter; game.fan.dieAfter = lib.element.player.dieAfter; @@ -3635,13 +3344,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { character: ["re_sp_zhugeliang", "yujin_yujin", "re_zhangliao", "re_lusu"], lib: { character: { - re_sp_zhugeliang: [ - "male", - "shu", - 3, - ["tiaoxin", "bazhen", "feiying"], - [], - ], + re_sp_zhugeliang: ["male", "shu", 3, ["tiaoxin", "bazhen", "feiying"], []], yujin_yujin: ["male", "wei", 4, ["jiangchi", "danshou"], []], re_zhangliao: ["male", "wei", 4, ["benxi", "tuifeng", "qingxi"], []], re_lusu: ["male", "wu", 3, ["kaikang", "shenxian"], []], @@ -3660,28 +3363,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { character: ["re_huangzhong", "re_xiahouyuan", "zhanghe", "xin_fazheng"], lib: { character: { - re_huangzhong: [ - "male", - "shu", - 4, - ["yingjian", "weikui", "gzyinghun"], - [], - ], - re_xiahouyuan: [ - "male", - "wei", - 4, - ["benxi", "yaowu", "dujin", "juesi"], - [], - ], + re_huangzhong: ["male", "shu", 4, ["yingjian", "weikui", "gzyinghun"], []], + re_xiahouyuan: ["male", "wei", 4, ["benxi", "yaowu", "dujin", "juesi"], []], zhanghe: ["male", "wei", 4, ["kaikang", "xingshang", "zhiheng"], []], - xin_fazheng: [ - "male", - "shu", - 4, - ["xinfu_zhanji", "nzry_chenglve", "yiji"], - [], - ], + xin_fazheng: ["male", "shu", 4, ["xinfu_zhanji", "nzry_chenglve", "yiji"], []], }, translate: { re_huangzhong: "定军黄忠", @@ -3698,20 +3383,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { lib: { character: { re_caocao: ["male", "wei", 4, ["fankui", "zhuiji", "duanbing"], []], - xin_yuanshao: [ - "male", - "qun", - "3/6", - ["reluanji", "kuanggu", "benghuai", "weizhong"], - [], - ], - guotufengji: [ - "male", - "qun", - 2, - ["sijian", "jigong", "shifei", "jianying"], - [], - ], + xin_yuanshao: ["male", "qun", "3/6", ["reluanji", "kuanggu", "benghuai", "weizhong"], []], + guotufengji: ["male", "qun", 2, ["sijian", "jigong", "shifei", "jianying"], []], re_guojia: ["male", "wei", 3, ["yiji", "sanyao", "gongxin"], []], }, translate: { @@ -3728,34 +3401,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { character: ["chunyuqiong", "sp_xuyou", "re_xuhuang", "gaolan"], lib: { character: { - chunyuqiong: [ - "male", - "qun", - 8, - ["ranshang", "duliang", "jiuchi"], - [], - ], - sp_xuyou: [ - "male", - "qun", - 3, - ["qice", "lianying", "nzry_jianxiang"], - [], - ], - re_xuhuang: [ - "male", - "wei", - 4, - ["shenduan", "xiaoguo", "nzry_juzhan"], - [], - ], - gaolan: [ - "male", - "qun", - 4, - ["yuanhu", "shensu", "benyu", "suishi"], - [], - ], + chunyuqiong: ["male", "qun", 8, ["ranshang", "duliang", "jiuchi"], []], + sp_xuyou: ["male", "qun", 3, ["qice", "lianying", "nzry_jianxiang"], []], + re_xuhuang: ["male", "wei", 4, ["shenduan", "xiaoguo", "nzry_juzhan"], []], + gaolan: ["male", "qun", 4, ["yuanhu", "shensu", "benyu", "suishi"], []], }, translate: { chunyuqiong: "乌巢淳于琼", @@ -3771,20 +3420,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { character: ["re_zhangzhang", "re_sp_zhugeliang", "guyong", "re_lusu"], lib: { character: { - re_sp_zhugeliang: [ - "male", - "shu", - 3, - ["tianbian", "jyzongshi", "xinfu_guolun"], - [], - ], - re_zhangzhang: [ - "male", - "wu", - 3, - ["zhuandui", "tiaoxin", "guzheng"], - [], - ], + re_sp_zhugeliang: ["male", "shu", 3, ["tianbian", "jyzongshi", "xinfu_guolun"], []], + re_zhangzhang: ["male", "wu", 3, ["zhuandui", "tiaoxin", "guzheng"], []], guyong: ["male", "wu", 3, ["qiaoshui", "qicai", "bingyi"], []], re_lusu: ["male", "wu", 3, ["qingzhongx", "shuimeng"], []], }, @@ -3804,20 +3441,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { character: { yj_jushou: ["male", "qun", 3, ["mingce", "jianyan", "shibei"], []], re_caocao: ["male", "wei", 4, ["miji", "beige", "feiying"], []], - jsp_guanyu: [ - "male", - "wei", - 4, - ["nuzhan", "jianchu", "new_rewusheng"], - [], - ], - re_yanwen: [ - "male", - "qun", - 4, - ["shuangxiong", "zhanyi", "zhichi"], - [], - ], + jsp_guanyu: ["male", "wei", 4, ["nuzhan", "jianchu", "new_rewusheng"], []], + re_yanwen: ["male", "qun", 4, ["shuangxiong", "zhanyi", "zhichi"], []], }, translate: { yj_jushou: "白马沮授", @@ -3835,13 +3460,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { character: { re_lingtong: ["male", "wu", 4, ["xuanfeng", "zishou", "tiaoxin"], []], re_lidian: ["male", "wei", 3, ["weijing", "wangxi", "zhuandui"], []], - re_zhangliao: [ - "male", - "wei", - 3, - ["retuxi", "mashu", "reyingzi", "xinpojun"], - [], - ], + re_zhangliao: ["male", "wei", 3, ["retuxi", "mashu", "reyingzi", "xinpojun"], []], re_ganning: ["male", "wu", 5, ["lizhan", "jiang", "zhenwei"], []], }, translate: { @@ -3859,20 +3478,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { lib: { character: { re_guanyu: ["male", "shu", 5, ["wusheng", "zishou", "zhongyong"], []], - caoren: [ - "male", - "wei", - 1, - ["xinjiewei", "qiuyuan", "gzbuqu", "xinjushou"], - [], - ], - re_lvmeng: [ - "male", - "wu", - 4, - ["gongxin", "duodao", "dujin", "huituo"], - [], - ], + caoren: ["male", "wei", 1, ["xinjiewei", "qiuyuan", "gzbuqu", "xinjushou"], []], + re_lvmeng: ["male", "wu", 4, ["gongxin", "duodao", "dujin", "huituo"], []], guanping: ["male", "shu", 5, ["longyin", "suishi"], []], }, translate: { @@ -3917,24 +3524,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { lib: { character: { caozhen: ["male", "wei", 4, ["xinsidi", "tuxi"]], - key_hisako: [ - "female", - "key", - "2/3", - [ - "hisako_yinbao", - "shenzhi", - "shiorimiyuki_banyin", - "hisako_zhuanyun", - ], - [], - ], - key_iwasawa: [ - "female", - "key", - "-999/3", - ["iwasawa_yinhang", "iwasawa_mysong", "hisako_zhuanyun"], - ], + key_hisako: ["female", "key", "2/3", ["hisako_yinbao", "shenzhi", "shiorimiyuki_banyin", "hisako_zhuanyun"], []], + key_iwasawa: ["female", "key", "-999/3", ["iwasawa_yinhang", "iwasawa_mysong", "hisako_zhuanyun"]], sp_key_kanade: ["female", "key", 3, ["xinwuyan", "xinbenxi"]], }, translate: { @@ -3952,20 +3543,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { lib: { character: { key_yuzuru: ["male", "key", 4, ["hinata_qiulve", "kurou"]], - sp_key_kanade: [ - "female", - "key", - 3, - ["hinata_qiulve", "benxi"], - [], - ], + sp_key_kanade: ["female", "key", 3, ["hinata_qiulve", "benxi"], []], key_ayato: ["male", "key", 3, ["hinata_qiulve", "retieji"]], - key_hinata: [ - "female", - "key", - 4, - ["hinata_qiulve", "hinata_ehou"], - ], + key_hinata: ["female", "key", 4, ["hinata_qiulve", "hinata_ehou"]], }, translate: { key_yuzuru: "新秀球王", @@ -3982,8 +3562,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { next.setContent(function () { "step 0"; for (var i in lib.skill) { - if (lib.skill[i].audio && !lib.skill[i].equipSkill) - lib.skill[i].audio = false; + if (lib.skill[i].audio && !lib.skill[i].equipSkill) lib.skill[i].audio = false; if (lib.skill[i].changeSeat) { lib.skill[i] = {}; if (lib.translate[i + "_info"]) { @@ -3998,15 +3577,12 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { choiceList.videoId = id; choiceList.add([ list.map((item, i) => { - return [ - i, - ``, - ]; + return [i, ``]; }), "textbutton", ]); game.me.chooseButton(true).set("dialog", id).set("onfree", true); - "step 1"; + ("step 1"); var pack = game.liangjunduilei[result.links[0]]; game.versusVideoName = pack.name; if (get.is.phoneLayout()) { @@ -4027,15 +3603,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { player.side = pack.place[i]; player = player.next; } - + for (var i = 0; i < game.players.length; i++) { if (game.players[i].side == game.me.side) { game.players[i].node.identity.firstChild.innerHTML = "友"; } else { game.players[i].node.identity.firstChild.innerHTML = "敌"; } - game.players[i].node.identity.dataset.color = - game.players[i].side + "zhu"; + game.players[i].node.identity.dataset.color = game.players[i].side + "zhu"; } game.addVideo("arrangeLib", null, pack.lib); setTimeout(function () { @@ -4103,27 +3678,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "导出扩展", this, function () { - var str = - '{name:"' + - name + - '",content:function(){\nif(lib.config.mode=="brawl"){\n' + - "if(!lib.storage.scene) lib.storage.scene={};\n" + - 'if(!lib.storage.scene["' + - name + - '"]){\nlib.storage.scene["' + - name + - '"]=' + - get.stringify(scene) + - ";\n_status.extensionscene=true;}\n" + - "if(!_status.extensionmade) _status.extensionmade=[];\n" + - '_status.extensionmade.push("' + - name + - '");\n}}\n}'; + var str = '{name:"' + name + '",content:function(){\nif(lib.config.mode=="brawl"){\n' + "if(!lib.storage.scene) lib.storage.scene={};\n" + 'if(!lib.storage.scene["' + name + '"]){\nlib.storage.scene["' + name + '"]=' + get.stringify(scene) + ";\n_status.extensionscene=true;}\n" + "if(!_status.extensionmade) _status.extensionmade=[];\n" + '_status.extensionmade.push("' + name + '");\n}}\n}'; var extension = { - "extension.js": - 'game.import("extension",function(lib,game,ui,get,ai,_status){return ' + - str + - "})", + "extension.js": 'game.import("extension",function(lib,game,ui,get,ai,_status){return ' + str + "})", }; game.importExtension(extension, null, name); }, @@ -4243,7 +3800,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } maxpos = Math.max(maxpos, scene.players[i].position); } - + if (maxpos < scene.players.length) { maxpos = scene.players.length; } @@ -4323,11 +3880,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } } } - if (info.linked) - target.classList.add("linked" + (get.is.linked2(target) ? "2" : "")); + if (info.linked) target.classList.add("linked" + (get.is.linked2(target) ? "2" : "")); if (info.turnedover) target.classList.add("turnedover"); - if (info.position < _status.firstAct.brawlinfo.position) - _status.firstAct = target; + if (info.position < _status.firstAct.brawlinfo.position) _status.firstAct = target; var hs = []; for (var j = 0; j < info.handcards.length; j++) { hs.push(createCard(info.handcards[j])); @@ -4398,7 +3953,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { lib.translate.zhong = lib.translate.zhong || "忠"; lib.translate.nei = lib.translate.nei || "内"; lib.translate.fan = lib.translate.fan || "反"; - + this.style.transition = "all 0s"; this.style.height = this.offsetHeight - 10 + "px"; this.style.overflow = "scroll"; @@ -4414,22 +3969,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { width: "100%", }; var style3 = { marginLeft: "4px", marginRight: "4px", position: "relative" }; - - var scenename = ui.create.node( - "input", - ui.create.div(style2, "", "场景名称:", this), - { width: "120px" } - ); + + var scenename = ui.create.node("input", ui.create.div(style2, "", "场景名称:", this), { width: "120px" }); scenename.type = "text"; scenename.style.marginTop = "20px"; - var sceneintro = ui.create.node( - "input", - ui.create.div(style2, "", "场景描述:", this), - { width: "120px" } - ); + var sceneintro = ui.create.node("input", ui.create.div(style2, "", "场景描述:", this), { width: "120px" }); sceneintro.type = "text"; sceneintro.style.marginBottom = "10px"; - + var line1 = ui.create.div(style2, this); var addCharacter = ui.create.node( "button", @@ -4476,7 +4023,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { line11.style.display = "block"; capt9.style.display = "block"; line3.style.display = "block"; - + line6_t.style.display = "block"; line6_b.style.display = "block"; line6_d.style.display = "block"; @@ -4548,7 +4095,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, style ); - + var capt1 = ui.create.div(style2, "", "角色信息", this); var line2 = ui.create.div(style2, this); line2.style.display = "none"; @@ -4600,12 +4147,12 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ui.create.node("span", "玩家 ", line2_t, { marginLeft: "10px" }); var playercontrol = ui.create.node("input", line2_t); playercontrol.type = "checkbox"; - + var list = []; for (var i in lib.character) { list.push([i, lib.translate[i]]); } - + list.sort(function (a, b) { a = a[0]; b = b[0]; @@ -4633,16 +4180,16 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { name2.style.marginLeft = "3px"; name2.style.marginRight = "3px"; name2.style.maxWidth = "80px"; - + var capt9 = ui.create.div(style2, "", "编辑牌堆", this); capt9.style.display = "none"; - + var capt2 = ui.create.div(style2, "", "添加卡牌", this); var line3 = ui.create.div(style2, this); line3.style.display = "none"; capt1.style.display = "none"; capt2.style.display = "none"; - + var line5 = ui.create.div(style2, this); line5.style.display = "none"; var pileaddlist = []; @@ -4686,15 +4233,11 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { cardpileaddsuit.style.marginLeft = "3px"; cardpileaddsuit.style.marginRight = "3px"; cardpileaddsuit.style.width = "85px"; - var cardpileaddnumber = ui.create.selectlist( - [["random", "随机点数"], 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], - null, - line3 - ); + var cardpileaddnumber = ui.create.selectlist([["random", "随机点数"], 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], null, line3); cardpileaddnumber.style.marginLeft = "3px"; cardpileaddnumber.style.marginRight = "3px"; cardpileaddnumber.style.width = "85px"; - + var fakecard = function (info, position, capt) { var name = info[0], suit = info[1], @@ -4726,11 +4269,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { return card; }; var cc_h = ui.create.node("button", "加入手牌区", line5, function () { - fakecard( - [cardpileaddname.value, cardpileaddsuit.value, cardpileaddnumber.value], - line6_h, - capt_h - ); + fakecard([cardpileaddname.value, cardpileaddsuit.value, cardpileaddnumber.value], line6_h, capt_h); capt_h.style.display = "block"; }); var cc_e = ui.create.node("button", "加入装备区", line5, function () { @@ -4742,11 +4281,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { break; } } - fakecard( - [cardpileaddname.value, cardpileaddsuit.value, cardpileaddnumber.value], - line6_e, - capt_e - ); + fakecard([cardpileaddname.value, cardpileaddsuit.value, cardpileaddnumber.value], line6_e, capt_e); capt_e.style.display = "block"; }); var cc_j = ui.create.node("button", "加入判定区", line5, function () { @@ -4757,11 +4292,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { break; } } - fakecard( - [cardpileaddname.value, cardpileaddsuit.value, cardpileaddnumber.value], - line6_j, - capt_j - ); + fakecard([cardpileaddname.value, cardpileaddsuit.value, cardpileaddnumber.value], line6_j, capt_j); capt_j.style.display = "block"; }); cc_h.style.marginLeft = "3px"; @@ -4773,7 +4304,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { cc_j.style.marginLeft = "3px"; cc_j.style.marginRight = "3px"; cc_j.style.width = "85px"; - + var capt_h = ui.create.div(style2, "", "手牌区", this); var line6_h = ui.create.div(style2, this); var capt_e = ui.create.div(style2, "", "装备区", this); @@ -4784,31 +4315,19 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { capt_h.style.display = "none"; capt_e.style.display = "none"; capt_j.style.display = "none"; - + var line10 = ui.create.div(style2, this); line10.style.display = "none"; var ac_h = ui.create.node("button", "加入牌堆顶", line10, function () { - fakecard( - [cardpileaddname.value, cardpileaddsuit.value, cardpileaddnumber.value], - line6_t, - capt_t - ); + fakecard([cardpileaddname.value, cardpileaddsuit.value, cardpileaddnumber.value], line6_t, capt_t); capt_t.style.display = "block"; }); var ac_e = ui.create.node("button", "加入牌堆底", line10, function () { - fakecard( - [cardpileaddname.value, cardpileaddsuit.value, cardpileaddnumber.value], - line6_b, - capt_b - ); + fakecard([cardpileaddname.value, cardpileaddsuit.value, cardpileaddnumber.value], line6_b, capt_b); capt_b.style.display = "block"; }); var ac_j = ui.create.node("button", "加入弃牌堆", line10, function () { - fakecard( - [cardpileaddname.value, cardpileaddsuit.value, cardpileaddnumber.value], - line6_d, - capt_d - ); + fakecard([cardpileaddname.value, cardpileaddsuit.value, cardpileaddnumber.value], line6_d, capt_d); capt_d.style.display = "block"; }); ac_h.style.marginLeft = "3px"; @@ -4820,17 +4339,17 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ac_j.style.marginLeft = "3px"; ac_j.style.marginRight = "3px"; ac_j.style.width = "85px"; - + var line11 = ui.create.div(style2, this, "", "替换牌堆"); line11.style.display = "none"; var replacepile = ui.create.node("input", line11); replacepile.type = "checkbox"; - + ui.create.node("span", line11, "开局摸牌", { marginLeft: "10px" }); var gameDraw = ui.create.node("input", line11); gameDraw.type = "checkbox"; gameDraw.checked = true; - + var capt_t = ui.create.div(style2, "", "牌堆顶", this); var line6_t = ui.create.div(style2, this); var capt_b = ui.create.div(style2, "", "牌堆底", this); @@ -4841,7 +4360,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { capt_t.style.display = "none"; capt_b.style.display = "none"; capt_d.style.display = "none"; - + var line4 = ui.create.div(style2, this); line4.style.display = "none"; line4.style.marginTop = "20px"; @@ -4865,7 +4384,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { capt_h.style.display = "none"; capt_e.style.display = "none"; capt_j.style.display = "none"; - + name1.value = "random"; name2.value = "none"; identity.value = "fan"; @@ -4952,14 +4471,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { player.style.top = 0; player.style.margin = "-18px"; player.node.marks.remove(); - + line7.appendChild(player); player.listen(function () { if (confirm("是否删除此角色?")) { this.remove(); } }); - + return player; }; ui.create.div(".menubutton.large", "确定", line4, style3, function () { @@ -4982,10 +4501,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { alert("不能有两个主公"); return; } - if ( - info.position != 0 && - info.position == line7.childNodes[i].info.position - ) { + if (info.position != 0 && info.position == line7.childNodes[i].info.position) { alert("座位与现在角色相同"); return; } @@ -5005,7 +4521,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ui.create.div(".menubutton.large", "取消", line4, style3, resetCharacter); var line7 = ui.create.div(style2, this); line7.style.marginTop = "12px"; - + var capt8 = ui.create.div(style2, "", "胜负条件", this); capt8.style.display = "none"; var line8 = ui.create.div(style2, this); @@ -5033,12 +4549,12 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var turns = ui.create.selectlist(turnslist, "1", line8); ui.create.node("span", "个回合后", line8, style); var turnsresult = ui.create.selectlist(results, "none", line8); - + var washes = ui.create.selectlist(turnslist, "1", line8); washes.style.marginLeft = "20px"; ui.create.node("span", "次洗牌后", line8, style); var washesresult = ui.create.selectlist(results, "none", line8); - + var line9 = ui.create.div(style2, this); line9.style.display = "none"; line9.style.marginTop = "20px"; @@ -5049,7 +4565,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { cardpileaddname.value = "random"; cardpileaddsuit.value = "random"; cardpileaddnumber.value = "random"; - + line8.style.display = "none"; capt8.style.display = "none"; capt9.style.display = "none"; @@ -5058,14 +4574,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { line11.style.display = "none"; line3.style.display = "none"; line7.style.display = "block"; - + line6_t.style.display = "none"; line6_b.style.display = "none"; line6_d.style.display = "none"; capt_t.style.display = "none"; capt_b.style.display = "none"; capt_d.style.display = "none"; - + if (all === true) { replacepile.checked = false; gameDraw.checked = true; @@ -5078,9 +4594,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { line6_d.innerHTML = ""; } }; - + ui.create.div(".menubutton.large", "确定", line9, style3, resetStatus); - + game.addSceneClear = function () { resetCharacter(); resetStatus(true); @@ -5116,7 +4632,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { for (var i = 0; i < scene.discardPile.length; i++) { fakecard(scene.discardPile[i], line6_d, capt_d); } - + for (var i = 0; i < scene.players.length; i++) { createCharacter(scene.players[i]); } @@ -5193,28 +4709,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { function () { var level = stage.level; stage.level = 0; - var str = - '{name:"' + - name + - '",content:function(){\nif(lib.config.mode=="brawl"){\n' + - "if(!lib.storage.stage) lib.storage.stage={};\n" + - 'if(!lib.storage.stage["' + - name + - '"]){\nlib.storage.stage["' + - name + - '"]=' + - get.stringify(stage) + - ";\n_status.extensionstage=true;}\n" + - "if(!_status.extensionmade) _status.extensionmade=[];\n" + - '_status.extensionmade.push("' + - name + - '");\n}}\n}'; + var str = '{name:"' + name + '",content:function(){\nif(lib.config.mode=="brawl"){\n' + "if(!lib.storage.stage) lib.storage.stage={};\n" + 'if(!lib.storage.stage["' + name + '"]){\nlib.storage.stage["' + name + '"]=' + get.stringify(stage) + ";\n_status.extensionstage=true;}\n" + "if(!_status.extensionmade) _status.extensionmade=[];\n" + '_status.extensionmade.push("' + name + '");\n}}\n}'; stage.level = level; var extension = { - "extension.js": - 'game.import("extension",function(lib,game,ui,get,ai,_status){return ' + - str + - "})", + "extension.js": 'game.import("extension",function(lib,game,ui,get,ai,_status){return ' + str + "})", }; game.importExtension(extension, null, name); }, @@ -5232,13 +4730,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } }; for (var i = 0; i < stage.scenes.length; i++) { - var node = ui.create.div( - ".menubutton.large", - line2, - stage.scenes[i].name, - style3, - clickNode - ); + var node = ui.create.div(".menubutton.large", line2, stage.scenes[i].name, style3, clickNode); node.index = i; if (stage.mode == "sequal") { if (i == stage.level) { @@ -5255,11 +4747,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (lib.storage.lastStage == i && !node.classList.contains("unselectable")) { node.classList.add("active"); noactive = false; - } else if ( - lib.storage.lastStage == undefined && - noactive && - !node.classList.contains("unselectable") - ) { + } else if (lib.storage.lastStage == undefined && noactive && !node.classList.contains("unselectable")) { node.classList.add("active"); noactive = false; } @@ -5288,22 +4776,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { width: "100%", }; var style3 = { marginLeft: "4px", marginRight: "4px", position: "relative" }; - - var scenename = ui.create.node( - "input", - ui.create.div(style2, "", "关卡名称:", this), - { width: "120px" } - ); + + var scenename = ui.create.node("input", ui.create.div(style2, "", "关卡名称:", this), { width: "120px" }); scenename.type = "text"; scenename.style.marginTop = "20px"; - var sceneintro = ui.create.node( - "input", - ui.create.div(style2, "", "关卡描述:", this), - { width: "120px" } - ); + var sceneintro = ui.create.node("input", ui.create.div(style2, "", "关卡描述:", this), { width: "120px" }); sceneintro.type = "text"; sceneintro.style.marginBottom = "10px"; - + var line1 = ui.create.div(style2, this); var line2 = ui.create.div(style2, this); line1.style.marginBottom = "10px"; @@ -5421,5 +4901,5 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - }; -}); + } +} diff --git a/mode/chess.js b/mode/chess.js index 1793680340..4566f97a3c 100644 --- a/mode/chess.js +++ b/mode/chess.js @@ -1,10 +1,14 @@ -"use strict"; -game.import("mode", function (lib, game, ui, get, ai, _status) { +import { lib, game, ui, get, ai, _status } from "../noname.js"; +export const type = 'mode'; +/** + * @type { () => importModeConfig } + */ +export default () => { return { name: "chess", canvasUpdates2: [], hiddenCharacters: [], - start: function () { + start() { "step 0"; _status.gameDrawed = true; _status.mode = get.config("chess_mode"); @@ -176,7 +180,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } else { side = Math.random() < 0.5; } - + switch (num) { case 1: ui.chessheight = 4; @@ -206,10 +210,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ui.chessheight = 8; } ui.chesswidth = Math.round(ui.chessheight * 1.5); - + if (num == 1) ui.chesswidth++; game.initChess(); - + var grids = []; var gridnum = ui.chessheight * ui.chesswidth; for (var i = 0; i < gridnum; i++) { @@ -275,7 +279,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } lib.posmap[enemy.dataset.position] = enemy; } - + if (lib.config.show_handcardbutton) { lib.setPopped( ui.create.system("手牌", null, true), @@ -297,13 +301,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (!added) { uiintro.add("无队友"); } - + return uiintro; }, 220 ); } - + if ( !event.video && _status.mode == "combat" && @@ -318,10 +322,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { lib.setPopped(ui.friendDied, function () { if (_status.replacelist.length) { var uiintro = ui.create.dialog("hidden"); - + uiintro.add("未上场"); uiintro.add([_status.replacelist, "character"]); - + return uiintro; } }); @@ -383,10 +387,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ui.finishGame.classList.add("finish_game"); ui.finishGame.parentNode.insertBefore(finishGameBr, ui.finishGame); } - + ui.create.me(); ui.create.fakeme(); - + if ( !event.video && ((_status.mode == "combat" && @@ -400,7 +404,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.friendZhu.maxHp++; game.friendZhu.update(); game.friendZhu.node.identity.firstChild.innerHTML = "将"; - + for (var i = 0; i < game.players.length; i++) { if (game.players[i].side != game.me.side) { game.enemyZhu = game.players[i]; @@ -411,7 +415,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { break; } } - + if ((get.config("main_zhu") || _status.mode == "three") && event.friendViceZhu) { game.friendViceZhu = event.friendViceZhu; game.friendViceZhu.node.identity.firstChild.innerHTML = "仕"; @@ -424,13 +428,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } } } - + ui.chessinfo = ui.create.div(".fakeme.player.playerbg", ui.me, function (e) { e.stopPropagation(); }); ui.create.div(ui.chessinfo); lib.setScroll(ui.chessinfo.firstChild); - + game.arrangePlayers(); "step 3"; ui.control.style.display = ""; @@ -455,7 +459,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.setChessInfo(p); return; } - + var players = get.players(lib.sort.position); var info = []; for (var i = 0; i < players.length; i++) { @@ -479,7 +483,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (event.obs) { game.addVideo("initobs", null, event.obs); } - + event.trigger("gameStart"); game.gameDraw(p); game.me.classList.add("current_action"); @@ -567,7 +571,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (y >= ui.chessheight) { y = ui.chessheight - 1; } - + var pos = y * ui.chesswidth + x; if (!lib.posmap[pos]) { delete lib.posmap[this.dataset.position]; @@ -576,7 +580,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { lib.posmap[pos] = this; this.chessFocus(); } - + if (get.mode() == "tafang" && !_status.video) { if (_status.tafangend.includes(this.dataset.position)) { if (_status.enemies.includes(this)) { @@ -699,7 +703,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var player = this; var dx = 0, dy = 0; - + if (player.getLeft() - ui.chessContainer.chessLeft < 14) { dx = player.getLeft() - ui.chessContainer.chessLeft - 14; } else if ( @@ -963,7 +967,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } else if (!num || typeof num == "number") { game.addVideo("chessgainmod", this, num); } - + return this.$gainmod(num); }, $gainmod: function (num) { @@ -1057,17 +1061,17 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } else { node = ui.create.div(".card.thrown"); } - + node.dataset.position = this.dataset.position; node.fixed = true; node.hide(); - + this.parentNode.appendChild(node); ui.refresh(node); node.show(); - + this.$randomMove(node, 130, 0); - + setTimeout(function () { lib.element.card.moveTo.call(node, player); setTimeout(function () { @@ -1098,8 +1102,16 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, $phaseJudge: function (card) { game.addVideo("phaseJudge", this, get.cardInfo(card)); - var clone = card.copy("thrown", this.parentNode).addTempClass("judgestart"); - var player = this; + let cardToThrow; + if(card.cards?.length){ + //TODO: 这里先偷懒,只用其中的第一张牌进行处理,先解决bug + cardToThrow = card.cards[0]; + } + else { + cardToThrow = game.createCard(card.name, "虚拟", ""); + } + const clone = cardToThrow.copy("thrown", this.parentNode).addTempClass("judgestart"); + const player = this; clone.style.opacity = 0.6; clone.style.left = Math.random() * 100 - @@ -1142,7 +1154,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } } thrown.push(node); - + var rect = this.getBoundingClientRect(); var amax, amin; if (rect.left <= 80) { @@ -1524,7 +1536,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { e.preventDefault(); }); } - + ui.chessscroll1 = ui.create.div(".chessscroll.left", ui.chessContainer); ui.chessscroll2 = ui.create.div(".chessscroll.right", ui.chessContainer); var chessscroll = function () { @@ -1547,11 +1559,11 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ui.chessscroll1.direction = -1; ui.chessscroll1.addEventListener("mouseenter", chessscroll); ui.chessscroll1.addEventListener("mouseleave", leavescroll); - + ui.chessscroll2.direction = 1; ui.chessscroll2.addEventListener("mouseenter", chessscroll); ui.chessscroll2.addEventListener("mouseleave", leavescroll); - + for (var i = 0; i < ui.chesswidth; i++) { for (var j = 0; j < ui.chessheight; j++) { var pos = '[data-position="' + (i + j * ui.chesswidth) + '"]'; @@ -1667,9 +1679,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } else if (game.players.length) { game.setChessInfo(game.players[0]); } - + game.triggerEnter(player); - + return player; }, replaceChessPlayer: function (name, enemy) { @@ -1698,7 +1710,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (y >= ui.chessheight) { y = ui.chessheight - 1; } - + pos = y * ui.chesswidth + x; } if (!lib.posmap[pos]) { @@ -2107,13 +2119,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } var ax = a % ui.chesswidth; var ay = Math.floor(a / ui.chesswidth); - + var bx = b % ui.chesswidth; var by = Math.floor(b / ui.chesswidth); - + if (ax == bx && Math.abs(ay - by) == 1) return true; if (ay == by && Math.abs(ax - bx) == 1) return true; - + return false; }, draw2: function (func) { @@ -2298,7 +2310,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { lib.rank.rarity.common.push(lib.rank.all[i]); } } - + ui.control.style.transition = "all 0s"; if (get.is.phoneLayout()) { ui.control.style.top = "calc(100% - 80px)"; @@ -2311,7 +2323,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { node.style.opacity = 0; node.style.zIndex = 4; node.classList.add("pointerdiv"); - + var kaibao = false; if (!name || typeof i == "string") { if (!name) { @@ -2588,7 +2600,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { fixButton(dialog1.buttons[i]); } dialog1.open(); - + var dialog2 = ui.create.dialog("战斗难度", "hidden"); event.dialog2 = dialog2; dialog2.classList.add("fullheight"); @@ -2631,7 +2643,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { dialog2.buttons[i]._nopup = true; dialog2.buttons[i].style.marginLeft = "4px"; dialog2.buttons[i].style.marginRight = "4px"; - + if (i < 3) { dialog2.buttons[i].area = "difficulty"; } else { @@ -2659,7 +2671,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } dialog2.open(); dialog1.classList.remove("hidden"); - + var selected = { lord: [], character: [], @@ -3527,7 +3539,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } } } - + var victory = ui.create.div().hide(); victory.innerHTML = "" + game.data.arena.win + "胜"; victory.style.top = "auto"; @@ -3540,7 +3552,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ui.window.appendChild(victory); ui.refresh(victory); victory.show(); - + event.checkPrize = function () { // event.kaibao=true; event.prize = []; @@ -3576,7 +3588,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { div.style.letterSpacing = "8px"; div.style.whiteSpace = "nowrap"; // div.dataset.nature='metal'; - + return; } node.style.transition = "all ease-in 0.3s"; @@ -3856,7 +3868,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } else { event.checkPrize(); } - + event.custom.add.window = function () { if (_status.chessclicked) { _status.chessclicked = false; @@ -3979,7 +3991,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var jiange = ui.create.div(".buttons"); event.jiange = jiange; var jiangebuttons = ui.create.buttons(jiangelist, "character", jiange); - + var clickedBoss = false; var clickBoss = function () { clickedBoss = true; @@ -4015,7 +4027,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } addToButton(); }; - + var clickedJiange = false; var clickJiange = function () { clickedJiange = true; @@ -4026,7 +4038,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } addToButton(); }; - + for (var i = 0; i < bossbuttons.length; i++) { bossbuttons[i].classList.add("noclick"); bossbuttons[i].listen(clickBoss); @@ -4035,7 +4047,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { jiangebuttons[i].classList.add("noclick"); jiangebuttons[i].listen(clickJiange); } - + if (get.config("additional_player") == undefined) game.saveConfig("additional_player", true, true); if (get.config("reward") == undefined) game.saveConfig("reward", 3, true); @@ -4047,7 +4059,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (get.config("single_control") == undefined) game.saveConfig("single_control", false, true); if (get.config("first_less") == undefined) game.saveConfig("first_less", true, true); - + var dialog = ui.create.dialog("选择出场角色", "hidden"); dialog.classList.add("fullwidth"); dialog.classList.add("fullheight"); @@ -4147,13 +4159,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { jiange.childNodes[i].classList.add("squarebutton"); } ui.control.style.transition = "all 0s"; - + if (get.is.phoneLayout()) { ui.control.style.top = "calc(100% - 80px)"; } else { ui.control.style.top = "calc(100% - 70px)"; } - + var next = game.me.chooseButton(dialog, true).set("onfree", true); next._triggered = null; next.selectButton = function () { @@ -4241,7 +4253,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.changeCoin(-3); } list.randomSort(); - + var buttons = ui.create.div(".buttons"); var node = _status.event.dialog.buttons[0].parentNode; _status.event.dialog.buttons = ui.create.buttons( @@ -4257,7 +4269,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _status.event.dialog.content.insertBefore(buttons, node); buttons.addTempClass("start"); node.remove(); - + // _status.event.dialog.close(); // var dialog=ui.create.dialog('选择出场角色','hidden'); // _status.event.dialog=dialog; @@ -4356,7 +4368,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ui.control.style.transition = ""; ui.control.style.display = "none"; } - + var glows = event.bosses.querySelectorAll(".glow"); var glows2 = event.jiange.querySelectorAll(".glow2"); if (!glows.length && !glows2.length) { @@ -5114,13 +5126,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } } mark.setBackground(currentname, "character"); - + player.addAdditionalSkill("tongshuai", link); game.addVideo("chess_tongshuai_skill", player, [currentname, link]); player.logSkill("tongshuai2"); game.log(player, "获得技能", "【" + get.translation(link) + "】"); player.popup(link); - + for (var i = 0; i < event.dialog.buttons.length; i++) { if (event.dialog.buttons[i].classList.contains("selected")) { var name = event.dialog.buttons[i].link; @@ -5244,7 +5256,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ai: { order: 10, effect: { - player: function (card, player) { + player_use: function (card, player) { var num = 0; for (var i = 0; i < game.players.length; i++) { if (get.attitude(player, game.players[i]) < 0) { @@ -6009,7 +6021,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { single_control_config: "单人控制", additional_player_config: "无尽模式", choice_number_config: "无尽模式候选", - + friend: "友", enemy: "敌", neutral: "中", @@ -6030,7 +6042,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { save3: "三", save4: "四", save5: "五", - + leader_2: " ", leader_2_bg: "二", leader_3: " ", @@ -6039,14 +6051,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { leader_5_bg: "五", leader_8: " ", leader_8_bg: "八", - + leader_easy: " ", leader_easy_bg: "简单", leader_medium: " ", leader_medium_bg: "普通", leader_hard: " ", leader_hard_bg: "困难", - + chess_caocao: "曹操", chess_xunyu: "荀彧", chess_simayi: "司马懿", @@ -6055,7 +6067,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { chess_xuzhu: "许褚", chess_zhangliao: "张辽", chess_jiaxu: "贾诩", - + chess_liubei: "刘备", chess_guanyu: "关羽", chess_zhangfei: "张飞", @@ -6064,7 +6076,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { chess_huangzhong: "黄忠", chess_maliang: "马良", chess_zhugeliang: "诸葛亮", - + chess_sunquan: "孙权", chess_zhouyu: "周瑜", chess_lvmeng: "吕蒙", @@ -6073,27 +6085,27 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { chess_luxun: "陆逊", chess_ganning: "甘宁", chess_taishici: "太史慈", - + chess_lvbu: "吕布", chess_sunshangxiang: "孙尚香", chess_diaochan: "貂蝉", chess_huatuo: "华佗", chess_zhangjiao: "张辽", chess_menghuo: "孟获", - + chess_dongzhuo: "董卓", chess_xingtian: "刑天", chess_jinchidiao: "金翅雕", chess_beimingjukun: "北溟巨鲲", chess_wuzhaojinlong: "五爪金龙", - + treasure_dubiaoxianjing: "毒镖陷阱", treasure_jiqishi: "集气石", treasure_shenmidiaoxiang: "神秘雕像", treasure_shenpanxianjing: "审判之刃", treasure_shiyuansu: "石元素", treasure_wuyashenxiang: "乌鸦神像", - + dubiaoxianjing: "飞刃", dubiaoxianjing_info: "距离两格体力值大于1的角色在回合结束后受到1点伤害,然后摸两张牌。", jiqishi: "集气", @@ -6108,7 +6120,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { wuyashenxiang: "厄音", wuyashenxiang_info: "距离3格以内的角色在其回合结束后,若体力值不大于1,令其回复1点体力,然后将牌堆中的一张延时锦囊牌置于其判定区。", - + leader_caocao: "曹操", leader_liubei: "刘备", leader_sunquan: "孙权", @@ -6121,31 +6133,31 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { leader_mouduan_info: "其他友方角色回合内的行动范围+1。", leader_zhenlve: "缜略", leader_zhenlve_info: "友方角色使用的普通锦囊牌不可被【无懈可击】响应。", - + tongshuai: "统率", tongshuai_info: "准备阶段和结束阶段,你可以选择一名未上场的已方武将的一个技能作为你的技能。", leader_zhaoxiang: "招降", leader_zhaoxiang_info: "出牌阶段限一次,你可以尝试对相邻敌方武将进行招降,若成功,你获得该武将并立即结束本局游戏,若失败,你受到1点伤害。每发动一次消耗10招募令。", - + common: "普通", rare: "精品", epic: "史诗", legend: "传说", - + chess_shezhang: "设置路障", chess_shezhang_info: "选择一名角色,在其四周设置临时路障,持续X回合(X为存活角色数)。", chess_chuzhang: "清除路障", chess_chuzhang_info: "将与你相邻的路障向后推移一格,每影响一个路障你摸一张牌。", - + _chess_chuzhang: "除障", _chess_chuzhang_info: "出牌阶段限一次,若你周围四格至少有三个为障碍或在边缘外,你可以选择将其中一个障碍向后推移一格(若无法推移则改为清除之)。", - + arenaAdd: "援军", arenaAdd_info: "出牌阶段限一次,你可以令一名未出场的已方角色加入战场。战斗结束后,该角色无论是否存活均不能再次出场。", - + pianyi: "翩仪", pianyi_info: "结束阶段,若你于本回合内未造成过伤害,你获得一次移动机会。", lingdong: "灵动", @@ -6160,13 +6172,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "你可以将两张【杀】当做【杀】使用,你以此法使用的【杀】可以指定距离5格内的角色为目标。", guanchuan: "强弩", guanchuan_info: "当你使用【杀】指定唯一目标后,你可令攻击射线内的其他角色也成为此【杀】的目标。", - + boss_stoneqiangzheng: "强征", boss_stoneqiangzheng_info: "锁定技,结束阶段,你获得所有其他角色的各一张手牌。", boss_stonebaolin: "暴凌", boss_moyan: "魔焰", boss_moyan_info: "锁定技,结束阶段,你对场上所有角色造成1点火焰伤害。", - + cangming: "颠动沧溟", cangming_info: "出牌阶段限一次,你可弃置四张花色不同的手牌并将武将牌翻至背面,然后令所有其他角色进入混乱状态直到你的下一回合开始。", @@ -6182,11 +6194,11 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_wushang_info: "锁定技,准备阶段,距离你5以内的所有其他角色需交给你一张手牌。", boss_wuying: "无影", boss_wuying_info: "锁定技,你回合内的移动距离-1;其他角色至你的距离+2。", - + chess_default: "常规", chess_boss: "魔王", chess_leader: "君主", - + mode_chess_character_config: "战棋模式", mode_chess_card_config: "战棋模式", }, @@ -6657,5 +6669,5 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "竞技场:
    随机选择9名武将,每次派出1~3名武将参战。战斗中阵亡的武将不能再次上场。

    战斗后武将进入疲劳状态,若立即再次出场则初始体力值-1。

    战斗中本方武将行动时可召唤后援,令一名未出场的已方武将加入战斗。后援武将在战斗结束后无论存活与否均不能再次出场

    当取得12场胜利或所有武将全部阵亡后结束,并根据胜场数获得随机奖励
  • " + "修改金钱:
    game.changeMoney
    修改招募令:
    game.changeDust", }, - }; -}); + } +} diff --git a/mode/connect.js b/mode/connect.js index 31272f31cc..842b45621b 100644 --- a/mode/connect.js +++ b/mode/connect.js @@ -1,8 +1,12 @@ -"use strict"; -game.import("mode", function (lib, game, ui, get, ai, _status) { +import { lib, game, ui, get, ai, _status } from '../noname.js'; +export const type = 'mode'; +/** + * @type { () => importModeConfig } + */ +export default () => { return { name: "connect", - start: function () { + start() { var directstartmode = lib.config.directstartmode; ui.create.menu(true); event.textnode = ui.create.div("", "输入联机地址"); @@ -31,7 +35,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { true ); } - + event.created = true; var node = ui.create.div(".shadowed"); node.style.width = "400px"; @@ -48,7 +52,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { node.style.webkitUserSelect = "text"; node.style.textAlign = "center"; node.style.overflow = "hidden"; - + var connect = function (e) { event.textnode.textContent = "正在连接..."; clearTimeout(event.timeout); @@ -78,7 +82,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }); ui.window.appendChild(node); ui.ipnode = node; - + var text = event.textnode; text.style.width = "400px"; text.style.height = "30px"; @@ -91,14 +95,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { text.style.textAlign = "center"; ui.window.appendChild(text); ui.iptext = text; - + var button = ui.create.div(".menubutton.highlight.large.pointerdiv", "连接", connect); button.style.width = "70px"; button.style.left = "calc(50% - 35px)"; button.style.top = "calc(50% + 60px)"; ui.window.appendChild(button); ui.ipbutton = button; - + ui.hall_button = ui.create.system( "联机大厅", function () { @@ -206,5 +210,5 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _status.connectDenied = createNode; setTimeout(lib.init.onfree, 1000); }, - }; -}); + } +} diff --git a/mode/doudizhu.js b/mode/doudizhu.js index 3141ed0ee2..d712251fd1 100644 --- a/mode/doudizhu.js +++ b/mode/doudizhu.js @@ -1,8 +1,12 @@ -"use strict"; -game.import("mode", function (lib, game, ui, get, ai, _status) { +import { lib, game, ui, get, ai, _status } from '../noname.js'; +export const type = 'mode'; +/** + * @type { () => importModeConfig } + */ +export default () => { return { name: "doudizhu", - start: function () { + start() { "step 0"; var playback = localStorage.getItem(lib.configprefix + "playback"); if (playback) { @@ -119,7 +123,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } game.syncState(); event.trigger("gameStart"); - + var players = get.players(lib.sort.position); var info = []; for (var i = 0; i < players.length; i++) { @@ -133,7 +137,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _status.videoInited = true; game.addVideo("init", null, info); if (_status.mode == "kaihei") game.addGlobalSkill("kaihei"); - + var next = game.gameDraw(game.zhu || _status.firstAct || game.me); if (_status.mode == "online") { game.zhu.$equip(game.createCard("diqi", "club", 13)); @@ -675,7 +679,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, 500); }); }, - + chooseCharacterKaihei: function () { var next = game.createEvent("chooseCharacter"); next.setContent(function () { @@ -695,7 +699,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.zhu = game.players[i]; } } - + if (!game.zhu) game.zhu = game.me; else { game.zhu.setIdentity(); @@ -705,7 +709,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.me.setIdentity(); game.me.node.identity.classList.remove("guessing"); } - + for (i in lib.characterReplace) { var ix = lib.characterReplace[i]; for (var j = 0; j < ix.length; j++) { @@ -829,7 +833,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var chosen = lib.config.continue_name || []; game.saveConfig("continue_name"); event.chosen = chosen; - + var addSetting = function (dialog) { dialog.add("选择身份").classList.add("add-setting"); var table = document.createElement("div"); @@ -837,7 +841,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { table.style.margin = "0"; table.style.width = "100%"; table.style.position = "relative"; - + var listi = ["random", "zhu", "fan"]; for (var i = 0; i < listi.length; i++) { var td = ui.create.div(".shadowed.reduce_radius.pointerdiv.tdnode"); @@ -918,7 +922,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }); } dialog.content.appendChild(table); - + dialog.add("选择座位").classList.add("add-setting"); var seats = document.createElement("div"); seats.classList.add("add-setting"); @@ -955,7 +959,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { seats.previousSibling.style.display = "none"; seats.style.display = "none"; } - + dialog.add(ui.create.div(".placeholder.add-setting")); dialog.add(ui.create.div(".placeholder.add-setting")); if (get.is.phoneLayout()) dialog.add(ui.create.div(".placeholder.add-setting")); @@ -996,7 +1000,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.zhu = game.players[i]; } } - + if (!game.zhu) game.zhu = game.me; else { game.zhu.setIdentity(); @@ -1048,7 +1052,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } dialog.setCaption("选择角色"); game.me.setIdentity(); - + if (!event.chosen.length) { game.me.chooseButton(dialog, true).set("onfree", true).selectButton = function () { return get.config("double_character") ? 2 : 1; @@ -1065,10 +1069,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (game.changeCoin) { game.changeCoin(-3); } - + event.list.randomSort(); list = event.list.slice(0, num); - + var buttons = ui.create.div(".buttons"); var node = _status.event.dialog.buttons[0].parentNode; _status.event.dialog.buttons = ui.create.buttons(list, "characterx", buttons); @@ -1091,7 +1095,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } else { event.dialogxx = ui.create.characterDialog("heightset"); } - + ui.create.cheat2 = function () { ui.cheat2 = ui.create.control("自由选将", function () { if (this.dialog == _status.event.dialog) { @@ -1181,7 +1185,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.me.update(); } } - + for (var i = 0; i < game.players.length; i++) { if (game.players[i] != game.me) { event.list.randomSort(); @@ -1203,7 +1207,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, 500); }); }, - + chooseCharacterKaiheiOL: function () { var next = game.createEvent("chooseCharacter"); next.setContent(function () { @@ -1228,7 +1232,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } event.list = []; var list4 = []; - + var libCharacter = {}; for (var i = 0; i < lib.configOL.characterPack.length; i++) { var pack = lib.characterPack[lib.configOL.characterPack[i]]; @@ -1253,7 +1257,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { event.list.push(i); } _status.characterlist = event.list.slice(0); - + var map = {}; for (var player of game.players) { player._characterChoice = event.list.randomRemove(player.identity == "zhu" ? 5 : 3); @@ -1300,13 +1304,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { lib.playerOL[i].init(result[i]); } } - + if (!game.zhu.isInitFilter("noZhuHp")) { game.zhu.maxHp++; game.zhu.hp++; game.zhu.update(); } - + game.broadcast( function (result, zhu) { for (var i in result) { @@ -1320,7 +1324,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.zhu.hp++; game.zhu.update(); } - + setTimeout(function () { ui.arena.classList.remove("choose-character"); }, 500); @@ -1444,13 +1448,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { lib.playerOL[i].init(result[i][0], result[i][1]); } } - + if (!game.zhu.isInitFilter("noZhuHp")) { game.zhu.maxHp++; game.zhu.hp++; game.zhu.update(); } - + game.broadcast( function (result, zhu) { for (var i in result) { @@ -1464,7 +1468,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.zhu.hp++; game.zhu.update(); } - + setTimeout(function () { ui.arena.classList.remove("choose-character"); }, 500); @@ -1510,7 +1514,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } event.start = game.players.randomGet(); event.current = event.start; - + event.videoId = lib.status.videoId++; game.zhuSkill = "zhuSkill_" + ["xiangyang", "jiangling", "fancheng"].randomGet(); game.broadcastAll( @@ -1612,13 +1616,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { lib.playerOL[i].init(result[i]); } } - + if (!game.zhu.isInitFilter("noZhuHp")) { game.zhu.maxHp++; game.zhu.hp++; game.zhu.update(); } - + game.broadcast( function (result, zhu) { for (var i in result) { @@ -1632,7 +1636,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.zhu.hp++; game.zhu.update(); } - + setTimeout(function () { ui.arena.classList.remove("choose-character"); }, 500); @@ -1703,7 +1707,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } event.start = game.players.randomGet(); event.current = event.start; - + event.videoId = lib.status.videoId++; game.broadcastAll( function (map, id) { @@ -1789,11 +1793,11 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { lib.playerOL[i].init(result[i][0], result[i][1]); } } - + game.zhu.hp = 4; game.zhu.maxHp = 4; game.zhu.update(); - + game.broadcast( function (result, zhu) { for (var i in result) { @@ -1805,7 +1809,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.zhu.hp = 4; game.zhu.maxHp = 4; game.zhu.update(); - + setTimeout(function () { ui.arena.classList.remove("choose-character"); }, 500); @@ -1849,11 +1853,11 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.players[i].identityShown = true; if (identityList[i] == "zhu") game.zhu = game.players[i]; } - + var list; var list4 = []; event.list = []; - + var libCharacter = {}; for (var i = 0; i < lib.configOL.characterPack.length; i++) { var pack = lib.characterPack[lib.configOL.characterPack[i]]; @@ -1890,7 +1894,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "step 1"; var list = []; var selectButton = lib.configOL.double_character ? 2 : 1; - + var num, num2 = 0; num = Math.floor(event.list.length / game.players.length); @@ -1901,7 +1905,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (num2 > 2) { num2 = 2; } - + for (var i = 0; i < game.players.length; i++) { var num3 = 0; if (game.players[i] == game.zhu) num3 = 3; @@ -1939,13 +1943,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { lib.playerOL[i].init(result[i][0], result[i][1]); } } - + if (!game.zhu.isInitFilter("noZhuHp")) { game.zhu.maxHp++; game.zhu.hp++; game.zhu.update(); } - + game.broadcast( function (result, zhu) { for (var i in result) { @@ -1959,7 +1963,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.zhu.hp++; game.zhu.update(); } - + setTimeout(function () { ui.arena.classList.remove("choose-character"); }, 500); @@ -2951,7 +2955,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { str += "使用了"; str += get.translation(card); str += ",是否对其使用【炸弹】?"; - + var next = player.chooseToUse({ filterCard: function (card, player) { if (get.name(card) != "zhadan" || get.itemtype(card) != "card") return false; @@ -2976,7 +2980,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { type: "zhadan", }); next.set("respondTo", [source, card]); - + if (game.online) { _status.event._resultid = id; game.resume(); @@ -3057,7 +3061,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } } }; - + var withme = false; var withol = false; var list = event.list; @@ -3520,7 +3524,6 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "re_zhurong", "re_fazheng", "re_masu", - "guanxingzhangbao", "xin_liaohua", "old_madai", "re_jianyong", @@ -3705,7 +3708,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["spade", 12, "zhangba"], ["spade", 13, "wuxie"], ["spade", 13, "dawanma"], - + ["club", 1, "baiyin"], ["club", 1, "zhuge"], ["club", 2, "tengjia"], @@ -3733,7 +3736,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["club", 13, "tiesuo"], ["club", 13, "jiedao"], ["club", 13, "wuxie"], - + ["heart", 1, "wuxie"], ["heart", 1, "gongshoujianbei"], ["heart", 1, "zhadan"], @@ -3761,7 +3764,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["heart", 12, "guohe"], ["heart", 13, "wuxie"], ["heart", 13, "zhuahuang"], - + ["diamond", 1, "zhuque"], ["diamond", 1, "juedou"], ["diamond", 2, "tao"], @@ -3795,5 +3798,5 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { '
    游戏规则
    ", }, - }; -}); + } +} diff --git a/mode/guozhan.js b/mode/guozhan.js index d9697c822c..b020754318 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -1,8 +1,12 @@ -"use strict"; -game.import("mode", function (lib, game, ui, get, ai, _status) { +import { lib, game, ui, get, ai, _status } from '../noname.js'; +export const type = 'mode'; +/** + * @type { () => importModeConfig } + */ +export default () => { return { name: "guozhan", - startBefore: function () { + startBefore() { var playback = localStorage.getItem(lib.configprefix + "playback"); for (var i in lib.characterPack.mode_guozhan) { if (!get.config("onlyguozhan") && !playback) { @@ -19,7 +23,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } } }, - onreinit: function () { + onreinit() { var pack = lib.characterPack.mode_guozhan; for (var i in pack) { lib.character[i] = pack[i]; @@ -33,7 +37,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } } }, - start: function () { + start() { "step 0"; var playback = localStorage.getItem(lib.configprefix + "playback"); if (playback) { @@ -189,7 +193,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { // } } }, event.playerx); - + var players = get.players(lib.sort.position); var info = []; for (var i = 0; i < players.length; i++) { @@ -310,7 +314,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gz_shibing2ye: ["female", "ye", 0, [], ["unseen"]], gz_shibing1key: ["male", "key", 0, [], ["unseen"]], gz_shibing2key: ["female", "key", 0, [], ["unseen"]], - + gz_zhonghui: ["male", "ye", 4, ["fakequanji", "fakepaiyi"], ["gzskin"]], gz_simazhao: ["male", "ye", 3, ["gzzhaoxin", "gzsuzhi"], ["gzskin"]], gz_gongsunyuan: ["male", "ye", 4, ["gzrehuaiyi", "gzrezisui"], ["gzskin"]], @@ -335,7 +339,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gz_liuba: ["male", "shu", 3, ["gztongduo", "qingyin"], ["gzskin"]], gz_pengyang: ["male", "shu", 3, ["gztongling", "gzjinyu"], ["doublegroup:shu:qun", "gzskin"]], gz_zhuling: ["male", "wei", 4, ["gzjuejue", "gzfangyuan"], ["gzskin"]], - + gz_caocao: ["male", "wei", 4, ["rejianxiong_old"]], gz_simayi: ["male", "wei", 3, ["fankui", "guicai"]], gz_xiahoudun: ["male", "wei", 4, ["reganglie"]], @@ -351,7 +355,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gz_xunyu: ["male", "wei", 3, ["quhu", "gzjieming"]], gz_caopi: ["male", "wei", 3, ["xingshang", "gzfangzhu"], ["gzskin"]], gz_yuejin: ["male", "wei", 4, ["fakexiaoguo"], ["gzskin"]], - + gz_liubei: ["male", "shu", 4, ["rerende"]], gz_guanyu: ["male", "shu", 5, ["new_rewusheng"], ["gzskin"]], gz_zhangfei: ["male", "shu", 4, ["gzpaoxiao"]], @@ -368,7 +372,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gz_zhurong: ["female", "shu", 4, ["juxiang", "lieren"]], gz_ganfuren: ["female", "shu", 3, ["new_shushen", "shenzhi"], ["gzskin"]], gz_yuji: ["male", "qun", 3, ["qianhuan"], ["gzskin"]], - + gz_sunquan: ["male", "wu", 4, ["gzzhiheng"]], gz_ganning: ["male", "wu", 4, ["qixi"]], gz_lvmeng: ["male", "wu", 4, ["new_keji", "new_mouduan"]], @@ -384,7 +388,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gz_re_lusu: ["male", "wu", 3, ["haoshi", "dimeng"]], gz_zhangzhang: ["male", "wu", 3, ["zhijian", "guzheng"]], gz_dingfeng: ["male", "wu", 4, ["fakeduanbing", "fenxun"], ["gzskin"]], - + gz_huatuo: ["male", "qun", 3, ["new_chuli", "jijiu"]], gz_lvbu: ["male", "qun", 5, ["gzwushuang"], ["gzskin"]], gz_diaochan: ["female", "qun", 3, ["lijian", "biyue"], ["gzskin"]], @@ -394,34 +398,34 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gz_pangde: ["male", "qun", 4, ["mashu", "jianchu"]], gz_zhangjiao: ["male", "qun", 3, ["leiji", "guidao"]], gz_caiwenji: ["female", "qun", 3, ["beige", "gzduanchang"]], - gz_mateng: ["male", "qun", 4, ["mashu2", "xiongyi"]], + gz_mateng: ["male", "qun", 4, ["mashu", "xiongyi"]], gz_kongrong: ["male", "qun", 3, ["gzmingshi", "lirang"]], gz_jiling: ["male", "qun", 4, ["shuangren"]], gz_tianfeng: ["male", "qun", 3, ["sijian", "gzsuishi"]], gz_panfeng: ["male", "qun", 4, ["gzkuangfu"], ["gzskin"]], gz_zoushi: ["female", "qun", 3, ["huoshui", "new_qingcheng"]], - - gz_dengai: ["male", "wei", 4, ["tuntian", "ziliang", "gzjixi"], ["gzskin", "die:dengai"]], + + gz_dengai: ["male", "wei", 4, ["tuntian", "ziliang", "gzjixi"], ["gzskin"]], gz_caohong: ["male", "wei", 4, ["fakehuyuan", "heyi"], ["gzskin"]], gz_jiangfei: ["male", "shu", 3, ["shengxi", "gzshoucheng"]], gz_jiangwei: ["male", "shu", 4, ["tiaoxin", "yizhi", "tianfu"], ["gzskin"]], gz_xusheng: ["male", "wu", 4, ["fakeyicheng"], ["gzskin"]], gz_jiangqing: ["male", "wu", 4, ["gzshangyi", "niaoxiang"]], gz_hetaihou: ["female", "qun", 3, ["zhendu", "qiluan"], ["gzskin"]], - + gz_re_lidian: ["male", "wei", 3, ["xunxun", "wangxi"]], gz_zangba: ["male", "wei", 4, ["rehengjiang"]], - gz_madai: ["male", "shu", 4, ["mashu2", "qianxi"], ["gzskin"]], + gz_madai: ["male", "shu", 4, ["mashu", "qianxi"], ["gzskin"]], gz_mifuren: ["female", "shu", 3, ["gzguixiu", "gzcunsi"]], gz_sunce: ["male", "wu", 4, ["jiang", "yingyang", "baka_hunshang"], ["gzskin"]], gz_chendong: ["male", "wu", 4, ["duanxie", "fakefenming"]], gz_sp_dongzhuo: ["male", "qun", 4, ["hengzheng", "fakebaoling"]], gz_zhangren: ["male", "qun", 4, ["chuanxin", "fengshi"]], - + gz_jun_liubei: ["male", "shu", 4, ["zhangwu", "jizhao", "shouyue"]], gz_jun_zhangjiao: ["male", "qun", 4, ["wuxin", "hongfa", "wendao"]], gz_jun_sunquan: ["male", "wu", 4, ["jiahe", "lianzi", "jubao"]], - + gz_liqueguosi: ["male", "qun", 4, ["gzxiongsuan"]], gz_zuoci: ["male", "qun", 3, ["fakeyigui", "fakejihun"], ["gzskin"]], gz_bianfuren: ["female", "wei", 3, ["wanwei", "gzyuejian"]], @@ -430,7 +434,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gz_lvfan: ["male", "wu", 3, ["gzdiaodu", "gzdiancai"]], gz_masu: ["male", "shu", 3, ["gzsanyao", "gzzhiman"], ["gzskin"]], gz_shamoke: ["male", "shu", 4, ["gzjili"], ["gzskin"]], - + gz_lingcao: ["male", "wu", 4, ["fakedujin"]], gz_lifeng: ["male", "shu", 3, ["faketunchu", "fakeshuliang"]], gz_beimihu: ["female", "qun", 3, ["fakeguishu", "fakeyuanyu"]], @@ -447,7 +451,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gz_re_xunchen: ["male", "qun", 3, ["gzfenglve", "gzanyong"]], gz_lvlingqi: ["female", "qun", 4, ["guowu", "gzshenwei", "gzzhuangrong"], ["gzskin"]], gz_dc_yanghu: ["male", "wei", 3, ["gzdeshao", "gzmingfa"]], - + gz_cuimao: ["male", "wei", 3, ["gzzhengbi", "gzfengying"], []], gz_yujin: ["male", "wei", 4, ["gzjieyue"], ["gzskin", "die:yujin.mp3"]], gz_wangping: ["male", "shu", 4, ["jianglue"], ["gzskin"]], @@ -457,7 +461,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gz_yuanshu: ["male", "qun", 4, ["gzweidi", "gzyongsi"], ["gzskin"]], gz_zhangxiu: ["male", "qun", 4, ["gzfudi", "gzcongjian"], ["gzskin"]], gz_jun_caocao: ["male", "wei", 4, ["jianan", "huibian", "gzzongyu"], []], - + gz_jin_zhangchunhua: ["female", "jin", 3, ["gzhuishi", "fakeqingleng"]], gz_jin_simayi: ["male", "jin", 3, ["fakequanbian", "smyyingshi", "fakezhouting"]], gz_jin_wangyuanji: ["female", "jin", 3, ["fakeyanxi", "fakeshiren"]], @@ -476,7 +480,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gz_xuangongzhu: ["female", "jin", 3, ["fakeqimei", "ybzhuiji"]], gz_xinchang: ["male", "jin", 3, ["fakecanmou", "congjian"]], gz_yangzhi: ["female", "jin", 3, ["gzwanyi", "gzmaihuo"]], - + gz_liaohua: ["male", "shu", 4, ["gzdangxian"]], gz_zhugejin: ["male", "wu", 3, ["gzhuanshi", "gzhongyuan", "gzmingzhe"]], gz_yangxiu: ["male", "wei", 3, ["gzdanlao", "gzjilei"]], @@ -487,18 +491,18 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gz_tw_liufuren: ["female", "qun", 3, ["gzzhuidu", "gzshigong"], []], gz_old_huaxiong: ["male", "qun", 4, ["gzyaowu", "gzshiyong"], []], gz_tw_xiahoushang: ["male", "wei", 4, ["gztanfeng"], []], - + gz_xf_huangquan: ["male", "wei", 3, ["gzdianhu", "gzjianji"], ["doublegroup:wei:shu"]], gz_guohuai: ["male", "wei", 4, ["gzduanshi", "gzjingce"], ["gzskin"]], gz_guanqiujian: ["male", "wei", 4, ["gzzhengrong", "gzhongju"], []], gz_zhujun: ["male", "qun", 4, ["gzgongjian", "gzkuimang"], []], gz_chengong: ["male", "qun", 3, ["gzyinpan", "gzxingmou"], ["doublegroup:wei:qun", "gzskin"]], gz_re_xugong: ["male", "wu", 3, ["gzbiaozhao", "gzyechou"], ["doublegroup:wu:qun"]], - + gz_yangwan: ["female", "shu", 3, ["gzyouyan", "gzzhuihuan"], ["gzskin"]], - + gz_key_ushio: ["female", "key", 3, ["ushio_huanxin", "ushio_xilv"], ["doublegroup:key:wei:shu:wu:qun:jin"]], - + gz_wangling: ["male", "wei", 4, ["fakemibei"]], gz_yanyan: ["male", "shu", 4, ["fakejuzhan"]], gz_xin_zhuran: ["male", "wu", 4, ["fakedanshou"]], @@ -659,7 +663,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { .set("_backupevent", "fakeduoshi_backup") .set("custom", { add: {}, - replace: { window: function () {} }, + replace: { window: function () { } }, }) .set("addCount", false) .set("oncard", () => _status.event.directHit.addArray(game.players)) @@ -1793,7 +1797,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { filter: function (event, player) { if (player == event.player || event.targets.length != 1 || event.player.countCards("h") >= event.player.hp) return false; var bool = function (card) { - return (card.name == "sha" || get.type(card, false) == "trick") && get.color(card, false) == "black"; + return (card.name == "sha" || get.type(card, null, false) == "trick") && get.color(card, false) == "black"; }; if (!bool(event.card)) return false; var evt = event.getParent("phaseUse"); @@ -2512,8 +2516,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, async cost(event, trigger, player) { const filterTarget = (card, player, target) => { - return target != player && target.isMaxHandcard(); - }, + return target != player && target.isMaxHandcard(); + }, targetx = game.filterPlayer(current => filterTarget(null, player, current)); if (targetx.length == 1) event.result = { bool: true, targets: targetx }; else @@ -3386,7 +3390,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (gains.length) await player.gain(gains, "gain2"); if ( game.getGlobalHistory("everything", evt => { - return evt.name == "die" && evt.getParent(6).name == "fakezhouting" && evt.getParent(6).player == player; + return evt.name == "die" && evt.getParent(6) == event && evt.getParent(6).player == player; }).length ) player.restoreSkill("fakezhouting"); @@ -3501,7 +3505,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { .set("_backupevent", "fakeqingleng_backup") .set("custom", { add: {}, - replace: { window: function () {} }, + replace: { window: function () { } }, }) .set("targetRequired", true) .set("complexSelect", true) @@ -3545,7 +3549,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, subSkill: { backup: { - filterCard: true, + filterCard(card) { + return get.itemtype(card) == "card"; + }, check(card) { return 7.5 - get.value(card); }, @@ -4439,14 +4445,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { typeof yingbianZhuzhanAI == "function" ? yingbianZhuzhanAI(player, card, source, targets) : cardx => { - var info = get.info(card); - if (info && info.ai && info.ai.yingbian) { - var ai = info.ai.yingbian(card, source, targets, player); - if (!ai) return 0; - return ai - get.value(cardx); - } else if (get.attitude(player, source) <= 0) return 0; - return 5 - get.value(cardx); - }, + var info = get.info(card); + if (info && info.ai && info.ai.yingbian) { + var ai = info.ai.yingbian(card, source, targets, player); + if (!ai) return 0; + return ai - get.value(cardx); + } else if (get.attitude(player, source) <= 0) return 0; + return 5 - get.value(cardx); + }, }); if (!game.online) return; _status.event._resultid = id; @@ -6910,12 +6916,12 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.countPlayer(function (current) { return !trigger.targets.includes(current) && lib.filter.filterTarget(trigger.card, trigger.player, current) && get.effect(current, trigger.card, trigger.player, player) > 0; }) >= - Math.min( - 2, - game.countPlayer(function (current) { - return !trigger.targets.includes(current) && lib.filter.filterTarget(trigger.card, trigger.player, current); - }) - ) + Math.min( + 2, + game.countPlayer(function (current) { + return !trigger.targets.includes(current) && lib.filter.filterTarget(trigger.card, trigger.player, current); + }) + ) ) .setHiddenSkill("gzzhaosong_sha"); ("step 1"); @@ -7189,7 +7195,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (player.checkMainSkill("gzpozhu")) player.removeMaxHp(); }, viewAsFilter(player) { - return !player.hasSkill("pozhu3", null, null, false) && player.countMark("gzsanchen") > 0 && player.countCards("hs") > 0; + return player.countMark("gzsanchen") > 0 && player.countCards("hs") > 0; }, viewAs: { name: "chuqibuyi" }, filterCard: true, @@ -7400,9 +7406,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { player.getHistory("useCard", function (evt) { return evt != event && get.suit(evt.card) == suit && lib.skill.quanbian.hasHand(evt) && evt.getParent("phaseUse") == phase; }).length + - player.getHistory("respond", function (evt) { - return evt != event && get.suit(evt.card) == suit && lib.skill.quanbian.hasHand(evt) && evt.getParent("phaseUse") == phase; - }).length == + player.getHistory("respond", function (evt) { + return evt != event && get.suit(evt.card) == suit && lib.skill.quanbian.hasHand(evt) && evt.getParent("phaseUse") == phase; + }).length == 0 ); }, @@ -7584,7 +7590,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if ( list.includes("trick") && source.countCards("h", function (card) { - return get.type(card, source) == "trick" && source.hasValueTarget(card); + return get.type(card, null, source) == "trick" && source.hasValueTarget(card); }) > 1 ) return "trick"; @@ -9031,7 +9037,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.countPlayer(function (current) { return get.attitude(current, player) <= 0; }) > - game.countPlayer() / 2 + game.countPlayer() / 2 ); }, preHidden: true, @@ -9227,9 +9233,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var player = _status.event.player; return ( (target.identity != "unknown" && - !game.hasPlayer(function (current) { - return current != target && current.isFriendOf(target) && current.isLinked(); - }) + !game.hasPlayer(function (current) { + return current != target && current.isFriendOf(target) && current.isLinked(); + }) ? 3 : 1) * (-get.attitude(target, player, player) + 1) @@ -9693,7 +9699,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, ai: { - order: 4, + order: (item, player) => { + if (game.hasPlayer(cur => { + if (player === cur || get.attitude(player, cur) <= 0) return false; + return Math.min(5, target.maxHp) - cur.countCards("h") > 2; + })) return get.order({ name: "nanman" }, player) - 0.1; + return 10; + }, result: { target: function (player, target) { if (get.attitude(player, target) > 0) return Math.min(5, target.maxHp - target.countCards("h")); @@ -11090,7 +11102,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { preHidden: true, trigger: { target: "useCardToTargeted" }, filter: function (event, player) { - if (player == event.player || event.targets.length != 1) return false; + if (player == event.player || event.targets.length != 1 || !event.player.isIn()) return false; var hs = player.getCards("h"); if (hs.length == 0) return false; for (var i of hs) { @@ -11409,8 +11421,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ai: { threaten: 3, effect: { - target: function (card, player, target, current) { - if (lib.skill.gzxingzhao.getNum() > 3 && get.type(card) == "equip" && !get.cardtag(card, "gifts")) return [1, 3]; + target_use: function (card, player, target, current) { + if (lib.skill.gzxingzhao.getNum() > 3 && get.type(card) == "equip" && !get.cardtag(card, "gifts")) return [1, 2]; }, }, reverseEquip: true, @@ -11827,7 +11839,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { dialog.content.appendChild(table2); dialog.add("  "); event.dialog.open(); - + event.switchToAuto = function () { event._result = { bool: true, @@ -12025,7 +12037,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } }, }, - + yigui: { audio: 2, hiddenCard: function (player, name) { @@ -13136,7 +13148,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { player.addTempSkill(link, "jiananUpdate"); player.addTempSkill("jianan_eff", "jiananUpdate"); game.log(player, "获得了技能", "#g【" + get.translation(result.control) + "】"); - + // 语音修复 var map = { new_retuxi: "jianan_tuxi", @@ -13300,7 +13312,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + gzzhengbi: { audio: "zhengbi", trigger: { player: "phaseUseBegin" }, @@ -13542,7 +13554,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + junling4_eff: { mod: { cardEnabled2: function (card) { @@ -13577,7 +13589,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + gzjieyue: { trigger: { player: "phaseZhunbeiBegin" }, filter: function (event, player) { @@ -13604,8 +13616,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (get.attitude(player, target) > 0) return 11 - get.value(card); return 7 - get.value(card); }, - ai2: function (card, player, target) { - var att = get.attitude(player, target); + ai2: function (target) { + var att = get.attitude(get.event().player, target); if (att < 0) return -att; return 1; }, @@ -13656,7 +13668,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { audio: ["jieyue", 2], audioname2: { gz_jun_caocao: "jianan_jieyue" }, }, - + jianglue: { limited: true, audio: 2, @@ -13815,16 +13827,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { position: "h", filterCard: true, check: function (card) { - var player = _status.event.player; - if (player.hasSkill("gzpaoxiao", true) || player.getEquip("zhuge")) return 0; - if ( - player.countCards("h", function (cardx) { + let player = _status.event.player, + shas = player.countCards("h", cardx => { return cardx != card && cardx.name == "sha" && player.hasUseTarget(cardx); - }) < - player.getCardUsable("sha") + 1 - ) - return 0; - return 7 - get.value(card); + }), + count = player.getCardUsable("sha"), + val = (get.name(card) == "sha" ? 2 : 1) * get.value(card); + if (!shas || count - shas > 1) return (player.needsToDiscard() ? 7 : 1) - val; + return 7 - val; }, content: function () { "step 0"; @@ -13832,9 +13842,18 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { player .chooseControl(list) .set("ai", function () { - if (list.includes("gzpaoxiao")) return "gzpaoxiao"; - return list.randomGet(); + let res = get.event().res; + if (list.includes(res)) return res; + return 0; }) + .set("res", function () { + let shas = player.mayHaveSha(player, "use", null, "count"), + count = player.getCardUsable("sha"); + if (shas > count) return "gzpaoxiao"; + if (shas < count) return "new_rewusheng"; + if (!shas) return "xinkuanggu"; + return ["new_longdan", "new_tieji", "liegong"].randomGet(); //脑子不够用了 + }()) .set("prompt", "选择并获得一项技能直到回合结束"); ("step 1"); player.popup(result.control); @@ -13880,6 +13899,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { fz_xinkuanggu: { audio: true, inherit: "xinkuanggu", + global: "_xinkuanggu_check", }, fz_new_longdan: { audio: true, @@ -14072,7 +14092,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + gzjushou: { audio: "xinjushou", trigger: { @@ -14116,13 +14136,6 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } } }, - ai: { - effect: { - target: function (card, player, target) { - if (card.name == "guiyoujie") return [0, 1]; - }, - }, - }, }, new_duanliang: { subSkill: { @@ -15042,19 +15055,19 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { return player != target; }) .setHiddenSkill("gzfangzhu").ai = function (target) { - if (target.hasSkillTag("noturn")) return 0; - var player = _status.event.player, - att = get.attitude(player, target); - if (att == 0) return 0; - if (att > 0) { - if (target.isTurnedOver()) return 1000 - target.countCards("h"); - return -1; - } else { - if (target.isTurnedOver()) return -1; - if (player.getDamagedHp() >= 3) return -1; - return target.countCards("h") + 1; - } - }; + if (target.hasSkillTag("noturn")) return 0; + var player = _status.event.player, + att = get.attitude(player, target); + if (att == 0) return 0; + if (att > 0) { + if (target.isTurnedOver()) return 1000 - target.countCards("h"); + return -1; + } else { + if (target.isTurnedOver()) return -1; + if (player.getDamagedHp() >= 3) return -1; + return target.countCards("h") + 1; + } + }; ("step 1"); if (result.bool) { var target = result.targets[0]; @@ -16206,7 +16219,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }; var skills = map[result.control]; player.addTempSkills(skills); - + // 语音修复 if (skills == "fakeduoshi") { var mapSkills = "jiahe_duoshi"; @@ -16221,7 +16234,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { subSkillInfo.audioname2[player.name2] = mapSkills; }, skills); } - + if (!event.done) player.logSkill("jiahe_put"); // game.log(player,'获得了技能','【'+get.translation(skill)+'】'); if (event.num >= 5 && !event.done) { @@ -18128,7 +18141,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, effect: { - target: function (card, player, target) { + target_use: function (card, player, target) { if (player == target && get.type(card) == "equip") { if (player.countCards("e", { subtype: get.subtype(card) })) { var players = game.filterPlayer(); @@ -18257,7 +18270,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var to = event.junzhu_name; event.maxHp = player.maxHp; player.reinit(player.name1, to, 4); - + // 修改君主亮将配音播放 var map = { gz_jun_liubei: "shouyue", @@ -18266,7 +18279,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gz_jun_caocao: "jianan", }; game.trySkillAudio(map[to], player); - + player.showCharacter(0); var group = lib.character[to][1]; var yelist = game.filterPlayer(function (current) { @@ -18913,9 +18926,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var str = get.translation(game.me.name1) + "/" + get.translation(game.me.name2); var str2 = _status.separatism ? get.modetrans({ - mode: lib.config.mode, - separatism: true, - }) + mode: lib.config.mode, + separatism: true, + }) : get.cnNumber(parseInt(get.config("player_number"))) + "人" + get.translation(lib.config.mode); if (game.me.identity == "ye") { str2 += " - 野心家"; @@ -19109,7 +19122,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { seats.previousSibling.style.display = "none"; seats.style.display = "none"; } - + dialog.add(ui.create.div(".placeholder.add-setting")); dialog.add(ui.create.div(".placeholder.add-setting")); if (get.is.phoneLayout()) dialog.add(ui.create.div(".placeholder.add-setting")); @@ -19128,11 +19141,11 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }; event.addSetting = addSetting; event.removeSetting = removeSetting; - + var chosen = lib.config.continue_name || []; game.saveConfig("continue_name"); event.chosen = chosen; - + var i; event.list = []; for (i in lib.character) { @@ -19641,6 +19654,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.players[i].identity = "unknown"; game.players[i].node.name.show(); game.players[i].node.name2.show(); + for (var j = 0; j < game.players[i].hiddenSkills.length; j++) { + game.players[i].addSkillTrigger(game.players[i].hiddenSkills[j], true); + } } setTimeout(function () { ui.arena.classList.remove("choose-character"); @@ -19714,7 +19730,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ye: "野", ye2: "野心家", yexinjia_mark: "野心家", - + bumingzhi: "不明置", mingzhizhujiang: "明置主将", mingzhifujiang: "明置副将", @@ -19722,7 +19738,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { mode_guozhan_character_config: "国战武将", _zhenfazhaohuan: "阵法召唤", _zhenfazhaohuan_info: "由拥有阵法技的角色发起,满足此阵法技条件的未确定势力角色均可按逆时针顺序依次明置其一张武将牌(响应阵法召唤),以发挥阵法技的效果。", - + junling: "军令", junling1: "军令一", junling1_bg: "令", @@ -19744,7 +19760,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { junling6: "军令六", junling6_bg: "令", junling6_info: "若被执行,执行者选择一张手牌和一张装备区内牌(若有),然后弃置其余的牌。", - + gz_miheng: "祢衡", gzshensu: "神速", gzshensu_info: "①判定阶段开始时,你可跳过此阶段和摸牌阶段,视为使用一张【杀】(无距离限制)。②出牌阶段开始时,你可跳过此阶段并弃置一张装备牌,视为使用一张【杀】(无距离限制)。③弃牌开始时,你可跳过此阶段并失去1点体力,视为使用一张【杀】(无距离限制)。", @@ -19762,7 +19778,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gzluoyi_info: "摸牌阶段结束时,你可弃置一张牌,然后你于本回合内造成渠道为【杀】或【决斗】的伤害+1。", gzqiangxi: "强袭", gzqiangxi_info: "出牌阶段限一次,你可以弃置一张武器牌或失去1点体力,然后对一名其他角色造成1点伤害。", - + gz_sp_duyu: "杜预", gzpozhen: "破阵", gzpozhen_info: "限定技,其他角色的回合开始时,你可以令其本回合不可使用、打出或重铸手牌;若其处于队列或围攻关系中,你可依次弃置此队列或参与围攻关系的其他角色的一张牌。", @@ -19773,7 +19789,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gzzhuosheng: "擢升", gzzhuosheng2: "擢升", gzzhuosheng_info: "当一名与你势力相同的角色受到伤害后,你可令其摸一张牌。然后直到其下个结束阶段前,其使用此牌根据类型执行以下效果:1. 基本牌,不计入次数且无距离限制;2. 普通锦囊牌,此牌目标可+1或-1;3. 装备牌,可摸一张牌。", - + gzzhaoxin: "昭心", gzzhaoxin_info: "当你受到伤害后,你可展示所有手牌,然后与一名手牌数不大于你的其他角色交换手牌。", gzsuzhi: "夙智", @@ -19782,7 +19798,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gzhuaiyi_info: "出牌阶段限一次,你可以展示所有手牌。若其中包含两种颜色,则你可以弃置其中一种颜色的所有牌,然后获得至多等量名角色的各一张牌。然后你将以此法得到的装备牌置于武将牌上,称为“异”。", gzzisui: "恣睢", gzzisui_info: "锁定技,摸牌阶段,你多摸X张牌。结束阶段,若X大于你的体力上限,你死亡(X为“异”数)。", - + gz_tangzi: "唐咨", gz_mengda: "孟达", gz_liuqi: "刘琦", @@ -19916,7 +19932,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gzmingfa_info: "出牌阶段限一次,你可以选择一名敌方角色。该角色的下个回合结束时,若其手牌数:小于你,你对其造成1点伤害并获得其一张手牌;大于你,你摸X张牌(X为你与其的手牌数之差且至多为5)。", gzjilei_info: "当你受到有来源的伤害后,你可以声明一种牌的类别。若如此做,你令伤害来源不能使用、打出或弃置此类别的手牌直到回合结束。", gzdanlao_info: "当你成为普通锦囊牌的目标后,若此牌的目标数大于1,则你可以摸一张牌,令此牌对你无效。", - + gz_cuimao: "崔琰毛玠", gzzhengbi: "征辟", gzzhengbi_info: "出牌阶段开始时,你可以选择一项:选择一名未确定势力的角色,此出牌阶段结束时,若其有明置的武将牌,则你获得其每个区域内的各一张牌;或将一张基本牌交给一名有明置武将牌的角色,然后其交给你一张非基本牌或两张基本牌。", @@ -19965,7 +19981,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { huibian_info: "出牌阶段限一次,你可以选择一名魏势力角色和另一名已受伤的魏势力角色。若如此做,你对前者造成1点伤害,然后其摸两张牌,然后后者回复1点体力。", gzzongyu: "总御", gzzongyu_info: "当【六龙骖驾】进入其他角色的装备区后,你可以将你装备区内所有坐骑牌(至少一张)与【六龙骖驾】交换位置。锁定技,当你使用坐骑牌后,若场上或弃牌堆中有【六龙骖驾】,则将【六龙骖驾】置入你的装备区。", - + yigui: "役鬼", yigui_info: "当你首次明置此武将牌时,你将剩余武将牌堆的两张牌置于武将牌上,称为“魂”;你可以展示一张武将牌上的“魂”并将其置入剩余武将牌堆,视为使用一张本回合内未以此法使用过的基本牌或普通锦囊牌。(此牌须指定目标,且目标须为未确定势力的角色或野心家或与此“魂”势力相同的角色)", yigui_init: "役鬼", @@ -19978,7 +19994,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { yigui_gzwuxie: "役鬼", jihun: "汲魂", jihun_info: "当你受到伤害后,或与你势力不同的角色脱离濒死状态后,你可以将剩余武将牌堆的一张牌置于武将牌上,称为“魂”。", - + _guozhan_marks: "标记", _guozhan_marks_backup: "标记", xianqu_mark: "先驱", @@ -19987,7 +20003,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _zhulianbihe_mark_tao: "珠联", _yinyang_mark_add: "阴阳鱼", yinyang_add: "阴阳鱼", - + gzjushou: "据守", gzjushou_info: "结束阶段,你可以摸X张牌(X为亮明势力数),然后弃置一张手牌。若以此法弃置的牌为装备牌,则改为使用此牌。若X大于2,则你将武将牌叠置。", new_duanliang: "断粮", @@ -20044,7 +20060,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { hmkguishu_info: "出牌阶段,你可以将一张黑桃手牌当作【知己知彼】或【远交近攻】使用。若你本局游戏内已经发动过了〖鬼术〗,则你必须选择与上次不同的选项。", _mingzhisuodingji: "亮将", _mingzhisuodingji_info: "出牌阶段,你可以明置拥有“锁定技”的武将牌。", - + gz_jun_liubei: "君刘备", gz_jun_liubei_prefix: "君", gz_jun_zhangjiao: "君张角", @@ -20057,7 +20073,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gz_shamoke: "沙摩柯", gz_masu: "马谡", gz_yuji: "于吉", - + gzshushen: "淑慎", gzshushen_info: "当你回复1点体力时,你可令与你势力相同的一名其他角色摸一张牌。", _lianheng: "合纵", @@ -20069,7 +20085,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gzsanyao_info: "出牌阶段限一次。你可以弃置一张牌,对一名手牌数或体力值大于你的角色造成1点伤害。", gzzhiman: "制蛮", gzzhiman_info: "当你对其他角色造成伤害时,你可以防止此伤害。若如此做,你获得其装备区或判定区里的一张牌。然后若该角色与你势力相同,该角色可以变更副将。", - + gzdiancai: "典财", gzdiancai_info: "其他角色的出牌阶段结束时,若你于此阶段失去了x张或更多的牌,则你可以将手牌摸至体力上限。若如此做,你可以变更副将(x为你的体力值)。", xuanlve: "旋略", @@ -20087,7 +20103,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gzhuashen_info: "准备阶段,若你的“化身”不足两张,则你可以观看剩余武将牌堆中的五张牌,然后扣置其中至多两张武将牌在你的武将旁,称为“化身”;若“化身”有两张以上,则你可以用剩余武将牌堆顶的一张牌替换一张“化身”。你可以于相应的时机明置并发动“化身”的一个技能,技能结算完成后将该“化身”放回剩余武将牌堆。你每个时机只能发动一张“化身”的技能,且不能发动带有技能类型的技能(锁定技、限定技等)。", gzxinsheng: "新生", gzxinsheng_info: "当你受到伤害后,你可以从剩余武将牌堆中扣置一张牌加入到“化身”牌中。", - + jubao: "聚宝", jubao_info: "锁定技,你装备区里的宝物牌不能被其他角色获得。结束阶段,若场上或弃牌堆有【定澜夜明珠】,则你摸一张牌,然后获得装备区里有【定澜夜明珠】角色的一张牌。", jiahe: "嘉禾", @@ -20203,7 +20219,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { duoshi_info: "出牌阶段限四次,你可以将一张红色手牌当做【以逸待劳】使用。", gzxiaoguo: "骁果", gzxiaoguo_info: "其他角色的结束阶段,你可以弃置一张基本牌,令该角色选择一项:1.弃置一张装备牌;2.受到你对其造成的1点伤害。", - + gzdangxian: "当先", gzdangxian_info: "锁定技。当你首次明置此武将牌时,你获得一枚“先驱”标记。回合开始时,你获得一个额外的出牌阶段。", gzhuanshi: "缓释", @@ -20325,14 +20341,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { gzrejinghe_info: "出牌阶段限一次,你可以转动“天书”,然后令一名角色获得“天书”向上一面的技能直到你的下个回合开始。", gzrejinghe_faq: "转动“天书”", gzrejinghe_faq_info: "
  • 若游戏未拥有“天书”,系统将[雷击,阴兵,活气,鬼助,仙授,论道,观月,言政]以顺时针方向组成圆环作为“天书”,并转动圆环将随机一个技能至于最上面。
  • 若游戏已拥有“天书”,则以逆时针方向转动转动“天书”至下个技能于最上面。", - + gz_key_ushio: "冈崎汐", ushio_huanxin: "幻心", ushio_huanxin_info: "当你受到伤害后/使用【杀】造成伤害后/使用装备牌后,你可进行判定。然后你获得判定牌并弃置一张牌。", ushio_xilv: "汐旅", ushio_xilv2: "汐旅", ushio_xilv_info: "锁定技,此武将牌可作为任意单势力武将牌的副将。当你进行判定后,你令你的手牌上限+1直至你的下个结束阶段。", - + //官盗2023 fakexiaoguo: "骁果", fakexiaoguo_info: "一名其他角色的准备阶段,你可以弃置任意张基本牌,然后弃置其装备区等量的牌,若其装备区的牌数小于你弃置的牌数,则你对其造成1点伤害。", @@ -20465,7 +20481,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { fakehuyuan_info: "①你的回合内,当一张装备牌进入一名角色的装备区后,你可以弃置与其距离为1以内的另一名角色区域里的一张牌。②结束阶段,你可以将一张装备牌置入一名角色的装备区。", fakekeshou: "恪守", fakekeshou_info: "①当你受到伤害时,你可以弃置两张颜色相同的牌并令此伤害-1。②当你因弃置而一次性失去至少两张牌后,若你的势力已确定且场上没有与你势力相同的其他角色,则你可以进行判定,若结果判定为红色,你摸一张牌。", - + guozhan_default: "国战标准", guozhan_zhen: "君临天下·阵", guozhan_shi: "君临天下·势", @@ -20482,7 +20498,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { guozhan_qunxiong: "群雄割据", guozhan_decade: "十年踪迹十年心", guozhan_others: "其他", - + // 台词部分 "#gz_zhonghui:die": "吾机关算尽,却还是棋错一着……", "#gzzhaoxin1": "行明动正,何惧他人讥毁。", @@ -20671,13 +20687,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "#qingcheng1": "我和你们真是投缘啊。", "#qingcheng2": "哼,眼睛都直了呀。", "#gz_zoushi:die": "年老色衰了吗?", - "#tuntian_gz_dengai1": "击鼓于此,以致四方。", + "#tuntian_gz_dengai1": "积谷于此,以制四方。", "#tuntian_gz_dengai2": "留得良田在,何愁不破敌?", "#ziliang1": "吃饱了,才有力气为国效力。", "#ziliang2": "兵,断不可无粮啊。", "#jixi_gz_dengai1": "哪里走!!", "#jixi_gz_dengai2": "谁占到先机,谁就胜了。", - "#gz_dengai:die": "吾破蜀克敌,竟葬于奸贼之手!", + "#gz_dengai:die": "君不知臣,臣不知君,罢了……罢了……", "#gz_caohong:die": "福兮祸所伏……", "#gz_jiangfei:die": "墨守成规,终为其害啊……", "#tiaoxin_gz_jiangwei1": "小小娃娃,乳臭未干。", @@ -21059,7 +21075,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["spade", 12, "tiesuo"], ["spade", 13, "nanman"], ["spade", 13, "dawan"], - + ["club", 1, "juedou"], ["club", 1, "baiyin"], ["club", 2, "sha"], @@ -21087,7 +21103,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["club", 12, "tiesuo"], ["club", 13, "wuxie", null, ["guo"]], ["club", 13, "tiesuo"], - + ["diamond", 1, "zhuge"], ["diamond", 1, "zhuque"], ["diamond", 2, "shan"], @@ -21115,7 +21131,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["diamond", 12, "wuxie", null, ["guo"]], ["diamond", 13, "shan"], ["diamond", 13, "zixin"], - + ["heart", 1, "taoyuan"], ["heart", 1, "wanjian"], ["heart", 2, "shan"], @@ -21172,7 +21188,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["spade", 12, "tiesuo"], ["spade", 13, "nanman"], ["spade", 13, "dawan"], - + ["club", 1, "juedou"], ["club", 1, "baiyin"], ["club", 2, "sha"], @@ -21200,7 +21216,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["club", 12, "tiesuo"], ["club", 13, "wuxie", null, ["guo"]], ["club", 13, "tiesuo"], - + ["diamond", 1, "zhuge"], ["diamond", 1, "zhuque"], ["diamond", 2, "shan"], @@ -21228,7 +21244,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["diamond", 12, "wuxie", null, ["guo"]], ["diamond", 13, "shan"], ["diamond", 13, "zixin"], - + ["heart", 1, "taoyuan"], ["heart", 1, "wanjian"], ["heart", 2, "shan"], @@ -21257,7 +21273,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["heart", 12, "guohe"], ["heart", 13, "shan"], ["heart", 13, "zhuahuang"], - + ["spade", 1, "xietianzi", null, ["lianheng"]], ["spade", 2, "minguangkai"], ["spade", 3, "huoshaolianying", null, ["lianheng"]], @@ -21271,7 +21287,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["spade", 11, "sha", "thunder", ["lianheng"]], ["spade", 12, "lulitongxin"], ["spade", 13, "wuxie"], - + ["heart", 1, "lianjunshengyan"], ["heart", 2, "diaohulishan"], ["heart", 3, "jingfanma", null, ["lianheng"]], @@ -21285,7 +21301,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["heart", 11, "sha"], ["heart", 12, "huoshaolianying", null, ["lianheng"]], ["heart", 13, "shuiyanqijunx"], - + ["club", 1, "yuxi"], ["club", 2, "huxinjing", null, ["lianheng"]], ["club", 3, "chiling"], @@ -21299,7 +21315,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["club", 11, "huoshaolianying", null, ["lianheng"]], ["club", 12, "shuiyanqijunx"], ["club", 13, "wuxie", null, ["guo"]], - + ["diamond", 1, "xietianzi", null, ["lianheng"]], ["diamond", 2, "tao"], ["diamond", 3, "tao", null, ["lianheng"]], @@ -21313,10 +21329,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["diamond", 11, "wuxie", null, ["guo"]], ["diamond", 12, "fangtian"], ["diamond", 13, "shan"], - + ["diamond", 6, "dinglanyemingzhu"], ["heart", 13, "liulongcanjia"], - + //['spade',12,'gz_haolingtianxia'], //['diamond',1,'gz_kefuzhongyuan'], //['heart',1,'gz_guguoanbang'], @@ -21523,6 +21539,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { for (var i = 0; i < _status.characterlist.length; i++) { var goon = false, group2 = lib.character[_status.characterlist[i]][1]; + if (game.hasPlayer2(current => get.nameList(current).includes(_status.characterlist[i]))) continue; if (group == "ye") { if (group2 != "ye") goon = true; } else { @@ -21570,6 +21587,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { event.tochange = []; for (var i = 0; i < _status.characterlist.length; i++) { if (_status.characterlist[i].indexOf("gz_jun_") == 0) continue; + if (game.hasPlayer2(current => get.nameList(current).includes(_status.characterlist[i]))) continue; var goon = false, group2 = lib.character[_status.characterlist[i]][1]; if (group == "ye") { @@ -21764,21 +21782,21 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { delete source.shijun2; source.draw( 1 + - game.countPlayer(function (current) { - return current.group == that.group; - }) + game.countPlayer(function (current) { + return current.group == that.group; + }) ); } else if (that.identity == "ye") { if (that.getStorage("yexinjia_friend").includes(source) || source.getStorage("yexinjia_friend").includes(that)) source.discard(source.getCards("he")); else source.draw( 1 + - game.countPlayer(function (current) { - if (current == that) return false; - if (current.getStorage("yexinjia_friend").includes(that)) return true; - if (that.getStorage("yexinjia_friend").includes(current)) return true; - return false; - }) + game.countPlayer(function (current) { + if (current == that) return false; + if (current.getStorage("yexinjia_friend").includes(that)) return true; + if (that.getStorage("yexinjia_friend").includes(current)) return true; + return false; + }) ); } else if (that.identity != source.identity) source.draw(get.population(that.identity) + 1); else source.discard(source.getCards("he")); @@ -21948,7 +21966,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { this.setIdentity(this.identity); this.ai.shown = 1; this.node.identity.classList.remove("guessing"); - + if (_status.clickingidentity && _status.clickingidentity[0] == this) { for (var i = 0; i < _status.clickingidentity[1].length; i++) { _status.clickingidentity[1][i].delete(); @@ -22344,7 +22362,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { return current.isFriendOf(to); }); if (to.identity == "ye") to_p += 1.5; - + if (to_p >= max) return -5; if (from_p >= max) return -2 - to_p; if (max >= game.players.length / 2) { @@ -22380,7 +22398,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { return att; } if (to.ai.shown >= 0.5) return att * to.ai.shown; - + var nshown = 0; for (var i = 0; i < game.players.length; i++) { if (game.players[i] != from && game.players[i].identity == "unknown") { @@ -22419,5 +22437,5 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "
  • 当场上触发了胜利条件时,若这些角色中存在未明置过主将的野心家角色,则这些野心家角色选择是否“暴露野心”。若无人选择“是”且场上存在非野心家角色存活,则所有非野心家角色胜利,野心家角色失败。若有人选择“是”,则这些角色明置主将,然后选择是否发起“拉拢人心”。
  • 选择发起“拉拢人心”的野心家角色选择一个新的势力作为自己的势力,弃置“野心家”标记,令所有其他非野心家角色且非君主且非已“结盟”角色依次选择是否和该野心家角色“结盟”。选择“是”的角色将势力改为和该野心家势力相同。此次“拉拢人心”对所有其他角色询问结束后,所有选择“否”的角色将手牌摸至四张并回复1点体力。" + '
    纵横捭阖
    ', }, - }; -}); + } +} diff --git a/mode/identity.js b/mode/identity.js index 0bddb22fad..9134c7eda6 100644 --- a/mode/identity.js +++ b/mode/identity.js @@ -1,8 +1,12 @@ -"use strict"; -game.import("mode", function (lib, game, ui, get, ai, _status) { +import { lib, game, ui, get, ai, _status } from '../noname.js'; +export const type = 'mode'; +/** + * @type { () => importModeConfig } + */ +export default () => { return { name: "identity", - start: function () { + start() { "step 0"; if (!lib.config.new_tutorial) { ui.arena.classList.add("only_dialog"); @@ -320,7 +324,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { beginner = game.players[Math.floor(Math.random() * game.players.length)]; } event.beginner = beginner; - + var stratagemBroadcast = () => { _status.stratagemFuryMax = 3; ui.css.stratagemCardStyle = lib.init.sheet( @@ -429,7 +433,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } game.syncState(); event.trigger("gameStart"); - + var players = get.players(lib.sort.position); var info = []; for (var i = 0; i < players.length; i++) { @@ -1135,7 +1139,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } } }, result); - + var list = []; var players = game.players.slice(0); players.removeArray([game.rZhu, game.bZhu]); @@ -1373,11 +1377,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } game.players[i].identityShown = false; } - - game.zhu.isZhu = game.zhu.identity == "zhu"; + game.me.setIdentity(); game.me.node.identity.classList.remove("guessing"); - + for (var i = 0; i < game.players.length; i++) { game.players[i].send( function (zhu, zhuid, me, identity) { @@ -1387,7 +1390,6 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } zhu.identity = zhuid; if (zhuid == "zhu") zhu.isZhu = true; - me.setIdentity(identity); me.node.identity.classList.remove("guessing"); ui.arena.classList.add("choose-character"); }, @@ -1397,13 +1399,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.players[i].identity ); } - + var list; var list3 = []; var list4 = []; event.list = []; event.list2 = []; - + var libCharacter = {}; for (var i = 0; i < lib.configOL.characterPack.length; i++) { var pack = lib.characterPack[lib.configOL.characterPack[i]]; @@ -1445,7 +1447,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "step 1"; var list = []; var selectButton = lib.configOL.double_character ? 2 : 1; - + var num, num2 = 0; num = Math.floor(event.list.length / (game.players.length - 1)); @@ -1571,7 +1573,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { result2, result ); - + for (var i in result2) { if (!lib.playerOL[i].name) { lib.playerOL[i].init(result2[i][0], result2[i][1]); @@ -1579,13 +1581,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (result[i] && result[i].length) lib.playerOL[i].changeGroup(result[i], false, false); } - + for (var i = 0; i < game.players.length; i++) { _status.characterlist.remove(game.players[i].name); _status.characterlist.remove(game.players[i].name1); _status.characterlist.remove(game.players[i].name2); } - + ["stratagem_gain", "stratagem_insight", "stratagem_expose"].forEach((globalSkill) => game.addGlobalSkill(globalSkill) ); @@ -1594,7 +1596,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { current.storage.stratagem_expose = []; current.markSkill("stratagem_fury"); }); - + setTimeout(function () { ui.arena.classList.remove("choose-character"); }, 500); @@ -1815,7 +1817,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { listi = ["random", "zhu", "zhong", "fan", "nei"]; if (get.config("enable_commoner") && !event.stratagemMode) listi.push("commoner"); } - + for (var i = 0; i < listi.length; i++) { var td = ui.create.div(".shadowed.reduce_radius.pointerdiv.tdnode"); td.link = listi[i]; @@ -1911,7 +1913,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }); } dialog.content.appendChild(table); - + dialog.add("选择座位").classList.add("add-setting"); var seats = document.createElement("div"); seats.classList.add("add-setting"); @@ -1960,7 +1962,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { seats.previousSibling.style.display = "none"; seats.style.display = "none"; } - + dialog.add(ui.create.div(".placeholder.add-setting")); dialog.add(ui.create.div(".placeholder.add-setting")); if (get.is.phoneLayout()) dialog.add(ui.create.div(".placeholder.add-setting")); @@ -2037,7 +2039,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.players[i].identityShown = false; } } - + if ( get.config("special_identity") && !event.zhongmode && @@ -2073,15 +2075,15 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } } } - + if (!game.zhu) game.zhu = game.me; else { if (!stratagemMode) { game.zhu.setIdentity(); + game.zhu.isZhu = game.zhu.identity == "zhu"; game.zhu.identityShown = true; game.zhu.node.identity.classList.remove("guessing"); } - game.zhu.isZhu = game.zhu.identity == "zhu"; game.me.setIdentity(); game.me.node.identity.classList.remove("guessing"); } @@ -2300,7 +2302,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } else { event.dialogxx = ui.create.characterDialog("heightset"); } - + ui.create.cheat2 = function () { ui.cheat2 = ui.create.control("自由选将", function () { if (this.dialog == _status.event.dialog) { @@ -2431,7 +2433,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { setTimeout(function () { ui.arena.classList.remove("choose-character"); }, 500); - + if (event.special_identity) { for (var i = 0; i < event.special_identity.length; i++) { game.zhu.addSkill(event.special_identity[i]); @@ -2509,7 +2511,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ); event.special_identity = map; } - + game.zhu.setIdentity(); game.zhu.identityShown = true; game.zhu.isZhu = game.zhu.identity == "zhu"; @@ -2521,7 +2523,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.me.special_identity + "_bg" ); } - + for (var i = 0; i < game.players.length; i++) { game.players[i].send( function (zhu, zhuid, me, identity) { @@ -2549,14 +2551,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.players[i].identity ); } - + var list; var list2 = []; var list3 = []; var list4 = []; event.list = []; event.list2 = []; - + var libCharacter = {}; for (var i = 0; i < lib.configOL.characterPack.length; i++) { var pack = lib.characterPack[lib.configOL.characterPack[i]]; @@ -2650,7 +2652,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { event.list.remove(get.sourceCharacter(game.zhu.name2)); event.list2.remove(get.sourceCharacter(game.zhu.name1)); event.list2.remove(get.sourceCharacter(game.zhu.name2)); - + if (game.players.length > 4) { if (!game.zhu.isInitFilter("noZhuHp")) { game.zhu.maxHp++; @@ -2676,7 +2678,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { result.links[1], game.players.length > 4 ); - + if (game.zhu.group == "shen" && !game.zhu.isUnseen(0)) { var list = ["wei", "shu", "wu", "qun", "jin", "key"]; for (var i = 0; i < list.length; i++) { @@ -2707,7 +2709,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "step 3"; var list = []; var selectButton = lib.configOL.double_character ? 2 : 1; - + var num, num2 = 0; if (event.zhongmode) { @@ -2904,7 +2906,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { result2, result ); - + for (var i in result2) { if (!lib.playerOL[i].name) { lib.playerOL[i].init(result2[i][0], result2[i][1]); @@ -2912,7 +2914,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (result[i] && result[i].length) lib.playerOL[i].changeGroup(result[i], false, false); } - + if (event.special_identity) { for (var i in event.special_identity) { game.zhu.addSkill(i); @@ -3200,7 +3202,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.delay(2); game.zhu.playerfocus(1000); } - + if (!_status.over) { var giveup; if (get.population("fan") + get.population("nei") == 1) { @@ -3284,7 +3286,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (this.ai.shown < -0.5) this.ai.shown = -0.5; if (_status.mode == "purple") return; if (stratagemMode) return; - + var marknow = !_status.connectMode && this != game.me && @@ -4694,7 +4696,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.cardsGotoOrdering(cards); var next = player.chooseToMove(); next.set("list", [["牌堆顶", cards], ["牌堆底"]]); - next.set("prompt", "观星:点击将牌移动到牌堆顶或牌堆底"); + next.set("prompt", "观星:点击或拖动将牌移动到牌堆顶或牌堆底"); next.processAI = function (list) { var cards = list[0][1], player = _status.event.player; @@ -4787,7 +4789,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { .set("ai", function (target) { var player = _status.event.player; var att = get.attitude(player, target); - + if (att > 0) { var js = target.getCards("j"); if (js.length) { @@ -4943,5 +4945,5 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "
  • 击杀奖惩
    杀死颜色不同的主帅的角色回复1点体力,杀死颜色不同的先锋的角色摸两张牌,杀死颜色相同的细作的角色摸三张牌,杀死颜色相同的先锋的主帅弃置所有手牌。
    " + "
  • 制作团队
    游戏出品:紫星居
    游戏设计:食茸貳拾肆
    游戏开发:食茸貳拾肆、紫髯的小乔、聆星Mine、空城琴音依旧弥漫、丽景原同志、雪之彩翼、拉普拉斯、明月照沟渠
    程序化:无名杀
    鸣谢:荆哲、魔风、萨巴鲁酱、这就是秋夜", }, - }; -}); + } +} diff --git a/mode/realtime.js b/mode/realtime.js index d8d9c16424..d97c2f82d6 100644 --- a/mode/realtime.js +++ b/mode/realtime.js @@ -1,8 +1,12 @@ -"use strict"; -game.import("mode", function (lib, game, ui, get, ai, _status) { +import { lib, game, ui, get, ai, _status } from '../noname.js'; +export const type = 'mode'; +/** + * @type { () => importModeConfig } + */ +export default () => { return { name: "realtime", - start: function () {}, + start() {}, game: {}, - }; -}); + } +} diff --git a/mode/single.js b/mode/single.js index 4eabdbe9f3..e4c3d519f6 100644 --- a/mode/single.js +++ b/mode/single.js @@ -1,5 +1,9 @@ -"use strict"; -game.import("mode", function (lib, game, ui, get, ai, _status) { +import { lib, game, ui, get, ai, _status } from '../noname.js'; +export const type = 'mode'; +/** + * @type { () => importModeConfig } + */ +export default () => { return { name: "single", changbanCharacter: [ @@ -172,7 +176,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["heart", 12, "guohe"], ["heart", 12, "shandian"], ["heart", 13, "shan"], - + ["diamond", 1, "juedou"], ["diamond", 1, "zhuge"], ["diamond", 1, "zhuque"], @@ -193,7 +197,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["diamond", 12, "tao"], ["diamond", 12, "wuxie"], ["diamond", 12, "huogong"], - + ["club", 1, "juedou"], ["club", 1, "baiyin"], ["club", 2, "sha"], @@ -214,7 +218,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["club", 9, "jiu"], ["club", 12, "wuxie"], ["club", 13, "wuxie"], - + ["spade", 1, "juedou"], ["spade", 1, "guding"], ["spade", 2, "cixiong"], @@ -242,74 +246,77 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["spade", 12, "zhangba"], ["spade", 13, "nanman"], ], - characterSingle: Object.assign(new Proxy( - {}, + characterSingle: Object.assign( + new Proxy( + {}, + { + set(target, prop, newValue) { + return Reflect.set(target, prop, get.convertedCharacter(newValue)); + }, + } + ), { - set(target, prop, newValue) { - return Reflect.set(target, prop, get.convertedCharacter(newValue)); - }, + caocao: ["male", "wei", 4, ["jianxiong"], ["zhu"]], + simayi: ["male", "wei", 3, ["fankui", "guicai"]], + xiahoudun: ["male", "wei", 4, ["ganglie"]], + zhangliao: ["male", "wei", 4, ["retuxi"]], + xuzhu: ["male", "wei", 4, ["luoyi", "xiechan"]], + guojia: ["male", "wei", 3, ["tiandu", "yiji"]], + zhenji: ["female", "wei", 3, ["luoshen", "sgqingguo"]], + liubei: ["male", "shu", 4, ["sgrenwang"], ["zhu"]], + guanyu: ["male", "shu", 4, ["wusheng", "huwei"]], + zhangfei: ["male", "shu", 4, ["paoxiao"]], + zhugeliang: ["male", "shu", 3, ["guanxing", "kongcheng"]], + zhaoyun: ["male", "shu", 4, ["longdan"]], + machao: ["male", "shu", 4, ["xiaoxi", "tieji"]], + huangyueying: ["female", "shu", 3, ["jizhi", "cangji"]], + sunquan: ["male", "wu", 4, ["sgzhiheng"], ["zhu"]], + ganning: ["male", "wu", 4, ["qixi"]], + lvmeng: ["male", "wu", 4, ["shenju", "botu"]], + huanggai: ["male", "wu", 4, ["kurou"]], + zhouyu: ["male", "wu", 3, ["yingzi", "fanjian"]], + daqiao: ["female", "wu", 3, ["guose", "wanrong"]], + luxun: ["male", "wu", 3, ["qianxun", "lianying"]], + sunshangxiang: ["female", "wu", 3, ["xiaoji", "yinli"]], + //huatuo:['male','qun',3,['qingnang','jijiu']], + lvbu: ["male", "qun", 4, ["wushuang"]], + diaochan: ["female", "qun", 3, ["pianyi", "biyue"]], + + xiahouyuan: ["male", "wei", 4, ["shensu", "suzi"]], + old_caoren: ["male", "wei", 4, ["jushou"]], + huangzhong: ["male", "shu", 4, ["liegong"]], + weiyan: ["male", "shu", 4, ["sgkuanggu"]], + xiaoqiao: ["female", "wu", 3, ["tianxiang", "hongyan"]], + old_zhoutai: ["male", "wu", 4, ["gzbuqu"]], + zhangjiao: ["male", "qun", 3, ["leiji", "guidao"], ["zhu"]], + + dianwei: ["male", "wei", 4, ["qiangxi"]], + yanwen: ["male", "qun", 4, ["shuangxiong"]], + pangde: ["male", "qun", 4, ["xiaoxi", "mengjin"]], + + menghuo: ["male", "shu", 4, ["manyi", "zaiqi"]], + zhurong: ["female", "shu", 4, ["manyi", "lieren"]], + xuhuang: ["male", "wei", 4, ["sgduanliang"]], + sunjian: ["male", "wu", 4, ["gzyinghun"]], + + jiangwei: ["male", "shu", 4, ["tiaoxin"]], + + hejin: ["male", "qun", 4, ["mouzhu", "yanhuo"]], + hansui: ["male", "qun", 4, ["xiaoxi", "niluan"]], + niujin: ["male", "wei", 4, ["cuorui", "liewei"]], + + jin_zhangchunhua: ["female", "jin", 3, ["huishi", "qingleng"]], + jin_simayi: ["male", "jin", 3, ["smyyingshi", "xiongzhi", "quanbian"]], + jin_wangyuanji: ["female", "jin", 3, ["yanxi"]], + jin_simazhao: ["male", "jin", 3, ["choufa", "zhaoran"]], + jin_xiahouhui: ["female", "jin", 3, ["jyishi", "shiduo"]], + jin_simashi: ["male", "jin", "3/4", ["yimie", "tairan"]], + zhanghuyuechen: ["male", "jin", 4, ["xijue"]], + duyu: ["male", "jin", 4, ["sanchen", "zhaotao"]], } - ), { - caocao: ["male", "wei", 4, ["jianxiong"], ["zhu"]], - simayi: ["male", "wei", 3, ["fankui", "guicai"]], - xiahoudun: ["male", "wei", 4, ["ganglie"]], - zhangliao: ["male", "wei", 4, ["retuxi"]], - xuzhu: ["male", "wei", 4, ["luoyi", "xiechan"]], - guojia: ["male", "wei", 3, ["tiandu", "yiji"]], - zhenji: ["female", "wei", 3, ["luoshen", "sgqingguo"]], - liubei: ["male", "shu", 4, ["sgrenwang"], ["zhu"]], - guanyu: ["male", "shu", 4, ["wusheng", "huwei"]], - zhangfei: ["male", "shu", 4, ["paoxiao"]], - zhugeliang: ["male", "shu", 3, ["guanxing", "kongcheng"]], - zhaoyun: ["male", "shu", 4, ["longdan"]], - machao: ["male", "shu", 4, ["xiaoxi", "tieji"]], - huangyueying: ["female", "shu", 3, ["jizhi", "cangji"]], - sunquan: ["male", "wu", 4, ["sgzhiheng"], ["zhu"]], - ganning: ["male", "wu", 4, ["qixi"]], - lvmeng: ["male", "wu", 4, ["shenju", "botu"]], - huanggai: ["male", "wu", 4, ["kurou"]], - zhouyu: ["male", "wu", 3, ["yingzi", "fanjian"]], - daqiao: ["female", "wu", 3, ["guose", "wanrong"]], - luxun: ["male", "wu", 3, ["qianxun", "lianying"]], - sunshangxiang: ["female", "wu", 3, ["xiaoji", "yinli"]], - //huatuo:['male','qun',3,['qingnang','jijiu']], - lvbu: ["male", "qun", 4, ["wushuang"]], - diaochan: ["female", "qun", 3, ["pianyi", "biyue"]], - - xiahouyuan: ["male", "wei", 4, ["shensu", "suzi"]], - old_caoren: ["male", "wei", 4, ["jushou"]], - huangzhong: ["male", "shu", 4, ["liegong"]], - weiyan: ["male", "shu", 4, ["sgkuanggu"]], - xiaoqiao: ["female", "wu", 3, ["tianxiang", "hongyan"]], - old_zhoutai: ["male", "wu", 4, ["gzbuqu"]], - zhangjiao: ["male", "qun", 3, ["leiji", "guidao"], ["zhu"]], - - dianwei: ["male", "wei", 4, ["qiangxi"]], - yanwen: ["male", "qun", 4, ["shuangxiong"]], - pangde: ["male", "qun", 4, ["xiaoxi", "mengjin"]], - - menghuo: ["male", "shu", 4, ["manyi", "zaiqi"]], - zhurong: ["female", "shu", 4, ["manyi", "lieren"]], - xuhuang: ["male", "wei", 4, ["sgduanliang"]], - sunjian: ["male", "wu", 4, ["gzyinghun"]], - - jiangwei: ["male", "shu", 4, ["tiaoxin"]], - - hejin: ["male", "qun", 4, ["mouzhu", "yanhuo"]], - hansui: ["male", "qun", 4, ["xiaoxi", "niluan"]], - niujin: ["male", "wei", 4, ["cuorui", "liewei"]], - - jin_zhangchunhua: ["female", "jin", 3, ["huishi", "qingleng"]], - jin_simayi: ["male", "jin", 3, ["smyyingshi", "xiongzhi", "quanbian"]], - jin_wangyuanji: ["female", "jin", 3, ["yanxi"]], - jin_simazhao: ["male", "jin", 3, ["choufa", "zhaoran"]], - jin_xiahouhui: ["female", "jin", 3, ["jyishi", "shiduo"]], - jin_simashi: ["male", "jin", "3/4", ["yimie", "tairan"]], - zhanghuyuechen: ["male", "jin", 4, ["xijue"]], - duyu: ["male", "jin", 4, ["sanchen", "zhaotao"]], - }), - startBefore: function () {}, - onreinit: function () { + ), + startBefore() {}, + onreinit() { _status.mode = _status.connectMode ? lib.configOL.single_mode : get.config("single_mode"); if (_status.mode != "normal") return; for (var i in lib.characterSingle) { @@ -317,7 +324,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } for (var j in lib.singleTranslate) lib.translate[j] = lib.singleTranslate[j]; }, - start: function () { + start() { "step 0"; _status.mode = _status.connectMode ? lib.configOL.single_mode : get.config("single_mode"); var playback = localStorage.getItem(lib.configprefix + "playback"); @@ -369,24 +376,16 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _status.characterlist = []; for (var i = 0; i < lib.changbanCharacter.length; i++) { var name = lib.changbanCharacter[i]; - if (lib.character[name] && !lib.filter.characterDisabled(name)) - _status.characterlist.push(name); + if (lib.character[name] && !lib.filter.characterDisabled(name)) _status.characterlist.push(name); } game.broadcastAll(function () { _status.mode = "changban"; - lib.translate.bingliang_info = - "目标角色判定阶段进行判定:若判定结果不为梅花,则跳过该角色的摸牌阶段。"; + lib.translate.bingliang_info = "目标角色判定阶段进行判定:若判定结果不为梅花,则跳过该角色的摸牌阶段。"; lib.translate.zhuge_info = "锁定技,出牌阶段,你使用杀的次数上限+3"; }); for (var i = 0; i < lib.card.list.length; i++) { var card = lib.card.list[i]; - if ( - card[2] == "muniu" || - card[2] == "shandian" || - (card[2] == "tengjia" && card[0] == "club") || - (card[2] == "wuxie" && card[0] == "diamond" && card[1] == 12) - ) - lib.card.list.splice(i--, 1); + if (card[2] == "muniu" || card[2] == "shandian" || (card[2] == "tengjia" && card[0] == "club") || (card[2] == "wuxie" && card[0] == "diamond" && card[1] == 12)) lib.card.list.splice(i--, 1); } } else if (_status.mode == "wuxianhuoli") { var list = []; @@ -396,8 +395,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { else { var list = []; for (var i in lib.character) { - if (!lib.filter.characterDisabled2(i) && !lib.filter.characterDisabled(i)) - list.push(i); + if (!lib.filter.characterDisabled2(i) && !lib.filter.characterDisabled(i)) list.push(i); } } game.countPlayer2(function (current) { @@ -406,7 +404,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { list.remove(current.name2); }); _status.characterlist = list; - game.broadcast((list) => (_status.characterlist = list), list); + game.broadcast(list => (_status.characterlist = list), list); } if (_status.connectMode) { lib.configOL.number = 2; @@ -424,10 +422,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (ui.coin) { _status.coinCoeff = get.coinCoeff([game.me.name]); } - + game.syncState(); event.trigger("gameStart"); - + var players = get.players(lib.sort.position); var info = []; for (var i = 0; i < players.length; i++) { @@ -440,7 +438,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } _status.videoInited = true; game.addVideo("init", null, info); - + game.gameDraw(game.zhu, function (player) { if (_status.mode == "dianjiang") return 4; if (_status.mode == "wuxianhuoli") return 4; @@ -455,7 +453,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (_status.connectMode && lib.configOL.change_card) game.replaceHandcards(game.players.slice(0)); "step 4"; game.phaseLoop(game.zhu); - game.countPlayer((current) => current.showGiveup(), true); + game.countPlayer(current => current.showGiveup(), true); }, game: { canReplaceViewpoint: () => true, @@ -480,14 +478,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { str += get.translation(j + 2) + ":
    "; for (var i = 0; i < list.length; i++) { if (data[j][list[i]]) { - str += - lib.translate[list[i] + "2"] + - ":" + - data[j][list[i]][0] + - "胜" + - " " + - data[j][list[i]][1] + - "负
    "; + str += lib.translate[list[i] + "2"] + ":" + data[j][list[i]][0] + "胜" + " " + data[j][list[i]][1] + "负
    "; } } } @@ -512,14 +503,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } }, getRoomInfo: function (uiintro) { - if (lib.configOL.single_mode == "normal") - uiintro.add( - '
    晋势力武将:' + (lib.configOL.enable_jin ? "开启" : "关闭") - ); + if (lib.configOL.single_mode == "normal") uiintro.add('
    晋势力武将:' + (lib.configOL.enable_jin ? "开启" : "关闭")); if (lib.configOL.bannedcards.length) { - uiintro.add( - '
    禁用卡牌:' + get.translation(lib.configOL.bannedcards) - ); + uiintro.add('
    禁用卡牌:' + get.translation(lib.configOL.bannedcards)); } uiintro.style.paddingBottom = "8px"; }, @@ -528,10 +514,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (game.me.name2) { str += "/" + get.translation(game.me.name2); } - var name = [ - str, - get.translation(_status.mode + 2) + " - " + lib.translate[game.me.identity + "2"], - ]; + var name = [str, get.translation(_status.mode + 2) + " - " + lib.translate[game.me.identity + "2"]]; return name; }, showIdentity: function () {}, @@ -561,7 +544,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { event.videoId = lib.status.videoId++; var list = []; for (var i in lib.character) { - if (lib.filter.characterDisabled(i)) continue; + if (lib.filter.characterDisabled2(i, "ignoreForibidden")) continue; list.push(i); } _status.characterlist = list; @@ -570,28 +553,54 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }; var dialog = ui.create.characterDialog("heightset", filter).open(); dialog.videoId = event.videoId; - + game.me .chooseButton(true) .set("ai", function (button) { return Math.random(); }) + .set( + "selectButton", + (function (choice) { + if (choice == "singble") return [1, 2]; + if (choice == "double") return 2; + return 1; + })(get.config("double_character")) + ) .set("dialog", event.videoId); "step 4"; - game.me.init(result.links[0]); - _status.characterlist.remove(result.links[0]); game.addRecentCharacter(result.links[0]); + _status.characterlist.removeArray(result.links); + if (result.links.length == 2) { + game.me.init(result.links[0], result.links[1]); + game.addRecentCharacter(result.links[1]); + } else { + game.me.init(result.links[0]); + } game.me .chooseButton(true) .set("ai", function (button) { return Math.random(); }) + .set( + "selectButton", + (function (choice) { + if (choice == "singble") return [1, 2]; + if (choice == "double") return 2; + return 1; + })(get.config("double_character")) + ) .set("dialog", event.videoId); "step 5"; game.broadcastAll("closeDialog", event.videoId); - game.me.next.init(result.links[0]); - _status.characterlist.remove(result.links[0]); game.addRecentCharacter(result.links[0]); + _status.characterlist.removeArray(result.links); + if (result.links.length == 2) { + game.me.next.init(result.links[0], result.links[1]); + game.addRecentCharacter(result.links[1]); + } else { + game.me.next.init(result.links[0]); + } setTimeout(function () { ui.arena.classList.remove("choose-character"); }, 500); @@ -619,12 +628,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.players[i].showIdentity(); } game.globalBuff = ["wuxianhuoli_weisuoyuwei"]; - const randomBuff = [ - "liuanhuaming", - "duoduoyishan", - "xushidaifa", - "mianmianjudao", - ].randomGet(); + const randomBuff = ["liuanhuaming", "duoduoyishan", "xushidaifa", "mianmianjudao"].randomGet(); game.globalBuff.add(`wuxianhuoli_${randomBuff}`); "step 1"; _status.characterChoice = { @@ -633,11 +637,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }; const dialog = ["请选择出场武将", '
    本局游戏Buff
    ']; game.globalBuff.forEach((buff, ind) => { - dialog.add( - `
    「${ind === 0 ? "固定" : "随机"}」 ${get.translation( - buff - )}:${get.skillInfoTranslation(buff)}
    ` - ); + dialog.add(`
    「${ind === 0 ? "固定" : "随机"}」 ${get.translation(buff)}:${get.skillInfoTranslation(buff)}
    `); }); dialog.add([_status.characterChoice[game.me.identity], "character"]); game.me.chooseButton(true, dialog); @@ -646,11 +646,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _status.characterChoice[game.me.identity].removeArray(result.links); var list = _status.characterChoice[game.me.enemy.identity].randomRemove(1); game.me.enemy.init(list[0]); - [game.me, game.me.enemy].forEach((current) => { - if ( - current.storage.nohp || - (lib.character[current.name1].hasHiddenSkil && !current.noclick) - ) { + [game.me, game.me.enemy].forEach(current => { + if (current.storage.nohp || (lib.character[current.name1].hasHiddenSkil && !current.noclick)) { current.storage.rawHp = 1; current.storage.rawMaxHp = 1; } @@ -659,16 +656,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { current.hujia = 0; current.update(); }); - game.globalBuff.forEach((buff) => { + game.globalBuff.forEach(buff => { game.addGlobalSkill(buff); }); game.addGlobalSkill("wuxianhuoli_task"); _status.wuxianhuoliProgress = 0; _status.wuxianhuoliLevel = 0; const func = () => { - ui.wuxianhuoliProgress = get.is.phoneLayout() - ? ui.create.div(".touchinfo.left", ui.window) - : ui.create.div(ui.gameinfo); + ui.wuxianhuoliProgress = get.is.phoneLayout() ? ui.create.div(".touchinfo.left", ui.window) : ui.create.div(ui.gameinfo); ui.wuxianhuoliProgress.innerHTML = "任务进度(0/3)"; const showTasks = () => { if (ui.wuxianhuoliInfo) return; @@ -679,34 +674,20 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ui.wuxianhuoliInfo, () => { var uiintro = ui.create.dialog("hidden"); - uiintro.add( - `
    任务列表
    ` - ); + uiintro.add(`
    任务列表
    `); if (typeof _status.wuxianhuoliLevel !== "number") { - uiintro.add( - `
    未获取当前进度,请于一名角色受伤后再查看
    ` - ); + uiintro.add(`
    未获取当前进度,请于一名角色受伤后再查看
    `); } else if (_status.wuxianhuoliLevel < 2) { - uiintro.add(`
    全场角色造成${ - _status.wuxianhuoliLevel === 0 ? 3 : 5 - }点伤害(当前${_status.wuxianhuoliProgress}点)
    \ + uiintro.add(`
    全场角色造成${_status.wuxianhuoliLevel === 0 ? 3 : 5}点伤害(当前${_status.wuxianhuoliProgress}点)
    \
    奖励:获得一个技能,摸两张牌
    `); } else { - uiintro.add( - `
    所有任务已完成,无后续任务
    ` - ); + uiintro.add(`
    所有任务已完成,无后续任务
    `); } - uiintro.add( - `
    全局Buff
    ` - ); + uiintro.add(`
    全局Buff
    `); uiintro.add( `
    ${game.globalBuff .map((buff, ind) => { - return ( - get.translation(buff) + - ":" + - get.skillInfoTranslation(buff) - ); + return get.translation(buff) + ":" + get.skillInfoTranslation(buff); }) .join("
    ")}
    ` ); @@ -775,10 +756,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { event.videoIdx = lib.status.videoId++; game.broadcastAll( function (id, list) { - var dialog = ui.create.dialog("选择武将", [list.all, "character"], "起始武将", [ - list[game.me.identity], - "character", - ]); + var dialog = ui.create.dialog("选择武将", [list.all, "character"], "起始武将", [list[game.me.identity], "character"]); dialog.videoId = id; }, event.videoIdx, @@ -807,8 +785,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } else { choosing = "对手"; } - dialog.content.firstChild.innerHTML = - choosing + "选择了" + get.translation(link); + dialog.content.firstChild.innerHTML = choosing + "选择了" + get.translation(link); for (var i = 0; i < dialog.buttons.length; i++) { if (link.includes(dialog.buttons[i].link)) { if (first) { @@ -846,8 +823,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } else { choosing = "对手"; } - dialog.content.firstChild.innerHTML = - choosing + "选择了" + get.translation(link); + dialog.content.firstChild.innerHTML = choosing + "选择了" + get.translation(link); for (var i = 0; i < dialog.buttons.length; i++) { if (link.includes(dialog.buttons[i].link)) { if (first) { @@ -885,8 +861,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } else { choosing = "对手"; } - dialog.content.firstChild.innerHTML = - choosing + "选择了" + get.translation(link); + dialog.content.firstChild.innerHTML = choosing + "选择了" + get.translation(link); for (var i = 0; i < dialog.buttons.length; i++) { if (link.includes(dialog.buttons[i].link)) { if (first) { @@ -924,8 +899,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } else { choosing = "对手"; } - dialog.content.firstChild.innerHTML = - choosing + "选择了" + get.translation(link); + dialog.content.firstChild.innerHTML = choosing + "选择了" + get.translation(link); for (var i = 0; i < dialog.buttons.length; i++) { if (link.includes(dialog.buttons[i].link)) { if (first) { @@ -945,17 +919,11 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "step 7"; game.broadcastAll("closeDialog", event.videoIdx); "step 8"; - game.me.chooseButton( - true, - ["请选择出场武将", [_status.characterChoice[game.me.identity], "character"]], - _status.mode == "changban" ? 2 : 1 - ); + game.me.chooseButton(true, ["请选择出场武将", [_status.characterChoice[game.me.identity], "character"]], _status.mode == "changban" ? 2 : 1); "step 9"; game.me.init(result.links[0], _status.mode == "changban" ? result.links[1] : null); _status.characterChoice[game.me.identity].removeArray(result.links); - var list = _status.characterChoice[game.me.enemy.identity].randomRemove( - _status.mode == "changban" ? 2 : 1 - ); + var list = _status.characterChoice[game.me.enemy.identity].randomRemove(_status.mode == "changban" ? 2 : 1); game.me.enemy.init(list[0], list[1]); "step 10"; setTimeout(function () { @@ -1006,40 +974,62 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { .set("ai", function (button) { return Math.random(); }) + .set( + "selectButton", + (function (choice) { + if (choice == "singble") return [1, 2]; + if (choice == "double") return 2; + return 1; + })(lib.configOL.double_character) + ) .set("dialog", event.videoId); "step 2"; game.broadcastAll( function (player, character, id) { - player.init(character); - _status.characterlist.remove(character); - if (player == game.me) game.addRecentCharacter(character); + if (player == game.me) game.addRecentCharacter(character[0]); + if (character.length !== 2) player.init(character[0]); + else { + player.init(character[0], character[1]); + if (player == game.me) game.addRecentCharacter(character[1]); + } + _status.characterlist.removeArray(character); }, game.zhu, - result.links[0] + result.links ); game.fan .chooseButton(true) .set("ai", function (button) { return Math.random(); }) + .set( + "selectButton", + (function (choice) { + if (choice == "singble") return [1, 2]; + if (choice == "double") return 2; + return 1; + })(lib.configOL.double_character) + ) .set("dialog", event.videoId); "step 3"; game.broadcastAll("closeDialog", event.videoId); game.broadcastAll( function (player, character, id) { var dialog = get.idDialog(id); - if (dialog) { - dialog.close(); + if (dialog) dialog.close(); + if (player == game.me) game.addRecentCharacter(character[0]); + if (character.length !== 2) player.init(character[0]); + else { + player.init(character[0], character[1]); + if (player == game.me) game.addRecentCharacter(character[1]); } - player.init(character); - _status.characterlist.remove(character); - if (player == game.me) game.addRecentCharacter(character); + _status.characterlist.removeArray(character); setTimeout(function () { ui.arena.classList.remove("choose-character"); }, 500); }, game.fan, - result.links[0], + result.links, event.videoId ); }); @@ -1065,33 +1055,23 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.players[i].showIdentity(); } game.globalBuff = ["wuxianhuoli_weisuoyuwei"]; - const randomBuff = [ - "liuanhuaming", - "duoduoyishan", - "xushidaifa", - "mianmianjudao", - ].randomGet(); + const randomBuff = ["liuanhuaming", "duoduoyishan", "xushidaifa", "mianmianjudao"].randomGet(); game.globalBuff.add(`wuxianhuoli_${randomBuff}`); - const setBuff = (buff) => { + const setBuff = buff => { game.globalBuff = buff; }; game.broadcast(setBuff, game.globalBuff); - if (!_status.postReconnect.wuxianhuoliBuff) - _status.postReconnect.wuxianhuoliBuff = [setBuff, []]; + if (!_status.postReconnect.wuxianhuoliBuff) _status.postReconnect.wuxianhuoliBuff = [setBuff, []]; _status.postReconnect.wuxianhuoliBuff[1].addArray(game.globalBuff); "step 1"; _status.characterChoice = { zhu: _status.characterlist.randomRemove(6), fan: _status.characterlist.randomRemove(6), }; - const list = ["zhu", "fan"].map((identity) => { + const list = ["zhu", "fan"].map(identity => { const dialog = ["请选择出场武将", '
    本局游戏Buff
    ']; game.globalBuff.forEach((buff, ind) => { - dialog.add( - `
    「${ind === 0 ? "固定" : "随机"}」 ${get.translation( - buff - )}:${get.skillInfoTranslation(buff)}
    ` - ); + dialog.add(`
    「${ind === 0 ? "固定" : "随机"}」 ${get.translation(buff)}:${get.skillInfoTranslation(buff)}
    `); }); dialog.add([_status.characterChoice[identity], "character"]); return [game[identity], true, dialog]; @@ -1116,10 +1096,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _status.characterChoice[current.identity].removeArray(result[i]); if (!current.name) { current.init(result[i][0]); - if ( - current.storage.nohp || - (lib.character[current.name1].hasHiddenSkil && !current.noclick) - ) { + if (current.storage.nohp || (lib.character[current.name1].hasHiddenSkil && !current.noclick)) { current.storage.rawHp = 1; current.storage.rawMaxHp = 1; } @@ -1134,11 +1111,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { const current = lib.playerOL[i]; if (!current.name) { current.init(result[i][0]); - if ( - current.storage.nohp || - (lib.character[current.name1].hasHiddenSkil && - !current.noclick) - ) { + if (current.storage.nohp || (lib.character[current.name1].hasHiddenSkil && !current.noclick)) { current.storage.rawHp = 1; current.storage.rawMaxHp = 1; } @@ -1152,7 +1125,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ui.arena.classList.remove("choose-character"); }, 500); }, result); - game.globalBuff.forEach((buff) => { + game.globalBuff.forEach(buff => { game.addGlobalSkill(buff); }); game.addGlobalSkill("wuxianhuoli_task"); @@ -1161,9 +1134,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _status.wuxianhuoliLevel = 0; }); const func = () => { - ui.wuxianhuoliProgress = get.is.phoneLayout() - ? ui.create.div(".touchinfo.left", ui.window) - : ui.create.div(ui.gameinfo); + ui.wuxianhuoliProgress = get.is.phoneLayout() ? ui.create.div(".touchinfo.left", ui.window) : ui.create.div(ui.gameinfo); ui.wuxianhuoliProgress.innerHTML = "任务进度(0/3)"; const showTasks = () => { if (ui.wuxianhuoliInfo) return; @@ -1174,34 +1145,20 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ui.wuxianhuoliInfo, () => { var uiintro = ui.create.dialog("hidden"); - uiintro.add( - `
    任务列表
    ` - ); + uiintro.add(`
    任务列表
    `); if (typeof _status.wuxianhuoliLevel !== "number") { - uiintro.add( - `
    未获取当前进度,请于一名角色受伤后再查看
    ` - ); + uiintro.add(`
    未获取当前进度,请于一名角色受伤后再查看
    `); } else if (_status.wuxianhuoliLevel < 2) { - uiintro.add(`
    全场角色造成${ - _status.wuxianhuoliLevel === 0 ? 3 : 5 - }点伤害(当前${_status.wuxianhuoliProgress}点)
    \ + uiintro.add(`
    全场角色造成${_status.wuxianhuoliLevel === 0 ? 3 : 5}点伤害(当前${_status.wuxianhuoliProgress}点)
    \
    奖励:获得一个技能,摸两张牌
    `); } else { - uiintro.add( - `
    所有任务已完成,无后续任务
    ` - ); + uiintro.add(`
    所有任务已完成,无后续任务
    `); } - uiintro.add( - `
    全局Buff
    ` - ); + uiintro.add(`
    全局Buff
    `); uiintro.add( `
    ${game.globalBuff .map((buff, ind) => { - return ( - get.translation(buff) + - ":" + - get.skillInfoTranslation(buff) - ); + return get.translation(buff) + ":" + get.skillInfoTranslation(buff); }) .join("
    ")}
    ` ); @@ -1214,8 +1171,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ); }; showTasks(); - if (!_status.postReconnect.wuxianhuoliShowTasks) - _status.postReconnect.wuxianhuoliShowTasks = [showTasks, []]; + if (!_status.postReconnect.wuxianhuoliShowTasks) _status.postReconnect.wuxianhuoliShowTasks = [showTasks, []]; const dialog = ui.create.dialog("hidden", "forcebutton"); dialog.add(`任务一`); dialog.addText(`任务:全场角色共计造成3点伤害
    奖励:获得一个技能,摸两张牌`); @@ -1271,12 +1227,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { event.videoIdx = lib.status.videoId++; game.broadcastAll( function (id, list) { - var dialog = ui.create.dialog( - game.me.identity == "fan" ? "选择武将" : "请等待对手选择武将", - [list.all, "character"], - "起始武将", - [list[game.me.identity], "character"] - ); + var dialog = ui.create.dialog(game.me.identity == "fan" ? "选择武将" : "请等待对手选择武将", [list.all, "character"], "起始武将", [list[game.me.identity], "character"]); dialog.videoId = id; }, event.videoIdx, @@ -1304,8 +1255,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } else { choosing = "对手"; } - dialog.content.firstChild.innerHTML = - choosing + "选择了" + get.translation(link); + dialog.content.firstChild.innerHTML = choosing + "选择了" + get.translation(link); for (var i = 0; i < dialog.buttons.length; i++) { if (link.includes(dialog.buttons[i].link)) { if (first) { @@ -1343,8 +1293,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } else { choosing = "对手"; } - dialog.content.firstChild.innerHTML = - choosing + "选择了" + get.translation(link); + dialog.content.firstChild.innerHTML = choosing + "选择了" + get.translation(link); for (var i = 0; i < dialog.buttons.length; i++) { if (link.includes(dialog.buttons[i].link)) { if (first) { @@ -1382,8 +1331,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } else { choosing = "对手"; } - dialog.content.firstChild.innerHTML = - choosing + "选择了" + get.translation(link); + dialog.content.firstChild.innerHTML = choosing + "选择了" + get.translation(link); for (var i = 0; i < dialog.buttons.length; i++) { if (link.includes(dialog.buttons[i].link)) { if (first) { @@ -1421,8 +1369,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } else { choosing = "对手"; } - dialog.content.firstChild.innerHTML = - choosing + "选择了" + get.translation(link); + dialog.content.firstChild.innerHTML = choosing + "选择了" + get.translation(link); for (var i = 0; i < dialog.buttons.length; i++) { if (link.includes(dialog.buttons[i].link)) { if (first) { @@ -1454,9 +1401,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { for (var i in result) { var current = lib.playerOL[i]; if (result[i] == "ai") { - result[i] = _status.characterChoice[current.identity].randomGets( - _status.mode == "changban" ? 2 : 1 - ); + result[i] = _status.characterChoice[current.identity].randomGets(_status.mode == "changban" ? 2 : 1); } else { result[i] = result[i].links; } @@ -1484,8 +1429,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { element: { player: { dieAfter: function () { - if (_status.mode != "normal" || _status.characterChoice[this.identity].length <= 3) - game.checkResult(); + if (_status.mode != "normal" || _status.characterChoice[this.identity].length <= 3) game.checkResult(); }, dieAfter2: function () { if (_status.mode != "normal") return; @@ -1496,17 +1440,12 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "step 0"; game.delay(); "step 1"; - player - .chooseButton(true, [ - "请选择一名出场武将", - [_status.characterChoice[player.identity].slice(0), "character"], - ]) - .set("forceDie", true); + player.chooseButton(true, ["请选择一名出场武将", [_status.characterChoice[player.identity].slice(0), "character"]]).set("forceDie", true); "step 2"; var source = player; var name = result.links[0]; var color = source.node.identity.dataset.color; - + game.broadcastAll( function (source, name, color) { source.revive(null, false); @@ -1519,7 +1458,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { color ); game.log(source, "出场"); - + var num = _status.mode == "normal" ? 4 : source.maxHp; if (player.hasSkill("cuorui")) { player.logSkill("cuorui"); @@ -1627,11 +1566,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, direct: true, content: function () { - player.chooseUseTarget( - "shuiyanqijunx", - get.prompt("huwei"), - "视为使用一张【水淹七军】" - ).logSkill = "huwei"; + player.chooseUseTarget("shuiyanqijunx", get.prompt("huwei"), "视为使用一张【水淹七军】").logSkill = "huwei"; }, }, sgkuanggu: { @@ -1692,20 +1627,12 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { trigger: { target: "useCardToTargeted" }, direct: true, filter: function (event, player) { - return ( - event.player != player && - event.player.isPhaseUsing() && - (event.card.name == "sha" || get.type(event.card) == "trick") - ); + return event.player != player && event.player.isPhaseUsing() && (event.card.name == "sha" || get.type(event.card) == "trick"); }, content: function () { - if (!player.hasSkill("sgrenwang_one")) - player.addTempSkill("sgrenwang_one", "phaseUseEnd"); + if (!player.hasSkill("sgrenwang_one")) player.addTempSkill("sgrenwang_one", "phaseUseEnd"); else if (trigger.player.countDiscardableCards(player, "he")) { - player.discardPlayerCard(trigger.player, "he", get.prompt("sgrenwang")).logSkill = [ - "sgrenwang", - trigger.player, - ]; + player.discardPlayerCard(trigger.player, "he", get.prompt("sgrenwang")).logSkill = ["sgrenwang", trigger.player]; } }, }, @@ -1719,10 +1646,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { return get.color(card) == "black"; }, filter: function (event, player) { - return ( - player.hasSkill("sgduanliang_sss") && - player.countCards("he", { type: ["basic", "equip"], color: "black" }) - ); + return player.hasSkill("sgduanliang_sss") && player.countCards("he", { type: ["basic", "equip"], color: "black" }); }, position: "he", viewAs: { name: "bingliang" }, @@ -1767,8 +1691,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, effect: { target: function (card, player, target, current) { - if (target.countCards("e") && get.tag(card, "respondShan") && current < 0) - return 0.6; + if (target.countCards("e") && get.tag(card, "respondShan") && current < 0) return 0.6; }, }, }, @@ -1795,15 +1718,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { audio: 2, trigger: { global: "loseEnd" }, filter: function (event, player) { - if ( - event.player == player || - event.player != _status.currentPhase || - event.getParent().name == "useCard" - ) - return false; + if (event.player == player || event.player != _status.currentPhase || event.getParent().name == "useCard") return false; for (var i = 0; i < event.cards.length; i++) { - if (get.type(event.cards[i]) == "equip" && get.position(event.cards[i]) == "d") - return true; + if (get.type(event.cards[i]) == "equip" && get.position(event.cards[i]) == "d") return true; } return false; }, @@ -1811,8 +1728,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { content: function () { var list = []; for (var i = 0; i < trigger.cards.length; i++) { - if (get.type(trigger.cards[i]) == "equip" && get.position(trigger.cards[i]) == "d") - list.push(trigger.cards[i]); + if (get.type(trigger.cards[i]) == "equip" && get.position(trigger.cards[i]) == "d") list.push(trigger.cards[i]); } if (list.length) player.gain(list, "gain2"); }, @@ -1825,7 +1741,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + _changeHandcard: { trigger: { global: "gameDrawAfter" }, silent: true, @@ -1850,10 +1766,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { player.draw(hs.length, "nodelay"); for (var i = 0; i < hs.length; i++) { hs[i].fix(); - ui.cardPile.insertBefore( - hs[i], - ui.cardPile.childNodes[get.rand(ui.cardPile.childElementCount)] - ); + ui.cardPile.insertBefore(hs[i], ui.cardPile.childNodes[get.rand(ui.cardPile.childElementCount)]); } }, }, @@ -1888,7 +1801,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (!event.card || event.card.name !== "sha") return false; return ( game - .getGlobalHistory("everything", (evt) => { + .getGlobalHistory("everything", evt => { if (evt.name !== "damage") return false; return evt.card && evt.card.name === "sha"; }) @@ -1906,13 +1819,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { wuxianhuoli_liuanhuaming: { trigger: { player: "loseAfter", - global: [ - "equipAfter", - "addJudgeAfter", - "gainAfter", - "loseAsyncAfter", - "addToExpansionAfter", - ], + global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], }, filter(event, player) { if (player === _status.currentPhase) return false; @@ -1937,7 +1844,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { async content(_, __, player) { const cards = []; for (const type of ["basic", "trick"]) { - const card = get.cardPile((card) => { + const card = get.cardPile(card => { const typex = get.type2(card, false); return type === typex; }); @@ -1962,12 +1869,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _status.wuxianhuoliProgress = num; _status.wuxianhuoliLevel = level; if (!ui.wuxianhuoliProgress) { - ui.wuxianhuoliProgress = get.is.phoneLayout() - ? ui.create.div(".touchinfo.left", ui.window) - : ui.create.div(ui.gameinfo); + ui.wuxianhuoliProgress = get.is.phoneLayout() ? ui.create.div(".touchinfo.left", ui.window) : ui.create.div(ui.gameinfo); } - ui.wuxianhuoliProgress.innerHTML = - "任务进度(" + num + "/" + (level === 0 ? 3 : 5) + ")"; + ui.wuxianhuoliProgress.innerHTML = "任务进度(" + num + "/" + (level === 0 ? 3 : 5) + ")"; }, _status.wuxianhuoliProgress, _status.wuxianhuoliLevel @@ -2058,7 +1962,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } } if (withol && !event.resultOL) { - await new Promise((resolve) => { + await new Promise(resolve => { const interval = setInterval(() => { if (results.length === players.length) { resolve(); @@ -2069,7 +1973,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } if (ai_targets.length > 0) { withai = true; - await new Promise((resolve) => { + await new Promise(resolve => { const interval = setInterval(() => { if (results.length === players.length) { resolve(); @@ -2106,17 +2010,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { return; } if (!ui.wuxianhuoliProgress) { - ui.wuxianhuoliProgress = get.is.phoneLayout() - ? ui.create.div(".touchinfo.left", ui.window) - : ui.create.div(ui.gameinfo); + ui.wuxianhuoliProgress = get.is.phoneLayout() ? ui.create.div(".touchinfo.left", ui.window) : ui.create.div(ui.gameinfo); } - ui.wuxianhuoliProgress.innerHTML = - "任务进度(" + num + "/" + (level === 0 ? 3 : 5) + ")"; + ui.wuxianhuoliProgress.innerHTML = "任务进度(" + num + "/" + (level === 0 ? 3 : 5) + ")"; }, _status.wuxianhuoliProgress, _status.wuxianhuoliLevel ); - await game.asyncDelay(); + await game.delay(); }, getSkills(num = 6) { let allList = _status.characterlist.slice(0); @@ -2134,17 +2035,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.expandSkills(list2); for (let k = 0; k < list2.length; k++) { let info = lib.skill[list2[k]]; - if ( - !info || - info.silent || - info.juexingji || - info.hiddenSkill || - info.dutySkill || - info.zhuSkill || - info.unique || - info.groupSkill - ) - continue; + if (!info || info.silent || info.juexingji || info.hiddenSkill || info.dutySkill || info.zhuSkill || info.unique || info.groupSkill) continue; if (info.ai && (info.ai.combo || info.ai.notemp || info.ai.neg)) continue; list.add(name); if (!map[name]) map[name] = []; @@ -2161,7 +2052,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { async contentx(event) { _status.noclearcountdown = true; const controls = [ - (link) => { + link => { const evt = get.event(); evt.result = { refresh: true }; event.control.classList.add("disabled"); @@ -2182,17 +2073,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { .chooseControl(skills) .set( "choiceList", - skills.map((skill) => { - return ( - '
    【' + - get.translation( - lib.translate[skill + "_ab"] || get.translation(skill).slice(0, 2) - ) + - "】
    " + - "
    " + - get.skillInfoTranslation(skill, game.me) + - "
    " - ); + skills.map(skill => { + return '
    【' + get.translation(lib.translate[skill + "_ab"] || get.translation(skill).slice(0, 2)) + "】
    " + "
    " + get.skillInfoTranslation(skill, game.me) + "
    "; }) ) .set("displayIndex", false) @@ -2218,10 +2100,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { zhangjiao: "张角", old_caoren: "曹仁", old_zhoutai: "周泰", - shuiyanqijunx_info: - "出牌阶段,对一名其他角色使用。目标角色选择一项:1、弃置装备区里的所有牌;2、受到你造成的1点伤害。", - guohe_info: - "出牌阶段,对有牌的一名其他角色使用。你选择一项:①弃置其装备区里的一张牌。②观看其手牌并弃置其中的一张。", + shuiyanqijunx_info: "出牌阶段,对一名其他角色使用。目标角色选择一项:1、弃置装备区里的所有牌;2、受到你造成的1点伤害。", + guohe_info: "出牌阶段,对有牌的一名其他角色使用。你选择一项:①弃置其装备区里的一张牌。②观看其手牌并弃置其中的一张。", shunshou_info: "出牌阶段,对距离为1且有牌的一名其他角色使用。你获得其的一张牌。", }, translate: { @@ -2233,7 +2113,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { changban2: "血战长坂坡", dianjiang2: "点将单挑", wuxianhuoli2: "无限火力", - + wuxianhuoli_weisuoyuwei: "为所欲为", wuxianhuoli_weisuoyuwei_info: "①准备阶段,你摸一张牌。②你使用【杀】的次数上限+1。", wuxianhuoli_duoduoyishan: "多多益善", @@ -2244,28 +2124,24 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { wuxianhuoli_liuanhuaming_info: "每回合限两次。当你于回合外失去牌后,你摸一张牌。", wuxianhuoli_mianmianjudao: "面面俱到", wuxianhuoli_mianmianjudao_info: "准备阶段,你从牌堆或弃牌堆中获得基本牌和锦囊牌各一张。", - + wanrong: "婉容", wanrong_info: "当你成为【杀】的目标后,你可以摸一张牌。", sgzhiheng: "制衡", sgzhiheng_info: "出牌阶段限一次,你可以弃置至多两张牌,然后摸等量的牌。", xiechan: "挟缠", - xiechan_info: - "限定技,出牌阶段,你可以和对手拼点。若你赢/没赢,你/其视为对其/你使用一张【决斗】。", + xiechan_info: "限定技,出牌阶段,你可以和对手拼点。若你赢/没赢,你/其视为对其/你使用一张【决斗】。", huwei: "虎威", huwei_info: "当你登场时,你可以视为使用一张【水淹七军】。", sgkuanggu: "狂骨", sgkuanggu_info: "当你造成伤害后,若你已受伤,你可以进行判定:若结果为黑色,你回复1点体力。", suzi: "肃资", cangji: "藏机", - cangji_info: - "当你死亡时,你可以将装备区内的所有牌移动到游戏外。若如此做,你的下一名角色登场时,你将这些牌置入你的装备区。", + cangji_info: "当你死亡时,你可以将装备区内的所有牌移动到游戏外。若如此做,你的下一名角色登场时,你将这些牌置入你的装备区。", sgrenwang: "仁望", - sgrenwang_info: - "当你于一名其他角色的出牌阶段内成为该角色使用的【杀】或普通锦囊牌的目标后,若此牌不是其本阶段内对你使用的第一张【杀】或普通锦囊牌,则你可以弃置该角色的一张牌。", + sgrenwang_info: "当你于一名其他角色的出牌阶段内成为该角色使用的【杀】或普通锦囊牌的目标后,若此牌不是其本阶段内对你使用的第一张【杀】或普通锦囊牌,则你可以弃置该角色的一张牌。", sgduanliang: "断粮", - sgduanliang_info: - "出牌阶段,若你本回合内使用牌指定过其他角色为目标,则你可以将一张黑色基本牌或装备牌当做【兵粮寸断】使用。", + sgduanliang_info: "出牌阶段,若你本回合内使用牌指定过其他角色为目标,则你可以将一张黑色基本牌或装备牌当做【兵粮寸断】使用。", sgqingguo: "倾国", sgqingguo_info: "你可以将一张装备区内的牌当做【闪】使用或打出。", pianyi: "翩仪", @@ -2276,12 +2152,8 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { shenju_info: "锁定技,你的手牌上限+X(X为你对手的体力值)。", }, help: { - 血战长坂: - '
    游戏规则
    • 选将阶段
      双方在游戏开始时由系统随机分配身份。分配到先手身份的玩家优先出牌,分配到后手身份的玩家优先选将。
      双方各自随机获得3名暗置武将,同时从将池中随机选出6名明置武将,由后手玩家开始,按照一次1张-2张-2张-1张的顺序,轮流选择获得明置武将。之后双方各从自己的6名武将中选择2名分别作为主将和副将进行游戏。
    • 胜利条件
      对方死亡。' + - "
    • 双将规则
      双将主将决定角色的性别和势力,体力上限为主副将体力上限的平均值,向下取整。体力上限为3的角色可在游戏开始后更换一次起始手牌。
    • 牌堆
      牌堆中移除【木牛流马】【闪电】,♣花色的【藤甲】和【无懈可击 ♦️Q】️
    ", - 无限火力: - '
    1v1火力全开模式
      (来自三国杀国际服)
    • 所有角色的初始体力值和体力上限均为10,护甲均为0
    • 每局游戏会有一个固定的Buff和一个随机的Buff,对所有角色生效' + - "
    • 游戏全程会有两个任务,分别为“所有角色造成3点伤害”和“所有角色造成5点伤害”,在任务一完成后才会解锁任务二。
      每当任务完成时,系统会发放奖励:所有角色观看三个随机的技能并获得其中一个(每名角色每局有一次刷新的机会),然后摸两张牌。", + 血战长坂: '
      游戏规则
      • 选将阶段
        双方在游戏开始时由系统随机分配身份。分配到先手身份的玩家优先出牌,分配到后手身份的玩家优先选将。
        双方各自随机获得3名暗置武将,同时从将池中随机选出6名明置武将,由后手玩家开始,按照一次1张-2张-2张-1张的顺序,轮流选择获得明置武将。之后双方各从自己的6名武将中选择2名分别作为主将和副将进行游戏。
      • 胜利条件
        对方死亡。' + "
      • 双将规则
        双将主将决定角色的性别和势力,体力上限为主副将体力上限的平均值,向下取整。体力上限为3的角色可在游戏开始后更换一次起始手牌。
      • 牌堆
        牌堆中移除【木牛流马】【闪电】,♣花色的【藤甲】和【无懈可击 ♦️Q】️
      ", + 无限火力: '
      1v1火力全开模式
        (来自三国杀国际服)
      • 所有角色的初始体力值和体力上限均为10,护甲均为0
      • 每局游戏会有一个固定的Buff和一个随机的Buff,对所有角色生效' + "
      • 游戏全程会有两个任务,分别为“所有角色造成3点伤害”和“所有角色造成5点伤害”,在任务一完成后才会解锁任务二。
        每当任务完成时,系统会发放奖励:所有角色观看三个随机的技能并获得其中一个(每名角色每局有一次刷新的机会),然后摸两张牌。", }, - }; -}); + } +} diff --git a/mode/stone.js b/mode/stone.js index 8618db3203..d0c9ccd11c 100644 --- a/mode/stone.js +++ b/mode/stone.js @@ -1,14 +1,18 @@ -"use strict"; -game.import("mode", function (lib, game, ui, get, ai, _status) { +import { lib, game, ui, get, ai, _status } from '../noname.js'; +export const type = 'mode'; +/** + * @type { () => importModeConfig } + */ +export default () => { return { name: "stone", - start: function () { + start() { "step 0"; lib.init.css(lib.assetURL + "layout/mode/", "stone"); _status.mode = "deck"; game.initStone(); var playback = localStorage.getItem(lib.configprefix + "playback"); - + if (!playback && _status.mode == "deck") { var createCardDialog = function () { ui.deckBuilder = ui.create.div(".popup-container#deck-builder", function () { @@ -126,7 +130,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var observer = new MutationObserver(removeLine); observer.observe(rename, { characterData: true, subtree: true }); rename.addEventListener("keyup", removeLine); - + var cardDialog = ui.create.cardDialog( true, function (name) { @@ -277,7 +281,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { cardDialog.listen(function (e) { e.stopPropagation(); }); - + ui.deckBuilder.appendChild(cardDialog); var deckList = ui.create.div(".shadowed.list", ui.deckBuilder, function (e) { e.stopPropagation(); @@ -394,7 +398,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, 500); } }; - + ui.deckcontrol = ui.create.system( "卡组管理", function () { @@ -421,7 +425,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, true ); - + if (lib.onfree) { ui.deckcontrol.style.transition = "all 0.5s"; ui.deckcontrol.hide(); @@ -430,7 +434,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { createCardDialog(); } } - + if (playback) { ui.create.me(); ui.arena.style.display = "none"; @@ -479,7 +483,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ); if (get.config("skill_bar")) { _status.rageEnabled = true; - + ui.friendBar = ui.create.div(".skillbar.right.shadowed.playerbg", ui.arena); ui.enemyBar = ui.create.div(".skillbar.left.shadowed.playerbg", ui.arena); // ui.friendBar.dataset.nature='metal'; @@ -494,7 +498,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { // ui.enemyBar.popnode=ui.create.div('.skillbartext',ui.enemyBar); _status.friendRage = 0; _status.enemyRage = 0; - + lib.setIntro(ui.friendBar, null, true); lib.setIntro(ui.enemyBar, null, true); } @@ -504,19 +508,19 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.updateStatusCount(); lib.setPopped(_status.friendCount, function () { var uiintro = ui.create.dialog("hidden"); - + if (_status.deadfriend.length) { uiintro.add("已阵亡"); uiintro.add([_status.deadfriend, "player"]); } - + uiintro.add("未上场"); if (_status.mylist.length) { uiintro.add([_status.mylist, "character"]); } else { uiintro.add("(无)"); } - + return uiintro; }); lib.setPopped(_status.enemyCount, function () { @@ -527,10 +531,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { return uiintro; } }); - + game.me.side = Math.random() < 0.5; game.enemy.side = !game.me.side; - + var players = get.players(lib.sort.position); var info = []; for (var i = 0; i < players.length; i++) { @@ -541,7 +545,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }); } (_status.videoInited = true), game.addVideo("init", null, info); - + event.trigger("gameStart"); if (_status.mode == "deck") { game.gameDraw(game.me, 3); @@ -967,7 +971,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } game.players.push(player); ui.arena.appendChild(player); - + game.addVideo("stoneSwap", null, { name: player.name1, name2: player.name2, @@ -1021,7 +1025,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.players.push(player); game.enemy = player; ui.arena.appendChild(player); - + game.addVideo("stoneSwap", null, { name: player.name1, name2: player.name2, @@ -1280,7 +1284,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["minskin", "stone"], [4, 2, "shaman"], ], - + stone_kuangyedoushi: [ "male", "wu", @@ -1356,7 +1360,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["minskin", "stone"], [3, 3, "druid"], ], - + stone_caoyuanshi: [ "male", "qun", @@ -1418,7 +1422,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["minskin", "stone"], [2, 3, "hunter"], ], - + stone_shuiyuansu: ["male", "wei", 4, ["mage_bingdong"], ["minskin", "stone"], [4, 2, "mage"]], stone_wushixuetu: ["female", "wu", 1, ["mage_zhufa"], ["minskin", "stone"], [1, 2, "mage"]], stone_huoyao: ["male", "shu", 3, ["mage_lieyan"], ["minskin", "stone"], [3, 1, "mage"]], @@ -1438,7 +1442,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { stone_kaodalalong: ["male", "qun", 4, ["mage_yufa"], ["minskin", "stone"], [5, 4, "mage"]], stone_yanshushi: ["male", "qun", 2, ["mage_yanshu"], ["minskin", "stone"], [4, 4, "mage"]], stone_xulingwushi: ["male", "qun", 2, ["mage_pingxu"], ["minskin", "stone"], [3, 3, "mage"]], - + stone_hudunren: [ "male", "qun", @@ -1521,7 +1525,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { [4, 4, "paladin"], ], stone_xunmashi: ["male", "qun", 3, ["paladin_moma"], ["minskin", "stone"], [3, 2, "paladin"]], - + stone_lieyanxiaogui: [ "male", "qun", @@ -1620,7 +1624,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["minskin", "stone"], [5, 4, "warlock"], ], - + stone_zhihuiguan: [ "female", "qun", @@ -1710,7 +1714,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["minskin", "stone"], [3, 1, "warrior"], ], - + stone_daomufeizei: [ "male", "qun", @@ -1787,7 +1791,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["minskin", "stone"], [4, 3, "rogue"], ], - + stone_beijunmushi: [ "male", "qun", @@ -1884,15 +1888,15 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["minskin", "stone"], [4, 3, "priest"], ], - + stone_zhongshi: ["male", "wei", 1, ["stone_zhongshi1"], ["minskin", "stone"], [1, 2]], stone_zhucangzhe: ["male", "wei", 1, ["stone_zhucangzhe1"], ["minskin", "stone"], [1, 2]], stone_huoqiangshou: ["male", "wei", 3, ["stone_huoqiangshou1"], ["minskin", "stone"], [3, 1]], - + stone_lansaizhanshi: ["male", "shu", 1, ["stone_chongfeng"], ["minskin", "stone"], [1, 2]], stone_kutongsiseng: ["male", "shu", 1, ["stone_kutongsiseng1"], ["minskin", "stone"], [1, 2]], stone_yuanguanying: ["male", "shu", 3, ["stone_yuanguanying1"], ["minskin", "stone"], [3, 1]], - + stone_dijieshicong: ["male", "wu", 2, ["stone_dijieshicong1"], ["minskin", "stone"], [1, 1]], stone_yaosaishouwei: [ "male", @@ -1903,7 +1907,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { [1, 1], ], stone_famingjia: ["male", "wu", 3, ["stone_famingjia1"], ["minskin", "stone"], [3, 1]], - + stone_chilundashi: ["male", "qun", 2, ["stone_chilundashi1"], ["minskin", "stone"], [1, 1]], stone_hanguangzhizhe: [ "male", @@ -1914,7 +1918,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { [2, 2], ], stone_aihaozhihun: ["male", "qun", 3, ["stone_aihaozhihun1"], ["minskin", "stone"], [3, 1]], - + stone_fennuxiaoji: ["male", "qun", 1, ["stone_fennuxiaoji1"], ["minskin", "stone"], [1, 2]], stone_juxingchanchu: [ "male", @@ -1927,7 +1931,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { stone_wuyi: ["male", "qun", 1, ["jijiu"], ["minskin", "stone", "die:wuyi"], [2, 2]], stone_langren: ["male", "qun", 1, ["stone_qianxing"], ["minskin", "stone"], [1, 2]], stone_shishigui: ["male", "qun", 2, ["stone_shishigui1"], ["minskin", "stone"], [2, 1]], - + stone_fatiaozhuru: ["female", "qun", 1, ["stone_fatiaozhuru1"], ["minskin", "stone"], [1, 2]], stone_mingguangjisi: ["female", "wu", 2, ["shushen"], ["minskin", "stone"], [2, 1]], stone_nianqingjisi: ["female", "wei", 2, ["stone_zhufu"], ["minskin", "stone"], [2, 1]], @@ -1935,7 +1939,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { stone_yanjingshe: ["female", "qun", 2, ["stone_yanjingshe1"], ["minskin", "stone"], [3, 2]], stone_zhiyuzhe: ["female", "qun", 3, ["stone_zhiyu"], ["minskin", "stone"], [3, 1]], stone_mafengzhuru: ["female", "qun", 1, ["stone_mafengzhuru1"], ["minskin", "stone"], [1, 2]], - + stone_shumiao: ["none", "wu", 1, [], ["minskin", "stone", "stonehidden"], [1, 1]], stone_shuren: [ "none", @@ -2019,7 +2023,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["minskin", "stone", "stonehidden"], [1, 1], ], - + stone_tuteng1: [ "none", "qun", @@ -2053,7 +2057,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { [2, 0], ], stone_xinbing: ["none", "qun", 2, [], ["minskin", "stone", "stonehidden"], [2, 0]], - + stone_siwangzhiyi: [ "male", "qun", @@ -2094,7 +2098,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["minskin", "stone", "stonehidden", "stonelegend"], [6, 2], ], - + stone_aolajier: [ "male", "qun", @@ -2380,7 +2384,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } lib.card.list.randomSort(); } - + lib.skill._recasting.usable = 3; for (i in lib.skill) { if (lib.skill[i].changeSeat) { @@ -2400,7 +2404,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } } } - + _status.deadfriend = []; _status.deadenemy = []; game.additionaldead = []; @@ -2429,7 +2433,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { dialog.add("0/" + (get.config("double_character") ? 2 : 1) * get.config("battle_number")); dialog.add([list.slice(0, get.config("battle_number") * 2 + 5), "character"]); dialog.open(); - + var next = game.me.chooseButton(dialog, true).set("onfree", true); next.selectButton = function () { return (get.config("double_character") ? 2 : 1) * get.config("battle_number"); @@ -2449,7 +2453,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.changeCoin(-3); } list.randomSort(); - + var buttons = ui.create.div(".buttons"); var node = _status.event.dialog.buttons[0].parentNode; _status.event.dialog.buttons = ui.create.buttons( @@ -2460,7 +2464,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _status.event.dialog.content.insertBefore(buttons, node); buttons.addTempClass("start"); node.remove(); - + game.uncheck(); game.check(); }; @@ -2553,7 +2557,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } else { event.dialog = ui.create.dialog("", "hidden", "forcebutton"); } - + var buttons = ui.create.div(".buttons", event.dialog.content); var currentNode = null; var clickButton = function (click) { @@ -2889,7 +2893,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + spell_fuchoudaji: { type: "stonecard", fullimage: true, @@ -3082,7 +3086,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + spell_jinyingduijue: { type: "stonecard", stoneact: 4, @@ -3278,7 +3282,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + spell_zhenyanshu: { type: "stonecard", stoneact: 1, @@ -3465,7 +3469,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + spell_shalumingling: { type: "stonecard", stoneact: 2, @@ -3647,7 +3651,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + spell_conglinzhihun: { type: "stonecard", stoneact: 3, @@ -3882,7 +3886,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + spell_mengun: { type: "stonecard", stoneact: 2, @@ -4059,7 +4063,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + spell_canying: { type: "stonecard", stoneact: 1, @@ -4282,7 +4286,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + spell_fengnu: { type: "stonecard", stoneact: 2, @@ -4465,7 +4469,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + spell_shenshengxinxing: { type: "stonecard", stoneact: 5, @@ -4682,7 +4686,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + spell_nuxi: { type: "stonecard", stoneact: 3, @@ -4852,7 +4856,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + spell_lierenyinji: { type: "stonecard", stoneact: 0, @@ -5025,7 +5029,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + spell_liliangdaijia: { type: "stonecard", fullimage: true, @@ -5222,7 +5226,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + spell_yexingchengzhang: { type: "stonecard", fullimage: true, @@ -5425,7 +5429,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + spell_cigu: { type: "stonecard", fullimage: true, @@ -5623,7 +5627,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + spell_fengxian: { type: "stonecard", fullimage: true, @@ -5803,7 +5807,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + spell_lianhuanbaolie: { type: "stonecard", fullimage: true, @@ -5979,7 +5983,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + spell_hanbingjian: { type: "stonecard", fullimage: true, @@ -6140,7 +6144,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, }, }, - + spell_chenmo: { type: "stonecard", enable: true, @@ -6791,7 +6795,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { threaten: 1.6, }, }, - + warlock_anyu: { trigger: { source: "fellow" }, forced: true, @@ -6936,7 +6940,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { threaten: 1.6, }, }, - + warrior_heiyao: { trigger: { global: "phaseEnd" }, forced: true, @@ -7043,7 +7047,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { target.damage(); }, }, - + priest_puzhao: { trigger: { source: "fellow" }, unique: true, @@ -7189,7 +7193,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ai: { effect: { target: function (card) { - if (card.name == "bingliang") return 0; + if (card.name == "bingliang") return [0, 0]; }, }, noPhaseDelay: 1, @@ -7208,7 +7212,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { player.update(); }, }, - + hunter_mishi: { trigger: { global: "fellow" }, forced: true, @@ -7317,7 +7321,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { trigger.num += player.countFellowSkill("hunter_zhanhuo", true); }, }, - + rogue_jiaoyi: { trigger: { source: "fellow" }, forced: true, @@ -7444,7 +7448,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { player.tempHide(); }, }, - + paladin_moma: { global: "paladin_moma2", ai: { @@ -7627,7 +7631,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } }, }, - + mage_yufa: { trigger: { global: "useSkillAfter" }, forced: true, @@ -7725,7 +7729,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } }, }, - + druid_juhuo: { trigger: { global: "dieAfter" }, filter: function (event, player) { @@ -7835,7 +7839,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { trigger.num++; }, }, - + shaman_anhun: { trigger: { global: "dieAfter" }, forced: true, @@ -7922,7 +7926,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { threaten: 1.5, }, }, - + warlock_fushishu: { trigger: { player: "phaseAfter" }, forced: true, @@ -7937,7 +7941,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { threaten: 0.1, }, }, - + paladin_zhengqianghaosheng: { trigger: { player: "phaseBegin" }, forced: true, @@ -7972,7 +7976,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { player.storage.paladin_zhihuizhufu.drawDeck(); }, }, - + priest_kuaisuzhiliao: { mark: true, intro: { @@ -8045,7 +8049,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } }, }, - + druid_conglinzhihun: { trigger: { player: "dieBegin" }, forced: true, @@ -8119,7 +8123,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { delete player.storage.shaman_xianzuzhihun; }, }, - + shaman_fengnu: { unique: true, trigger: { player: "phaseAfter" }, @@ -8308,7 +8312,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ai: { effect: { target: function (card) { - if (card.name == "bingliang") return 0; + if (card.name == "bingliang") return [0, 0]; }, }, noPhaseDelay: 1, @@ -9609,7 +9613,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ai: { effect: { target: function (card) { - if (card.name == "bingliang") return 0; + if (card.name == "bingliang") return [0, 0]; }, }, noPhaseDelay: 1, @@ -10480,7 +10484,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { paladin: "圣骑士", hunter: "猎人", druid: "德鲁伊", - + stone_siwangzhiyi: "死亡之翼", stone_alaikesita: "阿莱克萨", stone_yisela: "伊瑟拉", @@ -10496,7 +10500,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { stone_sainaliusi: "塞纳留斯", stone_fuding: "弗丁", stone_weilun: "维纶", - + stone_fushi: "缚誓", stone_fushi_info: "你出场时,为所有友方角色回复所有体力值。", stone_mieshi: "灭世", @@ -10507,7 +10511,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { stone_chenshui_info: "在你的结束阶段,令己方主将获得一张梦境牌。", stone_mowang: "魔网", stone_mowang_info: "己方法术对主将伤害+2,对随从伤害+4。", - + stone_zhiyin: "指引", stone_zhiyin_info: "每当己方主将使用一张法术牌,将一张火球术置于其手牌。", stone_bianshen: "变身", @@ -10526,7 +10530,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { stone_shenyou_info: "己方主将的职业技能和法术的治疗效果翻倍。", stone_jinu: "激怒", stone_jinu_info: "摸牌阶段,若你己受伤,则额外摸两张牌。", - + spell_shenshengxinxing: "神圣新星", spell_shenshengxinxing_info: "对所有敌方角色造成1点伤害,令所有友方角色回复1点体力。", spell_shengguangzhadan: "圣光炸弹", @@ -10540,7 +10544,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { spell_naluzhiguang_info: "恢复1点体力值,若目标仍处于受伤状态,则召唤一名圣光护卫。", spell_zhiliaozhihuan: "治疗之环", spell_zhiliaozhihuan_info: "令所有随从回复3点体力。", - + spell_zhenyanshu: "真言术", spell_zhenyanshu_info: "令一名随从增加1点体力和体力上限;从牌库中获得一张牌。", spell_enzeshu: "恩泽术", @@ -10554,11 +10558,11 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { spell_xinlinghanbao_info: "对敌方主将造成2点伤害。", spell_kongxinshu: "控心术", spell_kongxinshu_info: "复制敌方牌库中的一张随从,将其置入战场。", - + stone_shengguanghuwei: "圣光护卫", priest_shengguang: "圣光", priest_shengguang_info: "每当一名随从获得治疗,摸一张牌。", - + spell_nuxi: "怒袭", spell_nuxi_info: "造成1点伤害,获得2点护甲。", spell_dunpaimengji: "盾牌猛击", @@ -10571,7 +10575,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { spell_xuanfengzhan_info: "对所有随从造成1点伤害。", spell_juemingluandou: "绝命乱斗", spell_juemingluandou_info: "随机保留一名随从,然后令所有其他随从死亡。", - + spell_zhongnian: "重碾", spell_zhongnian_info: "造成X点伤害,X为已受伤的友方角色数且不超过3。", spell_zhandounuhuo: "战斗怒火", @@ -10584,7 +10588,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { spell_kuangbao_info: "令一名已受伤的友方随从摸四张牌。", spell_yingyongdaji: "英勇打击", spell_yingyongdaji_info: "令一名敌方角色对你造成2点伤害,然后对其造成2点伤害。", - + spell_dubiao: "毒镖", spell_dubiao_info: "对一名随机敌方角色造成1点伤害。", spell_qiangfengsheji: "强风射击", @@ -10600,7 +10604,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { spell_zhuizongshu_info: "从牌库中随机选择三张牌,获得其中的一张。", spell_tianjiangzhuqun: "天降蛛群", spell_tianjiangzhuqun_info: "召唤三只结网蛛。", - + spell_lierenyinji: "猎人印记", spell_lierenyinji_info: "将一名随从的体力上限降至1。", spell_kuaisusheji: "快速射击", @@ -10613,12 +10617,12 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { spell_zidanshangtang_info: "随机获得一张猎人职业法术牌,并获得技能〖上膛〗直到回合结束。", spell_duochongsheji: "多重射击", spell_duochongsheji_info: "对两名随机敌方随从各造成2点伤害。", - + stone_liegou: "猎狗", hunter_zidanshangtang: "上膛", hunter_zidanshangtang_bg: "膛", hunter_zidanshangtang_info: "每当你使用一张法术牌,便随机获得一张猎人职业法术牌。", - + spell_zuzhou: "诅咒", spell_zuzhou_info: "将目标随从翻面,摸一张牌。", spell_xishengqiyue: "牺牲契约", @@ -10631,7 +10635,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { spell_liliangdaijia_info: "令一名友方随从摸四张牌,将体力值变为5,并在其下个回合结束后死亡。", spell_emozhinu: "恶魔之怒", spell_emozhinu_info: "对所有随从造成2点伤害。", - + spell_emozhixin: "恶魔之心", spell_emozhixin_info: "对一名敌方随从造成4点伤害,或令一名友方随从摸四张牌。", spell_ansezhadan: "暗色炸弹", @@ -10646,7 +10650,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { spell_linghunhongxi_info: "令一名随从死亡,回复1点体力。", spell_siwangchanrao: "死亡缠绕", spell_siwangchanrao_info: "对一名随从造成1点伤害;若该随从死亡,从牌库中获得一张牌。", - + spell_wuyashenxiang: "乌鸦神像", spell_wuyashenxiang_info: "从三张法术牌或随从牌中选择一张加入手牌。", spell_huotigenxu: "活体根须", @@ -10661,7 +10665,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { spell_yemanpaoxiao_bg: "咆", spell_yemanpaoxiao2: "咆哮", spell_yemanpaoxiao_info: "所有友方角色造成的伤害+1,直到你的下个回合开始。", - + spell_conglinzhihun: "丛林之魂", druid_conglinzhihun: "树魂", druid_conglinzhihun_info: "你死亡后召唤一个树人。", @@ -10677,21 +10681,21 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { spell_heiandiyu: "黑暗低语", spell_heiandiyu_info: "召唤若干个小精灵直到你的随从数达到4;或令一名随从增加1点体力和体力上限并摸三张牌。", - + druid_yexingchengzhang: "成长", druid_yexingchengzhang_bg: "长", druid_yexingchengzhang_info: "下个出牌阶段开始时获得三点额外行动值。", druid_ziyang: "滋养", druid_ziyang_bg: "养", druid_ziyang_info: "下个出牌阶段开始时获得四点额外行动值。", - + stone_shumiao: "树苗", stone_shuren: "自爆树人", stone_shurenx: "树人", stone_shurenxx: "嘲讽树人", stone_zibao: "自爆", stone_zibao_info: "结合结束后立即死亡。", - + spell_cigu: "刺骨", spell_cigu_info: "造成1点伤害,你可以弃置一张装备区内的牌令伤害+1。", spell_jianrenluanwu: "剑刃乱舞", @@ -10704,7 +10708,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { spell_cisha_info: "杀死一名随从。", spell_modaoyou: "磨刀油", spell_modaoyou_info: "令你下一次剑刃乱舞造成的伤害+1,并与一名随机友方随从各摸两张牌。", - + spell_mengun: "闷棍", spell_mengun_info: "令一名敌方随从死亡(不触发死亡技能),将一张该随从的复制置入对手的手牌。", spell_anzhongpohuai: "暗中破坏", @@ -10721,7 +10725,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { spell_piaoqie_info: "复制两张对手牌库中的牌加入你的手牌。", spell_jipao: "疾跑", spell_jipao_info: "从牌库中获得四张牌。", - + spell_fengxian: "奉献", spell_fengxian_info: "对所有敌方角色造成1点伤害。", spell_fuchouzhinu: "复仇之怒", @@ -10734,7 +10738,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { spell_zuozhandongyuan_info: "召唤两个新兵,随机装备一把武器。", spell_liliangzhufu: "力量祝福", spell_liliangzhufu_info: "令一名随从摸两张牌。", - + spell_jinyingduijue: "精英对决", spell_jinyingduijue_info: "双方各保留体力值最高的一名随从,然后令其他随从死亡。", spell_shenpan: "审判", @@ -10752,7 +10756,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { spell_zhihuizhufu: "智慧祝福", paladin_zhihuizhufu: "智慧祝福", spell_zhihuizhufu_info: "选择一名随从,在其每个准备阶段,你从牌库中获得一张牌。", - + spell_fengnu: "风怒", shaman_fengnu: "风怒", shaman_fengnu_info: "回合结束后,你获得一个额外回合。", @@ -10774,7 +10778,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { shaman_xianzuzhishi: "先祖知识", shaman_xianzuzhishi_info: "本回合手牌上限-1。", spell_xianzuzhishi_info: "从牌库中获得两张牌,本回合手牌上限-1(多次使用不叠加)。", - + spell_lianhuanbaolie: "连环爆裂", spell_lianhuanbaolie_info: "造成1~2点雷电伤害。", spell_shandianfengbao: "闪电风暴", @@ -10787,7 +10791,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { spell_shixue_info: "所有友方随从摸两张牌。", spell_chazhuangshandian: "叉状闪电", spell_chazhuangshandian_info: "对两个随机敌方随从各造成1点雷电伤害。", - + stone_qingwa: "青蛙", stone_youlinglang: "幽灵狼", stone_jingxiang: "镜像", @@ -10795,7 +10799,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { shaman_qingwa: "青蛙", shaman_qingwa_info: "锁定技,你跳过摸牌阶段。", stone_xiaojingling: "小精灵", - + spell_laojiuhuoba: "老旧火把", spell_laojiuhuoba_info: "造成1点伤害,将一张炽热火把置入你的牌库。", spell_chirehuoba: "炽热火把", @@ -10812,7 +10816,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { mage_hanbingpingzhang: "寒冰屏障", mage_hanbingpingzhang_info: "体力值不能降到2以内。", spell_hanbingpingzhang_info: "令一名角色的体力值不能降到2以内,直到你的下一回合开始。", - + spell_hanbingjian: "寒冰箭", spell_hanbingjian_info: "对一个随从造成2点伤害,然后将其翻面。", spell_lieyanfengbao: "烈焰风暴", @@ -10825,25 +10829,25 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { spell_bianxingshu_info: "将一个随从变成一只绵羊。", spell_huoqiushu: "火球术", spell_huoqiushu_info: "造成3点火焰伤害(若目标为主将,伤害不能超过目标的当前体力值)。", - + stone_mianyang: "绵羊", mage_mianyang: "绵羊", mage_mianyang_info: "锁定技,你不能使用【杀】。", - + stone_beijunmushi: "北郡牧师", stone_guangyaozhizi: "光耀之子", stone_longmianjiaoguan: "龙眠教官", stone_linghunjisi: "灵魂祭司", stone_guanliyuan: "管理员", stone_heianjiaotu: "黑暗教徒", - + stone_shengdianzhishi: "圣殿执事", stone_suoxiaojishi: "缩小技师", stone_anyingzisi: "暗影子嗣", stone_guangmingquan: "光明泉", stone_muguangchulong: "暮光雏龙", stone_shenshengyongshi: "神圣勇士", - + priest_puzhao: "普照", priest_puzhao_info: "你出场时,己方主将可令一名其他友方随从增加2点体力和体力上限。", priest_suoxiao: "缩小", @@ -10854,7 +10858,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { priest_muguang_info: "你出场时,若主将手牌中有随从牌,则增加1点体力和体力上限。", priest_shixin: "蚀心", priest_shixin_info: "每当己方主将使用一次职业技能,对双方主将各造成1点伤害。", - + priest_shengliao: "圣疗", priest_shengliao_info: "每当一名随从回复体力,己方主将从牌库中获得一张牌。", priest_guangyao: "光耀", @@ -10867,7 +10871,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { priest_faxian_info: "你出场时,己方主将从三张随机随从牌中选择一张加入手牌。", priest_zhufu: "献身", priest_zhufu_info: "你死亡时,令一名随机友方随从增加1点体力和体力上限。", - + stone_daomufeizei: "盗墓匪贼", stone_haidao: "海盗", stone_haidaotoumu: "海盗头目", @@ -10875,14 +10879,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { stone_tegong: "特工", stone_qiezei: "窃贼", stone_heitieairen: "黑铁矮人", - + stone_duyanhaidao: "独眼海盗", stone_gangtiewushi: "刚铁武师", stone_lifaji: "理发机", stone_shihualong: "石化龙", stone_xiushuihaidao: "锈水海盗", stone_zousishangfan: "走私商贩", - + rogue_duxing: "独行", rogue_duxing_info: "每当敌方主将召唤一名随从,便获得潜行。", rogue_shoudao: "授道", @@ -10895,7 +10899,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { rogue_jielue_info: "每当己方主将装备一把武器牌,摸两张牌。", rogue_jiaoyi: "交易", rogue_jiaoyi_info: "你出场时,己方主将可以弃置一张装备牌令你摸三张牌。", - + rogue_touqie: "偷窃", rogue_touqie_info: "每当你造成一次伤害,己方主将从牌库中获得一张牌。", rogue_xunbao: "寻宝", @@ -10908,14 +10912,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { rogue_qiancang_info: "你出场时,对所有未受伤害的敌方随从造成1点伤害。", rogue_zhaomu: "结伙", rogue_zhaomu_info: "你出场时,召唤一个海盗。", - + stone_zhihuiguan: "指挥官", stone_jiangong: "监工", stone_yuanhou: "猿猴", stone_chidunshinv: "持盾侍女", stone_zhujiashi: "铸甲师", stone_kuangzhanshi: "狂战士", - + stone_heiyaoyaoshou: "黑曜妖兽", stone_honglongyongshi: "红龙勇士", stone_peilianshi: "陪练师", @@ -10923,7 +10927,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { stone_shengjiachong: "圣甲虫", stone_mengmaren: "猛犸人", stone_zhifuzhe: "掷斧者", - + warrior_heiyao: "黑曜", warrior_heiyao_info: "在己方主将的结束阶段,召唤一只圣甲虫。", warrior_peilian: "陪练", @@ -10934,7 +10938,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { warrior_chuanci_info: "每当你对一名敌方随从造成伤害,对另一名随机敌方随从造成等量的伤害。", warrior_zhifu: "掷斧", warrior_zhifu_info: "每当你受到一次伤害,对敌方主将造成1点伤害。", - + warrior_tongling: "统领", warrior_tongling_info: "每当你召唤一个初始手牌数不大于2的随从,令其获得冲锋。", warrior_baoluan: "暴乱", @@ -10945,7 +10949,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { warrior_zhujia_info: "每当你受到一次伤害,己方主将获得1点护甲。", warrior_tidun: "提盾", warrior_tidun_info: "你出场时,己方主将获得2点护甲。", - + stone_lieyanxiaogui: "烈焰小鬼", stone_xiaoguishouling: "小鬼首领", stone_kongjuzhanma: "恐惧战马", @@ -10954,14 +10958,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { stone_diyuhuo: "地狱火", stone_diyuhuox: "地狱火", stone_xiaogui: "小鬼", - + stone_heishitanfan: "黑市摊贩", stone_zhaohuanzhe: "召唤者", stone_meimo: "魅魔", stone_tongkunvwang: "痛苦女王", stone_xukongkongmo: "虚空恐魔", stone_fukongmoyan: "浮空魔眼", - + warlock_anyu: "暗语", warlock_anyu_info: "你出场时,己方主将从三张随机的行动值消耗为1的牌中选择一张加入手牌。", warlock_zhaohuan: "召唤", @@ -10975,7 +10979,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "你出场时,己方主将须令一名其他友方随从死亡,然后你获得其全部的手牌和体力值。", warlock_shijie: "视界", warlock_shijie_info: "每当己方主将受到一次伤害,你增加1点体力和体力上限并摸一张牌。", - + warlock_nonghuo: "弄火", warlock_nonghuo_info: "你出场时,对己方主将造成1点火焰伤害。", warlock_zhaogui: "召鬼", @@ -10986,21 +10990,21 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { warlock_yuhuo_info: "你出场时,对所有其他随从造成1点伤害。", warlock_zaihuo: "灾祸", warlock_zaihuo_info: "你出场时,随机弃置主将的两张手牌。", - + stone_hudunren: "护盾人", stone_junxuguan: "军需官", stone_yurenqishi: "鱼人骑士", stone_chidunweishi: "持盾卫士", stone_liewangshouwei: "列王守卫", stone_longwangpeiou: "龙王配偶", - + stone_baoweizhe: "保卫者", stone_guiqishi: "龟骑士", stone_shenmiqishou: "神秘骑手", stone_shixiangweishi: "石像卫士", stone_xuefanzhanshi: "血帆战士", stone_xunmashi: "训马师", - + paladin_baowei: "保卫", paladin_baowei_info: "你出场时,己方主将可令一名其他随从获得1点护甲。", paladin_tuxi: "吐息", @@ -11014,7 +11018,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { paladin_moma: "秣马", paladin_moma2: "秣马", paladin_moma_info: "所有友方新兵摸牌阶段摸牌数+1。", - + paladin_zhaohuan: "召唤", paladin_zhaohuan2: "召唤", paladin_zhaohuan_info: "你出场后,你的主将在使用下一张随从牌时获得两点行动值。", @@ -11028,21 +11032,21 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { paladin_hudun_info: "你出场时,获得1点护甲值。", paladin_zhaochao: "招潮", paladin_zhaochao_info: "每当你的主将使用一次英雄技能,便摸两张牌。", - + stone_shifazhe: "嗜法者", stone_wushixuetu: "巫师学徒", stone_shuiyuansu: "水元素", stone_falifulong: "法力浮龙", stone_yingxiongzhihun: "英雄之魂", stone_huoyao: "火妖", - + stone_aoshushi: "奥术师", stone_faqishi: "法骑士", stone_fuhuokaijia: "复活铠甲", stone_kaodalalong: "考达拉龙", stone_yanshushi: "炎术士", stone_xulingwushi: "虚灵巫师", - + mage_aoshu: "奥术", mage_aoshu_info: "你出场时,将一张奥术智慧置入主将的手牌。", mage_jili: "激励", @@ -11056,7 +11060,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "你出场时,造成X点火焰伤害,随机分配到敌方随从上,X为己方主将装备区内装备牌的数量。", mage_pingxu: "冯虚", mage_pingxu_info: "你出场时,己方主将从三张随机法术牌中选择一张加入手牌。", - + mage_shifa: "嗜法", mage_shifa_info: "你出场时,将一张随机法术牌置入双方主将的手牌。", mage_minghuo: "冥火", @@ -11069,21 +11073,21 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { mage_zhufa_info: "每当己方主将使用一张法术牌,令其获得1点行动值。", mage_bingdong: "冰冻", mage_bingdong_info: "每当你对一个随从造成伤害,该随从将武将牌翻至背面。", - + stone_caoyuanshi: "草原狮", stone_leiouke: "雷欧克", stone_misha: "米莎", stone_huofu: "霍弗", stone_jiewangzhu: "结网蛛", stone_xunshoushi: "驯兽师", - + stone_senlinlang: "森林狼", stone_tujiu: "秃鹫", stone_muyangren: "牧羊人", stone_jujishou: "狙击手", stone_damoshatuo: "大漠沙驼", stone_huangjialeixiang: "皇家雷象", - + hunter_jiewang: "结网", hunter_jiewang_info: "你死亡时,己方主将获得一张随机野兽牌。", hunter_xunshou: "驯兽", @@ -11094,7 +11098,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { hunter_zhanhuo: "战火", hunter_zhanhuo2: "战火", hunter_zhanhuo_info: "其他友方随从摸牌阶段的摸牌数+1。", - + hunter_qunxi: "群袭", hunter_qunxi_info: "你出场时,所有友方随从摸一张牌。", hunter_mishi: "觅食", @@ -11107,21 +11111,21 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { hunter_muyang_info: "你出场时,随机召唤一个行动值消耗为X的随从,X为其他友方随从数。", hunter_juji: "狙击", hunter_juji_info: "你的职业技能可以指定随从为目标。", - + stone_baoqishi: "豹骑士", stone_conglinshouwei: "从林守卫", stone_baohuzhishu: "保护之树", stone_kuangyedoushi: "狂野斗士", stone_liebao: "猎豹", stone_zongxiong: "棕熊", - + stone_renyaqishi: "刃牙骑士", stone_conglinxiaoshou: "丛林枭兽", stone_huangyeqishi: "荒野骑士", stone_xunmenglong: "迅猛龙", stone_lindishuyao: "林地树妖", stone_huoshanxiemu: "火山邪木", - + druid_renya: "刃牙", druid_renya_info: "你出场时,己方主将可以选择一项:令你摸一张牌并将武将牌翻至正面,或令你增加1点体力上限并获得技能潜行。", @@ -11135,7 +11139,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { druid_yeyou_info: "双方主将各从牌库中获得一张牌。", druid_juhuo: "举火", druid_juhuo_info: "己方主将回合内,每有一名随从死亡,令己方主将获得1点行动值。", - + stone_chongfeng: "冲锋", stone_chongfeng_info: "你出场时,立即将武将牌翻至正面。", druid_nuhuo: "怒火", @@ -11146,7 +11150,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { druid_huwei: "护卫", druid_huwei_info: "你出场时,己方主将可以选择一项:对一名随从造成1点伤害,或弃置一名随从的所有牌并将其体力上限改为2。", - + stone_fachao: "法潮图腾", stone_tutengyongshi: "图腾勇士", stone_huoshe: "火舌图腾", @@ -11160,7 +11164,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { stone_huoyanweishi: "火焰卫士", stone_wanshiyuansu: "顽石元素", stone_shalinxingzhe: "砂鳞行者", - + shaman_anhun: "暗魂", shaman_anhun_info: "每当一名友方随从死亡,令主将从牌库中获得一张牌。", shaman_zoushi: "走石", @@ -11179,7 +11183,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { shaman_fachao_info: "己方主将在其每个回合结束阶从牌库中获得一张牌并回复1点体力。", shaman_huoshe: "火舌", shaman_huoshe_info: "其他友方随从造成的伤害始终+1。", - + shaman_jili: "激励", shaman_jili_info: "己方主将的结束阶段,所有友方图腾摸一张牌。", shaman_tuteng: "图腾", @@ -11190,7 +11194,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { shaman_zhiliao_info: "在你的结束阶段,令所有友方随从回复1点体力。", shaman_zhuore: "灼热", shaman_zhuore_info: "已方主将的结束阶段,对一名随机敌方随从造成1点伤害。", - + _shaman_skill: "图腾", _shaman_skill_info: "召唤一个随机图腾。", _mage_skill: "火冲", @@ -11213,14 +11217,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _hunter_skill_info: "对敌方主将造成1点伤害。", _druid_skill: "猛击", _druid_skill_info: "视为使用一张不计入出杀次数的【杀】。", - + stone_tuteng1: "石爪图腾", stone_tuteng2: "灼热图腾", stone_tuteng3: "空气图腾", stone_tuteng4: "治疗图腾", - + stone_xinbing: "新兵", - + stone_zhongshi: "中士", stone_zhongshi1: "叫嚣", stone_zhongshi1_info: "你出场时,己方主将可以弃置对方一名随从的所有牌。", @@ -11230,7 +11234,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { stone_huoqiangshou: "火枪手", stone_huoqiangshou1: "火枪", stone_huoqiangshou1_info: "你出场时,己方主将可以对对方一名随从造成1点伤害。", - + stone_lansaizhanshi: "蓝腮战士", stone_kutongsiseng: "苦痛侍僧", stone_kutongsiseng1: "苦痛", @@ -11239,7 +11243,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { stone_yuanguanying: "远古暗影", stone_yuanguanying1: "暗影", stone_yuanguanying1_info: "你出场时,己方主将可视为对一名敌方角色使用一张【杀】。", - + stone_dijieshicong: "低阶侍从", stone_dijieshicong1: "持枪", stone_dijieshicong1_info: "你出场时,敌方主将随机弃置一张装备牌。", @@ -11249,7 +11253,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { stone_famingjia: "发明家", stone_famingjia1: "发明", stone_famingjia1_info: "你出场时,己方主将摸两张牌。", - + stone_chilundashi: "齿轮大师", stone_chilundashi1: "齿轮", stone_chilundashi2: "齿轮", @@ -11260,7 +11264,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { stone_aihaozhihun: "哀嚎之魂", stone_aihaozhihun1: "哀嚎", stone_aihaozhihun1_info: "你出场时,敌方随从弃置所有牌。", - + stone_fennuxiaoji: "愤怒小鸡", stone_fennuxiaoji1: "暴怒", stone_fennuxiaoji1_info: "准备阶段,若你没有手牌,你摸两张牌。", @@ -11274,7 +11278,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { stone_langren: "狼人", stone_qianxing: "潜行", stone_qianxing_info: "你出场时,获得潜行直到下一回合开始。", - + stone_mingguangjisi: "明光祭司", stone_nianqingjisi: "年轻祭司", stone_zhufu: "祝福", @@ -11292,12 +11296,12 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { stone_fatiaozhuru: "发条侏儒", stone_fatiaozhuru1: "发条", stone_fatiaozhuru1_info: "结束阶段,若你没有手牌,你摸两张牌。", - + stonesha: "进攻", stonesha_info: "锁定技,你的装备牌均视为【杀】。", stoneshan: "格挡", stoneshan_info: "锁定技,你的随从和法术牌均视为闪。", - + stonecharacter: "随从", spell_shengerpingdeng: "生而平等", spell_shengerpingdeng_info: "将所有随从体力上限降为1。", @@ -11330,7 +11334,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { spell_xiaoshi: "消失", spell_xiaoshi_info: "令敌方主将将所有装备区内的牌收入手牌,并弃置其若干张手牌,直到其手牌数与你相等。", - + stonecard: "法术", mode_stone_card_config: "炉石模式", mode_stone_character_config: "炉石模式", @@ -11366,5 +11370,5 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "
      • 嘲讽:若一方阵营中有嘲讽角色,则同阵营的无嘲讽角色不以能成为杀目标" + "
      • 行动顺序为先主将后随从。主将或随从死亡后立即移出游戏,主将死亡后替补登场,替补登场时摸3+X张牌,X为对方存活的随从数,无替补时游戏结束", }, - }; -}); + } +} \ No newline at end of file diff --git a/mode/tafang.js b/mode/tafang.js index c0e133f0e8..47c147ff20 100644 --- a/mode/tafang.js +++ b/mode/tafang.js @@ -1,9 +1,13 @@ -"use strict"; -game.import("mode", function (lib, game, ui, get, ai, _status) { +import { lib, game, ui, get, ai, _status } from '../noname.js'; +export const type = 'mode'; +/** + * @type { () => importModeConfig } + */ +export default () => { return { name: "tafang", canvasUpdates2: [], - start: function () { + start() { "step 0"; _status.gameDrawed = true; lib.init.css(lib.assetURL + "layout/mode", "chess"); @@ -138,7 +142,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ui.chesswidth = _status.map.size[0]; ui.chessheight = _status.map.size[1]; game.initChess(); - + var grids = []; var gridnum = ui.chessheight * ui.chesswidth; for (var i = 0; i < gridnum; i++) { @@ -176,7 +180,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { event.obs.push(cg.toString()); } } - + if (lib.config.show_handcardbutton) { lib.setPopped( ui.create.system("手牌", null, true), @@ -203,16 +207,16 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { 220 ); } - + ui.create.me(); ui.create.fakeme(); - + ui.chessinfo = ui.create.div(".fakeme.player", ui.me, function (e) { e.stopPropagation(); }); ui.create.div(ui.chessinfo); lib.setScroll(ui.chessinfo.firstChild); - + game.arrangePlayers(); "step 4"; ui.control.style.display = ""; @@ -234,10 +238,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (event.obs) { game.addVideo("initobs", null, event.obs); } - + ui.me.querySelector(".fakeme.player").hide(); ui.me.querySelector(".fakeme.avatar").hide(); - + var list = []; for (i in lib.character) { if (i.indexOf("treasure_") == 0) continue; @@ -256,7 +260,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _status.turnTotal = parseInt(get.config("tafang_turn")); ui.turnCount = ui.create.system("", null, true); _status.remainingCount = 0; - + _status.tafangend = []; for (var i = 0; i < ui.chesswidth; i++) { var tafangdes = ui.chesswidth * (ui.chessheight - 1) + i; @@ -1181,10 +1185,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { trueColor: "zhu", falseColor: "wei", _chessmove: "移动", - + mode_tafang_character_config: "塔防模式", mode_tafang_card_config: "塔防模式", - + tafang_mech_weixingxianjing: "小型陷阱", tafang_mech_weixingxianjing_skill: "捕猎", tafang_mech_weixingxianjing_skill_info: "每一轮令距离你2格以内的一名随机敌人翻面。", @@ -1205,7 +1209,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { tafang_mech_guangmingquan: "光明泉", tafang_mech_guangmingquan_skill: "圣疗", tafang_mech_guangmingquan_skill_info: "每一轮令距离2格以内的所有友方角色各回复1点体力。", - + tafang_mech_dubiaoxianjing: "毒镖陷阱", tafang_mech_dubiaoxianjing_skill: "毒镖", tafang_mech_dubiaoxianjing_skill_info: "每当距离2格以内的一名敌方角色。", @@ -1223,7 +1227,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { // tafang_mech_shenmidiaoxiang:['','',4,[],['boss'],5], // tafang_mech_shiyuansu:['','',4,[],['boss'],5], // tafang_mech_jiqishi:['','',4,[],['boss'],5], - + tafang_mech_guangmingquan: ["", "", 3, [], ["boss"], 3], tafang_mech_nengliangqiu: ["", "", 3, [], ["boss"], 3], tafang_mech_jiguanren: ["", "", 3, [], ["boss"], 3], @@ -1244,5 +1248,5 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "战场上最多出现3个相同的机关,每个机关在置入战场3轮后消失。战场上最多招募5名友方角色。
      • " + "敌方角色到达底部出口时游戏失败,已方角色到达底部出口,将被移出游戏", }, - }; -}); + } +} diff --git a/mode/versus.js b/mode/versus.js index d844e8b0ba..cf15ed4254 100644 --- a/mode/versus.js +++ b/mode/versus.js @@ -1,8 +1,12 @@ -"use strict"; -game.import("mode", function (lib, game, ui, get, ai, _status) { +import { lib, game, ui, get, ai, _status } from '../noname.js'; +export const type = 'mode'; +/** + * @type { () => importModeConfig } + */ +export default () => { return { name: "versus", - init: function () { + init() { if (get.config("versus_mode") == "jiange") { lib.characterPack.mode_versus = lib.jiangeboss; } else if (get.config("versus_mode") == "siguo") { @@ -25,7 +29,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { delete lib.card.lizhengshangyou; } }, - start: function () { + start() { "step 0"; _status.mode = get.config("versus_mode"); if (_status.connectMode) _status.mode = lib.configOL.versus_mode; @@ -163,7 +167,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { if (lib.storage.versus_reward == undefined) game.save("versus_reward", 3); if (lib.storage.versus_punish == undefined) game.save("versus_punish", "弃牌"); if (lib.storage.replace_number == undefined) game.save("replace_number", 3); - + switch (lib.storage.seat_order) { case "交叉": lib.storage.cross_seat = true; @@ -223,7 +227,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["zhu", "ezhu", "zhong", "ezhong", "zhong", "ezhong", "zhong", "ezhong"], ["zhu", "ezhong", "zhong", "ezhong", "zhong", "ezhu", "zhong", "ezhong"], ].randomGet(); - + var side = true; var num = Math.floor(Math.random() * 8); list = list.splice(8 - num).concat(list); @@ -271,7 +275,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { rand2--; } } - + for (var i in lib.skill) { if (lib.skill[i].changeSeat) { lib.skill[i] = {}; @@ -280,7 +284,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } } } - + var side = Math.random() < 0.5; var num = Math.floor(Math.random() * 8); list = list.splice(8 - num).concat(list); @@ -544,10 +548,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } _status.enemyCount = ui.create.system("杀敌: " + get.cnNumber(0, true), null, true); _status.friendCount = ui.create.system("阵亡: " + get.cnNumber(0, true), null, true); - + lib.setPopped(_status.friendCount, game.versusHoverFriend); lib.setPopped(_status.enemyCount, game.versusHoverEnemy); - + if (lib.storage.zhu) { game.versusPhaseLoop(firstAct); } else { @@ -995,7 +999,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "character", ]); dialog.buttons[7].node.name.innerHTML = get.verticalStr("队友选择"); - + var addSetting = function (dialog) { dialog.add("选择座位").classList.add("add-setting"); var seats = document.createElement("table"); @@ -1039,7 +1043,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { seats.previousSibling.style.display = "none"; seats.style.display = "none"; } - + dialog.add(ui.create.div(".placeholder.add-setting")); dialog.add(ui.create.div(".placeholder.add-setting")); if (get.is.phoneLayout()) dialog.add(ui.create.div(".placeholder.add-setting")); @@ -1058,11 +1062,11 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }; event.addSetting = addSetting; event.removeSetting = removeSetting; - + if (get.config("change_identity")) { addSetting(dialog); } - + ui.create.cheat = function () { _status.createControl = ui.cheat2; ui.cheat = ui.create.control("更换", function () { @@ -1214,7 +1218,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { setTimeout(function () { ui.arena.classList.remove("choose-character"); }, 500); - + ui.longchuanzhibao = ui.create.system("龙船至宝", null, true); // ui.longchuanzhibao.style.display='none'; lib.setPopped( @@ -1253,12 +1257,12 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var bool = Math.random() < 0.5; var bool2 = Math.random() < 0.5; var ref = game.players[0]; - + ref.side = bool; ref.next.side = bool2; ref.next.next.side = !bool; ref.previous.side = !bool2; - + var firstChoose = game.players.randomGet(); if (firstChoose.next.side == firstChoose.side) { firstChoose = firstChoose.next; @@ -1268,7 +1272,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { firstChoose.node.name.innerHTML = get.verticalStr(get.cnNumber(i + 1, true) + "号位"); firstChoose = firstChoose.next; } - + for (var i = 0; i < game.players.length; i++) { if (game.players[i].side == game.me.side) { game.players[i].node.identity.firstChild.innerHTML = "友"; @@ -1299,7 +1303,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var choose = []; event.list = list; _status.characterlist = list4; - + var addSetting = function (dialog) { dialog.add("选择座位").classList.add("add-setting"); var seats = document.createElement("table"); @@ -1354,7 +1358,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { seats.previousSibling.style.display = "none"; seats.style.display = "none"; } - + dialog.add(ui.create.div(".placeholder.add-setting")); dialog.add(ui.create.div(".placeholder.add-setting")); if (get.is.phoneLayout()) dialog.add(ui.create.div(".placeholder.add-setting")); @@ -1373,7 +1377,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }; event.addSetting = addSetting; event.removeSetting = removeSetting; - + var characterChoice; if (_status.brawl && _status.brawl.chooseCharacter) { characterChoice = _status.brawl.chooseCharacter(list, game.me); @@ -1400,7 +1404,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { addSetting(dialog); } } - + ui.create.cheat = function () { _status.createControl = ui.cheat2; ui.cheat = ui.create.control("更换", function () { @@ -1563,13 +1567,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } } } - + var firstChoose = game.players.randomGet(); _status.firstAct = firstChoose; - + firstChoose.side = false; firstChoose.next.side = true; - + for (var i = 0; i < game.players.length; i++) { if (game.players[i].side == game.me.side) { game.players[i].node.identity.firstChild.innerHTML = "友"; @@ -1587,11 +1591,11 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var choose = []; event.list = list; _status.endlessListAll = list.slice(0); - + var characterChoice = list.randomGets(6); var dialog = ui.create.dialog("选择角色", [characterChoice, "character"]); game.me.chooseButton(true, dialog).set("onfree", true); - + ui.create.cheat = function () { _status.createControl = ui.cheat2; ui.cheat = ui.create.control("更换", function () { @@ -1736,7 +1740,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var i; var list; var list2 = []; - + event.list = []; event.choiceFour = get.config("character_four") || lib.choiceFour; event.filterChoice = function (name) { @@ -1952,11 +1956,11 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { rand2--; } } - + var side = Math.random() < 0.5; var num = game.players.indexOf(_status.firstAct); list = list.splice(8 - num).concat(list); - + for (var i = 0; i < 8; i++) { if (list[i][0] == "e") { game.players[i].side = side; @@ -1978,7 +1982,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { delete game.players[i].node.name_seat; } } - + _status.rechoose = true; for (var i = 0; i < game.players.length; i++) { game.players[i].uninit(); @@ -2167,7 +2171,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _status.friendBackup = event.friendlist.slice(0); _status.enemyBackup = event.enemylist.slice(0); _status.coinCoeff = get.coinCoeff(event.friendlist); - + ui.create.players(6); for (var i = 0; i < game.players.length; i++) { game.players[i].getId(); @@ -2184,10 +2188,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _status.prepareArena = true; ui.create.me(); ui.me.appendChild(ui.fakeme); - + game.friend = []; game.enemy = []; - + for (var i in lib.skill) { if (lib.skill[i].changeSeat) { lib.skill[i] = {}; @@ -2232,13 +2236,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.friendZhu.hp++; game.friendZhu.update(); } - + if (!game.enemyZhu.isInitFilter("noZhuHp")) { game.enemyZhu.maxHp++; game.enemyZhu.hp++; game.enemyZhu.update(); } - + game.onSwapControl(); }); }, @@ -2334,7 +2338,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { this.dialog.choice = this.dialog .add(ui.create.switcher("choice", [12, 16, 20, 24, 40, "∞"], lib.storage.choice)) .querySelector(".toggle"); - + // if(lib.storage.cross_seat){ // this.dialog.versus_random_seat.parentNode.classList.add('disabled'); // } @@ -2420,7 +2424,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _status.friend.length = 0; _status.enemy.length = 0; var choice = lib.storage.choice == "∞" ? list.length : lib.storage.choice; - + ui.dialog.content.firstChild.innerHTML = "选择角色"; var buttons = ui.create.div(".buttons"); var node = _status.event.dialog.buttons[0].parentNode; @@ -2432,7 +2436,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _status.event.dialog.content.insertBefore(buttons, node); buttons.addTempClass("start"); node.remove(); - + // event.check(); }); delete _status.createControl; @@ -2626,12 +2630,12 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "step 1"; _status.friendBackup = _status.friend.slice(0); _status.enemyBackup = _status.enemy.slice(0); - + _status.friendDied = []; _status.enemyDied = []; _status.totalCount = _status.friend.length; _status.coinCoeff = get.coinCoeff(_status.friend); - + // ui.auto.show(); ui.wuxie.show(); ui.control.style.display = "none"; @@ -2786,7 +2790,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { for (i = 0; i < num; i++) { game.friend[i].init(_status.friend[i]); game.enemy[i].init(_status.enemy[i]); - + game.friend[i].node.identity.dataset.color = get.translation(_status.color + "Color"); game.enemy[i].node.identity.dataset.color = get.translation(!_status.color + "Color"); } @@ -2796,7 +2800,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.friendZhu.hp++; game.friendZhu.update(); } - + if (!game.enemyZhu.isInitFilter("noZhuHp")) { game.enemyZhu.maxHp++; game.enemyZhu.hp++; @@ -2841,7 +2845,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["zhu", "ezhu", "zhong", "ezhong", "zhong", "ezhong", "zhong", "ezhong"], ["zhu", "ezhong", "zhong", "ezhong", "zhong", "ezhu", "zhong", "ezhong"], ].randomGet(); - + var side = true; var num = Math.floor(Math.random() * 8); list = list.splice(8 - num).concat(list); @@ -2863,7 +2867,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ); game.players[i].getId(); } - + var side = true; var map = {}; var num = Math.floor(Math.random() * 8); @@ -2892,7 +2896,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { var evt = evt_list[0], character = evt_list[1]; game.addGlobalSkill(evt); - + var func = function (map, evt, character) { for (var i in map) { var player = lib.playerOL[i]; @@ -3334,7 +3338,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { rand2--; } } - + var side = Math.random() < 0.5; var map = {}; var num = Math.floor(Math.random() * 8); @@ -3371,7 +3375,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.players[i].node.name_seat.style.opacity = 1; } }, _status.firstAct); - + var filterChoice = function (name) { // if(name=='zuoci'||name=='miheng') return true; if (!lib.choiceFour.includes(name)) { @@ -3604,10 +3608,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, 500); _status.friendDied = []; _status.enemyDied = []; - + _status.friend = []; _status.enemy = []; - + _status.enemyCount = ui.create.system( "杀敌: " + get.cnNumber(0, true), null, @@ -3618,10 +3622,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { null, true ); - + lib.setPopped(_status.friendCount, func1); lib.setPopped(_status.enemyCount, func2); - + for (var i in result) { if (!lib.playerOL[i].name1) { lib.playerOL[i].init(result[i][0]); @@ -3650,10 +3654,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } _status.friendDied = list1; _status.enemyDied = list2; - + _status.friend = list3; _status.enemy = list4; - + _status.enemyCount = ui.create.system( "杀敌: " + get.cnNumber(_status.enemyDied.length, true), null, @@ -3664,10 +3668,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { null, true ); - + lib.setPopped(_status.friendCount, func1); lib.setPopped(_status.enemyCount, func2); - + for (var i = 0; i < game.players.length; i++) { if (game.players[i].side == game.me.side) { game.players[i].node.identity.firstChild.innerHTML = "友"; @@ -3754,7 +3758,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } }, ]; - + //22联机分配武将 var list = []; var libCharacter = {}; @@ -3946,7 +3950,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } }; event.sendback = sendback; - + //发送 event.ai_targets = []; for (var i = 0; i < game.players.length; i++) { @@ -4156,26 +4160,26 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { dialog.close(); } }, event.videoId); - + _status.friendDied = []; _status.enemyDied = []; - + _status.friend = game.players[0].storage.versuslist; _status.enemy = game.players[1].storage.versuslist; - + delete game.players[0].storage.versuslist; delete game.players[1].versuslist; - + _status.enemyCount = ui.create.system("杀敌: " + get.cnNumber(0, true), null, true); _status.friendCount = ui.create.system("阵亡: " + get.cnNumber(0, true), null, true); - + lib.setPopped(_status.friendCount, game.versusHoverFriend); lib.setPopped(_status.enemyCount, game.versusHoverEnemy); - + game.me.side = true; game.players[0].side = true; game.players[1].side = false; - + var func = function (list1, list2, list3, list4, func1, func2, playerid) { if (game.me.playerid == playerid) { game.me.side = true; @@ -4184,21 +4188,21 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.me.side = false; game.me.next.side = true; } - + if (game.me.side) { _status.enemyDied = list1; _status.friendDied = list2; - + _status.enemy = list3; _status.friend = list4; } else { _status.friendDied = list1; _status.enemyDied = list2; - + _status.friend = list3; _status.enemy = list4; } - + _status.enemyCount = ui.create.system( "杀敌: " + get.cnNumber(_status.enemyDied.length, true), null, @@ -4209,7 +4213,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { null, true ); - + lib.setPopped(_status.friendCount, func1); lib.setPopped(_status.enemyCount, func2); }; @@ -4233,7 +4237,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { game.versusHoverEnemy, game.players[0].playerid ); - + var list = [ [game.players[0], ["选择出场角色", [_status.friend, "character"]]], [game.players[1], ["选择出场角色", [_status.enemy, "character"]]], @@ -4493,36 +4497,36 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, versusHoverEnemy: function () { var uiintro = ui.create.dialog("hidden"); - + if (_status.enemyDied.length) { uiintro.add("已阵亡"); uiintro.add([_status.enemyDied, "character"]); } - + uiintro.add("未上场"); if (_status.enemy.length) { uiintro.add([_status.enemy, "character"]); } else { uiintro.add("(无)"); } - + return uiintro; }, versusHoverFriend: function () { var uiintro = ui.create.dialog("hidden"); - + if (_status.friendDied.length) { uiintro.add("已阵亡"); uiintro.add([_status.friendDied, "character"]); } - + uiintro.add("未上场"); if (_status.friend.length) { uiintro.add([_status.friend, "character"]); } else { uiintro.add("(无)"); } - + return uiintro; }, versusHoverHandcards: function () { @@ -4561,12 +4565,12 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ui.control.hide(); ui.intro = ui.create.dialog(); ui.intro.source = "versusCheckEnemy"; - + if (_status.enemyDied.length) { ui.intro.add("已阵亡"); ui.intro.add([_status.enemyDied, "character"]); } - + ui.intro.add("未上场"); if (_status.enemy.length) { ui.intro.add([_status.enemy, "character"]); @@ -4589,12 +4593,12 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ui.control.hide(); ui.intro = ui.create.dialog(); ui.intro.source = "versusCheckFriend"; - + if (_status.friendDied.length) { ui.intro.add("已阵亡"); ui.intro.add([_status.friendDied, "character"]); } - + ui.intro.add("未上场"); if (_status.friend.length) { ui.intro.add([_status.friend, "character"]); @@ -4660,7 +4664,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } ui.versushighlight = game.me; game.me.classList.add("current_action"); - + ui.fakeme.style.backgroundImage = game.me.node.avatar.style.backgroundImage; } }, @@ -4678,7 +4682,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } ui.lineme.width = ui.window.offsetWidth; ui.lineme.height = ui.window.offsetHeight; - + var ctx = ui.linemectx; ctx.shadowBlur = 5; ctx.shadowColor = "rgba(0,0,0,0.3)"; @@ -4689,9 +4693,9 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ctx.strokeStyle = "rgba(255,255,255," + opacity + ")"; ctx.lineWidth = 3; ctx.setLineDash([8, 2]); - + ctx.beginPath(); - + var startx, endx, pos; var endy = game.me.offsetHeight / 2 + game.me.offsetTop + ui.arena.offsetTop; var starty = ui.me.offsetTop + ui.arena.offsetTop + ui.me.offsetHeight / 2; @@ -4783,7 +4787,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["jiangeboss", "hiddenboss", "bossallowed"], "wei", ], - + boss_jileibaihu: [ "male", "shu", @@ -4848,7 +4852,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["jiangemech", "hiddenboss", "bossallowed"], "wei", ], - + boss_kumuyuanrang: [ "male", "wei", @@ -4936,7 +4940,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["heart", 9, "tao"], ["heart", 12, "tao"], ["diamond", 12, "tao"], - + ["spade", 2, "bagua"], ["club", 2, "bagua"], ["spade", 5, "jueying"], @@ -4954,7 +4958,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["diamond", 5, "guanshi"], ["diamond", 12, "fangtian"], ["heart", 5, "qilin"], - + ["heart", 3, "wugu"], ["heart", 4, "wugu"], ["heart", 1, "taoyuan"], @@ -5025,14 +5029,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["spade", 9, "jiu"], ["club", 3, "jiu"], ["club", 9, "jiu"], - + ["diamond", 13, "hualiu"], ["club", 1, "baiyin"], ["spade", 2, "tengjia"], ["club", 2, "tengjia"], ["spade", 1, "guding"], ["diamond", 1, "zhuque"], - + ["heart", 2, "huogong"], ["heart", 3, "huogong"], ["diamond", 12, "huogong"], @@ -5102,7 +5106,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["heart", 9, "tao"], ["heart", 12, "tao"], ["diamond", 12, "tao"], - + ["spade", 2, "bagua"], ["club", 2, "bagua"], ["spade", 5, "jueying"], @@ -5120,7 +5124,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["diamond", 5, "guanshi"], ["diamond", 12, "fangtian"], ["heart", 5, "qilin"], - + ["heart", 3, "wugu"], ["heart", 4, "wugu"], ["heart", 1, "taoyuan"], @@ -5156,7 +5160,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["heart", 6, "lebu"], ["spade", 1, "hanbing"], ["club", 2, "renwang"], - + ["heart", 4, "sha", "fire"], ["heart", 7, "sha", "fire"], ["heart", 10, "sha", "fire"], @@ -5189,13 +5193,13 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { ["spade", 9, "jiu"], ["club", 3, "jiu"], ["club", 9, "jiu"], - + ["diamond", 13, "hualiu"], ["club", 1, "baiyin"], ["spade", 2, "tengjia"], ["spade", 1, "guding"], ["diamond", 1, "zhuque"], - + ["heart", 2, "huogong"], ["heart", 3, "huogong"], ["diamond", 12, "huogong"], @@ -5436,10 +5440,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { choice_config: "候选人数", mode_versus_character_config: "剑阁武将", mode_versus_card_config: "同舟共济", - + tangzi: "唐咨", liuqi: "刘琦", - + wenji: "问计", wenji2: "问计", wenji_info: @@ -5453,7 +5457,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { xingzhao_bg: "棹", xingzhao_info: "锁定技,若你和队友持有的龙船至宝数合计为:1个以上,你具有技能“恂恂”;2个以上,当你或队友使用装备牌时,其摸一张牌;3个以上,你和队友跳过判定阶段。", - + boss_liedixuande: "烈帝玄德", boss_gongshenyueying: "工神月英", boss_tianhoukongming: "天侯孔明", @@ -5462,7 +5466,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_jiarenzidan: "佳人子丹", boss_duanyuzhongda: "断狱仲达", boss_juechenmiaocai: "绝尘妙才", - + boss_jileibaihu: "机雷白虎", boss_yunpingqinglong: "云屏青龙", boss_lingjiaxuanwu: "灵甲玄武", @@ -5471,12 +5475,12 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { boss_tuntianchiwen: "吞天螭吻", boss_shihuosuanni: "食火狻猊", boss_lieshiyazi: "裂石睚眦", - + boss_kumuyuanrang: "枯目元让", boss_baijiwenyuan: "百计文远", boss_yihanyunchang: "翊汉云长", boss_fuweizilong: "扶危子龙", - + boss_xiaorui: "骁锐", boss_xiaorui2: "骁锐", boss_xiaorui_info: "友方角色于其回合内使用【杀】造成伤害后,其使用【杀】的次数+1。", @@ -5727,7 +5731,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _status.shishengshibai % 10 == 9 && card.name == "tiesuo" ) - return "zerotarget"; + return [0, 0, 0, 0]; }, }, }, @@ -6872,11 +6876,6 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { }, ai: { threaten: 1.5, - effect: { - target: function (card, player, target) { - if (card.name == "guiyoujie") return [0, 1]; - }, - }, }, }, boss_zhenwei: { @@ -7003,13 +7002,6 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { event.redo(); } }, - ai: { - effect: { - target: function (card, player, target) { - if (card.name == "guiyoujie") return [0, 1]; - }, - }, - }, }, boss_tanshi: { trigger: { player: "phaseEnd" }, @@ -7262,7 +7254,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { nodamage: true, effect: { target: function (card, player, target, current) { - if (get.tag(card, "damage") && !get.tag(card, "thunderDamage")) return [0, 0]; + if (get.tag(card, "damage") && !get.tag(card, "thunderDamage")) return "zeroplayertarget"; }, }, }, @@ -7359,7 +7351,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { nofire: true, effect: { target: function (card, player, target, current) { - if (get.tag(card, "fireDamage")) return 0; + if (get.tag(card, "fireDamage")) return "zeroplayertarget"; }, }, }, @@ -8160,7 +8152,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { name: source.name, stat: source.stat, }); - + game.broadcastAll( function (source, name, color) { _status.friend.remove(name); @@ -8178,7 +8170,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { color ); game.log(source, "出场"); - + source.draw(4); var evt = event.getParent("dying"); if (evt && evt.parent) { @@ -8210,10 +8202,10 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } } if (!num || typeof num != "number") return this; - + this.storage.longchuanzhibao += num; this.updateMark("longchuanzhibao"); - + if (source) { source.storage.longchuanzhibao -= num; source.updateMark("longchuanzhibao"); @@ -8221,7 +8213,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } else { game.log(this, "获得了" + get.cnNumber(num) + "个", "#y龙船至宝"); } - + if (source && source.side != this.side) { this.draw(num, "nodelay"); var that = this; @@ -8232,7 +8224,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { friend.draw(num, "nodelay"); } } - + var map = { wei: 0, shu: 0, wu: 0, qun: 0 }; for (var i = 0; i < game.players.length; i++) { var current = game.players[i]; @@ -8380,7 +8372,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { } return; } - + var list = this.side == game.me.side ? _status.friend : _status.enemy; if ( (list.length == 0 && lib.storage.noreplace_end) || @@ -8644,7 +8636,7 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { _status.enemyCount.innerHTML = "杀敌: " + get.cnNumber(_status.enemyDied.length, true); } - + var list = this.side == me.side ? _status.friend : _status.enemy; if ( (list.length == 0 && lib.storage.noreplace_end) || @@ -8804,5 +8796,5 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { "8号位游戏开始时额外摸一张牌,7、8号位可在游戏开始时置换一次手牌
      • " + "杀死对方忠臣摸2+x张牌,x为对方(含刚被杀的忠臣)与己方的存活人数之差;主公杀死己方忠臣须弃置所有牌", }, - }; -}); + } +} diff --git a/node_modules/@types/noname-typings/Skill.d.ts b/node_modules/@types/noname-typings/Skill.d.ts index 1fbb75517e..992347e2a1 100644 --- a/node_modules/@types/noname-typings/Skill.d.ts +++ b/node_modules/@types/noname-typings/Skill.d.ts @@ -825,6 +825,22 @@ declare interface Skill { */ zhuSkill?: boolean; + /** + * 是否为势力技: + * + * 请填写对应势力 + */ + groupSkill?: string; + + /** + * 是否与【杀】相关: + * 用于DIY张绣〖百鸣〗检测 + * 默认技能描述中含“【杀】”的是“与杀相关的技能” + * 若shaRelated为true,则直接视为该技能是符合条件的技能 + * 若shaRelated为false,则直接视为该技能不是符合条件的技能 + */ + shaRelated?: boolean; + //主动技能(主动使用技能,包含技能使用的相关操作配置) /** * 可使用的阶段 @@ -1417,6 +1433,12 @@ declare interface Skill { * 比如伊籍的【急援】,可能会出现“同时将一些牌交给了多名角色”的情况 */ getIndex?: (event, player, triggername) => number | Player[]; + + /** + * 持恒技 + */ + persevereSkill?: boolean; + //日后还有很多属性要添加的 [key: string]: any; } @@ -1538,6 +1560,7 @@ declare interface SkillAI { nomingzhi?: boolean; /** * 反转装备的优先值,用于设置装备卡牌card.ai.basic.order的默认优先度; + * 一般是用来顶装备刷收益的,如〖枭姬〗 */ reverseEquip?: boolean; /** 非身份,国战使用,濒死阶段,有该标记,可以强行进行复活求帮助 */ @@ -1564,11 +1587,19 @@ declare interface SkillAI { usedu?: boolean; /** 不受毒影响 */ nodu?: boolean; + /** 免疫锦囊 */ notrick?: boolean; + /** 免疫锦囊牌造成的伤害 */ notricksource?: boolean; + /** 【闪】能用则用,即使数量不够 */ useShan?: boolean; + /** 不用【闪】,即使挨打要濒死 */ noShan?: boolean; + /** 此时让技能持有者获得牌没有收益,如〖自书〗 */ + nogain?: boolean; + /** 此时让技能持有者失去牌没有收益,如〖屯田〗 */ nolose?: boolean; + /** 此时让技能持有者弃置牌没有收益,如〖屯田〗 */ nodiscard?: boolean; /** 玩家不响应无懈 */ @@ -1953,4 +1984,4 @@ interface ChooseButtonConfigData { * @param player */ chooseControl?(event: GameEvent, player: Player): string[]; -} \ No newline at end of file +} diff --git a/node_modules/@types/noname-typings/nonameModules/game/codemirror.d.ts b/node_modules/@types/noname-typings/nonameModules/game/codemirror.d.ts index 83a361e3d0..5caf2e315a 100644 --- a/node_modules/@types/noname-typings/nonameModules/game/codemirror.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/game/codemirror.d.ts @@ -2,4 +2,4 @@ export default CodeMirror; /** * @type { typeof import('codemirror/index') } */ -declare var CodeMirror: typeof import("codemirror/index"); +declare var CodeMirror: typeof import('codemirror/index'); diff --git a/node_modules/@types/noname-typings/nonameModules/noname.d.ts b/node_modules/@types/noname-typings/nonameModules/noname.d.ts index 0074af79c2..2b570c8752 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname.d.ts @@ -1,5 +1,4 @@ export const rootURL: URL; -export { boot } from "./noname/init/index.js"; export { GNC, gnc, setGNC } from "./noname/gnc/index.js"; export { AI, ai, setAI } from "./noname/ai/index.js"; export { Game, game, setGame } from "./noname/game/index.js"; @@ -7,3 +6,4 @@ export { Get, get, setGet } from "./noname/get/index.js"; export { Library, lib, setLibrary } from "./noname/library/index.js"; export { status, _status, setStatus } from "./noname/status/index.js"; export { UI, ui, setUI } from "./noname/ui/index.js"; +export { boot, onload } from "./noname/init/index.js"; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/ai/index.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/ai/index.d.ts index 70c9609f77..19013932e5 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/ai/index.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/ai/index.d.ts @@ -1,6 +1,12 @@ export class AI { basic: Basic; get: import("../get/index.js").Get; + /** + * @param { any } obj + * @param { boolean } [similar] true伪equals, false统一前缀 + * @returns { string } cacheKey + */ + getCacheKey(obj: any, similar?: boolean): string; } export let ai: AI; export function setAI(instance?: InstanceType): void; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/game/PauseManager.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/game/PauseManager.d.ts new file mode 100644 index 0000000000..fa10d6c646 --- /dev/null +++ b/node_modules/@types/noname-typings/nonameModules/noname/game/PauseManager.d.ts @@ -0,0 +1,18 @@ +export default class PauseManager { + #private; + pause: Deferred; + pause2: Deferred; + pause3: Deferred; + over: Deferred; + delay: Deferred; + setDelay(promise: Promise): Promise; + waitPause(): Promise; +} +declare class Deferred { + #private; + get isStarted(): boolean; + start(): void; + resolve(): void; + then(onfulfilled?: ((value: void) => void | PromiseLike) | null, onrejected?: ((reason: any) => never | PromiseLike) | null): Promise; +} +export {}; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/game/compatible.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/game/compatible.d.ts new file mode 100644 index 0000000000..1505e3391e --- /dev/null +++ b/node_modules/@types/noname-typings/nonameModules/noname/game/compatible.d.ts @@ -0,0 +1,29 @@ +/** + * @param { InstanceType } [instance] + */ +export function setGameCompatible(instance?: InstanceType): void; +export class GameCompatible { + /** + * `game/game.js`中退出客户端用到的代码 + * + * @author Spmario233 + */ + exit(): void; + /** + * @async + * @param {UpdateReason} type + * @param {string} [text] + * @returns {Promise} + */ + tryUpdateClient(type: UpdateReason, text?: string): Promise; +} +export let game: GameCompatible; +/** + * * + */ +export type UpdateReason = number; +export namespace UpdateReason { + let DEBUG: number; + let FALLBACK: number; + let UNDERSUPPORT: number; +} diff --git a/node_modules/@types/noname-typings/nonameModules/noname/game/dynamic-style/index.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/game/dynamic-style/index.d.ts index 46cb93dc8f..64e1ceb645 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/game/dynamic-style/index.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/game/dynamic-style/index.d.ts @@ -37,7 +37,7 @@ export class DynamicStyle { */ get(name: string): { [x: string]: string | number; - } | null; + }; /** * Callback of `DynamicStyle#find`, getting the rule wanted. * `DynamicStyle#find`的回调函数,用于获取符合要求的规则 diff --git a/node_modules/@types/noname-typings/nonameModules/noname/game/index.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/game/index.d.ts index e5444619ea..75bef2ec4b 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/game/index.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/game/index.d.ts @@ -15,7 +15,7 @@ export class Game extends GameCompatible { * @type { { [key: string]: Player } } */ playerMap: { - [key: string]: Player; + [key: string]: import("noname-typings/nonameModules/noname/library/element/player.js").Player; }; phaseNumber: number; roundNumber: number; @@ -64,7 +64,7 @@ export class Game extends GameCompatible { /** * 洗牌 */ - washCard(): false | any[] | (import("../library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise); + washCard(): false | any[] | import("../library/element/gameEvent.js").GameEvent; /** * 基于钩子的添加势力方法 */ @@ -81,7 +81,7 @@ export class Game extends GameCompatible { * @param {Parameters} args */ callHook(name: Name, args: Parameters): void; - yingbianEffect(event: any, content: any, ...args: any[]): import("../library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + yingbianEffect(event: any, content: any, ...args: any[]): import("../library/element/gameEvent.js").GameEvent; setYingbianConditionColor(yingbianCondition: any, color: any): void; setComplexYingbianCondition(yingbianCondition: any, condition: any): void; setSimpleYingbianCondition(yingbianCondition: any, condition: any): void; @@ -168,7 +168,7 @@ export class Game extends GameCompatible { */ loseAsync(arg?: { [key: string]: any; - }): import("../library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + }): import("../library/element/gameEvent.js").GameEvent; callFuncUseStepCache(prefix: any, func: any, params: any): any; /** * @param {string} name @@ -189,7 +189,7 @@ export class Game extends GameCompatible { * @param { GameEventPromise } [last] * @returns { void } */ - checkGlobalHistory(key: T, filter: (event: GameEventPromise) => boolean, last?: GameEventPromise): void; + checkGlobalHistory(key: T_1, filter: (event: GameEventPromise) => boolean, last?: GameEventPromise): void; /** * @overload * @returns { GameHistory } @@ -203,7 +203,7 @@ export class Game extends GameCompatible { * @param { GameEventPromise } [last] * @returns { GameHistory[T] } */ - getGlobalHistory(key: T, filter?: (event: GameEventPromise) => boolean, last?: GameEventPromise): GameHistory[T]; + getGlobalHistory(key: T_2, filter?: (event: GameEventPromise) => boolean, last?: GameEventPromise): GameHistory[T_2]; /** * @template { keyof GameHistory } T * @param { T } key @@ -211,7 +211,7 @@ export class Game extends GameCompatible { * @param { GameEventPromise } [last] * @returns { boolean } */ - hasAllGlobalHistory(key: T, filter: (event: GameEventPromise) => boolean, last?: GameEventPromise): boolean; + hasAllGlobalHistory(key: T_3, filter: (event: GameEventPromise) => boolean, last?: GameEventPromise): boolean; /** * @template { keyof GameHistory } T * @param { T } key @@ -219,7 +219,7 @@ export class Game extends GameCompatible { * @param { GameEventPromise } [last] * @returns { void } */ - checkAllGlobalHistory(key: T, filter: (event: GameEventPromise) => boolean, last?: GameEventPromise): void; + checkAllGlobalHistory(key: T_4, filter: (event: GameEventPromise) => boolean, last?: GameEventPromise): void; /** * @overload * @returns { GameHistory[] } @@ -233,7 +233,7 @@ export class Game extends GameCompatible { * @param { GameEventPromise } [last] * @returns { GameHistory[T] } */ - getAllGlobalHistory(key: T, filter?: (event: GameEventPromise) => boolean, last?: GameEventPromise): GameHistory[T]; + getAllGlobalHistory(key: T_5, filter?: (event: GameEventPromise) => boolean, last?: GameEventPromise): GameHistory[T_5]; /** * @overload * @returns { void } @@ -279,14 +279,14 @@ export class Game extends GameCompatible { * @param { 'toRenku' | false } [bool] 为false时不触发trigger,为'toRenku'时牌放到仁库 * @returns { GameEventPromise } */ - cardsGotoSpecial(cards: Card, bool?: "toRenku" | false): GameEventPromise; + cardsGotoSpecial(cards: Card, bool?: 'toRenku' | false): GameEventPromise; /** * @overload * @param {Card[]} cards * @param { 'toRenku' | false } [bool] 为false时不触发trigger,为'toRenku'时牌放到仁库 * @returns { GameEventPromise } */ - cardsGotoSpecial(cards: Card[], bool?: "toRenku" | false): GameEventPromise; + cardsGotoSpecial(cards: Card[], bool?: 'toRenku' | false): GameEventPromise; /** * * @param {...( @@ -298,7 +298,10 @@ export class Game extends GameCompatible { * )} args * @returns */ - cardsGotoPile(...args: (Card[] | Card | Function | "insert" | "washCard" | "triggeronly" | [string, any])[]): import("../library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + cardsGotoPile(...args: (Card[] | Card | Function | 'insert' | 'washCard' | 'triggeronly' | [ + string, + any + ])[]): import("../library/element/gameEvent.js").GameEvent; /** * @param { GameEventPromise } event */ @@ -340,7 +343,7 @@ export class Game extends GameCompatible { /** * @param { 'hidden' } [type] */ - randomMapOL(type?: "hidden"): void; + randomMapOL(type?: 'hidden'): void; closeMenu(): void; closeConnectMenu(): void; closePopped(): void; @@ -351,7 +354,31 @@ export class Game extends GameCompatible { * @param { ...Parameters } args * @returns { void } */ - broadcast(func: T, ...args: Parameters<(typeof lib.message.client)[T]>[]): void; + broadcast(func: T_6, ...args: Parameters<{ + log: (arr: any) => void; + opened: () => void; + onconnection: (id: any) => void; + onmessage: (id: any, message: any) => void; + onclose: (id: any) => void; + selfclose: () => void; + reloadroom: (forced: any) => void; + createroom: (index: any, config: any, mode: any) => void; + enterroomfailed: () => void; + roomlist: (list: any, events: any, clients: any, wsid: any) => void; + updaterooms: (list: any, clients: any) => void; + updateclients: (clients: any, bool: any) => void; + updateevents: (events: any) => void; + eventsdenied: (reason: any) => void; + init: (id: any, config: any, ip: any, servermode: any, roomId: any) => void; + reinit: (config: any, state: any, state2: any, ip: any, observe: any, onreconnect: any, cardtag: any, postReconnect: any) => void; + exec: (func: any, ...args: any[]) => void; + denied: (reason: any) => void; + cancel: (id: any) => void; + closeDialog: (id: any) => void; + createDialog: (id: any, ...args: any[]) => void; + gameStart: () => void; + updateWaiting: (map: any) => void; + }[T_6]>): void; /** * @template { any[] } T * @overload @@ -359,7 +386,7 @@ export class Game extends GameCompatible { * @param { ...T } args * @returns { void } */ - broadcast(func: (...args: T) => void, ...args: T[]): void; + broadcast(func: (...args: T_6) => void, ...args: T_6): void; /** * @template { keyof typeof lib.message.client } T * @overload @@ -367,7 +394,31 @@ export class Game extends GameCompatible { * @param { ...Parameters } args * @returns { void } */ - broadcastAll(func: T, ...args: Parameters<(typeof lib.message.client)[T]>[]): void; + broadcastAll(func: T_7, ...args: Parameters<{ + log: (arr: any) => void; + opened: () => void; + onconnection: (id: any) => void; + onmessage: (id: any, message: any) => void; + onclose: (id: any) => void; + selfclose: () => void; + reloadroom: (forced: any) => void; + createroom: (index: any, config: any, mode: any) => void; + enterroomfailed: () => void; + roomlist: (list: any, events: any, clients: any, wsid: any) => void; + updaterooms: (list: any, clients: any) => void; + updateclients: (clients: any, bool: any) => void; + updateevents: (events: any) => void; + eventsdenied: (reason: any) => void; + init: (id: any, config: any, ip: any, servermode: any, roomId: any) => void; + reinit: (config: any, state: any, state2: any, ip: any, observe: any, onreconnect: any, cardtag: any, postReconnect: any) => void; + exec: (func: any, ...args: any[]) => void; + denied: (reason: any) => void; + cancel: (id: any) => void; + closeDialog: (id: any) => void; + createDialog: (id: any, ...args: any[]) => void; + gameStart: () => void; + updateWaiting: (map: any) => void; + }[T_7]>): void; /** * @template { any[] } T * @overload @@ -375,7 +426,7 @@ export class Game extends GameCompatible { * @param { ...T } args * @returns { void } */ - broadcastAll(func: (...args: T) => void, ...args: T[]): void; + broadcastAll(func: (...args: T_7) => void, ...args: T_7): void; syncState(): void; updateWaiting(): void; /** @@ -436,7 +487,7 @@ export class Game extends GameCompatible { * @param { ...string | number | ((evt: Event) => void) } args * @returns { HTMLAudioElement } */ - playAudio(...args: (string | number | ((evt: Event) => void))[]): HTMLAudioElement; + playAudio(...args: string | number | ((evt: Event) => void)): HTMLAudioElement; /** * @param { object } options * @param { string[] } options.audioList @@ -500,7 +551,12 @@ export class Game extends GameCompatible { audioname2?: { [playerName: string]: string | number | boolean | [string, number]; }; - } | (string | number | boolean | [string, number])): import("../get/audio.js").TextMap[]; + } | (string | number | boolean | [string, number])): { + name: string; + file: string; + text: string; + type: string; + }[]; /** * @deprecated 请使用get.Audio.die().audioList * @@ -508,7 +564,12 @@ export class Game extends GameCompatible { * @param { string | Player } player 角色名 * @returns 语音地址列表 */ - parseDieTextMap(player: string | Player): import("../get/audio.js").TextMap[]; + parseDieTextMap(player: string | Player): { + name: string; + file: string; + text: string; + type: string; + }[]; /** * * @param { string } skill @@ -516,9 +577,10 @@ export class Game extends GameCompatible { * @param { boolean } [directaudio] * @param { boolean } [nobroadcast] * @param { any } [skillInfo] + * @param { any[] } [args] logAudio的参数 * @returns */ - trySkillAudio(skill: string, player: Player | string, directaudio?: boolean, nobroadcast?: boolean, skillInfo?: any): HTMLAudioElement | (() => HTMLAudioElement); + trySkillAudio(skill: string, player: Player | string, directaudio?: boolean, nobroadcast?: boolean, skillInfo?: any, args?: any[]): HTMLAudioElement | (() => HTMLAudioElement); /** * @param { Player | string } player * @returns @@ -550,7 +612,7 @@ export class Game extends GameCompatible { * ) => importCharacterConfig } content * @param {*} [url] */ - import(type: "character", content: (lib: InstanceType, game: InstanceType, ui: InstanceType, get: InstanceType, ai: InstanceType, _status: InstanceType) => importCharacterConfig, url?: any): any; + import(type: 'character', content: (lib: InstanceType, game: InstanceType, ui: InstanceType, get: InstanceType, ai: InstanceType, _status: InstanceType) => importCharacterConfig, url?: any): any; /** * @overload * @param { 'card' } type @@ -564,7 +626,7 @@ export class Game extends GameCompatible { * ) => importCardConfig } content * @param {*} [url] */ - import(type: "card", content: (lib: InstanceType, game: InstanceType, ui: InstanceType, get: InstanceType, ai: InstanceType, _status: InstanceType) => importCardConfig, url?: any): any; + import(type: 'card', content: (lib: InstanceType, game: InstanceType, ui: InstanceType, get: InstanceType, ai: InstanceType, _status: InstanceType) => importCardConfig, url?: any): any; /** * @overload * @param { 'mode' } type @@ -578,7 +640,7 @@ export class Game extends GameCompatible { * ) => importModeConfig } content * @param {*} [url] */ - import(type: "mode", content: (lib: InstanceType, game: InstanceType, ui: InstanceType, get: InstanceType, ai: InstanceType, _status: InstanceType) => importModeConfig, url?: any): any; + import(type: 'mode', content: (lib: InstanceType, game: InstanceType, ui: InstanceType, get: InstanceType, ai: InstanceType, _status: InstanceType) => importModeConfig, url?: any): any; /** * @overload * @param { 'player' } type @@ -592,7 +654,7 @@ export class Game extends GameCompatible { * ) => importPlayerConfig } content * @param {*} [url] */ - import(type: "player", content: (lib: InstanceType, game: InstanceType, ui: InstanceType, get: InstanceType, ai: InstanceType, _status: InstanceType) => importPlayerConfig, url?: any): any; + import(type: 'player', content: (lib: InstanceType, game: InstanceType, ui: InstanceType, get: InstanceType, ai: InstanceType, _status: InstanceType) => importPlayerConfig, url?: any): any; /** * @overload * @param { 'extension' } type @@ -606,7 +668,7 @@ export class Game extends GameCompatible { * ) => importExtensionConfig } content * @param {*} [url] */ - import(type: "extension", content: (lib: InstanceType, game: InstanceType, ui: InstanceType, get: InstanceType, ai: InstanceType, _status: InstanceType) => importExtensionConfig, url?: any): any; + import(type: 'extension', content: (lib: InstanceType, game: InstanceType, ui: InstanceType, get: InstanceType, ai: InstanceType, _status: InstanceType) => importExtensionConfig, url?: any): any; /** * @overload * @param { 'play' } type @@ -620,53 +682,77 @@ export class Game extends GameCompatible { * ) => importPlayConfig } content * @param {*} [url] */ - import(type: "play", content: (lib: InstanceType, game: InstanceType, ui: InstanceType, get: InstanceType, ai: InstanceType, _status: InstanceType) => importPlayConfig, url?: any): any; + import(type: 'play', content: (lib: InstanceType, game: InstanceType, ui: InstanceType, get: InstanceType, ai: InstanceType, _status: InstanceType) => importPlayConfig, url?: any): any; loadExtension(object: any): Promise; /** * 下载文件 * @type { undefined | ((url: string, folder: string, onsuccess?: Function, onerror?: (e: Error) => void, dev?: 'nodev', onprogress?: Function) => void) } */ - download: undefined | ((url: string, folder: string, onsuccess?: Function, onerror?: (e: Error) => void, dev?: "nodev", onprogress?: Function) => void); + download: (url: string, folder: string, onsuccess?: Function, onerror?: (e: Error) => void, dev?: 'nodev', onprogress?: Function) => void; + /** + * 检查指定的路径是否是一个文件 + * + * @param {string} fileName - 需要查询的路径 + * @param {(result: -1 | 0 | 1) => void} [callback] - 回调函数;接受的参数意义如下: + * - `-1`: 路径不存在或无法访问 + * - `0`: 路径的内容不是文件 + * - `1`: 路径的内容是文件 + * @param {(err: Error) => void} [onerror] - 接收错误的回调函数 + * @return {void} - 由于三端的异步需求和历史原因,文件管理必须为回调异步函数 + */ + checkFile: any; + /** + * 检查指定的路径是否是一个目录 + * + * @param {string} dir - 需要查询的路径 + * @param {(result: -1 | 0 | 1) => void} [callback] - 回调函数;接受的参数意义如下: + * - `-1`: 路径不存在或无法访问 + * - `0`: 路径的内容不是目录 + * - `1`: 路径的内容是目录 + * @param {(err: Error) => void} [onerror] - 接收错误的回调函数 + * @return {void} - 由于三端的异步需求和历史原因,文件管理必须为回调异步函数 + */ + checkDir: any; /** * 读取文件为arraybuffer * @type { undefined | ((filename: string, callback?: (data: Buffer | ArrayBuffer) => any, onerror?: (e: Error) => void) => void) } */ - readFile: undefined | ((filename: string, callback?: (data: Buffer | ArrayBuffer) => any, onerror?: (e: Error) => void) => void); + readFile: (filename: string, callback?: (data: Buffer | ArrayBuffer) => any, onerror?: (e: Error) => void) => void; /** * 读取文件为文本 * @type { undefined | ((filename: string, callback?: (data: string) => any, onerror?: (e: Error) => void) => void) } */ - readFileAsText: undefined | ((filename: string, callback?: (data: string) => any, onerror?: (e: Error) => void) => void); + readFileAsText: (filename: string, callback?: (data: string) => any, onerror?: (e: Error) => void) => void; /** * 将数据写入文件 * @type { undefined | ((data: File | ArrayBuffer, path: string, name: string, callback?: (e: Error) => void) => void) } */ - writeFile: undefined | ((data: File | ArrayBuffer, path: string, name: string, callback?: (e: Error) => void) => void); + writeFile: (data: File | ArrayBuffer, path: string, name: string, callback?: (e: Error) => void) => void; /** * 移除文件 * @type { undefined | ((filename: string, callback?: (e: Error) => void) => void) } */ - removeFile: undefined | ((filename: string, callback?: (e: Error) => void) => void); + removeFile: (filename: string, callback?: (e: Error) => void) => void; /** * 获取文件列表 * @type { undefined | ((dir: string, success: (folders: string[], files: string[]) => any, failure?: (e: Error) => void) => void) } */ - getFileList: undefined | ((dir: string, success: (folders: string[], files: string[]) => any, failure?: (e: Error) => void) => void); + getFileList: (dir: string, success: (folders: string[], files: string[]) => any, failure?: (e: Error) => void) => void; /** * 按路径依次创建文件夹 * @type { undefined | ((list: string | string[], callback: Function, file?: boolean) => void) } */ - ensureDirectory: undefined | ((list: string | string[], callback: Function, file?: boolean) => void); + ensureDirectory: (list: string | string[], callback: Function, file?: boolean) => void; /** * 创建文件夹 * @type { undefined | ((directory: string, successCallback?: Function, errorCallback?: Function) => void) } */ - createDir: undefined | ((directory: string, successCallback?: Function, errorCallback?: Function) => void); + createDir: (directory: string, successCallback?: Function, errorCallback?: Function) => void; /** * 删除文件夹 * @type { undefined | ((directory: string, successCallback?: Function, errorCallback?: Function) => void) } */ - removeDir: undefined | ((directory: string, successCallback?: Function, errorCallback?: Function) => void); + removeDir: (directory: string, successCallback?: Function, errorCallback?: Function) => void; /** * @type { (forcecheck?: boolean | null, dev?: boolean) => Promise } */ @@ -717,6 +803,11 @@ export class Game extends GameCompatible { playVideoContent(video: Videos): void; videoContent: { arrangeLib: (content: any) => void; + cardtag: (cardtag: any) => void; + addVirtualEquip: (player: any, map: any) => void; + addVirtualJudge: (player: any, map: any) => void; + removeVirtualEquip: (player: any, card: any) => void; + removeVirtualJudge: (player: any, card: any) => void; $syncDisable: (player: any, map: any) => void; $syncExpand: (player: any, map: any) => void; $disableJudge: (player: any, map: any) => void; @@ -858,11 +949,11 @@ export class Game extends GameCompatible { run(): void; /** * @param { string } type - * @param { Player } player + * @param { Player|null } player * @param { any } [content] * @returns */ - addVideo(type: string, player: Player, content?: any): void; + addVideo(type: string, player: Player | null, content?: any): void; /** * @param { Function } func */ @@ -881,21 +972,21 @@ export class Game extends GameCompatible { /** * @param { [number, number | {opacity:any, color:any, dashed:any, duration:any} | string, number, number] } path */ - linexy(path: [number, number | { + linexy(path: [number, string | number | { opacity: any; color: any; dashed: any; duration: any; - } | string, number, number], ...args: any[]): any; + }, number, number], ...args: any[]): any; /** * @param { [number, number | {opacity:any, color:any, dashed:any, duration:any} | string, number, number] } path */ - _linexy(path: [number, number | { + _linexy(path: [number, string | number | { opacity: any; color: any; dashed: any; duration: any; - } | string, number, number], ...args: any[]): void; + }, number, number], ...args: any[]): void; /** * @param { string } name * @param { string } skill @@ -909,9 +1000,9 @@ export class Game extends GameCompatible { * * @param { string } name * @param { false } [trigger] - * @param { GameEventPromise } [triggerEvent] + * @param { GameEvent } [triggerEvent] */ - createEvent(name: string, trigger?: false, triggerEvent?: GameEventPromise): import("../library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + createEvent(name: string, trigger?: false, triggerEvent?: GameEvent): import("../library/element/gameEvent.js").GameEvent; /** * @param { string } name * @param { { extension: string, sex: Sex, group: string, hp: string | number, skills?: string[], tags?: any[], translate: string } } information @@ -930,15 +1021,15 @@ export class Game extends GameCompatible { * @param { string } [packagename] */ addCharacterPack(pack: { + [key: string]: any; mode?: string; forbid?: any; character: { [key: string]: Character; }; skill: { - [key: string]: object; + [key: string]: any; }; - [key: string]: any; }, packagename?: string): void; /** * @param { string } name @@ -962,10 +1053,10 @@ export class Game extends GameCompatible { forbid?: string[]; list: any[]; card: { - [key: string]: Card; + [key: string]: import("noname-typings/nonameModules/noname/library/element/card.js").Card; }; skill: { - [key: string]: object; + [key: string]: any; }; }, packagename?: string): void; /** @@ -977,7 +1068,7 @@ export class Game extends GameCompatible { * @param { string } [abInfo] */ addSkill(name: string, info: { - [key: string]: object; + [key: string]: any; }, translate?: string, description?: string, appendInfo?: string, abInfo?: string): boolean; /** * @param { string } name @@ -987,7 +1078,7 @@ export class Game extends GameCompatible { addMode(name: string, info: any, info2: { translate: string; config: { - [key: string]: object; + [key: string]: any; }; }): void; /** @@ -1062,63 +1153,59 @@ export class Game extends GameCompatible { */ over(result?: boolean | string, bool?: boolean, ...args: any[]): void; /** - * @type { Map> } - * - * 以Promise储存异步事件的执行链,使async content调用事件时无需必须使用await - * - * 但是需要事件结果的除外 - */ - executingAsyncEventMap: Map>; - /** - * @type { GameEventPromise[] } - */ - belongAsyncEventList: GameEventPromise[]; - /** - * @param { GameEventPromise } [belongAsyncEvent] - */ - loop(belongAsyncEvent?: GameEventPromise): Promise; - /** - * @param { GameEventPromise } [belongAsyncEvent] + * @param { GameEvent } [event] */ - runContent(belongAsyncEvent?: GameEventPromise): Promise; - pause(): void; - pause2(): void; + loop(event?: GameEvent): Promise; + pause(): { + "__#2@#promise": Promise; + "__#2@#resolver": () => void; + readonly isStarted: boolean; + start(): void; + resolve(): void; + then(onfulfilled?: (value: void) => void | PromiseLike, onrejected?: (reason: any) => PromiseLike): Promise; + }; + pause2(): { + "__#2@#promise": Promise; + "__#2@#resolver": () => void; + readonly isStarted: boolean; + start(): void; + resolve(): void; + then(onfulfilled?: (value: void) => void | PromiseLike, onrejected?: (reason: any) => PromiseLike): Promise; + }; resume(): void; resume2(): void; - delaye(...args: any[]): import("../library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - delayex(...args: any[]): import("../library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; /** * @param { number } [time] * @param { number } [time2] */ - delay(time?: number, time2?: number): void; + delaye(time?: number, time2?: number, ...args: any[]): import("../library/element/gameEvent.js").GameEvent; /** * @param { number } [time] * @param { number } [time2] */ - delayx(time?: number, time2?: number): void; + delayex(time?: number, time2?: number, ...args: any[]): import("../library/element/gameEvent.js").GameEvent; /** - * 在async content中对game.delay的代替使用方法 - * - * 因为async content里不应该使用game.pause和game.resume - * * @param { number } [time] * @param { number } [time2] */ - asyncDelay(time?: number, time2?: number): Promise; + delay(time?: number, time2?: number): Promise; /** - * 在async content中对game.delayx的代替使用方法 - * - * 因为async content里不应该使用game.pause和game.resume - * * @param { number } [time] * @param { number } [time2] */ - asyncDelayx(time?: number, time2?: number): Promise; + delayx(time?: number, time2?: number): Promise; /** - * @param { GameEventPromise } [event] + * @deprecated + */ + asyncDelay(time: any, time2: any): Promise; + /** + * @deprecated + */ + asyncDelayx(time: any, time2: any): Promise; + /** + * @param { GameEvent } [event] */ - check(event?: GameEventPromise): boolean; + check(event?: GameEvent): boolean; Check: Check; uncheck(...args: any[]): void; /** @@ -1145,9 +1232,10 @@ export class Game extends GameCompatible { findNext(player: Player): import("noname-typings/nonameModules/noname/library/element/player.js").Player; /** * @param { string } name - * @param { Function } callback + * @param { (exports: importModeConfig) => any } [callback] + * @param { (error: unknown) => any } [onerror] */ - loadModeAsync(name: string, callback: Function): void; + loadModeAsync(name: string, callback?: (exports: importModeConfig) => any, onerror?: (error: unknown) => any): Promise; /** * @param { string } name * @param {*} configx @@ -1168,7 +1256,7 @@ export class Game extends GameCompatible { /** * @param { Player } [player] */ - gameDraw(player?: Player, num?: number): import("../library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + gameDraw(player?: Player, num?: number): import("../library/element/gameEvent.js").GameEvent; chooseCharacterDouble(...args: any[]): void; updateRoundNumber(): void; /** @@ -1179,7 +1267,7 @@ export class Game extends GameCompatible { */ asyncDraw(players: Player[], num?: number | number[] | ((player: Player) => number), drawDeck?: { drawDeck: boolean; - }, bottom?: boolean): Promise; + }, bottom?: boolean): Promise[]>; /** * @param { Player[] } players * @param { number | number[] | (player: Player) => number } num @@ -1195,9 +1283,9 @@ export class Game extends GameCompatible { */ checkMod(...args: any[]): any; /** - * @param { number } num + * @param { number } [num] */ - prepareArena(num: number): void; + prepareArena(num?: number): void; clearArena(): void; clearConnect(): void; log(...args: any[]): void; @@ -1249,9 +1337,9 @@ export class Game extends GameCompatible { * @param { string } key * @param { * } [value] * @param { string | boolean } [local] - * @param { Function } [callback] + * @param { function(): void } [callback] */ - saveConfig(key: string, value?: any, local?: string | boolean, callback?: Function): void; + saveConfig(key: string, value?: any, local?: string | boolean, callback?: () => void): void; /** * @param { string } key */ @@ -1291,7 +1379,7 @@ export class Game extends GameCompatible { /** * @param { Player } player */ - triggerEnter(player: Player): import("../library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + triggerEnter(player: Player): import("../library/element/gameEvent.js").GameEvent; /** * @param { Player } player */ @@ -1342,12 +1430,7 @@ export class Game extends GameCompatible { * @param { (player: Player) => boolean } func * @param { boolean } [includeOut] */ - countPlayer2(func: (player: Player) => boolean, includeOut?: boolean): number; - /** - * @overload - * @returns { Player[] } - */ - filterPlayer(): Player[]; + countPlayer2(func?: (player: Player) => boolean, includeOut?: boolean): number; /** * @overload * @param { (player: Player) => boolean } func @@ -1356,11 +1439,6 @@ export class Game extends GameCompatible { * @returns { Player[] } */ filterPlayer(func: (player: Player) => boolean, list?: Player[], includeOut?: boolean): Player[]; - /** - * @overload - * @returns { Player[] } - */ - filterPlayer2(): Player[]; /** * @overload * @param { (player: Player) => boolean } func @@ -1430,3 +1508,4 @@ import { GamePromises } from "./promises.js"; import { DynamicStyle } from "./dynamic-style/index.js"; import { lib } from "../library/index.js"; import { Check } from "./check.js"; +import { delay } from "../util/index.js"; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/game/promises.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/game/promises.d.ts index 64459709ff..362e5e3b06 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/game/promises.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/game/promises.d.ts @@ -43,4 +43,45 @@ export class GamePromises { * @returns { Promise<[string[], string[]]> } 返回一个数组,第一个元素是文件夹列表,第二个元素是文件列表 */ getFileList(dir: string): Promise<[string[], string[]]>; + /** + * @param { string } key + * @param { * } [value] + * @param { string | boolean } [local] + */ + saveConfig(key: string, value?: any, local?: string | boolean): Promise; + /** + * @param { string } key + */ + saveConfigValue(key: string): Promise; + /** + * @param { string } extension + * @param { string } key + * @param { * } [value] + */ + saveExtensionConfig(extension: string, key: string, value?: any): Promise; + /** + * @param { string } extension + * @param { string } key + */ + saveExtensionConfigValue(extension: string, key: string): Promise; + /** + * 检查指定的路径是否是一个文件 + * + * @param {string} fileName - 需要查询的路径 + * @return {Promise<(-1 | 0 | 1)>} - 返回值意义如下: + * - `-1`: 路径不存在或无法访问 + * - `0`: 路径的内容不是文件 + * - `1`: 路径的内容是文件 + */ + checkFile(fileName: string): Promise<(-1 | 0 | 1)>; + /** + * 检查指定的路径是否是一个目录 + * + * @param {string} dir - 需要查询的路径 + * @return {Promise<(-1 | 0 | 1)>} - 返回值意义如下: + * - `-1`: 路径不存在或无法访问 + * - `0`: 路径的内容不是目录 + * - `1`: 路径的内容是目录 + */ + checkDir(dir: string): Promise<(-1 | 0 | 1)>; } diff --git a/node_modules/@types/noname-typings/nonameModules/noname/get/audio.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/get/audio.d.ts index 16e8c5499b..bbfe23999b 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/get/audio.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/get/audio.d.ts @@ -1,162 +1,84 @@ -/** - * @typedef { (string | number | boolean)[] | string | number | boolean } AudioInfo - * @typedef { { - * audio: AudioInfo, - * audioname?: string[], - * audioname2?: { [playerName: string]: AudioInfo } - * } } SkillInfo - * @typedef { { - * name: string, - * sex:Sex, - * name1?: string, - * name2?: string, - * tempname: string[] - * skin: { name?:string } - * } } FormatedPlayer - * @typedef { { - * name: string, - * file: string, - * text: string | undefined, - * type: string, - * } } TextMap - */ -export class Audio { - /** - * @type { { [key: string]: TextMap[] } } - */ - static "__#28@#audioCache": { - [key: string]: TextMap[]; +/// +type logAudio = (...args: any[]) => AudioInfo; +type AudioInfo = AudioInfo[] | string | number | boolean; +type SkillInfo = { + audio?: AudioInfo; + audioname?: string[]; + audioname2?: { + [playerName: string]: AudioInfo; }; + logAudio?: logAudio; + logAudio2?: { + [playerName: string]: logAudio; + }; +}; +type FormatedPlayer = { + name: string; + sex: Sex; + name1?: string; + name2?: string; + tempname: string[]; + skin: { + name?: string; + }; +}; +type TextMap = { + name: string; + file: string; + text: string | undefined; + type: string; +}; +export declare class Audio { + #private; /** * 根据skill中的audio,audioname,audioname2和player来获取技能台词列表及其对应的源文件名 - * @param { object } options - * @param { string } options.skill 技能名 - * @param { Player | string } [options.player] 角色/角色名 - * @param { AudioInfo | SkillInfo } [options.info] 使用指定的skillInfo/audioInfo - * @returns { Audio } + * @param skill 技能名 + * @param player 角色/角色名 + * @param info 使用指定的skillInfo/audioInfo + * @param args */ - static skill({ skill, player, info }: { + static skill({ skill, player, info, args }: { skill: string; - player?: Player | string; + player: Player | string; info?: AudioInfo | SkillInfo; + args?: any[]; }): Audio; /** * 获取角色死亡时能播放的所有阵亡台词列表及其对应的源文件名 - * @param { object } options - * @param { Player | string } options.player 角色/角色名 - * @param { AudioInfo } [options.info] 使用指定的audioInfo - * @returns { Audio } + * @param player 角色/角色名 + * @param info 使用指定的audioInfo + * @param args */ - static die({ player, info }: { + static die({ player, info, args }: { player: Player | string; info?: AudioInfo; + args?: any[]; }): Audio; - /** - * @param { Player | string } player - * @returns { FormatedPlayer } - */ static formatPlayer(player: Player | string): FormatedPlayer; - /** - * @param {TextMap[]} list - * @returns {string[]} - */ static toFile(list: TextMap[]): string[]; - /** - * @param {TextMap[]} list - * @returns {string[]} - */ static toText(list: TextMap[]): string[]; - /** - * @param {AudioBase} audio - * @param {string[]} history - */ - constructor(audio: AudioBase, history?: string[]); - get type(): string; get name(): string; - /** - * @type { TextMap[] } - */ + get type(): string; get audioList(): TextMap[]; get fileList(): string[]; get textList(): string[]; initAudioList(): void; - getAudio(name: any, info: any): TextMap[]; + constructor(audio: AudioBase, args?: any[], history?: string[]); + getReferenceAudio(name: string, info?: any): TextMap[]; checkHistory(): boolean; - /** - * @param {string} name - * @param {AudioInfo} audioInfo - * @returns {TextMap[]} - */ parseAudio(name: string, audioInfo: AudioInfo): TextMap[]; - #private; } -export type AudioInfo = (string | number | boolean)[] | string | number | boolean; -export type SkillInfo = { - audio: AudioInfo; - audioname?: string[]; - audioname2?: { - [playerName: string]: AudioInfo; - }; -}; -export type FormatedPlayer = { - name: string; - sex: Sex; - name1?: string; - name2?: string; - tempname: string[]; - skin: { - name?: string; - }; -}; -export type TextMap = { - name: string; - file: string; - text: string | undefined; +interface AudioBase { type: string; -}; -/** - * @interface - */ -declare class AudioBase { - /** - * @type { string } - */ - type: string; - /** - * @type { string } - */ name: string; - /** - * @type { (name: string) => boolean } - */ isExist: (name: string) => boolean; - /** - * @type { string } - */ defaultPath: string; - /** - * @type { boolean } - */ + defaultInfo: AudioInfo; useCache: boolean; - /** - * @type { () => string } - */ getCacheKey: () => string; - /** - * @type { () => AudioInfo } - */ - getAudioInfo: () => AudioInfo; - /** - * @type { (name: string, info?: AudioInfo) => AudioBase } - */ - getAudio: (name: string, info?: AudioInfo) => AudioBase; - /** - * @type { ( path: string, ext: string, name: string ) => TextMap } - */ + getAudioInfo: (useDefaultInfo: boolean, args?: any[]) => AudioInfo; + getReferenceAudio: (name: string, info?: AudioInfo) => AudioBase; textMap: (path: string, ext: string, name: string) => TextMap; - /** - * @type { ( path: string, ext: string, index?: number ) => TextMap } - */ textMapWithIndex: (path: string, ext: string, index?: number) => TextMap; } export {}; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/get/compatible.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/get/compatible.d.ts new file mode 100644 index 0000000000..a737264703 --- /dev/null +++ b/node_modules/@types/noname-typings/nonameModules/noname/get/compatible.d.ts @@ -0,0 +1,27 @@ +/** + * @param { InstanceType } [instance] + */ +export function setGetCompatible(instance?: InstanceType): void; +/** + * 用于老版本能用的`get` + */ +export class GetCompatible { + /** + * + * @param {[majorVersion: number, minorVersion: number, patchVersion: number]} require + * @param {[majorVersion: number, minorVersion: number, patchVersion: number]} current + * @returns + */ + checkVersion(require: [majorVersion: number, minorVersion: number, patchVersion: number], current: [majorVersion: number, minorVersion: number, patchVersion: number]): boolean; + /** + * 获取当前内核版本信息 + * + * 目前仅考虑`chrome`, `firefox`和`safari`三种浏览器的信息,其余均归于其他范畴 + * + * > 其他后续或许会增加,但`IE`永无可能 + * + * @returns {["firefox" | "chrome" | "safari" | "other", number, number, number]} + */ + coreInfo(): ["firefox" | "chrome" | "safari" | "other", number, number, number]; +} +export let get: GetCompatible; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/get/index.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/get/index.d.ts index 5726dfe18d..a3dedf500e 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/get/index.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/get/index.d.ts @@ -2,6 +2,12 @@ export class Get extends GetCompatible { is: Is; promises: Promises; Audio: typeof Audio; + /** + * 获取装备牌对应的技能 + * @param { Card[]|VCard[] } cards + * @returns { any[] } + */ + skillsFromEquips(cards: Card[] | VCard[]): any[]; /** * 将一个传统格式的character转化为Character对象格式 * @param { Array|Object|import("../library/element/character").Character } data @@ -107,6 +113,14 @@ export class Get extends GetCompatible { numOf(obj: any, item: any): any; connectNickname(): any; zhinangs(filter: any): any; + /** + * 用于获取武将的姓氏和名字 + * @param { string } str + * @param { string|undefined } defaultSurname + * @param { string|undefined } defaultName + * @returns { Array } + */ + characterSurname(str: string, defaultSurname: string | undefined, defaultName: string | undefined): any[]; /** * 返回角色对应的原角色 * @param { string } str @@ -136,7 +150,7 @@ export class Get extends GetCompatible { cardOffset(): number; colorspan(str: any): any; evtprompt(next: any, str: any): void; - autoViewAs(card: any, cards: any): import("../library/element/vcard.js").VCard; + autoViewAs(card: any, cards: any, owner: any, ...args: any[]): import("../library/element/vcard.js").VCard; /** * @deprecated */ @@ -156,7 +170,7 @@ export class Get extends GetCompatible { * @param { T } num * @returns { Character[T] } */ - character(name: string, num: T): Character[T]; + character(name: string, num: T): Character[T]; characterInitFilter(name: any): string[]; /** * 返回武将介绍 @@ -199,7 +213,8 @@ export class Get extends GetCompatible { playerNumber(): number; benchmark(func1: any, func2: any, iteration: any, arg: any): number; /** - * @param {any} obj + * 此方法仅用作将技能/卡牌代码转为字符串,返回值无法直接进行反序列化 + * @param { any } obj * @param { number } [level = 0] */ stringify(obj: any, level?: number): any; @@ -214,7 +229,7 @@ export class Get extends GetCompatible { * @param {WeakMap} [map] - 拷贝用的临时存储,用于处理循环引用(请勿自行赋值) * @returns {T} - 深拷贝后的对象,若传入值不是对象则为传入值 */ - copy(obj: T, copyKeyDeep?: boolean, map?: WeakMap): T; + copy(obj: T_1, copyKeyDeep?: boolean, map?: WeakMap): T_1; plainTextMap: Map; /** * 用于将HTML代码转换为纯文本。 @@ -241,7 +256,7 @@ export class Get extends GetCompatible { arenaState(): { number: string; players: {}; - mode: any; + mode: string; dying: any[]; servermode: any; roomId: any; @@ -263,8 +278,12 @@ export class Get extends GetCompatible { infoTargets(infos: any): import("noname-typings/nonameModules/noname/library/element/player.js").Player[]; cardInfo(card: any): any[]; cardsInfo(cards?: any[]): any[][]; - infoCard(info: any): import("../library/element/card.js").Card; - infoCards(infos: any): import("../library/element/card.js").Card[]; + infoCard(info: any): any; + infoCards(infos: any): any[]; + vcardInfo(card: any): {}; + vcardsInfo(cards?: any[]): {}[]; + infoVCard(card: any): any; + infoVCards(infos: any): any[]; cardInfoOL(card: any): string; infoCardOL(info: any): any; cardsInfoOL(cards: any): string[]; @@ -311,6 +330,10 @@ export class Get extends GetCompatible { * @param {string} item */ infoEventOL(item: string): string | import("../library/element/gameEvent.js").GameEvent; + vcardInfoOL(item: any): string; + vcardsInfoOL(cards: any): string[]; + infoVCardOL(item: any): any; + infoVCardsOL(infos: any): any[]; stringifiedResult(item: any, level: any, nomore: any): any; parsedResult(item: any): any; verticalStr(str: any, sp: any): string; @@ -334,7 +357,58 @@ export class Get extends GetCompatible { xyDistance(from: any, to: any): number; /** * @overload - * @returns { void } + * @param { any } obj + * @returns { 'position' | 'natures' | 'nature' | 'players' | 'cards' | 'select' | 'divposition' | 'button' | 'card' | 'vcard' | 'player' | 'dialog' | 'event' | void } + * + * @overload + * @param { string } obj + * @returns { 'position' | 'natures' | 'nature' } + * + * @overload + * @param { Player[] } obj + * @returns { 'players' } + * + * @overload + * @param { Card[] } obj + * @returns { 'cards' } + * + * @overload + * @param { [number, number] } obj + * @returns { 'select' } + * + * @overload + * @param { [number, number, number, number] } obj + * @returns { 'divposition' } + * + * @overload + * @param { Button } obj + * @returns { 'button' } + * + * @overload + * @param { Card } obj + * @returns { 'card' } + * + * @overload + * @param { VCard } obj + * @returns { 'vcard' } + * + * @overload + * @param { Player } obj + * @returns { 'player' } + * + * @overload + * @param { Dialog } obj + * @returns { 'dialog' } + * + * @overload + * @param { GameEvent | GameEventPromise } obj + * @returns { 'event' } + */ + itemtype(obj: any): 'position' | 'natures' | 'nature' | 'players' | 'cards' | 'select' | 'divposition' | 'button' | 'card' | 'vcard' | 'player' | 'dialog' | 'event' | void; + /** + * @overload + * @param { any } obj + * @returns { 'position' | 'natures' | 'nature' | 'players' | 'cards' | 'select' | 'divposition' | 'button' | 'card' | 'vcard' | 'player' | 'dialog' | 'event' | void } * * @overload * @param { string } obj @@ -365,6 +439,10 @@ export class Get extends GetCompatible { * @returns { 'card' } * * @overload + * @param { VCard } obj + * @returns { 'vcard' } + * + * @overload * @param { Player } obj * @returns { 'player' } * @@ -376,10 +454,11 @@ export class Get extends GetCompatible { * @param { GameEvent | GameEventPromise } obj * @returns { 'event' } */ - itemtype(): void; + itemtype(obj: string): 'position' | 'natures' | 'nature'; /** * @overload - * @returns { void } + * @param { any } obj + * @returns { 'position' | 'natures' | 'nature' | 'players' | 'cards' | 'select' | 'divposition' | 'button' | 'card' | 'vcard' | 'player' | 'dialog' | 'event' | void } * * @overload * @param { string } obj @@ -410,6 +489,10 @@ export class Get extends GetCompatible { * @returns { 'card' } * * @overload + * @param { VCard } obj + * @returns { 'vcard' } + * + * @overload * @param { Player } obj * @returns { 'player' } * @@ -421,10 +504,11 @@ export class Get extends GetCompatible { * @param { GameEvent | GameEventPromise } obj * @returns { 'event' } */ - itemtype(obj: string): "position" | "natures" | "nature"; + itemtype(obj: Player[]): 'players'; /** * @overload - * @returns { void } + * @param { any } obj + * @returns { 'position' | 'natures' | 'nature' | 'players' | 'cards' | 'select' | 'divposition' | 'button' | 'card' | 'vcard' | 'player' | 'dialog' | 'event' | void } * * @overload * @param { string } obj @@ -455,6 +539,10 @@ export class Get extends GetCompatible { * @returns { 'card' } * * @overload + * @param { VCard } obj + * @returns { 'vcard' } + * + * @overload * @param { Player } obj * @returns { 'player' } * @@ -466,10 +554,11 @@ export class Get extends GetCompatible { * @param { GameEvent | GameEventPromise } obj * @returns { 'event' } */ - itemtype(obj: Player[]): "players"; + itemtype(obj: Card[]): 'cards'; /** * @overload - * @returns { void } + * @param { any } obj + * @returns { 'position' | 'natures' | 'nature' | 'players' | 'cards' | 'select' | 'divposition' | 'button' | 'card' | 'vcard' | 'player' | 'dialog' | 'event' | void } * * @overload * @param { string } obj @@ -500,6 +589,10 @@ export class Get extends GetCompatible { * @returns { 'card' } * * @overload + * @param { VCard } obj + * @returns { 'vcard' } + * + * @overload * @param { Player } obj * @returns { 'player' } * @@ -511,10 +604,11 @@ export class Get extends GetCompatible { * @param { GameEvent | GameEventPromise } obj * @returns { 'event' } */ - itemtype(obj: Card[]): "cards"; + itemtype(obj: [number, number]): 'select'; /** * @overload - * @returns { void } + * @param { any } obj + * @returns { 'position' | 'natures' | 'nature' | 'players' | 'cards' | 'select' | 'divposition' | 'button' | 'card' | 'vcard' | 'player' | 'dialog' | 'event' | void } * * @overload * @param { string } obj @@ -545,6 +639,10 @@ export class Get extends GetCompatible { * @returns { 'card' } * * @overload + * @param { VCard } obj + * @returns { 'vcard' } + * + * @overload * @param { Player } obj * @returns { 'player' } * @@ -556,10 +654,11 @@ export class Get extends GetCompatible { * @param { GameEvent | GameEventPromise } obj * @returns { 'event' } */ - itemtype(obj: [number, number]): "select"; + itemtype(obj: [number, number, number, number]): 'divposition'; /** * @overload - * @returns { void } + * @param { any } obj + * @returns { 'position' | 'natures' | 'nature' | 'players' | 'cards' | 'select' | 'divposition' | 'button' | 'card' | 'vcard' | 'player' | 'dialog' | 'event' | void } * * @overload * @param { string } obj @@ -590,6 +689,10 @@ export class Get extends GetCompatible { * @returns { 'card' } * * @overload + * @param { VCard } obj + * @returns { 'vcard' } + * + * @overload * @param { Player } obj * @returns { 'player' } * @@ -601,10 +704,11 @@ export class Get extends GetCompatible { * @param { GameEvent | GameEventPromise } obj * @returns { 'event' } */ - itemtype(obj: [number, number, number, number]): "divposition"; + itemtype(obj: Button): 'button'; /** * @overload - * @returns { void } + * @param { any } obj + * @returns { 'position' | 'natures' | 'nature' | 'players' | 'cards' | 'select' | 'divposition' | 'button' | 'card' | 'vcard' | 'player' | 'dialog' | 'event' | void } * * @overload * @param { string } obj @@ -635,6 +739,10 @@ export class Get extends GetCompatible { * @returns { 'card' } * * @overload + * @param { VCard } obj + * @returns { 'vcard' } + * + * @overload * @param { Player } obj * @returns { 'player' } * @@ -646,10 +754,11 @@ export class Get extends GetCompatible { * @param { GameEvent | GameEventPromise } obj * @returns { 'event' } */ - itemtype(obj: Button): "button"; + itemtype(obj: Card): 'card'; /** * @overload - * @returns { void } + * @param { any } obj + * @returns { 'position' | 'natures' | 'nature' | 'players' | 'cards' | 'select' | 'divposition' | 'button' | 'card' | 'vcard' | 'player' | 'dialog' | 'event' | void } * * @overload * @param { string } obj @@ -680,6 +789,10 @@ export class Get extends GetCompatible { * @returns { 'card' } * * @overload + * @param { VCard } obj + * @returns { 'vcard' } + * + * @overload * @param { Player } obj * @returns { 'player' } * @@ -691,10 +804,11 @@ export class Get extends GetCompatible { * @param { GameEvent | GameEventPromise } obj * @returns { 'event' } */ - itemtype(obj: Card): "card"; + itemtype(obj: VCard): 'vcard'; /** * @overload - * @returns { void } + * @param { any } obj + * @returns { 'position' | 'natures' | 'nature' | 'players' | 'cards' | 'select' | 'divposition' | 'button' | 'card' | 'vcard' | 'player' | 'dialog' | 'event' | void } * * @overload * @param { string } obj @@ -725,6 +839,10 @@ export class Get extends GetCompatible { * @returns { 'card' } * * @overload + * @param { VCard } obj + * @returns { 'vcard' } + * + * @overload * @param { Player } obj * @returns { 'player' } * @@ -736,10 +854,11 @@ export class Get extends GetCompatible { * @param { GameEvent | GameEventPromise } obj * @returns { 'event' } */ - itemtype(obj: Player): "player"; + itemtype(obj: Player): 'player'; /** * @overload - * @returns { void } + * @param { any } obj + * @returns { 'position' | 'natures' | 'nature' | 'players' | 'cards' | 'select' | 'divposition' | 'button' | 'card' | 'vcard' | 'player' | 'dialog' | 'event' | void } * * @overload * @param { string } obj @@ -770,6 +889,10 @@ export class Get extends GetCompatible { * @returns { 'card' } * * @overload + * @param { VCard } obj + * @returns { 'vcard' } + * + * @overload * @param { Player } obj * @returns { 'player' } * @@ -781,10 +904,11 @@ export class Get extends GetCompatible { * @param { GameEvent | GameEventPromise } obj * @returns { 'event' } */ - itemtype(obj: Dialog): "dialog"; + itemtype(obj: Dialog): 'dialog'; /** * @overload - * @returns { void } + * @param { any } obj + * @returns { 'position' | 'natures' | 'nature' | 'players' | 'cards' | 'select' | 'divposition' | 'button' | 'card' | 'vcard' | 'player' | 'dialog' | 'event' | void } * * @overload * @param { string } obj @@ -815,6 +939,10 @@ export class Get extends GetCompatible { * @returns { 'card' } * * @overload + * @param { VCard } obj + * @returns { 'vcard' } + * + * @overload * @param { Player } obj * @returns { 'player' } * @@ -826,7 +954,7 @@ export class Get extends GetCompatible { * @param { GameEvent | GameEventPromise } obj * @returns { 'event' } */ - itemtype(obj: GameEvent | GameEventPromise): "event"; + itemtype(obj: GameEvent | GameEventPromise): 'event'; equipNum(card: any): number; /** * 返回对象的实际类型 @@ -862,7 +990,7 @@ export class Get extends GetCompatible { * @param { DocumentFragment } obj * @returns { 'fragment' } */ - objtype(obj: any[]): "array"; + objtype(obj: any[]): 'array'; /** * 返回对象的实际类型 * @overload @@ -897,7 +1025,7 @@ export class Get extends GetCompatible { * @param { DocumentFragment } obj * @returns { 'fragment' } */ - objtype(obj: any): "object"; + objtype(obj: any): 'object'; /** * 返回对象的实际类型 * @overload @@ -932,7 +1060,7 @@ export class Get extends GetCompatible { * @param { DocumentFragment } obj * @returns { 'fragment' } */ - objtype(obj: HTMLDivElement): "div"; + objtype(obj: HTMLDivElement): 'div'; /** * 返回对象的实际类型 * @overload @@ -967,7 +1095,7 @@ export class Get extends GetCompatible { * @param { DocumentFragment } obj * @returns { 'fragment' } */ - objtype(obj: HTMLTableElement): "table"; + objtype(obj: HTMLTableElement): 'table'; /** * 返回对象的实际类型 * @overload @@ -1002,7 +1130,7 @@ export class Get extends GetCompatible { * @param { DocumentFragment } obj * @returns { 'fragment' } */ - objtype(obj: HTMLTableRowElement): "tr"; + objtype(obj: HTMLTableRowElement): 'tr'; /** * 返回对象的实际类型 * @overload @@ -1037,7 +1165,7 @@ export class Get extends GetCompatible { * @param { DocumentFragment } obj * @returns { 'fragment' } */ - objtype(obj: HTMLTableCellElement): "td"; + objtype(obj: HTMLTableCellElement): 'td'; /** * 返回对象的实际类型 * @overload @@ -1072,7 +1200,7 @@ export class Get extends GetCompatible { * @param { DocumentFragment } obj * @returns { 'fragment' } */ - objtype(obj: HTMLBodyElement): "td"; + objtype(obj: HTMLBodyElement): 'td'; /** * 返回对象的实际类型 * @overload @@ -1107,37 +1235,16 @@ export class Get extends GetCompatible { * @param { DocumentFragment } obj * @returns { 'fragment' } */ - objtype(obj: DocumentFragment): "fragment"; + objtype(obj: DocumentFragment): 'fragment'; /** * 返回牌的类型 * @overload - * @param { string } obj - * @param { 'trick' } [method] - * @param { Player } [player] - * @returns { string } - * - * @overload - * @param { Card } obj - * @param { 'trick' } [method] - * @param { Player } [player] - * @returns { string } - */ - type(obj: string, method?: "trick", player?: Player): string; - /** - * 返回牌的类型 - * @overload - * @param { string } obj - * @param { 'trick' } [method] - * @param { Player } [player] - * @returns { string } - * - * @overload - * @param { Card } obj - * @param { 'trick' } [method] - * @param { Player } [player] + * @param { Card | string } obj + * @param { 'trick' | null} [method] + * @param { Player | false } [player] * @returns { string } */ - type(obj: Card, method?: "trick", player?: Player): string; + type(obj: Card | string, method?: 'trick' | null, player?: Player | false): string; type2(card: any, player: any): string; /** * 返回牌的副类型 @@ -1229,7 +1336,7 @@ export class Get extends GetCompatible { * @param {T} key * @returns {GameEvent[T]} */ - event(key: T): GameEvent[T]; + event(key: T_2): import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent[T_2]; player(): import("noname-typings/nonameModules/noname/library/element/player.js").Player; /** * 返回玩家的数组 @@ -1239,6 +1346,14 @@ export class Get extends GetCompatible { * @returns { Player[] } */ players(sort?: any, dead?: boolean, out?: boolean): Player[]; + /** + * 返回指定角色所有的id,用于统一双将和单将的检查 + * + * @author tangXins + * @param {Player} player + * @returns {string[]} + */ + nameList(player: Player): string[]; position(card: any, ordering: any): number | "h" | "e" | "j" | "s" | "x" | "c" | "d" | "o"; /** * @@ -1259,6 +1374,12 @@ export class Get extends GetCompatible { * @returns { string } */ strNumber(num: number): string; + /** + * 返回扑克牌中的表示形式对应的数字 + * @param { string } str + * @returns { number } + */ + numString(str: string): number; /** * 将阿拉伯数字转换为中文的表达形式 * @param { number } num @@ -1277,13 +1398,13 @@ export class Get extends GetCompatible { * @param {((a: Button, b: Button) => number)} [sort] 排序函数 * @returns { Button[] } */ - selectableButtons(sort?: ((a: Button, b: Button) => number)): Button[]; + selectableButtons(sort?: (a: Button, b: Button) => number): Button[]; /** * 返回可以选择的牌 * @param {((a: Card, b: Card) => number)} [sort] 排序函数 * @returns { Card[] } */ - selectableCards(sort?: ((a: Card, b: Card) => number)): Card[]; + selectableCards(sort?: (a: Card, b: Card) => number): Card[]; /** * @returns { string[] } 技能名数组 */ @@ -1296,7 +1417,7 @@ export class Get extends GetCompatible { * @param {((a: Player, b: Player) => number)} [sort] 排序函数 * @returns { Player[] } */ - selectableTargets(sort?: ((a: Player, b: Player) => number)): Player[]; + selectableTargets(sort?: (a: Player, b: Player) => number): Player[]; filter(filter: any, i: any): any; /** * 返回玩家本回合牌的使用次数 @@ -1365,7 +1486,7 @@ export class Get extends GetCompatible { * @param { 'judge' } [method] * @returns { Player | undefined } */ - owner(card: Card, method?: "judge"): Player | undefined; + owner(card: Card, method?: 'judge'): Player | undefined; noSelected(): boolean; population(identity: any): number; totalPopulation(identity: any): number; @@ -1376,11 +1497,11 @@ export class Get extends GetCompatible { cardtag(item: Card | VCard, tag: string): any; tag(item: any, tag: any, item2: any, bool: any): any; sortCard(sort: any): (card: any) => any; - difficulty(): 2 | 1 | 3; + difficulty(): 1 | 2 | 3; cardPile(name: any, create: any): any; cardPile2(name: any): any; discardPile(name: any): any; - aiStrategy(): 2 | 1 | 3 | 4 | 5 | 6; + aiStrategy(): 5 | 1 | 2 | 3 | 4 | 6; skillintro(name: any, learn: any, learn2: any): string; intro(name: any): string; storageintro(type: any, content: any, player: any, dialog: any, skill: any): any; @@ -1400,7 +1521,7 @@ export class Get extends GetCompatible { unuseful3(card: any): number; value(card: any, player: any, method: any): any; equipResult(player: any, target: any, name: any): number; - equipValue(card: any, player: any): number; + equipValue(card: any, player: any): any; equipValueNumber(card: any): number; disvalue(card: any, player: any): number; disvalue2(card: any, player: any): number; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/get/is.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/get/is.d.ts index 5f43cd24b9..b2bf2063e4 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/get/is.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/get/is.d.ts @@ -142,16 +142,10 @@ export class Is { object(obj: any): boolean; /** * @overload - * @param { Function } func - * @returns { false } - */ - singleSelect(func: Function): false; - /** - * @overload - * @param { number | [number, number] } func + * @param { Function | number | [number, number] } func * @returns { boolean } */ - singleSelect(func: number | [number, number]): boolean; + singleSelect(func: Function | number | [number, number]): boolean; /** * @param { string | Player } name */ @@ -176,8 +170,9 @@ export class Is { empty(obj: {}): boolean; /** * @param { string } str + * @returns { str is "h" | "e" | "j" | "he" | "hej" | "ej" | "hj" } */ - pos(str: string): str is "h" | "e" | "j" | "he" | "hej" | "ej" | "hj"; + pos(str: string): str is "h" | "e" | "j" | "hej" | "he" | "ej" | "hj"; /** * @param { string } skill * @param { Player } player @@ -190,4 +185,13 @@ export class Is { * @returns */ zhuanhuanji(skill: string, player: Player): boolean; + /** + * 检查指定玩家的名称的子串是否包含指定字符串 + * + * @author tangXins + * @param {Player} player + * @param {string} name + * @returns {boolean} + */ + playerNames(player: Player, name: string): boolean; } diff --git a/node_modules/@types/noname-typings/nonameModules/noname/gnc/index.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/gnc/index.d.ts index 0d1fb68dfa..b90b248263 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/gnc/index.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/gnc/index.d.ts @@ -1,9 +1,10 @@ export class GNC { /** - * @param {GeneratorFunction} fn - * @returns + * @template {GeneratorFunction} T + * @param {T} fn + * @returns { (...args: Parameters) => Promise> } */ - of(fn: GeneratorFunction): (...args: Parameters) => Promise>; + of(fn: T): (...args: Parameters) => Promise>; is: Is; } export let gnc: GNC; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/init/import.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/init/import.d.ts index f2362bb817..5f037dfa01 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/init/import.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/init/import.d.ts @@ -1,20 +1,4 @@ -/** - * @param {string} name - 卡牌包名 - * @returns {Promise} - */ -export const importCardPack: (name: string) => Promise; -/** - * @param {string} name - 武将包名 - * @returns {Promise} - */ -export const importCharacterPack: (name: string) => Promise; -/** - * @param {string} name - 扩展名 - * @returns {Promise} - */ -export const importExtension: (name: string) => Promise; -/** - * @param {string} name - 模式名 - * @returns {Promise} - */ -export const importMode: (name: string) => Promise; +export function importCardPack(name: string): Promise; +export function importCharacterPack(name: string): Promise; +export function importExtension(name: string): Promise; +export function importMode(name: string): Promise; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/init/index.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/init/index.d.ts index 51456cf8cf..8360a96a7d 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/init/index.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/init/index.d.ts @@ -5,3 +5,4 @@ export function canUseHttpProtocol(): boolean; */ export function sendUpdate(): string | void; export function boot(): Promise; +export { onload } from "./onload.js"; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/init/loading.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/init/loading.d.ts new file mode 100644 index 0000000000..29cb434043 --- /dev/null +++ b/node_modules/@types/noname-typings/nonameModules/noname/init/loading.d.ts @@ -0,0 +1,29 @@ +/** + * 读取导入的卡牌包信息 + * + * @param {importCardConfig} cardConfig + */ +export function loadCard(cardConfig: importCardConfig): void; +/** + * 读取牌堆信息 + */ +export function loadCardPile(): void; +/** + * 读取导入的武将包信息 + * + * @param {importCharacterConfig} character + */ +export function loadCharacter(character: importCharacterConfig): void; +export function loadExtension(extension: any): Promise; +/** + * 读取当前的模式信息 + * + * @param {importModeConfig} mode + */ +export function loadMode(mode: importModeConfig): void; +/** + * 读取导入的play信息 + * + * @param {importPlayConfig} playConfig + */ +export function loadPlay(playConfig: importPlayConfig): void; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/init/onload.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/init/onload.d.ts index ac51a2127a..1797f40dce 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/init/onload.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/init/onload.d.ts @@ -1 +1 @@ -export function onload(resetGameTimeout: any): Promise; +export function onload(): Promise; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/init/onload/index.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/init/onload/index.d.ts new file mode 100644 index 0000000000..e01f04e746 --- /dev/null +++ b/node_modules/@types/noname-typings/nonameModules/noname/init/onload/index.d.ts @@ -0,0 +1,3 @@ +export const defaultSplashs: (DefaultSplash | WideSplash)[]; +import { DefaultSplash } from "./default-splash.js"; +import { WideSplash } from "./wide-splash.js"; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/channel/index.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/channel/index.d.ts index 3933715011..a929b8a42f 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/channel/index.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/channel/index.d.ts @@ -9,7 +9,7 @@ export class Channel { /** * @type {PromiseResolve | [T, PromiseResolve] | null} */ - _buffer: ((value?: T | PromiseLike) => void) | [T, (value?: void | PromiseLike) => void] | null; + _buffer: ((value?: T | PromiseLike) => void) | [T, (value?: void | PromiseLike) => void]; /** * 向该频道发送消息,在消息未被接受前将等待 * diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/GameEventManager.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/GameEventManager.d.ts new file mode 100644 index 0000000000..7c203da255 --- /dev/null +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/GameEventManager.d.ts @@ -0,0 +1,11 @@ +import { GameEvent } from "../gameEvent.js"; +export default class GameEventManager { + get [Symbol.toStringTag](): string; + eventStack: GameEvent[]; + rootEvent?: GameEvent; + tempEvent?: GameEvent; + get event(): GameEvent; + getStartedEvent(): GameEvent; + getStatusEvent(): GameEvent; + setStatusEvent(event: GameEvent): void; +} diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/ArrayCompiler.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/ArrayCompiler.d.ts new file mode 100644 index 0000000000..7d49a00c10 --- /dev/null +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/ArrayCompiler.d.ts @@ -0,0 +1,7 @@ +import ContentCompilerBase from "./ContentCompilerBase.ts"; +import { EventContent, GameEvent } from "./IContentCompiler.ts"; +export default class ArrayCompiler extends ContentCompilerBase { + type: string; + filter(content: EventContent): boolean; + compile(content: EventContent): (event: GameEvent) => Promise; +} diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/AsyncCompiler.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/AsyncCompiler.d.ts new file mode 100644 index 0000000000..df42ad4631 --- /dev/null +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/AsyncCompiler.d.ts @@ -0,0 +1,7 @@ +import ContentCompilerBase from "./ContentCompilerBase.ts"; +import { EventContent } from "./IContentCompiler.ts"; +export default class AsyncCompiler extends ContentCompilerBase { + type: string; + filter(content: EventContent): boolean; + compile(content: EventContent): import("./IContentCompiler.ts").EventCompiledContent; +} diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/ContentCompiler.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/ContentCompiler.d.ts new file mode 100644 index 0000000000..bb64cb7f83 --- /dev/null +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/ContentCompiler.d.ts @@ -0,0 +1,35 @@ +import IContentCompiler, { EventCompileable, EventCompiledContent } from "./IContentCompiler.ts"; +declare class ContentCompiler { + #private; + /** + * ```plain + * 注册一个编译器实例 + * + * 如果后面开始全面迁移到 TypeScript,那么请使用依赖注入代替这个方法喵 + * ``` + * + * @todo 应该使用依赖注入替代 + * @param compiler 编译器实例对象 + */ + addCompiler(compiler: IContentCompiler): void; + /** + * ```plain + * 对无法直接编译的数据做处理 + * ``` + * + * @param content + * @returns + */ + private regularize; + /** + * ```plain + * 集成的编译函数 + * 通过责任链模式将content分发给所有注册的编译器喵 + * ``` + * + * @param content + */ + compile(content: EventCompileable): EventCompiledContent; +} +declare const compiler: ContentCompiler; +export default compiler; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/ContentCompilerBase.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/ContentCompilerBase.d.ts new file mode 100644 index 0000000000..674afaadd5 --- /dev/null +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/ContentCompilerBase.d.ts @@ -0,0 +1,34 @@ +import IContentCompiler, { EventContent, GameEvent } from "./IContentCompiler.js"; +/** + * 向子类提供统一的公共方法 + */ +export default abstract class ContentCompilerBase implements IContentCompiler { + abstract type: string; + abstract filter(content: EventContent): boolean; + abstract compile(content: EventContent): ((e: GameEvent) => Promise); + /** + * ```plain + * 对于事件执行前的一些准备工作 + * ``` + * + * @param event 事件 + */ + beforeExecute(event: GameEvent): void; + /** + * ```plain + * 判断事件能否继续执行 + * ``` + * + * @param event 事件 + * @returns 当返回true时,代表event.finish()已经被调用 + */ + isPrevented(event: GameEvent): boolean; + /** + * ```plain + * 对于事件执行后的一些收尾工作 + * ``` + * + * @param event 事件 + */ + afterExecute(event: GameEvent): void; +} diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/IContentCompiler.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/IContentCompiler.d.ts new file mode 100644 index 0000000000..610f8a5f13 --- /dev/null +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/IContentCompiler.d.ts @@ -0,0 +1,37 @@ +import { lib } from "../../../../../noname.js"; +import { GameEvent } from "../../gameEvent.js"; +export type EventContent = Function | Function[]; +export type EventCompileable = EventContent | Iterable | keyof typeof lib.element.content; +export { GameEvent }; +export type EventCompiledContent = ((e: GameEvent) => Promise) & { + compiled: true; + type: string; + original: EventCompileable; + /** + * array content的原始值 + */ + originals?: Function[]; +}; +export default interface IContentCompiler { + /** + * ```plain + * 当前编译器的事件content类型 + * ``` + */ + type: string; + /** + * ```plain + * 判断事件content是否被当前编译器支持 + * ``` + * + * @param content 事件content + */ + filter(content: EventContent): boolean; + /** + * 对content执行编译 + * 并返回标准的事件content + * + * @param content 要编译的content + */ + compile(content: EventCompileable): ((e: GameEvent) => Promise); +} diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/StepCompiler.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/StepCompiler.d.ts new file mode 100644 index 0000000000..1bf872781c --- /dev/null +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/StepCompiler.d.ts @@ -0,0 +1,7 @@ +import { EventContent, GameEvent } from "./IContentCompiler.ts"; +import ContentCompilerBase from "./ContentCompilerBase.ts"; +export default class StepCompiler extends ContentCompilerBase { + type: string; + filter(content: EventContent): boolean; + compile(content: EventContent): (e: GameEvent) => Promise; +} diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/YieldCompiler.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/YieldCompiler.d.ts new file mode 100644 index 0000000000..13b83b3fee --- /dev/null +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/compilers/YieldCompiler.d.ts @@ -0,0 +1,8 @@ +import { EventContent, GameEvent } from "./IContentCompiler.ts"; +import ContentCompilerBase from "./ContentCompilerBase.ts"; +export default class YieldCompiler extends ContentCompilerBase { + #private; + type: string; + filter(content: EventContent): boolean; + compile(content: EventContent): (event: GameEvent) => Promise; +} diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/button.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/button.d.ts index 4ea7a8776d..2432db0576 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/element/button.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/button.d.ts @@ -6,7 +6,7 @@ export class Button extends HTMLDivElement { * @param {true} [noClick] * @param { Button } [button] */ - constructor(item: {}, type: keyof typeof ui.create.buttonPresets | ((item: {}, type: Function, position?: HTMLDivElement | DocumentFragment, noClick?: true, button?: Button) => Button), position?: HTMLDivElement | DocumentFragment, noClick?: true, button?: Button); + constructor(item: {}, type: "player" | "card" | "tdnodes" | "blank" | "vcard" | "character" | "characterx" | ((item: {}, type: Function, position?: HTMLDivElement | DocumentFragment, noClick?: true, button?: Button) => Button), position?: HTMLDivElement | DocumentFragment, noClick?: true, button?: Button); /** * @type { string | undefined } */ diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/card.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/card.d.ts index 4c7e11d493..8b3d590010 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/element/card.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/card.d.ts @@ -7,7 +7,7 @@ export class Card extends HTMLDivElement { * @param {'noclick'} [info] * @param {true} [noclick] */ - build(info?: "noclick", noclick?: true): this; + build(info?: 'noclick', noclick?: true): this; buildEventListener(info: any): void; buildProperty(): void; /** @@ -38,6 +38,12 @@ export class Card extends HTMLDivElement { * @type { boolean } */ isCard: boolean; + /** + * @type { string[] } + * 卡牌“占用的装备栏” + * TODO: 补充对应的typings + */ + subtypes: string[]; selfDestroy(event: any): void; willBeDestroyed(targetPosition: any, player: any, event: any): any; hasNature(nature: any, player: any): boolean; @@ -103,10 +109,10 @@ export class Card extends HTMLDivElement { classListContainsAll(...args: any[]): boolean; /** * 返回一个键值,用于在缓存中作为键名。 - * + * @param { boolean } [similar] false统一前缀 * @returns {string} cacheKey */ - getCacheKey(): string; + getCacheKey(similar?: boolean): string; discard(bool: any): void; hasTag(tag: any): boolean; hasPosition(): boolean; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/character.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/character.d.ts index 02a5282716..a354199439 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/element/character.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/character.d.ts @@ -23,6 +23,11 @@ export class Character { * @type { number } **/ hujia: number; + /** + * 武将姓名 + * @type { string|undefined } + */ + names: string | undefined; /** * 武将牌的势力 * @type { string } @@ -143,6 +148,11 @@ export class Character { * @type { string[] } **/ clans: string[]; + /** + * 武将牌的图片信息 + * @type {string | undefined} + */ + img: string | undefined; /** * 武将牌拥有的全部阵亡语音 * @type { string[] } diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/client.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/client.d.ts index 9da74b3dae..14b7ec7692 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/element/client.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/client.d.ts @@ -3,7 +3,7 @@ export class Client { * @param {import('../index.js').NodeWS | InstanceType | Client} ws * @param {boolean} temp */ - constructor(ws: import("../index.js").NodeWS | InstanceType | Client, temp?: boolean); + constructor(ws: import('../index.js').NodeWS | InstanceType | Client, temp?: boolean); ws: any; /** * @type { string } diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/content.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/content.d.ts index a0abf206b4..e2782fd4c5 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/element/content.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/content.d.ts @@ -1,5 +1,5 @@ export namespace Content { - function emptyEvent(): void; + function emptyEvent(event: any): Promise; function changeCharacter(event: any, trigger: any, player: any): Promise; function changeSkills(event: any, trigger: any, player: any): Promise; function addShownCards(): void; @@ -10,8 +10,10 @@ export namespace Content { function disableEquip(): void; function enableEquip(): void; function expandEquip(): void; - function replaceEquip(): void; - function equip(): void; + function replaceEquip(event: any, trigger: any, player: any): Promise; + function replaceEquip_old(): void; + function equip(event: any, trigger: any, player: any): Promise; + function equip_old(): void; function changeGroup(): void; function chooseToDebate(): void; function delay(): void; @@ -28,8 +30,8 @@ export namespace Content { function cardsGotoOrdering(): void; function cardsGotoSpecial(): void; function cardsGotoPile(): void; - function chooseToEnable(): void; - function chooseToDisable(): void; + function chooseToEnable(event: import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent, trigger: import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent, player: import("noname-typings/nonameModules/noname/library/element/player.js").Player): Promise; + function chooseToDisable(event: import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent, trigger: import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent, player: import("noname-typings/nonameModules/noname/library/element/player.js").Player): Promise; function swapEquip(): void; function disableJudge(): void; function enableJudge(): void; @@ -44,7 +46,7 @@ export namespace Content { function gameDraw(): void; function phaseLoop(): void; function loadPackage(): void; - function loadMode(): void; + function loadMode(event: any): Promise; function forceOver(): void; function arrangeTrigger(event: any, trigger: any, player: any): Promise; function createTrigger(): any; @@ -110,7 +112,8 @@ export namespace Content { function changeHujia(): void; function dying(): void; function die(): void; - function addJudge(): void; + function addJudge(event: any, trigger: any, player: any): Promise; + function addJudge_old(): void; function judge(): void; function turnOver(): void; function link(): void; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/contents.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/contents.d.ts deleted file mode 100644 index 64d9acd0f7..0000000000 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/element/contents.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -/** - * @type { SMap<((event: GameEventPromise, trigger: GameEventPromise, player: Player) => Promise)[]> } - */ -export const Contents: SMap<((event: GameEventPromise, trigger: GameEventPromise, player: Player) => Promise)[]>; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/gameEvent.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/gameEvent.d.ts index 4b6bc6a9f1..2b8a1fd8f7 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/element/gameEvent.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/gameEvent.d.ts @@ -1,49 +1,34 @@ -export class GameEvent { - static initialGameEvent(): GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; +/** + * @implements { PromiseLike> } + */ +export class GameEvent implements PromiseLike> { + static initialGameEvent(): GameEvent; /** - * @param {string | GameEvent} [name] - * @param {false} [trigger] + * @param { string | GameEvent } [name] + * @param { boolean } [trigger] + * @param { GameEventManager } [manager] */ - constructor(name?: string | GameEvent, trigger?: false); + constructor(name?: string | GameEvent, trigger?: boolean, manager?: GameEventManager); /** * @type { string } */ name: string; - step: number; - finished: boolean; /** - * @type {GameEventPromise[]} + * @type { GameEventManager } */ - next: GameEventPromise[]; + manager: GameEventManager; /** - * @type {GameEventPromise[]} + * @type { number | null } */ - after: GameEventPromise[]; - custom: { - add: {}; - replace: {}; - }; - _aiexclude: any[]; - _notrigger: any[]; + _triggered: number | null; /** * @type { Result } */ - _result: Result; - _set: any[]; - /** - * @type {boolean} 这个事件是否使用异步函数处理 - **/ - async: boolean; - /** - * @type {null|((event: GameEvent | PromiseLike)=>void)} 这个异步事件对应Promise的resolve函数 - **/ - resolve: null | ((event: GameEvent | PromiseLike) => void); + result: Result; /** - * @type {null|((value?: any) => void)} 另一种结束event.content的resolve形式 - **/ - resolveContent: null | ((value?: any) => void); - _triggered: number; - __args: any; + * @type { string } + */ + type: string; /** * @type { Player } */ @@ -84,58 +69,88 @@ export class GameEvent { * @type { number } */ num: number; + /** + * @type { number } + */ + original_num: number; /** * @type { GameEvent } */ _trigger: GameEvent; /** - * @type { number } + * @type { string } */ - baseDamage: number; + triggername: string; /** - * @type { Player } + * @type { boolean } */ - customSource: Player; + notrigger: boolean; /** - * @type { number } + * @type { Player[] } */ - extraDamage: number; + _notrigger: Player[]; /** - * @type { string } + * @type { Result } */ - nature: string; + _result: Result; + /** + * @type { any[] } + */ + _args: any[]; + /** + * @type { [string, any][] } + */ + _set: [string, any][]; + /** + * @type { { + * add: {[type: string]: () => void} + * replace: {[type :string]: () => void} + * } } + */ + custom: { + add: { + [type: string]: () => void; + }; + replace: { + [type: string]: () => void; + }; + }; /** * @type { boolean } */ - notrigger: boolean; + directHit: boolean; /** * @type { number } */ - original_num: number; + baseDamage: number; /** - * @type { boolean } + * @type { number } */ - unreal: boolean; + extraDamage: number; /** - * @type { Button[] } + * @type { Player } */ - excludeButton: Button[]; + customSource: Player; /** - * @type { Result } + * @type { string } */ - result: Result; + nature: string; + /** + * @type { boolean } + */ + unreal: boolean; /** - * @type { GameEventPromise | void | null } + * @type { Button[] } */ - parent: GameEventPromise | void | null; + excludeButton: Button[]; /** - * @type { (this: GameEventPromise) => any | undefined | void | null } + * @type { ((this: this) => boolean) | undefined } */ - filterStop: (this: GameEventPromise) => any | undefined | void | null; + filterStop: (this: this) => boolean; /** * @type { Result['cost_data'] } */ - cost_data: Result["cost_data"]; + cost_data: Result['cost_data']; /** * @type { boolean } */ @@ -161,13 +176,9 @@ export class GameEvent { */ ai: Function | undefined; /** - * @type { string } - */ - triggername: string; - /** - * @type { ContentFuncByAll | GeneratorContentFuncByAll | OldContentFuncByAll } + * @type { string[] } */ - content: ContentFuncByAll | GeneratorContentFuncByAll | OldContentFuncByAll; + _aiexclude: string[]; /** * @type { boolean } */ @@ -211,22 +222,23 @@ export class GameEvent { * @returns {this} */ callHandler(type: Parameters[0], event: GameEvent, option: { - state?: "begin" | "end"; + state?: 'begin' | 'end'; }): this; getDefaultHandlerType(): string; + getDefaultNextHandlerType(): string; /** * @param {Parameters[0]} [type] * @returns {((event: GameEvent, option: { * state?: 'begin' | 'end'; * }) => void)[]} */ - getHandler(type?: Parameters[0]): ((event: GameEvent, option: { - state?: "begin" | "end"; + getHandler(type?: any): ((event: GameEvent, option: { + state?: 'begin' | 'end'; }) => void)[]; /** * @param {`on${Capitalize}`} [type] */ - hasHandler(type?: `on${Capitalize}`): boolean; + hasHandler(type?: `on${Capitalize}`): any; /** * @overload * @param {...((event: GameEvent, option: { @@ -235,8 +247,8 @@ export class GameEvent { * @returns {number} */ pushHandler(...handlers: ((event: GameEvent, option: { - state?: "begin" | "end"; - }) => void)[][]): number; + state?: 'begin' | 'end'; + }) => void)[]): number; /** * @overload * @param {Parameters[0]} type @@ -246,11 +258,8 @@ export class GameEvent { * @returns {number} */ pushHandler(type: Parameters[0], ...handlers: ((event: GameEvent, option: { - state?: "begin" | "end"; - }) => void)[][]): number; - changeToZero(): this; - numFixed: boolean; - finish(): this; + state?: 'begin' | 'end'; + }) => void)[]): number; putStepCache(key: any, value: any): this; _stepCache: {}; getStepCache(key: any): any; @@ -259,27 +268,35 @@ export class GameEvent { putTempCache(key1: any, key2: any, value: any): any; _tempCache: {}; getTempCache(key1: any, key2: any): any; - cancel(arg1: any, arg2: any, notrigger: any): GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - neutralize(event: any): this; + changeToZero(): this; + numFixed: boolean; + finish(): void; + /** + * @type { boolean } + */ + finished: boolean; + cancel(all: any, player: any, notrigger: any): GameEvent; + neutralize(event?: import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent): Promise>; + /** + * @type { boolean } + */ _neutralized: boolean; - _neutralize_event: any; - unneutralize(): this; - directHit: boolean; + _neutralize_event: import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent; + unneutralize(): void; goto(step: any): this; + set step(num: number); + get step(): number; redo(): this; setHiddenSkill(skill: any): this; set(key: any, value: any, ...args: any[]): this; /** - * @param {ArrayLike | Function | keyof typeof lib.element.content} item + * @param {import("./GameEvent/compilers/IContentCompiler.js").EventCompileable} content */ - setContent(item: ArrayLike | Function | keyof typeof lib.element.content): this; + setContent(content: import("./GameEvent/compilers/IContentCompiler.js").EventCompileable): this; /** - * - * @param {Function | keyof typeof lib.element.contents} contents - * @returns {GameEvent} + * @type { import("./GameEvent/compilers/IContentCompiler.js").EventCompiledContent } */ - setContents(contents: Function | keyof typeof lib.element.contents): GameEvent; - contents: (string | number | Function) & any[]; + content: import("./GameEvent/compilers/IContentCompiler.js").EventCompiledContent; getLogv(): any; send(): this; resume(): this; @@ -292,13 +309,13 @@ export class GameEvent { * @param {boolean} [includeSelf] 若level不是数字,指定搜索时是否包含事件本身 * @returns {GameEvent|{}|null} */ - getParent(level?: number | string | ((evt: GameEvent) => boolean), forced?: boolean, includeSelf?: boolean): GameEvent | {} | null; + getParent(level?: string | number | ((evt: GameEvent) => boolean), forced?: boolean, includeSelf?: boolean): GameEvent | {} | null; getTrigger(): any; getRand(name: any): any; _rand_map: {}; _rand: number; - insert(content: any, map: any): GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - insertAfter(content: any, map: any): GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + insert(content: any, map: any): GameEvent; + insertAfter(content: any, map: any): GameEvent; backup(skill: any): this; _backup: any; filterButton: any; @@ -328,12 +345,214 @@ export class GameEvent { isPhaseUsing(player: any): boolean; addTrigger(skills: any, player: any): this; removeTrigger(skills: any, player: any): this; - trigger(name: any): GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + /** + * + * @param { string } name + * @returns { GameEvent } + */ + trigger(name: string): GameEvent; untrigger(all: boolean, player: any): this; /** - * 事件转为Promise化 + * @deprecated + */ + toPromise(): this; + /** + * @deprecated + */ + toEvent(): this; + /** + * @type { GameEvent | void | null } */ - toPromise(): this & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + parent: GameEvent | void | null; + /** + * @type { GameEvent[] } + */ + childEvents: GameEvent[]; + /** + * @type { GameEvent | undefined } + */ + _triggering: GameEvent | undefined; + updateStep(): void; + /** + * @type { GameEvent[] } + */ + next: GameEvent[]; + /** + * @type { GameEvent[] } + */ + after: GameEvent[]; + /** + * @template TResult1 + * @template TResult2 + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param { ((event: Omit) => TResult1 | Promise) | null } [onfulfilled] The callback to execute when the Promise is resolved. + * @param { ((reason: any) => TResult2 | Promise) | null } [onrejected] The callback to execute when the Promise is rejected. + * @returns { Promise } A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: (event: Omit) => TResult1 | Promise, onrejected?: (reason: any) => TResult2 | Promise): Promise; + /** + * @template TResult + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected.* @param { ((reason: any) => TResult | Promise) | null } [onrejected] The callback to execute when the Promise is rejected. + * @returns { Promise | TResult> } A Promise for the completion of which ever callback is executed. + */ + catch(onrejected?: (reason: any) => TResult | Promise): Promise | TResult>; + /** + * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The + * resolved value cannot be modified from the callback. + * @param { (() => void) | null } [onfinally] The callback to execute when the Promise is settled (fulfilled or rejected). + * @returns { Promise> } A Promise for the completion of the callback. + */ + finally(onfinally?: (() => void) | null): Promise>; + resolve(): void; + start(): Promise; + loop(): Promise; + checkSkipped(): Promise; + waitNext(): Promise; + /** + * 获取 Result 对象中的信息。 + * @example + * ```js + // 示例 1: + const chooseCardResult = await player.chooseCard().forResult(); + // 获取整个结果对象,然后访问如 chooseCardResult.cards 等属性 + + // 示例 2: + const cards = await player.chooseCard().forResult('cards'); + // 获取结果对象中 'cards' 属性的值 + + // 示例 3: + const [success, cards, targets] = await player.chooseCardTarget().forResult('bool', 'cards', 'targets'); + // 获取结果对象中多个属性的值 + // - success 表示是否成功 + // - cards 表示选择的卡片 + // - targets 表示选择的目标 + ``` + * @template {keyof Result} T + * @this GameEvent + * @overload + * @returns {Promise} + * + * @overload + * @param {T} param0 + * @returns {Promise>} + * + * @overload + * @param { T[] } params + * @returns { Promise[]> } + */ + forResult(): Promise; + /** + * 获取 Result 对象中的信息。 + * @example + * ```js + // 示例 1: + const chooseCardResult = await player.chooseCard().forResult(); + // 获取整个结果对象,然后访问如 chooseCardResult.cards 等属性 + + // 示例 2: + const cards = await player.chooseCard().forResult('cards'); + // 获取结果对象中 'cards' 属性的值 + + // 示例 3: + const [success, cards, targets] = await player.chooseCardTarget().forResult('bool', 'cards', 'targets'); + // 获取结果对象中多个属性的值 + // - success 表示是否成功 + // - cards 表示选择的卡片 + // - targets 表示选择的目标 + ``` + * @template {keyof Result} T + * @this GameEvent + * @overload + * @returns {Promise} + * + * @overload + * @param {T} param0 + * @returns {Promise>} + * + * @overload + * @param { T[] } params + * @returns { Promise[]> } + */ + forResult(param0: T): Promise>; + /** + * 获取 Result 对象中的信息。 + * @example + * ```js + // 示例 1: + const chooseCardResult = await player.chooseCard().forResult(); + // 获取整个结果对象,然后访问如 chooseCardResult.cards 等属性 + + // 示例 2: + const cards = await player.chooseCard().forResult('cards'); + // 获取结果对象中 'cards' 属性的值 + + // 示例 3: + const [success, cards, targets] = await player.chooseCardTarget().forResult('bool', 'cards', 'targets'); + // 获取结果对象中多个属性的值 + // - success 表示是否成功 + // - cards 表示选择的卡片 + // - targets 表示选择的目标 + ``` + * @template {keyof Result} T + * @this GameEvent + * @overload + * @returns {Promise} + * + * @overload + * @param {T} param0 + * @returns {Promise>} + * + * @overload + * @param { T[] } params + * @returns { Promise[]> } + */ + forResult(params: T[]): Promise[]>; + /** + * 返回result中的bool项 + */ + forResultBool(): Promise; + /** + * 返回result中的targets项。 + */ + forResultTargets(): Promise; + /** + * 返回result中的cards项 + */ + forResultCards(): Promise; + /** + * 返回result中的card项 + * + * @returns {Promise|Promise} 返回的card项。 + * + */ + forResultCard(): Promise | Promise; + /** + * 返回result中的control项。 + */ + forResultControl(): Promise; + /** + * 返回result中的links项。 + */ + forResultLinks(): Promise; + /** + * 在某个异步事件中调试变量信息 + * + * 注: 在调试步骤中`定义的变量只在当前输入的语句有效` + * + * @example + * 在技能中调试技能content相关的信息 + * ```js + * await event.debugger(); + * ``` + * 在技能中调试触发此技能事件的相关的信息 + * ```js + * await trigger.debugger(); + * ``` + */ + debugger(): Promise; #private; } -import { lib } from "../index.js"; +import GameEventManager from "./GameEvent/GameEventManager.js"; +import ContentCompiler from "./GameEvent/compilers/ContentCompiler.js"; +export { GameEventManager, ContentCompiler }; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/gameEventPromise.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/gameEventPromise.d.ts index 93ff7357f9..9743ad3c6f 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/element/gameEventPromise.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/gameEventPromise.d.ts @@ -1,171 +1 @@ -/** - * 将事件Promise化以使用async异步函数来执行事件。 - * - * 事件Promise化后,需要既能使用await等待事件完成, - * 又需要在执行之前对事件进行配置。 - * - * 所以这个类的实例集成了事件和Promise二者的所有属性, - * 且Promise的原有属性无法被修改,一切对这个类实例的属性修改,删除, - * 再配置等操作都会转发到事件对应的属性中。 - * - * @extends {Promise} - * - * @example - * 使用await xx()等待异步事件执行: - * ```js - * await game.xxx().setContent('yyy').set(zzz, 'i'); - * ``` - * 使用await player.xxx()等待异步事件执行: - * ```js - * await player.draw(2); - * game.log('等待', player, '摸牌完成执行log'); - * ``` - */ -export class GameEventPromise extends Promise { - /** - * @param { GameEvent } arg - */ - constructor(arg: GameEvent); - /** 获取原事件对象 */ - toEvent(): import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent; - /** - * 在某个异步事件中调试变量信息 - * - * 注: 在调试步骤中`定义的变量只在当前输入的语句有效` - * - * @example - * 在技能中调试技能content相关的信息 - * ```js - * await event.debugger(); - * ``` - * 在技能中调试触发此技能事件的相关的信息 - * ```js - * await trigger.debugger(); - * ``` - */ - debugger(): Promise; - /** - * 获取 Result 对象中的信息。 - * @example - * ```js - // 示例 1: - const chooseCardResult = await player.chooseCard().forResult(); - // 获取整个结果对象,然后访问如 chooseCardResult.cards 等属性 - - // 示例 2: - const cards = await player.chooseCard().forResult('cards'); - // 获取结果对象中 'cards' 属性的值 - - // 示例 3: - const [success, cards, targets] = await player.chooseCardTarget().forResult('bool', 'cards', 'targets'); - // 获取结果对象中多个属性的值 - // - success 表示是否成功 - // - cards 表示选择的卡片 - // - targets 表示选择的目标 - ``` - * @template {keyof Result} T - * @overload - * @returns {Promise} - * - * @overload - * @param {T} param0 - * @returns {Promise>} - * - * @overload - * @param { T[] } params - * @returns { Promise[]> } - */ - forResult(): Promise; - /** - * 获取 Result 对象中的信息。 - * @example - * ```js - // 示例 1: - const chooseCardResult = await player.chooseCard().forResult(); - // 获取整个结果对象,然后访问如 chooseCardResult.cards 等属性 - - // 示例 2: - const cards = await player.chooseCard().forResult('cards'); - // 获取结果对象中 'cards' 属性的值 - - // 示例 3: - const [success, cards, targets] = await player.chooseCardTarget().forResult('bool', 'cards', 'targets'); - // 获取结果对象中多个属性的值 - // - success 表示是否成功 - // - cards 表示选择的卡片 - // - targets 表示选择的目标 - ``` - * @template {keyof Result} T - * @overload - * @returns {Promise} - * - * @overload - * @param {T} param0 - * @returns {Promise>} - * - * @overload - * @param { T[] } params - * @returns { Promise[]> } - */ - forResult(param0: T): Promise>; - /** - * 获取 Result 对象中的信息。 - * @example - * ```js - // 示例 1: - const chooseCardResult = await player.chooseCard().forResult(); - // 获取整个结果对象,然后访问如 chooseCardResult.cards 等属性 - - // 示例 2: - const cards = await player.chooseCard().forResult('cards'); - // 获取结果对象中 'cards' 属性的值 - - // 示例 3: - const [success, cards, targets] = await player.chooseCardTarget().forResult('bool', 'cards', 'targets'); - // 获取结果对象中多个属性的值 - // - success 表示是否成功 - // - cards 表示选择的卡片 - // - targets 表示选择的目标 - ``` - * @template {keyof Result} T - * @overload - * @returns {Promise} - * - * @overload - * @param {T} param0 - * @returns {Promise>} - * - * @overload - * @param { T[] } params - * @returns { Promise[]> } - */ - forResult(params: T[]): Promise[]>; - /** - * 返回result中的bool项 - */ - forResultBool(): Promise; - /** - * 返回result中的targets项。 - */ - forResultTargets(): Promise; - /** - * 返回result中的cards项 - */ - forResultCards(): Promise; - /** - * 返回result中的card项 - * - * @returns {Promise|Promise} 返回的card项。 - * - */ - forResultCard(): Promise | Promise; - /** - * 返回result中的control项。 - */ - forResultControl(): Promise; - /** - * 返回result中的links项。 - */ - forResultLinks(): Promise; - #private; -} +export { GameEvent as GameEventPromise } from "./gameEvent.js"; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/index.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/index.d.ts index 57432e1977..9cbed91bd5 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/element/index.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/index.d.ts @@ -2,7 +2,6 @@ export { Button } from "./button.js"; export { Card } from "./card.js"; export { Client } from "./client.js"; export { Content } from "./content.js"; -export { Contents } from "./contents.js"; export { Control } from "./control.js"; export { Dialog } from "./dialog.js"; export { GameEvent } from "./gameEvent.js"; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/player.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/player.d.ts index b2038fc863..2d6f35613c 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/element/player.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/player.d.ts @@ -124,6 +124,15 @@ export class Player extends HTMLDivElement { * @type { number } */ outCount: number; + vcardsMap: { + handcards: any[]; + equips: any[]; + judges: any[]; + } | { + handcards: any[]; + equips: any[]; + judges: any[]; + }; buildEventListener(noclick: any): void; noclick: boolean; /** @@ -232,27 +241,48 @@ export class Player extends HTMLDivElement { * })(); * ``` */ - when(...args: any[]): { + when(...triggerNames: any[]): { /** * @param { Required['filter'] } fun */ - filter(fun: Required["filter"]): any; + filter(fun: Required['filter']): any; /** * @param { Required['filter'] } fun */ - removeFilter(fun: Required["filter"]): any; + removeFilter(fun: Required['filter']): any; /** * @param { Required['filter'] } fun */ - filter2(fun: Required["filter"]): any; + filter2(fun: Required['filter']): any; /** * @param { Required['filter'] } fun */ - removeFilter2(fun: Required["filter"]): any; + removeFilter2(fun: Required['filter']): any; /** * @param { Required['content'] } fun */ - then(fun: Required["content"]): any; + then(fun: Required['content']): any; + /** + * ```plain + * 闭包用法的then,不再提供parsex变量,改为使用闭包访问 + * 传参为 event, trigger, player + * + * 闭包即你可以直接在when里面访问when外面的变量 + * 如下: + * ``` + * ```javascript + * var att = get.attitude(player, target); + * + * player.when("phaseEnd") + * .step(() => { + * if (att > 0) // 闭包访问了外面定义的变量 att + * player.say("你好喵!"); + * }); + * ``` + * + * @param { ContentFuncByAll } fun + */ + step(fun: ContentFuncByAll): any; /** * @param { string } str */ @@ -288,11 +318,11 @@ export class Player extends HTMLDivElement { /** * 让一名角色明置一些手牌 */ - addShownCards(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + addShownCards(...args: any[]): import("./gameEvent.js").GameEvent; /** * 让一名角色暗置一些手牌 */ - hideShownCards(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + hideShownCards(...args: any[]): import("./gameEvent.js").GameEvent; /** * 获取角色所有的明置手牌 */ @@ -330,7 +360,7 @@ export class Player extends HTMLDivElement { * @param {*} judge2 * @returns */ - executeDelayCardEffect(card: Card | string, target: Player, judge: any, judge2: any, ...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + executeDelayCardEffect(card: Card | string, target: Player, judge: any, judge2: any, ...args: any[]): import("./gameEvent.js").GameEvent; /** * Check if the card does not count toward hand limit * @@ -346,7 +376,7 @@ export class Player extends HTMLDivElement { * @param { Card | Card[] } cards * @param { Player } target */ - gift(cards: Card | Card[], target: Player, ...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + gift(cards: Card | Card[], target: Player, ...args: any[]): import("./gameEvent.js").GameEvent; /** * Check if the player can gift the card * @@ -355,7 +385,7 @@ export class Player extends HTMLDivElement { * @param { Player } target * @param { boolean } [strict] */ - canGift(card: Card, target: Player, strict?: boolean): any; + canGift(card: Card, target: Player, strict?: boolean): boolean; /** * Check if the player refuses gifts * @@ -383,7 +413,7 @@ export class Player extends HTMLDivElement { * @param { (player: Player, cards: Card[]) => any } [recastingLose] * @param { (player: Player, cards: Card[]) => any } [recastingGain] */ - recast(cards: Card | Card[], recastingLose?: (player: Player, cards: Card[]) => any, recastingGain?: (player: Player, cards: Card[]) => any, ...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + recast(cards: Card | Card[], recastingLose?: (player: Player, cards: Card[]) => any, recastingGain?: (player: Player, cards: Card[]) => any, ...args: any[]): import("./gameEvent.js").GameEvent; /** * Check if the player can recast the card * @@ -392,7 +422,7 @@ export class Player extends HTMLDivElement { * @param { Player } [source] * @param { boolean } [strict] */ - canRecast(card: Card, source?: Player, strict?: boolean): any; + canRecast(card: Card, source?: Player, strict?: boolean): boolean; /** * 判断一名角色的某个区域是否被废除 * @@ -456,24 +486,32 @@ export class Player extends HTMLDivElement { * @returns { Card[] } */ getEquips(subtype: number | string | Card | VCard): Card[]; + /** + * 获取一名角色装备区内某种类型的虚拟牌 + * + * 参数可以为数字/区域字符串/实体牌/虚拟牌/牌名 + * @param { number | string | Card | VCard } subtype + * @returns { VCard[] } + */ + getVEquips(subtype: number | string | Card | VCard): VCard[]; /** * 新的废除装备区 * * 参数:废除来源角色(不写默认当前事件角色),废除区域(数字/区域字符串/数组,可以写多个,重复废除) */ - disableEquip(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + disableEquip(...args: any[]): import("./gameEvent.js").GameEvent; /** * 新的恢复装备区 * * 参数:恢复来源角色(不写默认当前事件角色),恢复区域(数字/区域字符串/数组,可以写多个,重复恢复) */ - enableEquip(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + enableEquip(...args: any[]): import("./gameEvent.js").GameEvent; /** * 新的扩展装备区 * * 参数:扩展来源角色(不写默认当前事件角色),扩展区域(数字/区域字符串/数组,可以写多个,重复扩展) */ - expandEquip(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + expandEquip(...args: any[]): import("./gameEvent.js").GameEvent; /** * 判断判定区是否被废除 */ @@ -514,7 +552,7 @@ export class Player extends HTMLDivElement { * @deprecated */ $enableEquip(): void; - chooseToDebate(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + chooseToDebate(...args: any[]): import("./gameEvent.js").GameEvent; /** * 向target发起协力 * @param { Player } target @@ -522,7 +560,7 @@ export class Player extends HTMLDivElement { * @param {*} reason */ cooperationWith(target: Player, type: string, reason: any): void; - chooseCooperationFor(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + chooseCooperationFor(...args: any[]): import("./gameEvent.js").GameEvent; checkCooperationStatus(target: any, reason: any): boolean; removeCooperation(info: any): void; /** @@ -622,15 +660,15 @@ export class Player extends HTMLDivElement { * @param { 0 | 1 | 2 } num * @param { false } [log] */ - showCharacter(num: 0 | 1 | 2, log?: false, ...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + showCharacter(num: 0 | 1 | 2, log?: false, ...args: any[]): import("./gameEvent.js").GameEvent; /** * @param { 0 | 1 | 2 } num * @param { false } [log] */ $showCharacter(num: 0 | 1 | 2, log?: false): void; - chooseToPlayBeatmap(beatmap: any, ...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseToMove(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseToGuanxing(num: any): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + chooseToPlayBeatmap(beatmap: any, ...args: any[]): import("./gameEvent.js").GameEvent; + chooseToMove(...args: any[]): import("./gameEvent.js").GameEvent; + chooseToGuanxing(num: any): import("./gameEvent.js").GameEvent; /** * @param { Player } target * @param { string } name @@ -646,7 +684,7 @@ export class Player extends HTMLDivElement { * @param { string } popname * @param { 'main' | 'vice' | boolean } checkShow */ - trySkillAnimate(name: string, popname: string, checkShow: "main" | "vice" | boolean, ...args: any[]): void; + trySkillAnimate(name: string, popname: string, checkShow: 'main' | 'vice' | boolean, ...args: any[]): void; /** * @param { Card } card * @param { string } name @@ -699,7 +737,7 @@ export class Player extends HTMLDivElement { /** * @param { Player } target */ - chooseToDuiben(target: Player): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + chooseToDuiben(target: Player): import("./gameEvent.js").GameEvent; /** * 令玩家与target划拳 * @param { Player } target @@ -725,7 +763,7 @@ export class Player extends HTMLDivElement { * 与target交换装备区里的牌 * @param { Player } target */ - swapEquip(target: Player): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + swapEquip(target: Player): import("./gameEvent.js").GameEvent; /** * 返回玩家是否可以与target拼点 * @param { Player } target @@ -735,8 +773,8 @@ export class Player extends HTMLDivElement { canCompare(target: Player, goon?: boolean, bool?: boolean): boolean; $disableJudge(): void; $enableJudge(): void; - disableJudge(): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - enableJudge(): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + disableJudge(): import("./gameEvent.js").GameEvent; + enableJudge(): import("./gameEvent.js").GameEvent; init(character: any, character2: any, skill: any, update: any): this; skin: { name: any; @@ -812,6 +850,15 @@ export class Player extends HTMLDivElement { judges: import("noname-typings/nonameModules/noname/library/element/card.js").Card[]; specials: import("noname-typings/nonameModules/noname/library/element/card.js").Card[]; expansions: import("noname-typings/nonameModules/noname/library/element/card.js").Card[]; + vcardsMap: { + handcards: any[]; + equips: any[]; + judges: any[]; + } | { + handcards: any[]; + equips: any[]; + judges: any[]; + }; expansion_gaintag: any[]; disableJudge: boolean; disabledSlots: SMap; @@ -896,7 +943,12 @@ export class Player extends HTMLDivElement { */ getPrevious(): Player | null; countUsed(card: any, type: any): number; - getCacheKey(): string; + /** + * 返回一个键值,用于在缓存中作为键名。 + * @param { boolean } [similar] false统一前缀 + * @returns {string} cacheKey + */ + getCacheKey(similar?: boolean): string; /** * 返回玩家本回合使用某个技能的次数 * @param { string } skill @@ -910,6 +962,23 @@ export class Player extends HTMLDivElement { * @returns { string[] } */ getStockSkills(unowned?: any, unique?: any, hidden?: any): string[]; + /** + * @param { string } [arg1='h'] + * @param { string | Record | ((card: Card) => boolean) } [arg2] + * @returns { Iterable } + */ + iterableGetVCards(arg1?: string, arg2?: string | Record | ((card: Card) => boolean)): Iterable; + /** + * @param { string } [arg1='h'] + * @param { string | Record | ((card: Card) => boolean) } [arg2] + * @returns { Card[] } + */ + getVCards(arg1?: string, arg2?: string | Record | ((card: Card) => boolean)): Card[]; + /** + * @param { Parameters[0] } [arg1] + * @param { Parameters[1] } [arg2] + */ + countVCards(arg1?: Parameters[0], arg2?: Parameters[1]): number; /** * @param { string } [arg1='h'] * @param { string | Record | ((card: Card) => boolean) } [arg2] @@ -935,20 +1004,20 @@ export class Player extends HTMLDivElement { * @param {Parameters[0]} arg1 * @param {Parameters[1]} arg2 */ - iterableGetGainableCards(player: any, arg1: Parameters[0], arg2: Parameters[1]): Generator; + iterableGetGainableCards(player: [card?: any, player?: any, target?: any, event?: any][1], arg1: Parameters[0], arg2: Parameters[1]): Generator; /** * * @param {Parameters[0]} player * @param {Parameters[1]} [arg1] * @param {Parameters[2]} [arg2] */ - getGainableCards(player: Parameters[0], arg1?: Parameters[1], arg2?: Parameters[2]): any[]; + getGainableCards(player: Parameters[0], arg1?: Parameters[1], arg2?: Parameters[2]): any[]; getGainableSkills(func: any): any[]; /** * @param { Parameters[0] } [arg1] * @param { Parameters[1] } [arg2] */ - countCards(arg1?: Parameters<(typeof this)["iterableGetCards"]>[0], arg2?: Parameters<(typeof this)["iterableGetCards"]>[1]): number; + countCards(arg1?: Parameters[0], arg2?: Parameters[1]): number; getCardIndex(arg1: any, name: any, card: any, max: any): number; countDiscardableCards(player: any, arg1: any, arg2: any): number; /** @@ -956,7 +1025,7 @@ export class Player extends HTMLDivElement { * @param {Parameters[1]} [arg1] * @param {Parameters[2]} [arg2] */ - countGainableCards(player: Parameters[0], arg1?: Parameters[1], arg2?: Parameters[2]): number; + countGainableCards(player: Parameters[0], arg1?: Parameters[1], arg2?: Parameters[2]): number; /** * 返回武将牌上原有的技能 * @returns { Array } 技能名数组 @@ -977,38 +1046,38 @@ export class Player extends HTMLDivElement { syncSkills(): void; playerfocus(time: any): this; setIdentity(identity: any, nature: any): this; - insertPhase(skill: any, insert: any): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - insertEvent(name: any, content: any, arg: any): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - phase(skill: any): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - phaseZhunbei(): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - phaseJudge(): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - phaseDraw(): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - phaseUse(): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - phaseDiscard(): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - phaseJieshu(): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseToUse(use: any, ...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseToRespond(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseToGive(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseToDiscard(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseToCompare(target: any, check: any, ...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseSkill(target: any, ...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - discoverCard(list: any, ...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseCardButton(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseVCardButton(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseButton(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseButtonOL(list: any, callback: any, ai: any, ...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseCardOL(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseCard(choose: any, ...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseUseTarget(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseTarget(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseCardTarget(choose: any, ...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseControlList(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseControl(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseBool(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - chooseDrawRecover(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - choosePlayerCard(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - discardPlayerCard(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - gainPlayerCard(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + insertPhase(skill: any, insert: any): import("./gameEvent.js").GameEvent; + insertEvent(name: any, content: any, arg: any): import("./gameEvent.js").GameEvent; + phase(skill: any): import("./gameEvent.js").GameEvent; + phaseZhunbei(): import("./gameEvent.js").GameEvent; + phaseJudge(): import("./gameEvent.js").GameEvent; + phaseDraw(): import("./gameEvent.js").GameEvent; + phaseUse(): import("./gameEvent.js").GameEvent; + phaseDiscard(): import("./gameEvent.js").GameEvent; + phaseJieshu(): import("./gameEvent.js").GameEvent; + chooseToUse(use: any, ...args: any[]): import("./gameEvent.js").GameEvent; + chooseToRespond(...args: any[]): import("./gameEvent.js").GameEvent; + chooseToGive(...args: any[]): import("./gameEvent.js").GameEvent; + chooseToDiscard(...args: any[]): import("./gameEvent.js").GameEvent; + chooseToCompare(target: any, check: any, ...args: any[]): import("./gameEvent.js").GameEvent; + chooseSkill(target: any, ...args: any[]): import("./gameEvent.js").GameEvent; + discoverCard(list: any, ...args: any[]): import("./gameEvent.js").GameEvent; + chooseCardButton(...args: any[]): import("./gameEvent.js").GameEvent; + chooseVCardButton(...args: any[]): import("./gameEvent.js").GameEvent; + chooseButton(...args: any[]): import("./gameEvent.js").GameEvent; + chooseButtonOL(list: any, callback: any, ai: any, ...args: any[]): import("./gameEvent.js").GameEvent; + chooseCardOL(...args: any[]): import("./gameEvent.js").GameEvent; + chooseCard(choose: any, ...args: any[]): import("./gameEvent.js").GameEvent; + chooseUseTarget(...args: any[]): import("./gameEvent.js").GameEvent; + chooseTarget(...args: any[]): import("./gameEvent.js").GameEvent; + chooseCardTarget(choose: any, ...args: any[]): import("./gameEvent.js").GameEvent; + chooseControlList(...args: any[]): import("./gameEvent.js").GameEvent; + chooseControl(...args: any[]): import("./gameEvent.js").GameEvent; + chooseBool(...args: any[]): import("./gameEvent.js").GameEvent; + chooseDrawRecover(...args: any[]): import("./gameEvent.js").GameEvent; + choosePlayerCard(...args: any[]): import("./gameEvent.js").GameEvent; + discardPlayerCard(...args: any[]): import("./gameEvent.js").GameEvent; + gainPlayerCard(...args: any[]): import("./gameEvent.js").GameEvent; /** * 玩家展示手牌 * @param { string } str @@ -1041,7 +1110,7 @@ export class Player extends HTMLDivElement { * @returns { GameEventPromise } */ moveCard(...args: any[]): GameEventPromise; - useResult(result: any, event: any): import("noname-typings/nonameModules/noname/library/index.js").GameEventPromise; + useResult(result: any, event: any): import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent; /** * 令玩家使用牌 * @returns { GameEventPromise } @@ -1081,7 +1150,7 @@ export class Player extends HTMLDivElement { * @returns { GameEventPromise } */ respond(...args: any[]): GameEventPromise; - swapHandcards(target: any, cards1: any, cards2: any): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + swapHandcards(target: any, cards1: any, cards2: any): import("./gameEvent.js").GameEvent; directequip(cards: any): void; $addToExpansion(cards: any, broadcast: any, gaintag: any): this; directgain(cards: any, broadcast: any, gaintag: any): this; @@ -1090,7 +1159,7 @@ export class Player extends HTMLDivElement { * @param { Player[] } targets * @param { string } [position = "h"] */ - gainMultiple(targets: Player[], position?: string): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + gainMultiple(targets: Player[], position?: string): import("./gameEvent.js").GameEvent; /** * 令玩家获得一些牌 * @returns { GameEventPromise } @@ -1107,8 +1176,8 @@ export class Player extends HTMLDivElement { * @param { Player } target * @param { boolean } [visible] */ - give(cards: Card | Card[], target: Player, visible?: boolean): import("noname-typings/nonameModules/noname/library/index.js").GameEventPromise; - lose(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + give(cards: Card | Card[], target: Player, visible?: boolean): import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent; + lose(...args: any[]): import("./gameEvent.js").GameEvent; /** * 令玩家受到伤害 * @returns { GameEventPromise } @@ -1124,12 +1193,12 @@ export class Player extends HTMLDivElement { * @returns { GameEventPromise } */ recoverTo(...args: any[]): GameEventPromise; - doubleDraw(): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + doubleDraw(): import("./gameEvent.js").GameEvent; /** * 令玩家流失体力 * @param { number } [num] */ - loseHp(num?: number): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + loseHp(num?: number): import("./gameEvent.js").GameEvent; /** * 扣减玩家的体力上限 * @returns { GameEventPromise }} @@ -1186,7 +1255,7 @@ export class Player extends HTMLDivElement { unMad(): void; tempHide(): void; addExpose(num: any): this; - equip(card: any, draw: any): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + equip(card: any, draw: any): import("./gameEvent.js").GameEvent; /** * 将一些牌置入到玩家的判定区 * @param { Card } card @@ -1196,35 +1265,18 @@ export class Player extends HTMLDivElement { addJudge(card: Card, cards?: Card[]): GameEventPromise; /** * 返回某些牌是否能进入玩家的判定区 - * * @overload - * @param { string } card - * @returns { boolean } - * - * @overload - * @param { Card } card - * @returns { boolean } - */ - canAddJudge(card: string): boolean; - /** - * 返回某些牌是否能进入玩家的判定区 - * - * @overload - * @param { string } card - * @returns { boolean } - * - * @overload - * @param { Card } card + * @param { string | Card } card * @returns { boolean } */ - canAddJudge(card: Card): boolean; - addJudgeNext(card: any, unlimited: any): void; - judge(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - turnOver(bool: any): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + canAddJudge(card: string | Card): boolean; + addJudgeNext(card: any, unlimited: any): import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent; + judge(...args: any[]): import("./gameEvent.js").GameEvent; + turnOver(bool: any): import("./gameEvent.js").GameEvent; out(skill: any): void; outSkills: any[]; in(skill: any): void; - link(bool: any): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + link(bool: any): import("./gameEvent.js").GameEvent; skip(name: any): void; wait(callback: any): void; unwait(result: any): void; @@ -1235,7 +1287,7 @@ export class Player extends HTMLDivElement { * @param { boolean | string } [nature] * @param { boolean } [logv] */ - logSkill(name: string | string[], targets?: Player | Player[], nature?: boolean | string, logv?: boolean): void; + logSkill(name: string | string[], targets?: Player | Player[], nature?: boolean | string, logv?: boolean, args: any): void; unprompt(): void; prompt(str: any, nature: any): void; prompt_old(name2: any, className: any): void; @@ -1273,21 +1325,58 @@ export class Player extends HTMLDivElement { addLink(): void; removeLink(): void; /** - * @param { string | Card | VCard } card + * 能否对target使用card + * @param { Card | VCard | object | string } card * @param { Player } target - * @param { boolean } [distance] - * @param { GameEventPromise | boolean } [includecard] + * @param { false } [distance] false:无距离限制 + * @param { boolean | GameEvent } [includecard] 是否受使用次数限制,可以填入用于检测的事件 + * @returns + */ + canUse(card: Card | VCard | object | string, target: Player, distance?: false, includecard?: boolean | GameEvent): any; + /** + * 场上是否存在能对其使用card的目标 + * @param { Card | VCard | object | string } card + * @param { false } [distance] false:无距离限制 + * @param { boolean | GameEvent } [includecard] 是否受使用次数限制,可以填入用于检测的事件 + * @returns { boolean } + */ + hasUseTarget(card: Card | VCard | object | string, distance?: false, includecard?: boolean | GameEvent): boolean; + /** + * 场上是否存在收益为正的目标 + * @param { Card | VCard | object | string } card + * @param { false } [distance] false:无距离限制 + * @param { boolean | GameEvent } [includecard] 是否受使用次数限制,可以填入用于检测的事件 * @returns { boolean } */ - canUse(card: string | Card | VCard, target: Player, distance?: boolean, includecard?: GameEventPromise | boolean): boolean; - hasUseTarget(card: any, distance: any, includecard: any): boolean; - hasValueTarget(card: any, distance: any, includecard: any): boolean; - getUseValue(card: any, distance: any, includecard: any): number; - addSubPlayer(cfg: any): string; + hasValueTarget(card: Card | VCard | object | string, distance?: false, includecard?: boolean | GameEvent): boolean; + /** + * card使用价值 + * @param { Card | VCard | object | string } card + * @param { false } [distance] false:无距离限制 + * @param { boolean | GameEvent } [includecard] 是否受使用次数限制,可以填入用于检测的事件 + * @returns { number } 无可选或正收益目标返回0 + */ + getUseValue(card: Card | VCard | object | string, distance?: false, includecard?: boolean | GameEvent): number; + /** + * 添加随从 + * @param { { hs?: Card[], es?: Card[], skills?: string[], hp?: number, maxHp?: number, hujia?: number, sex?: Sex, group?: string, skill?: string, source?: string } } cfg + */ + addSubPlayer(cfg: { + hs?: Card[]; + es?: Card[]; + skills?: string[]; + hp?: number; + maxHp?: number; + hujia?: number; + sex?: Sex; + group?: string; + skill?: string; + source?: string; + }): string; removeSubPlayer(name: any): void; - callSubPlayer(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - toggleSubPlayer(...args: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - exitSubPlayer(remove: any): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + callSubPlayer(...args: any[]): import("./gameEvent.js").GameEvent; + toggleSubPlayer(...args: any[]): import("./gameEvent.js").GameEvent; + exitSubPlayer(remove: any): import("./gameEvent.js").GameEvent; getSubPlayers(tag: any): any[]; addSkillTrigger(skills: any, hidden: any, triggeronly: any): this; _hookTrigger: any[]; @@ -1295,50 +1384,36 @@ export class Player extends HTMLDivElement { removeSkillLog(skill: any, popup: any): this; addInvisibleSkill(skill: any): void; removeInvisibleSkill(skill: any, ...args: any[]): any; - addSkills(skill: any): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - removeSkills(skill: any): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - changeSkills(addSkill?: any[], removeSkill?: any[]): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + addSkills(skill: any): import("./gameEvent.js").GameEvent; + removeSkills(skill: any): import("./gameEvent.js").GameEvent; + changeSkills(addSkill?: any[], removeSkill?: any[]): import("./gameEvent.js").GameEvent; addSkill(skill: any, checkConflict: any, nobroadcast: any, addToSkills: any): any; - addAdditionalSkills(skill: any, skillsToAdd: any, keep: any): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + addAdditionalSkills(skill: any, skillsToAdd: any, keep: any): import("./gameEvent.js").GameEvent; addAdditionalSkill(skill: any, skillsToAdd: any, keep: any): this; $removeAdditionalSkills(skill: any, target: any): void; getRemovableAdditionalSkills(skill: any, target: any): string[]; removeAdditionalSkill(skill: any, target: any): this; - removeAdditionalSkills(skill: any, target: any): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; + removeAdditionalSkills(skill: any, target: any): import("./gameEvent.js").GameEvent; awakenSkill(skill: any, nounmark: any): this; restoreSkill(skill: any, nomark: any): this; disableSkill(skill: any, skills: any): this; enableSkill(skill: any): this; checkMarks(): this; addEquipTrigger(card: any): this; + removeVirtualJudge(VCard: any): void; + removeVirtualEquip(VCard: any): void; removeEquipTrigger(card: any): this; removeSkillTrigger(skills: any, triggeronly: any): this; removeSkill(skill: any, ...args: any[]): any; - addTempSkills(skillsToAdd: any, expire: any): import("./gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise; - /** - * @overload - * @param { string } skill - * @param { SkillTrigger | string | (event:GameEventPromise, player:Player, name:string) => boolean } [expire] - * @param { boolean } [checkConflict] - * - * @overload - * @param { string[] } skill 技能名数组 - * @param { SkillTrigger | string | (event:GameEventPromise, player:Player, name:string) => boolean } [expire] - * @param { boolean } [checkConflict] - */ - addTempSkill(skill: string, expire?: SkillTrigger | string | ((event: GameEventPromise, player: Player, name: string) => boolean), checkConflict?: boolean): any; + addTempSkills(skillsToAdd: any, expire: any): import("./gameEvent.js").GameEvent; /** + * 添加临时技能 * @overload - * @param { string } skill - * @param { SkillTrigger | string | (event:GameEventPromise, player:Player, name:string) => boolean } [expire] - * @param { boolean } [checkConflict] - * - * @overload - * @param { string[] } skill 技能名数组 + * @param { string | string[] } skill 技能名(数组) * @param { SkillTrigger | string | (event:GameEventPromise, player:Player, name:string) => boolean } [expire] * @param { boolean } [checkConflict] */ - addTempSkill(skill: string[], expire?: SkillTrigger | string | ((event: GameEventPromise, player: Player, name: string) => boolean), checkConflict?: boolean): any; + addTempSkill(skill: string | string[], expire?: string | SkillTrigger | ((event: GameEventPromise, player: Player, name: string) => boolean), checkConflict?: boolean): any; tempBanSkill(skill: any, expire: any, log: any): any; /** * 返回技能是否暂时失效 @@ -1385,7 +1460,7 @@ export class Player extends HTMLDivElement { * @param { (event: GameEventPromise) => boolean } filter * @param { GameEventPromise } [last] */ - checkHistory(key: T, filter: (event: GameEventPromise) => boolean, last?: GameEventPromise): void; + checkHistory(key: T_1, filter: (event: GameEventPromise) => boolean, last?: GameEventPromise): void; /** * @template { keyof ActionHistory } T * @param { T } key @@ -1393,7 +1468,7 @@ export class Player extends HTMLDivElement { * @param { GameEventPromise } [last] * @returns { boolean } */ - hasHistory(key: T, filter?: (event: GameEventPromise) => boolean, last?: GameEventPromise): boolean; + hasHistory(key: T_2, filter?: (event: GameEventPromise) => boolean, last?: GameEventPromise): boolean; /** * @template { keyof ActionHistory } T * @overload @@ -1402,14 +1477,14 @@ export class Player extends HTMLDivElement { * @param { GameEventPromise } [last] * @returns { null | ActionHistory[T] | boolean } */ - getLastHistory(key?: T, filter?: (event: GameEventPromise) => boolean, last?: GameEventPromise): null | ActionHistory[T] | boolean; + getLastHistory(key?: T_3, filter?: (event: GameEventPromise) => boolean, last?: GameEventPromise): boolean | ActionHistory[T_3]; /** * @template { keyof ActionHistory } T * @param { T } key * @param { (event: GameEventPromise) => boolean } filter * @param { GameEventPromise } [last] */ - checkAllHistory(key: T, filter: (event: GameEventPromise) => boolean, last?: GameEventPromise): void; + checkAllHistory(key: T_4, filter: (event: GameEventPromise) => boolean, last?: GameEventPromise): void; /** * @template { keyof ActionHistory } T * @param { T } [key] @@ -1417,7 +1492,7 @@ export class Player extends HTMLDivElement { * @param { GameEventPromise } [last] * @returns { ActionHistory[T] } */ - getAllHistory(key?: T, filter?: (event: GameEventPromise) => boolean, last?: GameEventPromise): ActionHistory[T]; + getAllHistory(key?: T_5, filter?: (event: GameEventPromise) => boolean, last?: GameEventPromise): ActionHistory[T_5]; /** * @template { keyof ActionHistory } T * @param { T } key @@ -1425,8 +1500,8 @@ export class Player extends HTMLDivElement { * @param { GameEventPromise } [last] * @returns { boolean } */ - hasAllHistory(key: T, filter: (event: GameEventPromise) => boolean, last?: GameEventPromise): boolean; - getLastUsed(num: any): import("noname-typings/nonameModules/noname/library/index.js").GameEventPromise; + hasAllHistory(key: T_6, filter: (event: GameEventPromise) => boolean, last?: GameEventPromise): boolean; + getLastUsed(num: any): import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent; getStat(key: any): any; getLastStat(key: any): any; queue(time: any): void; @@ -1534,12 +1609,16 @@ export class Player extends HTMLDivElement { isOnline(): boolean; isOnline2(): boolean; isOffline(): boolean; + isMajor(): boolean; + isNotMajor(): boolean; + isMinor(nomajor: any): boolean; checkShow(skill: any, showonly: any): false | "main" | "vice"; /** * - * @param { number | Card[] | Card } [add] - * @param { (card?: Card, player?: Player) => boolean } [filter] - * @param { boolean } [pure] + * @param { number | Card[] | Card } [add] (逻辑上)同时考虑“获得”的这张/些牌 + * @param { (card?: Card, player?: Player) => boolean } [filter] 代替默认策略(计入手牌数的手牌)进行筛选 + * @param { boolean } [pure] (手牌上限大于手牌数时)返回负值 + * @returns { number } 需要弃置的牌数 */ needsToDiscard(add?: number | Card[] | Card, filter?: (card?: Card, player?: Player) => boolean, pure?: boolean): number; distanceTo(target: any, method: any): number; @@ -1551,7 +1630,7 @@ export class Player extends HTMLDivElement { * @param { Parameters[2] } arg4 * @returns { boolean } */ - hasSkill(skill: string, arg2: Parameters[0], arg3: Parameters[1], arg4: Parameters[2]): boolean; + hasSkill(skill: string, arg2: Parameters[0], arg3: Parameters[1], arg4: Parameters[2]): boolean; /** * @param { string } skill * @param { Parameters[0] } arg1 @@ -1559,7 +1638,7 @@ export class Player extends HTMLDivElement { * @param { Parameters[2] } arg3 * @returns { boolean } */ - hasStockSkill(skill: string, arg1: Parameters[0], arg2: Parameters[1], arg3: Parameters[2]): boolean; + hasStockSkill(skill: string, arg1: Parameters[0], arg2: Parameters[1], arg3: Parameters[2]): boolean; isZhu2(): boolean; isInitFilter(tag: any): boolean; /** @@ -1573,31 +1652,14 @@ export class Player extends HTMLDivElement { * @param {string} tag * @param {Parameters[0]} [hidden] * @param {Parameters[2]} [arg] - * @param {boolean} [globalskill] + * @param {boolean} [globalskill] 只有为false才不添加全局技能ai进行筛选 */ - hasSkillTag(tag: string, hidden?: Parameters[0], arg?: Parameters[2], globalskill?: boolean): boolean; + hasSkillTag(tag: string, hidden?: Parameters[0], arg?: [player: import("noname-typings/nonameModules/noname/library/element/player.js").Player, tag: string, arg: any][2], globalskill?: boolean): boolean; /** - * 返回玩家是否有某个牌名的牌 - * - * @overload - * @param { Card } name - * @returns { boolean } * * @overload * @param { string } name - * @returns { boolean} - */ - hasJudge(name: Card): boolean; - /** - * 返回玩家是否有某个牌名的牌 - * - * @overload - * @param { Card } name - * @returns { boolean } - * - * @overload - * @param { string } name - * @returns { boolean} + * @returns { boolean} 返回玩家判定区是否有某(种牌名的)牌 */ hasJudge(name: string): boolean; /** @@ -1615,16 +1677,41 @@ export class Player extends HTMLDivElement { */ hasSha(respond?: string | boolean, noauto?: boolean): boolean; hasShan(respond: any): boolean; - mayHaveSha(viewer: any, type: any, ignore: any, rvt: any): number | boolean; - mayHaveShan(viewer: any, type: any, ignore: any, rvt: any): number | boolean; + /** + * 以viewer视角猜测Player手里的杀 + * @param { Player } [viewer] + * @param { "use" | "respond" } [type] 此杀用途:"use"/"respond",无则均加入 + * @param { Card[] | Card | null } [ignore] 此牌/这些牌不纳入考量 + * @param { "bool" | "count" | "odds" } [rvt] + * @returns { boolean | number } 返回值:rvt:"bool"(默认)是否可能有杀,"count"推测有多少张杀,"odds"有杀的概率 + */ + mayHaveSha(viewer?: Player, type?: "use" | "respond", ignore?: Card[] | Card | null, rvt?: "bool" | "count" | "odds"): boolean | number; + /** + * 以viewer视角猜测Player手里的闪 + * @param { Player } [viewer] + * @param { "use" | "respond" } [type] 此闪用途:"use"/"respond",无则均加入 + * @param { Card[] | Card | null } [ignore] 此牌/这些牌不纳入考量 + * @param { "bool" | "count" | "odds" } [rvt] + * @returns { boolean | number } 返回值:rvt:"bool"(默认)是否可能有闪,"count"推测有多少张闪,"odds"有闪的概率 + */ + mayHaveShan(viewer?: Player, type?: "use" | "respond", ignore?: Card[] | Card | null, rvt?: "bool" | "count" | "odds"): boolean | number; hasCard(name: any, position: any): boolean; + hasVCard(name: any, position: any): boolean; + getVEquip(name: any): import("noname-typings/nonameModules/noname/library/element/card.js").Card; getEquip(name: any): import("noname-typings/nonameModules/noname/library/element/card.js").Card; + /** + * 返回玩家判定区中的虚拟牌 + * @param { string } [name] + * @returns { VCard|null } + */ + getVJudge(name?: string): VCard | null; /** * 返回玩家判定区中的牌 + * @deprecated * @param { string } [name] - * @returns { Card[] } + * @returns { Card|null } */ - getJudge(name?: string): Card[]; + getJudge(name?: string): Card | null; $drawAuto(cards: any, target: any): void; $draw(num: any, init: any, config: any): void; $compareMultiple(card1: any, targets: any, cards: any): void; @@ -1639,6 +1726,10 @@ export class Player extends HTMLDivElement { $giveAuto(card: any, player: any, ...args: any[]): any; $give(card: any, player: any, log: any, init: any): void; $handleEquipChange(): void; + addVirtualJudge(card: any, cards: any): void; + $addVirtualJudge(VCard: any, cards: any): void; + addVirtualEquip(card: any, cards: any): void; + $addVirtualEquip(card: any, cards: any): void; $equip(card: any): this; $gain(card: any, log: any, init: any): void; $gain2(cards: any, log: any): boolean; @@ -1654,7 +1745,13 @@ export class Player extends HTMLDivElement { $coin(): void; $dust(): void; $recover(): void; - $fullscreenpop(str: any, nature: any, avatar: any, broadcast: any): void; + /** + * @param {*} str + * @param {*} [nature] + * @param {*} [avatar] + * @param { false } [broadcast] + */ + $fullscreenpop(str: any, nature?: any, avatar?: any, broadcast?: false): void; /** * * @param { number | string } num diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/vcard.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/vcard.d.ts index fb220de8c9..ba258d1fc4 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/element/vcard.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/vcard.d.ts @@ -4,8 +4,9 @@ export class VCard { * @param { number | Card[] } [numberOrCards] * @param { string } [name] * @param { string } [nature] + * @param { Player | false } [owner] */ - constructor(suitOrCard?: any, numberOrCards?: number | Card[], name?: string, nature?: string); + constructor(suitOrCard?: any, numberOrCards?: number | Card[], name?: string, nature?: string, owner?: Player | false); /** * @type {string} */ @@ -44,6 +45,13 @@ export class VCard { * @param { Player } player */ hasNature(nature: any, player: Player): boolean; - getCacheKey(): string; + /** + * 返回一个键值,用于在缓存中作为键名。 + * @param { boolean } [similar] true伪equals, false统一前缀 + * @returns {string} cacheKey + */ + getCacheKey(similar?: boolean): string; hasGaintag(tag: any): any; + initID(): void; + vcardID: string; } diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/index.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/index.d.ts index 032d623b1c..ab25877a92 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/index.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/index.d.ts @@ -1,3 +1,4 @@ +/// export class Library { configprefix: string; versionOL: number; @@ -40,6 +41,7 @@ export class Library { onresize: any[]; onphase: any[]; onwash: any[]; + onround: ((event: any) => boolean)[]; onover: any[]; ondb: any[]; ondb2: any[]; @@ -70,6 +72,10 @@ export class Library { inpile_nature: any[]; extensions: any[]; extensionPack: {}; + /** + * @type { IOnloadSplash[] } + */ + onloadSplashes: IOnloadSplash[]; cardType: {}; hook: { globalskill: {}; @@ -81,7 +87,7 @@ export class Library { /** * @type { 'android' | 'ios' | undefined } */ - device: "android" | "ios" | undefined; + device: 'android' | 'ios' | undefined; /** * @type { string } */ @@ -116,7 +122,7 @@ export class Library { * @type { { [key: string]: Player } } */ playerOL: { - [key: string]: Player; + [key: string]: Element.Player; }; /** * @type { IDBRequest } @@ -191,7 +197,17 @@ export class Library { announce: Announce; objectURL: Map; hookmap: {}; - imported: {}; + /** + * @type { { character?: SMap, card?: SMap, mode?: SMap, player?: SMap, extension?: SMap, play?: SMap } } + */ + imported: { + character?: SMap; + card?: SMap; + mode?: SMap; + player?: SMap; + extension?: SMap; + play?: SMap; + }; layoutfixed: string[]; pinyins: { _metadata: { @@ -229,7 +245,7 @@ export class Library { yingbian: { condition: { color: Map; - complex: Map Element.GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent & import("noname-typings/nonameModules/noname/library/element/gameEventPromise.js").GameEventPromise>; + complex: Map Element.GameEvent>; simple: Map any>; }; effect: Map void>; @@ -662,7 +678,7 @@ export class Library { style1: string; style2: string; }; - visualMenu: (node: any, link: any) => void; + visualMenu: (node: any, link: any) => Promise; }; player_height: { name: string; @@ -3025,6 +3041,27 @@ export class Library { name: string; init: boolean; frequent: boolean; + }; + connect_double_character: { + name: string; + init: string; + item: { + single: string; + double: string; + singble: string; + }; + restart: boolean; + }; + connect_double_hp: { + name: string; + init: string; + item: { + hejiansan: string; + pingjun: string; + zuidazhi: string; + zuixiaozhi: string; + zonghe: string; + }; restart: boolean; }; update: (config: any, map: any) => void; @@ -3059,6 +3096,28 @@ export class Library { unlimited: string; }; }; + double_character: { + name: string; + init: string; + item: { + single: string; + double: string; + singble: string; + }; + restart: boolean; + }; + double_hp: { + name: string; + init: string; + item: { + hejiansan: string; + pingjun: string; + zuidazhi: string; + zuixiaozhi: string; + zonghe: string; + }; + restart: boolean; + }; update: (config: any, map: any) => void; }; }; @@ -3348,10 +3407,13 @@ export class Library { run(time: any): void; getUTC(date: any): any; saveVideo(): void; - genAsync(fn: any): (...args: Parameters) => Promise>; + /** + * @param {Function} fn + */ + genAsync(fn: Function): (...args: any[]) => Promise>; genAwait(item: any): Promise; gnc: { - of: (fn: any) => (...args: Parameters) => Promise>; + of: (fn: any) => (...args: unknown[]) => Promise; is: { coroutine: (item: any) => boolean; generatorFunc: (item: any) => boolean; @@ -3893,7 +3955,7 @@ export class Library { experimental: typeof Experimental; element: { content: { - emptyEvent: () => void; + emptyEvent: (event: any) => Promise; changeCharacter(event: any, trigger: any, player: any): Promise; changeSkills(event: any, trigger: any, player: any): Promise; addShownCards: () => void; @@ -3904,8 +3966,10 @@ export class Library { disableEquip: () => void; enableEquip: () => void; expandEquip: () => void; - replaceEquip: () => void; - equip: () => void; + replaceEquip: (event: any, trigger: any, player: any) => Promise; + replaceEquip_old: () => void; + equip: (event: any, trigger: any, player: any) => Promise; + equip_old: () => void; changeGroup: () => void; chooseToDebate: () => void; delay: () => void; @@ -3922,8 +3986,8 @@ export class Library { cardsGotoOrdering: () => void; cardsGotoSpecial: () => void; cardsGotoPile: () => void; - chooseToEnable: () => void; - chooseToDisable: () => void; + chooseToEnable: (event: import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent, trigger: import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent, player: import("noname-typings/nonameModules/noname/library/element/player.js").Player) => Promise; + chooseToDisable: (event: import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent, trigger: import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent, player: import("noname-typings/nonameModules/noname/library/element/player.js").Player) => Promise; swapEquip: () => void; disableJudge: () => void; enableJudge: () => void; @@ -3938,7 +4002,7 @@ export class Library { gameDraw: () => void; phaseLoop: () => void; loadPackage: () => void; - loadMode: () => void; + loadMode(event: any): Promise; forceOver: () => void; arrangeTrigger: (event: any, trigger: any, player: any) => Promise; createTrigger: () => any; @@ -4004,19 +4068,19 @@ export class Library { changeHujia: () => void; dying: () => void; die: () => void; - addJudge: () => void; + addJudge: (event: any, trigger: any, player: any) => Promise; + addJudge_old: () => void; judge: () => void; turnOver: () => void; link: () => void; chooseToGuanxing: () => void; }; - contents: SMap<((event: globalThis.GameEventPromise, trigger: globalThis.GameEventPromise, player: globalThis.Player) => Promise)[]>; Player: typeof Element.Player; Card: typeof Element.Card; VCard: typeof Element.VCard; Button: typeof Element.Button; GameEvent: typeof Element.GameEvent; - GameEventPromise: typeof Element.GameEventPromise; + GameEventPromise: typeof Element.GameEvent; Dialog: typeof Element.Dialog; Control: typeof Element.Control; Client: typeof Element.Client; @@ -4069,7 +4133,7 @@ export class Library { /** * @type { [CardBaseUIData['suit'], CardBaseUIData['number'], string][] } */ - list: [CardBaseUIData["suit"], CardBaseUIData["number"], string][]; + list: [CardBaseUIData['suit'], CardBaseUIData['number'], string][]; cooperation_damage: { fullskin: boolean; }; @@ -4184,7 +4248,94 @@ export class Library { fullimage: boolean; }; }; - filter: any; + filter: { + all: () => boolean; + none: () => boolean; + /** + * Check if the card does not count toward the player's hand limit + * + * 检测此牌是否不计入此角色的手牌上限 + * @param { Card } card + * @param { Player } player + * @returns { boolean } + */ + ignoredHandcard: (card: Card, player: Player) => boolean; + /** + * Check if the card is giftable + * + * 检测此牌是否可赠予 + * @param { Card } card + * @param { Player } player + * @param { Player } target + * @param { boolean } [strict] + */ + cardGiftable: (card: Card, player: Player, target: Player, strict?: boolean) => boolean; + /** + * Check if the card is recastable + * + * 检查此牌是否可重铸 + * @param { Card } card + * @param { Player } player + * @param { Player } [source] + * @param { boolean } [strict] + */ + cardRecastable: (card: Card, player?: Player, source?: Player, strict?: boolean) => boolean; + /** + * @param { Card } card + * @param { Player } player + * @returns { boolean } + */ + canBeReplaced: (card: Card, player: Player) => boolean; + buttonIncluded: (button: any) => boolean; + filterButton: (button: any) => boolean; + cardSavable: (card: any, player: any, target: any) => any; + /** + * + * @param {GameEvent} event + * @param {Player} player + * @param {string} triggername + * @param {string} skill + * @returns {boolean} + */ + filterTrigger: (event: GameEvent, player: Player, triggername: string, skill: string, indexedData: any) => boolean; + /** + * + * @param {GameEvent} event + * @param {Player} player + * @param {string} skill + * @returns {boolean} + */ + filterEnable: (event: GameEvent, player: Player, skill: string) => boolean; + characterDisabled: (i: any, libCharacter: any, ...args: any[]) => boolean; + characterDisabled2: (i: any, ...args: any[]) => boolean; + skillDisabled: (skill: any) => boolean; + cardEnabled: (card: any, player: any, event: any) => any; + cardRespondable: (card: any, player: any, event: any) => any; + cardUsable2: (card: any, player: any, event: any) => boolean; + cardUsable: (card: any, player: any, event: any) => boolean; + cardDiscardable: (card: any, player: any, event: any) => any; + canBeDiscarded: (card: any, player: any, target: any, event: any) => any; + canBeGained: (card: any, player: any, target: any, event: any) => any; + cardAiIncluded: (card: any) => boolean; + filterCard: (card: any, player: any, event: any) => boolean; + targetEnabledx: (card: any, player: any, target: any, ...args: any[]) => any; + targetEnabled: (card: any, player: any, target: any) => any; + targetEnabled2: (card: any, player: any, target: any) => boolean; + targetEnabled3: (card: any, player: any, target: any) => boolean; + targetInRange: (card: any, player: any, target: any) => any; + filterTarget: (card: any, player: any, target: any) => any; + filterTarget2: (card: any, player: any, target: any) => any; + notMe: (card: any, player: any, target: any) => boolean; + isMe: (card: any, player: any, target: any) => boolean; + attackFrom: (card: any, player: any, target: any) => boolean; + globalFrom: (card: any, player: any, target: any) => boolean; + selectCard: () => number[]; + selectTarget: (card: any, player: any) => number | number[] | (() => number | Select); + judge: (card: any, player: any, target: any) => any; + autoRespondSha: () => boolean; + autoRespondShan: () => boolean; + wuxieSwap: (event: any) => boolean; + }; sort: { nature: (a: any, b: any) => number; group: (a: any, b: any) => number; @@ -4213,6 +4364,7 @@ export class Library { * }} */ skill: { + [key: string]: Skill; global: string[]; globalmap: SMap; storage: SMap; @@ -4221,7 +4373,6 @@ export class Library { zhu: SMap; zhuSkill: SMap; land_used: SMap; - [key: string]: Skill; }; /** @type {Object} */ character: { @@ -4430,6 +4581,7 @@ export type GameEvent = InstanceType; export type GameEventPromise = GameEvent & InstanceType; export type NodeWS = InstanceType; export type Control = InstanceType; +export type IOnloadSplash = import("../init/onload/onload-splash.d.ts").OnloadSplash; import * as Element from "./element/index.js"; import { Channel } from "./channel/index.js"; import { Announce } from "./announce/index.js"; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/init/index.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/init/index.d.ts index def457e8ac..347e0f3a9e 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/init/index.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/init/index.d.ts @@ -37,7 +37,7 @@ export class LibInit { * @param {Function} [scope] 作用域 * @returns */ - parsex(item: any, scope?: Function): any; + parsex(item: any, scope?: Function): import("../element/GameEvent/compilers/IContentCompiler.js").EventCompiledContent; eval(func: any): any; encode(strUni: any): string; decode(str: any): string; @@ -55,6 +55,6 @@ export class LibInit { * @param {boolean} [dbNow] - 此刻是否在解析数据库中的内容,请勿直接使用 * @returns {URL} */ - parseResourceAddress(link: string | URL, defaultHandle?: ((item: string) => string) | null, loadAsDataUrlCallback?: ((item: URL) => unknown) | null, dbNow?: boolean): URL; + parseResourceAddress(link: string | URL, defaultHandle?: (item: string) => string, loadAsDataUrlCallback?: (item: URL) => unknown, dbNow?: boolean): URL; } import { LibInitPromises } from "./promises.js"; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/init/promises.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/init/promises.d.ts index 40f901c408..04c9459916 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/init/promises.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/init/promises.d.ts @@ -45,12 +45,12 @@ export class LibInitPromises { * @param {boolean} [forceLoadAsDataUrl] - 是否将资源加载为[Data URL](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/Data_URLs),默认为`false` * @returns {Promise} */ - parseResourceAddress(link: string | URL, defaultHandle?: ((item: string) => string) | null, forceLoadAsDataUrl?: boolean): Promise; + parseResourceAddress(link: string | URL, defaultHandle?: (item: string) => string, forceLoadAsDataUrl?: boolean): Promise; /** * @async * @param {string | URL} link - 需要解析的路径 * @param {((item: string) => string) | null} [defaultHandle] - 在给定路径不符合可用情况(或基于无名杀相关默认情况)时,处理路径的函数,返回的路径应是相对于根目录的相对路径,默认为`null`,当且仅当无法解析成`URL`时会调用该回调 * @returns {Promise<[origin: URL, data: URL]>} */ - parseResourceAddressExt(link: string | URL, defaultHandle?: ((item: string) => string) | null): Promise<[origin: URL, data: URL]>; + parseResourceAddressExt(link: string | URL, defaultHandle?: (item: string) => string): Promise<[origin: URL, data: URL]>; } diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/update.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/update.d.ts index ed4eeb14e3..a0247cbd89 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/update.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/update.d.ts @@ -120,14 +120,14 @@ export function getRepoFilesList(path?: string, branch?: string, options?: { path: string; sha: string; size: number; - type: "file"; + type: 'file'; } | { download_url: null; name: string; path: string; sha: string; size: 0; - type: "dir"; + type: 'dir'; })[]>; /** * @@ -159,7 +159,7 @@ export function flattenRepositoryFiles(path?: string, branch?: string, options?: path: string; sha: string; size: number; - type: "file"; + type: 'file'; }[]>; /** * 请求一个文件而不是直接储存为文件,这样可以省内存空间 diff --git a/node_modules/@types/noname-typings/nonameModules/noname/status/index.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/status/index.d.ts index 7b4845bbf3..a9a75d3f26 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/status/index.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/status/index.d.ts @@ -1,17 +1,13 @@ export class status { - paused: boolean; - paused2: boolean; - /** - * @type { boolean | "paused" } - */ - paused3: boolean | "paused"; - over: boolean; + imchoosing: boolean; clicked: boolean; auto: boolean; + eventManager: GameEventManager; + set event(event: import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent); /** - * @type { GameEventPromise } + * @type { GameEvent | undefined } */ - event: GameEventPromise; + get event(): import("noname-typings/nonameModules/noname/library/element/gameEvent.js").GameEvent; ai: {}; lastdragchange: any[]; /** @@ -47,10 +43,7 @@ export class status { * @type { boolean | undefined } */ touchconfirmed: boolean | undefined; - /** - * @type { boolean | undefined } - */ - connectMode: boolean | undefined; + connectMode: boolean; /** * @type { boolean | undefined } */ @@ -60,9 +53,9 @@ export class status { */ importingExtension: boolean | undefined; /** - * @type { Promise[] | undefined } + * @type { string[] | undefined } */ - extensionLoaded: Promise[] | undefined; + extensionLoaded: string[] | undefined; /** * @type { Promise[] | undefined } */ @@ -72,7 +65,7 @@ export class status { */ importing: { [key: string]: Promise[]; - } | undefined; + }; /** * @type { Function | boolean | undefined } */ @@ -85,6 +78,39 @@ export class status { * @type { boolean } */ roundSkipped: boolean; + /** + * @type { boolean } + */ + withError: boolean; + /** + * @type { string | undefined } + */ + mode: string | undefined; + /** + * @type { { [key: string]: any } | undefined } + */ + brawl: { + [key: string]: any; + }; + /** + * @type { string | undefined } + */ + playback: string | undefined; + /** + * @type { number | undefined } + */ + coinCoeff: number | undefined; + pauseManager: PauseManager; + set paused(bool: boolean); + get paused(): boolean; + set paused2(bool: boolean); + get paused2(): boolean; + set paused3(bool: boolean); + get paused3(): boolean; + set over(bool: boolean); + get over(): boolean; } export let _status: status; export function setStatus(instance?: InstanceType): void; +import { GameEventManager } from "../library/element/gameEvent.js"; +import PauseManager from "../game/PauseManager.js"; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/ui/click/index.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/ui/click/index.d.ts index 94d3137b89..a8e45ee730 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/ui/click/index.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/ui/click/index.d.ts @@ -101,7 +101,7 @@ export class Click { logv(e: any): void; logvtimeout: any; logvleave(): void; - charactercard(name: any, sourcenode: any, noedit: any, resume: any, avatar: any): void; + charactercard(name: any, sourcenode: any, noedit: any, resume: any, avatar: any, audioName: any): void; intro(e: any): import("../../library/element/dialog.js").Dialog; intro2(): void; auto(...args: any[]): void; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/ui/create/index.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/ui/create/index.d.ts index 97cc86a66f..40ee0f4a9e 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/ui/create/index.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/ui/create/index.d.ts @@ -54,7 +54,7 @@ export class Create { /** 创建“扩展”菜单 */ extensionMenu: (connectMenu: any) => void; /** 创建“其他”菜单 */ - otherMenu: (connectMenu: boolean | undefined) => void; + otherMenu: (connectMenu: boolean) => void; statictable(...args: any[]): HTMLTableElement; giveup(): void; groupControl(dialog: any): import("../../library/element/control.js").Control; @@ -77,33 +77,33 @@ export class Create { prebutton(item: any, type: any, position: any, noclick: any): HTMLDivElement; buttonPresets: { /** - * @returns { import("../library/index.js").Button } + * @returns { import("../../library/index.js").Button } */ - tdnodes: (item: any, type: any, position: any, noclick: any, node: any) => any; + tdnodes: (item: any, type: any, position: any, noclick: any, node: any) => import("../../library/index.js").Button; /** - * @returns { import("../library/index.js").Button } + * @returns { import("../../library/index.js").Button } */ - blank: (item: any, type: any, position: any, noclick: any, node: any) => any; + blank: (item: any, type: any, position: any, noclick: any, node: any) => import("../../library/index.js").Button; /** - * @returns { import("../library/index.js").Button } + * @returns { import("../../library/index.js").Button } */ - card: (item: any, type: any, position: any, noclick: any, node: any) => any; + card: (item: any, type: any, position: any, noclick: any, node: any) => import("../../library/index.js").Button; /** - * @returns { import("../library/index.js").Button } + * @returns { import("../../library/index.js").Button } */ - vcard: (item: any, type: any, position: any, noclick: any, node: any) => any; + vcard: (item: any, type: any, position: any, noclick: any, node: any) => import("../../library/index.js").Button; /** - * @returns { import("../library/index.js").Button } + * @returns { import("../../library/index.js").Button } */ - character: (item: any, type: any, position: any, noclick: any, node: any) => any; + character: (item: any, type: any, position: any, noclick: any, node: any) => import("../../library/index.js").Button; /** - * @returns { import("../library/index.js").Button } + * @returns { import("../../library/index.js").Button } */ - characterx: (item: any, type: any, position: any, noclick: any, node: any) => any; + characterx: (item: any, type: any, position: any, noclick: any, node: any) => import("../../library/index.js").Button; /** - * @returns { import("../library/index.js").Button } + * @returns { import("../../library/index.js").Button } */ - player: (item: any, type: any, position: any, noclick: any, node: any) => any; + player: (item: any, type: any, position: any, noclick: any, node: any) => import("../../library/index.js").Button; }; button(item: any, type: any, position: any, noClick: any, button: any): import("../../library/element/button.js").Button; buttons(list: any, type: any, position: any, noclick: any, zoom: any): HTMLDivElement[]; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/ui/index.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/ui/index.d.ts index 5abf305ea0..0b83c73d17 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/ui/index.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/ui/index.d.ts @@ -31,6 +31,10 @@ export class UI { * @type { Dialog } */ dialog: Dialog; + /** + * @type { HTMLDivElement } + */ + system: HTMLDivElement; /** * @type { HTMLDivElement } */ @@ -137,6 +141,22 @@ export class UI { * @type {HTMLDivElement} */ cardPile: HTMLDivElement; + /** + * @type {HTMLDivElement} + */ + discardPile: HTMLDivElement; + /** + * @type {HTMLDivElement} + */ + ordering: HTMLDivElement; + /** + * @type {HTMLDivElement} + */ + coin: HTMLDivElement; + /** + * @type {SMap} + */ + css: SMap; refresh(node: any): void; clear(): void; updatec(): void; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/util/browser.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/util/browser.d.ts index 1450858ac4..b03c4cfffd 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/util/browser.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/util/browser.d.ts @@ -6,4 +6,5 @@ * @type {Record<"firefox" | "chrome" | "safari" | "other", new () => PromiseErrorHandler>} */ export const promiseErrorHandlerMap: Record<"firefox" | "chrome" | "safari" | "other", new () => PromiseErrorHandler>; -export type PromiseErrorHandler = import("./struct/interface/promise-error-handler.js").PromiseErrorHandler; +export type PromiseErrorHandler = import('./struct/interface/promise-error-handler.js').PromiseErrorHandler; +import { PromiseErrorHandler } from "./struct/index.js"; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/util/config.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/util/config.d.ts index 2169dd9395..39ad62a931 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/util/config.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/util/config.d.ts @@ -14,3 +14,28 @@ export function set(name: string, value: any): void; * @returns {boolean} */ export function has(name: string): boolean; +/** + * 从数据库中读取数据,根据目前可用情况自动选择相应地数据库 + * + * 此函数仅用于读取一个“数据库”形式的数据:即无论如何,`localStorage`存的必然是对象 + * + * @async + * @param {string} name - 要读取数据的`key` + * @param {string} type - `indexedDB`所使用的`storeName`和`localStorage`的`key`,当`type`为`"data"`时仅用于`indexedDB` + * @param {boolean} [reinitLocalStorage=true] - 是否在用`localStorage`读取失败时将对应键的值初始化为空对象 + * @param {any} [reinitIndexedDB=undefined] - 是否在用`indexedDB`读取失败时将对应键的值初始化;若给定值,则初始化为给定的值 + * @return {Promise} + */ +export function load(name: string, type: string, reinitLocalStorage?: boolean, reinitIndexedDB?: any): Promise; +/** + * 向数据库中保存数据,根据目前可用情况自动选择相应地数据库 + * + * 此函数仅用于保存一个“数据库”形式的数据:即无论如何,`localStorage`存的必然是对象 + * + * @async + * @param {string} name - 要保存数据的`key` + * @param {string} type - `indexedDB`所使用的`storeName`和`localStorage`的`key`,当`type`为`"data"`时仅用于`indexedDB` + * @param {any} value - 需要保存的数据;当`type`为`"data"`时必须为`object`类型 + * @return {Promise} + */ +export function save(name: string, type: string, value: any): Promise; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/util/error.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/util/error.d.ts index 740a68ac9a..2173fa23a9 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/util/error.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/util/error.d.ts @@ -1,6 +1,6 @@ export class CodeSnippet { /** @type {Array} */ - static "__#1@#snippetStack": Array; + static "__#3@#snippetStack": Array; /** * ```plain * 获取当前代码片段 @@ -51,9 +51,9 @@ export class CodeSnippet { #private; } export class ErrorReporter { - static "__#2@#topAlert": any; - static "__#2@#errorLineNoPatterns": RegExp[]; - static "__#2@#findLineNo": (line: any) => number; + static "__#4@#topAlert": any; + static "__#4@#errorLineNoPatterns": RegExp[]; + static "__#4@#findLineNo": (line: any) => number; /** * ```plain * 向用户报告错误信息 @@ -89,9 +89,9 @@ export class ErrorReporter { } export class ErrorManager { /** @type {WeakMap} */ - static "__#3@#codeSnippets": WeakMap; + static "__#5@#codeSnippets": WeakMap; /** @type {WeakMap} */ - static "__#3@#errorReporters": WeakMap; + static "__#5@#errorReporters": WeakMap; /** * ```plain * 获取函数对应的代码片段 @@ -118,7 +118,7 @@ export class ErrorManager { * @param {Error} error * @returns {string[]?} */ - static "__#3@#getFramesHead": (error: Error) => string[] | null; + static "__#5@#getFramesHead": (error: Error) => string[] | null; /** * ```plain * 计算错误A比错误B多的堆栈层数 @@ -128,7 +128,7 @@ export class ErrorManager { * @param {Error} errorB * @returns {number?} */ - static "__#3@#compareStackLevel": (errorA: Error, errorB: Error) => number | null; + static "__#5@#compareStackLevel": (errorA: Error, errorB: Error) => number | null; /** * ```plain * 封装被设定了代码片段函数的错误捕获调用 diff --git a/node_modules/@types/noname-typings/nonameModules/noname/util/index.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/util/index.d.ts index 7062b23cdf..a2c8fcbc2c 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/util/index.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/util/index.d.ts @@ -13,6 +13,13 @@ export function delay(ms: number): Promise; */ export function freezeButExtensible(record: T): Readonly; export function leaveCompatibleEnvironment(): void; +/** + * + * + * @return {never} + * @throws {Error} + */ +export function jumpToCatchBlock(): never; /** @type { string } */ export const nonameInitialized: string; export const assetURL: string; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/util/sandbox.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/util/sandbox.d.ts index 87d8ef49a3..f4d7d5fea6 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/util/sandbox.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/util/sandbox.d.ts @@ -56,7 +56,7 @@ export class Rule { * * @param {Rule} thiz */ - static "__#4@#assertOperator": (thiz: Rule) => void; + static "__#6@#assertOperator": (thiz: Rule) => void; /** * ```plain * 创建一个封送规则 @@ -174,7 +174,7 @@ export class Rule { */ export class Monitor { /** @type {Set} */ - static "__#8@#monitorSet": Set; + static "__#10@#monitorSet": Set; /** * ```plain * 检查当前是否是 Monitor 所属的运行域 @@ -182,7 +182,7 @@ export class Monitor { * * @param {Monitor} thiz */ - static "__#8@#assertOperator": (thiz: Monitor) => void; + static "__#10@#assertOperator": (thiz: Monitor) => void; /** * ```plain * 向外暴露 Monitor 监听的相关数据 @@ -190,20 +190,16 @@ export class Monitor { * * @param {Monitor} thiz */ - static "__#8@#exposeInfo": (thiz: Monitor) => Set[]; + static "__#10@#exposeInfo": (thiz: Monitor) => Set[]; /** * ```plain * 检查 Monitor 监听的命名参数是否符合要求 * ``` * - * @param {Object} nameds - * @param {Object} checkInfo + * @param {Record} nameds + * @param {Record} checkInfo */ - static "__#8@#check": (nameds: { - [x: string]: any; - }, checkInfo: { - [x: string]: Set; - }) => boolean; + static "__#10@#check": (nameds: Record, checkInfo: Record>) => boolean; /** * ```plain * 处理 Monitor 监听事件 @@ -214,7 +210,7 @@ export class Monitor { * @param {Nameds} nameds * @param {Control} control */ - static "__#8@#handle": (thiz: Monitor, access: number, nameds: { + static "__#10@#handle": (thiz: Monitor, access: number, nameds: { target: any; thisArg?: any; arguments?: Array; @@ -234,7 +230,7 @@ export class Monitor { }, control: { preventDefault: () => void; stopPropagation: () => void; - overrideParameter: (name: "descriptor" | "value" | "target" | "prototype" | "arguments" | "property" | "receiver" | "newTarget" | "thisArg", value: any) => void; + overrideParameter: (name: "descriptor" | "value" | "prototype" | "property" | "receiver" | "newTarget" | "arguments" | "thisArg" | "target", value: any) => void; setReturnValue: (value: any) => void; throwDenied: (message?: string) => never; }) => void; @@ -338,7 +334,7 @@ export class Monitor { * @param {...any} values 命名参数可能的值 * @returns {this} */ - require(name: "descriptor" | "value" | "target" | "prototype" | "arguments" | "property" | "receiver" | "newTarget" | "thisArg", ...values: any[]): this; + require(name: "descriptor" | "value" | "prototype" | "property" | "receiver" | "newTarget" | "arguments" | "thisArg" | "target", ...values: any[]): this; /** * ```plain * 指定 Monitor 监听的过滤器 @@ -408,7 +404,7 @@ export class Monitor { }, control: { preventDefault: () => void; stopPropagation: () => void; - overrideParameter: (name: "descriptor" | "value" | "target" | "prototype" | "arguments" | "property" | "receiver" | "newTarget" | "thisArg", value: any) => void; + overrideParameter: (name: "descriptor" | "value" | "prototype" | "property" | "receiver" | "newTarget" | "arguments" | "thisArg" | "target", value: any) => void; setReturnValue: (value: any) => void; throwDenied: (message?: string) => never; }) => void): this; @@ -440,10 +436,10 @@ export class Monitor { * ``` */ export class Marshal { - static "__#9@#revertTarget": symbol; - static "__#9@#sourceDomain": symbol; - static "__#9@#marshalRules": WeakMap; - static "__#9@#marshalledProxies": WeakSet; + static "__#11@#revertTarget": symbol; + static "__#11@#sourceDomain": symbol; + static "__#11@#marshalRules": WeakMap; + static "__#11@#marshalledProxies": WeakSet; /** * ```plain * 判断是否应该封送 @@ -452,7 +448,7 @@ export class Marshal { * @param {any} obj * @returns {boolean} */ - static "__#9@#shouldMarshal": (obj: any) => boolean; + static "__#11@#shouldMarshal": (obj: any) => boolean; /** * ```plain * 判断是否禁止封送 @@ -461,7 +457,7 @@ export class Marshal { * @param {any} obj * @returns {boolean} */ - static "__#9@#strictMarshal": (obj: any) => boolean; + static "__#11@#strictMarshal": (obj: any) => boolean; /** * ```plain * 拆除封送代理 @@ -475,7 +471,7 @@ export class Marshal { * @param {any} proxy * @returns {Reverted} */ - static "__#9@#revertProxy": (proxy: any) => [Domain, any]; + static "__#11@#revertProxy": (proxy: any) => [Domain, any]; /** * ```plain * 检查封送缓存 @@ -485,7 +481,7 @@ export class Marshal { * @param {Domain} domain * @returns {Object?} */ - static "__#9@#cacheProxy": (obj: any, domain: Domain) => any | null; + static "__#11@#cacheProxy": (obj: any, domain: Domain) => any | null; /** * ```plain * 获取指定对象的封送规则引用 @@ -494,7 +490,7 @@ export class Marshal { * @param {Object} obj * @returns {{rule: Rule}} */ - static "__#9@#ensureRuleRef": (obj: any) => { + static "__#11@#ensureRuleRef": (obj: any) => { rule: Rule; }; /** @@ -561,7 +557,7 @@ export class Marshal { * @param {Domain} domain * @param {() => any} action */ - static "__#9@#trapDomain": (domain: Domain, action: () => any) => any; + static "__#11@#trapDomain": (domain: Domain, action: () => any) => any; /** * ```plain * 封送数组 @@ -571,7 +567,7 @@ export class Marshal { * @param {Domain} targetDomain * @returns {Array} */ - static "__#9@#marshalArray": (array: any[], targetDomain: Domain) => any[]; + static "__#11@#marshalArray": (array: any[], targetDomain: Domain) => any[]; /** * ```plain * 封送对象 @@ -581,7 +577,7 @@ export class Marshal { * @param {Domain} targetDomain * @returns {Object} */ - static "__#9@#marshalObject": (object: any, targetDomain: Domain) => any; + static "__#11@#marshalObject": (object: any, targetDomain: Domain) => any; /** * ```plain * 根据目标对象的特征复制一个基本对象 @@ -590,7 +586,7 @@ export class Marshal { * @param {Object} src * @returns {any} */ - static "__#9@#clonePureObject": (src: any) => any; + static "__#11@#clonePureObject": (src: any) => any; /** * ```plain * 封送核心函数 @@ -600,7 +596,7 @@ export class Marshal { * @param {Domain} targetDomain * @returns {Object} */ - static "__#9@#marshal": (obj: any, targetDomain: Domain) => any; + static "__#11@#marshal": (obj: any, targetDomain: Domain) => any; /** * @param {Symbol} signal * @param {...any} args @@ -615,15 +611,15 @@ export class Marshal { * ``` */ export class Domain { - static "__#10@#hasInstance": (value: any) => boolean; + static "__#12@#hasInstance": (value: any) => boolean; /** @type {Array} */ - static "__#10@#domainStack": Array; + static "__#12@#domainStack": Array; /** @type {Domain} */ - static "__#10@#currentDomain": Domain; + static "__#12@#currentDomain": Domain; /** @type {Domain} */ - static "__#10@#topDomain": Domain; + static "__#12@#topDomain": Domain; /** @type {Array>} */ - static "__#10@#domainLinks": Array; + static "__#12@#domainLinks": Array; /** * ```plain * 检查对象是否是Promise对象 @@ -636,12 +632,12 @@ export class Domain { /** * @param {Domain} domain */ - static "__#10@#enterDomain": (domain: Domain) => void; - static "__#10@#exitDomain": () => void; + static "__#12@#enterDomain": (domain: Domain) => void; + static "__#12@#exitDomain": () => void; /** * @returns {Array} */ - static "__#10@#listDomain": () => Array; + static "__#12@#listDomain": () => Array; /** * ```plain * 获取当前运行域 @@ -733,14 +729,14 @@ export class Domain { * ``` */ export class Sandbox { - static "__#11@#topWindow": any; - static "__#11@#topWindowHTMLElement": any; + static "__#13@#topWindow": any; + static "__#13@#topWindowHTMLElement": any; /** @type {WeakMap} */ - static "__#11@#domainMap": WeakMap; + static "__#13@#domainMap": WeakMap; /** @type {Array} */ - static "__#11@#executingScope": any[]; + static "__#13@#executingScope": any[]; /** @type {WeakMap} */ - static "__#11@#functionRefCodes": WeakMap; + static "__#13@#functionRefCodes": WeakMap; /** * ```plain * 检查沙盒操作运行域 @@ -748,7 +744,7 @@ export class Sandbox { * * @param {Sandbox} thiz */ - static "__#11@#assertOperator": (thiz: Sandbox) => void; + static "__#13@#assertOperator": (thiz: Sandbox) => void; /** * ```plain * 封装沙盒的 Function 函数 @@ -757,7 +753,7 @@ export class Sandbox { * @param {Sandbox} thiz * @param {Window} global */ - static "__#11@#initDomainFunctions": (thiz: Sandbox, global: Window) => void; + static "__#13@#initDomainFunctions": (thiz: Sandbox, global: Window) => void; /** * ```plain * 替代原本的eval函数,阻止访问原生的 window 对象 @@ -767,7 +763,7 @@ export class Sandbox { * @param {any} x * @returns */ - static "__#11@#wrappedEval": (thiz: Sandbox, x: any) => any; + static "__#13@#wrappedEval": (thiz: Sandbox, x: any) => any; /** * ```plain * 核心编译函数 @@ -781,7 +777,7 @@ export class Sandbox { * @param {"exists"|"extend"|"all"} writeContext 当执行的代码尝试为未声明的变量赋值时,应该 根据context与window的变量写入(默认行为)|默认行为并且新的变量写入context|全部写入context * @returns */ - static "__#11@#compileCore": (thiz: Sandbox, code: string, context?: any | null, paramList?: Array | null, inheritScope?: boolean | null, writeContext?: "exists" | "extend" | "all") => (this: any, ...args: any) => any; + static "__#13@#compileCore": (thiz: Sandbox, code: string, context?: any | null, paramList?: Array | null, inheritScope?: boolean | null, writeContext?: "exists" | "extend" | "all") => (this: any, ...args: any) => any; /** * ```plain * 根据运行域获取沙盒对象 @@ -800,8 +796,8 @@ export class Sandbox { * * @param {Sandbox} thiz */ - static "__#11@#createScope": (thiz: Sandbox) => void; - static "__#11@#makeName": (prefix: string, conflict: any) => string; + static "__#13@#createScope": (thiz: Sandbox) => void; + static "__#13@#makeName": (prefix: string, conflict: any) => string; /** * @param {Symbol} signal * @param {...any} args diff --git a/node_modules/@types/noname-typings/nonameModules/noname/util/security.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/util/security.d.ts index 168dc3bdb4..8b694472e4 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/util/security.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/util/security.d.ts @@ -201,3 +201,15 @@ declare function _exec(x: any, scope?: any): any; declare function _exec2(x: any, scope?: any | "window"): any; /** @type {boolean} */ declare let SANDBOX_ENABLED: boolean; +/** @type {typeof import("./sandbox.js").Sandbox} */ +declare let Sandbox: typeof import("./sandbox.js").Sandbox; +/** @type {typeof import("./sandbox.js").AccessAction} */ +declare let AccessAction: typeof import("./sandbox.js").AccessAction; +/** @type {typeof import("./sandbox.js").Domain} */ +declare let Domain: typeof import("./sandbox.js").Domain; +/** @type {typeof import("./sandbox.js").Marshal} */ +declare let Marshal: typeof import("./sandbox.js").Marshal; +/** @type {typeof import("./sandbox.js").Monitor} */ +declare let Monitor: typeof import("./sandbox.js").Monitor; +/** @type {typeof import("./sandbox.js").Rule} */ +declare let Rule: typeof import("./sandbox.js").Rule; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/util/struct/promise-error-handler/chrome.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/util/struct/promise-error-handler/chrome.d.ts index 1c288ff002..440f4cc8cf 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/util/struct/promise-error-handler/chrome.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/util/struct/promise-error-handler/chrome.d.ts @@ -51,4 +51,4 @@ export class ChromePromiseErrorHandler implements PromiseErrorHandler { onErrorPrepare(): void; #private; } -export type PromiseErrorHandler = import("../interface/promise-error-handler").PromiseErrorHandler; +export type PromiseErrorHandler = import('../interface/promise-error-handler').PromiseErrorHandler; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/util/struct/promise-error-handler/firefox.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/util/struct/promise-error-handler/firefox.d.ts index 09d3e5f75a..af3d4a8a5a 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/util/struct/promise-error-handler/firefox.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/util/struct/promise-error-handler/firefox.d.ts @@ -17,4 +17,4 @@ export class FirefoxPromiseErrorHandler implements PromiseErrorHandler { */ onHandle(event: PromiseRejectionEvent): void; } -export type PromiseErrorHandler = import("../interface/promise-error-handler").PromiseErrorHandler; +export type PromiseErrorHandler = import('../interface/promise-error-handler').PromiseErrorHandler; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/util/struct/promise-error-handler/unknown.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/util/struct/promise-error-handler/unknown.d.ts index 9b3172c886..7744f67c74 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/util/struct/promise-error-handler/unknown.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/util/struct/promise-error-handler/unknown.d.ts @@ -19,4 +19,4 @@ export class UnknownPromiseErrorHandler implements PromiseErrorHandler { */ onHandle(event: PromiseRejectionEvent): void; } -export type PromiseErrorHandler = import("../interface/promise-error-handler").PromiseErrorHandler; +export type PromiseErrorHandler = import('../interface/promise-error-handler').PromiseErrorHandler; diff --git a/node_modules/@types/noname-typings/package.json b/node_modules/@types/noname-typings/package.json index 5c9f66ff69..2a84c26ce7 100644 --- a/node_modules/@types/noname-typings/package.json +++ b/node_modules/@types/noname-typings/package.json @@ -24,6 +24,7 @@ "@types/cordova": "*", "@types/node": "*", "@types/codemirror": "*", - "@types/jszip": "^0.0.33" + "@types/jszip": "^0.0.33", + "vue": "^3.4.21" } } \ No newline at end of file diff --git a/node_modules/@types/noname-typings/type.d.ts b/node_modules/@types/noname-typings/type.d.ts index 4875a9af20..0fb5b00881 100644 --- a/node_modules/@types/noname-typings/type.d.ts +++ b/node_modules/@types/noname-typings/type.d.ts @@ -81,7 +81,7 @@ declare type GameHistory = import('./nonameModules/noname/game/index.js').GameHi // declare type CodeMirror = typeof import('codemirror/index'); declare type Sex = 'male' | 'female' | 'dobule' | 'none'; -declare type Character = [Sex, string, number | string, string[], string[]] | [Sex, string, number | string, string[]]; +declare type Character = [Sex, string, number | string, string[], string[]] | [Sex, string, number | string, string[]] | import('./nonameModules/noname/library/element/character.js').Character; declare type Select = [number, number]; declare interface progress extends HTMLDivElement { @@ -300,7 +300,7 @@ declare interface importModeConfig { /** * mode的start启动方法 */ - start(): void; + start: ContentFuncByAll; /** * mode的start启动之前的处理方法 */ diff --git a/noname/ai/index.js b/noname/ai/index.js index 837c69f8cd..d1d0300895 100644 --- a/noname/ai/index.js +++ b/noname/ai/index.js @@ -5,6 +5,34 @@ import { Basic } from "./basic.js"; export class AI { basic = new Basic(); get = get; + /** + * @param { any } obj + * @param { boolean } [similar] true伪equals, false统一前缀 + * @returns { string } cacheKey + */ + getCacheKey(obj, similar) { + let str = "[" + typeof obj + ":"; + if (typeof obj !== "object" || obj === null) { + return str + String(obj) + "]"; + } + if (Array.isArray(obj)) { + return "[array:[" + obj.map(i => { + return this.getCacheKey(i, similar); + }).join("-") + "]]"; + } + if (typeof obj.getCacheKey === "function") { + return obj.getCacheKey(similar); + } + if (similar !== false) { + if (get.itemtype(obj)) str = "[" + get.itemtype(obj) + ":"; + else if (!similar) str = "[undefined:"; + } + try { + return str + JSON.stringify(obj) + "]"; + } catch (error) { + return str + get.translation(obj) + "]"; + } + } } export let ai = new AI(); diff --git a/noname/game/PauseManager.js b/noname/game/PauseManager.js new file mode 100644 index 0000000000..279abf987c --- /dev/null +++ b/noname/game/PauseManager.js @@ -0,0 +1,63 @@ +import { lib, _status } from "../../noname.js" + +export default class PauseManager { + pause = new Deferred(); + pause2 = new Deferred(); + pause3 = new Deferred(); + over = new Deferred(); + delay = new Deferred(); + #delayList = []; + + setDelay(promise) { + if (!this.delay.isStarted) this.delay.start(); + const newValue = promise.then(() => { + if (!this.#delayList.includes(newValue)) return; + this.#delayList.remove(newValue); + if (this.#delayList.length === 0) { + this.delay.resolve(); + } + }); + this.#delayList.push(newValue); + return newValue; + } + + async waitPause() { + if (_status.paused2 || _status.imchoosing) { + if (!lib.status.dateDelaying) { + lib.status.dateDelaying = new Date(); + } + } + await Promise.all([this.pause, this.pause2, this.pause3, this.over, this.delay].filter(i => i.isStarted)); + if (lib.status.dateDelaying) { + lib.status.dateDelayed += lib.getUTC(new Date()) - lib.getUTC(lib.status.dateDelaying); + delete lib.status.dateDelaying; + } + } + +} + +class Deferred { + #promise; + #resolver; + get isStarted() { + return !!this.#promise; + } + start() { + if (this.isStarted) return; + ({ promise: this.#promise, resolve: this.#resolver } = Promise.withResolvers()); + } + resolve() { + if (!this.isStarted) return; + Promise.resolve() + .then(() => this.#resolver && this.#resolver()) + .then(() => { + this.#promise = null; + this.#resolver = null; + }); + } + then(onfulfilled, onrejected) { + if (!this.#promise) return Promise.resolve().then(onfulfilled, onrejected); + return this.#promise.then(onfulfilled, onrejected); + } + +} \ No newline at end of file diff --git a/noname/game/PauseManager.ts b/noname/game/PauseManager.ts new file mode 100644 index 0000000000..782569a245 --- /dev/null +++ b/noname/game/PauseManager.ts @@ -0,0 +1,63 @@ +import { lib, _status } from "../../noname.js" + +export default class PauseManager { + pause = new Deferred(); + pause2 = new Deferred(); + pause3 = new Deferred(); + over = new Deferred(); + delay = new Deferred(); + #delayList: Promise[] = []; + + setDelay(promise: Promise) { + if (!this.delay.isStarted) this.delay.start(); + const newValue = promise.then(() => { + if (!this.#delayList.includes(newValue)) return; + this.#delayList.remove(newValue); + if (this.#delayList.length === 0) { + this.delay.resolve(); + } + }); + this.#delayList.push(newValue); + return newValue; + } + + async waitPause() { + if (_status.paused2 || _status.imchoosing) { + if (!lib.status.dateDelaying) { + lib.status.dateDelaying = new Date(); + } + } + await Promise.all([this.pause, this.pause2, this.pause3, this.over, this.delay].filter(i => i.isStarted)); + if (lib.status.dateDelaying) { + lib.status.dateDelayed += lib.getUTC(new Date()) - lib.getUTC(lib.status.dateDelaying); + delete lib.status.dateDelaying; + } + } + +} + +class Deferred { + #promise: Promise | null; + #resolver: (() => void) | null; + get isStarted() { + return !!this.#promise; + } + start() { + if (this.isStarted) return; + ({ promise: this.#promise, resolve: this.#resolver } = Promise.withResolvers()); + } + resolve() { + if (!this.isStarted) return; + Promise.resolve() + .then(() => this.#resolver && this.#resolver()) + .then(() => { + this.#promise = null; + this.#resolver = null; + }); + } + then(onfulfilled?: ((value: void) => void | PromiseLike) | null, onrejected?: ((reason: any) => never | PromiseLike) | null) { + if (!this.#promise) return Promise.resolve().then(onfulfilled, onrejected); + return this.#promise.then(onfulfilled, onrejected); + } + +} \ No newline at end of file diff --git a/noname/game/index.js b/noname/game/index.js index f46304065f..3376d12085 100644 --- a/noname/game/index.js +++ b/noname/game/index.js @@ -463,6 +463,7 @@ export class Game extends GameCompatible { cards: [], cards2: [], gaintag_map: {}, + vcard_map: new Map(), }; player.checkHistory("lose", function (evt) { if (evt.parent == that) { @@ -477,6 +478,9 @@ export class Game extends GameCompatible { if (!map.gaintag_map[key]) map.gaintag_map[key] = []; map.gaintag_map[key].addArray(evt.gaintag_map[key]); } + evt.vcard_map.forEach((value, key) => { + map.vcard_map.set(key, value); + }); } }); return map; @@ -1358,6 +1362,7 @@ export class Game extends GameCompatible { lib.node.torespondtimeout = {}; lib.playerOL = {}; lib.cardOL = {}; + lib.vcardOL = {}; lib.wsOL = {}; ui.create.roomInfo(); ui.create.chat(); @@ -1565,10 +1570,11 @@ export class Game extends GameCompatible { * @param { boolean } [directaudio] * @param { boolean } [nobroadcast] * @param { any } [skillInfo] + * @param { any[] } [args] logAudio的参数 * @returns */ - trySkillAudio(skill, player, directaudio, nobroadcast, skillInfo) { - if (!nobroadcast) game.broadcast(game.trySkillAudio, skill, player, directaudio, nobroadcast, skillInfo); + trySkillAudio(skill, player, directaudio, nobroadcast, skillInfo, args) { + if (!nobroadcast) game.broadcast(game.trySkillAudio, skill, player, directaudio, nobroadcast, skillInfo, args); if (!lib.config.background_speak) return; const info = skillInfo || lib.skill[skill]; @@ -1576,7 +1582,9 @@ export class Game extends GameCompatible { if (info.direct && !directaudio) return; if (lib.skill.global.includes(skill) && !info.forceaudio) return; - const audioList = get.Audio.skill({ skill, player, info: skillInfo }).fileList; + // if (!info.audio && info.sourceSkill) skill = info.sourceSkill.toString(); + + let audioList = get.Audio.skill({ skill, player, info: skillInfo, args }).fileList; return game.tryAudio({ audioList }); } /** @@ -1814,7 +1822,7 @@ export class Game extends GameCompatible { const promise = Promise.resolve((gnc.is.generator(content) ? gnc.of(content) : content)(lib, game, ui, get, ai, _status)).then(content2 => { if (content2.name) { lib.imported[type][content2.name] = content2; - delete content2.name; + // delete content2.name; } }); if (typeof _status.importing == "undefined") _status.importing = {}; @@ -1963,7 +1971,7 @@ export class Game extends GameCompatible { if (!lib.config.extension_alert) alert(`加载《${name}》扩展的precontent时出现错误。\n该错误本身可能并不影响扩展运行。您可以在“设置→通用→无视扩展报错”中关闭此弹窗。\n${decodeURI(e1.stack)}`); } - if (content) lib.extensions.push([name, content, config, _status.evaluatingExtension, objectPackage || {}]); + if (content) lib.extensions.push([name, content, config, _status.evaluatingExtension, objectPackage || {}, object.connect]); } catch (e) { console.log(e); } @@ -1975,6 +1983,33 @@ export class Game extends GameCompatible { * @type { undefined | ((url: string, folder: string, onsuccess?: Function, onerror?: (e: Error) => void, dev?: 'nodev', onprogress?: Function) => void) } */ download; + + /** + * 检查指定的路径是否是一个文件 + * + * @param {string} fileName - 需要查询的路径 + * @param {(result: -1 | 0 | 1) => void} [callback] - 回调函数;接受的参数意义如下: + * - `-1`: 路径不存在或无法访问 + * - `0`: 路径的内容不是文件 + * - `1`: 路径的内容是文件 + * @param {(err: Error) => void} [onerror] - 接收错误的回调函数 + * @return {void} - 由于三端的异步需求和历史原因,文件管理必须为回调异步函数 + */ + checkFile; + + /** + * 检查指定的路径是否是一个目录 + * + * @param {string} dir - 需要查询的路径 + * @param {(result: -1 | 0 | 1) => void} [callback] - 回调函数;接受的参数意义如下: + * - `-1`: 路径不存在或无法访问 + * - `0`: 路径的内容不是目录 + * - `1`: 路径的内容是目录 + * @param {(err: Error) => void} [onerror] - 接收错误的回调函数 + * @return {void} - 由于三端的异步需求和历史原因,文件管理必须为回调异步函数 + */ + checkDir; + /** * 读取文件为arraybuffer * @type { undefined | ((filename: string, callback?: (data: Buffer | ArrayBuffer) => any, onerror?: (e: Error) => void) => void) } @@ -2508,6 +2543,27 @@ export class Game extends GameCompatible { } } }, + cardtag: function (cardtag) { + _status.cardtag = cardtag; + }, + addVirtualEquip: function (player, map) { + const card = get.infoVCard(map[0]), + cards = get.infoCards(map[1]); + player.addVirtualEquip(card, cards); + }, + addVirtualJudge: function (player, map) { + const card = get.infoVCard(map[0]), + cards = get.infoCards(map[1]); + player.addVirtualJudge(card, cards); + }, + removeVirtualEquip: function (player, card) { + card = get.infoVCard(card); + player.removeVirtualEquip(card); + }, + removeVirtualJudge: function (player, card) { + card = get.infoVCard(card); + player.removeVirtualJudge(card); + }, $syncDisable: function (player, map) { player.disabledSlots = map; player.$syncDisable(map); @@ -3273,7 +3329,13 @@ export class Game extends GameCompatible { var checkMatch = function (l1, l2) { for (var i = 0; i < l1.length; i++) { for (var j = 0; j < l2.length; j++) { - if (l2[j].suit == l1[i][0] && l2[j].number == l1[i][1] && l2[j].name == l1[i][2]) { + if (l1[i].length === 5) { + if (l1[i][4] === l2[j].cardid) { + l2[j].addGaintag(content[1]); + l2.splice(j--, 1); + break; + } + } else if (l2[j].suit == l1[i][0] && l2[j].number == l1[i][1] && l2[j].name == l1[i][2]) { l2[j].addGaintag(content[1]); l2.splice(j--, 1); break; @@ -3281,7 +3343,7 @@ export class Game extends GameCompatible { } } }; - checkMatch(content[0], player.getCards("h")); + checkMatch(content[0], player.getCards("hs")); } else { console.log(player); } @@ -3292,8 +3354,14 @@ export class Game extends GameCompatible { const checkMatch = function (l1, l2) { for (var i = 0; i < l1.length; i++) { for (var j = 0; j < l2.length; j++) { - if (l2[j].suit == l1[i][0] && l2[j].number == l1[i][1] && l2[j].name == l1[i][2]) { - l2[j].addGaintag(content[0]); + if (l1[i].length === 5) { + if (l1[i][4] === l2[j].cardid) { + l2[j].removeGaintag(content[0]); + l2.splice(j--, 1); + break; + } + } else if (l2[j].suit == l1[i][0] && l2[j].number == l1[i][1] && l2[j].name == l1[i][2]) { + l2[j].removeGaintag(content[0]); l2.splice(j--, 1); break; } @@ -3301,7 +3369,7 @@ export class Game extends GameCompatible { } }; // player.removeGaintag.apply(player, content); - checkMatch(content[1], player.getCards("h")); + checkMatch(content[1], player.getCards("hs")); } else player.removeGaintag(content); } else { console.log(player); @@ -3453,7 +3521,9 @@ export class Game extends GameCompatible { }, directgains: function (player, cards) { if (player && cards) { - player.directgains(get.infoCards(cards)); + if (get.is.object(cards)) { + player.directgains(get.infoCards(cards.cards), null, cards.gaintag); + } else player.directgains(get.infoCards(cards)); } else { console.log(player); } @@ -3597,7 +3667,17 @@ export class Game extends GameCompatible { var checkMatch = function (l1, l2) { for (var i = 0; i < l1.length; i++) { for (var j = 0; j < l2.length; j++) { - if (l2[j].suit == l1[i][0] && l2[j].number == l1[i][1] && l2[j].name == l1[i][2]) { + if (l1[i].length === 5) { + if (l1[i][4] === l2[j].cardid) { + l2[j].classList.remove("glow"); + l2[j].classList.remove("glows"); + l2[j].remove(); + l2.splice(j--, 1); + break; + } + } else if (l2[j].suit == l1[i][0] && l2[j].number == l1[i][1] && l2[j].name == l1[i][2]) { + l2[j].classList.remove("glow"); + l2[j].classList.remove("glows"); l2[j].remove(); l2.splice(j--, 1); break; @@ -3888,7 +3968,9 @@ export class Game extends GameCompatible { } } reloadCurrent() { - game.saveConfig("continue_name", [game.me.name1 || game.me.name, game.me.name2]); + let names = [game.me.name1 || game.me.name, game.me.name2]; + if(game.me.name1 != game.me.name) names = [game.me.name]; + game.saveConfig("continue_name", names); game.saveConfig("mode", lib.config.mode); localStorage.setItem(lib.configprefix + "directstart", true); game.reload(); @@ -3925,7 +4007,7 @@ export class Game extends GameCompatible { } /** * @param { string } type - * @param { Player } player + * @param { Player|null } player * @param { any } [content] * @returns */ @@ -3961,6 +4043,9 @@ export class Game extends GameCompatible { }); _status.lastVideoLog = time; } + if (type === "init") { + game.addVideo("cardtag", null, _status.cardtag); + } } /** * @param { Function } func @@ -4501,11 +4586,13 @@ export class Game extends GameCompatible { * * @param { string } name * @param { false } [trigger] - * @param { GameEventPromise } [triggerEvent] + * @param { GameEvent } [triggerEvent] */ createEvent(name, trigger, triggerEvent) { - const next = new lib.element.GameEvent(name, trigger).toPromise(); - (triggerEvent || _status.event).next.push(next); + const next = new lib.element.GameEvent(name, trigger, _status.eventManager); + const parent = triggerEvent || _status.eventManager.getStartedEvent(); + if (parent) parent.next.push(next); + else _status.event = next; return next; } /** @@ -5617,339 +5704,46 @@ export class Game extends GameCompatible { } } /** - * @type { Map> } - * - * 以Promise储存异步事件的执行链,使async content调用事件时无需必须使用await - * - * 但是需要事件结果的除外 - */ - executingAsyncEventMap = new Map(); - /** - * @type { GameEventPromise[] } - */ - belongAsyncEventList = []; - /** - * @param { GameEventPromise } [belongAsyncEvent] + * @param { GameEvent } [event] */ - async loop(belongAsyncEvent) { - if (belongAsyncEvent) { - game.belongAsyncEventList.push(belongAsyncEvent); - } else if (game.belongAsyncEventList.length) { - belongAsyncEvent = game.belongAsyncEventList.at(-1); - } - while (true) { - let event = belongAsyncEvent && belongAsyncEvent.parent == _status.event ? belongAsyncEvent : _status.event; - let { step, source, player, target, targets, card, cards, skill, forced, num, _trigger: trigger, _result: result } = event; - const _resolve = () => { - if (event.async) { - if (typeof event.resolve == "function") { - event.resolve(event.toEvent()); - } else { - throw new TypeError("异步事件的event.resolve未赋值,使用await时将会被永久等待"); - } - } - }; - if (_status.paused2 || _status.imchoosing) { - if (!lib.status.dateDelaying) { - lib.status.dateDelaying = new Date(); - } - } - if (_status.paused || _status.paused2 || _status.over) { - return; - } - if (_status.paused3) { - _status.paused3 = "paused"; - return; - } - if (lib.status.dateDelaying) { - lib.status.dateDelayed += lib.getUTC(new Date()) - lib.getUTC(lib.status.dateDelaying); - delete lib.status.dateDelaying; - } - if (event.next.length > 0) { - var next = event.next.shift(); - if (next.player && next.player.skipList.includes(next.name)) { - event.trigger(next.name + "Skipped"); - next.player.skipList.remove(next.name); - if (lib.phaseName.includes(next.name)) next.player.getHistory("skipped").add(next.name); - } else { - next.parent = event; - _status.event = next; - game.getGlobalHistory("everything").push(next); - } - } else if (event.finished) { - if (event._triggered == 1) { - if (event.type == "card") event.trigger("useCardToOmitted"); - event.trigger(event.name + "Omitted"); - event._triggered = 4; - } else if (event._triggered == 2) { - if (event.type == "card") event.trigger("useCardToEnd"); - event.trigger(event.name + "End"); - event._triggered = 3; - } else if (event._triggered == 3) { - if (event.type == "card") event.trigger("useCardToAfter"); - event.trigger(event.name + "After"); - event._triggered++; - } else if (event.after && event.after.length) { - var next = event.after.shift(); - if (next.player && next.player.skipList.includes(next.name)) { - event.trigger(next.name + "Skipped"); - next.player.skipList.remove(next.name); - if (lib.phaseName.includes(next.name)) next.player.getHistory("skipped").add(next.name); - } else { - next.parent = event; - _status.event = next; - game.getGlobalHistory("everything").push(next); - } - } else { - game.executingAsyncEventMap.delete(event.toEvent()); - if (event.parent) { - if (event.result) { - event.parent._result = event.result; - } - _status.event = event.parent; - if (game.belongAsyncEventList.includes(event)) { - game.belongAsyncEventList.remove(event); - } - _resolve(); - // 此时应该退出了 - if (belongAsyncEvent && belongAsyncEvent.parent == _status.event) { - return; - } - } else { - if (game.belongAsyncEventList.includes(event)) { - game.belongAsyncEventList.remove(event); - } - return _resolve(); - } - } - } else { - if (event._triggered == 0) { - if (event.type == "card") event.trigger("useCardToBefore"); - event.trigger(event.name + "Before"); - event._triggered++; - } else if (event._triggered == 1) { - if (event.type == "card") event.trigger("useCardToBegin"); - event.trigger(event.name + "Begin"); - event._triggered++; - } else { - event.callHandler(event.getDefaultHandlerType(), event, { - state: "begin", - }); - const after = () => { - event.clearStepCache(); - event.callHandler(event.getDefaultHandlerType(), event, { - state: "end", - }); - if (typeof event.step == "number") ++event.step; - }; - if (player && player.classList.contains("dead") && !event.forceDie && event.name != "phaseLoop") { - game.broadcastAll(function () { - while (_status.dieClose.length) { - _status.dieClose.shift().close(); - } - }); - if (event._oncancel) { - event._oncancel(); - } - event.finish(); - after(); - } else if (player && player.removed && event.name != "phaseLoop") { - event.finish(); - after(); - } else if (player && player.isOut() && event.name != "phaseLoop" && !event.includeOut) { - if (event.name == "phase" && player == _status.roundStart && !event.skill) { - _status.roundSkipped = true; - } - event.finish(); - after(); - } else { - await game - .runContent(belongAsyncEvent) - .catch(e => { - if (_status.withError || lib.config.compatiblemode || (_status.connectMode && !lib.config.debug)) { - game.print("游戏出错:" + event.name); - game.print(e.toString()); - console.log(e); - } else throw e; - }) - .then(after) - .then(() => { - if (event.finished) { - game.executingAsyncEventMap.delete(event.toEvent()); - } - }); - } - } - } - } - } - /** - * @param { GameEventPromise } [belongAsyncEvent] - */ - runContent(belongAsyncEvent) { - return new Promise(resolve => { - let event = belongAsyncEvent && belongAsyncEvent.parent == _status.event ? belongAsyncEvent : _status.event; - let { step, source, player, target, targets, card, cards, skill, forced, num, _trigger: trigger, _result: result, _storeEvent } = event; - // 数组形式 - if ("contents" in event && Array.isArray(event.contents)) { - /* - event.contents[step](event, trigger, player, _storeEvent).then((evt) => { - if (evt) event._storeEvent = evt; - if (game.executingAsyncEventMap.has(event.toEvent())) { - game.executingAsyncEventMap.set(_status.event.toEvent(), game.executingAsyncEventMap.get(_status.event.toEvent()).then(() => { - if (event.step >= event.contents.length - 1) event.finish(); - resolve(); - })); - } else { - if (event.step >= event.contents.length - 1) event.finish(); - resolve(); - } - }); - */ - // 解决不了问题...就把问题统一 - const run = async event => { - if (typeof event.step !== "number") event.step = 0; - while (event.step < event.contents.length && !event.finished) { - const evt = await event.contents[event.step](event, event._trigger, event.player, event._tmpStoreEvent); - if (evt) event._tmpStoreEvent = evt; - - if (game.executingAsyncEventMap.has(event.toEvent())) { - await game.executingAsyncEventMap.get(_status.event.toEvent()); - await game.executingAsyncEventMap.get(event.toEvent()); - } - - ++event.step; - } - --event.step; - }; - - run(event).then(() => { - // 其实这个if几乎一定执行了 - if (game.executingAsyncEventMap.has(event.toEvent())) { - if (!game.executingAsyncEventMap.get(_status.event.toEvent())) { - console.warn(`game.executingAsyncEventMap中包括了event,但不包括_status.event!`); - console.log("event :>> ", event.toEvent()); - console.log("_status.event :>> ", _status.event.toEvent()); - // debugger; - game.executingAsyncEventMap.set( - event.toEvent(), - game.executingAsyncEventMap.get(event.toEvent()).then(() => { - event.finish(); - resolve(); - }) - ); - } else { - game.executingAsyncEventMap.set( - _status.event.toEvent(), - game.executingAsyncEventMap.get(_status.event.toEvent()).then(() => { - event.finish(); - resolve(); - }) - ); - } - } else { - event.finish(); - resolve(); - } - }); - } else if (event.content instanceof GeneratorFunction) { - if (!event.debugging) { - if (event.generatorContent) event.generatorContent.return(); - event.generatorContent = event.content(event, step, source, player, target, targets, card, cards, skill, forced, num, trigger, result, _status, lib, game, ui, get, ai); - } else { - delete event.debugging; - } - var next = event.generatorContent.next(); - if (typeof next.value == "function" && next.value.toString() == "code=>eval(code)") { - //触发debugger - var inputCallback = inputResult => { - if (inputResult === false) { - event.debugging = true; - game.resume2(); - } else { - alert(get.stringify(next.value(inputResult))); - game.prompt("", "debugger调试", inputCallback); - } - }; - game.prompt("", "debugger调试", inputCallback); - return game.pause2(); - } - if (event.finished) event.generatorContent.return(); - resolve(); - } else if (event.content instanceof AsyncFunction) { - // _status,lib,game,ui,get,ai六个变量由game.import提供 - // 使用另一种方式来停止event.content - const { promise, resolve: resolveContent } = Promise.withResolvers(); - promise.then(() => { - // 其实这个if几乎一定执行了 - if (game.executingAsyncEventMap.has(event.toEvent())) { - if (!game.executingAsyncEventMap.get(_status.event.toEvent())) { - console.warn(`game.executingAsyncEventMap中包括了event,但不包括_status.event!`); - console.log("event :>> ", event.toEvent()); - console.log("_status.event :>> ", _status.event.toEvent()); - game.executingAsyncEventMap.set( - event.toEvent(), - game.executingAsyncEventMap.get(event.toEvent()).then(() => { - event.finish(); - resolve(); - }) - ); - } else { - game.executingAsyncEventMap.set( - _status.event.toEvent(), - game.executingAsyncEventMap.get(_status.event.toEvent()).then(() => { - event.finish(); - resolve(); - }) - ); - } - } else { - event.finish(); - resolve(); - } - }); - event.resolveContent = resolveContent; - event.content(event, trigger, player).finally(() => resolveContent()); - } else { - event.content(event, step, source, player, target, targets, card, cards, skill, forced, num, trigger, result, _status, lib, game, ui, get, ai); - resolve(); - } - }); + loop(event = _status.event) { + if (!event) throw new Error("There is no _status.event when game.loop."); + return event.start(); } pause() { - clearTimeout(_status.timeout); _status.paused = true; + return _status.pauseManager.pause; } pause2() { - if (_status.connectMode) return; - _status.paused2 = true; + if (!_status.connectMode) _status.paused2 = true; + return _status.pauseManager.pause2; } resume() { - if (_status.paused) { - if (!_status.noclearcountdown) { - game.stopCountChoose(); - } - _status.paused = false; - delete _status.waitingForTransition; - if ((_status.event && _status.event.content instanceof AsyncFunction) || Array.isArray(_status.event.contents)) return; - game.loop(); - } + if (!_status.paused) return; + if (!_status.noclearcountdown) game.stopCountChoose(); + _status.paused = false; + delete _status.waitingForTransition; } resume2() { if (_status.connectMode) return; - if (_status.paused2) { - _status.paused2 = false; - if ((_status.event && _status.event.content instanceof AsyncFunction) || Array.isArray(_status.event.contents)) return; - game.loop(); - } + if (!_status.paused2) return; + _status.paused2 = false; } - delaye() { + /** + * @param { number } [time] + * @param { number } [time2] + */ + delaye(time = 1, time2 = 0) { let next = game.createEvent("delay", false); next.setContent("delay"); next._args = Array.from(arguments); return next; } - delayex() { + /** + * @param { number } [time] + * @param { number } [time2] + */ + delayex(time = 1, time2 = 0) { let next = game.createEvent("delayx", false); next.setContent("delay"); next._args = Array.from(arguments); @@ -5959,21 +5753,16 @@ export class Game extends GameCompatible { * @param { number } [time] * @param { number } [time2] */ - delay(time, time2) { - if (_status.paused) return; - game.pause(); - if (typeof time != "number") time = 1; - if (typeof time2 != "number") time2 = 0; + delay(time = 1, time2 = 0) { time = time * lib.config.duration + time2; if (lib.config.speed == "vvfast") time /= 3; - _status.timeout = setTimeout(game.resume, time); + return _status.pauseManager.setDelay(delay(time)); } /** * @param { number } [time] * @param { number } [time2] */ - delayx(time, time2) { - if (typeof time != "number") time = 1; + delayx(time = 1, time2 = 0) { switch (lib.config.game_speed) { case "vslow": time *= 2.5; @@ -5994,54 +5783,19 @@ export class Game extends GameCompatible { return game.delay(time, time2); } /** - * 在async content中对game.delay的代替使用方法 - * - * 因为async content里不应该使用game.pause和game.resume - * - * @param { number } [time] - * @param { number } [time2] + * @deprecated */ asyncDelay(time, time2) { - // if(_status.paused) return; - // game.pause(); - if (typeof time != "number") time = 1; - if (typeof time2 != "number") time2 = 0; - time = time * lib.config.duration + time2; - if (lib.config.speed == "vvfast") time /= 3; - //_status.timeout=setTimeout(game.resume,time); - return delay(time); + return game.delay(time, time2); } /** - * 在async content中对game.delayx的代替使用方法 - * - * 因为async content里不应该使用game.pause和game.resume - * - * @param { number } [time] - * @param { number } [time2] + * @deprecated */ asyncDelayx(time, time2) { - if (typeof time != "number") time = 1; - switch (lib.config.game_speed) { - case "vslow": - time *= 2.5; - break; - case "slow": - time *= 1.5; - break; - case "fast": - time *= 0.7; - break; - case "vfast": - time *= 0.4; - break; - case "vvfast": - time *= 0.2; - break; - } - return game.asyncDelay(time, time2); + return game.delayx(time, time2); } /** - * @param { GameEventPromise } [event] + * @param { GameEvent } [event] */ check(event = _status.event) { game.callHook("checkBegin", [event]); @@ -6376,29 +6130,47 @@ export class Game extends GameCompatible { let players = get.players(lib.sort.position); let position = parseInt(player.dataset.position); for (let i = 0; i < players.length; i++) { - if (parseInt(players[i].dataset.position) >= position) { - return players[i]; - } + if (parseInt(players[i].dataset.position) >= position) return players[i]; } return players[0]; } /** * @param { string } name - * @param { Function } callback + * @param { (exports: importModeConfig) => any } [callback] + * @param { (error: unknown) => any } [onerror] */ - loadModeAsync(name, callback) { - window.game = game; - let script = lib.init.js(lib.assetURL + "mode", name, async () => { + loadModeAsync(name, callback, onerror = e => console.error(e)) { + let promise = (async () => { + window.game = game; + const exports = await import(`../../mode/${name}.js`); + // esm模式 + if (Object.keys(exports).length > 0) { + if (typeof exports.default !== 'function') { + throw new Error(`导入的模式[${name}]格式不正确!`); + } + game.import('mode', exports.default); + } + // 普通模式 + else { + await new Promise((resolve, reject) => { + let script = lib.init.js(`${lib.assetURL}mode`, name, () => { + script?.remove(); + resolve(null); + }, e => reject(e.error)); + }); + } await Promise.allSettled(_status.importing.mode); if (!lib.config.dev) delete window.game; - script.remove(); - let content = lib.imported.mode[name]; + const content = lib.imported.mode[name]; + if (!content) throw new Error(`导入的模式[${name}]格式不正确!`); delete lib.imported.mode[name]; if (get.is.empty(lib.imported.mode)) { delete lib.imported.mode; } - callback(content); - }); + return content; + })(); + if (callback) promise = promise.then(callback, onerror); + return promise; } /** * @param { string } name @@ -6414,52 +6186,47 @@ export class Game extends GameCompatible { } } } - window.game = game; - let script = lib.init.js(lib.assetURL + "mode", name, async () => { - await Promise.allSettled(_status.importing.mode); - if (!lib.config.dev) delete window.game; - script.remove(); - let mode = lib.imported.mode; + game.loadModeAsync(name, async exports => { + let mode = exports; _status.sourcemode = lib.config.mode; lib.config.mode = name; - let i, j, k; - for (i in mode[lib.config.mode].element) { + for (let i in exports.element) { if (!lib.element[i]) lib.element[i] = []; - for (j in mode[lib.config.mode].element[i]) { + for (let j in exports.element[i]) { if (j == "init") { if (!lib.element[i].inits) lib.element[i].inits = []; - lib.element[i].inits.push(mode[lib.config.mode].element[i][j]); + lib.element[i].inits.push(exports.element[i][j]); } else { - lib.element[i][j] = mode[lib.config.mode].element[i][j]; + lib.element[i][j] = exports.element[i][j]; } } } - for (i in mode[lib.config.mode].ai) { - if (typeof mode[lib.config.mode].ai[i] == "object") { + for (let i in exports.ai) { + if (typeof exports.ai[i] == "object") { if (ai[i] == undefined) ai[i] = {}; - for (j in mode[lib.config.mode].ai[i]) { - ai[i][j] = mode[lib.config.mode].ai[i][j]; + for (let j in exports.ai[i]) { + ai[i][j] = exports.ai[i][j]; } } else { - ai[i] = mode[lib.config.mode].ai[i]; + ai[i] = exports.ai[i]; } } - for (i in mode[lib.config.mode].ui) { - if (typeof mode[lib.config.mode].ui[i] == "object") { + for (let i in exports.ui) { + if (typeof exports.ui[i] == "object") { if (ui[i] == undefined) ui[i] = {}; - for (j in mode[lib.config.mode].ui[i]) { - ui[i][j] = mode[lib.config.mode].ui[i][j]; + for (let j in exports.ui[i]) { + ui[i][j] = exports.ui[i][j]; } } else { - ui[i] = mode[lib.config.mode].ui[i]; + ui[i] = exports.ui[i]; } } - for (i in mode[lib.config.mode].game) { - game[i] = mode[lib.config.mode].game[i]; + for (let i in exports.game) { + game[i] = exports.game[i]; } - for (i in mode[lib.config.mode].get) { - get[i] = mode[lib.config.mode].get[i]; + for (let i in exports.get) { + get[i] = exports.get[i]; } if (game.onwash) { lib.onwash.push(game.onwash); @@ -6472,18 +6239,11 @@ export class Game extends GameCompatible { lib.config.banned = lib.config[lib.config.mode + "_banned"] || []; lib.config.bannedcards = lib.config[lib.config.mode + "_bannedcards"] || []; - for (i in mode[lib.config.mode]) { - if (i == "element") continue; - if (i == "game") continue; - if (i == "ai") continue; - if (i == "ui") continue; - if (i == "get") continue; - if (i == "config") continue; - if (i == "start") continue; - if (i == "startBefore") continue; - if (lib[i] == undefined) lib[i] = Array.isArray(mode[lib.config.mode][i]) ? [] : {}; - for (j in mode[lib.config.mode][i]) { - lib[i][j] = mode[lib.config.mode][i][j]; + for (let i in exports) { + if (["element", "game", "ai", "ui", "get", "config", "start", "startBefore"].includes(i)) continue; + if (lib[i] == undefined) lib[i] = Array.isArray(exports[i]) ? [] : {}; + for (let j in exports[i]) { + lib[i][j] = exports[i][j]; } } @@ -6527,7 +6287,7 @@ export class Game extends GameCompatible { lib.card.list = lib.card.list.concat(lib.cardPackList[i]); } } - for (i = 0; i < lib.card.list.length; i++) { + for (let i = 0; i < lib.card.list.length; i++) { if (lib.card.list[i][2] == "huosha") { lib.card.list[i] = lib.card.list[i].slice(0); lib.card.list[i][2] = "sha"; @@ -6553,15 +6313,14 @@ export class Game extends GameCompatible { ui.playerids.style.display = ""; } - if (mode[lib.config.mode].startBefore) mode[lib.config.mode].startBefore(); - game.createEvent("game", false).setContent(mode[lib.config.mode].start); + if (exports.startBefore) exports.startBefore(); + game.createEvent("game", false).setContent(exports.start); if (lib.mode[lib.config.mode] && lib.mode[lib.config.mode].fromextension) { - let startstr = mode[lib.config.mode].start.toString(); + let startstr = exports.start.toString(); if (startstr.indexOf("onfree") == -1) { setTimeout(lib.init.onfree, 500); } } - delete lib.imported.mode[name]; if (!lib.db) { try { @@ -6574,7 +6333,7 @@ export class Game extends GameCompatible { } game.loop(); } else { - game.getDB("data", lib.config.mode, function (obj) { + game.getDB("data", lib.config.mode, obj => { lib.storage = obj || {}; game.loop(); }); @@ -7148,17 +6907,19 @@ export class Game extends GameCompatible { * @param { { drawDeck: boolean } } [drawDeck] * @param { boolean } [bottom] */ - async asyncDraw(players, num, drawDeck, bottom) { - for (let index = 0; index < players.length; index++) { - const value = players[index]; - let num2 = 1; - if (typeof num == "number") num2 = num; - else if (Array.isArray(num)) num2 = num[index]; - else if (typeof num == "function") num2 = num(value); - if (drawDeck && drawDeck.drawDeck) await value.draw(num2, false, drawDeck); - else if (bottom) await value.draw(num2, "nodelay", "bottom"); - else await value.draw(num2, "nodelay"); - } + asyncDraw(players, num, drawDeck, bottom) { + return Promise.all( + players.map((player, index) => { + let num2 = 1; + if (typeof num === "number") num2 = num; + else if (Array.isArray(num)) num2 = num[index]; + else if (typeof num === "function") num2 = num(player); + + if (drawDeck && drawDeck.drawDeck) return player.draw(num2, false, drawDeck); + if (bottom) return player.draw(num2, "nodelay", "bottom"); + return player.draw(num2, "nodelay"); + }) + ); } /** * @param { Player[] } players @@ -7332,7 +7093,7 @@ export class Game extends GameCompatible { if (method == "raw2") return equipValue - value; return Math.max(0.1, equipValue - value); }, - aiResultTarget = (player, target, card) => get.equipResult(player, target, card.name); + aiResultTarget = (player, target, card) => get.equipResult(player, target, card); Object.keys(lib.card).forEach(libCardKey => { const info = `${libCardKey}_info`; if (lib.translate[`${info}_${mode}`]) lib.translate[info] = lib.translate[`${info}_${mode}`]; @@ -7410,7 +7171,7 @@ export class Game extends GameCompatible { return arg[arg.length - 1]; } /** - * @param { number } num + * @param { number } [num] */ prepareArena(num) { _status.prepareArena = true; @@ -8380,7 +8141,7 @@ export class Game extends GameCompatible { * @param { (player: Player) => boolean } func * @param { boolean } [includeOut] */ - countPlayer2(func, includeOut) { + countPlayer2(func = lib.filter.all, includeOut) { if (typeof func != "function") func = lib.filter.all; return game.players.concat(game.dead).reduce((previousValue, currentValue) => { if (!includeOut && currentValue.isOut()) return previousValue; @@ -8390,10 +8151,6 @@ export class Game extends GameCompatible { return previousValue; }, 0); } - /** - * @overload - * @returns { Player[] } - */ /** * @overload * @param { (player: Player) => boolean } func @@ -8406,10 +8163,6 @@ export class Game extends GameCompatible { if (typeof func != "function") func = lib.filter.all; return list.addArray(game.players.filter(value => (includeOut || !value.isOut()) && func(value))); } - /** - * @overload - * @returns { Player[] } - */ /** * @overload * @param { (player: Player) => boolean } func diff --git a/noname/game/promises.js b/noname/game/promises.js index 8f0c8d9a50..29cce744bb 100644 --- a/noname/game/promises.js +++ b/noname/game/promises.js @@ -173,4 +173,34 @@ export class GamePromises { saveExtensionConfigValue(extension, key) { return game.promises.saveExtensionConfig(extension, key, game.getExtensionConfig(extension, key)); } + + /** + * 检查指定的路径是否是一个文件 + * + * @param {string} fileName - 需要查询的路径 + * @return {Promise<(-1 | 0 | 1)>} - 返回值意义如下: + * - `-1`: 路径不存在或无法访问 + * - `0`: 路径的内容不是文件 + * - `1`: 路径的内容是文件 + */ + checkFile(fileName) { + return new Promise((resolve, reject) => { + game.checkFile(fileName, resolve, reject); + }); + } + + /** + * 检查指定的路径是否是一个目录 + * + * @param {string} dir - 需要查询的路径 + * @return {Promise<(-1 | 0 | 1)>} - 返回值意义如下: + * - `-1`: 路径不存在或无法访问 + * - `0`: 路径的内容不是目录 + * - `1`: 路径的内容是目录 + */ + checkDir(dir) { + return new Promise((resolve, reject) => { + game.checkDir(dir, resolve, reject); + }); + } } diff --git a/noname/get/audio.js b/noname/get/audio.js index a62334dbc6..06332f2341 100644 --- a/noname/get/audio.js +++ b/noname/get/audio.js @@ -1,88 +1,38 @@ -import { lib } from "../library/index.js"; -import { get } from "./index.js"; - -/** - * @typedef { (string | number | boolean)[] | string | number | boolean } AudioInfo - * @typedef { { - * audio: AudioInfo, - * audioname?: string[], - * audioname2?: { [playerName: string]: AudioInfo } - * } } SkillInfo - * @typedef { { - * name: string, - * sex:Sex, - * name1?: string, - * name2?: string, - * tempname: string[] - * skin: { name?:string } - * } } FormatedPlayer - * @typedef { { - * name: string, - * file: string, - * text: string | undefined, - * type: string, - * } } TextMap - */ - +import { lib, get } from "../../noname.js"; export class Audio { - /** - * @type { { [key: string]: TextMap[] } } - */ static #audioCache = {}; - - /** - * 根据skill中的audio,audioname,audioname2和player来获取技能台词列表及其对应的源文件名 - * @param { object } options - * @param { string } options.skill 技能名 - * @param { Player | string } [options.player] 角色/角色名 - * @param { AudioInfo | SkillInfo } [options.info] 使用指定的skillInfo/audioInfo - * @returns { Audio } - */ - static skill({ skill, player, info }) { - if (skill == void 0) throw new ReferenceError(`skill is not defined`); - + static skill({ skill, player, info, args }) { + if (skill == void 0) + throw new ReferenceError(`skill is not defined`); const formatedPlayer = player != void 0 ? this.formatPlayer(player) : void 0; let formatedInfo; - if (info != void 0 && (typeof info !== "object" || Array.isArray(info))) formatedInfo = { audio: info }; - else formatedInfo = info; - return new Audio(new SkillAudio(skill, formatedPlayer, formatedInfo)); + if (info != void 0 && (typeof info !== "object" || Array.isArray(info))) + formatedInfo = { audio: info }; + else + formatedInfo = info; + return new Audio(new SkillAudio(skill, formatedPlayer, formatedInfo), args); } - - /** - * 获取角色死亡时能播放的所有阵亡台词列表及其对应的源文件名 - * @param { object } options - * @param { Player | string } options.player 角色/角色名 - * @param { AudioInfo } [options.info] 使用指定的audioInfo - * @returns { Audio } - */ - static die({ player, info }) { - if (player == void 0) throw new ReferenceError(`player is not defined`); - + static die({ player, info, args }) { + if (player == void 0) + throw new ReferenceError(`player is not defined`); let formatedInfo; - if (info != void 0 && (typeof info !== "object" || Array.isArray(info))) formatedInfo = { dieAudios: info }; - - return new Audio(new DieAudio(this.formatPlayer(player), formatedInfo)); + if (info != void 0 && (typeof info !== "object" || Array.isArray(info))) + formatedInfo = { dieAudios: info }; + else + formatedInfo = info; + return new Audio(new DieAudio(this.formatPlayer(player), formatedInfo), args); } - - /** - * @param { Player | string } player - * @returns { FormatedPlayer } - */ static formatPlayer(player) { - /** - * @type { FormatedPlayer } - */ const formatedPlayer = { name: "", sex: "male", tempname: [], skin: {} }; if (typeof player === "string") { formatedPlayer.name = player; const sex = get.character(player).sex; - if (sex) formatedPlayer.sex = sex; + if (sex) + formatedPlayer.sex = sex; } - //@ts-ignore else if (typeof player === "object" && player !== null) { ({ name: formatedPlayer.name, - //@ts-ignore sex: formatedPlayer.sex, name1: formatedPlayer.name1, name2: formatedPlayer.name2, @@ -90,56 +40,24 @@ export class Audio { skin: formatedPlayer.skin = {}, } = player); } - - return formatedPlayer; } - - /** - * @param {TextMap[]} list - * @returns {string[]} - */ static toFile(list) { return list.map(data => data.file); } - - /** - * @param {TextMap[]} list - * @returns {string[]} - */ static toText(list) { return list.map(data => data.text).filter(text => text != void 0); } - - - - /** - * @type {AudioBase} - */ #Audio; - get name() { return this.#Audio.name; } - get type() { return this.#Audio.type; } - /** - * @type { string[] } - */ #history = []; - /** - * @type { AudioInfo } - */ #audioInfo; - /** - * @type { TextMap[] } - */ #audioList; - /** - * @type { TextMap[] } - */ get audioList() { this.initAudioList(); return JSON.parse(JSON.stringify(this.#audioList)); @@ -151,167 +69,106 @@ export class Audio { return Audio.toText(this.audioList); } initAudioList() { - if (this.#audioList) return; + if (this.#audioList) + return; if (!this.#Audio.useCache) { this.#audioList = this.parseAudio(this.name, this.#audioInfo); return; } const key = this.#Audio.getCacheKey(); const result = Audio.#audioCache[key]; - if (result != void 0) this.#audioList = JSON.parse(JSON.stringify(result)); + if (result != void 0) + this.#audioList = JSON.parse(JSON.stringify(result)); else { const result = this.parseAudio(this.name, this.#audioInfo); Audio.#audioCache[key] = result; this.#audioList = JSON.parse(JSON.stringify(result)); } } - /** - * @param {AudioBase} audio - * @param {string[]} history - */ - constructor(audio, history = []) { + constructor(audio, args, history = []) { this.#history = history.slice(); this.#Audio = audio; - const isExist = this.checkHistory(); - if (isExist) this.#history.unshift(this.#Audio.name); - this.#audioInfo = isExist ? this.#Audio.getAudioInfo() : this.#Audio.defaultInfo; + const useDefaultInfo = !this.checkHistory(); + this.#audioInfo = this.#Audio.getAudioInfo(useDefaultInfo, args); } - getAudio(name, info) { - const audio = this.#Audio.getAudio(name, info); - return new Audio(audio, this.#history).audioList; + getReferenceAudio(name, info) { + const audio = this.#Audio.getReferenceAudio(name, info); + return new Audio(audio, void 0, this.#history).audioList; } checkHistory() { - if (!this.#Audio.useCache) return false; - if (!this.#history.includes(this.#Audio.name)) return true; - if (this.#history[0] === this.#Audio.name) return false; - //deadlock + if (!this.#Audio.useCache) + return true; + if (!this.#history.includes(this.#Audio.name)) { + this.#history.unshift(this.#Audio.name); + return true; + } + if (this.#history[0] === this.#Audio.name) + return false; throw new RangeError(`${this.#Audio.name} in ${this.#history} forms a infinite recursion`); } - /** - * @param {string} name - * @param {AudioInfo} audioInfo - * @returns {TextMap[]} - */ parseAudio(name, audioInfo) { if (Array.isArray(audioInfo)) { - if (this.type === "skill") {//skill的屎山(不应该耦合但是没办法,悲) - if (audioInfo.length === 2 && typeof audioInfo[0] === "string" && typeof audioInfo[1] === "number") { + if (this.type === "skill") { + if (audioInfo.length === 2 && + typeof audioInfo[0] === "string" && + typeof audioInfo[1] === "number") { const [newName, number] = audioInfo; - if (this.#Audio.isExist(newName)) return this.getAudio(newName).slice(0, number); - return this.getAudio(newName, number); + if (this.#Audio.isExist(newName)) + return this.getReferenceAudio(newName).slice(0, number); + return this.getReferenceAudio(newName, number); } } const map = {}; - audioInfo.forEach(info => { - this.parseAudio(name, info).forEach(i => (map[i.name] = i)); + audioInfo.forEach((info) => { + this.parseAudio(name, info).forEach((i) => (map[i.name] = i)); }); return Object.values(map); } - - if (audioInfo === null) return []; - + if (audioInfo === null) + return []; let audioInfoString = String(audioInfo); - - if (audioInfoString === "false") return []; - - if (["data:", "blob:"].some(prefix => audioInfoString.startsWith(prefix))) { + if (audioInfoString === "false") + return []; + if (["data:", "blob:"].some((prefix) => audioInfoString.startsWith(prefix))) { return [this.#Audio.textMap("", "", audioInfoString)]; } - - const list = audioInfoString.match(/(?:(.*):|^)(true|\d+)(?::(.*)|$)/); // [path, number|true, ext] + const list = audioInfoString.match(/(?:(.*):|^)(true|\d+)(?::(.*)|$)/); if (list) { let [, path, audioNum, ext] = list; - if (path == void 0) path = this.#Audio.defaultPath; - else path = path + "/"; - if (ext == void 0) ext = ".mp3"; - else ext = "." + ext; - - if (audioNum === "true") return [this.#Audio.textMapWithIndex(path, ext)]; + if (path == void 0) + path = this.#Audio.defaultPath; + else + path = path + "/"; + if (ext == void 0) + ext = ".mp3"; + else + ext = "." + ext; + if (audioNum === "true") + return [this.#Audio.textMapWithIndex(path, ext)]; const audioList = []; for (let i = 1; i <= parseInt(audioNum); i++) { audioList.push(this.#Audio.textMapWithIndex(path, ext, i)); } return audioList; } - let path = this.#Audio.defaultPath; const pathIndex = audioInfoString.lastIndexOf("/"); if (pathIndex !== -1) { path = audioInfoString.slice(0, pathIndex + 1); audioInfoString = audioInfoString.slice(pathIndex + 1); } - let ext = ".mp3"; const extIndex = audioInfoString.lastIndexOf("."); if (extIndex !== -1) { ext = audioInfoString.slice(extIndex); audioInfoString = audioInfoString.slice(0, extIndex); } - - if (pathIndex === -1 && extIndex === -1) return this.getAudio(audioInfoString); + if (pathIndex === -1 && extIndex === -1) { + return this.getReferenceAudio(audioInfoString); + } return [this.#Audio.textMap(path, ext, audioInfoString)]; } - - } - - -/** - * @interface - */ -class AudioBase { - /** - * @type { string } - */ - type; - /** - * @type { string } - */ - name; - /** - * @type { (name: string) => boolean } - */ - isExist; - /** - * @type { string } - */ - defaultPath; - /** - * @type { AudioInfo } - */ - defaultInfo; - - /** - * @type { boolean } - */ - useCache; - - /** - * @type { () => string } - */ - getCacheKey; - /** - * @type { () => AudioInfo } - */ - getAudioInfo; - /** - * @type { (name: string, info?: AudioInfo) => AudioBase } - */ - getAudio; - /** - * @type { ( path: string, ext: string, name: string ) => TextMap } - */ - textMap; - /** - * @type { ( path: string, ext: string, index?: number ) => TextMap } - */ - textMapWithIndex; -} - - -/** - * @implements {AudioBase} - */ class SkillAudio { type = "skill"; defaultPath = "skill/"; @@ -319,29 +176,17 @@ class SkillAudio { isExist(name) { return !!get.info(name); } - name; info; - /** - * @type { FormatedPlayer } - */ player; - /** - * @type { string[] } - */ audioname = []; - /** - * @type { string } - */ filteredAudioName; - /** - * @type { AudioInfo } - */ filteredAudioName2; - + filteredLogAudio2; useCache = true; getCacheKey() { - if (!this.useCache) throw new ReferenceError("Cannot get cache key when not using cache."); + if (!this.useCache) + throw new ReferenceError("Cannot get cache key when not using cache."); const result = { type: this.type, name: this.name, @@ -350,76 +195,100 @@ class SkillAudio { }; return JSON.stringify(result); } - constructor(name, player, info, audioname) { this.name = name; - if (info != void 0) { this.info = info; this.useCache = false; } - else if (this.isExist(this.name)) this.info = get.info(this.name); + else if (this.isExist(this.name)) + this.info = get.info(this.name); else { console.error(new ReferenceError(`Cannot find ${this.name} when parsing ${this.type} audio.`)); this.info = {}; } - this.player = player; - - if (!audioname) this.audioname = []; - else this.audioname = audioname.slice(); - if (Array.isArray(this.info.audioname)) this.audioname.addArray(this.info.audioname); - this.filteredAudioName = this.getName(i => this.audioname.includes(i)); - - if (this.info.audioname2) { - const key = this.getName(name => this.info.audioname2 && this.info.audioname2[name]); + if (!audioname) + this.audioname = []; + else + this.audioname = audioname.slice(); + if (Array.isArray(this.info.audioname)) + this.audioname.addArray(this.info.audioname); + this.filteredAudioName = this.getName((i) => this.audioname.includes(i)); + if (this.info.logAudio2) { + const key = this.getName((name) => !!this.info.logAudio2?.[name]); + const logAudio2 = this.info.logAudio2[key]; + if (logAudio2 != void 0) { + this.filteredLogAudio2 = logAudio2; + this.useCache = false; + } + } + else if (this.info.audioname2) { + const key = this.getName((name) => !!this.info.audioname2?.[name]); const audioname2 = this.info.audioname2[key]; - if (audioname2 != void 0) this.filteredAudioName2 = audioname2; + if (audioname2 != void 0) + this.filteredAudioName2 = audioname2; } + else if (this.info.logAudio) + this.useCache = false; } - - getAudioInfo() { - if (this.filteredAudioName2 != void 0) return this.filteredAudioName2; - const audioInfo = this.info.audio; - if (audioInfo != void 0) return audioInfo; + getAudioInfo(useDefaultInfo, args) { + if (useDefaultInfo) + return this.defaultInfo; + if (this.filteredLogAudio2 && args) + return this.filteredLogAudio2(...args); + else if (this.filteredAudioName2 != void 0) + return this.filteredAudioName2; + else if (this.info.logAudio && args) + return this.info.logAudio(...args); + else if (this.info.audio != void 0) + return this.info.audio; return this.defaultInfo; } - getAudio(name, info) { + getReferenceAudio(name, info) { return new SkillAudio(name, this.player, info != void 0 ? { audio: info } : void 0, this.audioname); } getName(filter) { - if (!this.player) return ""; - const tempname = this.player.tempname.find(i => filter(i)); - if (tempname) return tempname; - for (const name of [this.player.name, this.player.name1, this.player.name2]) { - if (!name) continue; - if (filter(name)) return name; - const tempname = get.character(name).tempname.find(i => filter(i)); - if (tempname) return tempname; + if (!this.player) + return ""; + const tempname = this.player.tempname.find((i) => filter(i)); + if (tempname) + return tempname; + for (const name of [ + this.player.name, + this.player.name1, + this.player.name2, + ]) { + if (!name) + continue; + if (filter(name)) + return name; + const tempname = get.character(name).tempname.find((i) => filter(i)); + if (tempname) + return tempname; } return ""; } textMap(path, ext, name) { - const translatedPath = path.startsWith(this.defaultPath) ? path.slice(this.defaultPath.length) : path; + const translatedPath = path.startsWith(this.defaultPath) + ? path.slice(this.defaultPath.length) + : path; return { name: translatedPath + name, file: path + name + ext, text: lib.translate[`#${translatedPath}${name}`], type: "skill", - } + }; } textMapWithIndex(path, ext, index) { let name = this.name; - if (this.filteredAudioName) name += "_" + this.filteredAudioName; - if (typeof index === "number") name += index; + if (this.filteredAudioName) + name += "_" + this.filteredAudioName; + if (typeof index === "number") + name += index; return this.textMap(path, ext, name); } } - - -/** - * @implements {AudioBase} - */ class DieAudio { type = "die"; defaultPath = "die/"; @@ -427,17 +296,13 @@ class DieAudio { isExist(name) { return !get.character(name).isNull; } - - /** - * @type {FormatedPlayer} - */ player; name; info; - useCache = true; getCacheKey() { - if (!this.useCache) throw new ReferenceError("Cannot get cache key when not using cache."); + if (!this.useCache) + throw new ReferenceError("Cannot get cache key when not using cache."); const result = { type: this.type, name: this.name, @@ -445,10 +310,8 @@ class DieAudio { }; return JSON.stringify(result); } - constructor(player, info) { this.player = player; - if (info != void 0) { this.useCache = false; this.name = player.name; @@ -457,18 +320,23 @@ class DieAudio { else { const useDefaultInfo = () => { this.name = player.name; - if (this.isExist(this.name)) this.info = get.character(this.name); + if (this.isExist(this.name)) + this.info = get.character(this.name); else { console.error(new ReferenceError(`Cannot find ${this.name} when parsing ${this.type} audio.`)); this.info = {}; } - } + }; + const rawName = player.name; const skinName = player.skin.name; - if (!skinName || skinName === player.name) useDefaultInfo(); - else if (!lib.characterSubstitute[skinName]) useDefaultInfo(); + if (!skinName || skinName === rawName) + useDefaultInfo(); + else if (!lib.characterSubstitute[rawName]) + useDefaultInfo(); else { - const skin = lib.characterSubstitute[skinName].find(i => i[0] === skinName); - if (!skin) useDefaultInfo(); + const skin = lib.characterSubstitute[rawName].find((i) => i[0] === skinName); + if (!skin) + useDefaultInfo(); else { this.name = skinName; this.info = get.convertedCharacter(["", "", 0, [], skin[1]]); @@ -476,28 +344,34 @@ class DieAudio { } } } - - getAudioInfo() { + getAudioInfo(useDefaultInfo, args) { + if (useDefaultInfo) + return this.defaultInfo; const audioInfo = this.info.dieAudios; - if (audioInfo == void 0) return this.defaultInfo; - if (Array.isArray(audioInfo) && audioInfo.length === 0) return this.defaultInfo; + if (audioInfo == void 0) + return this.defaultInfo; + if (Array.isArray(audioInfo) && audioInfo.length === 0) + return this.defaultInfo; return audioInfo; } - getAudio(name, info) { + getReferenceAudio(name, info) { return new DieAudio(Audio.formatPlayer(name), info != void 0 ? { dieAudios: info } : void 0); } textMap(path, ext, name) { - const translatedPath = path.startsWith(this.defaultPath) ? path.slice(this.defaultPath.length) : path; + const translatedPath = path.startsWith(this.defaultPath) + ? path.slice(this.defaultPath.length) + : path; return { name: translatedPath + name, file: path + name + ext, text: lib.translate[`#${translatedPath}${name}:die`], type: "die", - } + }; } textMapWithIndex(path, ext, index) { let name = this.name; - if (typeof index === "number") name += index; + if (typeof index === "number") + name += index; return this.textMap(path, ext, name); } } diff --git a/noname/get/audio.ts b/noname/get/audio.ts new file mode 100644 index 0000000000..5c78324585 --- /dev/null +++ b/noname/get/audio.ts @@ -0,0 +1,459 @@ +import { lib, get } from "../../noname.js"; + +type logAudio = (...args: any[]) => AudioInfo; +type AudioInfo = AudioInfo[] | string | number | boolean; +type SkillInfo = { + audio?: AudioInfo; + audioname?: string[]; + audioname2?: { [playerName: string]: AudioInfo }; + logAudio?: logAudio; + logAudio2?: { [playerName: string]: logAudio }; +}; +type FormatedPlayer = { + name: string; + sex: Sex; + name1?: string; + name2?: string; + tempname: string[]; + skin: { name?: string }; +}; +type TextMap = { + name: string; + file: string; + text: string | undefined; + type: string; +}; + +export class Audio { + static #audioCache: SMap = {}; + + /** + * 根据skill中的audio,audioname,audioname2和player来获取技能台词列表及其对应的源文件名 + * @param skill 技能名 + * @param player 角色/角色名 + * @param info 使用指定的skillInfo/audioInfo + * @param args + */ + static skill({ skill, player, info, args }: { + skill: string; + player: Player | string; + info?: AudioInfo | SkillInfo; + args?: any[]; + }): Audio { + if (skill == void 0) throw new ReferenceError(`skill is not defined`); + + const formatedPlayer = player != void 0 ? this.formatPlayer(player) : void 0; + + let formatedInfo: SkillInfo | undefined; + if (info != void 0 && (typeof info !== "object" || Array.isArray(info))) + formatedInfo = { audio: info }; + else formatedInfo = info; + + return new Audio(new SkillAudio(skill, formatedPlayer, formatedInfo), args); + } + + /** + * 获取角色死亡时能播放的所有阵亡台词列表及其对应的源文件名 + * @param player 角色/角色名 + * @param info 使用指定的audioInfo + * @param args + */ + static die({ player, info, args }: { + player: Player | string; + info?: AudioInfo; + args?: any[]; + }): Audio { + if (player == void 0) throw new ReferenceError(`player is not defined`); + + let formatedInfo; + if (info != void 0 && (typeof info !== "object" || Array.isArray(info))) + formatedInfo = { dieAudios: info }; + else formatedInfo = info; + + return new Audio(new DieAudio(this.formatPlayer(player), formatedInfo), args); + } + + static formatPlayer(player: Player | string): FormatedPlayer { + const formatedPlayer: FormatedPlayer = { name: "", sex: "male", tempname: [], skin: {} }; + if (typeof player === "string") { + formatedPlayer.name = player; + const sex = get.character(player).sex; + if (sex) formatedPlayer.sex = sex; + } + //@ts-ignore + else if (typeof player === "object" && player !== null) { + ({ + name: formatedPlayer.name, + //@ts-ignore + sex: formatedPlayer.sex, + name1: formatedPlayer.name1, + name2: formatedPlayer.name2, + tempname: formatedPlayer.tempname = [], + skin: formatedPlayer.skin = {}, + } = player); + } + + return formatedPlayer; + } + + static toFile(list: TextMap[]): string[] { + return list.map(data => data.file); + } + + static toText(list: TextMap[]): string[] { + return list.map(data => data.text).filter(text => text != void 0); + } + + #Audio: AudioBase; + + get name() { + return this.#Audio.name; + } + get type() { + return this.#Audio.type; + } + + #history: string[] = []; + + #audioInfo: AudioInfo; + #audioList: TextMap[]; + get audioList(): TextMap[] { + this.initAudioList(); + return JSON.parse(JSON.stringify(this.#audioList)); + } + get fileList(): string[] { + return Audio.toFile(this.audioList); + } + get textList(): string[] { + return Audio.toText(this.audioList); + } + initAudioList() { + if (this.#audioList) return; + if (!this.#Audio.useCache) { + this.#audioList = this.parseAudio(this.name, this.#audioInfo); + return; + } + const key = this.#Audio.getCacheKey(); + const result = Audio.#audioCache[key]; + if (result != void 0) this.#audioList = JSON.parse(JSON.stringify(result)); + else { + const result = this.parseAudio(this.name, this.#audioInfo); + Audio.#audioCache[key] = result; + this.#audioList = JSON.parse(JSON.stringify(result)); + } + } + + constructor(audio: AudioBase, args?: any[], history: string[] = []) { + this.#history = history.slice(); + this.#Audio = audio; + const useDefaultInfo = !this.checkHistory(); + this.#audioInfo = this.#Audio.getAudioInfo(useDefaultInfo, args); + } + getReferenceAudio(name: string, info?: any): TextMap[] { + const audio = this.#Audio.getReferenceAudio(name, info); + return new Audio(audio, void 0, this.#history).audioList; + } + checkHistory(): boolean { + if (!this.#Audio.useCache) return true; + if (!this.#history.includes(this.#Audio.name)){ + this.#history.unshift(this.#Audio.name); + return true; + } + if (this.#history[0] === this.#Audio.name) return false; + //deadlock + throw new RangeError( + `${this.#Audio.name} in ${this.#history} forms a infinite recursion` + ); + } + parseAudio(name: string, audioInfo: AudioInfo): TextMap[] { + if (Array.isArray(audioInfo)) { + //skill的屎山(不应该耦合但是没办法,悲) + if (this.type === "skill") { + if ( + audioInfo.length === 2 && + typeof audioInfo[0] === "string" && + typeof audioInfo[1] === "number" + ) { + const [newName, number] = audioInfo; + if (this.#Audio.isExist(newName)) + return this.getReferenceAudio(newName).slice(0, number); + return this.getReferenceAudio(newName, number); + } + } + + const map: { [name: string]: TextMap } = {}; + audioInfo.forEach((info) => { + this.parseAudio(name, info).forEach((i) => (map[i.name] = i)); + }); + return Object.values(map); + } + + if (audioInfo === null) return []; + + let audioInfoString = String(audioInfo); + + if (audioInfoString === "false") return []; + + if (["data:", "blob:"].some((prefix) => audioInfoString.startsWith(prefix))) { + return [this.#Audio.textMap("", "", audioInfoString)]; + } + + const list = audioInfoString.match(/(?:(.*):|^)(true|\d+)(?::(.*)|$)/); // [path, number|true, ext] + if (list) { + let [, path, audioNum, ext] = list; + if (path == void 0) path = this.#Audio.defaultPath; + else path = path + "/"; + if (ext == void 0) ext = ".mp3"; + else ext = "." + ext; + + if (audioNum === "true") return [this.#Audio.textMapWithIndex(path, ext)]; + const audioList: TextMap[] = []; + for (let i = 1; i <= parseInt(audioNum); i++) { + audioList.push(this.#Audio.textMapWithIndex(path, ext, i)); + } + return audioList; + } + + let path = this.#Audio.defaultPath; + const pathIndex = audioInfoString.lastIndexOf("/"); + if (pathIndex !== -1) { + path = audioInfoString.slice(0, pathIndex + 1); + audioInfoString = audioInfoString.slice(pathIndex + 1); + } + + let ext = ".mp3"; + const extIndex = audioInfoString.lastIndexOf("."); + if (extIndex !== -1) { + ext = audioInfoString.slice(extIndex); + audioInfoString = audioInfoString.slice(0, extIndex); + } + + if (pathIndex === -1 && extIndex === -1) { + return this.getReferenceAudio(audioInfoString); + } + return [this.#Audio.textMap(path, ext, audioInfoString)]; + } +} + +interface AudioBase { + type: string; + name: string; + isExist: (name: string) => boolean; + defaultPath: string; + defaultInfo: AudioInfo; + useCache: boolean; + getCacheKey: () => string; + getAudioInfo: (useDefaultInfo: boolean, args?: any[]) => AudioInfo; + getReferenceAudio: (name: string, info?: AudioInfo) => AudioBase; + textMap: (path: string, ext: string, name: string) => TextMap; + textMapWithIndex: (path: string, ext: string, index?: number) => TextMap; +} + +class SkillAudio implements AudioBase { + type = "skill"; + defaultPath = "skill/"; + defaultInfo: AudioInfo = [true, 2]; + isExist(name: string): boolean { + return !!get.info(name); + } + + name: string; + info: SkillInfo; + player?: FormatedPlayer; + audioname: string[] = []; + filteredAudioName: string; + filteredAudioName2: AudioInfo; + filteredLogAudio2: logAudio; + + useCache = true; + getCacheKey(): string { + if (!this.useCache) + throw new ReferenceError("Cannot get cache key when not using cache."); + const result = { + type: this.type, + name: this.name, + filteredAudioName: this.filteredAudioName || void 0, + player: this.filteredAudioName2 != void 0 ? this.player : void 0 + }; + return JSON.stringify(result); + } + + constructor(name: string, player?: FormatedPlayer, info?: SkillInfo, audioname?: string[]) { + this.name = name; + + if (info != void 0) { + this.info = info; + this.useCache = false; + } + else if (this.isExist(this.name)) this.info = get.info(this.name); + else { + console.error(new ReferenceError( `Cannot find ${this.name} when parsing ${this.type} audio.`)); + this.info = {}; + } + + this.player = player; + + if (!audioname) this.audioname = []; + else this.audioname = audioname.slice(); + if (Array.isArray(this.info.audioname)) + this.audioname.addArray(this.info.audioname); + this.filteredAudioName = this.getName((i) => this.audioname.includes(i)); + + if (this.info.logAudio2) { + const key = this.getName((name) => !!this.info.logAudio2?.[name]); + const logAudio2 = this.info.logAudio2[key]; + if (logAudio2 != void 0) { + this.filteredLogAudio2 = logAudio2; + this.useCache = false; + } + } + else if (this.info.audioname2) { + const key = this.getName((name) => !!this.info.audioname2?.[name]); + const audioname2 = this.info.audioname2[key]; + if (audioname2 != void 0) this.filteredAudioName2 = audioname2; + } + else if (this.info.logAudio) this.useCache = false; + } + + getAudioInfo(useDefaultInfo: boolean, args?: any[]): AudioInfo { + if (useDefaultInfo) return this.defaultInfo; + if (this.filteredLogAudio2 && args) return this.filteredLogAudio2(...args); + else if (this.filteredAudioName2 != void 0) return this.filteredAudioName2; + else if (this.info.logAudio && args) return this.info.logAudio(...args); + else if (this.info.audio != void 0) return this.info.audio; + return this.defaultInfo; + } + getReferenceAudio(name: string, info?: AudioInfo): SkillAudio { + return new SkillAudio( + name, + this.player, + info != void 0 ? { audio: info } : void 0, + this.audioname + ); + } + getName(filter: (name: string) => boolean): string { + if (!this.player) return ""; + const tempname = this.player.tempname.find((i) => filter(i)); + if (tempname) return tempname; + for (const name of [ + this.player.name, + this.player.name1, + this.player.name2, + ]) { + if (!name) continue; + if (filter(name)) return name; + const tempname = get.character(name).tempname.find((i) => filter(i)); + if (tempname) return tempname; + } + return ""; + } + textMap(path: string, ext: string, name: string): TextMap { + const translatedPath = path.startsWith(this.defaultPath) + ? path.slice(this.defaultPath.length) + : path; + return { + name: translatedPath + name, + file: path + name + ext, + text: lib.translate[`#${translatedPath}${name}`], + type: "skill", + }; + } + textMapWithIndex(path: string, ext: string, index?: number): TextMap { + let name = this.name; + if (this.filteredAudioName) name += "_" + this.filteredAudioName; + if (typeof index === "number") name += index; + return this.textMap(path, ext, name); + } +} + +class DieAudio implements AudioBase { + type = "die"; + defaultPath = "die/"; + defaultInfo: AudioInfo = true; + isExist(name: string): boolean { + return !get.character(name).isNull; + } + + player: FormatedPlayer; + name: string; + info: any; + + useCache = true; + getCacheKey(): string { + if (!this.useCache) + throw new ReferenceError("Cannot get cache key when not using cache."); + const result = { + type: this.type, + name: this.name, + skin: this.name !== this.player.name ? this.player.skin : void 0 + }; + return JSON.stringify(result); + } + + constructor(player: FormatedPlayer, info?: any) { + this.player = player; + + if (info != void 0) { + this.useCache = false; + this.name = player.name; + this.info = info; + } else { + const useDefaultInfo = () => { + this.name = player.name; + if (this.isExist(this.name)) this.info = get.character(this.name); + else { + console.error( + new ReferenceError( + `Cannot find ${this.name} when parsing ${this.type} audio.` + ) + ); + this.info = {}; + } + }; + const rawName = player.name; + const skinName = player.skin.name; + if (!skinName || skinName === rawName) useDefaultInfo(); + else if (!lib.characterSubstitute[rawName]) useDefaultInfo(); + else { + const skin = lib.characterSubstitute[rawName].find( + (i) => i[0] === skinName + ); + if (!skin) useDefaultInfo(); + else { + this.name = skinName; + this.info = get.convertedCharacter(["", "", 0, [], skin[1]]); + } + } + } + } + + getAudioInfo(useDefaultInfo: boolean, args?: any[]): AudioInfo { + if (useDefaultInfo) return this.defaultInfo; + const audioInfo = this.info.dieAudios; + if (audioInfo == void 0) return this.defaultInfo; + if (Array.isArray(audioInfo) && audioInfo.length === 0) return this.defaultInfo; + return audioInfo; + } + getReferenceAudio(name: string, info?: AudioInfo): DieAudio { + return new DieAudio( + Audio.formatPlayer(name), + info != void 0 ? { dieAudios: info } : void 0 + ); + } + textMap(path: string, ext: string, name: string): TextMap { + const translatedPath = path.startsWith(this.defaultPath) + ? path.slice(this.defaultPath.length) + : path; + return { + name: translatedPath + name, + file: path + name + ext, + text: lib.translate[`#${translatedPath}${name}:die`], + type: "die", + }; + } + textMapWithIndex(path: string, ext: string, index?: number): TextMap { + let name = this.name; + if (typeof index === "number") name += index; + return this.textMap(path, ext, name); + } +} diff --git a/noname/get/index.js b/noname/get/index.js index 47bde76972..ff6ef40680 100644 --- a/noname/get/index.js +++ b/noname/get/index.js @@ -18,7 +18,18 @@ export class Get extends GetCompatible { is = new Is(); promises = new Promises(); Audio = Audio; - + /** + * 获取装备牌对应的技能 + * @param { Card[]|VCard[] } cards + * @returns { any[] } + */ + skillsFromEquips(cards){ + return cards.reduce((skills, card) => { + const info = get.info(card, false); + if (info.skills) skills.addArray(info.skills); + return skills; + }, []) + } /** * 将一个传统格式的character转化为Character对象格式 * @param { Array|Object|import("../library/element/character").Character } data @@ -193,7 +204,10 @@ export class Get extends GetCompatible { */ subtypes(obj, player) { if (typeof obj == "string") obj = { name: obj }; - if (typeof obj != "object") return; + if (typeof obj != "object" || obj === null) return []; + if (Array.isArray(obj.subtypes)) { + return get.copy(obj.subtypes); + } var name = get.name(obj, player); if (!lib.card[name]) return []; if (lib.card[name].subtypes) { @@ -529,8 +543,9 @@ export class Get extends GetCompatible { } } } - autoViewAs(card, cards) { - return new lib.element.VCard(card, cards); + autoViewAs(card, cards, owner) { + if (arguments.length === 1 && card instanceof lib.element.VCard) return card; //阻止无限嵌套 + return new lib.element.VCard(card, cards, void 0, void 0, owner); } /** * @deprecated @@ -843,110 +858,63 @@ export class Get extends GetCompatible { console.log("time2: " + (toc - tic)); } /** - * @param {any} obj + * 此方法仅用作将技能/卡牌代码转为字符串,返回值无法直接进行反序列化 + * @param { any } obj * @param { number } [level = 0] */ stringify(obj, level = 0) { - level = level || 0; let indent = ""; - let str; - for (let i = 0; i < level; i++) { - indent += " "; - } - if (get.objtype(obj) == "object" || obj instanceof lib.element.GameEventPromise) { - str = "{\n"; - for (let i in obj) { - /** - * @type {string} - */ - let insertDefaultString; - let insertFunctionString = indent + " " + get.stringify(obj[i], level + 1) + ",\n"; - let parseFunction = (/** @type {string} */ i) => { - // let string = obj[i].toString(); - i = i.replaceAll("$", "\\$"); - let execResult; - if (obj[i] instanceof GeneratorFunction) { - // *content(){} - execResult = new RegExp(`\\*\\s*${i}[\\s\\S]*?\\(`).exec(obj[i]); - if (execResult && execResult.index === 0) { - return insertFunctionString; - } - // content:function*(){} - else { - return insertDefaultString; - } - } else if (obj[i] instanceof AsyncFunction) { - execResult = new RegExp(`async\\s*${i}[\\s\\S]*?\\(`).exec(obj[i]); + for (let i = 0; i < level; i++) indent += " "; + try { + if (get.objtype(obj) === "object"/* || obj instanceof lib.element.GameEvent */) { + const isMethod = (/** @type {string} */ key) => { + const value = obj[key]; + if (!(typeof value === "function")) return false; + key = key.replaceAll("$", "\\$"); + let reg; + if (value instanceof GeneratorFunction) { + // content*(){} + reg = new RegExp(`\\*\\s*${key}[\\s\\S]*?\\(`); + } else if (value instanceof AsyncFunction) { // async content(){} - if (execResult && execResult.index === 0) { - return insertFunctionString; - } - // content:async function(){} - else { - return insertDefaultString; - } + reg = new RegExp(`async\\s*${key}[\\s\\S]*?\\(`); } else { - execResult = new RegExp(`${i}[\\s\\S]*?\\(`).exec(obj[i]); // content(){} - if (execResult && execResult.index === 0) { - return insertFunctionString; - } - // content:function(){} - else { - return insertDefaultString; - } + reg = new RegExp(`${key}[\\s\\S]*?\\(`) } + return reg.exec(value)?.index === 0; }; - if (/[^a-zA-Z]/.test(i)) { - insertDefaultString = indent + ' "' + i + '":' + get.stringify(obj[i], level + 1) + ",\n"; - if (typeof obj[i] !== "function") { - str += insertDefaultString; - } else { - str += parseFunction(i); - } - } else { - insertDefaultString = indent + " " + i + ":" + get.stringify(obj[i], level + 1) + ",\n"; - if (typeof obj[i] !== "function") { - str += insertDefaultString; - } else { - str += parseFunction(i); - } - } - } - str += indent + "}"; - return str; - } else { - if (typeof obj == "function") { - str = obj.toString(); - str = str.replace(/\t/g, " "); - let i = str.lastIndexOf("\n"); - let num = 0; - for (let j = i + 1; j < str.length && str[j] == " "; j++) { - num++; + + let str = "{\n"; + for (const key in obj) { + let keyString = (/[^a-zA-Z]/.test(key) ? `"${key}"` : key) + ": "; + const valueString = get.stringify(obj[key], level + 1); + if (isMethod(key)) keyString = ""; + str += indent + " " + keyString + valueString + ",\n"; } - num = Math.floor(num / 4); - for (i = 0; i < num - level; i++) { - str = str.replace(/\n {4}/g, "\n"); + str += indent + "}"; + return str; + + } else if (typeof obj === "function") { + let str = obj.toString().replace(/\t/g, " "); + let lastLine = str.slice(str.lastIndexOf("\n")); + let originIndent = Math.floor((/\S/.exec(lastLine)?.index ?? lastLine.length) / 4); + for (let i = 0; i < Math.abs(originIndent - level); i++) { + if (originIndent >= level) str = str.replace(/\n {4}/g, "\n"); + else str = str.replace(/\n/g, "\n "); } + return str; + } else if (Array.isArray(obj)) { + const rand = parseInt(get.id()); + obj = obj.map(i => i === Infinity ? rand : i === -Infinity ? -rand : i); + return JSON.stringify(obj).replace(new RegExp(rand.toString(), "g"), "Infinity"); } else { - try { - if (Array.isArray(obj) && obj.includes(Infinity)) { - obj = obj.slice(0); - let rand = get.id(); - for (let i = 0; i < obj.length; i++) { - if (obj[i] === Infinity) { - obj[i] = parseInt(rand); - } - } - str = JSON.stringify(obj).replace(new RegExp(rand, "g"), "Infinity"); - } else { - str = JSON.stringify(obj) || ""; - } - } catch (e) { - str = ""; - } + if (obj === Infinity) return "Infinity"; + if (obj === -Infinity) return "-Infinity"; + return JSON.stringify(obj); } - return str; + } catch (e) { + return ""; } } /** @@ -1504,21 +1472,88 @@ export class Get extends GetCompatible { return Array.from(infos || []).map(info => game.playerMap[info]); } cardInfo(card) { - return [card.suit, card.number, card.name, card.nature]; + return [card.suit, card.number, card.name, card.nature, card.cardid]; } cardsInfo(cards = []) { return Array.from(cards).map(get.cardInfo); } infoCard(info) { - var card = ui.create.card(); - if (info[0]) { - card.init(info); + if (!lib.cardOL) lib.cardOL = {}; + let card; + try { + const id = info[4]; + if (!id) { + card = ui.create.card(); + if (info && info[2]) card.init(info); + } else if (lib.cardOL[id]) { + if (lib.cardOL[id].name != info[2]) { + if (info && info[2]) lib.cardOL[id].init(info); + } + card = lib.cardOL[id]; + } else { + card = ui.create.card(); + card.cardid = id; + if (info && info[2]) card.init(info); + lib.cardOL[id] = card; + } + } catch (e) { + console.log(e); } - return card; + return card || info; } infoCards(infos) { return Array.from(infos || []).map(get.infoCard); } + vcardInfo(card) { + return Object.entries(card).reduce((stringifying, entry) => { + const key = entry[0]; + // @ts-ignore + if (key === "cards") stringifying[key] = get.cardsInfo(entry[1]); + else if (entry[1] !== void 0) stringifying[key] = JSON.stringify(entry[1]) + return stringifying; + }, {}) + } + vcardsInfo(cards = []) { + return Array.from(cards).map(get.vcardInfo); + } + infoVCard(card){ + // @ts-ignore + if (!lib.vcardOL) lib.vcardOL = {}; + const datas = Object.entries(card).reduce((vcard, entry) => { + const key = entry[0]; + if (key === "cards") vcard[key] = get.infoCards(entry[1]); + else if (entry[1] !== void 0) vcard[key] = JSON.parse(entry[1]); + return vcard; + }, {}); + // @ts-ignore + const vid = datas.vcardID; + // @ts-ignore + if (!vid || !lib.vcardOL) return new lib.element.VCard(datas); + // @ts-ignore + if (vid in lib.vcardOL) { + // @ts-ignore + const vcard = lib.vcardOL[vid]; + //TODO: 这里暂时偷懒 直接用了delete和直接赋值 不妥 + Object.keys(vcard).forEach(entry => { + delete vcard[entry]; + }); + Object.keys(datas).forEach((key) => { + const value = datas[key]; + if (Array.isArray(value)) vcard[key] = value.slice(); + vcard[key] = value; + }); + return vcard; + } + else { + const card = new lib.element.VCard(datas); + // @ts-ignore + lib.vcardOL[vid] = card; + return card; + } + } + infoVCards(infos) { + return Array.from(infos || []).map(get.infoVCard); + } cardInfoOL(card) { return "_noname_card:" + JSON.stringify([card.cardid, card.suit, card.number, card.name, card.nature]); } @@ -1821,6 +1856,53 @@ export class Get extends GetCompatible { } return evt || item; } + vcardInfoOL(item) { + return "_noname_vcard:" + JSON.stringify(Object.entries(item).reduce((stringifying, entry) => { + const key = entry[0]; + stringifying[key] = get.stringifiedResult(entry[1]); + return stringifying; + }, {})); + } + vcardsInfoOL(cards) { + return Array.from(cards || []).map(get.vcardInfoOL); + } + infoVCardOL(item) { + // @ts-ignore + const rawCard = JSON.parse(item.slice(14)); + const datas = Object.entries(rawCard).reduce((vcard, entry) => { + const key = entry[0]; + vcard[key] = get.parsedResult(entry[1]); + return vcard; + }, {}); + + const vid = datas.vcardID; + // @ts-ignore + if (!vid || !lib.vcardOL) return new lib.element.VCard(datas); + // @ts-ignore + if (vid in lib.vcardOL) { + // @ts-ignore + const vcard = lib.vcardOL[vid]; + //TODO: 这里暂时偷懒 直接用了delete和直接赋值 不妥 + Object.keys(vcard).forEach(entry => { + delete vcard[entry]; + }); + Object.keys(datas).forEach((key) => { + const value = datas[key]; + if (Array.isArray(value)) vcard[key] = value.slice(); + vcard[key] = value; + }); + return vcard; + } + else { + const card = new lib.element.VCard(datas); + // @ts-ignore + lib.vcardOL[vid] = card; + return card; + } + } + infoVCardsOL(infos) { + return Array.from(infos || []).map(get.infoVCardOL); + } stringifiedResult(item, level, nomore) { if (!item) return item; if (typeof item == "function") { @@ -1831,6 +1913,10 @@ export class Get extends GetCompatible { return get.cardInfoOL(item); case "cards": return get.cardsInfoOL(item); + case "vcard": + return get.vcardInfoOL(item); + case "vcards": + return get.vcardsInfoOL(item); case "player": return get.playerInfoOL(item); case "players": @@ -1877,6 +1963,8 @@ export class Get extends GetCompatible { return get.infoFuncOL(item); } else if (item.startsWith("_noname_card:")) { return get.infoCardOL(item); + } else if (item.startsWith("_noname_vcard:")) { + return get.infoVCardOL(item); } else if (item.startsWith("_noname_player:")) { return get.infoPlayerOL(item); } else if (item.startsWith("_noname_event:")) { @@ -1995,7 +2083,8 @@ export class Get extends GetCompatible { } /** * @overload - * @returns { void } + * @param { any } obj + * @returns { 'position' | 'natures' | 'nature' | 'players' | 'cards' | 'select' | 'divposition' | 'button' | 'card' | 'vcard' | 'player' | 'dialog' | 'event' | void } * * @overload * @param { string } obj @@ -2024,6 +2113,10 @@ export class Get extends GetCompatible { * @overload * @param { Card } obj * @returns { 'card' } + * + * @overload + * @param { VCard } obj + * @returns { 'vcard' } * * @overload * @param { Player } obj @@ -2055,6 +2148,7 @@ export class Get extends GetCompatible { if (Array.isArray(obj) && obj.length > 0) { if (obj.every(p => p instanceof lib.element.Player)) return "players"; if (obj.every(p => p instanceof lib.element.Card)) return "cards"; + if (obj.every(p => p instanceof lib.element.VCard)) return "vcards"; if (obj.length == 2) { if (typeof obj[0] == "number" && typeof obj[1] == "number") { if (obj[0] <= obj[1] || obj[1] <= -1) return "select"; @@ -2068,6 +2162,7 @@ export class Get extends GetCompatible { } if (obj instanceof lib.element.Button || (obj instanceof HTMLDivElement && obj.classList.contains("button"))) return "button"; if (obj instanceof lib.element.Card) return "card"; + if (obj instanceof lib.element.VCard) return "vcard"; if (obj instanceof lib.element.Player) return "player"; if (obj instanceof lib.element.Dialog) return "dialog"; if (obj instanceof lib.element.GameEvent || obj instanceof lib.element.GameEventPromise) return "event"; @@ -2077,8 +2172,9 @@ export class Get extends GetCompatible { if (lib.experimental.symbol.itemType in obj) return obj[lib.experimental.symbol.itemType]; } equipNum(card) { - if (get.type(card) == "equip") { - return parseInt(get.subtype(card)[5]); + const subtypes = get.subtypes(card) + if (subtypes.length) { + return parseInt(subtypes[0].slice(5)); } return 0; } @@ -2129,15 +2225,9 @@ export class Get extends GetCompatible { /** * 返回牌的类型 * @overload - * @param { string } obj - * @param { 'trick' } [method] - * @param { Player } [player] - * @returns { string } - * - * @overload - * @param { Card } obj - * @param { 'trick' } [method] - * @param { Player } [player] + * @param { Card | string } obj + * @param { 'trick' | null} [method] + * @param { Player | false } [player] * @returns { string } */ type(obj, method, player) { @@ -2388,11 +2478,15 @@ export class Get extends GetCompatible { } n = game.checkMod(from, to, n, "globalFrom", from); n = game.checkMod(from, to, n, "globalTo", to); - const equips1 = from.getCards("e", function (card) { - return !ui.selected.cards || !ui.selected.cards.includes(card); + const equips1 = from.getVCards("e", function (card) { + return !card.cards?.some(card => { + return ui.selected.cards?.includes(card); + }); }), - equips2 = to.getCards("e", function (card) { - return !ui.selected.cards || !ui.selected.cards.includes(card); + equips2 = to.getVCards("e", function (card) { + return !card.cards?.some(card => { + return ui.selected.cards?.includes(card); + }); }); for (let i = 0; i < equips1.length; i++) { let info = get.info(equips1[i]).distance; @@ -2540,6 +2634,7 @@ export class Get extends GetCompatible { position(card, ordering) { //哪个大聪明在返回牌位置的函数写返回玩家位置的功能 if (get.itemtype(card) == "player") return parseInt(card.dataset.position); + if (!card) return null; if (card.timeout && card.destiny && card.destiny.classList) { if (card.destiny.classList.contains("equips")) return "e"; if (card.destiny.classList.contains("judges")) return "j"; @@ -2725,6 +2820,25 @@ export class Get extends GetCompatible { return num.toString(); } } + /** + * 返回扑克牌中的表示形式对应的数字 + * @param { string } str + * @returns { number } + */ + numString(str) { + switch (str) { + case "A": + return 1; + case "J": + return 11; + case "Q": + return 12; + case "K": + return 13; + default: + return parseInt(str); + } + } /** * 将阿拉伯数字转换为中文的表达形式 * @param { number } num @@ -3918,15 +4032,18 @@ export class Get extends GetCompatible { if (node.link && node.link.name && lib.card[node.link.name]) { name = node.link.name; } - if (get.position(node) == "j" && node.viewAs && node.viewAs != name) { + var cardPosition = get.position(node); + if ((cardPosition === "e" || cardPosition === "j") && node.viewAs && node.viewAs != name) { uiintro.add(get.translation(node.viewAs)); - var cardInfo = lib.card[node.viewAs], - showCardIntro = true; + var cardInfo = lib.card[node.viewAs], showCardIntro = true; + var cardOwner = get.owner(node); if (cardInfo.blankCard) { - var cardOwner = get.owner(node); if (cardOwner && !cardOwner.isUnderControl(true)) showCardIntro = false; } - if (showCardIntro) uiintro.add('
        (' + get.translation(get.translation(node)) + ")
        "); + if(cardOwner){ + var sourceVCard = cardOwner.getVCards(cardPosition).find(card => card.cards?.includes(node)); + if (showCardIntro && sourceVCard) uiintro.add('
        (' + get.translation(get.translation(sourceVCard.cards)) + ")
        "); + } // uiintro.add(get.translation(node.viewAs)+'
        ('+get.translation(node)+')
        '); uiintro.nosub = true; name = node.viewAs; @@ -4021,8 +4138,9 @@ export class Get extends GetCompatible { } else if (lib.card[name] && lib.card[name].type && lib.translate[lib.card[name].type]) { typeinfo += get.translation(lib.card[name].type) + "牌"; } - if (get.subtype(name, false)) { - typeinfo += "-" + get.translation(get.subtype(name, false)); + let vcard = get.owner(node)?.getVCards(get.position(node))?.find(card => card.cards?.includes(node)); + if (get.subtypes(vcard || node, get.owner(node))?.length) { + typeinfo += "-" + get.subtypes(vcard || node, get.owner(node)).map(type => get.translation(type)).join("/"); } if (typeinfo) { uiintro.add('
        ' + typeinfo + "
        "); @@ -4623,15 +4741,20 @@ export class Get extends GetCompatible { return result; } equipResult(player, target, name) { - var card = get.card(); - if (!card || card.name != name) { - card = { name: name }; - } - var value1 = get.equipValue(card, target); - var value2 = 0; - if (!player.canEquip(card)) { - if (!player.canEquip(card, true)) return 0; - var current = target.getEquip(card); + let card = name; + if (typeof name === "string") { + card = { name }; + } + else { + const itemtype = get.itemtype(card); + if (itemtype !== "card" && itemtype !== "vcard") { + card = get.card(); + } + } + let value1 = get.equipValue(card, target), value2 = 0; + if (!target.canEquip(card)) { + if (!target.canEquip(card, true)) return 0; + let current = target.getVEquip(card); if (current && current != card) { value2 = get.equipValue(current, target); if (value2 > 0 && !target.needsToDiscard() && !get.tag(card, "valueswap")) { @@ -4642,9 +4765,9 @@ export class Get extends GetCompatible { return Math.max(0, value1 - value2) / 5; } equipValue(card, player) { - if (player == undefined || get.itemtype(player) != "player") player = get.owner(card); - if (player == undefined || get.itemtype(player) != "player") player = _status.event.player; - var info = get.info(card); + player = player ?? get.owner(card) ?? get.player(); + if (get.itemtype(card) === "card") card = player.getVCards("e").find(vcard => vcard.cards?.includes(card)) ?? card; + var info = get.info(card, false); if (!info.ai) return 0; var value = info.ai.equipValue; if (value == undefined) { @@ -4653,6 +4776,7 @@ export class Get extends GetCompatible { } else return 0; } if (typeof value == "number") return value; + //此处是否需要将实体牌改为虚拟牌呢?暂时不确定 if (typeof value == "function") return value(card, player, null, "raw2"); return 0; } diff --git a/noname/get/is.js b/noname/get/is.js index dfb9e8fe8d..e220fbfebc 100644 --- a/noname/get/is.js +++ b/noname/get/is.js @@ -381,12 +381,7 @@ export class Is { } /** * @overload - * @param { Function } func - * @returns { false } - */ - /** - * @overload - * @param { number | [number, number] } func + * @param { Function | number | [number, number] } func * @returns { boolean } */ singleSelect(func) { @@ -455,6 +450,7 @@ export class Is { } /** * @param { string } str + * @returns { str is "h" | "e" | "j" | "he" | "hej" | "ej" | "hj" } */ pos(str) { return str == "h" || str == "e" || str == "j" || str == "he" || str == "hj" || str == "ej" || str == "hej"; diff --git a/noname/gnc/index.js b/noname/gnc/index.js index 7cbdcebd99..0913c58242 100644 --- a/noname/gnc/index.js +++ b/noname/gnc/index.js @@ -4,8 +4,9 @@ import { Is } from "./is.js"; // gnc: GeNCoroutine export class GNC { /** - * @param {GeneratorFunction} fn - * @returns + * @template {GeneratorFunction} T + * @param {T} fn + * @returns { (...args: Parameters) => Promise> } */ of(fn) { /** diff --git a/noname/init/cordova.js b/noname/init/cordova.js index c900ae8ede..0b99b94cf6 100644 --- a/noname/init/cordova.js +++ b/noname/init/cordova.js @@ -9,20 +9,28 @@ import { checkVersion } from "../library/update.js"; export async function cordovaReady() { if (lib.device == "android") { // 新客户端导入扩展逻辑 - window.addEventListener("importExtension", e => { - const extensionName = e.detail.extensionName; - lib.config.extensions.add(extensionName); - game.saveConfig("extensions", lib.config.extensions); - game.saveConfig(`extension_${extensionName}_enable`, true); - if (confirm(`扩展${extensionName}已导入成功,是否重启游戏?`)) { - game.reload(); - } - }, false); - window.addEventListener("importPackage", () => { - if (confirm(`离线包/完整包已导入成功,是否重启游戏?`)) { - game.reload(); - } - }, false); + window.addEventListener( + "importExtension", + e => { + const extensionName = e.detail.extensionName; + lib.config.extensions.add(extensionName); + game.saveConfig("extensions", lib.config.extensions); + game.saveConfig(`extension_${extensionName}_enable`, true); + if (confirm(`扩展${extensionName}已导入成功,是否重启游戏?`)) { + game.reload(); + } + }, + false + ); + window.addEventListener( + "importPackage", + () => { + if (confirm(`离线包/完整包已导入成功,是否重启游戏?`)) { + game.reload(); + } + }, + false + ); document.addEventListener("pause", function () { if (!_status.paused2 && typeof _status.event.isMine == "function" && !_status.event.isMine()) { ui.click.pause(); @@ -64,33 +72,36 @@ export async function cordovaReady() { if ("cordova" in window && "plugins" in window.cordova && "permissions" in window.cordova.plugins) { const permissions = cordova.plugins.permissions; const requests = ["WRITE_EXTERNAL_STORAGE", "READ_EXTERNAL_STORAGE"]; - if (typeof device == 'object') { + if (typeof device == "object") { // 安卓13或以上 if (checkVersion(device.version, "13") >= 0) { requests.length = 0; - requests.push('READ_MEDIA_IMAGES', 'READ_MEDIA_VIDEO', 'READ_MEDIA_AUDIO'); + requests.push("READ_MEDIA_IMAGES", "READ_MEDIA_VIDEO", "READ_MEDIA_AUDIO"); } } - Promise.all(requests.map(request => { - return new Promise((resolve, reject) => { - permissions.checkPermission(permissions[request], status => { - resolve({ - request: request, - hasPermission: status.hasPermission - }); - }, reject); - }); - })).then(shouldRequestPermissions => { - return shouldRequestPermissions - .filter(({ hasPermission }) => !hasPermission) - .map(({ request }) => permissions[request] || `android.permission.${request}`); - }).then(willRequestPermissions => { - permissions.requestPermissions( - willRequestPermissions, - lib.other.ignore, - lib.other.ignore - ); - }).catch(console.log); + Promise.all( + requests.map(request => { + return new Promise((resolve, reject) => { + permissions.checkPermission( + permissions[request], + status => { + resolve({ + request: request, + hasPermission: status.hasPermission, + }); + }, + reject + ); + }); + }) + ) + .then(shouldRequestPermissions => { + return shouldRequestPermissions.filter(({ hasPermission }) => !hasPermission).map(({ request }) => permissions[request] || `android.permission.${request}`); + }) + .then(willRequestPermissions => { + permissions.requestPermissions(willRequestPermissions, lib.other.ignore, lib.other.ignore); + }) + .catch(console.log); } } game.download = function (url, folder, onsuccess, onerror, dev, onprogress) { @@ -119,6 +130,65 @@ export async function cordovaReady() { onerror ); }; + + /** + * 检查指定的路径是否是一个文件 + * + * @param {string} fileName - 需要查询的路径 + * @param {(result: -1 | 0 | 1) => void} [callback] - 回调函数;接受的参数意义如下: + * - `-1`: 路径不存在或无法访问 + * - `0`: 路径的内容不是文件 + * - `1`: 路径的内容是文件 + * @param {(err: Error) => void} [onerror] - 接收错误的回调函数 + * @return {void} - 由于三端的异步需求和历史原因,文件管理必须为回调异步函数 + */ + game.checkFile = function (fileName, callback, onerror) { + let path = lib.path.join(nonameInitialized, fileName); + + window.resolveLocalFileSystemURL( + path, + entry => { + callback?.(entry.isFile ? 1 : 0); + }, + error => { + if ([FileError.NOT_FOUND_ERR, FileError.NOT_READABLE_ERR].includes(error.code)) { + callback?.(-1); + } else { + onerror?.(new Error(`Code: ${error.code}`)); + } + } + ); + }; + + /** + * 检查指定的路径是否是一个目录 + * + * @param {string} dir - 需要查询的路径 + * @param {(result: -1 | 0 | 1) => void} [callback] - 回调函数;接受的参数意义如下: + * - `-1`: 路径不存在或无法访问 + * - `0`: 路径的内容不是目录 + * - `1`: 路径的内容是目录 + * @param {(err: Error) => void} [onerror] - 接收错误的回调函数 + * @return {void} - 由于三端的异步需求和历史原因,文件管理必须为回调异步函数 + */ + game.checkDir = function (dir, callback, onerror) { + let path = lib.path.join(nonameInitialized, dir); + + window.resolveLocalFileSystemURL( + path, + entry => { + callback?.(entry.isDirectory ? 1 : 0); + }, + error => { + if ([FileError.NOT_FOUND_ERR, FileError.NOT_READABLE_ERR].includes(error.code)) { + callback?.(-1); + } else { + onerror?.(new Error(`Code: ${error.code}`)); + } + } + ); + }; + game.readFile = function (filename, callback, onerror) { window.resolveLocalFileSystemURL( nonameInitialized, @@ -214,11 +284,11 @@ export async function cordovaReady() { folders = []; window.resolveLocalFileSystemURL( nonameInitialized + dir, - (entry) => { + entry => { var dirReader = entry.createReader(); var entries = []; var readEntries = () => { - dirReader.readEntries((results) => { + dirReader.readEntries(results => { if (!results.length) { entries.sort(); for (var i = 0; i < entries.length; i++) { @@ -261,7 +331,7 @@ export async function cordovaReady() { ) .catch( () => - new Promise((resolve) => + new Promise(resolve => entry.getDirectory( str, { @@ -271,15 +341,14 @@ export async function cordovaReady() { ) ) ) - .then((directoryEntry) => access(directoryEntry, directory, createDirectory)); + .then(directoryEntry => access(directoryEntry, directory, createDirectory)); }; return new Promise((resolve, reject) => window.resolveLocalFileSystemURL( nonameInitialized, - (rootEntry) => { + rootEntry => { const createDirectory = () => { - if (directoryList.length) - access(rootEntry, directoryList.pop().split("/").reverse(), createDirectory); + if (directoryList.length) access(rootEntry, directoryList.pop().split("/").reverse(), createDirectory); if (typeof callback == "function") callback(); resolve(); }; @@ -291,11 +360,9 @@ export async function cordovaReady() { }; game.createDir = (directory, successCallback, errorCallback) => { const paths = directory.split("/").reverse(); - new Promise((resolve, reject) => - window.resolveLocalFileSystemURL(nonameInitialized, resolve, reject) - ).then( - (directoryEntry) => { - const redo = (entry) => + new Promise((resolve, reject) => window.resolveLocalFileSystemURL(nonameInitialized, resolve, reject)).then( + directoryEntry => { + const redo = entry => new Promise((resolve, reject) => entry.getDirectory( paths.pop(), @@ -305,13 +372,13 @@ export async function cordovaReady() { resolve, reject ) - ).then((resolvedDirectoryEntry) => { + ).then(resolvedDirectoryEntry => { if (paths.length) return redo(resolvedDirectoryEntry); if (typeof successCallback == "function") successCallback(); }); return redo(directoryEntry); }, - (reason) => { + reason => { if (typeof errorCallback != "function") return Promise.reject(reason); errorCallback(reason); } @@ -320,12 +387,12 @@ export async function cordovaReady() { game.removeDir = (directory, successCallback, errorCallback) => { window.resolveLocalFileSystemURL( `${nonameInitialized}${directory}`, - (directoryEntry) => { + directoryEntry => { directoryEntry.removeRecursively(() => { if (typeof successCallback == "function") successCallback(); }); }, - (e) => { + e => { if (typeof errorCallback == "function") errorCallback(e); else throw e; } diff --git a/noname/init/import.js b/noname/init/import.js index d4dffdd711..595bd87e75 100644 --- a/noname/init/import.js +++ b/noname/init/import.js @@ -1,38 +1,35 @@ +// noinspection ES6PreferShortImport + import { game } from "../game/index.js"; -import { lib } from "../library/index.js"; +import { lib, Library } from "../library/index.js"; /** * @param {string} name - 卡牌包名 * @returns {Promise} */ -export const importCardPack = generateImportFunction("card", (name) => `../../card/${name}.js`); +export const importCardPack = generateImportFunction("card", name => `../../card/${name}.js`); /** * @param {string} name - 武将包名 * @returns {Promise} */ -export const importCharacterPack = generateImportFunction("character", (name) => { +export const importCharacterPack = generateImportFunction("character", name => { const alreadyModernCharacterPack = lib.config.moderned_chracters || []; - return alreadyModernCharacterPack.includes(name) - ? `../../character/${name}/index.js` - : `../../character/${name}.js`; + return alreadyModernCharacterPack.includes(name) ? `../../character/${name}/index.js` : `../../character/${name}.js`; }); /** * @param {string} name - 扩展名 * @returns {Promise} */ -export const importExtension = generateImportFunction( - "extension", - (name) => `../../extension/${name}/extension.js` -); +export const importExtension = generateImportFunction("extension", name => `../../extension/${name}/extension.js`); /** * @param {string} name - 模式名 * @returns {Promise} */ -export const importMode = generateImportFunction("mode", (name) => `../../mode/${name}.js`); +export const importMode = generateImportFunction("mode", name => `../../mode/${name}.js`); /** * 生成导入 @@ -42,12 +39,8 @@ export const importMode = generateImportFunction("mode", (name) => `../../mode/$ * @returns {(name: string) => Promise} */ function generateImportFunction(type, pathParser) { - return async (name) => { - if ( - type == "extension" && - !game.hasExtension(name) && - !lib.config.all.stockextension.includes(name) - ) { + return async name => { + if (type == "extension" && !game.hasExtension(name) && !lib.config.all.stockextension.includes(name)) { // @ts-ignore await game.import(type, await createEmptyExtension(name)); return; @@ -62,7 +55,7 @@ function generateImportFunction(type, pathParser) { let path = pathParser(name); // 通过浏览器自带的script标签导入可直接获取报错信息,且不会影响JS运行 // 此时代码内容也将缓存在浏览器中,故再次import后将不会重新执行代码内容(测试下来如此) - const [status, script] = await new Promise((resolve) => { + const [status, script] = await new Promise(resolve => { const createScript = () => { const script = document.createElement("script"); script.type = "module"; @@ -71,22 +64,23 @@ function generateImportFunction(type, pathParser) { return script; }; let script = createScript(); - script.onerror = (e) => { + script.onerror = e => { if (path.endsWith(".js") && window.isSecureContext) { path = path.slice(0, -3) + ".ts"; script.remove(); let ts = createScript(); - ts.onerror = (e2) => { - if ( - lib.path.basename(path) === "extension.js" && - lib.path.dirname(path).endsWith("/extension") - ) { + ts.onerror = e2 => { + if (lib.path.basename(path) === "extension.js" && lib.path.dirname(path).endsWith("/extension")) { console.error(`扩展《${name}》加载失败`, e, e2); - let remove = confirm( - `扩展《${name}》加载失败,是否移除此扩展?此操作不会移除目录下的文件。` - ); + let remove = confirm(`扩展《${name}》加载失败,是否移除此扩展?此操作不会移除目录下的文件。`); if (remove) { lib.config.extensions.remove(name); + if (lib.config[`@Experimental.extension.${name}.character`]) { + game.saveConfig(`@Experimental.extension.${name}.character`); + } + if (lib.config[`@Experimental.extension.${name}.card`]) { + game.saveConfig(`@Experimental.extension.${name}.card`); + } game.saveConfig("extensions", lib.config.extensions); } } @@ -102,16 +96,13 @@ function generateImportFunction(type, pathParser) { script.remove(); if (status === "error") { if (type === "character") { - console.warn( - "如果您在扩展中使用了game.import创建武将包,可将以下代码删除: lib.config.all.characters.push('武将包名');" - ); + console.warn("如果您在扩展中使用了game.import创建武将包,可将以下代码删除: lib.config.all.characters.push('武将包名');"); } return; } const modeContent = await import(path); if (!modeContent.type) return; - if (modeContent.type !== type) - throw new Error(`Loaded Content doesn't conform to "${type}" but "${modeContent.type}".`); + if (modeContent.type !== type) throw new Error(`Loaded Content doesn't conform to "${type}" but "${modeContent.type}".`); // @ts-ignore await game.import(type, modeContent.default); }; @@ -121,7 +112,7 @@ async function createEmptyExtension(name) { const extensionInfo = await lib.init.promises .json(`${lib.assetURL}extension/${name}/info.json`) //await import(`../../extension/${name}/info.json`,{assert:{type:'json'}}) .then( - (info) => info, + info => info, () => { return { name: name, diff --git a/noname/init/index.js b/noname/init/index.js index cbe7700aae..23fca6a370 100644 --- a/noname/init/index.js +++ b/noname/init/index.js @@ -195,7 +195,7 @@ export async function boot() { //但这种方式只允许修改game的文件读写函数。 if (typeof window.initReadWriteFunction == "function") { const g = {}; - const ReadWriteFunctionName = ["download", "readFile", "readFileAsText", "writeFile", "removeFile", "getFileList", "ensureDirectory", "createDir", "removeDir"]; + const ReadWriteFunctionName = ["download", "checkFile", "checkDir", "readFile", "readFileAsText", "writeFile", "removeFile", "getFileList", "ensureDirectory", "createDir", "removeDir"]; ReadWriteFunctionName.forEach(prop => { Object.defineProperty(g, prop, { configurable: true, @@ -264,6 +264,7 @@ export async function boot() { config.get("all").plays = []; config.get("all").mode = []; + if (!config.get("errstop") || config.get("compatiblemode")) _status.withError = true; if (config.get("debug")) { await lib.init.promises.js(`${lib.assetURL}game`, "asset"); if (window.noname_skin_list) { @@ -1020,12 +1021,6 @@ async function setOnError() { Reflect.set(window, "ec", column); Reflect.set(window, "eo", err); if (promiseErrorHandler.onErrorFinish) promiseErrorHandler.onErrorFinish(); - // @ts-ignore - if (!lib.config.errstop && _status && _status.event) { - if (_status.event.content instanceof AsyncFunction || Array.isArray(_status.event.contents)) return; - _status.withError = true; - game.loop(); - } }; return promiseErrorHandler; diff --git a/noname/init/loading.js b/noname/init/loading.js new file mode 100644 index 0000000000..bd5d050804 --- /dev/null +++ b/noname/init/loading.js @@ -0,0 +1,538 @@ +/** + * 从读取的内容中获取数据 + */ + +import { ai, setAI } from "../ai/index.js"; +import { get, setGet } from "../get/index.js"; +import { lib, Library, setLibrary } from "../library/index.js"; +import { game, setGame } from "../game/index.js"; +import { _status } from "../status/index.js"; +import { setUI, ui } from "../ui/index.js"; +import { gnc } from "../gnc/index.js"; +import { importMode } from "./import.js"; +import { Mutex } from "../util/mutex.js"; +import { load } from "../util/config.js"; + +/** + * 读取导入的卡牌包信息 + * + * @param {importCardConfig} cardConfig + */ +export function loadCard(cardConfig) { + const cardConfigName = cardConfig.name; + + lib.cardPack[cardConfigName] ??= []; + if (cardConfig.card) { + for (let [cardPackName, cardPack2] of Object.entries(cardConfig.card)) { + if (!(!cardPack2.hidden && cardConfig.translate[`${cardPackName}_info`])) continue; + lib.cardPack[cardConfigName].add(cardPackName); + } + } + + for (const [configName, configItem] of Object.entries(cardConfig)) { + switch (configName) { + case "name": + case "mode": + case "forbid": + break; + case "connect": + // @ts-ignore + lib.connectCardPack.push(cardConfigName); + break; + case "list": + if (lib.config.mode === "connect") { + // @ts-ignore + lib.cardPackList[cardConfigName] ??= []; + // @ts-ignore + lib.cardPackList[cardConfigName].addArray(configItem); + } else if (lib.config.cards.includes(cardConfigName)) { + /** + * @type {any[]} + */ + let pile = typeof configItem == "function" ? configItem() : configItem; + + lib.cardPile[cardConfigName] ??= []; + lib.cardPile[cardConfigName].addArray(pile); + + if (lib.config.bannedpile[cardConfigName]) { + pile = pile.filter((_value, index) => !lib.config.bannedpile[cardConfigName].includes(index)); + } + + if (lib.config.addedpile[cardConfigName]) { + pile = [...pile, ...lib.config.addedpile[cardConfigName]]; + } + + lib.card.list.addArray(pile); + } + break; + default: + for (const [itemName, item] of Object.entries(configItem)) { + if (configName === "skill" && itemName[0] === "_" && !item.forceLoad && (lib.config.mode !== "connect" ? !lib.config.cards.includes(cardConfigName) : !cardConfig.connect)) { + continue; + } + + if (configName === "translate" && itemName === cardConfigName) { + lib[configName][`${itemName}_card_config`] = item; + } else { + if (lib[configName][itemName] == null) { + if (configName === "skill" && !item.forceLoad && lib.config.mode === "connect" && !cardConfig.connect) { + lib[configName][itemName] = { + nopop: item.nopop, + derivation: item.derivation, + }; + } else { + // @ts-ignore + Object.defineProperty(lib[configName], itemName, Object.getOwnPropertyDescriptor(configItem, itemName)); + } + } else { + console.log(`duplicated ${configName} in card ${cardConfigName}:\n${itemName}:\nlib.${configName}.${itemName}`, lib[configName][itemName], `\ncard.${cardConfigName}.${configName}.${itemName}`, item); + } + + if (configName === "card" && lib[configName][itemName].derivation) { + // @ts-ignore + lib.cardPack.mode_derivation ??= []; + // @ts-ignore + lib.cardPack.mode_derivation.push(itemName); + } + } + } + break; + } + } +} + +/** + * 读取牌堆信息 + */ +export function loadCardPile() { + if (lib.config.mode === "connect") { + // @ts-ignore + lib.cardPackList = {}; + } else { + let pilecfg = lib.config.customcardpile[get.config("cardpilename") || "当前牌堆"]; + if (pilecfg) { + lib.config.bannedpile = get.copy(pilecfg[0] || {}); + lib.config.addedpile = get.copy(pilecfg[1] || {}); + } else { + lib.config.bannedpile = {}; + lib.config.addedpile = {}; + } + } +} + +/** + * 读取导入的武将包信息 + * + * @param {importCharacterConfig} character + */ +export function loadCharacter(character) { + let name = character.name; + + if (character.character) { + const characterPack = lib.characterPack[name]; + if (characterPack) { + Object.assign(characterPack, character.character); + } else { + lib.characterPack[name] = character.character; + } + } + + // 摆了 + for (let key in character) { + let value = character[key]; + + switch (key) { + case "name": + case "mode": + case "forbid": + break; + case "connect": + // @ts-ignore + lib.connectCharacterPack.push(name); + break; + case "character": + if (!lib.config.characters.includes(name) && lib.config.mode !== "connect") { + if (lib.config.mode === "chess" && get.config("chess_mode") === "leader" && get.config("chess_leader_allcharacter")) { + for (let charaName in value) { + // @ts-ignore + lib.hiddenCharacters.push(charaName); + } + } else if (lib.config.mode !== "boss" || name !== "boss") { + break; + } + } + // [falls through] + default: + if (Array.isArray(lib[key]) && Array.isArray(value)) { + lib[key].addArray(value); + break; + } + + for (let key2 in value) { + let value2 = value[key2]; + + if (key === "character") { + if (lib.config.forbidai_user && lib.config.forbidai_user.includes(key2)) { + lib.config.forbidai.add(key2); + } + if (Array.isArray(value2)) { + if (!value2[4]) { + value2[4] = []; + } + if (value2[4].includes("boss") || value2[4].includes("hiddenboss")) { + lib.config.forbidai.add(key2); + } + for (let skill of value2[3]) { + lib.skilllist.add(skill); + } + } else { + if (value2.isBoss || value2.isHiddenBoss) { + lib.config.forbidai.add(key2); + } + if (value2.skills) { + for (let skill of value2.skills) { + lib.skilllist.add(skill); + } + } + } + } + + if (key === "skill" && key2[0] === "_" && (lib.config.mode !== "connect" ? !lib.config.characters.includes(name) : !character.connect)) { + continue; + } + + if (key === "translate" && key2 === name) { + lib[key][`${key2}_character_config`] = value2; + } else { + if (lib[key][key2] == null) { + if (key === "skill" && !value2.forceLoad && lib.config.mode === "connect" && !character.connect) { + lib[key][key2] = { + nopop: value2.nopop, + derivation: value2.derivation, + }; + } else if (key === "character") { + lib.character[key2] = value2; + } else { + // @ts-ignore + Object.defineProperty(lib[key], key2, Object.getOwnPropertyDescriptor(character[key], key2)); + } + if (key === "card" && lib[key][key2].derivation) { + // @ts-ignore + if (!lib.cardPack.mode_derivation) { + // @ts-ignore + lib.cardPack.mode_derivation = [key2]; + } else { + // @ts-ignore + lib.cardPack.mode_derivation.push(key2); + } + } + } else if (Array.isArray(lib[key][key2]) && Array.isArray(value2)) { + lib[key][key2].addArray(value2); + } else { + console.log(`duplicated ${key} in character ${name}:\n${key2}:\nlib.${key}.${key2}`, lib[key][key2], `\ncharacter.${name}.${key}.${key2}`, value2); + } + } + } + break; + } + } +} + +export async function loadExtension(extension) { + if (!extension[5] && lib.config.mode === "connect") return; + + try { + _status.extension = extension[0]; + // @ts-ignore + _status.evaluatingExtension = extension[3]; + if (typeof extension[1] == "function") { + try { + await (gnc.is.coroutine(extension[1]) ? gnc.of(extension[1]) : extension[1]).call(extension, extension[2], extension[4]); + } catch (e) { + console.log(`加载《${extension[0]}》扩展的content时出现错误。`, e); + // @ts-ignore + if (!lib.config.extension_alert) alert(`加载《${extension[0]}》扩展的content时出现错误。\n该错误本身可能并不影响扩展运行。您可以在“设置→通用→无视扩展报错”中关闭此弹窗。\n${decodeURI(e.stack)}`); + } + } + + if (extension[4]) { + if (typeof extension[4].character?.character == "object" && Object.keys(extension[4].character.character).length > 0) { + const content = { ...extension[4].character }; + content.name = extension[0]; + content.translate ??= {}; + content.translate[content.name] = content.name; + + // ~~到最后,还得遍历一遍~~ + // 我就是被拷打,成为新的1103,受到白鼠群的嘲笑谩骂,我也绝不再次遍历! + if (content.mode === "guozhan") { + lib.characterGuozhanFilter.add(content.name); + } + for (const [charaName, character] of Object.entries(content.character)) { + if (!character[4]) { + character[4] = []; + } + + if (!character[4].some(str => typeof str == "string" && /^(?:db:extension-.+?|ext|img):.+/.test(str))) { + const img = extension[3] ? `db:extension-${content.name}:${charaName}.jpg` : `ext:${content.name}/${charaName}.jpg`; + character[4].add(img); + } + if (!character[4].some(str => typeof str == "string" && /^die:.+/.test(str))) { + const audio = `die:ext:${content.name}/${charaName}.mp3`; + character[4].add(audio); + } + + const boss = character[4].includes("boss") || character[4].includes("hiddenboss"); + const userForbidAI = lib.config.forbidai_user?.includes(charaName); + if (boss || userForbidAI) { + lib.config.forbidai.add(charaName); + } + + for (const skill of character[3]) { + lib.skilllist.add(skill); + } + } + if (typeof content.skill == "object") { + for (const skillInfo of Object.values(content.skill)) { + extSkillInject(extension[0], skillInfo); + } + } + + if (lib.imported.character) { + lib.imported.character[extension[0]] = content; + } + + if (!lib.config[`@Experimental.extension.${extension[0]}.character`]) { + game.saveConfig(`@Experimental.extension.${extension[0]}.character`, true); + lib.config.characters.add(extension[0]); + await game.promises.saveConfigValue("characters"); + } + + loadCharacter(content); + } + if (typeof extension[4].card?.card == "object" && Object.keys(extension[4].card.card).length > 0) { + const content = { ...extension[4].card }; + content.name = extension[0]; + content.translate ??= {}; + content.translate[content.name] = content.name; + + // ~~到最后,还得遍历一遍~~ + // 我就是被拷打,成为新的1103,受到白鼠群的嘲笑谩骂,我也绝不再次遍历! + for (const [cardName, card] of Object.entries(content.card)) { + if (card.audio === true) { + card.audio = `ext:${content.name}`; + } + if (!card.image) { + if (card.fullskin || card.fullimage) { + const suffix = card.fullskin ? "png" : "jpg"; + + if (extension[3]) { + card.image = `db:extension-${extension[0]}:${cardName}.${suffix}`; + } else { + card.image = `ext:${extension[0]}/${cardName}.${suffix}`; + } + } + } + } + if (typeof content.skill == "object") { + for (const skillInfo of Object.values(content.skill)) { + extSkillInject(extension[0], skillInfo); + } + } + + if (lib.imported.card) { + lib.imported.card[extension[0]] = content; + } + + if (!lib.config[`@Experimental.extension.${extension[0]}.card`]) { + game.saveConfig(`@Experimental.extension.${extension[0]}.card`, true); + lib.config.cards.add(extension[0]); + await game.promises.saveConfigValue("cards"); + } + + loadCard(content); + } + if (typeof extension[4].skill?.skill == "object" && Object.keys(extension[4].skill.skill).length > 0) { + for (const [skillName, skillInfo] of Object.entries(extension[4].skill.skill)) { + if (lib.skill[skillName]) { + console.log(`duplicated skill in extension ${extension[0]}:\n${skillName}:\nlib.skill.${skillName}`, lib.skill[skillName], `\nextension.${extension[0]}.skill.skill.${skillName}`, skillInfo); + continue; + } + + extSkillInject(extension[0], skillInfo); + lib.skill[skillName] = skillInfo; + } + + if (typeof extension[4].skill.translate == "object") { + for (const [transName, translate] of Object.entries(extension[4].skill.translate)) { + if (lib.translate[transName]) { + console.log(`duplicated translate in extension ${extension[0]}:\n${transName}:\nlib.translate.${transName}`, lib.translate[transName], `\nextension.${extension[0]}.skill.translate.${transName}`, translate); + continue; + } + + lib.translate[transName] = translate; + } + } + } + } + delete _status.extension; + // @ts-ignore + delete _status.evaluatingExtension; + } catch (e) { + console.error(e); + } +} + +/** + * 读取当前的模式信息 + * + * @param {importModeConfig} mode + */ +export function loadMode(mode) { + mixinLibrary(mode, lib); + mixinGeneral(mode, "game", game); + mixinGeneral(mode, "ui", ui); + mixinGeneral(mode, "get", get); + mixinGeneral(mode, "ai", ai); + + // @ts-ignore + delete window.noname_character_rank; + + ["onwash", "onover"].forEach(name => { + if (game[name]) { + lib[name]?.push(game[name]); + delete game[name]; + } + }); + + if (typeof mode.init == "function") { + mode.init(); + } +} + +/** + * 读取导入的play信息 + * + * @param {importPlayConfig} playConfig + */ +export function loadPlay(playConfig) { + const i = playConfig.name; + + if (lib.config.hiddenPlayPack.includes(i)) return; + if (playConfig.forbid && playConfig.forbid.includes(lib.config.mode)) return; + if (playConfig.mode && !playConfig.mode.includes(lib.config.mode)) return; + + // @ts-ignore + lib.element = mixinElement(playConfig, lib.element); + mixinGeneral(playConfig, "game", game); + mixinGeneral(playConfig, "ui", ui); + mixinGeneral(playConfig, "get", get); + for (const [configName, configItem] of Object.entries(playConfig)) { + switch (configName) { + case "name": + case "mode": + case "forbid": + case "init": + case "element": + case "game": + case "get": + case "ui": + case "arenaReady": + break; + default: + for (const [itemName, item] of Object.entries(configItem)) { + // lib[j][k+'_play_config']=play[i][j][k]; + if (configName !== "translate" || itemName !== i) { + if (lib[configName][itemName] != null) { + console.log(`duplicated ${configName} in play ${i}:\n${itemName}:\nlib.${configName}.${itemName}`, lib[configName][itemName], `\nplay.${i}.${configName}.${itemName}`, item); + } + lib[configName][itemName] = item; + } + } + break; + } + } + + if (typeof playConfig.init == "function") playConfig.init(); + if (typeof playConfig.arenaReady == "function") lib.arenaReady?.push(playConfig.arenaReady); +} + +function extSkillInject(extName, skillInfo) { + if (typeof skillInfo.audio == "number" || typeof skillInfo.audio == "boolean") { + skillInfo.audio = `ext:${extName}:${Number(skillInfo.audio)}`; + } +} + +/** + * 通用形式的内容注入 + * + * 由于历史原因,故直接覆盖对应的变量 + * + * @template {Object} T + * @param {importModeConfig | importPlayConfig} config + * @param {string} name + * @param {T} where + * @return {void} + */ +function mixinGeneral(config, name, where) { + if (!config[name]) return; + + for (let [key, value] of Object.entries(config[name])) { + where[key] = typeof value == "object" ? Object.assign(where[key] ?? {}, value) : value; + } +} + +/** + * `lib`的内容注入 + * + * @param {importModeConfig | importPlayConfig} config + * @param {Library} lib + * @return {void} + */ +function mixinLibrary(config, lib) { + const KeptWords = ["name", "element", "game", "ai", "ui", "get", "config", "onreinit", "start", "startBefore"]; + + // @ts-ignore + lib.element = mixinElement(config, lib.element); + lib.config.banned = lib.config[`${lib.config.mode}_banned`] || []; + lib.config.bannedcards = lib.config[`${lib.config.mode}_bannedcards`] || []; + // @ts-ignore + lib.rank = window.noname_character_rank; + + for (let name in config) { + if (KeptWords.includes(name)) continue; + if (lib[name] == null) lib[name] = Array.isArray(config[name]) ? [] : {}; + + Object.assign(lib[name], config[name]); + } +} + +/** + * `lib.element`的内容注入 + * + * @param {importModeConfig | importPlayConfig} config + * @param {Record} element + * @return {Record} + */ +function mixinElement(config, element) { + let newElement = { ...element }; + + if (config.element) { + for (let name in config.element) { + if (!newElement[name]) newElement[name] = []; + + let source = config.element[name]; + let target = newElement[name]; + + for (let key in source) { + if (key === "init") { + if (!target.inits) target.inits = []; + target.inits.push(source[key]); + } else { + target[key] = source[key]; + } + } + } + } + + return newElement; +} diff --git a/noname/init/node.js b/noname/init/node.js index 7331b4b2ed..1238df440a 100644 --- a/noname/init/node.js +++ b/noname/init/node.js @@ -68,6 +68,73 @@ export function nodeReady() { true ); }; + + /** + * 检查指定的路径是否是一个文件 + * + * @param {string} fileName - 需要查询的路径 + * @param {(result: -1 | 0 | 1) => void} [callback] - 回调函数;接受的参数意义如下: + * - `-1`: 路径不存在或无法访问 + * - `0`: 路径的内容不是文件 + * - `1`: 路径的内容是文件 + * @param {(err: Error) => void} [onerror] - 接收错误的回调函数 + * @return {void} - 由于三端的异步需求和历史原因,文件管理必须为回调异步函数 + */ + game.checkFile = function (fileName, callback, onerror) { + let filePath = __dirname + "/" + fileName; + + // 如果路径不存在,则无需再尝试获取信息 + if (!lib.node.fs.existsSync(filePath)) { + callback?.(-1); + return; + } + + lib.node.fs.stat(filePath, (err, stat) => { + if (err) { + // 如果是无法访问的情况,则按照函数需求返回-1 + if (err.code === "EACCES") callback?.(-1); + // 反之则直接将err传入onerror + else onerror?.(err); + return; + } + + callback?.(stat.isFile() ? 1 : 0); + }); + } + + /** + * 检查指定的路径是否是一个目录 + * + * @param {string} dir - 需要查询的路径 + * @param {(result: -1 | 0 | 1) => void} [callback] - 回调函数;接受的参数意义如下: + * - `-1`: 路径不存在或无法访问 + * - `0`: 路径的内容不是目录 + * - `1`: 路径的内容是目录 + * @param {(err: Error) => void} [onerror] - 接收错误的回调函数 + * @return {void} - 由于三端的异步需求和历史原因,文件管理必须为回调异步函数 + */ + game.checkDir = function (dir, callback, onerror) { + let dirPath = __dirname + "/" + dir; + + // 如果路径不存在,则无需再尝试获取信息 + if (!lib.node.fs.existsSync(dirPath)) { + callback?.(-1); + return; + } + + lib.node.fs.stat(dirPath, (err, stat) => { + if (err) { + // 如果是无法访问的情况,则按照函数需求返回-1 + if (err.code === "EACCES") callback?.(-1); + // 反之则直接将err传入onerror + else onerror?.(err); + return; + } + + callback?.(stat.isDirectory() ? 1 : 0); + }); + } + game.readFile = function (filename, callback, onerror) { lib.node.fs.readFile(__dirname + "/" + filename, function (err, data) { if (err) { diff --git a/noname/init/onload.js b/noname/init/onload.js index a44eb99e10..6c56282b14 100644 --- a/noname/init/onload.js +++ b/noname/init/onload.js @@ -1,14 +1,15 @@ // @ts-nocheck -import { ai } from "../ai/index.js"; -import { get } from "../get/index.js"; -import { lib } from "../library/index.js"; -import { game } from "../game/index.js"; +import { ai, setAI } from "../ai/index.js"; +import { get, setGet } from "../get/index.js"; +import { lib, Library, setLibrary } from "../library/index.js"; +import { game, setGame } from "../game/index.js"; import { _status } from "../status/index.js"; -import { ui } from "../ui/index.js"; +import { setUI, ui } from "../ui/index.js"; import { gnc } from "../gnc/index.js"; import { importMode } from "./import.js"; import { Mutex } from "../util/mutex.js"; import { load } from "../util/config.js"; +import { loadCard, loadCardPile, loadCharacter, loadExtension, loadMode, loadPlay } from "./loading.js"; export async function onload() { const libOnload = lib.onload; @@ -87,448 +88,6 @@ export async function onload() { lib.configMenu.appearence.config.splash_style.item[splash.id] = splash.name; }); - // 改不动,暂时不改了 - const proceed2 = async () => { - let mode = lib.imported.mode; - var card = lib.imported.card; - var character = lib.imported.character; - var play = lib.imported.play; - delete window.game; - var i, j, k; - for (i in mode[lib.config.mode].element) { - if (!lib.element[i]) lib.element[i] = []; - for (j in mode[lib.config.mode].element[i]) { - if (j == "init") { - if (!lib.element[i].inits) lib.element[i].inits = []; - lib.element[i].inits.push(mode[lib.config.mode].element[i][j]); - } else { - lib.element[i][j] = mode[lib.config.mode].element[i][j]; - } - } - } - for (i in mode[lib.config.mode].ai) { - if (typeof mode[lib.config.mode].ai[i] == "object") { - if (ai[i] == undefined) ai[i] = {}; - for (j in mode[lib.config.mode].ai[i]) { - ai[i][j] = mode[lib.config.mode].ai[i][j]; - } - } else { - ai[i] = mode[lib.config.mode].ai[i]; - } - } - for (i in mode[lib.config.mode].ui) { - if (typeof mode[lib.config.mode].ui[i] == "object") { - if (ui[i] == undefined) ui[i] = {}; - for (j in mode[lib.config.mode].ui[i]) { - ui[i][j] = mode[lib.config.mode].ui[i][j]; - } - } else { - ui[i] = mode[lib.config.mode].ui[i]; - } - } - for (i in mode[lib.config.mode].game) { - game[i] = mode[lib.config.mode].game[i]; - } - for (i in mode[lib.config.mode].get) { - get[i] = mode[lib.config.mode].get[i]; - } - lib.init.start = mode[lib.config.mode].start; - lib.init.startBefore = mode[lib.config.mode].startBefore; - if (game.onwash) { - lib.onwash.push(game.onwash); - delete game.onwash; - } - if (game.onover) { - lib.onover.push(game.onover); - delete game.onover; - } - lib.config.banned = lib.config[lib.config.mode + "_banned"] || []; - lib.config.bannedcards = lib.config[lib.config.mode + "_bannedcards"] || []; - - lib.rank = window.noname_character_rank; - delete window.noname_character_rank; - for (i in mode[lib.config.mode]) { - if (i == "element") continue; - if (i == "game") continue; - if (i == "ai") continue; - if (i == "ui") continue; - if (i == "get") continue; - if (i == "config") continue; - if (i == "onreinit") continue; - if (i == "start") continue; - if (i == "startBefore") continue; - if (lib[i] == undefined) lib[i] = Array.isArray(mode[lib.config.mode][i]) ? [] : {}; - for (j in mode[lib.config.mode][i]) { - lib[i][j] = mode[lib.config.mode][i][j]; - } - } - if (typeof mode[lib.config.mode].init == "function") { - mode[lib.config.mode].init(); - } - - var connectCharacterPack = []; - var connectCardPack = []; - for (i in character) { - if (character[i].character) { - const characterPack = lib.characterPack[i]; - if (characterPack) Object.assign(characterPack, character[i].character); - else lib.characterPack[i] = character[i].character; - } - for (j in character[i]) { - if (j == "mode" || j == "forbid") continue; - if (j == "connect") { - connectCharacterPack.push(i); - continue; - } - if (j == "character" && !lib.config.characters.includes(i) && lib.config.mode != "connect") { - if (lib.config.mode == "chess" && get.config("chess_mode") == "leader" && get.config("chess_leader_allcharacter")) { - for (k in character[i][j]) { - lib.hiddenCharacters.push(k); - } - } else if (lib.config.mode != "boss" || i != "boss") { - continue; - } - } - if (Array.isArray(lib[j]) && Array.isArray(character[i][j])) { - lib[j].addArray(character[i][j]); - continue; - } - for (k in character[i][j]) { - if (j == "character") { - if (lib.config.forbidai_user && lib.config.forbidai_user.includes(k)) { - lib.config.forbidai.add(k); - } - if (Array.isArray(character[i][j][k])) { - if (!character[i][j][k][4]) { - character[i][j][k][4] = []; - } - if (character[i][j][k][4].includes("boss") || character[i][j][k][4].includes("hiddenboss")) { - lib.config.forbidai.add(k); - } - for (var l = 0; l < character[i][j][k][3].length; l++) { - lib.skilllist.add(character[i][j][k][3][l]); - } - } else { - if (character[i][j][k].isBoss || character[i][j][k].isHiddenBoss) { - lib.config.forbidai.add(k); - } - if (character[i][j][k].skills) { - for (var l = 0; l < character[i][j][k].skills.length; l++) { - lib.skilllist.add(character[i][j][k].skills[l]); - } - } - } - } - if (j == "skill" && k[0] == "_" && (lib.config.mode != "connect" ? !lib.config.characters.includes(i) : !character[i].connect)) { - continue; - } - if (j == "translate" && k == i) { - lib[j][k + "_character_config"] = character[i][j][k]; - } else { - if (lib[j][k] == undefined) { - if (j == "skill" && !character[i][j][k].forceLoad && lib.config.mode == "connect" && !character[i].connect) { - lib[j][k] = { - nopop: character[i][j][k].nopop, - derivation: character[i][j][k].derivation, - }; - } else if (j === "character") { - lib.character[k] = character[i][j][k]; - } else { - Object.defineProperty(lib[j], k, Object.getOwnPropertyDescriptor(character[i][j], k)); - } - if (j == "card" && lib[j][k].derivation) { - if (!lib.cardPack.mode_derivation) { - lib.cardPack.mode_derivation = [k]; - } else { - lib.cardPack.mode_derivation.push(k); - } - } - } else if (Array.isArray(lib[j][k]) && Array.isArray(character[i][j][k])) { - lib[j][k].addArray(character[i][j][k]); - } else { - console.log(`duplicated ${j} in character ${i}:\n${k}:\nlib.${j}.${k}`, lib[j][k], `\ncharacter.${i}.${j}.${k}`, character[i][j][k]); - } - } - } - } - } - var connect_avatar_list = []; - for (var i in lib.character) { - connect_avatar_list.push(i); - } - connect_avatar_list.sort(lib.sort.capt); - for (var i = 0; i < connect_avatar_list.length; i++) { - var ia = connect_avatar_list[i]; - lib.mode.connect.config.connect_avatar.item[ia] = lib.translate[ia]; - } - if (lib.config.mode != "connect") { - var pilecfg = lib.config.customcardpile[get.config("cardpilename") || "当前牌堆"]; - if (pilecfg) { - lib.config.bannedpile = get.copy(pilecfg[0] || {}); - lib.config.addedpile = get.copy(pilecfg[1] || {}); - } else { - lib.config.bannedpile = {}; - lib.config.addedpile = {}; - } - } else { - lib.cardPackList = {}; - } - for (i in card) { - const cardPack = lib.cardPack[i] ? lib.cardPack[i] : (lib.cardPack[i] = []); - if (card[i].card) { - for (var j in card[i].card) { - if (!card[i].card[j].hidden && card[i].translate[j + "_info"]) { - cardPack.push(j); - } - } - } - for (j in card[i]) { - if (j == "mode" || j == "forbid") continue; - if (j == "connect") { - connectCardPack.push(i); - continue; - } - if (j == "list") { - if (lib.config.mode == "connect") { - const cardPackList = lib.cardPackList[i]; - if (cardPackList) cardPackList.addArray(card[i][j]); - else lib.cardPackList[i] = card[i][j]; - } else { - if (lib.config.cards.includes(i)) { - var pile; - if (typeof card[i][j] == "function") { - pile = card[i][j](); - } else { - pile = card[i][j]; - } - const cardPile = lib.cardPile[i]; - if (cardPile) cardPile.addArray(pile); - else lib.cardPile[i] = pile.slice(0); - if (lib.config.bannedpile[i]) { - for (var k = 0; k < lib.config.bannedpile[i].length; k++) { - pile[lib.config.bannedpile[i][k]] = null; - } - } - for (var k = 0; k < pile.length; k++) { - if (!pile[k]) { - pile.splice(k--, 1); - } - } - if (lib.config.addedpile[i]) { - for (var k = 0; k < lib.config.addedpile[i].length; k++) { - pile.push(lib.config.addedpile[i][k]); - } - } - lib.card.list.addArray(pile); - } - } - } else { - for (k in card[i][j]) { - if (j == "skill" && k[0] == "_" && !card[i][j][k].forceLoad && (lib.config.mode != "connect" ? !lib.config.cards.includes(i) : !card[i].connect)) { - continue; - } - if (j == "translate" && k == i) { - lib[j][k + "_card_config"] = card[i][j][k]; - } else { - if (lib[j][k] == undefined) { - if (j == "skill" && !card[i][j][k].forceLoad && lib.config.mode == "connect" && !card[i].connect) { - lib[j][k] = { - nopop: card[i][j][k].nopop, - derivation: card[i][j][k].derivation, - }; - } else { - Object.defineProperty(lib[j], k, Object.getOwnPropertyDescriptor(card[i][j], k)); - } - } else { - console.log(`duplicated ${j} in card ${i}:\n${k}:\nlib.${j}.${k}`, lib[j][k], `\ncard.${i}.${j}.${k}`, card[i][j][k]); - } - if (j == "card" && lib[j][k].derivation) { - if (!lib.cardPack.mode_derivation) { - lib.cardPack.mode_derivation = [k]; - } else { - lib.cardPack.mode_derivation.push(k); - } - } - } - } - } - } - } - if (lib.cardPack.mode_derivation) { - for (var i = 0; i < lib.cardPack.mode_derivation.length; i++) { - if (typeof lib.card[lib.cardPack.mode_derivation[i]].derivation == "string" && !lib.character[lib.card[lib.cardPack.mode_derivation[i]].derivation]) { - lib.cardPack.mode_derivation.splice(i--, 1); - } else if (typeof lib.card[lib.cardPack.mode_derivation[i]].derivationpack == "string" && !lib.config.cards.includes(lib.card[lib.cardPack.mode_derivation[i]].derivationpack)) { - lib.cardPack.mode_derivation.splice(i--, 1); - } - } - if (lib.cardPack.mode_derivation.length == 0) { - delete lib.cardPack.mode_derivation; - } - } - if (lib.config.mode != "connect") { - for (i in play) { - if (lib.config.hiddenPlayPack.includes(i)) continue; - if (play[i].forbid && play[i].forbid.includes(lib.config.mode)) continue; - if (play[i].mode && play[i].mode.includes(lib.config.mode) == false) continue; - for (j in play[i].element) { - if (!lib.element[j]) lib.element[j] = []; - for (k in play[i].element[j]) { - if (k == "init") { - if (!lib.element[j].inits) lib.element[j].inits = []; - lib.element[j].inits.push(play[i].element[j][k]); - } else { - lib.element[j][k] = play[i].element[j][k]; - } - } - } - for (j in play[i].ui) { - if (typeof play[i].ui[j] == "object") { - if (ui[j] == undefined) ui[j] = {}; - for (k in play[i].ui[j]) { - ui[j][k] = play[i].ui[j][k]; - } - } else { - ui[j] = play[i].ui[j]; - } - } - for (j in play[i].game) { - game[j] = play[i].game[j]; - } - for (j in play[i].get) { - get[j] = play[i].get[j]; - } - for (j in play[i]) { - if (j == "mode" || j == "forbid" || j == "init" || j == "element" || j == "game" || j == "get" || j == "ui" || j == "arenaReady") continue; - for (k in play[i][j]) { - if (j == "translate" && k == i) { - // lib[j][k+'_play_config']=play[i][j][k]; - } else { - if (lib[j][k] != undefined) { - console.log(`duplicated ${j} in play ${i}:\n${k}:\nlib.${j}.${k}`, lib[j][k], `\nplay.${i}.${j}.${k}`, play[i][j][k]); - } - lib[j][k] = play[i][j][k]; - } - } - } - if (typeof play[i].init == "function") play[i].init(); - if (typeof play[i].arenaReady == "function") lib.arenaReady.push(play[i].arenaReady); - } - } - - lib.connectCharacterPack = []; - lib.connectCardPack = []; - for (var i = 0; i < lib.config.all.characters.length; i++) { - var packname = lib.config.all.characters[i]; - if (connectCharacterPack.includes(packname)) { - lib.connectCharacterPack.push(packname); - } - } - for (var i = 0; i < lib.config.all.cards.length; i++) { - var packname = lib.config.all.cards[i]; - if (connectCardPack.includes(packname)) { - lib.connectCardPack.push(packname); - } - } - if (lib.config.mode != "connect") { - for (i = 0; i < lib.card.list.length; i++) { - if (lib.card.list[i][2] == "huosha") { - lib.card.list[i] = lib.card.list[i].slice(0); - lib.card.list[i][2] = "sha"; - lib.card.list[i][3] = "fire"; - } else if (lib.card.list[i][2] == "leisha") { - lib.card.list[i] = lib.card.list[i].slice(0); - lib.card.list[i][2] = "sha"; - lib.card.list[i][3] = "thunder"; - } - if (!lib.card[lib.card.list[i][2]]) { - lib.card.list.splice(i, 1); - i--; - } else if (lib.card[lib.card.list[i][2]].mode && lib.card[lib.card.list[i][2]].mode.includes(lib.config.mode) == false) { - lib.card.list.splice(i, 1); - i--; - } - } - } - - if (lib.config.mode == "connect") { - _status.connectMode = true; - } - if (window.isNonameServer) { - lib.cheat.i(); - } else if (lib.config.dev && (!_status.connectMode || lib.config.debug)) { - lib.cheat.i(); - } - lib.config.sort_card = get.sortCard(lib.config.sort); - delete lib.imported.character; - delete lib.imported.card; - delete lib.imported.mode; - delete lib.imported.play; - for (var i in lib.init) { - if (i.startsWith("setMode_")) { - delete lib.init[i]; - } - } - if (!_status.connectMode) { - for (var i = 0; i < lib.extensions.length; i++) { - try { - _status.extension = lib.extensions[i][0]; - _status.evaluatingExtension = lib.extensions[i][3]; - if (typeof lib.extensions[i][1] == "function") - try { - await (gnc.is.coroutine(lib.extensions[i][1]) ? gnc.of(lib.extensions[i][1]) : lib.extensions[i][1]).call(lib.extensions[i], lib.extensions[i][2], lib.extensions[i][4]); - } catch (e) { - console.log(`加载《${lib.extensions[i][0]}》扩展的content时出现错误。`, e); - if (!lib.config.extension_alert) alert(`加载《${lib.extensions[i][0]}》扩展的content时出现错误。\n该错误本身可能并不影响扩展运行。您可以在“设置→通用→无视扩展报错”中关闭此弹窗。\n${decodeURI(e.stack)}`); - } - if (lib.extensions[i][4]) { - if (lib.extensions[i][4].character) { - for (var j in lib.extensions[i][4].character.character) { - game.addCharacterPack(get.copy(lib.extensions[i][4].character)); - break; - } - } - if (lib.extensions[i][4].card) { - for (var j in lib.extensions[i][4].card.card) { - game.addCardPack(get.copy(lib.extensions[i][4].card)); - break; - } - } - if (lib.extensions[i][4].skill) { - for (var j in lib.extensions[i][4].skill.skill) { - game.addSkill(j, lib.extensions[i][4].skill.skill[j], lib.extensions[i][4].skill.translate[j], lib.extensions[i][4].skill.translate[j + "_info"], lib.extensions[i][4].skill.translate[j + "_append"], lib.extensions[i][4].skill.translate[j + "_ab"]); - } - } - } - delete _status.extension; - delete _status.evaluatingExtension; - } catch (e) { - console.log(e); - } - } - } - delete lib.extensions; - - if (lib.init.startBefore) { - lib.init.startBefore(); - delete lib.init.startBefore; - } - ui.create.arena(); - game.createEvent("game", false).setContent(lib.init.start); - if (lib.mode[lib.config.mode] && lib.mode[lib.config.mode].fromextension) { - var startstr = mode[lib.config.mode].start.toString(); - if (startstr.indexOf("onfree") == -1) { - setTimeout(lib.init.onfree, 500); - } - } - delete lib.init.start; - if (Array.isArray(_status.onprepare) && _status.onprepare.length) { - await Promise.allSettled(_status.onprepare); - delete _status.onprepare; - } - game.loop(); - }; - localStorage.removeItem(lib.configprefix + "directstart"); if (!lib.imported.mode?.[lib.config.mode]) { window.inSplash = true; @@ -554,27 +113,112 @@ export async function onload() { } lib.storage = (await load(lib.config.mode, "data")) || {}; - /* - if (!lib.db) { - try { - lib.storage = JSON.parse(localStorage.getItem(lib.configprefix + lib.config.mode)); - if (typeof lib.storage != "object" || lib.storage == null) jumpToCatchBlock(); - } catch (err) { - lib.storage = {}; - localStorage.setItem(lib.configprefix + lib.config.mode, "{}"); - } - } else { - let storage = await game.getDB("data", lib.config.mode); - lib.storage = storage || {}; - } - */ - const libOnload2 = lib.onload2; delete lib.onload2; await runCustomContents(libOnload2); await Promise.allSettled(loadingCustomStyle); - await proceed2(); + delete window.game; + + lib.connectCharacterPack = []; + lib.connectCardPack = []; + + const currentMode = lib.imported.mode[lib.config.mode]; + loadMode(currentMode); + // 为了模式扩展,两个东西删不了 + lib.init.start = currentMode.start; + lib.init.startBefore = currentMode.startBefore; + + if (lib.imported.character != null) { + Object.values(lib.imported.character).forEach(loadCharacter); + } + + // 我不好说,但我尊重水乎的想法 + Object.keys(lib.character) + .toSorted(lib.sort.capt) + .forEach(character => { + lib.mode.connect.config.connect_avatar.item[character] = lib.translate[character]; + }); + + loadCardPile(); + + if (lib.imported.card != null) { + Object.values(lib.imported.card).forEach(loadCard); + } + + if (lib.cardPack.mode_derivation) { + lib.cardPack.mode_derivation = lib.cardPack.mode_derivation.filter(item => { + if (typeof lib.card[item].derivation == "string" && !lib.character[lib.card[item].derivation]) { + return false; + } + return !(typeof lib.card[item].derivationpack == "string" && !lib.config.cards.includes(lib.card[item].derivationpack)); + }); + + if (lib.cardPack.mode_derivation.length === 0) { + delete lib.cardPack.mode_derivation; + } + } + + if (lib.config.mode === "connect") { + _status.connectMode = true; + } else { + if (lib.imported.play != null) { + Object.values(lib.imported.play).forEach(loadPlay); + } + + lib.card.list = lib.card.list + .filter(cardData => cardData[2] && !lib.card[cardData[2]].mode?.includes(lib.config.mode)) + .map(cardData => { + if (cardData[2] === "huosha") { + cardData = cardData.slice(0); + cardData[2] = "sha"; + cardData[3] = "fire"; + } else if (cardData[2] === "leisha") { + cardData = cardData.slice(0); + cardData[2] = "sha"; + cardData[3] = "thunder"; + } + return cardData; + }); + } + + if (window.isNonameServer) { + lib.cheat.i(); + } else if (lib.config.dev && (!_status.connectMode || lib.config.debug)) { + lib.cheat.i(); + } + lib.config.sort_card = get.sortCard(lib.config.sort); + + for (let funcName in lib.init) { + if (funcName.startsWith("setMode_")) { + delete lib.init[funcName]; + } + } + + if (Array.isArray(lib.extensions)) { + await Promise.allSettled(lib.extensions.map(loadExtension)); + } + + if (lib.init.startBefore) { + lib.init.startBefore(); + delete lib.init.startBefore; + } + + ui.create.arena(); + game.createEvent("game", false).setContent(lib.init.start); + if (lib.mode[lib.config.mode] && lib.mode[lib.config.mode].fromextension) { + var startstr = currentMode.start.toString(); + if (startstr.indexOf("onfree") === -1) { + setTimeout(lib.init.onfree, 500); + } + } + delete lib.init.start; + if (Array.isArray(_status.onprepare) && _status.onprepare.length) { + await Promise.allSettled(_status.onprepare); + delete _status.onprepare; + } + + game.loop(); } async function createBackground() { diff --git a/noname/init/onload/OnloadSplash.js b/noname/init/onload/OnloadSplash.js index c19176e58b..bcecd0da24 100644 --- a/noname/init/onload/OnloadSplash.js +++ b/noname/init/onload/OnloadSplash.js @@ -2,7 +2,7 @@ import { lib, get } from "../../../noname.js"; import { ref, onMounted } from "../../../game/vue.esm-browser.js"; import { delay } from "../../util/index.js"; -const html = String.raw; +const html = (strings, ...values) => String.raw({ raw: strings }, ...values); /** * @type {import("vue").Component} */ diff --git a/noname/library/element/GameEvent/GameEventManager.js b/noname/library/element/GameEvent/GameEventManager.js new file mode 100644 index 0000000000..b38bcc1005 --- /dev/null +++ b/noname/library/element/GameEvent/GameEventManager.js @@ -0,0 +1,25 @@ +import { GameEvent } from "../gameEvent.js"; + +export default class GameEventManager{ + get [Symbol.toStringTag]() { + return 'GameEventManager'; + } + eventStack = []; + rootEvent; + tempEvent; + get event(){ + return this.getStatusEvent(); + } + getStartedEvent(){ + return this.tempEvent || this.eventStack.at(-1); + } + getStatusEvent() { + return this.tempEvent || this.eventStack.at(-1) || this.rootEvent; + } + setStatusEvent(event) { + if (!(event instanceof GameEvent)) return; + if (this.eventStack.length === 0) this.rootEvent = event; + else if (this.eventStack.includes(event)) this.tempEvent = event; + else throw new Error("Cannot assign a value to _status.event that is not in eventStack."); + } +} \ No newline at end of file diff --git a/noname/library/element/GameEvent/GameEventManager.ts b/noname/library/element/GameEvent/GameEventManager.ts new file mode 100644 index 0000000000..f5a9bf7829 --- /dev/null +++ b/noname/library/element/GameEvent/GameEventManager.ts @@ -0,0 +1,25 @@ +import { GameEvent } from "../gameEvent.js"; + +export default class GameEventManager { + get [Symbol.toStringTag]() { + return 'GameEventManager'; + } + eventStack: GameEvent[] = []; + rootEvent?: GameEvent; + tempEvent?: GameEvent; + get event() { + return this.getStatusEvent(); + } + getStartedEvent() { + return this.tempEvent || this.eventStack.at(-1); + } + getStatusEvent() { + return this.tempEvent || this.eventStack.at(-1) || this.rootEvent; + } + setStatusEvent(event: GameEvent) { + if (!(event instanceof GameEvent)) return; + if (this.eventStack.length === 0) this.rootEvent = event; + else if (this.eventStack.includes(event)) this.tempEvent = event; + else throw new Error("Cannot assign a value to _status.event that is not in eventStack."); + } +} \ No newline at end of file diff --git a/noname/library/element/GameEvent/compilers/ArrayCompiler.js b/noname/library/element/GameEvent/compilers/ArrayCompiler.js new file mode 100644 index 0000000000..cf7cab7e9d --- /dev/null +++ b/noname/library/element/GameEvent/compilers/ArrayCompiler.js @@ -0,0 +1,35 @@ +import ContentCompilerBase from "./ContentCompilerBase.js"; +import { GameEvent } from "../../gameEvent.js"; +export default class ArrayCompiler extends ContentCompilerBase { + type = "array"; + filter(content) { + return Array.isArray(content); + } + compile(content) { + if (!Array.isArray(content)) + throw new ReferenceError("content必须是一个数组"); + const compiler = this; + return async function (event) { + if (!Number.isInteger(event.step)) + event.step = 0; + while (!event.finished) { + if (event.step >= content.length) { + event.finish(); + break; + } + compiler.beforeExecute(event); + event.step++; + let result; + if (!compiler.isPrevented(event)) { + const original = content[event.step]; + //@ts-ignore + const next = await Reflect.apply(original, this, [event, event._trigger, event.player]); + result = next instanceof GameEvent ? next.result : next; + } + const nextResult = await event.waitNext(); + event._result = result || nextResult || event._result; + compiler.afterExecute(event); + } + }; + } +} \ No newline at end of file diff --git a/noname/library/element/GameEvent/compilers/ArrayCompiler.ts b/noname/library/element/GameEvent/compilers/ArrayCompiler.ts new file mode 100644 index 0000000000..f66eaa04b6 --- /dev/null +++ b/noname/library/element/GameEvent/compilers/ArrayCompiler.ts @@ -0,0 +1,40 @@ +import ContentCompilerBase from "./ContentCompilerBase.ts"; +import { EventContent, GameEvent } from "./IContentCompiler.ts"; + +export default class ArrayCompiler extends ContentCompilerBase { + type = "array"; + + filter(content: EventContent): boolean { + return Array.isArray(content); + } + + compile(content: EventContent) { + if (!Array.isArray(content)) + throw new ReferenceError("content必须是一个数组"); + + const compiler = this; + return async function (event: GameEvent) { + if (!Number.isInteger(event.step)) + event.step = 0; + + while (!event.finished) { + if (event.step >= content.length) { + event.finish(); + break; + } + compiler.beforeExecute(event); + event.step++; + let result: Result | undefined; + if (!compiler.isPrevented(event)) { + const original = content[event.step]; + //@ts-ignore + const next = await Reflect.apply(original, this, [event, event._trigger, event.player]); + result = next instanceof GameEvent ? next.result : next; + } + const nextResult = await event.waitNext(); + event._result = result ?? nextResult ?? event._result; + compiler.afterExecute(event); + } + }; + } +} \ No newline at end of file diff --git a/noname/library/element/GameEvent/compilers/AsyncCompiler.js b/noname/library/element/GameEvent/compilers/AsyncCompiler.js new file mode 100644 index 0000000000..d60152be04 --- /dev/null +++ b/noname/library/element/GameEvent/compilers/AsyncCompiler.js @@ -0,0 +1,12 @@ +import ContentCompiler from "./ContentCompiler.js"; +import ContentCompilerBase from "./ContentCompilerBase.js"; +export default class AsyncCompiler extends ContentCompilerBase { + type = "async"; + filter(content) { + if (typeof content !== 'function') return false; + return content.constructor.name === "AsyncFunction" && content.length >= 1; + } + compile(content) { + return ContentCompiler.compile([content]); + } +} \ No newline at end of file diff --git a/noname/library/element/GameEvent/compilers/AsyncCompiler.ts b/noname/library/element/GameEvent/compilers/AsyncCompiler.ts new file mode 100644 index 0000000000..259ab3e8dd --- /dev/null +++ b/noname/library/element/GameEvent/compilers/AsyncCompiler.ts @@ -0,0 +1,20 @@ +// 因为需要规范content的函数体,所以即使是async也要编译喵! + +import ContentCompiler from "./ContentCompiler.ts"; +import ContentCompilerBase from "./ContentCompilerBase.ts"; +import { EventContent } from "./IContentCompiler.ts"; + +type AsyncFunction = (...args: any[]) => Promise; + +export default class AsyncCompiler extends ContentCompilerBase { + type = "async"; + + filter(content: EventContent): boolean { + if (typeof content !== 'function') return false; + return content.constructor.name === "AsyncFunction" && content.length >= 1; + } + + compile(content: EventContent) { + return ContentCompiler.compile([content as AsyncFunction]); + } +} diff --git a/noname/library/element/GameEvent/compilers/ContentCompiler.js b/noname/library/element/GameEvent/compilers/ContentCompiler.js new file mode 100644 index 0000000000..7513c110e6 --- /dev/null +++ b/noname/library/element/GameEvent/compilers/ContentCompiler.js @@ -0,0 +1,81 @@ +import { lib } from "../../../../../noname.js"; +import StepCompiler from "./StepCompiler.js"; +import YieldCompiler from "./YieldCompiler.js"; +import AsyncCompiler from "./AsyncCompiler.js"; +import ArrayCompiler from "./ArrayCompiler.js"; +class ContentCompiler { + #compilerTypes = new Set(); + #compilers = new Set(); + #compiledContent = new WeakMap(); + /** + * ```plain + * 注册一个编译器实例 + * + * 如果后面开始全面迁移到 TypeScript,那么请使用依赖注入代替这个方法喵 + * ``` + * + * @todo 应该使用依赖注入替代 + * @param compiler 编译器实例对象 + */ + addCompiler(compiler) { + const type = compiler.constructor; + if (typeof type !== "function") + throw new TypeError("content编译器没有明确的类型"); + if (this.#compilerTypes.has(type)) + throw new TypeError("相同的content编译器类型不能重复注册"); + this.#compilerTypes.add(type); + this.#compilers.add(compiler); + } + /** + * ```plain + * 对无法直接编译的数据做处理 + * ``` + * + * @param content + * @returns + */ + regularize(content) { + // 无法直接编译的数据做处理 + if (typeof content === 'string') { + return lib.element.content[content] || lib.element.contents[content]; + } + else if (Symbol.iterator in content) { + return Array.from(content); + } + return content; + } + /** + * ```plain + * 集成的编译函数 + * 通过责任链模式将content分发给所有注册的编译器喵 + * ``` + * + * @param content + */ + compile(content) { + if (content.compiled) return content; + const target = this.regularize(content); + const cached = this.#compiledContent.get(target); + if (cached) + return cached; + for (const compiler of this.#compilers) { + if (!compiler.filter(target)) + continue; + const compiled = compiler.compile(target); + compiled.compiled = true; + compiled.type = compiler.type; + compiled.original = content; + // 对编译结果进行缓存 + this.#compiledContent.set(target, compiled); + return compiled; + } + // 无家可归的可怜孩子喵 + throw new Error(`不受支持的content: \n ${String(target)}`); + } +} +const compiler = new ContentCompiler(); +compiler.addCompiler(new ArrayCompiler()); +compiler.addCompiler(new AsyncCompiler()); +compiler.addCompiler(new StepCompiler()); +compiler.addCompiler(new YieldCompiler()); +export default compiler; diff --git a/noname/library/element/GameEvent/compilers/ContentCompiler.ts b/noname/library/element/GameEvent/compilers/ContentCompiler.ts new file mode 100644 index 0000000000..d087fd8788 --- /dev/null +++ b/noname/library/element/GameEvent/compilers/ContentCompiler.ts @@ -0,0 +1,100 @@ +import { lib } from "../../../../../noname.js"; +import IContentCompiler, { EventCompileable, EventCompiledContent, EventContent } from "./IContentCompiler.ts"; + +import StepCompiler from "./StepCompiler.ts" +import YieldCompiler from "./YieldCompiler.ts" +import AsyncCompiler from "./AsyncCompiler.ts" +import ArrayCompiler from "./ArrayCompiler.ts" + +type Class = new (...args: any) => T; + +class ContentCompiler { + #compilerTypes = new Set>(); + #compilers = new Set(); + + #compiledContent = new WeakMap(); + + /** + * ```plain + * 注册一个编译器实例 + * + * 如果后面开始全面迁移到 TypeScript,那么请使用依赖注入代替这个方法喵 + * ``` + * + * @todo 应该使用依赖注入替代 + * @param compiler 编译器实例对象 + */ + addCompiler(compiler: IContentCompiler) { + const type = compiler.constructor as Class; + + if (typeof type !== "function") + throw new TypeError("content编译器没有明确的类型"); + + if (this.#compilerTypes.has(type)) + throw new TypeError("相同的content编译器类型不能重复注册"); + + this.#compilerTypes.add(type); + this.#compilers.add(compiler); + } + + /** + * ```plain + * 对无法直接编译的数据做处理 + * ``` + * + * @param content + * @returns + */ + private regularize(content: EventCompileable): EventContent { + // 无法直接编译的数据做处理 + if (typeof content === 'string') { + return lib.element.content[content] + ?? lib.element.contents[content]; + } else if (Symbol.iterator in content) { + return Array.from(content); + } + return content; + } + + /** + * ```plain + * 集成的编译函数 + * 通过责任链模式将content分发给所有注册的编译器喵 + * ``` + * + * @param content + */ + compile(content: EventCompileable): EventCompiledContent { + //@ts-ignore + if (content.compiled) return content; + + const target = this.regularize(content); + + const cached = this.#compiledContent.get(target); + + if (cached) return cached; + + for (const compiler of this.#compilers) { + if (!compiler.filter(target)) continue; + const compiled = compiler.compile(target) as EventCompiledContent; + compiled.compiled = true; + compiled.type = compiler.type; + compiled.original = content; + // 对编译结果进行缓存 + this.#compiledContent.set(target, compiled); + return compiled; + } + + // 无家可归的可怜孩子喵 + throw new Error(`不受支持的content: \n ${String(target)}`); + } +} + +const compiler = new ContentCompiler(); + +compiler.addCompiler(new ArrayCompiler()); +compiler.addCompiler(new AsyncCompiler()); +compiler.addCompiler(new StepCompiler()); +compiler.addCompiler(new YieldCompiler()); + +export default compiler; \ No newline at end of file diff --git a/noname/library/element/GameEvent/compilers/ContentCompilerBase.js b/noname/library/element/GameEvent/compilers/ContentCompilerBase.js new file mode 100644 index 0000000000..c1d4394db9 --- /dev/null +++ b/noname/library/element/GameEvent/compilers/ContentCompilerBase.js @@ -0,0 +1,42 @@ +import { game, _status } from "../../../../../noname.js"; +export default class ContentCompilerBase { + beforeExecute(event) { + const handlerType = event.getDefaultHandlerType(); + const option = { state: "begin" }; + event.callHandler(handlerType, event, option); + event.updateStep(); + } + isPrevented(event) { + const { player } = event; + if (event.name === "phaseLoop") + return false; + if (!player) return false; + if (player.isDead() && !event.forceDie) { + game.broadcastAll(function () { + while (_status.dieClose.length) { + _status.dieClose.shift().close(); + } + }); + if (event._oncancel) event._oncancel(); + } + else if (player.isOut() && !event.includeOut) { + if (event.name == "phase" + && player == _status.roundStart + && !event.skill) + _status.roundSkipped = true; + } + else if (player.removed) + void 0; + else + return false; + event.finish(); + return true; + } + afterExecute(event) { + event.clearStepCache(null); + const handlerType = event.getDefaultHandlerType(); + const option = { state: "end" }; + event.callHandler(handlerType, event, option); + event.updateStep(); + } +} diff --git a/noname/library/element/GameEvent/compilers/ContentCompilerBase.ts b/noname/library/element/GameEvent/compilers/ContentCompilerBase.ts new file mode 100644 index 0000000000..adf7523693 --- /dev/null +++ b/noname/library/element/GameEvent/compilers/ContentCompilerBase.ts @@ -0,0 +1,79 @@ +import { game, _status } from "../../../../../noname.js"; +import IContentCompiler, { EventContent, GameEvent } from "./IContentCompiler.js"; + +type HandlerOption = { state?: "begin" | "end" }; + +/** + * 向子类提供统一的公共方法 + */ +export default abstract class ContentCompilerBase implements IContentCompiler { + abstract type: string; + abstract filter(content: EventContent): boolean; + abstract compile(content: EventContent): ((e: GameEvent) => Promise); + + /** + * ```plain + * 对于事件执行前的一些准备工作 + * ``` + * + * @param event 事件 + */ + beforeExecute(event: GameEvent) { + const handlerType = event.getDefaultHandlerType() as `on${Capitalize}`; + const option: HandlerOption = { state: "begin" }; + event.callHandler(handlerType, event, option); + event.updateStep(); + } + + /** + * ```plain + * 判断事件能否继续执行 + * ``` + * + * @param event 事件 + * @returns 当返回true时,代表event.finish()已经被调用 + */ + isPrevented(event: GameEvent): boolean { + const { player } = event; + + if (event.name === "phaseLoop") return false; + + if (!player) return false; + if (player.isDead() && !event.forceDie) { + //@ts-ignore + game.broadcastAll(function () { + while (_status.dieClose.length) { + _status.dieClose.shift().close(); + } + }); + event._oncancel?.(); + } + else if (player.isOut() && !event.includeOut) { + if (event.name == "phase" + && player == _status.roundStart + && !event.skill) + _status.roundSkipped = true; + } + else if (player.removed) void 0; + else return false; + + event.finish(); + return true; + } + + /** + * ```plain + * 对于事件执行后的一些收尾工作 + * ``` + * + * @param event 事件 + */ + afterExecute(event: GameEvent) { + event.clearStepCache(null); + + const handlerType = event.getDefaultHandlerType() as `on${Capitalize}`; + const option: HandlerOption = { state: "end" }; + event.callHandler(handlerType, event, option); + event.updateStep(); + } +} diff --git a/noname/library/element/GameEvent/compilers/IContentCompiler.ts b/noname/library/element/GameEvent/compilers/IContentCompiler.ts new file mode 100644 index 0000000000..975f94a360 --- /dev/null +++ b/noname/library/element/GameEvent/compilers/IContentCompiler.ts @@ -0,0 +1,43 @@ +import { lib } from "../../../../../noname.js"; +import { GameEvent } from "../../gameEvent.js"; + +export type EventContent = Function | Function[]; +export type EventCompileable = EventContent | Iterable | keyof typeof lib.element.content; +export { GameEvent }; + +// 指示标准的事件content应该是只接受event一个参数的异步函数,同时有一个属性指示编译前的content类型 +export type EventCompiledContent = ((e: GameEvent) => Promise) & { + compiled: true; + type: string; + original: EventCompileable; + /** + * array content的原始值 + */ + originals?: Function[]; +}; + +export default interface IContentCompiler { + /** + * ```plain + * 当前编译器的事件content类型 + * ``` + */ + type: string; + + /** + * ```plain + * 判断事件content是否被当前编译器支持 + * ``` + * + * @param content 事件content + */ + filter(content: EventContent): boolean; + + /** + * 对content执行编译 + * 并返回标准的事件content + * + * @param content 要编译的content + */ + compile(content: EventCompileable): ((e: GameEvent) => Promise); +} \ No newline at end of file diff --git a/noname/library/element/GameEvent/compilers/StepCompiler.js b/noname/library/element/GameEvent/compilers/StepCompiler.js new file mode 100644 index 0000000000..eedfbb48fa --- /dev/null +++ b/noname/library/element/GameEvent/compilers/StepCompiler.js @@ -0,0 +1,133 @@ +// 喵喵!step写法的content全在这里处理喵! +import { _status, ai, game, get, lib, ui } from "../../../../../noname.js"; +import ContentCompilerBase from "./ContentCompilerBase.js"; +import ContentCompiler from "./ContentCompiler.js"; +import security from "../../../../util/security.js"; +import { CodeSnippet, ErrorManager } from "../../../../util/error.js"; +export default class StepCompiler extends ContentCompilerBase { + type = "step"; + filter(content) { + return typeof content === 'function' && content.length === 0; + } + compile(content) { + if (typeof content != "function") + throw new Error("StepCompiler只能接受函数"); + return new StepParser(content).getResult(); + } +} +/** + * @author 诗笺 & Tipx-L + */ +class StepParser { + static deconstructs = ["step", "source", "target", "targets", "card", "cards", "skill", "forced", "num", "_result: result"]; + static topVars = ["_status", "lib", "game", "ui", "get", "ai"]; + static params = ["topVars", "event", "trigger", "player"]; + /** + * 虽然现在 parsex 被控制到了沙盒, + * 但是因为默认沙盒还是可以额外操作东西, + * 故而对不同的运行域做了区分 + */ + functionConstructor; + str; + stepHead = ""; + //func中要写步骤的话,必须要写step 0 + step = 0; + contents = []; + originals = []; + constructor(func) { + if (typeof func !== "function") + throw new TypeError("为确保安全禁止用parsex/parseStep解析非函数"); + // ModAsyncFunction + this.functionConstructor = security.getIsolatedsFrom(func)[2]; + this.str = this.formatFunction(func); + if (lib.config.dev) + this.replaceDebugger(); + } + getResult() { + this.parseStep(); + const result = ContentCompiler.compile(this.contents); + result.originals = this.originals; + return result; + } + parseStep() { + let skipIndex = 0; + //去除99个step的限制 + while (true) { + const result = this.str.slice(skipIndex).match(new RegExp(`\\(?['"]step ${this.step}['"]\\)?;?`)); + if (result == null || result.index == null) { + this.packStep(this.str); + break; + } + const head = this.str.slice(0, skipIndex + result.index); + if (this.step === 0) { + this.stepHead = head.trim(); + } + else { + try { + this.packStep(head); + } + catch (e) { + skipIndex = result.index + result[0].length; + continue; + } + } + this.str = this.str.slice(head.length + result[0].length); + skipIndex = 0; + this.step++; + } + } + packStep(code) { + const compiled = new this.functionConstructor(...StepParser.params, ` + var { ${StepParser.deconstructs.join(", ")} } = event; + var { ${StepParser.topVars.join(", ")} } = topVars; + + ${this.stepHead} + { + ${code} + } + `); + ErrorManager.setCodeSnippet(compiled, new CodeSnippet(code, 3)); // 记录编译后函数的原代码片段 + this.originals.push(compiled); + this.contents.push(function (event, trigger, player) { + //@ts-ignore + return compiled.apply(this, [{ _status, ai, game, get, lib, ui }, event, trigger, player]); + }); + } + formatFunction(func) { + // 沙盒在封装函数时,为了保存源代码会另外存储函数的源代码 + const decompileFunction = security.isSandboxRequired() + ? security.importSandbox().Marshal.decompileFunction + : Function.prototype.call.bind(Function.prototype.toString); + //移除所有注释 + const code = decompileFunction(func) + .replace(/((?:(?:^[ \t]*)?(?:\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\/(?:[ \t]*\r?\n(?=[ \t]*(?:\r?\n|\/\*|\/\/)))?|\/\/(?:[^\\]|\\(?:\r?\n)?)*?(?:\r?\n(?=[ \t]*(?:\r?\n|\/\*|\/\/))|(?=\r?\n))))+)|("(?:\\[\s\S]|[^"\\])*"|'(?:\\[\s\S]|[^'\\])*'|(?:\r?\n|[\s\S])[^/"'\\\s]*)/gm, "$2") + .trim(); + //移除两边括号 + return code + .slice(0, code.lastIndexOf("}")) + .slice(code.indexOf("{") + 1) + .trimEnd(); + } + replaceDebugger() { + let regex = /event\.debugger\(\)/; + // let hasDebugger = false; + let insertDebugger = `await event.debugger()`; // yield code=>eval(code) 唔唔不是我干的喵 + let debuggerSkip = 0; + let debuggerResult; + while ((debuggerResult = this.str.slice(debuggerSkip).match(regex)) != null) { + if (debuggerResult.index == null) + throw new Error("匹配到了debugger但是没有索引值"); + let debuggerCopy = this.str; + debuggerCopy = debuggerCopy.slice(0, debuggerSkip + debuggerResult.index) + insertDebugger + debuggerCopy.slice(debuggerSkip + debuggerResult.index + debuggerResult[0].length, -1); + try { + new this.functionConstructor(debuggerCopy); + this.str = debuggerCopy + "}"; + debuggerSkip += debuggerResult.index + insertDebugger.length; + // hasDebugger = true; + } + catch (error) { + debuggerSkip += debuggerResult.index + debuggerResult[0].length; + } + } + } +} diff --git a/noname/library/element/GameEvent/compilers/StepCompiler.ts b/noname/library/element/GameEvent/compilers/StepCompiler.ts new file mode 100644 index 0000000000..27fae38705 --- /dev/null +++ b/noname/library/element/GameEvent/compilers/StepCompiler.ts @@ -0,0 +1,153 @@ +// 喵喵!step写法的content全在这里处理喵! + +import { EventContent, GameEvent } from "./IContentCompiler.ts"; +import { _status, ai, game, get, lib, ui } from "../../../../../noname.js"; +import ContentCompilerBase from "./ContentCompilerBase.ts"; +import ContentCompiler from "./ContentCompiler.ts"; +import security from "../../../../util/security.js"; +import { CodeSnippet, ErrorManager } from "../../../../util/error.js"; + +export default class StepCompiler extends ContentCompilerBase { + type = "step"; + + filter(content: EventContent) { + return typeof content === 'function' && content.length === 0; + } + + compile(content: EventContent) { + if (typeof content != "function") + throw new Error("StepCompiler只能接受函数"); + + return new StepParser(content).getResult(); + } + +} + +/** + * @author 诗笺、Tipx-L + */ +class StepParser { + static deconstructs = ["step", "source", "target", "targets", "card", "cards", "skill", "forced", "num", "_result: result"]; + static topVars = ["_status", "lib", "game", "ui", "get", "ai"]; + static params = ["topVars", "event", "trigger", "player"]; + + /** + * 虽然现在 parsex 被控制到了沙盒, + * 但是因为默认沙盒还是可以额外操作东西, + * 故而对不同的运行域做了区分 + */ + functionConstructor: new (...args: string[]) => Function; + str: string; + stepHead: string = ""; + //func中要写步骤的话,必须要写step 0 + step: number = 0; + contents: Function[] = []; + originals: Function[] = []; + + constructor(func: Function) { + if (typeof func !== "function") + throw new TypeError("为确保安全禁止用parsex/parseStep解析非函数"); + // ModAsyncFunction + this.functionConstructor = security.getIsolatedsFrom(func)[2]; + this.str = this.formatFunction(func); + if (lib.config.dev) this.replaceDebugger(); + } + + getResult(): ((e: GameEvent) => Promise) { + this.parseStep(); + const result = ContentCompiler.compile(this.contents); + result.originals = this.originals; + return result; + } + + parseStep() { + let skipIndex = 0; + //去除99个step的限制 + while (true) { + const result = this.str.slice(skipIndex).match(new RegExp(`\\(?['"]step ${this.step}['"]\\)?;?`)); + if (result == null || result.index == null){ + this.packStep(this.str); + break; + } + + const head = this.str.slice(0, skipIndex + result.index); + + if (this.step === 0) { + this.stepHead = head.trim(); + } else { + try { + this.packStep(head); + } catch (e) { + skipIndex = result.index + result[0].length; + continue; + } + } + + this.str = this.str.slice(head.length + result[0].length); + skipIndex = 0; + this.step++; + } + + } + + packStep(code: string) { + const compiled = new this.functionConstructor(...StepParser.params, ` + var { ${StepParser.deconstructs.join(", ")} } = event; + var { ${StepParser.topVars.join(", ")} } = topVars; + + ${this.stepHead} + { + ${code} + } + `); + ErrorManager.setCodeSnippet(compiled, new CodeSnippet(code, 3)); // 记录编译后函数的原代码片段 + this.originals.push(compiled); + this.contents.push(function (event, trigger, player) { + //@ts-ignore + return compiled.apply(this, [{ _status, ai, game, get, lib, ui }, event, trigger, player]); + }); + } + + formatFunction(func: Function) { + // 沙盒在封装函数时,为了保存源代码会另外存储函数的源代码 + const decompileFunction: (func: Function) => string = + security.isSandboxRequired() + ? security.importSandbox().Marshal.decompileFunction + : Function.prototype.call.bind(Function.prototype.toString); + + //移除所有注释 + const code = decompileFunction(func) + .replace(/((?:(?:^[ \t]*)?(?:\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\/(?:[ \t]*\r?\n(?=[ \t]*(?:\r?\n|\/\*|\/\/)))?|\/\/(?:[^\\]|\\(?:\r?\n)?)*?(?:\r?\n(?=[ \t]*(?:\r?\n|\/\*|\/\/))|(?=\r?\n))))+)|("(?:\\[\s\S]|[^"\\])*"|'(?:\\[\s\S]|[^'\\])*'|(?:\r?\n|[\s\S])[^/"'\\\s]*)/gm, "$2") + .trim(); + + //移除两边括号 + return code + .slice(0, code.lastIndexOf("}")) + .slice(code.indexOf("{") + 1) + .trim(); + } + + replaceDebugger() { + let regex = /event\.debugger\(\)/; + // let hasDebugger = false; + let insertDebugger = `await event.debugger()`; // yield code=>eval(code) 唔唔不是我干的喵 + let debuggerSkip = 0; + let debuggerResult: RegExpMatchArray | null; + + while ((debuggerResult = this.str.slice(debuggerSkip).match(regex)) != null) { + if (debuggerResult.index == null) + throw new Error("匹配到了debugger但是没有索引值"); + + let debuggerCopy = this.str; + debuggerCopy = debuggerCopy.slice(0, debuggerSkip + debuggerResult.index) + insertDebugger + debuggerCopy.slice(debuggerSkip + debuggerResult.index + debuggerResult[0].length, -1); + try { + new this.functionConstructor(debuggerCopy); + this.str = debuggerCopy + "}"; + debuggerSkip += debuggerResult.index + insertDebugger.length; + // hasDebugger = true; + } catch (error) { + debuggerSkip += debuggerResult.index + debuggerResult[0].length; + } + } + } +} \ No newline at end of file diff --git a/noname/library/element/GameEvent/compilers/YieldCompiler.js b/noname/library/element/GameEvent/compilers/YieldCompiler.js new file mode 100644 index 0000000000..41e74c4fc2 --- /dev/null +++ b/noname/library/element/GameEvent/compilers/YieldCompiler.js @@ -0,0 +1,43 @@ +import { _status, ai, game, get, lib, ui } from "../../../../../noname.js"; +import ContentCompilerBase from "./ContentCompilerBase.js"; +import { GameEvent } from "../../gameEvent.js"; +export default class YieldCompiler extends ContentCompilerBase { + type = "yield"; + static #mapArgs(event) { + const { step, source, target, targets, card, cards, skill, forced, num, _result, _trigger, player } = event; + return { + event, step, source, player, + target, targets, card, cards, skill, + forced, num, trigger: _trigger, + result: _result, + _status, lib, game, ui, get, ai, + }; + } + filter(content) { + return typeof content === "function" && content.constructor.name === "GeneratorFunction"; + } + compile(content) { + const compiler = this; + return async function (event) { + const args = YieldCompiler.#mapArgs(event); + //@ts-ignore + const generator = Reflect.apply(content, this, [event, args]); + let result = null; + let done = false; + while (!event.finished) { + if (done) { + event.finish(); + break; + } + let value = null; + compiler.beforeExecute(event); + if (!compiler.isPrevented(event)) + ({ value, done = false } = generator.next(result)); + await event.waitNext(); + result = value instanceof GameEvent ? value.result : value; + compiler.afterExecute(event); + } + generator.return(); + }; + } +} diff --git a/noname/library/element/GameEvent/compilers/YieldCompiler.ts b/noname/library/element/GameEvent/compilers/YieldCompiler.ts new file mode 100644 index 0000000000..c5256cafd1 --- /dev/null +++ b/noname/library/element/GameEvent/compilers/YieldCompiler.ts @@ -0,0 +1,59 @@ +import { EventContent, GameEvent } from "./IContentCompiler.ts"; +import { _status, ai, game, get, lib, ui } from "../../../../../noname.js"; +import ContentCompilerBase from "./ContentCompilerBase.ts"; + +export default class YieldCompiler extends ContentCompilerBase { + type = "yield"; + static #mapArgs(event: GameEvent): Record { + const { + step, source, target, targets, + card, cards, skill, forced, + num, _result, _trigger, player + } = event; + + return { + event, step, source, player, + target, targets, card, cards, skill, + forced, num, trigger: _trigger, + result: _result, + _status, lib, game, ui, get, ai, + }; + } + + filter(content: EventContent): boolean { + return typeof content === "function" && content.constructor.name === "GeneratorFunction"; + } + + compile(content: EventContent) { + const compiler = this; + return async function(event: GameEvent) { + const args = YieldCompiler.#mapArgs(event); + const generator: Generator = + //@ts-ignore + Reflect.apply(content as GeneratorFunction, this, [event, args]); + + let result: any = null; + let done: boolean = false; + + while (!event.finished) { + if (done) { + event.finish(); + break; + } + let value: any = null; + + compiler.beforeExecute(event); + + if (!compiler.isPrevented(event)) + ({ value, done = false } = generator.next(result)); + + await event.waitNext(); + result = value instanceof GameEvent ? value.result : value; + + compiler.afterExecute(event); + } + + generator.return(); + }; + } +} diff --git a/noname/library/element/card.js b/noname/library/element/card.js index d793cb1bfc..526fefce79 100644 --- a/noname/library/element/card.js +++ b/noname/library/element/card.js @@ -104,6 +104,12 @@ export class Card extends HTMLDivElement { * @type { boolean } */ isCard; + /** + * @type { string[] } + * 卡牌“占用的装备栏” + * TODO: 补充对应的typings + */ + subtypes; //执行销毁一张牌的钩子函数 selfDestroy(event) { if (this._selfDestroyed) return; @@ -891,11 +897,20 @@ export class Card extends HTMLDivElement { } /** * 返回一个键值,用于在缓存中作为键名。 - * + * @param { boolean } [similar] false统一前缀 * @returns {string} cacheKey */ - getCacheKey() { - return `[c:${this.cardid}]`; + getCacheKey(similar) { + let prefix = "[object:"; + if (similar !== false) prefix = "[card:"; + if (this.cardid) return prefix + this.cardid + "]"; + return prefix + `${this.name}+${ + this.suit ? this.suit : "none" + }+${ + this.number === undefined ? "none" : this.number + }${ + this.nature ? "+" + this.nature : "" + }]`; } discard(bool) { if (!this._selfDestroyed) { diff --git a/noname/library/element/content.js b/noname/library/element/content.js index 378777eaae..1bb6f7f5f3 100644 --- a/noname/library/element/content.js +++ b/noname/library/element/content.js @@ -8,8 +8,8 @@ import { gnc } from "../../gnc/index.js"; // 未来再改 export const Content = { - emptyEvent: () => { - event.trigger(event.name); + emptyEvent: async event => { + await event.trigger(event.name); }, //变更武将牌 async changeCharacter(event, trigger, player) { @@ -33,41 +33,23 @@ export const Content = { let rawName = rawPairs[i], newName = newPairs[i]; if (rawName != newName) { - game.log( - player, - `将${i == 0 ? "主" : "副"}将从`, - `#b${get.translation(rawName)}`, - "变更为了", - `#b${get.translation(newName)}` - ); + game.log(player, `将${i == 0 ? "主" : "副"}将从`, `#b${get.translation(rawName)}`, "变更为了", `#b${get.translation(newName)}`); } } } else if (rawPairs.length == 1 && newPairs.length == 2) { - game.log( - player, - "将单将", - `#b${get.translation(rawPairs[0])}`, - "变更为了双将", - `#b${get.translation(newPairs[0])}+${get.translation(newPairs[1])}` - ); + game.log(player, "将单将", `#b${get.translation(rawPairs[0])}`, "变更为了双将", `#b${get.translation(newPairs[0])}+${get.translation(newPairs[1])}`); } else if (rawPairs.length == 2 && newPairs.length == 1) { - game.log( - player, - "将双将", - `#b${get.translation(rawPairs[0])}+${get.translation(rawPairs[1])}`, - "变更为了单将", - `#b${get.translation(newPairs[0])}` - ); + game.log(player, "将双将", `#b${get.translation(rawPairs[0])}+${get.translation(rawPairs[1])}`, "变更为了单将", `#b${get.translation(newPairs[0])}`); } } //确定要失去和获得的技能 //失去技能时全部失去,但获得技能时,非主公角色不能获得主公技。 - rawPairs.forEach((name) => { + rawPairs.forEach(name => { removeSkills.addArray(lib.character[name][3]); }); - newPairs.forEach((name) => { + newPairs.forEach(name => { addSkills.addArray( - lib.character[name][3].filter((skill) => { + lib.character[name][3].filter(skill => { const info = get.info(skill); if (!info || (info.zhuSkill && !player.isZhu2())) return false; return true; @@ -92,10 +74,7 @@ export const Content = { newGroups = get.is.double(player.name2, true) || [get.character(player.name2, 1)]; } if (newGroups.length > 1) { - const newGroup = await player - .chooseControl(newGroups) - .set("prompt", "请选择一个新的势力") - .forResult("control"); + const newGroup = await player.chooseControl(newGroups).set("prompt", "请选择一个新的势力").forResult("control"); if (newGroup != player.group) { await player.changeGroup(newGroup); } @@ -112,8 +91,8 @@ export const Content = { event.addSkill.unique(); event.removeSkill.unique(); //避免失去还没拥有的技能 - event.removeSkill = event.removeSkill.filter((skill) => ownedSkills.includes(skill)); - const duplicatedSkills = event.addSkill.filter((skill) => event.removeSkill.includes(skill)); + event.removeSkill = event.removeSkill.filter(skill => ownedSkills.includes(skill)); + const duplicatedSkills = event.addSkill.filter(skill => event.removeSkill.includes(skill)); if (duplicatedSkills.length) { event.addSkill.removeArray(duplicatedSkills); event.removeSkill.removeArray(duplicatedSkills); @@ -131,9 +110,11 @@ export const Content = { game.log( player, "获得了技能", - ...event.addSkill.filter(i => i in lib.translate).map((i) => { - return "#g【" + get.translation(i) + "】"; - }) + ...event.addSkill + .filter(i => i in lib.translate) + .map(i => { + return "#g【" + get.translation(i) + "】"; + }) ); } if (event.removeSkill.length) { @@ -141,9 +122,11 @@ export const Content = { game.log( player, "失去了技能", - ...event.removeSkill.filter(i => i in lib.translate).map((i) => { - return "#g【" + get.translation(i) + "】"; - }) + ...event.removeSkill + .filter(i => i in lib.translate) + .map(i => { + return "#g【" + get.translation(i) + "】"; + }) ); } } @@ -154,11 +137,10 @@ export const Content = { //增加明置手牌 addShownCards: () => { const hs = player.getCards("h"), - showingCards = event._cards.filter((showingCard) => hs.includes(showingCard)), + showingCards = event._cards.filter(showingCard => hs.includes(showingCard)), shown = player.getShownCards(); - event.gaintag.forEach((tag) => player.addGaintag(showingCards, tag)); - if (!(event.cards = showingCards.filter((showingCard) => !shown.includes(showingCard))).length) - return; + event.gaintag.forEach(tag => player.addGaintag(showingCards, tag)); + if (!(event.cards = showingCards.filter(showingCard => !shown.includes(showingCard))).length) return; game.log(player, "明置了", event.cards); //if (event.animate != false) player.$give(event.cards, player, false); event.trigger("addShownCardsAfter"); @@ -166,19 +148,19 @@ export const Content = { //隐藏明置手牌 hideShownCards: () => { var shown = player.getShownCards(), - hidingCards = event._cards.filter((hidingCard) => shown.includes(hidingCard)); + hidingCards = event._cards.filter(hidingCard => shown.includes(hidingCard)); if (!hidingCards.length) return; - if (event.gaintag.length) event.gaintag.forEach((tag) => player.removeGaintag(tag, hidingCards)); + if (event.gaintag.length) event.gaintag.forEach(tag => player.removeGaintag(tag, hidingCards)); else { var map = hidingCards.reduce((constructingMap, hidingCard) => { - hidingCard.gaintag.forEach((tag) => { + hidingCard.gaintag.forEach(tag => { if (!tag.startsWith("visible_")) return; if (!constructingMap[tag]) constructingMap[tag] = []; constructingMap[tag].push(hidingCard); }); return constructingMap; }, {}); - Object.keys(map).forEach((key) => player.removeGaintag(key, map[key])); + Object.keys(map).forEach(key => player.removeGaintag(key, map[key])); } hidingCards.removeArray(player.getShownCards()); if (!hidingCards.length) return; @@ -188,6 +170,7 @@ export const Content = { }, //Execute the delay card effect //执行延时锦囊牌效果 + //TODO: 修改此处的虚拟牌/实体牌判断 executeDelayCardEffect: () => { "step 0"; target.$phaseJudge(card); @@ -281,7 +264,7 @@ export const Content = { player.$give(card, target, false); game.delay(0.5); event.trigger("giftAccept"); - if (get.type(card, false) == "equip") target.equip(card).log = false; + if (get.type(card) == "equip") target.equip(card).log = false; else target.gain(card, player).visible = true; event.trigger("giftAccepted"); "step 3"; @@ -297,7 +280,7 @@ export const Content = { event.trigger("recastingLose"); event.recastingLose(player, cards); event.trigger("recastingLost"); - event.recastingLosingEvents.push(...event.next.filter((value) => value.name != "arrangeTrigger")); + event.recastingLosingEvents.push(...event.next.filter(value => value.name != "arrangeTrigger")); "step 1"; event.trigger("recast"); "step 2"; @@ -305,7 +288,7 @@ export const Content = { event.trigger("recastingGain"); event.recastingGain(player, cards); event.trigger("recastingGained"); - event.recastingGainingEvents.push(...event.next.filter((value) => value.name != "arrangeTrigger")); + event.recastingGainingEvents.push(...event.next.filter(value => value.name != "arrangeTrigger")); }, //装备栏相关 disableEquip: function () { @@ -314,7 +297,7 @@ export const Content = { event.num = 0; event.slotsx = []; if (get.is.mountCombined()) { - event.slots.forEach((type) => { + event.slots.forEach(type => { if (type == "equip3" || type == "equip4") event.slotsx.add("equip3_4"); else event.slotsx.add(type); }); @@ -329,10 +312,7 @@ export const Content = { var left = player.countEnabledSlot(slot), lose; if (slot == "equip3_4") { - lose = Math.min( - left, - Math.max(get.numOf(event.slots, "equip3"), get.numOf(event.slots, "equip4")) - ); + lose = Math.min(left, Math.max(get.numOf(event.slots, "equip3"), get.numOf(event.slots, "equip4"))); slot_key = "equip3"; } else lose = Math.min(left, get.numOf(event.slots, slot)); if (lose <= 0) event.goto(3); @@ -341,7 +321,7 @@ export const Content = { if (!player.disabledSlots) player.disabledSlots = {}; if (!player.disabledSlots[slot_key]) player.disabledSlots[slot_key] = 0; player.disabledSlots[slot_key] += lose; - var cards = player.getEquips(slot).filter((card) => !event.cards.includes(card)); + var cards = player.getEquips(slot).filter(card => !event.cards.includes(card)); if (cards.length > 0) { if (lose >= left) { event._result = { bool: true, links: cards }; @@ -350,32 +330,12 @@ export const Content = { num = cards.length - (left - lose); if (!source || !source.isIn()) source = player; source - .chooseButton( - [ - "选择" + - (player == source ? "你" : get.translation(player)) + - "的" + - get.cnNumber(num) + - "张" + - get.translation(slot) + - "牌置入弃牌堆", - cards, - ], - true, - [1, num] - ) + .chooseButton(["选择" + (player == source ? "你" : get.translation(player)) + "的" + get.cnNumber(num) + "张" + get.translation(slot) + "牌置入弃牌堆", cards], true, [1, num]) .set("filterOk", function () { var evt = _status.event; return ( ui.selected.buttons.reduce(function (num, button) { - if (evt.slot == "equip3_4") - return ( - num + - Math.max( - get.numOf(get.subtypes(button.link, false), "equip3"), - get.numOf(get.subtypes(button.link, false), "equip4") - ) - ); + if (evt.slot == "equip3_4") return num + Math.max(get.numOf(get.subtypes(button.link, false), "equip3"), get.numOf(get.subtypes(button.link, false), "equip4")); return num + get.numOf(get.subtypes(button.link, false), evt.slot); }, 0) == evt.required ); @@ -415,7 +375,7 @@ export const Content = { if (!event.slots.length) return; var slotsx = []; if (get.is.mountCombined()) { - event.slots.forEach((type) => { + event.slots.forEach(type => { if (type == "equip3" || type == "equip4") slotsx.add("equip3_4"); else slotsx.add(type); }); @@ -430,11 +390,7 @@ export const Content = { expand = Math.max(get.numOf(event.slots, "equip3"), get.numOf(event.slots, "equip4")); slot_key = "equip3"; } - game.log( - player, - "获得了" + get.cnNumber(expand) + "个额外的", - "#g" + get.translation(slot) + "栏" - ); + game.log(player, "获得了" + get.cnNumber(expand) + "个额外的", "#g" + get.translation(slot) + "栏"); if (!player.expandedSlots) player.expandedSlots = {}; if (!player.expandedSlots[slot_key]) player.expandedSlots[slot_key] = 0; player.expandedSlots[slot_key] += expand; @@ -442,7 +398,81 @@ export const Content = { player.$syncExpand(); }, //选择顶装备要顶的牌 - replaceEquip: function () { + replaceEquip: async function (event, trigger, player) { + const vcards = event.vcards ?? [event.card]; + const specializedVCards = [], + normalVCards = []; + const replacedCards = []; + vcards.forEach(card => { + const info = get.info(card, false); + (info.customSwap ? specializedVCards : normalVCards).push(card); + }); + specializedVCards.forEach(card => { + const info = get.info(card, false); + replacedCards.addArray(player.getVCards("e", card => info.customSwap(card))); + }); + const types = normalVCards.reduce((types, card) => { + return types.concat(get.subtypes(card, false)); + }, []); + if (types.length > 0) { + const slots = types, + slotsx = []; + if (get.is.mountCombined()) { + slots.forEach(type => { + if (type == "equip3" || type == "equip4") slotsx.add("equip3_4"); + else slotsx.add(type); + }); + } else { + slotsx.addArray(slots); + } + slotsx.sort(); + for (const slot of slotsx) { + let left = player.countEquipableSlot(slot), + lose; + if (slot == "equip3_4") lose = Math.min(left, Math.max(get.numOf(slots, "equip3"), get.numOf(slots, "equip4"))); + else lose = Math.min(left, get.numOf(slots, slot)); + let result; + if (lose <= 0) continue; + else { + const cards = player.getVEquips(slot).filter(card => { + return !replacedCards.includes(card) && lib.filter.canBeReplaced(card, player); + }); + if (cards.length > 0) { + if (lose >= left) { + result = { bool: true, links: cards }; + } else if (cards.length > left - lose) { + var source = event.source, + num = cards.length - (left - lose); + if (!source || !source.isIn()) source = player; + const chooseEvent = source + .chooseButton(["选择替换掉" + get.cnNumber(num) + "张" + get.translation(slot) + "装备牌", [cards, "vcard"]], true, [1, num]) + .set("filterOk", function () { + var evt = _status.event; + return ( + ui.selected.buttons.reduce(function (num, button) { + if (evt.slot == "equip3_4") return num + Math.max(get.numOf(get.subtypes(button.link, false), "equip3"), get.numOf(get.subtypes(button.link, false), "equip4")); + return num + get.numOf(get.subtypes(button.link, false), evt.slot); + }, 0) == evt.required + ); + }) + .set("required", num) + .set("slot", slot); + result = await chooseEvent.forResult(); + } + } + } + if (result?.links) replacedCards.addArray(result.links); + } + } + event.result = { + vcards: replacedCards, + cards: replacedCards.reduce((cards, vcard) => { + if (vcard.cards) cards.addArray(vcard.cards); + return cards; + }, []), + }; + }, + replaceEquip_old: function () { "step 0"; event.cards = []; var types = get.subtypes(card, false); @@ -460,7 +490,7 @@ export const Content = { event.slots = types; event.slotsx = []; if (get.is.mountCombined()) { - event.slots.forEach((type) => { + event.slots.forEach(type => { if (type == "equip3" || type == "equip4") event.slotsx.add("equip3_4"); else event.slotsx.add(type); }); @@ -474,15 +504,11 @@ export const Content = { var slot = event.slotsx[event.num]; var left = player.countEquipableSlot(slot), lose; - if (slot == "equip3_4") - lose = Math.min( - left, - Math.max(get.numOf(event.slots, "equip3"), get.numOf(event.slots, "equip4")) - ); + if (slot == "equip3_4") lose = Math.min(left, Math.max(get.numOf(event.slots, "equip3"), get.numOf(event.slots, "equip4"))); else lose = Math.min(left, get.numOf(event.slots, slot)); if (lose <= 0) event.goto(3); else { - var cards = player.getEquips(slot).filter((card) => { + var cards = player.getEquips(slot).filter(card => { return !event.cards.includes(card) && lib.filter.canBeReplaced(card, player); }); if (cards.length > 0) { @@ -493,23 +519,12 @@ export const Content = { num = cards.length - (left - lose); if (!source || !source.isIn()) source = player; source - .chooseButton( - ["选择替换掉" + get.cnNumber(num) + "张" + get.translation(slot) + "牌", cards], - true, - [1, num] - ) + .chooseButton(["选择替换掉" + get.cnNumber(num) + "张" + get.translation(slot) + "牌", cards], true, [1, num]) .set("filterOk", function () { var evt = _status.event; return ( ui.selected.buttons.reduce(function (num, button) { - if (evt.slot == "equip3_4") - return ( - num + - Math.max( - get.numOf(get.subtypes(button.link, false), "equip3"), - get.numOf(get.subtypes(button.link, false), "equip4") - ) - ); + if (evt.slot == "equip3_4") return num + Math.max(get.numOf(get.subtypes(button.link, false), "equip3"), get.numOf(get.subtypes(button.link, false), "equip4")); return num + get.numOf(get.subtypes(button.link, false), evt.slot); }, 0) == evt.required ); @@ -528,7 +543,204 @@ export const Content = { event.result = cards; }, //装备牌 - equip: function () { + equip: async function (event, trigger, player) { + event.visible = true; + if (event.vcards && !event.cards) { + event.cards = event.vcards.reduce((cards, vcard) => { + if (vcard.cards) cards.addArray(vcard.cards); + return cards; + }, []); + } + //进行第一轮先行判断,让所有装备牌的原主失去装备牌 + if (event.cards) { + const map = {}; + for (const i of event.cards) { + var owner = get.owner(i, "judge"); + if (owner && (owner != player || get.position(i) != "e")) { + var id = owner.playerid; + if (!map[id]) map[id] = [[], [], []]; + map[id][0].push(i); + var position = get.position(i); + if (position == "h") map[id][1].push(i); + else map[id][2].push(i); + } else if (!event.updatePile && get.position(i) == "c") event.updatePile = true; + if (event.visible) i.addKnower("everyone"); + } + event.losing_map = map; + for (const i in map) { + const owner = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; + const next = owner.lose(map[i][0], ui.special).set("type", "equip").set("forceDie", true).set("getlx", false); + if (event.visible == true) { + // @ts-ignore + next.visible = true; + } + await next; + event.relatedLose = next; + } + } + player.equiping = true; + const handleEquip = async card => { + let cards = []; + // @ts-ignore + if (get.itemtype(card) === "card") { + cards = [card]; + card = get.autoViewAs(card, void 0, false); + } else { + cards = card.cards ?? []; + } + let cardInfo = get.info(card, false); + if (player.isMin() || !player.canEquip(card)) { + await game.cardsDiscard(cards); + delete player.equiping; + return; + } + let audioSubtype = get.subtype(card); + if (audioSubtype == "equip6") audioSubtype = "equip3"; + // @ts-ignore + game.broadcastAll(type => { + if (lib.config.background_audio) { + // @ts-ignore + game.playAudio("effect", type); + } + }, audioSubtype); + player.addVirtualEquip(card, cards); + //player.$equip(card); + //game.addVideo("equip", player, get.cardInfo(card)); + if (event.log != false) { + const isViewAsCard = cards.length !== 1 || cards[0].name !== card.name; + if (isViewAsCard && cards.length) { + game.log(player, '装备了' + get.translation(card) + "(", cards, ")"); + } else { + game.log(player, "装备了", card); + } + } + if (cardInfo.onEquip && (!cardInfo.filterEquip || cardInfo.filterEquip(card, player))) { + if (Array.isArray(cardInfo.onEquip)) { + for (var i = 0; i < cardInfo.onEquip.length; i++) { + var next = game.createEvent("equip_" + card.name); + next.setContent(cardInfo.onEquip[i]); + next.player = player; + next.card = card; + await next; + } + } else { + var next = game.createEvent("equip_" + card.name); + next.setContent(cardInfo.onEquip); + next.player = player; + next.card = card; + await next; + } + if (cardInfo.equipDelay != false) await game.delayx(); + } + delete player.equiping; + if (event.delay) { + await game.delayx(); + } + }; + //生成虚拟牌列表 + if (!event.vcards) { + if (event.card) { + // @ts-ignore + if (get.itemtype(event.card) === "card") event.card = get.autoViewAs(event.card, void 0, false); + event.vcards = [event.card]; + } else event.vcards = event.cards.map(card => get.autoViewAs(card, void 0, false)); + } + //过滤被销毁的装备牌 + event.vcards = event.vcards.filter(card => { + let cards; + // @ts-ignore + if (get.itemtype(card) === "card") { + cards = [card]; + card = get.autoViewAs(card); + } else { + cards = card.cards ?? []; + } + let canMoveOn = true; + cards.forEach(card => { + if (card.willBeDestroyed("equip", player, event)) { + card.selfDestroy(event); + canMoveOn = false; + return; + } else if (canMoveOn) { + // @ts-ignore + if ("hejx".includes(get.position(card, true))) { + canMoveOn = false; + return; + } + } + }); + return canMoveOn; + }); + event.cards = event.vcards.reduce((cards, vcard) => { + if (vcard.cards) cards.addArray(vcard.cards); + return cards; + }, []); + //同时播放所有装备牌的装备动画 + if (event.cards.length) { + if (event.draw) { + player.$draw(event.cards); + await game.delay(0, 300); + } else { + // @ts-ignore + game.broadcast( + function (cards, player) { + cards.forEach(card => { + if (card.clone) { + card.clone.moveDelete(player); + } + }); + }, + event.cards, + player + ); + event.cards.forEach(card => { + if (card.clone) { + card.clone.moveDelete(player); + game.addVideo("gain2", player, get.cardsInfo([card.clone])); + } + }); + } + } + //将多张装备牌的牌替换事件合并为一个,废弃卡牌的replaceEquip自定义事件属性(反正没人用) + const replaceEquipEvent = game.createEvent("replaceEquip"); + replaceEquipEvent.player = player; + // @ts-ignore + replaceEquipEvent.vcards = event.vcards; + replaceEquipEvent.setContent("replaceEquip"); + const result = await replaceEquipEvent.forResult(); + // @ts-ignore + if (get.itemtype(result?.cards) == "cards") { + // @ts-ignore + event.swapped = true; + const loseEvent = player.lose(result.cards, "visible").set("type", "equip").set("getlx", false); + loseEvent.swapEquip = true; + if ( + event.vcards.some(card => { + const info = get.info(card, false); + return info && info.loseThrow; + }) + ) { + player.$throw(result.cards, 1000); + } + await loseEvent; + // @ts-ignore + for (let card of result.cards) { + if (card.willBeDestroyed("discardPile", player, event)) { + card.selfDestroy(event); + } + } + } + result?.vcards?.forEach(card => { + player.removeVirtualEquip(card); + }); + //然后处理每一张装备牌的装备 + for (const card of event.vcards) { + event.card = card; + await handleEquip(card); + } + if (event.updatePile) game.updateRoundNumber(); + }, + equip_old: function () { "step 0"; var owner = get.owner(card); if (owner) { @@ -595,9 +807,9 @@ export const Content = { "step 6"; //if(player.isMin() || player.countCards('e',{subtype:get.subtype(card)})){ if (player.isMin() || !player.canEquip(card)) { - event.finish(); game.cardsDiscard(card); delete player.equiping; + event.finish(); return; } var subtype = get.subtype(card); @@ -771,12 +983,7 @@ export const Content = { var opinion = null; if (event.red.length > event.black.length) opinion = "red"; else if (event.red.length < event.black.length) opinion = "black"; - if (opinion) - game.log( - player, - "本次发起的议事结果为", - opinion == "red" ? '红色' : "#g黑色" - ); + if (opinion) game.log(player, "本次发起的议事结果为", opinion == "red" ? '红色' : "#g黑色"); else game.log(player, "本次发起的议事无结果"); event.result = { bool: true, @@ -798,10 +1005,7 @@ export const Content = { }, chooseCooperationFor: function () { "step 0"; - var next = player.chooseButton( - ["选择和" + get.translation(target) + "的协力方式", [event.cardlist, "vcard"]], - true - ); + var next = player.chooseButton(["选择和" + get.translation(target) + "的协力方式", [event.cardlist, "vcard"]], true); next.set( "ai", event.ai || @@ -822,15 +1026,7 @@ export const Content = { //给其他角色看的演奏框 game.broadcastAll( function (player, id, beatmap) { - if (_status.connectMode) - lib.configOL.choose_timeout = ( - Math.ceil( - (beatmap.timeleap[beatmap.timeleap.length - 1] + - beatmap.speed * 100 + - (beatmap.current || 0)) / - 1000 - ) + 5 - ).toString(); + if (_status.connectMode) lib.configOL.choose_timeout = (Math.ceil((beatmap.timeleap[beatmap.timeleap.length - 1] + beatmap.speed * 100 + (beatmap.current || 0)) / 1000) + 5).toString(); if (player == game.me) return; var str = get.translation(player) + "正在演奏《" + beatmap.name + "》..."; if (!_status.connectMode) str += "
        (点击屏幕可以跳过等待AI操作)"; @@ -891,11 +1087,7 @@ export const Content = { //建个框框 var dialog = ui.create.dialog("forcebutton", "hidden"); event.dialog = dialog; - event.dialog.textPrompt = event.dialog.add( - '
        ' + - (beatmap.prompt || "在音符滑条和底部判定区重合时点击屏幕!") + - "
        " - ); + event.dialog.textPrompt = event.dialog.add('
        ' + (beatmap.prompt || "在音符滑条和底部判定区重合时点击屏幕!") + "
        "); event.switchToAuto = function () {}; event.dialog.classList.add("fixed"); event.dialog.classList.add("scroll1"); @@ -910,11 +1102,9 @@ export const Content = { event.settleed = true; //评分 var acc = Math.floor((score / (added * 5)) * 100); - if (!Array.isArray(lib.config.choose_to_play_beatmap_accuracies)) - lib.config.choose_to_play_beatmap_accuracies = []; + if (!Array.isArray(lib.config.choose_to_play_beatmap_accuracies)) lib.config.choose_to_play_beatmap_accuracies = []; lib.config.choose_to_play_beatmap_accuracies.push(acc); - if (lib.config.choose_to_play_beatmap_accuracies.length > 5) - lib.config.choose_to_play_beatmap_accuracies.shift(); + if (lib.config.choose_to_play_beatmap_accuracies.length > 5) lib.config.choose_to_play_beatmap_accuracies.shift(); game.saveConfigValue("choose_to_play_beatmap_accuracies"); var rank; if (acc == 100) rank = ["SS", "metal"]; @@ -923,22 +1113,8 @@ export const Content = { else if (acc >= 80) rank = ["B", "water"]; else if (acc >= 65) rank = ["C", "thunder"]; else rank = ["D", "fire"]; - event.dialog.textPrompt.innerHTML = - '
        演奏结束!
        最大连击数:' + - max_combo + - " 精准度:" + - acc + - "%
        "; - game.me.$fullscreenpop( - '演奏评级:' + - rank[0] + - "", - null, - null, - false - ); + event.dialog.textPrompt.innerHTML = '
        演奏结束!
        最大连击数:' + max_combo + " 精准度:" + acc + "%
        "; + game.me.$fullscreenpop('演奏评级:' + rank[0] + "", null, null, false); //返回结果并继续游戏 setTimeout(function () { event._result = { @@ -964,8 +1140,7 @@ export const Content = { var speed = beatmap.speed || 25; //初始化底部的条子 var judger = ui.create.div(""); - judger.style["background-image"] = - beatmap.judgebar_color || "linear-gradient(rgba(240, 235, 3, 1), rgba(230, 225, 5, 1))"; + judger.style["background-image"] = beatmap.judgebar_color || "linear-gradient(rgba(240, 235, 3, 1), rgba(230, 225, 5, 1))"; judger.style["border-radius"] = "3px"; judger.style.position = "absolute"; judger.style.opacity = "0.3"; @@ -979,8 +1154,7 @@ export const Content = { var addNode = function () { var node = ui.create.div(""); nodes.push(node); - node.style["background-image"] = - beatmap.node_color || "linear-gradient(rgba(120, 120, 240, 1), rgba(100, 100, 230, 1))"; + node.style["background-image"] = beatmap.node_color || "linear-gradient(rgba(120, 120, 240, 1), rgba(100, 100, 230, 1))"; node.style["border-radius"] = "3px"; node.style.position = "absolute"; node.style.height = Math.ceil(height / 10) + "px"; @@ -1024,9 +1198,12 @@ export const Content = { addNode(); }, getTimeout()); } else { - setTimeout(function () { - event.settle(); - }, speed * 110 + 100); + setTimeout( + function () { + event.settle(); + }, + speed * 110 + 100 + ); } }; //点击时的判断操作 @@ -1069,11 +1246,14 @@ export const Content = { game.pause(); game.countChoose(); - setTimeout(() => { - if (!lib.config.background_audio) return; - if (beatmap.filename.startsWith("ext:")) game.playAudio(beatmap.filename); - else game.playAudio("effect", beatmap.filename); - }, Math.floor(speed * 100 * (0.9 + beatmap.judgebar_height)) + beatmap.current); + setTimeout( + () => { + if (!lib.config.background_audio) return; + if (beatmap.filename.startsWith("ext:")) game.playAudio(beatmap.filename); + else game.playAudio("effect", beatmap.filename); + }, + Math.floor(speed * 100 * (0.9 + beatmap.judgebar_height)) + beatmap.current + ); setTimeout(function () { addNode(); }, getTimeout()); @@ -1086,9 +1266,7 @@ export const Content = { _status.imchoosing = false; //Algorithm: Generate the random number range using the mean and the half standard deviation of accuracies of the player's last 5 plays //算法:用玩家的上5次游玩的准确率的平均数和半标准差生成随机数范围 - var choose_to_play_beatmap_accuracies = ( - lib.config.choose_to_play_beatmap_accuracies || [] - ).concat( + var choose_to_play_beatmap_accuracies = (lib.config.choose_to_play_beatmap_accuracies || []).concat( Array.from( { length: 6 - (lib.config.choose_to_play_beatmap_accuracies || []).length, @@ -1096,32 +1274,9 @@ export const Content = { () => get.rand(70, 100) ) ); - var mean = Math.round( - choose_to_play_beatmap_accuracies.reduce( - (previousValue, currentValue) => previousValue + currentValue - ) / choose_to_play_beatmap_accuracies.length - ); - var half_standard_deviation = Math.round( - Math.sqrt( - choose_to_play_beatmap_accuracies.reduce( - (previousValue, currentValue) => previousValue + Math.pow(currentValue - mean, 2), - 0 - ) - ) / 2 - ); - var acc = Math.min( - Math.max( - get.rand.apply( - get, - beatmap.aiAcc || [ - mean - half_standard_deviation - get.rand(0, half_standard_deviation), - mean + half_standard_deviation + get.rand(0, half_standard_deviation), - ] - ), - 0 - ), - 100 - ); + var mean = Math.round(choose_to_play_beatmap_accuracies.reduce((previousValue, currentValue) => previousValue + currentValue) / choose_to_play_beatmap_accuracies.length); + var half_standard_deviation = Math.round(Math.sqrt(choose_to_play_beatmap_accuracies.reduce((previousValue, currentValue) => previousValue + Math.pow(currentValue - mean, 2), 0)) / 2); + var acc = Math.min(Math.max(get.rand.apply(get, beatmap.aiAcc || [mean - half_standard_deviation - get.rand(0, half_standard_deviation), mean + half_standard_deviation + get.rand(0, half_standard_deviation)]), 0), 100); var rank; if (acc == 100) rank = ["SS", "metal"]; else if (acc >= 94) rank = ["S", "orange"]; @@ -1138,33 +1293,21 @@ export const Content = { if (event.control) event.control.close(); game.resume(); }; - var song_duration = - beatmap.timeleap[beatmap.timeleap.length - 1] + - beatmap.speed * 100 + - 1000 + - (beatmap.current || 0); + var song_duration = beatmap.timeleap[beatmap.timeleap.length - 1] + beatmap.speed * 100 + 1000 + (beatmap.current || 0); var settle_timeout = setTimeout(settle, song_duration); if (!_status.connectMode) { var skip_timeout; var skip = () => { settle(); - Array.from(ui.window.getElementsByTagName("audio")).forEach((audio) => { - if ( - audio.currentSrc.includes( - beatmap.filename.startsWith("ext:") ? beatmap.name : beatmap.filename - ) - ) - audio.remove(); + Array.from(ui.window.getElementsByTagName("audio")).forEach(audio => { + if (audio.currentSrc.includes(beatmap.filename.startsWith("ext:") ? beatmap.name : beatmap.filename)) audio.remove(); }); document.removeEventListener(lib.config.touchscreen ? "touchend" : "click", skip); clearTimeout(settle_timeout); clearTimeout(skip_timeout); }; document.addEventListener(lib.config.touchscreen ? "touchend" : "click", skip); - skip_timeout = setTimeout( - () => document.removeEventListener(lib.config.touchscreen ? "touchend" : "click", skip), - song_duration - ); + skip_timeout = setTimeout(() => document.removeEventListener(lib.config.touchscreen ? "touchend" : "click", skip), song_duration); } } "step 2"; @@ -1226,15 +1369,36 @@ export const Content = { event.dialog.classList.add("fullheight"); } + /** + * @type { Card[][] } 保存每次移动后的对应实体牌的位置 + */ event.moved = []; + /** + * @type { HTMLDivElement[] } 所有可移动的buttons数组 + */ var buttonss = []; event.buttonss = buttonss; + /** + * 是否处于拖拽动画中(禁止其他的选择,拖拽) + */ + event.isPlayingAnimation = false; + // 初始化触摸点位置和元素偏移量 + var touchStartX = 0; + var touchStartY = 0; + var elementOffsetX = 0; + var elementOffsetY = 0; + var currentElement; + // 首次触发move事件的元素 + var firstOnDragElement; + /** + * 每次移动后更新数据 + */ var updateButtons = function () { for (var i of buttonss) { + // 更新每次移动后的对应实体牌的位置 event.moved[i._link] = get.links(Array.from(i.childNodes)); - if (i.textPrompt) - i.previousSibling.innerHTML = - '
        ' + i.textPrompt(event.moved[i._link]) + "
        "; + // 更新这个buttons的提示文本 + if (typeof i.textPrompt == 'function') i.previousSibling.innerHTML = '
        ' + i.textPrompt(event.moved[i._link]) + "
        "; } if (filterOk(event.moved)) { ui.create.confirm("o"); @@ -1243,20 +1407,214 @@ export const Content = { else if (ui.confirm) ui.confirm.close(); } }; - var clickButtons = function () { - if (!ui.selected.guanxing_button) return; - if (ui.selected.guanxing_button.parentNode == this) return; - if (!filterMove(ui.selected.guanxing_button, this._link, event.moved)) return; - ui.selected.guanxing_button.classList.remove("glow2"); - this.appendChild(ui.selected.guanxing_button); - delete ui.selected.guanxing_button; - updateButtons(); + + /** + * 确认是否是拖拽开始 + * + * 按下时,是不能判断出是否拖拽开始的,得在move事件才可以 + * + * @this buttons + * @param { TouchEvent | MouseEvent } e + */ + var dragStart = function(e) { + if (event.isPlayingAnimation) return; + // 左键按下 + if (e instanceof MouseEvent) { + if (e.which != 1) return; + } + // 单个手指按下 + if (window.TouchEvent && e instanceof TouchEvent) { + if (e.touches.length != 1) return; + } + // 判断按下的元素是否是card + var cards = Array.from(this.children); + var target = cards.find(card => { + // Node.contains() + return card.contains(e.target); + }); + if (target) { + if (!target.copy) { + target.copy = target.cloneNode(true); + target.copy.style.opacity = '0.5'; + target.copy.style.pointerEvents = 'none'; + } + touchStartX = (e instanceof MouseEvent ? e.clientX : e.touches[0].clientX) / game.documentZoom; + touchStartY = (e instanceof MouseEvent ? e.clientY : e.touches[0].clientY) / game.documentZoom; + elementOffsetX = target.offsetLeft - touchStartX; + elementOffsetY = target.offsetTop - touchStartY; + currentElement = target; + e.stopPropagation(); + } }; + /** + * 判断出是否拖拽开始 + * + * move事件是在button元素上监听的,而不是在dialog.content上。 + * + * @this dialog + * @param { TouchEvent | MouseEvent } e + */ + var onDrag = function(e) { + if (event.isPlayingAnimation) return; + if (e instanceof MouseEvent) { + if (e.which != 1) return; + } + if (window.TouchEvent && e instanceof TouchEvent) { + if (e.touches.length != 1) return; + } + if (!currentElement || !currentElement.copy) return; + if (!firstOnDragElement) { + if (!currentElement.contains(e.target)) { + return; + } + else { + firstOnDragElement = currentElement; + } + } + // 拖动离开了这个牌的区域,进行赋值 + // if (!currentElement.contains(e.target)) { + + // } + // 移除高亮 + ui.selected.guanxing_button?.classList.remove('glow2'); + ui.selected.guanxing_button = currentElement; + ui.selected.guanxing_button.classList.add("glow2"); + // 显示拖拽的元素 + /** + * @type { HTMLDivElement } + */ + var copy = currentElement.copy; + if (!ui.window.contains(copy)) { + copy.style.position = 'absolute'; + copy.style.transition = 'none'; + copy.style.zIndex = '100'; + ui.window.appendChild(copy); + } + copy.style.left = `${(e instanceof MouseEvent ? e.clientX : e.touches[0].clientX) / game.documentZoom}px`; + copy.style.top = `${(e instanceof MouseEvent ? e.clientY : e.touches[0].clientY) / game.documentZoom}px`; + }; + + var dragEnd = function(e) { + if (event.isPlayingAnimation) return; + if (e instanceof MouseEvent) { + if (e.which != 1) return; + } + if (window.TouchEvent && e instanceof TouchEvent) { + if (e.changedTouches.length != 1) return; + } + firstOnDragElement = null; + buttonss.forEach(btn => { + Array.from(btn.children).forEach(element => { + if (element.copy && ui.window.contains(element.copy)) { + ui.window.removeChild(element.copy); + } + }); + }); + if (!ui.selected.guanxing_button?.copy) return; + var clientX = (e instanceof MouseEvent ? e.clientX : e.changedTouches[0].clientX) / game.documentZoom; + var clientY = (e instanceof MouseEvent ? e.clientY : e.changedTouches[0].clientY) / game.documentZoom; + // 鼠标当前处于哪个元素上 + var target = document.elementFromPoint(clientX * game.documentZoom, clientY * game.documentZoom); + // 相当于没移动,让它自己触发后续的click + if (ui.selected.guanxing_button.contains(target)) return; + // 停止拖拽的目标处于哪个button区域中 + var button = buttonss.find(b => { + // Node.contains() + return b.contains(target); + }); + // 不能拖拽到区域外 + if (!button) return; + var children = Array.from(button.children); + // 与card交换位置 + var card = children.find(element => element.contains(target)); + // 判断是否可以移动 + if (!card) { + if (!filterMove(ui.selected.guanxing_button, button._link, event.moved)) return; + } + else { + if (!filterMove(card, ui.selected.guanxing_button, event.moved)) return; + } + // FLIP动画 + // first + buttonss.forEach(btn => { + Array.from(btn.children).forEach(element => { + element.style.transition = 'none'; + element._rect = element.getBoundingClientRect(); + }); + }); + // last + // 如果拖拽到一个空区域内 + if (!button.hasChildNodes()) { + button.appendChild(ui.selected.guanxing_button); + } + else if (!card) { + // 判断是加在第一个还是最后一个 + if (children.length > 0) { + var firstChild = children[0]; + if (clientX < firstChild.getBoundingClientRect().left / game.documentZoom) { + button.insertBefore(ui.selected.guanxing_button, firstChild); + } + else button.appendChild(ui.selected.guanxing_button); + } + else button.appendChild(ui.selected.guanxing_button); + } + else { + // 是交换而不是到card前面 + var par1 = ui.selected.guanxing_button.parentNode, + ind1 = ui.selected.guanxing_button.nextSibling, + par2 = card.parentNode, + ind2 = card.nextSibling; + ui.selected.guanxing_button.classList.remove("glow2"); + par1.insertBefore(card, ind1); + par2.insertBefore(ui.selected.guanxing_button, ind2); + } + // invert + buttonss.forEach(btn => { + Array.from(btn.children).forEach(element => { + element._rect2 = element.getBoundingClientRect(); + element.style.transform = + `translateX(${(element._rect.left - element._rect2.left) / game.documentZoom}px) translateY(${(element._rect.top - element._rect2.top) / game.documentZoom}px)`; + }); + }); + // play + event.isPlayingAnimation = true; + setTimeout(() => { + Promise.race([ + new Promise(resolve => setTimeout(resolve, 700)), + Promise.all(buttonss.map(btn => Array.from(btn.children)).flat(1).map(element => { + return new Promise(resolve => { + element.classList.remove("glow2"); + element.style.transition = ''; + const transformValue = element.style.transform; + if (transformValue !== 'translateX(0px) translateY(0px)' && transformValue !== '') { + element.style.transform = 'translateX(0px) translateY(0px)'; + element.addEventListener('transitionend', event => { + // 确保 transitionend 事件是针对当前元素的 transform 属性 + if (event.propertyName === 'transform') { + resolve(); + } + }, { once: true }); + } + else resolve(); + }) + })) + ]).then(() => { + delete ui.selected.guanxing_button; + event.isPlayingAnimation = false; + updateButtons(); + }); + }, 0); + }; + + // 根据数据创建区域 for (var i = 0; i < list.length; i++) { var tex = event.dialog.add('
        ' + list[i][0] + "
        "); tex.classList.add("choosetomove"); - var buttons = ui.create.div(".buttons", event.dialog.content, clickButtons); + var buttons = ui.create.div(".buttons", event.dialog.content); + buttons.addEventListener(lib.config.touchscreen ? 'touchstart' : 'mousedown', dragStart, true); + event.dialog.addEventListener(lib.config.touchscreen ? 'touchmove' : 'mousemove', onDrag, true); + event.dialog.addEventListener(lib.config.touchscreen ? 'touchend' : 'mouseup', dragEnd, true); buttonss.push(buttons); buttons.classList.add("popup"); buttons.classList.add("guanxing"); @@ -1273,15 +1631,14 @@ export const Content = { } if (list[i][2] && typeof list[i][2] == "function") buttons.textPrompt = list[i][2]; } - var tex = event.dialog.add( - '
        点击两张牌以交换位置;点击一张牌并点击其他区域以移动卡牌
        ' - ); + var tex = event.dialog.add('
        点击或拖动两张牌以交换位置;点击一张牌并点击其他区域或拖动到其他区域以移动卡牌
        '); tex.classList.add("choosetomove"); event.dialog.open(); updateButtons(); event.custom.replace.button = function (button) { + if (event.isPlayingAnimation) return; var node = button.parentNode; if (!buttonss.includes(node)) return; if (!ui.selected.guanxing_button) { @@ -1294,16 +1651,6 @@ export const Content = { delete ui.selected.guanxing_button; return; } - if (!filterMove(button, ui.selected.guanxing_button, event.moved)) return; - var par1 = ui.selected.guanxing_button.parentNode, - ind1 = ui.selected.guanxing_button.nextSibling, - par2 = button.parentNode, - ind2 = button.nextSibling; - ui.selected.guanxing_button.classList.remove("glow2"); - par1.insertBefore(button, ind1); - par2.insertBefore(ui.selected.guanxing_button, ind2); - delete ui.selected.guanxing_button; - updateButtons(); }; event.custom.replace.confirm = function (bool) { if (bool) @@ -1340,7 +1687,7 @@ export const Content = { if (moved) result = { bool: true, - moved: moved, + moved, }; else result = { bool: false }; } @@ -1366,10 +1713,7 @@ export const Content = { } let evt = event.getParent("chooseToUse"); if (get.itemtype(evt) !== "event") evt = event; - if ( - !lib.filter.cardEnabled(card, player) || - (event.addCount !== false && !lib.filter.cardUsable(card, player, evt)) - ) { + if (!lib.filter.cardEnabled(card, player) || (event.addCount !== false && !lib.filter.cardUsable(card, player, evt))) { event.result = { bool: false }; event.finish(); return; @@ -1389,14 +1733,7 @@ export const Content = { if (!event.filterTarget(card, player, targets[i])) { targets.splice(i--, 1); } - } else if ( - !player.canUse( - card, - targets[i], - event.nodistance ? false : null, - event.addCount === false ? null : true - ) - ) { + } else if (!player.canUse(card, targets[i], event.nodistance ? false : null, event.addCount === false ? null : true)) { targets.splice(i--, 1); } } @@ -1412,16 +1749,7 @@ export const Content = { return; } else { var next = player.chooseBool(); - next.set( - "prompt", - event.prompt || - "是否" + - (event.targets2.length ? "对" : "") + - get.translation(event.targets2) + - "使用" + - get.translation(card) + - "?" - ); + next.set("prompt", event.prompt || "是否" + (event.targets2.length ? "对" : "") + get.translation(event.targets2) + "使用" + get.translation(card) + "?"); if (event.hsskill) next.setHiddenSkill(event.hsskill); if (event.prompt2) next.set("prompt2", event.prompt2); next.ai = function () { @@ -1453,8 +1781,7 @@ export const Content = { event.filterTarget || function (card, player, target) { if (!_status.event.targets.includes(target)) return false; - if (!_status.event.nodistance && !lib.filter.targetInRange(card, player, target)) - return false; + if (!_status.event.nodistance && !lib.filter.targetInRange(card, player, target)) return false; return lib.filter.targetEnabledx(card, player, target); } ); @@ -1497,14 +1824,18 @@ export const Content = { chooseToDuiben: function () { "step 0"; if (!event.namelist) event.namelist = ["全军出击", "分兵围城", "奇袭粮道", "开城诱敌"]; - game.broadcastAll(function (list, translationList = []) { - var list2 = ["db_atk1", "db_atk2", "db_def1", "db_def2"]; - for (var i = 0; i < 4; i++) { - lib.card[list2[i]].image = "card/" + list2[i] + (list[0] == "全军出击" ? "" : "_" + list[i]); - lib.translate[list2[i]] = list[i]; - lib.translate[list2[i] + "_info"] = translationList[i]; - } - }, event.namelist, event.translationList); + game.broadcastAll( + function (list, translationList = []) { + var list2 = ["db_atk1", "db_atk2", "db_def1", "db_def2"]; + for (var i = 0; i < 4; i++) { + lib.card[list2[i]].image = "card/" + list2[i] + (list[0] == "全军出击" ? "" : "_" + list[i]); + lib.translate[list2[i]] = list[i]; + lib.translate[list2[i] + "_info"] = translationList[i]; + } + }, + event.namelist, + event.translationList + ); if (!event.title) event.title = "对策"; game.log(player, "向", target, "发起了", "#y" + event.title); if (!event.ai) @@ -1631,10 +1962,8 @@ export const Content = { dialog.close(); }, 1000); }, str); - game.trySkillAudio( - event.getParent().name + "_" + (event.result.bool ? "true" + mes : "false"), - player - ); + const skill = event.getParent().name + "_" + (event.result.bool ? "true" + mes : "false"); + game.trySkillAudio(skill, player, true, null, null, [event, event.player]); game.delay(2); "step 6"; game.broadcastAll(function () { @@ -1838,6 +2167,7 @@ export const Content = { next.setContent("orderingDiscard"); } if (!evt.noOrdering) evt.orderingCards.addArray(cards); + event.result = { cards }; }, cardsGotoSpecial: function () { game.getGlobalHistory().cardMove.push(event); @@ -1874,6 +2204,11 @@ export const Content = { game.getGlobalHistory().cardMove.push(event); if (!event._triggeronly) game.$cardsGotoPile(event); }, + /** + * @param {GameEventPromise} event + * @param {GameEventPromise} trigger + * @param {Player} player + */ chooseToEnable: async function (event, trigger, player) { var source = event.source; if (event.selectButton) { @@ -1884,7 +2219,7 @@ export const Content = { var realList = []; realList = list.filter(current => { if (player.hasDisabledSlot(current)) return true; - }) + }); if (!list.length) event.finish(); else if (event.selectButton[0] >= realList.length) { event.list = list; @@ -1897,29 +2232,21 @@ export const Content = { var selectButton = get.select(event.selectButton); if (selectButton[0] == selectButton[1]) { str += get.cnNumber(selectButton[0]); - } - else if (selectButton[1] == Infinity) { - str += "至少" + get.cnNumber(selectButton[0]) + } else if (selectButton[1] == Infinity) { + str += "至少" + get.cnNumber(selectButton[0]); } else { - str += get.cnNumber(selectButton[0]) + "至" + get.cnNumber(selectButton[1]) + str += get.cnNumber(selectButton[0]) + "至" + get.cnNumber(selectButton[1]); } str += "个装备栏"; - var next = source.chooseButton( - selectButton, - true, - [ - str, - [list, "tdnodes"], - ] - ); - next.set('filterButton', function(button){ - if (player.hasDisabledSlot(button.link))return true; - return false; - }) + var next = source.chooseButton(selectButton, true, [str, [list, "tdnodes"]]); + next.set("filterButton", function (button) { + if (player.hasDisabledSlot(button.link)) return true; + return false; + }); if (!event.ai) { event.ai = function () { return Math.random(); - } + }; } next.set("ai", event.ai); var result = await next.forResult(); @@ -1953,6 +2280,11 @@ export const Content = { await player.enableEquip(result.control); } }, + /** + * @param {GameEventPromise} event + * @param {GameEventPromise} trigger + * @param {Player} player + */ chooseToDisable: async function (event, trigger, player) { var source = event.source; if (event.selectButton) { @@ -1963,11 +2295,11 @@ export const Content = { var realList = []; realList = list.filter(current => { if (player.hasEnabledSlot(current)) return true; - }) + }); if (event.horse) { - if (list.includes("equip3") && (get.is.mountCombined() || list.includes("equip4"))){ + if (list.includes("equip3") && (get.is.mountCombined() || list.includes("equip4"))) { list.push("equip3_4"); - realList.push("equip3_4") + realList.push("equip3_4"); } list.remove("equip3", "equip4"); realList.remove("equip3", "equip4"); @@ -1984,29 +2316,21 @@ export const Content = { var selectButton = get.select(event.selectButton); if (selectButton[0] == selectButton[1]) { str += get.cnNumber(selectButton[0]); - } - else if (selectButton[1] == Infinity) { - str += "至少" + get.cnNumber(selectButton[0]) + } else if (selectButton[1] == Infinity) { + str += "至少" + get.cnNumber(selectButton[0]); } else { - str += get.cnNumber(selectButton[0]) + "至" + get.cnNumber(selectButton[1]) + str += get.cnNumber(selectButton[0]) + "至" + get.cnNumber(selectButton[1]); } str += "个装备栏"; - var next = source.chooseButton( - selectButton, - true, - [ - str, - [list, "tdnodes"], - ] - ); - next.set("filterButton", function(button){ + var next = source.chooseButton(selectButton, true, [str, [list, "tdnodes"]]); + next.set("filterButton", function (button) { if (player.hasEnabledSlot(button.link)) return true; - return false; - }) + return false; + }); if (!event.ai) { event.ai = function () { return Math.random(); - } + }; } next.set("ai", event.ai); var result = await next.forResult(); @@ -2025,8 +2349,7 @@ export const Content = { if (player.hasEnabledSlot(i)) list.push("equip" + i); } if (event.horse) { - if (list.includes("equip3") && (get.is.mountCombined() || list.includes("equip4"))) - list.push("equip3_4"); + if (list.includes("equip3") && (get.is.mountCombined() || list.includes("equip4"))) list.push("equip3_4"); list.remove("equip3"); list.remove("equip4"); } @@ -2061,19 +2384,18 @@ export const Content = { "step 0"; game.log(player, "和", target, "交换了装备区中的牌"); event.cards = [player.getCards("e"), target.getCards("e")]; + event.vcards = [player.getVCards("e"), target.getVCards("e")]; game.loseAsync({ player: player, target: target, cards1: event.cards[0], cards2: event.cards[1], + vcards1: event.vcards[0], + vcards2: event.vcards[1], }).setContent("swapHandcardsx"); "step 1"; - for (var i = 0; i < event.cards[1].length; i++) { - if (get.position(event.cards[1][i], true) == "o") player.equip(event.cards[1][i]); - } - for (var i = 0; i < event.cards[0].length; i++) { - if (get.position(event.cards[0][i], true) == "o") target.equip(event.cards[0][i]); - } + player.equip(event.vcards[1]); + target.equip(event.vcards[0]); }, disableJudge: function () { "step 0"; @@ -2130,11 +2452,7 @@ export const Content = { game.log(); game.log(player, "的回合开始"); player._noVibrate = true; - if ( - get.config("identity_mode") != "zhong" && - get.config("identity_mode") != "purple" && - !_status.connectMode - ) { + if (get.config("identity_mode") != "zhong" && get.config("identity_mode") != "purple" && !_status.connectMode) { var num; switch (get.config("auto_identity")) { case "one": @@ -2153,12 +2471,7 @@ export const Content = { num = 0; break; } - if ( - num && - !_status.identityShown && - game.phaseNumber > game.players.length * num && - game.showIdentity - ) { + if (num && !_status.identityShown && game.phaseNumber > game.players.length * num && game.showIdentity) { if (!_status.video) player.popup("显示身份"); _status.identityShown = true; game.showIdentity(false); @@ -2211,7 +2524,7 @@ export const Content = { player.storage[current].maxHp = player.maxHp; player.storage[current].hujia = player.hujia; player.storage[current].hs = player.getCards("h"); - player.storage[current].es = player.getCards("e"); + player.storage[current].es = player.getVCards("e"); player.lose(player.getCards("he"), ui.special)._triggered = null; var cfg = player.storage[event.directresult]; @@ -2238,14 +2551,10 @@ export const Content = { player.storage[current].maxHp = player.maxHp; player.storage[current].hujia = player.hujia; player.storage[current].hs = player.getCards("h"); - player.storage[current].es = player.getCards("e"); + player.storage[current].es = player.getVCards("e"); player.lose(player.getCards("he"), ui.special)._triggered = null; } - player.reinit(current, player.storage.subplayer.name, [ - player.storage.subplayer.hp, - player.storage.subplayer.maxHp, - player.storage.subplayer.hujia, - ]); + player.reinit(current, player.storage.subplayer.name, [player.storage.subplayer.hp, player.storage.subplayer.maxHp, player.storage.subplayer.hujia]); if (goon) { const groupx = player.storage.subplayer.group || "qun"; player.group = groupx; @@ -2316,7 +2625,7 @@ export const Content = { hujia: player.hujia, skills: event.list.slice(0), hs: player.getCards("h"), - es: player.getCards("e"), + es: player.getVCards("e"), intro2: cfg.intro2, group: player.group, }; @@ -2360,7 +2669,7 @@ export const Content = { ); next.set("_get_card", card); next.set("preTarget", targets[num]); - next.set("ai", (target) => get.effect(target, get.card(), player, _status.event.player)); + next.set("ai", target => get.effect(target, get.card(), player, _status.event.player)); } else { event.addedTargets[num] = false; event._result = { bool: false }; @@ -2403,11 +2712,23 @@ export const Content = { } }, addJudgeCard: function () { - if (lib.filter.judge(card, player, target) && cards.length && get.position(cards[0], true) == "o") + if ( + !card?.cards.some(card => { + return get.position(card, true) !== "o"; + }) + ) { target.addJudge(card, cards); + } }, equipCard: function () { - if (cards.length && get.position(cards[0], true) == "o") target.equip(cards[0]); + if ( + !card?.cards.some(card => { + return get.position(card, true) !== "o"; + }) + ) { + target.equip(card); + } + //if (cards.length && get.position(cards[0], true) == "o") target.equip(cards[0]); }, gameDraw: function () { "step 0"; @@ -2423,26 +2744,14 @@ export const Content = { } if (player.getTopCards) player.directgain(player.getTopCards(numx)); else player.directgain(get.cards(numx)); - if ( - player.singleHp === true && - get.mode() != "guozhan" && - (lib.config.mode != "doudizhu" || _status.mode != "online") - ) { + if (player.singleHp === true && get.mode() != "guozhan" && (lib.config.mode != "doudizhu" || _status.mode != "online")) { player.doubleDraw(); } player._start_cards = player.getCards("h"); player = player.next; } while (player != end); event.changeCard = get.config("change_card"); - if ( - _status.connectMode || - (lib.config.mode == "single" && _status.mode != "wuxianhuoli") || - (lib.config.mode == "doudizhu" && _status.mode == "online") || - (lib.config.mode != "identity" && - lib.config.mode != "guozhan" && - lib.config.mode != "doudizhu" && - lib.config.mode != "single") - ) { + if (_status.connectMode || (lib.config.mode == "single" && _status.mode != "wuxianhuoli") || (lib.config.mode == "doudizhu" && _status.mode == "online") || (lib.config.mode != "identity" && lib.config.mode != "guozhan" && lib.config.mode != "doudizhu" && lib.config.mode != "single")) { event.changeCard = "disabled"; } "step 1"; @@ -2506,6 +2815,8 @@ export const Content = { } player.phase(); "step 2"; + event.trigger("phaseOver"); + "step 3"; if (!game.players.includes(event.player.next)) { event.player = game.findNext(event.player.next); } else { @@ -2549,10 +2860,7 @@ export const Content = { if (!character[i][j][k][4]) { character[i][j][k][4] = []; } - if ( - character[i][j][k][4].includes("boss") || - character[i][j][k][4].includes("hiddenboss") - ) { + if (character[i][j][k][4].includes("boss") || character[i][j][k][4].includes("hiddenboss")) { lib.config.forbidai.add(k); } if (lib.config.forbidai_user && lib.config.forbidai_user.includes(k)) { @@ -2566,20 +2874,11 @@ export const Content = { lib[j][k + "_character_config"] = character[i][j][k]; } else { if (lib[j][k] == undefined) { - Object.defineProperty( - lib[j], - k, - Object.getOwnPropertyDescriptor(character[i][j], k) - ); + Object.defineProperty(lib[j], k, Object.getOwnPropertyDescriptor(character[i][j], k)); } else if (Array.isArray(lib[j][k]) && Array.isArray(character[i][j][k])) { lib[j][k].addArray(character[i][j][k]); } else { - console.log( - `duplicated ${j} in character ${i}:\n${k}:\nlib.${j}.${k}`, - lib[j][k], - `\ncharacter.${i}.${j}.${k}`, - character[i][j][k] - ); + console.log(`duplicated ${j} in character ${i}:\n${k}:\nlib.${j}.${k}`, lib[j][k], `\ncharacter.${i}.${j}.${k}`, character[i][j][k]); } } } @@ -2604,15 +2903,9 @@ export const Content = { if (j == "translate" && k == i) { lib[j][k + "_card_config"] = card[i][j][k]; } else { - if (lib[j][k] == undefined) - Object.defineProperty(lib[j], k, Object.getOwnPropertyDescriptor(card[i][j], k)); + if (lib[j][k] == undefined) Object.defineProperty(lib[j], k, Object.getOwnPropertyDescriptor(card[i][j], k)); else { - console.log( - `duplicated ${j} in card ${i}:\n${k}\nlib.${j}.${k}`, - lib[j][k], - `\ncard.${i}.${j}.${k}`, - card[i][j][k] - ); + console.log(`duplicated ${j} in card ${i}:\n${k}\nlib.${j}.${k}`, lib[j][k], `\ncard.${i}.${j}.${k}`, card[i][j][k]); } } } @@ -2620,15 +2913,11 @@ export const Content = { } event.goto(0); }, - loadMode: function () { - "step 0"; - window.game = game; - lib.init.js(lib.assetURL + "mode", event.mode, game.resume); - game.pause(); - "step 1"; - if (!lib.config.dev) delete window.game; - event.result = lib.imported.mode[event.mode]; - delete lib.imported.mode[event.mode]; + async loadMode(event) { + await game.loadModeAsync(event.mode, exports => { + event.result = exports; + if (lib.imported.mode[event.mode]) delete lib.imported.mode[event.mode]; + }); }, forceOver: function () { "step 0"; @@ -2653,28 +2942,20 @@ export const Content = { event.doing = doingList.shift(); while (true) { if (trigger.filterStop && trigger.filterStop()) return; - const usableSkills = event.doing.todoList.filter((info) => { - return lib.filter.filterTrigger( - trigger, - info.player, - event.triggername, - info.skill, - info.indexedData - ); + const usableSkills = event.doing.todoList.filter(info => { + return lib.filter.filterTrigger(trigger, info.player, event.triggername, info.skill, info.indexedData); }); if (usableSkills.length == 0) { break; } else { - event.doing.todoList = event.doing.todoList.filter( - (i) => i.priority <= usableSkills[0].priority - ); + event.doing.todoList = event.doing.todoList.filter(i => i.priority <= usableSkills[0].priority); //firstDo时机和lastDo时机不进行技能优先级选择 if (get.itemtype(event.doing.player) !== "player") { event.current = usableSkills[0]; } else { - event.choice = usableSkills.filter((n) => n.priority == usableSkills[0].priority); + event.choice = usableSkills.filter(n => n.priority == usableSkills[0].priority); //现在只要找到一个同优先度技能为silent,或没有技能描述的技能 便优先执行该技能 - const silentSkill = event.choice.find((item) => { + const silentSkill = event.choice.find(item => { const skillInfo = lib.skill[item.skill]; return skillInfo && (skillInfo.silent || !lib.translate[item.skill]); }); @@ -2682,7 +2963,7 @@ export const Content = { event.current = silentSkill; } else { const currentChoice = event.choice[0], - skillsToChoose = event.choice.map((i) => i.skill).unique(); + skillsToChoose = event.choice.map(i => i.skill).unique(); if (event.choice.length === 1 || skillsToChoose.length === 1) { event.current = currentChoice; } else { @@ -2693,21 +2974,13 @@ export const Content = { next.set("arrangeSkill", true); next.set("includeOut", true); const { result } = await next; - event.current = usableSkills.find((info) => info.skill == result.control); + event.current = usableSkills.find(info => info.skill == result.control); } } } event.doing.doneList.push(event.current); event.doing.todoList.remove(event.current); - const result = await game - .createTrigger( - event.triggername, - event.current.skill, - event.current.player, - trigger, - event.current.indexedData - ) - .forResult(); + const result = await game.createTrigger(event.triggername, event.current.skill, event.current.player, trigger, event.current.indexedData).forResult(); if (get.itemtype(event.doing.player) === "player" && result === "cancelled") { for (let i = 0; i < event.doing.todoList.length; i++) { if (event.current.skill === event.doing.todoList[i].skill) { @@ -2734,7 +3007,7 @@ export const Content = { else event.skillHidden = true; } else if (invisible.includes(event.skill)) event.trigger("triggerInvisible"); else if ( - Object.keys(player.additionalSkills).every((i) => { + Object.keys(player.additionalSkills).every(i => { if (i.startsWith("hidden:")) return true; return !game.expandSkills(player.additionalSkills[i]).includes(event.skill); }) @@ -2751,8 +3024,7 @@ export const Content = { if (player.hasSkillTag("nofrequent", false, event.skill)) return false; if (typeof info.frequent == "boolean") return info.frequent; if (typeof info.frequent == "function") return info.frequent(trigger, player, event.triggername, event.indexedData); - if (info.frequent == "check" && typeof info.check == "function") - return info.check(trigger, player); + if (info.frequent == "check" && typeof info.check == "function") return info.check(trigger, player); return false; }; if (info.direct) { @@ -2782,12 +3054,10 @@ export const Content = { var str; var check = info.check; if (info.prompt) str = info.prompt; - else if (typeof info.logTarget == "string") - str = get.prompt(event.skill, trigger[info.logTarget], player); + else if (typeof info.logTarget == "string") str = get.prompt(event.skill, trigger[info.logTarget], player); else if (typeof info.logTarget == "function") { const logTarget = info.logTarget(trigger, player, event.triggername, event.indexedData); - if (get.itemtype(logTarget).startsWith("player")) - str = get.prompt(event.skill, logTarget, player); + if (get.itemtype(logTarget).startsWith("player")) str = get.prompt(event.skill, logTarget, player); } else str = get.prompt(event.skill, null, player); if (typeof str == "function") str = str(trigger, player, event.triggername, event.indexedData); @@ -2797,22 +3067,15 @@ export const Content = { next.set("includeOut", true); next.ai = () => !check || check(trigger, player, event.triggername, event.indexedData); - if (typeof info.prompt2 == "function") - next.set("prompt2", info.prompt2(trigger, player, event.triggername, event.indexedData)); + if (typeof info.prompt2 == "function") next.set("prompt2", info.prompt2(trigger, player, event.triggername, event.indexedData)); else if (typeof info.prompt2 == "string") next.set("prompt2", info.prompt2); else if (info.prompt2 != false) { - if (lib.dynamicTranslate[event.skill]) - next.set("prompt2", lib.dynamicTranslate[event.skill](player, event.skill)); - else if (lib.translate[event.skill + "_info"]) - next.set("prompt2", lib.translate[event.skill + "_info"]); + if (lib.dynamicTranslate[event.skill]) next.set("prompt2", lib.dynamicTranslate[event.skill](player, event.skill)); + else if (lib.translate[event.skill + "_info"]) next.set("prompt2", lib.translate[event.skill + "_info"]); } if (trigger.skillwarn) { - if (next.prompt2) - next.set( - "prompt2", - '' + trigger.skillwarn + "。" + next.prompt2 - ); + if (next.prompt2) next.set("prompt2", '' + trigger.skillwarn + "。" + next.prompt2); else next.set("prompt2", trigger.skillwarn); } } @@ -2840,17 +3103,15 @@ export const Content = { targets = result.targets.slice(0); } else if (info.logTarget) { if (typeof info.logTarget === "string") targets = trigger[info.logTarget]; - else if (typeof info.logTarget === "function") - targets = info.logTarget(trigger, player, event.triggername, event.indexedData); + else if (typeof info.logTarget === "function") targets = info.logTarget(trigger, player, event.triggername, event.indexedData); } if (get.itemtype(targets) === "player") { targets = [targets]; } if (info.popup != false && !info.direct && !("skill_popup" in result && !Boolean(result["skill_popup"]))) { - let popup_info = event.skill; - if (typeof info.popup === "string") popup_info = [event.skill, info.popup]; - if (info.logLine === false) player.logSkill(popup_info, false, info.line); - else player.logSkill(popup_info, targets, info.line); + const popup_info = typeof info.popup === "string" ? [event.skill, info.popup] : event.skill; + const args = [trigger, player, event.triggername, event.indexedData, result]; + player.logSkill(popup_info, info.logLine === false ? false: targets, info.line, null, args); } var next = game.createEvent(event.skill); if (typeof info.usable == "number") { @@ -2862,11 +3123,7 @@ export const Content = { next.player = player; next._trigger = trigger; next.triggername = event.triggername; - // if ("contents" in info && Array.isArray(info.contents)) { - // next.setContents(info.contents); - // } else { next.setContent(info.content); - // } next.skillHidden = event.skillHidden; if (info.forceDie) next.forceDie = true; @@ -2878,9 +3135,14 @@ export const Content = { if ("cost_data" in result) next.cost_data = result.cost_data; next.indexedData = event.indexedData; "step 4"; + if (event.skill.startsWith("player_when_")) { + player.removeSkill(event.skill); + delete lib.skill[event.skill]; + delete lib.translate[event.skill]; + } if (!player._hookTrigger) return; if ( - player._hookTrigger.some((i) => { + player._hookTrigger.some(i => { const info = lib.skill[i].hookTrigger; return info && info.after && info.after(event, player, event.triggername); }) @@ -3005,12 +3267,7 @@ export const Content = { delete window.play; } }); - } else if ( - typeof content.player == "string" && - game.playerMap[content.player] && - game.playerMap[content.player].classList && - !game.playerMap[content.player].classList.contains("obstacle") - ) { + } else if (typeof content.player == "string" && game.playerMap[content.player] && game.playerMap[content.player].classList && !game.playerMap[content.player].classList.contains("obstacle")) { game.videoContent[content.type](game.playerMap[content.player], content.content); } else { game.videoContent[content.type](content.content); @@ -3150,9 +3407,6 @@ export const Content = { game.pause(); } }, - /** - * @deprecated - */ phase: function () { "step 0"; //规则集中的“回合开始后③(处理“游戏开始时”的时机)” @@ -3169,7 +3423,7 @@ export const Content = { } //规则集中的“回合开始后①”,更新游戏轮数,触发“一轮游戏开始时” var isRound = false; - if (!event.skill) { + if (lib.onround.every(i => i(event, player))) { isRound = _status.roundSkipped; if (_status.isRoundFilter) { isRound = _status.isRoundFilter(event, player); @@ -3235,7 +3489,6 @@ export const Content = { "step 4"; //规则集中的“回合开始后⑤”,进行翻面检测 if (player.isTurnedOver() && !event._noTurnOver) { - event.cancel(); player.turnOver(); player.phaseSkipped = true; var players = game.players.slice(0).concat(game.dead); @@ -3244,6 +3497,7 @@ export const Content = { current.getHistory().isSkipped = true; current.getStat().isSkipped = true; } + event.cancel(); } else { player.phaseSkipped = false; player.getHistory().isMe = true; @@ -3411,24 +3665,18 @@ export const Content = { phaseJudge: function () { "step 0"; game.log(player, "进入了判定阶段"); - event.cards = player.getCards("j"); + event.cards = player.getVCards("j"); if (!event.cards.length) event.finish(); "step 1"; if (cards.length) { - event.card = cards.shift(); - var cardName = event.card.viewAs || event.card.name, + event.card = cards.pop(); + var cardName = event.card.name, cardInfo = lib.card[cardName]; - if (event.card.classList.contains("removing")) { - event.card.remove(); - delete event.card; - event.redo(); - } else if (event.card.classList.contains("feichu")) { - event.finish(); - return; - } else if (cardInfo.noEffect || !player.getCards("j").includes(event.card)) { + var currentCards = player.getCards("j"); + if (cardInfo.noEffect || event.card.cards?.some(card => !currentCards.includes(card))) { event.redo(); } else { - player.lose(event.card, "visible", ui.ordering); + if (event.card.cards?.length) player.lose(event.card.cards, "visible", ui.ordering); player.$phaseJudge(event.card); event.cancelled = false; event.trigger("phaseJudge"); @@ -3447,25 +3695,23 @@ export const Content = { "step 2"; if (!event.cancelled && !event.nojudge) player.judge(event.card).set("type", "phase"); "step 3"; - var name = event.card.viewAs || event.card.name; + var name = event.card.name; if (event.excluded) { delete event.excluded; } else if (event.cancelled && !event.direct) { if (lib.card[name].cancel) { var next = game.createEvent(name + "Cancel"); next.setContent(lib.card[name].cancel); - next.cards = [event.card]; - if (!event.card.viewAs) next.card = get.autoViewAs(event.card); - else next.card = get.autoViewAs({ name: name }, next.cards); + next.card = event.card; + next.cards = event.card.cards ?? []; next.player = player; } } else { var next = game.createEvent(name); next.setContent(lib.card[name].effect); next._result = result; - next.cards = [event.card]; - if (!event.card.viewAs) next.card = get.autoViewAs(event.card); - else next.card = get.autoViewAs({ name: name }, next.cards); + next.card = event.card; + next.cards = event.card.cards ?? []; next.player = player; } ui.clear(); @@ -3555,6 +3801,7 @@ export const Content = { "step 0"; game.log(player, "进入了弃牌阶段"); event.num = player.needsToDiscard(); + event.trigger("phaseDiscard"); if (event.num <= 0) event.finish(); else { game.broadcastAll(function (player) { @@ -3563,7 +3810,6 @@ export const Content = { } }, player); } - event.trigger("phaseDiscard"); "step 1"; player.chooseToDiscard(num, true).set("useCache", true); "step 2"; @@ -3620,11 +3866,7 @@ export const Content = { if (event.type == "wuxie") { if (ui.tempnowuxie) { var triggerevent = event.getTrigger(); - if ( - triggerevent && - triggerevent.targets && - triggerevent.num == triggerevent.targets.length - 1 - ) { + if (triggerevent && triggerevent.targets && triggerevent.num == triggerevent.targets.length - 1) { ui.tempnowuxie.close(); } } @@ -3678,8 +3920,7 @@ export const Content = { event.dialog = str; } } - } - else{ + } else { delete event.openskilldialog; } } else if (event.isOnline()) { @@ -3799,10 +4040,7 @@ export const Content = { if (event.buttoned) { if (result.bool || (result.control && result.control != "cancel2")) { var info = get.info(event.buttoned).chooseButton; - lib.skill[event.buttoned + "_backup"] = info.backup( - info.chooseControl ? result : result.links, - player - ); + lib.skill[event.buttoned + "_backup"] = info.backup(info.chooseControl ? result : result.links, player); lib.skill[event.buttoned + "_backup"].sourceSkill = lib.skill[event.buttoned].sourceSkill ? lib.skill[event.buttoned].sourceSkill : event.buttoned; if (game.online) { event._sendskill = [event.buttoned + "_backup", lib.skill[event.buttoned + "_backup"]]; @@ -3841,13 +4079,8 @@ export const Content = { } else if (event._sendskill) { event.result._sendskill = event._sendskill; } - if ( - (!event.result || !event.result.bool || event.result._noHidingTimer) && - (event.result.skill || event.logSkill) - ) { - var info = get.info( - event.result.skill || (Array.isArray(event.logSkill) ? event.logSkill[0] : event.logSkill) - ); + if ((!event.result || !event.result.bool || event.result._noHidingTimer) && (event.result.skill || event.logSkill)) { + var info = get.info(event.result.skill || (Array.isArray(event.logSkill) ? event.logSkill[0] : event.logSkill)); if (info.direct && !info.clearTime) { _status.noclearcountdown = "direct"; } @@ -3898,8 +4131,7 @@ export const Content = { if (event.prompt) event.dialog = ui.create.dialog(event.prompt); if (event.prompt2) event.dialog.addText(event.prompt2); } - } - else{ + } else { delete event.openskilldialog; } } else if (event.isOnline()) { @@ -4011,10 +4243,7 @@ export const Content = { if (event.buttoned) { if (result.bool || (result.control && result.control != "cancel2")) { var info = get.info(event.buttoned).chooseButton; - lib.skill[event.buttoned + "_backup"] = info.backup( - info.chooseControl ? result : result.links, - player - ); + lib.skill[event.buttoned + "_backup"] = info.backup(info.chooseControl ? result : result.links, player); lib.skill[event.buttoned + "_backup"].sourceSkill = lib.skill[event.buttoned].sourceSkill ? lib.skill[event.buttoned].sourceSkill : event.buttoned; if (game.online) { event._sendskill = [event.buttoned + "_backup", lib.skill[event.buttoned + "_backup"]]; @@ -4051,13 +4280,8 @@ export const Content = { if (event.onresult) { event.onresult(event.result); } - if ( - (!event.result || !event.result.bool || event.result._noHidingTimer) && - (event.result.skill || event.logSkill) - ) { - var info = get.info( - event.result.skill || (Array.isArray(event.logSkill) ? event.logSkill[0] : event.logSkill) - ); + if ((!event.result || !event.result.bool || event.result._noHidingTimer) && (event.result.skill || event.logSkill)) { + var info = get.info(event.result.skill || (Array.isArray(event.logSkill) ? event.logSkill[0] : event.logSkill)); if (info.direct && !info.clearTime) { _status.noclearcountdown = "direct"; } @@ -4076,13 +4300,7 @@ export const Content = { if (info && info.prerespond) { info.prerespond(event.result, player); } - var next = player.respond( - event.result.cards, - event.result.card, - event.animate, - event.result.skill, - event.source - ); + var next = player.respond(event.result.cards, event.result.card, event.animate, event.result.skill, event.source); if (event.result.noanimate) next.animate = false; if (event.parent.card && event.parent.type == "card") { next.set("respondTo", [event.parent.player, event.parent.card]); @@ -4107,7 +4325,7 @@ export const Content = { cards: [], targets: [], }; - event.filterCard = ((event) => { + event.filterCard = (event => { const filterCard = event.filterCard; return function (card, player) { if (!lib.filter.canBeGained(card, this.target, player)) return false; @@ -4119,21 +4337,8 @@ export const Content = { event.goto(2); return; } - const directFilter = - event.forced && - typeof event.filterOk != "function" && - typeof event.selectCard != "function" && - !event.complexCard; - const cards = directFilter - ? player - .getCards(event.position) - .filter( - (card) => - !card.classList.contains("uncheck") && - lib.filter.cardAiIncluded(card) && - event.filterCard(card, player) - ) - : []; + const directFilter = event.forced && typeof event.filterOk != "function" && typeof event.selectCard != "function" && !event.complexCard; + const cards = directFilter ? player.getCards(event.position).filter(card => !card.classList.contains("uncheck") && lib.filter.cardAiIncluded(card) && event.filterCard(card, player)) : []; const range = get.select(event.selectCard); if (directFilter && (range[0] >= cards.length || range[1] <= -1)) { if (player.isOut()) event.result.cards = []; @@ -4151,7 +4356,7 @@ export const Content = { if (_status.event.custom && _status.event.custom.add.card) { _status.event.custom.add.card(); } - ui.selected.cards.forEach((i) => i.updateTransform(true)); + ui.selected.cards.forEach(i => i.updateTransform(true)); }); } if (Array.isArray(event.dialog)) { @@ -4174,13 +4379,12 @@ export const Content = { event.dialog.addText(event.prompt2, event.prompt2.length <= 20); } if (Array.isArray(event.promptx)) { - event.promptx.forEach((i) => event.dialog.add(i)); + event.promptx.forEach(i => event.dialog.add(i)); } if (Array.isArray(event.selectCard)) { event.promptbar = event.dialog.add("0/" + get.numStr(event.selectCard[1], "card")); event.custom.add.card = function () { - _status.event.promptbar.innerHTML = - ui.selected.cards.length + "/" + get.numStr(_status.event.selectCard[1], "card"); + _status.event.promptbar.innerHTML = ui.selected.cards.length + "/" + get.numStr(_status.event.selectCard[1], "card"); }; } } else if (get.itemtype(event.dialog) == "dialog") { @@ -4210,7 +4414,7 @@ export const Content = { event.resume(); if (event.aiChoose) event.aiChoose.close(); if (event.glow_result && event.result.cards && !event.directresult) { - event.result.cards.forEach((i) => i.classList.add("glow")); + event.result.cards.forEach(i => i.classList.add("glow")); } if (event.dialog) event.dialog.close(); "step 3"; @@ -4305,10 +4509,7 @@ export const Content = { if (Array.isArray(event.selectCard)) { event.promptbar = event.dialog.add("0/" + get.numStr(event.selectCard[1], "card")); event.custom.add.card = function () { - _status.event.promptbar.innerHTML = - ui.selected.cards.length + - "/" + - get.numStr(_status.event.selectCard[1], "card"); + _status.event.promptbar.innerHTML = ui.selected.cards.length + "/" + get.numStr(_status.event.selectCard[1], "card"); }; } } else if (get.itemtype(event.dialog) == "dialog") { @@ -4347,14 +4548,7 @@ export const Content = { event.promptdiscard.close(); } "step 3"; - if ( - event.result.bool && - event.result.cards && - event.result.cards.length && - !game.online && - event.autodelay && - !event.isMine() - ) { + if (event.result.bool && event.result.cards && event.result.cards.length && !game.online && event.autodelay && !event.isMine()) { if (typeof event.autodelay == "number") { game.delayx(event.autodelay); } else { @@ -4394,7 +4588,7 @@ export const Content = { for (var i of event.gain_list) { if (get.itemtype(i[1]) == "card") i[1] = [i[1]]; if (event._lose) { - i[1] = i[1].filter((card) => { + i[1] = i[1].filter(card => { return !cards.includes(card) || !player.getCards("hejsx").includes(card); }); } @@ -4406,7 +4600,7 @@ export const Content = { for (var i of event.gain_list) { if (get.itemtype(i[1]) == "card") i[1] = [i[1]]; if (event._lose) { - i[1] = i[1].filter((card) => { + i[1] = i[1].filter(card => { return !cards.includes(card) || !player.getCards("hejsx").includes(card); }); } @@ -4419,7 +4613,7 @@ export const Content = { for (var i of event.gain_list) { if (get.itemtype(i[1]) == "card") i[1] = [i[1]]; if (event._lose) { - i[1] = i[1].filter((card) => { + i[1] = i[1].filter(card => { return !cards.includes(card) || !player.getCards("hejsx").includes(card); }); } @@ -4434,7 +4628,7 @@ export const Content = { for (var i of event.gain_list) { if (get.itemtype(i[1]) == "card") i[1] = [i[1]]; if (event._lose) { - i[1] = i[1].filter((card) => { + i[1] = i[1].filter(card => { return !cards.includes(card) || !player.getCards("hejsx").includes(card); }); } @@ -4452,8 +4646,6 @@ export const Content = { if (hidden.length > 0) player.$giveAuto(hidden, i[0]); } break; - default: - event.finish(); } for (var i of event.gain_list) { if (i[1].length > 0) { @@ -4577,11 +4769,7 @@ export const Content = { }); if (event.list.length || !event.fixedResult || !event.fixedResult[player.playerid]) { if (!event.fixedResult || !event.fixedResult[player.playerid]) event.list.unshift(player); - player - .chooseCardOL(event.list, "请选择拼点牌", true) - .set("type", "compare") - .set("ai", event.ai) - .set("source", player).aiCard = function (target) { + player.chooseCardOL(event.list, "请选择拼点牌", true).set("type", "compare").set("ai", event.ai).set("source", player).aiCard = function (target) { var hs = target.getCards("h"); var event = _status.event; event.player = target; @@ -4668,6 +4856,7 @@ export const Content = { delete event.player; event.trigger("compare"); } else { + event.iwhile = 0; game.delay(0, 1000); event.goto(9); } @@ -4690,18 +4879,35 @@ export const Content = { event.iwhile++; event.goto(6); "step 9"; + event.player = event.tempplayer; + event.trigger("compareFixing"); + "step 10"; + if (event.player) delete event.player; + if (event.iwhile < targets.length) { + event.target = targets[event.iwhile]; + event.card2 = event.cardlist[event.iwhile]; + event.num2 = event.result.num2[event.iwhile]; + event.trigger("compareFixing"); + } else { + event.goto(12); + } + "step 11"; + event.iwhile++; + event.goto(10); + "step 12"; var player = event.tempplayer; event.player = player; delete event.tempplayer; var str = "无人拼点成功"; - if (event.winner) { - event.result.winner = event.winner; - str = get.translation(event.winner) + "拼点成功"; - game.log(event.winner, "拼点成功"); - event.winner.popup("胜"); + const winner = event.forceWinner || event.winner; + if (winner) { + event.result.winner = winner; + str = get.translation(winner) + "拼点成功"; + game.log(winner, "拼点成功"); + winner.popup("胜"); } else game.log("#b无人", "拼点成功"); var list = [player].addArray(targets); - list.remove(event.winner); + list.remove(winner); for (var i of list) { i.popup("负"); } @@ -4715,9 +4921,9 @@ export const Content = { }, str); } game.delay(3); - "step 10"; + "step 13"; game.broadcastAll(ui.clear); - "step 11"; + "step 14"; event.cards.add(event.card1); }, chooseToCompareMultiple: function () { @@ -4745,11 +4951,7 @@ export const Content = { }); if (event.list.length || !event.fixedResult || !event.fixedResult[player.playerid]) { if (!event.fixedResult || !event.fixedResult[player.playerid]) event.list.unshift(player); - player - .chooseCardOL(event.list, "请选择拼点牌", true) - .set("type", "compare") - .set("ai", event.ai) - .set("source", player).aiCard = function (target) { + player.chooseCardOL(event.list, "请选择拼点牌", true).set("type", "compare").set("ai", event.ai).set("source", player).aiCard = function (target) { var hs = target.getCards("h"); var event = _status.event; event.player = target; @@ -4826,22 +5028,28 @@ export const Content = { event.trigger("compare"); game.delay(0, 1500); } else { - event.goto(9); + event.goto(10); } "step 6"; - event.result.num1[event.iwhile] = event.num1; - event.result.num2[event.iwhile] = event.num2; + event.iiwhile = event.iwhile; + delete event.iwhile; + event.trigger("compareFixing"); + "step 7"; + event.result.num1[event.iiwhile] = event.num1; + event.result.num2[event.iiwhile] = event.num2; var str; - if (event.num1 > event.num2) { + if (event.forceWinner === player || (event.forceWinner !== target && event.num1 > event.num2)) { + event.winner = player; str = get.translation(player) + "拼点成功"; player.popup("胜"); target.popup("负"); } else { str = get.translation(player) + "拼点失败"; - if (event.num1 == event.num2) { + if (event.forceWinner !== target && event.num1 == event.num2) { player.popup("平"); target.popup("平"); } else { + event.winner = target; player.popup("负"); target.popup("胜"); } @@ -4854,7 +5062,7 @@ export const Content = { }, 1000); }, str); game.delay(2); - "step 7"; + "step 8"; if (event.callback) { game.broadcastAll( function (card1, card2) { @@ -4871,22 +5079,22 @@ export const Content = { next.card2 = event.card2; next.num1 = event.num1; next.num2 = event.num2; + next.winner = event.winner; next.setContent(event.callback); event.compareMultiple = true; } - "step 8"; + "step 9"; game.broadcastAll(ui.clear); - event.iwhile++; + delete event.winner; + delete event.forceWinner; + event.iwhile = event.iiwhile + 1; event.goto(5); - "step 9"; + "step 10"; event.cards.add(event.card1); }, chooseToCompare: function () { "step 0"; - if ( - ((!event.fixedResult || !event.fixedResult[player.playerid]) && player.countCards("h") == 0) || - ((!event.fixedResult || !event.fixedResult[target.playerid]) && target.countCards("h") == 0) - ) { + if (((!event.fixedResult || !event.fixedResult[player.playerid]) && player.countCards("h") == 0) || ((!event.fixedResult || !event.fixedResult[target.playerid]) && target.countCards("h") == 0)) { event.result = { cancelled: true, bool: false }; event.finish(); return; @@ -4908,14 +5116,12 @@ export const Content = { player.wait(sendback); event.ol = true; player.send(function (ai) { - game.me.chooseCard("请选择拼点牌", true).set("type", "compare").set("glow_result", true).ai = - ai; + game.me.chooseCard("请选择拼点牌", true).set("type", "compare").set("glow_result", true).ai = ai; game.resume(); }, event.ai); } else { event.localPlayer = true; - player.chooseCard("请选择拼点牌", true).set("type", "compare").set("glow_result", true).ai = - event.ai; + player.chooseCard("请选择拼点牌", true).set("type", "compare").set("glow_result", true).ai = event.ai; } if (event.fixedResult && event.fixedResult[target.playerid]) { event.card2 = event.fixedResult[target.playerid]; @@ -4924,8 +5130,7 @@ export const Content = { target.wait(sendback); event.ol = true; target.send(function (ai) { - game.me.chooseCard("请选择拼点牌", true).set("type", "compare").set("glow_result", true).ai = - ai; + game.me.chooseCard("请选择拼点牌", true).set("type", "compare").set("glow_result", true).ai = ai; game.resume(); }, event.ai); } else { @@ -4940,8 +5145,7 @@ export const Content = { event.card1 = result.cards[0]; } if (event.localTarget) { - target.chooseCard("请选择拼点牌", true).set("type", "compare").set("glow_result", true).ai = - event.ai; + target.chooseCard("请选择拼点牌", true).set("type", "compare").set("glow_result", true).ai = event.ai; } "step 3"; if (event.localTarget) { @@ -4957,26 +5161,16 @@ export const Content = { "step 4"; try { if (!event.card1) { - if ( - event.resultOL[player.playerid].skill && - lib.skill[event.resultOL[player.playerid].skill] && - lib.skill[event.resultOL[player.playerid].skill].onCompare - ) { + if (event.resultOL[player.playerid].skill && lib.skill[event.resultOL[player.playerid].skill] && lib.skill[event.resultOL[player.playerid].skill].onCompare) { player.logSkill(event.resultOL[player.playerid].skill); - event.resultOL[player.playerid].cards = - lib.skill[event.resultOL[player.playerid].skill].onCompare(player); + event.resultOL[player.playerid].cards = lib.skill[event.resultOL[player.playerid].skill].onCompare(player); } else event.lose_list.push([player, event.resultOL[player.playerid].cards[0]]); event.card1 = event.resultOL[player.playerid].cards[0]; } if (!event.card2) { - if ( - event.resultOL[target.playerid].skill && - lib.skill[event.resultOL[target.playerid].skill] && - lib.skill[event.resultOL[target.playerid].skill].onCompare - ) { + if (event.resultOL[target.playerid].skill && lib.skill[event.resultOL[target.playerid].skill] && lib.skill[event.resultOL[target.playerid].skill].onCompare) { target.logSkill(event.resultOL[target.playerid].skill); - event.resultOL[target.playerid].cards = - lib.skill[event.resultOL[target.playerid].skill].onCompare(player); + event.resultOL[target.playerid].cards = lib.skill[event.resultOL[target.playerid].skill].onCompare(player); } else event.lose_list.push([target, event.resultOL[target.playerid].cards[0]]); event.card2 = event.resultOL[target.playerid].cards[0]; } @@ -5027,8 +5221,10 @@ export const Content = { num1: event.num1, num2: event.num2, }; + event.trigger("compareFixing"); + "step 8"; var str; - if (event.num1 > event.num2) { + if (event.forceWinner === player || (event.forceWinner !== target && event.num1 > event.num2)) { event.result.bool = true; event.result.winner = player; str = get.translation(player) + "拼点成功"; @@ -5037,7 +5233,7 @@ export const Content = { } else { event.result.bool = false; str = get.translation(player) + "拼点失败"; - if (event.num1 == event.num2) { + if (event.forceWinner !== target && event.num1 == event.num2) { event.result.tie = true; player.popup("平"); target.popup("平"); @@ -5055,7 +5251,7 @@ export const Content = { }, 1000); }, str); game.delay(2); - "step 8"; + "step 9"; if (typeof event.target.ai.shown == "number" && event.target.ai.shown <= 0.85 && event.addToAI) { event.target.ai.shown += 0.1; } @@ -5083,8 +5279,8 @@ export const Content = { list = event.target.getGainableSkills(event.func); } if (!list.length) { - event.finish(); event.result = { bool: false }; + event.finish(); return; } event.skillai = function (list) { @@ -5106,13 +5302,7 @@ export const Content = { } else { translation = translation.slice(0, 2); } - var item = dialog.add( - '" - ); + var item = dialog.add('"); item.firstChild.addEventListener("click", clickItem); item.firstChild.link = list[i]; } @@ -5273,8 +5463,7 @@ export const Content = { event.result = event.processAI(); } else { game.check(); - if ((ai.basic.chooseButton(event.ai) || forced) && (!event.filterOk || event.filterOk())) - ui.click.ok(); + if ((ai.basic.chooseButton(event.ai) || forced) && (!event.filterOk || event.filterOk())) ui.click.ok(); else ui.click.cancel(); } } @@ -5480,10 +5669,7 @@ export const Content = { if (Array.isArray(event.selectCard)) { event.promptbar = event.dialog.add("0/" + get.numStr(event.selectCard[1], "card")); event.custom.add.card = function () { - _status.event.promptbar.innerHTML = - ui.selected.cards.length + - "/" + - get.numStr(_status.event.selectCard[1], "card"); + _status.event.promptbar.innerHTML = ui.selected.cards.length + "/" + get.numStr(_status.event.selectCard[1], "card"); }; } } @@ -5544,14 +5730,9 @@ export const Content = { event.dialog.addText(event.prompt2, event.prompt2.length <= 20); } if (event.promptbar != "none") { - event.promptbar = event.dialog.add( - "0/" + get.numStr(get.select(event.selectTarget)[1], "target") - ); + event.promptbar = event.dialog.add("0/" + get.numStr(get.select(event.selectTarget)[1], "target")); event.custom.add.target = function () { - _status.event.promptbar.innerHTML = - ui.selected.targets.length + - "/" + - get.numStr(get.select(event.selectTarget)[1], "target"); + _status.event.promptbar.innerHTML = ui.selected.targets.length + "/" + get.numStr(get.select(event.selectTarget)[1], "target"); }; } } else if (get.itemtype(event.dialog) == "dialog") { @@ -5674,11 +5855,7 @@ export const Content = { } } } - } else if ( - event.hsskill && - _status.prehidden_skills.includes(event.hsskill) && - event.controls.includes("cancel2") - ) { + } else if (event.hsskill && _status.prehidden_skills.includes(event.hsskill) && event.controls.includes("cancel2")) { event.result = { bool: true, control: "cancel2", @@ -5706,10 +5883,7 @@ export const Content = { var item = ui.create.div(".button.card.pointerdiv.mebg"); item.style.width = "50px"; buttons.insertBefore(item, event.dialog.buttons[i]); - item.innerHTML = - '
        第' + - get.cnNumber(i + 1, true) + - "张
        "; + item.innerHTML = '
        第' + get.cnNumber(i + 1, true) + "张
        "; if (i == event.dialog.buttons.length + 1) { item.firstChild.innerHTML = "牌堆底"; } @@ -5723,11 +5897,7 @@ export const Content = { } else if (event.dialogcontrol) { event.dialog = ui.create.dialog(event.prompt || "选择一项", "hidden"); for (var i = 0; i < event.controls.length; i++) { - var item = event.dialog.add( - '" - ); + var item = event.dialog.add('"); item.firstChild.listen(ui.click.dialogcontrol); item.firstChild.link = event.controls[i]; } @@ -5784,22 +5954,12 @@ export const Content = { event.dialog.forcebutton = true; event.dialog.open(); for (var i = 0; i < event.choiceList.length; i++) { - event.dialog.add( - '" - ); + event.dialog.add('"); } } else if (event.prompt) { event.dialog = ui.create.dialog(event.prompt); if (event.prompt2) { - event.dialog.addText( - event.prompt2, - Boolean(event.prompt2.length <= 20 || event.centerprompt2) - ); + event.dialog.addText(event.prompt2, Boolean(event.prompt2.length <= 20 || event.centerprompt2)); } } } @@ -5911,15 +6071,7 @@ export const Content = { next.set("ai", event.ai); } else { var choice; - if ( - player.isDamaged() && - get.recoverEffect(player) > 0 && - (player.hp == 1 || - player.needsToDiscard() || - player.hasSkillTag("maixie_hp") || - event.num2 > event.num1 || - (event.num2 == event.num1 && player.needsToDiscard(1))) - ) { + if (player.isDamaged() && get.recoverEffect(player) > 0 && (player.hp == 1 || player.needsToDiscard() || player.hasSkillTag("maixie_hp") || event.num2 > event.num1 || (event.num2 == event.num1 && player.needsToDiscard(1)))) { choice = "recover_hp"; } else { choice = "draw_card"; @@ -5963,46 +6115,28 @@ export const Content = { let expand_length = 0; const cs = target.getCards(event.position); const select = get.select(event.selectButton); - const directFilter = - event.forced && - typeof event.filterOk != "function" && - typeof event.selectButton != "function" && - event.filterButton == lib.filter.all; - let directh = - !lib.config.unauto_choose && - !event.isOnline() && - select[0] == select[1] && - (!event.complexSelect || select[1] === 1); + const directFilter = event.forced && typeof event.filterOk != "function" && typeof event.selectButton != "function" && event.filterButton == lib.filter.all; + let directh = !lib.config.unauto_choose && !event.isOnline() && select[0] == select[1] && (!event.complexSelect || select[1] === 1); for (var i = 0; i < event.position.length; i++) { if (event.position[i] == "h") { var hs = target.getCards("h"); if (hs.length) { expand_length += Math.ceil(hs.length / 6); - var title = event.dialog.add( - '
        手牌区
        ' - ); + var title = event.dialog.add('
        手牌区
        '); title.style.margin = "0px"; title.style.padding = "0px"; hs.randomSort(); - if ( - event.visible || - target.isUnderControl(true) || - player.hasSkillTag("viewHandcard", null, target, true) - ) { + if (event.visible || target.isUnderControl(true) || player.hasSkillTag("viewHandcard", null, target, true)) { event.dialog.add(hs); directh = false; } else { - var shown = hs.filter((card) => get.is.shownCard(card)); + var shown = hs.filter(card => get.is.shownCard(card)); if (shown.length) { - var hidden = hs.filter((card) => !shown.includes(card)); + var hidden = hs.filter(card => !shown.includes(card)); var buttons = ui.create.div(".buttons", event.dialog.content); - event.dialog.buttons = event.dialog.buttons.concat( - ui.create.buttons(shown, "card", buttons) - ); - event.dialog.buttons = event.dialog.buttons.concat( - ui.create.buttons(hidden, "blank", buttons) - ); + event.dialog.buttons = event.dialog.buttons.concat(ui.create.buttons(shown, "card", buttons)); + event.dialog.buttons = event.dialog.buttons.concat(ui.create.buttons(hidden, "blank", buttons)); if (event.dialog.forcebutton !== false) event.dialog.forcebutton = true; if (event.dialog.buttons.length > 3) { event.dialog.classList.remove("forcebutton-auto"); @@ -6019,9 +6153,7 @@ export const Content = { var es = target.getCards("e"); if (es.length) { expand_length += Math.ceil(es.length / 6); - var title = event.dialog.add( - '
        装备区
        ' - ); + var title = event.dialog.add('
        装备区
        '); title.style.margin = "0px"; title.style.padding = "0px"; event.dialog.add(es); @@ -6031,26 +6163,20 @@ export const Content = { var js = target.getCards("j"); if (js.length) { expand_length += Math.ceil(js.length / 6); - var title = event.dialog.add( - '
        判定区
        ' - ); + var title = event.dialog.add('
        判定区
        '); title.style.margin = "0px"; title.style.padding = "0px"; - var shown = js.filter((card) => { + var shown = js.filter(card => { var name = card.viewAs || card.name, info = lib.card[name]; if (!info || !info.blankCard) return true; return false; }); if (shown.length < js.length && !target.isUnderControl(true)) { - var hidden = js.filter((card) => !shown.includes(card)); + var hidden = js.filter(card => !shown.includes(card)); var buttons = ui.create.div(".buttons", event.dialog.content); - event.dialog.buttons = event.dialog.buttons.concat( - ui.create.buttons(shown, "card", buttons) - ); - event.dialog.buttons = event.dialog.buttons.concat( - ui.create.buttons(hidden, "blank", buttons) - ); + event.dialog.buttons = event.dialog.buttons.concat(ui.create.buttons(shown, "card", buttons)); + event.dialog.buttons = event.dialog.buttons.concat(ui.create.buttons(hidden, "blank", buttons)); if (event.dialog.forcebutton !== false) event.dialog.forcebutton = true; if (event.dialog.buttons.length > 3) { event.dialog.classList.remove("forcebutton-auto"); @@ -6105,8 +6231,7 @@ export const Content = { "step 1"; if (event.result == "ai") { game.check(); - if ((ai.basic.chooseButton(event.ai) || forced) && (!event.filterOk || event.filterOk())) - ui.click.ok(); + if ((ai.basic.chooseButton(event.ai) || forced) && (!event.filterOk || event.filterOk())) ui.click.ok(); else ui.click.cancel(); } event.dialog.close(); @@ -6158,46 +6283,28 @@ export const Content = { let expand_length = 0; const cs = target.getCards(event.position); const select = get.select(event.selectButton); - const directFilter = - event.forced && - typeof event.filterOk != "function" && - typeof event.selectButton != "function" && - event.filterButton == lib.filter.all; - let directh = - !lib.config.unauto_choose && - !event.isOnline() && - select[0] == select[1] && - (!event.complexSelect || select[1] === 1); + const directFilter = event.forced && typeof event.filterOk != "function" && typeof event.selectButton != "function" && event.filterButton == lib.filter.all; + let directh = !lib.config.unauto_choose && !event.isOnline() && select[0] == select[1] && (!event.complexSelect || select[1] === 1); for (var i = 0; i < event.position.length; i++) { if (event.position[i] == "h") { var hs = target.getDiscardableCards(player, "h"); expand_length += Math.ceil(hs.length / 6); if (hs.length) { - var title = event.dialog.add( - '
        手牌区
        ' - ); + var title = event.dialog.add('
        手牌区
        '); title.style.margin = "0px"; title.style.padding = "0px"; hs.randomSort(); - if ( - event.visible || - target.isUnderControl(true) || - player.hasSkillTag("viewHandcard", null, target, true) - ) { + if (event.visible || target.isUnderControl(true) || player.hasSkillTag("viewHandcard", null, target, true)) { event.dialog.add(hs); directh = false; } else { - var shown = hs.filter((card) => get.is.shownCard(card)); + var shown = hs.filter(card => get.is.shownCard(card)); if (shown.length) { - var hidden = hs.filter((card) => !shown.includes(card)); + var hidden = hs.filter(card => !shown.includes(card)); var buttons = ui.create.div(".buttons", event.dialog.content); - event.dialog.buttons = event.dialog.buttons.concat( - ui.create.buttons(shown, "card", buttons) - ); - event.dialog.buttons = event.dialog.buttons.concat( - ui.create.buttons(hidden, "blank", buttons) - ); + event.dialog.buttons = event.dialog.buttons.concat(ui.create.buttons(shown, "card", buttons)); + event.dialog.buttons = event.dialog.buttons.concat(ui.create.buttons(hidden, "blank", buttons)); if (event.dialog.forcebutton !== false) event.dialog.forcebutton = true; if (event.dialog.buttons.length > 3) { event.dialog.classList.remove("forcebutton-auto"); @@ -6214,9 +6321,7 @@ export const Content = { var es = target.getDiscardableCards(player, "e"); if (es.length) { expand_length += Math.ceil(es.length / 6); - var title = event.dialog.add( - '
        装备区
        ' - ); + var title = event.dialog.add('
        装备区
        '); title.style.margin = "0px"; title.style.padding = "0px"; event.dialog.add(es); @@ -6226,26 +6331,20 @@ export const Content = { var js = target.getDiscardableCards(player, "j"); if (js.length) { expand_length += Math.ceil(js.length / 6); - var title = event.dialog.add( - '
        判定区
        ' - ); + var title = event.dialog.add('
        判定区
        '); title.style.margin = "0px"; title.style.padding = "0px"; - var shown = js.filter((card) => { + var shown = js.filter(card => { var name = card.viewAs || card.name, info = lib.card[name]; if (!info || !info.blankCard) return true; return false; }); if (shown.length < js.length && !target.isUnderControl(true)) { - var hidden = js.filter((card) => !shown.includes(card)); + var hidden = js.filter(card => !shown.includes(card)); var buttons = ui.create.div(".buttons", event.dialog.content); - event.dialog.buttons = event.dialog.buttons.concat( - ui.create.buttons(shown, "card", buttons) - ); - event.dialog.buttons = event.dialog.buttons.concat( - ui.create.buttons(hidden, "blank", buttons) - ); + event.dialog.buttons = event.dialog.buttons.concat(ui.create.buttons(shown, "card", buttons)); + event.dialog.buttons = event.dialog.buttons.concat(ui.create.buttons(hidden, "blank", buttons)); if (event.dialog.forcebutton !== false) event.dialog.forcebutton = true; if (event.dialog.buttons.length > 3) { event.dialog.classList.remove("forcebutton-auto"); @@ -6296,8 +6395,7 @@ export const Content = { "step 1"; if (event.result == "ai") { game.check(); - if ((ai.basic.chooseButton(event.ai) || forced) && (!event.filterOk || event.filterOk())) - ui.click.ok(); + if ((ai.basic.chooseButton(event.ai) || forced) && (!event.filterOk || event.filterOk())) ui.click.ok(); else ui.click.cancel(); } event.dialog.close(); @@ -6376,46 +6474,28 @@ export const Content = { let expand_length = 0; const cs = target.getCards(event.position); const select = get.select(event.selectButton); - const directFilter = - event.forced && - typeof event.filterOk != "function" && - typeof event.selectButton != "function" && - event.filterButton == lib.filter.all; - let directh = - !lib.config.unauto_choose && - !event.isOnline() && - select[0] == select[1] && - (!event.complexSelect || select[1] === 1); + const directFilter = event.forced && typeof event.filterOk != "function" && typeof event.selectButton != "function" && event.filterButton == lib.filter.all; + let directh = !lib.config.unauto_choose && !event.isOnline() && select[0] == select[1] && (!event.complexSelect || select[1] === 1); for (var i = 0; i < event.position.length; i++) { if (event.position[i] == "h") { var hs = target.getGainableCards(player, "h"); if (hs.length) { expand_length += Math.ceil(hs.length / 6); - var title = event.dialog.add( - '
        手牌区
        ' - ); + var title = event.dialog.add('
        手牌区
        '); title.style.margin = "0px"; title.style.padding = "0px"; hs.randomSort(); - if ( - event.visible || - target.isUnderControl(true) || - player.hasSkillTag("viewHandcard", null, target, true) - ) { + if (event.visible || target.isUnderControl(true) || player.hasSkillTag("viewHandcard", null, target, true)) { event.dialog.add(hs); directh = false; } else { - var shown = hs.filter((card) => get.is.shownCard(card)); + var shown = hs.filter(card => get.is.shownCard(card)); if (shown.length) { - var hidden = hs.filter((card) => !shown.includes(card)); + var hidden = hs.filter(card => !shown.includes(card)); var buttons = ui.create.div(".buttons", event.dialog.content); - event.dialog.buttons = event.dialog.buttons.concat( - ui.create.buttons(shown, "card", buttons) - ); - event.dialog.buttons = event.dialog.buttons.concat( - ui.create.buttons(hidden, "blank", buttons) - ); + event.dialog.buttons = event.dialog.buttons.concat(ui.create.buttons(shown, "card", buttons)); + event.dialog.buttons = event.dialog.buttons.concat(ui.create.buttons(hidden, "blank", buttons)); if (event.dialog.forcebutton !== false) event.dialog.forcebutton = true; if (event.dialog.buttons.length > 3) { event.dialog.classList.remove("forcebutton-auto"); @@ -6432,9 +6512,7 @@ export const Content = { var es = target.getGainableCards(player, "e"); if (es.length) { expand_length += Math.ceil(es.length / 6); - var title = event.dialog.add( - '
        装备区
        ' - ); + var title = event.dialog.add('
        装备区
        '); title.style.margin = "0px"; title.style.padding = "0px"; event.dialog.add(es); @@ -6444,26 +6522,20 @@ export const Content = { var js = target.getGainableCards(player, "j"); if (js.length) { expand_length += Math.ceil(js.length / 6); - var title = event.dialog.add( - '
        判定区
        ' - ); + var title = event.dialog.add('
        判定区
        '); title.style.margin = "0px"; title.style.padding = "0px"; - var shown = js.filter((card) => { + var shown = js.filter(card => { var name = card.viewAs || card.name, info = lib.card[name]; if (!info || !info.blankCard) return true; return false; }); if (shown.length < js.length && !target.isUnderControl(true)) { - var hidden = js.filter((card) => !shown.includes(card)); + var hidden = js.filter(card => !shown.includes(card)); var buttons = ui.create.div(".buttons", event.dialog.content); - event.dialog.buttons = event.dialog.buttons.concat( - ui.create.buttons(shown, "card", buttons) - ); - event.dialog.buttons = event.dialog.buttons.concat( - ui.create.buttons(hidden, "blank", buttons) - ); + event.dialog.buttons = event.dialog.buttons.concat(ui.create.buttons(shown, "card", buttons)); + event.dialog.buttons = event.dialog.buttons.concat(ui.create.buttons(hidden, "blank", buttons)); if (event.dialog.forcebutton !== false) event.dialog.forcebutton = true; if (event.dialog.buttons.length > 3) { event.dialog.classList.remove("forcebutton-auto"); @@ -6515,8 +6587,7 @@ export const Content = { "step 1"; if (event.result == "ai") { game.check(); - if ((ai.basic.chooseButton(event.ai) || forced) && (!event.filterOk || event.filterOk())) - ui.click.ok(); + if ((ai.basic.chooseButton(event.ai) || forced) && (!event.filterOk || event.filterOk())) ui.click.ok(); else ui.click.cancel(); } event.dialog.close(); @@ -6549,12 +6620,7 @@ export const Content = { } if (!event.chooseonly) { if (event.delay !== false) { - var next = player.gain( - event.cards, - target, - event.visibleMove ? "give" : "giveAuto", - "bySelf" - ); + var next = player.gain(event.cards, target, event.visibleMove ? "give" : "giveAuto", "bySelf"); event.done = next; } else { var next = player.gain(event.cards, target, "bySelf"); @@ -6661,12 +6727,12 @@ export const Content = { game.countChoose(); event.choosing = true; } else { - event.finish(); event.result = "viewed"; setTimeout(function () { event.dialog.close(); }, 2 * lib.config.duration); game.delayx(2); + event.finish(); } } else if (event.isOnline()) { event.send(); @@ -6681,16 +6747,7 @@ export const Content = { }, moveCard: function () { "step 0"; - if ( - !player.canMoveCard( - null, - event.nojudge, - event.sourceTargets, - event.aimTargets, - event.filter, - event.canReplace ? "canReplace" : "noReplace" - ) - ) { + if (!player.canMoveCard(null, event.nojudge, event.sourceTargets, event.aimTargets, event.filter, event.canReplace ? "canReplace" : "noReplace")) { event.finish(); return; } @@ -6699,13 +6756,13 @@ export const Content = { if (ui.selected.targets.length) { if (!get.event("aimTargets").includes(target)) return false; var from = ui.selected.targets[0]; - var js = from.getCards("j", filterCard); + var js = from.getVCards("j", filterCard); for (var i = 0; i < js.length; i++) { if (_status.event.nojudge) break; if (target.canAddJudge(js[i])) return true; } if (target.isMin()) return false; - var es = from.getCards("e", filterCard); + var es = from.getVCards("e", filterCard); for (var i = 0; i < es.length; i++) { if (target.canEquip(es[i], _status.event.canReplace)) return true; } @@ -6714,7 +6771,7 @@ export const Content = { if (!get.event("sourceTargets").includes(target)) return false; var range = "ej"; if (_status.event.nojudge) range = "e"; - return target.countCards(range, filterCard) > 0; + return target.countVCards(range, filterCard) > 0; } }); next.set("nojudge", event.nojudge || false); @@ -6728,32 +6785,23 @@ export const Content = { if (att > 0) { if ( !_status.event.nojudge && - target.countCards("j", function (card) { + target.countVCards("j", function (card) { if (!filterCard(card)) return false; return game.hasPlayer(function (current) { if (!aimTargets.includes(current)) return false; - return ( - current != target && - current.canAddJudge(card) && - get.attitude(player, current) < 0 - ); + return current != target && current.canAddJudge(card) && get.attitude(player, current) < 0; }); }) ) return 14; if ( - target.countCards("e", function (card) { + target.countVCards("e", function (card) { if (!filterCard(card)) return false; return ( get.value(card, target) < 0 && game.hasPlayer(function (current) { if (!aimTargets.includes(current)) return false; - return ( - current != target && - get.attitude(player, current) < 0 && - current.canEquip(card, _status.event.canReplace) && - get.effect(target, card, player, player) < 0 - ); + return current != target && get.attitude(player, current) < 0 && current.canEquip(card, _status.event.canReplace) && get.effect(target, card, player, player) < 0; }) ); }) > 0 @@ -6763,17 +6811,9 @@ export const Content = { if ( game.hasPlayer(function (current) { if (current != target && get.attitude(player, current) > 0) { - var es = target.getCards("e", filterCard); + var es = target.getVCards("e", filterCard); for (var i = 0; i < es.length; i++) { - if ( - get.value(es[i], target) > 0 && - current.canEquip(es[i], _status.event.canReplace) && - get.effect(current, es[i], player, player) > - (_status.event.canReplace - ? get.effect(target, es[i], player, player) - : 0) - ) - return true; + if (get.value(es[i], target) > 0 && current.canEquip(es[i], _status.event.canReplace) && get.effect(current, es[i], player, player) > (_status.event.canReplace ? get.effect(target, es[i], player, player) : 0)) return true; } } }) @@ -6783,25 +6823,18 @@ export const Content = { } return 0; } - var es = ui.selected.targets[0].getCards("e", filterCard); + var es = ui.selected.targets[0].getVCards("e", filterCard); var i; var att2 = get.sgn(get.attitude(player, ui.selected.targets[0])); for (i = 0; i < es.length; i++) { - if ( - sgnatt != 0 && - att2 != 0 && - sgnatt != att2 && - get.sgn(get.value(es[i], ui.selected.targets[0])) == -att2 && - get.sgn(get.effect(target, es[i], player, target)) == sgnatt && - target.canEquip(es[i], _status.event.canReplace) - ) { + if (sgnatt != 0 && att2 != 0 && sgnatt != att2 && get.sgn(get.value(es[i], ui.selected.targets[0])) == -att2 && get.sgn(get.effect(target, es[i], player, target)) == sgnatt && target.canEquip(es[i], _status.event.canReplace)) { return Math.abs(att); } } if ( i == es.length && (_status.event.nojudge || - !ui.selected.targets[0].countCards("j", function (card) { + !ui.selected.targets[0].countVCards("j", function (card) { if (!filterCard(card)) return false; return target.canAddJudge(card); }) || @@ -6824,7 +6857,17 @@ export const Content = { "step 1"; event.result = result; if (result.bool) { - if (event.logSkill) player.logSkill(event.logSkill, result.targets, false); + if (event.logSkill) { + if (typeof event.logSkill == "string") { + player.logSkill(event.logSkill, result.targets, false); + } else if (Array.isArray(event.logSkill)) { + if (event.logSkill.length >= 3) { + event.logSkill[1] = result.targets; + event.logSkill[2] = false; + } else if (event.logSkill.length) event.logSkill = [event.logSkill[0], result.targets, false]; + player.logSkill.apply(player, event.logSkill); + } + } player.line2(result.targets, "green"); event.targets = result.targets; } else { @@ -6834,64 +6877,78 @@ export const Content = { game.delay(); "step 3"; if (targets.length == 2) { - player - .choosePlayerCard( - "ej", - true, - function (button) { + const dialogArgs = ["请选择要移动的牌"]; + const es = targets[0].getVCards("e", card => { + return event.filter(card) && targets[1].canEquip(card, event.canReplace); + }), + js = event.nojudge + ? [] + : targets[0].getVCards("j", card => { + return event.filter(card) && targets[1].canAddJudge(card); + }); + if (es.length) { + dialogArgs.push(`
        装备区
        `); + dialogArgs.push([es, "vcard"]); + } + if (js.length) { + dialogArgs.push(`
        判定区
        `); + dialogArgs.push([js, "vcard"]); + } + if (es.length + js.length === 1) { + event._result = { + bool: true, + links: es.length > 0 ? es : js, + }; + } else + player + .chooseButton(dialogArgs, true, function (button) { var player = _status.event.player; var targets0 = _status.event.targets0; var targets1 = _status.event.targets1; if (get.attitude(player, targets0) > 0 && get.attitude(player, targets1) < 0) { if (get.position(button.link) == "j") return 12; - if ( - get.value(button.link, targets0) < 0 && - get.effect(targets1, button.link, player, targets1) > 0 - ) - return 10; + if (get.value(button.link, targets0) < 0 && get.effect(targets1, button.link, player, targets1) > 0) return 10; return 0; } else { if (get.position(button.link) == "j") return -10; - return ( - get.value(button.link) * get.effect(targets1, button.link, player, targets1) - ); + return get.value(button.link) * get.effect(targets1, button.link, player, targets1); } - }, - targets[0] - ) - .set("nojudge", event.nojudge || false) - .set("targets0", targets[0]) - .set("targets1", targets[1]) - .set("filterButton", function (button) { - var targets1 = _status.event.targets1; - if (!get.event("filter")(button.link)) return false; - if (get.position(button.link) == "j") { - if (_status.event.nojudge) return false; - return targets1.canAddJudge(button.link); - } else { - return targets1.canEquip(button.link, _status.event.canReplace); - } - }) - .set("filter", event.filter) - .set("canReplace", event.canReplace) - .set("custom", get.copy(event.custom)); + }) + .set("target", targets[0]) + .set("nojudge", event.nojudge || false) + .set("targets0", targets[0]) + .set("targets1", targets[1]) + /*.set("filterButton", function (button) { + var targets1 = _status.event.targets1; + if (!get.event("filter")(button.link)) return false; + if (get.position(button.link) == "j") { + if (_status.event.nojudge) return false; + return targets1.canAddJudge(button.link); + } else { + return targets1.canEquip(button.link, _status.event.canReplace); + } + })*/ + .set("filter", event.filter) + .set("canReplace", event.canReplace) + .set("custom", get.copy(event.custom)); } else { event.finish(); } "step 4"; if (result.bool && result.links.length) { - var link = result.links[0]; - if (get.position(link) == "e") { + var link = result.links[0], + position = "j"; + if (event.targets[0].getVCards("e").includes(link)) { + if (!link.cards?.length) event.targets[0].removeVirtualEquip(link); event.targets[1].equip(link); - } else if (link.viewAs) { - event.targets[1].addJudge({ name: link.viewAs }, [link]); } else { - event.targets[1].addJudge(link); + if (!link.cards?.length) event.targets[0].removeVirtualJudge(link); + event.targets[1].addJudge(link, link?.cards); } - event.targets[0].$give(link, event.targets[1], false); + if (link.cards?.length) event.targets[0].$give(link.cards, event.targets[1], false); game.log(event.targets[0], "的", link, "被移动给了", event.targets[1]); event.result.card = link; - event.result.position = get.position(link); + event.result.position = "e"; game.delay(); } }, @@ -6921,7 +6978,7 @@ export const Content = { cardaudio = false; } if (lib.skill[event.skill].log != false) { - player.logSkill(event.skill); + player.logSkill(event.skill, false, null, null, [event, event.player]); } if (get.info(event.skill).popname) { player.tryCardAnimate(card, event.card.name, "metal", true); @@ -6947,8 +7004,7 @@ export const Content = { event.id = get.id(); if (!Array.isArray(event.excluded)) event.excluded = []; if (!Array.isArray(event.directHit)) event.directHit = []; - if (typeof event.customArgs != "object" || typeof event.customArgs.default != "object") - event.customArgs = { default: {} }; + if (typeof event.customArgs != "object" || typeof event.customArgs.default != "object") event.customArgs = { default: {} }; if (typeof event.baseDamage != "number") event.baseDamage = get.info(card, false).baseDamage || 1; if (typeof event.effectCount != "number") event.effectCount = get.info(card, false).effectCount || 1; event.effectedCount = 0; @@ -7008,8 +7064,7 @@ export const Content = { player.line(lining, "green"); } } else if (card.name == "youdishenru" && event.getParent().source) { - var lining = - event.getParent().sourcex || event.getParent().source2 || event.getParent().source; + var lining = event.getParent().sourcex || event.getParent().source2 || event.getParent().source; if (lining == player && event.getParent().sourcex2) { lining = event.getParent().sourcex2; } @@ -7024,11 +7079,7 @@ export const Content = { if (nature || (card.classList && card.classList.contains(nature))) config.color = nature; if (event.addedTarget) { player.line2(targets.concat(event.addedTargets), config); - } else if ( - get.info(card, false).multitarget && - targets.length > 1 && - !get.info(card, false).multiline - ) { + } else if (get.info(card, false).multitarget && targets.length > 1 && !get.info(card, false).multiline) { player.line2(targets, config); } else { player.line(targets, config); @@ -7039,18 +7090,7 @@ export const Content = { var str = targets.length == 1 && targets[0] == player ? "#b自己" : targets; if (cards.length && !card.isCard) { if (event.addedTarget) { - game.log( - player, - "对", - str, - "使用了", - card, - "(", - cards, - ",指向", - event.addedTargets, - ")" - ); + game.log(player, "对", str, "使用了", card, "(", cards, ",指向", event.addedTargets, ")"); } else { game.log(player, "对", str, "使用了", card, "(", cards, ")"); } @@ -7259,12 +7299,7 @@ export const Content = { next.skill = event.skill; next.type = "precard"; if (event.forceDie) next.forceDie = true; - } else if ( - info.singleCard && - info.filterAddedTarget && - event.addedTargets && - event.addedTargets.length < targets.length - ) { + } else if (info.singleCard && info.filterAddedTarget && event.addedTargets && event.addedTargets.length < targets.length) { var next = game.createEvent(card.name + "ContentBefore"); next.setContent("addExtraTarget"); next.target = target; @@ -7391,7 +7426,7 @@ export const Content = { if (!info.noForceDie) event.forceDie = true; if (!info.noForceOut) event.includeOut = true; event._skill = event.skill; - game.trySkillAudio(event.skill, player); + game.trySkillAudio(event.skill, player, null, null, null, [event, event.player]); var checkShow = player.checkShow(event.skill); if (info.discard != false && info.lose != false && !info.viewAs) { player.discard(cards).delay = false; @@ -7443,8 +7478,7 @@ export const Content = { } var str = ""; if (targets && targets.length && info.log != "notarget") { - str += - '对' + (targets[0] == player ? "自己" : get.translation(targets[0])); + str += '对' + (targets[0] == player ? "自己" : get.translation(targets[0])); for (var i = 1; i < targets.length; i++) { str += "、" + (targets[i] == player ? "自己" : get.translation(targets[i])); } @@ -7582,11 +7616,7 @@ export const Content = { } } var info = get.info(event.skill); - if ( - (targets[num] && targets[num].isDead()) || - (targets[num] && targets[num].isOut()) || - (targets[num] && targets[num].removed) - ) { + if ((targets[num] && targets[num].isDead()) || (targets[num] && targets[num].isOut()) || (targets[num] && targets[num].removed)) { if (!info.multitarget && num < targets.length - 1) { event.num++; event.redo(); @@ -7653,8 +7683,7 @@ export const Content = { console.log(player.name, event.skill); } if (document.getElementsByClassName("thrown").length) { - if (event.skill && get.info(event.skill).delay !== false && get.info(event.skill).delay !== 0) - game.delayx(); + if (event.skill && get.info(event.skill).delay !== false && get.info(event.skill).delay !== 0) game.delayx(); } else { event.finish(); } @@ -7703,8 +7732,7 @@ export const Content = { if (event.animate != false) { if (event.visible) { next = player.gain(cards, "gain2"); - if (event.bottom) - game.log(player, "从牌堆底摸了" + get.cnNumber(num) + "张牌(", cards, ")"); + if (event.bottom) game.log(player, "从牌堆底摸了" + get.cnNumber(num) + "张牌(", cards, ")"); else game.log(player, "摸了" + get.cnNumber(num) + "张牌(", cards, ")"); } else { next = player.gain(cards, "draw"); @@ -7869,6 +7897,12 @@ export const Content = { next.delay = false; } "step 3"; + event.vcards1?.forEach(card => { + player.removeVirtualEquip(card); + }); + event.vcards2?.forEach(card => { + target.removeVirtualEquip(card); + }); if (!event.delayed) game.delay(); }, gainMultiple: function () { @@ -7913,11 +7947,7 @@ export const Content = { event.losing_map = map; for (var i in map) { var owner = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; - var next = owner - .lose(map[i][0], ui.special) - .set("type", "gain") - .set("forceDie", true) - .set("getlx", false); + var next = owner.lose(map[i][0], ui.special).set("type", "gain").set("forceDie", true).set("getlx", false); if (event.visible == true) { next.visible = true; } @@ -7996,11 +8026,7 @@ export const Content = { } var addv = function () { if (player == game.me) { - game.addVideo("gain12", player, [ - get.cardsInfo(frag1.childNodes), - get.cardsInfo(frag2.childNodes), - event.gaintag, - ]); + game.addVideo("gain12", player, [get.cardsInfo(frag1.childNodes), get.cardsInfo(frag2.childNodes), event.gaintag]); } }; var broadcast = function () { @@ -8018,42 +8044,51 @@ export const Content = { if (event.animate == "draw") { player.$draw(cards.length); game.pause(); - setTimeout(function () { - addv(); - player.node.handcards1.insertBefore(frag1, player.node.handcards1.firstChild); - player.node.handcards2.insertBefore(frag2, player.node.handcards2.firstChild); - player.update(); - if (player == game.me) ui.updatehl(); - broadcast(); - game.resume(); - }, get.delayx(500, 500)); + setTimeout( + function () { + addv(); + player.node.handcards1.insertBefore(frag1, player.node.handcards1.firstChild); + player.node.handcards2.insertBefore(frag2, player.node.handcards2.firstChild); + player.update(); + if (player == game.me) ui.updatehl(); + broadcast(); + game.resume(); + }, + get.delayx(500, 500) + ); } else if (event.animate == "gain") { player.$gain(cards, event.log); game.pause(); - setTimeout(function () { - addv(); - player.node.handcards1.insertBefore(frag1, player.node.handcards1.firstChild); - player.node.handcards2.insertBefore(frag2, player.node.handcards2.firstChild); - player.update(); - if (player == game.me) ui.updatehl(); - broadcast(); - game.resume(); - }, get.delayx(700, 700)); + setTimeout( + function () { + addv(); + player.node.handcards1.insertBefore(frag1, player.node.handcards1.firstChild); + player.node.handcards2.insertBefore(frag2, player.node.handcards2.firstChild); + player.update(); + if (player == game.me) ui.updatehl(); + broadcast(); + game.resume(); + }, + get.delayx(700, 700) + ); } else if (event.animate == "gain2" || event.animate == "draw2") { var gain2t = 300; if (player.$gain2(cards, event.log) && player == game.me) { gain2t = 500; } game.pause(); - setTimeout(function () { - addv(); - player.node.handcards1.insertBefore(frag1, player.node.handcards1.firstChild); - player.node.handcards2.insertBefore(frag2, player.node.handcards2.firstChild); - player.update(); - if (player == game.me) ui.updatehl(); - broadcast(); - game.resume(); - }, get.delayx(gain2t, gain2t)); + setTimeout( + function () { + addv(); + player.node.handcards1.insertBefore(frag1, player.node.handcards1.firstChild); + player.node.handcards2.insertBefore(frag2, player.node.handcards2.firstChild); + player.update(); + if (player == game.me) ui.updatehl(); + broadcast(); + game.resume(); + }, + get.delayx(gain2t, gain2t) + ); } else if (event.animate == "give" || event.animate == "giveAuto") { var evtmap = event.losing_map; if (event.animate == "give") { @@ -8069,27 +8104,33 @@ export const Content = { } } game.pause(); - setTimeout(function () { - addv(); - player.node.handcards1.insertBefore(frag1, player.node.handcards1.firstChild); - player.node.handcards2.insertBefore(frag2, player.node.handcards2.firstChild); - player.update(); - if (player == game.me) ui.updatehl(); - broadcast(); - game.resume(); - }, get.delayx(500, 500)); + setTimeout( + function () { + addv(); + player.node.handcards1.insertBefore(frag1, player.node.handcards1.firstChild); + player.node.handcards2.insertBefore(frag2, player.node.handcards2.firstChild); + player.update(); + if (player == game.me) ui.updatehl(); + broadcast(); + game.resume(); + }, + get.delayx(500, 500) + ); } else if (typeof event.animate == "function") { var time = event.animate(event); game.pause(); - setTimeout(function () { - addv(); - player.node.handcards1.insertBefore(frag1, player.node.handcards1.firstChild); - player.node.handcards2.insertBefore(frag2, player.node.handcards2.firstChild); - player.update(); - if (player == game.me) ui.updatehl(); - broadcast(); - game.resume(); - }, get.delayx(time, time)); + setTimeout( + function () { + addv(); + player.node.handcards1.insertBefore(frag1, player.node.handcards1.firstChild); + player.node.handcards2.insertBefore(frag2, player.node.handcards2.firstChild); + player.update(); + if (player == game.me) ui.updatehl(); + broadcast(); + game.resume(); + }, + get.delayx(time, time) + ); } else { addv(); player.node.handcards1.insertBefore(frag1, player.node.handcards1.firstChild); @@ -8122,11 +8163,7 @@ export const Content = { event.losing_map = map; for (var i in map) { var owner = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; - var next = owner - .lose(map[i][0], ui.special) - .set("type", "loseToExpansion") - .set("forceDie", true) - .set("getlx", false); + var next = owner.lose(map[i][0], ui.special).set("type", "loseToExpansion").set("forceDie", true).set("getlx", false); if (event.visible == true) next.visible = true; event.relatedLose = next; } @@ -8175,30 +8212,39 @@ export const Content = { player.$draw(cards.length); if (event.log) game.log(player, "将", get.cnNumber(cards.length), "张牌置于了武将牌上"); game.pause(); - setTimeout(function () { - player.$addToExpansion(cards, null, event.gaintag); - for (var i of event.gaintag) player.markSkill(i); - game.resume(); - }, get.delayx(500, 500)); + setTimeout( + function () { + player.$addToExpansion(cards, null, event.gaintag); + for (var i of event.gaintag) player.markSkill(i); + game.resume(); + }, + get.delayx(500, 500) + ); } else if (event.animate == "gain") { player.$gain(cards, false); game.pause(); - setTimeout(function () { - player.$addToExpansion(cards, null, event.gaintag); - for (var i of event.gaintag) player.markSkill(i); - game.resume(); - }, get.delayx(700, 700)); + setTimeout( + function () { + player.$addToExpansion(cards, null, event.gaintag); + for (var i of event.gaintag) player.markSkill(i); + game.resume(); + }, + get.delayx(700, 700) + ); } else if (event.animate == "gain2" || event.animate == "draw2") { var gain2t = 300; if (player.$gain2(cards) && player == game.me) { gain2t = 500; } game.pause(); - setTimeout(function () { - player.$addToExpansion(cards, null, event.gaintag); - for (var i of event.gaintag) player.markSkill(i); - game.resume(); - }, get.delayx(gain2t, gain2t)); + setTimeout( + function () { + player.$addToExpansion(cards, null, event.gaintag); + for (var i of event.gaintag) player.markSkill(i); + game.resume(); + }, + get.delayx(gain2t, gain2t) + ); } else if (event.animate == "give" || event.animate == "giveAuto") { var evtmap = event.losing_map; if (event.animate == "give") { @@ -8212,8 +8258,7 @@ export const Content = { var source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; if (evtmap[i][1].length) { source.$giveAuto(evtmap[i][1], player, false); - if (event.log) - game.log(player, "将", get.cnNumber(evtmap[i][1].length), "张牌置于了武将牌上"); + if (event.log) game.log(player, "将", get.cnNumber(evtmap[i][1].length), "张牌置于了武将牌上"); } if (evtmap[i][2].length) { source.$give(evtmap[i][2], player, false); @@ -8222,19 +8267,25 @@ export const Content = { } } game.pause(); - setTimeout(function () { - player.$addToExpansion(cards, null, event.gaintag); - for (var i of event.gaintag) player.markSkill(i); - game.resume(); - }, get.delayx(500, 500)); + setTimeout( + function () { + player.$addToExpansion(cards, null, event.gaintag); + for (var i of event.gaintag) player.markSkill(i); + game.resume(); + }, + get.delayx(500, 500) + ); } else if (typeof event.animate == "function") { var time = event.animate(event); game.pause(); - setTimeout(function () { - player.$addToExpansion(cards, null, event.gaintag); - for (var i of event.gaintag) player.markSkill(i); - game.resume(); - }, get.delayx(time, time)); + setTimeout( + function () { + player.$addToExpansion(cards, null, event.gaintag); + for (var i of event.gaintag) player.markSkill(i); + game.resume(); + }, + get.delayx(time, time) + ); } else { player.$addToExpansion(cards, null, event.gaintag); for (var i of event.gaintag) player.markSkill(i); @@ -8247,10 +8298,7 @@ export const Content = { lose: function () { "step 0"; var evt = event.getParent(); - if ( - (evt.name != "discard" || event.type != "discard") && - (evt.name != "loseToDiscardpile" || event.type != "loseToDiscardpile") - ) { + if ((evt.name != "discard" || event.type != "discard") && (evt.name != "loseToDiscardpile" || event.type != "loseToDiscardpile")) { event.delay = false; return; } @@ -8320,20 +8368,35 @@ export const Content = { if (cards[i].parentNode.classList.contains("equips")) { cards[i].original = "e"; es.push(cards[i]); + const VEquip = player.getVCards("e").find(card => { + return card.cards?.includes(cards[i]); + }); + if (VEquip) { + event.vcard_map.set(cards[i], VEquip); + } else event.vcard_map.set(cards[i], get.autoViewAs(cards[i], void 0, false)); } else if (cards[i].parentNode.classList.contains("judges")) { cards[i].original = "j"; js.push(cards[i]); + const VJudge = player.getVCards("j").find(card => { + return card.cards?.includes(cards[i]); + }); + if (VJudge) { + event.vcard_map.set(cards[i], VJudge); + } else event.vcard_map.set(cards[i], get.autoViewAs(cards[i], void 0, false)); } else if (cards[i].parentNode.classList.contains("expansions")) { cards[i].original = "x"; xs.push(cards[i]); + event.vcard_map.set(cards[i], get.autoViewAs(cards[i], void 0, false)); if (cards[i].gaintag && cards[i].gaintag.length) unmarks.addArray(cards[i].gaintag); } else if (cards[i].parentNode.classList.contains("handcards")) { if (cards[i].classList.contains("glows")) { cards[i].original = "s"; ss.push(cards[i]); + event.vcard_map.set(cards[i], get.autoViewAs(cards[i], void 0, false)); } else { cards[i].original = "h"; hs.push(cards[i]); + event.vcard_map.set(cards[i], get.autoViewAs(cards[i], void 0, player)); } } else { cards[i].original = null; @@ -8357,11 +8420,7 @@ export const Content = { continue; } } else if ("destroyed" in cards[i]) { - if ( - event.getlx !== false && - event.position && - cards[i].willBeDestroyed(event.position.id, null, event) - ) { + if (event.getlx !== false && event.position && cards[i].willBeDestroyed(event.position.id, null, event)) { cards[i].selfDestroy(event); continue; } @@ -8413,12 +8472,7 @@ export const Content = { cards, ui.cardPile.childNodes.length ); - game.addVideo("lose", player, [ - get.cardsInfo(hs), - get.cardsInfo(es), - get.cardsInfo(js), - get.cardsInfo(ss), - ]); + game.addVideo("lose", player, [get.cardsInfo(hs), get.cardsInfo(es), get.cardsInfo(js), get.cardsInfo(ss)]); event.cards2 = hs.concat(es); player.getHistory("lose").push(event); game.getGlobalHistory().cardMove.push(event); @@ -8444,11 +8498,7 @@ export const Content = { } if (unmarks.length) { for (var i of unmarks) { - player[ - (lib.skill[i] && lib.skill[i].mark) || player.hasCard((card) => card.hasGaintag(i), "x") - ? "markSkill" - : "unmarkSkill" - ](i); + player[(lib.skill[i] && lib.skill[i].mark) || player.hasCard(card => card.hasGaintag(i), "x") ? "markSkill" : "unmarkSkill"](i); } } event.hs = hs; @@ -8458,7 +8508,7 @@ export const Content = { event.xs = xs; game.clearCardKnowers(hs); if (hs.length && !event.visible) { - player.getCards("h").forEach((hcard) => { + player.getCards("h").forEach(hcard => { hcard.clearKnowers(); }); } @@ -8466,11 +8516,25 @@ export const Content = { if (num < cards.length) { if (event.es.includes(cards[num])) { event.loseEquip = true; - player.removeEquipTrigger(cards[num]); - var info = get.info(cards[num]); - if (info.onLose && (!info.filterLose || info.filterLose(cards[num], player))) { - event.goto(3); - return; + const VEquip = player.getVCards("e").find(card => { + return card.cards?.includes(cards[num]); + }); + if (VEquip) { + player.removeVirtualEquip(VEquip); + //player.removeEquipTrigger(cards[num]); + var info = get.info(VEquip, false); + if (info.onLose && (!info.filterLose || info.filterLose(VEquip, player))) { + event.goto(3); + event.currentVEquip = VEquip; + return; + } + } + } else if (event.js.includes(cards[num])) { + const VJudge = player.getVCards("j").find(card => { + return card.cards?.includes(cards[num]); + }); + if (VJudge) { + player.removeVirtualJudge(VJudge); } } event.num++; @@ -8482,25 +8546,28 @@ export const Content = { event.goto(4); } "step 3"; - var info = get.info(cards[num]); + const VEquip = event.currentVEquip; + var info = get.info(VEquip, false); if (info.loseDelay != false && (player.isAlive() || info.forceDie)) { - player.popup(cards[num].name); + player.popup(VEquip.name); game.delayx(); } if (Array.isArray(info.onLose)) { for (var i = 0; i < info.onLose.length; i++) { - var next = game.createEvent("lose_" + cards[num].name); + var next = game.createEvent("lose_" + VEquip.name); next.setContent(info.onLose[i]); if (info.forceDie) next.forceDie = true; next.player = player; - next.card = cards[num]; + next.card = VEquip; + next.cards = VEquip.cards; } } else { - var next = game.createEvent("lose_" + cards[num].name); + var next = game.createEvent("lose_" + VEquip.name); next.setContent(info.onLose); next.player = player; if (info.forceDie) next.forceDie = true; - next.card = cards[num]; + next.card = VEquip; + next.cards = VEquip.cards; } event.num++; event.goto(2); @@ -8520,13 +8587,7 @@ export const Content = { } "step 5"; var evt = event.getParent(); - if ( - evt.name != "discard" && - event.type != "discard" && - evt.name != "loseToDiscardpile" && - event.type != "loseToDiscardpile" - ) - return; + if (evt.name != "discard" && event.type != "discard" && evt.name != "loseToDiscardpile" && event.type != "loseToDiscardpile") return; if (event.animate === false || event.delay === false) return; if (evt.delay != false) { if (evt.waitingForTransition) { @@ -8579,11 +8640,7 @@ export const Content = { }, damageAudioInfo); } var str = event.unreal ? "视为受到了" : "受到了"; - if (source) - str += - '来自' + - (source == player ? "自己" : get.translation(source)) + - "的"; + if (source) str += '来自' + (source == player ? "自己" : get.translation(source)) + "的"; str += get.cnNumber(num) + "点"; if (event.nature) str += get.translation(event.nature) + "属性"; str += "伤害"; @@ -8718,8 +8775,8 @@ export const Content = { loseHp: function () { "step 0"; if (event.num <= 0) { - event.finish(); event._triggered = null; + event.finish(); return; } if (lib.config.background_audio) { @@ -8768,12 +8825,7 @@ export const Content = { //add to GlobalHistory game.getGlobalHistory().changeHp.push(event); //changeHujia moved here - if ( - num < 0 && - player.hujia > 0 && - event.getParent().name == "damage" && - !player.hasSkillTag("nohujia") - ) { + if (num < 0 && player.hujia > 0 && event.getParent().name == "damage" && !player.hasSkillTag("nohujia")) { event.hujia = Math.min(-num, player.hujia); event.getParent().hujia = event.hujia; event.num += event.hujia; @@ -8926,7 +8978,6 @@ export const Content = { game.players.remove(player); game.dead.push(player); _status.dying.remove(player); - }, player); game.tryDieAudio(player); @@ -8966,24 +9017,9 @@ export const Content = { } } if (_status.characterlist) { - if ( - lib.character[player.name] && - !player.name.startsWith("gz_shibing") && - !player.name.startsWith("gz_jun_") - ) - _status.characterlist.add(player.name); - if ( - lib.character[player.name1] && - !player.name1.startsWith("gz_shibing") && - !player.name1.startsWith("gz_jun_") - ) - _status.characterlist.add(player.name1); - if ( - lib.character[player.name2] && - !player.name2.startsWith("gz_shibing") && - !player.name2.startsWith("gz_jun_") - ) - _status.characterlist.add(player.name2); + if (lib.character[player.name] && !player.name.startsWith("gz_shibing") && !player.name.startsWith("gz_jun_")) _status.characterlist.add(player.name); + if (lib.character[player.name1] && !player.name1.startsWith("gz_shibing") && !player.name1.startsWith("gz_jun_")) _status.characterlist.add(player.name1); + if (lib.character[player.name2] && !player.name2.startsWith("gz_shibing") && !player.name2.startsWith("gz_jun_")) _status.characterlist.add(player.name2); } event.cards = player.getCards("hejsx"); if (event.cards.length) { @@ -9006,13 +9042,7 @@ export const Content = { if (get.config("revive") && lib.mode[lib.config.mode].config.revive && !ui.revive) { ui.revive = ui.create.control("revive", ui.click.dierevive); } - if ( - get.config("continue_game") && - !ui.continue_game && - lib.mode[lib.config.mode].config.continue_game && - !_status.brawl && - !game.no_continue_game - ) { + if (get.config("continue_game") && !ui.continue_game && lib.mode[lib.config.mode].config.continue_game && !_status.brawl && !game.no_continue_game) { ui.continue_game = ui.create.control("再战", game.reloadCurrent); } if (get.config("dierestart") && lib.mode[lib.config.mode].config.dierestart && !ui.restart) { @@ -9034,11 +9064,7 @@ export const Content = { _status.coin += 10; } } - if ( - source && - lib.config.border_style == "auto" && - (lib.config.autoborder_count == "kill" || lib.config.autoborder_count == "mix") - ) { + if (source && lib.config.border_style == "auto" && (lib.config.autoborder_count == "kill" || lib.config.autoborder_count == "mix")) { switch (source.node.framebg.dataset.auto) { case "gold": case "silver": @@ -9073,7 +9099,106 @@ export const Content = { source.classList.add("topcount"); } }, - addJudge: function () { + //暂时还是只能一次加一张牌,需要后续跟进处理 + addJudge: async function (event, trigger, player) { + let card, cardName; + if (typeof event.card == "string") { + cardName = event.card; + card = get.autoViewAs({ name: cardName }, event.cards); + event.card = card; + } else { + cardName = event.card.name; + if (get.itemtype(event.card) === "card") { + event.cards = [event.card]; + card = get.autoViewAs(event.card, void 0, false); + event.card = card; + } else if (!event.card.cards?.length && event.cards?.length) { + card = get.autoViewAs({ name: cardName, isCard: true }, event.cards); + event.card = card; + } else if (!event.cards) { + event.cards = []; + } + } + card = event.card; + const cards = event.cards, + cardInfo = lib.card[cardName], + visible = cardInfo && !cardInfo.blankCard; + event.visible = visible; + //失去牌的一长串 + if (event.cards?.length) { + const map = {}; + for (const i of event.cards) { + var owner = get.owner(i, "judge"); + if (owner/* && (owner != player || get.position(i) != "e")*/) { + var id = owner.playerid; + if (!map[id]) map[id] = [[], [], []]; + map[id][0].push(i); + var position = get.position(i); + if (position == "h") map[id][1].push(i); + else map[id][2].push(i); + } else if (!event.updatePile && get.position(i) == "c") event.updatePile = true; + if (event.visible) i.addKnower("everyone"); + } + event.losing_map = map; + for (const i in map) { + const owner = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; + const next = owner.lose(map[i][0], ui.special).set("type", "addJudge").set("forceDie", true).set("getlx", false); + if (event.visible == true) { + // @ts-ignore + next.visible = true; + } + await next; + event.relatedLose = next; + } + let canMoveOn = true; + event.cards.forEach(card => { + if (card.willBeDestroyed("judge", player, event)) { + card.selfDestroy(event); + canMoveOn = false; + return; + } else if (canMoveOn) { + // @ts-ignore + if ("hejx".includes(get.position(card, true))) { + canMoveOn = false; + return; + } + } + }); + if (!canMoveOn) return; + } + if (!cardInfo.effect && !cardInfo.noEffect) { + if (event.cards.length) await game.cardsDiscard(event.cards); + return; + } + game.broadcastAll( + (player, card, cards) => { + const cardsCloned = cards.filter(card => { + return cards[0].clone && (cards[0].clone.parentNode == player.parentNode || cards[0].clone.parentNode == ui.arena); + }); + if (cardsCloned.length) { + cardsCloned.forEach(card => { + card.clone.moveDelete(player); + }); + game.addVideo("gain2", player, get.cardsInfo(cardsCloned)); + } + }, + player, + event.card, + event.cards + ); + player.addVirtualJudge(event.card, event.cards); + const isViewAsCard = cards?.length !== 1 || cards[0].name !== card.name; + if (isViewAsCard && cards?.length) { + if (cardInfo.blankCard) { + game.log(player, '被扣置了' + get.translation(cardName) + ""); + } else { + game.log(player, '被贴上了' + get.translation(cardName) + "(", cards, ")"); + } + } else { + game.log(player, "被贴上了", card); + } + }, + addJudge_old: function () { "step 0"; const cardName = typeof card == "string" ? card : card.name, cardInfo = lib.card[cardName]; @@ -9120,23 +9245,15 @@ export const Content = { card.style.transform = ""; card.classList.add("drawinghidden"); card.viewAs = viewAs; - if ( - viewAs && - viewAs != card.name && - (card.classList.contains("fullskin") || card.classList.contains("fullborder")) - ) { + if (viewAs && viewAs != card.name && (card.classList.contains("fullskin") || card.classList.contains("fullborder"))) { card.classList.add("fakejudge"); - card.node.background.innerHTML = - lib.translate[viewAs + "_bg"] || get.translation(viewAs)[0]; + card.node.background.innerHTML = lib.translate[viewAs + "_bg"] || get.translation(viewAs)[0]; } else { card.classList.remove("fakejudge"); } player.node.judges.insertBefore(card, player.node.judges.firstChild); ui.updatej(player); - if ( - card.clone && - (card.clone.parentNode == player.parentNode || card.clone.parentNode == ui.arena) - ) { + if (card.clone && (card.clone.parentNode == player.parentNode || card.clone.parentNode == ui.arena)) { card.clone.moveDelete(player); game.addVideo("gain2", player, get.cardsInfo([card])); } @@ -9145,10 +9262,7 @@ export const Content = { cards[0], viewAs ); - if ( - cards[0].clone && - (cards[0].clone.parentNode == player.parentNode || cards[0].clone.parentNode == ui.arena) - ) { + if (cards[0].clone && (cards[0].clone.parentNode == player.parentNode || cards[0].clone.parentNode == ui.arena)) { cards[0].clone.moveDelete(player); game.addVideo("gain2", player, get.cardsInfo(cards)); } @@ -9162,21 +9276,12 @@ export const Content = { if (cards[0].viewAs && cards[0].viewAs != cards[0].name) { if (cards[0].classList.contains("fullskin") || cards[0].classList.contains("fullborder")) { cards[0].classList.add("fakejudge"); - cards[0].node.background.innerHTML = - lib.translate[cards[0].viewAs + "_bg"] || get.translation(cards[0].viewAs)[0]; + cards[0].node.background.innerHTML = lib.translate[cards[0].viewAs + "_bg"] || get.translation(cards[0].viewAs)[0]; } if (lib.card[viewAs].blankCard) { - game.log( - player, - '被扣置了' + get.translation(cards[0].viewAs) + "" - ); + game.log(player, '被扣置了' + get.translation(cards[0].viewAs) + ""); } else { - game.log( - player, - '被贴上了' + get.translation(cards[0].viewAs) + "(", - cards, - ")" - ); + game.log(player, '被贴上了' + get.translation(cards[0].viewAs) + "(", cards, ")"); } } else { cards[0].classList.remove("fakejudge"); @@ -9343,7 +9448,7 @@ export const Content = { game.cardsGotoOrdering(cards); var next = player.chooseToMove(); next.set("list", [["牌堆顶", cards], ["牌堆底"]]); - next.set("prompt", "点击将牌移动到牌堆顶或牌堆底"); + next.set("prompt", "点击或拖动将牌移动到牌堆顶或牌堆底"); next.processAI = event.processAI || function (list) { diff --git a/noname/library/element/contents.js b/noname/library/element/contents.js index 085fbe7a7b..8d708cf187 100644 --- a/noname/library/element/contents.js +++ b/noname/library/element/contents.js @@ -1,391 +1,4 @@ -import { get } from "../../get/index.js"; -import { game } from "../../game/index.js"; -import { lib } from "../index.js"; -import { _status } from "../../status/index.js"; -import { ui } from "../../ui/index.js"; -/** - * @type { SMap<((event: GameEventPromise, trigger: GameEventPromise, player: Player) => Promise)[]> } - */ export const Contents = { - phase: [ - async (event) => { - //规则集中的“回合开始后③(处理“游戏开始时”的时机)” - //提前phaseBefore时机解决“游戏开始时”时机和“一轮开始时”先后 - event.trigger("phaseBefore"); - }, - async (event, _trigger, player) => { - // 初始化阶段列表 - if (!event.phaseList) { - event.phaseList = [ - "phaseZhunbei", - "phaseJudge", - "phaseDraw", - "phaseUse", - "phaseDiscard", - "phaseJieshu", - ]; - } - - if (typeof event.num != "number") { - event.num = 0; - } - - // 规则集中的“回合开始后①”,更新游戏轮数,触发“一轮游戏开始时” - let isRound = false; - if (!event.skill) { - isRound = _status.roundSkipped; - if (_status.isRoundFilter) { - isRound = _status.isRoundFilter(event, player); - } else if (_status.seatNumSettled) { - var seatNum = player.getSeatNum(); - if (seatNum != 0) { - // @ts-ignore - if ( - get.itemtype(_status.lastPhasedPlayer) != "player" || - seatNum < _status.lastPhasedPlayer.getSeatNum() - ) - isRound = true; - _status.lastPhasedPlayer = player; - } - } else if (player == _status.roundStart) isRound = true; - if (isRound) { - delete _status.roundSkipped; - game.roundNumber++; - event._roundStart = true; - game.updateRoundNumber(); - for (var i = 0; i < game.players.length; i++) { - // @ts-ignore - if (game.players[i].isOut() && game.players[i].outCount > 0) { - // @ts-ignore - game.players[i].outCount--; - if (game.players[i].outCount == 0 && !game.players[i].outSkills) { - game.players[i].in(); - } - } - } - event.trigger("roundStart"); - } - } - - _status.globalHistory.push({ - cardMove: [], - custom: [], - useCard: [], - changeHp: [], - everything: [], - }); - - const players = game.players.slice(0).concat(game.dead); - for (const current of players) { - // @ts-ignore - current.actionHistory.push({ - useCard: [], - respond: [], - skipped: [], - lose: [], - gain: [], - sourceDamage: [], - damage: [], - custom: [], - useSkill: [], - }); - // @ts-ignore - current.stat.push({ card: {}, skill: {} }); - if (isRound) { - current.getHistory().isRound = true; - current.getStat().isRound = true; - } - } - - if (isRound) { - // @ts-ignore - game.getGlobalHistory().isRound = true; - } - }, - async (event) => { - //规则集中的“回合开始后②(1v1武将登场专用)” - event.trigger("phaseBeforeStart"); - }, - async (event) => { - //规则集中的“回合开始后④(卑弥呼〖纵傀〗的时机)” - event.trigger("phaseBeforeEnd"); - }, - async (event, _trigger, player) => { - //规则集中的“回合开始后⑤”,进行翻面检测 - if (player.isTurnedOver() && !event._noTurnOver) { - event.cancel(); - player.turnOver(); - player.phaseSkipped = true; - var players = game.players.slice(0).concat(game.dead); - for (var i = 0; i < players.length; i++) { - var current = players[i]; - current.getHistory().isSkipped = true; - current.getStat().isSkipped = true; - } - } else { - player.phaseSkipped = false; - player.getHistory().isMe = true; - player.getStat().isMe = true; - } - }, - async (event, _trigger, player) => { - // 规则集中的“回合开始后⑥”,更新“当前回合角色” - // @ts-ignore - while (ui.dialogs.length) { - // @ts-ignore - ui.dialogs[0].close(); - } - - ++game.phaseNumber; - ++player.phaseNumber; - - // @ts-ignore - game.broadcastAll( - (player, num, popup) => { - if (lib.config.glow_phase) { - player.classList.add("glow_phase"); - } - player.phaseNumber = num; - _status.currentPhase = player; - if (popup && lib.config.show_phase_prompt) player.popup("回合开始", null, false); - }, - player, - player.phaseNumber, - !player.noPhaseDelay - ); - - _status.currentPhase = player; - _status.discarded = []; - - game.syncState(); - // @ts-ignore - game.addVideo("phaseChange", player); - - if (game.phaseNumber == 1) { - delete player._start_cards; - if (lib.configOL.observe) { - lib.configOL.observeReady = true; - game.send("server", "config", lib.configOL); - } - } - - game.log(); - game.log(player, "的回合开始"); - player._noVibrate = true; - - if ( - get.config("identity_mode") != "zhong" && - get.config("identity_mode") != "purple" && - !_status.connectMode - ) { - let num; - switch (get.config("auto_identity")) { - case "one": - num = 1; - break; - case "two": - num = 2; - break; - case "three": - num = 3; - break; - case "always": - num = -1; - break; - default: - num = 0; - break; - } - // @ts-ignore - if ( - num && - !_status.identityShown && - game.phaseNumber > game.players.length * num && - game.showIdentity - ) { - if (!_status.video) player.popup("显示身份"); - _status.identityShown = true; - // @ts-ignore - game.showIdentity(false); - } - } - player.ai.tempIgnore = []; - // @ts-ignore - if (ui.land && ui.land.player == player) { - // @ts-ignore - game.addVideo("destroyLand"); - // @ts-ignore - ui.land.destroy(); - } - }, - async (event) => { - //规则集中的“回合开始后⑦”,国战武将明置武将牌 - event.trigger("phaseBeginStart"); - }, - async (event) => { - //规则集中的“回合开始后⑨”,进行当先,化身等操作 - //没有⑧ 因为⑧用不到 - event.trigger("phaseBegin"); - }, - async (event, _trigger, player) => { - if (event.num < event.phaseList.length) { - //规则集中没有的新时机 可以用来插入额外阶段啥的 - if (player.isIn()) event.trigger("phaseChange"); - } else event.goto(11); - }, - async (event, _trigger, player) => { - if (player.isIn() && event.num < event.phaseList.length) { - const phase = event.phaseList[event.num].split("|"); - event.currentPhase = phase[0]; - if (event.currentPhase == "phaseDraw" || event.currentPhase == "phaseDiscard") { - if (!player.noPhaseDelay) { - // @ts-ignore - if (player == game.me) { - await game.asyncDelay(); - // game.delay(); - } else { - await game.asyncDelayx(); - // game.delayx(); - } - } - } - const next = player[event.currentPhase](); - next.phaseIndex = event.num; - if (phase.length > 1) { - next._extraPhaseReason = phase[1]; - } - return await next; - } - }, - async (event, _trigger, player) => { - if (event.currentPhase === "phaseUse") { - // @ts-ignore - game.broadcastAll(() => { - // @ts-ignore - if (ui.tempnowuxie) { - // @ts-ignore - ui.tempnowuxie.close(); - // @ts-ignore - delete ui.tempnowuxie; - } - }); - delete player._noSkill; - } - ++event.num; - }, - async (event) => { - if (event.num < event.phaseList.length) { - event.goto(8); - } else if (!event._phaseEndTriggered) { - event._phaseEndTriggered = true; - event.trigger("phaseEnd"); - event.redo(); - } - }, - async (event) => { - event.trigger("phaseAfter"); - }, - async ({ player }) => { - //删除当前回合角色 此时处于“不属于任何角色的回合”的阶段 - // @ts-ignore - game.broadcastAll((player) => { - player.classList.remove("glow_phase"); - delete _status.currentPhase; - }, player); - }, - ], - phaseDraw: [ - async (event, _trigger, player) => { - game.log(player, "进入了摸牌阶段"); - event.trigger("phaseDrawBegin1"); - }, - async (event) => { - event.trigger("phaseDrawBegin2"); - }, - async (event, _trigger, player) => { - // @ts-ignore - if (game.modPhaseDraw) { - // @ts-ignore - return game.modPhaseDraw(player, event.num); - } else { - if (event.num > 0) { - let num = event.num; - if (event.attachDraw) { - for (let i = 0; i < event.attachDraw.length; i++) { - // @ts-ignore - ui.cardPile.insertBefore(event.attachDraw[i], ui.cardPile.firstChild); - } - num += event.attachDraw.length; - } - const next = player.draw(num); - if (event.attachDraw) { - next.minnum = event.attachDraw.length; - } - return next; - } - } - }, - async (event, _trigger, _player, { result }) => { - if (Array.isArray(result)) { - event.cards = result; - } - }, - ], - changeSkills: [ - async (event, trigger, player) => { - //获取玩家当前已有的技能 - const ownedSkills = player.getSkills(true, false, false); - //去重检查 - event.addSkill.unique(); - event.removeSkill.unique(); - //避免失去还没拥有的技能 - event.removeSkill = event.removeSkill.filter((skill) => ownedSkills.includes(skill)); - const duplicatedSkills = event.addSkill.filter((skill) => event.removeSkill.includes(skill)); - if (duplicatedSkills.length) { - event.addSkill.removeArray(duplicatedSkills); - event.removeSkill.removeArray(duplicatedSkills); - } - //if (!event.addSkill.length&&!event.removeSkill.length) return; - //手动触发时机 - await event.trigger("changeSkillsBefore"); - }, - async (event, trigger, player) => { - await event.trigger("changeSkillsBegin"); - }, - async (event, trigger, player) => { - //处理失去和获得的技能 - if (event.$handle) { - event.$handle(player, event.addSkill, event.removeSkill, event); - } else { - if (event.addSkill.length) { - player.addSkill(event.addSkill); - game.log( - player, - "获得了技能", - ...event.addSkill.map((i) => { - return "#g【" + get.translation(i) + "】"; - }) - ); - } - if (event.removeSkill.length) { - player.removeSkill(event.removeSkill); - game.log( - player, - "失去了技能", - ...event.removeSkill.map((i) => { - return "#g【" + get.translation(i) + "】"; - }) - ); - } - } - }, - async (event, trigger, player) => { - //手动触发时机 - await event.trigger("changeSkillsEnd"); - }, - async (event, trigger, player) => { - await event.trigger("changeSkillsAfter"); - }, - ], + // ? there's nothing, and there must have been nothing forever. }; diff --git a/noname/library/element/gameEvent.js b/noname/library/element/gameEvent.js index 689734ed84..e6e7bb4907 100644 --- a/noname/library/element/gameEvent.js +++ b/noname/library/element/gameEvent.js @@ -1,73 +1,51 @@ -import { get } from "../../get/index.js"; -import { game } from "../../game/index.js"; -import { lib } from "../index.js"; -import { _status } from "../../status/index.js"; -import { ui } from "../../ui/index.js"; -import { AsyncFunction } from "../../util/index.js"; +import { _status, game, get, lib, ui } from "../../../noname.js"; +import security from "../../util/security.js"; +import ContentCompiler from "./GameEvent/compilers/ContentCompiler.js"; +import GameEventManager from "./GameEvent/GameEventManager.js"; +export { GameEventManager, ContentCompiler }; +/** + * @implements { PromiseLike> } + */ export class GameEvent { - /** @type { this & GameEventPromise } */ - #promise; /** - * @param {string | GameEvent} [name] - * @param {false} [trigger] + * @param { string | GameEvent } [name] + * @param { boolean } [trigger] + * @param { GameEventManager } [manager] */ - constructor(name, trigger) { + constructor(name = "", trigger = true, manager = _status.eventManager) { if (name instanceof GameEvent) { const other = name; - [name, trigger] = other.__args; + name = other.name; + manager = other.manager; + trigger = other._triggered !== null; } - if (typeof name == "string") { - this.name = name; - const gameEvent = get.event(); - if (gameEvent) { - const type = `onNext${name[0].toUpperCase()}${name.slice(1)}`; - // @ts-ignore - if (gameEvent.hasHandler(type)) this.pushHandler(...gameEvent.getHandler(type)); - } - game.globalEventHandlers.addHandlerToEvent(this); - } - this.step = 0; - this.finished = false; - /** - * @type {GameEventPromise[]} - */ - this.next = []; - /** - * @type {GameEventPromise[]} - */ - this.after = []; - this.custom = { - add: {}, - replace: {}, - }; - this._aiexclude = []; - this._notrigger = []; - /** - * @type { Result } - */ - // @ts-ignore - this._result = {}; - this._set = []; - /** - * @type {boolean} 这个事件是否使用异步函数处理 - **/ - this.async = false; - /** - * @type {null|((event: GameEvent | PromiseLike)=>void)} 这个异步事件对应Promise的resolve函数 - **/ - this.resolve = null; - /** - * @type {null|((value?: any) => void)} 另一种结束event.content的resolve形式 - **/ - this.resolveContent = null; - if (trigger !== false && !game.online) this._triggered = 0; - this.__args = [name, trigger]; + this.name = name; + this.manager = manager; + if (trigger && !game.online) this._triggered = 0; + game.globalEventHandlers.addHandlerToEvent(this); } static initialGameEvent() { - return new GameEvent().finish().toPromise(); + const event = new GameEvent(); + event.finish(); + return event; + } + get [Symbol.toStringTag]() { + return "GameEvent"; } + /** + * @type { Result } + */ + result; + /** + * @type { string } + */ + name; + /** + * @type { string } + */ + type; /** * @type { Player } */ @@ -108,60 +86,79 @@ export class GameEvent { * @type { number } */ num; + /** + * @type { number } + */ + original_num; /** * @type { GameEvent } */ _trigger; /** - * @type { Result } + * @type { string } */ - _result; + triggername; /** - * @type { number } + * @type { boolean } */ - baseDamage; + notrigger; /** - * @type { Player } + * @type { Player[] } */ - customSource; + _notrigger = []; /** - * @type { number } + * @type { Result } */ - extraDamage; + //@ts-ignore + _result = {}; /** - * @type { string } + * @type { any[] } */ - nature; + _args = []; /** - * @type { boolean } + * @type { [string, any][] } */ - notrigger; + _set = []; /** - * @type { number } + * @type { { + * add: {[type: string]: () => void} + * replace: {[type :string]: () => void} + * } } */ - original_num; + custom = { + add: {}, + replace: {}, + }; /** * @type { boolean } */ - unreal; + directHit = false; /** - * @type { Button[] } + * @type { number } */ - excludeButton; + baseDamage; /** - * @type { Result } + * @type { number } */ - result; + extraDamage; /** - * @type { GameEventPromise | void | null } + * @type { Player } */ - parent; + customSource; /** * @type { string } */ - name; + nature; /** - * @type { (this: GameEventPromise) => any | undefined | void | null } + * @type { boolean } + */ + unreal; + /** + * @type { Button[] } + */ + excludeButton; + /** + * @type { ((this: this) => boolean) | undefined } */ filterStop; /** @@ -193,13 +190,9 @@ export class GameEvent { */ ai; /** - * @type { string } - */ - triggername; - /** - * @type { ContentFuncByAll | GeneratorContentFuncByAll | OldContentFuncByAll } + * @type { string[] } */ - content; + _aiexclude = []; /** * @type { boolean } */ @@ -268,7 +261,7 @@ export class GameEvent { */ callHandler(type, event, option) { if (this.hasHandler(type)) - this.getHandler(type).forEach((handler) => { + this.getHandler(type).forEach(handler => { if (typeof handler == "function") handler(event, option); }); return this; @@ -276,6 +269,12 @@ export class GameEvent { getDefaultHandlerType() { const eventName = this.name; if (eventName) return `on${eventName[0].toUpperCase()}${eventName.slice(1)}`; + else return ""; + } + getDefaultNextHandlerType() { + const eventName = this.name; + if (eventName) return `onNext${eventName[0].toUpperCase()}${eventName.slice(1)}`; + else return ""; } /** * @param {Parameters[0]} [type] @@ -313,18 +312,7 @@ export class GameEvent { * @returns {number} */ pushHandler(type) { - return typeof type == "string" - ? this.getHandler(type).push(...Array.from(arguments).slice(1)) - : this.getHandler().push(...arguments); - } - changeToZero() { - this.num = 0; - this.numFixed = true; - return this; - } - finish() { - this.finished = true; - return this; + return typeof type == "string" ? this.getHandler(type).push(...Array.from(arguments).slice(1)) : this.getHandler().push(...arguments); } putStepCache(key, value) { if (!this._stepCache) { @@ -374,41 +362,54 @@ export class GameEvent { } return this._tempCache[key1][key2]; } - cancel(arg1, arg2, notrigger) { - this.untrigger(arg1, arg2); - // this.forceFinish(); - this.finish(); - if (typeof this.resolveContent == 'function') { - this.resolveContent(); - } - if (notrigger != "notrigger") { - if (this.player && lib.phaseName.includes(this.name)) - this.player.getHistory("skipped").add(this.name); - return this.trigger(this.name + "Cancelled"); - } - return null; + changeToZero() { + this.num = 0; + this.numFixed = true; + return this; } - neutralize(event) { - this.untrigger(); + finish() { + this.finished = true; + } + cancel(all, player, notrigger) { + this.untrigger(all, player); + let next; + if (!notrigger) { + if (this.player && lib.phaseName.includes(this.name)) this.player.getHistory("skipped").add(this.name); + next = this.trigger(this.name + "Cancelled"); + } this.finish(); + return next; + } + async neutralize(event = _status.event) { + if (this._neutralized) return this._triggering; this._neutralized = true; - this.trigger("eventNeutralized"); - this._neutralize_event = event || _status.event; - return this; + this._neutralize_event = event; + const next = this.trigger("eventNeutralized"); + if (next) + next.filterStop = function () { + if (!this._neutralized) { + delete this.filterStop; + return true; + } + return false; + }; + await next; + if (this._neutralized == true) { + this.untrigger(); + this.finish(); + } } unneutralize() { - this.untrigger(); - delete this._neutralized; - delete this.finished; + if (!this._neutralized) return; + this._neutralized = false; if (this.type == "card" && this.card && this.name == "sha") this.directHit = true; - return this; } goto(step) { - this.step = step - 1; + this.step = step; return this; } redo() { - this.step--; + this.goto(this.step); return this; } setHiddenSkill(skill) { @@ -437,58 +438,11 @@ export class GameEvent { return this; } /** - * @param {ArrayLike | Function | keyof typeof lib.element.content} item - */ - setContent(item) { - switch (typeof item) { - case "object": - case "function": - if (item instanceof AsyncFunction) { - this.content = item; - } else this.content = lib.init.parsex(item); - break; - default: - try { - if ( - !(lib.element.content[item] instanceof AsyncFunction) && - // @ts-ignore - !lib.element.content[item]._parsed - ) { - lib.element.content[item] = lib.init.parsex(lib.element.content[item]); - // @ts-ignore - lib.element.content[item]._parsed = true; - } - } catch { - throw new Error( - `Content ${item} may not exist.\nlib.element.content[${item}] = ${lib.element.content[item]}` - ); - } - - if (typeof lib.element.content[item] === "undefined") - throw new Error(`Cannot find lib.element.content[${item}]`); - // Generator的状态重置 - else if (lib.element.content[item]._gen) { - this.content = lib.element.content[item].bind({ - gen: null, - last: undefined, - }); - } else { - this.content = lib.element.content[item]; - } - break; - } - return this; - } - - /** - * - * @param {Function | keyof typeof lib.element.contents} contents - * @returns {GameEvent} + * @param {import("./GameEvent/compilers/IContentCompiler.js").EventCompileable} content */ - setContents(contents) { - if (Array.isArray(contents)) this.contents = contents; - else if (contents in lib.element.contents) return this.setContents(lib.element.contents[contents]); - else throw new Error("not supported value."); + setContent(content) { + if (this.#inContent) throw new Error("Cannot set content when content is running"); + this.content = ContentCompiler.compile(content); return this; } @@ -544,12 +498,7 @@ export class GameEvent { let i = 0; const toreturn = forced ? null : {}; const historys = []; - const filter = - typeof level === "function" - ? level - : typeof level === "number" - ? (evt) => i === level - : (evt) => evt.name === level; + const filter = typeof level === "function" ? level : typeof level === "number" ? evt => i === level : evt => evt.name === level; while (true) { if (!event) return toreturn; historys.push(event); @@ -561,7 +510,7 @@ export class GameEvent { } } getTrigger() { - return this.getParent((e) => e._trigger, false, true)._trigger; + return this.getParent(e => e._trigger, false, true)._trigger; } getRand(name) { if (name) { @@ -573,17 +522,17 @@ export class GameEvent { return this._rand; } insert(content, map) { - const next = new lib.element.GameEvent(`${this.name}Inserted`, false).toPromise(); + const next = new GameEvent(`${this.name}Inserted`, false, this.manager); this.next.push(next); next.setContent(content); - Object.entries(map).forEach((entry) => next.set(entry[0], entry[1])); + Object.entries(map).forEach(entry => next.set(entry[0], entry[1])); return next; } insertAfter(content, map) { - const next = new lib.element.GameEvent(`${this.name}Inserted`, false).toPromise(); + const next = new GameEvent(`${this.name}Inserted`, false, this.manager); this.after.push(next); next.setContent(content); - Object.entries(map).forEach((entry) => next.set(entry[0], entry[1])); + Object.entries(map).forEach(entry => next.set(entry[0], entry[1])); return next; } backup(skill) { @@ -759,15 +708,15 @@ export class GameEvent { while (true) { evt = evt.getParent("arrangeTrigger"); if (!evt || evt.name != "arrangeTrigger" || !evt.doingList) return this; - const doing = evt.doingList.find((i) => i.player === player); - const firstDo = evt.doingList.find((i) => i.player === "firstDo"); - const lastDo = evt.doingList.find((i) => i.player === "lastDo"); + const doing = evt.doingList.find(i => i.player === player); + const firstDo = evt.doingList.find(i => i.player === "firstDo"); + const lastDo = evt.doingList.find(i => i.player === "lastDo"); - skills.forEach((skill) => { + skills.forEach(skill => { const info = lib.skill[skill]; if (!info.trigger) return; if ( - !Object.keys(info.trigger).some((i) => { + !Object.keys(info.trigger).some(i => { if (Array.isArray(info.trigger[i])) return info.trigger[i].includes(evt.triggername); return info.trigger[i] === evt.triggername; }) @@ -781,14 +730,10 @@ export class GameEvent { }; const map = info.firstDo ? firstDo : info.lastDo ? lastDo : doing; if (!map) return; - if (map.doneList.some((i) => i.skill === toadd.skill && i.player === toadd.player)) return; - if (map.todoList.some((i) => i.skill === toadd.skill && i.player === toadd.player)) return; + if (map.doneList.some(i => i.skill === toadd.skill && i.player === toadd.player)) return; + if (map.todoList.some(i => i.skill === toadd.skill && i.player === toadd.player)) return; map.todoList.add(toadd); - if (typeof map.player === "string") - map.todoList.sort( - (a, b) => - b.priority - a.priority || evt.playerMap.indexOf(a) - evt.playerMap.indexOf(b) - ); + if (typeof map.player === "string") map.todoList.sort((a, b) => b.priority - a.priority || evt.playerMap.indexOf(a) - evt.playerMap.indexOf(b)); else map.todoList.sort((a, b) => b.priority - a.priority); }); } @@ -801,19 +746,24 @@ export class GameEvent { while (true) { evt = evt.getParent("arrangeTrigger"); if (!evt || evt.name != "arrangeTrigger" || !evt.doingList) return this; - const doing = evt.doingList.find((i) => i.player == player); - const firstDo = evt.doingList.find((i) => i.player == "firstDo"); - const lastDo = evt.doingList.find((i) => i.player == "lastDo"); + const doing = evt.doingList.find(i => i.player == player); + const firstDo = evt.doingList.find(i => i.player == "firstDo"); + const lastDo = evt.doingList.find(i => i.player == "lastDo"); - skills.forEach((skill) => - [doing, firstDo, lastDo].forEach((map) => { + skills.forEach(skill => + [doing, firstDo, lastDo].forEach(map => { if (!map) return; - const toremove = map.todoList.filter((i) => i.skill == skill && i.player == player); + const toremove = map.todoList.filter(i => i.skill == skill && i.player == player); if (toremove.length > 0) map.todoList.removeArray(toremove); }) ); } } + /** + * + * @param { string } name + * @returns { GameEvent } + */ trigger(name) { if (_status.video) return; if (!_status.gameDrawed && ["lose", "gain", "loseAsync", "equip", "addJudge", "addToExpansion"].includes(this.name)) return; @@ -830,9 +780,7 @@ export class GameEvent { if (!game.players || !game.players.length) return; const event = this; if (event.filterStop && event.filterStop()) return; - let start = [_status.currentPhase, event.source, event.player, game.me, game.players[0]].find( - (i) => get.itemtype(i) == "player" - ); + let start = [_status.currentPhase, event.source, event.player, game.me, game.players[0]].find(i => get.itemtype(i) == "player"); if (!start) return; if (!game.players.includes(start) && !game.dead.includes(start)) start = game.findNext(start); const firstDo = { @@ -858,20 +806,16 @@ export class GameEvent { listAdded: {}, addList(skill) { if (!skill) return; - if (Array.isArray(skill)) return skill.forEach((i) => this.addList(i)); + if (Array.isArray(skill)) return skill.forEach(i => this.addList(i)); if (this.listAdded[skill]) return; this.listAdded[skill] = true; const info = lib.skill[skill]; - const list = info.firstDo - ? firstDo.todoList - : info.lastDo - ? lastDo.todoList - : this.todoList; + const list = info.firstDo ? firstDo.todoList : info.lastDo ? lastDo.todoList : this.todoList; if (typeof info.getIndex === "function") { const indexedResult = info.getIndex(event, player, name); if (Array.isArray(indexedResult)) { - indexedResult.forEach((indexedData) => { + indexedResult.forEach(indexedData => { list.push({ skill: skill, player: this.player, @@ -896,10 +840,7 @@ export class GameEvent { priority: get.priority(skill), }); } - if (typeof list.player == "string") - list.sort( - (a, b) => b.priority - a.priority || playerMap.indexOf(a) - playerMap.indexOf(b) - ); + if (typeof list.player == "string") list.sort((a, b) => b.priority - a.priority || playerMap.indexOf(a) - playerMap.indexOf(b)); else list.sort((a, b) => b.priority - a.priority); allbool = true; }, @@ -910,38 +851,35 @@ export class GameEvent { if (!j.startsWith("hidden:")) notemp.addArray(player.additionalSkills[j]); } Object.keys(player.tempSkills) - .filter((skill) => { + .filter(skill => { if (notemp.includes(skill)) return false; const expire = player.tempSkills[skill]; if (typeof expire === "function") return expire(event, player, name); if (get.objtype(expire) === "object") - return roles.some((role) => { + return roles.some(role => { if (role !== "global" && player !== event[role]) return false; if (Array.isArray(expire[role])) return expire[role].includes(name); return expire[role] === name; }); }) - .forEach((skill) => { + .forEach(skill => { delete player.tempSkills[skill]; player.removeSkill(skill); }); if (lib.config.compatiblemode) { doing.addList( - game - .expandSkills(player.getSkills("invisible").concat(lib.skill.global)) - .filter((skill) => { - const info = get.info(skill); - if (!info || !info.trigger) return false; - return roles.some((role) => { - if (info.trigger[role] === name) return true; - if (Array.isArray(info.trigger[role]) && info.trigger[role].includes(name)) - return true; - }); - }) + game.expandSkills(player.getSkills("invisible").concat(lib.skill.global)).filter(skill => { + const info = get.info(skill); + if (!info || !info.trigger) return false; + return roles.some(role => { + if (info.trigger[role] === name) return true; + if (Array.isArray(info.trigger[role]) && info.trigger[role].includes(name)) return true; + }); + }) ); } else - roles.forEach((role) => { + roles.forEach(role => { doing.addList(lib.hook.globalskill[role + "_" + name]); doing.addList(lib.hook[player.playerid + "_" + role + "_" + name]); }); @@ -962,33 +900,386 @@ export class GameEvent { next.triggername = name; next.playerMap = playerMap; event._triggering = next; + next.then(() => (event._triggering = void 0)); return next; } return null; } untrigger(all = true, player) { - const evt = this._triggering; if (all) { if (all !== "currentOnly") this._triggered = 5; - if (evt && evt.doingList) { - evt.doingList.forEach((doing) => (doing.todoList = [])); - } + if (this._triggering) this._triggering.finish(); } else if (player) { this._notrigger.add(player); - // if(!evt||!evt.doingList) return this; - // const doing=evt.doingList.find(doing=>doing.player==player); - // if(doing) doing.todoList=[]; } return this; } /** - * 事件转为Promise化 + * @deprecated */ toPromise() { - if (!this.#promise) { - // @ts-ignore - this.#promise = new lib.element.GameEventPromise(this); + return this; + } + /** + * @deprecated + */ + toEvent() { + return this; + } + + /** + * @type { GameEventManager } + */ + manager; + /** + * @type { import("./GameEvent/compilers/IContentCompiler.js").EventCompiledContent } + */ + content; + /** + * content执行中的标志,如果inContent && finished则不执行子事件 + * @type { boolean } + */ + #inContent = false; + /** + * @type { GameEvent | void | null } + */ + parent; + /** + * @type { GameEvent[] } + */ + childEvents = []; + /** + * @type { boolean } + */ + finished = false; + /** + * @type { boolean } + */ + _neutralized = false; + /** + * @type { number | null } + */ + _triggered = null; + /** + * @type { GameEvent | undefined } + */ + _triggering; + /** + * @type { number } + */ + #step = 0; + /** + * @type { number | null } + */ + #nextStep = null; + get step() { + return this.#step; + } + set step(num) { + this.#nextStep = num; + } + updateStep() { + if (this.#nextStep === null) return; + this.#step = this.#nextStep; + this.#nextStep = null; + } + + /** + * @type { GameEvent[] } + */ + next = (() => { + const event = this; + return new Proxy([], { + set(target, p, childEvent, receiver) { + //@ts-ignore + if (childEvent instanceof GameEvent && !target.includes(childEvent)) { + childEvent.parent = event; + const type = childEvent.getDefaultNextHandlerType(); + //@ts-ignore + if (type) childEvent.pushHandler(...event.getHandler(type)); + if (event.#inContent && event.finished) childEvent.resolve(); + } + return Reflect.set(target, p, childEvent); + }, + }); + })(); + /** + * @type { GameEvent[] } + */ + after = []; + /** + * @template TResult1 + * @template TResult2 + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param { ((event: Omit) => TResult1 | Promise) | null } [onfulfilled] The callback to execute when the Promise is resolved. + * @param { ((reason: any) => TResult2 | Promise) | null } [onrejected] The callback to execute when the Promise is rejected. + * @returns { Promise } A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled, onrejected) { + return (this.parent ? this.parent.waitNext() : this.start()).then( + onfulfilled + ? () => { + return onfulfilled( + new Proxy(this, { + get(target, p, receiver) { + if (p === "then") return void 0; + return Reflect.get(target, p, receiver); + }, + }) + ); + } + : onfulfilled, + onrejected + ); + } + /** + * @template TResult + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected.* @param { ((reason: any) => TResult | Promise) | null } [onrejected] The callback to execute when the Promise is rejected. + * @returns { Promise | TResult> } A Promise for the completion of which ever callback is executed. + */ + catch(onrejected) { + return this.then(void 0, onrejected); + } + /** + * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The + * resolved value cannot be modified from the callback. + * @param { (() => void) | null } [onfinally] The callback to execute when the Promise is settled (fulfilled or rejected). + * @returns { Promise> } A Promise for the completion of the callback. + */ + finally(onfinally) { + return this.then( + result => { + if (onfinally) onfinally(); + return result; + }, + err => { + if (onfinally) onfinally(); + throw err; + } + ); + } + /** + * @type { Promise | null } + */ + #start = null; + resolve() { + if (!this.#start) this.#start = Promise.resolve(); + } + start() { + if (this.#start) return this.#start; + this.#start = (async () => { + if (this.parent) this.parent.childEvents.push(this); + game.getGlobalHistory("everything").push(this); + if (this.manager.eventStack.length === 0) this.manager.rootEvent = this; + this.manager.eventStack.push(this); + await this.loop().finally(() => { + this.manager.eventStack.pop(); + }); + })(); + return this.#start; + } + async loop() { + const trigger = async (trigger, to) => { + if (this.type == "card") await this.trigger("useCardTo" + trigger); + await this.trigger(this.name + trigger); + this._triggered = to; + }; + if (await this.checkSkipped()) return; + while (true) { + await this.waitNext(); + if (!this.finished) { + if (this._triggered === 0) await trigger("Before", 1); + else if (this._triggered === 1) await trigger("Begin", 2); + else { + this.#inContent = true; + let next = this.content(this); + if (_status.withError || (_status.connectMode && !lib.config.debug)) { + next = next.catch(error => { + game.print("游戏出错:" + this.name); + game.print(error.toString()); + console.error(error); + }); + } + await next.finally(() => (this.#inContent = false)); + } + } else { + if (this._triggered === 1) await trigger("Omitted", 4); + else if (this._triggered === 2) await trigger("End", 3); + else if (this._triggered === 3) await trigger("After", 4); + //@ts-ignore + else if (this.after.length) this.next.push(this.after.shift()); + else return; + } + } + } + + async checkSkipped() { + if (!this.player || !this.player.skipList.includes(this.name)) return false; + this.player.skipList.remove(this.name); + if (lib.phaseName.includes(this.name)) this.player.getHistory("skipped").add(this.name); + this.finish(); + await this.trigger(this.name + "Skipped"); + return true; + } + + /** + * @type { Promise | null } + */ + #waitNext = null; + waitNext() { + if (this.#waitNext) return this.#waitNext; + this.#waitNext = (async () => { + let result; + while (true) { + await _status.pauseManager.waitPause(); + if (this.manager.tempEvent) { + if (this.manager.tempEvent === this) { + this.manager.tempEvent = void 0; + } else { + this.cancel(true, null, "notrigger"); + return result; + } + } + if (!this.next.length) return result; + const next = this.next[0]; + await next.start(); + if (next.result) result = next.result; + this.next.shift(); + } + })().finally(() => (this.#waitNext = null)); + return this.#waitNext; + } + /** + * 获取 Result 对象中的信息。 + * @example + * ```js + // 示例 1: + const chooseCardResult = await player.chooseCard().forResult(); + // 获取整个结果对象,然后访问如 chooseCardResult.cards 等属性 + + // 示例 2: + const cards = await player.chooseCard().forResult('cards'); + // 获取结果对象中 'cards' 属性的值 + + // 示例 3: + const [success, cards, targets] = await player.chooseCardTarget().forResult('bool', 'cards', 'targets'); + // 获取结果对象中多个属性的值 + // - success 表示是否成功 + // - cards 表示选择的卡片 + // - targets 表示选择的目标 + ``` + * @template {keyof Result} T + * @this GameEvent + * @overload + * @returns {Promise} + * + * @overload + * @param {T} param0 + * @returns {Promise>} + * + * @overload + * @param { T[] } params + * @returns { Promise[]> } + */ + async forResult(...params) { + await this; + if (params.length == 0) return this.result; + if (params.length == 1) return this.result[params[0]]; + return Array.from(params).map(key => this.result[key]); + } + /** + * 返回result中的bool项 + */ + forResultBool() { + return this.forResult("bool"); + } + + /** + * 返回result中的targets项。 + */ + forResultTargets() { + return this.forResult("targets"); + } + + /** + * 返回result中的cards项 + */ + forResultCards() { + return this.forResult("cards"); + } + + /** + * 返回result中的card项 + * + * @returns {Promise|Promise} 返回的card项。 + * + */ + forResultCard() { + return this.forResult("card"); + } + + /** + * 返回result中的control项。 + */ + forResultControl() { + return this.forResult("control"); + } + + /** + * 返回result中的links项。 + */ + forResultLinks() { + return this.forResult("links"); + } + + /** + * 在某个异步事件中调试变量信息 + * + * 注: 在调试步骤中`定义的变量只在当前输入的语句有效` + * + * @example + * 在技能中调试技能content相关的信息 + * ```js + * await event.debugger(); + * ``` + * 在技能中调试触发此技能事件的相关的信息 + * ```js + * await trigger.debugger(); + * ``` + */ + async debugger() { + if (!lib.config.dev) return; + if (security.isSandboxRequired()) throw new Error("当前模式下禁止调试"); + const runCode = function (event, code) { + try { + // 为了使玩家调试时使用var player=xxx时不报错,故使用var + // var { player, _trigger: trigger, _result: result } = event; + var context = { + event, + player: event.player, + trigger: event._trigger, + result: event._result, + }; + return security.exec(`return ${code}`, context); + } catch (error) { + return error; + } + }.bind(window); + + const input = async () => { + const result = await game.promises.prompt("debugger调试"); + + if (result === false) return false; + + const obj = runCode(this, result); + alert(!obj || obj instanceof Error ? String(obj) : get.stringify(obj)); + return true; + }; + + let result = true; + while (result) { + result = await input(); } - return this.#promise; } } diff --git a/noname/library/element/gameEventPromise.js b/noname/library/element/gameEventPromise.js index 47ca7e4abe..191c032ed8 100644 --- a/noname/library/element/gameEventPromise.js +++ b/noname/library/element/gameEventPromise.js @@ -1,338 +1 @@ -import { get } from "../../get/index.js"; -import { game } from "../../game/index.js"; -import { lib } from "../index.js"; -import { _status } from "../../status/index.js"; -import { AsyncFunction } from "../../util/index.js"; -import security from '../../util/security.js'; - -/** - * 将事件Promise化以使用async异步函数来执行事件。 - * - * 事件Promise化后,需要既能使用await等待事件完成, - * 又需要在执行之前对事件进行配置。 - * - * 所以这个类的实例集成了事件和Promise二者的所有属性, - * 且Promise的原有属性无法被修改,一切对这个类实例的属性修改,删除, - * 再配置等操作都会转发到事件对应的属性中。 - * - * @extends {Promise} - * - * @example - * 使用await xx()等待异步事件执行: - * ```js - * await game.xxx().setContent('yyy').set(zzz, 'i'); - * ``` - * 使用await player.xxx()等待异步事件执行: - * ```js - * await player.draw(2); - * game.log('等待', player, '摸牌完成执行log'); - * ``` - */ -export class GameEventPromise extends Promise { - // 我谢谢你,这里是必须有的 - // 否则Promise的方法对其子类无效 - static get [Symbol.species]() { - return Promise; - } - #event; - /** - * @param { GameEvent } arg - */ - constructor(arg) { - if (arg instanceof GameEventPromise) throw new Error("GameEventPromise cannot copy."); - const event = arg; - super((resolve) => { - // 设置为异步事件 - event.async = true; - // 事件结束后触发resolve - event.resolve = resolve; - if (!_status.event) return; - // game.createEvent的时候还没立即push到next里 - Promise.resolve().then(() => { - game.executingAsyncEventMap.set( - _status.event.toEvent(), - (game.executingAsyncEventMap.get(_status.event.toEvent()) || Promise.resolve()).then( - () => { - let eventPromise = _status.event.next.find((e) => e.toEvent() == event); - // 如果父级事件也是一个异步的话,那应该立即执行这个事件的 - // 如果在AsyncFunction执行过程中在别的位置新建了一个异步事件,那也直接(等会set配置完)执行 - if ( - eventPromise && - (_status.event.content instanceof AsyncFunction || - Array.isArray(_status.event.contents)) - ) { - // 异步执行game.loop - // 不直接game.loop(event)是因为需要让别人可以手动set()和setContent() - // 再执行game.loop是因为原有的game.loop被await卡住了, - // 得新执行一个只执行这个异步事件的game.loop - _status.event.next.remove(eventPromise); - - /** - * @param { import("noname-typings/nonameModules/noname/library/index.js").GameEventPromise } event - */ - const check = event => { - if (event.player) { - const { player } = event; - if (player.skipList.includes(event.name)) { - _status.event.trigger(event.name + "Skipped"); - player.skipList.remove(event.name); - if (lib.phaseName.includes(event.name)) - player.getHistory("skipped").add(event.name); - _status.event.next.remove(event); - event.finish(); - resolve(event.toEvent()); - } else if (player.classList.contains("dead") && !event.forceDie && event.name != "phaseLoop") { - game.broadcastAll(function () { - while (_status.dieClose.length) { - _status.dieClose.shift().close(); - } - }); - if (event._oncancel) event._oncancel(); - event.finish(); - resolve(event.toEvent()); - } else if (player.removed && event.name != "phaseLoop") { - event.finish(); - resolve(event.toEvent()); - } else if (player.isOut() && event.name != "phaseLoop" && !event.includeOut) { - if (event.name == "phase" && player == _status.roundStart && !event.skill) { - _status.roundSkipped = true; - } - event.finish(); - resolve(event.toEvent()); - } - } - }; - - check(eventPromise) - if (eventPromise.finished) { - return eventPromise; - } - - const oldEvent = _status.event; - // 处理eventNeutralized反复横跳 - if (!oldEvent.finished) { - if (_status.event != eventPromise) { - eventPromise.parent = _status.event; - _status.event = eventPromise; - game.getGlobalHistory("everything").push(eventPromise); - } - return game.loop(eventPromise).then(() => { - // 有时候event.finished还是false - return eventPromise; - }).then(event => { - check(event.toPromise()); - return event.toPromise(); - }); - } - else { - // event.neutralize()执行后只允许带有eventNeutralized的arrangeTrigger执行 - if (eventPromise.name == "arrangeTrigger" && - eventPromise.triggername == "eventNeutralized") { - if (_status.event != eventPromise) { - eventPromise.parent = _status.event; - _status.event = eventPromise; - game.getGlobalHistory("everything").push(eventPromise); - } - return game.loop(eventPromise).then(() => { - // 有时候event.finished还是false - return eventPromise; - }).then(event => { - // 如果它终于不给我跳了就给老子停 - if (oldEvent.finished === true && typeof oldEvent.resolveContent == 'function') { - oldEvent.resolveContent(); - } - return event.toPromise(); - }); - } - // 否则以其他形式使finished为true的时候停止oldEvent - else { - console.log(`不继续执行event(${eventPromise.name})`, eventPromise.toEvent()); - // 给老子停 - if (oldEvent.finished === true && typeof oldEvent.resolveContent == 'function') { - oldEvent.resolveContent(); - console.log(`事件结束(${oldEvent.name})`, oldEvent.toEvent()); - } - else { - if (oldEvent.finished === true) { - console.log(`事件未结束(${oldEvent.name})`, oldEvent.toEvent()); - } - if (typeof oldEvent.resolveContent != 'function') { - console.log(`事件未结束, event.resolveContent不是一个函数`, oldEvent.toEvent()); - } - } - } - } - } - } - ) - ); - }); - }); - this.#event = event; - return new Proxy(this, { - get(target, prop, receiver) { - const thisValue = Reflect.get(target, prop); - if (thisValue) { - if (typeof thisValue == "function") { - return thisValue.bind(target); - } - return thisValue; - } - const eventValue = Reflect.get(event, prop); - return eventValue == event ? receiver : eventValue; - }, - set(target, prop, newValue) { - return Reflect.set(event, prop, newValue); - }, - deleteProperty(target, prop) { - return Reflect.deleteProperty(event, prop); - }, - defineProperty(target, prop, attributes) { - return Reflect.defineProperty(event, prop, attributes); - }, - has(target, prop) { - return Reflect.has(event, prop); - }, - ownKeys(target) { - return Reflect.ownKeys(event); - }, - getOwnPropertyDescriptor(target, prop) { - return Reflect.getOwnPropertyDescriptor(event, prop); - }, - }); - } - /** 获取原事件对象 */ - toEvent() { - return this.#event; - } - /** - * 在某个异步事件中调试变量信息 - * - * 注: 在调试步骤中`定义的变量只在当前输入的语句有效` - * - * @example - * 在技能中调试技能content相关的信息 - * ```js - * await event.debugger(); - * ``` - * 在技能中调试触发此技能事件的相关的信息 - * ```js - * await trigger.debugger(); - * ``` - */ - async debugger() { - if (security.isSandboxRequired()) throw new Error("当前模式下禁止调试"); - return new Promise((resolve) => { - const runCode = function (event, code) { - try { - // 为了使玩家调试时使用var player=xxx时不报错,故使用var - // var { player, _trigger: trigger, _result: result } = event; - var context = { - event, - player: event.player, - _trigger: event.trigger, - _result: event.result, - }; - return security.exec(`return ${code}`, context); - } catch (error) { - return error; - } - }.bind(window); - const inputCallback = (inputResult) => { - if (inputResult === false) { - resolve(null); - } else { - const obj = runCode(this.toEvent(), inputResult); - alert(!obj || obj instanceof Error ? String(obj) : get.stringify(obj)); - game.promises.prompt("debugger调试").then(inputCallback); - } - }; - game.promises.prompt("debugger调试").then(inputCallback); - }); - } - - /** - * 获取 Result 对象中的信息。 - * @example - * ```js - // 示例 1: - const chooseCardResult = await player.chooseCard().forResult(); - // 获取整个结果对象,然后访问如 chooseCardResult.cards 等属性 - - // 示例 2: - const cards = await player.chooseCard().forResult('cards'); - // 获取结果对象中 'cards' 属性的值 - - // 示例 3: - const [success, cards, targets] = await player.chooseCardTarget().forResult('bool', 'cards', 'targets'); - // 获取结果对象中多个属性的值 - // - success 表示是否成功 - // - cards 表示选择的卡片 - // - targets 表示选择的目标 - ``` - * @template {keyof Result} T - * @overload - * @returns {Promise} - * - * @overload - * @param {T} param0 - * @returns {Promise>} - * - * @overload - * @param { T[] } params - * @returns { Promise[]> } - */ - forResult(...params) { - if (params.length == 0) { - return this.then(({ result }) => result); - } else if (params.length == 1) { - return this.then((event) => event.result[params[0]]); - } else { - return this.then((event) => Array.from(params).map((key) => event.result[key])); - } - } - /** - * 返回result中的bool项 - */ - forResultBool() { - return this.forResult("bool"); - } - - /** - * 返回result中的targets项。 - */ - forResultTargets() { - return this.forResult("targets"); - } - - /** - * 返回result中的cards项 - */ - forResultCards() { - return this.forResult("cards"); - } - - /** - * 返回result中的card项 - * - * @returns {Promise|Promise} 返回的card项。 - * - */ - forResultCard() { - return this.forResult("card"); - } - - /** - * 返回result中的control项。 - */ - forResultControl() { - return this.forResult("control"); - } - - /** - * 返回result中的links项。 - */ - forResultLinks() { - return this.forResult("links"); - } -} +export { GameEvent as GameEventPromise } from "./gameEvent.js"; \ No newline at end of file diff --git a/noname/library/element/index.js b/noname/library/element/index.js index c6ed5ca2d5..9cbed91bd5 100644 --- a/noname/library/element/index.js +++ b/noname/library/element/index.js @@ -2,7 +2,6 @@ export { Button } from "./button.js"; export { Card } from "./card.js"; export { Client } from "./client.js"; export { Content } from "./content.js"; -export { Contents } from "./contents.js"; export { Control } from "./control.js"; export { Dialog } from "./dialog.js"; export { GameEvent } from "./gameEvent.js"; @@ -10,4 +9,4 @@ export { GameEventPromise } from "./gameEventPromise.js"; export { NodeWS } from "./nodeWS.js"; export { Player } from "./player.js"; export { VCard } from "./vcard.js"; -export { Character } from "./character.js" +export { Character } from "./character.js"; diff --git a/noname/library/element/player.js b/noname/library/element/player.js index 8cdfc23558..811bbd0704 100644 --- a/noname/library/element/player.js +++ b/noname/library/element/player.js @@ -21,6 +21,7 @@ import { ui } from "../../ui/index.js"; import { CacheContext } from "../cache/cacheContext.js"; import { ChildNodesWatcher } from "../cache/childNodesWatcher.js"; import security from "../../util/security.js"; +import { ContentCompiler } from "./gameEvent.js"; export class Player extends HTMLDivElement { /** @@ -166,6 +167,12 @@ export class Player extends HTMLDivElement { }; player.queueCount = 0; player.outCount = 0; + //TODO: 添加对应的typedef + player.vcardsMap = { + handcards: [], + equips: [], + judges: [], + }; } buildEventListener(noclick) { let player = this; @@ -399,9 +406,9 @@ export class Player extends HTMLDivElement { * })(); * ``` */ - when() { + when(...triggerNames) { const player = this; - if (!_status.postReconnect.player_when) + if (!_status.postReconnect.player_when) { _status.postReconnect.player_when = [ function (map) { "use strict"; @@ -416,15 +423,15 @@ export class Player extends HTMLDivElement { }, {}, ]; - let triggerNames = Array.from(arguments); + } let trigger; let instantlyAdd = true; - if (triggerNames.length == 0) throw "player.when的参数数量应大于0"; //从triggerNames中取出instantlyAdd的部分 if (triggerNames.includes(false)) { instantlyAdd = false; triggerNames.remove(false); } + if (triggerNames.length == 0) throw "player.when的参数数量应大于0"; // add other triggerNames // arguments.length = 1 if (triggerNames.length == 1) { @@ -448,10 +455,6 @@ export class Player extends HTMLDivElement { do { skillName = "player_when_" + Math.random().toString(36).slice(-8); } while (lib.skill[skillName] != null); - const after = `${skillName}After`; - if (!trigger.player) trigger.player = after; - else if (Array.isArray(trigger.player)) trigger.player.add(after); - else if (typeof trigger.player == "string") trigger.player = [trigger.player, after]; const vars = {}; /** * 作用域 @@ -477,18 +480,10 @@ export class Player extends HTMLDivElement { return vars; }, get filter() { - return (event, player, name) => { - if (name == `${skillName}After`) { - skill.popup = false; - return true; - } - return skill.filterFuns.every(fun => Boolean(fun(event, player, name))) && skill.filter2(event, player, name); - }; + return (event, player, name) => skill.filterFuns.every(fun => Boolean(fun(event, player, name))) && skill.filter2(event, player, name); }, get filter2() { - return (event, player, name) => { - return skill.filter2Funs.length == 0 || skill.filter2Funs.some(fun => Boolean(fun(event, player, name))); - }; + return (event, player, name) => skill.filter2Funs.length === 0 || skill.filter2Funs.some(fun => Boolean(fun(event, player, name))); }, }; const warnVars = ["event", "step", "source", "player", "target", "targets", "card", "cards", "skill", "forced", "num", "trigger", "result"]; @@ -500,33 +495,58 @@ export class Player extends HTMLDivElement { if (errVars.includes(key)) throw new Error(`Variable '${key}' should not be referenced by vars objects`); varstr += `var ${key}=lib.skill['${skillName}'].vars['${key}'];\n`; } - let str = ` - ${varstr}if(event.triggername=='${skillName}After'){ - player.removeSkill('${skillName}'); - delete lib.skill['${skillName}']; - delete lib.translate['${skillName}']; - return event.finish(); + const originals = []; + const contents = []; + const compileStep = (code, scope) => { + const deconstructs = ["step", "source", "target", "targets", "card", "cards", "skill", "forced", "num", "_result: result"]; + const topVars = ["_status", "lib", "game", "ui", "get", "ai"]; + + const params = ["topVars", "event", "trigger", "player"]; + const body = ` + var { ${deconstructs.join(", ")} } = event; + var { ${topVars.join(", ")} } = topVars; + ${varstr} + { + ${code} } - `; + `; + + if (!get.isFunctionBody(body)) throw new Error(`无效的函数体: ${body}`); + + let compiled; + if (!scope) compiled = new Function(...params, body); + else compiled = scope(`(function (${params.join(", ")}) {\n${body}\n})`); + + originals.push(compiled); + contents.push(function (event, trigger, player) { + //@ts-ignore + return compiled.apply(this, [{ lib, game, ui, get, ai, _status }, event, trigger, player]); + }); + }; for (let i = 0; i < skill.contentFuns.length; i++) { const fun2 = skill.contentFuns[i]; - const a = fun2.toString(); - //防止传入()=>xxx的情况 - const begin = a.indexOf("{") == a.indexOf("}") && a.indexOf("{") == -1 && a.indexOf("=>") > -1 ? a.indexOf("=>") + 2 : a.indexOf("{") + 1; - const str2 = a.slice(begin, a.lastIndexOf("}") != -1 ? a.lastIndexOf("}") : undefined).trim(); - str += `'step ${i}'\n\t${str2}\n\t`; - } - // 防止注入喵 - if (!get.isFunctionBody(str, "any")) throw new Error("无效的content函数代码"); - let recompiledScope; - if (security.isSandboxRequired()) { - recompiledScope = scope ? security.eval(`return (${scope.toString()})`) : code => security.eval(`return (${code.toString()})`); - } else { - recompiledScope = scope || eval; + if (typeof fun2 === "function") { + originals.push(fun2); + contents.push(fun2); + } else { + const a = fun2; + //防止传入()=>xxx的情况 + const begin = a.indexOf("{") == a.indexOf("}") && a.indexOf("{") == -1 && a.indexOf("=>") > -1 ? a.indexOf("=>") + 2 : a.indexOf("{") + 1; + const str2 = a.slice(begin, a.lastIndexOf("}") != -1 ? a.lastIndexOf("}") : undefined).trim(); + // 防止注入喵 + if (!get.isFunctionBody(str2)) throw new Error("无效的content函数代码"); + let recompiledScope; + if (security.isSandboxRequired()) { + recompiledScope = scope ? security.eval(`return (${scope.toString()})`) : code => security.eval(`return (${code.toString()})`); + } else { + recompiledScope = scope || eval; + } + compileStep(str2, recompiledScope); + } } - skill.content = lib.init.parsex(recompiledScope(`(function(){\n${str}\n})`), scope && recompiledScope); - // @ts-ignore - skill.content._parsed = true; + const content = ContentCompiler.compile(contents); + content.original = originals; + skill.content = content; }; Object.defineProperty(lib.skill, skillName, { configurable: true, @@ -587,6 +607,32 @@ export class Player extends HTMLDivElement { * @param { Required['content'] } fun */ then(fun) { + if (lib.skill[skillName] != skill) throw `This skill has been destroyed`; + skill.contentFuns.push(String(fun)); // 提前转换,防止与闭包函数弄混 + createContent(); + return this; + }, + /** + * ```plain + * 闭包用法的then,不再提供parsex变量,改为使用闭包访问 + * 传参为 event, trigger, player + * + * 闭包即你可以直接在when里面访问when外面的变量 + * 如下: + * ``` + * ```javascript + * var att = get.attitude(player, target); + * + * player.when("phaseEnd") + * .step(() => { + * if (att > 0) // 闭包访问了外面定义的变量 att + * player.say("你好喵!"); + * }); + * ``` + * + * @param { ContentFuncByAll } fun + */ + step(fun) { if (lib.skill[skillName] != skill) throw `This skill has been destroyed`; skill.contentFuns.push(fun); createContent(); @@ -864,7 +910,7 @@ export class Player extends HTMLDivElement { */ getGiftAIResultTarget(card, target) { if (!card || target.refuseGifts(card, this)) return 0; - if (get.type(card, false) == "equip") return get.effect(target, card, target, target); + if (get.type(card, null, target) == "equip") return get.effect(target, card, target, target); if (card.name == "du") return this.hp > target.hp ? -1 : 0; if (target.hasSkillTag("nogain")) return 0; return Math.max(1, get.value(card, this) - get.value(card, target)); @@ -987,7 +1033,7 @@ export class Player extends HTMLDivElement { return Math.max( 0, this.countEnabledSlot(type) - - this.getEquips(type).reduce((num, card) => { + this.getVEquips(type).reduce((num, card) => { let types = get.subtypes(card, false); return num + get.numOf(types, type); }, 0) @@ -1019,7 +1065,7 @@ export class Player extends HTMLDivElement { return Math.max( 0, this.countEnabledSlot(type) - - this.getEquips(type).reduce((num, card) => { + this.getVEquips(type).reduce((num, card) => { let types = get.subtypes(card, false); if (!lib.filter.canBeReplaced(card, this)) num += get.numOf(types, type); return num; @@ -1080,17 +1126,32 @@ export class Player extends HTMLDivElement { * @returns { Card[] } */ getEquips(subtype) { + const VEquips = this.getVEquips(subtype); + return VEquips.reduce((cards, vcard) => { + //@ts-ignore + cards.addArray(vcard.cards || []); + return cards; + }, []); + } + /** + * 获取一名角色装备区内某种类型的虚拟牌 + * + * 参数可以为数字/区域字符串/实体牌/虚拟牌/牌名 + * @param { number | string | Card | VCard } subtype + * @returns { VCard[] } + */ + getVEquips(subtype) { switch (typeof subtype) { case "string": if (subtype == "equip3_4") { const cards = []; - cards.addArray(this.getEquips(3)); - cards.addArray(this.getEquips(4)); + cards.addArray(this.getVEquips(3)); + cards.addArray(this.getVEquips(4)); return cards; } else if (subtype.startsWith("equip") && parseInt(subtype.slice(5)) > 0) { break; } else if (lib.card[subtype]) { - return this.getCards("e", card => card.name == subtype); + return this.getVCards("e", card => card.name == subtype); } else return []; case "number": subtype = "equip" + subtype; @@ -1102,7 +1163,7 @@ export class Player extends HTMLDivElement { return []; } if (!subtype) return []; - return this.getCards("e", card => { + return this.getVCards("e", card => { // @ts-ignore return get.subtypes(card, false).includes(subtype); }); @@ -1239,6 +1300,7 @@ export class Player extends HTMLDivElement { * @param { SMap } [map] */ $syncDisable(map) { + //TODO:虚拟装备牌的添加暂时没有考虑到废除装备栏的情况,会出现排序错误的问题。需要手动设置排序。 const suits = { equip3: "+1马栏", equip4: "-1马栏", equip6: "特殊栏" }; if (get.is.mountCombined()) suits.equip3 = "坐骑栏"; if (!map) { @@ -1323,7 +1385,7 @@ export class Player extends HTMLDivElement { for (let range of rangex) { let num = this.countEquipableSlot(range); let num2 = get.numOf(rangex, range); - if (!replace) num -= this.getEquips(range).filter(card => lib.filter.canBeReplaced(card, this)).length; + if (!replace) num -= this.getVEquips(range).filter(card => lib.filter.canBeReplaced(card, this)).length; if (num < num2) return false; } return true; @@ -1345,7 +1407,7 @@ export class Player extends HTMLDivElement { * @deprecated */ isEmpty(num) { - return this.countEnabledSlot(num) > this.getEquips(num).length; + return this.countEnabledSlot(num) > this.getVEquips(num).length; } //以下函数将被废弃 /** @@ -1517,6 +1579,9 @@ export class Player extends HTMLDivElement { */ getSeatNum() { if (typeof this.seatNum == "number") return this.seatNum; + if (get.mode() === "boss") { + return get.distance(game.bossinfo.loopFirst ? game.bossinfo.loopFirst() : game.boss, this, "absolute") + 1; + } return 0; } /** @@ -1567,10 +1632,10 @@ export class Player extends HTMLDivElement { } } /** - * - * @param { Card[] } cards - * @param { string } tag - * @param { Player } target + * + * @param { Card[] } cards + * @param { string } tag + * @param { Player } target * @returns { GameEventPromise } */ loseToSpecial(cards, tag, target) { @@ -1783,13 +1848,17 @@ export class Player extends HTMLDivElement { switch (num) { case 0: player.classList.remove("unseen"); + player.classList.remove("unseen_show"); break; case 1: player.classList.remove("unseen2"); + player.classList.remove("unseen2_show"); break; case 2: player.classList.remove("unseen"); player.classList.remove("unseen2"); + player.classList.remove("unseen_show"); + player.classList.remove("unseen2_show"); break; } if (!player.isUnseen(2)) { @@ -2064,11 +2133,15 @@ export class Player extends HTMLDivElement { m = n; m = game.checkMod(from, to, m, "attackFrom", from); m = game.checkMod(from, to, m, "attackTo", to); - const equips1 = from.getCards("e", function (card) { - return !ui.selected.cards || !ui.selected.cards.includes(card); + const equips1 = from.getVCards("e", function (card) { + return !card.cards?.some(card => { + return ui.selected.cards?.includes(card); + }); }), - equips2 = to.getCards("e", function (card) { - return !ui.selected.cards || !ui.selected.cards.includes(card); + equips2 = to.getVCards("e", function (card) { + return !card.cards?.some(card => { + return ui.selected.cards?.includes(card); + }); }); for (let i = 0; i < equips1.length; i++) { const info = get.info(equips1[i]).distance; @@ -2350,7 +2423,7 @@ export class Player extends HTMLDivElement { var hujia2 = info2.hujia; this.hujia += hujia2; var double_hp; - if (_status.connectMode || get.mode() == "single") { + if (_status.connectMode || (get.mode() == "single" && _status.mode == "changban")) { double_hp = "pingjun"; } else { double_hp = get.config("double_hp"); @@ -2879,6 +2952,11 @@ export class Player extends HTMLDivElement { this.expandedSlots = {}; this.disabledSlots = {}; this.ai = { friend: [], enemy: [], neutral: [] }; + this.vcardsMap = { + handcards: [], + equips: [], + judges: [], + }; this.$uninit(); @@ -3023,7 +3101,7 @@ export class Player extends HTMLDivElement { } /** * 用法同 {@link say},但联机模式用这个 - * @param { string } str + * @param { string } str */ chat(str) { if (get.is.banWords(str)) return; @@ -3047,7 +3125,7 @@ export class Player extends HTMLDivElement { } /** * 让玩家说话 - * @param { string } str + * @param { string } str */ say(str) { str = str.replace(/##assetURL##/g, lib.assetURL); @@ -3147,6 +3225,7 @@ export class Player extends HTMLDivElement { judges: this.getCards("j"), specials: this.getCards("s"), expansions: this.getCards("x"), + vcardsMap: this.vcardsMap, expansion_gaintag: [], disableJudge: this.isDisabledJudge(), disabledSlots: this.disabledSlots, @@ -3388,8 +3467,8 @@ export class Player extends HTMLDivElement { } /** * 清除玩家的标记 - * @param { string } i - * @param { boolean } [log] + * @param { string } i + * @param { boolean } [log] */ clearMark(i, log) { let num = this.countMark(i); @@ -3397,8 +3476,8 @@ export class Player extends HTMLDivElement { } /** * 移除玩家的标记 - * @param { string } i - * @param { number } [num = 1] + * @param { string } i + * @param { number } [num = 1] * @param { boolean } [log] */ removeMark(i, num, log) { @@ -3418,9 +3497,9 @@ export class Player extends HTMLDivElement { } /** * 增加玩家的标记 - * @param { string } i - * @param { number } [num = 1] - * @param { boolean } [log] + * @param { string } i + * @param { number } [num = 1] + * @param { boolean } [log] */ addMark(i, num, log) { if (typeof num != "number" || !num) num = 1; @@ -3438,9 +3517,9 @@ export class Player extends HTMLDivElement { } /** * 设置玩家的标记数 - * @param { string } name + * @param { string } name * @param { number } num - * @param { boolean } [log] + * @param { boolean } [log] */ setMark(name, num, log) { const count = this.countMark(name); @@ -3460,7 +3539,7 @@ export class Player extends HTMLDivElement { } /** * 返回玩家是否拥有某个标记 - * @param { string } i + * @param { string } i * @returns { boolean } */ hasMark(i) { @@ -3632,12 +3711,25 @@ export class Player extends HTMLDivElement { if (typeof num != "number") return 0; return num; } - getCacheKey() { - return `[p:${this.playerid}]`; + /** + * 返回一个键值,用于在缓存中作为键名。 + * @param { boolean } [similar] false统一前缀 + * @returns {string} cacheKey + */ + getCacheKey(similar) { + let prefix = "[object:"; + if (similar !== false) prefix = "[player:"; + if (this.playerid) return prefix + this.playerid + "]"; + return ( + prefix + + ` + ${this.name}+${this.sex}+${this.group}+${this.hp}+${this.maxHp}+${this.hujia}+${"[" + this.skills.join(",") + "]"}+${this.name1}+${this.name2}] + ` + ); } /** * 返回玩家本回合使用某个技能的次数 - * @param { string } skill + * @param { string } skill * @returns { number } */ countSkill(skill) { @@ -3679,6 +3771,86 @@ export class Player extends HTMLDivElement { } return list; } + /** + * @param { string } [arg1='h'] + * @param { string | Record | ((card: Card) => boolean) } [arg2] + * @returns { Iterable } + */ + *iterableGetVCards(arg1, arg2) { + if (typeof arg1 != "string") { + arg1 = "h"; + } + const getCardName = card => { + return get.name(card, false); + }; + let filter = card => true; + if (arg2) { + if (typeof arg2 == "string") { + filter = card => getCardName(card) == arg2; + } else if (Array.isArray(arg2)) { + filter = card => arg2.includes(getCardName(card)); + } else if (typeof arg2 == "object") { + filter = card => { + for (let j in arg2) { + var value; + if (j == "type" || j == "subtype" || j == "color" || j == "suit" || j == "number") { + value = get[j](card); + } else if (j == "name") { + value = getCardName(card); + } else { + value = card[j]; + } + if ((typeof arg2[j] == "string" && value != arg2[j]) || (Array.isArray(arg2[j]) && !arg2[j].includes(value))) { + return false; + } + } + return true; + }; + } else if (typeof arg2 == "function") { + filter = arg2; + } + } + for (let i = 0; i < arg1.length; i++) { + if (arg1[i] == "h") { + for (let card of this.vcardsMap?.handcards ?? []) { + if (filter(card)) { + yield card; + } + } + } else if (arg1[i] == "e") { + for (let card of this.vcardsMap?.equips ?? []) { + if (filter(card)) { + yield card; + } + } + } else if (arg1[i] == "j") { + for (let card of this.vcardsMap?.judges ?? []) { + if (filter(card)) { + yield card; + } + } + } + } + } + /** + * @param { string } [arg1='h'] + * @param { string | Record | ((card: Card) => boolean) } [arg2] + * @returns { Card[] } + */ + getVCards(arg1, arg2) { + return Array.from(this.iterableGetVCards(arg1, arg2)); + } + /** + * @param { Parameters[0] } [arg1] + * @param { Parameters[1] } [arg2] + */ + countVCards(arg1, arg2) { + let count = 0; + for (let item of this.iterableGetVCards(arg1, arg2)) { + count++; + } + return count; + } /** * @param { string } [arg1='h'] * @param { string | Record | ((card: Card) => boolean) } [arg2] @@ -3694,7 +3866,7 @@ export class Player extends HTMLDivElement { } return get.name(card); }; - let filter; + let filter = card => true; if (arg2) { if (typeof arg2 == "string") { filter = card => getCardName(card) == arg2; @@ -3720,8 +3892,6 @@ export class Player extends HTMLDivElement { } else if (typeof arg2 == "function") { filter = arg2; } - } else { - filter = card => true; } for (let i = 0; i < arg1.length; i++) { if (arg1[i] == "h") { @@ -3879,19 +4049,13 @@ export class Player extends HTMLDivElement { var es = []; var i, j; if (arg3 !== false) { - for (i = 0; i < this.node.equips.childElementCount; i++) { - if (!this.node.equips.childNodes[i].classList.contains("removing")) { - var equipskills = get.info(this.node.equips.childNodes[i], false).skills; - if (equipskills) { - es.addArray(equipskills); - } - } - } + const VEquips = this.getVCards("e"); + es.addArray(get.skillsFromEquips(VEquips)); if (arg2 == "e") { return es; } } - for (var i in this.additionalSkills) { + for (let i in this.additionalSkills) { if (Array.isArray(this.additionalSkills[i]) && (arg2 || i.indexOf("hidden:") !== 0)) { for (j = 0; j < this.additionalSkills[i].length; j++) { if (this.additionalSkills[i][j]) { @@ -3902,13 +4066,13 @@ export class Player extends HTMLDivElement { skills.add(this.additionalSkills[i]); } } - for (var i in this.tempSkills) { + for (let i in this.tempSkills) { skills.add(i); } if (arg2) skills.addArray(this.hiddenSkills); if (arg2 === false || arg2 == "invisible") skills.addArray(this.invisibleSkills); if (arg3 !== false) skills.addArray(es); - for (var i in this.forbiddenSkills) { + for (let i in this.forbiddenSkills) { skills.remove(i); } if (arg4 !== false) { @@ -4499,7 +4663,8 @@ export class Player extends HTMLDivElement { var player = _status.event.player; var event = _status.event.getParent(); var getn = function (card) { - if (player.hasSkill("tianbian") && get.suit(card) == "heart") return 13 * (Boolean(event.small) ? -1 : 1); + //会赢吗?会赢的! + if (player.hasSkillTag("forceWin", null, { card })) return 13 * (Boolean(event.small) ? -1 : 1); return get.number(card) * (Boolean(event.small) ? -1 : 1); }; if (source && source != player) { @@ -4719,7 +4884,12 @@ export class Player extends HTMLDivElement { next.autochoose = function () { if (!this.forced) return false; if (typeof this.selectCard == "function") return false; - if (this.complexCard || this.complexSelect || this.filterOk || this.getParent().name.startsWith("chooseToCompare")) return false; + if (this.complexCard || this.complexSelect || this.filterOk) return false; + let evt=this.getParent(); + while(evt?.name){ + if(evt.name.startsWith("chooseToCompare")) return false; + evt=evt.getParent(); + } var cards = this.player.getCards(this.position); if (cards.some(card => !this.filterCard(card, this.player, this))) return false; return get.select(this.selectCard)[0] >= this.player.countCards(this.position); @@ -4962,7 +5132,10 @@ export class Player extends HTMLDivElement { if (next.ai) next.filterButton = arguments[i]; else next.ai = arguments[i]; } else if (typeof arguments[i] == "object" && arguments[i]) { - next.filterButton = get.filter(arguments[i]); + var filter = get.filter(arguments[i]); + next.filterButton = function (button) { + return filter(button.link); + }; } else if (typeof arguments[i] == "string") { next.prompt = arguments[i]; } @@ -5002,7 +5175,10 @@ export class Player extends HTMLDivElement { if (next.ai) next.filterButton = arguments[i]; else next.ai = arguments[i]; } else if (typeof arguments[i] == "object" && arguments[i]) { - next.filterButton = get.filter(arguments[i]); + var filter = get.filter(arguments[i]); + next.filterButton = function (button) { + return filter(button.link); + }; } else if (typeof arguments[i] == "string") { next.prompt = arguments[i]; } @@ -5044,7 +5220,10 @@ export class Player extends HTMLDivElement { if (next.ai) next.filterButton = arguments[i]; else next.ai = arguments[i]; } else if (typeof arguments[i] == "object" && arguments[i]) { - next.filterButton = get.filter(arguments[i]); + var filter = get.filter(arguments[i]); + next.filterButton = function (button) { + return filter(button.link); + }; } else if (typeof arguments[i] == "string") { next.prompt = arguments[i]; } @@ -5065,7 +5244,7 @@ export class Player extends HTMLDivElement { } /** * 玩家展示手牌 - * @param { string } str + * @param { string } str * @returns { GameEventPromise } */ showHandcards(str) { @@ -5080,8 +5259,8 @@ export class Player extends HTMLDivElement { } /** * 玩家展示一些牌 - * @param { Card[] } cards - * @param { string } str + * @param { Card[] } cards + * @param { string } str * @returns { GameEventPromise } */ showCards(cards, str) { @@ -5105,8 +5284,8 @@ export class Player extends HTMLDivElement { } /** * 玩家观看一些牌 - * @param { string } str - * @param { Card[] } cards + * @param { string } str + * @param { Card[] } cards * @returns { GameEventPromise } */ viewCards(str, cards) { @@ -5120,7 +5299,7 @@ export class Player extends HTMLDivElement { } /** * 玩家观看target的手牌 - * @param { Player } target + * @param { Player } target * @returns { GameEventPromise } */ viewHandcards(target) { @@ -5131,6 +5310,7 @@ export class Player extends HTMLDivElement { return false; } } + //TODO: 给canMoveCard函数适配虚拟牌的移动 canMoveCard(withatt, nojudge) { const player = this; const args = Array.from(arguments).slice(2); @@ -5155,7 +5335,7 @@ export class Player extends HTMLDivElement { return sourceTargets.some(current => { const att = get.sgn(get.attitude(player, current)); if (!withatt || att != 0) { - var es = current.getCards("e", filterCard); + var es = current.getVCards("e", filterCard); for (var i = 0; i < es.length; i++) { if ( aimTargets.some(current2 => { @@ -5174,7 +5354,7 @@ export class Player extends HTMLDivElement { } } if (!nojudge && (!withatt || att > 0)) { - var js = current.getCards("j", filterCard); + var js = current.getVCards("j", filterCard); for (var i = 0; i < js.length; i++) { if ( game.hasPlayer(function (current2) { @@ -5410,8 +5590,8 @@ export class Player extends HTMLDivElement { } /** * 令玩家摸牌摸至指定值 - * @param { number } num - * @param { * } args + * @param { number } num + * @param { * } args * @returns { GameEventPromise } */ drawTo(num, args) { @@ -5638,7 +5818,7 @@ export class Player extends HTMLDivElement { } directequip(cards) { for (var i = 0; i < cards.length; i++) { - this.$equip(cards[i]); + this.addVirtualEquip(cards[i]); } if (!_status.video) { game.addVideo("directequip", this, get.cardsInfo(cards)); @@ -5739,7 +5919,10 @@ export class Player extends HTMLDivElement { } if (this == game.me || _status.video) ui.updatehl(); if (!_status.video) { - game.addVideo("directgains", this, get.cardsInfo(cards)); + game.addVideo("directgains", this, { + cards: get.cardsInfo(cards), + gaintag, + }); this.update(); } if (broadcast !== false) @@ -5824,6 +6007,7 @@ export class Player extends HTMLDivElement { cards: [], cards2: [], gaintag_map: {}, + vcard_map: new Map(), }; player.checkHistory("lose", function (evt) { if (evt.parent == that) { @@ -5838,6 +6022,9 @@ export class Player extends HTMLDivElement { if (!map.gaintag_map[key]) map.gaintag_map[key] = []; map.gaintag_map[key].addArray(evt.gaintag_map[key]); } + evt.vcard_map.forEach((value, key) => { + map.vcard_map.set(key, value); + }); } }); return map; @@ -5908,6 +6095,7 @@ export class Player extends HTMLDivElement { cards: [], cards2: [], gaintag_map: {}, + vcard_map: new Map(), }; player.checkHistory("lose", function (evt) { if (evt.parent == that) { @@ -5922,6 +6110,9 @@ export class Player extends HTMLDivElement { if (!map.gaintag_map[key]) map.gaintag_map[key] = []; map.gaintag_map[key].addArray(evt.gaintag_map[key]); } + evt.vcard_map.forEach((value, key) => { + map.vcard_map.set(key, value); + }); } }); return map; @@ -5999,8 +6190,10 @@ export class Player extends HTMLDivElement { cards: [], cards2: [], gaintag_map: {}, + vcard_map: new Map(), }; }; + next.vcard_map = new Map(); return next; } /** @@ -6191,8 +6384,8 @@ export class Player extends HTMLDivElement { } /** * 调整玩家的体力值 - * @param { number } num - * @param { boolean } [popup] + * @param { number } num + * @param { boolean } [popup] * @returns { GameEventPromise } */ changeHp(num, popup) { @@ -6205,8 +6398,8 @@ export class Player extends HTMLDivElement { } /** * 调整玩家的护甲值 - * @param { number } [num] - * @param { "gain" | "lose" | "damage" | "null" } [type] + * @param { number } [num] + * @param { "gain" | "lose" | "damage" | "null" } [type] * @param { number } [limit] 护甲上限 * @returns { GameEventPromise } */ @@ -6340,7 +6533,7 @@ export class Player extends HTMLDivElement { } /** * 令玩家进入濒死状态 - * @param { GameEvent | GameEventPromise } [reason] + * @param { GameEvent | GameEventPromise } [reason] * @returns { GameEventPromise } */ dying(reason) { @@ -6360,7 +6553,7 @@ export class Player extends HTMLDivElement { } /** * 令玩家死亡 - * @param { GameEvent | GameEventPromise } reason + * @param { GameEvent | GameEventPromise } reason * @returns { GameEventPromise } */ die(reason) { @@ -6373,8 +6566,8 @@ export class Player extends HTMLDivElement { } /** * 令玩家复活 - * @param { number } [hp = 1] - * @param { boolean } [log] + * @param { number } [hp = 1] + * @param { boolean } [log] */ revive(hp, log) { if (log !== false) game.log(this, "复活"); @@ -6462,14 +6655,25 @@ export class Player extends HTMLDivElement { } equip(card, draw) { var next = game.createEvent("equip"); - next.card = card; + //next.card = card; next.player = this; + next.setContent(lib.element.content.equip); + //if (get.is.object(next.card) && next.card.cards) next.card = next.card.cards[0]; + //next.cards = [next.card]; + let itemtype = get.itemtype(card); + if (itemtype === "card") { + next.cards = [card]; + } else if (itemtype === "cards") { + next.cards = card.slice(0); + } else if (Array.isArray(card)) { + next.vcards = card.slice(0); + } else { + next.card = card; + if (card?.cards) next.cards = card.cards; + } if (draw) { next.draw = true; } - next.setContent(lib.element.content.equip); - if (get.is.object(next.card) && next.card.cards) next.card = next.card.cards[0]; - next.cards = [next.card]; next.getd = function (player, key, position) { if (!position) position = ui.discardPile; if (!key) key = "cards"; @@ -6494,6 +6698,7 @@ export class Player extends HTMLDivElement { cards: [], cards2: [], gaintag_map: {}, + vcard_map: new Map(), }; player.checkHistory("lose", function (evt) { if (evt.parent == that) { @@ -6508,6 +6713,9 @@ export class Player extends HTMLDivElement { if (!map.gaintag_map[key]) map.gaintag_map[key] = []; map.gaintag_map[key].addArray(evt.gaintag_map[key]); } + evt.vcard_map.forEach((value, key) => { + map.vcard_map.set(key, value); + }); } }); return map; @@ -6516,8 +6724,8 @@ export class Player extends HTMLDivElement { } /** * 将一些牌置入到玩家的判定区 - * @param { Card } card - * @param { Card[] } [cards] + * @param { Card } card + * @param { Card[] } [cards] * @returns { GameEventPromise } */ addJudge(card, cards) { @@ -6559,6 +6767,7 @@ export class Player extends HTMLDivElement { cards: [], cards2: [], gaintag_map: {}, + vcard_map: new Map(), }; player.checkHistory("lose", function (evt) { if (evt.parent == that) { @@ -6573,6 +6782,9 @@ export class Player extends HTMLDivElement { if (!map.gaintag_map[key]) map.gaintag_map[key] = []; map.gaintag_map[key].addArray(evt.gaintag_map[key]); } + evt.vcard_map.forEach((value, key) => { + map.vcard_map.set(key, value); + }); } }); return map; @@ -6581,13 +6793,8 @@ export class Player extends HTMLDivElement { } /** * 返回某些牌是否能进入玩家的判定区 - * * @overload - * @param { string } card - * @returns { boolean } - * - * @overload - * @param { Card } card + * @param { string | Card } card * @returns { boolean } */ canAddJudge(card) { @@ -6609,10 +6816,10 @@ export class Player extends HTMLDivElement { } addJudgeNext(card, unlimited) { if (!card.expired) { - let target = this.next; + let target = this.getNext(); const name = card.viewAs || card.name; - const cards = get.itemtype(card) == "card" ? [card] : card.cards; - if (get.itemtype(cards) != "cards") return; + const cards = get.itemtype(card) == "card" ? [card] : (card.cards ?? []); + //if (get.itemtype(cards) != "cards") return; let bool = false; if ( !unlimited && @@ -6629,16 +6836,10 @@ export class Player extends HTMLDivElement { bool = true; break; } - target = target.next; + target = target.getNext(); } if (bool) { - if (card.cards && card.cards.length) { - target.addJudge(name, card.cards[0]); - } else if (card.name != name) { - target.addJudge(name, card); - } else { - target.addJudge(card); - } + return target.addJudge(card, cards); } } else { card.expired = false; @@ -6648,7 +6849,7 @@ export class Player extends HTMLDivElement { var next = game.createEvent("judge"); next.player = this; for (var i = 0; i < arguments.length; i++) { - if (get.itemtype(arguments[i]) == "card") { + if (get.itemtype(arguments[i]) == "card" || get.is.object(arguments[i])) { next.card = arguments[i]; } else if (typeof arguments[i] == "string") { next.skill = arguments[i]; @@ -6839,7 +7040,7 @@ export class Player extends HTMLDivElement { * @param { boolean | string } [nature] * @param { boolean } [logv] */ - logSkill(name, targets, nature, logv) { + logSkill(name, targets, nature, logv, args) { if (get.itemtype(targets) == "player") targets = [targets]; var nopop = false; var popname = name; @@ -6880,7 +7081,7 @@ export class Player extends HTMLDivElement { this.syncStorage(roundname); this.markSkill(roundname); } - game.trySkillAudio(name, this, true); + game.trySkillAudio(name, this, true, null, null, args); if (game.chess) { this.chessFocus(); } @@ -7442,11 +7643,12 @@ export class Player extends HTMLDivElement { } } /** - * @param { string | Card | VCard } card + * 能否对target使用card + * @param { Card | VCard | object | string } card * @param { Player } target - * @param { boolean } [distance] - * @param { GameEventPromise | boolean } [includecard] - * @returns { boolean } + * @param { false } [distance] false:无距离限制 + * @param { boolean | GameEvent } [includecard] 是否受使用次数限制,可以填入用于检测的事件 + * @returns */ canUse(card, target, distance, includecard) { if (typeof card == "string") card = { name: card, isCard: true }; @@ -7462,12 +7664,26 @@ export class Player extends HTMLDivElement { if (distance !== false && !lib.filter.targetInRange(card, this, target)) return false; return lib.filter[includecard ? "targetEnabledx" : "targetEnabled"](card, this, target); } + /** + * 场上是否存在能对其使用card的目标 + * @param { Card | VCard | object | string } card + * @param { false } [distance] false:无距离限制 + * @param { boolean | GameEvent } [includecard] 是否受使用次数限制,可以填入用于检测的事件 + * @returns { boolean } + */ hasUseTarget(card, distance, includecard) { var player = this; return game.hasPlayer(function (current) { return player.canUse(card, current, distance, includecard); }); } + /** + * 场上是否存在收益为正的目标 + * @param { Card | VCard | object | string } card + * @param { false } [distance] false:无距离限制 + * @param { boolean | GameEvent } [includecard] 是否受使用次数限制,可以填入用于检测的事件 + * @returns { boolean } + */ hasValueTarget(card, distance, includecard) { if (typeof card == "string") { card = { name: card, isCard: true }; @@ -7509,6 +7725,13 @@ export class Player extends HTMLDivElement { } return min > 0; } + /** + * card使用价值 + * @param { Card | VCard | object | string } card + * @param { false } [distance] false:无距离限制 + * @param { boolean | GameEvent } [includecard] 是否受使用次数限制,可以填入用于检测的事件 + * @returns { number } 无可选或正收益目标返回0 + */ getUseValue(card, distance, includecard) { if (typeof card == "string") { card = { name: card, isCard: true }; @@ -7547,6 +7770,10 @@ export class Player extends HTMLDivElement { } return min; } + /** + * 添加随从 + * @param { { hs?: Card[], es?: Card[], skills?: string[], hp?: number, maxHp?: number, hujia?: number, sex?: Sex, group?: string, skill?: string, source?: string } } cfg + */ addSubPlayer(cfg) { var skill = "subplayer_" + cfg.name + "_" + get.id(); game.log(this, "获得了随从", "#g" + get.translation(cfg.name)); @@ -7788,7 +8015,7 @@ export class Player extends HTMLDivElement { next.forceDie = true; next.addSkill = addSkill.slice(0).unique(); next.removeSkill = removeSkill.slice(0).unique(); - next.setContents("changeSkills"); + next.setContent("changeSkills"); return next; } addSkill(skill, checkConflict, nobroadcast, addToSkills) { @@ -8075,14 +8302,14 @@ export class Player extends HTMLDivElement { } addEquipTrigger(card) { if (card) { - var info = get.info(card); + var info = get.info(card, false); if (info.skills) { for (var j = 0; j < info.skills.length; j++) { this.addSkillTrigger(info.skills[j]); } } } else { - var es = this.getCards("e"); + var es = this.getVCards("e"); for (var i = 0; i < es.length; i++) { this.addEquipTrigger(es[i]); } @@ -8090,10 +8317,52 @@ export class Player extends HTMLDivElement { _status.event.clearStepCache(); return this; } + removeVirtualJudge(VCard) { + const player = this; + game.addVideo("removeVirtualJudge", player, get.vcardInfo(VCard)); + game.broadcast( + (VCard, player) => { + const cards = player.vcardsMap?.judges; + if (cards && cards.includes(VCard)) { + cards.remove(VCard); + } + }, + VCard, + player + ); + const cards = player.vcardsMap?.judges; + if (cards && cards.includes(VCard)) { + cards.remove(VCard); + } + } + removeVirtualEquip(VCard) { + const player = this; + game.addVideo("removeVirtualEquip", player, get.vcardInfo(VCard)); + game.broadcast( + (VCard, player) => { + const cards = player.vcardsMap?.equips; + if (cards && cards.includes(VCard)) { + cards.remove(VCard); + } + }, + VCard, + player + ); + const cards = player.vcardsMap?.equips; + if (cards && cards.includes(VCard)) { + player.removeEquipTrigger(VCard); + cards.remove(VCard); + } + if (lib.config.equip_span) player.$handleEquipChange(); + } removeEquipTrigger(card) { + if (_status.video) return; if (card) { - var info = get.info(card); + var info = get.info(card, false); var skills = this.getSkills(null, false); + const VEquips = this.getVCards("e"); + VEquips.remove(card); + skills.addArray(get.skillsFromEquips(VEquips)); if (info.skills) { for (var j = 0; j < info.skills.length; j++) { if (skills.includes(info.skills[j])) continue; @@ -8107,7 +8376,7 @@ export class Player extends HTMLDivElement { next.card = card; } } else { - var es = this.getCards("e"); + var es = this.getVCards("e"); for (var i = 0; i < es.length; i++) { this.removeEquipTrigger(es[i]); } @@ -8261,13 +8530,9 @@ export class Player extends HTMLDivElement { }); } /** + * 添加临时技能 * @overload - * @param { string } skill - * @param { SkillTrigger | string | (event:GameEventPromise, player:Player, name:string) => boolean } [expire] - * @param { boolean } [checkConflict] - * - * @overload - * @param { string[] } skill 技能名数组 + * @param { string | string[] } skill 技能名(数组) * @param { SkillTrigger | string | (event:GameEventPromise, player:Player, name:string) => boolean } [expire] * @param { boolean } [checkConflict] */ @@ -8430,7 +8695,7 @@ export class Player extends HTMLDivElement { let currentHistory = history[i]; if (key) currentHistory = currentHistory[key]; if (filter) currentHistory = currentHistory.filter(filter); - evts.addArray(currentHistory.reverse()); + evts.addArray(currentHistory.slice().reverse()); } if (history[i].isRound) { if (num > 0) num--; @@ -8676,7 +8941,7 @@ export class Player extends HTMLDivElement { } /** * 返回玩家的攻击距离 - * @param { boolean } raw + * @param { boolean } raw * @returns { number } */ getAttackRange(raw) { @@ -8685,8 +8950,10 @@ export class Player extends HTMLDivElement { if (raw) { range = game.checkMod(player, player, range, "globalFrom", player); range = game.checkMod(player, player, range, "attackFrom", player); - const equips = player.getCards("e", function (card) { - return !ui.selected.cards || !ui.selected.cards.includes(card); + const equips = player.getVCards("e", function (card) { + return !card.cards?.some(card => { + return ui.selected.cards?.includes(card); + }); }); equips.forEach(card => { const info = get.info(card, false).distance; @@ -8707,14 +8974,16 @@ export class Player extends HTMLDivElement { } /** * 返回一些牌的攻击距离 - * @param { Card[] } cards + * @param { Card[] } cards * @returns { number } */ getEquipRange(cards) { const player = this; if (!cards) - cards = player.getCards("e", function (card) { - return !ui.selected.cards || !ui.selected.cards.includes(card); + cards = player.getVCards("e", function (card) { + return !card.cards?.some(card => { + return ui.selected.cards?.includes(card); + }); }); const range = cards.reduce((range, card) => { let newRange = false; @@ -8740,8 +9009,10 @@ export class Player extends HTMLDivElement { var player = this; var range = 0; range = game.checkMod(player, player, range, "globalFrom", player); - var equips = player.getCards("e", function (card) { - return !ui.selected.cards || !ui.selected.cards.includes(card); + var equips = player.getVCards("e", function (card) { + return !card.cards?.some(card => { + return ui.selected.cards?.includes(card); + }); }); for (var i = 0; i < equips.length; i++) { var info = get.info(equips[i]).distance; @@ -8756,8 +9027,10 @@ export class Player extends HTMLDivElement { var player = this; var range = 0; range = game.checkMod(player, player, range, "globalTo", player); - var equips = player.getCards("e", function (card) { - return !ui.selected.cards || !ui.selected.cards.includes(card); + var equips = player.getVCards("e", function (card) { + return !card.cards?.some(card => { + return ui.selected.cards?.includes(card); + }); }); for (var i = 0; i < equips.length; i++) { var info = get.info(equips[i]).distance; @@ -9006,7 +9279,7 @@ export class Player extends HTMLDivElement { /** * 判断玩家是否是场上体力最大的玩家 * @param { boolean } [only] 是否唯一 - * @param { boolean } [raw] + * @param { boolean } [raw] * @returns { boolean } */ isMaxHp(only, raw) { @@ -9018,7 +9291,7 @@ export class Player extends HTMLDivElement { /** * 判断玩家是否是场上体力最少的玩家 * @param { boolean } [only] 是否唯一 - * @param { boolean } [raw] + * @param { boolean } [raw] * @returns { boolean } */ isMinHp(only, raw) { @@ -9189,7 +9462,7 @@ export class Player extends HTMLDivElement { return false; } isMajor() { - if (get.mode() == 'guozhan') { + if (get.mode() == "guozhan") { if (this.identity == "unknown") return false; var list = game.filterPlayer(function (current) { return current.identity != "unknown" && current.hasSkillTag("forceMajor"); @@ -9226,8 +9499,7 @@ export class Player extends HTMLDivElement { if (map[i].length > map[player].length) return false; } return true; - } - else { + } else { var list = game.filterPlayer(function (current) { return current.hasSkillTag("forceMajor"); }); @@ -9257,7 +9529,7 @@ export class Player extends HTMLDivElement { return false; } isMinor(nomajor) { - if (get.mode() == 'guozhan') { + if (get.mode() == "guozhan") { if (this.identity == "unknown" || (!nomajor && this.isMajor())) return false; if ( !nomajor && @@ -9292,8 +9564,7 @@ export class Player extends HTMLDivElement { if (map[i].length < map[player].length) return false; } return true; - } - else { + } else { if (!nomajor && this.isMajor()) return false; if ( !nomajor && @@ -9350,16 +9621,12 @@ export class Player extends HTMLDivElement { } /** * - * @param { number | Card[] | Card } [add] - * @param { (card?: Card, player?: Player) => boolean } [filter] - * @param { boolean } [pure] + * @param { number | Card[] | Card } [add] (逻辑上)同时考虑“获得”的这张/些牌 + * @param { (card?: Card, player?: Player) => boolean } [filter] 代替默认策略(计入手牌数的手牌)进行筛选 + * @param { boolean } [pure] (手牌上限大于手牌数时)返回负值 + * @returns { number } 需要弃置的牌数 */ needsToDiscard(add, filter, pure) { - /** - * add: (逻辑上)同时考虑“获得”的这张/些牌 - * filter(function): 代替默认策略进行筛选 - * pure: 返回值可以为负数 - */ let cards = this.getCards("h"), num = 0; if (typeof add === "number") num = add; @@ -9463,7 +9730,7 @@ export class Player extends HTMLDivElement { * @param {string} tag * @param {Parameters[0]} [hidden] * @param {Parameters[2]} [arg] - * @param {boolean} [globalskill] + * @param {boolean} [globalskill] 只有为false才不添加全局技能ai进行筛选 */ hasSkillTag(tag, hidden, arg, globalskill) { var skills = this.getSkills(hidden); @@ -9483,23 +9750,18 @@ export class Player extends HTMLDivElement { return false; } /** - * 返回玩家是否有某个牌名的牌 - * - * @overload - * @param { Card } name - * @returns { boolean } * * @overload * @param { string } name - * @returns { boolean} + * @returns { boolean} 返回玩家判定区是否有某(种牌名的)牌 */ hasJudge(name) { - if (name && typeof name == "object") { + if (name && typeof name === "object") { name = name.viewAs || name.name; } - var judges = this.getCards("j"); + var judges = this.getVCards("j"); for (var i = 0; i < judges.length; i++) { - if ((judges[i].viewAs || judges[i].name) == name) { + if (judges[i].name === name) { return true; } } @@ -9592,12 +9854,15 @@ export class Player extends HTMLDivElement { if (typeof respond !== "string") respond = respond ? "respond" : "all"; return this.hasUsableCard("shan", respond); } + /** + * 以viewer视角猜测Player手里的杀 + * @param { Player } [viewer] + * @param { "use" | "respond" } [type] 此杀用途:"use"/"respond",无则均加入 + * @param { Card[] | Card | null } [ignore] 此牌/这些牌不纳入考量 + * @param { "bool" | "count" | "odds" } [rvt] + * @returns { boolean | number } 返回值:rvt:"bool"(默认)是否可能有杀,"count"推测有多少张杀,"odds"有杀的概率 + */ mayHaveSha(viewer, type, ignore, rvt) { - /** - * type: skill tag type 'use', 'respond' - * ignore: ignore cards, ui.selected.cards added - * rvt: return value type 'count', 'odds', 'bool'(default) - */ let count = 0; if ((this.hp > 2 || (!this.isZhu && this.hp > 1)) && this.hasSkillTag("respondSha", true, type, true)) { if (rvt === "count") count++; @@ -9637,12 +9902,15 @@ export class Player extends HTMLDivElement { if (rvt === "odds") return Math.min(1, count); return count > _status.event.getRand("mayHaveSha" + hs + this.playerid); } + /** + * 以viewer视角猜测Player手里的闪 + * @param { Player } [viewer] + * @param { "use" | "respond" } [type] 此闪用途:"use"/"respond",无则均加入 + * @param { Card[] | Card | null } [ignore] 此牌/这些牌不纳入考量 + * @param { "bool" | "count" | "odds" } [rvt] + * @returns { boolean | number } 返回值:rvt:"bool"(默认)是否可能有闪,"count"推测有多少张闪,"odds"有闪的概率 + */ mayHaveShan(viewer, type, ignore, rvt) { - /** - * type: skill tag type 'use', 'respond' or object - * ignore: ignore cards, ui.selected.cards added - * rvt: return value type 'count', 'odds', 'bool'(default) - */ let count = 0; if ((this.hp > 2 || (!this.isZhu && this.hp > 1)) && this.hasSkillTag("respondShan", true, type, true)) { if (rvt === "count") count++; @@ -9692,6 +9960,44 @@ export class Player extends HTMLDivElement { } return false; } + hasVCard(name, position) { + if (typeof name == "function") { + for (let card of this.iterableGetVCards(position, name)) { + return true; + } + } else { + if (this.countCards(position, name)) return true; + } + return false; + } + getVEquip(name) { + var es = this.getVCards("e"); + if (typeof name == "object" && get.info(name)) { + name = get.info(name).subtype; + if (name) { + name = parseInt(name[5]); + } + } else if (typeof name == "string" && name.startsWith("equip") && name.length == 6) { + name = parseInt(name[5]); + } + if (!name) { + return null; + } + for (var i = 0; i < es.length; i++) { + if (typeof name === "number") { + if (get.info(es[i]).subtype === "equip" + name) { + return es[i]; + } + } else { + if (es[i].name === name) return es[i]; + var source = get.info(es[i]).source; + if (Array.isArray(source) && source.includes(name)) { + return es[i]; + } + } + } + return null; + } getEquip(name) { var es = this.getCards("e"); if (typeof name == "object" && get.info(name)) { @@ -9720,15 +10026,29 @@ export class Player extends HTMLDivElement { } return null; } + /** + * 返回玩家判定区中的虚拟牌 + * @param { string } [name] + * @returns { VCard|null } + */ + getVJudge(name) { + var judges = this.getVCards("j"); + for (var i = 0; i < judges.length; i++) { + if (judges[i].name == name) { + return judges[i]; + } + } + return null; + } /** * 返回玩家判定区中的牌 - * @param { string } [name] - * @returns { Card[] } + * @deprecated + * @param { string } [name] + * @returns { Card|null } */ getJudge(name) { - var judges = this.node.judges.childNodes; + var judges = this.getCards("j"); for (var i = 0; i < judges.length; i++) { - if (judges[i].classList.contains("removing")) continue; if ((judges[i].viewAs || judges[i].name) == name) { return judges[i]; } @@ -10609,62 +10929,188 @@ export class Player extends HTMLDivElement { } $handleEquipChange() { let player = this; - const cards = Array.from(this.node.equips.childNodes); - const cardsResume = cards.slice(0); - cards.forEach(card => { - if (card.name.indexOf("empty_equip") == 0) { - let num = get.equipNum(card); - let remove = false; - if ((num == 4 || num == 3) && get.is.mountCombined()) { - remove = !this.hasEmptySlot("equip3_4") || this.getEquips("equip3_4").length; - } else if (!this.hasEmptySlot(num) || this.getEquips(num).length) { - remove = true; + const cards = Array.from(player.node.equips.childNodes); + for (const cardx of cards) { + if (cardx.name.indexOf("empty_equip") == 0) { + player.node.equips.removeChild(cardx); + } + } + for (let i = 1; i <= 5; i++) { + const goon = (i == 4 || i == 3) && get.is.mountCombined(); + if (player.hasEmptySlot(goon ? "equip3_4" : i)) { + let sum = player.countEmptySlot(goon ? "equip3_4" : i); + while (sum > 0) { + sum--; + const card = game.createCard("empty_equip" + i, "", ""); + card.fix(); + //console.log('add '+card.name); + card.style.transform = ""; + card.classList.remove("drawinghidden"); + card.classList.add("emptyequip"); + card.classList.add("hidden"); + delete card._transform; + const equipNum = get.equipNum(card); + let equipped = false; + for (let j = 0; j < player.node.equips.childNodes.length; j++) { + const card2 = player.vcardsMap.equips.find(i => i.cards?.includes(player.node.equips.childNodes[j])); + const cardx = card2 ? card2 : player.node.equips.childNodes[j]; + if (get.equipNum(cardx) >= equipNum) { + player.node.equips.insertBefore(card, player.node.equips.childNodes[j]); + equipped = true; + break; + } + } + if (!equipped) { + player.node.equips.appendChild(card); + if (_status.discarded) { + _status.discarded.remove(card); + } + } } - if (remove) { - this.node.equips.removeChild(card); - cardsResume.remove(card); + } + } + } + addVirtualJudge(card, cards) { + card.initID(); + const player = this; + game.broadcast( + (player, card, cards) => { + player.addVirtualJudge(card, cards); + }, + player, + card, + cards + ); + game.addVideo("addVirtualJudge", player, [get.vcardInfo(card), get.cardsInfo(cards)]); + player.vcardsMap?.judges.push(card); + if (_status.discarded) { + _status.discarded.removeArray(cards); + } + player.$addVirtualJudge(card, cards); + //game.addVideo("addVirtualJudge", ???); + } + $addVirtualJudge(VCard, cards) { + const player = this; + const isViewAsCard = cards.length !== 1 || cards[0].name !== VCard.name, + info = get.info(VCard, false); + cards.forEach(card => { + card.fix(); + card.style.transform = ""; + card.classList.remove("drawinghidden"); + delete card._transform; + if (isViewAsCard) { + card.viewAs = VCard.name; + if (card.classList.contains("fullskin") || card.classList.contains("fullborder")) { + card.classList.add("fakejudge"); + card.node.background.innerHTML = lib.translate[card.viewAs + "_bg"] || get.translation(card.viewAs)[0]; } + } else { + delete card.viewAs; + card.classList.remove("fakejudge"); } + card.classList.add("drawinghidden"); + player.node.judges.insertBefore(card, player.node.judges.firstChild); }); - for (let i = 1; i <= 4; i++) { - let add = false; - if ((i == 4 || i == 3) && get.is.mountCombined()) { - add = this.hasEmptySlot("equip3_4") && !this.getEquips("equip3_4").length; - } else { - add = this.hasEmptySlot(i) && !this.getEquips(i).length; + ui.updatej(player); + } + addVirtualEquip(card, cards) { + card.initID(); + const player = this; + game.broadcast( + (player, card, cards) => { + player.addVirtualEquip(card, cards); + }, + player, + card, + cards + ); + game.addVideo("addVirtualEquip", player, [get.vcardInfo(card), get.cardsInfo(cards)]); + player.vcardsMap?.equips.push(card); + player.vcardsMap?.equips.sort((a, b) => { + return get.equipNum(a) - get.equipNum(b); + }); + player.$addVirtualEquip(card, cards); + var info = get.info(card, false); + if (info.skills) { + for (var i = 0; i < info.skills.length; i++) { + player.addSkillTrigger(info.skills[i]); } - if ( - add && - !cardsResume.some(card => { - let num = get.equipNum(card); - if ((i == 4 || i == 3) && get.is.mountCombined()) { - return num == 4 || num == 3; - } else { - return num == i; - } - }) - ) { - const card = game.createCard("empty_equip" + i, "", ""); - card.fix(); - //console.log('add '+card.name); - card.style.transform = ""; - card.classList.remove("drawinghidden"); - card.classList.add("emptyequip"); - card.classList.add("hidden"); - delete card._transform; - const equipNum = get.equipNum(card); - let equipped = false; - for (let j = 0; j < player.node.equips.childNodes.length; j++) { - if (get.equipNum(player.node.equips.childNodes[j]) >= equipNum) { - player.node.equips.insertBefore(card, player.node.equips.childNodes[j]); - equipped = true; - break; - } + } + } + $addVirtualEquip(card, cards) { + const player = this; + if (cards?.length) { + const beforeCards = []; + const disableEquips = Array.from(player.node.equips.childNodes).filter(cardx => { + return cardx.name?.startsWith("feichu_"); + }); + if (disableEquips.length) { + for (const cardx of disableEquips) player.node.equips.removeChild(cardx); + } + const isViewAsCard = cards.length !== 1 || cards[0].name !== card.name, + info = get.info(card, false); + let cardShownName = get.translation(card.name); + if (info.subtype === "equip3") { + cardShownName += "+"; + } else if (info.subtype === "equip4") { + cardShownName += "-"; + } + cards.forEach(cardx => { + cardx.fix(); + cardx.style.transform = ""; + cardx.classList.remove("drawinghidden"); + delete cardx._transform; + const suit = get.translation(cardx.suit), + number = get.strNumber(cardx.number); + if (isViewAsCard) { + cardx.viewAs = card.name; + cardx.node.name2.innerHTML = `${suit}${number} [${cardShownName}]`; + cardx.classList.add("fakeequip"); + } else { + delete cardx.viewAs; + cardx.node.name2.innerHTML = `${suit}${number} ${cardShownName}`; + cardx.classList.remove("fakeequip"); } - if (!equipped) { + }); + this.vcardsMap?.equips.some(card2 => { + if (card2 === card) return true; + beforeCards.addArray(card2.cards ?? []); + }); + let equipped = false; + for (let i = 0; i < player.node.equips.childNodes.length; i++) { + if (beforeCards.length === 0) { + equipped = true; + cards.forEach(card => { + player.node.equips.insertBefore(card, player.node.equips.childNodes[i]); + }); + break; + } else { + beforeCards.remove(player.node.equips.childNodes[i]); + } + } + if (equipped === false) { + cards.reverse(); + cards.forEach(card => { player.node.equips.appendChild(card); - if (_status.discarded) { - _status.discarded.remove(card); + }); + if (_status.discarded) _status.discarded.removeArray(cards); + } + if (disableEquips.length) { + for (const cardx of disableEquips) { + const equipNum = get.equipNum(cardx); + let equipped = false; + for (let j = 0; j < player.node.equips.childNodes.length; j++) { + const card2 = player.vcardsMap.equips.find(i => i.cards?.includes(player.node.equips.childNodes[j])); + const card3 = card2 ? card2 : player.node.equips.childNodes[j]; + if (get.equipNum(card3) >= equipNum) { + player.node.equips.insertBefore(cardx, player.node.equips.childNodes[j]); + equipped = true; + break; + } + } + if (!equipped) { + player.node.equips.appendChild(cardx); + if (_status.discarded) _status.discarded.remove(cardx); } } } @@ -10996,6 +11442,12 @@ export class Player extends HTMLDivElement { } game.animate.flame(left + this.offsetWidth / 2, top + this.offsetHeight - 30, 700, "recover"); } + /** + * @param {*} str + * @param {*} [nature] + * @param {*} [avatar] + * @param { false } [broadcast] + */ $fullscreenpop(str, nature, avatar, broadcast) { if (broadcast !== false) game.broadcast( @@ -11238,19 +11690,37 @@ export class Player extends HTMLDivElement { } $phaseJudge(card) { game.addVideo("phaseJudge", this, get.cardInfo(card)); - var player = this; - var clone = player.$throw(card); - if (lib.config.low_performance && card && card.clone) { - var waitingForTransition = get.time(); - _status.waitingForTransition = waitingForTransition; - card.clone.listenTransition(function () { - if (_status.waitingForTransition == waitingForTransition && _status.paused) { - game.resume(); - } - }); - game.pause(); + const player = this; + if (card.cards?.length) { + const cards = card.cards; + const clone = player.$throw(cards); + if (lib.config.low_performance && cards[0] && cards[0].clone) { + const waitingForTransition = get.time(); + _status.waitingForTransition = waitingForTransition; + cards[0].clone.listenTransition(function () { + if (_status.waitingForTransition == waitingForTransition && _status.paused) { + game.resume(); + } + }); + game.pause(); + } else { + game.delay(); + } } else { - game.delay(); + const VCard = game.createCard(card.name, "虚拟", ""); + const clone = player.$throw(VCard); + if (lib.config.low_performance && VCard && VCard.clone) { + const waitingForTransition = get.time(); + _status.waitingForTransition = waitingForTransition; + VCard.clone.listenTransition(function () { + if (_status.waitingForTransition == waitingForTransition && _status.paused) { + game.resume(); + } + }); + game.pause(); + } else { + game.delay(); + } } } } diff --git a/noname/library/element/vcard.js b/noname/library/element/vcard.js index 2f2582e783..81426b921d 100644 --- a/noname/library/element/vcard.js +++ b/noname/library/element/vcard.js @@ -1,6 +1,7 @@ import { get } from "../../get/index.js"; import { lib } from "../index.js"; import { _status } from "../../status/index.js"; +import { ai } from "../../ai/index.js"; export class VCard { /** @@ -8,8 +9,9 @@ export class VCard { * @param { number | Card[] } [numberOrCards] * @param { string } [name] * @param { string } [nature] + * @param { Player | false } [owner] */ - constructor(suitOrCard, numberOrCards, name, nature) { + constructor(suitOrCard, numberOrCards, name, nature, owner) { if (Array.isArray(suitOrCard)) { /** * @type {string} @@ -30,11 +32,11 @@ export class VCard { } // @ts-ignore else if (get.itemtype(suitOrCard) == "card") { - this.name = get.name(suitOrCard); - this.suit = get.suit(suitOrCard); - this.color = get.color(suitOrCard); - this.number = get.number(suitOrCard); - this.nature = get.nature(suitOrCard); + this.name = get.name(suitOrCard, owner); + this.suit = get.suit(suitOrCard, owner); + this.color = get.color(suitOrCard, owner); + this.number = get.number(suitOrCard, owner); + this.nature = get.nature(suitOrCard, owner); /** * @type { boolean } */ @@ -70,10 +72,10 @@ export class VCard { */ this.cards = numberOrCards.slice(); if (noCards) { - if (!lib.suits.includes(this.suit)) this.suit = get.suit(this); - if (!Object.keys(lib.color).includes(this.color)) this.color = get.color(this); - if (typeof this.number != "number") this.number = get.number(this); - if (!this.nature) this.nature = get.nature(this); + if (!lib.suits.includes(this.suit)) this.suit = get.suit(this, owner); + if (!Object.keys(lib.color).includes(this.color)) this.color = get.color(this, owner); + if (typeof this.number != "number") this.number = get.number(this, owner); + if (!this.nature) this.nature = get.nature(this, owner); } } else if (numberOrCards === "unsure" && !this.isCard) { if (!this.suit) this.suit = "unsure"; @@ -120,12 +122,34 @@ export class VCard { if (nature == "linked") return natures.some((n) => lib.linked.includes(n)); return get.is.sameNature(natures, nature); } - getCacheKey() { - return `[vc:${this.name}+${this.suit ? this.suit : "none"}+${ + /** + * 返回一个键值,用于在缓存中作为键名。 + * @param { boolean } [similar] true伪equals, false统一前缀 + * @returns {string} cacheKey + */ + getCacheKey(similar) { + let prefix = "[object:"; + if (similar !== false) prefix = similar ? "[card:" : "[vcard:"; + if (this.cardid) return prefix + this.cardid + "]"; + if (!this.cards.length) return prefix + `${this.name}+${ + this.suit ? this.suit : (this.color || "none") + }+${ this.number === undefined ? "none" : this.number - }${this.nature ? "+" : ""}${this.nature ? this.nature : ""}]`; + }${ + this.nature ? "+" + this.nature : "" + }]`; + if (similar !== undefined && this.cards.length === 1) return ai.getCacheKey(this.cards[0], similar); + return prefix + "[array:[" + this.cards.map(i => { + return ai.getCacheKey(i, similar); + }).join("-") + "]]]"; } hasGaintag(tag) { return this.gaintag && this.gaintag.includes(tag); } + initID() { + if (!this.vcardID){ + this.vcardID = get.id(); + if (lib.vcardOL) lib.vcardOL[this.vcardID] = this; + } + } } diff --git a/noname/library/index.js b/noname/library/index.js index 2e1a2df66d..03ccee7ea0 100644 --- a/noname/library/index.js +++ b/noname/library/index.js @@ -36,7 +36,7 @@ export class Library { updateURLS = updateURLs; updateURL = updateURLs.github; mirrorURL = updateURLs.coding; - hallURL = "47.99.105.222"; + hallURL = ""; assetURL = assetURL; userAgent = userAgent; characterDefaultPicturePath = characterDefaultPicturePath; @@ -107,6 +107,11 @@ export class Library { onresize = []; onphase = []; onwash = []; + onround = [ + function roundSkillCheck(event) { + return !event.skill; + }, + ]; onover = []; ondb = []; ondb2 = []; @@ -243,6 +248,9 @@ export class Library { objectURL = new Map(); hookmap = {}; + /** + * @type { { character?: SMap, card?: SMap, mode?: SMap, player?: SMap, extension?: SMap, play?: SMap } } + */ imported = {}; layoutfixed = ["chess", "tafang", "stone"]; pinyins = { @@ -324,28 +332,28 @@ export class Library { return ai - get.value(cardx); } else if (get.attitude(player, source) <= 0) return 0; return 5 - get.value(cardx); - }, + }, }); if (!game.online) return; _status.event._resultid = id; game.resume(); }; - ("step 1"); + "step 1"; var type = get.type2(card); event.list = game.filterPlayer(current => current != player && current.countCards("h") && (_status.connectMode || current.hasCard(cardx => get.type2(cardx) == type, "h"))).sortBySeat(_status.currentPhase || player); event.id = get.id(); - ("step 2"); + "step 2"; if (!event.list.length) event.finish(); else if (_status.connectMode && (event.list[0].isOnline() || event.list[0] == game.me)) event.goto(4); else event.send((event.current = event.list.shift()), event.card, player, trigger.targets, event.id, trigger.parent.id, trigger.yingbianZhuzhanAI); - ("step 3"); + "step 3"; if (result.bool) { event.zhuzhanresult = event.current; event.zhuzhanresult2 = result; if (event.current != game.me) game.delayx(); event.goto(8); } else event.goto(2); - ("step 4"); + "step 4"; var id = event.id, sendback = (result, player) => { if (result && result.id == id && !event.zhuzhanresult && result.bool) { @@ -382,16 +390,16 @@ export class Library { if (value != player) value.showTimer(); }); event.withol = withol; - ("step 5"); + "step 5"; if (!result || !result.bool || event.zhuzhanresult) return; game.broadcast("cancel", event.id); event.zhuzhanresult = game.me; event.zhuzhanresult2 = result; - ("step 6"); + "step 6"; if (event.withol && !event.resultOL) game.pause(); - ("step 7"); + "step 7"; game.players.forEach(value => value.hideTimer()); - ("step 8"); + "step 8"; if (event.zhuzhanresult) { var target = event.zhuzhanresult; target.line(player, "green"); @@ -3684,7 +3692,7 @@ export class Library { init: false, unfrequent: true, onclick(bool) { - game.saveConfig("show_statusbar", bool); + game.saveConfig("show_statusbar_android", bool); if (window.StatusBar && lib.device == "android") { if (bool) { window.StatusBar.overlaysWebView(false); @@ -6957,6 +6965,27 @@ export class Library { name: "启用手气卡", init: false, frequent: true, + }, + connect_double_character: { + name: "启用双将", + init: "single", + item: { + single: "不启用", + double: "启用双将", + singble: "单双任选", + }, + restart: true, + }, + connect_double_hp: { + name: "双将体力上限", + init: "pingjun", + item: { + hejiansan: "和减三", + pingjun: "平均值", + zuidazhi: "最大值", + zuixiaozhi: "最小值", + zonghe: "相加", + }, restart: true, }, update: function (config, map) { @@ -6970,6 +6999,17 @@ export class Library { } else { map.connect_change_card.show(); } + if (config.connect_single_mode != "dianjiang") { + map.connect_double_character.hide(); + map.connect_double_hp.hide(); + } else { + map.connect_double_character.show(); + if (["double", "singble"].includes(config.connect_double_character)) { + map.connect_double_hp.show(); + } else { + map.connect_double_hp.hide(); + } + } }, }, config: { @@ -7002,6 +7042,28 @@ export class Library { unlimited: "无限", }, }, + double_character: { + name: "启用双将", + init: "single", + item: { + single: "不启用", + double: "启用双将", + singble: "单双任选", + }, + restart: true, + }, + double_hp: { + name: "双将体力上限", + init: "pingjun", + item: { + hejiansan: "和减三", + pingjun: "平均值", + zuidazhi: "最大值", + zuixiaozhi: "最小值", + zonghe: "相加", + }, + restart: true, + }, update: function (config, map) { if (config.single_mode != "normal") { map.enable_jin.hide(); @@ -7013,6 +7075,17 @@ export class Library { } else { map.change_card.show(); } + if (config.single_mode != "dianjiang") { + map.double_character.hide(); + map.double_hp.hide(); + } else { + map.double_character.show(); + if (["double", "singble"].includes(config.double_character)) { + map.double_hp.show(); + } else { + map.double_hp.hide(); + } + } }, }, }, @@ -8051,6 +8124,9 @@ export class Library { game.export(lib.init.encode(JSON.stringify(_status.videoToSave)), "无名杀 - 录像 - " + _status.videoToSave.name[0] + " - " + _status.videoToSave.name[1]); } } + /** + * @param {Function} fn + */ genAsync(fn) { return gnc.of(fn); } @@ -8060,7 +8136,7 @@ export class Library { for (const content of item) { yield content; } - })() + })() : Promise.resolve(item); } gnc = { @@ -9547,7 +9623,6 @@ export class Library { element = { content: Element.Content, - contents: Element.Contents, Player: Element.Player, Card: Element.Card, VCard: Element.VCard, @@ -9809,7 +9884,7 @@ export class Library { cardGiftable: (card, player, target, strict) => { const mod = game.checkMod(card, player, target, "unchanged", "cardGiftable", player); if (!mod || (strict && ((mod == "unchanged" && (get.position(card) != "h" || !get.cardtag(card, "gifts"))) || player == target))) return false; - return get.type(card, false) != "equip" || target.canEquip(card, true); + return get.type(card, null, target) != "equip" || target.canEquip(card, true); }, /** * Check if the card is recastable @@ -9966,9 +10041,12 @@ export class Library { return true; }, characterDisabled: function (i, libCharacter) { - if (!lib.character[i] || lib.character[i].isAiForbidden) return true; + const args = Array.from(arguments).slice(2); + if (!lib.character[i]) return true; if (lib.character[i].isUnseen) return true; - if (lib.config.forbidai.includes(i)) return true; + if (!args.includes("ignoreForibidden")) { + if (lib.config.forbidai.includes(i) || lib.character[i].isAiForbidden) return true; + } if (lib.characterFilter[i] && !lib.characterFilter[i](get.mode())) return true; if (_status.connectMode) { if (lib.configOL.banned.includes(i) || lib.connectBanned.includes(i)) return true; @@ -10020,13 +10098,14 @@ export class Library { }, characterDisabled2: function (i) { var info = lib.character[i]; + const args = Array.from(arguments).slice(1); if (!info) return true; if (info[4]) { if (info.isBoss) return true; if (info.isHiddenBoss) return true; if (info.isMinskin) return true; if (info.isUnseen) return true; - if (info.isAiForbidden && (!_status.event.isMine || !_status.event.isMine())) return true; + if (!args.includes("ignoreForibidden") && info.isAiForbidden && (!_status.event.isMine || !_status.event.isMine())) return true; if (lib.characterFilter[i] && !lib.characterFilter[i](get.mode())) return true; } return false; @@ -10645,7 +10724,7 @@ export class Library { storage: { stratagem_buffed: 1, }, - }) + }) : new lib.element.VCard(); } return null; @@ -11043,6 +11122,11 @@ export class Library { filter: function (event, player) { return player.storage.zhengsu_leijin || player.storage.zhengsu_bianzhen || player.storage.zhengsu_mingzhi; }, + filterx: function (skill, player) { + const zhengsus = player.storage[skill]; + if (!zhengsus || !zhengsus.length) return false; + return zhengsus.some(zhengsu => player.storage[zhengsu]); + }, content: function () { player.chooseDrawRecover(2, "整肃奖励:摸两张牌或回复1点体力"); }, @@ -11332,6 +11416,27 @@ export class Library { trigger.player.loseMaxHp(trigger.num).source = player; }, }, + _doublegroup_choice: { + trigger: { + global: "gameStart", + player: "enterGame", + }, + firstDo: true, + forced: true, + popup: false, + priority: 25, + charlotte: true, + filter: function (event, player) { + return get.mode() != "guozhan" && get.is.double(player.name1) && !player._groupChosen; + }, + content: function () { + "step 0"; + player._groupChosen = true; + player.chooseControl(get.is.double(player.name1, true)).set("prompt", "请选择你的势力"); + "step 1"; + player.changeGroup(result.control); + }, + }, aozhan: { charlotte: true, mod: { @@ -11601,7 +11706,7 @@ export class Library { nodamage: true, effect: { target: function (card, player, target, current) { - if (get.tag(card, "damage")) return [0, 0]; + if (get.tag(card, "damage")) return "zeroplayertarget"; }, }, }, @@ -11809,7 +11914,7 @@ export class Library { "step 0"; event.dying = trigger.player; if (!event.acted) event.acted = []; - ("step 1"); + "step 1"; if (trigger.player.isDead()) { event.finish(); return; @@ -11852,7 +11957,11 @@ export class Library { } return 1; }, - ai2: get.effect_use, + ai2: function (target) { + let effect_use = get.effect_use(target); + if (effect_use <= 0) return effect_use; + return get.effect(target); + }, type: "dying", targetRequired: true, dying: event.dying, @@ -11860,7 +11969,7 @@ export class Library { } else { event._result = { bool: false }; } - ("step 2"); + "step 2"; if (result.bool) { var player = trigger.player; if (player.hp <= 0 && !trigger.nodying && !player.nodying && player.isAlive() && !player.isOut() && !player.removed) event.goto(0); @@ -11950,7 +12059,7 @@ export class Library { content: function () { "step 0"; event.logvid = trigger.getLogv(); - ("step 1"); + "step 1"; event.targets = game.filterPlayer(function (current) { return current != event.player && current.isLinked(); }); @@ -11960,7 +12069,7 @@ export class Library { event._args = [trigger.num, trigger.nature, trigger.cards, trigger.card]; if (trigger.source) event._args.push(trigger.source); else event._args.push("nosource"); - ("step 2"); + "step 2"; if (event.targets.length) { var target = event.targets.shift(); if (target.isLinked()) target.damage.apply(target, event._args.slice(0)); @@ -12676,6 +12785,7 @@ export class Library { lib.configOL = config; lib.playerOL = {}; lib.cardOL = {}; + lib.vcardOL = {}; game.clearArena(); game.finishCards(); @@ -12788,6 +12898,7 @@ export class Library { lib.configOL = config; lib.playerOL = {}; lib.cardOL = {}; + lib.vcardOL = {}; game.loadModeAsync(config.mode, function (mode) { for (var i in mode.ai) { @@ -12948,8 +13059,13 @@ export class Library { player.directgain(info.handcards); lib.playerOL[i] = player; - for (var i = 0; i < info.equips.length; i++) { - player.$equip(info.equips[i]); + if (info.vcardsMap) { + for (var i = 0; i < info.vcardsMap.equips.length; i++) { + player.addVirtualEquip(info.vcardsMap.equips[i], info.vcardsMap.equips[i].cards); + } + for (var i = 0; i < info.vcardsMap.judges.length; i++) { + player.addVirtualJudge(info.vcardsMap.judges[i], info.vcardsMap.judges[i].cards); + } } for (var i = 0; i < info.handcards.length; i++) { info.handcards[i].addGaintag(info.gaintag[i]); @@ -13635,6 +13751,15 @@ export class Library { getSpan: () => `${get.prefixSpan("手杀")}${get.prefixSpan("界")}`, }, ], + [ + "手杀SP", + { + /** + * @returns {string} + */ + getSpan: () => `${get.prefixSpan("手杀")}${get.prefixSpan("SP")}`, + }, + ], [ "战役篇神", { @@ -13712,6 +13837,22 @@ export class Library { nature: "firemm", }, ], + [ + "桃", + { + color: "#FFC0CB", + nature: "firemm", + }, + ], + [ + "桃神", + { + /** + * @returns {string} + */ + getSpan: () => `${get.prefixSpan("桃")}${get.prefixSpan("神")}`, + }, + ], [ "玄", { @@ -13719,6 +13860,22 @@ export class Library { nature: "metalmm", }, ], + [ + "荆", + { + color: "#00ff00", + nature: "firemm", + }, + ], + [ + "荆神", + { + /** + * @returns {string} + */ + getSpan: () => `${get.prefixSpan("荆")}${get.prefixSpan("神")}`, + }, + ], [ "魂", { @@ -13737,7 +13894,30 @@ export class Library { "标", { color: "#912cee", - nature: "purple", + nature: "metalmm", + }, + ], + [ + "牢", + { + color: "#EEEE00", + nature: "black", + }, + ], + [ + "牢神", + { + /** + * @returns {string} + */ + getSpan: () => `${get.prefixSpan("牢")}${get.prefixSpan("神")}`, + }, + ], + [ + "鼎", + { + color: "#ffccff", + nature: "black", }, ], ]); diff --git a/noname/library/init/index.js b/noname/library/init/index.js index 35f99bce59..2765dfc436 100644 --- a/noname/library/init/index.js +++ b/noname/library/init/index.js @@ -3,15 +3,12 @@ import { game } from "../../game/index.js"; import { lib } from "../index.js"; import { _status } from "../../status/index.js"; import { ui } from "../../ui/index.js"; -import { gnc } from "../../gnc/index.js"; import { LibInitPromises } from "./promises.js"; -import { GameEvent } from "../element/gameEvent.js"; -import { GameEventPromise } from "../element/gameEventPromise.js"; import { rootURL } from "../../../noname.js"; import security from "../../util/security.js"; -import { CodeSnippet, ErrorManager } from "../../util/error.js"; +import { ContentCompiler } from "../element/gameEvent.js"; export class LibInit { /** @@ -90,7 +87,7 @@ export class LibInit { event._resultid = null; event._result = null; game.pause(); - ("step 1"); + "step 1"; if (result) { if (event._resultid) { result.id = event._resultid; @@ -593,189 +590,9 @@ export class LibInit { * @returns */ parsex(item, scope) { - // 虽然现在 parsex 被控制到了沙盒, - // 但是因为默认沙盒还是可以额外操作东西, - // 故而对不同的运行域做了区分 - const [ - ModFunction, - ModGeneratorFunction, - // ModAsyncFunction, - // ModAsyncGeneratorFunction, - ] = security.getIsolatedsFrom(item); - - //by 诗笺、Tipx-L - /** - * @param {Function} func - */ - function Legacy(func) { - // 沙盒在封装函数时,为了保存源代码会另外存储函数的源代码 - /** @type {(func: Function) => string} */ - const decompileFunction = security.isSandboxRequired() - ? security.importSandbox().Marshal.decompileFunction - : Function.prototype.call.bind(Function.prototype.toString); - //Remove all comments - //移除所有注释 - const code = decompileFunction(func) - .replace(/((?:(?:^[ \t]*)?(?:\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\/(?:[ \t]*\r?\n(?=[ \t]*(?:\r?\n|\/\*|\/\/)))?|\/\/(?:[^\\]|\\(?:\r?\n)?)*?(?:\r?\n(?=[ \t]*(?:\r?\n|\/\*|\/\/))|(?=\r?\n))))+)|("(?:\\[\s\S]|[^"\\])*"|'(?:\\[\s\S]|[^'\\])*'|(?:\r?\n|[\s\S])[^/"'\\\s]*)/gm, "$2") - .trim(); - //获取第一个 { 后的所有字符 - let str = code.slice(code.indexOf("{") + 1); - //判断代码中是否有debugger - let regex = /event\.debugger\(\)/; - let hasDebugger = false; - let insertDebugger = `yield code=>eval(code);`; - let debuggerSkip = 0; - let debuggerResult; - while ((debuggerResult = str.slice(debuggerSkip).match(regex)) != null) { - let debuggerCopy = str; - debuggerCopy = debuggerCopy.slice(0, debuggerSkip + debuggerResult.index) + insertDebugger + debuggerCopy.slice(debuggerSkip + debuggerResult.index + debuggerResult[0].length, -1); - //测试是否有错误 - try { - new ModGeneratorFunction(debuggerCopy); - str = debuggerCopy + "}"; - debuggerSkip += debuggerResult.index + insertDebugger.length; - hasDebugger = true; - } catch (error) { - debuggerSkip += debuggerResult.index + debuggerResult[0].length; - } - } - //func中要写步骤的话,必须要写step 0 - if (str.indexOf("step 0") == -1) { - str = "{if(event.step==1) {event.finish();return;}\n" + str; - } else { - let skip = 0; - let k = 0; - let result; - //去除99个step的限制 - while ((result = str.slice(skip).match(new RegExp(`\\(?['"]step ${k}['"]\\)?;?`))) != null) { - let insertStr; - if (k == 0) { - insertStr = `switch(step){case 0:`; - } else { - insertStr = `break;case ${k}:`; - } - let copy = str; - copy = copy.slice(0, skip + result.index) + insertStr + copy.slice(skip + result.index + result[0].length); - //测试是否有错误 - try { - new (hasDebugger ? ModGeneratorFunction : ModFunction)(copy); - str = copy; - skip += result.index + insertStr.length; - } catch (error) { - k--; - skip += result.index + result[0].length; - } - k++; - } - str = `if(event.step==${k}){event.finish();return;}` + str; - } - if (!scope) { - const argList = ["event", "step", "source", "player", "target", "targets", "card", "cards", "skill", "forced", "num", "trigger", "result", "_status", "lib", "game", "ui", "get", "ai"]; - const compiled = new (hasDebugger ? ModGeneratorFunction : ModFunction)(...argList, str); - ErrorManager.setCodeSnippet(compiled, new CodeSnippet(code, 3)); // 记录编译后函数的原代码片段 - return compiled; - } else { - new (hasDebugger ? ModGeneratorFunction : ModFunction)(str); // 防止注入喵 - return scope(`(function${hasDebugger ? "*" : ""}(event,step,source,player,target,targets, - card,cards,skill,forced,num,trigger,result, - _status,lib,game,ui,get,ai){${str}})`); - } - } - switch (typeof item) { - case "object": - if (Array.isArray(item)) { - let lastEvent = null; - return function* (event, step, source, player, target, targets, card, cards, skill, forced, num, trigger, result, _status, lib, game, ui, get, ai) { - if (step >= item.length) return event.finish(); - var current = item[step]; - if (typeof current != "function") throw new Error(`content ${step} of ${event.name} is not vaild: ${current}`); - var currentResult = current( - event, - { - event: event, - step: step, - source: source, - player: player, - target: target, - targets: targets, - card: card, - cards: cards, - skill: skill, - forced: forced, - num: num, - trigger: trigger, - result: result, - }, - lastEvent && "result" in lastEvent ? lastEvent.result : null - ); - // TODO: use `event.debugger` to replace source - if (gnc.is.generator(currentResult)) lastEvent = yield* currentResult; - else lastEvent = currentResult; - }; - } else { - if (Symbol.iterator in item) return lib.init.parsex(Array.from(item)); - // 根据狂神喵的建议,禁用parsex接受字符串喵 - // if (item.toString !== Object.prototype.toString) return lib.init.parsex(item.toString()); - if ("render" in item) { - // TODO: Object Render Parse - throw new Error("NYI: Object Render Parse"); - } - // TODO: Object Other Parse - throw new Error("NYI: Object Other Parse"); - } - case "function": - if (gnc.is.generatorFunc(item)) { - // let gen, lastEvent; - let content = function* (event, step, source, player, target, targets, card, cards, skill, forced, num, trigger, result, _status, lib, game, ui, get, ai) { - event.step = NaN; - if (!this.gen) - this.gen = item(event, { - event, - step, - source, - player, - target, - targets, - card, - cards, - skill, - forced, - num, - trigger, - result, - }); - - let res; - if (!this.last) res = this.gen.next(); - else if (typeof this.last !== "object") res = this.gen.next(this.last); - else if (this.last instanceof GameEvent || this.last instanceof GameEventPromise) res = this.gen.next(this.last.result); - else res = this.gen.next(this.last); - - if (res.done) { - this.gen = null; - return event.finish(); - } - let currentResult = res.value; - // TODO: use `event.debugger` to replace source - if (typeof currentResult == "function") yield currentResult; - else { - if (Array.isArray(currentResult)) { - event.step = currentResult[1]; - currentResult = currentResult[0]; - } - this.last = currentResult; - } - }.bind({ - gen: null, - last: undefined, - }); - content._gen = true; - return content; - } else if (item._parsed) return item; - return Legacy(item); - default: - throw new TypeError("为确保安全禁止用parsex解析字符串"); - } + if (scope) throw new Error("parsex已经被拆分,不再支持scope的使用"); + // parsex 的 Legacy 主体移动到 noname/library/event/compilers/StepCompiler.ts + return ContentCompiler.compile(item); } eval(func) { diff --git a/noname/status/index.js b/noname/status/index.js index dc6324d85b..37a8895812 100644 --- a/noname/status/index.js +++ b/noname/status/index.js @@ -1,20 +1,21 @@ import { lib } from "../library/index.js"; +import PauseManager from "../game/PauseManager.js"; +import { GameEventManager } from "../library/element/gameEvent.js"; export class status { - paused = false; - paused2 = false; - /** - * @type { boolean | "paused" } - */ - paused3 = false; - over = false; + imchoosing = false; clicked = false; auto = false; + eventManager= new GameEventManager(); /** - * @type { GameEventPromise } + * @type { GameEvent | undefined } */ - // @ts-ignore - event = null; + get event() { + return this.eventManager.getStatusEvent(); + } + set event(event) { + this.eventManager.setStatusEvent(event); + } ai = {}; lastdragchange = []; /** @@ -58,10 +59,7 @@ export class status { * @type { boolean | undefined } */ touchconfirmed = undefined; - /** - * @type { boolean | undefined } - */ - connectMode = undefined; + connectMode = false; /** * @type { boolean | undefined } */ @@ -94,6 +92,55 @@ export class status { * @type { boolean } */ roundSkipped; + /** + * @type { boolean } + */ + withError = false; + /** + * @type { string | undefined } + */ + mode = undefined; + /** + * @type { { [key: string]: any } | undefined } + */ + brawl = undefined; + /** + * @type { string | undefined } + */ + playback = undefined; + /** + * @type { number | undefined } + */ + coinCoeff = undefined; + pauseManager = new PauseManager(); + get paused() { + return this.pauseManager.pause.isStarted; + } + set paused(bool) { + if (bool) this.pauseManager.pause.start(); + else this.pauseManager.pause.resolve(); + } + get paused2() { + return this.pauseManager.pause2.isStarted; + } + set paused2(bool) { + if (bool) this.pauseManager.pause2.start(); + else this.pauseManager.pause2.resolve(); + } + get paused3() { + return this.pauseManager.pause3.isStarted; + } + set paused3(bool) { + if (bool) this.pauseManager.pause3.start(); + else this.pauseManager.pause3.resolve(); + } + get over() { + return this.pauseManager.over.isStarted; + } + set over(bool) { + if (bool) this.pauseManager.over.start(); + else this.pauseManager.over.resolve(); + } } export let _status = new status(); diff --git a/noname/ui/click/index.js b/noname/ui/click/index.js index f2a20ce747..87825b8726 100644 --- a/noname/ui/click/index.js +++ b/noname/ui/click/index.js @@ -2692,7 +2692,8 @@ export class Click { } // ui.click.skin(this,player.name); game.pause2(); - ui.click.charactercard(player.name1 || player.name, null, null, true, this); + var audioName=player.skin.name || player.name1 || player.name; + ui.click.charactercard(player.name1 || player.name, null, null, true, this, audioName); } avatar2() { if (!lib.config.doubleclick_intro) return; @@ -2711,7 +2712,7 @@ export class Click { } // ui.click.skin(this,player.name2); game.pause2(); - ui.click.charactercard(player.name2, null, null, true, this); + ui.click.charactercard(player.name2, null, null, true, this, player.skin.name2 || player.name2); } connectroom(e) { if (_status.dragged) return; @@ -3117,7 +3118,8 @@ export class Click { delete this.logvtimeout; } } - charactercard(name, sourcenode, noedit, resume, avatar) { + charactercard(name, sourcenode, noedit, resume, avatar, audioName) { + if(!audioName) audioName = name; if (_status.dragged) return; if (lib.config.theme != "simple") { ui.window.classList.add("shortcutpaused"); @@ -3155,7 +3157,7 @@ export class Click { changeskinfunc(); } }) - .setBackground(name, "character"); + .setBackground(audioName || name, "character"); var changeskinfunc = null; var nameskin = name; var nameskin2 = name; @@ -3360,10 +3362,12 @@ export class Click { } // 添加台词部分 - const dieAudios = game.parseDieTextMap(name).map(i => i.text).filter(Boolean); + let dieAudios = game.parseDieTextMap(audioName).map(i => i.text).filter(Boolean); + if(!dieAudios.length) dieAudios = game.parseDieTextMap(name).map(i => i.text).filter(Boolean); const skillAudioMap = new Map(); nameinfo.skills.forEach(skill => { - const voiceMap = game.parseSkillText(skill, name); + let voiceMap = game.parseSkillText(skill, audioName); + if(!voiceMap.length) voiceMap = game.parseSkillText(skill, name); if(voiceMap.length) skillAudioMap.set(skill, voiceMap); }); const derivationSkillAudioMap = new Map(); @@ -3376,7 +3380,8 @@ export class Click { } for(var i=0; i introduction.appendChild(value)); // 添加台词部分 - const dieAudios = game.parseDieTextMap(name).map(i => i.text).filter(Boolean); + let dieAudios = game.parseDieTextMap(audioName).map(i => i.text).filter(Boolean); + if(!dieAudios.length) dieAudios = game.parseDieTextMap(name).map(i => i.text).filter(Boolean); const skillAudioMap = new Map(); nameInfo.skills.forEach(skill => { - const voiceMap = game.parseSkillText(skill, name); + let voiceMap = game.parseSkillText(skill, audioName); + if(!voiceMap.length) voiceMap = game.parseSkillText(skill, name); if(voiceMap.length) skillAudioMap.set(skill, voiceMap); }); const derivationSkillAudioMap = new Map(); @@ -3723,7 +3730,8 @@ export class Click { } for(var i=0; i { node = ui.create.div( @@ -3169,7 +3170,7 @@ export class Create { return node; }, /** - * @returns { import("../library/index.js").Button } + * @returns { import("../../library/index.js").Button } */ blank: (item, type, position, noclick, node) => { node = ui.create.div(".button.card", position); @@ -3188,7 +3189,7 @@ export class Create { return node; }, /** - * @returns { import("../library/index.js").Button } + * @returns { import("../../library/index.js").Button } */ card: (item, type, position, noclick, node) => { if (typeof item.copy == "function") { @@ -3213,8 +3214,9 @@ export class Create { if (!noclick) { lib.setIntro(node); } + const itemPosition = get.position(item) if ( - get.position(item) == "j" && + (itemPosition === "e" || itemPosition === "j") && item.viewAs && item.viewAs != item.name && lib.config.cardtempname != "off" @@ -3224,7 +3226,7 @@ export class Create { return node; }, /** - * @returns { import("../library/index.js").Button } + * @returns { import("../../library/index.js").Button } */ vcard: (item, type, position, noclick, node) => { if (typeof item == "string") { @@ -3237,7 +3239,7 @@ export class Create { return node; }, /** - * @returns { import("../library/index.js").Button } + * @returns { import("../../library/index.js").Button } */ character: (item, type, position, noclick, node) => { if (node) { @@ -3415,7 +3417,7 @@ export class Create { return node; }, /** - * @returns { import("../library/index.js").Button } + * @returns { import("../../library/index.js").Button } */ characterx: (item, type, position, noclick, node) => { return ui.create.buttonPresets.character( @@ -3427,7 +3429,7 @@ export class Create { ); }, /** - * @returns { import("../library/index.js").Button } + * @returns { import("../../library/index.js").Button } */ player: (item, type, position, noclick, node) => { if (node) { diff --git a/noname/ui/create/menu/pages/otherMenu.js b/noname/ui/create/menu/pages/otherMenu.js index 647506e6d9..45c2b9cdbc 100644 --- a/noname/ui/create/menu/pages/otherMenu.js +++ b/noname/ui/create/menu/pages/otherMenu.js @@ -1484,6 +1484,7 @@ export const otherMenu = function (/** @type { boolean | undefined } */ connectM lib.videos = []; ui.create.videoNode = (video, before) => { lib.videos.remove(video); + if (_status.over) return; lib.videos[before === true ? "unshift" : "push"](video); }; node._initLink = function () { diff --git a/noname/ui/index.js b/noname/ui/index.js index 2d524574e8..2be1add039 100644 --- a/noname/ui/index.js +++ b/noname/ui/index.js @@ -38,6 +38,10 @@ export class UI { * @type { Dialog } */ dialog; + /** + * @type { HTMLDivElement } + */ + system; /** * @type { HTMLDivElement } */ @@ -145,6 +149,22 @@ export class UI { * @type {HTMLDivElement} */ cardPile; + /** + * @type {HTMLDivElement} + */ + discardPile; + /** + * @type {HTMLDivElement} + */ + ordering; + /** + * @type {HTMLDivElement} + */ + coin; + /** + * @type {SMap} + */ + css; refresh(node) { void window.getComputedStyle(node, null).getPropertyValue("opacity"); } diff --git a/noname/util/security.js b/noname/util/security.js index c3a197f0d4..38b21d47b6 100644 --- a/noname/util/security.js +++ b/noname/util/security.js @@ -12,9 +12,7 @@ const SANDBOX_AUTOTEST_NODELAY = false; const SANDBOX_DEV = false; const WSURL_FOR_IP = /ws:\/\/(\d+.\d+.\d+.\d+):\d+\//; -const TRUSTED_IPS = Object.freeze([ - "47.99.105.222", -]); +const TRUSTED_IPS = Object.freeze([]); // 声明导入类 /** @type {boolean} */