Merge branch 'PR-Branch' of https://github.com/PZ157/noname into PR-Branch

This commit is contained in:
157 2024-03-17 09:21:49 +08:00
commit 964e8ea7ff
69 changed files with 14369 additions and 13489 deletions

BIN
audio/die/clan_wuqiao.mp3 Normal file

Binary file not shown.

BIN
audio/die/sb_gaoshun.mp3 Normal file

Binary file not shown.

BIN
audio/die/sb_xiahoudun.mp3 Normal file

Binary file not shown.

BIN
audio/die/xia_guanyu.mp3 Normal file

Binary file not shown.

BIN
audio/die/xia_shie.mp3 Normal file

Binary file not shown.

BIN
audio/die/xia_shitao.mp3 Normal file

Binary file not shown.

BIN
audio/die/xia_yuzhenzi.mp3 Normal file

Binary file not shown.

BIN
audio/die/yangfeng.mp3 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
audio/skill/clanqiajue1.mp3 Normal file

Binary file not shown.

BIN
audio/skill/clanqiajue2.mp3 Normal file

Binary file not shown.

BIN
audio/skill/mbweiming1.mp3 Normal file

Binary file not shown.

BIN
audio/skill/mbweiming2.mp3 Normal file

Binary file not shown.

BIN
audio/skill/mbweiming3.mp3 Normal file

Binary file not shown.

BIN
audio/skill/mbxuetu1.mp3 Normal file

Binary file not shown.

BIN
audio/skill/mbxuetu2.mp3 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
audio/skill/sbganglie1.mp3 Normal file

Binary file not shown.

BIN
audio/skill/sbganglie2.mp3 Normal file

Binary file not shown.

BIN
audio/skill/sbjinjiu1.mp3 Normal file

Binary file not shown.

BIN
audio/skill/sbjinjiu2.mp3 Normal file

Binary file not shown.

BIN
audio/skill/sbqingjian1.mp3 Normal file

Binary file not shown.

BIN
audio/skill/sbqingjian2.mp3 Normal file

Binary file not shown.

BIN
audio/skill/sbxianzhen1.mp3 Normal file

Binary file not shown.

BIN
audio/skill/sbxianzhen2.mp3 Normal file

Binary file not shown.

BIN
audio/skill/twchue1.mp3 Normal file

Binary file not shown.

BIN
audio/skill/twchue2.mp3 Normal file

Binary file not shown.

BIN
audio/skill/twdengjian1.mp3 Normal file

Binary file not shown.

BIN
audio/skill/twdengjian2.mp3 Normal file

Binary file not shown.

BIN
audio/skill/twenchou1.mp3 Normal file

Binary file not shown.

BIN
audio/skill/twenchou2.mp3 Normal file

Binary file not shown.

BIN
audio/skill/twhuajing1.mp3 Normal file

Binary file not shown.

BIN
audio/skill/twhuajing2.mp3 Normal file

Binary file not shown.

BIN
audio/skill/twjieqiu1.mp3 Normal file

Binary file not shown.

BIN
audio/skill/twjieqiu2.mp3 Normal file

Binary file not shown.

BIN
audio/skill/twtianshou1.mp3 Normal file

Binary file not shown.

BIN
audio/skill/twtianshou2.mp3 Normal file

Binary file not shown.

BIN
audio/skill/twxinshou1.mp3 Normal file

Binary file not shown.

BIN
audio/skill/twxinshou2.mp3 Normal file

Binary file not shown.

BIN
audio/skill/twzhongyi1.mp3 Normal file

Binary file not shown.

BIN
audio/skill/twzhongyi2.mp3 Normal file

Binary file not shown.

View File

@ -12804,7 +12804,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){
dcjianshu_info:'出牌阶段限一次。你可以将一张黑色手牌交给一名其他角色并选择另一名其他角色你令前者与后者拼点。赢的角色随机弃置一张牌没赢的角色失去1点体力。若有角色因此死亡你令你〖间书〗于此阶段发动的次数上限+1。', dcjianshu_info:'出牌阶段限一次。你可以将一张黑色手牌交给一名其他角色并选择另一名其他角色你令前者与后者拼点。赢的角色随机弃置一张牌没赢的角色失去1点体力。若有角色因此死亡你令你〖间书〗于此阶段发动的次数上限+1。',
dcyongdi:'拥嫡', dcyongdi:'拥嫡',
dcyongdi_info:'限定技。出牌阶段你可以选择一名男性角色若其体力上限最少其加1点体力上限体力值最少其回复1点体力手牌数最少其摸X张牌X为其体力上限且至多为5。', dcyongdi_info:'限定技。出牌阶段你可以选择一名男性角色若其体力上限最少其加1点体力上限体力值最少其回复1点体力手牌数最少其摸X张牌X为其体力上限且至多为5。',
liupi:'刘辟', liupi:'新杀刘辟',
liupi_prefix:'新杀',
dcjuying:'踞营', dcjuying:'踞营',
dcjuying_info:'出牌阶段结束时若你于此阶段内使用【杀】的次数未达到上限你可以选择任意项1.下回合使用【杀】的次数上限+12.本回合手牌上限+23.摸三张牌。若你选择的项数超过了你的体力值,你弃置一张牌。', dcjuying_info:'出牌阶段结束时若你于此阶段内使用【杀】的次数未达到上限你可以选择任意项1.下回合使用【杀】的次数上限+12.本回合手牌上限+23.摸三张牌。若你选择的项数超过了你的体力值,你弃置一张牌。',
dc_huanghao:'新杀黄皓', dc_huanghao:'新杀黄皓',

View File

@ -26,7 +26,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
}, },
}, },
character:{ character:{
yangfeng:['male','shu',4,['mbxuetu','mbweiming']], yangfeng:['male','qun',4,['mbxuetu','mbweiming']],
xin_huojun:['male','shu',4,['sidai','jieyu'],['character:tw_huojun','die_audio:tw_huojun']], xin_huojun:['male','shu',4,['sidai','jieyu'],['character:tw_huojun','die_audio:tw_huojun']],
muludawang:['male','qun','3/3/1',['shoufa','zhoulin','yuxiang']], muludawang:['male','qun','3/3/1',['shoufa','zhoulin','yuxiang']],
mb_chengui:['male','qun',3,['guimou','zhouxian']], mb_chengui:['male','qun',3,['guimou','zhouxian']],
@ -399,6 +399,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
//杨奉 //杨奉
mbxuetu:{ mbxuetu:{
audio:2, audio:2,
audioname:['re_yangfeng'],
enable:'phaseUse', enable:'phaseUse',
usable:2, usable:2,
filter(event,player){ filter(event,player){
@ -528,41 +529,45 @@ game.import('character',function(lib,game,ui,get,ai,_status){
}, },
}, },
mbweiming:{ mbweiming:{
audio:2, audio:3,
trigger:{
player:'phaseUseBegin',
},
filter(event,player){
return game.hasPlayer(current => {
return !player.getStorage('mbweiming').includes(current);
});
},
dutySkill:true, dutySkill:true,
forced:true, locked:true,
direct:true, group:['mbweiming_achieve', 'mbweiming_fail','mbweiming_effect'],
group:['mbweiming_achieve', 'mbweiming_fail'],
async content(event, trigger, player){
const targets = await player.chooseTarget('威命:记录一名未记录过的角色','当你杀死没有被记录过的角色后,则〖威命〗使命成功;如果在你杀死这些角色中的一名之前,有被记录过的角色死亡,则你〖威命〗使命失败。',true)
.set('filterTarget', (card, player, target) => {
return !player.getStorage('mbweiming').includes(target);
})
.set('ai', target => {
if (target === player) return 1;
return 1 + Math.sqrt(Math.abs(get.attitude(player, target))) * Math.abs(get.threaten(target)) / Math.sqrt(target.getHp() + 1) / Math.sqrt(target.countCards('hes') + 1);
})
.forResultTargets();
if (targets && targets.length > 0) {
const target = targets[0];
player.logSkill('mbweiming', target);
player.markAuto('mbweiming', target);
}
},
intro:{ intro:{
content: '已记录$', content: '已记录$',
}, },
subSkill: { subSkill: {
effect:{
audio:'mbweiming1.mp3',
trigger:{
player:'phaseUseBegin',
},
filter(event,player){
return game.hasPlayer(current => {
return !player.getStorage('mbweiming').includes(current);
});
},
forced:true,
direct:true,
async content(event, trigger, player){
const targets = await player.chooseTarget('威命:记录一名未记录过的角色','当你杀死没有被记录过的角色后,则〖威命〗使命成功;如果在你杀死这些角色中的一名之前,有被记录过的角色死亡,则你〖威命〗使命失败。',true)
.set('filterTarget', (card, player, target) => {
return !player.getStorage('mbweiming').includes(target);
})
.set('ai', target => {
if (target === player) return 1;
return 1 + Math.sqrt(Math.abs(get.attitude(player, target))) * Math.abs(get.threaten(target)) / Math.sqrt(target.getHp() + 1) / Math.sqrt(target.countCards('hes') + 1);
})
.forResultTargets();
if (targets && targets.length > 0) {
const target = targets[0];
player.logSkill('mbweiming_effect', target);
player.markAuto('mbweiming', target);
}
},
},
achieve: { achieve: {
audio:'mbweiming', audio:'mbweiming2.mp3',
trigger:{ trigger:{
source:'dieAfter', source:'dieAfter',
}, },
@ -582,7 +587,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
} }
}, },
fail: { fail: {
audio:'mbweiming', audio:'mbweiming3.mp3',
trigger:{ trigger:{
global:'dieAfter', global:'dieAfter',
}, },
@ -595,6 +600,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){
game.log(player,'使命失败'); game.log(player,'使命失败');
player.awakenSkill('mbweiming'); player.awakenSkill('mbweiming');
player.storage.mbxuetu_status = 2; player.storage.mbxuetu_status = 2;
game.broadcastAll(player=>{
player.tempname.add('re_yangfeng');
},player);
await game.asyncDelayx(); await game.asyncDelayx();
} }
}, },

View File

@ -374,6 +374,9 @@ window.noname_character_rank={
'star_zhangchunhua', 'star_zhangchunhua',
], ],
am:[ am:[
'tw_yanliang',
'tw_wenchou',
'tw_yuantan',
'bailingyun', 'bailingyun',
'clan_wuqiao', 'clan_wuqiao',
'muludawang', 'muludawang',
@ -992,6 +995,7 @@ window.noname_character_rank={
'yuanji', 'yuanji',
'dc_chenqun', 'dc_chenqun',
'liupi', 'liupi',
'ol_liupi',
'mazhong', 'mazhong',
're_mazhong', 're_mazhong',
'tw_baoxin', 'tw_baoxin',
@ -2173,6 +2177,9 @@ window.noname_character_rank={
'dc_sb_simayi', 'dc_sb_simayi',
], ],
rare:[ rare:[
'tw_yanliang',
'tw_wenchou',
'tw_yuantan',
'zhugemengxue', 'zhugemengxue',
'ol_sb_taishici', 'ol_sb_taishici',
'clan_wuqiao', 'clan_wuqiao',
@ -2602,6 +2609,7 @@ window.noname_character_rank={
'xin_caoxiu', 'xin_caoxiu',
'dc_chenqun', 'dc_chenqun',
'liupi', 'liupi',
'ol_liupi',
'tw_baoxin', 'tw_baoxin',
'tw_bingyuan', 'tw_bingyuan',
'tw_chenzhen', 'tw_chenzhen',

View File

@ -1533,7 +1533,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
group:['sbhuoji_fire','sbhuoji_achieve','sbhuoji_fail','sbhuoji_mark'], group:['sbhuoji_fire','sbhuoji_achieve','sbhuoji_fail','sbhuoji_mark'],
subSkill:{ subSkill:{
fire:{ fire:{
audio:'sbhuoji1', audio:'sbhuoji1.mp3',
enable:'phaseUse', enable:'phaseUse',
filterTarget:lib.filter.notMe, filterTarget:lib.filter.notMe,
prompt:'选择一名其他角色对其与其势力相同的所有其他角色各造成1点火属性伤害', prompt:'选择一名其他角色对其与其势力相同的所有其他角色各造成1点火属性伤害',
@ -1568,7 +1568,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
}, },
}, },
achieve:{ achieve:{
audio:'sbhuoji2', audio:'sbhuoji2.mp3',
trigger:{player:'phaseZhunbeiBegin'}, trigger:{player:'phaseZhunbeiBegin'},
filter:function(event,player){ filter:function(event,player){
return player.getAllHistory('sourceDamage',evt=>evt.hasNature('fire')).reduce((num,evt)=>num+evt.num,0)>=game.players.length+game.dead.length; return player.getAllHistory('sourceDamage',evt=>evt.hasNature('fire')).reduce((num,evt)=>num+evt.num,0)>=game.players.length+game.dead.length;
@ -1585,7 +1585,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
}, },
}, },
fail:{ fail:{
audio:'sbhuoji3', audio:'sbhuoji3.mp3',
trigger:{player:'dying'}, trigger:{player:'dying'},
forced:true, forced:true,
locked:false, locked:false,
@ -1615,9 +1615,6 @@ game.import('character',function(lib,game,ui,get,ai,_status){
}, },
}, },
}, },
sbhuoji1:{audio:true},
sbhuoji2:{audio:true},
sbhuoji3:{audio:true},
sbkanpo:{ sbkanpo:{
init:function(player){ init:function(player){
if(!player.storage.sbkanpo){ if(!player.storage.sbkanpo){
@ -6589,7 +6586,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
forced:true, forced:true,
locked:false, locked:false,
filter:function(event,player){ filter:function(event,player){
return player.hasSkill('splveying',null,false,false)&&(get.type(event.card)=='trick'&&!get.tag(event.card,'damage'))&&player.countMark('splveying')>1; return player.hasSkill('splveying',null,null,false)&&(get.type(event.card)=='trick'&&!get.tag(event.card,'damage'))&&player.countMark('splveying')>1;
}, },
content:function(){ content:function(){
player.removeMark('splveying',2); player.removeMark('splveying',2);

View File

@ -18,7 +18,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
sp_zhongdan:["cuiyan","huangfusong"], sp_zhongdan:["cuiyan","huangfusong"],
sp_guozhan2:["sp_dongzhuo","liqueguosi","zhangren"], sp_guozhan2:["sp_dongzhuo","liqueguosi","zhangren"],
sp_others:["hanba","caiyang"], sp_others:["hanba","caiyang"],
sp_waitforsort:['ol_luyusheng','ol_pengyang','ol_tw_zhangji','ol_liwan','ol_liuyan','caoyu','liupan','ol_lukai'], sp_waitforsort:['ol_luyusheng','ol_pengyang','ol_tw_zhangji','ol_liwan','ol_liuyan','caoyu','liupan','ol_lukai','ol_liupi'],
}, },
}, },
characterFilter:{ characterFilter:{
@ -30,6 +30,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
}, },
}, },
character:{ character:{
ol_liupi:['male','qun',4,['olyicheng']],
ol_lukai:['male','wu',3,['olxuanzhu','oljiane']], ol_lukai:['male','wu',3,['olxuanzhu','oljiane']],
liupan:['male','qun',4,['olpijing']], liupan:['male','qun',4,['olpijing']],
guotu:['male','qun',3,['olqushi','olweijie']], guotu:['male','qun',3,['olqushi','olweijie']],
@ -45,7 +46,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
lvboshe:['male','qun',4,['olfushi','oldongdao']], lvboshe:['male','qun',4,['olfushi','oldongdao']],
ol_luyusheng:['female','wu',3,['olcangxin','olrunwei']], ol_luyusheng:['female','wu',3,['olcangxin','olrunwei']],
caoxi:['male','wei',3,['olgangshu','oljianxuan']], caoxi:['male','wei',3,['olgangshu','oljianxuan']],
ol_pengyang:['male','shu',3,['olqifan','oltuishi','nzry_cunmu']], ol_pengyang:['male','shu',3,['olxiaofan','oltuishi','nzry_cunmu']],
ol_qianzhao:['male','wei',4,['olweifu','olkuansai']], ol_qianzhao:['male','wei',4,['olweifu','olkuansai']],
niujin:['male','wei',4,['olcuorui','liewei']], niujin:['male','wei',4,['olcuorui','liewei']],
hejin:['male','qun',4,['mouzhu','olyanhuo']], hejin:['male','qun',4,['mouzhu','olyanhuo']],
@ -711,6 +712,85 @@ game.import('character',function(lib,game,ui,get,ai,_status){
}, },
}, },
skill:{ skill:{
//刘辟
olyicheng:{
audio:2,
enable:'phaseUse',
usable:1,
async content(event,trigger,player){
let cards=get.cards(3);
await game.cardsGotoOrdering(cards);
await player.showCards(cards,get.translation(player)+'发动了【易城】');
if(player.countCards('h')){
const sum=cards.reduce((num,card)=>num+get.number(card),0);
const {result:{bool,moved}}=await player.chooseToMove('易城:请选择你要交换的牌').set('list',[
['牌堆顶',cards,list=>{
const sum2=list.reduce((num,card)=>num+get.number(card,false),0);
return '牌堆顶(现'+sum2+{'0':'=','-1':'<','1':'>'}[get.sgn(sum2-sum).toString()]+'原'+sum+'';
}],
['手牌',player.getCards('h')],
]).set('filterOk',moved=>moved[1].some(i=>!get.owner(i))).set('processAI',list=>{
const player=get.event('player'),limit=Math.min(3,player.countCards('h'));
let cards=list[0][1].slice(),hs=player.getCards('h');
if(cards.reduce((num,card)=>num+get.value(card),0)>player.getCards('h').reduce((num,card)=>num+get.value(card),0)){
cards.sort((a,b)=>get.number(a)-get.number(b));
hs.sort((a,b)=>get.number(b)-get.number(a));
let cards2=cards.slice(0,limit),hs2=hs.slice(0,limit);
if(hs2.reduce((num,card)=>num+get.number(card),0)>cards2.reduce((num,card)=>num+get.number(card),0)){
cards.removeArray(cards2);hs.removeArray(hs2);
return [cards.concat(hs2),hs.concat(cards2)];
}
return [cards,hs];
}
else{
cards.sort((a,b)=>get.value(b)-get.value(a));
hs.sort((a,b)=>get.value(a)-get.value(b));
let cards2=cards.slice(0,limit),hs2=hs.slice(0,limit),list=[cards,hs];
for(let i=0;i<limit;i++){
if(get.value(cards2[i])>get.value(hs2[i])){
const change=[cards2[i],hs2[i]];
cards[i]=change[1];hs[i]=change[0];
}
else break;
}
return list;
}
});
if(bool){
const puts=player.getCards('h',i=>moved[0].includes(i));
const gains=cards.filter(i=>moved[1].includes(i));
if(puts.length&&gains.length){
player.$throw(puts,1000);
await player.lose(puts,ui.special);
await player.gain(gains,'gain2');
cards=moved[0].slice();
await player.showCards(cards,get.translation(player)+'【易城】第一次交换后');
if(cards.reduce((num,card)=>num+get.number(card),0)>sum&&player.countCards('h')){
const {result:{bool}}=await player.chooseBool('易城:是否使用全部手牌交换'+get.translation(cards)+'').set('choice',(()=>{
return cards.reduce((num,card)=>num+get.value(card),0)>player.getCards('h').reduce((num,card)=>num+get.value(card),0);
})());
if(bool){
const hs=player.getCards('h');
player.$throw(hs,1000);
await player.lose(hs,ui.special);
await player.gain(cards,'gain2');
cards=hs.slice();
await player.showCards(cards,get.translation(player)+'【易城】第二次交换后');
}
}
}
}
if(cards.length){
await game.cardsDiscard(cards);
//game.log(cards,'被置入了弃牌堆');
}
}
},
ai:{
order:9,
result:{player:1},
},
},
//陆凯 //陆凯
olxuanzhu:{ olxuanzhu:{
mark:true, mark:true,
@ -2457,8 +2537,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){
}, },
check:function(card){ check:function(card){
var player=_status.event.player; var player=_status.event.player;
if(player.hasSkill('hezhong')){ if(player.hasSkill('hezhong')&&(!(player.hasSkill('hezhong_0')&&player.hasSkill('hezhong_1')))){
if(player.countCards('h')-ui.selected.cards.length>1) return 1/(get.value(card)||0.5); if(player.countCards('h')-ui.selected.cards.length>2) return 1/(get.value(card)||0.5);
return 0; return 0;
} }
if(ui.selected.cards.length<player.countCards('h')/2) return 5-get.value(card); if(ui.selected.cards.length<player.countCards('h')/2) return 5-get.value(card);
@ -2478,7 +2558,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
'step 1' 'step 1'
player.chooseToDiscard('h','宴如:弃置至少一半手牌',[Math.floor(player.countCards('h')/2),Infinity],true).set('ai',card=>{ player.chooseToDiscard('h','宴如:弃置至少一半手牌',[Math.floor(player.countCards('h')/2),Infinity],true).set('ai',card=>{
var player=_status.event.player; var player=_status.event.player;
if(player.hasSkill('hezhong')&&player.countCards('h')-ui.selected.cards.length>1) return 1/(get.value(card)||0.5); if(player.hasSkill('hezhong')&&(!(player.hasSkill('hezhong_0')&&player.hasSkill('hezhong_1')))&&player.countCards('h')-ui.selected.cards.length>2) return 1/(get.value(card)||0.5);
if(!player.hasSkill('hezhong')&&ui.selected.cards.length<Math.floor(player.countCards('h')/2)) return 1/(get.value(card)||0.5); if(!player.hasSkill('hezhong')&&ui.selected.cards.length<Math.floor(player.countCards('h')/2)) return 1/(get.value(card)||0.5);
return 0; return 0;
}); });
@ -3244,15 +3324,15 @@ game.import('character',function(lib,game,ui,get,ai,_status){
}, },
}, },
//OL彭羕 //OL彭羕
olqifan:{ olxiaofan:{
audio:2, audio:2,
enable:'chooseToUse', enable:'chooseToUse',
hiddenCard:function(player,name){ hiddenCard:function(player,name){
if(name!='wuxie'&&lib.inpile.includes(name)) 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, getNum:(player)=>player.getHistory('useCard').reduce((list,evt)=>list.add(get.type2(evt.card)),[]).length,
filter:function(event,player){ filter:function(event,player){
if(event.responded||event.type=='wuxie'||event.olqifan) return false; if(event.responded||event.type=='wuxie'||event.olxiaofan) return false;
for(var i of lib.inpile){ for(var i of lib.inpile){
if(i!='wuxie'&&event.filterCard(get.autoViewAs({name:i},'unsure'),player,event)) return true; if(i!='wuxie'&&event.filterCard(get.autoViewAs({name:i},'unsure'),player,event)) return true;
} }
@ -3262,8 +3342,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){
content:function(){ content:function(){
'step 0' 'step 0'
var evt=event.getParent(2); var evt=event.getParent(2);
evt.set('olqifan',true); evt.set('olxiaofan',true);
var cards=get.bottomCards(lib.skill.olqifan.getNum()+1,true); var cards=get.bottomCards(lib.skill.olxiaofan.getNum(player)+1,true);
var aozhan=player.hasSkill('aozhan'); var aozhan=player.hasSkill('aozhan');
player.chooseButton(['嚣翻:选择要使用的牌',cards]).set('filterButton',function(button){ player.chooseButton(['嚣翻:选择要使用的牌',cards]).set('filterButton',function(button){
return _status.event.cards.includes(button.link); return _status.event.cards.includes(button.link);
@ -3300,11 +3380,11 @@ game.import('character',function(lib,game,ui,get,ai,_status){
},evt.player,evt)?'sha':'shan'; },evt.player,evt)?'sha':'shan';
} }
game.broadcastAll(function(result,name){ game.broadcastAll(function(result,name){
lib.skill.olqifan_backup.viewAs={name:name,cards:[result],isCard:true}; lib.skill.olxiaofan_backup.viewAs={name:name,cards:[result],isCard:true};
},card,name); },card,name);
evt.set('_backupevent','olqifan_backup'); evt.set('_backupevent','olxiaofan_backup');
evt.set('openskilldialog',('请选择'+get.translation(card)+'的目标')) evt.set('openskilldialog',('请选择'+get.translation(card)+'的目标'))
evt.backup('olqifan_backup'); evt.backup('olxiaofan_backup');
} }
evt.goto(0); evt.goto(0);
}, },
@ -3326,8 +3406,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){
} }
}, },
}, },
olqifan_backup:{ olxiaofan_backup:{
sourceSkill:'olqifan', sourceSkill:'olxiaofan',
precontent:function(){ precontent:function(){
delete event.result.skill; delete event.result.skill;
var name=event.result.card.name,cards=event.result.card.cards.slice(0); var name=event.result.card.name,cards=event.result.card.cards.slice(0);
@ -3338,9 +3418,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){
event.result.card=card; event.result.card=card;
var id=get.id(); var id=get.id();
player.when('chooseToUseAfter').filter((evt)=>evt==event.getParent()).then(()=>{ player.when('chooseToUseAfter').filter((evt)=>evt==event.getParent()).then(()=>{
var num=lib.skill.olqifan.getNum(),pos=('jeh').slice(0,num); var num=lib.skill.olxiaofan.getNum(player),pos=('jeh').slice(0,num);
if(num>0&&player.countCards(pos)>0){ if(num>0&&player.countCards(pos)>0){
event.maxNum=Math.min(3,lib.skill.olqifan.getNum()); event.maxNum=Math.min(3,num);
event.num=0; event.num=0;
} }
else event.finish(); else event.finish();
@ -3410,7 +3490,15 @@ game.import('character',function(lib,game,ui,get,ai,_status){
trigger:{player:'useCard1'}, trigger:{player:'useCard1'},
filter:function(event,player){ filter:function(event,player){
if(!event.targets||!event.targets.length) return false; if(!event.targets||!event.targets.length) return false;
return event.targets.some(target=>player.countCards('h')+event.cards.length>target.countCards('h')); let num=0;
if(event.cards&&event.cards.length){
const history=player.getHistory('lose',evt=>{
if(evt.getParent()!=event) return false;
return event.cards.some(card=>evt.hs.includes(card));
});
if(history.length) num+=event.cards.filter(card=>history[0].hs.includes(card)).length;
}
return event.targets.some(target=>player.countCards('h')+num>target.countCards('h')+(target==player?num:0));
}, },
forced:true, forced:true,
popup:false, popup:false,
@ -18675,8 +18763,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){
filter:function(event,player){ filter:function(event,player){
var num; var num;
var mode=get.mode(); var mode=get.mode();
if(mode=='identity'){ if(mode=='identity'||mode=='doudizhu'){
if(_status.mode=='purple') num=player.getEnemies().length; if(mode=='identity'&&_status.mode=='purple') num=player.getEnemies().length;
else num=get.population('fan'); else num=get.population('fan');
} }
else if(mode=='versus'){ else if(mode=='versus'){
@ -26434,6 +26522,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
zhangren:['jsrg_zhangren','zhangren'], zhangren:['jsrg_zhangren','zhangren'],
wenqin:['ol_wenqin','pe_wenqin'], wenqin:['ol_wenqin','pe_wenqin'],
lukai:['ol_lukai','lukai'], lukai:['ol_lukai','lukai'],
liupi:['ol_liupi','liupi'],
}, },
translate:{ translate:{
"xinfu_lingren":"凌人", "xinfu_lingren":"凌人",
@ -26799,6 +26888,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
hongde_info:'当你一次获得或失去至少两张牌后,你可以令一名其他角色摸一张牌。', hongde_info:'当你一次获得或失去至少两张牌后,你可以令一名其他角色摸一张牌。',
dingpan:'定叛', dingpan:'定叛',
dingpan_info_identity:'出牌阶段限X次你可以令一名装备区里有牌的角色摸一张牌然后其选择一项1.令你弃置其装备区里的一张牌2.获得其装备区里的所有牌若如此做你对其造成1点伤害。X为场上存活的反贼数', dingpan_info_identity:'出牌阶段限X次你可以令一名装备区里有牌的角色摸一张牌然后其选择一项1.令你弃置其装备区里的一张牌2.获得其装备区里的所有牌若如此做你对其造成1点伤害。X为场上存活的反贼数',
dingpan_info_doudizhu:'出牌阶段限X次你可以令一名装备区里有牌的角色摸一张牌然后其选择一项1.令你弃置其装备区里的一张牌2.获得其装备区里的所有牌若如此做你对其造成1点伤害。X为场上存活的农民数',
dingpan_info_versus_two:'出牌阶段限X次你可以令一名装备区里有牌的角色摸一张牌然后其选择一项1.令你弃置其装备区里的一张牌2.获得其装备区里的所有牌若如此做你对其造成1点伤害。X为场上存活的最大阵营角色数', dingpan_info_versus_two:'出牌阶段限X次你可以令一名装备区里有牌的角色摸一张牌然后其选择一项1.令你弃置其装备区里的一张牌2.获得其装备区里的所有牌若如此做你对其造成1点伤害。X为场上存活的最大阵营角色数',
dingpan_info_versus:'出牌阶段限X次你可以令一名装备区里有牌的角色摸一张牌然后其选择一项1.令你弃置其装备区里的一张牌2.获得其装备区里的所有牌若如此做你对其造成1点伤害。X为场上存活的敌方角色数', dingpan_info_versus:'出牌阶段限X次你可以令一名装备区里有牌的角色摸一张牌然后其选择一项1.令你弃置其装备区里的一张牌2.获得其装备区里的所有牌若如此做你对其造成1点伤害。X为场上存活的敌方角色数',
dingpan_info:'出牌阶段限一次你可以令一名装备区里有牌的角色摸一张牌然后其选择一项1.令你弃置其装备区里的一张牌2.获得其装备区里的所有牌若如此做你对其造成1点伤害。', dingpan_info:'出牌阶段限一次你可以令一名装备区里有牌的角色摸一张牌然后其选择一项1.令你弃置其装备区里的一张牌2.获得其装备区里的所有牌若如此做你对其造成1点伤害。',
@ -27585,8 +27675,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){
oljianxuan:'谏旋', oljianxuan:'谏旋',
oljianxuan_info:'当你受到伤害后,你可以令一名角色摸一张牌,然后若其手牌数等于你〖刚述①〗中的任意一项对应的数值,其重复此流程。', oljianxuan_info:'当你受到伤害后,你可以令一名角色摸一张牌,然后若其手牌数等于你〖刚述①〗中的任意一项对应的数值,其重复此流程。',
ol_pengyang:'彭羕', ol_pengyang:'彭羕',
olqifan:'嚣翻', olxiaofan:'嚣翻',
olqifan_info:'当你需要使用不为【无懈可击】的牌时你可以观看牌堆底的X+1张牌并使用其中的一张。此牌结算结束时你依次弃置以下前X个区域中的所有牌⒈判定区、⒉装备区、⒊手牌区X为本回合使用过的牌中包含的类型数)。', olxiaofan_info:'当你需要使用不为【无懈可击】的牌时你可以观看牌堆底的X+1张牌并使用其中的一张。此牌结算结束时你依次弃置以下前X个区域中的所有牌⒈判定区、⒉装备区、⒊手牌区X为本回合使用过的牌中包含的类型数)。',
oltuishi:'侻失', oltuishi:'侻失',
oltuishi_info:'锁定技。①你不能使用【无懈可击】。②当你使用点数为字母的牌时,你令此牌无效并摸一张牌,且你对手牌数小于你的角色使用的下一张牌无距离和次数限制。', oltuishi_info:'锁定技。①你不能使用【无懈可击】。②当你使用点数为字母的牌时,你令此牌无效并摸一张牌,且你对手牌数小于你的角色使用的下一张牌无距离和次数限制。',
ol_tw_zhangji:'张既', ol_tw_zhangji:'张既',
@ -27664,6 +27754,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){
olxuanzhu_info:'转换技,每回合限一次,你可以将一张牌称为“玄”置于武将牌上,然后视为使用:阴,任意基本牌;阳,任意普通锦囊牌(须指定目标且仅指定一个目标)。若此次置于武将牌上的“玄”:不为装备牌,你弃置一张牌;为装备牌,你将所有“玄”置入弃牌堆,然后摸等量的牌。', olxuanzhu_info:'转换技,每回合限一次,你可以将一张牌称为“玄”置于武将牌上,然后视为使用:阴,任意基本牌;阳,任意普通锦囊牌(须指定目标且仅指定一个目标)。若此次置于武将牌上的“玄”:不为装备牌,你弃置一张牌;为装备牌,你将所有“玄”置入弃牌堆,然后摸等量的牌。',
oljiane:'謇谔', oljiane:'謇谔',
oljiane_info:'锁定技。①当你对其他角色使用的牌生效后,其本回合无法抵消牌。②当你抵消牌后,你本回合无法成为牌的目标。', oljiane_info:'锁定技。①当你对其他角色使用的牌生效后,其本回合无法抵消牌。②当你抵消牌后,你本回合无法成为牌的目标。',
ol_liupi:'刘辟',
olyicheng:'易城',
olyicheng_info:'出牌阶段限一次,你可以亮出牌堆顶的三张牌,然后你可以以任意手牌交换这些牌,若这三张牌的点数和因此增加,则你可以选择用所有手牌交换这三张牌。',
sp_tianji:'天极·皇室宗亲', sp_tianji:'天极·皇室宗亲',
sp_sibi:'四弼·辅国文曲', sp_sibi:'四弼·辅国文曲',

View File

@ -2479,7 +2479,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
xinqicai_info:'锁定技,你使用锦囊牌无距离限制。', xinqicai_info:'锁定技,你使用锦囊牌无距离限制。',
xinqicai_info_alter:'锁定技,你使用的锦囊牌无距离限制,你装备区内的牌不能被弃置。', xinqicai_info_alter:'锁定技,你使用的锦囊牌无距离限制,你装备区内的牌不能被弃置。',
qicai_info:'锁定技,你使用锦囊牌无距离限制。', qicai_info:'锁定技,你使用锦囊牌无距离限制。',
zhiheng_info:'出牌阶段一次,你可以弃置任意张牌,然后摸等量的牌。', zhiheng_info:'出牌阶段一次,你可以弃置任意张牌,然后摸等量的牌。',
xinzhiheng:'制衡', xinzhiheng:'制衡',
xinzhiheng_info:'出牌阶段限1次你可以弃置任意张牌并摸等量的牌。', xinzhiheng_info:'出牌阶段限1次你可以弃置任意张牌并摸等量的牌。',
xinzhiheng_info_alter:'出牌阶段限1次你可以弃置任意张牌并摸等量的牌如果在发动制衡时弃置了所有手牌你额外摸一张牌。', xinzhiheng_info_alter:'出牌阶段限1次你可以弃置任意张牌并摸等量的牌如果在发动制衡时弃置了所有手牌你额外摸一张牌。',

View File

@ -5,7 +5,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
connect:true, connect:true,
characterSort:{ characterSort:{
tw:{ tw:{
tw_sp:['tw_zhangzhao','tw_zhanghong','tw_fuwan','tw_yujin','tw_zhaoxiang','tw_hucheer','tw_hejin','tw_mayunlu','tw_re_caohong','tw_zangba','tw_liuhong','tw_tianyu','jiachong','duosidawang','wuban','yuejiu','tw_caocao','tw_zhangmancheng','tw_caozhao','tw_wangchang','tw_puyangxing','tw_jiangji','tw_niujin','tw_xiahouen','tw_xiahoushang','tw_zhangji','tw_zhangnan','tw_fengxí','tw_furong','tw_liwei','tw_yangyi','tw_daxiaoqiao','tw_dengzhi','tw_baoxin','tw_bingyuan','tw_fanchou','tw_haomeng','tw_huchuquan','tw_jianshuo','tw_jiling','tw_liufuren','tw_liuzhang','tw_mateng','tw_niufudongxie','tw_qiaorui','tw_weixu','tw_yanxiang','tw_yufuluo','tw_zhangning','tw_dengzhi','tw_yangyi','tw_yangang','tw_gongsunfan'], tw_sp:['tw_yanliang','tw_wenchou','tw_yuantan','tw_zhangzhao','tw_zhanghong','tw_fuwan','tw_yujin','tw_zhaoxiang','tw_hucheer','tw_hejin','tw_mayunlu','tw_re_caohong','tw_zangba','tw_liuhong','tw_tianyu','jiachong','duosidawang','wuban','yuejiu','tw_caocao','tw_zhangmancheng','tw_caozhao','tw_wangchang','tw_puyangxing','tw_jiangji','tw_niujin','tw_xiahouen','tw_xiahoushang','tw_zhangji','tw_zhangnan','tw_fengxí','tw_furong','tw_liwei','tw_yangyi','tw_daxiaoqiao','tw_dengzhi','tw_baoxin','tw_bingyuan','tw_fanchou','tw_haomeng','tw_huchuquan','tw_jianshuo','tw_jiling','tw_liufuren','tw_liuzhang','tw_mateng','tw_niufudongxie','tw_qiaorui','tw_weixu','tw_yanxiang','tw_yufuluo','tw_zhangning','tw_dengzhi','tw_yangyi','tw_yangang','tw_gongsunfan'],
tw_yunchouzhi:['tw_wangcan','tw_dongzhao','tw_bianfuren','tw_feiyi','tw_chenzhen','tw_xunchen'], tw_yunchouzhi:['tw_wangcan','tw_dongzhao','tw_bianfuren','tw_feiyi','tw_chenzhen','tw_xunchen'],
tw_yunchouxin:['tw_wangling','tw_huojun','tw_wujing','tw_zhouchu'], tw_yunchouxin:['tw_wangling','tw_huojun','tw_wujing','tw_zhouchu'],
tw_yunchouren:['tw_xujing','tw_qiaogong'], tw_yunchouren:['tw_xujing','tw_qiaogong'],
@ -20,6 +20,9 @@ game.import('character',function(lib,game,ui,get,ai,_status){
}, },
}, },
character:{ character:{
tw_yanliang:['male','qun',4,['twduwang','twylyanshi']],
tw_wenchou:['male','qun',4,['twjuexing','twxiayong']],
tw_yuantan:['male','qun',4,['twqiaosi','twbaizu']],
xia_yuzhenzi:['male','qun',3,['twhuajing','twtianshou']], xia_yuzhenzi:['male','qun',3,['twhuajing','twtianshou']],
xia_shie:['male','wei',4,['twdengjian','twxinshou']], xia_shie:['male','wei',4,['twdengjian','twxinshou']],
xia_shitao:['male','qun',4,['twjieqiu','twenchou']], xia_shitao:['male','qun',4,['twjieqiu','twenchou']],
@ -291,6 +294,473 @@ game.import('character',function(lib,game,ui,get,ai,_status){
}, },
}, },
skill:{ skill:{
//颜良文丑,但是颜良+文丑
twduwang:{
audio:3,
dutySkill:true,
derivation:'twxiayong',
global:'twduwang_global',
group:['twduwang_effect','twduwang_achieve','twduwang_fail'],
subSkill:{
effect:{
audio:'twduwang1.mp3',
trigger:{player:'phaseUseBegin'},
filter(event,player){
return game.hasPlayer(target=>{
return target!=player&&target.hasCard(card=>{
if(get.position(card)=='h') return true;
return target.canUse(get.autoViewAs({name:'juedou'},[card]),player,false);
},'he');
});
},
async cost(event,trigger,player){
let {result}=await player.chooseTarget([1,3],(_,player,target)=>{
return target!=player&&target.hasCard(card=>{
if(get.position(card)=='h') return true;
return target.canUse(get.autoViewAs({name:'juedou'},[card]),player,false);
},'he');
}).set('prompt',get.prompt('twduwang')).set('ai',target=>{
const player=get.event('player');
const num=game.countPlayer(current=>{
return current!=player&&current.hasCard(card=>{
if(get.position(card)=='h') return true;
return current.canUse(get.autoViewAs({name:'juedou'},[card]),player,false);
},'he')&&get.effect(current,{name:'guohe_copy2'},current,player)+get.effect(player,{name:'juedou'},current,player)>0;
});
return (Math.min(num,3)+1)*get.effect(player,{name:'draw'},player,player)+get.effect(target,{name:'guohe_copy2'},target,player)+get.effect(player,{name:'juedou'},target,player);
}).set('prompt2','选择至多三名其他角色并摸选择角色数+1的牌然后这些角色须将一张牌当作【决斗】对你使用');
if(result.bool) result.targets.sortBySeat();
event.result=result;
},
async content(event,trigger,player){
const targets=event.targets;
player.logSkill('twduwang_effect',targets);
await player.draw(targets.length+1);
for(const target of targets){
if(!target.hasCard(card=>{
return target.canUse(get.autoViewAs({name:'juedou'},[card]),player,false);
},'he')) continue;
await target.chooseToUse()
.set('forced',true)
.set('openskilldialog','独往:将一张牌当作【决斗】对'+get.translation(player)+'使用')
.set('norestore',true)
.set('_backupevent','twduwang_backup')
.set('targetRequired',true)
.set('complexSelect',true)
.set('custom',{
add:{},
replace:{window:function(){}}
})
.backup('twduwang_backup')
.set('filterTarget',function(card,player,target){
if(target!=_status.event.sourcex&&!ui.selected.targets.includes(_status.event.sourcex)) return false;
return lib.filter.targetEnabled.apply(this,arguments);
})
.set('sourcex',player)
.set('addCount',false);
}
},
},
backup:{
viewAs:{name:'juedou'},
position:'he',
check(card){
if(get.name(card)=='sha') return 5-get.value(card);
return 8-get.value(card);
},
},
achieve:{
audio:'twduwang2.mp3',
trigger:{player:'phaseZhunbeiBegin'},
filter(event,player){
const history=player.actionHistory;
if(history.length<2) return false;
for(let i=history.length-2;i>=0;i--){
if(history[i].isMe){
let num=history[i].useCard.filter(evt=>{
return evt.card.name=='juedou';
}).length,targets=game.players.slice().concat(game.dead.slice());
for(const target of targets){
num+=target.actionHistory[i].useCard.filter(evt=>{
return evt.card.name=='juedou'&&evt.targets&&evt.targets.includes(player);
}).length;
}
return num>=(targets.length<4?3:4);
}
}
return false;
},
forced:true,
skillAnimation:true,
animationColor:'metal',
async content(event,trigger,player){
player.awakenSkill('twduwang');
game.log(player,'完成使命');
let result;
if(player.hasSkill('twxiayong',null,false,false)) result={index:1};
else result=await player.chooseControl().set('choiceList',[
'获得技能【狭勇】',
//'重置【独往】和【延势】,删除【独往】的使命失败分支,获得【延势】的历战效果',
'重置【独往】和【延势】,删除【独往】的使命失败分支',
]).set('prompt','独往:请选择一项').set('ai',()=>{
/*
const player=get.event('player'),num=game.countPlayer(current=>{
return current!=player&&current.hasCard(card=>{
if(get.position(card)=='h') return true;
return current.canUse(get.autoViewAs({name:'juedou'},[card]),player,false);
},'he')&&get.effect(current,{name:'guohe_copy2'},current,player)+get.effect(player,{name:'juedou'},current,player);
});
return Math.max(0,Math.min(2,num)-1);
*/
return 1;
}).forResult();
if(result.index==0) await player.addSkills('twxiayong');
else{
for(const skill of ['twduwang','twylyanshi']){
if(player.awakenedSkills.includes(skill)){
player.restoreSkill(skill);
player.popup(skill);
game.log(player,'重置了技能','#g【'+get.translation(skill)+'】');
}
}
player.storage.twduwang_fail=true;
game.log(player,'修改了技能','#g【独往】');
}
},
},
fail:{
audio:'twduwang3.mp3',
trigger:{player:'die'},
forceDie:true,
filter(event,player){
return !player.storage.twduwang_fail;
},
forced:true,
content(){
player.awakenSkill('twduwang');
game.log(player,'使命失败');
},
},
global:{
mod:{
cardSavable(card,player,target){
if(card.name=='tao'&&target!=player&&target.hasSkill('twduwang')&&!target.storage.twduwang_fail) return false;
},
},
audio:'twduwang3.mp3',
trigger:{player:'dying'},
filter(event,player){
return player.hasSkill('twduwang')&&!player.storage.twduwang_fail;
},
forced:true,
content(){},
},
},
},
twylyanshi:{
audio:2,
enable:['chooseToUse','chooseToRespond'],
filter(event,player){
return ['juedou','binglinchengxiax'].concat(get.zhinangs()).some(name=>{
const info={name:name};
return get.info(info)&&player.hasCard(card=>{
return get.name(card)=='sha'&&event.filterCard({name:name,cards:[card]},player,event);
},'hs');
});
},
limited:true,
skillAnimation:true,
animationColor:'fire',
chooseButton:{
dialog(event,player){
const list=['juedou','binglinchengxiax'].concat(get.zhinangs()).filter(name=>{
const info={name:name};
return get.info(info)&&player.hasCard(card=>{
return get.name(card)=='sha'&&event.filterCard({name:name,cards:[card]},player,event);
},'hs');
}).map(name=>[get.translation(get.type(name)),'',name]);
return ui.create.dialog('延势',[list,'vcard']);
},
check(button){
return get.event('player').getUseValue({name:button.link[2]});
},
backup(links,player){
return {
audio:'twylyanshi',
filterCard(card,player){
return get.name(card)=='sha';
},
popname:true,
check(card){
return 5-get.value(card);
},
position:'hs',
viewAs:{name:links[0][2]},
precontent(){
delete event.result.skill;
player.logSkill('twylyanshi');
player.awakenSkill('twylyanshi');
},
}
},
prompt(links,player){
return '将一张【杀】当作'+'【'+get.translation(links[0][2])+'】使用';
}
},
subSkill:{backup:{}},
hiddenCard(player,name){
if(player.awakenedSkills.includes('twylyanshi')||!player.countCards('hs',card=>_status.connectMode||get.name(card)=='sha')) return false;
return ['juedou','binglinchengxiax'].concat(get.zhinangs()).includes(name);
},
ai:{
order(item,player){
if(!player||_status.event.type!='phase') return 0.001;
let max=0,names=['juedou','binglinchengxiax'].concat(get.zhinangs()).filter(name=>{
const info={name:name};
return get.info(info)&&player.hasCard(card=>{
return get.name(card)=='sha'&&player.hasValueTarget(get.autoViewAs(info,[card]),true,true);
},'hs');
});
if(!names.length) return 0;
names=names.map(namex=>{return {name:namex}});
names.forEach(card=>{
if(player.getUseValue(card)>0){
let temp=get.order(card);
if(temp>max) max=temp;
}
});
if(max>0) max+=0.3;
return max;
},
result:{player:1},
},
},
twjuexing:{
audio:2,
enable:'phaseUse',
filter(event,player){
return game.hasPlayer(target=>get.info('twjuexing').filterTarget(null,player,target));
},
filterTarget(_,player,target){
const card=new lib.element.VCard({name:'juedou'});
return target!=player&&player.canUse(card,target);
},
usable:1,
async content(event,trigger,player){
const target=event.target;
const card=new lib.element.VCard({name:'juedou'});
player.when({global:'juedouBegin'}).filter(evt=>evt.getParent(2)==event)
.vars({target:target}).then(()=>{
player.addSkill('twjuexing_buff');
target.addSkill('twjuexing_buff');
}).then(()=>{
let list=[];
for(const i of [player,target]){
if(i.isIn()&&i.countCards('h')){
list.push([i,i.getCards('h')]);
}
}
if(list.length){
game.loseAsync({
lose_list:list,
log:true,
animate:'giveAuto',
gaintag:['twjuexing_buff'],
}).setContent(get.info('sbquhu').addToExpansionMultiple);
}
}).then(()=>{
if(player.getHp()) player.draw(player.getHp(),(target.getHp()?'nodelay':'')).gaintag=['twjuexing'];
if(target.getHp()) target.draw(target.getHp()).gaintag=['twjuexing'];
});
player.when({global:'useCardAfter'}).filter(evtx=>evtx.getParent()==event)
.vars({target:target}).then(()=>{
let list=[];
for(const i of [player,target]){
if(i.isIn()&&i.hasCard(card=>card.hasGaintag('twjuexing'),'h')){
list.push([i,i.getCards('h',card=>card.hasGaintag('twjuexing'))]);
}
}
if(list.length){
game.loseAsync({lose_list:list}).setContent('discardMultiple');
}
}).then(()=>{
let listx=[];
for(const i of [player,target]){
if(i.isIn()&&i.getExpansions('twjuexing_buff').length){
listx.push([i,i.getExpansions('twjuexing_buff')]);
}
}
if(listx.length){
game.loseAsync({gain_list:listx,animate:'draw'}).setContent('gaincardMultiple');
}
}).then(()=>{
player.removeSkill('twjuexing_buff');
target.removeSkill('twjuexing_buff');
});
await player.useCard(card,target,false);
},
ai:{
order:1,
result:{
target(player,target){
return get.sgn(get.attitude(player,target))*get.effect(target,{name:'juedou'},player,player)*((player.getHp()+1)/(target.getHp()+1));
},
},
},
subSkill:{
tuzhan:{
charlotte:true,
onremove:true,
marktext:'战',
intro:{content:'因【绝行】摸牌时,摸牌数+#'},
trigger:{player:'drawBegin'},
filter(event,player){
return (event.gaintag||[]).includes('twjuexing');
},
forced:true,
popup:false,
content(){
player.popup('历战');
game.log(player,'触发了','#g【绝行】','的','#y历战','效果');
trigger.num++;
},
},
buff:{
charlotte:true,
onremove(player,skill){
const cards=player.getExpansions(skill);
if(cards.length) player.gain(cards,'gain2');
},
intro:{
markcount:'expansion',
mark(dialog,_,player){
var cards=player.getExpansions('twjuexing_buff');
if(player.isUnderControl(true)) dialog.addAuto(cards);
else return '共有'+get.cnNumber(cards.length)+'张牌';
},
},
},
},
},
twxiayong:{
audio:2,
audioname:['tw_yanliang'],
trigger:{global:'damageBegin2'},
filter(event,player){
if(event.getParent().type!='card'||event.card.name!='juedou'||!event.player.isIn()) return false;
const evt=game.getGlobalHistory('useCard',evt=>evt.card==event.card)[0];
if(evt&&evt.targets&&(event.player!=player||player.countCards('h'))){
if(evt.player==player){
return evt.targets.includes(event.player)&&event.player!=player;
}
return evt.targets.includes(player)&&evt.player!=player;
}
return false;
},
forced:true,
logTarget:'player',
content(){
trigger.player==player?player.chooseToDiscard('h',true):trigger.num++;
},
},
//袁谭
twqiaosi:{
audio:2,
trigger:{player:'phaseJieshuBegin'},
filter(event,player){
return get.info('twqiaosi').getCards(player).length;
},
check(event,player){
const cards=get.info('twqiaosi').getCards(player);
if(cards.reduce((sum,card)=>sum+get.value(card),0)) return false;
if(cards.length>=player.getHp()||cards.some(card=>get.name(card,player)=='tao'||get.name(card,player)=='jiu')) return true;
return player.getHp()>2&&cards.length>1;
},
prompt2(event,player){
const cards=get.info('twqiaosi').getCards(player);
let str='获得'+get.translation(cards);
if(cards.length<player.getHp()) str+='然后你失去1点体力';
return str;
},
async content(event,trigger,player){
const cards=get.info('twqiaosi').getCards(player);
await player.gain(cards,'gain2');
if(cards.length<player.getHp()) await player.loseHp();
},
getCards(player){
let cards=[],targets=game.players.slice().concat(game.dead.slice());
for(const target of targets){
if(target==player) continue;
const history=target.getHistory('lose',evt=>evt.position==ui.discardPile);
if(history.length){
for(const evt of history) cards.addArray(evt.cards2.filterInD('d'));
}
}
const historyx=game.getGlobalHistory('cardMove',evt=>{
if(evt.name!='cardsDiscard') return false;
const evtx=evt.getParent();
if(evtx.name!='orderingDiscard') return false;
const evt2=(evtx.relatedEvent||evtx.getParent());
if(evt2.name=='phaseJudge'||evt2.player==player) return false;
return evt.cards.filterInD('d').length;
});
if(historyx.length){
for(const evtx of historyx) cards.addArray(evtx.cards.filterInD('d'));
}
return cards;
},
},
twbaizu:{
audio:2,
trigger:{player:'phaseJieshuBegin'},
filter(event,player){
return player.isDamaged()&&player.countCards('h')&&game.hasPlayer(target=>{
return target!=player&&target.countCards('h');
})&&(player.getHp()+player.countMark('twbaizu_tuzhan'));
},
forced:true,
async content(event,trigger,player){
const sum=player.getHp()+player.countMark('twbaizu_tuzhan');
let result,filterTarget=(_,player,target)=>{
return target!=player&&target.countCards('h');
},targets=game.filterPlayer(target=>filterTarget(null,player,target));
if(targets.length<=sum) result={bool:true,targets:targets};
else result=await player.chooseTarget('请选择【败族】的目标','令你和这些角色同时弃置一张手牌然后你对与你弃置牌类别相同的角色各造成1点伤害',filterTarget,sum,true).set('ai',target=>{
const player=get.event('player');
return get.effect(target,{name:'guohe_copy2'},target,player)+get.damageEffect(target,player,player);
}).forResult();
if(result.bool){
targets=result.targets.sortBySeat();
player.line(targets);
let list=[player].concat(targets).filter(target=>target.countDiscardableCards(target,'h'));
if(list.length){
let discards=[];
const {result}=await player.chooseCardOL(list,'败族:弃置一张手牌',(card,player)=>{
return lib.filter.cardDiscardable(card,player);
},true).set('ai',get.unuseful);
if(result){
for(let i=0;i<result.length;i++){
discards.push([list[i],result[i].cards]);
}
await game.loseAsync({lose_list:discards}).setContent('discardMultiple');
list=list.filter(i=>get.type2(result[0].cards[0])==get.type2(result[list.indexOf(i)].cards[0]));
if(list.length){
player.line(list);
for(const i of list) await i.damage();
}
}
}
}
},
subSkill:{
tuzhan:{
charlotte:true,
onremove:true,
marktext:'战',
intro:{content:'【败族】目标选择数+#'},
},
},
},
//玉真子 //玉真子
twhuajing:{ twhuajing:{
audio:2, audio:2,
@ -663,14 +1133,14 @@ game.import('character',function(lib,game,ui,get,ai,_status){
if(!player.hasSkill('twxinshou_1')) return goon&&game.hasPlayer(target=>target!=player); if(!player.hasSkill('twxinshou_1')) return goon&&game.hasPlayer(target=>target!=player);
return !player.hasSkill('twdengjian_ban')&&game.hasPlayer(target=>{ return !player.hasSkill('twdengjian_ban')&&game.hasPlayer(target=>{
if(target==player) return false; if(target==player) return false;
return !target.hasSkill('twdengjian',null,false,false); return !target.hasSkill('twdengjian',null,null,false);
})&&player.hasSkill('twdengjian',null,false,false); })&&player.hasSkill('twdengjian',null,null,false);
}, },
direct:true, direct:true,
async content(event,trigger,player){ async content(event,trigger,player){
if(player.hasSkill('twxinshou_0')&&player.hasSkill('twxinshou_1')){ if(player.hasSkill('twxinshou_0')&&player.hasSkill('twxinshou_1')){
const {result:{bool,targets}}=await player.chooseTarget((card,player,target)=>{ const {result:{bool,targets}}=await player.chooseTarget((card,player,target)=>{
return target!=player&&!target.hasSkill('twdengjian',null,false,false); return target!=player&&!target.hasSkill('twdengjian',null,null,false);
}).set('ai',target=>{ }).set('ai',target=>{
const player=get.event('player'); const player=get.event('player');
if(get.attitude(player,target)>0){ if(get.attitude(player,target)>0){
@ -689,13 +1159,14 @@ game.import('character',function(lib,game,ui,get,ai,_status){
const target=targets[0]; const target=targets[0];
player.logSkill('twxinshou',target); player.logSkill('twxinshou',target);
player.addSkill('twdengjian_ban'); player.addSkill('twdengjian_ban');
target.addAdditionalSkill('twxinshou_'+player.playerid,'twdengjian'); target.addAdditionalSkills('twxinshou_'+player.playerid,'twdengjian');
player.popup('登剑'); player.popup('登剑');
target.popup('登剑'); target.popup('登剑');
game.log(player,'将','#g【登剑】','传授给了',target); game.log(player,'将','#g【登剑】','传授给了',target);
game.log(player,'的','#g【登剑】','被失效了'); game.log(player,'的','#g【登剑】','被失效了');
player.when('phaseBegin').then(()=>{ player.when('phaseBegin').then(()=>{
target.removeAdditionalSkill('twxinshou_'+player.playerid); target.removeAdditionalSkills('twxinshou_'+player.playerid);
}).then(()=>{
const history=game.getAllGlobalHistory('everything'); const history=game.getAllGlobalHistory('everything');
for(let i=history.length-1;i>=0;i--){ for(let i=history.length-1;i>=0;i--){
const evt=history[i]; const evt=history[i];
@ -708,6 +1179,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
if(evt==evtx) break; if(evt==evtx) break;
} }
player.popup('杯具'); player.popup('杯具');
player.chat('剑法废掉了...');
}).vars({target:target,evtx:event}); }).vars({target:target,evtx:event});
} }
} }
@ -733,7 +1205,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
player.logSkill('twxinshou'); player.logSkill('twxinshou');
if(control=='摸牌'){ if(control=='摸牌'){
player.addTempSkill('twxinshou_0'); player.addTempSkill('twxinshou_0');
player.draw(); await player.draw();
} }
if(control=='给牌'){ if(control=='给牌'){
player.addTempSkill('twxinshou_1'); player.addTempSkill('twxinshou_1');
@ -750,7 +1222,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
if(bool){ if(bool){
const target=targets[0]; const target=targets[0];
player.line(target); player.line(target);
player.chooseToGive(target,'he',true); await player.chooseToGive(target,'he',true);
} }
} }
} }
@ -780,7 +1252,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
} }
} }
target.disableEquip(disables); target.disableEquip(disables);
if(num) target.draw(num); if(num) await target.draw(num);
target.addSkill('twjieqiu_buff'); target.addSkill('twjieqiu_buff');
target.markAuto('twjieqiu_buff',[player]); target.markAuto('twjieqiu_buff',[player]);
target.when('enableEquipEnd') target.when('enableEquipEnd')
@ -823,7 +1295,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
[transList,'tdnodes'], [transList,'tdnodes'],
],num,true).set('map',map) ],num,true).set('map',map)
.set('ai',button=>['equip5','equip4','equip1','equip3','equip2'].indexOf(get.event('map')[button.link])+2); .set('ai',button=>['equip5','equip4','equip1','equip3','equip2'].indexOf(get.event('map')[button.link])+2);
if(bool) player.enableEquip(links.slice().map(i=>map[i])); if(bool) await player.enableEquip(links.slice().map(i=>map[i]));
}, },
group:['twjieqiu_end'], group:['twjieqiu_end'],
}, },
@ -877,7 +1349,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
[transList,'tdnodes'], [transList,'tdnodes'],
],true).set('map',map) ],true).set('map',map)
.set('ai',button=>1/(['equip5','equip4','equip1','equip3','equip2'].indexOf(get.event('map')[button.link])+2)); .set('ai',button=>1/(['equip5','equip4','equip1','equip3','equip2'].indexOf(get.event('map')[button.link])+2));
if(bool) target.enableEquip(links.slice().map(i=>map[i])); if(bool) await target.enableEquip(links.slice().map(i=>map[i]));
}, },
ai:{ ai:{
order:9, order:9,
@ -13534,7 +14006,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
'step 0' 'step 0'
player.chooseTarget(get.prompt2('twjuezhu'),[1,2],function(card,player,target){ player.chooseTarget(get.prompt2('twjuezhu'),[1,2],function(card,player,target){
return !ui.selected.targets.length&&!target.hasSkill('feiying'); return !ui.selected.targets.length&&!target.hasSkill('feiying');
}).set('promptbar','none').set('ai',function(target){ }).set('multitarget',true).set('promptbar','none').set('ai',function(target){
if(player.hasUnknown()) return false; if(player.hasUnknown()) return false;
return get.attitude(player,target); return get.attitude(player,target);
}); });
@ -15441,6 +15913,13 @@ game.import('character',function(lib,game,ui,get,ai,_status){
str+='②你使用“剑法”牌不计入次数限制。'; str+='②你使用“剑法”牌不计入次数限制。';
return str; return str;
}, },
twduwang(player){
let str='使命技。使命出牌阶段开始时你可以选择至多三名其他角色并摸X张牌X为选择角色数+1然后这些角色依次将一张牌当作【决斗】对你使用。成功准备阶段若你上回合使用和成为【决斗】的次数和不小于4若游戏总人数小于4则改为3你选择一项①获得技能〖狭勇〗②重置〖独往〗和〖延势〗并删除〖独往〗的使命失败分支。';
if(player.storage.twduwang_fail) str+='<span style="text-decoration: line-through; ">';
str+='失败:当你进入濒死状态时,其他角色不能对你使用【桃】,当你死亡时,使命失败。';
if(player.storage.twduwang_fail) str+='</span>';
return str;
},
}, },
translate:{ translate:{
tw_beimihu:'TW卑弥呼', tw_beimihu:'TW卑弥呼',
@ -16111,6 +16590,21 @@ game.import('character',function(lib,game,ui,get,ai,_status){
twhuajing_gong_info:'当你使用【杀】造成伤害后,你随机弃置受伤角色装备区里的一张牌。', twhuajing_gong_info:'当你使用【杀】造成伤害后,你随机弃置受伤角色装备区里的一张牌。',
twtianshou:'天授', twtianshou:'天授',
twtianshou_info:'锁定技,回合结束时,若你本回合使用【杀】造成过伤害,且你拥有本回合获得过效果的“武”标记,则你须将其中一个“武”标记交给一名其他角色并令其获得此标记的效果直到其回合结束,然后你摸两张牌。', twtianshou_info:'锁定技,回合结束时,若你本回合使用【杀】造成过伤害,且你拥有本回合获得过效果的“武”标记,则你须将其中一个“武”标记交给一名其他角色并令其获得此标记的效果直到其回合结束,然后你摸两张牌。',
tw_yanliang:'颜良',
tw_wenchou:'文丑',
tw_yuantan:'袁谭',
twduwang:'独往',
twduwang_info:'使命技。使命出牌阶段开始时你可以选择至多三名其他角色并摸X张牌X为选择角色数+1然后这些角色依次将一张牌当作【决斗】对你使用。成功准备阶段若你上回合使用和成为【决斗】的次数和不小于4若游戏总人数小于4则改为3你选择一项①获得技能〖狭勇〗②重置〖独往〗和〖延势〗并删除〖独往〗的使命失败分支。失败当你进入濒死状态时其他角色不能对你使用【桃】当你死亡时使命失败。',
twylyanshi:'延势',
twylyanshi_info:'限定技,你可以将一张【杀】当作【决斗】、【兵临城下】或任意智囊牌使用或打出。',
twjuexing:'绝行',
twjuexing_info:'出牌阶段限一次,你可以视为对一名其他角色使用【决斗】。此【决斗】生效时,你与其将所有手牌扣置于武将牌上,然后各摸等同于当前体力值的牌,此牌结算完毕后,你与其弃置本次以此法摸的牌,然后获得扣置于武将牌上的牌。历战:当你因〖绝行〗摸牌时,摸牌数+1。',
twxiayong:'狭勇',
twxiayong_info:'锁定技,当你使用的【决斗】对其他角色造成伤害时,或其他角色使用【决斗】对你造成伤害时,若受伤角色为/不为你,则你弃置一张牌/此伤害+1。',
twqiaosi:'峭嗣',
twqiaosi_info:'结束阶段你可以获得其他角色本回合从其手牌区和装备区进入弃牌堆的牌然后若你以此法获得的牌数小于你的体力值则你失去1点体力。',
twbaizu:'败族',
twbaizu_info:'锁定技结束阶段若你已受伤且你有手牌则你须选择X名有手牌的其他角色X为你的体力值你与这些角色同时弃置一张手牌然后你对与你弃置牌类别相同的所有角色各造成1点伤害。历战〖败族〗目标选择数+1。',
tw_mobile:'海外服·稀有专属', tw_mobile:'海外服·稀有专属',
tw_yunchouzhi:'运筹帷幄·智', tw_yunchouzhi:'运筹帷幄·智',

View File

@ -5569,37 +5569,43 @@ game.import('character',function(lib,game,ui,get,ai,_status){
}, },
qinqing:{ qinqing:{
audio:2, audio:2,
mode:['identity','versus'], mode:['identity','versus','doudizhu'],
available:function(mode){ available:function(mode){
if(mode=='versus'&&_status.mode!='four') return false; if(mode=='versus'&&_status.mode!='four') return false;
if(mode=='identity'&&_status.mode=='purple') return false; if(mode=='identity'&&_status.mode=='purple') return false;
}, },
getZhu:(player)=>{
if(get.mode=='doudizhu') return game.findPlayer(i=>i.identity=='zhu');
return get.zhu(player);
},
trigger:{player:'phaseJieshuBegin'}, trigger:{player:'phaseJieshuBegin'},
direct:true, direct:true,
filter:function(event,player){ filter:function(event,player){
var zhu=get.zhu(player); var zhu=get.info('qinqing').getZhu(player);
if(!zhu||!zhu.isZhu) return false; if(!zhu||(get.mode!='doudizhu'&&!zhu.isZhu)) return false;
return game.hasPlayer(function(current){ return game.hasPlayer(function(current){
return current!=zhu&&current.inRange(zhu); return current!=zhu&&current.inRange(zhu);
}); });
}, },
content:function(){ content:function(){
'step 0' 'step 0'
event.zhu=get.info('qinqing').getZhu(player);
player.chooseTarget(get.prompt2('qinqing'),[1,Infinity],function(card,player,target){ player.chooseTarget(get.prompt2('qinqing'),[1,Infinity],function(card,player,target){
var zhu=get.zhu(player); var zhu=get.event('zhu');
if(target==zhu) return false; if(target==zhu) return false;
return target.inRange(zhu); return target.inRange(zhu);
}).set('ai',function(target){ }).set('ai',function(target){
var he=target.countCards('he') var he=target.countCards('he');
var zhu=get.event('zhu');
if(get.attitude(_status.event.player,target)>0){ if(get.attitude(_status.event.player,target)>0){
if(he==0) return 1; if(he==0) return 1;
if(target.countCards('h')>get.zhu(player).countCards('h')) return 1; if(target.countCards('h')>zhu.countCards('h')) return 1;
} }
else{ else{
if(he>0) return 1; if(he>0) return 1;
} }
return 0; return 0;
}); }).set('zhu',event.zhu);
'step 1' 'step 1'
if(result.bool){ if(result.bool){
event.targets=result.targets.slice(0).sortBySeat(); event.targets=result.targets.slice(0).sortBySeat();
@ -5620,9 +5626,8 @@ game.import('character',function(lib,game,ui,get,ai,_status){
} }
'step 3' 'step 3'
var num=0; var num=0;
var zhu=get.zhu(player); if(event.zhu){
if(zhu){ var nh=event.zhu.countCards('h');
var nh=zhu.countCards('h');
for(var i=0;i<event.list.length;i++){ for(var i=0;i<event.list.length;i++){
if(event.list[i].countCards('h')>nh){ if(event.list[i].countCards('h')>nh){
num++; num++;
@ -14151,6 +14156,7 @@ game.import('character',function(lib,game,ui,get,ai,_status){
jiyu_info:'出牌阶段限一次你可以令一名角色弃置一张手牌。若如此做你不能使用与之相同花色的牌直到回合结束。若其以此法弃置的牌为黑桃你翻面并令其失去1点体力。若你有未被〖讥谀〗限制的手牌则你可以继续发动此技能但不能选择本回合已经选择过的目标。', jiyu_info:'出牌阶段限一次你可以令一名角色弃置一张手牌。若如此做你不能使用与之相同花色的牌直到回合结束。若其以此法弃置的牌为黑桃你翻面并令其失去1点体力。若你有未被〖讥谀〗限制的手牌则你可以继续发动此技能但不能选择本回合已经选择过的目标。',
qinqing:'寝情', qinqing:'寝情',
qinqing_info:'结束阶段你可以选择任意名攻击范围内含有主公的角色然后弃置这些角色各一张牌并令其摸一张牌无牌则不弃若如此做你摸X张牌X为其中手牌比主公多的角色数。', qinqing_info:'结束阶段你可以选择任意名攻击范围内含有主公的角色然后弃置这些角色各一张牌并令其摸一张牌无牌则不弃若如此做你摸X张牌X为其中手牌比主公多的角色数。',
qinqing_info_doudizhu:'结束阶段你可以选择任意名攻击范围内含有地主的角色然后弃置这些角色各一张牌并令其摸一张牌无牌则不弃若如此做你摸X张牌X为其中手牌比地主多的角色数。',
huisheng:'贿生', huisheng:'贿生',
huisheng_info:'当你受到其他角色对你造成的伤害时你可以令其观看你任意数量的牌并令其选择一项1.获得这些牌中的一张防止此伤害然后你不能再对其发动〖贿生〗2.弃置等量的牌。', huisheng_info:'当你受到其他角色对你造成的伤害时你可以令其观看你任意数量的牌并令其选择一项1.获得这些牌中的一张防止此伤害然后你不能再对其发动〖贿生〗2.弃置等量的牌。',
jishe:'极奢', jishe:'极奢',

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -2693,6 +2693,7 @@ div:not(.handcards)>.card>.info>span,
width: 12px; width: 12px;
height: 12px; height: 12px;
background-size: 100% 100%; background-size: 100% 100%;
box-shadow: none;
} }
.hp[data-condition="high"]>div:not(.lost):not(.shield) { .hp[data-condition="high"]>div:not(.lost):not(.shield) {
background: rgba(57, 123, 4,1); background: rgba(57, 123, 4,1);

View File

@ -9305,7 +9305,7 @@ return event.junling=='junling5'?1:0;});
} }
event.target.addTempSkill('qingcheng_ai'); event.target.addTempSkill('qingcheng_ai');
if(get.type(cards[0])=='equip'&&!event.done){ if(get.type(cards[0])=='equip'&&!event.done){
player.chooseTarget('是否暗置一名武将牌均为置的角色的一张武将牌?',function(card,player,target){ player.chooseTarget('是否暗置一名武将牌均为置的角色的一张武将牌?',function(card,player,target){
return target!=player&&!target.isUnseen(2); return target!=player&&!target.isUnseen(2);
}).set('ai',function(target){ }).set('ai',function(target){
return -get.attitude(_status.event.player,target); return -get.attitude(_status.event.player,target);
@ -12799,7 +12799,7 @@ return event.junling=='junling5'?1:0;});
preHidden:true, preHidden:true,
getIndex(event, player){ getIndex(event, player){
const evt=event.getl(player); const evt=event.getl(player);
if (evt && evt.player === player && evt.es) return 1; if (evt && evt.player === player && evt.es && evt.es.length) return 1;
return false; return false;
}, },
content:function(){ content:function(){

View File

@ -211,8 +211,16 @@ export class Game extends Uninstantable {
game.callHook("addGroup", [id, short, name, config]); game.callHook("addGroup", [id, short, name, config]);
return id; return id;
} }
/**
* @typedef {import("../library/hooks/interface.js").NonameHookType} NonameHookType
*/
/** /**
* 通用的调用钩子函数 * 通用的调用钩子函数
*
* @template {NonameHookType} HookType
* @template {keyof HookType} Name
* @param {Name} name
* @param {Parameters<HookType[Name]>} args
*/ */
static callHook(name, args) { static callHook(name, args) {
const callHook = () => { const callHook = () => {
@ -5946,7 +5954,7 @@ export class Game extends Uninstantable {
if (!event.forced && !event.fakeforce && get.noSelected()) confirm += 'c'; if (!event.forced && !event.fakeforce && get.noSelected()) confirm += 'c';
if (event.isMine()) game.Check.confirm(event, confirm); if (event.isMine()) game.Check.confirm(event, confirm);
game.callHook("checkEnd", [event, { ok, auto, auto_confirm }]); game.callHook("checkEnd", [event, { ok, auto, auto_confirm, autoConfirm: auto_confirm }]);
// if (ui.confirm && ui.confirm.lastChild.link == 'cancel') { // if (ui.confirm && ui.confirm.lastChild.link == 'cancel') {
// if (_status.event.type == 'phase' && !_status.event.skill) { // if (_status.event.type == 'phase' && !_status.event.skill) {

View File

@ -2273,7 +2273,7 @@ export class Get extends Uninstantable {
let char = chars[+part]; let char = chars[+part];
let unit = units[i]; let unit = units[i];
if (char === '零') unit = ''; if (char === '零') unit = '';
else if (char === '一' && i === 1) char = ''; else if (char === '一' && i === 1 && str.length === 2) char = '';
else if (char === '二' && i > 1 && !ordinal) char = '两'; else if (char === '二' && i > 1 && !ordinal) char = '两';
result = char + unit + result; result = char + unit + result;
} }

View File

@ -0,0 +1,324 @@
import { lib } from "../index.js"
import { game } from "../../game/index.js"
import { ui } from "../../ui/index.js"
import { get } from "../../get/index.js"
import { _status } from "../../status/index.js"
/**
* @type {(import("./interface.js").NonameHookType["addGroup"])[]}
*/
export const addGroup = [
function addColor(id, _short, _name, config) {
if (typeof config.color != "undefined" && config.color != null) {
let color1, color2, color3, color4
if (typeof config.color == "string" && /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(config.color)) {
let c1 = parseInt(`0x${config.color.slice(1, 3)}`)
let c2 = parseInt(`0x${config.color.slice(3, 5)}`)
let c3 = parseInt(`0x${config.color.slice(5, 7)}`)
color1 = color2 = color3 = color4 = [c1, c2, c3, 1]
}
else if (Array.isArray(config.color) && config.color.length == 4) {
if (config.color.every(item => Array.isArray(item))) {
color1 = config.color[0]
color2 = config.color[1]
color3 = config.color[2]
color4 = config.color[3]
}
else color1 = color2 = color3 = color4 = config.color
}
if (color1 && color2 && color3 && color4) {
const cs = lib.linq.cselector
game.dynamicStyle.addObject({
[cs.group(
cs.of(
cs.class("player ", "identity"),
cs.isAttr("data-color", `"${id}"`)
),
cs.of(
"div",
cs.isAttr("data-nature", `"${id}"`)
),
cs.of(
"span",
cs.isAttr("data-nature", `"${id}"`)
)
)]: {
textShadow: cs.group(
"black 0 0 1px",
`rgba(${color1.join()}) 0 0 2px`,
`rgba(${color2.join()}) 0 0 5px`,
`rgba(${color3.join()}) 0 0 10px`,
`rgba(${color4.join()}) 0 0 10px`
)
},
[cs.group(
cs.of(
"div",
cs.isAttr("data-nature", `"${id}m"`)
),
cs.of(
"span",
cs.isAttr("data-nature", `"${id}m"`)
)
)]: {
textShadow: cs.group(
"black 0 0 1px",
`rgba(${color1.join()}) 0 0 2px`,
`rgba(${color2.join()}) 0 0 5px`,
`rgba(${color3.join()}) 0 0 5px`,
`rgba(${color4.join()}) 0 0 5px`,
"black 0 0 1px"
)
},
[cs.group(
cs.of(
"div",
cs.isAttr("data-nature", `"${id}mm"`)
),
cs.of(
"span",
cs.isAttr("data-nature", `"${id}mm"`)
)
)]: {
textShadow: cs.group(
"black 0 0 1px",
`rgba(${color1.join()}) 0 0 2px`,
`rgba(${color2.join()}) 0 0 2px`,
`rgba(${color3.join()}) 0 0 2px`,
`rgba(${color4.join()}) 0 0 2px`,
"black 0 0 1px"
)
}
})
lib.groupnature[id] = id
}
}
},
function addImage(id, _short, _name, config) {
if (typeof config.image == "string") {
Reflect.defineProperty(lib.card, `group_${id}`, {
configurable: true,
enumerable: false,
writable: true,
value: {
fullskin: true,
image: config.image
}
})
}
}
]
/**
* @type {(import("./interface.js").NonameHookType["addNature"])[]}
*/
export const addNature = [
function addColor(nature, _translation, config) {
if (typeof config != 'object') config = {}
/**
* @type {boolean}
*/
// @ts-ignore
let linked = config.linked
/**
* @type {number}
*/
// @ts-ignore
let order = config.order
/**
* @type {string}
*/
// @ts-ignore
let background = config.background
/**
* @type {number[]}
*/
// @ts-ignore
let lineColor = config.lineColor
if (typeof linked != 'boolean') linked = true
if (typeof order != 'number') order = 0
if (typeof background != 'string') background = ''
if (!Array.isArray(lineColor) || lineColor.length != 3) lineColor = []
else if (background.startsWith('ext:')) {
background = background.replace(/^ext:/, 'extension/')
}
if (linked) lib.linked.add(nature)
if (lineColor.length) lib.lineColor.set(nature, lineColor)
lib.nature.set(nature, order)
if (background.length > 0) lib.natureBg.set(nature, background)
if (config.audio) {
for (let key in config.audio) {
if (!lib.natureAudio[key]) {
lib.natureAudio[key] = config.audio[key]
} else {
for (let key2 in config.audio[key]) {
lib.natureAudio[key][key2] = config.audio[key][key2]
}
}
}
}
let color1, color2
if (typeof config.color == "string" && /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(config.color)) {
let c1 = parseInt(`0x${config.color.slice(1, 3)}`)
let c2 = parseInt(`0x${config.color.slice(3, 5)}`)
let c3 = parseInt(`0x${config.color.slice(5, 7)}`)
color1 = color2 = [c1, c2, c3, 1]
}
else if (Array.isArray(config.color) && config.color.length >= 2 && config.color.length <= 4) {
if (config.color.every(item => Array.isArray(item))) {
color1 = config.color[0]
color2 = config.color[1]
}
else {
let color = config.color.slice()
if (color.length == 3) color.push(1)
color1 = color2 = color
}
}
if (color1 && color2) {
const cs = lib.linq.cselector
const g1 = cs.group(
cs.of(
cs.class("card", "fullskin", `${nature}`),
'>',
cs.class("name")
)
)
let result = {}
result[g1] = {
color: `rgba(${color1.join()})`,
border: cs.merge(
'1px',
'solid',
`rgba(${color2.join()})`
),
}
// @ts-ignore
game.dynamicStyle.addObject(result)
const g2 = cs.group(
cs.of(
cs.class("tempname", `${nature}`),
':not([data-nature])>',
cs.class("span")
)
)
let result2 = {}
result2[g2] = {
color: `rgba(${color1.join()})`,
}
// @ts-ignore
game.dynamicStyle.addObject(result2)
}
}
]
/**
* @type {(import("./interface.js").NonameHookType["checkBegin"])[]}
*/
export const checkBegin = []
/**
* @type {(import("./interface.js").NonameHookType["checkCard"])[]}
*/
export const 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')
}
]
/**
* @type {(import("./interface.js").NonameHookType["checkTarget"])[]}
*/
export const checkTarget = [
function updateInstance(target, event) {
// @ts-ignore
if (!target.instance) return;
['selected', 'selectable'].forEach(className => {
if (target.classList.contains(className)) {
// @ts-ignore
target.instance.classList.add(className)
} else {
// @ts-ignore
target.instance.classList.remove(className)
}
})
},
]
/**
* @type {(import("./interface.js").NonameHookType["checkButton"])[]}
*/
export const checkButton = []
/**
* @type {(import("./interface.js").NonameHookType["checkEnd"])[]}
*/
export const checkEnd = [
function autoConfirm(event, { ok, auto, autoConfirm }) {
if (!event.isMine()) return
const skillinfo = get.info(event.skill) || {}
if (ok && auto && (autoConfirm || skillinfo.direct) && !_status.touchnocheck
&& !_status.mousedown && (!_status.mousedragging || !_status.mouseleft)) {
if (ui.confirm) ui.confirm.close()
// @ts-ignore
if (event.skillDialog === true) event.skillDialog = false
ui.click.ok()
_status.mousedragging = null
if (skillinfo.preservecancel) ui.create.confirm('c')
}
}
]
/**
* @type {(import("./interface.js").NonameHookType["uncheckBegin"])[]}
*/
export const uncheckBegin = []
/**
* @type {(import("./interface.js").NonameHookType["uncheckCard"])[]}
*/
export const uncheckCard = [
function removeTempname(card, event) {
// @ts-ignore
if (!card._tempName) return
// @ts-ignore
card._tempName.delete()
// @ts-ignore
delete card._tempName
},
]
/**
* @type {(import("./interface.js").NonameHookType["uncheckTarget"])[]}
*/
export const uncheckTarget = [
function removeInstance(target, event) {
// @ts-ignore
if (!target.instance) return
// @ts-ignore
target.instance.classList.remove('selected')
// @ts-ignore
target.instance.classList.remove('selectable')
},
]
/**
* @type {(import("./interface.js").NonameHookType["uncheckButton"])[]}
*/
export const uncheckButton = []
/**
* @type {(import("./interface.js").NonameHookType["uncheckEnd"])[]}
*/
export const uncheckEnd = []

View File

@ -0,0 +1,51 @@
import * as buildin from "./buildin.js"
/**
* @template {import("./interface.js").NonameHookType} HookType
* @template {keyof HookType} Name
*/
export class NonameHook {
/**
* @type {Name}
*/
#name
/**
* @type {HookType[Name][]}
*/
#methodList
/**
*
* @param {Name} name
*/
constructor(name) {
this.#name = name
this.#methodList = (name in buildin) ? [...buildin[name]] : []
}
get name() {
return this.#name
}
/**
*
* @param {HookType[Name]} method
*/
add(method) {
return this.#methodList.add(method)
}
/**
*
* @param {HookType[Name]} method
*/
push(method) {
return this.#methodList.push(method)
}
*[Symbol.iterator]() {
yield* this.#methodList
}
}

View File

@ -0,0 +1,18 @@
import { NonameHook } from "./hook.js"
export const defaultHooks = {
addGroup: new NonameHook("addGroup"),
addNature: new NonameHook("addNature"),
checkBegin: new NonameHook("checkBegin"),
checkCard: new NonameHook("checkCard"),
checkTarget: new NonameHook("checkTarget"),
checkButton: new NonameHook("checkButton"),
checkEnd: new NonameHook("checkEnd"),
uncheckBegin: new NonameHook("uncheckBegin"),
uncheckCard: new NonameHook("uncheckCard"),
uncheckTarget: new NonameHook("uncheckTarget"),
uncheckButton: new NonameHook("uncheckButton"),
uncheckEnd: new NonameHook("uncheckEnd")
}

92
noname/library/hooks/interface.d.ts vendored Normal file
View File

@ -0,0 +1,92 @@
import { Button, Card, GameEvent, GameEventPromise, Player } from "../element"
export interface NonameHookType {
/**
*
* @param id - id
* @param short -
* @param name -
* @param config -
*/
addGroup(id: string, short: string, name: string, config: Record<string, unknown>)
/**
*
* @param nature - id
* @param translation -
* @param config -
*/
addNature(nature: string, translation: string, config: Record<string, unknown>)
/**
*
* @param event -
*/
checkBegin(event: GameEvent & GameEventPromise)
/**
*
* @param event -
* @param config -
*/
checkEnd(event: GameEvent & GameEventPromise, config: { ok: boolean, auto: boolean, autoConfirm: boolean })
/**
*
* @param button - Button
* @param event -
*/
checkButton(button: Button, event: GameEvent & GameEventPromise)
/**
*
* @param card -
* @param event -
*/
checkCard(card: Card, event: GameEvent & GameEventPromise)
/**
*
* @param target -
* @param event -
*/
checkTarget(target: Player, event: GameEvent & GameEventPromise)
/**
*
* @param event -
* @param args -
*/
uncheckBegin(event: GameEvent & GameEventPromise, args: ("button" | "card" | "target")[] = ["button", "card", "target"])
/**
*
* @param event -
* @param args -
*/
uncheckEnd(event: GameEvent & GameEventPromise, args: ("button" | "card" | "target")[] = ["button", "card", "target"])
/**
*
* @param button - Button
* @param event -
*/
uncheckButton(button: Button, event: GameEvent & GameEventPromise)
/**
*
* @param card -
* @param event -
*/
uncheckCard(card: Card, event: GameEvent & GameEventPromise)
/**
*
* @param target -
* @param event -
*/
uncheckTarget(target: Player, event: GameEvent & GameEventPromise)
}

File diff suppressed because it is too large Load Diff

View File

@ -1411,13 +1411,14 @@ export class Create extends Uninstantable {
var packlist = []; var packlist = [];
for (var i = 0; i < lib.config.all.characters.length; i++) { for (var i = 0; i < lib.config.all.characters.length; i++) {
if (!lib.config.characters.includes(lib.config.all.characters[i])) continue; if (!lib.config.characters.includes(lib.config.all.characters[i])) continue;
packlist.push(lib.config.all.characters[i]); packlist.add(lib.config.all.characters[i]);
}
for (var i in lib.characterPack) {
if (lib.config.characters.includes(i) && !lib.config.all.characters.includes(i)) {
packlist.push(i);
}
} }
Object.keys(lib.characterPack).filter(key=>{
if(key.indexOf('mode_extension')!=0)return false;
const extName = key.slice(15);
//if (!game.hasExtension(extName) || !game.hasExtensionLoaded(extName)) return false;
return lib.config[`extension_${extName}_characters_enable`] === true;
}).forEach(key=>packlist.add(key));
for (var i = 0; i < packlist.length; i++) { for (var i = 0; i < packlist.length; i++) {
var span = document.createElement('div'); var span = document.createElement('div');
span.style.display = 'inline-block'; span.style.display = 'inline-block';

View File

@ -114,7 +114,13 @@ self.addEventListener('fetch', event => {
vueFileMap.set( vueFileMap.set(
request.url + '?type=script', request.url + '?type=script',
// 重写 default // 重写 default
sfc.rewriteDefault(script.content, "__sfc_main__") sfc.rewriteDefault(script.attrs && script.attrs.lang == 'ts' ? ts.transpile(script.content, {
module: ts.ModuleKind.ES2015,
target: ts.ScriptTarget.ES2019,
inlineSourceMap: true,
resolveJsonModule: true,
esModuleInterop: true,
}, request.url + '?type=script') : script.content, "__sfc_main__")
.replace(`const __sfc_main__`, `export const __sfc_main__`) .replace(`const __sfc_main__`, `export const __sfc_main__`)
// import vue重新指向 // import vue重新指向
.replaceAll(`from "vue"`, `from "/game/vue.esm-browser.js"`) .replaceAll(`from "vue"`, `from "/game/vue.esm-browser.js"`)