diff --git a/character/clan.js b/character/clan.js index aa012aef0..f330b635b 100644 --- a/character/clan.js +++ b/character/clan.js @@ -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/ddd.js b/character/ddd.js index 515e2ee68..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,'额外结算一次'); diff --git a/character/diy.js b/character/diy.js index 3efeaaff6..0cae0351b 100755 --- a/character/diy.js +++ b/character/diy.js @@ -14594,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); } @@ -17684,9 +17684,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){ return player.additionalSkills.junkyuheng&&player.additionalSkills.junkyuheng.length>0; }, async content(event,trigger,player){ - const skills = player.additionalSkills.junkyuheng; + const skillslength = player.additionalSkills.junkyuheng.length; await player.removeAdditionalSkills('junkyuheng'); - await player.draw(skills.length); + await player.draw(skillslength); }, }, }, diff --git a/character/huicui.js b/character/huicui.js index 307c9dae0..783493b81 100644 --- a/character/huicui.js +++ b/character/huicui.js @@ -1830,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)=>{ diff --git a/character/mobile.js b/character/mobile.js index 53a3a3fce..d9b5283ae 100644 --- a/character/mobile.js +++ b/character/mobile.js @@ -5733,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; }); @@ -14293,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(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; - } - } - } + 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(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]); - } - } - } + 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){ @@ -15664,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'], diff --git a/character/onlyOL.js b/character/onlyOL.js index 5fdc94d4f..9ac091b48 100644 --- a/character/onlyOL.js +++ b/character/onlyOL.js @@ -30,6 +30,14 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 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'], @@ -63,12 +71,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, ai2(target){ const player=get.event('player'),trigger=get.event().getTrigger(); - if(trigger.card.name=='tiesuo'){ - const att=get.attitude(player,target); - return get.sgn(att)*(2+get.sgn(att)); - } + 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.effect(target,trigger.card,trigger.player,player)*2-sum; + return get.sgn(att)*(eff*2-sum); }, }).set('prompt2','弃置一张'+get.translation(get.color(trigger.card))+'牌,令'+get.translation(trigger.card)+'改为对其中一个目标结算两次'); if(bool){ @@ -87,7 +93,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){ player(card,player){ if(!game.hasPlayer(target=>{ return target.hasSkill('olsbhetao')&&(get.attitude(player,target)<0||get.attitude(target,player)<0); - })) return; + })||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]; @@ -95,7 +103,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 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) return 'zeroplayertarget'; + if(range[1]==-1||(range[1]>1&&ui.selected.targets&&ui.selected.targets.length)) return 'zeroplayertarget'; }, }, }, @@ -149,8 +157,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 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); + const targets=game.filterPlayer(target=>trigger.targets.includes(target)&&player.canUse(trigger.card,target,false)); + if(targets.length&&(!trigger.cards||!trigger.cards.length||trigger.cards.every(card=>{ + return !get.owner(card); + }))) player.useCard(trigger.card,targets,false); } }); }, @@ -164,16 +174,21 @@ game.import('character',function(lib,game,ui,get,ai,_status){ player:'enterGame', }, filter(event,player){ - if(get.cardPile('sizhaojian','field')||lib.inpile.includes('sizhaojian')) return false; - return (event.name!='phase'||game.phaseNumber==0)&&player.hasEquipableSlot(1); + 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){ - game.broadcastAll(()=>lib.inpile.add('sizhaojian')); - const card=game.createCard2('sizhaojian','diamond',6); - player.$gain2(card,false); - game.delayx(); + 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:{ @@ -205,8 +220,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 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<=get.number(evt.respondTo[1]))) return false; + 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); @@ -254,12 +269,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){ const evt=trigger.getl(target); return evt&&evt.player==target&&evt.es&&evt.es.length>0; }).sortBySeat(); - const card=get.cardPile('sizhaojian','field'); + 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; } @@ -1023,15 +1042,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){ olsbhetao:'合讨', olsbhetao_info:'其他角色使用牌执行第一个目标后,若此牌指定的目标数大于1,则你可以弃置一张与此牌颜色相同的牌并令此牌改为对其中一名目标角色结算两次。', olsbshenli:'神离', - olsbshenli_info:'出牌阶段限一次,当你使用【杀】指定目标后,你可以令所有可成为此牌目标的其他角色均成为此牌目标,此牌结算完毕后,若你因此牌造成的伤害值X:大于你的手牌数,你摸X张牌(至多摸五张);大于你的体力值,你令此牌额外结算一次。', + olsbshenli_info:'出牌阶段限一次,当你使用【杀】指定目标后,你可以令所有可成为此牌目标的其他角色均成为此牌目标,此牌结算完毕后,若你因此牌造成的伤害值X:大于你的手牌数,你摸X张牌(至多摸五张);大于你的体力值,你再次对所有目标角色中可以成为此牌目标的角色使用此牌。', olsbyufeng:'玉锋', olsbyufeng_sizhaojian:'思召剑', olsbyufeng_block:'思召剑', - olsbyufeng_info:'游戏开始时,若【思召剑】未加入本局游戏,若你可装备【思召剑】,则你将【思召剑】置入装备区。', + olsbyufeng_info:'游戏开始时,你将【思召剑】置入装备区。', sizhaojian:'思召剑', sizhaojian_info:'当你使用有点数的【杀】指定目标后,你令目标角色只能使用无点数或点数大于等于此【杀】的【闪】响应此牌。', + sizhaojian_append:'【思召剑】于闪闪节(3月2日-3月15日)外离开装备区后,销毁此牌', olsbshishou:'士首', - olsbshishou_info:'主公技,其他群势力角色失去装备区的牌后,若你的装备区中没有武器牌,且【思召剑】存在于场上/牌堆/弃牌堆中,其可令你将【思召剑】置入装备区。', + olsbshishou_info:'主公技,其他群势力角色失去装备区的牌后,若你的装备区中没有武器牌,其可将【思召剑】置入你的装备区。', onlyOL_yijiang1:'OL专属·将1', onlyOL_yijiang2:'OL专属·将2', diff --git a/character/rank.js b/character/rank.js index a39d0f34b..42662b99f 100644 --- a/character/rank.js +++ b/character/rank.js @@ -966,6 +966,7 @@ window.noname_character_rank={ 'dc_liuba', 'key_seira', 'lukai', + 'ol_lukai', 'niufu', 're_liufeng', 'huzhao', @@ -1039,6 +1040,7 @@ window.noname_character_rank={ 'jsrg_zhenji', 'junk_xuyou', 'sp_machao', + 'liupan', 'mengyou', 're_wenpin', 'yue_zhoufei', @@ -2568,6 +2570,7 @@ window.noname_character_rank={ 'dc_wangchang', 'jin_zhouchu', 'lukai', + 'ol_lukai', 'caoxiancaohua', 'huzhao', 're_liufeng', diff --git a/character/sb.js b/character/sb.js index 4223c5cf9..9d0f998b4 100644 --- a/character/sb.js +++ b/character/sb.js @@ -936,8 +936,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, sbyijue:{ audio:2, - trigger:{source:'damageBegin2'}, + trigger:{global:'damageBegin4'}, filter:function(event,player){ + if(!event.source||event.source!=player||event.player==player) return false; return event.num>=event.player.hp&&!player.getStorage('sbyijue').includes(event.player); }, forced:true, @@ -1141,7 +1142,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); @@ -1296,7 +1297,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ sbkanpo:{ init:function(player){ if(!player.storage.sbkanpo){ - player.storage.sbkanpo=[get.mode()=='doudizhu'?2:4,[],[]]; + player.storage.sbkanpo=[(get.mode()=='doudizhu'||(get.mode()=='versus'&&_status.mode=='two'))?2:4,[],[]]; player.markSkill('sbkanpo'); } }, @@ -6684,6 +6685,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ sbkanpo:'看破', sbkanpo_info:'①一轮游戏开始时,你清除〖看破①〗记录的牌名,然后你可以依次记录任意个未于上次发动〖看破①〗记录清除过的非装备牌牌名(对其他角色不可见,每局游戏至多记录4个牌名)。②其他角色使用你〖看破①〗记录过的牌名的牌时,你可以移去一个〖看破①〗中的此牌名的记录令此牌无效,然后你摸一张牌。', sbkanpo_info_doudizhu:'①一轮游戏开始时,你清除〖看破①〗记录的牌名,然后你可以依次记录任意个未于上次发动〖看破①〗记录清除过的非装备牌牌名(对其他角色不可见,每局游戏至多记录2个牌名)。②其他角色使用你〖看破①〗记录过的牌名的牌时,你可以移去一个〖看破①〗中的此牌名的记录令此牌无效,然后你摸一张牌。', + sbkanpo_info_versus_two:'①一轮游戏开始时,你清除〖看破①〗记录的牌名,然后你可以依次记录任意个未于上次发动〖看破①〗记录清除过的非装备牌牌名(对其他角色不可见,每局游戏至多记录2个牌名)。②其他角色使用你〖看破①〗记录过的牌名的牌时,你可以移去一个〖看破①〗中的此牌名的记录令此牌无效,然后你摸一张牌。', sbguanxing:'观星', sbguanxing_info:'①准备阶段,你将所有“星”置入弃牌堆,将牌堆顶的X张牌置于你的武将牌上,称为“星”(X为7-此前发动〖观星①〗次数的三倍,且X至少为0)。然后你可以将任意张“星”置于牌堆顶。②结束阶段,若你未于本回合的准备阶段将“星”置于过牌堆顶,你可以将任意张“星”置于牌堆顶。③你可以如手牌般使用或打出“星”。', sbkongcheng:'空城', @@ -6703,7 +6705,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ sbwusheng_info:'你可以将一张手牌当作任意【杀】使用或打出。出牌阶段开始时,你可以选择一名非主公的其他角色,本阶段对其使用【杀】无距离和次数限制,使用【杀】指定其为目标后摸一张牌,对其使用三张【杀】后不能对其使用【杀】。', sbwusheng_info_identity:'你可以将一张手牌当作任意【杀】使用或打出。出牌阶段开始时,你可以选择一名非主公的其他角色,本阶段对其使用【杀】无距离和次数限制,使用【杀】指定其为目标后摸两张牌,对其使用三张【杀】后不能对其使用【杀】。', sbyijue:'义绝', - sbyijue_info:'锁定技,每名角色每局游戏限一次,当你对一名角色造成大于等于其体力值的伤害时,你防止此伤害,且本回合你使用牌指定其为目标时,此牌对其无效。', + sbyijue_info:'锁定技,每名角色每局游戏限一次,一名其他角色受到你对其造成的大于等于其体力值的伤害时,你防止此伤害,且本回合你使用牌指定其为目标时,此牌对其无效。', sb_caopi:'谋曹丕', sb_caopi_prefix:'谋', sbxingshang:'行殇', diff --git a/character/shenhua.js b/character/shenhua.js index 7372f033a..c42bdf4c1 100755 --- a/character/shenhua.js +++ b/character/shenhua.js @@ -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{ + 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, @@ -841,10 +1139,10 @@ game.import('character',function(lib,game,ui,get,ai,_status){ if(result2.bool){ const card=result2.cards[0]; if(get.name(card,target)==event.result.card.name){ - player.popup('洗具'); + player.popup('诿解成功'); stop=true; } - else player.popup('杯具'); + else player.popup('诿解失败'); } } if(!stop){ @@ -2950,11 +3248,11 @@ game.import('character',function(lib,game,ui,get,ai,_status){ audio:2, enable:'chooseToUse', hiddenCard:function(player,name){ - if(name!='wuxie'&&lib.inpile.includes(name)&&lib.skill.olqifan.getNum()) return true; + if(name!='wuxie'&&lib.inpile.includes(name)) return true; }, getNum:()=>game.getGlobalHistory('useCard').reduce((list,evt)=>list.add(get.type2(evt.card)),[]).length, filter:function(event,player){ - if(event.responded||event.type=='wuxie'||event.olqifan||!lib.skill.olqifan.getNum()) return false; + if(event.responded||event.type=='wuxie'||event.olqifan) return false; for(var i of lib.inpile){ if(i!='wuxie'&&event.filterCard(get.autoViewAs({name:i},'unsure'),player,event)) return true; } @@ -2965,7 +3263,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ 'step 0' var evt=event.getParent(2); evt.set('olqifan',true); - var cards=get.bottomCards(lib.skill.olqifan.getNum(),true); + var cards=get.bottomCards(lib.skill.olqifan.getNum()+1,true); var aozhan=player.hasSkill('aozhan'); player.chooseButton(['嚣翻:选择要使用的牌',cards]).set('filterButton',function(button){ return _status.event.cards.includes(button.link); @@ -14050,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(); @@ -17632,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); @@ -26107,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'], @@ -26170,6 +26473,7 @@ 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":"凌人", @@ -27323,7 +27627,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ ol_pengyang:'OL彭羕', ol_pengyang_prefix:'OL', olqifan:'嚣翻', - olqifan_info:'当你需要使用不为【无懈可击】的牌时,你可以观看牌堆底的X张牌并使用其中的一张。此牌结算结束时,你依次弃置以下前X个区域中的所有牌:⒈判定区、⒉装备区、⒊手牌区(X为本回合使用过的牌中包含的类型数)。', + olqifan_info:'当你需要使用不为【无懈可击】的牌时,你可以观看牌堆底的X+1张牌并使用其中的一张。此牌结算结束时,你依次弃置以下前X个区域中的所有牌:⒈判定区、⒉装备区、⒊手牌区(X为本回合使用过的牌中包含的类型数)。', oltuishi:'侻失', oltuishi_info:'锁定技。①你不能使用【无懈可击】。②当你使用点数为字母的牌时,你令此牌无效并摸一张牌,且你对手牌数小于你的角色使用的下一张牌无距离和次数限制。', ol_tw_zhangji:'张既', @@ -27391,7 +27695,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){ olqushi:'趋势', olqushi_info:'出牌阶段限一次,你可以摸一张牌,然后将一张手牌扣置于一名其他角色的武将牌上,称为“趋”。目标角色于其结束阶段移去武将牌上的所有“趋”,若其于本回合使用过与“趋”相同类别的牌,则你摸X张牌(X为其本回合使用牌指定过的目标数之和且至多为5)。', olweijie:'诿解', - olweijie_info:'每回合限一次,你的回合外,当你需要使用或打出一张基本牌时,你可以弃置距离为1的一名角色的一张手牌,若此牌牌名与你需要使用或打出的牌的牌名相同,则视为你使用或打出之。', + 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 fe6fdc3bc..9d586d032 100644 --- a/character/sp2.js +++ b/character/sp2.js @@ -3445,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'}); @@ -3470,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'}); diff --git a/character/tw.js b/character/tw.js index 72611083c..9d91e7fba 100644 --- a/character/tw.js +++ b/character/tw.js @@ -6403,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, @@ -15889,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点体力。', diff --git a/character/xianding.js b/character/xianding.js index cba10ea68..904c79a7c 100644 --- a/character/xianding.js +++ b/character/xianding.js @@ -154,10 +154,14 @@ game.import('character',function(lib,game,ui,get,ai,_status){ ai:{ order:9, result:{ - player:1, + 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){ - if(!player.storage.dcsbquanmou) return 1.2; - return -0.2; + let res=target.hasSkillTag('noh')?0:-1; + if(player.storage.dcsbquanmou) return res+0.6; + return res; }, }, }, @@ -218,6 +222,14 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, 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:{ @@ -253,10 +265,17 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, }, ai:{ - filterDamage:true, + 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'; + } + } }, }, }, @@ -319,7 +338,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ ignoreLogAI:true, skillTagFilter:function(player,tag,args){ if(args){ - return args.card&&get.name(arg.card)=='sha'; + return args.card&&get.name(args.card)=='sha'; } }, }, @@ -390,12 +409,12 @@ game.import('character',function(lib,game,ui,get,ai,_status){ return target!=get.event('aim'); },true).set('ai',target=>{ const player=get.event('player'); - return att=get.attitude(player,target); + return get.attitude(player,target); }).set('aim',aim); if(bool&&get.owner(card)==player){ const target=targets[0]; player.line(target,'green'); - await player.give([card],target); + 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(); @@ -410,7 +429,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ audio:2, inherit:'mbdiancai', filter(event,player){ - if(!player.getHp()||_status.currentPhase===player) return false; + 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)=>{ @@ -13416,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点伤害'); @@ -13445,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, @@ -13456,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(); + } }, }, }, diff --git a/character/xianjian.js b/character/xianjian.js index b4889de9c..e4aca3408 100644 --- a/character/xianjian.js +++ b/character/xianjian.js @@ -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/yijiang.js b/character/yijiang.js index ec53d0cb3..83c9ca693 100755 --- a/character/yijiang.js +++ b/character/yijiang.js @@ -13963,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'], 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/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/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/mode/boss.js b/mode/boss.js index 21ccec660..d40696c6e 100644 --- a/mode/boss.js +++ b/mode/boss.js @@ -80,6 +80,7 @@ game.import('mode',function(lib,game,ui,get,ai,_status){ event.current=null; var list=[]; + if(lib.storage.current==undefined) lib.storage.current='boss_hundun'; for(var i in lib.character){ var info=lib.character[i]; if(info[4].includes('boss')){ diff --git a/mode/guozhan.js b/mode/guozhan.js index 65688b013..9b0e6e035 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -10587,10 +10587,10 @@ return event.junling=='junling5'?1:0;}); if(huoshao&&player.inline(target.getNext())) return -3; if(target.isUnseen()) return 0; if(player.isMajor()) return 0; - 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; + 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){ diff --git a/mode/identity.js b/mode/identity.js index fe6fd96bd..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;i'+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); @@ -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 11d53ac10..f0ffc7fdf 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)}`); @@ -5874,36 +5874,28 @@ export class Game extends Uninstantable { return false; } - const useCache = !lib.config.compatiblemode && !event.skill - && ['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)}`]; - }); + let useCache = !lib.config.compatiblemode && !event.skill && !event.multitarget; + const filterCache = type => { + if (get.select(event[`select${uppercaseType(type)}`])[1] < 0) return false; + const cardinfo = get.info(get.card() || {}); + if (cardinfo && cardinfo.complexTarget) return false; + if (type === "button") type = "select"; + return !event[`complex${uppercaseType(type)}`]; + }; ['button', 'card', 'target'].forEach(type => { if (!event[`filter${uppercaseType(type)}`]) return; + if (!filterCache(type)) useCache = false; if (!ok) game.uncheck(type); else ({ ok, auto = auto } = game.Check[type](event, useCache)); }); game.Check.skill(event); - 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; - } - - _status.multitarget = false; - const skillinfo = get.info(_status.event.skill); + const skillinfo = get.info(event.skill)||{}; if (_status.event.multitarget) _status.multitarget = true; - else if (_status.event.name === 'chooseToUse' && skillinfo) { + 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()); @@ -5913,6 +5905,13 @@ export class Game extends Uninstantable { } } + 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() && game.chess && get.config('show_distance') && game.me) { const players = game.players.slice(); @@ -5928,7 +5927,13 @@ export class Game extends Uninstantable { }); } - if (event.isMine()) game.Check.confirm(event, { ok, auto, auto_confirm }); + 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) { @@ -5938,12 +5943,10 @@ export class Game extends Uninstantable { // ui.confirm.lastChild.innerHTML = '取消'; // } // } - - game.callHook("checkEnd", [event]); return ok; } static Check = class extends Uninstantable { - static processSelection({ type, items, event, useCache, isSelectable, custom }) { + static processSelection({ type, items, event, useCache, isSelectable }) { let ok = true, auto; let selectableItems = false; const uppercaseType = (type) => type[0].toUpperCase() + type.slice(1); @@ -5997,7 +6000,7 @@ export class Game extends Uninstantable { if (item.classList.contains('selectable')) selectableItems = true; else if (item.classList.contains('selected')) item.classList.add('selectable'); - if (custom) custom(item); + game.callHook(`check${uppercaseType(type)}`, [item, event]); }); if (event[`${type}Required`] && uiSelected.length === 0) ok = false; @@ -6010,7 +6013,7 @@ export class Game extends Uninstantable { static button(event, useCache) { const player = event.player; const buttons = event.dialog.buttons; - const isSelectable = button => { + const isSelectable = (button, event) => { if (!lib.filter.buttonIncluded(button)) return false; if (button.classList.contains('unselectable')) return false; return event.filterButton(button, player); @@ -6019,22 +6022,14 @@ export class Game extends Uninstantable { } static card(event, useCache) { const player = event.player; - const players = game.players.slice(); - if (event.deadTarget) players.addArray(game.dead); const cards = player.getCards(event.position); - const range = get.select(event.selectCard); - const isSelectable = card => { + 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); } - const custom = lib.config.cardtempname === 'off' ? null : card => { - 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'); - } - return game.Check.processSelection({ type: 'card', items: cards, event, useCache, isSelectable, custom }); + return game.Check.processSelection({ type: 'card', items: cards, event, useCache, isSelectable }); } static target(event, useCache) { const player = event.player; @@ -6046,17 +6041,7 @@ export class Game extends Uninstantable { if (target.isOut()) return false; return event.filterTarget(card, player, target); } - const custom = target => { - if (!target.instance) return; - ['selected', 'selectable'].forEach(className => { - if (target.classList.contains(className)) { - target.instance.classList.add(className); - } else { - target.instance.classList.remove(className); - } - }); - } - return game.Check.processSelection({ type: 'target', items: targets, event, useCache, isSelectable, custom }); + return game.Check.processSelection({ type: 'target', items: targets, event, useCache, isSelectable }); } static skill(event) { if (ui.skills) ui.skills.close(); @@ -6082,80 +6067,58 @@ export class Game extends Uninstantable { if (globalSkills.length) ui.create.skills2(globalSkills); if (equipSkills.length) ui.create.skills3(equipSkills); } - static confirm(event, { ok, auto, auto_confirm }) { - const skillinfo = get.info(event.skill) || {}; - if (ok && (!event.filterOk || event.filterOk()) - && auto && (auto_confirm || skillinfo.direct) - && (!_status.mousedragging || !_status.mouseleft) && !_status.mousedown && !_status.touchnocheck) { - if (ui.confirm && !skillinfo.preservecancel) { - ui.confirm.close(); - } - if (!ui.confirm && skillinfo.preservecancel) { - ui.create.confirm('c'); - } - if (event.skillDialog === true) event.skillDialog = false; - ui.click.ok(); - _status.mousedragging = null; + 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'); } - else { - 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)) { - let str = ''; - if (ok && (!event.filterOk || event.filterOk())) str += 'o'; - if (!event.forced && !event.fakeforce && get.noSelected()) str += 'c'; - ui.create.confirm(str); - } + 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; @@ -6163,20 +6126,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/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/content.js b/noname/library/element/content.js index 9ce2bc139..83fb76409 100644 --- a/noname/library/element/content.js +++ b/noname/library/element/content.js @@ -3151,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'; @@ -4546,7 +4547,7 @@ export const Content = { event.dialog.style.display = ''; event.dialog.open(); } - if (['chooseCharacter', 'chooseButtonOL'].includes(event.getParent().name)) event.complexSelect = true; + // 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; diff --git a/noname/library/element/player.js b/noname/library/element/player.js index ca64ccef2..b0f1bf01e 100644 --- a/noname/library/element/player.js +++ b/noname/library/element/player.js @@ -2055,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'); @@ -4267,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]; @@ -4293,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; diff --git a/noname/library/index.js b/noname/library/index.js index f7ff023bb..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,9 +330,60 @@ export class Library extends Uninstantable { game.dynamicStyle.addObject(result2); } }], - //game.check美化 + //game.check checkBegin: [], - checkEnd: [], + 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'); + }, + ], }; /** @@ -7919,7 +7975,9 @@ export class Library extends Uninstantable { let type; try { type = typeof obj[text]; - } catch {} + } catch { + void 0; + } if (type == 'function') { className += 'function'; } @@ -11652,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')) { 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); } }