Merge pull request #1075 from libccy/skill-cost-dev

分离技能的cost选择与content执行;允许在同一个时机内多次发动同一个技能
This commit is contained in:
Spmario233 2024-03-14 13:03:30 +08:00 committed by GitHub
commit 4fb3f87326
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 1082 additions and 1128 deletions

File diff suppressed because it is too large Load Diff

View File

@ -5861,23 +5861,23 @@ game.import('character',function(lib,game,ui,get,ai,_status){
str=get.prompt(event.skill,trigger[info.logTarget],player); str=get.prompt(event.skill,trigger[info.logTarget],player);
} }
else if(typeof info.logTarget=='function'){ else if(typeof info.logTarget=='function'){
var logTarget=info.logTarget(trigger,player); var logTarget=info.logTarget(trigger,player,trigger.triggername,trigger.indexedData);
if(get.itemtype(logTarget).indexOf('player')==0) str=get.prompt(event.skill,logTarget,player); if(get.itemtype(logTarget).indexOf('player')==0) str=get.prompt(event.skill,logTarget,player);
} }
else{ else{
str=get.prompt(event.skill,null,player); str=get.prompt(event.skill,null,player);
} }
} }
if(typeof str=='function'){str=str(trigger,player)} if(typeof str=='function'){str=str(trigger,player,trigger.triggername,trigger.indexedData)}
var next=player.chooseBool('评鉴:'+str); var next=player.chooseBool('评鉴:'+str);
next.set('yes',!info.check||info.check(trigger,player)); next.set('yes',!info.check||info.check(trigger,player,trigger.triggername,trigger.indexedData));
next.set('hsskill',event.skill); next.set('hsskill',event.skill);
next.set('forceDie',true); next.set('forceDie',true);
next.set('ai',function(){ next.set('ai',function(){
return _status.event.yes; return _status.event.yes;
}); });
if(typeof info.prompt2=='function'){ if(typeof info.prompt2=='function'){
next.set('prompt2',info.prompt2(trigger,player)); next.set('prompt2',info.prompt2(trigger,player,trigger.triggername,trigger.indexedData));
} }
else if(typeof info.prompt2=='string'){ else if(typeof info.prompt2=='string'){
next.set('prompt2',info.prompt2); next.set('prompt2',info.prompt2);

View File

@ -11709,16 +11709,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){
filter:function (event){ filter:function (event){
return (event.num>0) return (event.num>0)
}, },
getIndex(event, player, triggername){
return event.num;
},
content:function (){ content:function (){
'step 0' 'step 0'
event.count=trigger.num;
'step 1'
player.draw(2); player.draw(2);
event.count--;
if(_status.connectMode) game.broadcastAll(function(){_status.noclearcountdown=true}); if(_status.connectMode) game.broadcastAll(function(){_status.noclearcountdown=true});
event.given_map={}; event.given_map={};
event.num=2; event.num=2;
'step 2' 'step 1'
player.chooseCardTarget({ player.chooseCardTarget({
filterCard:function(card){ filterCard:function(card){
return get.itemtype(card)=='card'&&!card.hasGaintag('reyiji_tag'); return get.itemtype(card)=='card'&&!card.hasGaintag('reyiji_tag');
@ -11737,7 +11737,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
return get.value(card,target)*get.attitude(player,target); return get.value(card,target)*get.attitude(player,target);
}, },
}); });
'step 3' 'step 2'
if(result.bool){ if(result.bool){
var res=result.cards,target=result.targets[0].playerid; var res=result.cards,target=result.targets[0].playerid;
player.addGaintag(res,'reyiji_tag'); player.addGaintag(res,'reyiji_tag');
@ -11750,9 +11750,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){
if(_status.connectMode){ if(_status.connectMode){
game.broadcastAll(function(){delete _status.noclearcountdown;game.stopCountChoose()}); game.broadcastAll(function(){delete _status.noclearcountdown;game.stopCountChoose()});
} }
event.goto(5); event.finish();
} }
'step 4' 'step 3'
if(_status.connectMode){ if(_status.connectMode){
game.broadcastAll(function(){delete _status.noclearcountdown;game.stopCountChoose()}); game.broadcastAll(function(){delete _status.noclearcountdown;game.stopCountChoose()});
} }
@ -11771,16 +11771,6 @@ game.import('character',function(lib,game,ui,get,ai,_status){
giver:player, giver:player,
animate:'giveAuto', animate:'giveAuto',
}).setContent('gaincardMultiple'); }).setContent('gaincardMultiple');
'step 5'
if(event.count>0&&player.hasSkill('new_reyiji')){
player.chooseBool(get.prompt2('new_reyiji'));
}
else event.finish();
'step 6'
if(result.bool){
player.logSkill('new_reyiji');
event.goto(1);
}
}, },
ai:{ ai:{
maixie:true, maixie:true,

View File

@ -98,17 +98,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){
stdshushen:{ stdshushen:{
audio:'shushen', audio:'shushen',
trigger:{player:'recoverEnd'}, trigger:{player:'recoverEnd'},
direct:true, getIndex(event){
return event.num||1;
},
async cost(event,trigger,player){
event.result = await player.chooseTarget(get.prompt2('stdshushen'),lib.filter.notMe)
.set('ai',target=>get.attitude(_status.event.player,target)).forResult();
},
async content(event,trigger,player){ async content(event,trigger,player){
event.num=trigger.num||1; const target = event.targets[0];
do { await target.draw(target.countCards('h') > 0 ? 1 : 2);
const {result:{bool,targets}}=await player.chooseTarget(get.prompt2('stdshushen'),lib.filter.notMe)
.set('ai',target=>get.attitude(_status.event.player,target));
if(!bool) return;
const target=targets[0];
player.logSkill('stdshushen',target);
target.draw(target.countCards('h')?1:2);
}while(--event.num>0&&player.hasSkill('stdshushen'));
}, },
ai:{threaten:0.8,expose:0.1}, ai:{threaten:0.8,expose:0.1},
}, },
@ -178,13 +177,13 @@ game.import('character',function(lib,game,ui,get,ai,_status){
trigger:{global:'useCardToTarget'}, trigger:{global:'useCardToTarget'},
logTarget:'target', logTarget:'target',
audio:'tongji', audio:'tongji',
direct:true,
filter(event,player){ filter(event,player){
return event.card.name=='sha'&&event.player!=player&&!event.targets.includes(player)&& return event.card.name=='sha'&&event.player!=player&&!event.targets.includes(player)&&
event.target.inRange(player)&&event.target.countCards('he')>0; event.target.inRange(player)&&event.target.countCards('he')>0;
}, },
async content(event,trigger,player){ async cost(event, trigger, player){
const {result:{bool,cards}}=await trigger.target.chooseCard('he','是否对'+get.translation(player)+'发动【同疾】?','弃置一张牌,将'+get.translation(trigger.card)+'转移给'+get.translation(player)) const {result} = await trigger.target.chooseCard('he', '是否对'+get.translation(player)+'发动【同疾】?',
'弃置一张牌,将'+get.translation(trigger.card)+'转移给'+get.translation(player), lib.filter.cardDiscardable)
.set('ai',card=>{ .set('ai',card=>{
if(!_status.event.check) return -1; if(!_status.event.check) return -1;
return get.unuseful(card)+9; return get.unuseful(card)+9;
@ -204,15 +203,22 @@ game.import('character',function(lib,game,ui,get,ai,_status){
} }
return -1; return -1;
})()>0); })()>0);
if(bool){ if(result.bool){
player.logSkill('retongji',trigger.target); event.result = {
trigger.target.discard(cards); bool:true,
const evt=trigger.getParent(); cost_data:{
evt.triggeredTargets2.remove(trigger.target); cards: result.cards
evt.targets.remove(trigger.target); }
evt.targets.push(player); };
} }
}, },
async content(event,trigger,player){
trigger.target.discard(event.cost_data.cards);
const evt=trigger.getParent();
evt.triggeredTargets2.remove(trigger.target);
evt.targets.remove(trigger.target);
evt.targets.push(player);
},
}, },
hujia:{ hujia:{
audio:2, audio:2,
@ -324,13 +330,12 @@ game.import('character',function(lib,game,ui,get,ai,_status){
guicai:{ guicai:{
audio:2, audio:2,
trigger:{global:'judge'}, trigger:{global:'judge'},
direct:true,
preHidden:true, preHidden:true,
filter(event,player){ filter(event,player){
return player.countCards(get.mode()=='guozhan'?'hes':'hs')>0; return player.countCards(get.mode()=='guozhan'?'hes':'hs')>0;
}, },
async content(event,trigger,player){ async cost(event, trigger, player){
const {result:{bool:chooseCardResultBool,cards:chooseCardResultCards}}=await player.chooseCard(get.translation(trigger.player)+'的'+(trigger.judgestr||'')+'判定为'+ const {result:{bool,cards}}=await player.chooseCard(get.translation(trigger.player)+'的'+(trigger.judgestr||'')+'判定为'+
get.translation(trigger.player.judging[0])+''+get.prompt('guicai'),get.mode()=='guozhan'?'hes':'hs',card=>{ get.translation(trigger.player.judging[0])+''+get.prompt('guicai'),get.mode()=='guozhan'?'hes':'hs',card=>{
const player=_status.event.player; const player=_status.event.player;
const mod2=game.checkMod(card,player,'unchanged','cardEnabled2',player); const mod2=game.checkMod(card,player,'unchanged','cardEnabled2',player);
@ -352,7 +357,12 @@ game.import('character',function(lib,game,ui,get,ai,_status){
return -result-get.value(card)/2; return -result-get.value(card)/2;
} }
}).set('judging',trigger.player.judging[0]).setHiddenSkill('guicai'); }).set('judging',trigger.player.judging[0]).setHiddenSkill('guicai');
if(!chooseCardResultBool) return; if(bool) event.result = {bool,cost_data:{cards}}
},
//技能的logSkill跟着打出牌走 不进行logSkill
popup:false,
async content(event,trigger,player){
const chooseCardResultCards = event.cost_data.cards;
player.respond(chooseCardResultCards,'guicai','highlight','noOrdering'); player.respond(chooseCardResultCards,'guicai','highlight','noOrdering');
if(trigger.player.judging[0].clone){ if(trigger.player.judging[0].clone){
trigger.player.judging[0].clone.classList.remove('thrownhighlight'); trigger.player.judging[0].clone.classList.remove('thrownhighlight');
@ -418,29 +428,30 @@ game.import('character',function(lib,game,ui,get,ai,_status){
ganglie_three:{ ganglie_three:{
audio:'ganglie', audio:'ganglie',
trigger:{player:'damageEnd'}, trigger:{player:'damageEnd'},
direct:true, async cost(event, trigger, player){
async content(event,trigger,player){ const {result} = await player.chooseTarget(get.prompt2('ganglie_three'),(card,player,target)=>{
const {result:{bool:chooseTargetResultBool,targets:chooseTargetResultTargets}}=await player.chooseTarget(get.prompt2('ganglie_three'),(card,player,target)=>{
return target.isEnemyOf(player); return target.isEnemyOf(player);
}).set('ai',target=>{ }).set('ai',target=>{
return -get.attitude(_status.event.player,target)/(1+target.countCards('h')); return -get.attitude(_status.event.player,target)/Math.sqrt(1+target.countCards('h'));
}); });
if(!chooseTargetResultBool) return; event.result = result;
event.target=chooseTargetResultTargets[0]; },
player.logSkill('ganglie_three',event.target); async content(event, trigger, player){
event.target = event.targets[0];
player.logSkill('ganglie_three', event.target);
const judgeEvent=player.judge(card=>{ const judgeEvent=player.judge(card=>{
if(get.suit(card)=='heart') return -2; if(get.suit(card)=='heart') return -2;
return 2; return 2;
}); });
judgeEvent.judge2=result=>result.bool; judgeEvent.judge2 = (result => result.bool);
const {result:{judge}}=await judgeEvent; const {result:{judge}} = await judgeEvent;
if(judge<2) return; if (judge < 2) return;
const {result:{bool:chooseToDiscardResultBool}}=await event.target.chooseToDiscard(2).set('ai',card=>{ const {result:{bool:chooseToDiscardResultBool}} = await event.target.chooseToDiscard(2).set('ai',card=>{
if(card.name=='tao') return -10; if (card.name=='tao') return -10;
if(card.name=='jiu'&&_status.event.player.hp==1) return -10; if (card.name=='jiu' && _status.event.player.hp==1) return -10;
return get.unuseful(card)+2.5*(5-get.owner(card).hp); return get.unuseful(card)+2.5*(5-get.owner(card).hp);
}); });
if(chooseToDiscardResultBool==false){ if (chooseToDiscardResultBool === false) {
event.target.damage(); event.target.damage();
} }
}, },
@ -458,24 +469,24 @@ game.import('character',function(lib,game,ui,get,ai,_status){
tuxi:{ tuxi:{
audio:2, audio:2,
trigger:{player:'phaseDrawBegin1'}, trigger:{player:'phaseDrawBegin1'},
direct:true,
filter(event,player){ filter(event,player){
return !event.numFixed; return !event.numFixed;
}, },
async content(event,trigger,player){ async cost(event, trigger, player){
let num=game.countPlayer(current=>current!=player&&current.countCards('h')&&get.attitude(player,current)<=0); let num = game.countPlayer(current => current != player && current.countCards('h') && get.attitude(player,current) <= 0);
let check=num>=2; let check = (num >= 2);
const {result:{bool,targets}}=await player.chooseTarget(get.prompt('tuxi'),'获得其他一至两名角色的各一张手牌',[1,2],(card,player,target)=>{ const {result} = await player.chooseTarget(get.prompt('tuxi'), '获得其他一至两名角色的各一张手牌', [1,2], (card, player, target) => {
return target.countCards('h')>0&&player!=target; return target.countCards('h') > 0 && player != target;
},target=>{ }, target => {
if(!_status.event.aicheck) return 0; if (!_status.event.aicheck) return 0;
const att=get.attitude(_status.event.player,target); const att=get.attitude(_status.event.player, target);
if(target.hasSkill('tuntian')) return att/10; if (target.hasSkill('tuntian')) return att / 10;
return 1-att; return 1 - att;
}).set('aicheck',check); }).set('aicheck', check);
if(!bool) return; event.result = result;
player.logSkill('tuxi',targets); },
player.gainMultiple(targets); async content(event, trigger, player){
player.gainMultiple(event.targets);
trigger.changeToZero(); trigger.changeToZero();
game.asyncDelay(); game.asyncDelay();
}, },
@ -540,71 +551,63 @@ game.import('character',function(lib,game,ui,get,ai,_status){
filter(event){ filter(event){
return event.num>0; return event.num>0;
}, },
async content(event,trigger,player){ getIndex(event, player, triggername){
event.count=trigger.num; return event.num;
// event.goto -> while },
while(true){ async content(event, trigger, player){
event.count--; const {cards}=await game.cardsGotoOrdering(get.cards(2));
const {cards}=await game.cardsGotoOrdering(get.cards(2)); if(_status.connectMode) game.broadcastAll(function(){_status.noclearcountdown=true});
if(_status.connectMode) game.broadcastAll(function(){_status.noclearcountdown=true}); event.given_map={};
event.given_map={}; if(!cards.length) return;
if(!cards.length) return; // event.goto -> do while
// event.goto -> do while do{
do{ const {result:{bool,links}} =
const {result:{bool,links}} = cards.length==1?
cards.length==1? {result:{links:cards.slice(0),bool: true}}:
{result:{links:cards.slice(0),bool: true}}: await player.chooseCardButton('遗计:请选择要分配的牌',true,cards,[1,cards.length])
await player.chooseCardButton('遗计:请选择要分配的牌',true,cards,[1,cards.length]) .set('ai',()=>{
.set('ai',()=>{ if(ui.selected.buttons.length==0) return 1;
if(ui.selected.buttons.length==0) return 1; return 0;
return 0; });
}); if(!bool) return;
if(!bool) return; cards.removeArray(links);
cards.removeArray(links); event.togive=links.slice(0);
event.togive=links.slice(0); const {result:{targets}}=await player.chooseTarget('选择一名角色获得'+get.translation(links),true)
const {result:{targets}}=await player.chooseTarget('选择一名角色获得'+get.translation(links),true) .set('ai',target=>{
.set('ai',target=>{ const att=get.attitude(_status.event.player,target);
const att=get.attitude(_status.event.player,target); if(_status.event.enemy){
if(_status.event.enemy){ return -att;
return -att; }
} else if(att>0){
else if(att>0){ return att/(1+target.countCards('h'));
return att/(1+target.countCards('h')); }
} else{
else{ return att/100;
return att/100; }
} })
}) .set('enemy',get.value(event.togive[0],player,'raw')<0);
.set('enemy',get.value(event.togive[0],player,'raw')<0); if(targets.length){
if(targets.length){ const id=targets[0].playerid,
const id=targets[0].playerid, map=event.given_map;
map=event.given_map; if(!map[id]) map[id]=[];
if(!map[id]) map[id]=[]; map[id].addArray(event.togive);
map[id].addArray(event.togive);
}
}while(cards.length>0);
if(_status.connectMode){
game.broadcastAll(function(){delete _status.noclearcountdown;game.stopCountChoose()});
} }
const list=[]; }while(cards.length>0);
for(const i in event.given_map){ if(_status.connectMode){
const source=(_status.connectMode?lib.playerOL:game.playerMap)[i]; game.broadcastAll(function(){delete _status.noclearcountdown;game.stopCountChoose()});
player.line(source,'green');
if(player!==source&&(get.mode()!=='identity'||player.identity!=='nei')) player.addExpose(0.2);
list.push([source, event.given_map[i]]);
}
game.loseAsync({
gain_list:list,
giver:player,
animate:'draw',
}).setContent('gaincardMultiple');
if(event.count>0&&player.hasSkill(event.name)&&!get.is.blocked(event.name, player)){
const {result:{bool:chooseBoolResultBool}}=await player.chooseBool(get.prompt2(event.name)).set('frequentSkill',event.name);
if(chooseBoolResultBool) player.logSkill(event.name);
else return;
}
else return;
} }
const list=[];
for(const i in event.given_map){
const source=(_status.connectMode?lib.playerOL:game.playerMap)[i];
player.line(source,'green');
if(player!==source&&(get.mode()!=='identity'||player.identity!=='nei')) player.addExpose(0.2);
list.push([source, event.given_map[i]]);
}
game.loseAsync({
gain_list:list,
giver:player,
animate:'draw',
}).setContent('gaincardMultiple');
}, },
ai:{ ai:{
maixie:true, maixie:true,
@ -1632,7 +1635,6 @@ game.import('character',function(lib,game,ui,get,ai,_status){
audio:2, audio:2,
audioname:['re_daqiao','daxiaoqiao'], audioname:['re_daqiao','daxiaoqiao'],
trigger:{target:'useCardToTarget'}, trigger:{target:'useCardToTarget'},
direct:true,
preHidden:true, preHidden:true,
filter(event,player){ filter(event,player){
if(event.card.name!='sha') return false; if(event.card.name!='sha') return false;
@ -1642,8 +1644,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){
current!=player&&lib.filter.targetEnabled(event.card,event.player,current); current!=player&&lib.filter.targetEnabled(event.card,event.player,current);
}); });
}, },
async content(event,trigger,player){ async cost(event,trigger,player){
const [bool,targets,cards]=await player.chooseCardTarget({ event.result = await player.chooseCardTarget({
position:'he', position:'he',
filterCard:lib.filter.cardDiscardable, filterCard:lib.filter.cardDiscardable,
filterTarget:(card,player,target)=>{ filterTarget:(card,player,target)=>{
@ -1674,17 +1676,16 @@ game.import('character',function(lib,game,ui,get,ai,_status){
source:trigger.player, source:trigger.player,
card:trigger.card, card:trigger.card,
}) })
.setHiddenSkill(event.name) .setHiddenSkill(event.name).forResult();
.forResult('bool','targets','cards'); },
if(bool){ async content(event,trigger,player){
const target=targets[0]; const target = event.targets[0];
player.logSkill(event.name,target); player.logSkill(event.name,target);
player.discard(cards); player.discard(event.cards);
const evt=trigger.getParent(); const evt=trigger.getParent();
evt.triggeredTargets2.remove(player); evt.triggeredTargets2.remove(player);
evt.targets.remove(player); evt.targets.remove(player);
evt.targets.push(target); evt.targets.push(target);
}
}, },
ai:{ ai:{
effect:{ effect:{
@ -2209,9 +2210,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){
trigger:{ trigger:{
player:"phaseDrawEnd", player:"phaseDrawEnd",
}, },
direct:true, async cost(event,trigger,player){
async content(event,trigger,player){ const list=['弃牌','摸牌','cancel2'];
const list=['弃牌','摸牌','取消'];
if(!player.countCards('he')) list.remove('弃牌'); if(!player.countCards('he')) list.remove('弃牌');
const control=await player.chooseControl(list,()=>{ const control=await player.chooseControl(list,()=>{
const player=_status.event.player; const player=_status.event.player;
@ -2230,16 +2230,22 @@ game.import('character',function(lib,game,ui,get,ai,_status){
}) })
.set('prompt',get.prompt2('new_jiangchi')) .set('prompt',get.prompt2('new_jiangchi'))
.forResultControl(); .forResultControl();
if (control === 'cancel2') event.result = {bool: false};
else event.result = {
bool: true,
cost_data: control
};
},
async content(event,trigger,player){
const control = event.cost_data;
if(control=='弃牌'){ if(control=='弃牌'){
player.chooseToDiscard(true,'he'); player.chooseToDiscard(true,'he');
player.addTempSkill('jiangchi2','phaseUseEnd'); player.addTempSkill('jiangchi2','phaseUseEnd');
player.logSkill('new_jiangchi');
} }
else if(control=='摸牌'){ else if(control=='摸牌'){
player.draw(); player.draw();
player.addTempSkill('new_jiangchi3','phaseEnd'); player.addTempSkill('new_jiangchi3','phaseEnd');
player.logSkill('new_jiangchi');
} }
}, },
}, },
@ -2301,30 +2307,27 @@ game.import('character',function(lib,game,ui,get,ai,_status){
global:['dying','gainAfter','loseAsyncAfter'], global:['dying','gainAfter','loseAsyncAfter'],
}, },
audio:2, audio:2,
filter(event,player){ getIndex:function(event, player){
if(event.name=='dying') return true; if (event.name !== 'loseAsync') return [event.player];
if(event.giver!=player) return false; else return game.filterPlayer(current => current != player && event.getg(current).length > 0).sortBySeat();
if(event.name=='gain'){ },
return event.player!=player&&event.getg(event.player).length>0; filter(event, player, triggername, target){
if (!target.isIn()) return false;
if (event.name === 'dying') return true;
if (event.giver !== player) return false;
if (event.name === 'gain') {
return event.player!=player&&event.getg(target).length>0;
} }
return game.hasPlayer(current=>current!=player&&event.getg(current).length>0); return game.hasPlayer(current=>current!=player&&event.getg(current).length>0);
}, },
direct:true, logTarget(event, player, triggername, target){
async content(event,trigger,player){ return target;
if(trigger.name!='loseAsync') event.targets=[trigger.player]; },
else event.targets=game.filterPlayer(current=>current!=player&&trigger.getg(current).length>0); check(event, player, triggername, target){
do{ return get.attitude(player,target) > 0;
const target=event.targets.shift(); },
event.target=target; async content(event, trigger, player){
const {result:{bool}}=await player.chooseBool(get.prompt2('xinfu_jiyuan',target)).set('ai',()=>{ event.targets[0].draw();
const evt=_status.event;
return get.attitude(player,evt.getParent().target)>0;
});
if(bool){
player.logSkill('xinfu_jiyuan',target);
target.draw();
}
}while(event.targets.length>0);
}, },
}, },
}, },

View File

@ -13131,7 +13131,7 @@ return event.junling=='junling5'?1:0;});
} }
var info=get.info(trigger.skill); var info=get.info(trigger.skill);
var next=player.chooseBool('是否明置'+get.translation(event.name)+'以发动【'+get.translation(trigger.skill)+'】?'); var next=player.chooseBool('是否明置'+get.translation(event.name)+'以发动【'+get.translation(trigger.skill)+'】?');
next.set('yes',!info.check||info.check(trigger._trigger,player)); next.set('yes',!info.check||info.check(trigger._trigger,player,trigger.triggername,trigger.indexedData));
next.set('hsskill',trigger.skill); next.set('hsskill',trigger.skill);
next.set('ai',nai); next.set('ai',nai);
} }

View File

@ -4302,7 +4302,7 @@ export class Game extends Uninstantable {
* @param { GameEventPromise } event * @param { GameEventPromise } event
* @returns { GameEventPromise } * @returns { GameEventPromise }
*/ */
static createTrigger(name, skill, player, event) { static createTrigger(name, skill, player, event, indexedData) {
let info = get.info(skill); let info = get.info(skill);
if (!info) return false; if (!info) return false;
if ((player.isOut() || player.removed) && !info.forceOut) return; if ((player.isOut() || player.removed) && !info.forceOut) return;
@ -4314,6 +4314,7 @@ export class Game extends Uninstantable {
next.forceDie = true; next.forceDie = true;
next.includeOut = true; next.includeOut = true;
next._trigger = event; next._trigger = event;
next.indexedData = indexedData;
next.setContent('createTrigger'); next.setContent('createTrigger');
return next; return next;
} }

View File

@ -2134,7 +2134,9 @@ export const Content = {
event.doing = doingList.shift(); event.doing = doingList.shift();
while(true){ while(true){
if (trigger.filterStop && trigger.filterStop()) return; if (trigger.filterStop && trigger.filterStop()) return;
const usableSkills = event.doing.todoList.filter(info => lib.filter.filterTrigger(trigger, info.player, event.triggername, info.skill)); const usableSkills = event.doing.todoList.filter(info => {
return lib.filter.filterTrigger(trigger, info.player, event.triggername, info.skill, info.indexedData);
});
if (usableSkills.length == 0){ if (usableSkills.length == 0){
break; break;
} }
@ -2155,25 +2157,32 @@ export const Content = {
event.current = silentSkill; event.current = silentSkill;
} }
else { else {
const currentChoice = event.choice[0]; const currentChoice = event.choice[0], skillsToChoose = event.choice.map(i => i.skill).unique();
if (event.choice.length == 1) { if (event.choice.length === 1 || skillsToChoose.length === 1) {
event.current = currentChoice; event.current = currentChoice;
} }
else{ else{
const currentPlayer = currentChoice.player , skillsToChoose = event.choice.map(i => i.skill); const currentPlayer = currentChoice.player;
const next = currentPlayer.chooseControl(skillsToChoose); const next = currentPlayer.chooseControl(skillsToChoose);
next.set('prompt', '选择下一个触发的技能'); next.set('prompt', '选择下一个触发的技能');
next.set('forceDie', true); next.set('forceDie', true);
next.set('arrangeSkill', true); next.set('arrangeSkill', true);
next.set('includeOut', true); next.set('includeOut', true);
const {result} = await next; const {result} = await next;
event.current = event.doing.todoList.find(info => info.skill == result.control); event.current = usableSkills.find(info => info.skill == result.control);
} }
} }
} }
event.doing.doneList.push(event.current); event.doing.doneList.push(event.current);
event.doing.todoList.remove(event.current); event.doing.todoList.remove(event.current);
await game.createTrigger(event.triggername, event.current.skill, event.current.player, trigger); const result = await game.createTrigger(event.triggername, event.current.skill, event.current.player, trigger, event.current.indexedData).forResult();
if (get.itemtype(event.doing.player) === 'player' && result === 'cancelled'){
for (let i = 0; i < event.doing.todoList.length; i++) {
if (event.current.skill === event.doing.todoList[i].skill) {
event.doing.doneList.push(event.doing.todoList.splice(i--, 1)[0]);
}
}
}
} }
} }
} }
@ -2189,7 +2198,7 @@ export const Content = {
game.expandSkills(invisible); game.expandSkills(invisible);
if (hidden.includes(event.skill)) { if (hidden.includes(event.skill)) {
if (!info.silent && player.hasSkillTag('nomingzhi', false, null, true)) event.finish(); if (!info.silent && player.hasSkillTag('nomingzhi', false, null, true)) event.finish();
else if (!info.direct) event.trigger('triggerHidden'); else if (!info.direct && typeof info.cost !== 'function') event.trigger('triggerHidden');
else event.skillHidden = true; else event.skillHidden = true;
} }
else if (invisible.includes(event.skill)) event.trigger('triggerInvisible'); else if (invisible.includes(event.skill)) event.trigger('triggerInvisible');
@ -2200,7 +2209,10 @@ export const Content = {
"step 1"; "step 1";
if (event.cancelled) return event.finish(); if (event.cancelled) return event.finish();
var info = get.info(event.skill); var info = get.info(event.skill);
if (event.revealed || info.forced) return; if (event.revealed || info.forced) {
event._result = { bool: true };
return;
}
const checkFrequent = function (info) { const checkFrequent = function (info) {
if (player.hasSkillTag('nofrequent', false, event.skill)) return false; if (player.hasSkillTag('nofrequent', false, event.skill)) return false;
if (typeof info.frequent == 'boolean') return info.frequent; if (typeof info.frequent == 'boolean') return info.frequent;
@ -2214,6 +2226,24 @@ export const Content = {
event._result = { bool: true }; event._result = { bool: true };
event._direct = true; event._direct = true;
} }
else if(typeof info.cost === 'function'){
if (checkFrequent(info)) event.frequentSkill = true;
if (player.isUnderControl()) game.swapPlayerAuto(player);
//创建cost事件
var next = game.createEvent(`${event.skill}_cost`);
next.player = player;
if (event.frequentSkill) next.set('frequentSkill', event.skill);
next.set('forceDie', true);
next.set('includeOut', true);
next._trigger = trigger;
next.triggername = event.triggername;
next.skillHidden = event.skillHidden;
next.indexedData = event.indexedData;
if (info.forceDie) next.forceDie = true;
if (info.forceOut) next.includeOut = true;
next.skill = event.skill;
next.setContent(info.cost);
}
else { else {
if (checkFrequent(info)) event.frequentSkill = true; if (checkFrequent(info)) event.frequentSkill = true;
var str; var str;
@ -2221,19 +2251,19 @@ export const Content = {
if (info.prompt) str = info.prompt; if (info.prompt) str = info.prompt;
else if (typeof info.logTarget == 'string') str = get.prompt(event.skill, trigger[info.logTarget], player); else if (typeof info.logTarget == 'string') str = get.prompt(event.skill, trigger[info.logTarget], player);
else if (typeof info.logTarget == 'function') { else if (typeof info.logTarget == 'function') {
const logTarget = info.logTarget(trigger, player); const logTarget = info.logTarget(trigger, player, event.triggername, event.indexedData);
if (get.itemtype(logTarget).startsWith('player')) str = get.prompt(event.skill, logTarget, player); if (get.itemtype(logTarget).startsWith('player')) str = get.prompt(event.skill, logTarget, player);
} }
else str = get.prompt(event.skill, null, player); else str = get.prompt(event.skill, null, player);
if (typeof str == 'function') str = str(trigger, player); if (typeof str == 'function') str = str(trigger, player, event.triggername, event.indexedData);
var next = player.chooseBool(str); var next = player.chooseBool(str);
if (event.frequentSkill) next.set('frequentSkill', event.skill); if (event.frequentSkill) next.set('frequentSkill', event.skill);
next.set('forceDie', true); next.set('forceDie', true);
next.set('includeOut', true); next.set('includeOut', true);
next.ai = () => !check || check(trigger, player); next.ai = () => !check || check(trigger, player, event.triggername, event.indexedData);
if (typeof info.prompt2 == 'function') next.set('prompt2', info.prompt2(trigger, player)); if (typeof info.prompt2 == 'function') next.set('prompt2', info.prompt2(trigger, player, event.triggername, event.indexedData));
else if (typeof info.prompt2 == 'string') next.set('prompt2', info.prompt2); else if (typeof info.prompt2 == 'string') next.set('prompt2', info.prompt2);
else if (info.prompt2 != false) { else if (info.prompt2 != false) {
if (lib.dynamicTranslate[event.skill]) next.set('prompt2', lib.dynamicTranslate[event.skill](player, event.skill)); if (lib.dynamicTranslate[event.skill]) next.set('prompt2', lib.dynamicTranslate[event.skill](player, event.skill));
@ -2257,18 +2287,29 @@ export const Content = {
} }
"step 3"; "step 3";
var info = get.info(event.skill); var info = get.info(event.skill);
if (result && result.bool == false) { if (!result || !result.bool) {
if (info.oncancel) info.oncancel(trigger, player); if (info.oncancel) info.oncancel(trigger, player);
if (event.indexedData === true) {
event.result = 'cancelled';
}
return event.finish(); return event.finish();
} }
let targets = null;
if (result.targets && result.targets.length > 0) {
targets = result.targets.slice(0);
}
else if (info.logTarget) {
if (typeof info.logTarget === 'string') targets = trigger[info.logTarget];
else if (typeof info.logTarget === 'function') targets = info.logTarget(trigger, player, event.triggername, event.indexedData);
}
if (get.itemtype(targets) === 'player'){
targets = [targets];
}
if (info.popup != false && !info.direct) { if (info.popup != false && !info.direct) {
if (info.popup) { let popup_info = event.skill;
player.popup(info.popup); if(typeof info.popup === 'string') popup_info = [event.skill, info.popup];
game.log(player, '发动了', '【' + get.skillTranslation(event.skill, player) + '】'); if (info.logLine === false) player.logSkill(popup_info, false, info.line);
} else player.logSkill(popup_info, targets, info.line);
else if (!info.logTarget || info.logLine === false) player.logSkill(event.skill, false, info.line);
else if (typeof info.logTarget == 'string') player.logSkill(event.skill, trigger[info.logTarget], info.line);
else if (typeof info.logTarget == 'function') player.logSkill(event.skill, info.logTarget(trigger, player), info.line);
} }
var next = game.createEvent(event.skill); var next = game.createEvent(event.skill);
if (typeof info.usable == 'number') { if (typeof info.usable == 'number') {
@ -2280,7 +2321,6 @@ export const Content = {
next.player = player; next.player = player;
next._trigger = trigger; next._trigger = trigger;
next.triggername = event.triggername; next.triggername = event.triggername;
// if ("contents" in info && Array.isArray(info.contents)) { // if ("contents" in info && Array.isArray(info.contents)) {
// next.setContents(info.contents); // next.setContents(info.contents);
// } else { // } else {
@ -2290,6 +2330,12 @@ export const Content = {
next.skillHidden = event.skillHidden; next.skillHidden = event.skillHidden;
if (info.forceDie) next.forceDie = true; if (info.forceDie) next.forceDie = true;
if (info.forceOut) next.includeOut = true; if (info.forceOut) next.includeOut = true;
//传入数据
if (get.itemtype(targets) == 'players') next.targets = targets.slice(0);
if (get.itemtype(result.cards) === 'cards') next.cards = result.cards.slice(0);
//语法糖部分
if ('cost_data' in result) next.cost_data = result.cost_data;
next.indexedData = event.indexedData;
"step 4"; "step 4";
if (!player._hookTrigger) return; if (!player._hookTrigger) return;
if (player._hookTrigger.some(i => { if (player._hookTrigger.some(i => {
@ -3715,7 +3761,7 @@ export const Content = {
player.logSkill.apply(player, event.logSkill); player.logSkill.apply(player, event.logSkill);
} }
} }
if (!game.online) { if (!game.online && !event.chooseonly) {
if (typeof event.delay == 'boolean') { if (typeof event.delay == 'boolean') {
event.done = player.discard(event.result.cards).set('delay', event.delay); event.done = player.discard(event.result.cards).set('delay', event.delay);
} }

View File

@ -333,10 +333,10 @@ export class GameEvent {
this.untrigger(arg1, arg2); this.untrigger(arg1, arg2);
this.finish(); this.finish();
if (notrigger != 'notrigger') { if (notrigger != 'notrigger') {
this.trigger(this.name + 'Cancelled');
if (this.player && lib.phaseName.includes(this.name)) this.player.getHistory('skipped').add(this.name); if (this.player && lib.phaseName.includes(this.name)) this.player.getHistory('skipped').add(this.name);
return this.trigger(this.name + 'Cancelled');
} }
return this; return null;
} }
neutralize(event) { neutralize(event) {
this.untrigger(); this.untrigger();
@ -791,11 +791,36 @@ export class GameEvent {
const info = lib.skill[skill]; const info = lib.skill[skill];
const list = info.firstDo ? firstDo.todoList : info.lastDo ? lastDo.todoList : this.todoList; const list = info.firstDo ? firstDo.todoList : info.lastDo ? lastDo.todoList : this.todoList;
list.push({ if (typeof info.getIndex === 'function') {
skill: skill, const indexedResult = info.getIndex(event, player, name);
player: this.player, if(Array.isArray(indexedResult)){
priority: get.priority(skill), indexedResult.forEach(indexedData => {
}); list.push({
skill: skill,
player: this.player,
priority: get.priority(skill),
indexedData,
})
});
}
else if (typeof indexedResult === 'number' && indexedResult>0){
for(let i = 0; i < indexedResult; i++){
list.push({
skill: skill,
player: this.player,
priority: get.priority(skill),
indexedData: true,
})
}
}
}
else{
list.push({
skill: skill,
player: this.player,
priority: get.priority(skill),
});
}
if (typeof list.player == 'string') list.sort((a, b) => (b.priority - a.priority) || (playerMap.indexOf(a) - playerMap.indexOf(b))); if (typeof list.player == 'string') list.sort((a, b) => (b.priority - a.priority) || (playerMap.indexOf(a) - playerMap.indexOf(b)));
else list.sort((a, b) => b.priority - a.priority); else list.sort((a, b) => b.priority - a.priority);
allbool = true; allbool = true;

View File

@ -371,6 +371,7 @@ export class Player extends HTMLDivElement {
* ``` * ```
*/ */
when() { when() {
const player = this;
if (!_status.postReconnect.player_when) _status.postReconnect.player_when = [ if (!_status.postReconnect.player_when) _status.postReconnect.player_when = [
function (map) { function (map) {
"use strict"; "use strict";
@ -386,7 +387,13 @@ export class Player extends HTMLDivElement {
]; ];
let triggerNames = Array.from(arguments); let triggerNames = Array.from(arguments);
let trigger; let trigger;
let instantlyAdd = true;
if (triggerNames.length == 0) throw 'player.when的参数数量应大于0'; if (triggerNames.length == 0) throw 'player.when的参数数量应大于0';
//从triggerNames中取出instantlyAdd的部分
if (triggerNames.includes(false)) {
instantlyAdd = false;
triggerNames.remove(false);
}
// add other triggerNames // add other triggerNames
// arguments.length = 1 // arguments.length = 1
if (triggerNames.length == 1) { if (triggerNames.length == 1) {
@ -506,7 +513,7 @@ export class Player extends HTMLDivElement {
} }
}); });
}, skillName); }, skillName);
this.addSkill(skillName); if (instantlyAdd !== false) this.addSkill(skillName);
_status.postReconnect.player_when[1][skillName] = true; _status.postReconnect.player_when[1][skillName] = true;
return { return {
/** /**
@ -603,6 +610,14 @@ export class Player extends HTMLDivElement {
if (skill.contentFuns.length > 0) createContent(); if (skill.contentFuns.length > 0) createContent();
return this; return this;
}, },
/**
* 获得技能
* 如果instantlyAdd为false则需要以此法获得技能
**/
finish() {
player.addSkill(skillName);
return this;
}
}; };
} }
/** /**
@ -4188,7 +4203,8 @@ export class Player extends HTMLDivElement {
next.filterCard = get.filter(arguments[i]); next.filterCard = get.filter(arguments[i]);
} }
else if (typeof arguments[i] == 'string') { else if (typeof arguments[i] == 'string') {
get.evtprompt(next, arguments[i]); if (arguments[i]=='chooseonly') next.chooseonly=true;
else get.evtprompt(next, arguments[i]);
} }
if (arguments[i] === null) { if (arguments[i] === null) {
for (var i = 0; i < arguments.length; i++) { for (var i = 0; i < arguments.length; i++) {
@ -7876,14 +7892,14 @@ export class Player extends HTMLDivElement {
skillName = 'player_tempSkills_' + Math.random().toString(36).slice(-8); skillName = 'player_tempSkills_' + Math.random().toString(36).slice(-8);
} while (player.additionalSkills[skillName] != null); } while (player.additionalSkills[skillName] != null);
player.addAdditionalSkill(skillName, skillsToAdd); player.addAdditionalSkill(skillName, skillsToAdd);
player.when(expire).assign({ player.when(expire,false).assign({
firstDo: true, firstDo: true,
priority: Infinity, priority: Infinity,
}).vars({ }).vars({
skillName skillName
}).then(() => { }).then(() => {
player.removeAdditionalSkills(skillName); player.removeAdditionalSkills(skillName);
}); }).finish();
} }
}); });
} }
@ -7926,13 +7942,13 @@ export class Player extends HTMLDivElement {
if (!expire) expire = { global: ['phaseAfter', 'phaseBeforeStart'] }; if (!expire) expire = { global: ['phaseAfter', 'phaseBeforeStart'] };
else if (typeof expire == 'string' || Array.isArray(expire)) expire = { global: expire }; else if (typeof expire == 'string' || Array.isArray(expire)) expire = { global: expire };
this.when(expire).assign({ this.when(expire,false).assign({
firstDo: true, firstDo: true,
}).vars({ }).vars({
bannedSkill: skill, bannedSkill: skill,
}).then(() => { }).then(() => {
delete player.storage[`temp_ban_${bannedSkill}`]; delete player.storage[`temp_ban_${bannedSkill}`];
}); }).finish();
} }
return skill; return skill;
} }

View File

@ -9830,7 +9830,7 @@ export class Library extends Uninstantable {
* @param {string} skill * @param {string} skill
* @returns {boolean} * @returns {boolean}
*/ */
filterTrigger: function (event, player, triggername, skill) { filterTrigger: function (event, player, triggername, skill, indexedData) {
if (player._hookTrigger && player._hookTrigger.some(i => { if (player._hookTrigger && player._hookTrigger.some(i => {
const info = lib.skill[i].hookTrigger; const info = lib.skill[i].hookTrigger;
return info && info.block && info.block(event, player, triggername, skill); return info && info.block && info.block(event, player, triggername, skill);
@ -9853,7 +9853,7 @@ export class Library extends Uninstantable {
if (Array.isArray(info.trigger[role])) return info.trigger[role].includes(triggername); if (Array.isArray(info.trigger[role])) return info.trigger[role].includes(triggername);
return info.trigger[role] == triggername; return info.trigger[role] == triggername;
})) return false; })) return false;
if (info.filter && !info.filter(event, player, triggername)) return false; if (info.filter && !info.filter(event, player, triggername, indexedData)) return false;
if (event._notrigger.includes(player) && !lib.skill.global.includes(skill)) return false; if (event._notrigger.includes(player) && !lib.skill.global.includes(skill)) return false;
if (typeof info.usable == 'number' && player.hasSkill('counttrigger') && if (typeof info.usable == 'number' && player.hasSkill('counttrigger') &&
player.storage.counttrigger && player.storage.counttrigger[skill] >= info.usable) return false; player.storage.counttrigger && player.storage.counttrigger[skill] >= info.usable) return false;
@ -10396,7 +10396,7 @@ export class Library extends Uninstantable {
return (Math.random() - 0.5); return (Math.random() - 0.5);
}, },
seat: function (a, b) { seat: function (a, b) {
var player = lib.tempSortSeat || _status.event.player; var player = lib.tempSortSeat || _status.event.player || game.me || game.players[0];
var delta = get.distance(player, a, 'absolute') - get.distance(player, b, 'absolute'); var delta = get.distance(player, a, 'absolute') - get.distance(player, b, 'absolute');
if (delta) return delta; if (delta) return delta;
delta = parseInt(a.dataset.position) - parseInt(b.dataset.position); delta = parseInt(a.dataset.position) - parseInt(b.dataset.position);