diff --git a/.editorconfig b/.editorconfig index d8a6ed938..61c31431d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,7 +3,7 @@ root = true [*] charset = utf-8 -end_of_line = crlf +end_of_line = lf insert_final_newline = true [*.js] diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..fde9df50f --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,3 @@ +> W.I.P + +自由开源是无名杀社区的灵魂,希望所有人都能够遵循这一精神。 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..88c1282ad --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,3 @@ +> W.I.P + +请参考[此处](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)了解无名杀的PR规范。 diff --git a/README.md b/README.md index 3a5b36c02..cf85e125a 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,17 @@ https://github.com/nonameShijian/noname-server --- +贡献代码可阅读相关文档: + +[Git下载安装指南](https://github.com/libccy/noname/wiki/Git%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85%E6%8C%87%E5%8D%97) + +[Github桌面版客户端使用入门](https://docs.github.com/zh/desktop/overview/getting-started-with-github-desktop) + +[如何提交代码到《无名杀》Github仓库](https://github.com/libccy/noname/wiki/%E5%A6%82%E4%BD%95%E6%8F%90%E4%BA%A4%E4%BB%A3%E7%A0%81%E5%88%B0%E3%80%8A%E6%97%A0%E5%90%8D%E6%9D%80%E3%80%8BGithub%E4%BB%93%E5%BA%93) + +[《无名杀》项目 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 (图片素材加载速度较慢,不推荐) diff --git a/audio/die/dc_caoshuang.mp3 b/audio/die/dc_caoshuang.mp3 new file mode 100644 index 000000000..197e405b0 Binary files /dev/null and b/audio/die/dc_caoshuang.mp3 differ diff --git a/audio/die/guotu.mp3 b/audio/die/guotu.mp3 new file mode 100644 index 000000000..b98d647d4 Binary files /dev/null and b/audio/die/guotu.mp3 differ diff --git a/audio/die/junk_guanyu.mp3 b/audio/die/junk_guanyu.mp3 new file mode 100644 index 000000000..76ce3f303 Binary files /dev/null and b/audio/die/junk_guanyu.mp3 differ diff --git a/audio/die/ol_sb_yuanshao.mp3 b/audio/die/ol_sb_yuanshao.mp3 new file mode 100644 index 000000000..b9060a40e Binary files /dev/null and b/audio/die/ol_sb_yuanshao.mp3 differ diff --git a/audio/skill/dcfanshi1.mp3 b/audio/skill/dcfanshi1.mp3 new file mode 100644 index 000000000..df118d549 Binary files /dev/null and b/audio/skill/dcfanshi1.mp3 differ diff --git a/audio/skill/dcfanshi2.mp3 b/audio/skill/dcfanshi2.mp3 new file mode 100644 index 000000000..fc675e346 Binary files /dev/null and b/audio/skill/dcfanshi2.mp3 differ diff --git a/audio/skill/dcfudou1.mp3 b/audio/skill/dcfudou1.mp3 new file mode 100644 index 000000000..1601c7461 Binary files /dev/null and b/audio/skill/dcfudou1.mp3 differ diff --git a/audio/skill/dcfudou2.mp3 b/audio/skill/dcfudou2.mp3 new file mode 100644 index 000000000..721715d7f Binary files /dev/null and b/audio/skill/dcfudou2.mp3 differ diff --git a/audio/skill/dcjianzhuan1.mp3 b/audio/skill/dcjianzhuan1.mp3 new file mode 100644 index 000000000..4aeefb409 Binary files /dev/null and b/audio/skill/dcjianzhuan1.mp3 differ diff --git a/audio/skill/dcjianzhuan2.mp3 b/audio/skill/dcjianzhuan2.mp3 new file mode 100644 index 000000000..9507853df Binary files /dev/null and b/audio/skill/dcjianzhuan2.mp3 differ diff --git a/audio/skill/olqushi1.mp3 b/audio/skill/olqushi1.mp3 new file mode 100644 index 000000000..7bee1ab45 Binary files /dev/null and b/audio/skill/olqushi1.mp3 differ diff --git a/audio/skill/olqushi2.mp3 b/audio/skill/olqushi2.mp3 new file mode 100644 index 000000000..04407ec1f Binary files /dev/null and b/audio/skill/olqushi2.mp3 differ diff --git a/audio/skill/olsbhetao1.mp3 b/audio/skill/olsbhetao1.mp3 new file mode 100644 index 000000000..97d08d11f Binary files /dev/null and b/audio/skill/olsbhetao1.mp3 differ diff --git a/audio/skill/olsbhetao2.mp3 b/audio/skill/olsbhetao2.mp3 new file mode 100644 index 000000000..0e378bfa6 Binary files /dev/null and b/audio/skill/olsbhetao2.mp3 differ diff --git a/audio/skill/olsbshenli1.mp3 b/audio/skill/olsbshenli1.mp3 new file mode 100644 index 000000000..8f530eafd Binary files /dev/null and b/audio/skill/olsbshenli1.mp3 differ diff --git a/audio/skill/olsbshenli2.mp3 b/audio/skill/olsbshenli2.mp3 new file mode 100644 index 000000000..088198f20 Binary files /dev/null and b/audio/skill/olsbshenli2.mp3 differ diff --git a/audio/skill/olsbshishou1.mp3 b/audio/skill/olsbshishou1.mp3 new file mode 100644 index 000000000..6c29b43eb Binary files /dev/null and b/audio/skill/olsbshishou1.mp3 differ diff --git a/audio/skill/olsbshishou2.mp3 b/audio/skill/olsbshishou2.mp3 new file mode 100644 index 000000000..0e93a590c Binary files /dev/null and b/audio/skill/olsbshishou2.mp3 differ diff --git a/audio/skill/olsbyufeng1.mp3 b/audio/skill/olsbyufeng1.mp3 new file mode 100644 index 000000000..ae5c6cf7b Binary files /dev/null and b/audio/skill/olsbyufeng1.mp3 differ diff --git a/audio/skill/olweijie1.mp3 b/audio/skill/olweijie1.mp3 new file mode 100644 index 000000000..358fd3792 Binary files /dev/null and b/audio/skill/olweijie1.mp3 differ diff --git a/audio/skill/olweijie2.mp3 b/audio/skill/olweijie2.mp3 new file mode 100644 index 000000000..ccd833930 Binary files /dev/null and b/audio/skill/olweijie2.mp3 differ diff --git a/card/extra.js b/card/extra.js index 4bb555b7d..e3dc67ed2 100644 --- a/card/extra.js +++ b/card/extra.js @@ -308,12 +308,7 @@ game.import('card',function(lib,game,ui,get,ai,_status){ if(status*get.attitude(viewer,player._trueMe||player)>0 || target.hasSkillTag('nodamage') || target.hasSkillTag('nofire') || target.hasSkillTag('nothunder') || get.attitude(viewer,player)>0 || (1+target.countCards('hs'))*_status.event.getRand()>1.57) return 0; }, basic:{ - order:(item,player)=>{ - if(player.hasCard(card=>{ - return get.tag(card,'damage')&&game.hasNature(card)&&player.hasValueTarget(card); - },'hs')) return 7.3; - return 4.1; - }, + order:7.3, useful:1.2, value:4 }, diff --git a/card/guozhan.js b/card/guozhan.js index e043aa8cd..3e5ad1a4f 100644 --- a/card/guozhan.js +++ b/card/guozhan.js @@ -137,7 +137,16 @@ game.import('card',function(lib,game,ui,get,ai,_status){ } }, ai:{ - order:3, + wuxie:function(target,card,player,viewer){ + if(get.mode()=='guozhan'){ + if(!_status._aozhan){ + if(!player.isMajor()){ + if(!viewer.isMajor()) return 0; + } + } + } + }, + order:4, value:9, useful:6, tag:{ @@ -194,6 +203,15 @@ game.import('card',function(lib,game,ui,get,ai,_status){ } }, ai:{ + wuxie:function(target,card,player,viewer){ + if(get.mode()=='guozhan'){ + if(!_status._aozhan){ + if(!player.isMajor()){ + if(!viewer.isMajor()) return 0; + } + } + } + }, order:6, value:9, useful:6, @@ -299,7 +317,7 @@ game.import('card',function(lib,game,ui,get,ai,_status){ if(player.hasSkill('gzzongyu')) return 9; if(game.hasPlayer(function(current){ return current.hasSkill('gzzongyu')&&get.attitude(player,current)<=0; - })) return 1; + })) return 1; return 7.2; }, basic:{ @@ -604,9 +622,6 @@ game.import('card',function(lib,game,ui,get,ai,_status){ order:7.5, value:4, useful:2, - wuxie:function(){ - return 0; - }, result:{ target:function(player,target){ if(get.mode()=='versus'){ @@ -678,7 +693,7 @@ game.import('card',function(lib,game,ui,get,ai,_status){ list.push('摸'+(num-i)+'回'+i); } target.chooseControl(list).set('prompt','请分配自己的摸牌数和回复量').ai=function(){ - return Math.min(_status.event.player.getDamagedHp(),list.length)-1; + return 0; }; } } @@ -697,7 +712,16 @@ game.import('card',function(lib,game,ui,get,ai,_status){ } }, ai:{ - order:3, + wuxie:function(target,card,player,viewer){ + if(get.mode()=='guozhan'){ + if(!_status._aozhan){ + if(!player.isMajor()){ + if(!viewer.isMajor()) return 0; + } + } + } + }, + order:6, value:4, useful:2, result:{ @@ -777,7 +801,7 @@ game.import('card',function(lib,game,ui,get,ai,_status){ target.draw(); }, destroy:function(card,targetPosition,player,event){ - if(event.name!='lose'||event.name!='cardsDiscard'||targetPosition!='discardPile') return false; + if((event.name!='lose'&&event.name!='cardsDiscard')||targetPosition!='discardPile') return false; var evt=event.getParent().relatedEvent; if(evt&&evt.name=='useCard') return false; return true; @@ -821,7 +845,16 @@ game.import('card',function(lib,game,ui,get,ai,_status){ target.addTempSkill('diaohulishan'); }, ai:{ - order:10, + order:function(item, player){ + if(!player) player=get.player(); + if(player.hasCard(function(card){ + return ['gz_haolingtianxia','gz_guguoanbang','gz_kefuzhongyuan','wuzhong','yuanjiao','lianjunshengyan','lulitongxin','yiyi'].includes(get.name(card)); + },'hs')) return 3.5; + if(player.hasCard(function(card){ + return get.name(card)=='taoyuan'; + },'hs')) return get.order({name:'taoyuan'},player)-1; + return 9.5; + }, value:4, useful:[2,1], wuxie:function(){ @@ -947,6 +980,15 @@ game.import('card',function(lib,game,ui,get,ai,_status){ player.draw(3); }, ai:{ + wuxie:function(target,card,player,viewer){ + if(get.mode()=='guozhan'){ + if(!_status._aozhan){ + if(!player.isMajor()){ + if(!viewer.isMajor()) return 0; + } + } + } + }, basic:{ useful:4, value:8, diff --git a/card/standard.js b/card/standard.js index 07a473079..7369fa8fe 100644 --- a/card/standard.js +++ b/card/standard.js @@ -155,7 +155,7 @@ game.import('card',function(lib,game,ui,get,ai,_status){ next.set('useShan',(()=>{ if(target.hasSkillTag('noShan',null,event)) return false; if(target.hasSkillTag('useShan',null,event)) return true; - if(event.baseDamage+event.extraDamage<=0 || get.attitude(target,player._trueMe||player)>0) return false; + if(event.baseDamage+event.extraDamage<=0 || target.isLinked()&&game.hasNature(event.card)&&get.attitude(target,player._trueMe||player)>0) return false; if(event.shanRequired>1&&target.mayHaveShan(target,'use',null,'count')=target.hp+ ((player.hasSkillTag('jueqing',false,target)||target.hasSkill('gangzhi'))?target.hujia:0)) return true; @@ -1145,6 +1145,15 @@ game.import('card',function(lib,game,ui,get,ai,_status){ target.draw(2); }, ai:{ + wuxie:function(target,card,player,viewer){ + if(get.mode()=='guozhan'){ + if(!_status._aozhan){ + if(!player.isMajor()){ + if(!viewer.isMajor()) return 0; + } + } + } + }, basic:{ order:7.2, useful:4.5, @@ -1262,33 +1271,39 @@ game.import('card',function(lib,game,ui,get,ai,_status){ value:5.5 }, result:{ - target:-1.5, - player:function(player,target,card){ - if(player.hasSkillTag('directHit_ai',true,{ - target:target, - card:card, - },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','sha'); - if(hs1.length>hs2.length+1){ + player(player, target, card) { + if (player.hasSkillTag('directHit_ai', true, { + target: target, + card: card + }, true)) return 0; + if (get.damageEffect(target, player, target) >= 0) return 0; + let pd = get.damageEffect(player, target, player), att = get.attitude(player, target); + if (att > 0 && get.damageEffect(target, player, player) > pd) return 0; + let ts = target.mayHaveSha(player, 'respond', null, 'count'), ps = player.mayHaveSha(player, 'respond', null, 'count'); + if (ts < 1 && ts << 3 < Math.pow(player.hp, 2)) return 0; + if (att > 0) { + if (ts < 1) return 0; 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; + if (ts - ps + Math.exp(0.8 - player.hp) < 1) return -ts; + if (pd >= 0) return pd / get.attitude(player, player); + return -2 - ts; + }, + target(player, target, card) { + if (player.hasSkillTag('directHit_ai', true, { + target: target, + card: card + }, true)) return -2; + let td = get.damageEffect(target, player, target); + if (td >= 0) return td / get.attitude(target, target); + let pd = get.damageEffect(player, target, player), att = get.attitude(player, target); + if (att > 0 && get.damageEffect(target, player, player) > pd) return -2; + let ts = target.mayHaveSha(player, 'respond', null, 'count'), ps = player.mayHaveSha(player, 'respond', null, 'count'); + if (ts < 1) return -1.5; + if (att > 0) return -2; + if (ts - ps < 1) return -2 - ts; + if (pd >= 0) return -1; + return -ts; } }, tag:{ diff --git a/character/clan.js b/character/clan.js index 0890a31a8..f330b635b 100644 --- a/character/clan.js +++ b/character/clan.js @@ -100,9 +100,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var key=`${suit}+${get.type2(trigger.card)}`; if(key in storage){ if(!player.hasSkill('qice')){ - player.addTempSkill('qice','roundStart'); + player.addTempSkills('qice','roundStart'); player.popup('奇策'); - game.log(player,'获得了技能','#g【奇策】'); + // game.log(player,'获得了技能','#g【奇策】'); } event.goto(2); } @@ -487,8 +487,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var player=_status.event.player; var num=_status.event.num; var num2=player.getDamagedHp(); - if(num>num2) return 7-get.value(card); - if(num==num2) return lib.skill.zhiheng.check(card); + if(num=(2+num-num2)) return lib.skill.zhiheng.check(card); return 0; }).set('num',num).logSkill='clanxieshu'; 'step 1' diff --git a/character/collab.js b/character/collab.js index 0d5ed1258..daca94166 100644 --- a/character/collab.js +++ b/character/collab.js @@ -101,10 +101,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, filter(event,player){ var filter=event.filterCard; - if(filter({name:'sha',nature:'fire'},player,event)&&player.countCards('hes',{suit:'diamond'})) return true; - if(filter({name:'shan'},player,event)&&player.countCards('hes',{suit:'club'})) return true; - if(filter({name:'tao'},player,event)&&player.countCards('hes',{suit:'heart'})) return true; - if(filter({name:'wuxie'},player,event)&&player.countCards('hes',{suit:'spade'})) return true; + if(filter(get.autoViewAs({name:'sha',nature:'fire'},'unsure'),player,event)&&player.countCards('hes',{suit:'diamond'})) return true; + if(filter(get.autoViewAs({name:'shan'},'unsure'),player,event)&&player.countCards('hes',{suit:'club'})) return true; + if(filter(get.autoViewAs({name:'tao'},'unsure'),player,event)&&player.countCards('hes',{suit:'heart'})) return true; + if(filter(get.autoViewAs({name:'wuxie'},'unsure'),player,event)&&player.countCards('hes',{suit:'spade'})) return true; return false; }, usable:20, @@ -603,7 +603,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ ]); 'step 1' var skill=result.control; - player.addTempSkill(skill,'dcbianzhuangAfter'); + player.addTempSkills(skill,'dcbianzhuangAfter'); for(var i in lib.skill.dcbianzhuang.characterMap){ if(lib.skill.dcbianzhuang.characterMap[i]==skill){ player.flashAvatar('dcbianzhuang',i); diff --git a/character/ddd.js b/character/ddd.js index 1149e4d8d..b437eb13f 100644 --- a/character/ddd.js +++ b/character/ddd.js @@ -2031,7 +2031,13 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(trigger.targets&&trigger.targets.length){ let result=yield player.chooseControl(['额外结算','摸一张牌']).set('prompt','实荐:请选择一项').set('prompt2',`令${get.translation(trigger.card)}额外结算一次,或摸一张牌`).set('ai',()=>{ return get.event('choice'); - }).set('choice',['basic','trick'].includes(get.type(trigger.card))&&trigger.targets.map(i=>get.effect(i,trigger.card,target,player)).reduce((p,c)=>p+c,0)>=5?0:1); + }).set('choice',function(){ + if(trigger.card.name==='tiesuo'||!['basic','trick'].includes(get.type(trigger.card))) return 1; + if(trigger.targets.reduce((p,c)=>{ + return p+get.effect(c,trigger.card,target,_status.event.player); + },0)>=get.effect(player,{name:'draw'},player,_status.event.player)) return 0; + return 1; + }()); if(result.index==0){ trigger.getParent().effectCount++; game.log(player,'令',trigger.card,'额外结算一次'); @@ -2385,8 +2391,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ else wuxie=true; } } - if(shan&&event.filterCard({name:'shan'},player,event)) return true; - if(wuxie&&event.filterCard({name:'wuxie'},player,event)) return true; + if(shan&&event.filterCard(get.autoViewAs({name:'shan'},'unsure'),player,event)) return true; + if(wuxie&&event.filterCard(get.autoViewAs({name:'wuxie'},'unsure'),player,event)) return true; return false; }, hiddenCard (player,name){ @@ -2486,7 +2492,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(result.bool){ var target=trigger.player,cards=result.cards; player.logSkill('dddqiahua',target); - target.addTempSkill('dddxunxun'); + target.addTempSkills('dddxunxun'); player.addShownCards(cards,'visible_dddxianglang'); game.log(player,'选择了',cards,'作为“明”'); player.showCards(cards,get.translation(player)+'对'+get.translation(target)+'发动了【恰化】'); @@ -4815,17 +4821,17 @@ game.import('character',function(lib,game,ui,get,ai,_status){ cardEnabled(card,player){ if(!player.storage['dddlianer_ceiling']) return; var num=get.number(card); - if(typeof num!='number'||player.storage['dddlianer_ceiling']<=num) return false; + if(num!='unsure'&&(typeof num!='number'||player.storage['dddlianer_ceiling']<=num)) return false; }, cardRespondable(card,player){ if(!player.storage['dddlianer_ceiling']) return; var num=get.number(card); - if(typeof num!='number'||player.storage['dddlianer_ceiling']<=num) return false; + if(num!='unsure'&&(typeof num!='number'||player.storage['dddlianer_ceiling']<=num)) return false; }, cardSavable(card,player){ if(!player.storage['dddlianer_ceiling']) return; var num=get.number(card); - if(typeof num!='number'||player.storage['dddlianer_ceiling']<=num) return false; + if(num!='unsure'&&(typeof num!='number'||player.storage['dddlianer_ceiling']<=num)) return false; }, } } @@ -5459,7 +5465,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ ddd_luoxian:'罗宪', dddshilie:'示烈', visible_dddshilie:'明', - dddshilie_info:'每回合限一次。当你需要使用一张【杀】或【闪】时,你可以明置任意点数之和不小于X的手牌,视为你使用之。若本次明置的牌点数等于X,你摸等同于本次明置的牌数的牌(X为你于当前回合角色的体力值之和)。', + dddshilie_info:'每回合限一次。当你需要使用一张【杀】或【闪】时,你可以明置任意点数之和不小于X的手牌,视为你使用之。若本次明置的牌点数等于X,你摸等同于本次明置的牌数的牌(X为你与当前回合角色的体力值之和)。', ddd_lie:'李娥', dddyeshen:'冶身', dddyeshen_info:'一名角色的结束阶段,你可以亮出牌堆底三张牌,令其将其中一张黑色牌当做最大目标数为牌名字数的【铁索连环】使用或重铸,其余牌置于牌堆顶,然后此技能亮出牌数-1;若减至零张或其中没有黑色牌,你复原此技能并对自己造成1点火焰伤害。', diff --git a/character/diy.js b/character/diy.js index 158f89fa1..9c060b60e 100755 --- a/character/diy.js +++ b/character/diy.js @@ -192,6 +192,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ junk_duanwei:['male','qun',4,['junklangmie']], junk_xuyou:["male","qun",3,["nzry_chenglve","junkshicai","nzry_cunmu"]], junk_zhangjiao:['male','shen',3,['yizhao','junksijun','tianjie'],['qun','die_audio:shen_zhangjiao']], + junk_guanyu:['male','shu',4,['olsbfumeng','olsbguidao']], }, characterFilter:{ key_jojiro(mode){ @@ -226,7 +227,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ diy_default:["diy_yuji","diy_caiwenji","diy_lukang","diy_zhenji","old_majun"], diy_noname:['noname'], diy_key:["key_lucia","key_kyousuke","key_yuri","key_haruko","key_umi","key_rei","key_komari","key_yukine","key_yusa","key_misa","key_masato","key_iwasawa","key_kengo","key_yoshino","key_yui","key_tsumugi","key_saya","key_harukakanata","key_inari","key_shiina","key_sunohara","key_rin","key_sasami","key_akane","key_doruji","key_yuiko","key_riki","key_hisako","key_hinata","key_noda","key_tomoya","key_nagisa","key_ayato","key_ao","key_yuzuru","sp_key_kanade","key_mio","key_midori","key_kyoko","key_shizuru","key_shiorimiyuki","key_miki","key_shiori","key_kaori","sp_key_yuri","key_akiko","key_abyusa","key_godan","key_yuu","key_ryoichi","key_kotori","key_jojiro","key_shiroha","key_shizuku","key_hiroto","key_sakuya","key_youta","key_rumi","key_chihaya","key_yukito","key_asara","key_kotomi","key_mia","key_kano","db_key_liyingxia","key_erika","key_satomi","key_iriya","key_fuuko"], - diy_trashbin:['junk_zhangjiao','old_jiakui','ol_guohuai','junk_zhangrang','old_bulianshi','junk_sunquan','ol_maliang','junk_liubei','junk_huangyueying','junk_lidian','junk_duanwei','junk_xuyou'], + diy_trashbin:['junk_guanyu','junk_zhangjiao','old_jiakui','ol_guohuai','junk_zhangrang','old_bulianshi','junk_sunquan','ol_maliang','junk_liubei','junk_huangyueying','junk_lidian','junk_duanwei','junk_xuyou'], }, }, characterIntro:{ @@ -1908,6 +1909,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(!Array.isArray(list)||typeof num!='number'||list.length<=num) return false; var card=get.copy(list[num]); delete card.isCard; + card=get.autoViewAs(card,'unsure'); if(event.filterCard(card,player,event)) return true; return false; }, @@ -2265,10 +2267,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ for(var i of lib.inpile){ var type=lib.skill.nsxingyun.getSixiang(i); if(!type||list.includes(type)) continue; - if(event.filterCard({name:i},player,event)) return true; + if(event.filterCard(get.autoViewAs({name:i},'unsure'),player,event)) return true; if(i=='sha'){ for(var j of lib.inpile_nature){ - if(event.filterCard({name:i,nature:j},player,event)) return true; + if(event.filterCard(get.autoViewAs({name:i,nature:j},'unsure'),player,event)) return true; } } } @@ -5869,7 +5871,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ filter(event,player){ var list=['wei','shu','wu','qun','key','jin']; for(var i in list){ - if(player.hasMark('kotori_yumo_'+list[i])) return true; + if(player.hasMark('kotori_yumo_'+list[i])) return true; } return false; }, @@ -5878,7 +5880,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var list=['wei','shu','wu','qun','key','jin']; var list2=[]; for(var i of list){ - if(player.hasMark('kotori_yumo_'+i)) list2.push('kotori_skill_'+i); + if(player.hasMark('kotori_yumo_'+i)) list2.push('kotori_skill_'+i); } list2.push('cancel2'); player.chooseControl(list2).set('prompt','###是否发动【驭魔】?###弃置对应的标记并获得下列技能中的一个,或点取消,不获得技能').set('choice',function(){ @@ -6089,7 +6091,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var list=['wei','shu','wu','qun','key','jin']; var list2=[]; for(var i of list){ - if(player.hasMark('kotori_yumo_'+i)&&!player.getStorage('kotori_huazhan2').includes('kotori_yumo_'+i)) list2.push('kotori_yumo_'+i); + if(player.hasMark('kotori_yumo_'+i)&&!player.getStorage('kotori_huazhan2').includes('kotori_yumo_'+i)) list2.push('kotori_yumo_'+i); } list2.push('cancel2'); return list2; @@ -6099,7 +6101,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var list=['wei','shu','wu','qun','key','jin']; var list2=[]; for(var i of list){ - if(player.hasMark('kotori_yumo_'+i)&&!player.getStorage('kotori_huazhan2').includes('kotori_yumo_'+i)) list2.push('kotori_yumo_'+i); + if(player.hasMark('kotori_yumo_'+i)&&!player.getStorage('kotori_huazhan2').includes('kotori_yumo_'+i)) list2.push('kotori_yumo_'+i); } if(list2.includes('kotori_yumo_wei')) return 'kotori_yumo_wei'; if(list2.includes('kotori_yumo_wu')) return 'kotori_yumo_wu'; @@ -8201,15 +8203,17 @@ game.import('character',function(lib,game,ui,get,ai,_status){ locked:false, mod:{ targetInRange(card,player){ - var list=player.getExpansions('ao_diegui'); - for(var i=0;i0; }, }, - group:['inari_baiwei_shan','inari_baiwei_draw'], - }, - inari_baiwei_shan:{ - prompt:'将一张♦牌当做闪使用或打出', - enable:['chooseToRespond','chooseToUse'], - viewAs:{name:'shan'}, - selectCard:1, - filterCard:{suit:'diamond'}, - popname:true, - check(card){ - return 1/Math.max(0.1,get.value(card)); - }, - position:'hse', - ai:{ - order:10, - result:{player:1}, - respondShan:true, - skillTagFilter(player){ - return player.countCards('hse',{suit:'diamond'})>0; - }, - }, + group:['inari_baiwei_draw'], }, inari_baiwei_draw:{ trigger:{player:['useCardAfter','respondAfter']}, @@ -14610,7 +14594,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(event.current.needsToDiscard()){ att=1; } - player.chooseControlList(['令'+name+'摸一张牌展示','令'+name+'手牌上永久+1','弃置一张牌并令'+name+'获得一张本回进入弃牌堆的牌'],function(){ + player.chooseControlList(['令'+name+'摸一张牌展示','令'+name+'手牌上永久+1','弃置一张牌并令'+name+'获得一张本回合进入弃牌堆的牌'],function(){ return _status.event.att; }).set('att',att); } @@ -17701,8 +17685,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, async content(event,trigger,player){ const skills = player.additionalSkills.junkyuheng; - await player.draw(skills.length); await player.removeAdditionalSkills('junkyuheng'); + await player.draw(skills.length); }, }, }, @@ -19046,6 +19030,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ junk_zhangjiao_prefix:'OL神', junksijun:'肆军', junksijun_info:'准备阶段,若“黄”数大于牌堆的牌数,你可以移去所有“黄”,然后从牌堆中随机获得任意张点数之和为36的牌(若牌堆没有点数和为36的组合则获得牌堆顶点数和刚好超过36的牌组)。', + junk_guanyu:'旧谋关羽', + junk_guanyu_prefix:'旧谋', diy_tieba:'吧友设计', diy_xushi:'玩点论杀·虚实篇', diff --git a/character/extra.js b/character/extra.js index 72a6a1a58..0e38c614e 100755 --- a/character/extra.js +++ b/character/extra.js @@ -1875,7 +1875,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ twgongxin2:{ mod:{ cardEnabled2(card,player){ - if(player.getStorage('twgongxin2').includes(get.color(card))) return false; + const color = get.color(card); + if(color!='unsure' && player.getStorage('twgongxin2').includes(color)) return false; }, }, charlotte:true, @@ -2266,10 +2267,12 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(lib.skill.xunshi.isXunshi(card)) return 'none'; }, targetInRange(card){ - if(get.color(card)=='none') return true; + const suit = get.color(card); + if (suit=='none' || suit=='unsure') return true; }, cardUsable(card){ - if(get.color(card)=='none') return Infinity; + const suit = get.color(card); + if (suit=='none' || suit=='unsure') return Infinity; }, }, isXunshi(card){ @@ -2343,10 +2346,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(get.suit(card)=='heart') return false; }, targetInRange(card){ - if(get.suit(card)=='heart') return true; + if(card.name === 'sha'){ + const suit = get.suit(card); + if (suit === 'heart' || suit === 'unsure') return true; + } }, cardUsable(card){ - if(card.name=='sha'&&get.suit(card)=='heart') return Infinity; + if(card.name === 'sha'){ + const suit = get.suit(card); + if (suit === 'heart' || suit === 'unsure') return Infinity; + } } }, audio:'wushen', @@ -2511,16 +2520,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(event.responded||event.shouli||event.type=='wuxie') return false; if(game.hasPlayer(function(current){ return current.getCards('e',card=>get.is.attackingMount(card)).length>0; - })&&event.filterCard({ + })&&event.filterCard(get.autoViewAs({ name:'sha', storage:{shouli:true}, - },player,event)) return true; + },'unsure'),player,event)) return true; if(game.hasPlayer(function(current){ return current.getCards('e',card=>get.is.defendingMount(card)).length>0; - })&&event.filterCard({ + })&&event.filterCard(get.autoViewAs({ name:'shan', storage:{shouli:true}, - },player,event)) return true; + },'unsure'),player,event)) return true; return false; }, delay:false, @@ -5548,7 +5557,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ player.removeMark('baonu',2); player.addTempSkills('wushuang'); player.popup('无双'); - game.log(player,'获得了技能','#g【无双】'); + // game.log(player,'获得了技能','#g【无双】'); target.addTempSkill('ol_wuqian_targeted'); }, ai:{ @@ -6164,10 +6173,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(get.suit(card)=='heart') return false; }, targetInRange(card){ - if(get.suit(card)=='heart') return true; + if(card.name === 'sha'){ + const suit = get.suit(card); + if (suit === 'heart' || suit === 'unsure') return true; + } }, cardUsable(card){ - if(card.name=='sha'&&get.suit(card)=='heart') return Infinity; + if(card.name === 'sha'){ + const suit = get.suit(card); + if (suit === 'heart' || suit === 'unsure') return Infinity; + } } }, audio:2, @@ -6875,13 +6890,13 @@ game.import('character',function(lib,game,ui,get,ai,_status){ //获取卡牌花色 var name=get.suit(card,player); //如果这张牌是梅花并且当前时机能够使用/打出闪 那么这张牌可以选择 - if(name=='club'&&filter({name:'shan',cards:[card]},player,event)) return true; + if(name=='club'&&filter(get.autoViewAs({name:'shan'},'unsure'),player,event)) return true; //如果这张牌是方片并且当前时机能够使用/打出火杀 那么这张牌可以选择 - if(name=='diamond'&&filter({name:'sha',cards:[card],nature:'fire'},player,event)) return true; + if(name=='diamond'&&filter(get.autoViewAs({name:'sha',nature:'fire'},'unsure'),player,event)) return true; //如果这张牌是黑桃并且当前时机能够使用/打出无懈 那么这张牌可以选择 - if(name=='spade'&&filter({name:'wuxie',cards:[card]},player,event)) return true; + if(name=='spade'&&filter(get.autoViewAs({name:'wuxie'},'unsure'),player,event)) return true; //如果这张牌是红桃并且当前时机能够使用/打出桃 那么这张牌可以选择 - if(name=='heart'&&filter({name:'tao',cards:[card]},player,event)) return true; + if(name=='heart'&&filter(get.autoViewAs({name:'tao'},'unsure'),player,event)) return true; //上述条件都不满足 那么就不能选择这张牌 return false; }, @@ -6890,13 +6905,13 @@ game.import('character',function(lib,game,ui,get,ai,_status){ //获取当前时机的卡牌选择限制 var filter=event.filterCard; //如果当前时机能够使用/打出火杀并且角色有方片 那么可以发动技能 - if(filter({name:'sha',nature:'fire'},player,event)&&player.countCards('hes',{suit:'diamond'})) return true; + if(filter(get.autoViewAs({name:'sha',nature:'fire'},'unsure'),player,event)&&player.countCards('hes',{suit:'diamond'})) return true; //如果当前时机能够使用/打出闪并且角色有梅花 那么可以发动技能 - if(filter({name:'shan'},player,event)&&player.countCards('hes',{suit:'club'})) return true; + if(filter(get.autoViewAs({name:'shan'},'unsure'),player,event)&&player.countCards('hes',{suit:'club'})) return true; //如果当前时机能够使用/打出桃并且角色有红桃 那么可以发动技能 - if(filter({name:'tao'},player,event)&&player.countCards('hes',{suit:'heart'})) return true; + if(filter(get.autoViewAs({name:'tao'},'unsure'),player,event)&&player.countCards('hes',{suit:'heart'})) return true; //如果当前时机能够使用/打出无懈可击并且角色有黑桃 那么可以发动技能 - if(filter({name:'wuxie'},player,event)&&player.countCards('hes',{suit:'spade'})) return true; + if(filter(get.autoViewAs({name:'wuxie'},'unsure'),player,event)&&player.countCards('hes',{suit:'spade'})) return true; return false; }, ai:{ @@ -7029,10 +7044,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, filter(event,player){ var filter=event.filterCard; - if(filter({name:'sha',nature:'fire'},player,event)&&player.countCards('hs',{suit:'diamond'})) return true; - if(filter({name:'shan'},player,event)&&player.countCards('hs',{suit:'club'})) return true; - if(filter({name:'tao'},player,event)&&player.countCards('hs',{suit:'heart'})) return true; - if(filter({name:'wuxie'},player,event)&&player.countCards('hs',{suit:'spade'})) return true; + if(filter(get.autoViewAs({name:'sha',nature:'fire'},'unsure'),player,event)&&player.countCards('hs',{suit:'diamond'})) return true; + if(filter(get.autoViewAs({name:'shan'},'unsure'),player,event)&&player.countCards('hs',{suit:'club'})) return true; + if(filter(get.autoViewAs({name:'tao'},'unsure'),player,event)&&player.countCards('hs',{suit:'heart'})) return true; + if(filter(get.autoViewAs({name:'wuxie'},'unsure'),player,event)&&player.countCards('hs',{suit:'spade'})) return true; return false; }, precontent(){ @@ -7516,13 +7531,13 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } else event.finish(); 'step 2' - player.addTempSkill(result.control,{player:'dieAfter'}); - player.popup(result.control,'thunder'); + player.addTempSkills(result.control,{player:'dieAfter'}); + // player.popup(result.control,'thunder'); player.storage.drlt_duorui=[result.control]; player.storage.drlt_duorui_player=trigger.player; trigger.player.storage.drlt_duorui=[result.control]; trigger.player.addTempSkill('drlt_duorui1',{player:'phaseAfter'}); - game.log(player,'获得了技能','#g【'+get.translation(result.control)+'】') + // game.log(player,'获得了技能','#g【'+get.translation(result.control)+'】') }, group:['duorui_clear'], }, diff --git a/character/gwent.js b/character/gwent.js index 48530c477..3dc3c055e 100644 --- a/character/gwent.js +++ b/character/gwent.js @@ -803,7 +803,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ player.storage.gwjingtian--; player.updateMark('gwjingtian',true); player.logSkill('gwjingtian'); - if(_status.imchoosing){ + if (_status.imchoosing) { + delete _status.event._buttonChoice; delete _status.event._cardChoice; delete _status.event._targetChoice; game.check(); diff --git a/character/huicui.js b/character/huicui.js index b51764139..783493b81 100644 --- a/character/huicui.js +++ b/character/huicui.js @@ -4,6 +4,12 @@ game.import('character',function(lib,game,ui,get,ai,_status){ name:'huicui', connect:true, character:{ + dc_caoshuang:['male','wei',4,['dcjianzhuan','dcfanshi']], + zangba:['male','wei',4,['rehengjiang']], + dc_simashi:['male','wei',3,['dcsanshi','dczhenrao','dcchenlve']], + dc_wangling:['male','wei',4,['dcjichou','dcmouli'],['clan:太原王氏']], + dc_jiangji:['male','wei',3,['dcshiju','dcyingshi']], + gongsunxiu:['male','qun',4,['dcgangu','dckuizhen']], dc_liuli:['male','shu',3,['dcfuli','dcdehua']], yue_daqiao:['female','wu',3,['dcqiqin','dczixi']], dc_kongrong:['male','qun',3,['dckrmingshi','lirang']], @@ -104,7 +110,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 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_guixin:['re_kanze','re_chendeng','caimaozhangyun','dc_lvkuanglvxiang','dc_gaolan','yinfuren','chengui','chenjiao','dc_sp_jiaxu','qinlang','dc_dongzhao'], + 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','wanglie','leibo','qiaorui','dongwan','yuanyin'], sp_jianghu:['guanning','huzhao','dc_huangchengyan','mengjie'], sp_zongheng:['huaxin','luyusheng','re_xunchen','re_miheng','fengxi','re_dengzhi','dc_yanghu','zongyu'], @@ -112,12 +118,845 @@ game.import('character',function(lib,game,ui,get,ai,_status){ sp_yanhan:['dc_liuba','dc_huangquan','furongfuqian','xianglang','dc_huojun','gaoxiang','dc_wuban','jiangfei'], sp_jishi:['dc_jiben','zhenghun','dc_sunhanhua','liuchongluojun'], sp_raoting:['dc_huanghao','dc_sunziliufang','dc_sunchen','dc_jiachong'], - sp_yijun:['gongsundu','mengyou','dc_sp_menghuo'], + sp_yijun:['gongsundu','mengyou','dc_sp_menghuo','gongsunxiu'], sp_zhengyin:['yue_caiwenji','yue_zhoufei','yue_caiyong','yue_xiaoqiao','yue_daqiao'], + sp_zhonghu:['dc_jiangji','dc_wangling','dc_simashi','dc_caoshuang'], } }, /** @type { importCharacterConfig['skill'] } */ skill:{ + //新杀曹爽 + dcjianzhuan:{ + audio:2, + trigger:{player:'useCard'}, + filter(event,player){ + const evtx=event.getParent('phaseUse'); + return player.isPhaseUsing()&&player.getHistory('useSkill',evt=>{ + return evt.skill=='dcjianzhuan'&&evt.event.getParent('phaseUse')==evtx; + }).length<4-player.getStorage('dcjianzhuan').length; + }, + forced:true, + async content(event,trigger,player){ + const evtx=event.getParent('phaseUse'),num=player.getHistory('useSkill',evt=>{ + return evt.skill=='dcjianzhuan'&&evt.event.getParent('phaseUse')==evtx; + }).length,info=get.info('dcjianzhuan').choices; + let choices=[],choiceList=[],map={}; + for(const i in info){ + map[info[i].intro]=i; + if(player.getStorage('dcjianzhuan').includes(i)||player.getStorage('dcjianzhuan_used').includes(i)) continue; + choices.push(info[i].intro);choiceList.push(info[i].introx(num)); + } + const {result:{control}}=await player.chooseControl(choices).set('choiceList',choiceList).set('ai',()=>{ + const player=get.event('player'),num=get.event('num'),info=get.info('dcjianzhuan').choices; + let choices=get.event('controls').slice(),map=get.event('map') + return choices.sort((a,b)=>info[map[b]].ai_effect(player,num)-info[map[a]].ai_effect(player,num))[0]; + }).set('num',num).set('map',map).set('prompt','渐专:请选择一项执行'); + if(control){ + if(!player.storage.dcjianzhuan_used){ + player.when('phaseUseAfter').then(()=>delete player.storage.dcjianzhuan_used); + } + player.markAuto('dcjianzhuan_used',[map[control]]); + await info[map[control]].content(player,num); + } + }, + choices:{ + discard_target:{ + intro:'拆牌', + introx:(num)=>'令一名角色弃置'+num+'张牌', + ai_effect(player,num){ + return game.hasPlayer(target=>{ + return get.effect(target,{name:'guohe_copy2'},player,player)>0; + })?(2+num):0; + }, + async content(player,num=1){ + const {result:{bool,targets}}=await player.chooseTarget('令一名角色弃置'+num+'张牌',true).set('ai',target=>{ + return get.effect(target,{name:'guohe_copy2'},get.event('player'),get.event('player'))*Math.sqrt(Math.min(get.event('num'),target.countDiscardableCards(target,'he'))); + }).set('num',num); + if(bool){ + const target=targets[0]; + player.line(target); + await target.chooseToDiscard(num,'he',true); + } + }, + }, + draw_self:{ + intro:'摸牌', + introx:(num)=>'摸'+num+'张牌', + ai_effect(player,num){ + return 3; + }, + async content(player,num=1){ + await player.draw(num); + }, + }, + recast_self:{ + intro:'重铸', + introx:(num)=>'重铸'+num+'张牌', + ai_effect(player,num){ + return 1; + }, + async content(player,num=1){ + const {result:{bool,cards}}=await player.chooseCard('重铸'+num+'张牌','he',num,lib.filter.cardRecastable,true).set('ai',lib.skill.zhiheng.check); + if(bool) await player.recast(cards); + }, + }, + discard_self:{ + intro:'弃牌', + introx:(num)=>'弃置'+num+'张牌', + ai_effect(player,num){ + let cards=player.getCards('hs'); + cards.sort((a,b)=>get.value(b)-get.value(a)); + cards=cards.slice(0,-Math.min(num,cards.length)); + return cards.some(card=>player.hasValueTarget(card,true,true))?4:-4; + }, + async content(player,num=1){ + await player.chooseToDiscard(num,'he',true); + }, + }, + }, + group:'dcjianzhuan_remove', + subSkill:{ + remove:{ + audio:'dcjianzhuan', + trigger:{player:'phaseUseEnd'}, + filter(event,player){ + if(player.getStorage('dcjianzhuan').length>=4) return false; + return player.getStorage('dcjianzhuan_used').length>=4-player.getStorage('dcjianzhuan').length; + }, + forced:true, + async content(event,trigger,player){ + const info=get.info('dcjianzhuan').choices; + let choices=[],map={}; + for(const i in info){ + map[info[i].intro]=i; + if(player.getStorage('dcjianzhuan').includes(i)) continue; + choices.push(info[i].intro); + } + const removeChoice=choices.randomGet(); + player.markAuto('dcjianzhuan',[map[removeChoice]]); + player.popup(removeChoice); + game.log(player,'移去了','#g'+removeChoice,'项'); + }, + }, + }, + mark:true, + intro:{ + markcount(storage){ + return 4-(storage||[]).length; + }, + content(storage){ + if(!(storage||[]).length) return '暂未移去任何项'; + const info=get.info('dcjianzhuan').choices; + let str=''; + for(const i of storage){ + str+=info[i].intro; + str+='、'; + } + str=str.slice(0,-1); + return '已移去'+str+'项'; + }, + }, + }, + dcfanshi:{ + unique:true, + audio:2, + trigger:{player:'phaseJieshuBegin'}, + filter(event,player){ + return 4-player.getStorage('dcjianzhuan').length<2; + }, + forced:true, + juexingji:true, + skillAnimation:true, + animationColor:'thunder', + async content(event,trigger,player){ + player.awakenSkill('dcfanshi'); + const info=get.info('dcjianzhuan').choices; + let choices=[]; + for(const i in info){ + if(!player.getStorage('dcjianzhuan').includes(i)) choices.push(i); + } + if(choices.length){ + const choice=choices.randomGet(); + for(let i=1;i<=3;i++){ + await info[choice].content(player,1); + } + } + await player.gainMaxHp(2); + await player.recover(2); + await player.changeSkills(['dcfudou'],['dcjianzhuan']); + }, + derivation:'dcfudou', + }, + dcfudou:{ + audio:2, + trigger:{player:'useCardToPlayered'}, + filter(event,player){ + if(event.targets.length!=1||event.target==player) return false; + const color=get.color(event.card); + if(!['black','red'].includes(color)) return false; + const damage=event.target.getAllHistory('sourceDamage',evt=>evt.player==player).length; + return Math.min(1,damage)==(color=='black'); + }, + check(event,player){ + const color=get.color(event.card); + if(color=='red') return get.attitude(player,event.target)>0; + if(player.getHp()+player.countCards('hs',card=>player.canSaveCard(card,player))<=1) return false; + return get.effect(player,{name:'losehp'},player,player)>=get.effect(event.target,{name:'losehp'},player,player); + }, + prompt2(event,player){ + return '与'+get.translation(event.target)+'各'+(get.color(event.card)=='black'?'失去1点体力':'摸一张牌'); + }, + logTarget:'target', + async content(event,trigger,player){ + const color=get.color(trigger.card),target=trigger.target; + if(color=='red'){ + await player.draw('nodelay'); + await target.draw(); + } + else{ + await player.loseHp(); + await target.loseHp(); + } + }, + }, + //司马师 + dcsanshi:{ + audio:2, + trigger:{global:'roundStart'}, + forced:true, + filter(event,player){ + return game.roundNumber===1; + }, + group:['dcsanshi_gain','dcsanshi_directHit'], + async content(event,trigger,player){ + const recordedNumbers=[]; + let num=get.rand(0,ui.cardPile.childNodes.length-1); + for(let i=0;i=ui.cardPile.childNodes.length) j-=ui.cardPile.childNodes.length; + const card=ui.cardPile.childNodes[j],number=get.number(card,false); + if(!recordedNumbers.includes(number)){ + recordedNumbers.add(number); + card.storage.dcsanshi=true; + num=get.rand(0,ui.cardPile.childNodes.length-1); + } + } + player.addSkill('dcsanshi_mark'); + }, + subSkill:{ + gain:{ + audio:'dcsanshi', + trigger:{global:'phaseEnd'}, + filter(event,player){ + return game.hasGlobalHistory('cardMove',evt=>{ + if(evt.name=='lose'){ + if(evt.position!==ui.discardPile) return false; + } + else if(evt.name!=='cardsDiscard') return false; + if(lib.skill.dcsanshi_gain.notUseOrRespond(evt,player)){ + return evt.cards.some(card=>{ + return card.storage.dcsanshi&&get.position(card)==='d'; + }); + } + return false; + }); + }, + forced:true, + notUseOrRespond(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; + }, + async content(event,trigger,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(lib.skill.dcsanshi_gain.notUseOrRespond(evt,player)){ + cards.addArray(evt.cards.filter(card=>{ + return card.storage.dcsanshi&&get.position(card)==='d'; + })); + } + }); + if(cards.length) player.gain(cards,'gain2'); + } + }, + directHit:{ + audio:'dcsanshi', + trigger:{player:'useCard'}, + forced:true, + filter(event,player){ + return event.cards&&event.cards.some(card=>{ + return card.storage.dcsanshi; + }); + }, + async content(event,trigger,player){ + trigger.directHit.addArray(game.filterPlayer()); + game.log(trigger.card,'不可被响应'); + }, + }, + mark:{ + trigger:{ + player:'gainEnd', + global:'loseAsyncEnd', + }, + forced:true, + popup:false, + silent:true, + lastDo:true, + filter(event,player){ + if(!['dcsanshi','dcchenlve'].every(skill=>player.hasSkill(skill,null,false,false))) return false; + const cards=event.getg(player); + if(!cards.length) return false; + return cards.some(card=>card.storage.dcsanshi); + }, + async content(event,trigger,player){ + var cards=trigger.getg(player); + if(cards.length){ + cards=cards.filter(card=>card.storage.dcsanshi); + player.addGaintag(cards,'dcsanshi_tag'); + } + }, + }, + }, + ai:{ + threaten:3, + }, + }, + dczhenrao:{ + audio:2, + trigger:{global:'useCardToPlayered'}, + filter(event,player){ + if((()=>{ + if(event.player===player){ + if(!event.isFirstTarget) return false; + return event.targets.some(target=>target!==player); + } + return event.target===player; + })()){ + return event.targets.concat(event.player).some(target=>{ + return target.countCards('h')>player.countCards('h')&&!player.getStorage('dczhenrao').includes(target); + }); + } + return false; + }, + direct:true, + async content(event,trigger,player){ + const result=await player.chooseTarget(get.prompt('dczhenrao'),'对一名可选角色造成1点伤害',(card,player,target)=>{ + return get.event('targets').includes(target); + }) + .set('targets',trigger.targets.concat(trigger.player).filter(target=>target.countCards('h')>player.countCards('h'))) + .set('ai',target=>{ + const player=get.player(); + return get.damageEffect(target,player,player); + }) + .forResult(); + 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); + }, + intro:{ + content:'已以此法对$造成过伤害', + onunmark:true, + }, + ai:{ + expose:0.2, + threaten:3, + }, + }, + dcchenlve:{ + audio:2, + enable:'phaseUse', + limited:true, + skillAnimation:true, + animationColor:'thunder', + filterCard:()=>false, + selectCard:[-2,-1], + async content(event,trigger,player){ + player.awakenSkill('dcchenlve'); + const cards=['cardPile','discardPile'].map(pos=>Array.from(ui[pos].childNodes)).flat(); + const sishiList=[]; + const isSishi=card=>card.storage.dcsanshi; + const lose_list=[],players=game.filterPlayer(); + players.forEach(current=>{ + const pos='ej'+(current===player?'h':''); + const sishis=current.getCards(pos,isSishi); + if(sishis.length>0){ + current.$throw(sishis); + lose_list.push([current,sishis]); + sishiList.addArray(sishis); + } + }); + if(lose_list.length){ + await game.loseAsync({lose_list}).setContent('chooseToCompareLose'); + } + sishiList.addArray(cards.filter(isSishi)); + if(lose_list.length) await game.asyncDelayx(); + player.gain(sishiList,'gain2'); + player.when('phaseEnd') + .filter(evt=>evt===event.getParent('phase')) + .vars({ + sishiList + }) + .then(()=>{ + const lose_list=[],players=game.filterPlayer(); + players.forEach(current=>{ + const cards=current.getCards('hej').filter(card=>sishiList.includes(card)); + if(cards.length>0){ + current.$throw(cards); + lose_list.push([current,cards]); + } + }); + if(lose_list.length){ + game.loseAsync({lose_list}).setContent('chooseToCompareLose'); + } + }) + .then(()=>{ + game.cardsGotoSpecial(sishiList); + game.log(sishiList,'被移出了游戏'); + }); + player.when('die') + .vars({ + sishiList + }) + .assign({ + forceDie:true, + }) + .then(()=>{ + game.cardsDiscard(sishiList); + game.log(sishiList,'被置入了弃牌堆'); + }); + }, + ai:{ + order:0.5, + result:{ + player(player){ + if(player.getHp(true)>1&&player.countCards('he')>1) return 0; + if(!player.isDamaged()&&(player.countCards('h')>1||player.countCards('e')>0)) return 0; + return 13; + } + }, + }, + }, + //王凌 + dcjichou:{ + audio:2, + trigger:{player:'phaseUseEnd'}, + filter(event,player){ + const evts=player.getHistory('useCard',evt=>evt.getParent('phaseUse')===event); + const names=evts.map(evt=>evt.card.name).unique(); + return evts.length>0&&evts.length===names.length&&evts.some(evt=>evt.cards.some(card=>get.position(card)==='d')); + }, + async content(event,trigger,player){ + const cards=[]; + player.checkHistory('useCard',evt=>{ + if(evt.getParent('phaseUse')!==trigger) return; + cards.addArray(evt.cards.filterInD('d')); + }); + const num=Math.min(cards.length,game.countPlayer()); + if(_status.connectMode) game.broadcastAll(()=>{_status.noclearcountdown=true}); + const [bool,links]=await player.chooseButton([ + `集筹:将${numget.attitude(player,current)>0), + game.countPlayer(current=>get.attitude(player,current)<0) + ]) + .set('ai',button=>{ + const card=button.link,population=get.event('population'); + if(ui.selected.buttons.length>population[0]+population[1]) return 0; + if(ui.selected.buttons.length>get.event('population')[0]) return 2-get.value(card); + return 2+get.value(card); + }) + .forResult('bool','links'); + if(bool){ + const [bool,targets]=await player.chooseTarget( + `集筹:请选择${get.cnNumber(links.length)}名角色`, + `操作提示:请按照顺序选择要交给牌的目标,令这些角色按顺序获得这些牌:${get.translation(links)}`, + true, + links.length, + ) + .set('values',links.map(i=>get.value(i))) + .set('ai',target=>{ + const att=get.attitude(get.player(),target); + const chosenNum=ui.selected.targets.length,values=get.event('values'); + if(values[chosenNum]>0) return att; + return 0.01-att; + }) + .forResult('bool','targets'); + if(_status.connectMode){game.broadcastAll(()=>{delete _status.noclearcountdown;game.stopCountChoose()})} + if(bool){ + const gain_list=[],givenCards=[]; + targets.forEach((target,i)=>{ + player.line(target,'green'); + gain_list.push([target,links[i]]); + givenCards.push(links[i]); + game.log(player,'将',links[i],'交给了',target); + }); + event.getParent().set('givenCards',givenCards); + await game.loseAsync({ + gain_list, + player:player, + cards:givenCards, + giver:player, + animate:'gain2', + }).setContent('gaincardMultiple'); + const toDraw=player.getAllHistory('useSkill',evt=>{ + const evtx=evt.event; + return evt.skill==='dcjichou'&&evtx.givenCards&&evtx.givenCards.length; + })[0].event.givenCards.length; + await game.asyncDelayx(); + await player.draw(toDraw); + } + } + if(_status.connectMode){game.broadcastAll(()=>{delete _status.noclearcountdown;game.stopCountChoose()})} + }, + }, + dcmouli:{ + audio:2, + trigger:{player:'phaseEnd'}, + filter(event,player){ + const names=[]; + player.checkAllHistory('useSkill',evt=>{ + if(evt.skill!=='dcjichou') return; + const evtx=evt.event; + if(evtx.givenCards) names.addArray(evtx.givenCards.map(card=>get.name(card,false))); + }); + return names.length>=5; + }, + forced:true, + juexingji:true, + skillAnimation:true, + animationColor:'water', + derivation:['dczifu'], + async content(event,trigger,player){ + player.awakenSkill('dcmouli'); + await player.gainMaxHp(); + await player.recover(); + await player.addSkills('dczifu'); + }, + }, + dczifu:{ + audio:2, + trigger:{player:'phaseUseBegin'}, + forced:true, + async content(event,trigger,player){ + const maxLimit=Math.min(5,player.maxHp); + let count=player.countCards('h'); + if(countevt.getParent(2)===event)) return; + count=player.countCards('h'); + const toKeepCount=player.getCards('h').map(card=>get.name(card)).unique(); + if(count>toKeepCount){ + const [bool,cards]=await player.chooseCard('自缚:选择要保留的手牌','选择不同牌名的手牌各一张,然后弃置其余手牌',toKeepCount) + .set('filterCard',card=>{ + if(!ui.selected.cards.length) return true; + const name=get.name(card,player); + if(ui.selected.cards.some(card=>get.name(card,player)===name)) return false; + return true; + }) + .set('complexCard',true) + .set('ai',get.value) + .forResult('bool','cards'); + if(!bool) return; + const toDiscard=player.getCards('h').removeArray(cards); + if(toDiscard.length) player.discard(toDiscard); + } + }, + ai:{ + halfneg:true, + }, + }, + //蒋济 + dcshiju:{ + audio:2, + global:'dcshiju_global', + subSkill:{ + global:{ + audio:'dcshiju', + enable:'phaseUse', + usable:1, + filter(event,player){ + return game.hasPlayer(current=>{ + if(current==player||!current.hasSkill('dcshiju')) return false; + return player.countCards('he'); + }); + }, + filterTarget(card,player,target){ + return target!=player&&target.hasSkill('dcshiju'); + }, + selectTarget(){ + const num=game.countPlayer(current=>{ + return current.hasSkill('dcshiju'); + }); + return num>1?1:-1; + }, + filterCard:true, + position:'he', + check(card){ + const player=get.player(); + if(get.type(card)==='equip'){ + const subtype=get.subtype(card); + let valueFix=0; + if(game.hasPlayer(current=>{ + if(current==player||!current.hasSkill('dcshiju')) return false; + if(current.hasUseTarget(card)&&!player.countEmptySlot(subtype)) return true; + })) valueFix+=5; + if(player.countCards('he',{subtype})>1){ + return valueFix+12-get.equipValue(card); + } + return valueFix+6-get.value(card); + } + return 4-get.value(card); + }, + prompt(){ + const list=game.filterPlayer(current=>{ + return current.hasSkill('dcshiju'); + }); + return `将一张牌交给${get.translation(list)}${list.length>1?'中的一人':''},若此牌为装备牌,其可以使用之,且你本回合的攻击范围+X(X为其装备区的牌数)。若其以此法替换了装备,你与其各摸两张牌。`; + }, + discard:false, + lose:false, + prepare(cards,player,targets){ + 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.getCards('h').includes(card)||get.type(card)!=='equip') return; + const bool=await target.chooseUseTarget(card).forResultBool(); + if(!bool) return; + const count=target.countCards('e'); + if(count>0){ + player.addTempSkill('dcshiju_range'); + player.addMark('dcshiju_range',count,false); + if(target.hasHistory('lose',evt=>{ + return evt.getParent().name==='equip'&&evt.getParent(5)===event&&evt.es&&evt.es.length>0; + })){ + for(const current of [player,target]) await current.draw(2); + } + } + }, + ai:{ + order:10, + result:{ + target(player,target){ + const card=ui.selected.cards[0]; + if(!card) return; + if(target.hasSkillTag('nogain')&&get.type(card)!='equip') return 0; + if(card.name=='du'&&target.hasSkillTag('nodu')) return 0; + if(get.value(card)<0) return -5; + const nh=target.countCards('h'); + return Math.max(1,5-nh); + }, + }, + }, + }, + range:{ + charlotte:true, + onremove:true, + mod:{ + attackRange:function(player,num){ + return num+player.countMark('dcshiju_range'); + }, + }, + intro:{content:'本回合攻击范围+#'}, + }, + }, + }, + dcyingshi:{ + audio:2, + trigger:{player:'useCardToPlayered'}, + filter(event,player){ + if(!event.isFirstTarget) return false; + if(get.type(event.card)!=='trick') return false; + const evt=event.getParent(); + const evts=game.getGlobalHistory('useCard',null,evt).slice().remove(evt); + return event.targets.some(target=>{ + return evts.some(evt=>evt.targets.includes(target)); + }); + }, + direct:true, + async content(event,trigger,player){ + const evt=trigger.getParent(); + const evts=game.getGlobalHistory('useCard',null,evt).slice().remove(evt); + const chooseableTargets=trigger.targets.filter(target=>{ + return evts.some(evt=>evt.targets.includes(target)); + }); + const result=await player.chooseTarget() + .set('prompt',get.prompt('dcyingshi')) + .set('prompt2',`令一名可选角色选择本回合未被选择过的一项:⒈令你于此牌结算结束后视为对其使用一张${get.translation(trigger.card.name)};⒉弃置${get.cnNumber(player.countCards('e'))}张牌,此牌对其无效。`) + .set('filterTarget',(card,player,target)=>{ + return get.event('targets').includes(target); + }) + .set('targets',chooseableTargets) + .set('toFriends',(()=>{ + const isPositive=chooseableTargets.some(current=>{ + return get.effect(current,trigger.card,trigger.player,player)>0; + }),isNegative=chooseableTargets.some(current=>{ + return get.effect(current,trigger.card,trigger.player,player)<-5; + }); + if((player.hasSkill('dcyingshi_choice1')||player.countCards('e')<2)&&isNegative) return true; + if(!player.hasSkill('dcyingshi_choice1')&&(get.tag(trigger.card,'norepeat')&&isNegative||isPositive)) return true; + return false; + })()) + .set('ai',target=>{ + const player=get.player(),count=player.countCards('e'),att=get.attitude(player,target); + if(att>0&&get.event('toFriends')){ + if(target.countCards('he',card=>get.value(card)<5)0){ + const prompt=`###${get.translation(player)}对你发动了【应时】###${forced?'请':'是否'}弃置${get.cnNumber(count)}张牌,令${get.translation(trigger.card)}对你无效${forced?'。':'?或点击“取消”,令其与此牌结算后视为对你使用一张同名牌。'}`; + bool=await target.chooseToDiscard(prompt,count,forced,'he').set('ai',card=>{ + if(get.event('goon')) return 5.5-get.value(card); + return 0; + }).set('goon',!get.tag(trigger.card,'norepeat')&&get.effect(target,trigger.card,trigger.player,target)<-5).forResultBool(); + } + else bool=false; + } + else bool=player.hasSkill('dcyingshi_choice1'); + if(bool){ + trigger.excluded.add(target); + } + else{ + player.when({global:'useCardAfter'}) + .filter(evt=>evt===trigger.getParent()) + .vars({ + targetx:target, + cardx:{ + name:trigger.card.name, + nature:trigger.card.nature, + isCard:true, + storage:{dcyingshi:true}, + }, + }) + .then(()=>{ + const next=player.useCard(get.copy(cardx),targetx,false); + if(trigger.addedTarget) next.addedTarget=trigger.addedTarget; + 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}, + }, + }, + //公孙修 + dcgangu:{ + audio:2, + trigger:{global:'loseHpAfter'}, + filter(event,player){ + return event.player!==player; + }, + usable:1, + forced:true, + async content(event,trigger,player){ + await player.draw(2); + await player.loseHp(); + }, + }, + dckuizhen:{ + audio:2, + enable:'phaseUse', + filter(event,player){ + return game.hasPlayer(current=>{ + return lib.skill.dckuizhen.filterTarget(null,player,current); + }); + }, + filterTarget(card,player,target){ + return target.countCards('h')>player.countCards('h')||target.getHp()>player.getHp(); + }, + usable:1, + forced:true, + async content(event,trigger,player){ + const {target}=event,juedou=new lib.element.VCard({name:'juedou'}); + if(target.canUse(juedou,player,false)){ + await target.useCard(juedou,player,'noai'); + } + if(player.hasHistory('damage',evt=>{ + return evt.getParent(3)===event; + })){ + await player.viewHandcards(target); + const shas=target.getGainableCards(player,'h').filter(card=>get.name(card)==='sha'); + if(shas.length){ + player.addTempSkill('dckuizhen_effect'); + await player.gain(shas,'give',target).gaintag.add('dckuizhen'); + } + } + else{ + await target.loseHp(); + } + }, + ai:{ + result:{ + 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; + }, + } + }, + subSkill:{ + effect:{ + trigger:{player:'useCard1'}, + forced:true, + popup:false, + firstDo:true, + charlotte:true, + filter:function(event,player){ + if(event.addCount===false) return false; + return player.hasHistory('lose',evt=>{ + if(evt.getParent()!=event) return false; + for(const i in evt.gaintag_map){ + if(evt.gaintag_map[i].includes('dckuizhen')) return true; + } + return false; + }); + }, + async content(event,trigger,player){ + trigger.addCount=false; + var stat=player.getStat().card,name=trigger.card.name; + if(typeof stat[name]=='number') stat[name]--; + }, + mod:{ + cardUsable(card){ + if(!card.cards) return; + if(card.cards.some(card=>card.hasGaintag('dckuizhen'))) return Infinity; + }, + }, + } + } + }, //刘理 dcfuli:{ audio:2, @@ -399,14 +1238,14 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(bool){ const name=links.find(i=>typeof i=='string'),card=links.find(j=>j!=name),cardname=map[name]; const {result:{bool,targets}}=await player.chooseTarget('请选择【'+name+'('+get.translation(card)+')】置入的目标',(cardx,player,target)=>{ - return target.canAddJudge(get.autoViewAs({name:'dczixi_'+get.event('name')},[get.event('card')])); + return target.canAddJudge(get.autoViewAs({name:'dczixi_'+get.event('cardname')},[get.event('card')])); },true).set('ai',target=>{ const player=get.event('player'),card=get.event('card'); if(game.hasPlayer(current=>{ - return get.attitude(player,current)<0&¤t.canAddJudge(get.autoViewAs({name:'dczixi_'+get.event('name')},[card])); + return get.attitude(player,current)<0&¤t.canAddJudge(get.autoViewAs({name:'dczixi_'+get.event('cardname')},[card])); })) return -target.countCards('j')-1; return target.countCards('j')+1; - }).set('card',card).set('name',cardname); + }).set('card',card).set('cardname',cardname); if(bool){ const target=targets[0]; player.logSkill('dczixi',target); @@ -991,7 +1830,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ let result; if(_status.connectMode) game.broadcastAll(()=>{_status.noclearcountdown=true}); if(choices.length==1) result={control:choices[0]}; - else result=yield player.chooseControl(choices,'cancel2').set('choiceList',choiceList).set('prompt',get.prompt('dcxunjie')).set('ai',()=>{ + else result=yield player.chooseControl(choices,'cancel2').set('choiceList',choiceList).set('prompt',get.prompt('dcxunjie')).set('ai',()=>{ return get.event('choice'); }).set('choice',(()=>{ const getValue=(index,target)=>{ @@ -1257,9 +2096,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){ for(var target of game.filterPlayer()){ if(user==target) continue; var targetsx=[user,target]; - targetsx.forEach(i=>i.addSkill('dcbeini_fengyin')); + targetsx.forEach(i=>i.addSkill('dcbeini_fengyin2')); var effx=get.effect(target,sha,user,player); - targetsx.forEach(i=>i.removeSkill('dcbeini_fengyin')); + targetsx.forEach(i=>i.removeSkill('dcbeini_fengyin2')); if(user==player) effx+=1; if(get.attitude(player,user)>0) effx-=0.1; if(effx>eff){ @@ -1291,6 +2130,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){ fengyin:{ inherit:'fengyin', }, + fengyin2:{ + inherit:'fengyin', + }, } }, dcshizong:{ @@ -1363,12 +2205,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ return 1/(1.1+Math.max(-1,get.value(card))); }, ai2:function(target){ - const att=get.attitude(get.player(),target); - const value=ui.selected.cards.map(card=>get.value(card)).reduce((p,c)=>{ - return p+c; - },0); - if(value>0||player.getHp()<=1) return att; - return -att; + return get.attitude(get.player(),target); }, precontent:function*(event,map){ var player=map.player,target=event.result.targets[0]; @@ -3034,7 +3871,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, filter:function(event,player){ if(event.dcgue||event.type=='wuxie'||player==_status.currentPhase) return false; - if(!player.countCards('h')||player.hasSkill('dcgue_blocker',null,null,false)) return false; + if(player.hasSkill('dcgue_blocker',null,null,false)) return false; for(var name of ['sha','shan']){ if(event.filterCard({name:name,isCard:true},player,event)) return true; } @@ -3066,7 +3903,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 'step 0' player.logSkill('dcgue'); player.addTempSkill('dcgue_blocker'); - player.showHandcards(); + if(player.countCards('h')) player.showHandcards(); delete event.result.skill; 'step 1' if(player.countCards('h',{name:['sha','shan']})>1){ @@ -3081,7 +3918,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } }, prompt:function(links,player){ - return '展示所有手牌'+(player.countCards('h',{name:['sha','shan']})<=1?',然后视为使用【'+get.translation(links[0][2])+'】':''); + return (player.countCards?'展示所有手牌':'')+(player.countCards('h',{name:['sha','shan']})<=1?',然后视为使用【'+get.translation(links[0][2])+'】':''); } }, subSkill:{blocker:{charlotte:true}}, @@ -4341,7 +5178,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ source:'damageSource', player:'damageEnd', }, - usable:1, + usable:2, logTarget:'source', check:function(event,player){ if(typeof player.storage.dchaochong!='number'||player.storage.dchaochong==0) return true; @@ -5230,16 +6067,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){ dccuijin:{ audio:2, trigger:{global:'useCard'}, - direct:true, filter:function(event,player){ - return event.card.name=='sha'&&(event.player==player||player.inRange(event.player))&&player.countCards('he')>0; + return (event.card.name=='sha'||event.card.name=='juedou')&&(event.player==player||player.inRange(event.player))&&player.countCards('he')>0; }, + direct:true, content:function(){ 'step 0' if(player!=game.me&&!player.isOnline()) game.delayx(); var target=trigger.player; event.target=target; - player.chooseToDiscard('he',get.prompt('dccuijin',target),'弃置一张牌并令'+get.translation(trigger.player)+'使用的【杀】伤害+1,但若其未造成伤害,则你摸一张牌并对其造成1点伤害。').set('ai',function(card){ + player.chooseToDiscard('he',get.prompt('dccuijin',target),'弃置一张牌并令'+get.translation(trigger.player)+'使用的'+get.translation(trigger.card)+'伤害+1,但若其未造成伤害,则你摸两张牌并对其造成1点伤害。').set('ai',function(card){ if(_status.event.goon) return 7-get.value(card); return 0; }).set('goon',lib.skill.cuijin.checkx(trigger,player)).logSkill=['dccuijin',target]; @@ -5297,7 +6134,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ })){ player.logSkill('dccuijin_damage',source); player.storage.dccuijin_map[card.cardid].remove(target); - player.draw(); + player.draw(2); if(source&&source.isIn()){ player.line(trigger.player,'green'); trigger.player.damage(); @@ -7189,6 +8026,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ mark:true, marktext:'阵', intro:{ + markcount:()=>0, content:function(storage,player,skill){ if(storage.length) return '失效技能:'+get.translation(storage); return '无失效技能'; @@ -7300,12 +8138,13 @@ game.import('character',function(lib,game,ui,get,ai,_status){ target.addAdditionalSkills('dczecai_effect','rejizhi'); target.addTempSkill('dczecai_effect','roundStart'); if(target==event.target){ - var evt=trigger._trigger; + var evt=trigger; target.insertPhase(); if(evt.player!=target&&!evt._finished){ evt.finish(); evt._triggered=5; - evt.player.insertPhase(); + var evtx=evt.player.insertPhase(); + delete evtx.skill; } } } @@ -8046,7 +8885,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(!player.hasCard((card)=>(get.type(card)!='basic'),'ehs')) return false; for(var i of list){ var type=get.type2(i,false); - if((type=='basic'||type=='trick')&&event.filterCard({name:i},player,event)) return true; + if((type=='basic'||type=='trick')&&event.filterCard(get.autoViewAs({name:i},'unsure'),player,event)) return true; } return false; }, @@ -8057,7 +8896,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var list2=[]; for(var i of list){ var type=get.type2(i,false); - if((type=='basic'||type=='trick')&&event.filterCard({name:i},player,event)) list2.push([type,'',i]); + if((type=='basic'||type=='trick')&&event.filterCard(get.autoViewAs({name:i},'unsure'),player,event)) list2.push([type,'',i]); } return ui.create.dialog('浮萍',[list2,'vcard']); }, @@ -8073,7 +8912,6 @@ game.import('character',function(lib,game,ui,get,ai,_status){ popname:true, viewAs:{ name:links[0][2], - isCard:true, }, check:function(card){ return 8-get.value(card); @@ -10219,11 +11057,13 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, zhente2:{ mod:{ - cardEnabled:function(card,player){ - if(player.getStorage('zhente2').includes(get.color(card))) return false; + cardEnabled(card, player) { + const color = get.color(card); + if (color != 'unsure' && player.getStorage('zhente2').includes(color)) return false; }, - cardSavable:function(card,player){ - if(player.getStorage('zhente2').includes(get.color(card))) return false; + cardSavable(card,player) { + const color = get.color(card); + if (color != 'unsure' && player.getStorage('zhente2').includes(color)) return false; }, }, charlotte:true, @@ -10548,7 +11388,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ player.line(target,'green'); player.markAuto('remeibu_gain',[get.suit(card,player)]); player.addTempSkill('remeibu_gain'); - target.addTempSkill('rezhixi','phaseUseEnd'); + target.addTempSkills('rezhixi','phaseUseEnd'); } }, ai:{ @@ -11548,6 +12388,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ yuechen:'乐綝(195~257年),字号不详,阳平郡卫国县(今河南省清丰县)人。三国时期曹魏将领,右将军乐进的儿子。果毅坚毅,袭封广昌亭侯,累迁扬州刺史。甘露二年,为叛乱的征东大将军诸葛诞所杀,追赠卫尉。', kuaiqi:'蒯祺(?~219年),南郡中卢人,荆州望族子弟,与荆州牧刘表帐下谋士蒯良、蒯越为同族,东汉末年房陵太守。建安二十四年(219年),汉中王刘备遣宜都太守孟达从秭归北攻房陵,蒯祺于战斗中被孟达所部士兵所杀。清朝任兆麟《心斋十种》中的《襄阳记》辑本引用《万历襄阳府志》“(蒯)钦从祖祺妇,即诸葛孔明之姊也”,称蒯祺娶故兖州泰山郡丞诸葛珪长女,即他是知名政治家、蜀汉丞相诸葛亮的姐夫。但在任兆麟之前的《襄阳记》辑本中,并没有这一条。', pangshanmin:'庞山民,荆州襄阳人,三国时期曹魏大臣。庞山民出身荆州庞氏,为隐士庞德公之子、凤雏庞统的堂兄,娶诸葛亮二姐诸葛氏(“若雪”为网络小说虚构)为妻。后出仕曹魏,历任黄门、吏部郎等职。', + gongsunxiu:'公孙修(?-238),三国时期人物,公孙渊之子。景初元年(237年),魏明帝曹叡派出幽州刺史毌丘俭攻打公孙渊,久战不利回师。公孙渊即自立为燕王,改元绍汉,引诱鲜卑侵扰北方,背叛曹魏。景初二年(238年)春,曹魏又派司马懿和高句丽国王高位宫率军攻打公孙渊,围城日久,公孙渊粮尽之后,与儿子公孙修一起出逃后被擒获,父子二人同时被斩首示众。', }, characterTitle:{ }, @@ -11591,6 +12432,27 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(num<4) str+=''; return str; }, + dcjianzhuan(player){ + let str='锁定技。①当你于出牌阶段使用牌时,你选择此阶段未执行过的一项执行:'; + const list=[ + '⒈令一名角色弃置X张牌', + ';', + '⒉摸X张牌', + ';', + '⒊重铸X张牌', + ';', + '⒋弃置X张牌', + ],info=get.info('dcjianzhuan').choices,storage=player.getStorage('dcjianzhuan'); + let choices=[]; + for(const k in info) choices.push(k); + for(let i=0;ii).includes(j); + if(goon&&storage.includes(choices[j])) str+=''; + str+=list[i]; + if(goon&&storage.includes(choices[j])) str+=''; + } + return str+'(X为此技能于本阶段的发动次数)。②出牌阶段结束时,若你本阶段执行过〖渐专①〗的所有选项,则你随机移除〖渐专①〗的一项。'; + }, }, perfectPair:{}, characterReplace:{ @@ -11879,7 +12741,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ dcanliao_info:'出牌阶段限X次(X为群势力角色数)。你可以重铸一名角色的一张牌。', dc_yuejiu:'乐就', dccuijin:'催进', - dccuijin_info:'当你或你攻击范围内的角色使用【杀】时,你可以弃置一张牌,令此【杀】的伤害基数+1。然后当此杀被目标角色抵消或无效或防止伤害后,你摸一张牌,对使用者造成1点伤害。', + dccuijin_info:'当你或你攻击范围内的角色使用【杀】或【决斗】时,你可以弃置一张牌,令此牌的伤害基数+1。然后当此牌被目标角色抵消或无效或防止伤害后,你摸两张牌并对使用者造成1点伤害。', panghui:'庞会', dcyiyong:'异勇', dcyiyong_info:'当你对其他角色造成伤害时,若你有牌,你可以与其同时弃置至少一张牌。若你以此法弃置的牌的点数之和:不大于其,你摸X张牌;不小于其,此伤害+1(X为其以此法弃置的牌数)。', @@ -11930,7 +12792,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ dchaochong:'昊宠', dchaochong_info:'当你使用牌后,你可以将手牌摸至或弃置至你的手牌上限数(至多摸五张)。然后若你以此法:得到牌,你的手牌上限-1;失去牌,你的手牌上限+1。', dcjinjin:'矜谨', - dcjinjin_info:'每回合限一次。当你造成或受到伤害后,你可以重置因〖昊宠〗增加或减少的手牌上限,令伤害来源弃置至多X张牌,然后你摸Y张牌(X为你以此法变化的手牌上限且至少为1,Y为X减其以此法弃置的牌数)。', + dcjinjin_info:'每回合限两次。当你造成或受到伤害后,你可以重置因〖昊宠〗增加或减少的手牌上限,令伤害来源弃置至多X张牌,然后你摸Y张牌(X为你以此法变化的手牌上限且至少为1,Y为X减其以此法弃置的牌数)。', xianglang:'向朗', dckanji:'勘集', dckanji_info:'出牌阶段限两次。你可以展示所有手牌,若花色均不同,你摸两张牌。然后若你的手牌因此包含了四种花色,你跳过下一个弃牌阶段。', @@ -11977,7 +12839,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ dcqinghuang_info:'出牌阶段开始时,你可以减1点体力上限,然后你于本回合发动〖踏寂〗时额外随机执行一种效果。', dc_huojun:'霍峻', dcgue:'孤扼', - dcgue_info:'每回合限一次。当你需要于回合外使用或打出【杀】或【闪】时,若你有手牌,你可以展示之。若其中【杀】和【闪】的数量之和不超过1,你视为使用或打出此牌。', + dcgue_info:'每回合限一次。当你需要于回合外使用或打出【杀】或【闪】时,你可以发动此技能:你展示所有手牌,若其中【杀】和【闪】的数量之和不超过1,你视为使用或打出此牌。', dcsigong:'伺攻', dcsigong_info:'其他角色的回合结束时,若其于本回合内使用牌被响应过,你可以将手牌摸至或弃置至1,视为对其使用一张需使用X张【闪】抵消的【杀】,且此【杀】的伤害基数+1(X为你以此法弃置的牌数且至少为1)。当你以此法造成伤害后,该技能于本轮失效。', peiyuanshao:'裴元绍', @@ -12107,6 +12969,39 @@ game.import('character',function(lib,game,ui,get,ai,_status){ dcfuli_info:'出牌阶段限一次,你可以展示手牌并弃置一种类别的所有手牌,然后摸X张牌(X为这些牌的牌名字数和且X至多为场上手牌数最多的角色的手牌数)。若你因此弃置了伤害类卡牌,则你可以选择一名角色,令其攻击范围-1直到你的下个回合开始。', dcdehua:'德化', dcdehua_info:'锁定技。①一轮游戏开始时,若有你可以使用的非延时类伤害类牌的牌名,你选择其中一个并视为使用之,然后你不能从手牌中使用此牌名的牌,然后若你已选择过所有的伤害类牌牌名,你失去〖德化〗。②你的手牌上限+Y(Y为你〖德化①〗选择过的牌名数)。', + gongsunxiu:'公孙修', + dcgangu:'干蛊', + dcgangu_info:'锁定技。每回合限一次。当其他角色失去体力后,你摸两张牌,然后失去1点体力。', + dckuizhen:'溃阵', + dckuizhen_info:'出牌阶段限一次。你可以令一名手牌数或体力值大于你的角色视为对你使用一张【决斗】。若你:受到渠道为此牌的伤害,你观看其手牌并获得其中所有的【杀】(你使用以此法得到的牌无任何次数限制);未受到渠道为此牌的伤害,其失去1点体力。', + dc_jiangji:'蒋济', + dcshiju:'势举', + dcshiju_info:'其他角色的出牌阶段限一次。其可以交给你一张牌,若此牌为装备牌,你可以使用之,然后其本回合攻击范围+X(X为你装备区里的牌数)。若你以此法替换了装备,你与其各摸两张牌。', + dcyingshi:'应时', + dcyingshi_info:'每回合每项各限一次。当你使用普通锦囊牌指定第一个目标后,若有目标不为本回合第一次成为牌的目标,则你可以令其选择一项:⒈令你于此牌结算结束后视为对其使用一张与此牌牌名相同的牌;⒉弃置X张牌,此牌对其无效(X为你装备区里的牌数)。', + dc_wangling:'王淩', + dcjichou:'集筹', + dcjichou_info:'出牌阶段结束时,若你于此阶段使用过牌且这些牌的牌名均不同,你可以观看位于弃牌堆中的这些牌,选择任意张牌并选择等量角色,将这些牌交给这些角色各一张,然后你摸X张牌(X为你本局游戏首次发动〖集筹〗给出的牌数)。', + dcmouli:'谋立', + dcmouli_info:'觉醒技。回合结束时,若你因〖集筹〗给出的牌的牌名总数不小于5,你加1点体力上限并回复1点体力,然后获得〖自缚〗。', + dczifu:'自缚', + dczifu_info:'锁定技。出牌阶段开始时,你将手牌摸至体力上限(至多摸至五张)。若你以此法得到牌,你须选择手牌中不同牌名的牌各一张,然后弃置其余的手牌。', + dc_simashi:'司马师', + dcsanshi:'散士', + dcsanshi_tag:'死士', + dcsanshi_info:'锁定技。①第一轮游戏开始时,你令系统将牌堆中每个点数的随机一张牌永久标记为“死士”(“死士”对你可见)。②一名角色的回合结束时,若本回合有“死士”不因你使用或打出而进入弃牌堆,你于弃牌堆中获得这些牌。③你使用“死士”不能被响应。', + dczhenrao:'震扰', + dczhenrao_info:'每回合每名角色限一次。当你使用牌指定第一个目标后,若目标角色包含其他角色,或当其他角色使用牌指定你为目标后,你可以选择手牌数大于你的其中一个目标或此牌的使用者,然后对其造成1点伤害。', + dcchenlve:'沉略', + dcchenlve_info:'限定技。出牌阶段,你可以将牌堆、弃牌堆、场上及其他角色的手牌区里的所有“死士”置入处理区,然后你获得这些牌。若如此做,你获得如下效果:1.此回合结束时,你将这些牌移出游戏;2.当你死亡时,你将所有以此法移出游戏的“死士”置入弃牌堆。', + dc_caoshuang:'新杀曹爽', + dc_caoshuang_prefix:'新杀', + dcjianzhuan:'渐专', + dcjianzhuan_info:'锁定技。①当你于出牌阶段使用牌时,你选择此阶段未执行过的一项执行:⒈令一名角色弃置X张牌;⒉摸X张牌;⒊重铸X张牌;⒋弃置X张牌(X为此技能于本阶段的发动次数)。②出牌阶段结束时,若你本阶段执行过〖渐专①〗的所有选项,则你随机移除〖渐专①〗的一项。', + dcfanshi:'返势', + dcfanshi_info:'觉醒技,结束阶段,若〖渐专①〗剩余选项数小于2,则你执行三次X视为1的剩余选项,然后增加2点体力上限并回复2点体力,失去技能〖渐专〗并获得技能〖覆斗〗。', + dcfudou:'覆斗', + dcfudou_info:'当你使用黑色牌/红色牌指定唯一目标后,若该角色不为你,且其于本局游戏对你/未对你造成过伤害,则你可以与其各失去1点体力/各摸一张牌。', sp_baigei:'无双上将', sp_caizijiaren:'才子佳人', @@ -12121,6 +13016,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ sp_raoting:'绕庭之鸦', sp_yijun:'异军突起', sp_zhengyin:'正音雅乐', + sp_zhonghu:'冢虎狼顾', }, }; }); diff --git a/character/jsrg.js b/character/jsrg.js index 5b2b293d5..4b0b2bf72 100644 --- a/character/jsrg.js +++ b/character/jsrg.js @@ -235,7 +235,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ enable:'chooseToUse', filter:function(event,player){ for(const name of ['wuxie','huogong']){ - if(event.filterCard({name},player,event)) return true; + if(event.filterCard(get.autoViewAs({name},'unsure'),player,event)) return true; } return false; }, @@ -246,7 +246,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ viewAs:function(cards,player){ const event=get.event(),filter=event._backup.filterCard; for(const name of ['wuxie','huogong']){ - if(filter({name},player,event)) return {name}; + if(filter(get.autoViewAs({name},'unsure'),player,event)) return {name}; } return null; }, @@ -508,13 +508,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){ onremove:true, mod:{ cardEnabled:function(card,player){ - if(player.getStorage('jsrgfumou_forbid').includes(get.color(card))) return false; + const color = get.color(card); + if (color != 'unsure' && player.getStorage('jsrgfumou_forbid').includes(color)) return false; }, cardRespondable:function(card,player){ - if(player.getStorage('jsrgfumou_forbid').includes(get.color(card))) return false; + const color = get.color(card); + if (color != 'unsure' && player.getStorage('jsrgfumou_forbid').includes(color)) return false; }, cardSavable:function(card,player){ - if(player.getStorage('jsrgfumou_forbid').includes(get.color(card))) return false; + const color = get.color(card); + if (color != 'unsure' && player.getStorage('jsrgfumou_forbid').includes(color)) return false; }, }, mark:true, @@ -810,14 +813,14 @@ game.import('character',function(lib,game,ui,get,ai,_status){ })) return false; return get.inpileVCardList(info=>{ if(info[0]!='basic') return false; - return event.filterCard({name:info[2],nature:info[3]},player,event); + return event.filterCard(get.autoViewAs({name:info[2],nature:info[3]},'unsure'),player,event); }).length; }, chooseButton:{ dialog(event,player){ const vcards=get.inpileVCardList(info=>{ if(info[0]!='basic') return false; - return event.filterCard({name:info[2],nature:info[3]},player,event); + return event.filterCard(get.autoViewAs({name:info[2],nature:info[3]},'unsure'),player,event); }); return ui.create.dialog('镇胆',[vcards,'vcard']); }, @@ -952,7 +955,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(curLen<=2) return false; for(let i=curLen-2;i>=0;i--){ const history=player.actionHistory[i]; - if(history.isMe&&!history.isSkipped) return false; + if(history.isMe&&!history.isSkipped&&!history._jsrgtuigu) return false; if(history.isRound) break; } return true; @@ -960,12 +963,20 @@ game.import('character',function(lib,game,ui,get,ai,_status){ forced:true, locked:false, async content(event,trigger,player){ - const evt=trigger; - player.insertPhase(); + const evt=trigger,evtx=player.insertPhase(); + player.when('phaseBeforeStart') + .filter(evtt=>evtt==evtx) + .then(()=>{ + game.players.slice().concat(game.dead).forEach(current=>{ + current.getHistory()._jsrgtuigu=true; + current.getStat()._jsrgtuigu=true; + }); + }); if(evt.player!=player&&!evt._finished){ evt.finish(); evt._triggered=5; - evt.player.insertPhase(); + const evtxx=evt.player.insertPhase(); + delete evtxx.skill; } }, }, @@ -1236,6 +1247,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } }, charlotte:true, + onremove:true, mod:{ maxHandcard(player,num){ return num-player.countMark('jsrgzhaotu_handcard'); @@ -1247,8 +1259,13 @@ game.import('character',function(lib,game,ui,get,ai,_status){ order:5, result:{ target(player,target){ - if(player.hasSkill('jsrgjingju')||player.hasZhuSkill('jsrgweizhui')) return get.attitude(player,target); - return -1; + let dis=0.5-0.75*target.needsToDiscard(2,null,true); + if(dis>0) return dis; + if(player.hasSkill('jsrgjingju')&&player.hasZhuSkill('jsrgweizhui')&&get.attitude(player,target)>0) return game.countPlayer(current=>{ + if(current===player||current===target||current.group!=='wei') return false; + return player.hasZhuSkill('jsrgweizhui',current)&&get.attitude(player,current)>0; + }); + return dis; }, }, }, @@ -1263,20 +1280,24 @@ game.import('character',function(lib,game,ui,get,ai,_status){ })) return false; return get.inpileVCardList(info=>{ if(info[0]!='basic') return false; - return event.filterCard({name:info[2],nature:info[3]},player,event); + return event.filterCard(get.autoViewAs({name:info[2],nature:info[3]},'unsure'),player,event); }).length; }, chooseButton:{ dialog:function(event,player){ const vcards=get.inpileVCardList(info=>{ if(info[0]!='basic') return false; - return event.filterCard({name:info[2],nature:info[3]},player,event); + return event.filterCard(get.autoViewAs({name:info[2],nature:info[3]},'unsure'),player,event); }); return ui.create.dialog('惊惧',[vcards,'vcard'],'hidden'); }, check:function(button){ + let player=_status.event.player; if(get.event().getParent().type!='phase') return 1; - return get.player().getUseValue({name:button.link[2],nature:button.link[3]}); + return get.player().getUseValue({name:button.link[2],nature:button.link[3]})+game.countPlayer(current=>{ + if(current===player||current.group!=='wei') return false; + return player.hasZhuSkill('jsrgweizhui',current)&&get.attitude(player,current)>0; + }); }, backup:function(links,player){ return { @@ -1365,7 +1386,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ return player.canUse(get.autoViewAs({name:'guohe'},[card]),get.event('target')); }).set('target',player).set('ai',card=>{ if(get.effect(get.event('target'),get.autoViewAs({name:'guohe'},[card]),player)<=0) return 0; - return 6-get.value(card); + return 7-get.value(card); }); if(bool){ trigger.player.logSkill('jsrgweizhui',player); @@ -3811,16 +3832,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){ return game.hasPlayer(i=>i!=player); }, content:function*(event,map){ - var player=map.player,trigger=map.trigger; - var targets=game.filterPlayer(i=>i!=player); + var player=map.player,trigger=map.trigger, targets=game.filterPlayer(i=>i!=player); + var shas=player.mayHaveSha(target,'use',null,'count')-player.getCardUsable('sha',true); for(var target of targets){ var att=get.attitude(target,player); var result=yield target.chooseCard('he',`负山:是否交给${get.translation(player)}一张牌?`,`若如此做,其此阶段使用【杀】的次数上限+1`).set('att',att).set('ai',card=>{ if(!get.event('goon')) return -get.value(card); var isSha=get.name(card,get.event('target'))=='sha'; if(get.event('att')<0) return (isSha?0:5)-get.value(card); - return (isSha?10:5.5)-get.value(card); - }).set('goon',att>0&&player.countCards('sha')>player.getCardUsable('sha',true)||att<0&&!player.hasSkill('jsrgfushan_sha')).set('target',player); + return (isSha?10:0)-get.value(card); + }).set('goon',att>0&&shas>=0||att<0&&target.hp>player.getCardUsable('sha',true)&&shas<-1/Math.max(1,player.hp)).set('target',player); if(result.bool){ target.give(result.cards,player); target.line(player); @@ -4741,11 +4762,11 @@ game.import('character',function(lib,game,ui,get,ai,_status){ for(var name of lib.inpile){ if(get.type2(name)!='basic') continue; var card={name:name}; - if(event.filterCard(card,player,event)) return true; + if(event.filterCard(get.autoViewAs(card,'unsure'),player,event)) return true; if(name=='sha'){ for(var nature of lib.inpile_nature){ card.nature=nature; - if(event.filterCard(card,player,event)) return true; + if(event.filterCard(get.autoViewAs(card,'unsure'),player,event)) return true; } } } @@ -4757,19 +4778,19 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var list=[]; for(var name of lib.inpile){ if(name=='sha'){ - if(event.filterCard({name:name},player,event)) list.push(['基本','','sha']); + if(event.filterCard(get.autoViewAs({name},'unsure'),player,event)) list.push(['基本','','sha']); for(var nature of lib.inpile_nature){ - if(event.filterCard({name:name,nature:nature},player,event)) list.push(['基本','','sha',nature]); + if(event.filterCard(get.autoViewAs({name,nature},'unsure'),player,event)) list.push(['基本','','sha',nature]); } } - else if(get.type(name)=='basic'&&event.filterCard({name:name},player,event)) list.push(['基本','',name]); + else if(get.type(name)=='basic'&&event.filterCard(get.autoViewAs({name},'unsure'),player,event)) list.push(['基本','',name]); } var dialog=ui.create.dialog('念恩',[list,'vcard']); dialog.direct=true; return dialog; }, filter:function(button,player){ - return _status.event.getParent().filterCard({name:button.link[2],nature:button.link[3]},player,_status.event.getParent()); + return _status.event.getParent().filterCard(get.autoViewAs({name:button.link[2],nature:button.link[3]},'unsure'),player,_status.event.getParent()); }, check:function(button){ if(_status.event.getParent().type!='phase') return 1; @@ -5017,7 +5038,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ for(var name of lib.inpile){ if(get.type(name)!='basic') continue; if(player.getStorage('jsrgjixiang_used').includes(name)) continue; - var card={name:name}; + var card={name:name,isCard:true}; if(event.filterCard(card,event.player,event)) return true; if(name=='sha'){ for(var nature of lib.inpile_nature){ @@ -7454,6 +7475,42 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, jsrgtushe:{ audio:'xinfu_tushe', + 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', }, @@ -7465,6 +7522,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ check:function(event,player){ return !player.countCards('h',{type:'basic'}); }, + locked: false, content:function (){ 'step 0' player.showHandcards(); @@ -7480,7 +7538,22 @@ game.import('character',function(lib,game,ui,get,ai,_status){ presha:true, pretao:true, threaten:1.8, - }, + effect: { + player(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]; + } + } + } + } }, jsrgtongjue:{ audio:2, @@ -8233,7 +8306,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ jsrgyingshi:'鹰眎', jsrgyingshi_info:'当你翻面时,你可以观看牌堆底的三张牌(若死亡角色数大于2则改为五张),然后将其中任意数量的牌以任意顺序置于牌堆顶,其余以任意顺序置于牌堆底。', jsrgtuigu:'蜕骨', - jsrgtuigu_info:'①回合开始时,你可以翻面并令你本回合的手牌上限+X,然后摸X张牌并视为使用一张【解甲归田】(X为存活角色数的一半,向下取整),目标角色不能使用以此法得到的牌直到其回合结束。②一轮游戏开始时,若你上一轮未执行过回合,你获得一个额外的回合。③当你失去装备牌里的牌后,你回复1点体力。', + jsrgtuigu_info:'①回合开始时,你可以翻面并令你本回合的手牌上限+X,然后摸X张牌并视为使用一张【解甲归田】(X为存活角色数的一半,向下取整),目标角色不能使用以此法得到的牌直到其回合结束。②一轮游戏开始时,若你上一轮未执行过回合(因〖蜕骨②〗执行的回合除外),你获得一个额外的回合。③当你失去装备牌里的牌后,你回复1点体力。', jsrg_guoxun:'合郭循', jsrg_guoxun_prefix:'合', jsrgeqian:'遏前', diff --git a/character/mobile.js b/character/mobile.js index 57e9c1aaf..d9b5283ae 100644 --- a/character/mobile.js +++ b/character/mobile.js @@ -543,7 +543,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ '令其摸一张牌', ][['豹','鹰','熊','兔'].indexOf(zhoufa)]:'令其随机执行一个效果'; const {result:{bool,targets}}=await player.chooseTarget(get.prompt('shoufa'),'选择一名距离'+(event.triggername=='damageEnd'?'':'不')+'大于2的角色,'+str,(card,player,target)=>{ - const name=_status.event.name; + const name=_status.event.triggername; if(name=='damageEnd'&&get.distance(player,target)<=2) return false; if(name=='damageSource'&&get.distance(player,target)>2) return false; const zhoufa=player.storage.zhoulin_zhoufa; @@ -570,7 +570,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ case '兔': return get.effect(target,{name:'draw'},player,player); } - }).set('name',event.triggername); + }).set('triggername',event.triggername); if(!bool) return; const target=targets[0]; player.logSkill('shoufa',target); @@ -687,7 +687,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } targets=targets.filter(target=>target!=player&&target.countCards('h')); if(targets.length){ - var result=yield player.chooseTarget('请选择【诡谋】的目标','观看一名可选择的角色的手牌并选择其中至多三张牌,然后你可以将其中至多两张牌交给另一名其他角色,然后弃置剩余的牌',(card,player,target)=>{ + var result=yield player.chooseTarget('请选择【诡谋】的目标','观看一名可选择的角色的手牌并选择其中一张牌,然后你可以此牌交给另一名其他角色或弃置此牌',(card,player,target)=>{ return _status.event.targets.includes(target)&&target.countCards('h'); },true).set('ai',target=>{ return Math.sqrt(Math.min(3,target.countCards('h')))*get.effect(target,{name:'guohe_copy2'},player,player); @@ -696,28 +696,21 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var target=result.targets[0]; player.logSkill('guimou',target); player.addExpose(0.3); - var result2=yield player.choosePlayerCard(target,'h','visible','
选择其中至多三张牌,然后你可以将其中至多两张牌交给另一名其他角色,然后弃置剩余的牌
',[1,3],true).set('ai',button=>get.value(button.link)); + var result2=yield player.choosePlayerCard(target,'h','visible',true).set('ai',button=>{ + return get.value(button.link); + }).set('prompt','诡谋:请选择'+get.translation(target)+'的一张手牌').set('prompt2','
将选择的牌交给另一名其他角色或弃置此牌
'); if(result2.bool){ - var cards=result2.links.slice(); - var result3; + var cards=result2.links.slice(),result3; if(!game.hasPlayer(targetx=>targetx!=player&&targetx!=target)) result3={bool:false}; - else result3=yield player.chooseCardButton('是否将其中至多两张牌交给另一名其他角色',cards,[1,Math.min(2,cards.length)]).set('ai',button=>{ - var player=_status.event.player; - if(!game.hasPlayer(target=>target!=player&&target!=_status.event.target&&get.attitude(player,target)>0)) return 0; - return get.value(button.link,_status.event.player); - }).set('target',target); + else result3=yield player.chooseTarget('是否令另一名其他角色获得'+get.translation(cards)+'?',(card,player,target)=>{ + return target!=player&&target!=_status.event.target; + }).set('ai',target=>get.attitude(_status.event.player,target)).set('target',target); if(result3.bool){ - var result4=yield player.chooseTarget('请选择获得'+get.translation(result3.links)+'的目标',(card,player,target)=>{ - return target!=player&&target!=_status.event.target; - }).set('ai',target=>get.attitude(_status.event.player,target)).set('target',target); - if(result4.bool){ - var targetx=result4.targets[0]; - player.line(targetx); - targetx.gain(result3.links,target,'give'); - cards.removeArray(result3.links); - } + var targetx=result3.targets[0]; + player.line(targetx); + targetx.gain(cards,target,'give'); } - if(cards.length) target.discard(cards).discarder=player; + else target.discard(cards).discarder=player; } } } @@ -870,7 +863,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ logTarget:'player', content:function*(event,map){ var player=map.player,trigger=map.trigger,target=trigger.player; - var cards=get.cards(2); + var cards=get.cards(3); + yield game.cardsDiscard(cards); player.showCards(cards,get.translation(player)+'发动了【州贤】'); var result=yield target.chooseToDiscard('he','州贤:弃置一张其中有的类别的牌,或令此牌对'+get.translation(player)+'无效',(card,player)=>{ return _status.event.cards.some(cardx=>get.type2(cardx)==get.type2(card)); @@ -890,7 +884,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ bs.remove(card); if(card.cards) bs.removeArray(card.cards); else bs.removeArray(ui.selected.cards); - var cardx=Array.from(ui.cardPile.childNodes).slice(0,2); + var cardx=Array.from(ui.cardPile.childNodes).slice(0,3); bs=bs.filter(i=>cardx.some(j=>get.type2(j)==get.type2(i))); if(!bs.length) return 'zerotarget'; if(bs.length<=2){ @@ -956,15 +950,19 @@ game.import('character',function(lib,game,ui,get,ai,_status){ mbyilie3:{ audio:'mbyilie', trigger:{player:'phaseEnd'}, - filter:function(event,player){ - return player.countMark('mbyilie'); - }, + //filter:function(event,player){ + // return player.countMark('mbyilie'); + //}, forced:true, content:function(){ + 'step 0' + player.draw(); + 'step 1' var num=player.countMark('mbyilie'); - player.draw(num); - player.loseHp(num); - player.removeMark('mbyilie',num); + if(num){ + player.loseHp(num); + player.removeMark('mbyilie',num); + } }, }, //向朗 @@ -1170,7 +1168,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var target=trigger.player; var card=result.cards[0]; player.line(target,'green'); - target.addTempSkill('mbzhixi','phaseUseAfter'); + target.addTempSkills('mbzhixi','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); @@ -3110,7 +3108,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ cardEnabled:function(card,player){ if(!player.storage.scschihe_blocker) return; var suit=get.suit(card); - if(suit=='none') return; + if(suit=='none'||suit=='unsure') return; var evt=_status.event; if(evt.name!='chooseToUse') evt=evt.getParent('chooseToUse'); if(!evt||!evt.respondTo||evt.respondTo[1].name!='sha') return; @@ -3224,10 +3222,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, filter:function(event,player){ var filter=event.filterCard; - if(filter({name:'sha',nature:'fire'},player,event)&&player.countCards('hes',{suit:'diamond'})) return true; - if(filter({name:'shan'},player,event)&&player.countCards('hes',{suit:'club'})) return true; - if(filter({name:'tao'},player,event)&&player.countCards('hes',{suit:'heart'})) return true; - if(filter({name:'wuxie'},player,event)&&player.countCards('hes',{suit:'spade'})) return true; + if(filter(get.autoViewAs({name:'sha',nature:'fire'},'unsure'),player,event)&&player.countCards('hes',{suit:'diamond'})) return true; + if(filter(get.autoViewAs({name:'shan'},'unsure'),player,event)&&player.countCards('hes',{suit:'club'})) return true; + if(filter(get.autoViewAs({name:'tao'},'unsure'),player,event)&&player.countCards('hes',{suit:'heart'})) return true; + if(filter(get.autoViewAs({name:'wuxie'},'unsure'),player,event)&&player.countCards('hes',{suit:'spade'})) return true; return false; }, precontent:function(){ @@ -3401,10 +3399,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, filter:function(event,player){ var filter=event.filterCard; - if(filter({name:'sha',nature:'fire'},player,event)&&player.countCards('hes',{suit:'diamond'})) return true; - if(filter({name:'shan'},player,event)&&player.countCards('hes',{suit:'club'})) return true; - if(filter({name:'tao'},player,event)&&player.countCards('hes',{suit:'heart'})) return true; - if(filter({name:'wuxie'},player,event)&&player.countCards('hes',{suit:'spade'})) return true; + if(filter(get.autoViewAs({name:'sha',nature:'fire'},'unsure'),player,event)&&player.countCards('hes',{suit:'diamond'})) return true; + if(filter(get.autoViewAs({name:'shan'},'unsure'),player,event)&&player.countCards('hes',{suit:'club'})) return true; + if(filter(get.autoViewAs({name:'tao'},'unsure'),player,event)&&player.countCards('hes',{suit:'heart'})) return true; + if(filter(get.autoViewAs({name:'wuxie'},'unsure'),player,event)&&player.countCards('hes',{suit:'spade'})) return true; return false; }, precontent:function(){ @@ -4529,13 +4527,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ forceDie:true, filter:function(event,player){ if(event.name=='die') return true; - if(!lib.skill.yijin.getKane(event.player).length) return false; - if(event.player.additionalSkills['yijin_'+player.playerid]){ - return true; - } - return false; + return lib.skill.yijin.getKane(event.player).length&&event.player.additionalSkills['yijin_'+player.playerid]; }, content:function(){ + 'step 0' if(trigger.name=='die'){ game.countPlayer(current=>{ var skills=current.additionalSkills['yijin_'+player.playerid]; @@ -4546,16 +4541,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } } }); + event.finish(); + return; } else { - var skills=trigger.player.additionalSkills['yijin_'+player.playerid]; - trigger.player.removeAdditionalSkill('yijin_'+player.playerid); - for(var i of skills){ - trigger.player.removeMark(i,1); - trigger.player.removeSkill(i); - } + const skills=trigger.player.additionalSkills['yijin_'+player.playerid]; + for(const mark of skills) trigger.player.removeMark(mark,1); } - } + 'step 1' + trigger.player.removeAdditionalSkill('yijin_'+player.playerid); + }, }, wushi:{ charlotte:true, @@ -5630,7 +5625,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var evt=lib.skill.dcjianying.getLastUsed(player); if(!evt||!evt.card) return; var num1=get.number(card),num2=get.number(evt.card); - if(typeof num1=='number'&&typeof num2=='number'&&num1%num2==0) return Infinity; + if(num1==='unsure'||typeof num1=='number'&&typeof num2=='number'&&num1%num2==0) return Infinity; } }, aiOrder:function(player,card,num){ @@ -5638,7 +5633,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var evt=lib.skill.dcjianying.getLastUsed(player); if(!evt||!evt.card) return; var num1=get.number(card),num2=num2=get.number(evt.card); - if(typeof num1=='number'&&typeof num2=='number'&&num2%num1==0) return num+5; + if(num1==='unsure'||typeof num1=='number'&&typeof num2=='number'&&num2%num1==0) return num+5; } }, }, @@ -5738,7 +5733,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var num=0; for(var i of cards) num+=get.number(i,player); num=num%13; - if(num==0) num=13; + if(num==0) num=13; var card=get.cardPile2(function(card){ return get.number(card,false)==num; }); @@ -6639,19 +6634,19 @@ game.import('character',function(lib,game,ui,get,ai,_status){ audio:2, enable:['chooseToUse','chooseToRespond'], filter:function(event,player){ - return player.getExpansions('jibing').length>0&&(event.filterCard({name:'sha'},player,event)||event.filterCard({name:'shan'},player,event)); + return player.getExpansions('jibing').length>0&&(event.filterCard(get.autoViewAs({name:'sha'},'unsure'),player,event)||event.filterCard(get.autoViewAs({name:'shan'},'unsure'),player,event)); }, chooseButton:{ dialog:function(event,player){ var dialog=ui.create.dialog('集兵','hidden'); - if(event.filterCard({name:'sha'},player,event)&&event.filterCard({name:'shan'},player,event)){ + if(event.filterCard(get.autoViewAs({name:'sha'},'unsure'),player,event)&&event.filterCard(get.autoViewAs({name:'shan'},'unsure'),player,event)){ dialog._chooseButton=2; var list=['sha','shan']; dialog.add([list.map(i=>{ return [i,get.translation(i)]; }),'tdnodes']); } - else dialog._cardName=event.filterCard({name:'sha'},player,event)?'sha':'shan'; + else dialog._cardName=event.filterCard(get.autoViewAs({name:'sha'},'unsure'),player,event)?'sha':'shan'; dialog.add(player.getExpansions('jibing')); return dialog; }, @@ -13284,7 +13279,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ },'hs')) return false; for(var name of lib.inpile){ if(get.type(name)!='basic') continue; - if(event.filterCard({name:name},player,event)) return true; + if(event.filterCard(get.autoViewAs({name},'unsure'),player,event)) return true; } return false; }, @@ -13293,7 +13288,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var list=[]; for(var name of lib.inpile){ if(get.type(name)!='basic') continue; - if(event.filterCard({name:name},player,event)) list.push(['基本','',name]); + if(event.filterCard(get.autoViewAs({name},'unsure'),player,event)) list.push(['基本','',name]); if(name!='sha') continue; for(var j of lib.inpile_nature){ if(event.filterCard({name:name,nature:j},player,event)) list.push(['基本','','sha',j]); @@ -13906,7 +13901,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } return false; } - })) return -att; + })) return -att; } return 0; } @@ -13962,7 +13957,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 'step 4' if(result.bool&&result.links.length){ var link=result.links[0]; - if(get.position(link)=='e') event.targets[1].equip(link); + 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],false) @@ -14298,34 +14293,34 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, filter:function(event,player){ if(!player.storage.yizan&&player.countCards('hes')<2) return false; - if(!player.hasCard(function(card){ - return get.type(card)=='basic'; - },'hs')) return false; - for(var name of lib.inpile){ - if(get.type(name)!='basic') continue; - if(event.filterCard({name:name},player,event)) return true; - if(name=='sha'){ - for(var nature of lib.inpile_nature){ - if(event.filterCard({name:'sha',nature:nature},player,event)) return true; - } - } - } + if(!player.hasCard(function(card){ + return get.type(card)=='basic'; + },'hs')) return false; + for(var name of lib.inpile){ + if(get.type(name)!='basic') continue; + if(event.filterCard(get.autoViewAs({name},'unsure'),player,event)) return true; + if(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:function(event,player){ var list=[]; - for(var name of lib.inpile){ - if(get.type(name)!='basic') continue; - if(event.filterCard({name:name},player,event)){ - list.push(['基本','',name]); - } - if(name=='sha'){ - for(var nature of lib.inpile_nature){ - if(event.filterCard({name:name,nature:nature},player,event)) list.push(['基本','','sha',nature]); - } - } - } + for(var name of lib.inpile){ + if(get.type(name)!='basic') continue; + if(event.filterCard(get.autoViewAs({name},'unsure'),player,event)){ + list.push(['基本','',name]); + } + if(name=='sha'){ + for(var nature of lib.inpile_nature){ + if(event.filterCard(get.autoViewAs({name,nature},'unsure'),player,event)) list.push(['基本','','sha',nature]); + } + } + } return ui.create.dialog('翊赞',[list,'vcard'],'hidden'); }, check:function(button){ @@ -15669,7 +15664,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ sunru:['dc_sunru','sunru'], liuye:['dc_liuye','liuye'], zhaotongzhaoguang:['dc_zhaotongzhaoguang','zhaotongzhaoguang'], - yangbiao:['yangbiao','dc_yangbiao','jsrg_yangbiao'], + yangbiao:['yangbiao','dc_yangbiao','jsrg_yangbiao'], qiaozhou:['yj_qiaozhou','qiaozhou'], sunhanhua:['dc_sunhanhua','sunhanhua'], zhoubuyi:['zhoubuyi','yj_zhoubuyi'], @@ -16034,7 +16029,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ requanfeng_info:'限定技。①其他角色死亡时,你可失去〖弘仪〗,然后获得其武将牌上的所有非主公技,非隐匿技和非Charlotte技,加1点体力上限并回复1点体力。②当你处于濒死状态时,你可以加2点体力上限,然后回复4点体力。', quanfeng:'劝封', quanfeng_info:'锁定技,限定技,一名角色死亡时,你选择获得其的一个技能(主公技,限定技,觉醒技,隐匿技,使命技,带有Charlotte标签的技能除外),然后加1点体力上限并回复1点体力。', - simashi:'司马师', + simashi:'手杀司马师', + simashi_prefix:'手杀', baiyi:'败移', baiyi_info:'限定技,出牌阶段,若你已受伤,你可以交换两名其他角色的座次。', jinglve:'景略', @@ -16470,7 +16466,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ mutao_info:'出牌阶段限一次。你可以选择一名角色,令其将手牌中所有的【杀】置于武将牌上,然后将这些牌依次随机交给其下家开始的每一名角色。然后其对最后一名以此法获得【杀】的角色A造成X点伤害(X为A手牌中【杀】的数量且至多为2)。', yimou:'毅谋', yimou_info:'当一名角色受到伤害后,若其存活且你至其的距离不大于1,你可以选择一项:1.令其从牌堆中获得一张【杀】;2.令其将一张手牌交给另一名角色,然后摸一张牌。', - jiangji:'蒋济', + jiangji:'手杀蒋济', + jiangji_prefix:'手杀', jilun:'机论', jilun_info:'①当你受到伤害后,若你拥有技能〖急筹〗,则你可以一项:1.摸两张牌。2.获得1枚“机论”标记。②一名角色的结束阶段,若你拥有“机论”,则重复选择执行以下项直到你没有“机论”标记:1.失去1枚“机论”标记,视为使用一张〖急筹①〗记录过且未被〖机论②〗记录过的普通锦囊牌并记录此牌牌名。2.失去所有“机论”标记。', liwei:'李遗', @@ -16507,15 +16504,15 @@ game.import('character',function(lib,game,ui,get,ai,_status){ mb_chengui:'手杀陈珪', mb_chengui_prefix:'手杀', guimou:'诡谋', - guimou_info:'锁定技。游戏开始时/回合结束时,你随机/须选择以下一项直到你的下个准备阶段:①记录场上期间角色使用牌数;②记录期间场上角色弃置牌数;③记录期间场上角色获得牌数。准备阶段,你可以选择一名场上对应记录数值最少的其他角色,观看其手牌并选择其中至多三张牌,然后你可以将其中至多两张牌交给另一名其他角色,然后弃置其余牌。', + guimou_info:'锁定技。游戏开始时/回合结束时,你随机/须选择以下一项直到你的下个准备阶段:①记录场上期间角色使用牌数;②记录期间场上角色弃置牌数;③记录期间场上角色获得牌数。准备阶段,你可以选择一名场上对应记录数值最少的其他角色,观看其手牌并选择其中一张牌,然后你将此牌交给另一名其他角色或弃置此牌。', zhouxian:'州贤', - zhouxian_info:'锁定技。当你成为其他角色使用的伤害类卡牌的目标后,你亮出牌堆顶的两张牌,然后其须选择一项:①弃置一张与亮出牌之一类别相同的牌;②令此牌对你无效。', + zhouxian_info:'锁定技。当你成为其他角色使用的伤害类卡牌的目标后,你亮出牌堆顶的三张牌,然后其须选择一项:①弃置一张与亮出牌之一类别相同的牌;②令此牌对你无效。', mb_huban:'手杀胡班', mb_huban_prefix:'手杀', mbyilie:'义烈', mbyilie2:'义烈', mbyilie3:'义烈', - mbyilie_info:'锁定技。①游戏开始时,你选择一名其他角色,然后你获得以下效果:其受到伤害时,若你的“烈”标记数小于2,则你获得等同于伤害值的“烈”标记,然后防止此伤害;其对其他角色造成伤害后,你回复1点体力。②结束阶段,若你有“烈”标记,你摸X张牌并失去X点体力,然后移去所有“烈”标记(X为你拥有的“烈”标记数)。', + mbyilie_info:'锁定技。①游戏开始时,你选择一名其他角色,然后你获得以下效果:其受到伤害时,若你没有“烈”,则你获得等同于伤害值的“烈”标记,然后防止此伤害;其对其他角色造成伤害后,你回复1点体力。②结束阶段,你摸一张牌并失去X点体力,然后移去所有“烈”(X为你拥有的“烈”标记数)。', muludawang:'木鹿大王', shoufa:'兽法', shoufa_info:'当你受到伤害后/于一回合首次造成伤害后,你可以选择一名与你距离大于/不大于2的角色,令其随机执行以下一项:豹,令其受到1点无来源伤害;鹰,你随机获得其一张牌;熊,你随机弃置其装备区的一张牌;兔,令其摸一张牌。', diff --git a/character/offline.js b/character/offline.js index 4cea6a97f..74a84574e 100644 --- a/character/offline.js +++ b/character/offline.js @@ -11,7 +11,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ offline_yijiang:['ol_xinxianying'], 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:['shen_jiaxu','pe_wangyun','pe_zhonghui','pe_sunchen','pe_mengda','pe_wenqin','ns_caoanmin','chendong','jiangqing','kongrong','jiling','tianfeng','mateng'], + offline_piracyE:['shen_jiaxu','pe_wangyun','pe_zhonghui','pe_sunchen','pe_mengda','pe_wenqin','ns_caoanmin','jiangqing','kongrong','jiling','tianfeng','mateng'], 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'], @@ -34,7 +34,6 @@ game.import('character',function(lib,game,ui,get,ai,_status){ tianfeng:['male','qun',3,['sijian','gzsuishi']], jiling:['male','qun',4,['shuangren']], kongrong:['male','qun',3,['zymingshi','lirang']], - chendong:['male','wu',4,['duanxie','fenming']], jiangqing:['male','wu',4,['zyshangyi']], pk_sp_duyu:['male','qun',4,['pkwuku','pksanchen']], ps_lvbu:['male','qun',4,['wushuang','pssheji']], @@ -456,137 +455,137 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } }, //小乐 - vtbleyu:{ - audio:1, - trigger:{ - global:'phaseBegin', - }, - direct:true, - filter:function(event,player){ - return player.countCards('he')>=3; - }, - content:function(){ - 'step 0' - player.chooseToDiscard(get.prompt2('vtbleyu',trigger.player),3,'he').set('ai',card=>{ - if(ui.selected.cards.length==2) return 10-get.value(card); - if(_status.event.effect>0){ - return 6-get.value(card); - } - return 0; - }).set('effect',trigger.player.hasJudge('lebu')?0:get.effect(trigger.player,{name:'lebu'},player,player)).set('logSkill',['vtbleyu',trigger.player]); - 'step 1' - if(result.bool){ - trigger.player.judge(lib.card.lebu.judge).judge2=lib.card.lebu.judge2; - } else event.finish(); - 'step 2' - if(!result.bool){ - trigger.player.skip('phaseUse'); - } - }, - ai:{ - expose:0.3, + vtbleyu:{ + audio:1, + trigger:{ + global:'phaseBegin', + }, + direct:true, + filter:function(event,player){ + return player.countCards('he')>=3; + }, + content:function(){ + 'step 0' + player.chooseToDiscard(get.prompt2('vtbleyu',trigger.player),3,'he').set('ai',card=>{ + if(ui.selected.cards.length==2) return 10-get.value(card); + if(_status.event.effect>0){ + return 6-get.value(card); + } + return 0; + }).set('effect',trigger.player.hasJudge('lebu')?0:get.effect(trigger.player,{name:'lebu'},player,player)).set('logSkill',['vtbleyu',trigger.player]); + 'step 1' + if(result.bool){ + trigger.player.judge(lib.card.lebu.judge).judge2=lib.card.lebu.judge2; + } else event.finish(); + 'step 2' + if(!result.bool){ + trigger.player.skip('phaseUse'); + } + }, + ai:{ + expose:0.3, threaten:2.9, - }, - }, - vtbyuanli:{ - audio:1, - trigger:{global:['phaseUseSkipped','phaseUseCancelled']}, - direct:true, - content:function(){ - 'step 0' - player.chooseTarget(get.prompt2('vtbyuanli'),lib.filter.notMe).set('ai',target=>get.attitude(_status.event.player,target)+1); - 'step 1' - if(result.bool){ - player.logSkill('vtbyuanli',result.targets[0]); - game.asyncDraw([player,result.targets[0]].sortBySeat(_status.currentPhase)); - } - }, - ai:{ - expose:0.1, - }, - }, - vtbmeiniang:{ - audio:1, - trigger:{global:'phaseUseBegin'}, - filter:function(event,player){ - return event.player!=player; - }, - check:function(event,player){ - return get.attitude(player,event.player)>0&&event.player.getUseValue('jiu')>=0; - }, - logTarget:'player', - content:function(){ - trigger.player.chooseUseTarget('jiu',true,false); - } - }, - vtbyaoli:{ - audio:1, - trigger:{global:'useCardAfter'}, - filter:function(event,player){ - return event.card.name=='jiu'&&event.player!=player&&event.player.isPhaseUsing(); - }, - logTarget:'player', + }, + }, + vtbyuanli:{ + audio:1, + trigger:{global:['phaseUseSkipped','phaseUseCancelled']}, + direct:true, + content:function(){ + 'step 0' + player.chooseTarget(get.prompt2('vtbyuanli'),lib.filter.notMe).set('ai',target=>get.attitude(_status.event.player,target)+1); + 'step 1' + if(result.bool){ + player.logSkill('vtbyuanli',result.targets[0]); + game.asyncDraw([player,result.targets[0]].sortBySeat(_status.currentPhase)); + } + }, + ai:{ + expose:0.1, + }, + }, + vtbmeiniang:{ + audio:1, + trigger:{global:'phaseUseBegin'}, + filter:function(event,player){ + return event.player!=player; + }, + check:function(event,player){ + return get.attitude(player,event.player)>0&&event.player.getUseValue('jiu')>=0; + }, + logTarget:'player', + content:function(){ + trigger.player.chooseUseTarget('jiu',true,false); + } + }, + vtbyaoli:{ + audio:1, + trigger:{global:'useCardAfter'}, + filter:function(event,player){ + return event.card.name=='jiu'&&event.player!=player&&event.player.isPhaseUsing(); + }, + logTarget:'player', check:function(event,player){ return get.attitude(player,event.player)>0; }, - content:function(){ - trigger.player.addTempSkill('vtbyaoli_effect'); - trigger.player.addMark('vtbyaoli_effect',1,false); - }, - ai:{ - expose:0.15, - }, - subSkill:{ - effect:{ - audio:'vtbyaoli', - charlotte:true, - trigger:{player:'useCard2'}, - forced:true, - popup:false, - onremove:true, - nopop:true, - filter:function(event,player){ - return event.card.name=='sha'&&player.countMark('vtbyaoli_effect')>0; - }, - content:function(){ - 'step 0' - trigger.directHit.addArray(game.filterPlayer()); - var num=player.countMark('vtbyaoli_effect'); - if(!game.hasPlayer(current=>{ - return !trigger.targets.includes(current)&&lib.filter.targetEnabled2(trigger.card,player,current); - })) event.finish(); - else player.chooseTarget('媱丽:是否为'+get.translation(trigger.card)+'额外指定'+(num>1?'至多':'')+get.cnNumber(num)+'个目标?',num==1?1:[1,num],(card,player,target)=>{ - return !_status.event.sourcex.includes(target)&&player.canUse(_status.event.card,target); - }).set('sourcex',trigger.targets).set('ai',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('vtbyaoli_effect',event.targets); - trigger.targets.addArray(event.targets); - player.removeSkill('vtbyaoli_effect'); - }, - marktext:'媱', - intro:{ - content:'下一张【杀】不可被响应且可以额外指定&个目标', - }, - ai:{ - directHit_ai:true, - skillTagFilter:function(player,tag,arg){ - return arg.card.name=='sha'; - }, - } - } - } - }, + content:function(){ + trigger.player.addTempSkill('vtbyaoli_effect'); + trigger.player.addMark('vtbyaoli_effect',1,false); + }, + ai:{ + expose:0.15, + }, + subSkill:{ + effect:{ + audio:'vtbyaoli', + charlotte:true, + trigger:{player:'useCard2'}, + forced:true, + popup:false, + onremove:true, + nopop:true, + filter:function(event,player){ + return event.card.name=='sha'&&player.countMark('vtbyaoli_effect')>0; + }, + content:function(){ + 'step 0' + trigger.directHit.addArray(game.filterPlayer()); + var num=player.countMark('vtbyaoli_effect'); + if(!game.hasPlayer(current=>{ + return !trigger.targets.includes(current)&&lib.filter.targetEnabled2(trigger.card,player,current); + })) event.finish(); + else player.chooseTarget('媱丽:是否为'+get.translation(trigger.card)+'额外指定'+(num>1?'至多':'')+get.cnNumber(num)+'个目标?',num==1?1:[1,num],(card,player,target)=>{ + return !_status.event.sourcex.includes(target)&&player.canUse(_status.event.card,target); + }).set('sourcex',trigger.targets).set('ai',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('vtbyaoli_effect',event.targets); + trigger.targets.addArray(event.targets); + player.removeSkill('vtbyaoli_effect'); + }, + marktext:'媱', + intro:{ + content:'下一张【杀】不可被响应且可以额外指定&个目标', + }, + ai:{ + directHit_ai:true, + skillTagFilter:function(player,tag,arg){ + return arg.card.name=='sha'; + }, + } + } + } + }, //官盗S特015神马超 psshouli:{ audio:'shouli', @@ -598,16 +597,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(event.responded||event.psshouli||event.type=='wuxie') return false; if(game.hasPlayer(function(current){ return current.getEquips(4).length>0; - })&&event.filterCard({ + })&&event.filterCard(get.autoViewAs({ name:'sha', storage:{psshouli:true}, - },player,event)) return true; + },'unsure'),player,event)) return true; if(game.hasPlayer(function(current){ return current.getEquips(3).length>0; - })&&event.filterCard({ + })&&event.filterCard(get.autoViewAs({ name:'shan', storage:{psshouli:true}, - },player,event)) return true; + },'unsure'),player,event)) return true; return false; }, delay:false, @@ -1089,7 +1088,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(!player.countMark('pkwuku')||player.hasSkill('pkmiewu2')) return false; for(var i of lib.inpile){ var type=get.type(i); - if((type=='basic'||type=='trick')&&event.filterCard({name:i},player,event)) return true; + if((type=='basic'||type=='trick')&&event.filterCard(get.autoViewAs({name:i},'unsure'),player,event)) return true; } return false; }, @@ -1099,19 +1098,20 @@ game.import('character',function(lib,game,ui,get,ai,_status){ for(var i=0;i=2){ var list=[]; - if(lib.filter.cardUsable({name:'sha'},player,event.getParent('chooseToUse'))&&game.hasPlayer(function(current){ + if(lib.filter.cardUsable({name:'sha',isCard:true},player,event.getParent('chooseToUse'))&&game.hasPlayer(function(current){ return player.canUse('sha',current); })){ list.push(['基本','','sha']); } for(var i of lib.inpile_nature){ - if(lib.filter.cardUsable({name:'sha',nature:i},player,event.getParent('chooseToUse'))&&game.hasPlayer(function(current){ - return player.canUse({name:'sha',nature:i},current); + if(lib.filter.cardUsable({name:'sha',nature:i,isCard:true},player,event.getParent('chooseToUse'))&&game.hasPlayer(function(current){ + return player.canUse({name:'sha',nature:i,isCard:true},current); })){ list.push(['基本','','sha',i]); } } - if(lib.filter.cardUsable({name:'tao'},player,event.getParent('chooseToUse'))&&game.hasPlayer(function(current){ + if(lib.filter.cardUsable({name:'tao',isCard:true},player,event.getParent('chooseToUse'))&&game.hasPlayer(function(current){ return player.canUse('tao',current); })){ list.push(['基本','','tao']); } - if(lib.filter.cardUsable({name:'jiu'},player,event.getParent('chooseToUse'))&&game.hasPlayer(function(current){ + if(lib.filter.cardUsable({name:'jiu',isCard:true},player,event.getParent('chooseToUse'))&&game.hasPlayer(function(current){ return player.canUse('jiu',current); })){ list.push(['基本','','jiu']); @@ -4184,7 +4184,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(list.length){ player.chooseButton(['是否视为使用一张基本牌?',[list,'vcard']]).set('ai',function(button){ var player=_status.event.player; - var card={name:button.link[2],nature:button.link[3]}; + var card={name:button.link[2],nature:button.link[3],isCard:true}; if(card.name=='tao'){ if(player.hp==1||(player.hp==2&&!player.hasShan())||player.needsToDiscard()){ return 5; @@ -4221,7 +4221,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } 'step 1' if(result&&result.bool&&result.links[0]){ - var card={name:result.links[0][2],nature:result.links[0][3]}; + var card={name:result.links[0][2],nature:result.links[0][3],isCard:true}; player.chooseUseTarget(card,true); } }, @@ -4965,9 +4965,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){ else event.finish(); 'step 2' var skill=result.control; - player.addTempSkill(skill); - player.popup(skill,'wood'); - game.log(player,'获得了技能','#g【'+get.translation(skill)+'】'); + player.addTempSkills(skill); + // player.popup(skill,'wood'); + // game.log(player,'获得了技能','#g【'+get.translation(skill)+'】'); }, }, sphuangen:{ @@ -6095,10 +6095,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, mod:{ cardRespondable:function(card,player){ - if(card.name=='shan'&&get.suit(card)!='heart') return false; + if(card.name=='shan'){ + const suit=get.suit(card); + if(suit!='heart'&&suit!='unsure') return false; + } }, cardEnabled:function(card,player){ - if(card.name=='shan'&&get.suit(card)!='heart') return false; + if(card.name=='shan'){ + const suit=get.suit(card); + if(suit!='heart'&&suit!='unsure') return false; + } }, } }, @@ -6771,16 +6777,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){ vtbtaoyan_info:'回合开始时,你可以令至多两名其他角色摸一张牌并于游戏外获得一张【桃】(共五张且均为♥6)。', vtbyanli:'妍丽', vtbyanli_info:'每轮限一次。一名角色于你的回合外进入濒死状态时,你可以令其回复至1点体力,然后其摸一张牌。', - vtb_xiaole:'小乐', - vtbleyu:'乐虞', - vtbleyu_info:'一名角色的回合开始时,你可以弃置三张牌令其判定。若结果不为♥,其跳过本回合的出牌阶段。', - vtbyuanli:'媛丽', - vtbyuanli_info:'一名角色跳过出牌阶段后,你可以与一名其他角色各摸一张牌。', - vtb_xiaojiu:'小酒', - vtbmeiniang:'美酿', - vtbmeiniang_info:'其他角色的出牌阶段开始时,你可以令其视为使用一张无次数限制且不计入次数的【酒】。', - vtbyaoli:'媱丽', - vtbyaoli_info:'其他角色于其出牌阶段内使用【酒】后,你可以令其于本回合内使用的下一张【杀】不能被响应且可以额外指定一个目标。', + vtb_xiaole:'小乐', + vtbleyu:'乐虞', + vtbleyu_info:'一名角色的回合开始时,你可以弃置三张牌令其判定。若结果不为♥,其跳过本回合的出牌阶段。', + vtbyuanli:'媛丽', + vtbyuanli_info:'一名角色跳过出牌阶段后,你可以与一名其他角色各摸一张牌。', + vtb_xiaojiu:'小酒', + vtbmeiniang:'美酿', + vtbmeiniang_info:'其他角色的出牌阶段开始时,你可以令其视为使用一张无次数限制且不计入次数的【酒】。', + vtbyaoli:'媱丽', + vtbyaoli_info:'其他角色于其出牌阶段内使用【酒】后,你可以令其于本回合内使用的下一张【杀】不能被响应且可以额外指定一个目标。', old_machao:'J.SP马超', old_machao_prefix:'J.SP', jsp_caoren:'☆SP曹仁', @@ -6791,8 +6797,6 @@ game.import('character',function(lib,game,ui,get,ai,_status){ zhangliang_prefix:'SP', ol_xinxianying:'将辛宪英', ol_xinxianying_prefix:'将', - chendong:'战役篇陈武董袭', - chendong_prefix:'战役篇', jiangqing:'战役篇蒋钦', jiangqing_prefix:'战役篇', tianfeng:'战役篇田丰', diff --git a/character/old.js b/character/old.js index def28bd53..3da5443ee 100755 --- a/character/old.js +++ b/character/old.js @@ -499,7 +499,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } var next=target.insertPhase(); next._noTurnOver=true; - next.setContent(lib.skill.oldmingjian.phase); + next.phaseList=['phaseUse']; + //next.setContent(lib.skill.oldmingjian.phase); }, phase:function(){ 'step 0' @@ -527,10 +528,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(!player.countCards('hs')) return false; for(var i of lib.inpile){ var type=get.type(i); - if((type=='basic'||type=='trick')&&event.filterCard({name:i},player,event)) return true; + if((type=='basic'||type=='trick')&&event.filterCard(get.autoViewAs({name:i},'unsure'),player,event)) return true; if(i=='sha'){ for(var j of lib.inpile_nature){ - if(event.filterCard({name:i,nature:j},player,event)) return true; + if(event.filterCard(get.autoViewAs({name:i,nature:j},'unsure'),player,event)) return true; } } } @@ -540,20 +541,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){ dialog:function(event,player){ var list=[]; for(var i of lib.inpile){ - if(event.type!='phase') if(!event.filterCard({name:i},player,event)) continue; + if(event.type!='phase') if(!event.filterCard(get.autoViewAs({name:i},'unsure'),player,event)) continue; var type=get.type(i); if(type=='basic'||type=='trick') list.push([type,'',i]); if(i=='sha'){ - if(event.type!='phase') if(!event.filterCard({name:i,nature:j},player,event)) continue; + if(event.type!='phase') if(!event.filterCard(get.autoViewAs({name:i,nature:j},'unsure'),player,event)) continue; for(var j of lib.inpile_nature) list.push(['基本','','sha',j]); } } return ui.create.dialog('蛊惑',[list,'vcard']); }, - filter:function(button,player){ - var evt=_status.event.getParent(); - return evt.filterCard({name:button.link[2],nature:button.link[3]},player,evt); - }, check:function(button){ var player=_status.event.player; var order=Math.max(0,get.order(card)+1); diff --git a/character/onlyOL.js b/character/onlyOL.js index 4f4e7e6ba..1e7f5da6e 100644 --- a/character/onlyOL.js +++ b/character/onlyOL.js @@ -11,19 +11,279 @@ game.import('character',function(lib,game,ui,get,ai,_status){ ol_sb_guanyu:['male','shu',4,['olsbweilin','olsbduoshou']], ol_sb_taishici:['male','wu',4,['olsbdulie','olsbdouchan']], ol_gaoshun:['male','qun',4,['olxianzhen','decadejinjiu'],['die_audio:re_gaoshun']], + ol_sb_yuanshao:['male','qun',4,['olsbhetao','olsbshenli','olsbyufeng','olsbshishou'],['zhu']], }, characterSort:{ onlyOL:{ onlyOL_yijiang1:['ol_jianyong','ol_lingtong','ol_gaoshun'], onlyOL_yijiang2:['ol_caozhang'], - onlyOL_sb:['ol_sb_jiangwei','ol_sb_guanyu','ol_sb_taishici'], + onlyOL_sb:['ol_sb_jiangwei','ol_sb_guanyu','ol_sb_taishici','ol_sb_yuanshao'], }, }, characterIntro:{ }, characterReplace:{ }, + card:{ + sizhaojian:{ + derivation:'ol_sb_yuanshao', + fullskin:true, + type:'equip', + subtype:'equip1', + get destroy(){ + return !lib.card.sizhaojian.inShanShanFestival(); + }, + inShanShanFestival(){ + //闪闪节外离开装备区会销毁 + const date=new Date(); + return date.getMonth()+1==3&&date.getDate()>=2&&date.getDate()<=15; + }, + distance:{attackFrom:-1}, + ai:{basic:{equipValue:7}}, + skills:['olsbyufeng_sizhaojian'], + }, + }, skill:{ + //OL谋袁绍 + //真·四世三公——袁神,启动 + olsbhetao:{ + audio:2, + trigger:{global:'useCardToPlayered'}, + filter(event,player){ + return event.player!=player&&event.isFirstTarget&&event.targets.length>1&&player.countCards('he',card=>{ + if(get.position(card)=='h'&&_status.connectMode) return true; + return get.color(card)==get.color(event.card)&&lib.filter.cardDiscardable(card,player); + }); + }, + direct:true, + async content(event,trigger,player){ + const {result:{bool,cards,targets}}=await player.chooseCardTarget({ + prompt:get.prompt('olsbhetao'), + filterCard(card,player){ + return get.color(card)==get.color(get.event().getTrigger().card)&&lib.filter.cardDiscardable(card,player); + }, + position:'he', + filterTarget(card,player,target){ + return get.event().getTrigger().targets.includes(target); + }, + ai1(card){ + return 7.5-get.value(card); + }, + ai2(target){ + const player=get.event('player'),trigger=get.event().getTrigger(); + const att=get.attitude(player,target),eff=get.effect(target,trigger.card,trigger.player,player); + if(trigger.card.name=='tiesuo') return eff>0?0:get.sgn(att)*(2+get.sgn(att)); + const sum=trigger.targets.reduce((i,j)=>i+get.effect(j,trigger.card,trigger.player,player),0); + return get.sgn(att)*(eff*2-sum); + }, + }).set('prompt2','弃置一张'+get.translation(get.color(trigger.card))+'牌,令'+get.translation(trigger.card)+'改为对其中一个目标结算两次'); + if(bool){ + const target=targets[0]; + player.logSkill('olsbhetao',target); + player.discard(cards); + trigger.getParent().effectCount++; + trigger.getParent().excluded.addArray(game.filterPlayer(i=>trigger.targets.includes(i)&&target!=i)); + } + }, + ai:{threaten:3.5}, + global:'olsbhetao_ai', + subSkill:{ + ai:{ + effect:{ + player(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'; + }, + }, + }, + }, + }, + olsbshenli:{ + audio:2, + trigger:{player:'useCardToPlayered'}, + filter(event,player){ + if(!player.isPhaseUsing()||player.hasSkill('olsbshenli_used')) return false; + return event.card.name=='sha'&&game.hasPlayer(target=>{ + return !event.targets.includes(target)&&player.canUse(event.card,target,false); + })&&event.isFirstTarget; + }, + check(event,player){ + const targets=game.filterPlayer(target=>player.canUse(event.card,target,false)); + const num1=event.targets.reduce((sum,target)=>sum+get.effect(target,event.card,player,player),0); + const num2=targets.reduce((sum,target)=>sum+get.effect(target,event.card,player,player),0); + if(num2>=num1) return true; + let num=(event.baseDamage||1); + if(event.extraDamage) num+=event.extraDamage; + let extra_num=0; + for(const target of targets){ + if(target.mayHaveShan(player,'use',target.getCards('h',i=>{ + return i.hasGaintag('sha_notshan'); + }))&&!player.hasSkillTag('directHit_ai',true,{ + target:target, + card:event.card, + },true)){ + if(player.hasSkill('jueqing')||target.hasSkill('gangzhi')) extra_num--; + else if(target.hasSkillTag('filterDamage',null,{ + player:event.player, + card:event.card, + })) extra_num++; + } + else extra_num+=num; + } + const sum=targets.length+extra_num; + return num2+(sum>player.countCards('h')?Math.min(5,sum):0)+(sum>player.getHp()?num2:0)>=num1; + }, + async content(event,trigger,player){ + player.addTempSkill('olsbshenli_used','phaseUseAfter'); + trigger.getParent().targets.addArray(game.filterPlayer(target=>{ + return !trigger.targets.includes(target)&&player.canUse(trigger.card,target,false); + })); + player.when('useCardAfter').filter(evt=>evt==trigger.getParent()) + .then(()=>{ + const sum=player.getHistory('sourceDamage',evt=>evt.card&&evt.card==trigger.card).reduce((num,evt)=>{ + return num+evt.num; + },0); + const bool=(sum>player.countCards('h')),goon=(sum>player.getHp()); + if(bool) player.draw(Math.min(5,sum)); + if(goon){ + const targets=game.filterPlayer(target=>trigger.targets.includes(target)) + if(targets.length) player.useCard(trigger.card,targets,false); + } + }); + }, + ai:{threaten:3.5}, + subSkill:{used:{charlotte:true}}, + }, + olsbyufeng:{ + audio:1, + trigger:{ + global:'phaseBefore', + player:'enterGame', + }, + filter(event,player){ + const card=get.cardPile('sizhaojian','field')||game.createCard2('sizhaojian','diamond',6); + return (event.name!='phase'||game.phaseNumber==0)&&player.canEquip(card,true); + }, + forced:true, + locked:false, + async content(event,trigger,player){ + if(lib.card.sizhaojian.inShanShanFestival()){ + game.broadcastAll(()=>lib.inpile.add('sizhaojian')); + } + const card=get.cardPile('sizhaojian','field')||game.createCard2('sizhaojian','diamond',6); + if(get.owner(card)) get.owner(card).$give(card,player,false); + else{ + player.$gain2(card,false); + game.delayx(); + } + player.equip(card); + }, + subSkill:{ + sizhaojian:{ + equipSkill:true, + mod:{ + aiOrder(player,card,num){ + if(card.name=='sha'&&typeof get.number(card)=='number') return num+get.number(card)/114514; + }, + }, + trigger:{player:'useCardToPlayered'}, + filter(event,player){ + return event.card.name=='sha'&&typeof get.number(event.card)=='number'; + }, + forced:true, + locked:false, + logTarget:'target', + async content(event,trigger,player){ + const target=trigger.target; + target.addTempSkill('olsbyufeng_block'); + target.markAuto('olsbyufeng_block',[trigger.card]); + }, + }, + block:{ + mod:{ + cardEnabled(card,player){ + if(!player.storage.olsbyufeng_block) return; + const storage=player.getStorage('olsbyufeng_block'); + let evt=_status.event; + if(evt.name!='chooseToUse') evt=evt.getParent('chooseToUse'); + if(!evt||!evt.respondTo||!storage.includes(evt.respondTo[1])) return; + const num=get.number(card); + if(num!='unsure'&&typeof num=='number'&&num{ + if(target==player||target.group!='qun') return false; + const evt=event.getl(target); + return evt&&evt.player==target&&evt.es&&evt.es.length>0; + }); + }, + direct:true, + zhuSkill:true, + async content(event,trigger,player){ + const targets=game.filterPlayer(target=>{ + if(target==player||target.group!='qun') return false; + const evt=trigger.getl(target); + return evt&&evt.player==target&&evt.es&&evt.es.length>0; + }).sortBySeat(); + const card=get.cardPile('sizhaojian','field')||game.createCard2('sizhaojian','diamond',6); + for(const target of targets){ + const {result:{bool}}=await target.chooseBool(get.prompt('olsbshishou',player),'将'+get.translation(card)+'置入'+get.translation(player)+'的装备区中').set('choice',get.attitude(target,player)>0); + if(bool){ + target.logSkill('olsbshishou',player); + if(get.owner(card)) get.owner(card).$give(card,player,false); + else{ + player.$gain2(card,false); + game.delayx(); + } + player.equip(card); + break; + } + } + }, + ai:{combo:'olsbyufeng'}, + }, //界高顺 olxianzhen:{ audio:'rexianzhen', @@ -581,6 +841,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, }, }, + kunfenx:{ + audio:'kunfen', + audioname:['ol_sb_jiangwei'], + }, //界曹彰 oljiangchi:{ audio:'rejiangchi', @@ -771,10 +1035,25 @@ game.import('character',function(lib,game,ui,get,ai,_status){ ol_gaoshun_prefix:'OL界', olxianzhen:'陷阵', olxianzhen_info:'出牌阶段限一次,你可以与一名角色拼点。若你赢,本回合你无视该角色的防具且对其使用牌没有次数和距离限制,且当你使用【杀】或普通锦囊牌指定其他角色为唯一目标时可以令该角色也成为此牌的目标;若你没赢,本回合你不能对其使用【杀】且你的【杀】不计入手牌上限。', + ol_sb_yuanshao:'OL谋袁绍', + ol_sb_yuanshao_prefix:'OL谋', + olsbhetao:'合讨', + olsbhetao_info:'其他角色使用牌执行第一个目标后,若此牌指定的目标数大于1,则你可以弃置一张与此牌颜色相同的牌并令此牌改为对其中一名目标角色结算两次。', + olsbshenli:'神离', + olsbshenli_info:'出牌阶段限一次,当你使用【杀】指定目标后,你可以令所有可成为此牌目标的其他角色均成为此牌目标,此牌结算完毕后,若你因此牌造成的伤害值X:大于你的手牌数,你摸X张牌(至多摸五张);大于你的体力值,你令此牌额外结算一次。', + olsbyufeng:'玉锋', + olsbyufeng_sizhaojian:'思召剑', + olsbyufeng_block:'思召剑', + olsbyufeng_info:'游戏开始时,你将【思召剑】置入装备区。', + sizhaojian:'思召剑', + sizhaojian_info:'当你使用有点数的【杀】指定目标后,你令目标角色只能使用无点数或点数大于等于此【杀】的【闪】响应此牌。', + sizhaojian_append:'【思召剑】于闪闪节(3月2日-3月15日)外离开装备区后,销毁此牌', + olsbshishou:'士首', + olsbshishou_info:'主公技,其他群势力角色失去装备区的牌后,若你的装备区中没有武器牌,其可将【思召剑】置入你的装备区。', onlyOL_yijiang1:'OL专属·将1', onlyOL_yijiang2:'OL专属·将2', - onlyOL_sb:'OL专属·谋武将', + onlyOL_sb:'OL专属·上兵伐谋', }, }; }); diff --git a/character/rank.js b/character/rank.js index ba4d34c46..42662b99f 100644 --- a/character/rank.js +++ b/character/rank.js @@ -51,6 +51,7 @@ window.noname_character_rank={ ], ap:[ 'xia_guanyu', + 'ol_sb_yuanshao', 'gjqt_aruan', 'gjqt_cenying', 'gjqt_ouyangshaogong', @@ -134,6 +135,8 @@ window.noname_character_rank={ 'jsrg_guozhao', 'sb_caopi', 'xia_yuzhenzi', + 'dc_simashi', + 'dc_sb_simayi', ], a:[ 'star_caoren', @@ -367,6 +370,8 @@ window.noname_character_rank={ 'dc_lingcao', 'jsrg_zhugeliang', 'shen_lusu', + 'huzun', + 'star_zhangchunhua', ], am:[ 'bailingyun', @@ -673,6 +678,9 @@ window.noname_character_rank={ 'sb_xunyu', 'ol_sb_taishici', 'tianchou', + 'ol_sb_guanyu', + 'gongsunxiu', + 'dc_caoshuang', ], bp:[ 'xin_huojun', @@ -916,6 +924,9 @@ window.noname_character_rank={ 'tw_mayunlu', 'tw_hucheer', 'sp_lvfan', + 'lvfan', + 'cuimao', + 'liqueguosi', 're_chendeng', 'wuyan', 'wangyue', @@ -955,6 +966,7 @@ window.noname_character_rank={ 'dc_liuba', 'key_seira', 'lukai', + 'ol_lukai', 'niufu', 're_liufeng', 'huzhao', @@ -1028,6 +1040,7 @@ window.noname_character_rank={ 'jsrg_zhenji', 'junk_xuyou', 'sp_machao', + 'liupan', 'mengyou', 're_wenpin', 'yue_zhoufei', @@ -1053,9 +1066,11 @@ window.noname_character_rank={ 'jsrg_sunlubansunluyu', 'jsrg_weiwenzhugezhi', 'shen_xuzhu', + 'dc_jiangji', + 'dc_wangling', ], b:[ - 'ol_sb_guanyu', + 'junk_guanyu', 'liyi', 'diy_feishi', 'diy_liufu', @@ -1199,6 +1214,7 @@ window.noname_character_rank={ 'zumao', 'wenpin', 'zhangling', + 'guotu', 'caoshuang', 'fuwan', 'litong', @@ -1635,6 +1651,7 @@ window.noname_character_rank={ 'sb_yl_luzhi', ], d:[ + 'chendong', 'lvmeng', 'huaxiong', 'gongsunzan', @@ -1685,6 +1702,7 @@ window.noname_character_rank={ 'dc_sunce', 'xia_yuzhenzi', 'xia_guanyu', + 'ol_sb_yuanshao', 'swd_muyun', 'swd_zhaoyun', 'swd_septem', @@ -1870,6 +1888,7 @@ window.noname_character_rank={ 'caoxian', ], epic:[ + 'dc_caoshuang', 'tianchou', 'star_yuanshao', 'yue_xiaoqiao', @@ -2025,6 +2044,7 @@ window.noname_character_rank={ 'jin_xiahouhui', 'jin_simashi', 'zhangling', + 'guotu', 'ns_luyusheng', 'fanyufeng', 're_taoqian', @@ -2145,6 +2165,7 @@ window.noname_character_rank={ 'dc_sb_zhouyu', 'xia_shitao', 'bailingyun', + 'dc_sb_simayi', ], rare:[ 'zhugemengxue', @@ -2549,6 +2570,7 @@ window.noname_character_rank={ 'dc_wangchang', 'jin_zhouchu', 'lukai', + 'ol_lukai', 'caoxiancaohua', 'huzhao', 're_liufeng', @@ -2627,6 +2649,7 @@ window.noname_character_rank={ ], junk:[ 'ol_sb_guanyu', + 'junk_guanyu', 'sunshao', 'ol_guohuai', 'gongsunzan', diff --git a/character/refresh.js b/character/refresh.js index 498a65866..ed07c2251 100755 --- a/character/refresh.js +++ b/character/refresh.js @@ -6758,7 +6758,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ return Infinity; }, cardUsable:function(card,player){ - if(card.name=='sha'&&player.storage.xingongji2.includes(get.suit(card))) return Infinity; + if(card.name=='sha'){ + const suit = get.suit(card); + return suit === 'unsure' || player.storage.xingongji2.includes(suit); + } }, aiOrder:function(player,card,num){ if(get.name(card)=='sha'&&!player.storage.xingongji2.includes(get.suit(card))) return num+1; @@ -8347,7 +8350,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ return get.value(button.link,_status.event.getTrigger().target); }); } - if(draw) event.draw=true; + if(draw) event.draw=true; 'step 3' if(event.equip&&result.links&&result.links.length){ trigger.target.loseToDiscardpile(result.links); @@ -8523,7 +8526,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ player.discardPlayerCard(trigger.target,get.prompt('rejianchu',trigger.target)).set('ai',function(button){ if(!_status.event.att) return 0; if(get.position(button.link)=='e'){ - if(get.subtype(button.link)=='equip2') return 2*get.value(button.link); + if(get.subtype(button.link)=='equip2') return 2*get.value(button.link); return get.value(button.link); } return 1; @@ -8739,10 +8742,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, filter:function(event,player){ var filter=event.filterCard; - if(filter({name:'sha'},player,event)&&player.countCards('hs','shan')) return true; - if(filter({name:'shan'},player,event)&&player.countCards('hs','sha')) return true; - if(filter({name:'tao'},player,event)&&player.countCards('hs','jiu')) return true; - if(filter({name:'jiu'},player,event)&&player.countCards('hs','tao')) return true; + if(filter(get.autoViewAs({name:'sha'},'unsure'),player,event)&&player.countCards('hs','shan')) return true; + if(filter(get.autoViewAs({name:'shan'},'unsure'),player,event)&&player.countCards('hs','sha')) return true; + if(filter(get.autoViewAs({name:'tao'},'unsure'),player,event)&&player.countCards('hs','jiu')) return true; + if(filter(get.autoViewAs({name:'jiu'},'unsure'),player,event)&&player.countCards('hs','tao')) return true; return false; }, ai:{ @@ -8922,7 +8925,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ trigger:{source:'damageBegin1'}, forced:true, audio:'paoxiao', - audioname:['re_zhangfei','guanzhang','xiahouba'], + audioname:['re_zhangfei','guanzhang','xiahouba','re_guanzhang'], filter:function(event,player){ return event.card&&event.card.name=='sha'&&player.countMark('olpaoxiao2')>0; }, @@ -10822,10 +10825,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(!player.countCards('hs')||player.hasSkill('reguhuo_phase')) return false; for(var i of lib.inpile){ var type=get.type(i); - if((type=='basic'||type=='trick')&&event.filterCard({name:i},player,event)) return true; + if((type=='basic'||type=='trick')&&event.filterCard(get.autoViewAs({name:i},'unsure'),player,event)) return true; if(i=='sha'){ for(var j of lib.inpile_nature){ - if(event.filterCard({name:i,nature:j},player,event)) return true; + if(event.filterCard(get.autoViewAs({name:i,nature:j},'unsure'),player,event)) return true; } } } @@ -10845,7 +10848,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, filter:function(button,player){ var evt=_status.event.getParent(); - return evt.filterCard({name:button.link[2],nature:button.link[3]},player,evt); + return evt.filterCard(get.autoViewAs({name:button.link[2],nature:button.link[3]},'unsure'),player,evt); }, check:function(button){ var player=_status.event.player; @@ -12062,7 +12065,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } if(get.type(he[i])=='equip'){ var subtype=get.subtype(he[i]); - if(subtype=='equip3'||subtype=='equip4'){ + if(subtype=='equip3'||subtype=='equip4'||subtype=='equip6'){ num++; } } @@ -12078,7 +12081,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } if(get.type(he[i])=='equip'){ var subtype=get.subtype(he[i]); - if(subtype=='equip3'||subtype=='equip4'){ + if(subtype=='equip3'||subtype=='equip4'||subtype=='equip6'){ list.push(he[i]); } } @@ -13879,7 +13882,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(result.bool){ var card=result.cards[0]; if(get.position(card)=='d'){ - if(get.subtype(card)=='equip3'||get.subtype(card)=='equip4'){ + if(get.subtype(card)=='equip3'||get.subtype(card)=='equip4'||get.subtype(card)=='equip6'){ player.gain(card,player,'gain2'); } } @@ -13902,7 +13905,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(result.bool){ var card=result.cards[0]; if(get.position(card)=='d'){ - if(get.subtype(card)=='equip3'||get.subtype(card)=='equip4'){ + if(get.subtype(card)=='equip3'||get.subtype(card)=='equip4'||get.subtype(card)=='equip6'){ player.gain(card,player,'gain2'); } } diff --git a/character/sb.js b/character/sb.js index 6602f4aa7..0927c735a 100644 --- a/character/sb.js +++ b/character/sb.js @@ -828,7 +828,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ return name=='sha'&&player.countCards('hs'); }, filter:function(event,player){ - return event.filterCard({name:'sha'},player,event)||lib.inpile_nature.some(nature=>event.filterCard({name:'sha',nature:nature},player,event)); + return event.filterCard(get.autoViewAs({name:'sha'},'unsure'),player,event)||lib.inpile_nature.some(nature=>event.filterCard(get.autoViewAs({name:'sha',nature},'unsure'),player,event)); }, chooseButton:{ dialog:function(event,player){ @@ -904,7 +904,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(card.name=='sha'&&typeof player.storage.sbwusheng_effect[target.playerid]=='number') return true; }, cardUsableTarget:function(card,player,target){ - if(card.name=='sha'&&typeof player.storage.sbwusheng_effect[target.playerid]=='number') return true; + if(card.name!=='sha'||typeof player.storage.sbwusheng_effect[target.playerid]!=='number') return; + return player.storage.sbwusheng_effect[target.playerid]<3; }, playerEnabled:function(card,player,target){ if(card.name!='sha'||typeof player.storage.sbwusheng_effect[target.playerid]!='number') return; @@ -1140,7 +1141,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }); if(!target){ event.finish(); - return; + return; } event.target=target; player.logSkill('sbqicai_gain',target); @@ -1420,20 +1421,17 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, marktext:'破', intro:{ - markcount:function(storage,player){ - if(player.isUnderControl(true)) return storage[1].length; - return '?'; + markcount:function(storage){ + return storage[1].length; }, mark:function(dialog,content,player){ - if(player.isUnderControl(true)){ - const storage=player.getStorage('sbkanpo'); - const sum=storage[0]; - const names=storage[1]; - dialog.addText('剩余可记录'+sum+'次牌名'); - if(names.length){ - dialog.addText('已记录牌名:'); - dialog.addSmall([names,'vcard']); - } + const storage=player.getStorage('sbkanpo'); + const sum=storage[0]; + const names=storage[1]; + dialog.addText('剩余可记录'+sum+'次牌名'); + if(player.isUnderControl(true)&&names.length){ + dialog.addText('当前记录牌名:'); + dialog.addSmall([names,'vcard']); } }, }, @@ -1749,7 +1747,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ target.removeSkill(skills); num+=skills.length; }); - if(get.mode()=='versus'&&_status.mode=='two') num+=3; + if(get.mode()!='identity') num+=2; player.draw(num); }, }, @@ -3765,10 +3763,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(!marked&&name!='sha'&&name!='shan') continue; if(get.type(name)!='basic') continue; if(player.hasCard(lib.skill.sblongdan.getFilter(name,player),'hs')){ - if(event.filterCard({name:name},player,event)) return true; + 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({name:name,nature:nature},player,event)) return true; + if(event.filterCard(get.autoViewAs({name,nature},'unsure'),player,event)) return true; } } } @@ -3783,10 +3781,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(!marked&&name!='sha'&&name!='shan') continue; if(get.type(name)!='basic') continue; if(player.hasCard(lib.skill.sblongdan.getFilter(name,player),'hs')){ - if(event.filterCard({name:name},player,event)) list.push(['基本','',name]); + 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({name:name,nature:nature},player,event)) list.push(['基本','',name,nature]) + if(event.filterCard(get.autoViewAs({name,nature},'unsure'),player,event)) list.push(['基本','',name,nature]) } } } @@ -6675,8 +6673,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ sb_xiaoqiao:'谋小乔', sb_xiaoqiao_prefix:'谋', sbtianxiang:'天香', - sbtianxiang_info:'①出牌阶段限三次,你可以交给一名没有“天香”标记的其他角色一张红色牌,然后令其获得此牌花色的“天香”标记。②当你受到伤害时,你可以移去一名角色的“天香”标记,若此“天香”标记为:红桃,你防止此伤害,其受到伤害来源对其造成的1点伤害(若没有伤害来源则改为无来源伤害);方片,其交给你两张牌。③准备阶段,你移去场上所有的“天香”标记,然后摸等量的牌。', - sbtianxiang_info_versus_two:'①出牌阶段限三次,你可以交给一名没有“天香”标记的其他角色一张红色牌,然后令其获得此牌花色的“天香”标记。②当你受到伤害时,你可以移去一名角色的“天香”标记,若此“天香”标记为:红桃,你防止此伤害,其受到伤害来源对其造成的1点伤害(若没有伤害来源则改为无来源伤害);方片,其交给你两张牌。③准备阶段,你移去场上所有的“天香”标记,然后摸X张牌(X为移去的“天香”标记数+3)。', + sbtianxiang_info_identity:'①出牌阶段限三次,你可以交给一名没有“天香”标记的其他角色一张红色牌,然后令其获得此牌花色的“天香”标记。②当你受到伤害时,你可以移去一名角色的“天香”标记,若此“天香”标记为:红桃,你防止此伤害,其受到伤害来源对其造成的1点伤害(若没有伤害来源则改为无来源伤害);方片,其交给你两张牌。③准备阶段,你移去场上所有的“天香”标记,然后摸等量的牌。', + sbtianxiang_info:'①出牌阶段限三次,你可以交给一名没有“天香”标记的其他角色一张红色牌,然后令其获得此牌花色的“天香”标记。②当你受到伤害时,你可以移去一名角色的“天香”标记,若此“天香”标记为:红桃,你防止此伤害,其受到伤害来源对其造成的1点伤害(若没有伤害来源则改为无来源伤害);方片,其交给你两张牌。③准备阶段,你移去场上所有的“天香”标记,然后摸X张牌(X为移去的“天香”标记数+2)。', sb_sp_zhugeliang:'谋卧龙', sb_sp_zhugeliang_prefix:'谋', sb_zhugeliang:'谋诸葛亮', diff --git a/character/shenhua.js b/character/shenhua.js index 6d3d50e85..c42bdf4c1 100755 --- a/character/shenhua.js +++ b/character/shenhua.js @@ -150,7 +150,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ enable:'chooseToUse', filter:function(event,player){ if(!player.hasCard(card=>get.suit(card)=='club','sh')) return false; - return (event.type=='phase'||event.filterCard({name:'tiesuo'},player,event)); + return (event.type=='phase'||event.filterCard(get.autoViewAs({name:'tiesuo'},'unsure'),player,event)); }, position:'hs', filterCard:function(card,player,event){ @@ -816,24 +816,20 @@ game.import('character',function(lib,game,ui,get,ai,_status){ audio:2, enable:'phaseUse', filter:function(event,player){ - return player.storage.drlt_zhenrong&&player.storage.drlt_zhenrong.length>0; + return player.getExpansions('drlt_zhenrong').length>0; }, filterTarget:function(card,player,target){ return target.countDiscardableCards(player,'ej')>0; }, content:function(){ 'step 0' - player.chooseCardButton(player.storage.drlt_zhenrong,1,'请选择需要弃置的“荣”',true).ai=function(button){ + player.chooseCardButton(player.getExpansions('drlt_zhenrong'),1,'请选择需要弃置的“荣”',true).ai=function(button){ return 6-get.value(button.link); }; 'step 1' if(result.bool){ var cards=result.links; - for(var i=0;i=0) return false; + if(trigger.num=0) return false; if(trigger.num<2&&target.hp>trigger.num) return 6/Math.sqrt(num); if(target==get.zhu(player)) return 9; return 8/Math.sqrt(num); @@ -5780,7 +5780,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(!player.countMark('spwuku')||!player.countCards('hse')||player.hasSkill('spmiewu2')) return false; for(var i of lib.inpile){ var type=get.type2(i); - if((type=='basic'||type=='trick')&&event.filterCard({name:i},player,event)) return true; + if((type=='basic'||type=='trick')&&event.filterCard(get.autoViewAs({name:i},'unsure'),player,event)) return true; } return false; }, @@ -5790,19 +5790,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){ for(var i=0;i{ + 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)); + }, + 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)?'(仅能指定一个目标)':''); + }, + }, + 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; + }, + 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){ + if(!game.hasPlayer(target=>target!=player&&!event.targets.includes(target)&&lib.filter.targetEnabled2(event.card,player,target)&&lib.filter.targetInRange(event.card,player,target))) return false; + return get.color(event.card)=='black'&&(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(); + return target!=player&&!trigger.targets.includes(target)&&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 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); + trigger.targets.addArray(targets); + for(const target of targets){ + target.addSkill('olpijing_effect'); + target.markAuto('olpijing_effect',[player]); + await target.chooseToGive(player,'he',true,'披荆:交给'+get.translation(player)+'一张牌'); + } + } + else player.storage.counttrigger.olpijing--; + }, + mod:{ + aiOrder(player,card,num){ + if(!(card.name=='sha'||get.type(card)=='trick')||get.color(card)!='black') 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.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'); + } + } + }, + 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){ + 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((sum,evt)=>{ + return sum+evt.targets.length + },0),5); + if(targets.length&&player.getHistory('useCard',evt=>{ + return cards.some(card=>get.type2(card)==get.type2(evt.card)); + }).length&&num){ + 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, @@ -721,7 +1197,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 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),'he')); + 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; @@ -730,23 +1206,27 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 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),'he')).randomGet(); + 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('he',card=>{ + player.gain(target.getCards('h',card=>{ return lib.filter.canBeGained(card,target,player); }).randomGet(),target,'giveAuto'); } else{ - const {result:{bool,targets}}=await player.chooseTarget((card,player,target)=>{ + const filterTarget=(card,player,target)=>{ return target!=player&&!player.getStorage('olqingyuan').includes(target); - },true).set('prompt2','每回合限一次,当你以此法选择的角色获得牌后,你随机获得其中一名角色的一张牌') + },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); - }); - if(bool){ - const target=targets[0]; + }) + .forResult(); + if(result.bool){ + const target=result.targets[0]; player.line(target); game.log(player,'选择了',target); player.markAuto('olqingyuan',[target]); @@ -764,14 +1244,14 @@ game.import('character',function(lib,game,ui,get,ai,_status){ locked:false, enable:'chooseToUse', filterCard(card){ - return get.itemtype(card)=='card'&&card.hasGaintag('olchongshen'); + 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'))) return false; + if(!player.countCards('h',card=>card.hasGaintag('olchongshen')&&get.color(card)=='red')) return false; }, - prompt:'将本轮得到的牌当作【闪】使用', + prompt:'将本轮得到的红色牌当作【闪】使用', check(card){ return 7-get.value(card); }, @@ -779,7 +1259,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ order:2, respondShan:true, skillTagFilter(player,tag,arg){ - if(arg=='respond'||!player.countCards('h',card=>_status.connectMode||card.hasGaintag('olchongshen'))) return false; + if(arg=='respond'||!player.countCards('h',card=>_status.connectMode||card.hasGaintag('olchongshen')&&get.color(card)=='red')) return false; }, effect:{ target(card,player,target,current){ @@ -790,7 +1270,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ group:'olchongshen_mark', mod:{ aiValue(player,card,num){ - if(get.name(card)!='shan'&&(get.itemtype(card)=='card'&&!card.hasGaintag('olchongshen'))) return; + 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=()=>{ @@ -803,12 +1283,12 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 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; - }, + // 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){ @@ -1077,7 +1557,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 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._guanshi_temp=true; + 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); @@ -2774,7 +3254,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ filter:function(event,player){ if(event.responded||event.type=='wuxie'||event.olqifan||!lib.skill.olqifan.getNum()) return false; for(var i of lib.inpile){ - if(i!='wuxie'&&event.filterCard({name:i},player,event)) return true; + if(i!='wuxie'&&event.filterCard(get.autoViewAs({name:i},'unsure'),player,event)) return true; } return false; }, @@ -8274,13 +8754,13 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, filter:function(event,player){ if(event.type=='wuxie') return false; - if(!player.hasSkill('liangyuan_tao',null,null,false)&&event.filterCard({name:'tao'},player,event)&&game.hasPlayer(function(current){ + if(!player.hasSkill('liangyuan_tao',null,null,false)&&event.filterCard(get.autoViewAs({name:'tao'},'unsure'),player,event)&&game.hasPlayer(function(current){ var storage=current.getExpansions('huamu'); return storage.length>0&&storage.filter(function(i){ return get.color(i,false)=='red'; }).length>0; })) return true; - if(!player.hasSkill('liangyuan_jiu',null,null,false)&&event.filterCard({name:'jiu'},player,event)&&game.hasPlayer(function(current){ + if(!player.hasSkill('liangyuan_jiu',null,null,false)&&event.filterCard(get.autoViewAs({name:'jiu'},'unsure'),player,event)&&game.hasPlayer(function(current){ var storage=current.getExpansions('huamu'); return storage.length>0&&storage.filter(function(i){ return get.color(i,false)=='black'; @@ -8706,12 +9186,12 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(!bool) return false; for(var name of lib.inpile){ if(get.type(name)!='basic'||list.includes(name)) continue; - var card={name:name}; - if(event.filterCard(card,player,event)) return true; + var card={name}; + if(event.filterCard(get.autoViewAs(card,'unsure'),player,event)) return true; if(name=='sha'){ for(var nature of lib.inpile_nature){ card.nature=nature; - if(event.filterCard(card,player,event)) return true; + if(event.filterCard(get.autoViewAs(card,'unsure'),player,event)) return true; } } } @@ -8723,12 +9203,12 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var storage=player.getStorage('yilie_count'); for(var i of lib.inpile){ if(get.type(i)!='basic'||storage.includes(i)) continue; - var card={name:i,isCard:true}; - if(event.filterCard(card,player,event)) list.push(['基本','',i]); + var card={name:i}; + if(event.filterCard(get.autoViewAs(card,'unsure'),player,event)) list.push(['基本','',i]); if(i=='sha'){ for(var j of lib.inpile_nature){ card.nature=j; - if(event.filterCard(card,player,event)) list.push(['基本','',i,j]); + if(event.filterCard(get.autoViewAs(card,'unsure'),player,event)) list.push(['基本','',i,j]); } } } @@ -10564,7 +11044,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ content:function(){ var target=trigger.getParent().target; trigger.num=Math.max(1,target.getAllHistory('useCard',(evt)=>evt.card.name=='sha').length); - target.addTempSkill('juesheng',{player:'phaseAfter'}); + target.addTempSkills('juesheng',{player:'phaseAfter'}); }, }, }, @@ -12877,7 +13357,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 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},player,event)) return true; + if(get.type(i)=='basic'&&event.filterCard({name:i,isCard:true},player,event)) return true; } return false; }, @@ -12885,7 +13365,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ dialog:function(event,player){ var list=[]; for(var i of lib.inpile){ - if(get.type(i)=='basic'&&event.filterCard({name:i},player,event)){ + 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]); @@ -13868,6 +14348,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 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(); @@ -14957,21 +15438,6 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, } }, - xiongsuan:{ - audio:2, - }, - diancai:{ - audio:2, - }, - diaodu:{ - audio:2, - }, - zhengbi:{ - audio:2, - }, - fengying:{ - audio:2, - }, //新服曹笨 xinshanjia:{ group:["xinshanjia_count"], @@ -15289,7 +15755,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var target=trigger.player; var card=result.cards[0]; player.line(target,'green'); - target.addTempSkill('new_zhixi','phaseUseAfter'); + 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); @@ -16770,7 +17236,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ trigger:{global:'phaseEnd'}, forced:true, charlotte:true, - filter:function(event,player){ + 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; @@ -16779,10 +17245,13 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, logTarget:'player', content:function(){ - var num=player.getHistory('useSkill',function(evt){ - return evt.skill=='rehengjiang'&&evt.targets.includes(trigger.player); - }).length; - if(num>0) player.draw(num); + 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(); }, }, shuangren:{ @@ -17462,9 +17931,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){ skillAnimation:true, animationColor:'orange', forceunique:true, - //filter:function(event,player){ - // return player.storage.fanghun2>0; - //}, + 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); @@ -17663,7 +18132,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 'step 2' var map=event.result||result; if(map&&map.skills&&map.skills.length){ - player.addSkils(map.skills); + player.addSkills(map.skills); } game.broadcastAll(function(list){ game.expandSkills(list); @@ -17792,10 +18261,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ filter:function(event,player){ if(!player.storage.fanghun||player.storage.fanghun<=0) return false; var filter=event.filterCard; - if(filter({name:'sha'},player,event)&&player.countCards('hs','shan')) return true; - if(filter({name:'shan'},player,event)&&player.countCards('hs','sha')) return true; - if(filter({name:'tao'},player,event)&&player.countCards('hs','jiu')) return true; - if(filter({name:'jiu'},player, event)&&player.countCards('hs','tao')) return true; + if(filter(get.autoViewAs({name:'sha'},'unsure'),player,event)&&player.countCards('hs','shan')) return true; + if(filter(get.autoViewAs({name:'shan'},'unsure'),player,event)&&player.countCards('hs','sha')) return true; + if(filter(get.autoViewAs({name:'jiu'},'unsure'),player,event)&&player.countCards('hs','jiu')) return true; + if(filter(get.autoViewAs({name:'tao'},'unsure'),player, event)&&player.countCards('hs','tao')) return true; return false; }, onrespond:function(){return this.onuse.apply(this,arguments)}, @@ -21656,13 +22125,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, 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(){ + '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; @@ -21670,23 +22136,17 @@ game.import('character',function(lib,game,ui,get,ai,_status){ return false; }); } - else{ - event.forced=true; - } - "step 1" - if(event.forced||result.bool){ + else event._result={bool:true}; + 'step 1' + if(result.bool){ player.logSkill('kunfen'); player.loseHp(); } - else{ - event.finish(); - } - "step 2" + else event.finish(); + 'step 2' player.draw(2); }, - ai:{ - threaten:1.5 - } + ai:{threaten:1.5}, }, fengliang:{ skillAnimation:true, @@ -21710,6 +22170,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ player.recover(2-player.hp); } "step 2" + player.storage.kunfen=true; player.addSkills('oltiaoxin'); }, }, @@ -22703,10 +23164,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){ qiangwu3:{ mod:{ targetInRange:function(card,player){ - if(_status.currentPhase==player&&card.name=='sha'&&get.number(card)player.storage.qiangwu) return Infinity; + if (card.name == 'sha') { + const num = get.number(card); + if (num == 'unsure' || num > player.storage.qiangwu) return true; + } } }, trigger:{player:'useCard1'}, @@ -23728,7 +24195,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 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({name:i},player,event)) return true; + if(get.type(i)=='basic'&&event.filterCard(get.autoViewAs({name:i},'unsure'),player,event)) return true; } return false; }, @@ -24714,20 +25181,19 @@ game.import('character',function(lib,game,ui,get,ai,_status){ else trigger.player.discard(event.card); } }, - "xinfu_lingren":{ - usable:1, + xinfu_lingren:{ audio:2, trigger:{ player:"useCardToPlayered", }, - direct:true, filter:function(event,player){ if(event.getParent().triggeredTargets3.length>1) return false; - if(!player.isPhaseUsing()) 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, content:function(){ 'step 0' player.chooseTarget(get.prompt('xinfu_lingren'),'选择一名目标角色并猜测其手牌构成',function(card,player,target){ @@ -24874,6 +25340,22 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } }, }, + 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', @@ -25924,6 +26406,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ str+='然后若没有角色因此【杀】死亡,你移除本次被选择的项。'; return str; }, + olxuanzhu(player){ + if(player.storage.olxuanzhu) return '转换技,每回合限一次,你可以将一张牌称为“玄”置于武将牌上,然后视为使用:阴,任意基本牌;阳,任意普通锦囊牌(须指定目标且仅指定一个目标)。若此次置于武将牌上的“玄”:不为装备牌,你弃置一张牌;为装备牌,你将所有“玄”置入弃牌堆,然后摸等量的牌。'; + return '转换技,每回合限一次,你可以将一张牌称为“玄”置于武将牌上,然后视为使用:阴,任意基本牌;阳,任意普通锦囊牌(须指定目标且仅指定一个目标)。若此次置于武将牌上的“玄”:不为装备牌,你弃置一张牌;为装备牌,你将所有“玄”置入弃牌堆,然后摸等量的牌。'; + }, }, characterReplace:{ guanyinping:['guanyinping','old_guanyinping'], @@ -25987,10 +26473,11 @@ game.import('character',function(lib,game,ui,get,ai,_status){ zhugedan:['re_zhugedan','zhugedan'], zhangren:['jsrg_zhangren','zhangren'], wenqin:['ol_wenqin','pe_wenqin'], + lukai:['ol_lukai','lukai'], }, translate:{ "xinfu_lingren":"凌人", - "xinfu_lingren_info":"每回合限一次。当你于出牌阶段内使用带有「伤害」标签的基本牌或普通锦囊牌指定目标后,你可以猜测其中的一个目标的手牌中是否有基本牌,锦囊牌或装备牌。若你猜中的项目数:≥1,此牌对该角色的伤害+1;≥2,你摸两张牌;≥3,你获得技能〖奸雄〗和〖行殇〗直到你的下回合开始。", + "xinfu_lingren_info":"每回合限一次。当你使用带有「伤害」标签的基本牌或普通锦囊牌指定目标后,你可以猜测其中的一个目标的手牌中是否有基本牌,锦囊牌或装备牌。若你猜中的项目数:≥1,此牌对该角色的伤害+1;≥2,你摸两张牌;≥3,你获得技能〖奸雄〗和〖行殇〗直到你的下回合开始。", "lingren_adddamage":"凌人", "lingren_adddamage_info":"", "lingren_jianxiong":"奸雄", @@ -25998,7 +26485,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){ "lingren_xingshang":"行殇", "lingren_xingshang_info":"当有角色死亡后,你可以选择一项:1.回复1点体力。2.获得该角色的所有牌。", "xinfu_fujian":"伏间", - "xinfu_fujian_info":"锁定技,结束阶段开始时,你观看一名随机的其他角色的随机X张手牌。(X为场上手牌最少的角色的手牌数)", + "xinfu_fujian_info":"锁定技,结束阶段,你观看一名随机的其他角色的随机X张手牌。(X为场上手牌最少的角色的手牌数)", + fujian:'伏间', + fujian_info:'锁定技,准备阶段和结束阶段,你随机观看一名手牌数不为全场最多的其他角色的手牌。', xinfu_xionghuo:'凶镬', xinfu_xionghuo_info:'游戏开始时,你获得3个“暴戾”标记(标记上限为3)。出牌阶段,你可以交给一名其他角色一个“暴戾”标记。当你对有“暴戾”标记的其他角色造成伤害时,此伤害+1。有“暴戾”标记的其他角色的出牌阶段开始时,其移去所有“暴戾”标记并随机执行一项:1.受到1点火焰伤害且本回合不能对你使用【杀】;2.失去1点体力且本回合手牌上限-1;3.你随机获得其一张手牌和一张装备区的牌。', xinfu_shajue:'杀绝', @@ -26075,7 +26564,6 @@ game.import('character',function(lib,game,ui,get,ai,_status){ mifuren:'糜夫人', sp_dongzhuo:'SP董卓', sp_dongzhuo_prefix:'SP', - gz_chendong:'陈武董袭', gz_jiangfei:'蒋琬费祎', gz_jiangqing:'蒋钦', hetaihou:'何太后', @@ -26141,9 +26629,6 @@ game.import('character',function(lib,game,ui,get,ai,_status){ bianfuren:'卞夫人', ol_bianfuren:'卞夫人', shamoke:'沙摩柯', - lvfan:'吕范', - liqueguosi:'李傕郭汜', - cuimao:'崔琰毛玠', caoying:"曹婴", simahui:"司马徽", @@ -26241,16 +26726,6 @@ game.import('character',function(lib,game,ui,get,ai,_status){ wanwei_info:'当你因被其他角色获得或弃置而失去牌时,你可以改为自己选择失去的牌。', gzjili:'蒺藜', gzjili_info:'当你于一回合内使用或打出第X张牌时,你可以摸X张牌(X为你的攻击范围)。', - xiongsuan:'凶算', - xiongsuan_info:'限定技,出牌阶段,你可以弃置一张手牌并选择一名角色,对其造成1点伤害,然后你摸三张牌。若该角色有已发动的限定技,则你选择其中一个限定技。此回合结束后,视为该限定技未发动过。', - diaodu:"调度", - diaodu_info:"当你使用装备牌时,你可以摸一张牌;出牌阶段开始时,你可以获得一名其他角色装备区里的一张牌,然后你可以将此牌交给另一名角色。", - diancai:'典财', - diancai_info:'其他角色的出牌阶段结束时,若你于此阶段失去了X张或更多的牌,则你可以将手牌摸至体力上限。(X为你的体力值)', - zhengbi:'征辟', - zhengbi_info:'出牌阶段开始时,你可以选择一项:选择一名未受伤的其他角色,你对其使用的牌无距离限制且不计入使用次数直到回合结束;或将一张基本牌交给一名其他角色,然后其交给你一张非基本牌或两张基本牌。', - fengying:'奉迎', - fengying_info:'限定技,出牌阶段,你可以弃置所有手牌。若如此做,你可以令等量的角色将手牌摸至X张(X为其体力上限且至多为5)。然后,你结束出牌阶段,并在当前回合结束后进行一个新的回合。', qingzhong:'清忠', qingzhong_info:'出牌阶段开始时,你可以摸两张牌,若如此做,此阶段结束时,你与手牌数最少的角色交换手牌。', @@ -26310,7 +26785,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ rehengjiang:'横江', rehengjiang2:'横江', rehengjiang3:'横江', - rehengjiang_info:'当你受到1点伤害后,你可以令当前回合角色本回合的手牌上限-1。然后若其弃牌阶段内没有弃牌,则你摸X张牌(X为你本回合内对其发动过〖横江〗的次数)。', + rehengjiang_info:'当你受到1点伤害后,你可以令当前回合角色本回合的手牌上限-1。然后若其弃牌阶段内有/没有弃牌,则你摸一/X张牌(X为你本回合内对其发动过〖横江〗的次数)。', shuangren:'双刃', shuangren_info:'出牌阶段开始时,你可以与一名角色拼点。若你赢,你视为对其或与其势力相同的另一名角色使用一张【杀】(不计入出牌阶段的次数限制);若你没赢,你本回合内不能对其他角色使用牌。', xiashu:'下书', @@ -27213,9 +27688,23 @@ game.import('character',function(lib,game,ui,get,ai,_status){ olshandao_info:'出牌阶段限一次,你可以选择任意名角色,你选择这些角色的各一张牌,依次将这些牌放置到牌堆顶,然后你视为对这些角色使用【五谷丰登】,然后你视为对这些角色外的所有其他角色使用【万箭齐发】。', ol_hujinding:'胡金定', olqingyuan:'轻缘', - olqingyuan_info:'锁定技。①游戏开始时,或当你于本局游戏首次受到伤害后,你选择一名未以此法选择过的其他角色。②每回合限一次,你发动〖轻缘①〗选择过的角色得到牌后,你随机获得其中一名角色的随机一张牌。', + olqingyuan_info:'锁定技。①游戏开始时,或当你于本局游戏首次受到伤害后,你选择一名未以此法选择过的其他角色。②每回合限一次,你发动〖轻缘①〗选择过的角色得到牌后,你随机获得其中一名角色的随机一张手牌。', olchongshen:'重身', - olchongshen_info:'你可以将本轮得到的手牌当作【闪】使用,且这些牌不计入你的手牌上限。', + olchongshen_info:'你可以将本轮得到的红色手牌当作【闪】使用。', + guotu:'郭图', + olqushi:'趋势', + olqushi_info:'出牌阶段限一次,你可以摸一张牌,然后将一张手牌扣置于一名其他角色的武将牌上,称为“趋”。目标角色于其结束阶段移去武将牌上的所有“趋”,若其于本回合使用过与“趋”相同类别的牌,则你摸X张牌(X为其本回合使用牌指定过的目标数之和且至多为5)。', + olweijie:'诿解', + olweijie_info:'回合外每名角色的回合限一次,当你需要使用或打出一张基本牌时,你可以弃置距离为1的一名角色的一张手牌,若此牌牌名与你需要使用或打出的牌的牌名相同,则视为你使用或打出之。', + liupan:'刘磐', + olpijing:'披荆', + olpijing_info:'每回合限一次,当你使用黑色【杀】或黑色普通锦囊牌指定唯一目标后,你可以令至多X名其他角色成为此牌的额外目标并依次交给你一张牌(X为你已损失的体力值且X至少为1)。这些角色下次使用基本牌或普通锦囊牌指定唯一目标时,其可令你成为此牌的额外目标或摸一张牌。', + ol_lukai:'OL陆凯', + ol_lukai_prefix:'OL', + olxuanzhu:'玄注', + olxuanzhu_info:'转换技,每回合限一次,你可以将一张牌称为“玄”置于武将牌上,然后视为使用:阴,任意基本牌;阳,任意普通锦囊牌(须指定目标且仅指定一个目标)。若此次置于武将牌上的“玄”:不为装备牌,你弃置一张牌;为装备牌,你将所有“玄”置入弃牌堆,然后摸等量的牌。', + oljiane:'謇谔', + oljiane_info:'锁定技。①当你对其他角色使用的牌生效后,其本回合无法抵消牌。②当你抵消牌后,你本回合无法成为牌的目标。', sp_tianji:'天极·皇室宗亲', sp_sibi:'四弼·辅国文曲', diff --git a/character/sp2.js b/character/sp2.js index c2c617482..9d586d032 100644 --- a/character/sp2.js +++ b/character/sp2.js @@ -4,6 +4,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ name:'sp2', connect:true, character:{ + liqueguosi:['male','qun',4,['xiongsuan']], + star_zhangchunhua:['female','wei',3,['starliangyan','starminghui']], star_yuanshao:['male','qun',4,['starxiaoyan','starzongshi','starjiaowang','staraoshi'],['zhu']], star_dongzhuo:['male','qun',5,['starweilin','starzhangrong','starhaoshou'],['zhu']], star_yuanshu:['male','qun',4,['starcanxi','starpizhi','starzhonggu'],['zhu']], @@ -37,7 +39,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ xinping:['male','qun',3,['fuyuan','zhongjie','yongdi']], zhangning:['female','qun',3,['tianze','difa']], tongyuan:['male','qun',4,['chaofeng','chuanshu']], - sp_mifangfushiren:['male','shu',4,['dcmffengshi']], + sp_mifangfushiren:['male','shu',4,['fengshi']], re_nanhualaoxian:['male','qun',4,['gongxiu','jinghe']], dufuren:['female','wei',3,['yise','shunshi']], caoanmin:['male','wei',4,['xianwei']], @@ -96,7 +98,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, characterSort:{ sp2:{ - sp_whlw:["xurong","lijue","zhangji","fanchou","guosi","duanwei","liangxing","zhangheng",'tangji','niufu','dongxie'], + 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"], sp_zizouqi:["mangyachang","xugong","zhangchangpu"], @@ -111,12 +113,186 @@ game.import('character',function(lib,game,ui,get,ai,_status){ sp_xuzhou:['re_taoqian','caosong','zhangmiao','qiuliju'], sp_zhongyuan:['re_hucheer','re_zoushi','caoanmin','re_dongcheng'], sp_xiaohu:['haomeng','yanfuren','yanrou','dc_zhuling'], - sp_star:['star_caoren','star_yuanshu','star_dongzhuo','star_yuanshao'], + sp_star:['star_caoren','star_yuanshu','star_dongzhuo','star_yuanshao','star_zhangchunhua'], mini_qixian:['mp_liuling'], sp_decade:['caobuxing','re_maliang','dc_jikang'], } }, skill:{ + //李傕郭汜 + xiongsuan:{ + audio:2, + enable:'phaseUse', + filterTarget:true, + filterCard:lib.filter.cardDiscardable, + position:'h', + usable:1, + async content(event,trigger,player){ + const target=event.target; + await target.damage(); + await player.draw(3); + if(target!=player) await player.loseHp(); + }, + ai:{ + order:9, + result:{ + target(player,target){ + if(player.getHp()+player.countCards('hs',card=>player.canSaveCard(card,player))<=1) return 0; + const num=get.sgn(get.attitude(player,target)); + if(num*get.damageEffect(target,player,player)>0) return num*get.damageEffect(target,player,player); + if(target==player) return 0.00001; + return 0; + }, + }, + }, + }, + //张春华 + starliangyan:{ + audio:2, + enable:'phaseUse', + usable:1, + filterTarget:lib.filter.notMe, + chooseButton:{ + dialog(event,player){ + const name=get.translation(event.result.targets[0]); + const list=[ + '你摸一张牌,其弃置一张牌','你弃置一张牌,其摸一张牌', + '你摸两张牌,其弃置两张牌','你弃置两张牌,其摸两张牌' + ].map((item,i)=>[i,item]); + const dialog=ui.create.dialog( + `梁燕:请选择你与${name}要执行的选项`, + [list.slice(0,2),'tdnodes'], + [list.slice(2,4),'tdnodes'], + 'hidden' + ); + return dialog; + }, + filter(button,player){ + const link=button.link; + if(link%2===0) return true; + return player.countDiscardableCards(player,'he')>=(link+1)/2; + }, + check(button){ + const player=get.player(),target=get.event().getParent().result.targets[0]; + const link=button.link; + if(get.attitude(player,target)<=0&&link===2) return 100; + const ph=player.countCards('h'),th=target.countCards('h'); + if(link%2===0){ + const num=(link/2)+1; + if(ph+num===th-num) return 10; + } + else{ + const num=(link+1)/2; + if(ph-num===th+num) return 10; + } + return 5; + }, + backup(links){ + return { + audio:'starliangyan', + target:get.event().result.targets[0], + link:links[0], + filterTarget(card,player,target){ + return target===lib.skill.starliangyan_backup.target; + }, + selectTarget:-1, + async content(content,trigger,player){ + const target=lib.skill.starliangyan_backup.target; + const link=lib.skill.starliangyan_backup.link; + const num=link<=1?1:2; + const fn=['draw','chooseToDiscard']; + if(link%2===1) fn.reverse(); + await player[fn[0]](num,true,'he'); + await target[fn[1]](num,true,'he'); + if(player.countCards('h')===target.countCards('h')){ + const skipper=[player,target][link%2]; + skipper.skip('phaseDiscard'); + game.log(skipper,'跳过了下一个','#y弃牌阶段'); + } + } + }; + }, + prompt(links){ + return '点击“确定”以执行效果'; + }, + }, + subSkill:{ + backup:{}, + }, + ai:{ + order(item,player){ + if(!game.hasPlayer(current=>current!==player&&get.attitude(player,current)>0)&&game.hasPlayer(current=>get.attitude(player,current)<=0)) return 10; + if(game.hasPlayer(current=>{ + const del=player.countCards('h')-current.countCards('h'),toFind=[2,4].find(num=>Math.abs(del)===num); + if(toFind===4&&del<0&&get.attitude(player,current)<=0){ + return true; + } + return false; + })) return 10; + return 1; + }, + result:{ + target(player,target){ + const del=player.countCards('h')-target.countCards('h'),toFind=[2,4].find(num=>Math.abs(del)===num); + if(toFind){ + return -del*(get.attitude(player,target)*Math.min(3,target.countCards('h')))*toFind/10; + } + return -1; + }, + }, + }, + }, + starminghui:{ + audio:2, + trigger:{global:'phaseEnd'}, + filter(event,player){ + return player.isMinHandcard()||player.isMaxHandcard(); + }, + direct:true, + async content(event,trigger,player){ + let logged=false; + if(player.isMinHandcard()){ + const card=new lib.element.VCard({ + name:'sha', + }); + const result=await player.chooseUseTarget(`###${get.prompt('starminghui')}###视为使用一张无距离限制的【杀】`,card,false,'nodistance').set('logSkill','starminghui').forResult(); + if(result.bool) logged=true; + } + const num=player.countCards('h'); + if(player.isMaxHandcard()&&num>0){ + const maxNum=game.findPlayer(current=>{ + return !game.hasPlayer(current2=>{ + if(current2===player) return false; + return current2.countCards('h')>current.countCards('h'); + }); + }).countCards('h'); + const leastDiscardNum=num-maxNum+1; + const prompt=logged?`是否将手牌弃置至不为最多?`:get.prompt('starminghui'); + const next=player.chooseToDiscard(prompt,`弃置至少${get.cnNumber(leastDiscardNum)}张手牌,然后你令一名角色回复1点体力`) + .set('selectCard',[leastDiscardNum,Infinity]) + .set('goon',game.hasPlayer(current=>get.recoverEffect(current,get.player(),get.player()))) + .set('ai',card=>{ + if(!get.event('goon')) return 0; + if(get.tag(card,'recover')) return 0; + if(ui.selected.cards.length===get.event('selectCard')[0]-1) return 6.5-get.value(card); + return 4-get.value(card); + }); + if(!logged) next.set('logSkill','starminghui'); + const result=await next.forResult(); + if(!result.bool) return; + if(!player.isUnderControl(true)&&!player.isOnline()) await game.asyncDelayx(); + const [bool,targets]=await player.chooseTarget('令一名角色回复1点体力') + .set('ai',target=>get.recoverEffect(target,get.player(),get.player())) + .forResult('bool','targets'); + if(bool){ + const target=targets[0]; + player.line(target,'green'); + await target.recover(); + } + } + }, + + }, //星袁绍 starxiaoyan:{ audio:2, @@ -698,16 +874,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){ audio:2, enable:'chooseToUse', filter:function(event,player){ - if(!event.filterCard({name:'sha'},player,event)&&!event.filterCard({name:'wuxie'},player,event)) return false; - return player.countCards('hs',card=>{ - return !player.getStorage('starlifeng_count').includes(get.color(card,player))||_status.connectMode; - }); + if(!event.filterCard(get.autoViewAs({name:'sha'},'unsure'),player,event)&&!event.filterCard(get.autoViewAs({name:'wuxie'},'unsure'),player,event)) return false; + return player.hasCard(card=>{ + return !player.getStorage('starlifeng_count').includes(get.color(card,player)); + },'hs'); }, chooseButton:{ dialog:function(event,player){ var list=[]; - if(event.filterCard({name:'sha'},player,event)) list.push(['基本','','sha']); - if(event.filterCard({name:'wuxie'},player,event)) list.push(['锦囊','','wuxie']); + if(event.filterCard(get.autoViewAs({name:'sha'},'unsure'),player,event)) list.push(['基本','','sha']); + if(event.filterCard(get.autoViewAs({name:'wuxie'},'unsure'),player,event)) list.push(['锦囊','','wuxie']); return ui.create.dialog('砺锋',[list,'vcard']); }, check:function(button){ @@ -1390,10 +1566,12 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, mod:{ targetInRange:function(card,player){ - if(get.color(card)=='none') return true; + const color = get.color(card); + if (color === 'none' || color === 'unsure') return true; }, cardUsable:function(card){ - if(get.color(card)=='none') return Infinity; + const color = get.color(card); + if (color === 'none' || color === 'unsure') return Infinity; }, } }, @@ -1483,10 +1661,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(i!=skills.length-1) str+='、'; } game.log(target,'的技能','#g'+str,'失效了'); - game.log(player,'获得了技能','#g'+str); + // game.log(player,'获得了技能','#g'+str); player.popup(skills,'thunder'); for(var skill of skills){ - player.addTempSkill(skill,['phaseUseAfter','phaseAfter']); + player.addTempSkills(skill,['phaseUseAfter','phaseAfter']); } } } @@ -1569,10 +1747,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(i!=skills.length-1) str+='、'; } game.log(target,'的技能','#g'+str,'失效了'); - game.log(player,'获得了技能','#g'+str); + // game.log(player,'获得了技能','#g'+str); player.popup(skills,'thunder'); for(var skill of skills){ - player.addTempSkill(skill,['phaseUseAfter','phaseAfter']); + player.addTempSkills(skill,['phaseUseAfter','phaseAfter']); } } } @@ -3267,15 +3445,15 @@ game.import('character',function(lib,game,ui,get,ai,_status){ else{ switch(type){ case 'basic': - if(sha>0&&get.name(card)=='sha'){ + if(sha>0&&get.name(i)=='sha'){ sha--; var add=3; - if(!player.hasValueTarget(card)&&player.hasValueTarget(card,false)) add+=player.getUseValue(card,false); + if(!player.hasValueTarget(i)&&player.hasValueTarget(i,false)) add+=player.getUseValue(i,false); eff+=add; } break case 'trick': - if(player.hasValueTarget(card)) eff+=6; + if(player.hasValueTarget(i)) eff+=6; break; case 'equip': if(player.hasValueTarget({name:'guohe_copy2'})) eff+=player.getUseValue({name:'guohe_copy2'}); @@ -3292,15 +3470,15 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(type==control) continue; switch(type){ case 'basic': - if(sha>0&&get.name(card)=='sha'){ + if(sha>0&&get.name(i)=='sha'){ sha--; var add=3; - if(!player.hasValueTarget(card)&&player.hasValueTarget(card,false)) add+=player.getUseValue(card,false); + if(!player.hasValueTarget(i)&&player.hasValueTarget(i,false)) add+=player.getUseValue(i,false); eff+=add; } break case 'trick': - if(player.hasValueTarget(card)) eff+=6; + if(player.hasValueTarget(i)) eff+=6; break; case 'equip': if(player.hasValueTarget({name:'guohe_copy2'})) eff+=player.getUseValue({name:'guohe_copy2'}); @@ -6224,10 +6402,12 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } }, targetInRange:function(card){ - if(get.color(card)=='black') return true; + const color = get.color(card); + if (color === 'black' || color === 'unsure') return true; }, cardUsable:function(card){ - if(get.color(card)=='black') return Infinity; + const color = get.color(card); + if (color === 'black' || color === 'unsure') return Infinity; }, }, }, @@ -10577,6 +10757,72 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, }, //糜芳傅士仁 + fengshi:{ + audio:'mffengshi', + audioname:['sp_mifangfushiren'], + trigger:{player:'useCardToPlayered'}, + filter(event,player){ + if(!event.isFirstTarget) return false; + return event.targets.some(target=>{ + return player.countCards('h')>target.countCards('h')&&target.countCards('he')>0&&player.hasCard(card=>{ + return lib.filter.cardDiscardable(card,player,'fengshi'); + },'he'); + }); + }, + direct:true, + async content(event,trigger,player){ + const {result:{bool,targets}}=await player.chooseTarget(get.prompt('fengshi'),'弃置你与一名目标角色的各一张牌,然后令'+get.translation(event.card)+'对其造成的伤害+1',(card,player,target)=>{ + const targets=get.event().getTrigger().targets; + if(!targets.includes(target)) return false; + return player.countCards('h')>target.countCards('h')&&target.countCards('he')>0&&player.hasCard(card=>{ + return lib.filter.cardDiscardable(card,player,'fengshi'); + },'he'); + }).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); + }); + if(bool){ + const target=targets[0]; + player.logSkill('fengshi',target); + await player.chooseToDiscard('he',true); + await player.discardPlayerCard(target,'he',true); + if(get.tag(trigger.card,'damage')){ + var id=target.playerid; + var map=trigger.getParent().customArgs; + if(!map[id]) map[id]={}; + if(typeof map[id].extraDamage!='number') map[id].extraDamage=0; + map[id].extraDamage++; + } + } + }, + group:'fengshi_target', + subSkill:{ + target:{ + inherit:'dcmffengshi', + trigger:{target:'useCardToTargeted'}, + filter(event,player){ + if(event.player==event.target) return false; + return event.player.countCards('h')>player.countCards('h')&&event.player.countCards('he')>0&&player.hasCard(card=>{ + return lib.filter.cardDiscardable(card,player,'fengshi'); + },'he'); + }, + async content(event,trigger,player){ + const target=trigger.player; + await player.chooseToDiscard('he',true); + await player.discardPlayerCard(target,'he',true); + if(get.tag(trigger.card,'damage')){ + var id=player.playerid; + var map=trigger.getParent().customArgs; + if(!map[id]) map[id]={}; + if(typeof map[id].extraDamage!='number') map[id].extraDamage=0; + map[id].extraDamage++; + } + }, + }, + }, + }, dcmffengshi:{ audio:'mffengshi', audioname:['sp_mifangfushiren'], @@ -10602,7 +10848,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 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; + 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; } @@ -10793,7 +11039,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ dingyuan:['ol_dingyuan','dingyuan'], quyi:['quyi','re_quyi'], hansui:['hansui','re_hansui','xin_hansui','jsrg_hansui'], - jin_simashi:['jin_simashi','simashi'], + jin_simashi:['dc_simashi','jin_simashi','simashi'], jin_yanghuiyu:['jin_yanghuiyu','yanghuiyu'], taoqian:['re_taoqian','taoqian'], sp_liubei:['jsrg_liubei','sp_liubei'], @@ -11201,6 +11447,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ mffengshi_info:'当你使用牌指定唯一目标后,或成为其他角色使用牌的唯一目标后,若此牌使用者的手牌数大于此牌目标的手牌数,则此牌的使用者可令你弃置自己和对方的各一张牌,并令此牌的伤害值+1。', dcmffengshi:'锋势', dcmffengshi_info:'当你使用牌指定唯一目标后,或成为其他角色使用牌的唯一目标后,若此牌使用者的手牌数大于此牌目标的手牌数,则你可弃置自己和对方的各一张牌,并令此牌的伤害值+1。', + fengshi:'锋势', + fengshi_info:'当你使用牌指定第一个目标后,你可弃置你与其中一名手牌数小于你的目标角色的各一张牌,并令此牌对其造成的伤害+1;当你成为其他角色使用牌的目标后,若你的手牌数小于其,则你可以弃置你与其的各一张牌,并令此牌对你造成的伤害+1。', tongyuan:'童渊', chaofeng:'朝凤', chaofeng_info:'出牌阶段限一次。当你造成伤害时,你可以弃置一张牌,然后摸一张牌。若此伤害的渠道为牌且你弃置的牌:与此牌颜色相同,则你改为摸两张牌;与此牌类型相同,则此伤害+1。', @@ -11383,6 +11631,15 @@ game.import('character',function(lib,game,ui,get,ai,_status){ starjiaowang_info:'锁定技,非首轮游戏开始时,若上一轮没有角色死亡(因〖硝焰〗死亡的角色除外),则你失去1点体力并发动〖硝焰〗。', staraoshi:'傲势', staraoshi_info:'主公技,其他群势力角色的出牌阶段限一次,其可以交给你一张手牌,然后你可以发动一次〖纵势〗。', + star_zhangchunhua:'星张春华', + star_zhangchunhua_prefix:'星', + starliangyan:'梁燕', + starliangyan_info:'出牌阶段限一次。你可以选择一名其他角色,你摸/弃置至多两张牌,令其弃置/摸等量的牌。然后若你与其手牌数相同,以此法摸牌的角色跳过其下一个弃牌阶段。', + starminghui:'明慧', + starminghui_info:'一名角色的回合结束时,若你的手牌数:最少,你可以视为使用一张无距离限制的【杀】;最多,你可以将手牌弃置至你手牌数不为最多,然后令一名角色回复1点体力。', + liqueguosi:'李傕郭汜', + xiongsuan:'凶算', + xiongsuan_info:'出牌阶段限一次,你可以弃置一张手牌并对一名角色造成1点伤害,然后你摸三张牌。若该角色不为你,你失去1点体力。', sp_whlw:"文和乱武", sp_zlzy:"逐鹿中原", diff --git a/character/standard.js b/character/standard.js index a3524e995..128354334 100755 --- a/character/standard.js +++ b/character/standard.js @@ -224,7 +224,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(event.responded) return false; if(player.storage.hujiaing) return false; if(!player.hasZhuSkill('hujia')) return false; - if(!event.filterCard({name:'shan'},player,event)) return false; + if(!event.filterCard({name:'shan',isCard:true},player,event)) return false; return game.hasPlayer(current=>current!=player&¤t.group=='wei'); }, check(event,player){ @@ -2339,7 +2339,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ sp_zhangliao:['sp_zhangliao','yj_zhangliao','jsrg_zhangliao'], xiahoudun:['xiahoudun','re_xiahoudun','xin_xiahoudun'], liubei:['liubei','re_liubei','sb_liubei','dc_liubei','junk_liubei'], - guanyu:['guanyu','re_guanyu','ol_sb_guanyu','sb_guanyu','ps_guanyu','old_guanyu'], + guanyu:['guanyu','re_guanyu','ol_sb_guanyu','sb_guanyu','ps_guanyu','old_guanyu','junk_guanyu'], zhangfei:['zhangfei','re_zhangfei','old_zhangfei','xin_zhangfei','sb_zhangfei','tw_zhangfei','jsrg_zhangfei','yj_zhangfei'], zhaoyun:['zhaoyun','re_zhaoyun','old_zhaoyun','sb_zhaoyun','jsrg_zhaoyun','ps2063_zhaoyun','ps2067_zhaoyun'], sp_zhaoyun:['sp_zhaoyun','jsp_zhaoyun'], diff --git a/character/swd.js b/character/swd.js index affefb1ae..bec8cbafa 100644 --- a/character/swd.js +++ b/character/swd.js @@ -9768,7 +9768,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ gxianyin_info:'出牌阶段限一次,你可以选择一种花色,将你的手牌中该花色的牌移至弃牌堆,然后选择另一种花色,从牌堆中获得等量的该花色的牌。', // gxianyin_info_alter:'', cyxianjiang:'仙匠', - cyxianjiang_info:'每当你使用一张牌指定惟一目标时,你可以复制对方装备区内的一张你没有的牌,并置入你的装备区,每回合对一名角色最多发动一次。', + cyxianjiang_info:'每当你使用一张牌指定唯一目标时,你可以复制对方装备区内的一张你没有的牌,并置入你的装备区,每回合对一名角色最多发动一次。', cyqiaoxie:'巧械', cyqiaoxie_info:'每当你失去一张装备牌(使用除外),你可以随机观看三张机关牌,并使用其中一张。', cyqiaoxie_info_alter:'每当你装备一件装备,若你的手牌数不大于体力值,你可以摸一张牌;每当你失去一件装备牌,你可以随机观看2张机关牌,并使用其中一张。', @@ -9923,7 +9923,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ pingshen2:'凭神', pingshen_info:'锁定技,受到过你的伤害的角色可在回合内对你发动一次【离魂】(每局限发动一次)。', xingzhui:'星坠', - xingzhui_info:'出牌阶段限一次,你可以弃置一张牌,并令一名有牌的其他角色弃置一张类别相同的牌,若则受到1点伤害。', + xingzhui_info:'出牌阶段限一次,你可以弃置一张牌,并令一名有牌的其他角色弃置一张类别相同的牌,否则受到1点伤害。', lingxian:'凌仙', lingxian_info:'每当你于回合外使用或打出一张手牌,你可以选择攻击范围外的一名其他角色与你各摸一张牌。', shouyin:'守印', @@ -9965,7 +9965,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ xiaomoyu:'魔愈', xiaomoyu_info:'锁定技,每当你于一个回合内首次造成伤害,你回复1点体力,若你没有受伤,则改为摸一张牌。', yihua:'移花', - yihua_info:'每当你成为其他角色的某张卡牌的惟一目标时,你可以弃置两张手牌,将使用者与目标对调。', + yihua_info:'每当你成为其他角色的某张卡牌的唯一目标时,你可以弃置两张手牌,将使用者与目标对调。', youyin:'游吟', youyin_info:'每当有其他角色弃置卡牌时,若其中有非基本牌且你的手牌数不超过5,你可以摸一张牌。', rexue:'热血', diff --git a/character/tw.js b/character/tw.js index ae9c495fe..9d91e7fba 100644 --- a/character/tw.js +++ b/character/tw.js @@ -575,7 +575,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ target.addTempSkill(control,{player:'phaseAfter'}); target.addTempSkill('twhuajing_blocker',{player:'phaseAfter'}); target.getHistory('custom').push({twhuajing_skills:[control]}); - await player.draw(); + await player.draw(2); } } }, @@ -610,14 +610,15 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } return cards; }, - direct:true, + //direct:true, + frequent:true, async content(event,trigger,player){ const cards=lib.skill.twdengjian.getCards(player,trigger.player); - const {result:{bool}}=await player.chooseToDiscard(get.prompt('twdengjian'),'he') + /*const {result:{bool}}=await player.chooseToDiscard(get.prompt('twdengjian'),'he') .set('prompt2','弃置一张牌并随机获得本回合所有造成伤害的牌对应的实体牌的其中一张与你本轮以此法获得的牌的颜色均不同的【杀】') .set('ai',card=>7-get.value(card)) .set('logSkill','twdengjian'); - if(bool) player.gain(cards.randomGet(),'gain2').gaintag.add('twdengjianx'); + if(bool) */player.gain(cards.randomGet(),'gain2').gaintag.add('twdengjianx'); }, group:'twdengjian_buff', subSkill:{ @@ -898,7 +899,12 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, forced:true, async content(event,trigger,player){ - const num=player.getHistory('sourceDamage',evt=>evt.card&&evt.card==trigger.card).reduce((sum,evt)=>sum+evt.num,0); + //const num=player.getHistory('sourceDamage',evt=>evt.card&&evt.card==trigger.card).reduce((sum,evt)=>sum+evt.num,0); + const num=game.countPlayer2(target=>{ + return target.hasHistory('damage',evt=>{ + return evt.card&&evt.card==trigger.card; + }); + }); const num2=1+player.getAllHistory('custom',evt=>evt.twzhongyi).length; let choice=['摸牌'],choiceList=['摸'+get.cnNumber(num)+'张牌']; if(player.isDamaged()){ @@ -973,9 +979,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){ trigger:{global:'phaseEnd'}, filter(event,player){ const card=new lib.element.VCard({name:'sha'}); - return player.hasUseTarget(card)&&player.getHistory('useSkill',evt=>{ + return player.hasUseTarget(card)&&/*player.getHistory('useSkill',evt=>{ return evt.skill=='twchue_gain'; - }).length&&player.getHp()&&player.countMark('twchue')>=player.getHp(); + }).length&&player.getHp()&&*/player.countMark('twchue')>=player.getHp(); }, check(event,player){ return player.hasValueTarget(new lib.element.VCard({name:'sha'})); @@ -2031,7 +2037,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ filter(event,player){ if(!player.hasZhuSkill('twniju')) return false; if(event.iwhile||(event.target&&event.compareMeanwhile)) return false; - return true; + const participant=[event.player]; + if(event.targets) participant.addArray(event.targets); + else participant.add(event.target); + return participant.includes(player); }, direct:true, async content(event,trigger,player){ @@ -4334,7 +4343,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ player.awakenSkill('twmibei'); player.logSkill('twmibei_achieve'); game.log(player,'成功完成使命'); - player.addSkils('twmouli'); + player.addSkills('twmouli'); }, intro:{content:'已使用牌名:$'}, subSkill:{ @@ -4676,27 +4685,75 @@ game.import('character',function(lib,game,ui,get,ai,_status){ game.addVideo('delay',null,2); 'step 1' var list=['basic','trick','equip'].filter(type=>cards.some(card=>get.type2(card)==type)); + let fs=game.filterPlayer(i=>get.attitude(_status.event.player,i)>0).sort((a,b)=>{ + if(a===player){//尽量把player往前放 + if(a.hpget.attitude(_status.event.player,i)<0).sort((a,b)=>a.hp-b.hp), + types=list.map(type=>{ + let num=0; + for(let i of event.cards){ + if(get.type2(i)==type) num++; + } + return [type,num]; + }).sort((a,b)=>b[1]-a[1]); + event.tempCache={ + max:-Infinity, + tars:[] + }; + for(let idx=0;idx=type){//都分给敌人 + e=-type; + while(tempevent.tempCache.max){ + event.tempCache.type=types[idx][0]; + event.tempCache.max=e; + event.tempCache.tars=tars.slice(0); + delete event.tempCache.more; + } + } + if(fs.length*3>=type){//都分给队友 + tars=[]; + f=type-10/(2+fs[0].hp); + temp=type-Math.max(3,type);//让血厚的尽可能多拿 + if(temp){ + if(fs.length<3){ + tars.push(fs[1]); + if(temp>=3) f-=10/(2+fs[1].hp); + } + else{ + if(player!==fs[0]){ + tars.push(player); + temp-=Math.max(2,temp); + } + if(temp) tars.addArray(fs.filter(i=>fs[0]!==i&&player!==i).sort((a,b)=>{ + return get.attitude(_status.event.player,b)-get.attitude(_status.event.player,a); + }).slice(temp<3?-1:-2)); + } + } + if(f>event.tempCache.max){ + event.tempCache.type=types[idx][0]; + event.tempCache.max=f; + event.tempCache.more=fs[0]; + event.tempCache.tars=tars.slice(0); + } + } + } player.chooseControl(list).set('ai',function(){ - var listy=['basic','trick','equip'],listz=[0,0,0]; - var num=0,numx=0,num2=0,numx2=0; - for(var i of _status.event.getParent().cards){ - for(var j=0;j<2;j++){ - if(get.type2(i)==listy[j]) listz[j]++; - } - } - for(var k=0;k<2;k++){ - if(listz[k]>num){ - num=listz[k]; - numx=k; - } - if(listz[k]2) return listy[numx2]; - return listy[numx]; - }); + return _status.event.type; + }).set('type',event.tempCache.type); 'step 2' game.broadcastAll('closeDialog',event.videoId); event.cardsx=[]; @@ -4714,7 +4771,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 'step 3' if(event.cardsx.length>1){ player.chooseCardButton('兴乱:请选择要分配的牌',true,event.cardsx,[1,Math.min(3,event.cardsx.length)]).set('ai',function(button){ - if(ui.selected.buttons.length==0) return 1; + if(ui.selected.buttons.length==0) return get.buttonValue(button); return 0; }); } @@ -4733,18 +4790,25 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var togive=_status.event.getParent().togive; return (map[target.playerid]||[]).length+togive.length<=3; }).set('ai',function(target){ - var player=_status.event.player,att=get.attitude(player,target); - var map=_status.event.getParent().given_map; - var togive=_status.event.getParent().togive; - var num=(map[player.playerid]||[]).length,num2=(map[target.playerid]||[]).length; - var value=_status.event.value,eff=get.effect(target,{name:'losehp'},player,player); - if(num2+togive.length==num&&player!=target) return value*Math.sign(att)+eff+1000; - else{ - if(value<0) return -att+1000; - else if(att>0) return 1.5*att/(1+target.countCards('h'))+(player==target?eff/3:0)+1000; - else return att/100+1000; + let targets=_status.event.targets,att=get.attitude(_status.event.player,target); + if(targets.length){ + if(targets.includes(target)) return Math.max(1,att*_status.event.value); + return 0; } - }).set('value',cards.reduce((p,c)=>p+get.value(c,player,'raw'),0)); + return att*_status.event.value; + }).set('value',cards.reduce((p,c)=>p+get.value(c,player,'raw'),0)).set('more',event.tempCache.more).set('targets',function(){ + let arr=[],arr2=[]; + if(event.tempCache.more&&(event.given_map[event.tempCache.more.playerid]||[]).length+cards.length<=3) return [event.tempCache.more]; + for(let cur of event.tempCache.tars){ + let map=(event.given_map[cur.playerid]||[]).length; + if(map+cards.length<=3){ + if(map) arr2.push(cur); + else arr.push(cur); + } + } + if(arr.length) return arr; + return arr2; + }()); } 'step 5' if(result.bool){ @@ -6194,7 +6258,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, mod:{ cardUsable:function(card,player){ - if(card.name=='sha'&&player.getStorage('twgongji2').includes(get.suit(card))) return Infinity; + if(card.name=='sha'){ + const suit = get.suit(card); + return suit === 'unsure' || player.getStorage('twgongji2').includes(suit); + } }, aiOrder:function(player,card,num){ if(get.name(card)=='sha'&&!player.getStorage('twgongji2').includes(get.suit(card))) return num+1; @@ -6336,7 +6403,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ return !player.hasHistory('useSkill',function(evt){ return evt.skill=='twshuangren'; })&&!player.hasHistory('sourceDamage',function(evt){ - return evt.card.name=='sha'; + return evt.card&&evt.card.name=='sha'; }); }, direct:true, @@ -9484,8 +9551,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, filter:function(event,player){ const names=[]; - if(event.filterCard({name:'sha'},player,event)) names.push('shan'); - if(event.filterCard({name:'shan'},player,event)) names.push('sha'); + if(event.filterCard(get.autoViewAs({name:'sha'},'unsure'),player,event)) names.push('shan'); + if(event.filterCard(get.autoViewAs({name:'shan'},'unsure'),player,event)) names.push('sha'); return names.length>0&&player.hasCard(function(card){ return names.includes(get.name(card)); },'hs'); @@ -11229,10 +11296,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ for(var i of lib.inpile){ if(i=='wuxie') continue; var type=get.type(i); - if((type=='basic'||type=='trick')&&event.filterCard({name:i},player,event)) return true; + if((type=='basic'||type=='trick')&&event.filterCard({name:i,isCard:true},player,event)) return true; if(i=='sha'){ for(var j of lib.inpile_nature){ - if(event.filterCard({name:i,nature:j},player,event)) return true; + if(event.filterCard({name:i,nature:j,isCard:true},player,event)) return true; } } } @@ -13374,7 +13441,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ case 'equip2': target.draw(); break; - case 'equip3': case 'equip4': case 'equip5': + case 'equip3': case 'equip4': case 'equip5': case 'equip6': target.recover(); break; } @@ -13400,7 +13467,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var hp=player.hp,hs=player.countCards('h',(card)=>card!=ui.selected.cards[0]); var tp=target.hp,ts=target.countCards('h'); if(sub=='equip2') ts++; - if(tp{ - return i.hasGaintag('sha_notshan'); - }))||event.player.hasSkillTag('directHit_ai',true,{ - target:tar, - card:event.card, - },true)){ - if(!tar.hasSkill('gangzhi')) d1=false; - if(!tar.hasSkillTag('filterDamage',null,{ - player:event.player, + if(event.card.name=='sha'){ + if(!tar.mayHaveShan(player,'use',tar.getCards('h',i=>{ + return i.hasGaintag('sha_notshan'); + }))||event.player.hasSkillTag('directHit_ai',true,{ + target:tar, card:event.card, - })){ - let att=get.attitude(_status.event.player,tar); - if(att>0) return false; - if(att<0) e=true; + },true)){ + if(!tar.hasSkill('gangzhi')) d1=false; + if(!tar.hasSkillTag('filterDamage',null,{ + player:event.player, + card:event.card, + })){ + let att=get.attitude(_status.event.player,tar); + if(att>0) return false; + if(att<0) e=true; + } } } + else e=true; } if(e) return true; if(d1) return get.damageEffect(event.player,player,_status.event.player)>0; @@ -15338,7 +15408,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ tw_caocao:['tw_caocao','jsrg_caocao','yj_caocao'], mateng:['tw_mateng','mateng'], xiahouen:['tw_xiahouen','jsrg_xiahouen'], - jiangji:['tw_jiangji','jiangji'], + jiangji:['dc_jiangji','tw_jiangji','jiangji'], baoxin:['tw_baoxin','baoxin'], yanxiang:['yanxiang','tw_yanxiang'], liwei:['liwei','tw_liwei'], @@ -15367,7 +15437,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ return '转换技。阴:出牌阶段限一次。你可以弃置一张牌并对攻击范围内的一名角色造成1点伤害。阳:当你或你攻击范围内的一名角色于你的回合外受到伤害时,你可以弃置一张牌令此伤害-1。然后若你以此法弃置的牌颜色与“任”的颜色相同,你摸一张牌。'; }, twdengjian:function(player){ - let str='①其他角色的弃牌阶段结束时,你可以弃置一张牌并随机获得本回合所有造成伤害的牌对应的实体牌的其中一张与你本轮以此法获得的牌的颜色均不同的【杀】,称为“剑法”。'; + let str='①其他角色的弃牌阶段结束时,你可以随机获得本回合所有造成伤害的牌对应的实体牌的其中一张与你本轮以此法获得的牌的颜色均不同的【杀】,称为“剑法”。'; if(player.hasSkill('twdengjian_ban')) str=''+str+''; str+='②你使用“剑法”牌不计入次数限制。'; return str; @@ -15819,7 +15889,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ twkujian_info:'出牌阶段限一次。你可以将至多三张手牌交给一名其他角色,称为“谏”,你获得以下效果:当其他角色使用或打出牌后,若其中有“谏”,你与其各摸一张牌;当其他角色不因使用或打出而失去牌后,若其中有“谏”,你与其各弃置一张牌。', twruilian:'睿敛', twruilian2:'睿敛', - twruilian_info:'一轮游戏开始时,你可以选择一名角色。其下回合结束时,若其本回弃置过至少两张其的牌,你可以选择其本回合弃置过的一种类别,你与其各从弃牌堆中获得一张此类别的牌。', + twruilian_info:'一轮游戏开始时,你可以选择一名角色。其下回合结束时,若其本回合弃置过至少两张牌,你可以选择其本回合弃置过的一种类别,你与其各从弃牌堆中获得一张此类别的牌。', tw_xiahouen:'夏侯恩', twfujian:'负剑', twfujian_info:'锁定技。①游戏开始时或准备阶段,若你的装备区里没有武器牌,你随机将牌堆中的一张武器牌置入装备区。②当你于回合外失去武器牌后,你失去1点体力。', @@ -16011,9 +16081,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){ xia_guanyu:'侠关羽', xia_guanyu_prefix:'侠', twzhongyi:'忠义', - twzhongyi_info:'锁定技。①你使用【杀】无距离限制。②当你使用【杀】结算完毕后,你选择一项:⒈摸X张牌;⒉回复X点体力;⒊背水:失去Y点体力,依次执行以上两项(X为此牌造成的伤害值,Y为你本局游戏此前选择此项的次数+1)。', + twzhongyi_info:'锁定技。①你使用【杀】无距离限制。②当你使用【杀】结算完毕后,你选择一项:⒈摸X张牌;⒉回复X点体力;⒊背水:失去Y点体力,依次执行以上两项(X为受到此牌造成的伤害的角色数,Y为你本局游戏选择此项的次数)。', twchue:'除恶', - twchue_info:'①当你使用【杀】指定唯一目标时,你可以失去1点体力,为此牌额外指定Z个目标。②当你受到伤害或失去体力后,你摸一张牌并获得1个“勇”标记。③回合结束时,若你本回合发动过〖除恶②〗,则你可以失去Z个“勇”标记,视为使用一张伤害+1且可以额外指定Z个目标的【杀】。(Z为你的体力值)', + twchue_info:'①当你使用【杀】指定唯一目标时,若场上存在可称为此【杀】目标的非目标角色,则你可以失去1点体力,为此牌额外指定Z个目标。②当你受到伤害或失去体力后,你摸一张牌并获得1个“勇”标记。③回合结束时,若你的“勇”标记数大于等于Z,则你可以失去Z个“勇”标记,视为使用一张伤害+1且可以额外指定Z个目标的【杀】。(Z为你的体力值)', xia_shitao:'石韬', twjieqiu:'劫囚', twjieqiu_info:'出牌阶段限一次,你可以选择一名装备区没有废除栏的其他角色,废除其所有装备栏,然后其摸X张牌(X为其废除装备栏前的装备区牌数),直到其恢复所有装备栏前:其弃牌阶段结束时,其恢复等同于其弃置牌数的装备栏;其回合结束时,若其仍有已废除的装备栏,则你执行一个额外回合(每轮限一次)。', @@ -16022,7 +16092,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ xia_shie:'史阿', twdengjian:'登剑', twdengjianx:'剑法', - twdengjian_info:'①其他角色的弃牌阶段结束时,你可以弃置一张牌并随机获得本回合所有造成伤害的牌对应的实体牌的其中一张与你本轮以此法获得的牌的颜色均不同的【杀】,称为“剑法”。②你使用“剑法”牌不计入次数限制。', + twdengjian_info:'①其他角色的弃牌阶段结束时,你可以随机获得本回合所有造成伤害的牌对应的实体牌的其中一张与你本轮以此法获得的牌的颜色均不同的【杀】,称为“剑法”。②你使用“剑法”牌不计入次数限制。', twxinshou:'心授', twxinshou_info:'①当你于出牌阶段使用【杀】时,若此【杀】与你本回合使用的所有其他【杀】的颜色均不相同,则你可以选择执行以下一项本回合未执行过的项:⒈摸一张牌;⒉交给一名其他角色一张牌。②当你使用【杀】时,若〖心授①〗的两项本回合均已被你选择过,则你可以令〖登剑①〗失效并令一名其他角色获得〖登剑〗,你的下个回合开始时,其失去〖登剑〗,若其这期间使用【杀】造成过伤害,则你结束〖登剑①〗的失效状态。', xia_yuzhenzi:'玉真子', @@ -16041,7 +16111,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ twhuajing_gong:'弓', twhuajing_gong_info:'当你使用【杀】造成伤害后,你随机弃置受伤角色装备区里的一张牌。', twtianshou:'天授', - twtianshou_info:'锁定技,回合结束时,若你本回合使用【杀】造成过伤害,且你拥有本回合获得过效果的“武”标记,则你须将其中一个“武”标记交给一名其他角色并令其获得此标记的效果直到其回合结束,然后你摸一张牌。', + twtianshou_info:'锁定技,回合结束时,若你本回合使用【杀】造成过伤害,且你拥有本回合获得过效果的“武”标记,则你须将其中一个“武”标记交给一名其他角色并令其获得此标记的效果直到其回合结束,然后你摸两张牌。', tw_mobile:'海外服·稀有专属', tw_yunchouzhi:'运筹帷幄·智', diff --git a/character/xianding.js b/character/xianding.js index 8a7b023bc..904c79a7c 100644 --- a/character/xianding.js +++ b/character/xianding.js @@ -4,6 +4,11 @@ game.import('character',function(lib,game,ui,get,ai,_status){ name:'xianding', connect:true, character:{ + dc_sb_simayi:['male','wei',3,['dcsbquanmou','dcsbpingliao']], + chendong:['male','wu',4,['dcduanxie','fenming']], + lvfan:['male','wu',3,['diaodu','diancai']], + cuimao:['male','wei',3,['zhengbi','fengying']], + huzun:['male','wei',4,['dczhantao','dcanjing']], zhugemengxue:['female','wei',3,['dcjichun','dchanying']], bailingyun:['female','wei',3,['dclinghui','dcxiace','dcyuxin']], dc_qinghegongzhu:['female','wei',3,['dczhangji','dczengou']], @@ -95,24 +100,490 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, characterSort:{ xianding:{ - sp2_huben:['wangshuang','wenyang','re_liuzan','dc_huangzu','wulan','leitong','chentai','dc_duyu','dc_wangjun','dc_xiahouba','old_huangfusong'], + sp2_huben:['chendong','wangshuang','wenyang','re_liuzan','dc_huangzu','wulan','leitong','chentai','dc_duyu','dc_wangjun','dc_xiahouba','old_huangfusong','huzun'], 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'], + 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'], sp2_zhangtai:['guozhao','fanyufeng','ruanyu','yangwan','re_panshu'], sp2_jinse:['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'], sp2_doukou:['re_xinxianying','huaman','xuelingyun','dc_ruiji','duanqiaoxiao','tianshangyi','malingli','bailingyun'], - sp2_jichu:['zhaoang','dc_liuye','dc_wangyun','yanghong','huanfan','xizheng'], + sp2_jichu:['zhaoang','dc_liuye','dc_wangyun','yanghong','huanfan','xizheng','lvfan'], sp2_yuxiu:['dongguiren','dc_tengfanglan','zhangjinyun','zhoubuyi','dc_xujing'], sp2_qifu:['dc_guansuo','xin_baosanniang','dc_zhaoxiang'], sp2_gaoshan:['wanglang','liuhui','zhangjian'], sp2_wumiao:['wu_zhugeliang','wu_luxun'], - sp2_mouding:['dc_sb_lusu','dc_sb_zhouyu'], + sp2_mouding:['dc_sb_lusu','dc_sb_zhouyu','dc_sb_simayi'], } }, skill:{ + //谋司马懿 + dcsbquanmou:{ + audio:2, + zhuanhuanji:true, + marktext:'☯', + enable:'phaseUse', + filter(event,player){ + const selected=player.getStorage('dcsbquanmou_selected'); + return game.hasPlayer(current=>!selected.includes(current)&&player.inRange(current)&¤t.countCards('he')>0); + }, + filterTarget(card,player,target){ + if(player===target) return false; + const selected=player.getStorage('dcsbquanmou_selected'); + return !selected.includes(target)&&player.inRange(target)&&target.countCards('he')>0; + }, + prompt(){ + const player = get.player(); + if(player.storage.dcsbquanmou) return '转换技。出牌阶段每名角色限一次,你可以令一名攻击范围内的其他角色交给你一张牌。当你于本阶段内下次对其造成伤害后,你可以选择除其外的至多三名其他角色,对这些角色依次造成1点伤害。'; + return '转换技。出牌阶段每名角色限一次,你可以令一名攻击范围内的其他角色交给你一张牌。当你于本阶段内下次对其造成伤害时,取消之。'; + }, + async content(event,trigger,player){ + const target = event.targets[0]; + player.changeZhuanhuanji('dcsbquanmou'); + player.markAuto('dcsbquanmou_selected', [target]); + const cards = await target.chooseCard('he', true, `选择交给${get.translation(player)}一张牌`).forResultCards(); + if (cards && cards.length) { + await target.give(cards, player); + const key = `dcsbquanmou_${Boolean(!player.storage.dcsbquanmou)}`; + player.addTempSkill(key, {global:['phaseUseBefore','phaseChange']}); + player.markAuto(key, [target]); + target.addAdditionalSkill(`${key}_${player.playerid}`, `${key}_mark`); + } + }, + ai:{ + order:9, + result:{ + player:function(player,target){ + if(player.storage.dcsbquanmou) return 1; + return 1+game.countPlayer(i=>player!==i&&target!==i&&!i.hasSkill('false_mark')&&get.attitude(player,i)<0); + }, + target:function(player,target){ + let res=target.hasSkillTag('noh')?0:-1; + if(player.storage.dcsbquanmou) return res+0.6; + return res; + }, + }, + }, + onremove:true, + mark:true, + intro:{ + content:(storage)=>{ + if(storage) return '转换技。出牌阶段每名角色限一次,你可以令一名攻击范围内的其他角色交给你一张牌。当你于本阶段内下次对其造成伤害后,你可以选择除其外的至多三名其他角色,对这些角色依次造成1点伤害。'; + return '转换技。出牌阶段每名角色限一次,你可以令一名攻击范围内的其他角色交给你一张牌。当你于本阶段内下次对其造成伤害时,取消之。'; + } + }, + subSkill:{ + true:{ + audio:'dcsbquanmou', + charlotte:true, + trigger:{source:'damageSource'}, + forced:true, + popup:false, + filter(event,player){ + return player.getStorage('dcsbquanmou_true').includes(event.player); + }, + async content(event, trigger, player){ + const target = trigger.player; + player.getStorage('dcsbquanmou_true').remove(target); + target.removeAdditionalSkill(`dcsbquanmou_true_${player.playerid}`); + if(game.hasPlayer(current => (current != player && current != target))){ + const result = await player.chooseTarget([1,3], `权谋:是否对${get.translation(target)}之外的至多三名其他角色各造成1点伤害?`, (card, player, target)=>{ + return target != player && target != get.event().getTrigger().player; + }).set('ai',target => { + const player = get.player(); + return get.damageEffect(target, player, player); + }).forResult(); + if (result.bool) { + await player.logSkill('dcsbquanmou', result.targets); + for(let i of result.targets){ + if(i.isIn()) await i.damage(); + } + } + } + }, + onremove(player,skill){ + game.filterPlayer(current=>{ + current.removeAdditionalSkill(`${skill}_${player.playerid}`); + }); + delete player.storage[skill]; + delete player.storage.dcsbquanmou_selected; + }, + }, + true_mark:{ + charlotte:true, + mark:true, + marktext:'讨', + intro:{ + name:'权谋 - 阳', + content:()=>{ + return `当你下次受到${get.translation(_status.currentPhase)}造成的伤害后,其可以对除你之外的至多三名其他角色各造成1点伤害。` + }, + }, + ai:{ + threaten:2.5, + effect:{ + target(card,player,target){ + if(get.tag(card,'damage')&&player&&player.hasSkill('dcsbquanmou_true')){ + let tars=game.countPlayer(i=>player!==i&&target!==i&&get.attitude(player,target)<0&&!target.hasSkill('dcsbquanmou_false_mark')); + return [1,0,1,6*Math.min(3,tars)/(3+Math.pow(target.countCards('h'),2))]; + } + } + } + }, + }, + false:{ + audio:'dcsbquanmou', + charlotte:true, + trigger:{source:'damageBegin2'}, + forced:true, + filter(event,player){ + return player.getStorage('dcsbquanmou_false').includes(event.player); + }, + async content(event, trigger, player){ + const target = trigger.player; + player.getStorage('dcsbquanmou_false').remove(target); + target.removeAdditionalSkill(`dcsbquanmou_false_${player.playerid}`); + trigger.cancel(); + }, + onremove(player,skill){ + game.filterPlayer(current=>{ + current.removeAdditionalSkill(`${skill}_${player.playerid}`); + }); + delete player.storage[skill]; + delete player.storage.dcsbquanmou_selected; + }, + }, + false_mark:{ + charlotte:true, + mark:true, + marktext:'抚', + intro:{ + name:'权谋 - 阴', + content:()=>{ + return `当你下次受到${get.translation(_status.currentPhase)}造成的伤害时,防止此伤害。` + }, + }, + ai:{ + nodamage:true, + nofire:true, + nothunder:true, + skillTagFilter(player,tag,arg){ + return (arg&&arg.player&&arg.player.hasSkill('dcsbquanmou_false')); + }, + effect:{ + target(card,player,target){ + if(get.tag(card,'damage')&&player&&player.hasSkill('dcsbquanmou_false')) return 'zeroplayertarget'; + } + } + }, + }, + }, + }, + dcsbpingliao:{ + audio:2, + trigger:{player:'useCard0'}, + forced:true, + filter(event,player){ + return event.card.name=='sha'; + }, + logTarget(event,player){ + return game.filterPlayer(current=>player.inRange(current)); + }, + async content(event, trigger, player) { + trigger.hideTargets = true; + const unrespondedTargets = []; + const respondedTargets = []; + let nonnonTargetResponded = false; + const targets = game.filterPlayer().sortBySeat(); + const prompt = `###是否打出红色基本牌响应${get.translation(player)}?###${get.translation(player)}使用了一张不公开目标的${get.translation(trigger.card)}。若你选择响应且你不是此牌的隐藏目标,则其摸两张牌;若你选择不响应且你是此牌的隐藏目标,则你本回合内不能使用或打出手牌。` + for (let target of targets) { + if (target.isIn() && player.inRange(target)) { + const result = await target.chooseToRespond(prompt, (card,player)=>{ + if (get.type(card) !== 'basic') return false; + const color = get.color(card); + return (color == 'red' || color == 'unsure'); + }).set('ai',card => { + const player = get.player(), event = get.event(); + const source = event.getParent().player; + //是队友且没有其他疑似队友的选手响应 那响应一下 + if (get.attitude(player,source) > 0){ + if(!event.respondedTargets.some(current => { + return get.attitude(player, current) > 0 || get.attitude(source, current) >= 0; + })) return get.order(card); + return -1; + } + //先用随机数凑合一下 等157优化 + return event.getRand('dcsbpingliao') > 0.5 ? 0 : get.order(card); + }).set('respondedTargets', respondedTargets).forResult(); + if (result.bool) { + respondedTargets.push(target); + if(!trigger.targets.includes(target)) nonnonTargetResponded = true; + await game.asyncDelay(); + } + else if (trigger.targets.includes(target)) unrespondedTargets.push(target); + } + } + unrespondedTargets.forEach(current => { + current.addTempSkill('dcsbpingliao_blocker'); + game.log(current,'本回合内无法使用或打出手牌'); + }); + if (nonnonTargetResponded) { + player.draw(2); + player.addTempSkill('dcsbpingliao_buff', {global:'phaseChange'}); + player.addMark('dcsbpingliao_buff',1,false); + } + }, + ai:{ + ignoreLogAI:true, + skillTagFilter:function(player,tag,args){ + if(args){ + return args.card&&get.name(args.card)=='sha'; + } + }, + }, + subSkill:{ + buff:{ + onremove:true, + charlotte:true, + mod:{ + cardUsable(card, player, num){ + if(card.name=='sha') return num + player.countMark('dcsbpingliao_buff'); + } + }, + mark:true, + intro:{ + content:'本阶段内使用【杀】的次数上限+#', + }, + }, + blocker:{ + charlotte:true, + mod:{ + cardEnabled2(card, player){ + if(player.getCards('h').includes(card)) return false; + } + }, + mark:true, + marktext:'封', + intro:{ + content:'本回合内不能使用或打出手牌', + }, + }, + }, + }, + //陈武董袭 + dcduanxie:{ + audio:'duanxie', + inherit:'duanxie', + selectTarget:1, + }, + //吕范 + diaodu:{ + audio:2, + trigger:{player:['phaseUseBegin','logSkill']}, + filter(event,player){ + if(event.name=='logSkill'&&event.skill!='diancai') return false; + return game.hasPlayer(target=>{ + return get.distance(player,target)<=1&&target.countGainableCards(player,'e'); + }); + }, + direct:true, + async content(event,trigger,player){ + const {result:{bool,targets}}=await player.chooseTarget(get.prompt2('diaodu'),(card,player,target)=>{ + return get.distance(player,target)<=1&&target.countGainableCards(player,'e'); + }).set('ai',target=>{ + const player=get.event('player'),att=get.attitude(player,target); + let num=0; + if(target.hasSkill('gzxiaoji')) num+=2.5; + if(target.isDamaged()&&target.getEquip('baiyin')) num+=2.5; + if(target.hasSkill('xuanlve')) num+=2; + return get.sgn(att)*num+(target==player?1:0); + }); + if(bool){ + const aim=targets[0]; + player.logSkill('diaodu',aim); + const {result:{bool,cards}}=await player.gainPlayerCard(aim,'e',true); + if(bool&&game.hasPlayer(target=>target!=aim)){ + const card=cards[0]; + const {result:{bool,targets}}=await player.chooseTarget('调度:将'+get.translation(card)+'交给另一名角色',(card,player,target)=>{ + return target!=get.event('aim'); + },true).set('ai',target=>{ + const player=get.event('player'); + return get.attitude(player,target); + }).set('aim',aim); + if(bool&&get.owner(card)==player){ + const target=targets[0]; + player.line(target,'green'); + if(target!=player) await player.give([card],target); + if(get.owner(card)==target){ + const {result:{bool}}=await target.chooseUseTarget(card); + if(bool) await player.draw(); + else await target.draw(); + } + } + } + } + }, + }, + diancai:{ + audio:2, + inherit:'mbdiancai', + filter(event,player){ + if(_status.currentPhase===player) return false; + let num=player.getHistory('lose',evt=>{ + return evt.cards2&&evt.cards2.length&&evt.getParent('phaseUse')==event; + }).reduce((sum,evt)=>{ + return sum+evt.cards2.length; + },0); + return num>=Math.min(5,player.getHp()); + }, + }, + //崔琰毛玠 + zhengbi:{ + audio:2, + trigger:{player:'phaseUseBegin'}, + filter(event,player){ + return game.hasPlayer(target=>target!=player); + }, + direct:true, + async content(event,trigger,player){ + const {result:{bool,targets}}=await player.chooseTarget(get.prompt2('zhengbi'),lib.filter.notMe).set('ai',target=>{ + const player=get.event('player'); + return -get.attitude(player,target)*target.countCards('he'); + }); + if(bool){ + const target=targets[0],str=get.translation(target); + player.logSkill('zhengbi',target); + let choiceList=['此阶段结束时,若'+str+'本阶段获得过牌,则你获得其手牌区和装备区各一张牌']; + if(player.countCards('h',{type:'basic'})) choiceList.push('交给'+str+'一张基本牌,然后其交给你一张非基本牌或两张基本牌'); + const {result:{index}}=await player.chooseControl().set('choiceList',choiceList).set('ai',()=>get.event('controls').length-1); + if(index==0){ + player.line(target); + player.when('phaseUseEnd').filter(evt=>evt==trigger).then(()=>{ + if(target.isIn()&&target.getHistory('gain',evt=>evt.getParent('phaseUse')==trigger).length){ + player.line(target); + let num=(target.countGainableCards(player,'h')>0)+(target.countGainableCards(player,'e')>0); + if(num){ + player.gainPlayerCard(target,num,'he',true).set('filterButton',button=>{ + return !ui.selected.buttons.some(but=>get.position(button.link)==get.position(but.link)); + }); + } + } + }).vars({target:target}); + } + else{ + const {result:{bool}}=await player.chooseToGive(target,{type:'basic'},true).set('prompt','征辟:交给'+str+'一张基本牌'); + if(bool){ + let choices=[]; + if(target.countCards('he',{type:['trick','delay','equip']})) choices.push('一张非基本牌'); + if(target.countCards('h',{type:'basic'})>1) choices.push('两张基本牌'); + if(choices.length){ + const {result:{control}}=await target.chooseControl(choices).set('ai',function(event,player){ + if(choices.length>1){ + if(player.countCards('he',{type:['trick','delay','equip']},function(card){return get.value(card)<7})) return 0; + return 1; + } + return 0; + }).set('prompt','征辟:交给'+get.translation(player)+'…'); + const check=(control=='一张非基本牌'); + await target.chooseToGive('he',(check?1:2),{type:(check?['trick','delay','equip']:'basic')},player,true).set('prompt','征辟:交给'+get.translation(player)+control); + } + else if(target.countCards('h')) await target.give(target.getCards('h'),player); + } + } + } + }, + }, + fengying:{ + unique:true, + limited:true, + audio:2, + enable:'phaseUse', + filter(event,player){ + return player.countCards('h')&&player.countCards('h')==player.countDiscardableCards(player,'h'); + }, + skillAnimation:true, + animationColor:'thunder', + async content(event,trigger,player){ + player.awakenSkill('fengying'); + await player.discard(player.getCards('h')); + const evt=player.insertPhase(); + player.when('phaseBegin').filter(evtx=>evtx==evt).then(()=>{ + if(player.isMinHp()&&player.maxHp>0&&player.countCards('h')=0; + }, + logTarget:'player', + async content(event,trigger,player){ + player.judge(card=>{ + const evt=get.event().getParent(get.event('eventName')).getTrigger(); + if(!evt.source.isIn()||!evt.card||typeof get.number(evt.card)!=='number') return 0; + if(get.number(card)>get.number(evt.card)) return 1.5; + return 0; + }).set('judge2',r=>r.bool).set('callback',()=>{ + const evtx=event.getParent(); + const evt=event.getParent(evtx.eventName).getTrigger(); + if(!evt.source.isIn()||!evt.card||typeof get.number(evt.card)!=='number') return; + if(event.judgeResult.number>get.number(evt.card)){ + const sha=new lib.element.VCard({name:'sha'}),target=evt.source; + if(player.canUse(sha,target,false,false)){ + player.useCard(sha,target,false); + } + } + }) + .set('eventName',event.name) + } + }, + dcanjing:{ + audio:2, + trigger:{source:'damageSource'}, + filter(event,player){ + return game.hasPlayer(current=>current.isDamaged()); + }, + usable:1, + direct:true, + async content(event,trigger,player){ + const maxCount=player.getAllHistory('useSkill',evt=>evt.skill==='dcanjing').length+1; + const result=await player.chooseTarget(get.prompt2('dcanjing'),(card,player,target)=>target.isDamaged(),[1,maxCount]) + .set('ai',target=>{ + return get.attitude(get.player(),target)>0; + }) + .forResult(); + if(!result.bool) return player.storage.counttrigger.dcanjing--; + const targets=result.targets.slice(); + targets.sortBySeat(_status.currentPhase); + 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(); + for(const target of targets){ + if(!target.isIn()) continue; + if(target.getHp()===minHp) await target.recover(); + } + } + }, //诸葛梦雪 dcjichun:{ audio:2, @@ -213,7 +684,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ frequent:true, async content(event,trigger,player){ let cards=get.cards(3); - const {result:{bool,links}}=await player.chooseButton(['灵慧:是否使用其中的一张牌并随机获得其中一张剩余牌?',cards]).set('ai',button=>{ + await game.cardsGotoOrdering(cards); + const {result:{bool,links}}=await player.chooseButton(['灵慧:是否使用其中的一张牌并随机获得其中一张剩余牌?',cards]).set('filterButton',button=>{ + return get.player().hasUseTarget(button.link); + }).set('ai',button=>{ return get.event('player').getUseValue(button.link); }); if(bool){ @@ -222,14 +696,17 @@ game.import('character',function(lib,game,ui,get,ai,_status){ player.$gain2(card,false); await game.asyncDelayx(); await player.chooseUseTarget(true,card,false); - if(cards.length) await player.gain(cards.randomGet(),'gain2'); - } - if(cards.length){ - for(let i=cards.length-1;i--;i>=0){ - ui.cardPile.insertBefore(cards[i],ui.cardPile.firstChild); + cards=cards.filterInD(); + if(cards.length){ + const cardx=cards.randomRemove(); + await player.gain(cardx,'gain2'); } } - game.updateRoundNumber(); + if(cards.length){ + cards.reverse(); + game.cardsGotoPile(cards.filterInD(),'insert'); + game.log(player,'将',get.cnNumber(cards.length),'张牌置于了牌堆顶'); + } }, }, dcxiace:{ @@ -246,6 +723,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ })); return bool1||bool2; }, + direct:true, async content(event,trigger,player){ if(trigger.player==player&&!player.hasHistory('custom',evt=>evt.dcxiace=='player')&&game.hasPlayer(target=>target!=player&&!target.hasSkill('fengyin'))){ const {result:{bool,targets}}=await player.chooseTarget((card,player,target)=>{ @@ -296,6 +774,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ return lib.skill.luanfeng.check(event,player); }, logTarget:'player', + skillAnimation:true, + animationColor:'thunder', async content(event,trigger,player){ player.awakenSkill('dcyuxin'); trigger.player.recover((trigger.player==player?1:player.getHp())-trigger.player.hp); @@ -471,7 +951,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ return game.getGlobalHistory('cardMove',function(evt){ if(evt.name!='lose'||event!=evt.getParent()) return false; for(var i in evt.gaintag_map){ - if(evt.gaintag_map[i].includes('dclingxi')) return evt.player==player; + if(evt.gaintag_map[i].includes('dclingxi')&&evt.player==player) return true; } return false; }).length; @@ -3365,7 +3845,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var choices=['选项二']; var choiceList=[ '令'+get.translation(target)+'回复1点体力', - '你于'+get.translation(target)+'各摸一张牌' + '你与'+get.translation(target)+'各摸一张牌' ]; if(target.isDamaged()) choices.unshift('选项一'); else choiceList[0]=''+choiceList[0]+''; @@ -3454,7 +3934,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ })) return false; var storage=player.getStorage('dczhaowen_viewed'); for(var i of lib.inpile){ - if(!storage.includes(i)&&get.type(i)=='trick'&&event.filterCard({name:i},player,event)) return true; + if(!storage.includes(i)&&get.type(i)=='trick'&&event.filterCard(get.autoViewAs({name:i},'unsure'),player,event)) return true; } return false; }, @@ -3466,7 +3946,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ var storage=player.getStorage('dczhaowen_viewed'); var list=[]; for(var i of lib.inpile){ - if(!storage.includes(i)&&get.type(i)=='trick'&&event.filterCard({name:i},player,event)){ + if(!storage.includes(i)&&get.type(i)=='trick'&&event.filterCard(get.autoViewAs({name:i},'unsure'),player,event)){ list.push(['锦囊','',i]); } } @@ -6501,7 +6981,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(!storage.length) return false; var storage2=player.getStorage('dcfengying_used') return storage.some(name=>{ - return !storage2.includes(name)&&event.filterCard({name:name},player,event); + return !storage2.includes(name)&&event.filterCard(get.autoViewAs({name},'unsure'),player,event); }); }, hiddenCard:function(player,name){ @@ -6521,7 +7001,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ filter:function(button,player){ var card={name:button.link[2],storage:{dcfengying:true}}; if(player.getStorage('dcfengying_used').includes(card.name)) return false; - return _status.event.getParent().filterCard(card,player,_status.event.getParent()); + return _status.event.getParent().filterCard(get.autoViewAs(card,'unsure'),player,_status.event.getParent()); }, check:function(button){ var player=_status.event.player; @@ -12241,13 +12721,13 @@ game.import('character',function(lib,game,ui,get,ai,_status){ filter:function(button,player){ var evt=_status.event.getParent(); if(evt&&typeof evt.filterCard=='function') return evt.filterCard({name:button.link[2]},player,evt); - return lib.filter.filterCard({name:button.link[2]},player,_status.event.getParent()); + return lib.filter.filterCard({name:button.link[2],isCard:true},player,_status.event.getParent()); }, check:function(button){ var player=_status.event.player; if(player.countCards('h',button.link[2])) return 0; if(_status.event.getParent().type!='phase'&&!_status.event.getParent().lvli6) return 1; - return player.getUseValue({name:button.link[2]}); + return player.getUseValue({name:button.link[2],isCard:true}); }, backup:function(links,player){ return { @@ -12686,7 +13166,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(result.bool){ var target=result.targets[0]; player.line(target,'fire'); - player.addSkills(['hmxili'],['mansi']); + player.changeSkills(['hmxili'],['mansi']); target.addSkills('hmxili'); } }, @@ -12955,8 +13435,11 @@ game.import('character',function(lib,game,ui,get,ai,_status){ player.draw(); 'step 1' var next=player.chooseTarget().set('ai',function(target){ - var player=_status.event.player; - return get.damageEffect(target,player,player) + let player=_status.event.player; + if(target.hasSkillTag('filterDamage',null,{ + player:player + },true)) return get.damageEffect(target,player,player); + return 2*get.damageEffect(target,player,player); }); if(!['identity','guozhan'].includes(get.mode())){ next.set('prompt','选择一名体力值最大的敌方角色,对其造成2点伤害'); @@ -12984,9 +13467,19 @@ game.import('character',function(lib,game,ui,get,ai,_status){ ai:{ result:{ target:function(player,target){ - if(!['identity','guozhan'].includes(get.mode())) return 1; - var target=game.filterPlayer(i=>i!=player).sort((a,b)=>b.hp-a.hp)[0]; - return target&&get.damageEffect(target,player,player)>0?1:0; + let es; + if(['identity','guozhan'].includes(get.mode())) es=game.hasPlayer(i=>{ + return i!=player&&!game.hasPlayer(j=>{ + return player!==j&&j.hp>i.hp; + })&&get.attitude(player,i)<0; + }); + else es=game.hasPlayer(i=>{ + return i.isEnemyOf(player)&&!game.hasPlayer(j=>{ + return j.hp>i.hp&&j.isEnemyOf(player); + })&&get.attitude(player,i)<0; + }); + if(es) return 2; + return -1.5; }, }, order:12, @@ -12995,26 +13488,38 @@ game.import('character',function(lib,game,ui,get,ai,_status){ subSkill:{ dying:{ trigger:{global:'dying'}, - forced:true, - popup:false, filter:function(event,player){ - var evt=event.getParent(2); - if(!evt||evt.name!='kuiji_content'||evt.player!=player) return false; - var list=game.filterPlayer(function(current){ - return current.isFriendOf(player); - }).sort(function(a,b){ - return a.hp-b.hp; - }); - return (list.length==1||list[0].hp{ + return current!==trigger.player&&!game.hasPlayer(i=>{ + return trigger.player!==i&&i.hpi.isDamaged()); + else list=game.filterPlayer(current=>{ + return current.isFriendOf(player)&&!game.hasPlayer(i=>{ + return i.hpi.isDamaged()); + if(list.length>1) player.chooseTarget('溃击:选择一名角色回复1点体力',(card,player,target)=>{ + return _status.event.list.includes(target); + },true).set('list',list).set('ai',target=>{ + return get.recoverEffect(target,player,_status.event.player); + }); + else if(list.length) event._result={bool:true,targets:list}; + else event._result={bool:false}; + 'step 1' + if(result.bool){ + let target=result.targets[0]; + player.logSkill('kuiji',target); + target.recover(); + } }, }, }, @@ -13440,7 +13945,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }); if(card) cards2.push(card); } - player.addTempSkill(skill); + player.addTempSkills(skill); if(cards2.length) player.gain(cards2,'gain2','log'); }, }, @@ -13744,6 +14249,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, }, characterIntro:{ + cuimao:'请分别查看“崔琰”和“毛玠”的武将介绍。', bailingyun:'柏灵筠,女,是电视剧《大军师司马懿之军师联盟》、《虎啸龙吟》中的主要角色之一,由张钧甯饰演。20岁,是曹丕赏赐司马懿的美人,也是曹丕的眼线,被送入司马府中为妾室。柔弱美貌、心机极深。', caoxian:'曹宪(生卒年不详),女,沛国谯县(今安徽省亳州市)人。东汉末年历史人物,汉献帝刘协嫔妃,魏武帝曹操女儿。建安十八年,嫁给汉献帝刘协,受封为贵人。黄初元年(220年),兄弟曹丕称帝后,汉献帝成为山阳公,不知所终。', zhangjian:'张臶(136年-240年),字子明,钜鹿人。汉末三国时期隐士、音乐家,精通谶纬之学。张臶生活的年代从东汉一直到曹魏齐王时期,受到朝廷多次征召,一直回避,不愿做官。他活了一百零五岁,是三国时期有可靠记载的最长寿的人之一。', @@ -13797,6 +14303,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ zhugeruoxue:'诸葛氏(“若雪”为网络小说虚构),诸葛亮的二姐,庞山民之妻。', zhugemengxue:'诸葛氏(“梦雪”为网络小说虚构),诸葛亮的大姐。', caoyi:'曹轶,游卡桌游旗下产品《三国杀》原创角色。设定上为曹纯所收养的孙女,从小受到曹纯的教导,在军营中长大,性情坚毅有担当,军事谋略丰富,战斗能力超强。曹轶喜欢美食,特别是甜食,并且擅长制作各种点心。她身边跟随的雪白小老虎是曹纯在她及笄时送的生辰礼物,希望她如小老虎一样,英勇无畏。曹轶与曹婴交好,两人以姐妹相称。曹轶成年后继承祖父衣钵,接手精锐部队“虎豹骑”,成为新的虎豹骑的统领者。', + huzun:'胡遵(?~256年),安定临泾(今甘肃省镇原县)人,三国时期曹魏大臣,官至卫将军,封阴密侯。出身安定胡氏。历任征东将军、征东大将军、卫将军等职。早年由张既征辟。后追随司马懿,参与平定匈奴胡薄居姿职叛乱、抵御诸葛亮北伐、平定公孙渊叛乱。嘉平四年(252年),作为曹魏三征之一的征东将军,主持征讨东吴,被诸葛恪击败。正元元年(255年)参与平定淮南三叛的第二叛毌丘俭、文钦之乱,事后升任卫将军。甘露元年(256年)秋七月己卯去世,追赠车骑将军。', }, characterTitle:{ // wulan:'#b对决限定武将', @@ -13893,6 +14400,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(storage) str+=''; return str; }, + dcsbquanmou:function(player){ + if(player.storage.dcsbquanmou) return '转换技。出牌阶段每名角色限一次,你可以令一名攻击范围内的其他角色交给你一张牌。阴:当你于本阶段内下次对其造成伤害时,取消之;阳:当你于本阶段内下次对其造成伤害后,你可以选择除其外的至多三名其他角色,对这些角色依次造成1点伤害。'; + return '转换技。出牌阶段每名角色限一次,你可以令一名攻击范围内的其他角色交给你一张牌。阴:当你于本阶段内下次对其造成伤害时,取消之;阳:当你于本阶段内下次对其造成伤害后,你可以选择除其外的至多三名其他角色,对这些角色依次造成1点伤害。'; + } }, characterReplace:{ wenyang:['wenyang','db_wenyang','diy_wenyang'], @@ -14440,6 +14951,30 @@ game.import('character',function(lib,game,ui,get,ai,_status){ dcjichun_info:'出牌阶段限一次,你可以展示一张手牌并选择一项:①将此牌交给一名手牌数小于你的角色,然后摸X张牌。②弃置此牌并弃置一名手牌数大于你的角色区域里至多X张牌。(X为此牌牌名字数)', dchanying:'寒英', dchanying_info:'准备阶段,你可以展示牌堆里的一张非赠物装备牌,然后令一名手牌数等于你的角色使用此牌。', + huzun:'胡遵', + dczhantao:'斩涛', + dczhantao_info:'当你或你攻击范围内的角色受到伤害后,若你不为伤害来源,你可以判定,若造成此伤害的渠道为牌且此牌有点数且判定结果点数大于此牌的点数,你视为对来源使用一张【杀】。', + dcanjing:'安境', + dcanjing_info:'每回合限一次。当你造成伤害后,你可以令至多X名已受伤的角色各摸一张牌,然后其中体力值最少的角色回复1点体力(X为你本局游戏发动〖安境〗的次数)。', + cuimao:'崔琰毛玠', + zhengbi:'征辟', + zhengbi_info:'出牌阶段开始时,你可以选择一名其他角色并选择一项:①本阶段结束时,若其本阶段得到过牌,则你获得其手牌区和装备区各一张牌;②将一张基本牌交给该角色,然后其交给你一张非基本牌或两张基本牌。', + fengying:'奉迎', + fengying_info:'限定技,出牌阶段,你可以弃置所有手牌。若如此做,你于本回合结束后进行一个额外回合,此额外回合开始时,若你的体力值为全场最低,则你将手牌数摸至体力上限。', + lvfan:'吕范', + diaodu:'调度', + diaodu_info:'出牌阶段开始时,或当你发动〖典财〗后,你可以获得一名距离不大于1的一名角色A装备区里的一张牌,然后你将此牌交给另一名角色B,然后B选择是否使用此牌,若B使用/不使用,则你/B摸一张牌。', + diancai:'典财', + diancai_info:'其他角色的出牌阶段结束时,若你于此阶段失去了至少X张牌,则你可以将手牌摸至体力上限(X为你的体力值且X至多为5)。', + chendong:'陈武董袭', + dcduanxie:'断绁', + dcduanxie_info:'出牌阶段限一次,你可以令一名其他角色横置,然后你横置。', + dc_sb_simayi:'新杀谋司马懿', + dc_sb_simayi_prefix:'新杀谋', + dcsbquanmou:'权谋', + dcsbquanmou_info:'转换技。出牌阶段每名角色限一次,你可以令一名攻击范围内的其他角色交给你一张牌。阴:当你于本阶段内下次对其造成伤害时,取消之;阳:当你于本阶段内下次对其造成伤害后,你可以选择除其外的至多三名其他角色,对这些角色依次造成1点伤害。', + dcsbpingliao:'平辽', + dcsbpingliao_info:'锁定技。当你声明使用【杀】时,你令此【杀】的目标对其他角色不可见,且你令攻击范围内的其他角色依次选择是否打出一张红色基本牌。所有角色选择完成后,此牌的目标角色中没有以此法打出牌的角色本回合内无法使用或打出手牌;若有不为此牌目标的角色以此法打出了牌,则你摸两张牌,且你本回合使用【杀】的次数上限+1。', sp2_yinyu:'隐山之玉', sp2_huben:'百战虎贲', diff --git a/character/xianjian.js b/character/xianjian.js index e18fcdddc..e4aca3408 100644 --- a/character/xianjian.js +++ b/character/xianjian.js @@ -4194,8 +4194,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ chengxin2_bg:'心', chengxin_info:'每四轮限一次,当一名角色进入濒死状态时,你可以令其将体力值回复至1,然后该角色防止一切伤害直到下一回合结束。', tianwu:'天舞', - tianwu_info:'每当你使用卡牌指定一名敌方角色为惟一目标,你可以对其施加一个随机的负面效果。', - tianwu_info_alter:'每当你使用卡牌指定一名敌方角色为惟一目标,你可以对其施加一个随机的负面效果,每回合限发动一次。', + tianwu_info:'每当你使用卡牌指定一名敌方角色为唯一目标,你可以对其施加一个随机的负面效果。', + tianwu_info_alter:'每当你使用卡牌指定一名敌方角色为唯一目标,你可以对其施加一个随机的负面效果,每回合限发动一次。', liguang:'离光', liguang_info:'结束阶段,你可以弃置一张手牌并将场上的一张牌移动到另一个合理的位置。', shiying:'逝影', @@ -4342,8 +4342,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ longxi2:'龙息', longxi_info:'锁定技,在回合外每当你需要使用或打出一张卡牌时,若牌堆顶的前两张中有可使用或打出的牌,你立即获得之。', zhuyue:'逐月', - zhuyue_info:'出牌阶段限一次,你可以弃置一张非基本牌并指定至多两个目标各随机弃置一张牌,若如此做,你本回使用的杀须指定选中角色为目标。', - zhuyue_info_alter:'出牌阶段限一次,你可以弃置一张黑色非基本牌并指定至多两个目标各随机弃置一张牌,若如此做,你本回使用的杀须指定选中角色为目标。', + zhuyue_info:'出牌阶段限一次,你可以弃置一张非基本牌并指定至多两个目标各随机弃置一张牌,若如此做,你本回合使用的杀须指定选中角色为目标。', + zhuyue_info_alter:'出牌阶段限一次,你可以弃置一张黑色非基本牌并指定至多两个目标各随机弃置一张牌,若如此做,你本回合使用的杀须指定选中角色为目标。', guanri:'贯日', guanri_info:'限制技,你可以弃置两张红色手牌并失去1点体力,然后对一名体力值不少于你的其他角色造成2点火焰伤害并弃置其所有装备牌。', tianxian:'天弦', diff --git a/character/xinghuoliaoyuan.js b/character/xinghuoliaoyuan.js index 684e8addc..da72301b6 100755 --- a/character/xinghuoliaoyuan.js +++ b/character/xinghuoliaoyuan.js @@ -1490,9 +1490,46 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, "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; @@ -1506,7 +1543,22 @@ game.import('character',function(lib,game,ui,get,ai,_status){ presha:true, pretao:true, threaten:1.8, - }, + effect: { + player(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:{ @@ -1518,11 +1570,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){ cardUsableTarget:function(card,player,target){ if(player.countCards('j')&&player.inRange(target)) return true; }, - aiValue:function(player,card,num){ - if(card.name=='zhangba') return 15; - if(player.getEquip('zhangba')&&player.countCards('hs')>1&&['shan','tao'].includes(card.name)) return 0; - if(card.name=='shan'||card.name=='tao') return num/2; - }, + aiOrder(player, card, num) { + if (get.type(card, 'delay') && player.canUse(card, player) && player.canAddJudge(card)) return 15; + } }, locked:false, audio:2, @@ -1542,21 +1592,22 @@ game.import('character',function(lib,game,ui,get,ai,_status){ filterTarget:function (card,player,target){ return player==target; }, - check:function(card){ - var player=_status.event.player; - if(!player.getEquip('zhangba')&&player.countCards('hs','sha')<2){ - if(player.countCards('h',function(cardx){ - return cardx!=card&&cardx.name=='shan'; - })>0) return 0; - var damaged=player.maxHp-player.hp-1; - var ts=player.countCards('h',function(cardx){ - return cardx!=card&&cardx.name=='tao'; - }); - if(ts>0&&ts>damaged) return 0; + 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') return 10; - return 9-get.value(card); + 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()); @@ -1564,10 +1615,29 @@ game.import('character',function(lib,game,ui,get,ai,_status){ next.setContent(function(){player.recover()}); }, ai:{ - result:{ - target:1, + 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:12, + 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]; + } + } + } }, }, }, diff --git a/character/yijiang.js b/character/yijiang.js index ae80bebf0..83c9ca693 100755 --- a/character/yijiang.js +++ b/character/yijiang.js @@ -654,7 +654,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ content:function(){ 'step 0' player.addTempSkill('shiming_round','roundStart'); - var cards=get.cards(2); + 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; @@ -713,6 +713,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ player.logSkill('jiangxi'); event.logged=true; player.removeSkill('shiming_round'); + player.draw(); } 'step 2' if(!game.hasPlayer2(current=>current.getHistory('damage').length>0)){ @@ -1504,8 +1505,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ unlimit:{ mod:{ cardUsable:function(card,player){ - var list=lib.skill.lkbushi.getBushi(player); - if(list[0]==get.suit(card)) return Infinity; + const list = lib.skill.lkbushi.getBushi(player), suit = get.suit(card); + if (suit === 'unsure' || list[0] === suit) return Infinity; }, }, trigger:{player:'useCard1'}, @@ -2029,8 +2030,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 'step 2' player.gain(cards,'gain2'); if(get.color(cards[0])!=get.color(cards[1])){ - player.addTempSkill('wusheng'); - player.addTempSkill('paoxiao'); + player.addTempSkills(['wusheng','paoxiao']); } }, derivation:['wusheng','paoxiao'], @@ -2673,7 +2673,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ audio:'taoluan', enable:'chooseToUse', filter:function(event,player){ - return !player.hasSkill('xintaoluan3')&&player.countCards('hes',card=>lib.inpile.some(name=>{ + return !player.hasSkill('xintaoluan3')&&player.hasCard(card=>lib.inpile.some(name=>{ if(player.getStorage('xintaoluan').includes(name)) return false; if(get.type(name)!='basic'&&get.type(name)!='trick') return false; if(event.filterCard({name:name,isCard:true,cards:[card]},player,event)) return true; @@ -2683,7 +2683,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } } return false; - }))>0&&!_status.dying.length; + },'hes'))>0&&!_status.dying.length; }, chooseButton:{ dialog:function(event,player){ @@ -2783,7 +2783,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ event.num=player.countMark('xintaoluan2'); player.chooseTarget(true,function(card,player,target){ return target!=player; - },'滔乱

令一名其他角色选择一项:1.交给你'+get.cnNumber(event.num)+'张与你以此法使用的牌类别相同的牌;2.你失去'+get.cnNumber(event.num)+'点体力').set('ai',function(target){ + },'滔乱

令一名其他角色选择一项:1.交给你'+get.cnNumber(event.num)+'张与你以此法使用的牌类别不同的牌;2.你失去'+get.cnNumber(event.num)+'点体力').set('ai',function(target){ var player=_status.event.player; if(get.attitude(player,target)>0){ if(get.attitude(target,player)>0){ @@ -5255,7 +5255,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ audio:2, enable:'chooseToUse', filter:function(event,player){ - return !player.hasSkill('taoluan3')&&player.countCards('hes',card=>lib.inpile.some(name=>{ + return !player.hasSkill('taoluan3')&&player.hasCard(card=>lib.inpile.some(name=>{ if(player.getStorage('taoluan').includes(name)) return false; if(get.type(name)!='basic'&&get.type(name)!='trick') return false; if(event.filterCard({name:name,isCard:true,cards:[card]},player,event)) return true; @@ -5265,7 +5265,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } } return false; - }))>0; + },'hes'))>0; }, onremove:true, chooseButton:{ @@ -5355,7 +5355,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 'step 0' player.chooseTarget(true,function(card,player,target){ return target!=player; - },'滔乱

令一名其他角色选择一项:1.交给你一张与你以此法使用的牌类别相同的牌;2.你失去1点体力').set('ai',function(target){ + },'滔乱

令一名其他角色选择一项:1.交给你一张与你以此法使用的牌类别不同的牌;2.你失去1点体力').set('ai',function(target){ var player=_status.event.player; if(get.attitude(player,target)>0){ if(get.attitude(target,player)>0){ @@ -9539,16 +9539,17 @@ game.import('character',function(lib,game,ui,get,ai,_status){ group:'fuhun2' }, fuhun2:{ + audio:'fuhun', + audioname:['re_guanzhang'], trigger:{source:'damageSource'}, forced:true, filter:function(event,player){ - if(player.hasSkill('fuhun3')) return false; + if(['new_rewusheng','olpaoxiao'].every(skill=>player.hasSkill(skill,null,false,false))) return false; return event.getParent().skill=='fuhun'; }, content:function(){ - player.addTempSkill('new_rewusheng'); - player.addTempSkill('olpaoxiao'); - player.addTempSkill('fuhun3'); + player.addTempSkills(['new_rewusheng','olpaoxiao']); + // player.addTempSkill('fuhun3'); } }, fuhun3:{}, @@ -13962,7 +13963,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ chengong:['chengong','re_chengong','sb_chengong'], xunyou:['xunyou','re_xunyou'], xuezong:['xuezong','tw_xuezong'], - huanghao:['huanghao','dc_huanghao','old_huanghao'], + huanghao:['huanghao','dc_huanghao','old_huanghao'], caorui:['caorui','re_caorui','old_caorui'], sunziliufang:['sunziliufang','dc_sunziliufang'], liyan:['liyan','old_liyan'], @@ -14328,7 +14329,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ xinxuanhuo_info:'摸牌阶段开始时,你可以改为令一名其他角色摸两张牌,然后该角色需对其攻击范围内你选择的另一名角色使用一张【杀】,否则你获得其两张牌。', fuhun:'父魂', fuhun2:'父魂', - fuhun_info:'你可以将两张手牌当做【杀】使用或打出;出牌阶段,若你以此法使用的【杀】造成了伤害,你获得技能〖武圣〗和〖咆哮〗直到回合结束。', + fuhun_info:'你可以将两张手牌当做【杀】使用或打出;当你于出牌阶段以此法使用的【杀】造成伤害后,你获得〖武圣〗和〖咆哮〗直到回合结束。', yuce:'御策', yuce_info:'当你受到伤害后,你可以展示一张手牌,并令伤害来源选择一项:弃置一张与此牌类型不同的手牌,或令你回复1点体力。', xiansi:'陷嗣', @@ -14528,7 +14529,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ oldmiji:'秘计', oldmiji_info:'准备/结束阶段开始时,若你已受伤,你可以判定,若判定结果为黑色,你观看牌堆顶的X张牌(X为你已损失的体力值),然后将这些牌交给一名角色。', old_fuhun:'父魂', - old_fuhun_info:'摸牌阶段开始时,你可以放弃摸牌,改为从牌堆顶亮出两张牌并获得之,若亮出的牌颜色不同,你获得技能“武圣”、“咆哮”,直到回合结束。', + old_fuhun_info:'摸牌阶段开始时,你可以放弃摸牌,改为从牌堆顶亮出两张牌并获得之,若亮出的牌颜色不同,你获得〖武圣〗和〖咆哮〗直到回合结束。', rejueqing:'绝情', rejueqing_info:'当你对其他角色造成伤害时,你可以令此伤害值+X。若如此做,你失去X点体力并修改〖绝情〗(X为伤害值)。', rejueqing_1st:'绝情', @@ -14578,9 +14579,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){ shuojian_info:'出牌阶段限三次。你可以交给一名其他角色一张牌,其选择一项:1.令你摸X张牌并弃置X-1张牌;2.视为使用X张【过河拆桥】,然后此技能本回合失效(X为此技能本阶段剩余发动次数+1)。', yj_qiaozhou:'谯周', shiming:'识命', - shiming_info:'每轮限一次。一名角色的摸牌阶段,你可以观看牌堆顶的两张牌,并可以将其中一张置于牌堆底。然后该角色可以改为对自己造成1点伤害,然后从牌堆底摸三张牌。', + shiming_info:'每轮限一次。一名角色的摸牌阶段,你可以观看牌堆顶的三张牌,并可以将其中一张置于牌堆底。然后该角色可以改为对自己造成1点伤害,然后从牌堆底摸三张牌。', jiangxi:'将息', - jiangxi_info:'一名角色的回合结束时,若一号位于此回合内进入过濒死状态或未受到过伤害,你可以重置〖识命〗;若所有角色均未受到过伤害,你可以与当前回合角色各摸一张牌。', + jiangxi_info:'一名角色的回合结束时,若一号位于此回合内进入过濒死状态或未受到过伤害,你可以重置〖识命〗并摸一张牌;若所有角色均未受到过伤害,你可以与当前回合角色各摸一张牌。', hanlong:'韩龙', duwang:'独往', duwang_info:'锁定技。①游戏开始时,你从牌堆顶将五张不为【杀】的牌置于武将牌上,称为“刺”。②若你有牌名不为【杀】“刺”,你至其他角色或其他角色至你的距离+1。', diff --git a/character/yingbian.js b/character/yingbian.js index 7f9747452..aa215d04b 100644 --- a/character/yingbian.js +++ b/character/yingbian.js @@ -1673,9 +1673,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } else event.finish(); 'step 1' - player.addTempSkill(result.control,'phaseUseEnd'); + player.addTempSkills(result.control,'phaseUseEnd'); player.popup(result.control); - game.log(player,'获得了','#g【'+get.translation(result.control)+'】'); + // game.log(player,'获得了','#g【'+get.translation(result.control)+'】'); }, ai:{threaten:0.9}, subSkill:{ @@ -3407,13 +3407,13 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(list.length==result.cards.length){ target.draw(); player.getStat('skill').sanchen--; - if(get.mode()=='guozhan') player.addTempSkill('pozhu'); + if(get.mode()=='guozhan') player.addTempSkills('pozhu'); } } else{ target.draw(); player.getStat('skill').sanchen--; - if(get.mode()=='guozhan') player.addTempSkill('pozhu'); + if(get.mode()=='guozhan') player.addTempSkills('pozhu'); } }, ai:{ @@ -3954,7 +3954,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ dezhang_info:'觉醒技。准备阶段,若你没有“绥”,则你减1点体力上限并获得〖卫戍〗。', weishu:'卫戍', weishu_info:'锁定技。①当你于摸牌阶段外不因〖卫戍①〗而摸牌后,你令一名角色摸一张牌。②当你于弃牌阶段外不因〖卫戍②〗而弃置牌后,你弃置一名其他角色的一张牌。', - jin_jiachong:'贾充', + jin_jiachong:'晋贾充', + jin_jiachong_prefix:'晋', xiongshu:'凶竖', xiongshu_info:'其他角色的出牌阶段开始时,你可弃置X张牌(X为你本轮内此前已发动过此技能的次数,为0则不弃)并展示其一张手牌,然后你预测“其本阶段内是否会使用与展示牌牌名相同的牌”。此阶段结束时,若你的预测正确,则你对其造成1点伤害;否则你获得展示牌。', jianhui:'奸回', diff --git a/game/asset.js b/game/asset.js index 3ed1953a6..ecb8fc610 100644 --- a/game/asset.js +++ b/game/asset.js @@ -268,6 +268,7 @@ window.noname_asset_list=[ 'audio/die/db_wenyang.mp3', 'audio/die/dc_bulianshi.mp3', 'audio/die/dc_caiyang.mp3', + 'audio/die/dc_caoshuang.mp3', 'audio/die/dc_caozhi.mp3', 'audio/die/dc_chenqun.mp3', 'audio/die/dc_dengzhi.mp3', @@ -384,6 +385,7 @@ window.noname_asset_list=[ 'audio/die/guohuanghou.mp3', 'audio/die/guojia.mp3', 'audio/die/guosi.mp3', + 'audio/die/guotu.mp3', 'audio/die/guotufengji.mp3', 'audio/die/guozhao.mp3', 'audio/die/guyong.mp3', @@ -477,6 +479,7 @@ window.noname_asset_list=[ 'audio/die/jsp_caoren.mp3', 'audio/die/jsp_guanyu.mp3', 'audio/die/jsp_huangyueying.mp3', + 'audio/die/junk_guanyu.mp3', 'audio/die/kanze.mp3', 'audio/die/kebineng.mp3', 'audio/die/key_abyusa.mp3', @@ -623,6 +626,7 @@ window.noname_asset_list=[ 'audio/die/ol_sb_guanyu.mp3', 'audio/die/ol_sb_jiangwei.mp3', 'audio/die/ol_sb_taishici.mp3', + 'audio/die/ol_sb_yuanshao.mp3', 'audio/die/ol_sp_zhugeliang.mp3', 'audio/die/ol_sunjian.mp3', 'audio/die/ol_wangrong.mp3', @@ -1859,6 +1863,8 @@ window.noname_asset_list=[ 'audio/skill/dcenyu2.mp3', 'audio/skill/dcfangdu1.mp3', 'audio/skill/dcfangdu2.mp3', + 'audio/skill/dcfanshi1.mp3', + 'audio/skill/dcfanshi2.mp3', 'audio/skill/dcfanyin1.mp3', 'audio/skill/dcfanyin2.mp3', 'audio/skill/dcfaqi1.mp3', @@ -1873,6 +1879,8 @@ window.noname_asset_list=[ 'audio/skill/dcfozong2.mp3', 'audio/skill/dcfudao1.mp3', 'audio/skill/dcfudao2.mp3', + 'audio/skill/dcfudou1.mp3', + 'audio/skill/dcfudou2.mp3', 'audio/skill/dcfuli1.mp3', 'audio/skill/dcfuli2.mp3', 'audio/skill/dcfumou1.mp3', @@ -1919,6 +1927,8 @@ window.noname_asset_list=[ 'audio/skill/dcjianying2.mp3', 'audio/skill/dcjianzheng1.mp3', 'audio/skill/dcjianzheng2.mp3', + 'audio/skill/dcjianzhuan1.mp3', + 'audio/skill/dcjianzhuan2.mp3', 'audio/skill/dcjiaofeng1.mp3', 'audio/skill/dcjiaofeng2.mp3', 'audio/skill/dcjiaoxia1.mp3', @@ -3645,6 +3655,8 @@ window.noname_asset_list=[ 'audio/skill/olqingyuan2.mp3', 'audio/skill/olqisi1.mp3', 'audio/skill/olqisi2.mp3', + 'audio/skill/olqushi1.mp3', + 'audio/skill/olqushi2.mp3', 'audio/skill/olruoyu1.mp3', 'audio/skill/olruoyu2.mp3', 'audio/skill/olsaogu1.mp3', @@ -3659,10 +3671,17 @@ window.noname_asset_list=[ 'audio/skill/olsbfumeng2.mp3', 'audio/skill/olsbguidao1.mp3', 'audio/skill/olsbguidao2.mp3', + 'audio/skill/olsbhetao1.mp3', + 'audio/skill/olsbhetao2.mp3', 'audio/skill/olsbranji1.mp3', 'audio/skill/olsbranji2.mp3', + 'audio/skill/olsbshenli1.mp3', + 'audio/skill/olsbshenli2.mp3', + 'audio/skill/olsbshishou1.mp3', + 'audio/skill/olsbshishou2.mp3', 'audio/skill/olsbweilin1.mp3', 'audio/skill/olsbweilin2.mp3', + 'audio/skill/olsbyufeng1.mp3', 'audio/skill/olsbzhuri1.mp3', 'audio/skill/olsbzhuri2.mp3', 'audio/skill/olshandao1.mp3', @@ -3691,6 +3710,8 @@ window.noname_asset_list=[ 'audio/skill/oltuntian2.mp3', 'audio/skill/olweifu1.mp3', 'audio/skill/olweifu2.mp3', + 'audio/skill/olweijie1.mp3', + 'audio/skill/olweijie2.mp3', 'audio/skill/olxianbi1.mp3', 'audio/skill/olxianbi2.mp3', 'audio/skill/olxiangxv1.mp3', @@ -6669,6 +6690,7 @@ window.noname_asset_list=[ 'image/card/shujinsan.png', 'image/card/shunshou.png', 'image/card/sifeizhenmian.png', + 'image/card/sizhaojian.png', 'image/card/suijiyingbian.png', 'image/card/suolianjia.png', 'image/card/taigongyinfu.png', @@ -6726,6 +6748,7 @@ window.noname_asset_list=[ 'image/card/xuanyuanjian.png', 'image/card/xuejibingbao.png', 'image/card/xuelunyang.png', + 'image/card/xumou_jsrg.jpg', 'image/card/yajiaoqiang.png', 'image/card/yangpijuan.png', 'image/card/yanjiadan_club.png', @@ -6878,6 +6901,7 @@ window.noname_asset_list=[ 'image/character/dc_bulianshi.jpg', 'image/character/dc_caiyang.jpg', 'image/character/dc_caocao.jpg', + 'image/character/dc_caoshuang.jpg', 'image/character/dc_caozhi.jpg', 'image/character/dc_chenqun.jpg', 'image/character/dc_daxiaoqiao.jpg', @@ -6913,8 +6937,11 @@ window.noname_asset_list=[ 'image/character/dc_mifuren.jpg', 'image/character/dc_ruiji.jpg', 'image/character/dc_sb_lusu.jpg', + 'image/character/dc_sb_simayi.jpg', + 'image/character/dc_sb_simayi_shadow.jpg', 'image/character/dc_sb_zhouyu.jpg', 'image/character/dc_shixie.jpg', + 'image/character/dc_simashi.jpg', 'image/character/dc_sp_jiaxu.jpg', 'image/character/dc_sp_machao.jpg', 'image/character/dc_sunce.jpg', @@ -6926,6 +6953,7 @@ window.noname_asset_list=[ 'image/character/dc_tengfanglan.jpg', 'image/character/dc_wangchang.jpg', 'image/character/dc_wangjun.jpg', + 'image/character/dc_wangling.jpg', 'image/character/dc_wangyun.jpg', 'image/character/dc_wuban.jpg', 'image/character/dc_xiahouba.jpg', @@ -7073,6 +7101,7 @@ window.noname_asset_list=[ 'image/character/guohuanghou.jpg', 'image/character/guojia.jpg', 'image/character/guosi.jpg', + 'image/character/guotu.jpg', 'image/character/guotufengji.jpg', 'image/character/guozhao.jpg', 'image/character/guyong.jpg', @@ -7446,6 +7475,7 @@ window.noname_asset_list=[ 'image/character/jun_sunquan.jpg', 'image/character/jun_zhangjiao.jpg', 'image/character/junk_duanwei.jpg', + 'image/character/junk_guanyu.jpg', 'image/character/junk_huangyueying.jpg', 'image/character/junk_lidian.jpg', 'image/character/junk_liubei.jpg', @@ -7572,6 +7602,7 @@ window.noname_asset_list=[ 'image/character/liufeng.jpg', 'image/character/liuhong.jpg', 'image/character/liuhui.jpg', + 'image/character/liupan.jpg', 'image/character/liupi.jpg', 'image/character/liuqi.jpg', 'image/character/liushan.jpg', @@ -7742,6 +7773,7 @@ window.noname_asset_list=[ 'image/character/ol_liushan.jpg', 'image/character/ol_liuyu.jpg', 'image/character/ol_liwan.jpg', + 'image/character/ol_lukai.jpg', 'image/character/ol_lusu.jpg', 'image/character/ol_luyusheng.jpg', 'image/character/ol_maliang.jpg', @@ -7754,6 +7786,7 @@ window.noname_asset_list=[ 'image/character/ol_sb_guanyu.jpg', 'image/character/ol_sb_jiangwei.jpg', 'image/character/ol_sb_taishici.jpg', + 'image/character/ol_sb_yuanshao.jpg', 'image/character/ol_sp_zhugeliang.jpg', 'image/character/ol_sunjian.jpg', 'image/character/ol_wanglang.jpg', @@ -8287,6 +8320,7 @@ window.noname_asset_list=[ 'image/character/star_dongzhuo.jpg', 'image/character/star_yuanshao.jpg', 'image/character/star_yuanshu.jpg', + 'image/character/star_zhangchunhua.jpg', 'image/character/std_panfeng.jpg', 'image/character/sunce.jpg', 'image/character/sunchen.jpg', diff --git a/game/game.js b/game/game.js index cfb62e7c3..74b1414a5 100644 --- a/game/game.js +++ b/game/game.js @@ -92,11 +92,31 @@ new Promise(resolve => { "safari": [14, 5, 0] } const versions = [major, minor, patch] + // require是需求的版本号,current是浏览器环境本身的版本号 + const check = (require, current) => { + // 防止不存在的意外,提前截断当前版本号的长度 + if (current.length > require.length) current.length = require.length - // current是需求的版本号,versions[index]是浏览器环境本身的版本号 - // 如果current > versions[index],即当前版本的浏览器版本号达不到要求的版本号,则可判定当前版本无法支持 - // 如果versions[index]为NaN,必然返回false;由于ua信息不可能存在主版本号NaN的情况,故不必考虑次版本号/修补版本号并不存在的情况 - if (core in supportMap && supportMap[core].some((current, index) => current > versions[index])) { + // 考虑到玄学的NaN情况,记录是否存在NaN + let flag = false + // 从主版本号遍历到修订版本号,只考虑当前版本号的长度 + for (let i = 0; i < current.length; ++i) { + // 当前环境版本号当前位若是NaN,则记录后直接到下一位 + if (isNaN(current[i])) { + flag = true + continue + } + // 如果此时flag为true且current[i]不为NaN,版本号则不合法,直接否 + if (flag) return false + // 上位版本号未达到要求,直接否决 + if (require[i] > current[i]) return false + // 上位版本号已超过要求,直接可行 + if (current[i] > require[i]) return true + } + return true + } + + if (core in supportMap && !check(supportMap[core], versions)) { const tip = '检测到您的浏览器内核版本无法支持当前无名杀所需的功能,请立即升级浏览器或手机webview内核!'; console.error(tip); let redirect_tip = `您使用的浏览器或无名杀客户端内核版本过低,已经无法正常运行无名杀!\n目前使用的浏览器UA信息为:\n${userAgent}\n点击“确认”以前往GitHub下载最新版无名杀客户端(可能需要科学上网)。\n稍后您的无名杀将自动退出(可能的话)`; diff --git a/game/update.js b/game/update.js index 5492fcd73..85f4da8fe 100644 --- a/game/update.js +++ b/game/update.js @@ -1,14 +1,17 @@ window.noname_update={ - version:'1.10.8', - update:'1.10.7.1', + version:'1.10.9', + update:'1.10.8', changeLog:[ - '整合@mengxinzxz @Rintim @universe-st @nonameShijian @kuangshen04 @copcap @lieren2023 @7754496 的Pull Request', - '“获得技能时/失去技能时”的新时机', + '整合@mengxinzxz @copcap @hadeszoro @universe-st @cjk7989 @PZ157 @lieren2023 @Ansolve @Rintim @kuangshen04 @XboxSoldier 的Pull Request', + 'OL谋袁绍、郭图、刘磐、陆凯、谋关羽(初版)', + '十周年谋司马懿、曹爽、星张春华、司马师、王凌、蒋济、公孙修、胡遵、吕范、李傕郭汜、臧霸、陈武董袭', + '“转化牌花色/点数”的模糊匹配', '其他AI优化与bug修复', ], files:[ - 'card/swd.js', - 'card/yunchou.js', + 'card/extra.js', + 'card/guozhan.js', + 'card/standard.js', 'character/clan.js', 'character/collab.js', @@ -30,16 +33,18 @@ window.noname_update={ 'character/sp.js', 'character/sp2.js', 'character/standard.js', + 'character/swd.js', 'character/tw.js', 'character/xianding.js', + 'character/xianjian.js', 'character/xinghuoliaoyuan.js', 'character/yijiang.js', 'character/yingbian.js', - 'game/entry.js', 'game/game.js', 'mode/boss.js', + 'mode/brawl.js', 'mode/guozhan.js', 'mode/identity.js', 'mode/versus.js', @@ -47,36 +52,21 @@ window.noname_update={ 'noname/game/index.js', 'noname/get/index.js', - - 'noname/init/cordova.js', - 'noname/init/import.js', - 'noname/init/index.js', - 'noname/init/onload.js', + 'noname/get/is.js', 'noname/library/index.js', - 'noname/library/element/card.js', + 'noname/library/element/button.js', 'noname/library/element/content.js', + 'noname/library/element/contents.js', 'noname/library/element/gameEvent.js', 'noname/library/element/player.js', + 'noname/library/element/vcard.js', 'noname/library/init/index.js', - 'noname/ui/index.js', - - 'noname/ui/click/index.js', - 'noname/ui/create/index.js', 'noname/ui/create/menu/index.js', - - 'noname/ui/create/menu/pages/cardPackMenu.js', - 'noname/ui/create/menu/pages/characterPackMenu.js', - 'noname/ui/create/menu/pages/extensionMenu.js', - 'noname/ui/create/menu/pages/optionsMenu.js', - 'noname/ui/create/menu/pages/otherMenu.js', - 'noname/ui/create/menu/pages/startMenu.js', - - 'service-worker.js', ] }; diff --git a/image/card/sizhaojian.png b/image/card/sizhaojian.png new file mode 100644 index 000000000..40c1683f9 Binary files /dev/null and b/image/card/sizhaojian.png differ diff --git a/image/character/dc_caoshuang.jpg b/image/character/dc_caoshuang.jpg new file mode 100644 index 000000000..c6db64170 Binary files /dev/null and b/image/character/dc_caoshuang.jpg differ diff --git a/image/character/dc_sb_simayi.jpg b/image/character/dc_sb_simayi.jpg new file mode 100644 index 000000000..a206b7af9 Binary files /dev/null and b/image/character/dc_sb_simayi.jpg differ diff --git a/image/character/dc_sb_simayi_shadow.jpg b/image/character/dc_sb_simayi_shadow.jpg new file mode 100644 index 000000000..d38881a70 Binary files /dev/null and b/image/character/dc_sb_simayi_shadow.jpg differ diff --git a/image/character/dc_simashi.jpg b/image/character/dc_simashi.jpg new file mode 100644 index 000000000..28d9178e5 Binary files /dev/null and b/image/character/dc_simashi.jpg differ diff --git a/image/character/dc_wangling.jpg b/image/character/dc_wangling.jpg new file mode 100644 index 000000000..95aeb7844 Binary files /dev/null and b/image/character/dc_wangling.jpg differ diff --git a/image/character/guotu.jpg b/image/character/guotu.jpg new file mode 100644 index 000000000..526bbbdf5 Binary files /dev/null and b/image/character/guotu.jpg differ diff --git a/image/character/junk_guanyu.jpg b/image/character/junk_guanyu.jpg new file mode 100644 index 000000000..69bd7fbaa Binary files /dev/null and b/image/character/junk_guanyu.jpg differ diff --git a/image/character/liupan.jpg b/image/character/liupan.jpg new file mode 100644 index 000000000..1b2d1d694 Binary files /dev/null and b/image/character/liupan.jpg differ diff --git a/image/character/ol_feiyi.jpg b/image/character/ol_feiyi.jpg index 0f50f7dec..9bb706d81 100644 Binary files a/image/character/ol_feiyi.jpg and b/image/character/ol_feiyi.jpg differ diff --git a/image/character/ol_lukai.jpg b/image/character/ol_lukai.jpg new file mode 100644 index 000000000..ed8ce8938 Binary files /dev/null and b/image/character/ol_lukai.jpg differ diff --git a/image/character/ol_sb_yuanshao.jpg b/image/character/ol_sb_yuanshao.jpg new file mode 100644 index 000000000..96af5734a Binary files /dev/null and b/image/character/ol_sb_yuanshao.jpg differ diff --git a/image/character/star_zhangchunhua.jpg b/image/character/star_zhangchunhua.jpg new file mode 100644 index 000000000..5a583eb98 Binary files /dev/null and b/image/character/star_zhangchunhua.jpg differ diff --git a/mode/boss.js b/mode/boss.js index e0291fcb0..21ccec660 100644 --- a/mode/boss.js +++ b/mode/boss.js @@ -8577,7 +8577,7 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ if(!player.hasSkill('olxuanfeng')) list.push('olxuanfeng'); if(!player.hasSkill('rewansha')) list.push('rewansha'); if(list.length==1){ - player.addTempSkill(list[0]); + player.addTempSkills(list[0]); event.finish(); } else{ @@ -8602,8 +8602,8 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ }).set('prompt','选择获得一项技能直到回合结束'); } 'step 1' - player.addTempSkill(result.control); - player.popup(get.translation(result.control)); + player.addTempSkills(result.control); + // player.popup(get.translation(result.control)); }, ai:{ order:function(){ diff --git a/mode/brawl.js b/mode/brawl.js index a8f9734b7..949dd730a 100644 --- a/mode/brawl.js +++ b/mode/brawl.js @@ -571,7 +571,7 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ if(list.length==3) break; } if(!list.length){event.finish();return;} - if(player.storage._lingli>0) list.push('刷新'); + if(player.storage._lingli>0) list.push('刷新'); event.list=list; var dialog=game.getSkillDialog(event.list,'选择获得一个技能'); player.chooseControl(event.list).set('ai',function(){ diff --git a/mode/guozhan.js b/mode/guozhan.js index 11f1ee0f5..9b0e6e035 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -1666,7 +1666,7 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ var cards=[]; //因为是线下武将 所以同一张牌重复进入只算一张 game.getGlobalHistory('cardMove',function(evt){ - if(evt.name=='cardsDiscard'||(evt.name=='lose'&&evt.position==ui.discardPile)) cards.addArray(evt.cards); + if(evt.name=='cardsDiscard'||(evt.name=='lose'&&evt.position==ui.discardPile)) cards.addArray(evt.cards); }); return cards.length; }, @@ -8692,12 +8692,14 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ if(event.current&&event.current.isAlive()){ event.showCharacter=false; var choiceList=['执行该军令,增加1点体力上限,然后回复1点体力','不执行该军令']; - if(event.current.isFriendOf(player)) event.current.chooseJunlingControl(player,event.junling,targets).set('prompt','将略').set('choiceList',choiceList).set('ai',function(){return 0}); + if(event.current.isFriendOf(player)) event.current.chooseJunlingControl(player,event.junling,targets).set('prompt','将略').set('choiceList',choiceList).set('ai',function(){if(event.junling=='junling6'&&(event.current.countCards('h')>3||event.current.countCards('e')>2)) return 1; +return event.junling=='junling5'?1:0;}); else if((event.filterName(event.current.name1)||event.filterName(event.current.name2))&&event.current.wontYe(player.identity)){ event.showCharacter=true; choiceList[0]='明置一张武将牌以'+choiceList[0]; choiceList[1]='不明置武将牌且'+choiceList[1]; - event.current.chooseJunlingControl(player,event.junling,targets).set('prompt','将略').set('choiceList',choiceList).set('ai',function(){return 0}); + event.current.chooseJunlingControl(player,event.junling,targets).set('prompt','将略').set('choiceList',choiceList).set('ai',function(){if(event.junling=='junling6'&&(event.current.countCards('h')>3||event.current.countCards('e')>2)) return 1; +return event.junling=='junling5'?1:0;}); } else event.current.chooseJunlingControl(player,event.junling,targets).set('prompt','将略').set('controls',['ok']); } @@ -8744,7 +8746,7 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ skillAnimation:'epic', animationColor:'soil', ai:{ - order:4, + order:10, result:{ player:function(player){ if(player.isUnseen()&&player.wontYe()){ @@ -10555,7 +10557,7 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ }, check:function(card){ if(card.name=='tao') return 0; - return 5-get.value(card); + return 7-get.value(card); }, selectCard:[1,3], discard:false, @@ -10571,7 +10573,7 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ }, ai:{ basic:{ - order:2 + order:8 }, result:{ player:function(player,target){ @@ -10585,7 +10587,11 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ if(huoshao&&player.inline(target.getNext())) return -3; if(target.isUnseen()) return 0; if(player.isMajor()) return 0; - return 0.5; + if(!player.isMajor()&&huoshao&&player.getNext().isMajor()) return -2; + if(!player.isMajor()&&huoshao&&player.getNext().isMajor()&&player.getNext().getNext().isMajor()) return -3; + if(!player.isMajor()&&huoshao&&!target.isMajor()&&target.getNext().isMajor()&&target.getNext().getNext().isMajor()) return 3; + if(!player.isMajor()&&huoshao&&!target.isMajor()&&target.getNext().isMajor()) return 1.5; + return 1; }, target:function(player,target){ if(target.isUnseen()) return 0; @@ -11030,9 +11036,9 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ 'step 2' if(result.control!='cancel2'){ var skill='jiahe_'+result.control; - player.addTempSkill(skill); + player.addTempSkills(skill); if(!event.done) player.logSkill('jiahe_put'); - game.log(player,'获得了技能','【'+get.translation(skill)+'】'); + // game.log(player,'获得了技能','【'+get.translation(skill)+'】'); if(event.num>=5&&!event.done){ event.done=true; event.goto(1); diff --git a/mode/identity.js b/mode/identity.js index c1a68d4bf..9e1e30cc2 100644 --- a/mode/identity.js +++ b/mode/identity.js @@ -580,7 +580,7 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ case 'fan':list[i]='反贼';break; case 'zhong':list[i]='忠臣';break; case 'nei':list[i]='内奸';break; - case 'commoner':list[i]='平民'; break; + case 'commoner':list[i]='平民'; break; case 'zhu':list[i]='主公';break; case 'enemy':list[i]='敌方';break; case 'friend':list[i]='友方';break; @@ -737,7 +737,7 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ switch(me.identity){ case 'fan':game.over(false);break; case 'zhong':game.over(true);break; - case 'commoner':game.over(true); break; + case 'commoner':game.over(true); break; default:game.over();break; } } @@ -745,7 +745,7 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ switch(me.identity){ case 'fan':game.over(true);break; case 'zhong':game.over(false);break; - case 'commoner':game.over(true); break; + case 'commoner':game.over(true); break; default:game.over();break; } } @@ -765,7 +765,7 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ } } else if(me.identity=='nei'){ - if(game.players.length==(1+game.players.filter(i=>i.identity=='commoner').length)&&me.isAlive()){ + if(game.players.length==(1+game.players.filter(i=>i.identity=='commoner').length)&&me.isAlive()){ game.over(true); } else{ @@ -781,8 +781,8 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ game.over(false); } } - else if(me.identity=='commoner'){ - game.over(true); + else if(me.identity=='commoner'){ + game.over(true); } }, checkOnlineResult:function(player){ @@ -794,7 +794,7 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ if(game.zhu.isAlive()){ return (player.identity=='zhu'||player.identity=='zhong'||player.identity=='mingzhong'||player.identity=='commoner'&&player.isAlive()); } - else if(game.players.length==(1+game.players.filter(i=>i.identity=='commoner').length)&&game.players[0].identity=='nei'||game.players[0].identity=='commoner'){ + else if(game.players.length==(1+game.players.filter(i=>i.identity=='commoner').length)&&game.players[0].identity=='nei'||game.players[0].identity=='commoner'){ return player.isAlive(); } else{ @@ -1568,9 +1568,9 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ link=['zhu','zhong','nei','fan','mingzhong'].randomGet(); } else{ - var listi=['zhu','zhong','nei','fan']; - if(get.config('enable_commoner')&&!event.stratagemMode) listi.push('commoner'); - link=listi.randomGet(); + var listi=['zhu','zhong','nei','fan']; + if(get.config('enable_commoner')&&!event.stratagemMode) listi.push('commoner'); + link=listi.randomGet(); } for(var i=0;i1&&to.hp>fan.hp&&to.countCards('he')>fan.countCards('he')){ - return -3; + return -1.7; } } return 0; @@ -3706,8 +3706,8 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ if(game.zhu&&game.zhu.hp<=2) return -1; return Math.min(3,situation); case 'fan': return 5; - case 'commoner': - return 2*get.population('fan')-3; + case 'commoner': + return 2*get.population('fan')-3; } break; case 'commoner': @@ -3874,7 +3874,8 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ 'step 2' player.recover(); player.draw(); - const skills = player.getStockSkills(true,true).forEach(stockSkill=>{ + 'step 3' + const skills = player.getStockSkills(true,true).filter(stockSkill=>{ if(player.hasSkill(stockSkill)) return; var info=get.info(stockSkill); if(!info||!info.zhuSkill) return; diff --git a/mode/versus.js b/mode/versus.js index cac594d7b..7cb58103d 100644 --- a/mode/versus.js +++ b/mode/versus.js @@ -2632,7 +2632,7 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ } } game.falseZhu.init('re_caocao'); - game.trueZhu.init('ol_yuanshao'); + game.trueZhu.init('ol_sb_yuanshao'); game.trueZhu.hp++; game.trueZhu.maxHp++; game.falseZhu.hp++; @@ -2640,13 +2640,32 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ game.trueZhu.update(); game.falseZhu.update(); ui.arena.classList.add('choose-character'); - if(get.is.phoneLayout()){ - ui.guanduInfo=ui.create.div('.touchinfo.left',ui.window); + if(evt=='shishengshibai'){ + ui.guanduInfo=get.is.phoneLayout()?ui.create.div('.touchinfo.left',ui.window):ui.create.div(ui.gameinfo); + ui.guanduInfo.innerHTML='十胜十败(0)'; } - else{ - ui.guanduInfo=ui.create.div(ui.gameinfo); + const showGuanduEvent=function(evt){ + if(ui['GuanduEvent_'+evt]) return; + ui['GuanduEvent_'+evt]=ui.create.system(get.translation(evt),null,true); + lib.setPopped(ui['GuanduEvent_'+evt],function(){ + var uiintro=ui.create.dialog('hidden'); + uiintro.add(get.translation(evt)); + uiintro.add('
'+get.translation(evt+'_info')+'
'); + var ul=uiintro.querySelector('ul'); + if(ul) ul.style.width='180px'; + uiintro.add(ui.create.div('.placeholder')); + return uiintro; + },250); + }; + for(const i in lib.playerOL){ + const target=lib.playerOL[i]; + if(target==game.me){ + showGuanduEvent(evt); + } + else if(target.isOnline2()){ + target.send(showGuanduEvent,evt); + } } - ui.guanduInfo.innerHTML='当前事件:'+get.translation(evt); if(lib.config.background_speak) game.playAudio('skill',evt); var dialog=ui.create.dialog('本局特殊事件:'+get.translation(evt)); dialog.addText(get.translation(evt+'_info'),false); @@ -2715,7 +2734,7 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ lib.init.onfree(); ui.arena.classList.add('choose-character'); game.falseZhu.init('re_caocao'); - game.trueZhu.init('ol_yuanshao'); + game.trueZhu.init('ol_sb_yuanshao'); game.trueZhu.hp++; game.trueZhu.maxHp++; game.falseZhu.hp++; @@ -2725,15 +2744,26 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ var evt_list=[['huoshaowuchao','chunyuqiong'],['liangcaokuifa','sp_xuyou'],['zhanyanliangzhuwenchou','jsp_guanyu'],['shishengshibai','re_guojia'],['xutuhuanjin','yj_jushou'],['liangjunxiangchi','yj_jushou'],['jianshoudaiyuan','tianfeng'],['yiruoshengqiang','re_caocao'],['shichongerjiao','sp_xuyou']].randomGet(); var evt=evt_list[0],character=evt_list[1]; game.addGlobalSkill(evt); + const showGuanduEvent=function(evt){ + if(ui['GuanduEvent_'+evt]) return; + ui['GuanduEvent_'+evt]=ui.create.system(get.translation(evt),null,true); + lib.setPopped(ui['GuanduEvent_'+evt],function(){ + var uiintro=ui.create.dialog('hidden'); + uiintro.add(get.translation(evt)); + uiintro.add('
'+get.translation(evt+'_info')+'
'); + var ul=uiintro.querySelector('ul'); + if(ul) ul.style.width='180px'; + uiintro.add(ui.create.div('.placeholder')); + return uiintro; + },250); + }; + showGuanduEvent(evt); game.broadcastAll(function(evt){ - if(get.is.phoneLayout()){ - ui.guanduInfo=ui.create.div('.touchinfo.left',ui.window); - } - else{ - ui.guanduInfo=ui.create.div(ui.gameinfo); - } if(lib.config.background_speak) game.playAudio('skill',evt); - ui.guanduInfo.innerHTML='当前事件:'+get.translation(evt); + if(evt=='shishengshibai'){ + ui.guanduInfo=get.is.phoneLayout()?ui.create.div('.touchinfo.left',ui.window):ui.create.div(ui.gameinfo); + ui.guanduInfo.innerHTML='十胜十败(0)'; + } },evt); game.me.chooseControl('ok').set('dialog',['###本局特殊事件:'+get.translation(evt)+'###'+get.translation(evt+'_info'),[[character],'character']]); 'step 1' @@ -4688,7 +4718,7 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ if(!_status.shishengshibai) _status.shishengshibai=0; _status.shishengshibai++; game.broadcastAll(function(num){ - if(ui.guanduInfo) ui.guanduInfo.innerHTML='当前事件:十胜十败('+num+')'; + if(ui.guanduInfo) ui.guanduInfo.innerHTML='十胜十败('+num+')'; },_status.shishengshibai); if(_status.shishengshibai%10==0&&trigger.targets&&trigger.targets.length>0&&!['delay','equip'].includes(get.type(trigger.card))){ trigger.effectCount++; diff --git a/noname/game/index.js b/noname/game/index.js index 6a029bcd1..5407f0c13 100644 --- a/noname/game/index.js +++ b/noname/game/index.js @@ -1881,12 +1881,12 @@ export class Game extends Uninstantable { config: objectConfig } try{ - if (precontent) { - _status.extension = name; - - await (gnc.is.generatorFunc(precontent) ? gnc.of(precontent) : precontent).call(object, config); - delete _status.extension; - } + if (precontent) { + _status.extension = name; + + await (gnc.is.generatorFunc(precontent) ? gnc.of(precontent) : precontent).call(object, config); + delete _status.extension; + } }catch(e1){ console.log(`加载《${name}》扩展的precontent时出现错误。`,e1); if(!lib.config.extension_alert) alert(`加载《${name}》扩展的precontent时出现错误。\n该错误本身可能并不影响扩展运行。您可以在“设置→通用→无视扩展报错”中关闭此弹窗。\n${decodeURI(e1.stack)}`); @@ -5860,479 +5860,264 @@ export class Game extends Uninstantable { /** * @param { GameEventPromise } [event] */ - static check(event) { - let i, range; - if (event == undefined) event = _status.event; + static check(event = _status.event) { + game.callHook("checkBegin", [event]); + event._checked = true; - let custom = event.custom || {}; - let ok = true, auto = true; - let player = event.player; - let auto_confirm = lib.config.auto_confirm; - let players = game.players.slice(0); - if (event.deadTarget) players.addArray(game.dead); + let ok = true, auto = true, auto_confirm = lib.config.auto_confirm; + const player = event.player; + const uppercaseType = (type) => type[0].toUpperCase() + type.slice(1); + + if (!event.filterButton && !event.filterCard && !event.filterTarget && (!event.skill || !event._backup)) { - if (event.choosing) { - _status.imchoosing = true; - } - return; + if (event.choosing) _status.imchoosing = true; + return false; } - player.node.equips.classList.remove('popequip'); - if (event.filterButton) { - let dialog = event.dialog; - range = get.select(event.selectButton); - let selectableButtons = false; - if (event.forceAuto && ui.selected.buttons.length == range[1]) auto = true; - else if (range[0] != range[1] || range[0] > 1) auto = false; - for (i = 0; i < dialog.buttons.length; i++) { - if (dialog.buttons[i].classList.contains('unselectable')) continue; - if (event.filterButton(dialog.buttons[i], player) && lib.filter.buttonIncluded(dialog.buttons[i])) { - if (ui.selected.buttons.length < range[1]) { - dialog.buttons[i].classList.add('selectable'); - } - else if (range[1] <= -1) { - dialog.buttons[i].classList.add('selected'); - ui.selected.buttons.add(dialog.buttons[i]); - } - else { - dialog.buttons[i].classList.remove('selectable'); - } - } - else { - dialog.buttons[i].classList.remove('selectable'); - if (range[1] <= -1) { - dialog.buttons[i].classList.remove('selected'); - ui.selected.buttons.remove(dialog.buttons[i]); - } - } - if (dialog.buttons[i].classList.contains('selected')) { - dialog.buttons[i].classList.add('selectable'); - } - else if (!selectableButtons && dialog.buttons[i].classList.contains('selectable')) { - selectableButtons = true; - } - } - if (ui.selected.buttons.length < range[0]) { - if (!event.forced || selectableButtons) { - ok = false; - } - if (event.complexSelect || event.getParent().name == 'chooseCharacter' || event.getParent().name == 'chooseButtonOL') { - ok = false; - } - } - if (custom.add.button) { - custom.add.button(); - } - } - if (event.filterCard) { - if (ok == false) { - game.uncheck('card'); - } - else { - let cards = player.getCards(event.position); - let firstCheck = false; - range = get.select(event.selectCard); - if (!event._cardChoice && typeof event.selectCard != 'function' && - !event.complexCard && range[1] > -1 && !lib.config.compatiblemode) { - event._cardChoice = []; - firstCheck = true; - } - if (event.isMine() && event.name == 'chooseToUse' && event.parent.name == 'phaseUse' && !event.skill && - !event._targetChoice && !firstCheck && !lib.config.compatiblemode) { - event._targetChoice = new Map(); - for (let i = 0; i < event._cardChoice.length; i++) { - if (!lib.card[event._cardChoice[i].name].complexTarget) { - let targets = []; - for (let j = 0; j < players.length; j++) { - if (event.filterTarget(event._cardChoice[i], player, players[j])) { - targets.push(players[j]); - } - } - event._targetChoice.set(event._cardChoice[i], targets); - } - } - } - let selectableCards = false; - if (range[0] != range[1] || range[0] > 1) auto = false; - for (i = 0; i < cards.length; i++) { - if (lib.config.cardtempname != 'off') { - let cardname = get.name(cards[i]); - if (cards[i].name != cardname || !get.is.sameNature(get.nature(cards[i]), cards[i].nature, true)) { - let node = ui.create.cardTempName(cards[i]); - let cardtempnameConfig = lib.config.cardtempname; - if (cardtempnameConfig !== 'default') node.classList.remove('vertical'); - } - } - let nochess = true; - if (!lib.filter.cardAiIncluded(cards[i])) { - nochess = false; - } - else if (event._cardChoice && !firstCheck) { - if (!event._cardChoice.includes(cards[i])) { - nochess = false; - } - } - else { - if (player.isOut() || !lib.filter.cardRespondable(cards[i], player) || - cards[i].classList.contains('uncheck') || - !event.filterCard(cards[i], player)) { - nochess = false; - } - } - if (nochess) { - if (ui.selected.cards.length < range[1]) { - cards[i].classList.add('selectable'); - if (event._cardChoice && firstCheck) { - event._cardChoice.push(cards[i]); - } - } - else if (range[1] <= -1) { - cards[i].classList.add('selected'); - cards[i].updateTransform(true); - ui.selected.cards.add(cards[i]); - } - else { - cards[i].classList.remove('selectable'); - } - } - else { - cards[i].classList.remove('selectable'); - if (range[1] <= -1) { - cards[i].classList.remove('selected'); - cards[i].updateTransform(); - ui.selected.cards.remove(cards[i]); - } - } - if (cards[i].classList.contains('selected')) { - cards[i].classList.add('selectable'); - } - else if (!selectableCards && cards[i].classList.contains('selectable')) { - selectableCards = true; - } - } - if (ui.selected.cards.length < range[0]) { - if (!event.forced || selectableCards || event.complexSelect) { - ok = false; - } - } - if (lib.config.popequip && get.is.phoneLayout() && - typeof event.position == 'string' && event.position.includes('e') && - player.node.equips.querySelector('.card.selectable')) { - player.node.equips.classList.add('popequip'); - auto_confirm = false; - } - } - if (custom.add.card) { - custom.add.card(); - } - } - if (event.filterTarget) { - if (ok == false) { - game.uncheck('target'); - } - else { - let card = get.card(); - let firstCheck = false; - range = get.select(event.selectTarget); - let selectableTargets = false; - if (range[0] != range[1] || range[0] > 1) auto = false; - for (i = 0; i < players.length; i++) { - let nochess = true; - if (game.chess && !event.chessForceAll && player && get.distance(player, players[i], 'pure') > 7) { - nochess = false; - } - else if (players[i].isOut()) { - nochess = false; - } - else if (event._targetChoice && event._targetChoice.has(card)) { - let targetChoice = event._targetChoice.get(card); - if (!Array.isArray(targetChoice) || !targetChoice.includes(players[i])) { - nochess = false; - } - } - else if (!event.filterTarget(card, player, players[i])) { - nochess = false; - } - if (nochess) { - if (ui.selected.targets.length < range[1]) { - players[i].classList.add('selectable'); - if (Array.isArray(event._targetChoice)) { - event._targetChoice.push(players[i]); - } - } - else if (range[1] <= -1) { - players[i].classList.add('selected'); - ui.selected.targets.add(players[i]); - } - else { - players[i].classList.remove('selectable'); - } - } - else { - players[i].classList.remove('selectable'); - if (range[1] <= -1) { - players[i].classList.remove('selected'); - ui.selected.targets.remove(players[i]); - } - } - if (players[i].classList.contains('selected')) { - players[i].classList.add('selectable'); - } - else if (!selectableTargets && players[i].classList.contains('selectable')) { - selectableTargets = true; - } - if (players[i].instance) { - if (players[i].classList.contains('selected')) { - players[i].instance.classList.add('selected'); - } - else { - players[i].instance.classList.remove('selected'); - } - if (players[i].classList.contains('selectable')) { - players[i].instance.classList.add('selectable'); - } - else { - players[i].instance.classList.remove('selectable'); - } - } - } - if (ui.selected.targets.length < range[0]) { - if (!event.forced || selectableTargets || event.complexSelect) { - ok = false; - } - } - if (range[1] <= -1 && ui.selected.targets.length == 0 && event.targetRequired) { - ok = false; - } - } - if (custom.add.target) { - custom.add.target(); - } - } - if (!event.skill && get.noSelected() && !_status.noconfirm) { - const skills = []; - if (event._skillChoice) { - let skills2 = event._skillChoice; - for (let i = 0; i < skills2.length; i++) { - if (event.isMine() || !event._aiexclude.includes(skills2[i])) { - skills.push(skills2[i]); - } - } - } - else { - let skills2; - if (get.mode() == 'guozhan' && player.hasSkillTag('nomingzhi', false, null, true)) { - skills2 = player.getSkills(false, true, false); - } - else { - skills2 = player.getSkills('invisible', true, false); - } - skills2 = game.filterSkills(skills2.concat(lib.skill.global), player, player.getSkills('e').concat(lib.skill.global)); - event._skillChoice = []; - game.expandSkills(skills2); - for (let i = 0; i < skills2.length; i++) { - const info = get.info(skills2[i]); - if (!info) throw new ReferenceError(`Cannot find ${skills2[i]} in lib.skill`); - let enable = false; - if (typeof info.enable == 'function') enable = info.enable(event); - else if (Array.isArray(info.enable)) enable = info.enable.includes(event.name); - else if (info.enable == 'phaseUse') enable = (event.type == 'phase'); - else if (typeof info.enable == 'string') enable = (info.enable == event.name); - if (enable) { - if (!game.expandSkills(player.getSkills(false).concat(lib.skill.global)).includes(skills2[i]) && (info.noHidden || get.mode() != 'guozhan' || player.hasSkillTag('nomingzhi', false, null, true))) enable = false; - if (info.filter && !info.filter(event, player)) enable = false; - if (info.viewAs && typeof info.viewAs != 'function' && event.filterCard && !event.filterCard(info.viewAs, player, event)) enable = false; - if (info.viewAs && typeof info.viewAs != 'function' && info.viewAsFilter && info.viewAsFilter(player) == false) enable = false; - if (info.usable && get.skillCount(skills2[i]) >= info.usable) enable = false; - if (info.chooseButton && _status.event.noButton) enable = false; - if (info.round && (info.round - (game.roundNumber - player.storage[skills2[i] + '_roundcount']) > 0)) enable = false; - for (const item in player.storage) { - if (item.startsWith('temp_ban_')) { - if(player.storage[item] !== true) continue; - const skillName = item.slice(9); - if (lib.skill[skillName]) { - const skills=game.expandSkills([skillName]); - if(skills.includes(skills2[i])) { - enable = false; break; - } - } - } - } - } - if (enable) { - if (event.isMine() || !event._aiexclude.includes(skills2[i])) { - skills.add(skills2[i]); - } - event._skillChoice.add(skills2[i]); - } - } - } + const useCache = !lib.config.compatiblemode && !event.skill && !event.multitarget + && ['button', 'card', 'target'].every(type => { + if (!event[`filter${uppercaseType(type)}`]) return true; + // if (typeof event[`select${uppercaseType(type)}`] === 'function') return false; + if (get.select(event[`select${uppercaseType(type)}`])[1] < 0) return false; + if (type === "button") type = "select"; + return !event[`complex${uppercaseType(type)}`]; + }); + + ['button', 'card', 'target'].forEach(type => { + if (!event[`filter${uppercaseType(type)}`]) return; + if (!ok) game.uncheck(type); + else ({ ok, auto = auto } = game.Check[type](event, useCache)); + }); + + game.Check.skill(event); - let globalskills = []; - let globallist = lib.skill.global.slice(0); - game.expandSkills(globallist); - for (let i = 0; i < skills.length; i++) { - if (globallist.includes(skills[i])) { - globalskills.push(skills.splice(i--, 1)[0]); - } - } - let equipskills = []; - let ownedskills = player.getSkills('invisible', false); - game.expandSkills(ownedskills); - for (let i = 0; i < skills.length; i++) { - if (!ownedskills.includes(skills[i])) { - equipskills.push(skills.splice(i--, 1)[0]); - } - } - if (equipskills.length) { - ui.create.skills3(equipskills); - } - else if (ui.skills3) { - ui.skills3.close(); - } - if (skills.length) { - ui.create.skills(skills); - } - else if (ui.skills) { - ui.skills.close(); - } - if (globalskills.length) { - ui.create.skills2(globalskills); - } - else if (ui.skills2) { - ui.skills2.close(); - } - } - else { - if (ui.skills) { - ui.skills.close() - } - if (ui.skills2) { - ui.skills2.close() - } - if (ui.skills3) { - ui.skills3.close() - } - } _status.multitarget = false; - let skillinfo = get.info(_status.event.skill); - if (_status.event.name == 'chooseToUse') { - if (skillinfo && skillinfo.multitarget && !skillinfo.multiline) { - _status.multitarget = true; - } - if ((skillinfo && skillinfo.viewAs && typeof skillinfo.viewAs != 'function') || !_status.event.skill) { - let cardinfo = get.info(get.card()); + const skillinfo = get.info(event.skill)||{}; + if (_status.event.multitarget) _status.multitarget = true; + else if (_status.event.name === 'chooseToUse') { + if (skillinfo.multitarget && !skillinfo.multiline) _status.multitarget = true; + if (skillinfo.viewAs && typeof skillinfo.viewAs !== 'function') { + const cardinfo = get.info(get.card()); if (cardinfo && (cardinfo.multitarget || cardinfo.complexSelect) && !cardinfo.multiline) { _status.multitarget = true; } } } - else if (_status.event.multitarget) { - _status.multitarget = true; + + player.node.equips.classList.remove('popequip'); + if (event.filterCard && lib.config.popequip && !_status.nopopequip && get.is.phoneLayout() && + typeof event.position === 'string' && event.position.includes('e') && + player.node.equips.querySelector('.card.selectable')) { + player.node.equips.classList.add('popequip'); + auto_confirm = false; } - if (event.isMine()) { - if (game.chess && game.me && get.config('show_distance')) { - for (let i = 0; i < players.length; i++) { - if (players[i] == game.me) { - players[i].node.action.hide(); - } - else { - players[i].node.action.show(); - let dist = get.distance(game.me, players[i], 'pure'); - let dist2 = get.distance(game.me, players[i]); - players[i].node.action.innerHTML = '距离:' + dist2 + '/' + dist; - if (dist > 7) { - players[i].node.action.classList.add('thunder'); - } - else { - players[i].node.action.classList.remove('thunder'); - } - } - } - } - if (ok && (!event.filterOk || event.filterOk()) && auto && (auto_confirm || (skillinfo && skillinfo.direct)) && (!_status.mousedragging || !_status.mouseleft) && - !_status.mousedown && !_status.touchnocheck) { - if (ui.confirm) { - if (!skillinfo || !skillinfo.preservecancel) { - ui.confirm.close(); - } - } - if (skillinfo && skillinfo.preservecancel && !ui.confirm) { - ui.create.confirm('c'); - } - if (event.skillDialog == true) event.skillDialog = false; - ui.click.ok(); - _status.mousedragging = null; - } - else { - ui.arena.classList.add('selecting'); - if (event.filterTarget && (!event.filterCard || !event.position || (typeof event.position == 'string' && event.position.indexOf('e') == -1))) { - ui.arena.classList.add('tempnoe'); - } - game.countChoose(); - if (!_status.noconfirm && !_status.event.noconfirm) { - if (!_status.mousedown || _status.mouseleft) { - let str = ''; - if (ok && (!event.filterOk || event.filterOk())) str += 'o'; - if (!event.forced && !event.fakeforce && get.noSelected()) str += 'c'; - ui.create.confirm(str); - } - } - } - if (ui.confirm && ui.confirm.lastChild.link == 'cancel') { - if (_status.event.type == 'phase' && !_status.event.skill) { - ui.confirm.lastChild.innerHTML = '结束'; - } - else { - ui.confirm.lastChild.innerHTML = '取消'; - } - } + + if (event.isMine() && game.chess && get.config('show_distance') && game.me) { + const players = game.players.slice(); + if (event.deadTarget) players.addArray(game.dead); + players.forEach(player => { + if (player === game.me) return player.node.action.hide(); + player.node.action.show(); + let dist = get.distance(game.me, player, 'pure'); + let dist2 = get.distance(game.me, player); + player.node.action.innerHTML = `距离:${dist2}/${dist}`; + if (dist > 7) player.node.action.classList.add('thunder'); + else player.node.action.classList.remove('thunder'); + }); } + + ok = ok && (!event.filterOk || event.filterOk()); + let confirm = ''; + if (ok) confirm += 'o'; + if (!event.forced && !event.fakeforce && get.noSelected()) confirm += 'c'; + if (event.isMine()) game.Check.confirm(event, confirm); + + game.callHook("checkEnd", [event, { ok, auto, auto_confirm }]); + + // if (ui.confirm && ui.confirm.lastChild.link == 'cancel') { + // if (_status.event.type == 'phase' && !_status.event.skill) { + // ui.confirm.lastChild.innerHTML = '结束'; + // } + // else { + // ui.confirm.lastChild.innerHTML = '取消'; + // } + // } return ok; } + static Check = class extends Uninstantable { + static processSelection({ type, items, event, useCache, isSelectable }) { + let ok = true, auto; + let selectableItems = false; + const uppercaseType = (type) => type[0].toUpperCase() + type.slice(1); + const uiSelected = ui.selected[`${type}s`]; + const range = get.select(event[`select${uppercaseType(type)}`]); + + if (event.forceAuto && uiSelected.length === range[1]) auto = true; + else if (range[0] !== range[1] || range[0] > 1) auto = false; + + let cache; + let firstCheck = false; + + if (useCache) { + if (!event[`_${type}Choice`]) event[`_${type}Choice`] = {}; + let cacheId = 0; + for (let Type of ['button', 'card', 'target']) { + if (type === Type) break; + if (Type === "target") Type = "player"; + ui.selected[`${Type}s`].forEach(i => cacheId ^= i[`${Type}id`]); + } + if (!event[`_${type}Choice`][cacheId]) { + event[`_${type}Choice`][cacheId] = []; + firstCheck = true; + } + cache = event[`_${type}Choice`][cacheId]; + } + + items.forEach(item => { + let selectable; + if (!lib.filter.cardAiIncluded(item)) selectable = false; + else if (useCache && !firstCheck) selectable = cache.includes(item); + else selectable = isSelectable(item, event); + + if (range[1] <= -1) { + if (selectable) { + item.classList.add('selected'); + uiSelected.add(item); + } else { + item.classList.remove('selected'); + uiSelected.remove(item); + } + if (item.updateTransform) item.updateTransform(selectable); + } else { + if (selectable && uiSelected.length < range[1]) { + item.classList.add('selectable'); + if (firstCheck) cache.push(item); + } + else item.classList.remove('selectable'); + } + + if (item.classList.contains('selectable')) selectableItems = true; + else if (item.classList.contains('selected')) item.classList.add('selectable'); + + game.callHook(`check${uppercaseType(type)}`, [item, event]); + }); + + if (event[`${type}Required`] && uiSelected.length === 0) ok = false; + else if (uiSelected.length < range[0] && (!event.forced || selectableItems || event.complexSelect)) ok = false; + + if (event.custom && event.custom.add[type]) event.custom.add[type](); + + return { ok, auto }; + } + static button(event, useCache) { + const player = event.player; + const buttons = event.dialog.buttons; + const isSelectable = (button, event) => { + if (!lib.filter.buttonIncluded(button)) return false; + if (button.classList.contains('unselectable')) return false; + return event.filterButton(button, player); + } + return game.Check.processSelection({ type: 'button', items: buttons, event, useCache, isSelectable }); + } + static card(event, useCache) { + const player = event.player; + const cards = player.getCards(event.position); + const isSelectable = (card, event) => { + if (card.classList.contains('uncheck')) return false; + if (player.isOut()) return false; + if (!lib.filter.cardRespondable(card, player)) return false; + return event.filterCard(card, player); + } + return game.Check.processSelection({ type: 'card', items: cards, event, useCache, isSelectable }); + } + static target(event, useCache) { + const player = event.player; + const card = get.card(); + const targets = game.players.slice(); + if (event.deadTarget) targets.addArray(game.dead); + const isSelectable = (target, event) => { + if (game.chess && !event.chessForceAll && player && get.distance(player, target, 'pure') > 7) return false; + if (target.isOut()) return false; + return event.filterTarget(card, player, target); + } + return game.Check.processSelection({ type: 'target', items: targets, event, useCache, isSelectable }); + } + static skill(event) { + if (ui.skills) ui.skills.close(); + if (ui.skills2) ui.skills2.close(); + if (ui.skills3) ui.skills3.close(); + if (event.skill || !get.noSelected() || _status.noconfirm) return; + + const player = event.player; + if (!event._skillChoice) event._skillChoice = game.expandSkills(player.getSkills('invisible').concat(lib.skill.global)).filter(skill => lib.filter.filterEnable(event, player, skill)); + + const skills = event._skillChoice.filter(i => event.isMine() || !event._aiexclude.includes(i)); + const globallist = game.expandSkills(lib.skill.global.slice()); + const ownedlist = game.expandSkills(player.getSkills('invisible', false)); + + const ownedSkills = [], globalSkills = [], equipSkills = []; + skills.forEach(skill => { + if (globallist.includes(skill)) globalSkills.push(skill); + else if (!ownedlist.includes(skill)) equipSkills.push(skill); + else ownedSkills.push(skill); + }); + + if (ownedSkills.length) ui.create.skills(ownedSkills); + if (globalSkills.length) ui.create.skills2(globalSkills); + if (equipSkills.length) ui.create.skills3(equipSkills); + } + static confirm(event, confirm) { + ui.arena.classList.add('selecting'); + if (event.filterTarget && (!event.filterCard || !event.position || (typeof event.position == 'string' && !event.position.includes('e')))) { + ui.arena.classList.add('tempnoe'); + } + game.countChoose(); + if (!_status.noconfirm && !_status.event.noconfirm && (_status.mouseleft || !_status.mousedown)) { + ui.create.confirm(confirm); + } + } + } static uncheck(...args) { - let i, j; - if (game.chess) { - let shadows = ui.chessContainer.getElementsByClassName('playergrid temp'); - while (shadows.length) { - shadows[0].remove(); - } - } - if ((args.length == 0 || args.includes('card')) && _status.event.player) { - let cards = _status.event.player.getCards('hejsx'); - for (j = 0; j < cards.length; j++) { - cards[j].classList.remove('selected'); - cards[j].classList.remove('selectable'); - if (cards[j]._tempName) { - cards[j]._tempName.delete(); - delete cards[j]._tempName; - } - cards[j].updateTransform(); - } - ui.selected.cards.length = 0; - _status.event.player.node.equips.classList.remove('popequip'); - } - let players = game.players.slice(0); + if (args.length === 0) args = ['button', 'card', 'target']; + const event = _status.event; + const players = game.players.slice(); if (_status.event.deadTarget) players.addArray(game.dead); - if ((args.length == 0 || args.includes('target'))) { - for (j = 0; j < players.length; j++) { - players[j].classList.remove('selected'); - players[j].classList.remove('selectable'); - if (players[j].instance) { - players[j].instance.classList.remove('selected'); - players[j].instance.classList.remove('selectable'); - } - } - ui.selected.targets.length = 0; + + game.callHook("uncheckBegin", [event, args]); + + if (game.chess) { + const shadows = Array.from(ui.chessContainer.querySelectorAll('.playergrid.temp')); + shadows.forEach(i => i.remove()); } - if ((args.length == 0 || args.includes('button')) && _status.event.dialog && _status.event.dialog.buttons) { - for (let j = 0; j < _status.event.dialog.buttons.length; j++) { - _status.event.dialog.buttons[j].classList.remove('selectable'); - _status.event.dialog.buttons[j].classList.remove('selected'); - } + if(event.player) event.player.node.equips.classList.remove('popequip'); + + if (args.includes('button') && event.dialog && event.dialog.buttons) { + event.dialog.buttons.forEach(button => { + button.classList.remove('selectable'); + button.classList.remove('selected'); + game.callHook("uncheckButton", [button, event]); + }); ui.selected.buttons.length = 0; } - if (args.length == 0) { + if (args.includes('card') && event.player) { + const cards = event.player.getCards('hejsx'); + cards.forEach(card => { + card.classList.remove('selected'); + card.classList.remove('selectable'); + card.updateTransform(false); + game.callHook("uncheckCard", [card, event]); + }); + ui.selected.cards.length = 0; + } + if (args.includes('target')) { + players.forEach(target => { + target.classList.remove('selected'); + target.classList.remove('selectable'); + game.callHook("uncheckTarget", [target, event]); + }); + ui.selected.targets.length = 0; + } + if (args.length === 3) { ui.arena.classList.remove('selecting'); ui.arena.classList.remove('tempnoe'); _status.imchoosing = false; @@ -6340,20 +6125,17 @@ export class Game extends Uninstantable { _status.mousedragging = null; _status.mousedragorigin = null; - while (ui.touchlines.length) { - ui.touchlines.shift().delete(); - } + ui.touchlines.forEach(i => i.delete()); + ui.touchlines.length = 0; } ui.canvas.width = ui.arena.offsetWidth; ui.canvas.height = ui.arena.offsetHeight; - for (let i = 0; i < players.length; i++) { - players[i].unprompt(); - } - for (let i = 0; i < _status.dragline.length; i++) { - if (_status.dragline[i]) _status.dragline[i].remove(); - } - ui.arena.classList.remove('dragging'); + players.forEach(i => i.unprompt()); + _status.dragline.forEach(i => i && i.remove()); _status.dragline.length = 0; + ui.arena.classList.remove('dragging'); + + game.callHook("uncheckEnd", [event, args]); } /** * @param { Player } player1 diff --git a/noname/get/index.js b/noname/get/index.js index 82b671517..5ebe6b942 100644 --- a/noname/get/index.js +++ b/noname/get/index.js @@ -1791,7 +1791,7 @@ export class Get extends Uninstantable { return game.checkMod(card, owner, game.checkMod(card, card.suit, 'suit', owner), 'cardsuit', owner); } } - if (lib.suits.includes(card.suit)) return card.suit; + if (card.suit === 'unsure' || lib.suits.includes(card.suit)) return card.suit; return 'none'; } } @@ -1810,7 +1810,7 @@ export class Get extends Uninstantable { } return color; } - else if (Object.keys(lib.color).includes(card.color)) { + else if (card.color === 'unsure' || Object.keys(lib.color).includes(card.color)) { return card.color; } else if (Array.isArray(card.cards) && !lib.suit.includes(card.suit)) { @@ -1835,7 +1835,8 @@ export class Get extends Uninstantable { var number = null; if ('number' in card) { number = card.number; - if (typeof number != 'number') number = null; + if (number === 'unsure') return number; + else if (typeof number != 'number') number = null; } else { if (card.cards && card.cards.length == 1) number = get.number(card.cards[0], false); @@ -2226,6 +2227,12 @@ export class Get extends Uninstantable { } return ''; } + static menuZoom(){ + if(game.menuZoom === undefined || game.menuZoom === null){ + return game.documentZoom; + } + return game.menuZoom; + } static strNumber(num) { switch (num) { case 1: return 'A'; diff --git a/noname/get/is.js b/noname/get/is.js index a5dee8a87..143bde0f1 100644 --- a/noname/get/is.js +++ b/noname/get/is.js @@ -131,8 +131,8 @@ export class Is extends Uninstantable { * @param { Card | VCard } card */ // @ts-ignore - static vituralCard(card) { - return card.isCard || (!("cards" in card) || !Array.isArray(card.cards) || card.cards.length == 0); + static virtualCard(card) { + return (!("cards" in card) || !Array.isArray(card.cards) || card.cards.length === 0); } /** * 是否是转化牌 @@ -147,7 +147,9 @@ export class Is extends Uninstantable { * @param { Card | VCard } card */ // @ts-ignore - static ordinaryCard(card) { return card.isCard && ("cards" in card) && Array.isArray(card.cards) && card.cards.length == 1 } + static ordinaryCard(card) { + return card.isCard && ("cards" in card) && Array.isArray(card.cards) && card.cards.length === 1 + } /** * 押韵判断 * @param { string } str1 diff --git a/noname/library/element/button.js b/noname/library/element/button.js index 4fcf2a866..4785b1648 100644 --- a/noname/library/element/button.js +++ b/noname/library/element/button.js @@ -30,6 +30,7 @@ export class Button extends HTMLDivElement { const intro = button.querySelector('.intro'); if (intro) intro.remove(); } + if (!button.buttonid) button.buttonid = get.id(); // @ts-ignore button._args = [item, type, position, noClick, button]; return button; diff --git a/noname/library/element/content.js b/noname/library/element/content.js index 0e3b60436..83fb76409 100644 --- a/noname/library/element/content.js +++ b/noname/library/element/content.js @@ -85,15 +85,19 @@ export const Content = { }, //变更技能 async changeSkills (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; + //if (!event.addSkill.length&&!event.removeSkill.length) return; //手动触发时机 await event.trigger('changeSkillsBefore'); await event.trigger('changeSkillsBegin'); @@ -2243,6 +2247,7 @@ export const Content = { } "step 2"; var info = get.info(event.skill); + if (result && result.control) result.bool = !result.control.includes('cancel'); if (!result || !result.bool) return; var autodelay = info.autodelay; if (typeof autodelay == 'function') autodelay = autodelay(trigger, player); @@ -3146,6 +3151,7 @@ export const Content = { next.set('ai', info.chooseButton.check || function () { return 1; }); next.set('filterButton', info.chooseButton.filter || function () { return true; }); next.set('selectButton', info.chooseButton.select || 1); + next.set('complexSelect', info.chooseButton.complexSelect !== false); next.set('filterOk', info.chooseButton.filterOk || (() => true)); if (event.id) next._parent_id = event.id; next.type = 'chooseToUse_button'; @@ -4541,6 +4547,7 @@ export const Content = { event.dialog.style.display = ''; event.dialog.open(); } + // if (['chooseCharacter', 'chooseButtonOL'].includes(event.getParent().name)) event.complexSelect = true; var filterButton = event.filterButton || function () { return true; }; var selectButton = get.select(event.selectButton); var buttons = event.dialog.buttons; @@ -6139,73 +6146,7 @@ export const Content = { } if (cardaudio) game.broadcastAll((player, card) => { game.playCardAudio(card, player); - /* - if(!lib.config.background_audio||get.type(card)=='equip'&&!lib.config.equip_audio) return; - const sex=player.sex=='female'?'female':'male'; - var nature=get.natureList(card)[0]; - if(card.name=='sha'&&['fire','thunder','ice','stab'].includes(nature)){ - game.playAudio('card',sex,`${card.name}_${nature}`); - return; - } - const audio=lib.card[card.name].audio; - if(typeof audio=='string'){ - const audioInfo=audio.split(':'); - if(audio.startsWith('db:')) game.playAudio(`${audioInfo[0]}:${audioInfo[1]}`,audioInfo[2],`${card.name}_${sex}.${audioInfo[3]||'mp3'}`); - else if(audio.startsWith('ext:')) game.playAudio(`${audioInfo[0]}:${audioInfo[1]}`,`${card.name}_${sex}.${audioInfo[2]||'mp3'}`); - else game.playAudio('card',sex,`${audioInfo[0]}.${audioInfo[1]||'mp3'}`); - } - else game.playAudio('card',sex,card.name);*/ }, player, card); - if (event.animate != false && event.line != false) { - if (card.name == 'wuxie' && event.getParent()._info_map) { - var evtmap = event.getParent()._info_map; - if (evtmap._source) evtmap = evtmap._source; - var lining = (evtmap.multitarget ? evtmap.targets : evtmap.target) || event.player; - if (Array.isArray(lining) && event.getTrigger().name == 'jiedao') { - player.line(lining[0], 'green'); - } - else { - player.line(lining, 'green'); - } - } - else if (card.name == 'youdishenru' && event.getParent().source) { - var lining = event.getParent().sourcex || event.getParent().source2 || event.getParent().source; - if (lining == player && event.getParent().sourcex2) { - lining = event.getParent().sourcex2; - } - if (Array.isArray(lining) && event.getTrigger().name == 'jiedao') { - player.line(lining[0], 'green'); - } - else { - player.line(lining, 'green'); - } - } - else { - var config = {}; - var nature = get.natureList(card)[0]; - 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) { - player.line2(targets, config); - } - else { - player.line(targets, config); - } - } - if (event.throw !== false) player.$throw(cards); - if (lib.config.sync_speed && cards[0] && cards[0].clone) { - var waitingForTransition = get.time(); - event.waitingForTransition = waitingForTransition; - cards[0].clone.listenTransition(function () { - if (_status.waitingForTransition == waitingForTransition && _status.paused) { - game.resume(); - } - delete event.waitingForTransition; - }); - } - } event.id = get.id(); if (!Array.isArray(event.excluded)) event.excluded = []; if (!Array.isArray(event.directHit)) event.directHit = []; @@ -6243,7 +6184,64 @@ export const Content = { } } } - if (targets.length) { + + if (event.animate != false) { + if (event.throw !== false){ + player.$throw(cards); + if (lib.config.sync_speed && cards[0] && cards[0].clone) { + var waitingForTransition = get.time(); + event.waitingForTransition = waitingForTransition; + cards[0].clone.listenTransition(function () { + if (_status.waitingForTransition == waitingForTransition && _status.paused) { + game.resume(); + } + delete event.waitingForTransition; + }); + } + } + } + event.trigger('useCard0'); + "step 1"; + if (event.animate != false && event.line != false && !event.hideTargets) { + if (card.name == 'wuxie' && event.getParent()._info_map) { + var evtmap = event.getParent()._info_map; + if (evtmap._source) evtmap = evtmap._source; + var lining = (evtmap.multitarget ? evtmap.targets : evtmap.target) || event.player; + if (Array.isArray(lining) && event.getTrigger().name == 'jiedao') { + player.line(lining[0], 'green'); + } + else { + player.line(lining, 'green'); + } + } + else if (card.name == 'youdishenru' && event.getParent().source) { + var lining = event.getParent().sourcex || event.getParent().source2 || event.getParent().source; + if (lining == player && event.getParent().sourcex2) { + lining = event.getParent().sourcex2; + } + if (Array.isArray(lining) && event.getTrigger().name == 'jiedao') { + player.line(lining[0], 'green'); + } + else { + player.line(lining, 'green'); + } + } + else { + var config = {}; + var nature = get.natureList(card)[0]; + 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) { + player.line2(targets, config); + } + else { + player.line(targets, config); + } + } + } + if (targets.length && !event.hideTargets) { var str = (targets.length == 1 && targets[0] == player) ? '#b自己' : targets; if (cards.length && !card.isCard) { if (event.addedTarget) { @@ -6287,11 +6285,11 @@ export const Content = { game.logv(player, [card, cards], targets); } event.trigger('useCard1'); - "step 1"; - event.trigger('yingbian'); "step 2"; - event.trigger('useCard2'); + event.trigger('yingbian'); "step 3"; + event.trigger('useCard2'); + "step 4"; event.trigger('useCard'); event._oncancel = function () { game.broadcastAll(function (id) { @@ -6301,7 +6299,7 @@ export const Content = { } }, event.id); }; - "step 4"; + "step 5"; event.sortTarget = function (animate, sort) { var info = get.info(card, false); if (num == 0 && targets.length > 1) { @@ -6328,7 +6326,7 @@ export const Content = { } return null; }; - "step 5"; + "step 6"; if (event.all_excluded) return; if (!event.triggeredTargets1) event.triggeredTargets1 = []; var target = event.getTriggerTarget(targets, event.triggeredTargets1); @@ -6352,7 +6350,7 @@ export const Content = { if (event.forceDie) next.forceDie = true; event.redo(); } - "step 6"; + "step 7"; if (event.all_excluded) return; if (!event.triggeredTargets2) event.triggeredTargets2 = []; var target = event.getTriggerTarget(targets, event.triggeredTargets2); @@ -6376,7 +6374,7 @@ export const Content = { if (event.forceDie) next.forceDie = true; event.redo(); } - "step 7"; + "step 8"; var info = get.info(card, false); if (!info.nodelay && event.animate != false) { if (event.delayx !== false) { @@ -6389,7 +6387,7 @@ export const Content = { } } } - "step 8"; + "step 9"; if (event.all_excluded) return; if (!event.triggeredTargets3) event.triggeredTargets3 = []; var target = event.getTriggerTarget(targets, event.triggeredTargets3); @@ -6413,7 +6411,7 @@ export const Content = { if (event.forceDie) next.forceDie = true; event.redo(); } - "step 9"; + "step 10"; if (event.all_excluded) return; if (!event.triggeredTargets4) event.triggeredTargets4 = []; var target = event.getTriggerTarget(targets, event.triggeredTargets4); @@ -6440,7 +6438,7 @@ export const Content = { } event.redo(); } - "step 10"; + "step 11"; if (event.all_excluded) return; event.effectedCount++; event.num = 0; @@ -6481,7 +6479,7 @@ export const Content = { next.addedTargets = event.addedTargets; if (event.forceDie) next.forceDie = true; } - "step 11"; + "step 12"; if (event.all_excluded) return; var info = get.info(card, false); if (num == 0 && targets.length > 1) { @@ -6545,13 +6543,13 @@ export const Content = { game.delayx(0.5); } } - "step 12"; + "step 13"; if (event.all_excluded) return; if (!get.info(event.card, false).multitarget && num < targets.length - 1 && !event.cancelled) { event.num++; - event.goto(11); + event.goto(12); } - "step 13"; + "step 14"; if (event.all_excluded) return; if (get.info(card, false).contentAfter) { var next = game.createEvent(card.name + 'ContentAfter'); @@ -6565,15 +6563,15 @@ export const Content = { next.type = 'postcard'; if (event.forceDie) next.forceDie = true; } - "step 14"; + "step 15"; if (event.all_excluded) return; if (event.effectedCount < event.effectCount) { if (document.getElementsByClassName('thrown').length) { if (event.delayx !== false && get.info(event.card, false).finalDelay !== false) game.delayx(); } - event.goto(10); + event.goto(11); } - "step 15"; + "step 16"; if (event.postAi) { event.player.logAi(event.targets, event.card); } @@ -6587,7 +6585,7 @@ export const Content = { else { event.finish(); } - "step 16"; + "step 17"; event._oncancel(); }, useSkill: function () { diff --git a/noname/library/element/contents.js b/noname/library/element/contents.js index c46269f49..163a9869b 100644 --- a/noname/library/element/contents.js +++ b/noname/library/element/contents.js @@ -295,5 +295,54 @@ export const Contents = { 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'); + }, + ], }; diff --git a/noname/library/element/gameEvent.js b/noname/library/element/gameEvent.js index 2eddf8f6e..3c0912053 100644 --- a/noname/library/element/gameEvent.js +++ b/noname/library/element/gameEvent.js @@ -409,7 +409,18 @@ export class GameEvent { catch { throw new Error(`Content ${item} may not exist.\nlib.element.content[${item}] = ${lib.element.content[item]}`); } - this.content = 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; @@ -453,6 +464,7 @@ export class GameEvent { return this; } resume() { + delete this._buttonChoice; delete this._cardChoice; delete this._targetChoice; delete this._skillChoice; @@ -527,6 +539,7 @@ export class GameEvent { complexSelect: this.complexSelect, complexCard: this.complexCard, complexTarget: this.complexTarget, + _buttonChoice: this._buttonChoice, _cardChoice: this._cardChoice, _targetChoice: this._targetChoice, _skillChoice: this._skillChoice, @@ -630,6 +643,7 @@ export class GameEvent { } delete this.fakeforce; } + delete this._buttonChoice; delete this._cardChoice; delete this._targetChoice; delete this._skillChoice; @@ -652,6 +666,7 @@ export class GameEvent { this.complexTarget = this._backup.complexTarget; this.ai1 = this._backup.ai1; this.ai2 = this._backup.ai2; + this._buttonChoice = this._backup._buttonChoice; this._cardChoice = this._backup._cardChoice; this._targetChoice = this._backup._targetChoice; this._skillChoice = this._backup._skillChoice; diff --git a/noname/library/element/player.js b/noname/library/element/player.js index c6e2affeb..b0f1bf01e 100644 --- a/noname/library/element/player.js +++ b/noname/library/element/player.js @@ -728,7 +728,10 @@ export class Player extends HTMLDivElement { virtualCard.init(['', '', card, info && info.cardnature]); } else if (get.itemtype(card) == 'card') executeDelayCardEffect.card = card; - else _status.event.next.remove(executeDelayCardEffect); + else { + _status.event.next.remove(executeDelayCardEffect); + executeDelayCardEffect.resolve(); + } executeDelayCardEffect.judge = judge; executeDelayCardEffect.judge2 = judge2; executeDelayCardEffect.setContent('executeDelayCardEffect'); @@ -759,7 +762,10 @@ export class Player extends HTMLDivElement { const isArray = Array.isArray(cards); if (cards && !isArray) gift.cards = [cards]; else if (isArray && cards.length) gift.cards = cards; - else _status.event.next.remove(gift); + else { + _status.event.next.remove(gift); + gift.resolve(); + } gift.deniedGifts = []; gift.setContent('gift'); gift._args = Array.from(arguments); @@ -825,7 +831,10 @@ export class Player extends HTMLDivElement { const isArray = Array.isArray(cards); if (cards && !isArray) recast.cards = [cards]; else if (isArray && cards.length) recast.cards = cards; - else _status.event.next.remove(recast); + else { + _status.event.next.remove(recast); + recast.resolve(); + } if (typeof recastingLose != 'function') { if (recastingLose === null) console.trace(`recast的recastingLose参数不应传入null,可以用void 0或undefined占位`); recastingLose = (player, cards) => player.loseToDiscardpile(cards).log = false; @@ -1073,6 +1082,7 @@ export class Player extends HTMLDivElement { if (!next.source) next.source = _status.event.player; if (!next.slots.length) { _status.event.next.remove(next); + next.resolve(); } next.setContent('disableEquip'); return next; @@ -1110,6 +1120,7 @@ export class Player extends HTMLDivElement { if (!next.source) next.source = _status.event.player; if (!next.slots.length) { _status.event.next.remove(next); + next.resolve(); } next.setContent('enableEquip'); return next; @@ -1147,6 +1158,7 @@ export class Player extends HTMLDivElement { if (!next.source) next.source = _status.event.player; if (!next.slots.length) { _status.event.next.remove(next); + next.resolve(); } next.setContent('expandEquip'); return next; @@ -2043,8 +2055,11 @@ export class Player extends HTMLDivElement { return true; } $disableJudge() { - game.addVideo('$disableJudge', this); this.storage._disableJudge = true; + for (let i = 0; i < this.node.judges.childNodes.length; i++) { + if (this.node.judges.childNodes[i].classList.contains('feichu')) return; + } + game.addVideo('$disableJudge', this); var card = game.createCard('disable_judge', '', ''); card.fix(); card.classList.add('feichu'); @@ -4255,7 +4270,8 @@ export class Player extends HTMLDivElement { var next = game.createEvent('chooseButton'); for (var i = 0; i < arguments.length; i++) { if (typeof arguments[i] == 'boolean') { - next.forced = arguments[i]; + if (!next.forced) next.forced = arguments[i]; + else next.complexSelect = arguments[i]; } else if (get.itemtype(arguments[i]) == 'dialog') { next.dialog = arguments[i]; @@ -4281,6 +4297,7 @@ export class Player extends HTMLDivElement { if (next.filterButton == undefined) next.filterButton = lib.filter.filterButton; if (next.selectButton == undefined) next.selectButton = [1, 1]; if (next.ai == undefined) next.ai = function () { return 1; }; + if (next.complexSelect !== false) next.complexSelect = true; next.setContent('chooseButton'); next._args = Array.from(arguments); next.forceDie = true; @@ -4766,7 +4783,10 @@ export class Player extends HTMLDivElement { } if (get.itemtype(cards) == 'card') next.cards = [cards]; else if (get.itemtype(cards) == 'cards') next.cards = cards.slice(0); - else _status.event.next.remove(next); + else { + _status.event.next.remove(next); + next.resolve(); + } next.setContent('showCards'); next._args = Array.from(arguments); return next; @@ -5009,7 +5029,10 @@ export class Player extends HTMLDivElement { this.ai.tempIgnore.add(next.targets[i]); } } - if (typeof this.logAi == 'function' && !next.noai && !get.info(next.card).noai) { + if (typeof this.logAi == 'function' && !next.noai && !get.info(next.card).noai && !this.hasSkillTag(this, true, { + card: next.card, + targets: next.targets, + }, true)) { var postAi = get.info(next.card).postAi; if (postAi && postAi(next.targets)) { next.postAi = true; @@ -5123,7 +5146,10 @@ export class Player extends HTMLDivElement { } } if (next.num == undefined) next.num = 1; - if (next.num <= 0) _status.event.next.remove(next); + if (next.num <= 0) { + _status.event.next.remove(next); + next.resolve(); + } next.setContent('draw'); if (lib.config.mode == 'stone' && _status.mode == 'deck' && next.drawDeck == undefined && !next.player.isMin() && next.num > 1) { @@ -5207,7 +5233,10 @@ export class Player extends HTMLDivElement { next.notBySelf = true; } } - if (next.cards == undefined) _status.event.next.remove(next); + if (next.cards == undefined) { + _status.event.next.remove(next); + next.resolve(); + } next.setContent('discard'); return next; } @@ -5241,7 +5270,10 @@ export class Player extends HTMLDivElement { next.blank = true; } } - if (next.cards == undefined) _status.event.next.remove(next); + if (next.cards == undefined) { + _status.event.next.remove(next); + next.resolve(); + } next.setContent('loseToDiscardpile'); return next; } @@ -5621,6 +5653,7 @@ export class Player extends HTMLDivElement { } if (!next.cards || !next.cards.length) { _status.event.next.remove(next); + next.resolve(); } else { if (next.position == undefined) next.position = ui.discardPile; @@ -5738,7 +5771,10 @@ export class Player extends HTMLDivElement { if (next.cards == undefined && !nocard) next.cards = event.cards; if (next.source == undefined && !nosource) next.source = event.customSource || event.player; if (next.num == undefined) next.num = (event.baseDamage || 1) + (event.extraDamage || 0); - if (next.num <= 0) _status.event.next.remove(next); + if (next.num <= 0) { + _status.event.next.remove(next); + next.resolve(); + } next.setContent('recover'); return next; } @@ -7305,7 +7341,7 @@ export class Player extends HTMLDivElement { next.forceDie = true; next.addSkill = addSkill.slice(0).unique(); next.removeSkill = removeSkill.slice(0).unique(); - next.setContent('changeSkills'); + next.setContents('changeSkills'); return next; } addSkill(skill, checkConflict, nobroadcast, addToSkills) { @@ -7434,6 +7470,22 @@ export class Player extends HTMLDivElement { _status.event.clearStepCache(); return this; } + $removeAdditionalSkills(skill, target){ + const additionalSkills = this.additionalSkills[skill]; + if (Array.isArray(additionalSkills)) { + if (typeof target === 'string') { + if (additionalSkills.includes(target)) { + additionalSkills.remove(target); + if (!additionalSkills.length) { + delete this.additionalSkills[skill]; + } + } + } + else { + delete this.additionalSkills[skill]; + } + } + } getRemovableAdditionalSkills(skill, target){ const player = this, removableSkills = []; if (this.additionalSkills[skill]) { @@ -7462,22 +7514,22 @@ export class Player extends HTMLDivElement { const player = this, skills = this.getRemovableAdditionalSkills(skill, target); if(skills.length){ player.removeSkill(skills); - if (player.additionalSkills[skill]&&player.additionalSkills[skill].length) delete player.additionalSkills[skill]; } + player.$removeAdditionalSkills(skill, target); _status.event.clearStepCache(); return this; } removeAdditionalSkills(skill, target) { const player = this, skills = this.getRemovableAdditionalSkills(skill, target); - if(skills.length){ - return player.changeSkills([], skills).set('$handle', function(player, addSkills, removeSkills){ + return player.changeSkills([], skills).set('$handle', function(player, addSkills, removeSkills){ + if(removeSkills.length>0){ game.log(player, '失去了技能', ...removeSkills.map(i => { return '#g【' + get.translation(i) + '】'; })); - player.removeSkill(skills); - if (player.additionalSkills[skill]&&player.additionalSkills[skill].length) delete player.additionalSkills[skill]; - }); - } + player.removeSkill(removeSkills); + } + player.$removeAdditionalSkills(skill, target); + }); } awakenSkill(skill, nounmark) { if (!nounmark) this.unmarkSkill(skill); @@ -7823,7 +7875,7 @@ export class Player extends HTMLDivElement { this.removeAdditionalSkill(i); } } - this[all ? 'removeSkill' : 'removeSkillLog'](list); + this[all ? 'removeSkill' : 'removeSkills'](list); this.checkConflict(); this.checkMarks(); return list; diff --git a/noname/library/element/vcard.js b/noname/library/element/vcard.js index dbb98a9ca..4cd565e83 100644 --- a/noname/library/element/vcard.js +++ b/noname/library/element/vcard.js @@ -79,6 +79,11 @@ export class VCard { if (!this.nature) this.nature = get.nature(this); } } + else if(numberOrCards === 'unsure' && !this.isCard) { + if(!this.suit) this.suit = 'unsure'; + if(!this.color) this.color = 'unsure'; + if(!this.number) this.number = 'unsure'; + } const info = get.info(this, false); if (info) { const autoViewAs = info.autoViewAs; diff --git a/noname/library/index.js b/noname/library/index.js index e74b8e9cc..b5ee89964 100644 --- a/noname/library/index.js +++ b/noname/library/index.js @@ -146,6 +146,11 @@ export class Library extends Uninstantable { } //函数钩子 + /** + * 你可以往这里加入{钩子名:函数数组},并在数组里增加你的自定义函数 + * 这样当某个地方调用game.callHook(钩子名,[...函数参数])时,就会按顺序将对应数组中的每个函数运行一遍(传参为callHook的第二个参数)。 + * 你可以将hook机制类比为event.trigger(),但是这里只能放同步代码 + */ static hooks = { // 本体势力的颜色 addGroup: [(id, _short, _name, config) => { @@ -325,6 +330,60 @@ export class Library extends Uninstantable { game.dynamicStyle.addObject(result2); } }], + //game.check + checkBegin: [], + checkEnd: [ + function autoConfirm(event, { ok, auto, auto_confirm }) { + if (!event.isMine()) return; + const skillinfo = get.info(event.skill) || {}; + if (ok && auto && (auto_confirm || skillinfo.direct) && !_status.touchnocheck + && !_status.mousedown && (!_status.mousedragging || !_status.mouseleft)) { + if (ui.confirm) ui.confirm.close(); + if (event.skillDialog === true) event.skillDialog = false; + ui.click.ok(); + _status.mousedragging = null; + if (skillinfo.preservecancel) ui.create.confirm('c'); + } + } + ], + checkButton: [], + checkCard: [ + function updateTempname(card, event) { + if (lib.config.cardtempname === 'off') return; + if (get.name(card) === card.name && get.is.sameNature(get.nature(card), card.nature, true)) return; + const node = ui.create.cardTempName(card); + if (lib.config.cardtempname !== 'default') node.classList.remove('vertical'); + }, + ], + checkTarget: [ + function updateInstance(target, event) { + if (!target.instance) return; + ['selected', 'selectable'].forEach(className => { + if (target.classList.contains(className)) { + target.instance.classList.add(className); + } else { + target.instance.classList.remove(className); + } + }); + }, + ], + uncheckBegin: [], + uncheckEnd: [], + uncheckButton: [], + uncheckCard: [ + function removeTempname(card, event) { + if (!card._tempName) return; + card._tempName.delete(); + delete card._tempName; + }, + ], + uncheckTarget: [ + function removeInstance(target, event) { + if (!target.instance) return; + target.instance.classList.remove('selected'); + target.instance.classList.remove('selectable'); + }, + ], }; /** @@ -7916,7 +7975,9 @@ export class Library extends Uninstantable { let type; try { type = typeof obj[text]; - } catch {} + } catch { + void 0; + } if (type == 'function') { className += 'function'; } @@ -8794,6 +8855,7 @@ export class Library extends Uninstantable { game.me.actused = -99; } ui.updatehl(); + delete _status.event._buttonChoice; delete _status.event._cardChoice; delete _status.event._targetChoice; delete _status.event._skillChoice; @@ -8811,6 +8873,7 @@ export class Library extends Uninstantable { game.me.actused = -99; } ui.updatehl(); + delete _status.event._buttonChoice; delete _status.event._cardChoice; delete _status.event._targetChoice; delete _status.event._skillChoice; @@ -9009,6 +9072,7 @@ export class Library extends Uninstantable { const card = lib.cheat.gn(name); if (!card) return; target.node.handcards1.appendChild(card); + delete _status.event._buttonChoice; delete _status.event._cardChoice; delete _status.event._targetChoice; delete _status.event._skillChoice; @@ -9124,6 +9188,7 @@ export class Library extends Uninstantable { for (let i = 0; i < num; i++) { const card = cards[i]; game.me.node.handcards1.appendChild(card); + delete _status.event._buttonChoice; delete _status.event._cardChoice; delete _status.event._targetChoice; delete _status.event._skillChoice; @@ -9140,6 +9205,7 @@ export class Library extends Uninstantable { for (var i = 0; i < args.length; i++) { game.me.addSkill(args[i], true); } + delete _status.event._buttonChoice; delete _status.event._cardChoice; delete _status.event._targetChoice; delete _status.event._skillChoice; @@ -9800,6 +9866,51 @@ export class Library extends Uninstantable { } return true; }, + /** + * + * @param {GameEvent} event + * @param {Player} player + * @param {string} skill + * @returns {boolean} + */ + filterEnable: function (event, player, skill) { + const info = get.info(skill); + if (!info) { + console.error(new ReferenceError('缺少info的技能:', skill)); + return false; + } + // if (!game.expandSkills(player.getSkills('invisible').concat(lib.skill.global)).includes(skill)) return false; + if (!game.expandSkills(player.getSkills(false).concat(lib.skill.global)).includes(skill)) {//hiddenSkills + if (player.hasSkillTag('nomingzhi', false, null, true)) return false; + if (get.mode() !== 'guozhan') return false; + if (info.noHidden) return false; + } + const checkEnable = enable => { + if (typeof enable === 'function') return enable(event); + if (Array.isArray(enable)) return enable.some(i => checkEnable(i)); + if (enable === 'phaseUse') return event.type === 'phase'; + if (typeof enable === 'string') return enable === event.name; + return false; + } + if (!checkEnable(info.enable)) return false; + if (info.filter && !info.filter(event, player)) return false; + if (info.viewAs && typeof info.viewAs !== 'function') { + if (info.viewAsFilter && info.viewAsFilter(player) === false) return false; + if (event.filterCard && !event.filterCard(get.autoViewAs(info.viewAs, 'unsure'), player, event)) return false; + } + if (info.usable && get.skillCount(skill) >= info.usable) return false; + if (info.chooseButton && _status.event.noButton) return false; + if (info.round && (info.round - (game.roundNumber - player.storage[skill + '_roundcount']) > 0)) return false; + for (const item in player.storage) { + if (!item.startsWith('temp_ban_')) continue; + if (player.storage[item] !== true) continue; + const skillName = item.slice(9); + if (!lib.skill[skillName]) continue; + const skills = game.expandSkills([skillName]); + if (skills.includes(skill)) return false; + } + return true; + }, characterDisabled: function (i, libCharacter) { if (!lib.character[i] || lib.character[i][4] && lib.character[i][4].includes('forbidai')) return true; if (lib.character[i][4] && lib.character[i][4].includes('unseen')) return true; @@ -11599,7 +11710,7 @@ export class Library extends Uninstantable { lose: false, delay: false, content: () => { - player.recast(cards, null, (player, cards) => { + player.recast(cards, void 0, (player, cards) => { var numberOfCardsToDraw = cards.length; cards.forEach(value => { if (lib.config.mode == 'stone' && _status.mode == 'deck' && !player.isMin() && get.type(value).startsWith('stone')) { @@ -13148,6 +13259,12 @@ export class Library extends Uninstantable { * @returns {string} */ getSpan: () => `${get.prefixSpan('经典')}${get.prefixSpan('神')}` + }], + ['旧谋', { + /** + * @returns {string} + */ + getSpan: () => `${get.prefixSpan('旧')}${get.prefixSpan('谋')}` }] ]); static groupnature = { diff --git a/noname/library/init/index.js b/noname/library/init/index.js index f63b8b9d0..0cecce180 100644 --- a/noname/library/init/index.js +++ b/noname/library/init/index.js @@ -1,13 +1,15 @@ import { nonameInitialized, assetURL, userAgent, Uninstantable, GeneratorFunction, AsyncFunction } from "../../util/index.js"; -import { AI as ai } from '../../ai/index.js'; -import { Get as get } from '../../get/index.js'; -import { Game as game } from '../../game/index.js'; -import { Library as lib } from "../index.js"; -import { status as _status } from '../../status/index.js'; -import { UI as ui } from '../../ui/index.js'; -import { GNC as gnc } from '../../gnc/index.js'; +import { AI as ai } from '../../ai/index.js' +import { Get as get } from '../../get/index.js' +import { Game, Game as game } from '../../game/index.js' +import { Library as lib } from "../index.js" +import { status as _status } from '../../status/index.js' +import { UI as ui } from '../../ui/index.js' +import { GNC as gnc } from '../../gnc/index.js' -import { LibInitPromises } from "./promises.js"; +import { LibInitPromises } from "./promises.js" +import { GameEvent } from "../element/gameEvent.js" +import { GameEventPromise } from "../element/gameEventPromise.js" export class LibInit extends Uninstantable { /** @@ -693,30 +695,37 @@ export class LibInit extends Uninstantable { } case "function": if (gnc.is.generatorFunc(item)) { - let gen, lastEvent; - return function* (event, step, source, player, target, targets, card, cards, skill, forced, num, trigger, result, _status, lib, game, ui, get, ai) { + // 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 (!gen) gen = item(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 + if (!this.gen) this.gen = item(event, { + event, + step, + source, + player, + target, + targets, + card, + cards, + skill, + forced, + num, + trigger, + result }); - var res = gen.next((lastEvent && (typeof lastEvent == 'object') && ("result" in lastEvent)) ? lastEvent.result : lastEvent); + + 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){ - gen = null; + this.gen = null; return event.finish(); } - var currentResult = res.value; + let currentResult = res.value; // TODO: use `event.debugger` to replace source if (typeof currentResult == "function") yield currentResult; else { @@ -724,9 +733,14 @@ export class LibInit extends Uninstantable { event.step = currentResult[1]; currentResult = currentResult[0]; } - lastEvent = currentResult; + this.last = currentResult; } - } + }.bind({ + gen: null, + last: undefined + }) + content._gen = true + return content } else if (item._parsed) return item; // falls through default: diff --git a/noname/ui/create/index.js b/noname/ui/create/index.js index 594eba298..c33cd2488 100644 --- a/noname/ui/create/index.js +++ b/noname/ui/create/index.js @@ -1414,7 +1414,7 @@ export class Create extends Uninstantable { packlist.push(lib.config.all.characters[i]); } for (var i in lib.characterPack) { - if (!lib.config.all.characters.includes(i)) { + if (lib.config.characters.includes(i) && !lib.config.all.characters.includes(i)) { packlist.push(i); } } diff --git a/noname/ui/create/menu/index.js b/noname/ui/create/menu/index.js index 9180b7832..4b9b2a79d 100644 --- a/noname/ui/create/menu/index.js +++ b/noname/ui/create/menu/index.js @@ -2,7 +2,7 @@ import { ui, game, get, lib, _status } from "../../../../noname.js"; export function openMenu(node, e, onclose) { popupContainer.innerHTML = ''; - var left = Math.round(e.clientX / game.documentZoom); + var left = Math.round(e.clientX / get.menuZoom()); var zoom = get.is.phoneLayout() ? 1.3 : 1; popupContainer.appendChild(node); // var rect=node.getBoundingClientRect(); @@ -23,7 +23,7 @@ export function openMenu(node, e, onclose) { // } // if(e){ var height = node.offsetHeight; - var idealtop = e.clientY / game.documentZoom; + var idealtop = e.clientY / get.menuZoom(); if (idealtop < 10) { idealtop = 10; } @@ -141,7 +141,7 @@ export function createMenu(connectMenu, tabs, config) { var menuTab = ui.create.div('.menu-tab', menu); var menuTabBar = ui.create.div('.menu-tab-bar', menu); menuTabBar.style.left = (config.bar || 0) + 'px'; - if (Math.round(2 * game.documentZoom) < 2) { + if (Math.round(2 * get.menuZoom()) < 2) { menuTabBar.style.height = '3px'; } var menuContent = ui.create.div('.menu-content', menu); @@ -153,7 +153,7 @@ export function createMenu(connectMenu, tabs, config) { active._link.remove(); } this.classList.add('active'); - menuTabBar.style.transform = 'translateX(' + (this.getBoundingClientRect().left - this.parentNode.firstChild.getBoundingClientRect().left) / game.documentZoom + 'px)'; + menuTabBar.style.transform = 'translateX(' + (this.getBoundingClientRect().left - this.parentNode.firstChild.getBoundingClientRect().left) / get.menuZoom() + 'px)'; menuContent.appendChild(this._link); }; ui.click.menuTab = function (tab) {