From 1d785b02c04a7cf12828a1980665c7d4e1196ca9 Mon Sep 17 00:00:00 2001 From: Tipx-L <138244655+Tipx-L@users.noreply.github.com> Date: Mon, 28 Aug 2023 00:42:57 -0700 Subject: [PATCH] The Use of Spies. --- card/yongjian.js | 98 ++++++++++++------------------------ character/diy.js | 31 +++++------- character/offline.js | 31 +++++------- character/shenhua.js | 2 +- character/xianding.js | 8 +-- game/game.js | 113 +++++++++++++++++++++++++++++++++++------- 6 files changed, 158 insertions(+), 125 deletions(-) diff --git a/card/yongjian.js b/card/yongjian.js index ce5b6d6b3..99f2b2c7b 100644 --- a/card/yongjian.js +++ b/card/yongjian.js @@ -404,14 +404,15 @@ game.import('card',function(lib,game,ui,get,ai,_status){ audio:true, equipSkill:true, forced:true, - trigger:{target:'_yongjian_zengyuBegin'}, - content:function(){ - trigger._zengyu_denied=true; - game.log(player,'拒绝了',trigger.player,'发起的赠予'); + trigger:{target:'gift'}, + filter:(event,player)=>event.target!=player, + logTarget:'player', + content:()=>{ + trigger.deniedGift.add(trigger.card); }, ai:{ - refuseGifts:true, - }, + refuseGifts:true + } }, xinge:{ audio:true, @@ -595,6 +596,13 @@ game.import('card',function(lib,game,ui,get,ai,_status){ map.push([source,event.given_map[i]]); cards.addArray(event.given_map[i]); } + player.showCards(cards,`${get.translation(player)}对${(targets=>{ + if(get.itemtype(targets)=='player') targets=[targets]; + if(targets[0]!=player) return get.translation(targets); + const selfTargets=targets.slice(); + selfTargets[0]='自己'; + return get.translation(selfTargets); + })(logs)}发动了【${get.skillTranslation(event.name,player)}】`); game.loseAsync({ gain_list:map, player:player, @@ -609,79 +617,37 @@ game.import('card',function(lib,game,ui,get,ai,_status){ _yongjian_zengyu:{ enable:'phaseUse', forceLoad:true, - filter:function(event,player){ - return player.hasCard((card)=>lib.skill._yongjian_zengyu.filterCard(card,player),'he'); - }, - filterCard:function(card,player){ - var mod=game.checkMod(card,player,'unchanged','cardZengyuable',player); - if(mod!='unchanged') return mod; - return get.position(card)=='h'&&get.cardtag(card,'gifts'); - }, - filterTarget:function(card,player,target){ - if(player==target) return false; - var card=ui.selected.cards[0]; - if(get.type(card,false)=='equip'){ - return target.canEquip(card,true); - } - return true; - }, + filter:(event,player)=>player.hasCard(card=>lib.skill._yongjian_zengyu.filterCard(card,player),lib.skill._yongjian_zengyu.position), + filterCard:(card,player)=>game.hasPlayer(current=>player.canGift(card,current,true)), + filterTarget:(card,player,target)=>ui.selected.cards.every(value=>player.canGift(value,target,true)), position:'he', discard:false, lose:false, delay:false, - check:function(card){ - var player=_status.event.player; - if(get.cardtag(card,'gifts')&&get.type(card,false)=='equip'&&game.hasPlayer(function(current){ - return current!=player&¤t.canEquip(card,true)&&!current.hasSkillTag('refuseGifts')&&get.effect(current,card,player,player)>0; - })) return 2; + check:card=>{ + const player=_status.event.player; + if(game.hasPlayer(current=>player.canGift(card,current,true)&&!current.refuseGifts(card,player)&&get.effect(current,card,player,player)>0)) return 2; if(!player.needsToDiscard()&&get.position(card)=='h') return 0; return 1+Math.random(); }, - content:function(){ - 'step 0' - if(event._zengyu_denied){ - player.loseToDiscardpile(cards); - } - else{ - if(get.type(cards[0],false)=='equip'){ - player.$give(cards[0],target,false); - game.delay(0.5); - target.equip(cards[0]); - } - else{ - target.gain(cards,player,'give'); - event.finish(); - } - } - 'step 1' - game.delayx(); + content:()=>{ + player.gift(cards,target); }, ai:{ - order:function(item,player){ - if(player.hasCard(function(card){ - return get.cardtag(card,'gifts')&&get.type(card,false)=='equip'&&game.hasPlayer(function(current){ - return current!=player&¤t.canEquip(card,true)&&!current.hasSkillTag('refuseGifts')&&get.effect(current,card,player,player)>0; - }); - },'h')) return 7; - return 0.51; - }, + order:(item,player)=>player.hasCard(card=>game.hasPlayer(current=>player.canGift(card,current,true)&&!current.refuseGifts(card,player)&&get.effect(current,card,player,player)>0),'h')?7:0.51, result:{ - target:function(player,target){ - var card=ui.selected.cards[0]; - if(!card||target.hasSkillTag('refuseGifts')) return 0; - if(get.type(card,false)=='equip') return get.effect(target,card,target,target); - if(card.name=='du') return player.hp>target.hp?-1:0; - if(target.hasSkillTag('nogain')) return 0; - return Math.max(1,get.value(card,player)-get.value(card,target)); - }, - }, - }, - }, + target:(player,target)=>{ + const result=ui.selected.cards.map(value=>player.getGiftAIResultTarget(value,target)); + return result.reduce((previousValue,currentValue)=>previousValue+currentValue,0)/result.length; + } + } + } + } }, translate:{ gifts_tag:'赠', du:'毒', - du_info:'①当此牌正面向上离开你的手牌区,或作为你的拼点牌而亮出时,你失去1点体力。②当你因摸牌或分发起始手牌而获得【毒】后,你可将其分配给其他角色(正面朝上移动,且不触发〖毒①〗)。', + du_info:'①当此牌正面向上离开你的手牌区,或作为你的拼点牌而亮出时,你失去1点体力。②当你因摸牌或分发起始手牌而获得【毒】后,你可展示之并交给其他角色(不触发〖毒①〗)。', g_du:'毒', g_du_give:'赠毒', du_given:'已分配', @@ -707,7 +673,7 @@ game.import('card',function(lib,game,ui,get,ai,_status){ yonglv_info:'锁定技。①你至其他角色的距离-1。②其他角色至你的距离视为1。', yonglv_append:'它旁边的就是王仲宣。', zhanxiang:'战象', - zhanxiang_info:'锁定技。①其他角色至你的距离+1。②当你成为〖赠予〗的目标后,你将此次赠予的效果改为“将赠予牌移动至弃牌堆”。', + zhanxiang_info:'锁定技。①其他角色至你的距离+1。②其他角色对你赠予的牌视为赠予失败。', xinge:'信鸽', xinge_info:'出牌阶段限一次。你可以将一张手牌交给一名其他角色。', xinge_append:'咕咕咕。', diff --git a/character/diy.js b/character/diy.js index a98a335c2..6048a0b46 100755 --- a/character/diy.js +++ b/character/diy.js @@ -1243,20 +1243,13 @@ game.import('character',function(lib,game,ui,get,ai,_status){ lose:false, delay:false, promptfunc:()=>'出牌阶段,你可以赠予一张“米券”,然后执行一项本回合内未被选择过的效果:⒈对其造成1点伤害;⒉摸两张牌;⒊弃置其的两张牌;⒋亮出牌堆顶的一张牌,然后你可以使用之。', - check:function(card){ - var player=_status.event.player; - if(get.cardtag(card,'gifts')&&get.type(card,false)=='equip'&&game.hasPlayer(function(current){ - return current!=player&¤t.canEquip(card,true)&&!current.hasSkillTag('refuseGifts')&&get.effect(current,card,player,player)>0; - })) return 2; - return 1+Math.random(); + check:card=>{ + const player=_status.event.player; + return get.type(card,false)=='equip'&&game.hasPlayer(current=>player.canGift(card,current,true)&&!current.refuseGifts(card,player)&&get.effect(current,card,player,player)>0)?2:1+Math.random(); }, content:function(){ 'step 0' - var next=game.createEvent('_yongjian_zengyu'); - next.player=player; - next.target=target; - next.cards=cards; - next.setContent(lib.skill._yongjian_zengyu.content); + player.gift(cards,target); 'step 1' var list=player.getStorage('minagi_peiquan_yukito'); if(list.length>=4) event.finish(); @@ -1300,12 +1293,13 @@ game.import('character',function(lib,game,ui,get,ai,_status){ ai:{ order:4, result:{ - player:function(player,target){ - var baseEffect=Math.min(3,get.effect(target,'_yongjian_zengyu',player,player)); - var choices=['damage','draw','discard','use']; + player:(player,target)=>{ + const giftEffects=ui.selected.cards.map(value=>player.getGiftEffect(value,target)); + const baseEffect=Math.min(3,giftEffects.reduce((previousValue,currentValue)=>previousValue+currentValue,0)/giftEffects.length); + const choices=['damage','draw','discard','use']; choices.removeArray(player.getStorage('minagi_peiquan_yukito')); if(choices.length<=0) return baseEffect; - var eff=Math.max.apply(Math,choices.map(function(choice){ + return baseEffect+Math.max(...choices.map(choice=>{ switch(choice){ case 'damage':return get.damageEffect(target,player,player); case 'draw':return get.effect(player,{name:'wuzhong'},player,player); @@ -1313,9 +1307,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){ case 'use':return _status.event.getRand('minagi_peiquan')*4; } })); - return baseEffect+eff; - }, - }, + } + } }, group:'minagi_peiquan_umareta', subSkill:{ @@ -8514,7 +8507,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ return true; } else if(event.name=='gain'){ - if(event.giver||event.getParent().name=='_yongjian_zengyu') return false; + if(event.giver||event.getParent().name=='gift') return false; var cards=event.getg(event.player); if(!cards.length) return false; return game.hasPlayer(function(current){ diff --git a/character/offline.js b/character/offline.js index 071d8a546..ae53a698b 100644 --- a/character/offline.js +++ b/character/offline.js @@ -3652,7 +3652,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, }, mod:{ - cardZengyuable:function(card,player){ + cardGiftable:function(card,player){ return get.type(card)=='equip'; } } @@ -3786,19 +3786,17 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, //群曹操 yjxiandao:{ - trigger:{player:'_yongjian_zengyuEnd'}, + trigger:{player:'giftAccepted'}, usable:1, forced:true, locked:false, - filter:function(event,player){ - return !event._zengyu_denied&&event.target.isIn(); - }, + filter:(event,player)=>event.target!=player&&event.target.isIn(), logTarget:'target', content:function(){ 'step 0' event.target=trigger.target; - event.card=trigger.cards[0]; - event.target.markAuto('yjxiandao',[get.suit(event.card,false)]) + event.card=trigger.card; + event.target.markAuto('yjxiandao_block',[get.suit(event.card,false)]); event.target.addTempSkill('yjxiandao_block'); 'step 1' var type=get.type(card,false); @@ -3859,14 +3857,11 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }); 'step 2' if(result.bool){ - player.line(result.targets[0],'green'); - var next=game.createEvent('_yongjian_zengyu'); - next.player=player; - next.target=result.targets[0]; - next.cards=result.cards; - next.setContent(lib.skill._yongjian_zengyu.content); + var target=result.targets[0]; + player.line(target,'green'); + player.gift(result.cards,target); } - }, + } }, yjyibing:{ trigger:{ @@ -3875,7 +3870,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ }, direct:true, filter:function(event,player){ - if(event.getParent().name=='_yongjian_zengyu') return false; + if(event.getParent().name=='gift') return false; if(event.getParent('yjyibing').player==player) return false; var evt=event.getParent('phaseDraw'),hs=player.getCards('h'),cards=event.getg(player); return cards.length>0&&(!evt||evt.player!=player)&&cards.filter(function(card){ @@ -6403,11 +6398,11 @@ game.import('character',function(lib,game,ui,get,ai,_status){ //用间 yj_caocao:'SP曹操', yjxiandao:'献刀', - yjxiandao_info:'每回合限一次。当你对其他角色发动〖赠予〗后,你令其不能使用或打出与本次赠予移动的牌A花色相同的牌直到回合结束。然后若牌A:为锦囊牌,你摸两张牌。为装备牌,你获得其一张不为A的牌。为武器牌,你对其造成1点伤害。', + yjxiandao_info:'每回合限一次。当你赠予其他角色一张牌后,你令其不能使用或打出与本次赠予移动的牌A花色相同的牌直到回合结束。然后若牌A:为锦囊牌,你摸两张牌。为装备牌,你获得其一张不为A的牌。为武器牌,你对其造成1点伤害。', yjsancai:'散财', - yjsancai_info:'出牌阶段限一次,你可以展示所有手牌。若这些牌的类别均相同,则你可以发动一次〖赠予〗(可以选择任意手牌)。', + yjsancai_info:'出牌阶段限一次,你可以展示所有手牌。若这些牌的类别均相同,则你可以赠予一名其他角色一张手牌。', yjyibing:'义兵', - yjyibing_info:'当你不因〖赠予〗且不因〖义兵〗的嵌套结算而于摸牌阶段外获得牌时,你可以将此次获得的所有牌当做【杀】使用(无距离限制且不计入使用次数)。', + yjyibing_info:'当你不因赠予且不因〖义兵〗的嵌套结算而于摸牌阶段外获得牌时,你可以将此次获得的所有牌当做【杀】使用(无距离限制且不计入使用次数)。', yj_caohong:'用间曹洪', yj_caohong_ab:'曹洪', yjlifeng:'厉锋', diff --git a/character/shenhua.js b/character/shenhua.js index b1955c9d7..9c44b2849 100755 --- a/character/shenhua.js +++ b/character/shenhua.js @@ -7023,7 +7023,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ return true; } else if(event.name=='gain'){ - if(event.giver||event.getParent().name=='_yongjian_zengyu') return false; + if(event.giver||event.getParent().name=='gift') return false; var cards=event.getg(event.player); if(!cards.length) return false; return game.hasPlayer(function(current){ diff --git a/character/xianding.js b/character/xianding.js index ff3d2a0e9..19a7811f6 100644 --- a/character/xianding.js +++ b/character/xianding.js @@ -4884,7 +4884,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } else if(evt.type=='gain'){ var evtx=evt.getParent(); - if(evtx.giver||evtx.getParent().name=='_yongjian_zengyu') return false; + if(evtx.giver||evtx.getParent().name=='gift') return false; var cards=evtx.getg(target); if(!cards.length) return false; var cards2=evtx.getl(current).cards2; @@ -4895,7 +4895,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ return false; })) guojue=true; if(!renzhi&¤t.hasHistory('gain',evt=>{ - if(evt.giver!=target||evt.getParent().name=='_yongjian_zengyu') return false; + if(evt.giver!=target||evt.getParent().name=='gift') return false; return evt.cards.length; })) renzhi=true; }); @@ -4927,7 +4927,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ } else if(evt.type=='gain'){ var evtx=evt.getParent(); - if(evtx.giver||evtx.getParent().name=='_yongjian_zengyu') return false; + if(evtx.giver||evtx.getParent().name=='gift') return false; var cards=evtx.getg(target); if(!cards.length) return false; var cards2=evtx.getl(current).cards2; @@ -4938,7 +4938,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){ return false; })) guojue=true; if(!renzhi&¤t.hasHistory('gain',evt=>{ - if(evt.giver!=target||evt.getParent().name=='_yongjian_zengyu') return false; + if(evt.giver!=target||evt.getParent().name=='gift') return false; return evt.cards.length; })) renzhi=true; }); diff --git a/game/game.js b/game/game.js index 161d3cc81..29452bf3b 100644 --- a/game/game.js +++ b/game/game.js @@ -10711,6 +10711,36 @@ emptyEvent:function(){ event.trigger(event.name); }, + //Gift + //赠予 + gift:()=>{ + 'step 0' + event.num=0; + 'step 1' + if(num{ @@ -10719,6 +10749,7 @@ if(typeof event.recastingLose!='function') return; event.trigger('recastingLose'); var recastingLosingEvents=event.recastingLose(player,cards); + event.trigger('recastingLost'); if(get.itemtype(recastingLosingEvents)=='event') event.recastingLosingEvents.push(event.recastingLosingEvents); else if(Array.isArray(recastingLosingEvents)) event.recastingLosingEvents.push(...recastingLosingEvents); 'step 1' @@ -10727,6 +10758,7 @@ if(typeof event.recastingGain!='function') return; event.trigger('recastingGain'); var recastingGainingEvents=event.recastingGain(player,cards); + event.trigger('recastingGained'); if(get.itemtype(recastingGainingEvents)=='event') event.recastingGainingEvents.push(event.recastingGainingEvents); else if(Array.isArray(recastingGainingEvents)) event.recastingGainingEvents.push(...recastingGainingEvents); 'step 3' @@ -10942,7 +10974,7 @@ },subtype); player.$equip(card); game.addVideo('equip',player,get.cardInfo(card)); - game.log(player,'装备了',card); + if(event.log!=false) game.log(player,'装备了',card); if(event.updatePile) game.updateRoundNumber(); "step 6" var info=get.info(card,false); @@ -17067,7 +17099,7 @@ },get.delayx(500,500)); } else if(event.animate=='gain'){ - player.$gain(cards); + player.$gain(cards,event.log); game.pause(); setTimeout(function(){ addv(); @@ -17081,7 +17113,7 @@ } else if(event.animate=='gain2'||event.animate=='draw2'){ var gain2t=300; - if(player.$gain2(cards)&&player==game.me){ + if(player.$gain2(cards,event.log)&&player==game.me){ gain2t=500; } game.pause(); @@ -17100,14 +17132,14 @@ if(event.animate=='give'){ for(var i in evtmap){ var source=(_status.connectMode?lib.playerOL:game.playerMap)[i]; - source.$give(evtmap[i][0],player) + source.$give(evtmap[i][0],player,event.log) } } else{ for(var i in evtmap){ var source=(_status.connectMode?lib.playerOL:game.playerMap)[i]; - if(evtmap[i][1].length) source.$giveAuto(evtmap[i][1],player); - if(evtmap[i][2].length) source.$give(evtmap[i][2],player); + if(evtmap[i][1].length) source.$giveAuto(evtmap[i][1],player,event.log); + if(evtmap[i][2].length) source.$give(evtmap[i][2],player,event.log); } } game.pause(); @@ -17143,9 +17175,6 @@ broadcast(); event.finish(); } - if(event.log){ - game.log(player,'获得了',cards); - } "step 4" game.delayx(); if(event.updatePile) game.updateRoundNumber(); @@ -18287,6 +18316,46 @@ canIgnoreHandcard:function(card){ return lib.filter.ignoredHandcard(card,this); }, + //Gift + //赠予 + gift:function(cards,target){ + const gift=game.createEvent('gift'); + gift.player=this; + gift.target=target; + 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); + gift.deniedGifts=[]; + gift.setContent('gift'); + gift._args=Array.from(arguments); + return gift; + }, + //Check if the player can gift the card + //检测角色是否能赠予此牌 + canGift:function(card,target,strict){ + return lib.filter.cardGiftable(card,this,target,strict); + }, + //Check if the player refuses gifts + //检测角色是否拒绝赠予 + refuseGifts:function(card,player){ + return this.hasSkillTag('refuseGifts',null,{ + player:player, + card:card + }); + }, + //Gift AI related + //赠予AI相关 + getGiftAIResultTarget:function(card,target){ + if(!card||target.refuseGifts(card,this)) return 0; + if(get.type(card,false)=='equip') return get.effect(target,card,target,target); + if(card.name=='du') return this.hp>target.hp?-1:0; + if(target.hasSkillTag('nogain')) return 0; + return Math.max(1,get.value(card,this)-get.value(card,target)); + }, + getGiftEffect:function(card,target){ + return this.getGiftAIResultTarget(card,target)*get.attitude(this,target); + }, //Recast //重铸 recast:function(cards,recastingLose,recastingGain){ @@ -18307,13 +18376,9 @@ return recast; }, //Check if the player can recast the card - //检查角色是否能重铸此牌 + //检测角色是否能重铸此牌 canRecast:function(card,source,strict){ - const cardRecastable=lib.filter.cardRecastable(card,this,source,strict); - if(cardRecastable!='unchanged') return cardRecastable; - if(get.position(card)!='h') return false; - const info=get.info(card); - return typeof info.chongzhu=='function'?info.chongzhu(_status.event,this):info.chongzhu; + return lib.filter.cardRecastable(card,this,source,strict); }, //装备栏相关 //判断一名角色的某个区域是否被废除 @@ -28403,11 +28468,25 @@ //Check if the card does not count toward the player's hand limit //检测此牌是否不计入此角色的手牌上限 ignoredHandcard:(card,player)=>game.checkMod(card,player,false,'ignoredHandcard',player), + //Check if the card is giftable + //检测此牌是否可赠予 + cardGiftable:(card,player,target,strict)=>{ + const mod=game.checkMod(card,player,target,'unchanged','cardGiftable',player); + if(!mod||strict&&(mod=='unchanged'&&(get.position(card)!='h'||!get.cardtag(card,'gifts'))||player==target)) return false; + return get.type(card,false)!='equip'||target.canEquip(card,true); + }, //Check if the card is recastable //检查此牌是否可重铸 - cardRecastable:(card,player,source,raw)=>{ + cardRecastable:(card,player,source,strict)=>{ if(typeof player=='undefined') player=get.owner(card); - return game.checkMod(card,player,source,!raw||'unchanged','cardRecastable',player); + const mod=game.checkMod(card,player,source,'unchanged','cardRecastable',player); + if(!mod) return false; + if(strict&&mod=='unchanged'){ + if(get.position(card)!='h') return false; + const info=get.info(card); + return typeof info.chongzhu=='function'?info.chongzhu(_status.event,player):info.chongzhu; + } + return true; }, //装备栏相关 canBeReplaced:function(card,player){